Fixed reactivation problems

This commit is contained in:
2024-08-28 16:41:02 +03:00
parent 7486334c04
commit bbb13546b1
9 changed files with 310 additions and 15 deletions

View File

@@ -0,0 +1,215 @@
#undef NDEBUG
#include <cassert>
#include <scene/main/viewport.h>
#include <scene/gui/item_list.h>
#include <scene/3d/immediate_geometry.h>
#include <core/io/config_file.h>
#include <core/os/file_access.h>
#include <core/io/json.h>
#include "world_editor.h"
#include "from_string.h"
#include "road_lines_editor.h"
struct road_line {
std::vector<Transform> points;
std::vector<int> indices;
int lanes;
int pattern;
int flags;
};
static HashMap<String, struct road_line> lines;
static ImmediateGeometry *line_im = nullptr;
static Ref<Material> debug_material;
#define __evhandler(vname, mtype) \
template <class T> class GDEventHandler_##vname : public Object { \
GDCLASS(GDEventHandler_##vname, Object) \
T *obj; \
\
public: \
GDEventHandler_##vname(T *obj) \
: Object() \
, obj(obj) \
{ \
} \
virtual ~GDEventHandler_##vname() \
{ \
} \
bool connect(Object *obj, const String &signal) \
{ \
return obj->connect(signal, this, "handler"); \
} \
void disconnect(Object *obj, const String &signal) \
{ \
obj->disconnect(signal, this, "handler"); \
} \
\
protected: \
void handler(const String &event, const Array &args) \
{ \
obj->vname(event, args); \
} \
static void _bind_methods() \
{ \
ClassDB::bind_method( \
D_METHOD("handler", "args"), \
&GDEventHandler_##vname::handler); \
} \
}
#define __evhandler_type(vname, mtype) GDEventHandler_##vname<mtype>
__evhandler(editor_event, RoadLinesEditor);
static __evhandler_type(editor_event, RoadLinesEditor) * gd_editor_event;
RoadLinesEditor::RoadLinesEditor(WorldEditor *editor)
: active(false)
, editor(editor)
{
}
RoadLinesEditor::~RoadLinesEditor()
{
if (active && editor->is_inside_tree())
deactivate();
}
void RoadLinesEditor::update(float delta)
{
if (!active)
activate();
print_line("road_lines_editor");
}
void RoadLinesEditor::exit()
{
if (active)
deactivate();
}
void RoadLinesEditor::editor_command(const String &command, const Array &args)
{
print_line("command: " + command);
}
void RoadLinesEditor::editor_event(const String &event, const Array &args)
{
print_line("event: " + event);
}
void RoadLinesEditor::update_ui()
{
Node *lines_list_node =
editor->get_tree()->get_current_scene()->get_node(
NodePath("%lines_list"));
ItemList *lines_list = Object::cast_to<ItemList>(lines_list_node);
assert(lines_list);
List<String> line_keys;
lines.get_key_list(&line_keys);
List<String>::Element *e = line_keys.front();
lines_list->clear();
while (e) {
String key = e->get();
lines_list->add_item(key);
e = e->next();
}
}
void RoadLinesEditor::activate()
{
assert(!active);
load_data();
print_line("activate::update UI");
update_ui();
if (!line_im) {
line_im = memnew(ImmediateGeometry);
editor->get_viewport()->add_child(line_im);
}
Ref<SpatialMaterial> tmpmat;
tmpmat.instance();
tmpmat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
tmpmat->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, true);
tmpmat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
debug_material = tmpmat;
line_im->begin(Mesh::PRIMITIVE_LINES);
line_im->set_color(Color(1.0f, 0.0f, 0.0f, 1.0f));
line_im->add_vertex(Vector3(0.0f, -100.0f, 0.0f));
line_im->add_vertex(Vector3(0.0f, 100.0f, 0.0f));
line_im->end();
if (!gd_editor_event)
gd_editor_event = memnew(
__evhandler_type(editor_event, RoadLinesEditor)(this));
gd_editor_event->connect(editor, "editor_event");
active = true;
}
void RoadLinesEditor::deactivate()
{
Node *lines_list_node =
editor->get_tree()->get_current_scene()->get_node(
NodePath("%lines_list"));
ItemList *lines_list = Object::cast_to<ItemList>(lines_list_node);
lines_list->clear();
lines.clear();
if (line_im) {
line_im->queue_delete();
line_im = nullptr;
}
gd_editor_event->disconnect(editor, "editor_event");
if (debug_material.is_valid())
debug_material.unref();
if (gd_editor_event) {
memdelete(gd_editor_event);
gd_editor_event = nullptr;
}
active = false;
}
void RoadLinesEditor::load_data()
{
int i;
ConfigFile config;
Error result = config.load("res://config/stream.conf");
ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
String road_lines_path = config.get_value("road", "road_lines_path");
String road_lines_json =
FileAccess::get_file_as_string(road_lines_path);
Variant json_v;
String es;
int eline;
Error status = JSON::parse(road_lines_json, json_v, es, eline);
ERR_FAIL_COND_MSG(status != OK, "Can't parse json: " + es +
" at line: " + itos(eline));
Dictionary json = json_v;
List<Variant> keys;
json.get_key_list(&keys);
List<Variant>::Element *e = keys.front();
while (e) {
String key = e->get();
struct road_line rline;
Dictionary entry = json.get(key, Dictionary());
Array points = entry.get("points", Array());
Array indices;
if (entry.has("indices"))
indices = entry.get("indices", Array());
int lanes = entry.get("lanes", -1);
int pattern = entry.get("pattern", -1);
rline.pattern = pattern;
rline.points.resize(points.size());
rline.indices.resize(indices.size());
for (i = 0; i < (int)points.size(); i++) {
String point_s = points[i];
rline.points[i] = from_string<Transform>(point_s);
}
for (i = 0; i < (int)indices.size(); i++) {
int index = indices[i];
rline.indices[i] = index;
}
// TODO: wtf is flags?
rline.lanes = lanes;
lines[key] = rline;
e = e->next();
}
}

