Skip to content

Add Tiled Import and Export functionality#15

Merged
wernerbihl merged 12 commits intomainfrom
feature/2026-05-04
May 5, 2026
Merged

Add Tiled Import and Export functionality#15
wernerbihl merged 12 commits intomainfrom
feature/2026-05-04

Conversation

@wernerbihl
Copy link
Copy Markdown
Collaborator

Introduce comprehensive import and export capabilities for Tiled projects, enhancing support for various map and tileset formats. Implement improved error handling, resource management, and user dialogs for missing resources. Update related utilities and add tests to ensure functionality and coverage. Refactor existing code for better maintainability and clarity.

wernerbihl added 10 commits May 4, 2026 19:20
- Refactor useTiledProjectImport hook to support both zip and raw Tiled project files.
- Implement directory file selection for linked resources.
- Add validation for Tiled project files and improve error handling.
- Introduce a dialog for resolving missing resources during import.
- Update import-export action utilities to handle directory file picking.
- Create a new function to prepare Tiled project imports with better resource management.
- Add tests for the new import functionality and ensure coverage for missing resource handling.
- Refactor project creation logic to use a dedicated function for initializing empty projects.
Copilot AI review requested due to automatic review settings May 5, 2026 19:00
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

Adds Tiled project-level import/export support to the app’s import/export layer and wires file-based import entry points into the editor UI. It also refactors a few map-canvas helpers and expands test coverage around the new flows.

Changes:

  • Adds Tiled project archive import/export, missing-resource resolution, and imported-project session replacement.
  • Extends map/tileset UI to support file-based import from dialogs and drag-and-drop.
  • Refactors map canvas rendering helpers and adds tests for project import/export behavior.

Reviewed changes

Copilot reviewed 47 out of 47 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
TODO.txt Updates roadmap items.
tests/features/project-management/lib/project.test.ts Adds coverage for empty-project creation.
tests/features/map-editor/components/MapCanvas/draw-layer-entries.test.ts Adds active-layer redraw regression coverage.
tests/features/import-export/lib/imported-tiled-project-session.test.ts Tests imported Tiled project replacement flow.
tests/features/import-export/lib/import-export-tiled-project.test.ts Adds Tiled project import/export tests.
tests/features/import-export/lib/import-export-gamemaker.test.ts Expands GameMaker export coverage for GMX.
tests/features/import-export/lib/import-export-action-utils.test.ts Tests picker helpers, including directory selection.
tests/features/import-export/lib/gamemaker-map-import.test.ts Expands GameMaker GMX import coverage.
tests/features/import-export/hooks/use-tiled-map-import.test.ts Adds hook tests for Tiled project import UX.
src/features/project-management/lib/project.ts Extracts reusable empty-project factory.
src/features/project-management/components/ProjectDialog.tsx Switches project creation to shared helper.
src/features/map-editor/types/map-panel.ts Threads map-file import callbacks through panel props.
src/features/map-editor/types/map-canvas-rendering.ts Adds paint-buffer input to active-layer rendering params.
src/features/map-editor/types/dialogs.ts Extends new-map dialog props for file import.
src/features/map-editor/dialogs/NewMapDialog.tsx Adds “From File” tab with picker/drop-zone import.
src/features/map-editor/components/TilesetPanel.tsx Enables tileset import from non-image files and drag-drop.
src/features/map-editor/components/MapPanel/MapPanelWorkspace.tsx Adds map-file drag-drop import surface.
src/features/map-editor/components/MapPanel/MapPanelDialogs.tsx Passes new map import callback into dialog layer.
src/features/map-editor/components/MapPanel.tsx Wires map-file import callback through panel.
src/features/map-editor/components/MapCanvas/use-map-canvas-imperative-handle.ts Extracts imperative paint-canvas helpers.
src/features/map-editor/components/MapCanvas/use-animation-elapsed-ms.ts Extracts animated-tile timer hook.
src/features/map-editor/components/MapCanvas/index.tsx Adopts extracted hooks and paint-buffer redraw path.
src/features/map-editor/components/MapCanvas/draw-layer-entries.ts Merges live paint buffer into active-layer redraws.
src/features/import-export/types/index.ts Adds Tiled project import state/dialog/result types.
src/features/import-export/lib/tiled-project-action-utils.ts Adds project-level Tiled export helper.
src/features/import-export/lib/imported-tiled-project-session.ts Replaces current editor session with imported Tiled project data.
src/features/import-export/lib/import-export-tiled-project.ts Implements Tiled project import/export bundle logic.
src/features/import-export/lib/import-export-options.ts Marks Tiled project option as supported.
src/features/import-export/lib/import-export-action-utils.ts Refactors picker helpers and adds directory picker support.
src/features/import-export/index.ts Re-exports new Tiled project dialog.
src/features/import-export/hooks/use-unity-tileset-import.ts Allows preselected Unity tileset files.
src/features/import-export/hooks/use-unity-map-import.ts Allows preselected Unity map files.
src/features/import-export/hooks/use-tiled-tileset-import.ts Allows preselected Tiled tileset files.
src/features/import-export/hooks/use-tiled-project-import.ts Adds Tiled project import hook and dialog state flow.
src/features/import-export/hooks/use-tiled-map-import.ts Allows preselected Tiled map files.
src/features/import-export/hooks/use-tide-map-import.ts Allows preselected tIDE map files.
src/features/import-export/hooks/use-mappy-map-import.ts Allows preselected Mappy map files.
src/features/import-export/hooks/use-import-export-actions.ts Integrates Tiled project flows and generic file-based map/tileset import routing.
src/features/import-export/hooks/use-godot-tileset-import.ts Allows preselected Godot tileset files.
src/features/import-export/hooks/use-godot-map-import.ts Allows preselected Godot map files.
src/features/import-export/hooks/use-gamemaker-map-import.ts Allows preselected GameMaker map files.
src/features/import-export/hooks/use-defold-tileset-import.ts Allows preselected Defold tileset files.
src/features/import-export/hooks/use-defold-map-import.ts Allows preselected Defold map files.
src/features/import-export/components/TiledProjectFilesDialog.tsx Adds folder-selection dialog for raw Tiled project imports.
src/features/import-export/components/TiledMissingResourcesDialog.tsx Allows custom dialog description text.
src/features/app-shell/components/AppShell.tsx Wires new import handlers and lazy-loaded Tiled project dialog into the shell.
AGENTS.md Adds code-search/workflow guidance.

Comment on lines +126 to +133
for (const entry of entries) {
if (entry.path === expectedMapPath) {
const uniquePath = getUniqueArchivePath(entry.path, seenPaths);
archiveEntries.push({ path: uniquePath, data: entry.data });
} else if (!seenPaths.has(entry.path)) {
seenPaths.add(entry.path);
archiveEntries.push(entry);
}
Comment on lines +48 to +55
function detectMapFormat(fileName: string): TiledMapFormat | null {
const lower = fileName.toLowerCase();
if (lower.endsWith(".tmx") || lower.endsWith(".xml")) return "xml";
if (lower.endsWith(".tmj")) return "json";
if (lower.endsWith(".js")) return "js";
if (lower.endsWith(".lua")) return "lua";
return null;
}
Comment on lines +179 to +187

export async function prepareTiledProjectImport(
entries: readonly ImportExportArchiveEntry[],
): Promise<TiledProjectImportPreparationResult> {
const mapPaths = entries
.map((entry) => entry.path)
.filter((path) => {
if (isTilesetOrImageEntry(path)) return false;
if (path.toLowerCase().endsWith(".tiled-project")) return false;
): Promise<void> {
const targetProject = createEmptyProject(
suggestedProjectName,
result.maps[0]?.map.tileSize ?? 32,
Comment on lines +26 to +33
for (const mapImport of result.maps) {
mergeImportedMapData(
mapImport,
targetProject,
targetMapGroupId,
targetTilesetGroupId,
setState,
);
Comment on lines +47 to +49
async function handleImportFile(file: File) {
await onImportMapFromFile(file);
onOpenChange(false);
Comment on lines 20 to 21
label: "Tiled Project (.tiled-project)",
description: "Tiled multi-map project container.",
Comment thread AGENTS.md Outdated
Comment on lines +5 to +9
​`bash
semble search "authentication flow" ./my-project
semble search "save_pretrained" ./my-project
semble search "save model to disk" ./my-project --top-k 10
​`
Comment thread AGENTS.md Outdated
Comment on lines +13 to +15
​`bash
semble find-related src/auth.py 42 ./my-project
​`
Comment on lines +198 to +208
<div
className={`flex min-h-32 cursor-pointer flex-col items-center justify-center gap-3 rounded-md border-2 border-dashed p-6 transition-colors ${
isDroppingFile
? "border-primary bg-primary/10"
: "border-muted-foreground/30 hover:border-muted-foreground/50"
}`}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={(e) => void handleDrop(e)}
onClick={() => importFileInputRef.current?.click()}
>
@wernerbihl
Copy link
Copy Markdown
Collaborator Author

@copilot apply changes based on the comments in this thread

Copilot AI and others added 2 commits May 5, 2026 19:27
Copy link
Copy Markdown
Contributor

Copilot AI commented May 5, 2026

@copilot apply changes based on the comments in this thread

Applied all 9 fixes from the review thread in commit cb23220:

  1. Export path collision — asset entries with the same path but different data now get a unique path via getUniqueArchivePath, and the map file's asset references are rewritten to match.
  2. .json map extensiondetectMapFormat now recognises .json alongside .tmj as a JSON-format map.
  3. Extension scriptsprepareTiledProjectImport reads extensionsPath from the .tiled-project file and excludes any files under that path from map detection.
  4. Invalid tile size — the imported tileSize is now snapped to the nearest value in TILE_SIZES before creating the project.
  5. Shared tileset deduplication — after all maps are merged, deduplicateProjectTilesets removes duplicate tilesets (matched by name + tileSize + dimensions) and rewrites tile-layer references to the canonical ID.
  6. Dialog close on failurehandleImportFile now only closes the dialog when onImportMapFromFile returns true.
  7. Label mismatch — the project-tiled option label and description now say .tiled-project.zip to match the actual exported archive.
  8. AGENTS.md code fences — replaced the hidden zero-width-space + single-backtick markers with proper triple-backtick fences.
  9. Drop-zone accessibility — the import drop zone is now a <button type="button"> with an aria-label, so it is reachable and activatable via keyboard and assistive technology.

@wernerbihl wernerbihl merged commit 9536e0d into main May 5, 2026
4 checks passed
@wernerbihl wernerbihl deleted the feature/2026-05-04 branch May 5, 2026 19:31
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.

3 participants