Skip to content

Feature/2026 04 11#2

Merged
wernerbihl merged 19 commits intomainfrom
feature/2026-04-11
Apr 19, 2026
Merged

Feature/2026 04 11#2
wernerbihl merged 19 commits intomainfrom
feature/2026-04-11

Conversation

@wernerbihl
Copy link
Copy Markdown
Collaborator

No description provided.

wernerbihl and others added 19 commits April 19, 2026 15:19
- Refactored ObjectsPanel to use ObjectPropertiesDialogManager for managing object properties.
- Added support for text objects in the project, including rendering, editing, and properties management.
- Introduced TextObjectEditorOverlay for editing text objects directly on the canvas.
- Created utility functions for handling text object properties and rendering.
- Enhanced drawMapObjects to include text object rendering.
- Added local font loading capabilities and presets for text objects.
- Updated project normalization to include text object properties.
- Introduced hooks for managing text object editing state.
- Expanded type definitions to accommodate new text object features.

Co-authored-by: Copilot <copilot@github.com>
…ng options

Co-authored-by: Copilot <copilot@github.com>
- Introduced new map geometry utilities in `map-geometry.ts` for handling different map types (orthogonal, hexagonal).
- Updated `use-scene-interaction.ts` to utilize new geometry functions for cell interactions and drawing previews.
- Enhanced `MapPanel` to support new map types and geometry settings during map creation.
- Modified fill region logic in `terrain.ts` to leverage new map geometry functions for adjacent cell calculations.
- Updated project normalization to include new map geometry properties.
- Added types for new map geometry in `map-geometry.ts` and updated related interfaces across the codebase.
- Improved context menu interactions in `use-map-canvas-context-menu.ts` to use new cell retrieval methods.

Co-authored-by: Copilot <copilot@github.com>
Copilot AI review requested due to automatic review settings April 19, 2026 21:16
@wernerbihl wernerbihl merged commit 280ad30 into main Apr 19, 2026
5 checks passed
@wernerbihl wernerbihl deleted the feature/2026-04-11 branch April 19, 2026 21:18
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the editor’s capabilities by adding hexagonal map geometry support, introducing “text” objects on object layers (with inline editing + font handling), and improving import/export + editor UX (resize handles, delete shortcuts, context menu updates). It also switches fonts from Google Fonts to self-hosted @fontsource packages and tightens CSP directives accordingly.

Changes:

  • Add map geometry primitives (hex grids) and propagate orientation/stagger fields through schema, normalization, new-map creation, rendering, and fill adjacency.
  • Add text objects (schema type, defaults, property editing, inline canvas overlay editing, local font browsing).
  • Enhance UX: map/image resize handles with preview, context menu refactor + delete shortcut, and map import/export now includes image layers/layer groups/override tilesets.

Reviewed changes

