Use editor preview nodes when running current or custom scene is pressed

This commit is contained in:
Jayden Sipe 2024-10-18 21:28:42 -04:00
parent 44fa552343
commit 05490a77db
10 changed files with 157 additions and 4 deletions

View File

@ -991,6 +991,9 @@
<member name="editor/naming/script_name_casing" type="int" setter="" getter="" default="0">
When generating script file names from the selected node, set the type of casing to use in this project. This is mostly an editor setting.
</member>
<member name="editor/run/automatically_add_preview_nodes_when_running_single_3d_scene" type="bool" setter="" getter="" default="true">
If [code]true[/code], when using Run Current Scene or Run Specific Scene, the editor's preview Environment, Sun and Camera will be duplicated and added to the scene if no other [WorldEnvironment], [DirectionalLight3D] or [Camera3D] nodes are present. This will also be disabled for the [WorldEnvironment] and [DirectionalLight3D] if the preview Environment/Sun is toggled off.
</member>
<member name="editor/run/main_run_args" type="String" setter="" getter="" default="&quot;&quot;">
The command-line arguments to append to Godot's own command line when running the project. This doesn't affect the editor itself.
It is possible to make another executable run Godot by using the [code]%command%[/code] placeholder. The placeholder will be replaced with Godot's own command line. Program-specific arguments should be placed [i]before[/i] the placeholder, whereas Godot-specific arguments should be placed [i]after[/i] the placeholder.

View File

@ -30,6 +30,7 @@
#include "editor_debugger_node.h"
#include "core/config/project_settings.h"
#include "core/object/undo_redo.h"
#include "editor/debugger/editor_debugger_tree.h"
#include "editor/debugger/script_editor_debugger.h"
@ -396,6 +397,13 @@ void EditorDebuggerNode::_notification(int p_what) {
} // Will arrive too late, how does the regular run work?
debugger->update_live_edit_root();
#ifndef _3D_DISABLED
// Adds the preview WorldEnvironment, DirectionalLight3D, Camera3D nodes from the Editor if they are not present in the current scene when using RUN_CURRENT or RUN_CUSTOM.
if (GLOBAL_GET("editor/run/automatically_add_preview_nodes_when_running_single_3d_scene") && (EditorRunBar::get_singleton()->get_run_mode() == EditorRunBar::RUN_CURRENT || EditorRunBar::get_singleton()->get_run_mode() == EditorRunBar::RUN_CUSTOM)) {
debugger->add_preview_nodes_to_current_3d_scene();
}
#endif // _3D_DISABLED
}
} break;
}

View File