View File

@@ -0,0 +1,24 @@
#ifndef ROAD_LINES_EDITOR_H
#define ROAD_LINES_EDITOR_H
#include "world_editor.h"
class ItemList;
class RoadLinesEditor {
bool active;
WorldEditor *editor;
public:
RoadLinesEditor(WorldEditor *editor);
virtual ~RoadLinesEditor();
void update(float delta);
void exit();
void editor_command(const String &command, const Array &args);
void editor_event(const String &event, const Array &args);
void update_ui();
protected:
void activate();
void deactivate();
void load_data();
};
#endif

View File

@@ -443,11 +443,11 @@ void StreamWorld::run_command(const String &command, const Array &args)
}
VariantWriter::write_to_string(buildings[id].xform, key);
buildings[id].key = key;
} else if (command == "buildings_checkpoint") {
/* TODO */
} else if (command == "buildings_undo") {
/* TODO */
} else if (command == "buildings_save") {
} else if (command == "checkpoint")
checkpoint();
else if (command == "undo")
undo();
else if (command == "buildings_save") {
String buildings_path =
config.get_value("buildings", "buildings_path");
save_buildings_json(buildings_path);
@@ -553,6 +553,7 @@ StreamWorld::StreamWorld()
, viewer(nullptr)
, terrain(nullptr)
, current_scene(nullptr)
, undo_log_size(64)
, world_extent(0)
, tile_size(0)
, view_distance(0)
@@ -597,6 +598,26 @@ StreamWorld::StreamWorld()
view_distance = config.get_value("world", "view_distance");
initialized = true;
}
void StreamWorld::checkpoint()
{
struct checkpoint_data cp;
cp.building_data = building_data;
cp.buildings = buildings;
undo_log.push_back(cp);
while ((int)undo_log.size() > undo_log_size)
undo_log.erase(undo_log.begin());
}
void StreamWorld::undo()
{
struct checkpoint_data cp = *undo_log.end();
int id;
for (id = 0; id < (int)buildings.size(); id++)
unload_building(id);
building_data = cp.building_data;
buildings = cp.buildings;
update_view();
update_items();
}
void StreamWorld::cleanup()
{
RoadProcessing::cleanup();

View File

@@ -15,6 +15,7 @@ private:
VoxelLodTerrain *terrain;
Node *current_scene;
ConfigFile config;
/* Per-building information */
struct building {
String id;
int pattern_id;
@@ -29,6 +30,7 @@ private:
const String &key);
Dictionary to_dict() const;
};
/* Scene objects data */
struct scene_data {
Ref<PackedScene> packed_scene;
String path;
@@ -46,11 +48,20 @@ private:
};
using tile_map_t = std::unordered_map<const tile_key_t,
std::vector<int>, tile_hash>;
/* Data for each building type */
HashMap<String, String> building_data;
/* Data for each building in a world */
std::vector<struct building> buildings;
Vector3 eye;
tile_map_t tiles;
tile_map_t loaded_tiles;
struct checkpoint_data {
HashMap<String, String> building_data;
std::vector<struct building> buildings;
};
std::vector<struct checkpoint_data> undo_log;
int undo_log_size;
int world_extent;
int tile_size;
int view_distance;
@@ -69,6 +80,8 @@ private:
void unload_building(int id);
void request_item(int type, int item);
void update_items();
void checkpoint();
void undo();
static void _bind_methods();

