1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-29 16:16:38 +00:00

Portals - Improve UI and add shortcuts

This PR makes the 'convert rooms' button permanently on the toolbar and accessible whichever node is selected, so you can convert rooms without having to select the RoomManager first.

It also adds a togglable item 'view portal culling' to the 'View' menu which is a simple way of setting the RoomManager 'active' setting without the RoomManager being the selected node.

Both of these have keyboard shortcuts, which should make it much faster to reconvert rooms and edit.

In addition there the string in the 'Perspective' Listbox is modified to show [portals active] when portal culling is operational, for visual feedback. This is updated when you change modes, and when the rooms are invalidated.
This commit is contained in:
lawnjelly
2021-08-01 08:56:26 +01:00
parent 4542e3382b
commit 776623d56b
12 changed files with 162 additions and 33 deletions

View File

@@ -32,12 +32,6 @@
#include "editor/spatial_editor_gizmos.h"
void RoomManagerEditorPlugin::_rooms_convert() {
if (_room_manager) {
_room_manager->rooms_convert();
}
}
void RoomManagerEditorPlugin::_flip_portals() {
if (_room_manager) {
_room_manager->rooms_flip_portals();
@@ -59,16 +53,15 @@ bool RoomManagerEditorPlugin::handles(Object *p_object) const {
void RoomManagerEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
button_rooms_convert->show();
button_flip_portals->show();
} else {
button_rooms_convert->hide();
button_flip_portals->hide();
}
SpatialEditor::get_singleton()->show_advanced_portal_tools(p_visible);
}
void RoomManagerEditorPlugin::_bind_methods() {
ClassDB::bind_method("_rooms_convert", &RoomManagerEditorPlugin::_rooms_convert);
ClassDB::bind_method("_flip_portals", &RoomManagerEditorPlugin::_flip_portals);
}
@@ -82,13 +75,6 @@ RoomManagerEditorPlugin::RoomManagerEditorPlugin(EditorNode *p_node) {
button_flip_portals->connect("pressed", this, "_flip_portals");
add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, button_flip_portals);
button_rooms_convert = memnew(ToolButton);
button_rooms_convert->set_icon(editor->get_gui_base()->get_icon("RoomGroup", "EditorIcons"));
button_rooms_convert->set_text(TTR("Convert Rooms"));
button_rooms_convert->hide();
button_rooms_convert->connect("pressed", this, "_rooms_convert");
add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, button_rooms_convert);
_room_manager = nullptr;
Ref<RoomGizmoPlugin> room_gizmo_plugin = Ref<RoomGizmoPlugin>(memnew(RoomGizmoPlugin));

View File

