237 lines
8.2 KiB
Python
237 lines
8.2 KiB
Python
import json
|
|
import os
|
|
|
|
PROJECT_ROOT = "/Users/davidkotnik/repos/novafarma"
|
|
LDTK_FILE = os.path.join(PROJECT_ROOT, "AutoLayers_2_stamps.ldtk")
|
|
|
|
def create_tileset_def(uid, identifier, rel_path, w=512, h=512):
|
|
return {
|
|
"__cWid": w // 32,
|
|
"__cHei": h // 32,
|
|
"identifier": identifier,
|
|
"uid": uid,
|
|
"relPath": rel_path,
|
|
"embedAtlas": None,
|
|
"pxWid": w,
|
|
"pxHei": h,
|
|
"tileGridSize": 32,
|
|
"spacing": 0,
|
|
"padding": 0,
|
|
"tags": [],
|
|
"tagsSourceEnumUid": None,
|
|
"enumTags": [],
|
|
"customData": [],
|
|
"savedSelections": [],
|
|
"cachedPixelData": None
|
|
}
|
|
|
|
def main():
|
|
data = {
|
|
"__header__": { "fileType": "LDtk Project JSON", "app": "LDtk", "doc": "https://ldtk.io/json", "schema": "https://ldtk.io/files/JSON_SCHEMA.json", "appAuthor": "Sebastien 'deepnight' Benard", "appVersion": "1.5.3", "url": "https://ldtk.io" },
|
|
"iid": "6440c680-d380-11f0-b813-5db2a94f8a9c",
|
|
"jsonVersion": "1.5.3",
|
|
"appBuildId": 473703,
|
|
"nextUid": 10000,
|
|
"identifierStyle": "Capitalize",
|
|
"toc": [],
|
|
"worldLayout": "Free",
|
|
"worldGridWidth": 256,
|
|
"worldGridHeight": 256,
|
|
"defaultLevelWidth": 512,
|
|
"defaultLevelHeight": 512,
|
|
"defaultPivotX": 0,
|
|
"defaultPivotY": 0,
|
|
"defaultGridSize": 16,
|
|
"defaultEntityWidth": 16,
|
|
"defaultEntityHeight": 16,
|
|
"bgColor": "#40465B",
|
|
"defaultLevelBgColor": "#696A79",
|
|
"minifyJson": False,
|
|
"externalLevels": False,
|
|
"exportTiled": False,
|
|
"simplifiedExport": False,
|
|
"imageExportMode": "None",
|
|
"exportLevelBg": True,
|
|
"pngFilePattern": None,
|
|
"backupOnSave": False,
|
|
"backupLimit": 10,
|
|
"backupRelPath": None,
|
|
"levelNamePattern": "Level_%idx",
|
|
"tutorialDesc": None,
|
|
"customCommands": [],
|
|
"flags": [],
|
|
"defs": { "layers": [], "entities": [], "tilesets": [], "enums": [], "externalEnums": [], "levelFields": [] },
|
|
"levels": [],
|
|
"worlds": [],
|
|
"dummyWorldIid": "6440c681-d380-11f0-b813-a103d476f7a1"
|
|
}
|
|
|
|
# 1. TILESETS
|
|
t_uid = 100
|
|
ts_grass = create_tileset_def(t_uid, "Grass", "godot/world/GROUND/grass.png"); t_uid+=1
|
|
ts_dirt = create_tileset_def(t_uid, "Dirt", "godot/world/GROUND/dirt.png"); t_uid+=1
|
|
ts_water = create_tileset_def(t_uid, "Water", "godot/world/GROUND/water.png"); t_uid+=1
|
|
ts_farm = create_tileset_def(t_uid, "Farmland", "godot/world/GROUND/farmland.png"); t_uid+=1
|
|
|
|
tilesets = [ts_grass, ts_dirt, ts_water, ts_farm]
|
|
data['defs']['tilesets'] = tilesets
|
|
|
|
# 2. INTGRID LAYER (The "Kocke")
|
|
intgrid_uid = 200
|
|
int_grid_def = {
|
|
"__type": "IntGrid",
|
|
"identifier": "Terrain_Control",
|
|
"type": "IntGrid",
|
|
"uid": intgrid_uid,
|
|
"gridSize": 32,
|
|
"displayOpacity": 1,
|
|
"pxOffsetX": 0,
|
|
"pxOffsetY": 0,
|
|
"intGridValues": [
|
|
{ "value": 1, "identifier": "Grass", "color": "#36BC29" },
|
|
{ "value": 2, "identifier": "Dirt", "color": "#8B5F2A" },
|
|
{ "value": 3, "identifier": "Water", "color": "#388BE7" },
|
|
{ "value": 4, "identifier": "Farmland", "color": "#54301A" }
|
|
],
|
|
"autoRuleGroups": [],
|
|
"autoSourceLayerDefUid": None,
|
|
"tilesetDefUid": None,
|
|
"tilePivotX": 0,
|
|
"tilePivotY": 0
|
|
}
|
|
|
|
# 3. AUTO LAYERS (The "Visuals")
|
|
layer_defs = [int_grid_def]
|
|
layer_uid = 300
|
|
rule_uid_counter = 5000
|
|
|
|
# Simplified tiles list: just index 0 for now to ensure it works, or random list
|
|
# 512x512 with 32x32 tiles has 16 * 16 = 256 tiles.
|
|
# Let's use indices 0..15 (first row) to be safe for texture variety
|
|
tile_ids_list = list(range(16))
|
|
|
|
mapping = [
|
|
("View_Grass", ts_grass['uid'], 1),
|
|
("View_Dirt", ts_dirt['uid'], 2),
|
|
("View_Water", ts_water['uid'], 3),
|
|
("View_Farm", ts_farm['uid'], 4)
|
|
]
|
|
|
|
for ident, ts_uid, val in mapping:
|
|
auto_layer = {
|
|
"__type": "AutoLayer",
|
|
"identifier": ident,
|
|
"type": "AutoLayer",
|
|
"uid": layer_uid,
|
|
"gridSize": 32,
|
|
"displayOpacity": 1,
|
|
"pxOffsetX": 0,
|
|
"pxOffsetY": 0,
|
|
"autoSourceLayerDefUid": intgrid_uid, # LINKED TO INTGRID
|
|
"tilesetDefUid": ts_uid,
|
|
"tilePivotX": 0,
|
|
"tilePivotY": 0,
|
|
"autoRuleGroups": [{
|
|
"uid": rule_uid_counter,
|
|
"name": "Full_Fill",
|
|
"active": True,
|
|
"isOptional": False,
|
|
"rules": [
|
|
{
|
|
"uid": rule_uid_counter + 1,
|
|
"active": True,
|
|
"size": 1,
|
|
"tileIds": tile_ids_list, # Random tile from first row
|
|
"alpha": 1,
|
|
"chance": 1,
|
|
"breakOnMatch": True,
|
|
"pattern": [val], # CHECK FOR THE SPECIFIC INTGRID VALUE (1, 2, 3, or 4)
|
|
"flipX": True,
|
|
"flipY": True,
|
|
"xModulo": 1, "yModulo": 1,
|
|
"checker": "None",
|
|
"tileMode": "Random",
|
|
"pivotX": 0, "pivotY": 0,
|
|
"outTileIds": [], "perlinActive": False, "perlinSeed": 0, "perlinScale": 0.2, "perlinOctaves": 2
|
|
}
|
|
]
|
|
}]
|
|
}
|
|
layer_defs.append(auto_layer)
|
|
layer_uid += 1
|
|
rule_uid_counter += 100
|
|
|
|
data['defs']['layers'] = layer_defs[::-1] # Reverse order so Control is bottom or top?
|
|
# LDtk renders bottom-to-top of list? No, usually list order is Top to Bottom in UI.
|
|
# We want Control on TOP or visible separately.
|
|
# Actually in LDtk JSON, first in list = top layer.
|
|
# Let's keep IntGrid (Control) FIRST so it's on top for editing.
|
|
|
|
# 4. LEVEL SETUP
|
|
data['levels'] = [{
|
|
"identifier": "Level_0",
|
|
"iid": "level_0_iid",
|
|
"uid": 0,
|
|
"worldX": 0, "worldY": 0, "worldDepth": 0,
|
|
"pxWid": 512, "pxHei": 512,
|
|
"__bgColor": "#696A79",
|
|
"bgColor": None,
|
|
"useAutoIdentifier": True,
|
|
"bgRelPath": None,
|
|
"bgPos": None,
|
|
"bgPivotX": 0.5, "bgPivotY": 0.5,
|
|
"__smartColor": "#ADADB5",
|
|
"__bgPos": None,
|
|
"externalRelPath": None,
|
|
"fieldInstances": [],
|
|
"layerInstances": [
|
|
|
|
# Creating valid layer instances to match defs is good practice to avoid errors
|
|
],
|
|
"__neighbours": []
|
|
}]
|
|
|
|
# Generate empty layer instances structure
|
|
layer_instances = []
|
|
# Order matches definitions
|
|
for l_def in data['defs']['layers']:
|
|
inst = {
|
|
"__identifier": l_def["identifier"],
|
|
"__type": l_def["type"],
|
|
"__cWid": 16,
|
|
"__cHei": 16,
|
|
"__gridSize": 32,
|
|
"__opacity": 1,
|
|
"__pxTotalOffsetX": 0,
|
|
"__pxTotalOffsetY": 0,
|
|
"__tilesetDefUid": l_def.get("tilesetDefUid"),
|
|
"__tilesetRelPath": None,
|
|
"iid": f"inst_{l_def['uid']}",
|
|
"levelId": 0,
|
|
"layerDefUid": l_def["uid"],
|
|
"pxOffsetX": 0, "pxOffsetY": 0,
|
|
"visible": True,
|
|
"optionalRules": [],
|
|
"intGridCsv": [], # Empty grid
|
|
"autoLayerTiles": [],
|
|
"seed": 0,
|
|
"overrideTilesetUid": None,
|
|
"gridTiles": [],
|
|
"entityInstances": []
|
|
}
|
|
# Fill IntGridCsv with 0s for the IntGrid layer
|
|
if l_def["type"] == "IntGrid":
|
|
inst["intGridCsv"] = [0] * (16 * 16)
|
|
|
|
layer_instances.append(inst)
|
|
|
|
data['levels'][0]['layerInstances'] = layer_instances
|
|
|
|
with open(LDTK_FILE, 'w') as f:
|
|
json.dump(data, f, indent=2)
|
|
|
|
print("LDtk fixed and updated successfully!")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|