Editor UI refactoring
This commit is contained in:
@@ -63,264 +63,24 @@ margin_bottom = 48.0
|
||||
rect_min_size = Vector2( 48, 48 )
|
||||
focus_mode = 2
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="VBoxContainer"]
|
||||
[node name="MainTabs" type="MainTabs" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 52.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 82.0
|
||||
rect_min_size = Vector2( 160, 30 )
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 5
|
||||
color = Color( 0.25098, 0.25098, 0.25098, 1 )
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/ColorRect"]
|
||||
margin_left = 39.0
|
||||
margin_top = 8.0
|
||||
margin_right = 118.0
|
||||
margin_bottom = 22.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 7
|
||||
text = "Mode select"
|
||||
align = 1
|
||||
valign = 1
|
||||
|
||||
[node name="select_buildings" type="Button" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 86.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 106.0
|
||||
text = "Buildings Mode"
|
||||
|
||||
[node name="select_navigation" type="Button" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 110.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 130.0
|
||||
text = "Navigation Mode"
|
||||
|
||||
[node name="select_poi" type="Button" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 134.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 154.0
|
||||
text = "POI Mode"
|
||||
|
||||
[node name="select_road_lines" type="Button" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 158.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 178.0
|
||||
text = "Road Lines Mode"
|
||||
|
||||
[node name="select_npc" type="Button" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 182.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 202.0
|
||||
text = "NPC Mode"
|
||||
margin_bottom = 500.0
|
||||
|
||||
[node name="v_buildings" type="VBoxContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 206.0
|
||||
margin_top = 504.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 650.0
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_buildings"]
|
||||
margin_right = 248.0
|
||||
margin_bottom = 4.0
|
||||
|
||||
[node name="base" type="PanelContainer" parent="VBoxContainer/v_buildings"]
|
||||
margin_top = 8.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 444.0
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/v_buildings/base"]
|
||||
margin_left = 7.0
|
||||
margin_top = 7.0
|
||||
margin_right = 241.0
|
||||
margin_bottom = 429.0
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_right = 234.0
|
||||
margin_bottom = 14.0
|
||||
text = "Buildings mode"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 18.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 22.0
|
||||
|
||||
[node name="Label3" type="Label" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 26.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 40.0
|
||||
text = "Cursor position"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 44.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 68.0
|
||||
|
||||
[node name="building_cursor_x" type="LineEdit" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_right = 63.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="building_cursor_y" type="LineEdit" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_left = 67.0
|
||||
margin_right = 130.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="building_cursor_z" type="LineEdit" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_left = 134.0
|
||||
margin_right = 197.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="buildings_set_cursor_position" type="Button" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_left = 201.0
|
||||
margin_right = 233.0
|
||||
margin_bottom = 24.0
|
||||
text = "Set"
|
||||
|
||||
[node name="Label5" type="Label" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 72.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 86.0
|
||||
text = "Selected building position"
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 90.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 114.0
|
||||
|
||||
[node name="building_position_x" type="LineEdit" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
margin_right = 75.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="building_position_y" type="LineEdit" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
margin_left = 79.0
|
||||
margin_right = 154.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="building_position_z" type="LineEdit" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
margin_left = 158.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="HBoxContainer3" type="HBoxContainer" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 118.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 142.0
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer3"]
|
||||
margin_top = 5.0
|
||||
margin_right = 18.0
|
||||
margin_bottom = 19.0
|
||||
text = "rot"
|
||||
|
||||
[node name="building_rotation_y" type="LineEdit" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer3"]
|
||||
unique_name_in_owner = true
|
||||
margin_left = 22.0
|
||||
margin_right = 80.0
|
||||
margin_bottom = 24.0
|
||||
|
||||
[node name="buildings_set_building_position" type="Button" parent="VBoxContainer/v_buildings/base/VBoxContainer/HBoxContainer3"]
|
||||
unique_name_in_owner = true
|
||||
margin_left = 84.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 24.0
|
||||
text = "Set"
|
||||
|
||||
[node name="HSeparator3" type="HSeparator" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 146.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 150.0
|
||||
|
||||
[node name="Label4" type="Label" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 154.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 168.0
|
||||
text = "Mode"
|
||||
|
||||
[node name="buildings_edit_mode" type="OptionButton" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 172.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 192.0
|
||||
text = "Select"
|
||||
items = [ "Select", null, false, 0, null, "Move", null, false, 1, null, "Rotate", null, false, 2, null, "Create", null, false, 3, null ]
|
||||
selected = 0
|
||||
|
||||
[node name="Label2" type="Label" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 196.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 210.0
|
||||
text = "Building type"
|
||||
|
||||
[node name="building_type" type="OptionButton" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 214.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 234.0
|
||||
text = "Building Type"
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
margin_top = 238.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 242.0
|
||||
|
||||
[node name="buildings_delete_building" type="Button" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 246.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 266.0
|
||||
text = "Delete building"
|
||||
|
||||
[node name="buildings_create_building" type="Button" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 270.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 290.0
|
||||
text = "Create building"
|
||||
|
||||
[node name="buildings_save" type="Button" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 294.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 314.0
|
||||
text = "Save Buildings"
|
||||
|
||||
[node name="lines_list_building" type="ItemList" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 318.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 398.0
|
||||
rect_min_size = Vector2( 0, 80 )
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="buildings_assign_to_line" type="Button" parent="VBoxContainer/v_buildings/base/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 402.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 422.0
|
||||
text = "Assign To Line"
|
||||
margin_bottom = 504.0
|
||||
|
||||
[node name="v_navigation" type="VBoxContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 654.0
|
||||
visible = false
|
||||
margin_top = 246.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 676.0
|
||||
margin_bottom = 268.0
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_navigation"]
|
||||
margin_right = 248.0
|
||||
@@ -334,9 +94,10 @@ text = "Navigation mode"
|
||||
|
||||
[node name="v_poi" type="VBoxContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 680.0
|
||||
visible = false
|
||||
margin_top = 246.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 702.0
|
||||
margin_bottom = 268.0
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_poi"]
|
||||
margin_right = 248.0
|
||||
@@ -350,9 +111,10 @@ text = "POI mode"
|
||||
|
||||
[node name="v_road_lines" type="VBoxContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 706.0
|
||||
visible = false
|
||||
margin_top = 246.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 1665.0
|
||||
margin_bottom = 1205.0
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_road_lines"]
|
||||
margin_right = 248.0
|
||||
@@ -604,8 +366,8 @@ size_flags_vertical = 3
|
||||
scroll_horizontal_enabled = false
|
||||
|
||||
[node name="v" type="VBoxContainer" parent="VBoxContainer/v_road_lines/road_lines_edit_metadata_dlg/scroll"]
|
||||
margin_right = 222.0
|
||||
margin_bottom = 418.0
|
||||
margin_right = 234.0
|
||||
margin_bottom = 250.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
@@ -730,9 +492,10 @@ text = "Close"
|
||||
|
||||
[node name="v_npc" type="VBoxContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 1669.0
|
||||
visible = false
|
||||
margin_top = 1749.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 1691.0
|
||||
margin_bottom = 1771.0
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_npc"]
|
||||
margin_right = 248.0
|
||||
|
||||
Submodule src/flecs updated: b002dcb575...de8b378bd8
Submodule src/godot updated: 3ee8ecdf25...3841d76515
Submodule src/meshoptimizer updated: 7f936ad1b5...b0cc223e1a
@@ -3,14 +3,14 @@
|
||||
Import("env")
|
||||
Import("env_modules")
|
||||
|
||||
|
||||
env_stream = env_modules.Clone()
|
||||
|
||||
# Godot source files
|
||||
|
||||
module_obj = []
|
||||
|
||||
SConscript("buildings/SCsub")
|
||||
SConscript("ui/SCsub")
|
||||
|
||||
env_stream = env_modules.Clone()
|
||||
|
||||
env_stream.Prepend(CPPPATH=["../../meshoptimizer/src"])
|
||||
env_stream.add_source_files(module_obj, "*.cpp")
|
||||
|
||||
@@ -205,6 +205,7 @@ void ElementData::grow_cell(int type, const String &key, bool exterior, int fl,
|
||||
}
|
||||
void ElementData::create_new_layout(const String &key)
|
||||
{
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
flecs::entity layout = ecs.entity(key.ascii().ptr()).child_of(top);
|
||||
@@ -220,6 +221,7 @@ void ElementData::create_new_layout(const String &key)
|
||||
void ElementData::create_new_exterior_floor(const String &key)
|
||||
{
|
||||
int i;
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity ext = get_base(key, true);
|
||||
assert(ext.is_valid());
|
||||
struct grid_layout_base *l = ext.get_mut<grid_layout_base>();
|
||||
@@ -243,6 +245,7 @@ void ElementData::create_new_interior_floor(const String &key)
|
||||
assert(intr.is_valid());
|
||||
struct grid_layout_base *l = intr.get_mut<grid_layout_base>();
|
||||
int floor = l->floor_count;
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity fl = ecs.entity(("floor_" + itos(floor)).ascii().ptr())
|
||||
.child_of(intr);
|
||||
assert(fl.is_valid());
|
||||
@@ -257,6 +260,7 @@ void ElementData::create_new_interior_floor(const String &key)
|
||||
}
|
||||
void ElementData::serialize_layouts(Dictionary &store)
|
||||
{
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
top.children([this, &store](flecs::entity l) {
|
||||
@@ -324,6 +328,7 @@ void ElementData::serialize_layouts(Dictionary &store)
|
||||
void ElementData::unserialize_layouts(const Dictionary &store)
|
||||
{
|
||||
int i;
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
// delete all layouts
|
||||
@@ -417,6 +422,7 @@ void ElementData::ensure_floor(const String &key, bool exterior, int fl)
|
||||
int i;
|
||||
if (has_floor(key, exterior, fl))
|
||||
return;
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity base = get_base(key, exterior);
|
||||
flecs::entity floor_e =
|
||||
ecs.entity(("floor_" + itos(fl)).ascii().ptr()).child_of(base);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <core/engine.h>
|
||||
#include <editor/editor_node.h>
|
||||
#include <flecs/flecs.h>
|
||||
#include "base_data.h"
|
||||
#include "editor_event.h"
|
||||
template <class T> T *get_as_node(const String &path)
|
||||
{
|
||||
@@ -60,7 +61,6 @@ template <class T> void select_control_item(T *ctl, const String &item)
|
||||
}
|
||||
#define ELEMENT_SOCKETS 16
|
||||
class ElementData {
|
||||
flecs::world ecs;
|
||||
static ElementData *singleton;
|
||||
|
||||
public:
|
||||
@@ -124,6 +124,7 @@ public:
|
||||
protected:
|
||||
ElementData()
|
||||
{
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
ecs.component<struct grid_layouts>();
|
||||
ecs.component<struct grid_layout>();
|
||||
ecs.component<struct grid_layout_exterior>();
|
||||
@@ -185,6 +186,7 @@ public:
|
||||
}
|
||||
inline const flecs::entity get_layout(const String &key) const
|
||||
{
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
flecs::entity layout = top.lookup(key.ascii().ptr());
|
||||
@@ -301,6 +303,7 @@ public:
|
||||
}
|
||||
void get_grid_layouts_key_list(List<String> *keys)
|
||||
{
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity top = ecs.lookup("grid_layouts");
|
||||
assert(top.is_valid());
|
||||
flecs::query_builder<const struct grid_layout> qb =
|
||||
@@ -438,4 +441,4 @@ public:
|
||||
void load_data();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#undef NDEBUG
|
||||
#include <cassert>
|
||||
#include <core/variant.h>
|
||||
#include <core/engine.h>
|
||||
#include <core/os/time.h>
|
||||
#include <scene/gui/option_button.h>
|
||||
#include <scene/gui/line_edit.h>
|
||||
@@ -12,342 +13,10 @@
|
||||
#include "editor_event.h"
|
||||
#include "world_editor.h"
|
||||
#include "buildings_data.h"
|
||||
#include "base_data.h"
|
||||
#include "ui/main_tabs.h"
|
||||
#include "buildings_editor.h"
|
||||
|
||||
class HandlePositionSetting : public Object {
|
||||
GDCLASS(HandlePositionSetting, Object)
|
||||
BuildingsEditor *editor;
|
||||
int old_mode;
|
||||
|
||||
public:
|
||||
HandlePositionSetting(BuildingsEditor *editor)
|
||||
: Object()
|
||||
, editor(editor)
|
||||
, old_mode(-1)
|
||||
{
|
||||
SceneTree::get_singleton()->connect("idle_frame", this,
|
||||
"handle_update");
|
||||
Button *set_cursor_position = editor->get_as_node<Button>(
|
||||
"%buildings_set_cursor_position");
|
||||
set_cursor_position->connect("pressed", this,
|
||||
"handle_set_cursor");
|
||||
Button *set_building_position = editor->get_as_node<Button>(
|
||||
"%buildings_set_building_position");
|
||||
set_building_position->connect("pressed", this,
|
||||
"handle_set_building");
|
||||
EditorEvent::get_singleton()->event.add_listener(
|
||||
this, &HandlePositionSetting::handle_event);
|
||||
#if 0
|
||||
String building = editor->get_selected_building();
|
||||
if (building.length() > 0) {
|
||||
Vector3 building_pos =
|
||||
editor->get_selected_building_xform().origin;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
virtual ~HandlePositionSetting()
|
||||
{
|
||||
EditorEvent::get_singleton()->event.remove_listener(
|
||||
this, &HandlePositionSetting::handle_event);
|
||||
Button *set_building_position = editor->get_as_node<Button>(
|
||||
"%buildings_set_building_position");
|
||||
set_building_position->disconnect("pressed", this,
|
||||
"handle_set_building");
|
||||
Button *set_cursor_position = editor->get_as_node<Button>(
|
||||
"%buildings_set_cursor_position");
|
||||
set_cursor_position->disconnect("pressed", this,
|
||||
"handle_set_cursor");
|
||||
SceneTree::get_singleton()->disconnect("idle_frame", this,
|
||||
"handle_update");
|
||||
}
|
||||
|
||||
protected:
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(D_METHOD("handle_update"),
|
||||
&HandlePositionSetting::handle_update);
|
||||
ClassDB::bind_method(D_METHOD("handle_set_cursor"),
|
||||
&HandlePositionSetting::handle_set_cursor);
|
||||
ClassDB::bind_method(
|
||||
D_METHOD("handle_set_building"),
|
||||
&HandlePositionSetting::handle_set_building);
|
||||
}
|
||||
|
||||
private:
|
||||
void handle_event(const String &event, const Vector<Variant> &args)
|
||||
{
|
||||
if (event == "buildings_building_cursor_moved") {
|
||||
Vector3 position = args[0];
|
||||
LineEdit *cursor_x = editor->get_as_node<LineEdit>(
|
||||
"%building_cursor_x");
|
||||
LineEdit *cursor_y = editor->get_as_node<LineEdit>(
|
||||
"%building_cursor_y");
|
||||
LineEdit *cursor_z = editor->get_as_node<LineEdit>(
|
||||
"%building_cursor_z");
|
||||
cursor_x->set_text(String::num(position.x));
|
||||
cursor_y->set_text(String::num(position.y));
|
||||
cursor_z->set_text(String::num(position.z));
|
||||
} else if (event == "buildings_building_selected" ||
|
||||
event == "buildings_building_moved" ||
|
||||
event == "buildings_building_rotated") {
|
||||
LineEdit *position_x = editor->get_as_node<LineEdit>(
|
||||
"%building_position_x");
|
||||
LineEdit *position_y = editor->get_as_node<LineEdit>(
|
||||
"%building_position_y");
|
||||
LineEdit *position_z = editor->get_as_node<LineEdit>(
|
||||
"%building_position_z");
|
||||
LineEdit *position_rot = editor->get_as_node<LineEdit>(
|
||||
"%building_rotation_y");
|
||||
Transform xform = editor->get_selected_building_xform();
|
||||
position_x->set_text(String::num(xform.origin.x));
|
||||
position_y->set_text(String::num(xform.origin.y));
|
||||
position_z->set_text(String::num(xform.origin.z));
|
||||
Vector3 reference(0, 0, -1);
|
||||
Vector3 rotated =
|
||||
xform.basis.xform(reference).normalized();
|
||||
float angle = reference.signed_angle_to(
|
||||
rotated, Vector3(0, 1, 0));
|
||||
position_rot->set_text(
|
||||
String::num(angle * 180.0f / Math_PI));
|
||||
}
|
||||
}
|
||||
void handle_set_cursor()
|
||||
{
|
||||
LineEdit *cursor_x =
|
||||
editor->get_as_node<LineEdit>("%building_cursor_x");
|
||||
LineEdit *cursor_y =
|
||||
editor->get_as_node<LineEdit>("%building_cursor_y");
|
||||
LineEdit *cursor_z =
|
||||
editor->get_as_node<LineEdit>("%building_cursor_z");
|
||||
Vector3 position;
|
||||
position.x = cursor_x->get_text().to_float();
|
||||
position.y = cursor_y->get_text().to_float();
|
||||
position.z = cursor_z->get_text().to_float();
|
||||
editor->set_cursor_position(position);
|
||||
}
|
||||
void handle_set_building()
|
||||
{
|
||||
LineEdit *position_x =
|
||||
editor->get_as_node<LineEdit>("%building_position_x");
|
||||
LineEdit *position_y =
|
||||
editor->get_as_node<LineEdit>("%building_position_y");
|
||||
LineEdit *position_z =
|
||||
editor->get_as_node<LineEdit>("%building_position_z");
|
||||
LineEdit *position_rot =
|
||||
editor->get_as_node<LineEdit>("%building_rotation_y");
|
||||
Transform xform = editor->get_selected_building_xform();
|
||||
xform.basis = Basis().rotated(
|
||||
Vector3(0, 1, 0),
|
||||
position_rot->get_text().to_float() * Math_PI / 180.0f);
|
||||
xform.origin.x = position_x->get_text().to_float();
|
||||
xform.origin.y = position_y->get_text().to_float();
|
||||
xform.origin.z = position_z->get_text().to_float();
|
||||
String key = editor->get_selected_building();
|
||||
int mode = editor->get_buildings_editor_mode();
|
||||
if (mode == 1 || mode == 2)
|
||||
editor->set_cursor_position(xform.origin);
|
||||
editor->emit("run_update_building_transform",
|
||||
varray(key, xform));
|
||||
}
|
||||
void handle_update()
|
||||
{
|
||||
// TODO: handle selection
|
||||
int i;
|
||||
int mode = editor->get_buildings_editor_mode();
|
||||
LineEdit *cursor_x =
|
||||
editor->get_as_node<LineEdit>("%building_cursor_x");
|
||||
LineEdit *cursor_y =
|
||||
editor->get_as_node<LineEdit>("%building_cursor_y");
|
||||
LineEdit *cursor_z =
|
||||
editor->get_as_node<LineEdit>("%building_cursor_z");
|
||||
LineEdit *cursor_le[] = { cursor_x, cursor_y, cursor_z };
|
||||
Button *set_cursor_position = editor->get_as_node<Button>(
|
||||
"%buildings_set_cursor_position");
|
||||
LineEdit *position_x =
|
||||
editor->get_as_node<LineEdit>("%building_position_x");
|
||||
LineEdit *position_y =
|
||||
editor->get_as_node<LineEdit>("%building_position_y");
|
||||
LineEdit *position_z =
|
||||
editor->get_as_node<LineEdit>("%building_position_z");
|
||||
LineEdit *position_rot =
|
||||
editor->get_as_node<LineEdit>("%building_rotation_y");
|
||||
LineEdit *position_le[] = { position_x, position_y, position_z,
|
||||
position_rot };
|
||||
Button *set_building_position = editor->get_as_node<Button>(
|
||||
"%buildings_set_building_position");
|
||||
int sz_cursor = (int)(sizeof(cursor_le) / sizeof(cursor_le[0]));
|
||||
int sz_position =
|
||||
(int)(sizeof(position_le) / sizeof(position_le[0]));
|
||||
if (mode != old_mode) {
|
||||
switch (mode) {
|
||||
case 0: // select
|
||||
for (i = 0; i < sz_cursor; i++)
|
||||
cursor_le[i]->set_editable(false);
|
||||
set_cursor_position->set_disabled(true);
|
||||
for (i = 0; i < sz_position; i++)
|
||||
position_le[i]->set_editable(false);
|
||||
set_building_position->set_disabled(true);
|
||||
break;
|
||||
case 1: // move
|
||||
for (i = 0; i < sz_cursor; i++)
|
||||
cursor_le[i]->set_editable(false);
|
||||
set_cursor_position->set_disabled(true);
|
||||
for (i = 0; i < sz_position; i++)
|
||||
position_le[i]->set_editable(true);
|
||||
set_building_position->set_disabled(false);
|
||||
break;
|
||||
case 2: // rotate
|
||||
for (i = 0; i < sz_cursor; i++)
|
||||
cursor_le[i]->set_editable(false);
|
||||
set_cursor_position->set_disabled(true);
|
||||
for (i = 0; i < sz_position; i++)
|
||||
position_le[i]->set_editable(true);
|
||||
set_building_position->set_disabled(false);
|
||||
break;
|
||||
case 3: // create
|
||||
for (i = 0; i < sz_cursor; i++)
|
||||
cursor_le[i]->set_editable(true);
|
||||
set_cursor_position->set_disabled(false);
|
||||
for (i = 0; i < sz_position; i++)
|
||||
position_le[i]->set_editable(true);
|
||||
set_building_position->set_disabled(false);
|
||||
break;
|
||||
}
|
||||
old_mode = mode;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class HandleChangeBuildingType : public Object {
|
||||
GDCLASS(HandleChangeBuildingType, Object)
|
||||
BuildingsEditor *editor;
|
||||
|
||||
void change_building_type(int index)
|
||||
{
|
||||
OptionButton *building_type =
|
||||
editor->get_as_node<OptionButton>("%building_type");
|
||||
const String &item = building_type->get_item_text(index);
|
||||
int bmode = editor->get_buildings_editor_mode();
|
||||
if (bmode == 0 || bmode == 1 ||
|
||||
bmode == 2) /* select, move, rotate */
|
||||
editor->change_building_type(item);
|
||||
/* do not change building types in create mode (3) */
|
||||
}
|
||||
|
||||
public:
|
||||
HandleChangeBuildingType(BuildingsEditor *editor)
|
||||
: Object()
|
||||
, editor(editor)
|
||||
{
|
||||
OptionButton *building_type =
|
||||
editor->get_as_node<OptionButton>("%building_type");
|
||||
building_type->connect("item_selected", this,
|
||||
"change_building_type");
|
||||
}
|
||||
virtual ~HandleChangeBuildingType()
|
||||
{
|
||||
OptionButton *building_type =
|
||||
editor->get_as_node<OptionButton>("%building_type");
|
||||
if (building_type->is_connected("item_selected", this,
|
||||
"change_building_type"))
|
||||
building_type->disconnect("item_selected", this,
|
||||
"change_building_type");
|
||||
}
|
||||
|
||||
protected:
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(
|
||||
D_METHOD("change_building_type", "index"),
|
||||
&HandleChangeBuildingType::change_building_type);
|
||||
}
|
||||
};
|
||||
class HandleButton : public Object {
|
||||
GDCLASS(HandleButton, Object)
|
||||
BuildingsEditor *editor;
|
||||
String button_path;
|
||||
String event_string;
|
||||
Vector<Variant> event_args;
|
||||
Button *get_button()
|
||||
{
|
||||
Button *button = editor->get_as_node<Button>(button_path);
|
||||
assert(button);
|
||||
return button;
|
||||
}
|
||||
void button_handler()
|
||||
{
|
||||
editor->emit("button:" + event_string, event_args);
|
||||
}
|
||||
|
||||
public:
|
||||
HandleButton(BuildingsEditor *editor, const String &button_path,
|
||||
const String &event_string,
|
||||
const Vector<Variant> &event_args = varray())
|
||||
: Object()
|
||||
, editor(editor)
|
||||
, button_path(button_path)
|
||||
, event_string(event_string)
|
||||
, event_args(event_args)
|
||||
{
|
||||
if (!get_button()->is_connected("pressed", this,
|
||||
"button_handler"))
|
||||
get_button()->connect("pressed", this,
|
||||
"button_handler");
|
||||
}
|
||||
virtual ~HandleButton()
|
||||
{
|
||||
if (get_button()->is_connected("pressed", this,
|
||||
"button_handler"))
|
||||
get_button()->disconnect("pressed", this,
|
||||
"button_handler");
|
||||
}
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(D_METHOD("button_handler"),
|
||||
&HandleButton::button_handler);
|
||||
}
|
||||
};
|
||||
|
||||
class HandleDeleteButton : public Object {
|
||||
GDCLASS(HandleDeleteButton, Object)
|
||||
BuildingsEditor *editor;
|
||||
|
||||
public:
|
||||
HandleDeleteButton(BuildingsEditor *editor)
|
||||
: Object()
|
||||
, editor(editor)
|
||||
{
|
||||
Button *delete_button = editor->get_as_node<Button>(
|
||||
"%buildings_delete_building");
|
||||
assert(delete_button);
|
||||
/* FIXME */
|
||||
if (!delete_button->is_connected("pressed", this,
|
||||
"delete_building_handler"))
|
||||
delete_button->connect("pressed", this,
|
||||
"delete_building_handler");
|
||||
}
|
||||
~HandleDeleteButton()
|
||||
{
|
||||
Button *delete_button = editor->get_as_node<Button>(
|
||||
"%buildings_delete_building");
|
||||
if (delete_button->is_connected("pressed", this,
|
||||
"delete_building_handler"))
|
||||
delete_button->disconnect("pressed", this,
|
||||
"delete_building_handler");
|
||||
}
|
||||
void delete_building_handler()
|
||||
{
|
||||
editor->delete_building_handler();
|
||||
}
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(
|
||||
D_METHOD("delete_building_handler"),
|
||||
&HandleDeleteButton::delete_building_handler);
|
||||
}
|
||||
};
|
||||
static std::vector<Object *> ui_handlers;
|
||||
|
||||
BuildingsEditor::BuildingsEditor(WorldEditor *editor)
|
||||
: editor(editor)
|
||||
, selected_building("")
|
||||
@@ -363,37 +32,16 @@ void BuildingsEditor::exit()
|
||||
|
||||
void BuildingsEditor::activate()
|
||||
{
|
||||
assert(scene());
|
||||
assert(!active);
|
||||
ConfigFile config;
|
||||
Error result = config.load("res://config/stream.conf");
|
||||
ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
|
||||
print_line("BuildingsEditor ACTIVE");
|
||||
ui_handlers.push_back(
|
||||
memnew(HandleButton(this, "%buildings_create_building",
|
||||
"create_building", varray())));
|
||||
ui_handlers.push_back(memnew(HandleChangeBuildingType(this)));
|
||||
ui_handlers.push_back(memnew(HandleDeleteButton(this)));
|
||||
ui_handlers.push_back(memnew(HandlePositionSetting(this)));
|
||||
int i;
|
||||
for (i = 0; i < (int)ui_handlers.size(); i++)
|
||||
assert(ui_handlers[i]);
|
||||
/* TODO: make separate function for this */
|
||||
EditorEvent::get_singleton()->event.add_listener(
|
||||
this, &BuildingsEditor::event_handler);
|
||||
Dictionary buildings_data =
|
||||
config.get_value("buildings", "building_data");
|
||||
OptionButton *building_type =
|
||||
get_as_node<OptionButton>("%building_type");
|
||||
building_type->clear();
|
||||
List<Variant> keys;
|
||||
buildings_data.get_key_list(&keys);
|
||||
List<Variant>::Element *e = keys.front();
|
||||
while (e) {
|
||||
const String &key = e->get();
|
||||
print_line("EE::" + key);
|
||||
building_type->add_item(key);
|
||||
e = e->next();
|
||||
}
|
||||
active = true;
|
||||
}
|
||||
|
||||
@@ -403,16 +51,13 @@ void BuildingsEditor::deactivate()
|
||||
EditorEvent::get_singleton()->event.remove_listener(
|
||||
this, &BuildingsEditor::event_handler);
|
||||
print_line("BuildingsEditor DEACTIVE");
|
||||
int i;
|
||||
for (i = 0; i < (int)ui_handlers.size(); i++)
|
||||
memdelete(ui_handlers[i]);
|
||||
ui_handlers.clear();
|
||||
active = false;
|
||||
}
|
||||
|
||||
void BuildingsEditor::event_handler(const String &event,
|
||||
const Vector<Variant> &args)
|
||||
{
|
||||
assert(scene());
|
||||
assert(active);
|
||||
print_line("E::" + event);
|
||||
if (event == "mouse_drag")
|
||||
@@ -421,6 +66,8 @@ void BuildingsEditor::event_handler(const String &event,
|
||||
mouse_press(args[0]);
|
||||
else if (event == "button:create_building")
|
||||
handle_create_building();
|
||||
else if (event == "button:delete_building")
|
||||
delete_building_handler();
|
||||
else if (event == "result:get_closest_building") {
|
||||
select_building(args[0], args[3], args[4]);
|
||||
if (get_buildings_editor_mode() == 2 /* rotate */) {
|
||||
@@ -444,34 +91,35 @@ void BuildingsEditor::event_handler(const String &event,
|
||||
|
||||
void BuildingsEditor::handle_create_building()
|
||||
{
|
||||
assert(scene());
|
||||
print_line("create_building");
|
||||
int bmode = get_buildings_editor_mode();
|
||||
assert(bmode == 3);
|
||||
OptionButton *building_type =
|
||||
get_as_node<OptionButton>("%building_type");
|
||||
int index = building_type->get_selected();
|
||||
if (index >= 0) {
|
||||
const String &item = building_type->get_item_text(index);
|
||||
Transform xform;
|
||||
xform.origin = get_cursor_position();
|
||||
Dictionary building_data;
|
||||
/* FIXME: calculate AABBs as in previous editor */
|
||||
String building_xform = to_string<Transform>(xform);
|
||||
building_data["id"] = item;
|
||||
building_data["key"] = String::num_uint64(
|
||||
String(item + building_xform +
|
||||
itos(Time::get_singleton()->get_ticks_usec()))
|
||||
.hash64(),
|
||||
16);
|
||||
building_data["xform"] = building_xform;
|
||||
editor->editor_command("create_building",
|
||||
varray(building_data));
|
||||
}
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity e = ecs.lookup("world_editor");
|
||||
assert(e.is_valid());
|
||||
const String &item =
|
||||
e.get<WorldEditor::components::buildings_editor_mode>()
|
||||
->current_type;
|
||||
Transform xform;
|
||||
xform.origin = get_cursor_position();
|
||||
Dictionary building_data;
|
||||
/* FIXME: calculate AABBs as in previous editor */
|
||||
String building_xform = to_string<Transform>(xform);
|
||||
building_data["id"] = item;
|
||||
building_data["key"] = String::num_uint64(
|
||||
String(item + building_xform +
|
||||
itos(Time::get_singleton()->get_ticks_usec()))
|
||||
.hash64(),
|
||||
16);
|
||||
building_data["xform"] = building_xform;
|
||||
editor->editor_command("create_building", varray(building_data));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void BuildingsEditor::mode_visibility(int mode, const String &path)
|
||||
{
|
||||
assert(scene());
|
||||
T *obj = get_as_node<T>(path);
|
||||
if (get_buildings_editor_mode() == mode) {
|
||||
if (!obj->is_visible())
|
||||
@@ -484,6 +132,7 @@ inline void BuildingsEditor::mode_visibility(int mode, const String &path)
|
||||
|
||||
void BuildingsEditor::update(float delta)
|
||||
{
|
||||
assert(scene());
|
||||
#ifdef _VERBOSE_DEBUG
|
||||
if (active)
|
||||
print_line("update: " + String::num(delta) + " " +
|
||||
@@ -500,13 +149,11 @@ void BuildingsEditor::update(float delta)
|
||||
rot_cursor->set_global_transform(
|
||||
selected_building_xform);
|
||||
}
|
||||
mode_visibility<Button>(0, "%buildings_delete_building");
|
||||
mode_visibility<Spatial>(2, "%building_rot_cursor");
|
||||
mode_visibility<Button>(3, "%buildings_create_building");
|
||||
}
|
||||
|
||||
void BuildingsEditor::mouse_drag(const Vector2 &position)
|
||||
{
|
||||
assert(scene());
|
||||
if (editor->get_current_mode() != WorldEditor::MODE_BUILDINGS) {
|
||||
print_verbose("bad editor mode: " +
|
||||
itos(editor->get_current_mode()));
|
||||
@@ -579,6 +226,7 @@ void BuildingsEditor::mouse_drag(const Vector2 &position)
|
||||
|
||||
void BuildingsEditor::mouse_press(const Vector2 &position)
|
||||
{
|
||||
assert(scene());
|
||||
if (editor->get_current_mode() != WorldEditor::MODE_BUILDINGS) {
|
||||
print_verbose("bad editor mode: " +
|
||||
itos(editor->get_current_mode()));
|
||||
@@ -644,6 +292,7 @@ void BuildingsEditor::mouse_press(const Vector2 &position)
|
||||
|
||||
void BuildingsEditor::set_cursor_position(const Vector3 &position)
|
||||
{
|
||||
assert(scene());
|
||||
Spatial *cursor = get_as_node<Spatial>("%building_cursor");
|
||||
if (!cursor->is_visible())
|
||||
cursor->show();
|
||||
@@ -657,6 +306,7 @@ void BuildingsEditor::set_cursor_position(const Vector3 &position)
|
||||
|
||||
Vector3 BuildingsEditor::get_cursor_position() const
|
||||
{
|
||||
assert(scene());
|
||||
const Spatial *cursor = get_as_node<Spatial>("%building_cursor");
|
||||
Transform xform = cursor->get_global_transform();
|
||||
return xform.origin;
|
||||
@@ -664,10 +314,12 @@ Vector3 BuildingsEditor::get_cursor_position() const
|
||||
|
||||
int BuildingsEditor::get_buildings_editor_mode() const
|
||||
{
|
||||
const OptionButton *buildings_edit_mode =
|
||||
get_as_node<OptionButton>("%buildings_edit_mode");
|
||||
int selected = buildings_edit_mode->get_selected();
|
||||
return selected;
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity e = ecs.lookup("world_editor");
|
||||
assert(e.is_valid());
|
||||
int mode =
|
||||
e.get<WorldEditor::components::buildings_editor_mode>()->mode;
|
||||
return mode;
|
||||
}
|
||||
|
||||
BuildingsEditor::~BuildingsEditor()
|
||||
@@ -717,27 +369,11 @@ void BuildingsEditor::select_building(const Transform &xform, const String &key,
|
||||
const String &mid)
|
||||
{
|
||||
int i;
|
||||
assert(scene());
|
||||
selected_building_xform = xform;
|
||||
selected_building = key;
|
||||
print_line("selected key: " + key);
|
||||
OptionButton *building_type = Object::cast_to<OptionButton>(
|
||||
editor->get_node(NodePath("%building_type")));
|
||||
assert(building_type);
|
||||
bool ok = false;
|
||||
for (i = 0; i < building_type->get_item_count(); i++) {
|
||||
const String &item = building_type->get_item_text(i);
|
||||
if (item == mid) {
|
||||
building_type->select(i);
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
Button *delete_button =
|
||||
get_as_node<Button>("%buildings_delete_building");
|
||||
delete_button->show();
|
||||
emit("buildings_building_selected", varray());
|
||||
}
|
||||
emit("set_selected_building_type", varray(mid));
|
||||
set_cursor_position(xform.origin);
|
||||
}
|
||||
|
||||
@@ -761,6 +397,7 @@ template <class T> T *BuildingsEditor::get_as_node(const String &path)
|
||||
template <class T>
|
||||
const T *BuildingsEditor::get_as_node(const String &path) const
|
||||
{
|
||||
assert(scene());
|
||||
const Node *node = scene()->get_node(NodePath(path));
|
||||
assert(node);
|
||||
const T *ret = Object::cast_to<T>(node);
|
||||
@@ -770,11 +407,15 @@ const T *BuildingsEditor::get_as_node(const String &path) const
|
||||
|
||||
Node *BuildingsEditor::scene()
|
||||
{
|
||||
assert(editor);
|
||||
assert(editor->get_tree());
|
||||
return editor->get_tree()->get_current_scene();
|
||||
}
|
||||
|
||||
const Node *BuildingsEditor::scene() const
|
||||
{
|
||||
assert(editor);
|
||||
assert(editor->get_tree());
|
||||
const Node *ret = editor->get_tree()->get_current_scene();
|
||||
return ret;
|
||||
}
|
||||
|
||||
11
src/modules/stream/npc/SCsub
Normal file
11
src/modules/stream/npc/SCsub
Normal file
@@ -0,0 +1,11 @@
|
||||
Import("env")
|
||||
Import("env_modules")
|
||||
|
||||
env.stream_building_sources = []
|
||||
|
||||
env.add_source_files(env.stream_building_sources, "*.cpp")
|
||||
|
||||
lib = env.add_library("npc", env.stream_building_sources)
|
||||
env.Prepend(LIBS=[lib])
|
||||
env.Prepend(CPPPATH=[".."])
|
||||
env.Prepend(CPPPATH=["../../../meshoptimizer/src"])
|
||||
147
src/modules/stream/npc/npc.cpp
Normal file
147
src/modules/stream/npc/npc.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
#include <core/os/memory.h>
|
||||
#include <core/vector.h>
|
||||
#include <core/ustring.h>
|
||||
#include <core/math/transform.h>
|
||||
#include <core/object.h>
|
||||
#include <scene/main/scene_tree.h>
|
||||
#include "flecs/flecs.h"
|
||||
#include "base_data.h"
|
||||
#include "npc.h"
|
||||
|
||||
NPC *NPC::singleton = nullptr;
|
||||
|
||||
namespace NPCModule
|
||||
{
|
||||
struct NPCBase {
|
||||
int id;
|
||||
String name;
|
||||
};
|
||||
|
||||
struct NPCLocation {
|
||||
Transform global_location, local_position;
|
||||
};
|
||||
struct NPCTarget {
|
||||
Transform target;
|
||||
};
|
||||
struct NPCTargetKey {
|
||||
String location_key;
|
||||
};
|
||||
struct NPCBackgroundMotion {
|
||||
float speed;
|
||||
};
|
||||
|
||||
struct NPCBody {
|
||||
/* TODO: implement */
|
||||
void *nothing;
|
||||
};
|
||||
|
||||
struct NPCAnimation {
|
||||
/* TODO: implement */
|
||||
void *nothing;
|
||||
};
|
||||
|
||||
struct NPCResidence {
|
||||
String residence_key;
|
||||
};
|
||||
|
||||
struct NPCOccupation {
|
||||
/* building key */
|
||||
String occupation_key;
|
||||
// index in building's job list
|
||||
int job_type;
|
||||
int start_hour;
|
||||
int end_hour;
|
||||
// bit field from mon to sun
|
||||
int week_days;
|
||||
};
|
||||
|
||||
/* Assign leisure on the go depending on
|
||||
character mood and stats */
|
||||
struct NPCLeisure {
|
||||
String leisure_key;
|
||||
};
|
||||
|
||||
struct module {
|
||||
module(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<struct module>();
|
||||
ecs.component<struct NPCBase>();
|
||||
ecs.component<struct NPCLocation>();
|
||||
ecs.component<struct NPCTarget>();
|
||||
ecs.component<struct NPCTargetKey>();
|
||||
ecs.component<struct NPCBody>();
|
||||
ecs.component<struct NPCAnimation>();
|
||||
ecs.component<struct NPCResidence>();
|
||||
ecs.component<struct NPCOccupation>();
|
||||
ecs.component<struct NPCLeisure>();
|
||||
/* moving NPC despawned NPC */
|
||||
ecs.system<NPCBase>("Update").each(
|
||||
[](flecs::entity e, NPCBase &b) {
|
||||
// TODO: implement;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class Updater : public Object {
|
||||
GDCLASS(Updater, Object)
|
||||
NPC *base;
|
||||
|
||||
public:
|
||||
Updater(NPC *base)
|
||||
: Object()
|
||||
, base(base)
|
||||
{
|
||||
SceneTree::get_singleton()->connect("physics_frame", this,
|
||||
"update");
|
||||
}
|
||||
virtual ~Updater()
|
||||
{
|
||||
}
|
||||
void update()
|
||||
{
|
||||
float delta =
|
||||
SceneTree::get_singleton()->get_physics_process_time();
|
||||
base->update(delta);
|
||||
print_line("Update running");
|
||||
}
|
||||
|
||||
protected:
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(D_METHOD("update"), &Updater::update);
|
||||
}
|
||||
};
|
||||
|
||||
static Updater *updater = nullptr;
|
||||
|
||||
NPC::NPC()
|
||||
{
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
ecs.import <NPCModule::module>();
|
||||
flecs::entity npcs_e = ecs.entity("npc");
|
||||
if (!updater)
|
||||
updater = memnew(Updater(this));
|
||||
}
|
||||
|
||||
NPC *NPC::get_singleton()
|
||||
{
|
||||
if (!singleton)
|
||||
singleton = memnew(NPC);
|
||||
return singleton;
|
||||
}
|
||||
|
||||
void NPC::cleanup()
|
||||
{
|
||||
memdelete(singleton);
|
||||
}
|
||||
|
||||
NPC::~NPC()
|
||||
{
|
||||
}
|
||||
|
||||
void NPC::update(float delta)
|
||||
{
|
||||
BaseData::get_singleton()->get().progress(delta);
|
||||
}
|
||||
13
src/modules/stream/npc/npc.h
Normal file
13
src/modules/stream/npc/npc.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef NPC_H_
|
||||
#define NPC_H_
|
||||
class NPC {
|
||||
static NPC *singleton;
|
||||
NPC();
|
||||
|
||||
public:
|
||||
static NPC *get_singleton();
|
||||
static void cleanup();
|
||||
virtual ~NPC();
|
||||
void update(float delta);
|
||||
};
|
||||
#endif
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "nav_panel.h"
|
||||
#include "line_metadata_editor.h"
|
||||
#include "buildings/building_layout_editor.h"
|
||||
#include "ui/main_tabs.h"
|
||||
|
||||
void register_stream_types()
|
||||
{
|
||||
@@ -14,6 +15,7 @@ void register_stream_types()
|
||||
ClassDB::register_class<NavPanel>();
|
||||
ClassDB::register_class<LineMetadataEditor>();
|
||||
ClassDB::register_class<BuildingLayoutEditor>();
|
||||
ClassDB::register_class<MainTabs>();
|
||||
}
|
||||
|
||||
void unregister_stream_types()
|
||||
|
||||
18
src/modules/stream/ui/SCsub
Normal file
18
src/modules/stream/ui/SCsub
Normal file
@@ -0,0 +1,18 @@
|
||||
Import("env")
|
||||
Import("env_modules")
|
||||
|
||||
#env_modules.stream_building_sources = []
|
||||
#
|
||||
#env_modules.add_source_files(env_modules.stream_building_sources, "*.cpp")
|
||||
#
|
||||
#lib = env_modules.add_library("buildings", env_modules.stream_building_sources)
|
||||
#env_modules.Prepend(LIBS=[lib])
|
||||
|
||||
env.stream_building_sources = []
|
||||
|
||||
env.add_source_files(env.stream_building_sources, "*.cpp")
|
||||
|
||||
lib = env.add_library("ui", env.stream_building_sources)
|
||||
env.Prepend(LIBS=[lib])
|
||||
env.Prepend(CPPPATH=[".."])
|
||||
env.Prepend(CPPPATH=["../../../meshoptimizer/src"])
|
||||
910
src/modules/stream/ui/main_tabs.cpp
Normal file
910
src/modules/stream/ui/main_tabs.cpp
Normal file
@@ -0,0 +1,910 @@
|
||||
#include <unordered_map>
|
||||
#include <cstdio>
|
||||
#include <core/engine.h>
|
||||
#include <scene/gui/box_container.h>
|
||||
#include <scene/gui/label.h>
|
||||
#include <scene/gui/separator.h>
|
||||
#include <scene/gui/panel_container.h>
|
||||
#include <scene/gui/button.h>
|
||||
#include <scene/gui/option_button.h>
|
||||
#include <scene/gui/line_edit.h>
|
||||
#include <scene/gui/item_list.h>
|
||||
#include "world_editor.h"
|
||||
#include "buildings_editor.h"
|
||||
#include "base_data.h"
|
||||
#include "editor_event.h"
|
||||
#include "main_tabs.h"
|
||||
|
||||
class HandleBuildingsEditorMode : public Object {
|
||||
GDCLASS(HandleBuildingsEditorMode, Object)
|
||||
OptionButton *ob;
|
||||
BuildingsEditor *editor;
|
||||
void update_editor_mode(int index)
|
||||
{
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity e = ecs.lookup("world_editor");
|
||||
assert(e.is_valid());
|
||||
e.set<WorldEditor::components::buildings_editor_mode>(
|
||||
{ index });
|
||||
}
|
||||
|
||||
public:
|
||||
HandleBuildingsEditorMode(OptionButton *ob, BuildingsEditor *editor)
|
||||
: Object()
|
||||
, ob(ob)
|
||||
, editor(editor)
|
||||
{
|
||||
ob->connect("item_selected", this, "update_editor_mode");
|
||||
}
|
||||
~HandleBuildingsEditorMode()
|
||||
{
|
||||
ob->disconnect("item_selected", this, "update_editor_mode");
|
||||
}
|
||||
|
||||
protected:
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(
|
||||
D_METHOD("update_editor_mode", "index"),
|
||||
&HandleBuildingsEditorMode::update_editor_mode);
|
||||
}
|
||||
};
|
||||
class HandleBuildingType : public Object {
|
||||
GDCLASS(HandleBuildingType, Object)
|
||||
OptionButton *ob;
|
||||
BuildingsEditor *editor;
|
||||
|
||||
void change_building_type(int index)
|
||||
{
|
||||
assert(editor->scene());
|
||||
const String &item = ob->get_item_text(index);
|
||||
int bmode = editor->get_buildings_editor_mode();
|
||||
if (bmode == 0 || bmode == 1 ||
|
||||
bmode == 2) /* select, move, rotate */
|
||||
editor->change_building_type(item);
|
||||
/* do not change building types in create mode (3) */
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity e = ecs.lookup("world_editor");
|
||||
assert(e.is_valid());
|
||||
e.get_mut<WorldEditor::components::buildings_editor_mode>()
|
||||
->current_type = item;
|
||||
}
|
||||
|
||||
public:
|
||||
HandleBuildingType(OptionButton *ob, BuildingsEditor *editor)
|
||||
: Object()
|
||||
, ob(ob)
|
||||
, editor(editor)
|
||||
{
|
||||
ConfigFile config;
|
||||
Error result = config.load("res://config/stream.conf");
|
||||
ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
|
||||
Dictionary buildings_data =
|
||||
config.get_value("buildings", "building_data");
|
||||
ob->clear();
|
||||
List<Variant> keys;
|
||||
buildings_data.get_key_list(&keys);
|
||||
List<Variant>::Element *e = keys.front();
|
||||
while (e) {
|
||||
const String &key = e->get();
|
||||
print_line("EE::" + key);
|
||||
ob->add_item(key);
|
||||
e = e->next();
|
||||
}
|
||||
ob->connect("item_selected", this, "change_building_type");
|
||||
}
|
||||
virtual ~HandleBuildingType()
|
||||
{
|
||||
if (ob->is_connected("item_selected", this,
|
||||
"change_building_type"))
|
||||
ob->disconnect("item_selected", this,
|
||||
"change_building_type");
|
||||
}
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(D_METHOD("change_building_type", "index"),
|
||||
&HandleBuildingType::change_building_type);
|
||||
}
|
||||
};
|
||||
|
||||
class HandleFullPositionSetting : public Object {
|
||||
GDCLASS(HandleFullPositionSetting, Object)
|
||||
BuildingsEditor *editor;
|
||||
MainTabs *gui;
|
||||
int old_mode;
|
||||
|
||||
public:
|
||||
HandleFullPositionSetting(BuildingsEditor *editor, MainTabs *gui)
|
||||
: Object()
|
||||
, editor(editor)
|
||||
, gui(gui)
|
||||
, old_mode(-1)
|
||||
{
|
||||
SceneTree::get_singleton()->connect("idle_frame", this,
|
||||
"handle_update");
|
||||
Button *set_cursor_position = gui->get_as_node<Button>(
|
||||
"%buildings_set_cursor_position");
|
||||
set_cursor_position->connect("pressed", this,
|
||||
"handle_set_cursor");
|
||||
Button *set_building_position = gui->get_as_node<Button>(
|
||||
"%buildings_set_building_position");
|
||||
set_building_position->connect("pressed", this,
|
||||
"handle_set_building");
|
||||
EditorEvent::get_singleton()->event.add_listener(
|
||||
this, &HandleFullPositionSetting::handle_event);
|
||||
#if 0
|
||||
String building = editor->get_selected_building();
|
||||
if (building.length() > 0) {
|
||||
Vector3 building_pos =
|
||||
editor->get_selected_building_xform().origin;
|
||||
}
|
||||
#endif
|
||||
assert(set_cursor_position);
|
||||
assert(set_building_position);
|
||||
}
|
||||
virtual ~HandleFullPositionSetting()
|
||||
{
|
||||
EditorEvent::get_singleton()->event.remove_listener(
|
||||
this, &HandleFullPositionSetting::handle_event);
|
||||
Button *set_building_position = gui->get_as_node<Button>(
|
||||
"%buildings_set_building_position");
|
||||
set_building_position->disconnect("pressed", this,
|
||||
"handle_set_building");
|
||||
Button *set_cursor_position = gui->get_as_node<Button>(
|
||||
"%buildings_set_cursor_position");
|
||||
set_cursor_position->disconnect("pressed", this,
|
||||
"handle_set_cursor");
|
||||
SceneTree::get_singleton()->disconnect("idle_frame", this,
|
||||
"handle_update");
|
||||
}
|
||||
|
||||
protected:
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(D_METHOD("handle_update"),
|
||||
&HandleFullPositionSetting::handle_update);
|
||||
ClassDB::bind_method(
|
||||
D_METHOD("handle_set_cursor"),
|
||||
&HandleFullPositionSetting::handle_set_cursor);
|
||||
ClassDB::bind_method(
|
||||
D_METHOD("handle_set_building"),
|
||||
&HandleFullPositionSetting::handle_set_building);
|
||||
}
|
||||
|
||||
private:
|
||||
void handle_event(const String &event, const Vector<Variant> &args)
|
||||
{
|
||||
if (event == "buildings_building_cursor_moved") {
|
||||
Vector3 position = args[0];
|
||||
LineEdit *cursor_x = gui->get_as_node<LineEdit>(
|
||||
"%building_cursor_x");
|
||||
LineEdit *cursor_y = gui->get_as_node<LineEdit>(
|
||||
"%building_cursor_y");
|
||||
LineEdit *cursor_z = gui->get_as_node<LineEdit>(
|
||||
"%building_cursor_z");
|
||||
cursor_x->set_text(String::num(position.x));
|
||||
cursor_y->set_text(String::num(position.y));
|
||||
cursor_z->set_text(String::num(position.z));
|
||||
} else if (event == "buildings_building_selected" ||
|
||||
event == "buildings_building_moved" ||
|
||||
event == "buildings_building_rotated") {
|
||||
LineEdit *position_x = gui->get_as_node<LineEdit>(
|
||||
"%building_position_x");
|
||||
LineEdit *position_y = gui->get_as_node<LineEdit>(
|
||||
"%building_position_y");
|
||||
LineEdit *position_z = gui->get_as_node<LineEdit>(
|
||||
"%building_position_z");
|
||||
LineEdit *position_rot = gui->get_as_node<LineEdit>(
|
||||
"%building_rotation_y");
|
||||
Transform xform = editor->get_selected_building_xform();
|
||||
position_x->set_text(String::num(xform.origin.x));
|
||||
position_y->set_text(String::num(xform.origin.y));
|
||||
position_z->set_text(String::num(xform.origin.z));
|
||||
Vector3 reference(0, 0, -1);
|
||||
Vector3 rotated =
|
||||
xform.basis.xform(reference).normalized();
|
||||
float angle = reference.signed_angle_to(
|
||||
rotated, Vector3(0, 1, 0));
|
||||
position_rot->set_text(
|
||||
String::num(angle * 180.0f / Math_PI));
|
||||
}
|
||||
}
|
||||
void handle_set_cursor()
|
||||
{
|
||||
LineEdit *cursor_x =
|
||||
gui->get_as_node<LineEdit>("%building_cursor_x");
|
||||
LineEdit *cursor_y =
|
||||
gui->get_as_node<LineEdit>("%building_cursor_y");
|
||||
LineEdit *cursor_z =
|
||||
gui->get_as_node<LineEdit>("%building_cursor_z");
|
||||
Vector3 position;
|
||||
position.x = cursor_x->get_text().to_float();
|
||||
position.y = cursor_y->get_text().to_float();
|
||||
position.z = cursor_z->get_text().to_float();
|
||||
editor->set_cursor_position(position);
|
||||
}
|
||||
void handle_set_building()
|
||||
{
|
||||
LineEdit *position_x =
|
||||
gui->get_as_node<LineEdit>("%building_position_x");
|
||||
LineEdit *position_y =
|
||||
gui->get_as_node<LineEdit>("%building_position_y");
|
||||
LineEdit *position_z =
|
||||
gui->get_as_node<LineEdit>("%building_position_z");
|
||||
LineEdit *position_rot =
|
||||
gui->get_as_node<LineEdit>("%building_rotation_y");
|
||||
Transform xform = editor->get_selected_building_xform();
|
||||
xform.basis = Basis().rotated(
|
||||
Vector3(0, 1, 0),
|
||||
position_rot->get_text().to_float() * Math_PI / 180.0f);
|
||||
xform.origin.x = position_x->get_text().to_float();
|
||||
xform.origin.y = position_y->get_text().to_float();
|
||||
xform.origin.z = position_z->get_text().to_float();
|
||||
String key = editor->get_selected_building();
|
||||
int mode = editor->get_buildings_editor_mode();
|
||||
if (mode == 1 || mode == 2)
|
||||
editor->set_cursor_position(xform.origin);
|
||||
editor->emit("run_update_building_transform",
|
||||
varray(key, xform));
|
||||
}
|
||||
void handle_update()
|
||||
{
|
||||
if (Engine::get_singleton()->is_editor_hint())
|
||||
return;
|
||||
// TODO: handle selection
|
||||
int i;
|
||||
int mode = editor->get_buildings_editor_mode();
|
||||
LineEdit *cursor_x =
|
||||
gui->get_as_node<LineEdit>("%building_cursor_x");
|
||||
LineEdit *cursor_y =
|
||||
gui->get_as_node<LineEdit>("%building_cursor_y");
|
||||
LineEdit *cursor_z =
|
||||
gui->get_as_node<LineEdit>("%building_cursor_z");
|
||||
LineEdit *cursor_le[] = { cursor_x, cursor_y, cursor_z };
|
||||
Button *set_cursor_position = gui->get_as_node<Button>(
|
||||
"%buildings_set_cursor_position");
|
||||
LineEdit *position_x =
|
||||
gui->get_as_node<LineEdit>("%building_position_x");
|
||||
LineEdit *position_y =
|
||||
gui->get_as_node<LineEdit>("%building_position_y");
|
||||
LineEdit *position_z =
|
||||
gui->get_as_node<LineEdit>("%building_position_z");
|
||||
LineEdit *position_rot =
|
||||
gui->get_as_node<LineEdit>("%building_rotation_y");
|
||||
LineEdit *position_le[] = { position_x, position_y, position_z,
|
||||
position_rot };
|
||||
Button *set_building_position = gui->get_as_node<Button>(
|
||||
"%buildings_set_building_position");
|
||||
int sz_cursor = (int)(sizeof(cursor_le) / sizeof(cursor_le[0]));
|
||||
int sz_position =
|
||||
(int)(sizeof(position_le) / sizeof(position_le[0]));
|
||||
if (mode != old_mode) {
|
||||
switch (mode) {
|
||||
case 0: // select
|
||||
for (i = 0; i < sz_cursor; i++)
|
||||
cursor_le[i]->set_editable(false);
|
||||
set_cursor_position->set_disabled(true);
|
||||
for (i = 0; i < sz_position; i++)
|
||||
position_le[i]->set_editable(false);
|
||||
set_building_position->set_disabled(true);
|
||||
break;
|
||||
case 1: // move
|
||||
for (i = 0; i < sz_cursor; i++)
|
||||
cursor_le[i]->set_editable(false);
|
||||
set_cursor_position->set_disabled(true);
|
||||
for (i = 0; i < sz_position; i++)
|
||||
position_le[i]->set_editable(true);
|
||||
set_building_position->set_disabled(false);
|
||||
break;
|
||||
case 2: // rotate
|
||||
for (i = 0; i < sz_cursor; i++)
|
||||
cursor_le[i]->set_editable(false);
|
||||
set_cursor_position->set_disabled(true);
|
||||
for (i = 0; i < sz_position; i++)
|
||||
position_le[i]->set_editable(true);
|
||||
set_building_position->set_disabled(false);
|
||||
break;
|
||||
case 3: // create
|
||||
for (i = 0; i < sz_cursor; i++)
|
||||
cursor_le[i]->set_editable(true);
|
||||
set_cursor_position->set_disabled(false);
|
||||
for (i = 0; i < sz_position; i++)
|
||||
position_le[i]->set_editable(true);
|
||||
set_building_position->set_disabled(false);
|
||||
break;
|
||||
}
|
||||
old_mode = mode;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class HandleCmdButton : public Object {
|
||||
GDCLASS(HandleCmdButton, Object)
|
||||
Button *button;
|
||||
WorldEditor *editor;
|
||||
String command;
|
||||
Vector<Variant> args;
|
||||
|
||||
void button_handler()
|
||||
{
|
||||
assert(command.length() > 0);
|
||||
editor->editor_command(command, args);
|
||||
}
|
||||
|
||||
public:
|
||||
HandleCmdButton(Button *button, WorldEditor *editor,
|
||||
const String &command,
|
||||
const Vector<Variant> &args = varray())
|
||||
: Object()
|
||||
, button(button)
|
||||
, editor(editor)
|
||||
, command(command)
|
||||
, args(args)
|
||||
{
|
||||
assert(button);
|
||||
assert(this->command.length() > 0);
|
||||
if (!button->is_connected("pressed", this, "button_handler")) {
|
||||
button->connect("pressed", this, "button_handler");
|
||||
assert(button->is_connected("pressed", this,
|
||||
"button_handler"));
|
||||
}
|
||||
}
|
||||
virtual ~HandleCmdButton()
|
||||
{
|
||||
assert(button);
|
||||
assert(button->is_connected("pressed", this, "button_handler"));
|
||||
if (button->is_connected("pressed", this, "button_handler"))
|
||||
button->disconnect("pressed", this, "button_handler");
|
||||
}
|
||||
|
||||
protected:
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(D_METHOD("button_handler"),
|
||||
&HandleCmdButton::button_handler);
|
||||
}
|
||||
};
|
||||
|
||||
class HandleEventButton : public Object {
|
||||
GDCLASS(HandleEventButton, Object)
|
||||
Button *button;
|
||||
BuildingsEditor *editor;
|
||||
String event_string;
|
||||
Vector<Variant> event_args;
|
||||
|
||||
void button_handler()
|
||||
{
|
||||
assert(event_string.length() > 0);
|
||||
editor->emit("button:" + event_string, event_args);
|
||||
}
|
||||
|
||||
public:
|
||||
HandleEventButton(Button *button, BuildingsEditor *editor,
|
||||
const String &event_string,
|
||||
const Vector<Variant> &event_args = varray())
|
||||
: Object()
|
||||
, button(button)
|
||||
, editor(editor)
|
||||
, event_string(event_string)
|
||||
, event_args(event_args)
|
||||
{
|
||||
assert(button);
|
||||
assert(this->event_string.length() > 0);
|
||||
if (!button->is_connected("pressed", this, "button_handler")) {
|
||||
button->connect("pressed", this, "button_handler");
|
||||
assert(button->is_connected("pressed", this,
|
||||
"button_handler"));
|
||||
}
|
||||
}
|
||||
virtual ~HandleEventButton()
|
||||
{
|
||||
assert(button);
|
||||
assert(button->is_connected("pressed", this, "button_handler"));
|
||||
if (button->is_connected("pressed", this, "button_handler"))
|
||||
button->disconnect("pressed", this, "button_handler");
|
||||
}
|
||||
|
||||
protected:
|
||||
static void _bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(D_METHOD("button_handler"),
|
||||
&HandleEventButton::button_handler);
|
||||
}
|
||||
};
|
||||
|
||||
static Vector<Object *> c_handlers;
|
||||
|
||||
static void ui_field_builder(Node *owner, Node *parent, const String format,
|
||||
const Vector<Variant> args)
|
||||
{
|
||||
int argp = 0, i;
|
||||
List<Node *> stack;
|
||||
int fmt_size = (int)format.length();
|
||||
int args_size = (int)args.size();
|
||||
Control *last_created = nullptr;
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity world_editor_e = ecs.lookup("world_editor");
|
||||
WorldEditor *we =
|
||||
world_editor_e
|
||||
.get<WorldEditor::components::world_editor_node>()
|
||||
->node;
|
||||
BuildingsEditor *be =
|
||||
world_editor_e
|
||||
.get<WorldEditor::components::buildings_editor_node>()
|
||||
->node;
|
||||
for (i = 0; i < format.length(); i++) {
|
||||
const char *fmt = format.ascii().ptr();
|
||||
int c = fmt[i];
|
||||
printf("character: %c : argp: %d\n", (char)c, argp);
|
||||
switch (c) {
|
||||
case '{':
|
||||
stack.push_front(parent);
|
||||
parent = last_created;
|
||||
break;
|
||||
case '}':
|
||||
parent = stack.front()->get();
|
||||
stack.pop_front();
|
||||
break;
|
||||
case '#': {
|
||||
assert(argp < args_size);
|
||||
String name = args[argp++];
|
||||
assert(name.length() > 0);
|
||||
last_created->set_name(name);
|
||||
printf("set name: %s\n", name.ascii().ptr());
|
||||
} break;
|
||||
case '.':
|
||||
assert(argp < args_size);
|
||||
last_created->set_custom_minimum_size(args[argp++]);
|
||||
break;
|
||||
case '!':
|
||||
last_created->set_unique_name_in_owner(true);
|
||||
break;
|
||||
case '+':
|
||||
assert(argp < args_size);
|
||||
last_created->set_h_size_flags(args[argp++]);
|
||||
break;
|
||||
case 'v':
|
||||
case 'V':
|
||||
case 'h':
|
||||
case 'H':
|
||||
if (c == 'v' || c == 'V') {
|
||||
VBoxContainer *vb = memnew(VBoxContainer);
|
||||
parent->add_child(vb);
|
||||
vb->set_owner(owner);
|
||||
last_created = vb;
|
||||
} else {
|
||||
HBoxContainer *hb = memnew(HBoxContainer);
|
||||
parent->add_child(hb);
|
||||
hb->set_owner(owner);
|
||||
last_created = hb;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
assert(i < fmt_size - 1);
|
||||
assert(argp < args_size);
|
||||
{
|
||||
Label *l = memnew(Label);
|
||||
l->set_text(args[argp++]);
|
||||
parent->add_child(l);
|
||||
l->set_owner(owner);
|
||||
last_created = l;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
assert(i < fmt_size);
|
||||
assert(argp < args_size);
|
||||
{
|
||||
LineEdit *l = memnew(LineEdit);
|
||||
assert(argp < args_size);
|
||||
l->set_text(args[argp++]);
|
||||
parent->add_child(l);
|
||||
l->set_owner(owner);
|
||||
last_created = l;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
assert(argp < args_size);
|
||||
{
|
||||
Button *b = memnew(Button);
|
||||
assert(argp < args_size);
|
||||
b->set_text(args[argp++]);
|
||||
parent->add_child(b);
|
||||
b->set_owner(owner);
|
||||
last_created = b;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
assert(argp < args_size);
|
||||
{
|
||||
int j, count;
|
||||
OptionButton *b = memnew(OptionButton);
|
||||
assert(argp < args_size);
|
||||
b->set_text(args[argp++]);
|
||||
parent->add_child(b);
|
||||
b->set_owner(owner);
|
||||
assert(argp < args_size);
|
||||
count = args[argp++];
|
||||
for (j = 0; j < count; j++) {
|
||||
assert(argp < args_size);
|
||||
int id = args[argp++];
|
||||
assert(argp < args_size);
|
||||
String text = args[argp++];
|
||||
b->add_item(text, id);
|
||||
}
|
||||
last_created = b;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
assert(argp < args_size);
|
||||
{
|
||||
int j, count;
|
||||
ItemList *l = memnew(ItemList);
|
||||
assert(argp < args_size);
|
||||
parent->add_child(l);
|
||||
l->set_owner(owner);
|
||||
assert(argp < args_size);
|
||||
count = args[argp++];
|
||||
for (j = 0; j < count; j++) {
|
||||
assert(argp < args_size);
|
||||
String text = args[argp++];
|
||||
l->add_item(text);
|
||||
}
|
||||
last_created = l;
|
||||
}
|
||||
break;
|
||||
case '_': {
|
||||
HSeparator *hs = memnew(HSeparator);
|
||||
parent->add_child(hs);
|
||||
hs->set_owner(owner);
|
||||
last_created = hs;
|
||||
} break;
|
||||
case '|': {
|
||||
VSeparator *vs = memnew(VSeparator);
|
||||
parent->add_child(vs);
|
||||
vs->set_owner(owner);
|
||||
last_created = vs;
|
||||
} break;
|
||||
case 'q': {
|
||||
assert(argp + 1 < args_size);
|
||||
Button *b = Object::cast_to<Button>(last_created);
|
||||
assert(b);
|
||||
HandleCmdButton *cmd = memnew(HandleCmdButton(
|
||||
b, we, args[argp++], args[argp++]));
|
||||
c_handlers.push_back(cmd);
|
||||
} break;
|
||||
case 'Q': {
|
||||
assert(argp + 1 < args_size);
|
||||
Button *b = Object::cast_to<Button>(last_created);
|
||||
assert(b);
|
||||
HandleEventButton *cmd = memnew(HandleEventButton(
|
||||
b, be, args[argp++], args[argp++]));
|
||||
c_handlers.push_back(cmd);
|
||||
} break;
|
||||
case 'T': {
|
||||
assert(argp < args_size);
|
||||
OptionButton *b =
|
||||
Object::cast_to<OptionButton>(last_created);
|
||||
assert(b);
|
||||
HandleBuildingType *cmd =
|
||||
memnew(HandleBuildingType(b, be));
|
||||
c_handlers.push_back(cmd);
|
||||
} break;
|
||||
case 'M': {
|
||||
assert(argp < args_size);
|
||||
OptionButton *b =
|
||||
Object::cast_to<OptionButton>(last_created);
|
||||
assert(b);
|
||||
HandleBuildingsEditorMode *cmd =
|
||||
memnew(HandleBuildingsEditorMode(b, be));
|
||||
c_handlers.push_back(cmd);
|
||||
} break;
|
||||
default:
|
||||
printf("bad character %c\n", (char)c);
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void MainTabs::mode_visibility(int mode, const String &path)
|
||||
{
|
||||
T *obj = get_as_node<T>(path);
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity e = ecs.lookup("world_editor");
|
||||
assert(e.is_valid());
|
||||
int bmode =
|
||||
e.get<WorldEditor::components::buildings_editor_mode>()->mode;
|
||||
if (bmode == mode) {
|
||||
if (!obj->is_visible())
|
||||
obj->show();
|
||||
} else {
|
||||
if (obj->is_visible())
|
||||
obj->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void MainTabs::handle_event(const String &event, const Vector<Variant> &args)
|
||||
{
|
||||
int i;
|
||||
if (event == "buildings_building_selected")
|
||||
get_as_node<Button>("%buildings_delete_building")->show();
|
||||
else if (event == "set_selected_building_type") {
|
||||
String mid = args[0];
|
||||
OptionButton *building_type = Object::cast_to<OptionButton>(
|
||||
get_node(NodePath("%building_type")));
|
||||
assert(building_type);
|
||||
bool ok = false;
|
||||
for (i = 0; i < building_type->get_item_count(); i++) {
|
||||
const String &item = building_type->get_item_text(i);
|
||||
if (item == mid) {
|
||||
building_type->select(i);
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok)
|
||||
EditorEvent::get_singleton()->event.emit(
|
||||
"buildings_building_selected", varray());
|
||||
}
|
||||
}
|
||||
|
||||
void MainTabs::_notification(int which)
|
||||
{
|
||||
struct StringHasher {
|
||||
std::size_t operator()(const String &s) const
|
||||
{
|
||||
return (std::size_t)s.hash64();
|
||||
}
|
||||
};
|
||||
int j;
|
||||
switch (which) {
|
||||
case NOTIFICATION_ENTER_TREE:
|
||||
connect("tab_changed", this, "tab_changed");
|
||||
EditorEvent::get_singleton()->event.add_listener(
|
||||
this, &MainTabs::handle_event);
|
||||
break;
|
||||
case NOTIFICATION_READY: {
|
||||
struct menu_data {
|
||||
String title, command, header;
|
||||
};
|
||||
struct menu_data items[] = {
|
||||
{ "Buildings", "select_buildings", "Buildings mode" },
|
||||
{ "Navigation", "select_navigation",
|
||||
"Navigation mode" },
|
||||
{ "POI", "select_poi", "POI mode" },
|
||||
{ "Lines", "select_road_lines", "Lines mode" },
|
||||
{ "NPC", "select_npc", "NPC mode" },
|
||||
};
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity world_editor_e = ecs.lookup("world_editor");
|
||||
assert(world_editor_e.is_valid());
|
||||
assert(world_editor_e.has<
|
||||
WorldEditor::components::buildings_editor_node>());
|
||||
WorldEditor *we =
|
||||
world_editor_e
|
||||
.get<WorldEditor::components::world_editor_node>()
|
||||
->node;
|
||||
BuildingsEditor *editor =
|
||||
world_editor_e
|
||||
.get<WorldEditor::components::
|
||||
buildings_editor_node>()
|
||||
->node;
|
||||
int i;
|
||||
for (i = 0; i < (int)(sizeof(items) / sizeof(items[0])); i++) {
|
||||
VBoxContainer *tab = memnew(VBoxContainer);
|
||||
tab->set_name(items[i].title);
|
||||
tab->set_meta("command", items[i].command);
|
||||
tab->set_owner(this);
|
||||
add_child(tab);
|
||||
Label *header = memnew(Label);
|
||||
header->set_text(items[i].header);
|
||||
tab->add_child(header);
|
||||
header->set_owner(this);
|
||||
HSeparator *sep = memnew(HSeparator);
|
||||
tab->add_child(sep);
|
||||
sep->set_owner(this);
|
||||
PanelContainer *panel = memnew(PanelContainer);
|
||||
tab->add_child(panel);
|
||||
panel->set_owner(this);
|
||||
switch (i) {
|
||||
case 0: {
|
||||
// VBoxContainer *v = memnew(VBoxContainer);
|
||||
//panel->add_child(v);
|
||||
//v->set_owner(this);
|
||||
//Label *l1 = memnew(Label);
|
||||
//v->add_child(l1);
|
||||
//l1->set_owner(this);
|
||||
//l1->set_text("Cursor position");
|
||||
// create_position_setting(
|
||||
// this, v, "building_cursor",
|
||||
// "buildings_set_cursor_position");
|
||||
{
|
||||
String cursor_prefix =
|
||||
"building_cursor";
|
||||
String building_prefix =
|
||||
"building_position";
|
||||
/* clang-format off */
|
||||
std::vector<Variant> args_data = {
|
||||
/* 0 */
|
||||
"Cursor position",
|
||||
|
||||
/* 1 */
|
||||
"", cursor_prefix + "_x", Control::SIZE_EXPAND_FILL,
|
||||
"", cursor_prefix + "_y", Control::SIZE_EXPAND_FILL,
|
||||
"", cursor_prefix + "_z", Control::SIZE_EXPAND_FILL,
|
||||
"Set", "buildings_set_cursor_position",
|
||||
|
||||
/* 12 */
|
||||
"Selected building position",
|
||||
"", building_prefix + "_x", Control::SIZE_EXPAND_FILL,
|
||||
"", building_prefix + "_y", Control::SIZE_EXPAND_FILL,
|
||||
"", building_prefix + "_z", Control::SIZE_EXPAND_FILL,
|
||||
"rot",
|
||||
"", "building_rotation_y",
|
||||
/* 25 */
|
||||
"Set", "buildings_set_building_position",
|
||||
"Mode",
|
||||
/* 28 */
|
||||
"Select", 4, 0, "Select", 1, "Move", 2, "Rotate", 3, "Create", "buildings_edit_mode",
|
||||
/* 39 */
|
||||
"Building type",
|
||||
/* 40 */
|
||||
"Building Type", 0, "building_type",
|
||||
/* 43 */
|
||||
"Delete Building", "buildings_delete_building", "delete_building", varray(),
|
||||
/* 47 */
|
||||
"Create Building", "buildings_create_building", "create_building", varray(),
|
||||
/* 51 */
|
||||
"Save Buildings", "buildings_save", "buildings_save", varray(),
|
||||
/* 55 */
|
||||
0, Vector2(0, 80), "lines_list_building",
|
||||
/* 58 */
|
||||
"Assign To Line", "buildings_assign_to_line"
|
||||
/* 60 */
|
||||
};
|
||||
/* clang-format on */
|
||||
Vector<Variant> args;
|
||||
args.resize(args_data.size());
|
||||
{
|
||||
Variant *pw = args.ptrw();
|
||||
for (j = 0; j < args.size();
|
||||
j++)
|
||||
pw[j] = args_data.data()
|
||||
[j];
|
||||
}
|
||||
#if 0
|
||||
/* clang-format off */
|
||||
/* 0 */
|
||||
args.push_back("Cursor position");
|
||||
/* 1 */
|
||||
args.push_back(""); args.push_back(cursor_prefix + "_x"); args.push_back(Control::SIZE_EXPAND_FILL);
|
||||
/* 4 */
|
||||
args.push_back(""); args.push_back(cursor_prefix + "_y"); args.push_back(Control::SIZE_EXPAND_FILL);
|
||||
/* 7 */
|
||||
args.push_back(""); args.push_back(cursor_prefix + "_z"); args.push_back(Control::SIZE_EXPAND_FILL);
|
||||
/* 10 */
|
||||
args.push_back("Set"); args.push_back("building_set_cursor_position");
|
||||
/* 12 */
|
||||
args.push_back("Selected building position");
|
||||
/* 13 */
|
||||
args.push_back(""); args.push_back(building_prefix + "_x"); args.push_back(Control::SIZE_EXPAND_FILL);
|
||||
/* 16 */
|
||||
args.push_back(""); args.push_back(building_prefix + "_y"); args.push_back(Control::SIZE_EXPAND_FILL);
|
||||
/* 19 */
|
||||
args.push_back(""); args.push_back(building_prefix + "_z"); args.push_back(Control::SIZE_EXPAND_FILL);
|
||||
/* 22 */
|
||||
args.push_back("rot");
|
||||
/* 23 */
|
||||
args.push_back(""); args.push_back("building_rotation_y");
|
||||
/* 25 */
|
||||
args.push_back("Set"); args.push_back("buildings_set_building_position");
|
||||
args.push_back("Mode");
|
||||
/* 28 */
|
||||
args.push_back("Select");
|
||||
args.push_back(4);
|
||||
args.push_back(0); args.push_back("Select");
|
||||
args.push_back(1); args.push_back("Move");
|
||||
args.push_back(2); args.push_back("Rotate");
|
||||
args.push_back(3); args.push_back("Create");
|
||||
args.push_back("buildings_edit_mode");
|
||||
/* 39 */
|
||||
args.push_back("Building type");
|
||||
/* 40 */
|
||||
args.push_back("Building Type"); args.push_back(0); args.push_back("building_type");
|
||||
/* 43 */
|
||||
args.push_back("Delete Building");
|
||||
args.push_back("buildings_delete_building");
|
||||
args.push_back("delete_building");
|
||||
args.push_back(varray());
|
||||
/* 47 */
|
||||
args.push_back("Create Building");
|
||||
args.push_back("buildings_create_building");
|
||||
args.push_back("create_building");
|
||||
args.push_back(varray());
|
||||
/* 51 */
|
||||
args.push_back("Save Buildings");
|
||||
args.push_back("buildings_save");
|
||||
args.push_back("buildings_save");
|
||||
args.push_back(varray());
|
||||
/* 55 */
|
||||
args.push_back(0); args.push_back(Vector2(0, 80)); args.push_back("lines_list_building");
|
||||
/* 58 */
|
||||
args.push_back("Assign To Line"); args.push_back("buildings_assign_to_line");
|
||||
/* 60 */
|
||||
/* clang-format on */
|
||||
print_line(itos(args_data.size()) +
|
||||
" " + itos(args.size()));
|
||||
assert((int)args_data.size() ==
|
||||
(int)args.size());
|
||||
#endif
|
||||
ui_field_builder(
|
||||
this, panel,
|
||||
"v{lh{e#!+e#!+e#!+b#!}lh{e#!+e#!+e#!+}h{le#!b#!}_lo#!Mlo#!T_b#!Qb#!QB#!qi.#!b#!}",
|
||||
args);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
handlers.push_back(
|
||||
memnew(HandleFullPositionSetting(editor, this)));
|
||||
set_process(true);
|
||||
} break;
|
||||
case NOTIFICATION_PROCESS: {
|
||||
mode_visibility<Button>(0, "%buildings_delete_building");
|
||||
mode_visibility<Spatial>(2, "%building_rot_cursor");
|
||||
mode_visibility<Button>(3, "%buildings_create_building");
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE:
|
||||
set_process(false);
|
||||
EditorEvent::get_singleton()->event.remove_listener(
|
||||
this, &MainTabs::handle_event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MainTabs::_bind_methods()
|
||||
{
|
||||
ClassDB::bind_method(D_METHOD("tab_changed", "tab"),
|
||||
&MainTabs::tab_changed);
|
||||
}
|
||||
|
||||
void MainTabs::tab_changed(int tab)
|
||||
{
|
||||
print_line(get_tab_control(tab)->get_name());
|
||||
assert(get_tab_control(tab)->has_meta("command"));
|
||||
if (Engine::get_singleton()->is_editor_hint())
|
||||
return;
|
||||
String command = get_tab_control(tab)->get_meta("command");
|
||||
EditorEvent::get_singleton()->event.emit(command, varray());
|
||||
}
|
||||
|
||||
void MainTabs::hide_control(const String &path)
|
||||
{
|
||||
get_as_node<Control>(path)->hide();
|
||||
}
|
||||
|
||||
void MainTabs::show_control(const String &path)
|
||||
{
|
||||
get_as_node<Control>(path)->show();
|
||||
}
|
||||
|
||||
template <class T> T *MainTabs::get_as_node(const String &path)
|
||||
{
|
||||
Node *node = get_node(NodePath(path));
|
||||
assert(node);
|
||||
T *ret = Object::cast_to<T>(node);
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class T> const T *MainTabs::get_as_node(const String &path) const
|
||||
{
|
||||
const Node *node = get_node(NodePath(path));
|
||||
assert(node);
|
||||
const T *ret = Object::cast_to<T>(node);
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
22
src/modules/stream/ui/main_tabs.h
Normal file
22
src/modules/stream/ui/main_tabs.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <scene/gui/tab_container.h>
|
||||
class MainTabs : public TabContainer {
|
||||
GDCLASS(MainTabs, TabContainer)
|
||||
|
||||
Vector<Object *> handlers;
|
||||
template <class T>
|
||||
inline void mode_visibility(int mode, const String &path);
|
||||
void handle_event(const String &event, const Vector<Variant> &args);
|
||||
|
||||
public:
|
||||
void _notification(int which);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void tab_changed(int tab);
|
||||
|
||||
public:
|
||||
template <class T> T *get_as_node(const String &path);
|
||||
template <class T> const T *get_as_node(const String &path) const;
|
||||
void hide_control(const String &path);
|
||||
void show_control(const String &path);
|
||||
};
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "road_lines_editor.h"
|
||||
#include "world_editor.h"
|
||||
#include "editor_event.h"
|
||||
#include "base_data.h"
|
||||
#include "buildings_editor.h"
|
||||
|
||||
class HandleCommandButton : public Object {
|
||||
@@ -76,6 +77,14 @@ WorldEditor::WorldEditor()
|
||||
, road_lines_editor(memnew(RoadLinesEditor(this)))
|
||||
, buildings_editor(memnew(BuildingsEditor(this)))
|
||||
{
|
||||
flecs::entity e;
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
ecs.component<WorldEditor::components::world_editor_node>();
|
||||
ecs.component<WorldEditor::components::buildings_editor_node>();
|
||||
ecs.component<WorldEditor::components::road_lines_editor_node>();
|
||||
ecs.component<WorldEditor::components::buildings_editor_mode>();
|
||||
e = ecs.lookup("world_editor");
|
||||
assert(!e.is_valid());
|
||||
if (!InputMap::get_singleton()->has_action("left"))
|
||||
InputMap::get_singleton()->add_action("left");
|
||||
if (!InputMap::get_singleton()->has_action("right"))
|
||||
@@ -98,11 +107,23 @@ WorldEditor::WorldEditor()
|
||||
InputMap::get_singleton()->add_action("mouse1");
|
||||
EditorEvent::get_singleton()->event.add_listener(
|
||||
this, &WorldEditor::event_signal_handler);
|
||||
e = ecs.entity("world_editor");
|
||||
assert(e.is_valid());
|
||||
e.set<WorldEditor::components::world_editor_node>({ this });
|
||||
e.set<WorldEditor::components::buildings_editor_node>(
|
||||
{ buildings_editor });
|
||||
e.set<WorldEditor::components::road_lines_editor_node>(
|
||||
{ road_lines_editor });
|
||||
e.set<WorldEditor::components::buildings_editor_mode>({ 0, "" });
|
||||
print_line("constructed");
|
||||
}
|
||||
|
||||
WorldEditor::~WorldEditor()
|
||||
{
|
||||
flecs::world ecs = BaseData::get_singleton()->get();
|
||||
flecs::entity e = ecs.lookup("world_editor");
|
||||
assert(e.is_valid());
|
||||
e.destruct();
|
||||
EditorEvent::get_singleton()->event.remove_listener(
|
||||
this, &WorldEditor::event_signal_handler);
|
||||
if (road_lines_editor) {
|
||||
@@ -218,6 +239,8 @@ static std::unordered_map<int, String> vmode = { { 2, "%v_buildings" },
|
||||
void WorldEditor::tools_button(const String &button)
|
||||
{
|
||||
print_line("tools_button: " + button);
|
||||
if (Engine::get_singleton()->is_editor_hint())
|
||||
return;
|
||||
if (modes.find(button) == modes.end())
|
||||
goto end;
|
||||
assert(modes[button] >= 0);
|
||||
@@ -330,6 +353,10 @@ int WorldEditor::get_current_mode() const
|
||||
void WorldEditor::event_signal_handler(const String &event,
|
||||
const Vector<Variant> &args)
|
||||
{
|
||||
if (event.begins_with("select_")) {
|
||||
editor_command(event, args);
|
||||
return;
|
||||
}
|
||||
if (event == "mode_change_pre") {
|
||||
int prev_mode = args[0];
|
||||
if (prev_mode == -1) {
|
||||
@@ -404,12 +431,14 @@ void WorldEditor::_notification(int which)
|
||||
Node *base = get_parent();
|
||||
int count = base->get_child_count();
|
||||
int i;
|
||||
#if 0
|
||||
for (i = 0; i < (int)tool_buttons.size(); i++) {
|
||||
String bname =
|
||||
get_node(NodePath(tool_buttons[i]))->get_name();
|
||||
tool_handlers.push_back(memnew(HandleCommandButton(
|
||||
this, tool_buttons[i], bname)));
|
||||
}
|
||||
#endif
|
||||
for (i = 0; i < count; i++) {
|
||||
Node *node = base->get_child(i);
|
||||
StreamWorld *sw = Object::cast_to<StreamWorld>(node);
|
||||
|
||||
@@ -53,6 +53,21 @@ public:
|
||||
int get_current_mode() const;
|
||||
void event_signal_handler(const String &event,
|
||||
const Vector<Variant> &args);
|
||||
struct components {
|
||||
struct world_editor_node {
|
||||
WorldEditor *node;
|
||||
};
|
||||
struct buildings_editor_node {
|
||||
BuildingsEditor *node;
|
||||
};
|
||||
struct road_lines_editor_node {
|
||||
RoadLinesEditor *node;
|
||||
};
|
||||
struct buildings_editor_mode {
|
||||
int mode;
|
||||
String current_type;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user