@@ -43,11 +43,9 @@ class RoomManagerEditorPlugin : public EditorPlugin {
RoomManager *_room_manager;
ToolButton *button_rooms_convert;
ToolButton *button_flip_portals;
EditorNode *editor;
void _rooms_convert();
void _flip_portals();
protected:

View File

@@ -47,6 +47,7 @@
#include "scene/3d/collision_shape.h"
#include "scene/3d/mesh_instance.h"
#include "scene/3d/physics_body.h"
#include "scene/3d/room_manager.h"
#include "scene/3d/visual_instance.h"
#include "scene/gui/viewport_container.h"
#include "scene/resources/packed_scene.h"
@@ -733,6 +734,10 @@ void SpatialEditorViewport::_update_name() {
view_mode += " [auto]";
}
if (RoomManager::static_rooms_get_active_and_loaded()) {
view_mode += " [portals active]";
}
if (name != "") {
view_menu->set_text(name + " " + view_mode);
} else {
@@ -4303,6 +4308,42 @@ void SpatialEditor::select_gizmo_highlight_axis(int p_axis) {
}
}
void SpatialEditor::show_advanced_portal_tools(bool p_show) {
// toolbar button
Button *const button = tool_button[TOOL_CONVERT_ROOMS];
if (p_show) {
button->set_text(TTR("Convert Rooms"));
} else {
button->set_text("");
}
}
void SpatialEditor::update_portal_tools() {
// the view portal culling toggle
int view_portal_item_index = view_menu->get_popup()->get_item_index(MENU_VIEW_PORTAL_CULLING);
if (RoomManager::active_room_manager) {
view_menu->get_popup()->set_item_disabled(view_portal_item_index, false);
bool active = RoomManager::static_rooms_get_active();
view_menu->get_popup()->set_item_checked(view_portal_item_index, active);
} else {
view_menu->get_popup()->set_item_disabled(view_portal_item_index, true);
}
// toolbar button
Button *const button = tool_button[TOOL_CONVERT_ROOMS];
if (RoomManager::active_room_manager) {
button->show();
} else {
button->hide();
}
for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) {
viewports[i]->_update_name();
}
}
void SpatialEditor::update_transform_gizmo() {
List<Node *> &selection = editor_selection->get_selected_node_list();
AABB center;
@@ -4791,6 +4832,10 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
update_transform_gizmo();
} break;
case MENU_TOOL_CONVERT_ROOMS: {
RoomManager::static_rooms_convert();
update_portal_tools();
} break;
case MENU_TRANSFORM_CONFIGURE_SNAP: {
snap_dialog->popup_centered(Size2(200, 180));
} break;
@@ -4897,6 +4942,11 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(p_option), grid_enabled);
} break;
case MENU_VIEW_PORTAL_CULLING: {
bool is_checked = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(p_option));
RoomManager::static_rooms_set_active(!is_checked);
update_portal_tools();
} break;
case MENU_VIEW_CAMERA_SETTINGS: {
settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50));
} break;
@@ -5916,6 +5966,7 @@ void SpatialEditor::_notification(int p_what) {
tool_button[SpatialEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_icon("Unlock", "EditorIcons"));
tool_button[SpatialEditor::TOOL_GROUP_SELECTED]->set_icon(get_icon("Group", "EditorIcons"));
tool_button[SpatialEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_icon("Ungroup", "EditorIcons"));
tool_button[SpatialEditor::TOOL_CONVERT_ROOMS]->set_icon(get_icon("RoomGroup", "EditorIcons"));
tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_icon("Object", "EditorIcons"));
tool_option_button[SpatialEditor::TOOL_OPT_USE_SNAP]->set_icon(get_icon("Snap", "EditorIcons"));
@@ -6293,6 +6344,15 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect("toggled", this, "_menu_item_toggled", button_binds);
_update_camera_override_button(false);
tool_button[TOOL_CONVERT_ROOMS] = memnew(ToolButton);
hbc_menu->add_child(tool_button[TOOL_CONVERT_ROOMS]);
tool_button[TOOL_CONVERT_ROOMS]->set_toggle_mode(false);
tool_button[TOOL_CONVERT_ROOMS]->set_flat(true);
button_binds.write[0] = MENU_TOOL_CONVERT_ROOMS;
tool_button[TOOL_CONVERT_ROOMS]->connect("pressed", this, "_menu_item_pressed", button_binds);
tool_button[TOOL_CONVERT_ROOMS]->set_shortcut(ED_SHORTCUT("spatial_editor/convert_rooms", TTR("Convert Rooms"), KEY_MASK_ALT | KEY_C));
tool_button[TOOL_CONVERT_ROOMS]->set_tooltip(TTR("Converts rooms for portal culling."));
hbc_menu->add_child(memnew(VSeparator));
// Drag and drop support;
@@ -6363,6 +6423,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
p->add_separator();
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN);
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid"), KEY_MASK_CMD + KEY_G), MENU_VIEW_GRID);
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_portal_culling", TTR("View Portal Culling"), KEY_MASK_ALT | KEY_P), MENU_VIEW_PORTAL_CULLING);
p->add_separator();
p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings...")), MENU_VIEW_CAMERA_SETTINGS);

View File

@@ -207,7 +207,8 @@ class SpatialEditorViewport : public Control {
VIEW_DISPLAY_SHADELESS,
VIEW_LOCK_ROTATION,
VIEW_CINEMATIC_PREVIEW,
VIEW_AUTO_ORTHOGONAL
VIEW_AUTO_ORTHOGONAL,
VIEW_PORTAL_CULLING,
};
public:
@@ -545,6 +546,7 @@ public:
TOOL_UNLOCK_SELECTED,
TOOL_GROUP_SELECTED,
TOOL_UNGROUP_SELECTED,
TOOL_CONVERT_ROOMS,
TOOL_MAX
};
@@ -624,6 +626,7 @@ private:
MENU_TOOL_LOCAL_COORDS,
MENU_TOOL_USE_SNAP,
MENU_TOOL_OVERRIDE_CAMERA,
MENU_TOOL_CONVERT_ROOMS,
MENU_TRANSFORM_CONFIGURE_SNAP,
MENU_TRANSFORM_DIALOG,
MENU_VIEW_USE_1_VIEWPORT,
@@ -634,6 +637,7 @@ private:
MENU_VIEW_USE_4_VIEWPORTS,
MENU_VIEW_ORIGIN,
MENU_VIEW_GRID,
MENU_VIEW_PORTAL_CULLING,
MENU_VIEW_GIZMOS_3D_ICONS,
MENU_VIEW_CAMERA_SETTINGS,
MENU_LOCK_SELECTED,
@@ -762,6 +766,8 @@ public:
void update_grid();
void update_transform_gizmo();
void update_portal_tools();
void show_advanced_portal_tools(bool p_show);
void update_all_gizmos(Node *p_node = nullptr);
void snap_selected_nodes_to_floor();
void select_gizmo_highlight_axis(int p_axis);

View File