Copilot reviewed 51 out of 52 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
vite.config.ts Updates dev CSP rules to match new font strategy and other restrictions.
src/types/text-object.ts Adds shared types/constants for text object settings/editing/font querying.
src/types/schema.ts Adds map geometry fields + new text object type.
src/types/persistence.ts Extends packed map format to include image layers, groups, override tilesets.
src/types/map-panel-context-menu.ts Adds types for map canvas context menu + orientation actions.
src/types/map-geometry.ts Adds orientation/stagger/new-map-type enums and defaults.
src/types/map-canvas.ts Extends MapCanvas types for map resize + text editing overlay props.
src/types/index.ts Re-exports new map-geometry and text-object types.
src/types/image-editor-ui.ts Moves brush/blur sizing controls into sidebar + adds canvas resize typing.
src/types/image-editor-internals.ts Refines undo snapshot types and adds stroke path tracking.
src/types/image-editor-hook.ts Adds resize operation snapshot types and action type.
src/types/editor-helpers.ts Extends fill options to include map geometry.
src/types/dialogs.ts Adds new map type selection + object properties manager props.
src/lib/text-objects.ts Implements text object defaults, parsing, patch building, normalization.
src/lib/terrain.ts Uses geometry-aware adjacency for fill region discovery.
src/lib/project.ts Normalizes new map geometry + normalizes text objects in project.
src/lib/map-geometry.ts Implements hex geometry math (cell bounds/polygon/adjacency/hit-testing).
src/lib/local-fonts.ts Adds font presets + Local Font Access API integration.
src/lib/image-editor-tools.ts Improves pixel blending, pencil stroke rendering, eraser clearing, fill behavior.
src/lib/image-editor-history.ts Stores width/height per snapshot to support resized undo/redo.
src/lib/format.ts Exports/imports additional map assets and normalizes imported geometry.
src/index.css Imports self-hosted fontsource CSS.
src/hooks/use-text-object-editing.ts Adds state management for inline text editing + commit/cancel.
src/hooks/use-keyboard-shortcuts.ts Adds Delete/Backspace shortcut dispatch for selection deletion.
src/components/ui/DropdownMenu.tsx Improves hover/highlight styles for dropdown items.
src/components/tools/ImageEditor/index.tsx Wires sidebar sizing controls + resize callback to canvas.
src/components/tools/ImageEditor/ToolSidebar.tsx Adds tool size dropdown menus for brush/blur sizing.
src/components/tools/ImageEditor/ImageCanvas.tsx Adds interactive resize gutter/handles with preview + commit callback.
src/components/tools/ImageEditor/EditorToolbar.tsx Removes brush/blur sizing UI from top toolbar.
src/components/editor/ObjectsPanel.tsx Adds “text” object type + swaps to dialog manager for properties.
src/components/editor/ObjectPropertiesDialogManager.tsx Centralizes object lookup + ensures text rotation sync after save.
src/components/editor/MapPanel/use-map-canvas-context-menu.ts Extracts context-menu hit testing for tiles/images/objects.
src/components/editor/MapPanel/MapCanvasContextMenuContent.tsx New context menu component with delete + object properties entry.
src/components/editor/MapPanel.tsx Integrates new context menu, delete behavior, new-map type selection, text editing.
src/components/editor/MapCanvas/use-scene-interaction.ts Uses geometry-aware cell hit testing + updated object hit/handle utils.
src/components/editor/MapCanvas/text-object-rendering.ts Renders wrapped/rotated text and measures layout.
src/components/editor/MapCanvas/object-utils.ts Centralizes box-object handle positions and hit-testing.
src/components/editor/MapCanvas/index.tsx Adds map resize gutter UI, hex grid rendering updates, text editor overlay.
src/components/editor/MapCanvas/draw-map-objects.ts Extracts object rendering, including text objects.
src/components/editor/MapCanvas/TextObjectEditorOverlay.tsx Inline textarea overlay for editing text objects on canvas.
src/components/dialogs/ObjectPropertiesDialog.tsx Adds text-specific property UI + local font browsing + better ARIA fields.
src/components/dialogs/NewMapDialog.tsx Adds map type dropdown (orthogonal/hex row/hex column).
src/components/dialogs/KeyboardShortcutsDialog.tsx Documents delete shortcut.
src/App.tsx Updates map export/import to include new layer types and remap IDs robustly.
public/_headers Updates production CSP to remove Google Fonts and use self-hosted fonts.
package.json Adds @fontsource/* dependencies.
index.html Removes Google Fonts <link> tags.
bun.lock Locks new font dependencies.
TODO.txt Updates TODO list content.
SECURITY.md Adds a vulnerability reporting policy document.
AGENTS.md Updates contributor/agent workflow requirements.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

contextMenuTileRef.current = tile;
const tileRef = activeTileLayer?.tiles[`${tile.x},${tile.y}`] ?? null;
setHasContextMenuTile(!!tileRef);
} else {
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When right-clicking outside the map (or outside any valid cell), contextMenuTileRef.current is left unchanged. Downstream actions (copy/cut/paste/orient/delete) use contextMenuTileRef.current when invoked from the context menu, so this can apply the operation to a stale tile coordinate. Clear contextMenuTileRef.current when tile is null to avoid acting on the previous click location.

Suggested change
} else {
} else {
contextMenuTileRef.current = null;

Copilot uses AI. Check for mistakes.
Comment on lines +349 to +351
if (isHexMap) return;
const bounds = getMapCellBounds(map, zoom, gx, gy);
ctx.clearRect(bounds.x, bounds.y, bounds.width, bounds.height);
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eraseBufferTile() becomes a no-op on hex maps (if (isHexMap) return). MapPanel relies on this to provide immediate visual feedback while erasing (it buffers the deletion and calls eraseBufferTile during the drag). On hex maps this means erasing won't visually update until the stroke is committed. Consider clearing via a hex-shaped clip (using getMapCellPolygon) or otherwise redrawing the paint buffer region so erasing works interactively on hex maps too.

Suggested change
if (isHexMap) return;
const bounds = getMapCellBounds(map, zoom, gx, gy);
ctx.clearRect(bounds.x, bounds.y, bounds.width, bounds.height);
const bounds = getMapCellBounds(map, zoom, gx, gy);
if (!isHexMap) {
ctx.clearRect(bounds.x, bounds.y, bounds.width, bounds.height);
return;
}
const polygon = getMapCellPolygon(map, zoom, gx, gy);
if (polygon.length === 0) return;
let minX = polygon[0].x;
let minY = polygon[0].y;
let maxX = polygon[0].x;
let maxY = polygon[0].y;
for (let i = 1; i < polygon.length; i += 1) {
const point = polygon[i];
if (point.x < minX) minX = point.x;
if (point.y < minY) minY = point.y;
if (point.x > maxX) maxX = point.x;
if (point.y > maxY) maxY = point.y;
}
ctx.save();
ctx.beginPath();
ctx.moveTo(polygon[0].x, polygon[0].y);
for (let i = 1; i < polygon.length; i += 1) {
ctx.lineTo(polygon[i].x, polygon[i].y);
}
ctx.closePath();
ctx.clip();
ctx.clearRect(minX, minY, maxX - minX, maxY - minY);
ctx.restore();

Copilot uses AI. Check for mistakes.
Comment on lines 663 to +672
// ---- Grid ----
ctx.strokeStyle = "rgba(255, 165, 0, 0.15)";
ctx.lineWidth = 1;
ctx.beginPath();
for (let x = 0; x <= canvasW; x += scaledTile) {
ctx.moveTo(x + 0.5, 0);
ctx.lineTo(x + 0.5, canvasH);
}
for (let y = 0; y <= canvasH; y += scaledTile) {
ctx.moveTo(0, y + 0.5);
ctx.lineTo(canvasW, y + 0.5);
if (isHexMap) {
for (let y = 0; y < mapH; y++) {
for (let x = 0; x < mapW; x++) {
traceCellPath(ctx, x, y);
ctx.stroke();
}
}
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The canvas dimensions are computed from previewMapW/previewMapH (via mapResizePreview), but the hex grid rendering still iterates y < mapH and x < mapW (the committed map size). During a resize preview on hex maps, the grid/border won't match the previewed size. Use previewMapW/previewMapH (or a derived preview geometry object) for grid/selection drawing when mapResizePreview is active.

Copilot uses AI. Check for mistakes.
Comment thread src/App.tsx
values: Record<string, PropertyValue> = {},
): Record<string, PropertyValue> {
return Object.fromEntries(
Object.entries(values).map(([key, value]) => [key, { ...value }]),
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clonePropertyValues spreads each property value ({ ...value }). Other parts of the codebase still tolerate legacy property formats where a property value can be a raw string (e.g. MapOptionsDialog/ObjectPropertiesDialog check typeof propertyValue === "string"). If an imported map/project contains legacy string values, spreading will convert the string into an object of character indices, corrupting properties. Update this helper to preserve strings as-is and only clone { value, type } objects.

Suggested change
Object.entries(values).map(([key, value]) => [key, { ...value }]),
Object.entries(values).map(([key, value]) => [
key,
typeof value === "string" ? value : { ...value },
]),

Copilot uses AI. Check for mistakes.
Comment thread vite.config.ts
Comment on lines 47 to 54
"Content-Security-Policy":
"default-src 'self'; " +
"script-src 'self' 'unsafe-inline' https://www.gstatic.com https://static.cloudflareinsights.com; " +
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " +
"script-src 'self' 'unsafe-inline' https://static.cloudflareinsights.com; " +
"style-src 'self' 'unsafe-inline'; " +
"img-src 'self' data: blob: https:; " +
"font-src 'self' data: https://fonts.gstatic.com; " +
"connect-src 'self' https://o4510891797250048.ingest.us.sentry.io https://*.sentry.io https://www.google.com https://cloudflareinsights.com; " +
"frame-src https://www.google.com; " +
"font-src 'self' data:; " +
"connect-src 'self' https://o4510891797250048.ingest.us.sentry.io https://*.sentry.io https://cloudflareinsights.com; " +
"worker-src 'self' blob:; " +
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dev-server CSP connect-src is stricter than production and currently omits AI provider endpoints used in the app (e.g. https://api.openai.com, https://api.together.xyz, https://api.x.ai, and https://generativelanguage.googleapis.com). This will cause those features to fail in local dev due to CSP violations. Consider aligning connect-src here with public/_headers (and adding any additional endpoints actually used by the generator).

Copilot uses AI. Check for mistakes.
@wernerbihl
Copy link
Copy Markdown
Collaborator Author

@copilot apply changes based on the comments in this thread

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants