diff --git a/TODO.md b/TODO.md index 3ebb036..7a9e5ff 100644 --- a/TODO.md +++ b/TODO.md @@ -5,6 +5,8 @@ - make hashmap grid type - in-game editor for adding removing hexes to line up with terrain/indoor meshes - need to update json schema with "oneOf" to validate different grid types + - find a better alternative to g_data_dir in scene_loader.cpp + - make and validate json schema for grid hash_map - position entities on grid hexes - gooey - add object inspector window diff --git a/data/hashmap_scene_hexmap.json b/data/hashmap_scene_hexmap.json index 39017d8..8b13789 100644 --- a/data/hashmap_scene_hexmap.json +++ b/data/hashmap_scene_hexmap.json @@ -1 +1 @@ -{"hex_size":10,"layout_mode":"layout_flat","world_position":{"x":0.0,"y":0.0,"z":0.0},"world_normal":{"x":0.0,"y":0.0,"z":1.0},"hexes":[{"XPos":195.0,"YPos":25.98076211353316,"q":13,"r":-5,"s":-8,"vertices":[{"x":205.0,"y":25.980762481689454,"z":0.0},{"x":200.0,"y":17.32050895690918,"z":0.0},{"x":190.0,"y":17.32050895690918,"z":0.0},{"x":185.0,"y":25.980762481689454,"z":0.0},{"x":190.0,"y":34.64101791381836,"z":0.0},{"x":200.0,"y":34.64101791381836,"z":0.0}]},{"XPos":210.0,"YPos":17.320508075688769,"q":14,"r":-6,"s":-8,"vertices":[{"x":220.0,"y":17.32050895690918,"z":0.0},{"x":215.0,"y":8.66025447845459,"z":0.0},{"x":205.0,"y":8.66025447845459,"z":0.0},{"x":200.0,"y":17.32050895690918,"z":0.0},{"x":205.0,"y":25.980762481689454,"z":0.0},{"x":215.0,"y":25.980762481689454,"z":0.0}]},{"XPos":210.0,"YPos":0.0,"q":14,"r":-7,"s":-7,"vertices":[{"x":220.0,"y":0.0,"z":0.0},{"x":215.0,"y":-8.66025447845459,"z":0.0},{"x":205.0,"y":-8.66025447845459,"z":0.0},{"x":200.0,"y":-1.2246467996456087e-15,"z":0.0},{"x":205.0,"y":8.66025447845459,"z":0.0},{"x":215.0,"y":8.66025447845459,"z":0.0}]},{"XPos":210.0,"YPos":-34.641016151377538,"q":14,"r":-9,"s":-5,"vertices":[{"x":220.0,"y":-34.64101791381836,"z":0.0},{"x":215.0,"y":-43.30126953125,"z":0.0},{"x":205.0,"y":-43.30126953125,"z":0.0},{"x":200.0,"y":-34.64101791381836,"z":0.0},{"x":205.0,"y":-25.980762481689454,"z":0.0},{"x":215.0,"y":-25.980762481689454,"z":0.0}]},{"XPos":195.0,"YPos":43.301270189221927,"q":13,"r":-4,"s":-9,"vertices":[{"x":205.0,"y":43.30126953125,"z":0.0},{"x":200.0,"y":34.64101791381836,"z":0.0},{"x":190.0,"y":34.64101791381836,"z":0.0},{"x":185.0,"y":43.30126953125,"z":0.0},{"x":190.0,"y":51.961524963378909,"z":0.0},{"x":200.0,"y":51.961524963378909,"z":0.0}]},{"XPos":210.0,"YPos":-69.28203230275509,"q":14,"r":-11,"s":-3,"vertices":[{"x":220.0,"y":-69.28203582763672,"z":0.0},{"x":215.0,"y":-77.9422836303711,"z":0.0},{"x":205.0,"y":-77.9422836303711,"z":0.0},{"x":200.0,"y":-69.28203582763672,"z":0.0},{"x":205.0,"y":-60.62177658081055,"z":0.0},{"x":215.0,"y":-60.62177658081055,"z":0.0}]},{"XPos":195.0,"YPos":60.621778264910698,"q":13,"r":-3,"s":-10,"vertices":[{"x":205.0,"y":60.62177658081055,"z":0.0},{"x":200.0,"y":51.961524963378909,"z":0.0},{"x":190.0,"y":51.961524963378909,"z":0.0},{"x":185.0,"y":60.62177658081055,"z":0.0},{"x":190.0,"y":69.28203582763672,"z":0.0},{"x":200.0,"y":69.28203582763672,"z":0.0}]},{"XPos":210.0,"YPos":-86.60254037844388,"q":14,"r":-12,"s":-2,"vertices":[{"x":220.0,"y":-86.6025390625,"z":0.0},{"x":215.0,"y":-95.2627944946289,"z":0.0},{"x":205.0,"y":-95.2627944946289,"z":0.0},{"x":200.0,"y":-86.6025390625,"z":0.0},{"x":205.0,"y":-77.9422836303711,"z":0.0},{"x":215.0,"y":-77.9422836303711,"z":0.0}]},{"XPos":105.0,"YPos":-112.58330249197701,"q":7,"r":-10,"s":3,"vertices":[{"x":115.0,"y":-112.58330535888672,"z":0.0},{"x":110.0,"y":-121.2435531616211,"z":0.0},{"x":100.0,"y":-121.2435531616211,"z":0.0},{"x":95.0,"y":-112.58330535888672,"z":0.0},{"x":100.0,"y":-103.92304992675781,"z":0.0},{"x":110.0,"y":-103.92304992675781,"z":0.0}]},{"XPos":60.0,"YPos":-155.88457268119897,"q":4,"r":-11,"s":7,"vertices":[{"x":70.0,"y":-155.8845672607422,"z":0.0},{"x":65.0,"y":-164.54483032226563,"z":0.0},{"x":55.0,"y":-164.54483032226563,"z":0.0},{"x":50.0,"y":-155.8845672607422,"z":0.0},{"x":55.0,"y":-147.2243194580078,"z":0.0},{"x":65.0,"y":-147.2243194580078,"z":0.0}]},{"XPos":75.0,"YPos":-129.90381056766578,"q":5,"r":-10,"s":5,"vertices":[{"x":85.0,"y":-129.90380859375,"z":0.0},{"x":80.0,"y":-138.56407165527345,"z":0.0},{"x":70.0,"y":-138.56407165527345,"z":0.0},{"x":65.0,"y":-129.90380859375,"z":0.0},{"x":70.0,"y":-121.2435531616211,"z":0.0},{"x":80.0,"y":-121.2435531616211,"z":0.0}]},{"XPos":210.0,"YPos":-17.320508075688769,"q":14,"r":-8,"s":-6,"vertices":[{"x":220.0,"y":-17.32050895690918,"z":0.0},{"x":215.0,"y":-25.980762481689454,"z":0.0},{"x":205.0,"y":-25.980762481689454,"z":0.0},{"x":200.0,"y":-17.32050895690918,"z":0.0},{"x":205.0,"y":-8.66025447845459,"z":0.0},{"x":215.0,"y":-8.66025447845459,"z":0.0}]},{"XPos":75.0,"YPos":-147.22431864335457,"q":5,"r":-11,"s":6,"vertices":[{"x":85.0,"y":-147.2243194580078,"z":0.0},{"x":80.0,"y":-155.8845672607422,"z":0.0},{"x":70.0,"y":-155.8845672607422,"z":0.0},{"x":65.0,"y":-147.2243194580078,"z":0.0},{"x":70.0,"y":-138.56407165527345,"z":0.0},{"x":80.0,"y":-138.56407165527345,"z":0.0}]},{"XPos":45.0,"YPos":-129.90381056766578,"q":3,"r":-9,"s":6,"vertices":[{"x":55.0,"y":-129.90380859375,"z":0.0},{"x":50.0,"y":-138.56407165527345,"z":0.0},{"x":40.0,"y":-138.56407165527345,"z":0.0},{"x":35.0,"y":-129.90380859375,"z":0.0},{"x":40.0,"y":-121.2435531616211,"z":0.0},{"x":50.0,"y":-121.2435531616211,"z":0.0}]},{"XPos":60.0,"YPos":-138.56406460551018,"q":4,"r":-10,"s":6,"vertices":[{"x":70.0,"y":-138.56407165527345,"z":0.0},{"x":65.0,"y":-147.2243194580078,"z":0.0},{"x":55.0,"y":-147.2243194580078,"z":0.0},{"x":50.0,"y":-138.56407165527345,"z":0.0},{"x":55.0,"y":-129.90380859375,"z":0.0},{"x":65.0,"y":-129.90380859375,"z":0.0}]},{"XPos":210.0,"YPos":-51.961524227066309,"q":14,"r":-10,"s":-4,"vertices":[{"x":220.0,"y":-51.961524963378909,"z":0.0},{"x":215.0,"y":-60.62177658081055,"z":0.0},{"x":205.0,"y":-60.62177658081055,"z":0.0},{"x":200.0,"y":-51.961524963378909,"z":0.0},{"x":205.0,"y":-43.30126953125,"z":0.0},{"x":215.0,"y":-43.30126953125,"z":0.0}]},{"XPos":90.0,"YPos":-121.24355652982139,"q":6,"r":-10,"s":4,"vertices":[{"x":100.0,"y":-121.2435531616211,"z":0.0},{"x":95.0,"y":-129.90380859375,"z":0.0},{"x":85.0,"y":-129.90380859375,"z":0.0},{"x":80.0,"y":-121.2435531616211,"z":0.0},{"x":85.0,"y":-112.58330535888672,"z":0.0},{"x":95.0,"y":-112.58330535888672,"z":0.0}]},{"XPos":45.0,"YPos":-147.22431864335455,"q":3,"r":-10,"s":7,"vertices":[{"x":55.0,"y":-147.2243194580078,"z":0.0},{"x":50.0,"y":-155.8845672607422,"z":0.0},{"x":40.0,"y":-155.8845672607422,"z":0.0},{"x":35.0,"y":-147.2243194580078,"z":0.0},{"x":40.0,"y":-138.56407165527345,"z":0.0},{"x":50.0,"y":-138.56407165527345,"z":0.0}]},{"XPos":180.0,"YPos":-103.92304845413264,"q":12,"r":-12,"s":0,"vertices":[{"x":190.0,"y":-103.92304992675781,"z":0.0},{"x":185.0,"y":-112.58330535888672,"z":0.0},{"x":175.0,"y":-112.58330535888672,"z":0.0},{"x":170.0,"y":-103.92304992675781,"z":0.0},{"x":175.0,"y":-95.2627944946289,"z":0.0},{"x":185.0,"y":-95.2627944946289,"z":0.0}]},{"XPos":60.0,"YPos":-121.24355652982139,"q":4,"r":-9,"s":5,"vertices":[{"x":70.0,"y":-121.2435531616211,"z":0.0},{"x":65.0,"y":-129.90380859375,"z":0.0},{"x":55.0,"y":-129.90380859375,"z":0.0},{"x":50.0,"y":-121.2435531616211,"z":0.0},{"x":55.0,"y":-112.58330535888672,"z":0.0},{"x":65.0,"y":-112.58330535888672,"z":0.0}]},{"XPos":120.0,"YPos":-121.2435565298214,"q":8,"r":-11,"s":3,"vertices":[{"x":130.0,"y":-121.2435531616211,"z":0.0},{"x":125.0,"y":-129.90380859375,"z":0.0},{"x":115.0,"y":-129.90380859375,"z":0.0},{"x":110.0,"y":-121.2435531616211,"z":0.0},{"x":115.0,"y":-112.58330535888672,"z":0.0},{"x":125.0,"y":-112.58330535888672,"z":0.0}]},{"XPos":135.0,"YPos":-112.58330249197701,"q":9,"r":-11,"s":2,"vertices":[{"x":145.0,"y":-112.58330535888672,"z":0.0},{"x":140.0,"y":-121.2435531616211,"z":0.0},{"x":130.0,"y":-121.2435531616211,"z":0.0},{"x":125.0,"y":-112.58330535888672,"z":0.0},{"x":130.0,"y":-103.92304992675781,"z":0.0},{"x":140.0,"y":-103.92304992675781,"z":0.0}]},{"XPos":150.0,"YPos":-121.24355652982143,"q":10,"r":-12,"s":2,"vertices":[{"x":160.0,"y":-121.2435531616211,"z":0.0},{"x":155.0,"y":-129.90380859375,"z":0.0},{"x":145.0,"y":-129.90380859375,"z":0.0},{"x":140.0,"y":-121.2435531616211,"z":0.0},{"x":145.0,"y":-112.58330535888672,"z":0.0},{"x":155.0,"y":-112.58330535888672,"z":0.0}]},{"XPos":165.0,"YPos":-112.58330249197704,"q":11,"r":-12,"s":1,"vertices":[{"x":175.0,"y":-112.58330535888672,"z":0.0},{"x":170.0,"y":-121.2435531616211,"z":0.0},{"x":160.0,"y":-121.2435531616211,"z":0.0},{"x":155.0,"y":-112.58330535888672,"z":0.0},{"x":160.0,"y":-103.92304992675781,"z":0.0},{"x":170.0,"y":-103.92304992675781,"z":0.0}]},{"XPos":195.0,"YPos":-95.26279441628827,"q":13,"r":-12,"s":-1,"vertices":[{"x":205.0,"y":-95.2627944946289,"z":0.0},{"x":200.0,"y":-103.92304992675781,"z":0.0},{"x":190.0,"y":-103.92304992675781,"z":0.0},{"x":185.0,"y":-95.2627944946289,"z":0.0},{"x":190.0,"y":-86.6025390625,"z":0.0},{"x":200.0,"y":-86.6025390625,"z":0.0}]}]} \ No newline at end of file + diff --git a/src/hexgame.cpp b/src/hexgame.cpp index 12d3b1a..f313ea9 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -46,6 +46,7 @@ static vector g_polygon_select_vertices = {Point(), Point(), Point(), Poi bool loadSceneFromJson(game_state* s, render_state* rs) { + bool ret = true; slSceneDoc* sd = slLoadFile(DATA_DIR, DEFAULT_SCENE_FILE, SCENE_SCHEMA_FILE); if (sd != nullptr) { @@ -54,35 +55,35 @@ loadSceneFromJson(game_state* s, render_state* rs) if (!slParseEntities(sd, gs->entities, gs->entity_count, MAX_ENTITIES, DATA_DIR)) { LOG(ERROR) << "Error loading Entities, exiting\n"; - slFreeSceneDoc(sd); - return false; + ret = false; } slParseCamera(sd, rs->cam); slParseHexGrid(sd, gs->grid, rs->palette_image); if (slCreateHexRenderGroups(gs->grid, rs)) { - if (!hgInit(gs->grid, rs->filled_hex_render_group, rs->hex_line_render_group, DATA_DIR)) { - slFreeSceneDoc(sd); - return false; + if (gs->grid.gridT == HASH_MAP) { + if (!slParseGridHashMap(gs->grid, DATA_DIR)) + ret = false; } + + if (!hgInit(gs->grid, rs->filled_hex_render_group, rs->hex_line_render_group)) + ret = false; } else { LOG(ERROR) << "Error creating hexgrid render groups\n"; - slFreeSceneDoc(sd); - return false; + ret = false; } if (!slParseLights(sd, rs->lights, rs->num_lights, rs->max_lights)) { LOG(ERROR) << "Error loading lights, exiting\n"; - slFreeSceneDoc(sd); - return false; + ret = false; } } else { - return false; + ret = false; } slFreeSceneDoc(sd); - return true; + return ret; } bool diff --git a/src/hexgrid.cpp b/src/hexgrid.cpp index 7fdc04a..1d2fa3d 100644 --- a/src/hexgrid.cpp +++ b/src/hexgrid.cpp @@ -7,7 +7,6 @@ // forward declarations hex_info createHexInfo(hexgrid& hg, int q, int r); void createHexagonGrid(hexgrid& hg); -bool createHashMapGrid(hexgrid& hg, const char* data_dir); void populateFilledHexGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_filled); void populateLineGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_lines); @@ -15,7 +14,7 @@ void populateLineGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_lines); // interface bool -hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines, const char* data_dir) +hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines) { Orientation o = (hg.layout_mode == LAYOUT_FLAT) ? layout_flat : layout_pointy; hg.hexlib_layout = Layout(o, Point(hg.hex_size, hg.hex_size), Point(hg.position.x, hg.position.y)); @@ -24,9 +23,7 @@ hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines, const char* case HEXAGON: createHexagonGrid(hg); break; - case HASH_MAP: - if (!createHashMapGrid(hg, data_dir)) - return false; + case HASH_MAP: // NOTE: for HASH_MAP the file will be parsed in scene_loader break; default: LOG(ERROR) << "Unhandled grid type\n"; @@ -345,23 +342,6 @@ createHexagonGrid(hexgrid& hg) } } -bool -createHashMapGrid(hexgrid& hg, const char* data_dir) -{ - LOG(DEBUG) << "starting createHashMapGrid with map_file: " << hg.map_file << "\n"; - - uint max_len = 256; - char full_path[max_len]; - if (utilConcatPath(full_path, data_dir, hg.map_file, max_len)) { - char* hashmap_contents = utilDumpTextFile(full_path); - // parse contents - // insert hexes into hex_map - return true; - } - - return false; -} - void populateFilledHexGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_filled) { diff --git a/src/hexgrid.h b/src/hexgrid.h index 796cef3..53e60c6 100644 --- a/src/hexgrid.h +++ b/src/hexgrid.h @@ -87,7 +87,7 @@ struct hexgrid }; -bool hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines, const char* data_dir); +bool hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines); bool hgAddHex(hexgrid& hg, v3f hex_coords, render_group* rg_filled, render_group* rg_lines); diff --git a/src/scene_loader.cpp b/src/scene_loader.cpp index 27c266f..29549f8 100644 --- a/src/scene_loader.cpp +++ b/src/scene_loader.cpp @@ -26,7 +26,8 @@ static const char* g_data_dir; // forward declarations -bool parseFile(rapidjson::Document* doc, const char* data_dir, const char* file_name); +bool loadTextFile(char*& output, const char* data_dir, const char* file_name); +bool parseFile(rapidjson::Document* doc, const char* file_contents, const char* file_name); glm::vec3 parseVec3(const rapidjson::Value& node); glm::vec4 parseVec4(const rapidjson::Value& node); bool validateScene(rapidjson::Document* schema_doc, rapidjson::Document* scene_doc, @@ -44,8 +45,18 @@ slLoadFile(const char* data_dir, const char* scene_file, const char* schema_file slSceneDoc* sd = UTIL_ALLOC(1, slSceneDoc); sd->doc = new rapidjson::Document(); - bool retDoc = parseFile(sd->doc, data_dir, scene_file); - bool retSchema = parseFile(&schema_doc, data_dir, schema_file); + bool retDoc, retSchema = false; + + char* scene_contents; + if (loadTextFile(scene_contents, data_dir, scene_file)) + retDoc = parseFile(sd->doc, scene_contents, scene_file); + + char* schema_contents; + if (loadTextFile(schema_contents, data_dir, schema_file)) + retSchema = parseFile(&schema_doc, schema_contents, schema_file); + + utilSafeFree(scene_contents); + utilSafeFree(schema_contents); if (!retDoc || !retSchema || !validateScene(&schema_doc, sd->doc, scene_file)) { slFreeSceneDoc(sd); @@ -151,6 +162,65 @@ slParseHexGrid(slSceneDoc* sd, hexgrid& hg, util_image& palette_image) hg.layout_mode = (orientation_str == "layout_flat") ? LAYOUT_FLAT : LAYOUT_POINTY; } +bool +slParseGridHashMap(hexgrid& hg, const char* data_dir) +{ + LOG(DEBUG) << "loading map_file: " << hg.map_file << "\n"; + char* contents; + + if (!loadTextFile(contents, data_dir, hg.map_file)) + return false; + + // NOTE: allow creating/saving over blank files + if (contents[0] == 0 || contents[0] == '\n') { + utilSafeFree(contents); + LOG(INFO) << "empty map file\n"; + return true; + } + + // TODO: still need a schema for the hashmap + rapidjson::Document doc; + bool ret = false; + + if (parseFile(&doc, contents, hg.map_file)) { + hg.hex_size = doc["hex_size"].GetInt(); + std::string orientation_str = doc["layout_mode"].GetString(); + hg.layout_mode = (orientation_str == "layout_flat") ? LAYOUT_FLAT : LAYOUT_POINTY; + glm::vec3 v = parseVec3(doc["world_position"]); + hg.position.x = v.x; hg.position.y = v.y; hg.position.z = v.z; + glm::vec3 n = parseVec3(doc["world_normal"]); + hg.normal.x = n.x; hg.normal.y = n.y; hg.normal.z = n.z; + rapidjson::Value& hexes = doc["hexes"]; + + for (uint i = 0; i < doc["hexes"].Size(); i++) { + // TODO: could re-use hexgrid.createHexInfo() here + hex_info hxi; + hxi.hexID = i; + hxi.selected = false; + hxi.XPos = hexes[i]["XPos"].GetFloat(); + hxi.YPos = hexes[i]["YPos"].GetFloat(); + hxi.hex.q = hexes[i]["q"].GetInt(); + hxi.hex.r = hexes[i]["r"].GetInt(); + hxi.hex.s = hexes[i]["s"].GetInt(); + + for (uint j = 0; j < hexes[i]["vertices"].Size(); j++) { + rapidjson::Value& v = hexes[i]["vertices"][j]; + glm::vec3 v3 = parseVec3(v); + Point p(v3.x, v3.y); + hxi.vertices.push_back(p); + } + + hxi.vertices.shrink_to_fit(); + hg.hex_map.insert({hxi.hex, hxi}); + } + + ret = true; + } + + utilSafeFree(contents); + return ret; +} + bool slCreateHexRenderGroups(hexgrid& hg, render_state* rs) { @@ -262,29 +332,33 @@ slSaveGridFile(hexgrid& hg) // internal bool -parseFile(rapidjson::Document* doc, const char* data_dir, const char* file_name) +loadTextFile(char*& output, const char* data_dir, const char* file_name) { bool ret = true; std::string file_path; file_path.append(data_dir).append("/").append(file_name); - char* contents = utilDumpTextFile(file_path.c_str()); + output = utilDumpTextFile(file_path.c_str()); - if (contents == nullptr) { + if (output == nullptr) { LOG(ERROR) << "Error reading file: " << file_name << "\n"; ret = false; } - rapidjson::ParseResult pr = doc->Parse(contents/*, rapidjson::kParseStopWhenDoneFlag*/); + return ret; +} + +bool +parseFile(rapidjson::Document* doc, const char* file_contents, const char* file_name) +{ + rapidjson::ParseResult pr = doc->Parse(file_contents); if (!pr || !doc->IsObject()) { - LOG(ERROR) << "Error parrsing scene file: " << file_name << "\n"; + LOG(ERROR) << "Error parrsing json file: " << file_name << "\n"; LOG(ERROR) << "Error desscription: " << rapidjson::GetParseError_En(pr.Code()) << " (" << pr.Offset() << ")\n"; - ret = false; + return false; } - utilSafeFree(contents); - - return ret; + return true; } bool diff --git a/src/scene_loader.h b/src/scene_loader.h index a92b41d..b670b78 100644 --- a/src/scene_loader.h +++ b/src/scene_loader.h @@ -27,6 +27,8 @@ void slParseCamera(slSceneDoc* sd, camera& cam); void slParseHexGrid(slSceneDoc* sd, hexgrid& hg, util_image& palette_image); +bool slParseGridHashMap(hexgrid& hg, const char* data_dir); + bool slCreateHexRenderGroups(hexgrid& hg, render_state* rs); bool slParseLights(slSceneDoc* sd, rg_point_light* lights, uint& num_lights, uint max_lights);