Implement game camera override

Implemented uniform API in Viewport class to override 2D and/or
3D camera.

Added buttons in 2D and 3D editor viewport toolbars that override
the running game camera transform with the editor viewport camera
transform. Implemented via remote debugger protocol and camera
override API.

Removed LiveEditFuncs function pointers from ScriptDebugger class.
Since the debugger got access to the SceneTree instance (if one
exists), there is no need to store the function pointers. The live
edit functions in SceneTree are used directly instead. Also removed
the static version of live edit functions in SceneTree for the same
reason. This reduced the SceneTree -> Debugger coupling too since
the function pointers don't need to be set from SceneTree anymore.

Moved script_debugger_remote.h/cpp from 'core/' to 'scene/debugger/'.
This is because the remote debugger is now using SceneTree directly
and 'core/' classes should not depend on 'scene/' classes.
This commit is contained in:
Erik 2019-04-06 22:55:01 +02:00 committed by SeleckyErik
parent 72dfa67dd3
commit 8b0546d93b
17 changed files with 536 additions and 169 deletions

View file

@ -427,31 +427,6 @@ class ScriptDebugger {
ScriptLanguage *break_lang;
public:
typedef void (*RequestSceneTreeMessageFunc)(void *);
struct LiveEditFuncs {
void *udata;
void (*node_path_func)(void *, const NodePath &p_path, int p_id);
void (*res_path_func)(void *, const String &p_path, int p_id);
void (*node_set_func)(void *, int p_id, const StringName &p_prop, const Variant &p_value);
void (*node_set_res_func)(void *, int p_id, const StringName &p_prop, const String &p_value);
void (*node_call_func)(void *, int p_id, const StringName &p_method, VARIANT_ARG_DECLARE);
void (*res_set_func)(void *, int p_id, const StringName &p_prop, const Variant &p_value);
void (*res_set_res_func)(void *, int p_id, const StringName &p_prop, const String &p_value);
void (*res_call_func)(void *, int p_id, const StringName &p_method, VARIANT_ARG_DECLARE);
void (*root_func)(void *, const NodePath &p_scene_path, const String &p_scene_from);
void (*tree_create_node_func)(void *, const NodePath &p_parent, const String &p_type, const String &p_name);
void (*tree_instance_node_func)(void *, const NodePath &p_parent, const String &p_path, const String &p_name);
void (*tree_remove_node_func)(void *, const NodePath &p_at);
void (*tree_remove_and_keep_node_func)(void *, const NodePath &p_at, ObjectID p_keep_id);
void (*tree_restore_node_func)(void *, ObjectID p_id, const NodePath &p_at, int p_at_pos);
void (*tree_duplicate_node_func)(void *, const NodePath &p_at, const String &p_new_name);
void (*tree_reparent_node_func)(void *, const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos);
};
_FORCE_INLINE_ static ScriptDebugger *get_singleton() { return singleton; }
void set_lines_left(int p_left);
int get_lines_left() const;
@ -480,8 +455,6 @@ public:
virtual bool is_remote() const { return false; }
virtual void request_quit() {}
virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata) {}
virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs) {}
virtual void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {}
virtual bool is_profiling() const = 0;

View file

@ -3730,6 +3730,7 @@ void CanvasItemEditor::_notification(int p_what) {
grid_snap_button->set_icon(get_icon("SnapGrid", "EditorIcons"));
snap_config_menu->set_icon(get_icon("GuiTabMenu", "EditorIcons"));
skeleton_menu->set_icon(get_icon("Bone", "EditorIcons"));
override_camera_button->set_icon(get_icon("Camera2D", "EditorIcons"));
pan_button->set_icon(get_icon("ToolPan", "EditorIcons"));
ruler_button->set_icon(get_icon("Ruler", "EditorIcons"));
pivot_button->set_icon(get_icon("EditPivot", "EditorIcons"));
@ -3799,6 +3800,15 @@ void CanvasItemEditor::_notification(int p_what) {
anchor_mode_button->set_icon(get_icon("Anchor", "EditorIcons"));
}
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
if (!is_visible() && override_camera_button->is_pressed()) {
ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger();
debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
override_camera_button->set_pressed(false);
}
}
}
void CanvasItemEditor::_selection_changed() {
@ -4140,6 +4150,15 @@ void CanvasItemEditor::_button_toggle_grid_snap(bool p_status) {
grid_snap_active = p_status;
viewport->update();
}
void CanvasItemEditor::_button_override_camera(bool p_pressed) {
ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger();
if (p_pressed) {
debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_2D);
} else {
debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
}
}
void CanvasItemEditor::_button_tool_select(int p_index) {
@ -4237,6 +4256,17 @@ void CanvasItemEditor::_button_toggle_anchor_mode(bool p_status) {
viewport->update();
}
void CanvasItemEditor::_update_override_camera_button(bool p_game_running) {
if (p_game_running) {
override_camera_button->set_disabled(false);
override_camera_button->set_tooltip(TTR("Game camera override\nOverrides game camera with editor viewport camera."));
} else {
override_camera_button->set_disabled(true);
override_camera_button->set_pressed(false);
override_camera_button->set_tooltip(TTR("Game camera override\nNo game instance running."));
}
}
void CanvasItemEditor::_popup_callback(int p_op) {
last_option = MenuOption(p_op);
@ -4829,6 +4859,8 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method("_button_zoom_plus", &CanvasItemEditor::_button_zoom_plus);
ClassDB::bind_method("_button_toggle_smart_snap", &CanvasItemEditor::_button_toggle_smart_snap);
ClassDB::bind_method("_button_toggle_grid_snap", &CanvasItemEditor::_button_toggle_grid_snap);
ClassDB::bind_method(D_METHOD("_button_override_camera", "pressed"), &CanvasItemEditor::_button_override_camera);
ClassDB::bind_method(D_METHOD("_update_override_camera_button", "game_running"), &CanvasItemEditor::_update_override_camera_button);
ClassDB::bind_method("_button_toggle_anchor_mode", &CanvasItemEditor::_button_toggle_anchor_mode);
ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll);
ClassDB::bind_method("_update_scrollbars", &CanvasItemEditor::_update_scrollbars);
@ -5141,6 +5173,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
editor_selection->connect("selection_changed", this, "update");
editor_selection->connect("selection_changed", this, "_selection_changed");
editor->call_deferred("connect", "play_pressed", this, "_update_override_camera_button", make_binds(true));
editor->call_deferred("connect", "stop_pressed", this, "_update_override_camera_button", make_binds(false));
hb = memnew(HBoxContainer);
add_child(hb);
hb->set_anchors_and_margins_preset(Control::PRESET_WIDE);
@ -5385,6 +5420,15 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->add_child(memnew(VSeparator));
override_camera_button = memnew(ToolButton);
hb->add_child(override_camera_button);
override_camera_button->connect("toggled", this, "_button_override_camera");
override_camera_button->set_toggle_mode(true);
override_camera_button->set_disabled(true);
_update_override_camera_button(false);
hb->add_child(memnew(VSeparator));
view_menu = memnew(MenuButton);
view_menu->set_text(TTR("View"));
hb->add_child(view_menu);

View file

@ -360,6 +360,7 @@ private:
ToolButton *ungroup_button;
MenuButton *skeleton_menu;
ToolButton *override_camera_button;
MenuButton *view_menu;
HBoxContainer *animation_hb;
MenuButton *animation_menu;
@ -533,8 +534,11 @@ private:
void _button_zoom_plus();
void _button_toggle_smart_snap(bool p_status);
void _button_toggle_grid_snap(bool p_status);
void _button_override_camera(bool p_pressed);
void _button_tool_select(int p_index);
void _update_override_camera_button(bool p_game_running);
HSplitContainer *palette_split;
VSplitContainer *bottom_split;

View file

@ -901,6 +901,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
emit_signal("clicked", this);
float zoom_factor = 1 + (ZOOM_MULTIPLIER - 1) * b->get_factor();
switch (b->get_button_index()) {
@ -3096,6 +3098,7 @@ void SpatialEditorViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpatialEditorViewport::drop_data_fw);
ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")));
ADD_SIGNAL(MethodInfo("clicked", PropertyInfo(Variant::OBJECT, "viewport")));
}
void SpatialEditorViewport::reset() {
@ -4369,6 +4372,19 @@ void SpatialEditor::_menu_item_toggled(bool pressed, int p_option) {
tool_option_button[TOOL_OPT_USE_SNAP]->set_pressed(pressed);
snap_enabled = pressed;
} break;
case MENU_TOOL_OVERRIDE_CAMERA: {
ScriptEditorDebugger *const debugger = ScriptEditor::get_singleton()->get_debugger();
if (pressed) {
using Override = ScriptEditorDebugger::CameraOverride;
debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id));
} else {
debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
}
} break;
}
}
@ -4396,6 +4412,35 @@ void SpatialEditor::_menu_gizmo_toggled(int p_option) {
update_all_gizmos();
}
void SpatialEditor::_update_camera_override_button(bool p_game_running) {
Button *const button = tool_option_button[TOOL_OPT_OVERRIDE_CAMERA];
if (p_game_running) {
button->set_disabled(false);
button->set_tooltip(TTR("Game camera override\nNo game instance running."));
} else {
button->set_disabled(true);
button->set_pressed(false);
button->set_tooltip(TTR("Game camera override\nOverrides game camera with editor viewport camera."));
}
}
void SpatialEditor::_update_camera_override_viewport(Object *p_viewport) {
SpatialEditorViewport *current_viewport = Object::cast_to<SpatialEditorViewport>(p_viewport);
if (!current_viewport)
return;
ScriptEditorDebugger *const debugger = ScriptEditor::get_singleton()->get_debugger();
camera_override_viewport_id = current_viewport->index;
if (debugger->get_camera_override() >= ScriptEditorDebugger::OVERRIDE_3D_1) {
using Override = ScriptEditorDebugger::CameraOverride;
debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id));
}
}
void SpatialEditor::_menu_item_pressed(int p_option) {
switch (p_option) {
@ -5290,6 +5335,7 @@ void SpatialEditor::_notification(int p_what) {
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"));
tool_option_button[SpatialEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_icon("Camera", "EditorIcons"));
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_icon("Panels1", "EditorIcons"));
view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_icon("Panels2", "EditorIcons"));
@ -5305,6 +5351,9 @@ void SpatialEditor::_notification(int p_what) {
get_tree()->connect("node_removed", this, "_node_removed");
EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", this, "_refresh_menu_icons");
editor_selection->connect("selection_changed", this, "_refresh_menu_icons");
editor->connect("stop_pressed", this, "_update_camera_override_button", make_binds(false));
editor->connect("play_pressed", this, "_update_camera_override_button", make_binds(true));
} else if (p_what == NOTIFICATION_ENTER_TREE) {
_register_all_gizmos();
@ -5339,6 +5388,13 @@ void SpatialEditor::_notification(int p_what) {
// Update grid color by rebuilding grid.
_finish_grid();
_init_grid();
} else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
if (!is_visible() && tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->is_pressed()) {
ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger();
debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_pressed(false);
}
}
}
@ -5483,6 +5539,8 @@ void SpatialEditor::_bind_methods() {
ClassDB::bind_method("_request_gizmo", &SpatialEditor::_request_gizmo);
ClassDB::bind_method("_toggle_maximize_view", &SpatialEditor::_toggle_maximize_view);
ClassDB::bind_method("_refresh_menu_icons", &SpatialEditor::_refresh_menu_icons);
ClassDB::bind_method("_update_camera_override_button", &SpatialEditor::_update_camera_override_button);
ClassDB::bind_method("_update_camera_override_viewport", &SpatialEditor::_update_camera_override_viewport);
ADD_SIGNAL(MethodInfo("transform_key_request"));
ADD_SIGNAL(MethodInfo("item_lock_status_changed"));
@ -5536,6 +5594,8 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
snap_key_enabled = false;
tool_mode = TOOL_MODE_SELECT;
camera_override_viewport_id = 0;
hbc_menu = memnew(HBoxContainer);
vbc->add_child(hbc_menu);
@ -5633,6 +5693,17 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
hbc_menu->add_child(memnew(VSeparator));
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(ToolButton);
hbc_menu->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]);
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_toggle_mode(true);
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_flat(true);
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_disabled(true);
button_binds.write[0] = MENU_TOOL_OVERRIDE_CAMERA;
tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect("toggled", this, "_menu_item_toggled", button_binds);
_update_camera_override_button(false);
hbc_menu->add_child(memnew(VSeparator));
// Drag and drop support;
preview_node = memnew(Spatial);
preview_bounds = AABB();
@ -5721,6 +5792,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
viewports[i] = memnew(SpatialEditorViewport(this, editor, i));
viewports[i]->connect("toggle_maximize_view", this, "_toggle_maximize_view");
viewports[i]->connect("clicked", this, "_update_camera_override_viewport");
viewports[i]->assign_pending_data_pointers(preview_node, &preview_bounds, accept);
viewport_base->add_child(viewports[i]);
}

