diff --git a/data/events/test_event.json b/data/events/test_event.json new file mode 100644 index 0000000..c23ed8d --- /dev/null +++ b/data/events/test_event.json @@ -0,0 +1,14 @@ +{ + "key": "test_event", + "items": [ + { + "type": "text", + "texts": [ + "This is a bucket", + "Dear God", + "There's more!", + "No!" + ] + } + ] +} \ No newline at end of file diff --git a/data/map project.tiled-session b/data/map project.tiled-session index d145a65..5157b4f 100644 --- a/data/map project.tiled-session +++ b/data/map project.tiled-session @@ -1,8 +1,8 @@ { "activeFile": "map.tmj", "expandedProjectPaths": [ - "templates", - "." + ".", + "templates" ], "fileStates": { ":/automap-tiles.tsx": { @@ -16,8 +16,8 @@ "scale": 3, "selectedLayer": 2, "viewCenter": { - "x": 6585.833333333333, - "y": 6840.833333333333 + "x": 6603.333333333333, + "y": 6846.5 } }, "minogram.tsx": { @@ -33,14 +33,15 @@ "last.imagePath": "/home/yourwishes/htdocs/dusk/data", "last.objectTemplatePath": "/home/yourwishes/htdocs/dusk/data/templates", "openFiles": [ - "map.tmj" + "map.tmj", + "overworld.tsx" ], "project": "map project.tiled-project", "property.type": "tileSolidType", "recentFiles": [ + "overworld.tsx", "map.tmj", "minogram.tsx", - "overworld.tsx", "entities.tsx" ], "tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)", diff --git a/data/map.tmj b/data/map.tmj index 14a38ff..739284f 100644 --- a/data/map.tmj +++ b/data/map.tmj @@ -438,7 +438,7 @@ }], "template":"templates\/NPC.tx", "x":6539.95833333333, - "y":6849.33333333333 + "y":6849.66666666666 }], "opacity":1, "type":"objectgroup", diff --git a/src/dusk/event/event.c b/src/dusk/event/event.c new file mode 100644 index 0000000..0def703 --- /dev/null +++ b/src/dusk/event/event.c @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "event.h" \ No newline at end of file diff --git a/src/dusk/event/event.h b/src/dusk/event/event.h new file mode 100644 index 0000000..edab15b --- /dev/null +++ b/src/dusk/event/event.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "eventtext.h" + +typedef enum { + EVENT_TYPE_NULL = 0, + EVENT_TYPE_TEXT, +} eventtype_t; + +typedef struct _eventitem_t { + eventtype_t type; + + union { + eventtext_t texts; + }; +} eventitem_t; + +#define EVENT_ITEM_COUNT_MAX 32 + +typedef struct { + uint8_t itemCount; + eventitem_t items[EVENT_ITEM_COUNT_MAX]; +} event_t; \ No newline at end of file diff --git a/src/dusk/event/eventtext.h b/src/dusk/event/eventtext.h new file mode 100644 index 0000000..2ebd7ac --- /dev/null +++ b/src/dusk/event/eventtext.h @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct _eventitem_t eventitem_t; + +#define EVENT_TEXT_STRING_COUNT_MAX 8 + +typedef const char_t* eventtext_t[EVENT_TEXT_STRING_COUNT_MAX]; \ No newline at end of file diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 8544a21..c9b0d81 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -4,7 +4,8 @@ # https://opensource.org/licenses/MIT # Tools -add_subdirectory(mapcompile) -add_subdirectory(tilecompile) +add_subdirectory(eventcompile) add_subdirectory(fontcompile) -add_subdirectory(languagecompile) \ No newline at end of file +add_subdirectory(languagecompile) +add_subdirectory(mapcompile) +add_subdirectory(tilecompile) \ No newline at end of file diff --git a/tools/eventcompile/CMakeLists.txt b/tools/eventcompile/CMakeLists.txt new file mode 100644 index 0000000..daf1f97 --- /dev/null +++ b/tools/eventcompile/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +find_package(Python3 COMPONENTS Interpreter REQUIRED) + +# Custom command to generate all header files +add_custom_target(DUSK_EVENTS + COMMAND + ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/eventcompile.py + --output ${DUSK_GENERATED_HEADERS_DIR}/event/ + --input ${DUSK_DATA_DIR}/events/ + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/eventcompile.py + COMMENT "Generating event header files" + VERBATIM +) + +# Ensure headers are generated before compiling main +add_dependencies(${DUSK_TARGET_NAME} DUSK_EVENTS) \ No newline at end of file diff --git a/tools/eventcompile/eventcompile.py b/tools/eventcompile/eventcompile.py new file mode 100644 index 0000000..1dc9ec7 --- /dev/null +++ b/tools/eventcompile/eventcompile.py @@ -0,0 +1,90 @@ +import sys, os +import argparse +from datetime import datetime +import json + +# Check if the script is run with the correct arguments +parser = argparse.ArgumentParser(description="Generate event header files") +parser.add_argument('--output', required=True, help='Dir to write headers') +parser.add_argument('--input', required=True, help='Input directory containing event files') +args = parser.parse_args() + +# Ensure outdir exists +outputFile = args.output +outputDir = args.output +os.makedirs(outputDir, exist_ok=True) + +inputDir = args.input +# Scan for .json files in the input directory +if not os.path.exists(inputDir): + print(f"Error: Input directory '{inputDir}' does not exist.") + sys.exit(1) + +jsonFiles = [f for f in os.listdir(inputDir) if f.endswith('.json')] +if not jsonFiles or len(jsonFiles) == 0: + print(f"Error: No JSON files found in '{inputDir}'.") + sys.exit(1) + +# For each language file... +now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + +eventFiles = [] + +for jsonFile in jsonFiles: + inputFile = os.path.join(inputDir, jsonFile) + data = json.load(open(inputFile, 'r', encoding='utf-8')) + + if 'key' not in data: + print(f"Error: JSON file '{inputFile}' does not contain 'key' field.") + sys.exit(1) + + if 'items' not in data or not isinstance(data['items'], list) or len(data['items']) == 0: + print(f"Error: JSON file '{inputFile}' does not contain 'items' field.") + sys.exit(1) + + key = data['key'] + keyUpper = key.upper() + + if jsonFile != f'{key}.json': + print(f"Error: JSON file '{jsonFile}' does not match expected filename '{key}.json'.") + sys.exit(1) + + outputFile = os.path.join(outputDir, f"{key}.h") + + with open(outputFile, 'w', encoding='utf-8') as f: + f.write(f"// Generated event header for {jsonFile}\n") + f.write(f"// Generated at {now}\n") + f.write("#pragma once\n\n") + f.write("#include \"event/event.h\"\n\n") + f.write(f"static const event_t EVENT_{key.upper()} = {{\n") + f.write(f" .itemCount = {len(data['items'])},\n") + f.write(f" .items = {{\n") + for i, item in enumerate(data['items']): + if 'type' not in item: + print(f"Error: Item {i} in '{jsonFile}' does not contain 'type' field.") + sys.exit(1) + + itemType = item['type'] + f.write(f" {{\n") + + # Text(s) Type + if itemType == 'text': + if 'texts' not in item or not isinstance(item['texts'], list) or len(item['texts']) == 0: + print(f"Error: Item {i} in '{jsonFile}' of type 'text' does not contain 'texts' field.") + sys.exit(1) + f.write(f" .type = EVENT_TYPE_TEXT,\n") + f.write(f" .texts = {{\n") + for text in item['texts']: + f.write(f" \"{text}\",\n") + f.write(f" }},\n") + + + else: + print(f"Error: Unknown item type '{itemType}' in item {i} of '{jsonFile}'.") + sys.exit(1) + + f.write(f" }},\n") + f.write(f" }},\n") + f.write(f"}};\n\n") + + eventFiles.append(key) \ No newline at end of file