Skip to content

Commit a8a8067

Browse files
authored
Merge pull request #46 from eleniums/fix/project-root
Revert breaking changes to projectRoot and automatically determine projectRoot
2 parents 6327ac4 + 540ee8e commit a8a8067

4 files changed

+97
-41
lines changed

README.md

+31-10
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,42 @@ If you prefer watching check the video in YouTube:
5757

5858
[How to export from Tiled To Godot 3.2](https://youtu.be/4jSFAXIa_Lo)
5959

60+
The exporter needs to know how to set resource paths correctly for Godot before exporting. There are several ways to do this:
61+
62+
- If your Tiled files exist in your Godot project structure alongside the exported files, the exporter can automatically determine the resource paths. There is also the option to use the `projectRoot` custom property if needed.
63+
- If your Tiled files exist outside your Godot project structure, you will need to set the `relativePath` custom property so the exporter can determine resource paths.
64+
65+
**_!!! Pay attention to the "/" instead of standard windows "\\". Single Backslash "\\" is used for escaping special symbols._**
66+
67+
### Setting relativePath
68+
69+
The custom property `relativePath : string` contains the relative path to the exported files from the Godot project root.
70+
The value of `relativePath` is transformed to a resource path which Godot uses.
71+
72+
* When placed on a Tiled TileMap (.tmx) object, it will define where the Tileset objects (.tres) are located in the exported TileMap (.tscn).
73+
* When placed on a Tiled TileSet (.tsx) object, it will define where the Image is located in the exported TileMap (.tres).
74+
75+
Example:
76+
If the location of an exported tileset is: `C:/project/maps/level1/tileset.tres`
77+
Then the `relativePath` custom property would be: `/maps/level1`
78+
6079
### Setting projectRoot `res://`
6180

62-
The exporter needs to know where `res://` is. By default, it's in the same directory where the Tiled files are being saved.
63-
You can override this path with a custom property `projectRoot : string` that is either relative to the file you are exporting (starting with a `.`), or absolute path,
64-
Either way the value of projectRoot is transformed to a resource path which Godot use.
81+
The exporter needs to know where `res://` is so when you export to a subfolder in your Godot project all the relative paths for the resources `(res://)` are set correctly and relative to the project root. `res://` is equivalent to the location of `project.godot` in your Godot project.
82+
83+
**By default, the exporter expects the Tiled files to be saved in a subfolder of your Godot project next to the exported files and will determine the project root automatically. Setting `projectRoot` is no longer required in this scenario.**
84+
85+
If needed, you can override this path with a custom property `projectRoot : string` that is either relative to the file you are exporting (starting with a `.`) or an absolute path.
86+
Either way, the value of `projectRoot` is transformed to the `res://` resource path which Godot uses and should be equivalent to the location of `project.godot`.
6587

66-
* When placed on a Tiled TileMap (.tmx) object it will define where the Tileset objects (.tres) are located in the exported TileMap (.tscn).
67-
* When placed on a Tiled TileSet (.tsx) object it will define where the Image is located in the exported TileMap (.tres).
88+
* When placed on a Tiled TileMap (.tmx) object it will be used as the root to determine the relative resource path to the Tileset objects (.tres) used in the exported TileMap (.tscn).
89+
* When placed on a Tiled TileSet (.tsx) object it will be used as the root to determine the relative resource path to the Image used in the exported TileMap (.tres).
6890

69-
**_!!! Pay attention to the "/" instead of standard windows "\\".
70-
Single Backslash "\\" is used for escaping special symbols._**
91+
Example:
92+
If the location of an exported tileset is: `C:/project/maps/level1/tileset.tres`
93+
Then the `projectRoot` custom property would be: `C:/project`
7194

72-
This is needed so when you export to a subfolder in your Godot project all the relative
73-
paths for the resources `(res://)` are set correctly and relative to the custom property
74-
you've added `"projectRoot"`;
95+
### Exporting to Godot
7596

7697
If everything is fine when you go to _File -> Export As_, a new option should exist:
7798

export_to_godot_tilemap.js

+6-7
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,9 @@ class GodotTilemapExporter {
7474
const tileset = this.map.tilesets[index];
7575
this.extResourceId = index + 1;
7676
this.tilesetsIndex.set(tileset.name, this.extResourceId);
77-
// noinspection JSUnresolvedVariable
78-
let tilesetPath = getResPath(this.map.property("projectRoot"), tileset.asset.fileName);
79-
let tilesetName = FileInfo.fileName(tileset.asset.fileName).replace('.tsx', '.tres');
80-
this.tilesetsString += this.getTilesetResourceTemplate(this.extResourceId, FileInfo.joinPaths(tilesetPath, tilesetName), "TileSet");
77+
// noinspection JSUnresolvedFunction
78+
let tilesetPath = getResPath(this.map.property("projectRoot"), this.map.property("relativePath"), tileset.asset.fileName.replace('.tsx', '.tres'));
79+
this.tilesetsString += this.getTilesetResourceTemplate(this.extResourceId, tilesetPath, "TileSet");
8180
}
8281

8382
}
@@ -131,9 +130,9 @@ class GodotTilemapExporter {
131130
this.extResourceId = this.extResourceId + 1;
132131
textureResourceId = this.extResourceId;
133132
this.tilesetsIndex.set(tilesetsIndexKey, this.extResourceId);
134-
let tileImagePath = getResPath(this.map.property("projectRoot"), object.tile.tileset.image);
135-
let tileImageName = FileInfo.fileName(object.tile.tileset.image);
136-
this.tilesetsString += this.getTilesetResourceTemplate(this.extResourceId, FileInfo.joinPaths(tileImagePath, tileImageName), "Texture");
133+
// noinspection JSUnresolvedFunction
134+
let tilesetPath = getResPath(this.map.property("projectRoot"), this.map.property("relativePath"), object.tile.tileset.image);
135+
this.tilesetsString += this.getTilesetResourceTemplate(this.extResourceId, tilesetPath, "Texture");
137136
} else {
138137
textureResourceId = this.tilesetsIndex.get(tilesetsIndexKey);
139138
}

export_to_godot_tileset.js

+1-5
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ class GodotTilesetExporter {
66
this.tileset = tileset;
77
this.fileName = fileName;
88
// noinspection JSUnresolvedFunction
9-
this.imagePath = getResPath(this.tileset.property("projectRoot"), this.tileset.image);
10-
this.spriteImagePath = FileInfo.joinPaths(this.imagePath, FileInfo.fileName(this.tileset.image));
11-
12-
// Strip leading slashes to prevent invalid triple slashes in Godot res:// path:
13-
this.spriteImagePath = this.spriteImagePath.replace(/^\/+/, '');
9+
this.spriteImagePath = getResPath(this.tileset.property("projectRoot"), this.tileset.property("relativePath"), this.tileset.image);
1410
this.shapesResources = "";
1511
this.shapes = "";
1612
this.navpolyMap = [];

utils.js

+59-19
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,65 @@ function logk(data) {
1010
console.log(Object.keys(data));
1111
}
1212

13-
function getResPath(projectRoot, outputPath) {
14-
const p = outputPath.split('/').slice(0, -1)
15-
// check for projectRoot
16-
// If projectRoot is not set, set it to current file's location
17-
if (!projectRoot) {
18-
projectRoot = p.join('/')
19-
}
20-
projectRoot = projectRoot.replace(/\\/g, '/')
21-
// Use it as absolute, if it doesn't start with ".", relative if it does
22-
if (projectRoot[0] === '.') {
23-
const out = p
24-
projectRoot.split('/').forEach((segment, i) => {
25-
if (segment === '..') {
26-
out.pop()
27-
}
28-
})
29-
projectRoot = out.join('/')
13+
/**
14+
* Returns a full res path to a file.
15+
*
16+
* If relativePath is defined, uses relativePath to determine the res path.
17+
* If relativePath is undefined, uses projectRoot to determine the res path.
18+
* If relativePath is undefined and projectRoot is undefined, automatically determines the res path.
19+
*
20+
* Information on file paths in Godot: https://docs.godotengine.org/en/stable/tutorials/io/data_paths.html
21+
*
22+
* @param {string} projectRoot desired project root path, which can be an absolute or relative path to the outputPath. Ex: 'C:/project' or './../..'
23+
* @param {string} relativePath relative path to file. Ex: '/maps/level1'
24+
* @param {string} outputPath full path and name of destination file. Ex: 'C:/project/maps/level1/tileset.tres'
25+
* @returns {string} full relative path to file to be included in a 'res://' path. Ex: 'maps/level1/tileset.tres'
26+
*/
27+
function getResPath(projectRoot, relativePath, outputPath) {
28+
let fullResPath = ''
29+
if (relativePath) {
30+
// Replace all backslashes with forward slashes
31+
relativePath = relativePath.replace(/\\/g, '/');
32+
33+
fullResPath = FileInfo.joinPaths(relativePath, FileInfo.fileName(outputPath));
34+
} else {
35+
const p = outputPath.split('/').slice(0, -1)
36+
37+
// If projectRoot is not set, attempt to automatically determine projectRoot by searching for godot project file
38+
if (!projectRoot) {
39+
const out = p
40+
outputPath.split('/').every(_ => {
41+
let godotProjectFile = FileInfo.joinPaths(out.join('/'), 'project.godot');
42+
if (!File.exists(godotProjectFile)) {
43+
out.pop()
44+
return true;
45+
}
46+
return false;
47+
})
48+
projectRoot = out.join('/')
49+
}
50+
51+
// Replace all backslashes with forward slashes
52+
projectRoot = projectRoot.replace(/\\/g, '/');
53+
54+
// Use projectRoot as absolute if it doesn't start with ".", relative if it does
55+
if (projectRoot[0] === '.') {
56+
const out = p
57+
projectRoot.split('/').forEach((segment) => {
58+
if (segment === '..') {
59+
out.pop()
60+
}
61+
})
62+
projectRoot = out.join('/')
63+
}
64+
65+
fullResPath = outputPath.replace(projectRoot, "");
3066
}
31-
return projectRoot
67+
68+
// Strip leading slashes to prevent invalid triple slashes in Godot res:// path
69+
fullResPath = fullResPath.replace(/^\/+/, '');
70+
71+
return fullResPath
3272
}
3373

3474
/**
@@ -65,7 +105,7 @@ function splitCommaSeparated(str) {
65105
* @param {object} nodeProperties pair key/values for the "node" properties
66106
* @param {object} contentProperties pair key/values for the content properties
67107
* @param {object} metaProperties pair key/values for the meta properties
68-
* @return {string} TSCN scene node like so :
108+
* @returns {string} TSCN scene node like so :
69109
* ```
70110
* [node key="value"]
71111
* content_key = AnyValue

0 commit comments

Comments
 (0)