View file

@ -494,6 +494,7 @@ public:
TOOL_OPT_LOCAL_COORDS,
TOOL_OPT_USE_SNAP,
TOOL_OPT_OVERRIDE_CAMERA,
TOOL_OPT_MAX
};
@ -559,6 +560,7 @@ private:
MENU_TOOL_LIST_SELECT,
MENU_TOOL_LOCAL_COORDS,
MENU_TOOL_USE_SNAP,
MENU_TOOL_OVERRIDE_CAMERA,
MENU_TRANSFORM_CONFIGURE_SNAP,
MENU_TRANSFORM_DIALOG,
MENU_VIEW_USE_1_VIEWPORT,
@ -585,9 +587,6 @@ private:
PopupMenu *gizmos_menu;
MenuButton *view_menu;
ToolButton *lock_button;
ToolButton *unlock_button;
AcceptDialog *accept;
ConfirmationDialog *snap_dialog;
@ -615,13 +614,16 @@ private:
void _menu_item_pressed(int p_option);
void _menu_item_toggled(bool pressed, int p_option);
void _menu_gizmo_toggled(int p_option);
void _update_camera_override_button(bool p_game_running);
void _update_camera_override_viewport(Object *p_viewport);
HBoxContainer *hbc_menu;
void _generate_selection_box();
UndoRedo *undo_redo;
void _instance_scene();
int camera_override_viewport_id;
void _init_indicators();
void _update_gizmos_menu();
void _update_gizmos_menu_theme();
@ -716,7 +718,7 @@ public:
void set_can_preview(Camera *p_preview);
SpatialEditorViewport *get_editor_viewport(int p_idx) {
ERR_FAIL_INDEX_V(p_idx, 4, NULL);
ERR_FAIL_INDEX_V(p_idx, static_cast<int>(VIEWPORTS_COUNT), NULL);
return viewports[p_idx];
}

View file

