diff --git a/modules/entity_spell_system/editor/ess_editor_plugin.cpp b/modules/entity_spell_system/editor/ess_editor_plugin.cpp index a9096e96b..5db55ff46 100644 --- a/modules/entity_spell_system/editor/ess_editor_plugin.cpp +++ b/modules/entity_spell_system/editor/ess_editor_plugin.cpp @@ -34,6 +34,8 @@ #include "editor/editor_settings.h" #include "../world_spawners/ess_entity_world_spawner_3d.h" +#include "../world_spawners/ess_entity_world_spawner_3d_area.h" +#include "scene/3d/camera.h" #include "scene/resources/mesh/mesh.h" #include "scene/resources/mesh/primitive_meshes.h" @@ -60,10 +62,14 @@ void ESSEditorPlugin::_bind_methods() { //////// WorldSpawner3DSpatialGizmoPlugin::WorldSpawner3DSpatialGizmoPlugin() { - const Color gizmo_color = EDITOR_DEF("editors/props/gizmo_colors/outline", Color(0.5, 0.5, 1)); + const Color gizmo_outline_color = EDITOR_DEF("editors/ess/gizmo_colors/world_spawner_outline", Color(0.5, 0.5, 1)); + const Color gizmo_text_color = EDITOR_DEF("editors/ess/gizmo_colors/world_spawner_text", Color(0.5, 0.5, 1)); + const Color gizmo_area_outline_color = EDITOR_DEF("editors/ess/gizmo_colors/world_spawner_area_outline", Color(0.7, 0.3, 0.3)); - create_material("outline_material", gizmo_color); - create_material("text_material", gizmo_color); + create_material("outline_material", gizmo_outline_color); + create_material("text_material", gizmo_text_color); + create_material("area_outline_material", gizmo_area_outline_color); + create_handle_material("handles"); } bool WorldSpawner3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { @@ -129,7 +135,7 @@ void WorldSpawner3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { mesh_arr[RS::ARRAY_VERTEX] = points; - cm->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, mesh_arr); + cm->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, mesh_arr, Array(), 0); Ref tm = cm->generate_triangle_mesh_from_aabb(); @@ -153,4 +159,112 @@ void WorldSpawner3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { // TODO this should be configurable tt.basis.rotate_local(Vector3(0, 1, 0), Math_PI); p_gizmo->add_mesh(text_mesh, text_material, tt); + + ESSEntityWorldSpawner3DArea *aws = Object::cast_to(ws); + + if (!aws) { + return; + } + + const Ref area_outline_material = get_material("area_outline_material"); + Ref handles_material = get_material("handles"); + + Vector lines; + Vector3 extents = aws->get_spawn_area_extents(); + + aabb.position = -extents; + aabb.size = aabb.position * -2; + + for (int i = 0; i < 12; i++) { + Vector3 a, b; + aabb.get_edge(i, a, b); + lines.push_back(a); + lines.push_back(b); + } + + Vector handles; + + for (int i = 0; i < 3; i++) { + Vector3 ax; + ax[i] = extents[i]; + handles.push_back(ax); + } + + p_gizmo->add_lines(lines, area_outline_material); + p_gizmo->add_collision_segments(lines); + p_gizmo->add_handles(handles, handles_material); +} + +String WorldSpawner3DSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary) const { + ESSEntityWorldSpawner3DArea *aws = Object::cast_to(p_gizmo->get_spatial_node()); + + if (aws) { + return "Spawn Area"; + } + + return String(); +} + +Variant WorldSpawner3DSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary) const { + ESSEntityWorldSpawner3DArea *aws = Object::cast_to(p_gizmo->get_spatial_node()); + + if (aws) { + return aws->get_spawn_area_extents(); + } + + return Variant(); +} +void WorldSpawner3DSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary, Camera *p_camera, const Point2 &p_point) { + ESSEntityWorldSpawner3DArea *aws = Object::cast_to(p_gizmo->get_spatial_node()); + + if (!aws) { + return; + } + + Transform gt = aws->get_global_transform(); + Transform gi = gt.affine_inverse(); + + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; + + Vector3 axis; + axis[p_id] = 1.0; + Vector3 ra, rb; + Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); + float d = ra[p_id]; + if (SpatialEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + } + + if (d < 0.001) { + d = 0.001; + } + + Vector3 spawn_area = aws->get_spawn_area_extents(); + + spawn_area[p_id] = d; + + aws->set_spawn_area_extents(spawn_area); + + aws->update_gizmos(); +} +void WorldSpawner3DSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { + ESSEntityWorldSpawner3DArea *aws = Object::cast_to(p_gizmo->get_spatial_node()); + + if (!aws) { + return; + } + + if (p_cancel) { + aws->set_spawn_area_extents(p_restore); + return; + } + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Change ESSEntityWorldSpawner3DArea Spawn Area")); + ur->add_do_method(aws, "set_spawn_area_extents", aws->get_spawn_area_extents()); + ur->add_undo_method(aws, "set_spawn_area_extents", p_restore); + ur->commit_action(); } diff --git a/modules/entity_spell_system/editor/ess_editor_plugin.h b/modules/entity_spell_system/editor/ess_editor_plugin.h index ba9bb8fec..310f5376a 100644 --- a/modules/entity_spell_system/editor/ess_editor_plugin.h +++ b/modules/entity_spell_system/editor/ess_editor_plugin.h @@ -71,6 +71,11 @@ public: bool can_be_hidden() const; void redraw(EditorSpatialGizmo *p_gizmo); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false); + WorldSpawner3DSpatialGizmoPlugin(); }; diff --git a/modules/entity_spell_system/world_spawners/ess_entity_world_spawner_3d_area.cpp b/modules/entity_spell_system/world_spawners/ess_entity_world_spawner_3d_area.cpp index 929df6629..8116d8bf0 100644 --- a/modules/entity_spell_system/world_spawners/ess_entity_world_spawner_3d_area.cpp +++ b/modules/entity_spell_system/world_spawners/ess_entity_world_spawner_3d_area.cpp @@ -43,6 +43,13 @@ #include "../singletons/ess.h" +Vector3 ESSEntityWorldSpawner3DArea::get_spawn_area_extents() const { + return _spawn_area_extents; +} +void ESSEntityWorldSpawner3DArea::set_spawn_area_extents(const Vector3 &p_extents) { + _spawn_area_extents = p_extents; +} + String ESSEntityWorldSpawner3DArea::get_entity_name() const { return _entity_name; } @@ -124,6 +131,7 @@ ESSEntityWorldSpawner3DArea::ESSEntityWorldSpawner3DArea() { _respawn_time_min = 0; _respawn_time_max = 0; _respawn_timer = 0; + _spawn_area_extents = Vector3(2, 2, 2); } ESSEntityWorldSpawner3DArea::~ESSEntityWorldSpawner3DArea() { @@ -173,6 +181,10 @@ void ESSEntityWorldSpawner3DArea::_notification(int p_what) { } void ESSEntityWorldSpawner3DArea::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_spawn_area_extents"), &ESSEntityWorldSpawner3DArea::get_spawn_area_extents); + ClassDB::bind_method(D_METHOD("set_spawn_area_extents", "value"), &ESSEntityWorldSpawner3DArea::set_spawn_area_extents); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "spawn_area_extents"), "set_spawn_area_extents", "get_spawn_area_extents"); + ClassDB::bind_method(D_METHOD("get_entity_name"), &ESSEntityWorldSpawner3DArea::get_entity_name); ClassDB::bind_method(D_METHOD("set_entity_name", "value"), &ESSEntityWorldSpawner3DArea::set_entity_name); ADD_PROPERTY(PropertyInfo(Variant::STRING, "entity_name"), "set_entity_name", "get_entity_name"); diff --git a/modules/entity_spell_system/world_spawners/ess_entity_world_spawner_3d_area.h b/modules/entity_spell_system/world_spawners/ess_entity_world_spawner_3d_area.h index dda61dd02..33b950ab9 100644 --- a/modules/entity_spell_system/world_spawners/ess_entity_world_spawner_3d_area.h +++ b/modules/entity_spell_system/world_spawners/ess_entity_world_spawner_3d_area.h @@ -40,6 +40,9 @@ class ESSEntityWorldSpawner3DArea : public ESSEntityWorldSpawner3D { GDCLASS(ESSEntityWorldSpawner3DArea, ESSEntityWorldSpawner3D); public: + Vector3 get_spawn_area_extents() const; + void set_spawn_area_extents(const Vector3 &p_extents); + String get_entity_name() const; void set_entity_name(const String &p_name); @@ -66,6 +69,8 @@ protected: void _on_entity_tree_exited(); + Vector3 _spawn_area_extents; + String _entity_name; Ref _entity_data; int _level;