View File

@@ -8,6 +8,7 @@
#include <scene/main/viewport.h>
#include <scene/3d/camera.h>
#include <scene/scene_string_names.h>
#include "road_lines_editor.h"
#include "world_editor.h"
WorldEditor::WorldEditor()
@@ -20,6 +21,7 @@ WorldEditor::WorldEditor()
, old_mouse_pos(Vector2(-1, -1))
, dragging(false)
, drag_delay(0.2f)
, road_lines_editor(memnew(RoadLinesEditor(this)))
{
if (!InputMap::get_singleton()->has_action("left"))
InputMap::get_singleton()->add_action("left");
@@ -45,6 +47,7 @@ WorldEditor::WorldEditor()
WorldEditor::~WorldEditor()
{
memdelete(road_lines_editor);
}
void WorldEditor::set_camera_mode(int mode)
@@ -158,6 +161,11 @@ void WorldEditor::tools_button(const String &button)
change[0] = current_mode;
change[1] = modes[button];
emit_signal("editor_event", "mode_change_pre", change);
switch (current_mode) {
case MODE_ROAD_LINES:
road_lines_editor->exit();
break;
}
switch (modes[button]) {
case MODE_BUILDINGS:
mode_buildings();
@@ -195,11 +203,11 @@ void WorldEditor::editor_command(const String &command, const Array &args)
if (stream_world) {
stream_world->run_command(command, args);
}
} else if (command == "buildings_checkpoint") {
} else if (command == "checkpoint") {
if (stream_world) {
stream_world->run_command(command, args);
}
} else if (command == "buildings_undo") {
} else if (command == "undo") {
if (stream_world) {
stream_world->run_command(command, args);
}
@@ -215,6 +223,8 @@ void WorldEditor::editor_command(const String &command, const Array &args)
if (stream_world) {
stream_world->run_command(command, args);
}
} else if (road_lines_editor) {
road_lines_editor->editor_command(command, args);
}
}
@@ -333,6 +343,12 @@ void WorldEditor::_notification(int which)
}
if (!dragging && drag_delay >= 0.0f)
drag_delay -= delta;
switch (current_mode) {
case MODE_ROAD_LINES:
print_line("current_mode: " + itos(current_mode));
road_lines_editor->update(delta);
break;
}
} break;
}
}

View File

@@ -2,6 +2,7 @@
#define WORLD_EDITOR_H
#include <scene/3d/spatial.h>
#include "stream.h"
class RoadLinesEditor;
class WorldEditor : public Spatial {
GDCLASS(WorldEditor, Spatial)
protected:
@@ -16,7 +17,6 @@ protected:
void mode_road_lines();
void mode_npc();
void tools_button(const String &button);
void editor_command(const String &command, const Array &args);
int get_current_mode() const;
StreamWorld *get_stream_world();
void world_command_result(const String &what, const Array &data);
@@ -32,9 +32,11 @@ private:
Vector2 old_mouse_pos;
bool dragging;
float drag_delay;
RoadLinesEditor *road_lines_editor;
public:
WorldEditor();
~WorldEditor();
virtual ~WorldEditor();
void editor_command(const String &command, const Array &args);
};
#endif