@ -33,6 +33,8 @@
#include "core/io/marshalls.h"
#include "core/project_settings.h"
#include "core/ustring.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/spatial_editor_plugin.h"
#include "editor_network_profiler.h"
#include "editor_node.h"
#include "editor_profiler.h"
@ -1212,6 +1214,42 @@ void ScriptEditorDebugger::_notification(int p_what) {
}
}
}
if (camera_override == OVERRIDE_2D) {
CanvasItemEditor *editor = CanvasItemEditor::get_singleton();
Dictionary state = editor->get_state();
float zoom = state["zoom"];
Point2 offset = state["ofs"];
Transform2D transform;
transform.scale_basis(Size2(zoom, zoom));
transform.elements[2] = -offset * zoom;
Array msg;
msg.push_back("override_camera_2D:transform");
msg.push_back(transform);
ppeer->put_var(msg);
} else if (camera_override >= OVERRIDE_3D_1) {
int viewport_idx = camera_override - OVERRIDE_3D_1;
SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(viewport_idx);
Camera *const cam = viewport->get_camera();
Array msg;
msg.push_back("override_camera_3D:transform");
msg.push_back(cam->get_camera_transform());
if (cam->get_projection() == Camera::PROJECTION_ORTHOGONAL) {
msg.push_back(false);
msg.push_back(cam->get_size());
} else {
msg.push_back(true);
msg.push_back(cam->get_fov());
}
msg.push_back(cam->get_znear());
msg.push_back(cam->get_zfar());
ppeer->put_var(msg);
}
}
if (error_count != last_error_count || warning_count != last_warning_count) {
@ -1426,6 +1464,7 @@ void ScriptEditorDebugger::start() {
set_process(true);
breaked = false;
camera_override = OVERRIDE_NONE;
}
void ScriptEditorDebugger::pause() {
@ -1870,6 +1909,45 @@ void ScriptEditorDebugger::live_debug_reparent_node(const NodePath &p_at, const
}
}
ScriptEditorDebugger::CameraOverride ScriptEditorDebugger::get_camera_override() const {
return camera_override;
}
void ScriptEditorDebugger::set_camera_override(CameraOverride p_override) {
if (p_override == OVERRIDE_2D && camera_override != OVERRIDE_2D) {
if (connection.is_valid()) {
Array msg;
msg.push_back("override_camera_2D:set");
msg.push_back(true);
ppeer->put_var(msg);
}
} else if (p_override != OVERRIDE_2D && camera_override == OVERRIDE_2D) {
if (connection.is_valid()) {
Array msg;
msg.push_back("override_camera_2D:set");
msg.push_back(false);
ppeer->put_var(msg);
}
} else if (p_override >= OVERRIDE_3D_1 && camera_override < OVERRIDE_3D_1) {
if (connection.is_valid()) {
Array msg;
msg.push_back("override_camera_3D:set");
msg.push_back(true);
ppeer->put_var(msg);
}
} else if (p_override < OVERRIDE_3D_1 && camera_override >= OVERRIDE_3D_1) {
if (connection.is_valid()) {
Array msg;
msg.push_back("override_camera_3D:set");
msg.push_back(false);
ppeer->put_var(msg);
}
}
camera_override = p_override;
}
void ScriptEditorDebugger::set_breakpoint(const String &p_path, int p_line, bool p_enabled) {
if (connection.is_valid()) {

View file

@ -35,6 +35,7 @@
#include "core/io/tcp_server.h"
#include "editor/editor_inspector.h"
#include "editor/property_editor.h"
#include "scene/3d/camera.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
@ -58,6 +59,17 @@ class ScriptEditorDebugger : public Control {
GDCLASS(ScriptEditorDebugger, Control);
public:
enum CameraOverride {
OVERRIDE_NONE,
OVERRIDE_2D,
OVERRIDE_3D_1, // 3D Viewport 1
OVERRIDE_3D_2, // 3D Viewport 2
OVERRIDE_3D_3, // 3D Viewport 3
OVERRIDE_3D_4 // 3D Viewport 4
};
private:
enum MessageType {
MESSAGE_ERROR,
MESSAGE_WARNING,
@ -165,6 +177,8 @@ class ScriptEditorDebugger : public Control {
bool live_debug;
CameraOverride camera_override;
void _performance_draw();
void _performance_select();
void _stack_dump_frame_selected();
@ -250,6 +264,9 @@ public:
void live_debug_duplicate_node(const NodePath &p_at, const String &p_new_name);
void live_debug_reparent_node(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos);
CameraOverride get_camera_override() const;
void set_camera_override(CameraOverride p_override);
void set_breakpoint(const String &p_path, int p_line, bool p_enabled);
void update_live_edit_root();

View file

@ -44,7 +44,6 @@
#include "core/project_settings.h"
#include "core/register_core_types.h"
#include "core/script_debugger_local.h"
#include "core/script_debugger_remote.h"
#include "core/script_language.h"
#include "core/translation.h"
#include "core/version.h"
@ -59,6 +58,7 @@
#include "main/tests/test_main.h"
#include "modules/register_module_types.h"
#include "platform/register_platform_apis.h"
#include "scene/debugger/script_debugger_remote.h"
#include "scene/main/scene_tree.h"
#include "scene/main/viewport.h"
#include "scene/register_scene_types.h"
@ -1583,6 +1583,12 @@ bool Main::start() {
if (!project_manager && !editor) { // game
if (game_path != "" || script != "") {
if (script_debugger && script_debugger->is_remote()) {
ScriptDebuggerRemote *remote_debugger = static_cast<ScriptDebuggerRemote *>(script_debugger);
remote_debugger->set_scene_tree(sml);
}
//autoload
List<PropertyInfo> props;
ProjectSettings::get_singleton()->get_property_list(&props);

View file

@ -30,6 +30,7 @@ SConscript('2d/SCsub')
SConscript('animation/SCsub')
SConscript('audio/SCsub')
SConscript('resources/SCsub')
SConscript('debugger/SCsub')
# Build it all as a library

5
scene/debugger/SCsub Normal file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env python
Import('env')
env.add_source_files(env.scene_sources, "*.cpp")

View file

@ -37,7 +37,10 @@
#include "core/os/os.h"
#include "core/project_settings.h"
#include "scene/main/node.h"
#include "scene/main/scene_tree.h"
#include "scene/main/viewport.h"
#include "scene/resources/packed_scene.h"
#include "servers/visual_server.h"
void ScriptDebuggerRemote::_send_video_memory() {
@ -150,7 +153,10 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue,
if (mouse_mode != Input::MOUSE_MODE_VISIBLE)
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
uint64_t loop_begin_usec = 0;
uint64_t loop_time_sec = 0;
while (true) {
loop_begin_usec = OS::get_singleton()->get_ticks_usec();
_get_output();
@ -279,9 +285,10 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue,
break;
} else if (command == "request_scene_tree") {
if (request_scene_tree)
request_scene_tree(request_scene_tree_ud);
#ifdef DEBUG_ENABLED
if (scene_tree)
scene_tree->_debugger_request_tree();
#endif
} else if (command == "request_video_mem") {
_send_video_memory();
@ -293,6 +300,40 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue,
_set_object_property(cmd[1], cmd[2], cmd[3]);
} else if (command == "override_camera_2D:set") {
bool enforce = cmd[1];
if (scene_tree) {
scene_tree->get_root()->enable_canvas_transform_override(enforce);
}
} else if (command == "override_camera_2D:transform") {
Transform2D transform = cmd[1];
if (scene_tree) {
scene_tree->get_root()->set_canvas_transform_override(transform);
}
} else if (command == "override_camera_3D:set") {
bool enable = cmd[1];
if (scene_tree) {
scene_tree->get_root()->enable_camera_override(enable);
}
} else if (command == "override_camera_3D:transform") {
Transform transform = cmd[1];
bool is_perspective = cmd[2];
float size_or_fov = cmd[3];
float near = cmd[4];
float far = cmd[5];
if (scene_tree) {
if (is_perspective) {
scene_tree->get_root()->set_camera_override_perspective(size_or_fov, near, far);
} else {
scene_tree->get_root()->set_camera_override_orthogonal(size_or_fov, near, far);
}
scene_tree->get_root()->set_camera_override_transform(transform);
}
} else if (command == "reload_scripts") {
reload_all_scripts = true;
} else if (command == "breakpoint") {
@ -315,6 +356,13 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue,
OS::get_singleton()->delay_usec(10000);
OS::get_singleton()->process_and_drop_events();
}
// This is for the camera override to stay live even when the game is paused from the editor
loop_time_sec = (OS::get_singleton()->get_ticks_usec() - loop_begin_usec) / 1000000.0f;
VisualServer::get_singleton()->sync();
if (VisualServer::get_singleton()->has_changed()) {
VisualServer::get_singleton()->draw(true, loop_time_sec * Engine::get_singleton()->get_time_scale());
}
}
packet_peer_stream->put_var("debug_exit");
@ -446,93 +494,75 @@ void ScriptDebuggerRemote::_err_handler(void *ud, const char *p_func, const char
bool ScriptDebuggerRemote::_parse_live_edit(const Array &p_command) {
#ifdef DEBUG_ENABLED
String cmdstr = p_command[0];
if (!live_edit_funcs || !cmdstr.begins_with("live_"))
if (!scene_tree || !cmdstr.begins_with("live_"))
return false;
//print_line(Variant(cmd).get_construct_string());
if (cmdstr == "live_set_root") {
if (!live_edit_funcs->root_func)
return true;
//print_line("root: "+Variant(cmd).get_construct_string());
live_edit_funcs->root_func(live_edit_funcs->udata, p_command[1], p_command[2]);
scene_tree->_live_edit_root_func(p_command[1], p_command[2]);
} else if (cmdstr == "live_node_path") {
if (!live_edit_funcs->node_path_func)
return true;
//print_line("path: "+Variant(cmd).get_construct_string());
live_edit_funcs->node_path_func(live_edit_funcs->udata, p_command[1], p_command[2]);
scene_tree->_live_edit_node_path_func(p_command[1], p_command[2]);
} else if (cmdstr == "live_res_path") {
if (!live_edit_funcs->res_path_func)
return true;
live_edit_funcs->res_path_func(live_edit_funcs->udata, p_command[1], p_command[2]);
scene_tree->_live_edit_res_path_func(p_command[1], p_command[2]);
} else if (cmdstr == "live_node_prop_res") {
if (!live_edit_funcs->node_set_res_func)
return true;
live_edit_funcs->node_set_res_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3]);
scene_tree->_live_edit_node_set_res_func(p_command[1], p_command[2], p_command[3]);
} else if (cmdstr == "live_node_prop") {
if (!live_edit_funcs->node_set_func)
return true;
live_edit_funcs->node_set_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3]);
scene_tree->_live_edit_node_set_func(p_command[1], p_command[2], p_command[3]);
} else if (cmdstr == "live_res_prop_res") {
if (!live_edit_funcs->res_set_res_func)
return true;
live_edit_funcs->res_set_res_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3]);
scene_tree->_live_edit_res_set_res_func(p_command[1], p_command[2], p_command[3]);
} else if (cmdstr == "live_res_prop") {
if (!live_edit_funcs->res_set_func)
return true;
live_edit_funcs->res_set_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3]);
scene_tree->_live_edit_res_set_func(p_command[1], p_command[2], p_command[3]);
} else if (cmdstr == "live_node_call") {
if (!live_edit_funcs->node_call_func)
return true;
live_edit_funcs->node_call_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3], p_command[4], p_command[5], p_command[6], p_command[7]);
scene_tree->_live_edit_node_call_func(p_command[1], p_command[2], p_command[3], p_command[4], p_command[5], p_command[6], p_command[7]);
} else if (cmdstr == "live_res_call") {
if (!live_edit_funcs->res_call_func)
return true;
live_edit_funcs->res_call_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3], p_command[4], p_command[5], p_command[6], p_command[7]);
scene_tree->_live_edit_res_call_func(p_command[1], p_command[2], p_command[3], p_command[4], p_command[5], p_command[6], p_command[7]);
} else if (cmdstr == "live_create_node") {
live_edit_funcs->tree_create_node_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3]);
scene_tree->_live_edit_create_node_func(p_command[1], p_command[2], p_command[3]);
} else if (cmdstr == "live_instance_node") {
live_edit_funcs->tree_instance_node_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3]);
scene_tree->_live_edit_instance_node_func(p_command[1], p_command[2], p_command[3]);
} else if (cmdstr == "live_remove_node") {
live_edit_funcs->tree_remove_node_func(live_edit_funcs->udata, p_command[1]);
scene_tree->_live_edit_remove_node_func(p_command[1]);
} else if (cmdstr == "live_remove_and_keep_node") {
live_edit_funcs->tree_remove_and_keep_node_func(live_edit_funcs->udata, p_command[1], p_command[2]);
scene_tree->_live_edit_remove_and_keep_node_func(p_command[1], p_command[2]);
} else if (cmdstr == "live_restore_node") {
live_edit_funcs->tree_restore_node_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3]);
scene_tree->_live_edit_restore_node_func(p_command[1], p_command[2], p_command[3]);
} else if (cmdstr == "live_duplicate_node") {
live_edit_funcs->tree_duplicate_node_func(live_edit_funcs->udata, p_command[1], p_command[2]);
scene_tree->_live_edit_duplicate_node_func(p_command[1], p_command[2]);
} else if (cmdstr == "live_reparent_node") {
live_edit_funcs->tree_reparent_node_func(live_edit_funcs->udata, p_command[1], p_command[2], p_command[3], p_command[4]);
scene_tree->_live_edit_reparent_node_func(p_command[1], p_command[2], p_command[3], p_command[4]);
} else {
@ -540,6 +570,10 @@ bool ScriptDebuggerRemote::_parse_live_edit(const Array &p_command) {
}
return true;
#else
return false;
#endif
}
void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
@ -732,8 +766,10 @@ void ScriptDebuggerRemote::_poll_events() {
debug(get_break_language());
} else if (command == "request_scene_tree") {
if (request_scene_tree)
request_scene_tree(request_scene_tree_ud);
#ifdef DEBUG_ENABLED
if (scene_tree)
scene_tree->_debugger_request_tree();
#endif
} else if (command == "request_video_mem") {
_send_video_memory();
@ -777,6 +813,40 @@ void ScriptDebuggerRemote::_poll_events() {
multiplayer->profiling_end();
profiling_network = false;
} else if (command == "override_camera_2D:set") {
bool enforce = cmd[1];
if (scene_tree) {
scene_tree->get_root()->enable_canvas_transform_override(enforce);
}
} else if (command == "override_camera_2D:transform") {
Transform2D transform = cmd[1];
if (scene_tree) {
scene_tree->get_root()->set_canvas_transform_override(transform);
}
} else if (command == "override_camera_3D:set") {
bool enable = cmd[1];
if (scene_tree) {
scene_tree->get_root()->enable_camera_override(enable);
}
} else if (command == "override_camera_3D:transform") {
Transform transform = cmd[1];
bool is_perspective = cmd[2];
float size_or_fov = cmd[3];
float near = cmd[4];
float far = cmd[5];
if (scene_tree) {
if (is_perspective) {
scene_tree->get_root()->set_camera_override_perspective(size_or_fov, near, far);
} else {
scene_tree->get_root()->set_camera_override_orthogonal(size_or_fov, near, far);
}
scene_tree->get_root()->set_camera_override_transform(transform);
}
} else if (command == "reload_scripts") {
reload_all_scripts = true;
} else if (command == "breakpoint") {
@ -1106,17 +1176,6 @@ void ScriptDebuggerRemote::request_quit() {
requested_quit = true;
}
void ScriptDebuggerRemote::set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata) {
request_scene_tree = p_func;
request_scene_tree_ud = p_udata;
}
void ScriptDebuggerRemote::set_live_edit_funcs(LiveEditFuncs *p_funcs) {
live_edit_funcs = p_funcs;
}
void ScriptDebuggerRemote::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
multiplayer = p_multiplayer;
}
@ -1195,8 +1254,7 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() :
msec_count(0),
locking(false),
poll_every(0),
request_scene_tree(NULL),
live_edit_funcs(NULL) {
scene_tree(NULL) {
packet_peer_stream->set_stream_peer(tcp_client);
packet_peer_stream->set_output_buffer_max_size(1024 * 1024 * 8); //8mb should be way more than enough

View file

@ -37,6 +37,8 @@
#include "core/os/os.h"
#include "core/script_language.h"
class SceneTree;
class ScriptDebuggerRemote : public ScriptDebugger {
struct Message {
@ -116,16 +118,14 @@ class ScriptDebuggerRemote : public ScriptDebugger {
void _poll_events();
uint32_t poll_every;
bool _parse_live_edit(const Array &p_command);
SceneTree *scene_tree;
RequestSceneTreeMessageFunc request_scene_tree;
void *request_scene_tree_ud;
bool _parse_live_edit(const Array &p_command);
void _set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value);
void _send_object_id(ObjectID p_id);
void _send_video_memory();
LiveEditFuncs *live_edit_funcs;
Ref<MultiplayerAPI> multiplayer;
@ -176,8 +176,6 @@ public:
virtual void send_message(const String &p_message, const Array &p_args);
virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info);
virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata);
virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs);
virtual void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer);
virtual bool is_profiling() const;
@ -189,6 +187,8 @@ public:
virtual void set_skip_breakpoints(bool p_skip_breakpoints);
void set_scene_tree(SceneTree *p_scene_tree) { scene_tree = p_scene_tree; };
ScriptDebuggerRemote();
~ScriptDebuggerRemote();
};