@ -35,6 +35,7 @@
#include "core/debugger/remote_debugger.h"
#include "core/io/marshalls.h"
#include "core/string/ustring.h"
#include "core/variant/variant_utility.h"
#include "core/version.h"
#include "editor/debugger/debug_adapter/debug_adapter_protocol.h"
#include "editor/debugger/editor_expression_evaluator.h"
@ -42,12 +43,14 @@
#include "editor/debugger/editor_profiler.h"
#include "editor/debugger/editor_visual_profiler.h"
#include "editor/editor_file_system.h"
#include "editor/editor_interface.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_property_name_processor.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/gui/editor_run_bar.h"
#include "editor/inspector_dock.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/editor_debugger_plugin.h"
@ -55,6 +58,8 @@
#include "editor/themes/editor_scale.h"
#include "main/performance.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/world_environment.h"
#include "scene/debugger/scene_debugger.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/grid_container.h"
@ -1490,6 +1495,60 @@ void ScriptEditorDebugger::set_camera_override(CameraOverride p_override) {
camera_override = p_override;
}
void ScriptEditorDebugger::add_preview_nodes_to_current_3d_scene() {
Array msg;
const Node3DEditor *editor = Node3DEditor::get_singleton();
const Ref<PackedScene> current_running_scene = ResourceLoader::load(EditorRunBar::get_singleton()->get_playing_scene());
if (current_running_scene.is_null()) {
return;
}
const Ref<SceneState> scene_state = current_running_scene->get_state();
// Make sure we have a root node.
ERR_FAIL_COND(scene_state->get_node_count() < 1);
// If the root node isn't a 3D node, check if we have an inherited scene as the root node or return.
if (!ClassDB::is_parent_class(scene_state->get_node_type(0), "Node3D")) {
const Ref<SceneState> base_state = current_running_scene->get_state()->get_base_scene_state();
// If our inherited scene does not inherit a 3D node, return.
if (base_state.is_valid()) {
if (!ClassDB::is_parent_class(base_state->get_node_type(0), "Node3D")) {
return;
}
} else {
return;
}
}
// Check to see if nodes already exists in the current scene and if the preview Environment/Sun buttons are not pressed.
bool should_add_world_environment = true;
bool should_add_directional_light_3d = true;
bool should_add_camera_3d = true;
for (int i = 0; i < scene_state->get_node_count(); i++) {
if (scene_state->get_node_type(i) == "WorldEnvironment" || !editor->is_environ_button_pressed()) {
should_add_world_environment = false;
}
if (scene_state->get_node_type(i) == "DirectionalLight3D" || !editor->is_sun_button_pressed()) {
should_add_directional_light_3d = false;
}
if (scene_state->get_node_type(i) == "Camera3D") {
should_add_camera_3d = false;
}
}
msg.push_back(should_add_world_environment);
msg.push_back(should_add_directional_light_3d);
msg.push_back(should_add_camera_3d);
// Serialize WorldEnvironment, DirectionalLight3D and Camera3D nodes to bytes and send to running game.
msg.push_back(VariantUtilityFunctions::var_to_bytes_with_objects(editor->get_preview_environment()->duplicate()));
msg.push_back(VariantUtilityFunctions::var_to_bytes_with_objects(editor->get_preview_sun()->duplicate()));
msg.push_back(VariantUtilityFunctions::var_to_bytes_with_objects(EditorInterface::get_singleton()->get_editor_viewport_3d(0)->get_camera_3d()->duplicate()));
_put_msg("scene:add_preview_nodes_to_current_3d_scene", msg);
}
void ScriptEditorDebugger::set_breakpoint(const String &p_path, int p_line, bool p_enabled) {
Array msg;
msg.push_back(p_path);

View File

@ -300,6 +300,8 @@ public:
EditorDebuggerNode::CameraOverride get_camera_override() const;
void set_camera_override(EditorDebuggerNode::CameraOverride p_override);
void add_preview_nodes_to_current_3d_scene();
void set_breakpoint(const String &p_path, int p_line, bool p_enabled);
void update_live_edit_root();

View File

@ -356,6 +356,10 @@ HBoxContainer *EditorRunBar::get_buttons_container() {
return main_hbox;
}
EditorRunBar::RunMode EditorRunBar::get_run_mode() const {
return current_mode;
}
void EditorRunBar::_bind_methods() {
ADD_SIGNAL(MethodInfo("play_pressed"));
ADD_SIGNAL(MethodInfo("stop_pressed"));

View File

@ -41,10 +41,7 @@ class PanelContainer;
class HBoxContainer;
class EditorRunBar : public MarginContainer {
GDCLASS(EditorRunBar, MarginContainer);
static EditorRunBar *singleton;
public:
enum RunMode {
STOPPED = 0,
RUN_MAIN,
@ -52,6 +49,13 @@ class EditorRunBar : public MarginContainer {
RUN_CUSTOM,
};
RunMode get_run_mode() const;
private:
GDCLASS(EditorRunBar, MarginContainer);
static EditorRunBar *singleton;
PanelContainer *main_panel = nullptr;
HBoxContainer *main_hbox = nullptr;

View File

@ -6039,6 +6039,29 @@ Node3DEditorViewportContainer::Node3DEditorViewportContainer() {
dragging_h = false;
}
WorldEnvironment *Node3DEditor::get_preview_environment() const {
return preview_environment;
}
DirectionalLight3D *Node3DEditor::get_preview_sun() const {
return preview_sun;
}
bool Node3DEditor::is_environ_button_pressed() const {
if (environ_button->is_disabled()) {
return false;
}
return environ_button->is_pressed();
}
bool Node3DEditor::is_sun_button_pressed() const {
if (sun_button->is_disabled()) {
return false;
}
return sun_button->is_pressed();
}
///////////////////////////////////////////////////////////////////
Node3DEditor *Node3DEditor::singleton = nullptr;

View File

@ -604,6 +604,12 @@ class Node3DEditor : public VBoxContainer {
GDCLASS(Node3DEditor, VBoxContainer);
public:
WorldEnvironment *get_preview_environment() const;
DirectionalLight3D *get_preview_sun() const;
bool is_environ_button_pressed() const;
bool is_sun_button_pressed() const;
static const unsigned int VIEWPORTS_COUNT = 4;
enum ToolMode {

View File

@ -269,6 +269,7 @@ void register_editor_types() {
// For correct doc generation.
GLOBAL_DEF("editor/run/main_run_args", "");
GLOBAL_DEF("editor/run/automatically_add_preview_nodes_when_running_single_3d_scene", true);
GLOBAL_DEF(PropertyInfo(Variant::STRING, "editor/script/templates_search_path", PROPERTY_HINT_DIR), "res://script_templates");

View File

@ -35,6 +35,12 @@
#include "core/io/marshalls.h"
#include "core/object/script_language.h"
#include "core/templates/local_vector.h"
#include "core/variant/variant_utility.h"
#ifndef _3D_DISABLED
#include "scene/3d/camera_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/world_environment.h"
#endif // _3D_DISABLED
#include "scene/main/scene_tree.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
@ -127,6 +133,43 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
scene_tree->get_root()->set_camera_3d_override_orthogonal(size_or_fov, depth_near, depth_far);
}
scene_tree->get_root()->set_camera_3d_override_transform(transform);
} else if (p_msg == "add_preview_nodes_to_current_3d_scene") {
ERR_FAIL_COND_V(p_args.size() < 6, ERR_INVALID_DATA);
const bool should_add_world_environment = p_args[0];
const bool should_add_directional_light_3d = p_args[1];
const bool should_add_camera_3d = p_args[2];
if (should_add_world_environment) {
WARN_PRINT_ED("Current scene was run without a WorldEnvironment node, adding preview WorldEnvironment to the scene. You can disable this by changing `editor/run/automatically_add_preview_nodes_when_running_single_3d_scene` in Project Settings.");
WorldEnvironment *world_environment = Object::cast_to<WorldEnvironment>(VariantUtilityFunctions::bytes_to_var_with_objects(p_args[3]));
ERR_FAIL_COND_V(world_environment == nullptr, ERR_INVALID_DATA);
scene_tree->get_root()->add_child(world_environment, false, Node::INTERNAL_MODE_BACK);
world_environment->set_name("WorldEnvironmentPreview");
}
if (should_add_directional_light_3d) {
WARN_PRINT_ED("Current scene was run without a DirectionalLight3D node, adding preview DirectionalLight3D to the scene. You can disable this by changing `editor/run/automatically_add_preview_nodes_when_running_single_3d_scene` in Project Settings.");
DirectionalLight3D *sun = Object::cast_to<DirectionalLight3D>(VariantUtilityFunctions::bytes_to_var_with_objects(p_args[4]));
ERR_FAIL_COND_V(sun == nullptr, ERR_INVALID_DATA);
scene_tree->get_root()->add_child(sun, false, Node::INTERNAL_MODE_BACK);
sun->set_name("SunPreview");
}
if (should_add_camera_3d) {
WARN_PRINT_ED("Current scene was run without a Camera3D node, adding preview Camera3D to the scene. You can disable this by changing `editor/run/automatically_add_preview_nodes_when_running_single_3d_scene` in Project Settings.");
Camera3D *camera_3d = Object::cast_to<Camera3D>(VariantUtilityFunctions::bytes_to_var_with_objects(p_args[5]));
ERR_FAIL_COND_V(camera_3d == nullptr, ERR_INVALID_DATA);
scene_tree->get_root()->add_child(camera_3d, false, Node::INTERNAL_MODE_BACK);
camera_3d->set_name("Camera3DPreview");
camera_3d->make_current();
}
#endif // _3D_DISABLED
} else if (p_msg == "set_object_property") {
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);