Worked on buildings in lines
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -233,7 +233,7 @@ text = "POI mode"
|
|||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
margin_top = 538.0
|
margin_top = 538.0
|
||||||
margin_right = 248.0
|
margin_right = 248.0
|
||||||
margin_bottom = 1188.0
|
margin_bottom = 1497.0
|
||||||
|
|
||||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_road_lines"]
|
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_road_lines"]
|
||||||
margin_right = 248.0
|
margin_right = 248.0
|
||||||
@@ -283,7 +283,7 @@ margin_left = 79.0
|
|||||||
margin_right = 124.0
|
margin_right = 124.0
|
||||||
margin_bottom = 20.0
|
margin_bottom = 20.0
|
||||||
text = "Point"
|
text = "Point"
|
||||||
items = [ "", null, 0, false, false, 0, 0, null, "", true, "Create", null, 0, false, false, 11, 0, null, "", false, "Remove", null, 0, false, false, 12, 0, null, "", false, "", null, 0, false, false, 3, 0, null, "", true, "Point To Cursor", null, 0, false, false, 51, 0, null, "", false, "Cursor To Point", null, 0, false, false, 52, 0, null, "", false, "Item 6", null, 0, false, true, 6, 0, null, "", false, "Item 7", null, 0, false, true, 7, 0, null, "", false ]
|
items = [ "", null, 0, false, false, 0, 0, null, "", true, "Create", null, 0, false, false, 11, 0, null, "", false, "Remove", null, 0, false, false, 12, 0, null, "", false, "", null, 0, false, false, 3, 0, null, "", true, "Point To Cursor", null, 0, false, false, 51, 0, null, "", false, "Cursor To Point", null, 0, false, false, 52, 0, null, "", false, "Cursor to closest building", null, 0, false, false, 53, 0, null, "", false, "Item 7", null, 0, false, true, 7, 0, null, "", false ]
|
||||||
switch_on_hover = true
|
switch_on_hover = true
|
||||||
|
|
||||||
[node name="road_lines_line_menu" type="MenuButton" parent="VBoxContainer/v_road_lines/road_lines_base/VBoxContainer/road_lines_menu_block"]
|
[node name="road_lines_line_menu" type="MenuButton" parent="VBoxContainer/v_road_lines/road_lines_base/VBoxContainer/road_lines_menu_block"]
|
||||||
@@ -293,7 +293,7 @@ margin_right = 167.0
|
|||||||
margin_bottom = 20.0
|
margin_bottom = 20.0
|
||||||
focus_mode = 2
|
focus_mode = 2
|
||||||
text = "Line"
|
text = "Line"
|
||||||
items = [ "Create", null, 0, false, false, 21, 0, null, "", false, "Delete", null, 0, false, false, 22, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Remove Generated", null, 0, false, false, 30, 0, null, "", false, "Place Generated Objects", null, 0, false, false, 31, 0, null, "", false, "Edit Line Metadata", null, 0, false, false, 23, 0, null, "", false, "Rebuild roads", null, 0, false, false, 32, 0, null, "", false, "Remove road meshes", null, 0, false, false, 33, 0, null, "", false ]
|
items = [ "Create", null, 0, false, false, 21, 0, null, "", false, "Delete", null, 0, false, false, 22, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Remove Generated", null, 0, false, false, 30, 0, null, "", false, "Place Generated Objects", null, 0, false, false, 31, 0, null, "", false, "Edit Line Metadata", null, 0, false, false, 23, 0, null, "", false, "Rebuild roads", null, 0, false, false, 32, 0, null, "", false, "Remove road meshes", null, 0, false, false, 33, 0, null, "", false, "Assign close (generated) buildings", null, 0, false, false, 34, 0, null, "", false, "Create new building at cursor", null, 0, false, false, 35, 0, null, "", false, "View Buildings", null, 0, false, false, 36, 0, null, "", false ]
|
||||||
switch_on_hover = true
|
switch_on_hover = true
|
||||||
|
|
||||||
[node name="road_lines_options_menu" type="MenuButton" parent="VBoxContainer/v_road_lines/road_lines_base/VBoxContainer/road_lines_menu_block"]
|
[node name="road_lines_options_menu" type="MenuButton" parent="VBoxContainer/v_road_lines/road_lines_base/VBoxContainer/road_lines_menu_block"]
|
||||||
@@ -517,11 +517,103 @@ margin_top = 212.0
|
|||||||
margin_right = 222.0
|
margin_right = 222.0
|
||||||
margin_bottom = 418.0
|
margin_bottom = 418.0
|
||||||
|
|
||||||
|
[node name="road_lines_buildings" type="PanelContainer" parent="VBoxContainer/v_road_lines"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 654.0
|
||||||
|
margin_right = 248.0
|
||||||
|
margin_bottom = 959.0
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/v_road_lines/road_lines_buildings"]
|
||||||
|
margin_left = 7.0
|
||||||
|
margin_top = 7.0
|
||||||
|
margin_right = 241.0
|
||||||
|
margin_bottom = 298.0
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer"]
|
||||||
|
margin_right = 234.0
|
||||||
|
margin_bottom = 31.0
|
||||||
|
text = "Line buildings
|
||||||
|
"
|
||||||
|
|
||||||
|
[node name="line_buildings_list" type="ItemList" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 35.0
|
||||||
|
margin_right = 234.0
|
||||||
|
margin_bottom = 135.0
|
||||||
|
rect_min_size = Vector2( 0, 100 )
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="GridContainer" type="GridContainer" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer"]
|
||||||
|
margin_top = 139.0
|
||||||
|
margin_right = 234.0
|
||||||
|
margin_bottom = 219.0
|
||||||
|
columns = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer/GridContainer"]
|
||||||
|
margin_top = 5.0
|
||||||
|
margin_right = 85.0
|
||||||
|
margin_bottom = 19.0
|
||||||
|
text = "line offset"
|
||||||
|
|
||||||
|
[node name="line_buildings_line_offset" type="LineEdit" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer/GridContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 89.0
|
||||||
|
margin_right = 234.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="Label2" type="Label" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer/GridContainer"]
|
||||||
|
margin_top = 33.0
|
||||||
|
margin_right = 85.0
|
||||||
|
margin_bottom = 47.0
|
||||||
|
text = "normal offset"
|
||||||
|
|
||||||
|
[node name="line_buildings_normal_offset" type="LineEdit" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer/GridContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_left = 89.0
|
||||||
|
margin_top = 28.0
|
||||||
|
margin_right = 234.0
|
||||||
|
margin_bottom = 52.0
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="Label3" type="Label" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer/GridContainer"]
|
||||||
|
margin_top = 61.0
|
||||||
|
margin_right = 85.0
|
||||||
|
margin_bottom = 75.0
|
||||||
|
text = "Y-rotation"
|
||||||
|
|
||||||
|
[node name="LineEdit" type="LineEdit" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer/GridContainer"]
|
||||||
|
margin_left = 89.0
|
||||||
|
margin_top = 56.0
|
||||||
|
margin_right = 234.0
|
||||||
|
margin_bottom = 80.0
|
||||||
|
|
||||||
|
[node name="line_buildings_remove_from_line" type="Button" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 223.0
|
||||||
|
margin_right = 234.0
|
||||||
|
margin_bottom = 243.0
|
||||||
|
text = "Remove"
|
||||||
|
|
||||||
|
[node name="line_buildings_assign" type="Button" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 247.0
|
||||||
|
margin_right = 234.0
|
||||||
|
margin_bottom = 267.0
|
||||||
|
text = "Assign"
|
||||||
|
|
||||||
|
[node name="line_buildings_close" type="Button" parent="VBoxContainer/v_road_lines/road_lines_buildings/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
margin_top = 271.0
|
||||||
|
margin_right = 234.0
|
||||||
|
margin_bottom = 291.0
|
||||||
|
text = "Close"
|
||||||
|
|
||||||
[node name="v_npc" type="VBoxContainer" parent="VBoxContainer"]
|
[node name="v_npc" type="VBoxContainer" parent="VBoxContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
margin_top = 1192.0
|
margin_top = 1501.0
|
||||||
margin_right = 248.0
|
margin_right = 248.0
|
||||||
margin_bottom = 1214.0
|
margin_bottom = 1523.0
|
||||||
|
|
||||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_npc"]
|
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_npc"]
|
||||||
margin_right = 248.0
|
margin_right = 248.0
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <core/os/memory.h>
|
#include <core/os/memory.h>
|
||||||
#include <core/io/json.h>
|
#include <core/io/json.h>
|
||||||
|
#include <core/os/time.h>
|
||||||
#include <core/os/file_access.h>
|
#include <core/os/file_access.h>
|
||||||
#include <core/io/config_file.h>
|
#include <core/io/config_file.h>
|
||||||
#include <scene/resources/packed_scene.h>
|
#include <scene/resources/packed_scene.h>
|
||||||
@@ -71,6 +72,29 @@ void BuildingsData::build_building_aabbs()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BuildingsData::update_building_transform(int index, const Transform &xform)
|
||||||
|
{
|
||||||
|
buildings[index].xform = xform;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BuildingsData::get_closest_building(const Transform &xform)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float dst = Math_INF;
|
||||||
|
String rkey;
|
||||||
|
int id = -1;
|
||||||
|
for (i = 0; i < (int)buildings.size(); i++) {
|
||||||
|
Vector3 o = xform.origin;
|
||||||
|
Vector3 m = buildings[i].xform.origin;
|
||||||
|
float mdst = o.distance_squared_to(m);
|
||||||
|
if (dst > mdst) {
|
||||||
|
dst = mdst;
|
||||||
|
id = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
void BuildingsData::cleanup()
|
void BuildingsData::cleanup()
|
||||||
{
|
{
|
||||||
if (singleton) {
|
if (singleton) {
|
||||||
@@ -80,6 +104,19 @@ void BuildingsData::cleanup()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BuildingsData::get_building_by_key(const String &key)
|
||||||
|
{
|
||||||
|
int i, index = -1;
|
||||||
|
uint64_t key_hash = key.hash64();
|
||||||
|
for (i = 0; i < (int)buildings.size(); i++) {
|
||||||
|
if (key_hash == buildings[i].key_hash) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
void BuildingsData::read_buildings_json(const String &buildings_path)
|
void BuildingsData::read_buildings_json(const String &buildings_path)
|
||||||
{
|
{
|
||||||
String buildings_json = FileAccess::get_file_as_string(buildings_path);
|
String buildings_json = FileAccess::get_file_as_string(buildings_path);
|
||||||
@@ -103,7 +140,11 @@ void BuildingsData::read_buildings_json(const String &buildings_path)
|
|||||||
e = e->next();
|
e = e->next();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
building::from_dict(&b, json[key], key);
|
if (!entry.has("xform")) // legacy
|
||||||
|
entry["xform"] = key;
|
||||||
|
if (!entry.has("key")) // legacy
|
||||||
|
entry["key"] = key;
|
||||||
|
building::from_dict(&b, json[key]);
|
||||||
buildings.push_back(b);
|
buildings.push_back(b);
|
||||||
e = e->next();
|
e = e->next();
|
||||||
}
|
}
|
||||||
@@ -136,8 +177,7 @@ void BuildingsData::save_buildings_json(const String &buildings_path)
|
|||||||
fa->close();
|
fa->close();
|
||||||
Dictionary json;
|
Dictionary json;
|
||||||
for (i = 0; i < (int)buildings.size(); i++) {
|
for (i = 0; i < (int)buildings.size(); i++) {
|
||||||
String key;
|
String key = buildings[i].key;
|
||||||
VariantWriter::write_to_string(buildings[i].xform, key);
|
|
||||||
Dictionary dict = buildings[i].to_dict();
|
Dictionary dict = buildings[i].to_dict();
|
||||||
dict["index"] = i;
|
dict["index"] = i;
|
||||||
json[key] = dict;
|
json[key] = dict;
|
||||||
@@ -149,12 +189,13 @@ void BuildingsData::save_buildings_json(const String &buildings_path)
|
|||||||
print_line("entries count: " + itos(buildings.size()));
|
print_line("entries count: " + itos(buildings.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildingsData::building::from_dict(building *b, const Dictionary &dict,
|
void BuildingsData::building::from_dict(building *b, const Dictionary &dict)
|
||||||
const String &key)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
b->key = key;
|
assert(dict.has("key"));
|
||||||
b->xform = from_string<Transform>(key);
|
assert(dict.has("xform"));
|
||||||
|
b->xform = from_string<Transform>(
|
||||||
|
dict.get("xform", to_string<Transform>(Transform())));
|
||||||
b->id = dict.get("id", "empty");
|
b->id = dict.get("id", "empty");
|
||||||
b->pattern_id = dict.get("pattern_id", 0);
|
b->pattern_id = dict.get("pattern_id", 0);
|
||||||
b->generated = dict.get("generated", false);
|
b->generated = dict.get("generated", false);
|
||||||
@@ -178,6 +219,14 @@ void BuildingsData::building::from_dict(building *b, const Dictionary &dict,
|
|||||||
}
|
}
|
||||||
b->worktime[0] = worktime[0];
|
b->worktime[0] = worktime[0];
|
||||||
b->worktime[1] = worktime[1];
|
b->worktime[1] = worktime[1];
|
||||||
|
String new_key = String::num_uint64(
|
||||||
|
String(b->id +
|
||||||
|
dict.get("xform", to_string<Transform>(Transform())) +
|
||||||
|
itos(Time::get_singleton()->get_ticks_usec()))
|
||||||
|
.hash64(),
|
||||||
|
16);
|
||||||
|
b->key = dict.get("key", new_key);
|
||||||
|
b->key_hash = b->key.hash64();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> static inline void v2a(Array &ret, const Vector<T> &data)
|
template <class T> static inline void v2a(Array &ret, const Vector<T> &data)
|
||||||
@@ -206,6 +255,8 @@ Dictionary BuildingsData::building::to_dict() const
|
|||||||
wt[0] = worktime[0];
|
wt[0] = worktime[0];
|
||||||
wt[1] = worktime[1];
|
wt[1] = worktime[1];
|
||||||
ret["worktime"] = wt;
|
ret["worktime"] = wt;
|
||||||
|
ret["key"] = key;
|
||||||
|
ret["xform"] = to_string<Transform>(xform);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,13 +12,14 @@ public:
|
|||||||
int pattern_id;
|
int pattern_id;
|
||||||
Vector<int> residents, workers, guests;
|
Vector<int> residents, workers, guests;
|
||||||
String key;
|
String key;
|
||||||
|
uint64_t key_hash;
|
||||||
Transform xform;
|
Transform xform;
|
||||||
int worktime[2];
|
int worktime[2];
|
||||||
bool generated;
|
bool generated;
|
||||||
static void from_dict(struct building *b,
|
static void from_dict(struct building *b,
|
||||||
const Dictionary &dict,
|
const Dictionary &dict);
|
||||||
const String &key);
|
|
||||||
Dictionary to_dict() const;
|
Dictionary to_dict() const;
|
||||||
|
String line_name;
|
||||||
};
|
};
|
||||||
/* Scene objects data */
|
/* Scene objects data */
|
||||||
struct scene_data {
|
struct scene_data {
|
||||||
@@ -54,7 +55,10 @@ public:
|
|||||||
void undo();
|
void undo();
|
||||||
void fill_door_locations();
|
void fill_door_locations();
|
||||||
void build_building_aabbs();
|
void build_building_aabbs();
|
||||||
|
void update_building_transform(int index, const Transform &xform);
|
||||||
|
int get_closest_building(const Transform &xform);
|
||||||
static BuildingsData *get_singleton();
|
static BuildingsData *get_singleton();
|
||||||
static void cleanup();
|
static void cleanup();
|
||||||
|
int get_building_by_key(const String &key);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#undef NDEBUG
|
#undef NDEBUG
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <core/variant.h>
|
#include <core/variant.h>
|
||||||
|
#include <core/os/time.h>
|
||||||
#include <scene/gui/option_button.h>
|
#include <scene/gui/option_button.h>
|
||||||
#include <scene/main/viewport.h>
|
#include <scene/main/viewport.h>
|
||||||
#include <scene/3d/camera.h>
|
#include <scene/3d/camera.h>
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
#include "from_string.h"
|
#include "from_string.h"
|
||||||
#include "editor_event.h"
|
#include "editor_event.h"
|
||||||
#include "world_editor.h"
|
#include "world_editor.h"
|
||||||
|
#include "buildings_data.h"
|
||||||
#include "buildings_editor.h"
|
#include "buildings_editor.h"
|
||||||
|
|
||||||
class HandleChangeBuildingType : public Object {
|
class HandleChangeBuildingType : public Object {
|
||||||
@@ -240,10 +242,15 @@ void BuildingsEditor::handle_create_building()
|
|||||||
->get_global_transform();
|
->get_global_transform();
|
||||||
Dictionary building_data;
|
Dictionary building_data;
|
||||||
/* FIXME: calculate AABBs as in previous editor */
|
/* FIXME: calculate AABBs as in previous editor */
|
||||||
|
String building_xform = to_string<Transform>(xform);
|
||||||
building_data["id"] = item;
|
building_data["id"] = item;
|
||||||
String building_key = to_string<Transform>(xform);
|
building_data["key"] = String::num_uint64(
|
||||||
|
String(item + building_xform +
|
||||||
|
itos(Time::get_singleton()->get_ticks_usec()))
|
||||||
|
.hash64(),
|
||||||
|
16);
|
||||||
|
building_data["xform"] = building_xform;
|
||||||
args.push_back(building_data);
|
args.push_back(building_data);
|
||||||
args.push_back(building_key);
|
|
||||||
editor->editor_command("create_building", args);
|
editor->editor_command("create_building", args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,6 +432,7 @@ void BuildingsEditor::mouse_press(const Vector2 &position)
|
|||||||
float h = gen->get_height_full(newpos);
|
float h = gen->get_height_full(newpos);
|
||||||
newpos.y = h;
|
newpos.y = h;
|
||||||
Transform xform(Basis(), newpos);
|
Transform xform(Basis(), newpos);
|
||||||
|
get_as_node<Spatial>("%building_cursor")->show();
|
||||||
get_as_node<Spatial>("%building_cursor")
|
get_as_node<Spatial>("%building_cursor")
|
||||||
->set_global_transform(xform);
|
->set_global_transform(xform);
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <scene/3d/immediate_geometry.h>
|
#include <scene/3d/immediate_geometry.h>
|
||||||
#include <scene/main/viewport.h>
|
#include <scene/main/viewport.h>
|
||||||
#include "from_string.h"
|
#include "from_string.h"
|
||||||
|
#include "buildings_data.h"
|
||||||
#include "road_lines_data.h"
|
#include "road_lines_data.h"
|
||||||
|
|
||||||
ImmediateGeometry *RoadLinesData::debug_im = nullptr;
|
ImmediateGeometry *RoadLinesData::debug_im = nullptr;
|
||||||
@@ -62,7 +63,6 @@ RoadLinesData::RoadLinesData()
|
|||||||
e = e->next();
|
e = e->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RoadLinesData *RoadLinesData::singleton = nullptr;
|
RoadLinesData *RoadLinesData::singleton = nullptr;
|
||||||
RoadLinesData *RoadLinesData::get_singleton()
|
RoadLinesData *RoadLinesData::get_singleton()
|
||||||
{
|
{
|
||||||
@@ -70,7 +70,6 @@ RoadLinesData *RoadLinesData::get_singleton()
|
|||||||
singleton = memnew(RoadLinesData);
|
singleton = memnew(RoadLinesData);
|
||||||
return singleton;
|
return singleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
RoadLinesData::~RoadLinesData()
|
RoadLinesData::~RoadLinesData()
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@@ -80,18 +79,15 @@ RoadLinesData::~RoadLinesData()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoadLinesData::cleanup()
|
void RoadLinesData::cleanup()
|
||||||
{
|
{
|
||||||
memdelete(singleton);
|
memdelete(singleton);
|
||||||
singleton = nullptr;
|
singleton = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
String RoadLinesData::get_road_lines_path()
|
String RoadLinesData::get_road_lines_path()
|
||||||
{
|
{
|
||||||
return road_lines_path;
|
return road_lines_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoadLinesData::get_road_lines_key_list(List<String> *keys)
|
void RoadLinesData::get_road_lines_key_list(List<String> *keys)
|
||||||
{
|
{
|
||||||
List<String> line_keys;
|
List<String> line_keys;
|
||||||
@@ -234,8 +230,7 @@ void RoadLinesData::create_segments(const String &road,
|
|||||||
std::vector<int> &segments)
|
std::vector<int> &segments)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
RoadLinesData *rld = RoadLinesData::get_singleton();
|
for (i = 0; i < (int)lines[road].indices.size() - 1; i++) {
|
||||||
for (i = 0; i < (int)rld->lines[road].indices.size() - 1; i++) {
|
|
||||||
segments.push_back(i);
|
segments.push_back(i);
|
||||||
segments.push_back(i + 1);
|
segments.push_back(i + 1);
|
||||||
}
|
}
|
||||||
@@ -296,14 +291,12 @@ void RoadLinesData::insert_close_points(std::vector<Vector3> &road_lines_nodes,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoadLinesData::update_road_lines_nodes(
|
void RoadLinesData::update_road_lines_nodes(
|
||||||
std::vector<Vector3> &road_lines_nodes)
|
std::vector<Vector3> &road_lines_nodes)
|
||||||
{
|
{
|
||||||
List<String> keys;
|
List<String> keys;
|
||||||
RoadLinesData *rld = RoadLinesData::get_singleton();
|
|
||||||
|
|
||||||
rld->get_road_lines_key_list(&keys);
|
get_road_lines_key_list(&keys);
|
||||||
std::unordered_map<uint32_t, std::tuple<String, String> > kcmp;
|
std::unordered_map<uint32_t, std::tuple<String, String> > kcmp;
|
||||||
{
|
{
|
||||||
List<String>::Element *k = keys.front();
|
List<String>::Element *k = keys.front();
|
||||||
@@ -335,25 +328,22 @@ void RoadLinesData::update_road_lines_nodes(
|
|||||||
std::tuple<String, String> data = kcmp[it->first];
|
std::tuple<String, String> data = kcmp[it->first];
|
||||||
const String &k = std::get<0>(data);
|
const String &k = std::get<0>(data);
|
||||||
const String &r = std::get<1>(data);
|
const String &r = std::get<1>(data);
|
||||||
if (rld->lines[k].indices.size() < 2)
|
if (lines[k].indices.size() < 2)
|
||||||
continue;
|
continue;
|
||||||
if (rld->lines[r].indices.size() < 2)
|
if (lines[r].indices.size() < 2)
|
||||||
continue;
|
continue;
|
||||||
for (i = 0; i < (int)rld->lines[k].indices.size() - 1; i++) {
|
for (i = 0; i < (int)lines[k].indices.size() - 1; i++) {
|
||||||
for (j = 0; j < (int)rld->lines[k].indices.size() - 1;
|
for (j = 0; j < (int)lines[k].indices.size() - 1; j++) {
|
||||||
j++) {
|
|
||||||
uint32_t key = k.hash() ^ i ^ r.hash() ^ j ^
|
uint32_t key = k.hash() ^ i ^ r.hash() ^ j ^
|
||||||
2147483137;
|
2147483137;
|
||||||
uint32_t key2 = r.hash() ^ j ^ k.hash() ^ i ^
|
uint32_t key2 = r.hash() ^ j ^ k.hash() ^ i ^
|
||||||
2147463167;
|
2147463167;
|
||||||
if (checks.find(key) == checks.end() &&
|
if (checks.find(key) == checks.end() &&
|
||||||
checks.find(key2) == checks.end()) {
|
checks.find(key2) == checks.end()) {
|
||||||
int idx_a1 = rld->lines[k].indices[i];
|
int idx_a1 = lines[k].indices[i];
|
||||||
int idx_a2 =
|
int idx_a2 = lines[k].indices[i + 1];
|
||||||
rld->lines[k].indices[i + 1];
|
int idx_b1 = lines[k].indices[j];
|
||||||
int idx_b1 = rld->lines[k].indices[j];
|
int idx_b2 = lines[k].indices[j + 1];
|
||||||
int idx_b2 =
|
|
||||||
rld->lines[k].indices[j + 1];
|
|
||||||
std::vector<int> cmp1 = { idx_a1,
|
std::vector<int> cmp1 = { idx_a1,
|
||||||
idx_a2 };
|
idx_a2 };
|
||||||
if (std::find(cmp1.begin(), cmp1.end(),
|
if (std::find(cmp1.begin(), cmp1.end(),
|
||||||
@@ -419,16 +409,16 @@ void RoadLinesData::update_road_lines_nodes(
|
|||||||
int nidx = road_lines_nodes.size();
|
int nidx = road_lines_nodes.size();
|
||||||
road_lines_nodes.push_back(pxt);
|
road_lines_nodes.push_back(pxt);
|
||||||
// int il = (int)road_lines[k].indices.size();
|
// int il = (int)road_lines[k].indices.size();
|
||||||
assert(std::find(rld->lines[k].indices.begin(),
|
assert(std::find(lines[k].indices.begin(),
|
||||||
rld->lines[k].indices.end(),
|
lines[k].indices.end(),
|
||||||
nidx) == rld->lines[k].indices.end());
|
nidx) == lines[k].indices.end());
|
||||||
assert(std::find(rld->lines[r].indices.begin(),
|
assert(std::find(lines[r].indices.begin(),
|
||||||
rld->lines[r].indices.end(),
|
lines[r].indices.end(),
|
||||||
nidx) == rld->lines[r].indices.end());
|
nidx) == lines[r].indices.end());
|
||||||
rld->lines[k].indices.insert(
|
lines[k].indices.insert(
|
||||||
rld->lines[k].indices.begin() + i + 1, nidx);
|
lines[k].indices.begin() + i + 1, nidx);
|
||||||
rld->lines[r].indices.insert(
|
lines[r].indices.insert(
|
||||||
rld->lines[k].indices.begin() + j + 1, nidx);
|
lines[k].indices.begin() + j + 1, nidx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,12 +426,11 @@ void RoadLinesData::dump_road_lines(const std::vector<Vector3> &road_lines_nodes
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
List<String> keys;
|
List<String> keys;
|
||||||
RoadLinesData *rld = RoadLinesData::get_singleton();
|
get_road_lines_key_list(&keys);
|
||||||
rld->get_road_lines_key_list(&keys);
|
|
||||||
List<String>::Element *e = keys.front();
|
List<String>::Element *e = keys.front();
|
||||||
while (e) {
|
while (e) {
|
||||||
String rkey = e->get();
|
String rkey = e->get();
|
||||||
struct RoadLinesData::road_line &pt = rld->lines[rkey];
|
struct RoadLinesData::road_line &pt = lines[rkey];
|
||||||
String outline = rkey + ": ";
|
String outline = rkey + ": ";
|
||||||
for (i = 0; i < (int)pt.indices.size(); i++) {
|
for (i = 0; i < (int)pt.indices.size(); i++) {
|
||||||
outline += " " + itos(pt.indices[i]);
|
outline += " " + itos(pt.indices[i]);
|
||||||
@@ -453,7 +442,6 @@ void RoadLinesData::dump_road_lines(const std::vector<Vector3> &road_lines_nodes
|
|||||||
e = e->next();
|
e = e->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmediateGeometry *RoadLinesData::get_debug_node()
|
ImmediateGeometry *RoadLinesData::get_debug_node()
|
||||||
{
|
{
|
||||||
if (!debug_im) {
|
if (!debug_im) {
|
||||||
@@ -474,7 +462,6 @@ ImmediateGeometry *RoadLinesData::get_debug_node()
|
|||||||
}
|
}
|
||||||
return debug_im;
|
return debug_im;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoadLinesData::process_lines(
|
void RoadLinesData::process_lines(
|
||||||
std::unordered_map<uint32_t, std::vector<Vector3> >
|
std::unordered_map<uint32_t, std::vector<Vector3> >
|
||||||
&road_lines_nodes_hash,
|
&road_lines_nodes_hash,
|
||||||
@@ -485,13 +472,181 @@ void RoadLinesData::process_lines(
|
|||||||
update_road_lines_nodes(road_lines_nodes);
|
update_road_lines_nodes(road_lines_nodes);
|
||||||
dump_road_lines(road_lines_nodes);
|
dump_road_lines(road_lines_nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoadLinesData::set_debug_flags(int debug_flags)
|
void RoadLinesData::set_debug_flags(int debug_flags)
|
||||||
{
|
{
|
||||||
this->debug_flags = debug_flags;
|
this->debug_flags = debug_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RoadLinesData::get_debug_flags() const
|
int RoadLinesData::get_debug_flags() const
|
||||||
{
|
{
|
||||||
return debug_flags;
|
return debug_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RoadLinesData::update_line_segments(const String &line)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
lines[line].segments.clear();
|
||||||
|
lines[line].segments.resize(lines[line].points.size() - 1);
|
||||||
|
float offset = 0.0f;
|
||||||
|
for (i = 0; i < (int)lines[line].points.size() - 1; i++) {
|
||||||
|
struct line_segment segment;
|
||||||
|
segment.p1 = lines[line].points[i].origin;
|
||||||
|
segment.p2 = lines[line].points[i + 1].origin;
|
||||||
|
segment.length = segment.p1.distance_to(segment.p2);
|
||||||
|
segment.dir = (segment.p2 - segment.p1).normalized();
|
||||||
|
Vector3 side = segment.dir.cross(Vector3(0, 1, 0));
|
||||||
|
side.y = 0;
|
||||||
|
segment.tangent = side.normalized();
|
||||||
|
segment.offset = offset;
|
||||||
|
lines[line].segments[i] = segment;
|
||||||
|
offset += segment.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoadLinesData::line_add_building(const String &line, const String &key,
|
||||||
|
float curve_offset, float normal_offset)
|
||||||
|
{
|
||||||
|
int index = BuildingsData::get_singleton()->get_building_by_key(key);
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
struct line_building_data lb;
|
||||||
|
lb.building_key = key;
|
||||||
|
lb.building_key_hash = key.hash64();
|
||||||
|
lb.line_offset = curve_offset;
|
||||||
|
lb.normal_offset = normal_offset;
|
||||||
|
lines[line].buildings.push_back(lb);
|
||||||
|
// TODO: save/load
|
||||||
|
BuildingsData::get_singleton()->buildings[index].line_name = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoadLinesData::assign_close_buildings(const String &line)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
print_line("assign_close_buildings: " + line);
|
||||||
|
if (!lines.has(line))
|
||||||
|
return;
|
||||||
|
if (!line.ends_with("_buildings"))
|
||||||
|
return;
|
||||||
|
if (lines[line].points.size() < 2)
|
||||||
|
return;
|
||||||
|
update_line_segments(line);
|
||||||
|
if (lines[line].segments.size() == 0)
|
||||||
|
return;
|
||||||
|
print_line("assign_close_buildings: processing: " +
|
||||||
|
itos(BuildingsData::get_singleton()->buildings.size()) +
|
||||||
|
" buildings");
|
||||||
|
for (i = 0; i < (int)BuildingsData::get_singleton()->buildings.size();
|
||||||
|
i++) {
|
||||||
|
float dst = Math_INF;
|
||||||
|
float result_offset = 0.0f;
|
||||||
|
float side = 0.0f;
|
||||||
|
String building_key;
|
||||||
|
struct BuildingsData::building &data =
|
||||||
|
BuildingsData::get_singleton()->buildings[i];
|
||||||
|
// manually placed
|
||||||
|
if (!data.generated)
|
||||||
|
continue;
|
||||||
|
// already assigned to another line
|
||||||
|
const String &building_line =
|
||||||
|
BuildingsData::get_singleton()->buildings[i].line_name;
|
||||||
|
if (building_line != line && building_line != "")
|
||||||
|
continue;
|
||||||
|
if (line_has_building(line, data.key))
|
||||||
|
continue;
|
||||||
|
Vector3 p = data.xform.origin;
|
||||||
|
Vector3 segment_point;
|
||||||
|
int segment_index = -1;
|
||||||
|
|
||||||
|
for (j = 0; j < (int)lines[line].segments.size(); j++) {
|
||||||
|
Vector3 seg[] = { lines[line].segments[j].p1,
|
||||||
|
lines[line].segments[j].p2 };
|
||||||
|
Vector3 closest =
|
||||||
|
Geometry::get_closest_point_to_segment(p, seg);
|
||||||
|
Vector3 xp = p;
|
||||||
|
xp.y = p.y;
|
||||||
|
float tmpdst = xp.distance_squared_to(closest);
|
||||||
|
if (closest.is_equal_approx(
|
||||||
|
lines[line].segments[j].p1) ||
|
||||||
|
closest.is_equal_approx(
|
||||||
|
lines[line].segments[j].p2)) {
|
||||||
|
float w = closest.dot(
|
||||||
|
lines[line].segments[j].dir);
|
||||||
|
float wt = xp.dot(lines[line].segments[j].dir);
|
||||||
|
if (wt - w > 0.1f || wt - w < -0.1f)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (dst > tmpdst) {
|
||||||
|
dst = tmpdst;
|
||||||
|
building_key = data.key;
|
||||||
|
segment_index = j;
|
||||||
|
segment_point = closest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (segment_index < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const Vector3 &p1 = lines[line].segments[segment_index].p1;
|
||||||
|
const Vector3 &p2 = lines[line].segments[segment_index].p2;
|
||||||
|
const Vector3 &dir = lines[line].segments[segment_index].dir;
|
||||||
|
assert(segment_index >= 0);
|
||||||
|
// assert(!segment_point.is_equal_approx(p1));
|
||||||
|
// assert(!segment_point.is_equal_approx(p2));
|
||||||
|
assert((segment_point - p1).dot(dir) >= 0);
|
||||||
|
float wdst = (p - p1).dot(dir);
|
||||||
|
print_line("wdst=" + String::num(wdst));
|
||||||
|
assert(wdst >= 0);
|
||||||
|
result_offset =
|
||||||
|
lines[line].segments[segment_index].offset + wdst;
|
||||||
|
side = (p - p1).dot(lines[line].segments[j].tangent);
|
||||||
|
|
||||||
|
assert(result_offset >= 0);
|
||||||
|
|
||||||
|
print_line("key: " + building_key +
|
||||||
|
" dst: " + String::num(dst));
|
||||||
|
if (dst < 16 * 16) {
|
||||||
|
print_line("adding: key: " + building_key +
|
||||||
|
" dst: " + String::num(dst));
|
||||||
|
assert(result_offset >= 0);
|
||||||
|
line_add_building(line, building_key, result_offset,
|
||||||
|
side);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RoadLinesData::line_has_building(const String &line,
|
||||||
|
const String &building_key)
|
||||||
|
{
|
||||||
|
uint64_t key_hash = building_key.hash64();
|
||||||
|
bool ret = false;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < (int)lines[line].buildings.size(); i++)
|
||||||
|
if (lines[line].buildings[i].building_key_hash == key_hash) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 RoadLinesData::get_point_by_offsets(const String &line,
|
||||||
|
float dir_offset,
|
||||||
|
float normal_offset)
|
||||||
|
{
|
||||||
|
Vector3 ret;
|
||||||
|
int i;
|
||||||
|
print_verbose("line: " + line +
|
||||||
|
" line_offset: " + String::num(dir_offset) +
|
||||||
|
" normal_offset: " + String::num(normal_offset));
|
||||||
|
float n_offset = dir_offset;
|
||||||
|
int selected_segment = 0;
|
||||||
|
for (i = 0; i < (int)lines[line].segments.size(); i++) {
|
||||||
|
struct line_segment *segment = &lines[line].segments[i];
|
||||||
|
if (n_offset < segment->length) {
|
||||||
|
selected_segment = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n_offset -= segment->length;
|
||||||
|
}
|
||||||
|
ret = lines[line].segments[selected_segment].p1 +
|
||||||
|
lines[line].segments[selected_segment].dir * n_offset +
|
||||||
|
lines[line].segments[selected_segment].tangent * normal_offset;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,17 +14,34 @@ protected:
|
|||||||
_Signal<void> lines_updated;
|
_Signal<void> lines_updated;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static ImmediateGeometry *get_debug_node();
|
struct line_building_data {
|
||||||
|
String building_key;
|
||||||
|
uint64_t building_key_hash;
|
||||||
|
float line_offset;
|
||||||
|
float normal_offset;
|
||||||
|
};
|
||||||
|
struct line_segment {
|
||||||
|
Vector3 p1;
|
||||||
|
Vector3 p2;
|
||||||
|
float length;
|
||||||
|
Vector3 dir;
|
||||||
|
Vector3 tangent;
|
||||||
|
float offset;
|
||||||
|
};
|
||||||
struct road_line {
|
struct road_line {
|
||||||
std::vector<Transform> points;
|
std::vector<Transform> points;
|
||||||
std::vector<int> indices;
|
std::vector<int> indices;
|
||||||
|
std::vector<struct line_building_data> buildings;
|
||||||
|
std::vector<struct line_segment> segments;
|
||||||
int lanes;
|
int lanes;
|
||||||
int pattern;
|
int pattern;
|
||||||
int flags;
|
int flags;
|
||||||
Dictionary metadata;
|
Dictionary metadata;
|
||||||
_Signal<void> line_updated;
|
_Signal<void> line_updated;
|
||||||
};
|
};
|
||||||
|
static ImmediateGeometry *get_debug_node();
|
||||||
HashMap<String, struct road_line> lines;
|
HashMap<String, struct road_line> lines;
|
||||||
|
HashMap<String, Ref<Curve3D> > curves;
|
||||||
static RoadLinesData *get_singleton();
|
static RoadLinesData *get_singleton();
|
||||||
virtual ~RoadLinesData();
|
virtual ~RoadLinesData();
|
||||||
static void cleanup();
|
static void cleanup();
|
||||||
@@ -36,6 +53,13 @@ public:
|
|||||||
std::vector<Vector3> &road_lines_nodes);
|
std::vector<Vector3> &road_lines_nodes);
|
||||||
void set_debug_flags(int debug_flags);
|
void set_debug_flags(int debug_flags);
|
||||||
int get_debug_flags() const;
|
int get_debug_flags() const;
|
||||||
|
void update_line_segments(const String &line);
|
||||||
|
void line_add_building(const String &line, const String &key,
|
||||||
|
float curve_offset, float normal_offset);
|
||||||
|
void assign_close_buildings(const String &line);
|
||||||
|
bool line_has_building(const String &line, const String &building_key);
|
||||||
|
Vector3 get_point_by_offsets(const String &line, float dir_offset,
|
||||||
|
float normal_offset);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void create_segments_from_lines();
|
void create_segments_from_lines();
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "from_string.h"
|
#include "from_string.h"
|
||||||
#include "road_lines_data.h"
|
#include "road_lines_data.h"
|
||||||
#include "road_processing.h"
|
#include "road_processing.h"
|
||||||
|
#include "buildings_data.h"
|
||||||
#include "road_lines_editor.h"
|
#include "road_lines_editor.h"
|
||||||
|
|
||||||
static ImmediateGeometry *line_im = nullptr;
|
static ImmediateGeometry *line_im = nullptr;
|
||||||
@@ -241,6 +242,8 @@ public:
|
|||||||
"%road_lines_metadata_update");
|
"%road_lines_metadata_update");
|
||||||
TextEdit *metadata_edit = editor->get_as_node<TextEdit>(
|
TextEdit *metadata_edit = editor->get_as_node<TextEdit>(
|
||||||
"%road_lines_metadata_edit");
|
"%road_lines_metadata_edit");
|
||||||
|
Button *line_buildings_close =
|
||||||
|
editor->get_as_node<Button>("%line_buildings_close");
|
||||||
cancel_button->connect("pressed", this, "cancel_handler");
|
cancel_button->connect("pressed", this, "cancel_handler");
|
||||||
line_name->connect("text_entered", this, "entered_handler");
|
line_name->connect("text_entered", this, "entered_handler");
|
||||||
line_name->connect("text_changed", this, "changed_handler");
|
line_name->connect("text_changed", this, "changed_handler");
|
||||||
@@ -250,10 +253,14 @@ public:
|
|||||||
"update_metadata_handler");
|
"update_metadata_handler");
|
||||||
metadata_edit->connect("text_changed", this,
|
metadata_edit->connect("text_changed", this,
|
||||||
"metadata_changed_handler");
|
"metadata_changed_handler");
|
||||||
|
line_buildings_close->connect("pressed", this,
|
||||||
|
"line_buildings_close_handler");
|
||||||
}
|
}
|
||||||
virtual ~HandleCreateNewLine()
|
virtual ~HandleCreateNewLine()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
Button *line_buildings_close =
|
||||||
|
editor->get_as_node<Button>("%line_buildings_close");
|
||||||
TextEdit *metadata_edit = editor->get_as_node<TextEdit>(
|
TextEdit *metadata_edit = editor->get_as_node<TextEdit>(
|
||||||
"%road_lines_metadata_edit");
|
"%road_lines_metadata_edit");
|
||||||
Button *update_metadata_button = editor->get_as_node<Button>(
|
Button *update_metadata_button = editor->get_as_node<Button>(
|
||||||
@@ -264,6 +271,8 @@ public:
|
|||||||
"%road_lines_create_new_cancel");
|
"%road_lines_create_new_cancel");
|
||||||
LineEdit *line_name = editor->get_as_node<LineEdit>(
|
LineEdit *line_name = editor->get_as_node<LineEdit>(
|
||||||
"%road_lines_create_new_line_name");
|
"%road_lines_create_new_line_name");
|
||||||
|
line_buildings_close->disconnect(
|
||||||
|
"pressed", this, "line_buildings_close_handler");
|
||||||
metadata_edit->disconnect("text_changed", this,
|
metadata_edit->disconnect("text_changed", this,
|
||||||
"metadata_changed_handler");
|
"metadata_changed_handler");
|
||||||
update_metadata_button->disconnect("pressed", this,
|
update_metadata_button->disconnect("pressed", this,
|
||||||
@@ -296,6 +305,25 @@ protected:
|
|||||||
String text = editor->get_current_line_metadata();
|
String text = editor->get_current_line_metadata();
|
||||||
metadata_edit->set_text(text);
|
metadata_edit->set_text(text);
|
||||||
}
|
}
|
||||||
|
void update_line_buildings_editor()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (current_line == "")
|
||||||
|
return;
|
||||||
|
ItemList *items =
|
||||||
|
editor->get_as_node<ItemList>("%line_buildings_list");
|
||||||
|
items->clear();
|
||||||
|
for (i = 0; i < (int)RoadLinesData::get_singleton()
|
||||||
|
->lines[current_line]
|
||||||
|
.buildings.size();
|
||||||
|
i++) {
|
||||||
|
const String &key = RoadLinesData::get_singleton()
|
||||||
|
->lines[current_line]
|
||||||
|
.buildings[i]
|
||||||
|
.building_key;
|
||||||
|
items->add_item(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
void main_handler(int id)
|
void main_handler(int id)
|
||||||
{
|
{
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -340,12 +368,25 @@ protected:
|
|||||||
case 33:
|
case 33:
|
||||||
editor->remove_road_meshes();
|
editor->remove_road_meshes();
|
||||||
break;
|
break;
|
||||||
|
case 34: {
|
||||||
|
RoadLinesData::get_singleton()->assign_close_buildings(
|
||||||
|
current_line);
|
||||||
|
editor->update_line_geometry();
|
||||||
|
} break;
|
||||||
|
case 36:
|
||||||
|
editor->get_as_node<Control>("%road_lines_base")->hide();
|
||||||
|
editor->get_as_node<Control>("%road_lines_buildings")
|
||||||
|
->show();
|
||||||
|
update_line_buildings_editor();
|
||||||
|
break;
|
||||||
case 51:
|
case 51:
|
||||||
editor->set_point_to_cursor();
|
editor->set_point_to_cursor();
|
||||||
break;
|
break;
|
||||||
case 52:
|
case 52:
|
||||||
editor->move_cursor_to_point();
|
editor->move_cursor_to_point();
|
||||||
break;
|
break;
|
||||||
|
case 53:
|
||||||
|
editor->move_cursor_to_closest_building();
|
||||||
case 101:
|
case 101:
|
||||||
editor->save_data();
|
editor->save_data();
|
||||||
break;
|
break;
|
||||||
@@ -403,6 +444,7 @@ protected:
|
|||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
print_line("menu option pressed: " + itos(id));
|
print_line("menu option pressed: " + itos(id));
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void cancel_handler()
|
void cancel_handler()
|
||||||
@@ -496,6 +538,19 @@ protected:
|
|||||||
} else
|
} else
|
||||||
metadata_text->remove_color_override("font_color");
|
metadata_text->remove_color_override("font_color");
|
||||||
}
|
}
|
||||||
|
void line_buildings_close_handler()
|
||||||
|
{
|
||||||
|
editor->get_as_node<Control>("%road_lines_base")->show();
|
||||||
|
editor->get_as_node<Control>("%road_lines_buildings")->hide();
|
||||||
|
}
|
||||||
|
void line_buildings_assign_handler()
|
||||||
|
{
|
||||||
|
update_line_buildings_editor();
|
||||||
|
}
|
||||||
|
void line_buildings_remove_handler()
|
||||||
|
{
|
||||||
|
update_line_buildings_editor();
|
||||||
|
}
|
||||||
static void _bind_methods()
|
static void _bind_methods()
|
||||||
{
|
{
|
||||||
ClassDB::bind_method(D_METHOD("main_handler", "id"),
|
ClassDB::bind_method(D_METHOD("main_handler", "id"),
|
||||||
@@ -515,6 +570,15 @@ protected:
|
|||||||
ClassDB::bind_method(
|
ClassDB::bind_method(
|
||||||
D_METHOD("metadata_changed_handler"),
|
D_METHOD("metadata_changed_handler"),
|
||||||
&HandleCreateNewLine::metadata_changed_handler);
|
&HandleCreateNewLine::metadata_changed_handler);
|
||||||
|
ClassDB::bind_method(
|
||||||
|
D_METHOD("line_buildings_close_handler"),
|
||||||
|
&HandleCreateNewLine::line_buildings_close_handler);
|
||||||
|
ClassDB::bind_method(
|
||||||
|
D_METHOD("line_buildings_assign_handler"),
|
||||||
|
&HandleCreateNewLine::line_buildings_assign_handler);
|
||||||
|
ClassDB::bind_method(
|
||||||
|
D_METHOD("line_buildings_remove_handler"),
|
||||||
|
&HandleCreateNewLine::line_buildings_remove_handler);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -593,6 +657,25 @@ void RoadLinesEditor::update_line_geometry()
|
|||||||
}
|
}
|
||||||
line_im->end();
|
line_im->end();
|
||||||
}
|
}
|
||||||
|
if (rld->lines[current_line].buildings.size() > 1) {
|
||||||
|
line_im->begin(Mesh::PRIMITIVE_LINES);
|
||||||
|
for (i = 0;
|
||||||
|
i < (int)rld->lines[current_line].buildings.size();
|
||||||
|
i++) {
|
||||||
|
const RoadLinesData::line_building_data &b =
|
||||||
|
rld->lines[current_line].buildings[i];
|
||||||
|
Vector3 pt = rld->get_point_by_offsets(
|
||||||
|
current_line, b.line_offset,
|
||||||
|
b.normal_offset);
|
||||||
|
line_im->set_color(
|
||||||
|
Color(0.1f, 0.8f, 0.8f, 1.0f));
|
||||||
|
line_im->add_vertex(pt +
|
||||||
|
Vector3(0.0f, 5.0f, 0.0f));
|
||||||
|
line_im->add_vertex(pt +
|
||||||
|
Vector3(0.0f, 15.0f, 0.0f));
|
||||||
|
}
|
||||||
|
line_im->end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RoadLinesEditor::update_line_index_ui()
|
void RoadLinesEditor::update_line_index_ui()
|
||||||
@@ -705,6 +788,20 @@ void RoadLinesEditor::move_cursor_to_point()
|
|||||||
set_ui_cursor_position(xform.origin);
|
set_ui_cursor_position(xform.origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RoadLinesEditor::move_cursor_to_closest_building()
|
||||||
|
{
|
||||||
|
print_line("move_cursor_to_closest_building");
|
||||||
|
Vector3 pt = get_cursor_position();
|
||||||
|
int index = BuildingsData::get_singleton()->get_closest_building(
|
||||||
|
Transform(Basis(), pt));
|
||||||
|
const Transform &xform =
|
||||||
|
BuildingsData::get_singleton()->buildings[index].xform;
|
||||||
|
set_cursor_position(xform.origin);
|
||||||
|
Spatial *cursor = get_as_node<Spatial>(cursor_name);
|
||||||
|
if (!cursor->is_visible())
|
||||||
|
cursor->show();
|
||||||
|
}
|
||||||
|
|
||||||
void RoadLinesEditor::update(float delta)
|
void RoadLinesEditor::update(float delta)
|
||||||
{
|
{
|
||||||
if (!active)
|
if (!active)
|
||||||
@@ -794,6 +891,7 @@ void RoadLinesEditor::update_ui()
|
|||||||
get_as_node<Control>("%road_lines_base")->show();
|
get_as_node<Control>("%road_lines_base")->show();
|
||||||
get_as_node<Control>("%road_lines_create_new_line_dlg")->hide();
|
get_as_node<Control>("%road_lines_create_new_line_dlg")->hide();
|
||||||
get_as_node<Control>("%road_lines_edit_metadata_dlg")->hide();
|
get_as_node<Control>("%road_lines_edit_metadata_dlg")->hide();
|
||||||
|
get_as_node<Control>("%road_lines_buildings")->hide();
|
||||||
ItemList *lines_list = get_as_node<ItemList>("%lines_list");
|
ItemList *lines_list = get_as_node<ItemList>("%lines_list");
|
||||||
List<String> line_keys;
|
List<String> line_keys;
|
||||||
rld->lines.get_key_list(&line_keys);
|
rld->lines.get_key_list(&line_keys);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public:
|
|||||||
void set_point_to_cursor();
|
void set_point_to_cursor();
|
||||||
int get_line_index();
|
int get_line_index();
|
||||||
void move_cursor_to_point();
|
void move_cursor_to_point();
|
||||||
|
void move_cursor_to_closest_building();
|
||||||
void update(float delta);
|
void update(float delta);
|
||||||
void exit();
|
void exit();
|
||||||
void editor_command(const String &command, const Array &args);
|
void editor_command(const String &command, const Array &args);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <core/set.h>
|
#include <core/set.h>
|
||||||
|
#include <core/io/json.h>
|
||||||
#include <scene/main/viewport.h>
|
#include <scene/main/viewport.h>
|
||||||
#include <scene/resources/packed_scene.h>
|
#include <scene/resources/packed_scene.h>
|
||||||
#include <scene/resources/material.h>
|
#include <scene/resources/material.h>
|
||||||
@@ -258,27 +259,13 @@ void StreamWorld::run_command(const String &command, const Array &args)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const Transform &xform = args[0];
|
const Transform &xform = args[0];
|
||||||
int i;
|
int id = data()->get_closest_building(xform);
|
||||||
float dst = Math_INF;
|
|
||||||
Transform ret;
|
|
||||||
String rkey;
|
|
||||||
int id = -1;
|
|
||||||
for (i = 0; i < (int)data()->buildings.size(); i++) {
|
|
||||||
Vector3 o = xform.origin;
|
|
||||||
Vector3 m = data()->buildings[i].xform.origin;
|
|
||||||
float mdst = o.distance_squared_to(m);
|
|
||||||
if (dst > mdst) {
|
|
||||||
ret = data()->buildings[i].xform;
|
|
||||||
dst = mdst;
|
|
||||||
rkey = data()->buildings[i].key;
|
|
||||||
id = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Array ret_data;
|
Array ret_data;
|
||||||
ret_data.resize(5);
|
ret_data.resize(5);
|
||||||
ret_data[0] = ret;
|
ret_data[0] = data()->buildings[id].xform;
|
||||||
ret_data[1] = dst;
|
ret_data[1] = xform.origin.distance_squared_to(
|
||||||
ret_data[2] = rkey;
|
data()->buildings[id].xform.origin);
|
||||||
|
ret_data[2] = data()->buildings[id].key;
|
||||||
ret_data[3] = id;
|
ret_data[3] = id;
|
||||||
ret_data[4] = data()->buildings[id].id;
|
ret_data[4] = data()->buildings[id].id;
|
||||||
emit_signal("command_result", command, ret_data);
|
emit_signal("command_result", command, ret_data);
|
||||||
@@ -288,11 +275,12 @@ void StreamWorld::run_command(const String &command, const Array &args)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String key = args[1];
|
String key = args[1];
|
||||||
|
uint64_t khash = key.hash64();
|
||||||
Array ret_data;
|
Array ret_data;
|
||||||
ret_data.resize(1);
|
ret_data.resize(1);
|
||||||
int id = -1, i;
|
int id = -1, i;
|
||||||
for (i = 0; i < (int)data()->buildings.size(); i++)
|
for (i = 0; i < (int)data()->buildings.size(); i++)
|
||||||
if (data()->buildings[i].key == key) {
|
if (data()->buildings[i].key.hash64() == khash) {
|
||||||
id = i;
|
id = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -306,16 +294,12 @@ void StreamWorld::run_command(const String &command, const Array &args)
|
|||||||
int id = args[0];
|
int id = args[0];
|
||||||
if (id < 0 || id >= (int)data()->buildings.size())
|
if (id < 0 || id >= (int)data()->buildings.size())
|
||||||
return;
|
return;
|
||||||
String key = data()->buildings[id].key;
|
data()->update_building_transform(id, args[1]);
|
||||||
data()->buildings[id].xform == args[1];
|
|
||||||
if (item_nodes.has(id)) {
|
if (item_nodes.has(id)) {
|
||||||
Spatial *bnode =
|
Spatial *bnode =
|
||||||
Object::cast_to<Spatial>(item_nodes[id]);
|
Object::cast_to<Spatial>(item_nodes[id]);
|
||||||
bnode->set_global_transform(args[1]);
|
bnode->set_global_transform(args[1]);
|
||||||
}
|
}
|
||||||
VariantWriter::write_to_string(data()->buildings[id].xform,
|
|
||||||
key);
|
|
||||||
data()->buildings[id].key = key;
|
|
||||||
} else if (command == "checkpoint")
|
} else if (command == "checkpoint")
|
||||||
data()->checkpoint();
|
data()->checkpoint();
|
||||||
else if (command == "undo")
|
else if (command == "undo")
|
||||||
@@ -356,10 +340,10 @@ void StreamWorld::run_command(const String &command, const Array &args)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const Dictionary &building_dict = args[0];
|
const Dictionary &building_dict = args[0];
|
||||||
const String &key = args[1];
|
|
||||||
struct BuildingsData::building b;
|
struct BuildingsData::building b;
|
||||||
// TODO: check that key is valid
|
// TODO: check that key is valid
|
||||||
BuildingsData::building::from_dict(&b, building_dict, key);
|
print_verbose("DICT: " + (JSON::print(building_dict, "\t")));
|
||||||
|
BuildingsData::building::from_dict(&b, building_dict);
|
||||||
data()->buildings.push_back(b);
|
data()->buildings.push_back(b);
|
||||||
load_building(data()->buildings.size() - 1);
|
load_building(data()->buildings.size() - 1);
|
||||||
} else if (command == "remove_building") {
|
} else if (command == "remove_building") {
|
||||||
|
|||||||
@@ -389,12 +389,8 @@ void WorldEditor::world_command_result(const String &what, const Array &data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<String> tool_buttons = {
|
static std::vector<String> tool_buttons = {
|
||||||
"%select_buildings"
|
"%select_buildings", "%select_navigation", "%select_poi",
|
||||||
"%select_navigation",
|
"%select_road_lines", "%select_npc", "%buildings_save",
|
||||||
"%select_poi",
|
|
||||||
"%select_road_lines",
|
|
||||||
"%select_npc",
|
|
||||||
"%buildings_save",
|
|
||||||
};
|
};
|
||||||
std::vector<HandleCommandButton *> tool_handlers;
|
std::vector<HandleCommandButton *> tool_handlers;
|
||||||
void WorldEditor::_notification(int which)
|
void WorldEditor::_notification(int which)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <scene/3d/spatial.h>
|
#include <scene/3d/spatial.h>
|
||||||
#include "editor_mixin.h"
|
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
class RoadLinesEditor;
|
class RoadLinesEditor;
|
||||||
class BuildingsEditor;
|
class BuildingsEditor;
|
||||||
|
|||||||
Reference in New Issue
Block a user