Now access buildings externally only by string keys

This commit is contained in:
2024-10-01 12:40:38 +03:00
parent 5e6bcedd09
commit b6971322f2
7 changed files with 102 additions and 114 deletions

View File

@@ -97,6 +97,14 @@ void BuildingsData::update_building_transform(const String &key,
get_building(key).xform = xform; get_building(key).xform = xform;
} }
bool BuildingsData::has_building(const String &key)
{
int index = get_building_by_key(key);
if (index >= 0)
return true;
return false;
}
String BuildingsData::get_closest_building(const Transform &xform) String BuildingsData::get_closest_building(const Transform &xform)
{ {
int i; int i;
@@ -724,18 +732,18 @@ struct BuildingsData::building *BuildingsData::get_building_ptr(int index)
return &buildings_[index]; return &buildings_[index];
} }
int BuildingsData::create_building(const Dictionary &dict) String BuildingsData::create_building(const Dictionary &dict)
{ {
struct building b; struct building b;
building::from_dict(&b, dict); building::from_dict(&b, dict);
return create_building(b); return create_building(b);
} }
int BuildingsData::create_building(const struct building &building) String BuildingsData::create_building(const struct building &building)
{ {
int index = get_building_count(); assert(building.key.length() > 0);
buildings_.push_back(building); buildings_.push_back(building);
return index; return building.key;
} }
void BuildingsData::for_each_building(callme &c) void BuildingsData::for_each_building(callme &c)
@@ -769,14 +777,15 @@ void BuildingsData::get_building_keys_list(List<String> *keys)
keys->push_back(buildings_[i].key); keys->push_back(buildings_[i].key);
} }
int BuildingsData::create_building(const building *building) String BuildingsData::create_building(const building *building)
{ {
assert(building); assert(building);
return create_building(*building); return create_building(*building);
} }
bool BuildingsData::destroy_building(int index) bool BuildingsData::destroy_building(const String &key)
{ {
int index = get_building_by_key(key);
assert(index >= 0 && index < get_building_count()); assert(index >= 0 && index < get_building_count());
buildings_.erase(buildings_.begin() + index); buildings_.erase(buildings_.begin() + index);
return true; return true;

View File

@@ -46,9 +46,9 @@ public:
// void item_nodes_set_node(const String &key, Node *node); // void item_nodes_set_node(const String &key, Node *node);
void item_nodes_item_removed(const String &key); void item_nodes_item_removed(const String &key);
Node *item_nodes_get_node(const String &key) const; Node *item_nodes_get_node(const String &key) const;
String item_nodes_get_key(int item) const;
private: private:
String item_nodes_get_key(int item) const;
Error scene_loader_poll(const String &key); Error scene_loader_poll(const String &key);
public: public:
@@ -111,10 +111,10 @@ public:
void get_building_keys_list(List<String> *keys); void get_building_keys_list(List<String> *keys);
int get_building_count() const; int get_building_count() const;
int create_building(const Dictionary &dict); String create_building(const Dictionary &dict);
int create_building(const struct building &building); String create_building(const struct building &building);
int create_building(const struct building *building); String create_building(const struct building *building);
bool destroy_building(int index); bool destroy_building(const String &key);
struct checkpoint_data { struct checkpoint_data {
HashMap<String, String> building_data; HashMap<String, String> building_data;
std::vector<struct building> buildings; std::vector<struct building> buildings;
@@ -137,9 +137,12 @@ public:
void build_building_aabbs(); void build_building_aabbs();
void update_building_transform(const String &key, void update_building_transform(const String &key,
const Transform &xform); const Transform &xform);
bool has_building(const String &key);
String get_closest_building(const Transform &xform); String get_closest_building(const Transform &xform);
static BuildingsData *get_singleton(); static BuildingsData *get_singleton();
static void cleanup(); static void cleanup();
private:
int get_building_by_key(const String &key) const; int get_building_by_key(const String &key) const;
}; };
#endif #endif

View File

@@ -37,11 +37,13 @@ public:
"handle_set_building"); "handle_set_building");
EditorEvent::get_singleton()->event.add_listener( EditorEvent::get_singleton()->event.add_listener(
this, &HandlePositionSetting::handle_event); this, &HandlePositionSetting::handle_event);
int building = editor->get_selected_building(); #if 0
if (building >= 0) { String building = editor->get_selected_building();
if (building.length() > 0) {
Vector3 building_pos = Vector3 building_pos =
editor->get_selected_building_xform().origin; editor->get_selected_building_xform().origin;
} }
#endif
} }
virtual ~HandlePositionSetting() virtual ~HandlePositionSetting()
{ {
@@ -140,9 +142,9 @@ private:
xform.origin.x = position_x->get_text().to_float(); xform.origin.x = position_x->get_text().to_float();
xform.origin.y = position_y->get_text().to_float(); xform.origin.y = position_y->get_text().to_float();
xform.origin.z = position_z->get_text().to_float(); xform.origin.z = position_z->get_text().to_float();
int id = editor->get_selected_building(); String key = editor->get_selected_building();
Array args; Array args;
args.push_back(id); args.push_back(key);
args.push_back(xform); args.push_back(xform);
int mode = editor->get_buildings_editor_mode(); int mode = editor->get_buildings_editor_mode();
if (mode == 1 || mode == 2) if (mode == 1 || mode == 2)
@@ -350,7 +352,7 @@ static std::vector<Object *> ui_handlers;
BuildingsEditor::BuildingsEditor(WorldEditor *editor) BuildingsEditor::BuildingsEditor(WorldEditor *editor)
: editor(editor) : editor(editor)
, selected_building(-1) , selected_building("")
, active(false) , active(false)
{ {
} }
@@ -684,7 +686,7 @@ BuildingsEditor::~BuildingsEditor()
deactivate(); deactivate();
} }
int BuildingsEditor::get_selected_building() const String BuildingsEditor::get_selected_building() const
{ {
return selected_building; return selected_building;
} }
@@ -726,13 +728,13 @@ void BuildingsEditor::remove_buildings_by_prefix(const String &prefix)
editor->editor_command("remove_buildings_by_prefix", args); editor->editor_command("remove_buildings_by_prefix", args);
} }
void BuildingsEditor::select_building(const Transform &xform, int id, void BuildingsEditor::select_building(const Transform &xform, const String &key,
const String &mid) const String &mid)
{ {
int i; int i;
selected_building_xform = xform; selected_building_xform = xform;
selected_building = id; selected_building = key;
print_line("selected id: " + itos(id)); print_line("selected key: " + key);
OptionButton *building_type = Object::cast_to<OptionButton>( OptionButton *building_type = Object::cast_to<OptionButton>(
editor->get_node(NodePath("%building_type"))); editor->get_node(NodePath("%building_type")));
assert(building_type); assert(building_type);

View File

@@ -4,7 +4,7 @@
class WorldEditor; class WorldEditor;
class BuildingsEditor { class BuildingsEditor {
WorldEditor *editor; WorldEditor *editor;
int selected_building; String selected_building;
Transform selected_building_xform; Transform selected_building_xform;
bool active; bool active;
void activate(); void activate();
@@ -23,9 +23,10 @@ public:
Vector3 get_cursor_position() const; Vector3 get_cursor_position() const;
int get_buildings_editor_mode() const; int get_buildings_editor_mode() const;
virtual ~BuildingsEditor(); virtual ~BuildingsEditor();
int get_selected_building() const; String get_selected_building() const;
Transform get_selected_building_xform() const; Transform get_selected_building_xform() const;
void select_building(const Transform &xform, int id, const String &mid); void select_building(const Transform &xform, const String &key,
const String &mid);
void remove_buildings_by_prefix(const String &prefix); void remove_buildings_by_prefix(const String &prefix);
void editor_command(const String &command, const Array &args); void editor_command(const String &command, const Array &args);
void delete_building_handler(); void delete_building_handler();

View File

@@ -536,7 +536,7 @@ void RoadLinesData::line_add_building(const String &line, const String &key,
void RoadLinesData::assign_close_buildings(const String &line) void RoadLinesData::assign_close_buildings(const String &line)
{ {
int i, j; int j;
print_line("assign_close_buildings: " + line); print_line("assign_close_buildings: " + line);
if (!lines.has(line)) if (!lines.has(line))
return; return;
@@ -688,16 +688,13 @@ void RoadLinesData::update_buildings_from_lines()
lines.get_key_list(&keys); lines.get_key_list(&keys);
List<String>::Element *e = keys.front(); List<String>::Element *e = keys.front();
while (e) { while (e) {
int i, j; int i;
const String &line = e->get(); const String &line = e->get();
for (i = 0; i < (int)lines[line].buildings.size(); i++) { for (i = 0; i < (int)lines[line].buildings.size(); i++) {
const uint64_t &building_key_hash = const uint64_t &building_key_hash =
lines[line].buildings[i].building_key_hash; lines[line].buildings[i].building_key_hash;
bool found = false; bool found = bd->has_building(
int index = bd->get_building_by_key(
lines[line].buildings[i].building_key); lines[line].buildings[i].building_key);
if (index >= 0)
found = true;
if (found) { if (found) {
struct BuildingsData::building &b = struct BuildingsData::building &b =
bd->get_building(lines[line] bd->get_building(lines[line]
@@ -713,7 +710,8 @@ void RoadLinesData::update_buildings_from_lines()
b.xform.origin = pt; b.xform.origin = pt;
b.xform.basis = basis; b.xform.basis = basis;
Array args; Array args;
args.push_back(index); args.push_back(
lines[line].buildings[i].building_key);
EditorEvent::get_singleton()->event.emit( EditorEvent::get_singleton()->event.emit(
"building_updated", args); "building_updated", args);
} else { } else {
@@ -729,10 +727,10 @@ void RoadLinesData::update_buildings_from_lines()
data["id"] = lines[line].buildings[i].id; data["id"] = lines[line].buildings[i].id;
data["xform"] = Transform(basis, pt); data["xform"] = Transform(basis, pt);
BuildingsData::building::from_dict(&nb, data); BuildingsData::building::from_dict(&nb, data);
index = bd->get_building_count(); String bkey = bd->create_building(nb);
bd->create_building(nb); assert(bkey.length() > 0);
Array args; Array args;
args.push_back(index); args.push_back(bkey);
EditorEvent::get_singleton()->event.emit( EditorEvent::get_singleton()->event.emit(
"building_created", args); "building_created", args);
} }

View File

@@ -24,11 +24,10 @@ void StreamWorld::create_tilemap()
tile_size; tile_size;
std::tuple<int, int> tkey = std::tuple<int, int> tkey =
std::make_tuple(tile_x, tile_z); std::make_tuple(tile_x, tile_z);
int index = data()->get_building_by_key(key);
if (tiles.find(tkey) != tiles.end()) if (tiles.find(tkey) != tiles.end())
tiles[tkey].push_back(index); tiles[tkey].push_back(key);
else { else {
std::vector<int> data = { index }; std::vector<String> data = { key };
tiles[tkey] = data; tiles[tkey] = data;
} }
}, },
@@ -152,11 +151,12 @@ void StreamWorld::load_tile(int tx, int ty)
{ {
int i; int i;
std::tuple<int, int> key = std::make_tuple(tx, ty); std::tuple<int, int> key = std::make_tuple(tx, ty);
const std::vector<int> &items = tiles[key]; const std::vector<String> &items = tiles[key];
for (i = 0; i < (int)items.size(); i++) { for (i = 0; i < (int)items.size(); i++) {
print_line("load item: " + itos(i) + ": " + itos(items[i]) + print_line("load item: " + itos(i) + ": key: " + (items[i]) +
": " /* + data()->get_building(items[i]).id */); ": " /* + data()->get_building(items[i]).id */);
load_building(items[i]); const String &bkey = items[i];
load_building(bkey);
} }
} }
@@ -164,27 +164,27 @@ void StreamWorld::erase_tile(int tx, int ty)
{ {
int i; int i;
std::tuple<int, int> key = std::make_tuple(tx, ty); std::tuple<int, int> key = std::make_tuple(tx, ty);
const std::vector<int> &items = tiles[key]; const std::vector<String> &items = tiles[key];
for (i = 0; i < (int)items.size(); i++) { for (i = 0; i < (int)items.size(); i++) {
print_line("unload item: " + itos(i) + ": " + itos(items[i]) + print_line("unload item: " + itos(i) + ": key: " + items[i] +
": " /* + data()->get_building(items[i]).id */); ": " /* + data()->get_building(items[i]).id */);
unload_building(items[i]); const String &bkey = items[i];
unload_building(bkey);
} }
} }
void StreamWorld::load_building(int id) void StreamWorld::load_building(const String &key)
{ {
request_item(0, id); request_item(0, key);
} }
void StreamWorld::unload_building(int id) void StreamWorld::unload_building(const String &key)
{ {
request_item(1, id); request_item(1, key);
} }
void StreamWorld::request_item(int type, int item) void StreamWorld::request_item(int type, const String &bkey)
{ {
const String &bkey = data()->item_nodes_get_key(item);
String id = data()->get_building(bkey).id; String id = data()->get_building(bkey).id;
if (id == "empty") if (id == "empty")
return; return;
@@ -196,7 +196,7 @@ void StreamWorld::request_item(int type, int item)
data()->add_scene_item(id, bkey); data()->add_scene_item(id, bkey);
break; break;
case 1: { case 1: {
print_line("Removing " + itos(item)); print_line("Removing key:" + bkey);
if (data()->has_scene(id)) { if (data()->has_scene(id)) {
data()->remove_scene_item(id, bkey); data()->remove_scene_item(id, bkey);
} }
@@ -238,12 +238,11 @@ void StreamWorld::update_items()
} }
} }
void StreamWorld::remove_building(int index) void StreamWorld::remove_building(const String &key)
{ {
// TODO: implement // TODO: implement
unload_building(index); unload_building(key);
String key = data()->item_nodes_get_key(index); data()->destroy_building(key);
data()->destroy_building(index);
data()->item_nodes_item_removed(key); data()->item_nodes_item_removed(key);
update_items(); update_items();
} }
@@ -263,29 +262,15 @@ void StreamWorld::run_command(const String &command, const Array &args)
ret_data[1] = xform.origin.distance_squared_to( ret_data[1] = xform.origin.distance_squared_to(
data()->get_building(key).xform.origin); data()->get_building(key).xform.origin);
ret_data[2] = key; ret_data[2] = key;
ret_data[3] = data()->get_building_by_key(key); ret_data[3] = key;
ret_data[4] = data()->get_building(key).id; ret_data[4] = data()->get_building(key).id;
emit_signal("command_result", command, ret_data); emit_signal("command_result", command, ret_data);
} else if (command == "get_building_id_for_key") {
if (args.size() == 0) {
print_error("bad command: not enough args: " + command);
return;
}
String key = args[1];
Array ret_data;
ret_data.resize(1);
int id = data()->get_building_by_key(key);
ret_data[0] = id;
emit_signal("command_result", command, ret_data);
} else if (command == "update_building_transform") { } else if (command == "update_building_transform") {
if (args.size() == 0) { if (args.size() == 0) {
print_error("bad command: not enough args: " + command); print_error("bad command: not enough args: " + command);
return; return;
} }
int id = args[0]; String key = args[0];
if (id < 0 || id >= (int)data()->get_building_count())
return;
const String &key = data()->item_nodes_get_key(id);
data()->update_building_transform(key, args[1]); data()->update_building_transform(key, args[1]);
Node *node = data()->item_nodes_get_node(key); Node *node = data()->item_nodes_get_node(key);
Spatial *bnode = Object::cast_to<Spatial>(node); Spatial *bnode = Object::cast_to<Spatial>(node);
@@ -310,7 +295,7 @@ void StreamWorld::run_command(const String &command, const Array &args)
print_error("bad command: not enough args: " + command); print_error("bad command: not enough args: " + command);
return; return;
} }
int id = args[0]; String key = args[0];
String new_type = args[1]; String new_type = args[1];
Dictionary buildings_data = Dictionary buildings_data =
config.get_value("buildings", "building_data"); config.get_value("buildings", "building_data");
@@ -318,13 +303,12 @@ void StreamWorld::run_command(const String &command, const Array &args)
print_error("unknown building type: " + new_type); print_error("unknown building type: " + new_type);
return; return;
} }
String key = data()->item_nodes_get_key(id);
String old_type = data()->get_building(key).id; String old_type = data()->get_building(key).id;
unload_building(id); unload_building(key);
data()->get_building(key).id = new_type; data()->get_building(key).id = new_type;
load_building(id); load_building(key);
update_items(); update_items();
print_line("changed building: " + itos(id) + print_line("changed building: key:" + key +
" from: " + old_type + " to: " + new_type); " from: " + old_type + " to: " + new_type);
} else if (command == "create_building") { } else if (command == "create_building") {
if (args.size() == 0) { if (args.size() == 0) {
@@ -337,43 +321,38 @@ void StreamWorld::run_command(const String &command, const Array &args)
print_verbose("DICT: " + (JSON::print(building_dict, "\t"))); print_verbose("DICT: " + (JSON::print(building_dict, "\t")));
BuildingsData::building::from_dict(&b, building_dict); BuildingsData::building::from_dict(&b, building_dict);
data()->create_building(b); data()->create_building(b);
load_building(data()->get_building_count() - 1); assert(b.key.length() > 0);
load_building(b.key);
} else if (command == "remove_building") { } else if (command == "remove_building") {
if (args.size() == 0) { if (args.size() == 0) {
print_error("bad command: not enough args: " + command); print_error("bad command: not enough args: " + command);
return; return;
} }
int id = args[0]; const String &key = args[0];
remove_building(id); remove_building(key);
} else if (command == "remove_buildings_by_prefix") { } else if (command == "remove_buildings_by_prefix") {
if (args.size() == 0) { if (args.size() == 0) {
print_error("bad command: not enough args: " + command); print_error("bad command: not enough args: " + command);
return; return;
} }
std::vector<int> erased_indices; std::vector<String> erased_keys;
erased_indices.reserve(data()->get_building_count()); erased_keys.reserve(data()->get_building_count());
String prefix = args[0]; String prefix = args[0];
int i; int i;
data()->for_each_building( data()->for_each_building(
[&erased_indices, prefix](const String &key, [&erased_keys, prefix](const String &key, void *data) {
void *data) {
if (data()->get_building(key).id.begins_with( if (data()->get_building(key).id.begins_with(
prefix)) { prefix)) {
int index = data()->get_building_by_key( erased_keys.push_back(key);
key);
assert(index >= 0);
erased_indices.push_back(index);
} }
}, },
nullptr); nullptr);
print_line("delete buildings: " + itos(erased_indices.size()) + print_line("delete buildings: " + itos(erased_keys.size()) +
" prefix: " + prefix); " prefix: " + prefix);
for (i = erased_indices.size() - 1; i >= 0; i--) { for (i = erased_keys.size() - 1; i >= 0; i--) {
int index = erased_indices[i]; unload_building(erased_keys[i]);
unload_building(index); data()->destroy_building(erased_keys[i]);
String key = data()->item_nodes_get_key(index); data()->item_nodes_item_removed(erased_keys[i]);
data()->destroy_building(index);
data()->item_nodes_item_removed(key);
} }
update_items(); update_items();
} else if (command == "remove_generated_stuff") { } else if (command == "remove_generated_stuff") {
@@ -463,7 +442,7 @@ StreamWorld::StreamWorld()
tile_map_t::iterator map_it = tiles.begin(); tile_map_t::iterator map_it = tiles.begin();
while (map_it != tiles.end()) { while (map_it != tiles.end()) {
std::tuple<int, int> key = map_it->first; std::tuple<int, int> key = map_it->first;
std::vector<int> &tile_buildings = map_it->second; std::vector<String> &tile_buildings = map_it->second;
print_line("x: " + itos(std::get<0>(key)) + print_line("x: " + itos(std::get<0>(key)) +
" y: " + itos(std::get<1>(key)) + " " + " y: " + itos(std::get<1>(key)) + " " +
itos(tile_buildings.size())); itos(tile_buildings.size()));
@@ -483,23 +462,19 @@ StreamWorld::~StreamWorld()
void StreamWorld::remove_generated_stuff() void StreamWorld::remove_generated_stuff()
{ {
std::vector<int> erased_indices; std::vector<String> erased_keys;
erased_indices.reserve(data()->get_building_count()); erased_keys.reserve(data()->get_building_count());
int i; int i;
data()->for_each_building( data()->for_each_building(
[&erased_indices](const String &key, void *mdata) { [&erased_keys](const String &key, void *mdata) {
if (data()->get_building(key).generated) { if (data()->get_building(key).generated)
int index = data()->get_building_by_key(key); erased_keys.push_back(key);
assert(index >= 0);
erased_indices.push_back(index);
}
}, },
nullptr); nullptr);
for (i = erased_indices.size() - 1; i >= 0; i--) { for (i = erased_keys.size() - 1; i >= 0; i--) {
int index = erased_indices[i]; const String &key = erased_keys[i];
unload_building(index); unload_building(key);
String key = data()->item_nodes_get_key(index); data()->destroy_building(key);
data()->destroy_building(index);
data()->item_nodes_item_removed(key); data()->item_nodes_item_removed(key);
} }
update_items(); update_items();
@@ -507,9 +482,9 @@ void StreamWorld::remove_generated_stuff()
void StreamWorld::undo() void StreamWorld::undo()
{ {
int id; data()->for_each_building([this](const String &key,
for (id = 0; id < (int)data()->get_building_count(); id++) void *mdata) { unload_building(key); },
unload_building(id); nullptr);
data()->undo(); data()->undo();
update_view(); update_view();
update_items(); update_items();

View File

@@ -24,7 +24,7 @@ private:
} }
}; };
using tile_map_t = std::unordered_map<const tile_key_t, using tile_map_t = std::unordered_map<const tile_key_t,
std::vector<int>, tile_hash>; std::vector<String>, tile_hash>;
Vector3 eye; Vector3 eye;
tile_map_t tiles; tile_map_t tiles;
tile_map_t loaded_tiles; tile_map_t loaded_tiles;
@@ -41,11 +41,11 @@ private:
void terrain_dead(); void terrain_dead();
void load_tile(int tx, int ty); void load_tile(int tx, int ty);
void erase_tile(int tx, int ty); void erase_tile(int tx, int ty);
void load_building(int id); void load_building(const String &key);
void unload_building(int id); void unload_building(const String &key);
void request_item(int type, int item); void request_item(int type, const String &key);
void update_items(); void update_items();
void remove_building(int index); void remove_building(const String &key);
void remove_generated_stuff(); void remove_generated_stuff();
void place_zebras(); void place_zebras();
void undo(); void undo();