@@ -43,6 +43,10 @@
#include "scene/3d/light.h"
#include "visibility_notifier.h"
#ifdef TOOLS_ENABLED
#include "editor/plugins/spatial_editor_plugin.h"
#endif
#include "modules/modules_enabled.gen.h"
#ifdef MODULE_CSG_ENABLED
#include "modules/csg/csg_shape.h"
@@ -54,31 +58,55 @@
#include "core/math/convex_hull.h"
#endif
#ifdef TOOLS_ENABLED
RoomManager *RoomManager::active_room_manager = nullptr;
#endif
// This needs to be static because it cannot easily be propagated to portals
// during load (as the RoomManager may be loaded before Portals enter the scene tree)
real_t RoomManager::_default_portal_margin = 1.0;
#ifdef TOOLS_ENABLED
RoomManager *RoomManager::active_room_manager = nullptr;
// static versions of functions for use from editor toolbars
void RoomManager::static_rooms_set_active(bool p_active) {
if (active_room_manager) {
active_room_manager->rooms_set_active(p_active);
active_room_manager->property_list_changed_notify();
}
}
bool RoomManager::static_rooms_get_active() {
if (active_room_manager) {
return active_room_manager->rooms_get_active();
}
return false;
}
bool RoomManager::static_rooms_get_active_and_loaded() {
if (active_room_manager) {
if (active_room_manager->rooms_get_active()) {
Ref<World> world = active_room_manager->get_world();
RID scenario = world->get_scenario();
return active_room_manager->rooms_get_active() && VisualServer::get_singleton()->rooms_is_loaded(scenario);
}
}
return false;
}
void RoomManager::static_rooms_convert() {
if (active_room_manager) {
return active_room_manager->rooms_convert();
}
}
#endif
RoomManager::RoomManager() {
// some high value, we want room manager to be processed after other
// nodes because the camera should be moved first
set_process_priority(10000);
#ifdef TOOLS_ENABLED
// note this mechanism may fail to work correctly if the user creates two room managers,
// but should not create major problems as it is just used to auto update when portals etc
// are changed in the editor, and there is a check for nullptr.
active_room_manager = this;
#endif
}
RoomManager::~RoomManager() {
#ifdef TOOLS_ENABLED
active_room_manager = nullptr;
#endif
}
String RoomManager::get_configuration_warning() const {
@@ -173,12 +201,33 @@ void RoomManager::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
if (Engine::get_singleton()->is_editor_hint()) {
set_process_internal(_godot_preview_camera_ID != (ObjectID)-1);
#ifdef TOOLS_ENABLED
// note this mechanism may fail to work correctly if the user creates two room managers,
// but should not create major problems as it is just used to auto update when portals etc
// are changed in the editor, and there is a check for nullptr.
active_room_manager = this;
SpatialEditor *spatial_editor = SpatialEditor::get_singleton();
if (spatial_editor) {
spatial_editor->update_portal_tools();
}
#endif
} else {
if (_settings_gameplay_monitor_enabled) {
set_process_internal(true);
}
}
} break;
case NOTIFICATION_EXIT_TREE: {
#ifdef TOOLS_ENABLED
active_room_manager = nullptr;
if (Engine::get_singleton()->is_editor_hint()) {
SpatialEditor *spatial_editor = SpatialEditor::get_singleton();
if (spatial_editor) {
spatial_editor->update_portal_tools();
}
}
#endif
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
// can't call visual server if not inside world
if (!is_inside_world()) {
@@ -459,6 +508,10 @@ void RoomManager::rooms_set_active(bool p_active) {
if (is_inside_world() && get_world().is_valid()) {
VisualServer::get_singleton()->rooms_set_active(get_world()->get_scenario(), p_active);
_active = p_active;
#ifdef TOOLS_ENABLED
SpatialEditor::get_singleton()->update_portal_tools();
#endif
}
}

View File

@@ -135,6 +135,12 @@ public:
// an easy way of grabbing the active room manager for tools purposes
#ifdef TOOLS_ENABLED
static RoomManager *active_room_manager;
// static versions of functions for use from editor toolbars
static void static_rooms_set_active(bool p_active);
static bool static_rooms_get_active();
static bool static_rooms_get_active_and_loaded();
static void static_rooms_convert();
#endif
private:

View File

@@ -159,6 +159,7 @@ public:
// for use in the editor only, to allow a cheap way of turning off portals
// if there has been a change, e.g. moving a room etc.
void rooms_unload() { _ensure_unloaded(); }
bool rooms_is_loaded() const { return _loaded; }
// debugging
void set_debug_sprawl(bool p_active) { _debug_sprawl = p_active; }

View File

@@ -593,6 +593,9 @@ public:
BIND3(rooms_set_debug_feature, RID, RoomsDebugFeature, bool)
BIND2(rooms_update_gameplay_monitor, RID, const Vector<Vector3> &)
// don't use this in a game
BIND1RC(bool, rooms_is_loaded, RID)
// Callbacks
BIND1(callbacks_register, VisualServerCallbacks *)

View File

@@ -1308,6 +1308,12 @@ void VisualServerScene::rooms_update_gameplay_monitor(RID p_scenario, const Vect
scenario->_portal_renderer.rooms_update_gameplay_monitor(p_camera_positions);
}
bool VisualServerScene::rooms_is_loaded(RID p_scenario) const {
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND_V(!scenario, false);
return scenario->_portal_renderer.rooms_is_loaded();
}
Vector<ObjectID> VisualServerScene::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {
Vector<ObjectID> instances;
Scenario *scenario = scenario_owner.get(p_scenario);

View File

@@ -647,6 +647,9 @@ public:
virtual void rooms_set_debug_feature(RID p_scenario, VisualServer::RoomsDebugFeature p_feature, bool p_active);
virtual void rooms_update_gameplay_monitor(RID p_scenario, const Vector<Vector3> &p_camera_positions);
// don't use this in a game
virtual bool rooms_is_loaded(RID p_scenario) const;
virtual void callbacks_register(VisualServerCallbacks *p_callbacks);
VisualServerCallbacks *get_callbacks() const { return _visual_server_callbacks; }

View File

@@ -516,6 +516,9 @@ public:
FUNC3(rooms_set_debug_feature, RID, RoomsDebugFeature, bool)
FUNC2(rooms_update_gameplay_monitor, RID, const Vector<Vector3> &)
// don't use this in a game
FUNC1RC(bool, rooms_is_loaded, RID)
// Callbacks
FUNC1(callbacks_register, VisualServerCallbacks *)

View File

@@ -909,6 +909,9 @@ public:
virtual void rooms_set_debug_feature(RID p_scenario, RoomsDebugFeature p_feature, bool p_active) = 0;
virtual void rooms_update_gameplay_monitor(RID p_scenario, const Vector<Vector3> &p_camera_positions) = 0;
// don't use this in a game!
virtual bool rooms_is_loaded(RID p_scenario) const = 0;
// callbacks are used to send messages back from the visual server to scene tree in thread friendly manner
virtual void callbacks_register(VisualServerCallbacks *p_callbacks) = 0;