View file

@ -40,6 +40,7 @@
#include "core/project_settings.h"
#include "main/input_default.h"
#include "node.h"
#include "scene/debugger/script_debugger_remote.h"
#include "scene/resources/dynamic_font.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
@ -1094,27 +1095,6 @@ void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_li
}
}
static void _fill_array(Node *p_node, Array &array, int p_level) {
array.push_back(p_node->get_child_count());
array.push_back(p_node->get_name());
array.push_back(p_node->get_class());
array.push_back(p_node->get_instance_id());
for (int i = 0; i < p_node->get_child_count(); i++) {
_fill_array(p_node->get_child(i), array, p_level + 1);
}
}
void SceneTree::_debugger_request_tree(void *self) {
SceneTree *sml = (SceneTree *)self;
Array arr;
_fill_array(sml->root, arr, 0);
ScriptDebugger::get_singleton()->send_message("scene_tree", arr);
}
void SceneTree::_flush_delete_queue() {
_THREAD_SAFE_METHOD_
@ -1337,6 +1317,25 @@ void SceneTree::add_current_scene(Node *p_current) {
}
#ifdef DEBUG_ENABLED
static void _fill_array(Node *p_node, Array &array, int p_level) {
array.push_back(p_node->get_child_count());
array.push_back(p_node->get_name());
array.push_back(p_node->get_class());
array.push_back(p_node->get_instance_id());
for (int i = 0; i < p_node->get_child_count(); i++) {
_fill_array(p_node->get_child(i), array, p_level + 1);
}
}
void SceneTree::_debugger_request_tree() {
Array arr;
_fill_array(root, arr, 0);
ScriptDebugger::get_singleton()->send_message("scene_tree", arr);
}
void SceneTree::_live_edit_node_path_func(const NodePath &p_path, int p_id) {
live_edit_node_path_cache[p_id] = p_path;
@ -2117,7 +2116,11 @@ SceneTree::SceneTree() {
_update_root_rect();
if (ScriptDebugger::get_singleton()) {
ScriptDebugger::get_singleton()->set_request_scene_tree_message_func(_debugger_request_tree, this);
if (ScriptDebugger::get_singleton()->is_remote()) {
ScriptDebuggerRemote *remote_debugger = static_cast<ScriptDebuggerRemote *>(ScriptDebugger::get_singleton());
remote_debugger->set_scene_tree(this);
}
ScriptDebugger::get_singleton()->set_multiplayer(multiplayer);
}
@ -2129,29 +2132,6 @@ SceneTree::SceneTree() {
#ifdef DEBUG_ENABLED
live_edit_funcs.udata = this;
live_edit_funcs.node_path_func = _live_edit_node_path_funcs;
live_edit_funcs.res_path_func = _live_edit_res_path_funcs;
live_edit_funcs.node_set_func = _live_edit_node_set_funcs;
live_edit_funcs.node_set_res_func = _live_edit_node_set_res_funcs;
live_edit_funcs.node_call_func = _live_edit_node_call_funcs;
live_edit_funcs.res_set_func = _live_edit_res_set_funcs;
live_edit_funcs.res_set_res_func = _live_edit_res_set_res_funcs;
live_edit_funcs.res_call_func = _live_edit_res_call_funcs;
live_edit_funcs.root_func = _live_edit_root_funcs;
live_edit_funcs.tree_create_node_func = _live_edit_create_node_funcs;
live_edit_funcs.tree_instance_node_func = _live_edit_instance_node_funcs;
live_edit_funcs.tree_remove_node_func = _live_edit_remove_node_funcs;
live_edit_funcs.tree_remove_and_keep_node_func = _live_edit_remove_and_keep_node_funcs;
live_edit_funcs.tree_restore_node_func = _live_edit_restore_node_funcs;
live_edit_funcs.tree_duplicate_node_func = _live_edit_duplicate_node_funcs;
live_edit_funcs.tree_reparent_node_func = _live_edit_reparent_node_funcs;
if (ScriptDebugger::get_singleton()) {
ScriptDebugger::get_singleton()->set_live_edit_funcs(&live_edit_funcs);
}
live_edit_root = NodePath("/root");
#endif

View file

@ -211,7 +211,6 @@ private:
Variant _call_group_flags(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
Variant _call_group(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
static void _debugger_request_tree(void *self);
void _flush_delete_queue();
//optimization
friend class CanvasItem;
@ -220,6 +219,7 @@ private:
SelfList<Node>::List xform_change_list;
friend class ScriptDebuggerRemote;
#ifdef DEBUG_ENABLED
Map<int, NodePath> live_edit_node_path_cache;
@ -231,7 +231,7 @@ private:
Map<String, Set<Node *> > live_scene_edit_cache;
Map<Node *, Map<ObjectID, Node *> > live_edit_remove_list;
ScriptDebugger::LiveEditFuncs live_edit_funcs;
void _debugger_request_tree();
void _live_edit_node_path_func(const NodePath &p_path, int p_id);
void _live_edit_res_path_func(const String &p_path, int p_id);
@ -252,25 +252,6 @@ private:
void _live_edit_duplicate_node_func(const NodePath &p_at, const String &p_new_name);
void _live_edit_reparent_node_func(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos);
static void _live_edit_node_path_funcs(void *self, const NodePath &p_path, int p_id) { reinterpret_cast<SceneTree *>(self)->_live_edit_node_path_func(p_path, p_id); }
static void _live_edit_res_path_funcs(void *self, const String &p_path, int p_id) { reinterpret_cast<SceneTree *>(self)->_live_edit_res_path_func(p_path, p_id); }
static void _live_edit_node_set_funcs(void *self, int p_id, const StringName &p_prop, const Variant &p_value) { reinterpret_cast<SceneTree *>(self)->_live_edit_node_set_func(p_id, p_prop, p_value); }
static void _live_edit_node_set_res_funcs(void *self, int p_id, const StringName &p_prop, const String &p_value) { reinterpret_cast<SceneTree *>(self)->_live_edit_node_set_res_func(p_id, p_prop, p_value); }
static void _live_edit_node_call_funcs(void *self, int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) { reinterpret_cast<SceneTree *>(self)->_live_edit_node_call_func(p_id, p_method, VARIANT_ARG_PASS); }
static void _live_edit_res_set_funcs(void *self, int p_id, const StringName &p_prop, const Variant &p_value) { reinterpret_cast<SceneTree *>(self)->_live_edit_res_set_func(p_id, p_prop, p_value); }
static void _live_edit_res_set_res_funcs(void *self, int p_id, const StringName &p_prop, const String &p_value) { reinterpret_cast<SceneTree *>(self)->_live_edit_res_set_res_func(p_id, p_prop, p_value); }
static void _live_edit_res_call_funcs(void *self, int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) { reinterpret_cast<SceneTree *>(self)->_live_edit_res_call_func(p_id, p_method, VARIANT_ARG_PASS); }
static void _live_edit_root_funcs(void *self, const NodePath &p_scene_path, const String &p_scene_from) { reinterpret_cast<SceneTree *>(self)->_live_edit_root_func(p_scene_path, p_scene_from); }
static void _live_edit_create_node_funcs(void *self, const NodePath &p_parent, const String &p_type, const String &p_name) { reinterpret_cast<SceneTree *>(self)->_live_edit_create_node_func(p_parent, p_type, p_name); }
static void _live_edit_instance_node_funcs(void *self, const NodePath &p_parent, const String &p_path, const String &p_name) { reinterpret_cast<SceneTree *>(self)->_live_edit_instance_node_func(p_parent, p_path, p_name); }
static void _live_edit_remove_node_funcs(void *self, const NodePath &p_at) { reinterpret_cast<SceneTree *>(self)->_live_edit_remove_node_func(p_at); }
static void _live_edit_remove_and_keep_node_funcs(void *self, const NodePath &p_at, ObjectID p_keep_id) { reinterpret_cast<SceneTree *>(self)->_live_edit_remove_and_keep_node_func(p_at, p_keep_id); }
static void _live_edit_restore_node_funcs(void *self, ObjectID p_id, const NodePath &p_at, int p_at_pos) { reinterpret_cast<SceneTree *>(self)->_live_edit_restore_node_func(p_id, p_at, p_at_pos); }
static void _live_edit_duplicate_node_funcs(void *self, const NodePath &p_at, const String &p_new_name) { reinterpret_cast<SceneTree *>(self)->_live_edit_duplicate_node_func(p_at, p_new_name); }
static void _live_edit_reparent_node_funcs(void *self, const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos) { reinterpret_cast<SceneTree *>(self)->_live_edit_reparent_node_func(p_at, p_new_place, p_new_name, p_at_pos); }
#endif
enum {

View file

@ -779,10 +779,45 @@ bool Viewport::is_audio_listener_2d() const {
return audio_listener_2d;
}
void Viewport::enable_canvas_transform_override(bool p_enable) {
if (override_canvas_transform == p_enable) {
return;
}
override_canvas_transform = p_enable;
if (p_enable) {
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override);
} else {
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform);
}
}
bool Viewport::is_canvas_transform_override_enbled() const {
return override_canvas_transform;
}
void Viewport::set_canvas_transform_override(const Transform2D &p_transform) {
if (canvas_transform_override == p_transform) {
return;
}
canvas_transform_override = p_transform;
if (override_canvas_transform) {
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override);
}
}
Transform2D Viewport::get_canvas_transform_override() const {
return canvas_transform_override;
}
void Viewport::set_canvas_transform(const Transform2D &p_transform) {
canvas_transform = p_transform;
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform);
if (!override_canvas_transform) {
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform);
}
}
Transform2D Viewport::get_canvas_transform() const {
@ -890,10 +925,12 @@ void Viewport::_camera_set(Camera *p_camera) {
camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
}
camera = p_camera;
if (camera)
VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
else
VisualServer::get_singleton()->viewport_attach_camera(viewport, RID());
if (!camera_override) {
if (camera)
VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
else
VisualServer::get_singleton()->viewport_attach_camera(viewport, RID());
}
if (camera) {
camera->notification(Camera::NOTIFICATION_BECAME_CURRENT);
@ -1108,10 +1145,82 @@ Listener *Viewport::get_listener() const {
}
Camera *Viewport::get_camera() const {
return camera;
}
void Viewport::enable_camera_override(bool p_enable) {
#ifndef _3D_DISABLED
if (p_enable == camera_override) {
return;
}
if (p_enable) {
camera_override.rid = VisualServer::get_singleton()->camera_create();
} else {
VisualServer::get_singleton()->free(camera_override.rid);
camera_override.rid = RID();
}
if (p_enable) {
VisualServer::get_singleton()->viewport_attach_camera(viewport, camera_override.rid);
} else if (camera) {
VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
} else {
VisualServer::get_singleton()->viewport_attach_camera(viewport, RID());
}
#endif
}
bool Viewport::is_camera_override_enabled() const {
return camera_override;
}
void Viewport::set_camera_override_transform(const Transform &p_transform) {
if (camera_override) {
camera_override.transform = p_transform;
VisualServer::get_singleton()->camera_set_transform(camera_override.rid, p_transform);
}
}
Transform Viewport::get_camera_override_transform() const {
if (camera_override) {
return camera_override.transform;
}
return Transform();
}
void Viewport::set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
if (camera_override) {
if (camera_override.fov == p_fovy_degrees && camera_override.z_near == p_z_near &&
camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_PERSPECTIVE)
return;
camera_override.fov = p_fovy_degrees;
camera_override.z_near = p_z_near;
camera_override.z_far = p_z_far;
camera_override.projection = CameraOverrideData::PROJECTION_PERSPECTIVE;
VisualServer::get_singleton()->camera_set_perspective(camera_override.rid, camera_override.fov, camera_override.z_near, camera_override.z_far);
}
}
void Viewport::set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far) {
if (camera_override) {
if (camera_override.size == p_size && camera_override.z_near == p_z_near &&
camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_ORTHOGONAL)
return;
camera_override.size = p_size;
camera_override.z_near = p_z_near;
camera_override.z_far = p_z_far;
camera_override.projection = CameraOverrideData::PROJECTION_ORTHOGONAL;
VisualServer::get_singleton()->camera_set_orthogonal(camera_override.rid, camera_override.size, camera_override.z_near, camera_override.z_far);
}
}
Transform2D Viewport::get_final_transform() const {
return stretch_transform * global_canvas_transform;
@ -3180,6 +3289,7 @@ Viewport::Viewport() {
parent = NULL;
listener = NULL;
camera = NULL;
override_canvas_transform = false;
canvas_layers.insert(NULL); // This eases picking code (interpreted as the canvas of the Viewport)
arvr = false;
size_override = false;

View file

@ -160,6 +160,24 @@ private:
bool arvr;
struct CameraOverrideData {
Transform transform;
enum Projection {
PROJECTION_PERSPECTIVE,
PROJECTION_ORTHOGONAL
};
Projection projection;
float fov;
float size;
float z_near;
float z_far;
RID rid;
operator bool() const {
return rid != RID();
}
} camera_override;
Camera *camera;
Set<Camera *> cameras;
Set<CanvasLayer *> canvas_layers;
@ -173,6 +191,9 @@ private:
bool audio_listener_2d;
RID internal_listener_2d;
bool override_canvas_transform;
Transform2D canvas_transform_override;
Transform2D canvas_transform;
Transform2D global_canvas_transform;
Transform2D stretch_transform;
@ -394,6 +415,15 @@ public:
Listener *get_listener() const;
Camera *get_camera() const;
void enable_camera_override(bool p_enable);
bool is_camera_override_enabled() const;
void set_camera_override_transform(const Transform &p_transform);
Transform get_camera_override_transform() const;
void set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
void set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far);
void set_use_arvr(bool p_use_arvr);
bool use_arvr();
@ -418,6 +448,12 @@ public:
Ref<World2D> get_world_2d() const;
Ref<World2D> find_world_2d() const;
void enable_canvas_transform_override(bool p_enable);
bool is_canvas_transform_override_enbled() const;
void set_canvas_transform_override(const Transform2D &p_transform);
Transform2D get_canvas_transform_override() const;
void set_canvas_transform(const Transform2D &p_transform);
Transform2D get_canvas_transform() const;

View file

@ -56,12 +56,12 @@
#include "audio_server.h"
#include "camera/camera_feed.h"
#include "camera_server.h"
#include "core/script_debugger_remote.h"
#include "physics/physics_server_sw.h"
#include "physics_2d/physics_2d_server_sw.h"
#include "physics_2d/physics_2d_server_wrap_mt.h"
#include "physics_2d_server.h"
#include "physics_server.h"
#include "scene/debugger/script_debugger_remote.h"
#include "visual/shader_types.h"
#include "visual_server.h"