From b4e9134403cb239c82df3443e0ee2e5532c7d3e0 Mon Sep 17 00:00:00 2001 From: Daylily-Zeleen Date: Sun, 4 Jan 2026 14:51:03 +0800 Subject: [PATCH] Implement Scene DTS generate strategic. --- .changeset/loud-camels-sink.md | 5 +++ internal/jsb_settings.cpp | 37 +++++++++++++++++ internal/jsb_settings.h | 2 + weaver-editor/jsb_editor_helper.cpp | 62 ++++++++++++++++++++++++----- weaver-editor/jsb_editor_helper.h | 12 +++++- 5 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 .changeset/loud-camels-sink.md diff --git a/.changeset/loud-camels-sink.md b/.changeset/loud-camels-sink.md new file mode 100644 index 00000000..6dff060d --- /dev/null +++ b/.changeset/loud-camels-sink.md @@ -0,0 +1,5 @@ +--- +"@godot-js/editor": minor +--- + +feat:Implement Scene DTS generate strategic. diff --git a/internal/jsb_settings.cpp b/internal/jsb_settings.cpp index 11e64850..b5ac26bb 100644 --- a/internal/jsb_settings.cpp +++ b/internal/jsb_settings.cpp @@ -4,6 +4,11 @@ #include "jsb_macros.h" #include "jsb_logger.h" +#ifdef TOOLS_ENABLED +#include "../weaver-editor/jsb_editor_helper.h" +#include "core/templates/pair.h" +#endif // TOOLS_ENABLED + #define JSB_SET_RESTART(val) (val) #define JSB_SET_IGNORE_DOCS(val) (val) #define JSB_SET_BASIC(val) (val) @@ -38,6 +43,8 @@ namespace jsb::internal static constexpr char kRtPackagingIncludeDirectories[] = JSB_MODULE_NAME_STRING "/editor/packaging/include_directories"; static constexpr char kRtPackagingReferencedNodeModules[] = JSB_MODULE_NAME_STRING "/editor/packaging/referenced_node_modules"; + static constexpr char kRtSceneDTSGenerateStrategic[] = JSB_MODULE_NAME_STRING "/codegen/scene_dts/generate_strategic"; + #ifdef TOOLS_ENABLED bool init_editor_settings() { @@ -124,6 +131,30 @@ namespace jsb::internal } _GLOBAL_DEF(kRtPackagingReferencedNodeModules, true, false); + +#ifdef TOOLS_ENABLED + { + PropertyInfo SceneDTSGenerateStrategic; + SceneDTSGenerateStrategic.type = Variant::INT; + SceneDTSGenerateStrategic.name = kRtSceneDTSGenerateStrategic; + SceneDTSGenerateStrategic.hint = PROPERTY_HINT_FLAGS; + + // NOTE: Keep this map sync with GodotJSEditorHelper::SceneDTSGenerateStrategic + const LocalVector> scene_dts_generate_strategic_flags = { + {"Origin Name Node", GodotJSEditorHelper::SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE}, + {"Unique Name Node", GodotJSEditorHelper::SCENE_DTS_GENERATE_STRATEGIC_UNIQUE_NAME_NODE} + }; + + Vector flag_hints; + for (const auto &[name, value]: scene_dts_generate_strategic_flags) + { + flag_hints.push_back(vformat("%s:%s", name, value)); + } + + SceneDTSGenerateStrategic.hint_string = String(",").join(flag_hints); + _GLOBAL_DEF(SceneDTSGenerateStrategic, BitField(GodotJSEditorHelper::SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE), false, JSB_SET_IGNORE_DOCS(false), JSB_SET_BASIC(true), JSB_SET_INTERNAL(false)); + } +#endif // TOOLS_ENABLED } } @@ -202,6 +233,12 @@ namespace jsb::internal return GLOBAL_GET(kRtPackagingReferencedNodeModules); } + int Settings::get_scene_dts_generate_strategic() + { + init_settings(); + return GLOBAL_GET(kRtSceneDTSGenerateStrategic); + } + uint16_t Settings::get_debugger_port() { #ifdef TOOLS_ENABLED diff --git a/internal/jsb_settings.h b/internal/jsb_settings.h index bb84f4f6..01e56bb8 100644 --- a/internal/jsb_settings.h +++ b/internal/jsb_settings.h @@ -47,6 +47,8 @@ namespace jsb::internal static bool is_packaging_referenced_node_modules(); + static int get_scene_dts_generate_strategic(); + #ifdef TOOLS_ENABLED // [EDITOR ONLY] static bool editor_settings_available(); diff --git a/weaver-editor/jsb_editor_helper.cpp b/weaver-editor/jsb_editor_helper.cpp index 93594214..384a8b67 100644 --- a/weaver-editor/jsb_editor_helper.cpp +++ b/weaver-editor/jsb_editor_helper.cpp @@ -110,16 +110,22 @@ StringName GodotJSEditorHelper::_get_exposed_node_class_name(const StringName& c return jsb::internal::NamingUtil::get_class_name(exposed_class_name); } -Dictionary GodotJSEditorHelper::_build_node_type_descriptor(jsb::JSEnvironment& p_env, Node* p_node, const String& p_scene_resource_path) +Dictionary GodotJSEditorHelper::_build_node_type_descriptor(const BitField p_strategic, jsb::JSEnvironment& p_env, Node* p_node, const Node* p_root_node, Dictionary& r_unique_name_nodes, const String& p_scene_resource_path) { + jsb_check(p_strategic != 0); + Dictionary descriptor; Dictionary children; int child_count = p_node->get_child_count(true); - for (int i = 0; i < child_count; i++) + // If p_node is PackedScene, only editable instance's children should be collected. + if (p_node == p_root_node || p_node->get_scene_file_path().is_empty() || p_root_node->is_editable_instance(p_node)) { - Node* child = p_node->get_child(i, true); - children[child->get_name()] = _build_node_type_descriptor(p_env, child); + for (int i = 0; i < child_count; i++) + { + Node* child = p_node->get_child(i, true); + children[child->get_name()] = _build_node_type_descriptor(p_strategic, p_env, child, p_root_node, r_unique_name_nodes); + } } ScriptInstance* script_instance = p_node->get_script_instance(); @@ -148,12 +154,15 @@ Dictionary GodotJSEditorHelper::_build_node_type_descriptor(jsb::JSEnvironment& || GodotJSScriptLanguage::get_singleton()->is_global_class_generic(script->get_path()) || script->get_global_name().is_empty()) { - Dictionary object_literal; - object_literal[jsb_string_name(type)] = (int32_t) DescriptorType::ObjectLiteral; - object_literal[jsb_string_name(properties)] = children; - Array generic_arguments; - generic_arguments.push_back(object_literal); + + if (p_strategic.has_flag(SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE)) + { + Dictionary object_literal; + object_literal[jsb_string_name(type)] = (int32_t) DescriptorType::ObjectLiteral; + object_literal[jsb_string_name(properties)] = children; + generic_arguments.push_back(object_literal); + } AnimationMixer *animation_mixer = Object::cast_to(p_node); @@ -253,6 +262,13 @@ Dictionary GodotJSEditorHelper::_build_node_type_descriptor(jsb::JSEnvironment& } } + if (p_strategic.has_flag(SCENE_DTS_GENERATE_STRATEGIC_UNIQUE_NAME_NODE)) + { + if (p_node->is_unique_name_in_owner()) + { + r_unique_name_nodes["%" + p_node->get_name()] = descriptor; + } + } return descriptor; } @@ -302,6 +318,9 @@ void GodotJSEditorHelper::_bind_methods() ClassDB::bind_static_method(jsb_typename(GodotJSEditorHelper), D_METHOD("show_toast", "text", "severity"), &GodotJSEditorHelper::show_toast); ClassDB::bind_static_method(jsb_typename(GodotJSEditorHelper), D_METHOD("get_resource_type_descriptor", "resource_path"), &GodotJSEditorHelper::get_resource_type_descriptor); ClassDB::bind_static_method(jsb_typename(GodotJSEditorHelper), D_METHOD("get_scene_nodes", "scene_path"), &GodotJSEditorHelper::get_scene_nodes); + + BIND_BITFIELD_FLAG(SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE); + BIND_BITFIELD_FLAG(SCENE_DTS_GENERATE_STRATEGIC_UNIQUE_NAME_NODE); } Dictionary GodotJSEditorHelper::get_resource_type_descriptor(const String& p_path) @@ -329,8 +348,16 @@ Dictionary GodotJSEditorHelper::get_resource_type_descriptor(const String& p_pat jsb::JSEnvironment env(instantiated_scene->get_scene_file_path(), true); + BitField strategic = jsb::internal::Settings::get_scene_dts_generate_strategic(); + if (strategic == 0) + { + strategic.set_flag(SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE); + JSB_LOG(Warning, "Scene DTS generate strategic is undefine, use SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE (please configure it through project setting)."); + } + Array generic_arguments; - generic_arguments.push_back(_build_node_type_descriptor(env, instantiated_scene, p_path)); + Dictionary unique_name_nodes; + generic_arguments.push_back(_build_node_type_descriptor(strategic, env, instantiated_scene, instantiated_scene, unique_name_nodes, p_path)); descriptor[jsb_string_name(type)] = (int32_t) DescriptorType::Godot; descriptor[jsb_string_name(name)] = "PackedScene"; @@ -407,16 +434,29 @@ Dictionary GodotJSEditorHelper::get_scene_nodes(const String& p_path) v8::HandleScope handle_scope(isolate); Dictionary nodes; + Dictionary unique_name_nodes; int child_count = instantiated_scene->get_child_count(true); + BitField strategic = jsb::internal::Settings::get_scene_dts_generate_strategic(); + if (strategic == 0) + { + strategic.set_flag(SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE); + JSB_LOG(Warning, "Scene DTS generate strategic is undefine, use SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE (please configure it through project setting)."); + } for (int i = 0; i < child_count; i++) { Node* child = instantiated_scene->get_child(i, true); - nodes[child->get_name()] = _build_node_type_descriptor(env, child); + nodes[child->get_name()] = _build_node_type_descriptor(strategic, env, child, instantiated_scene, unique_name_nodes); } instantiated_scene->queue_free(); + if (!strategic.has_flag(SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE)) + { + nodes.clear(); + } + nodes.merge(unique_name_nodes); + return nodes; } diff --git a/weaver-editor/jsb_editor_helper.h b/weaver-editor/jsb_editor_helper.h index b3e7c0be..8b7420f2 100644 --- a/weaver-editor/jsb_editor_helper.h +++ b/weaver-editor/jsb_editor_helper.h @@ -6,17 +6,24 @@ class GodotJSEditorHelper : public Object { GDCLASS(GodotJSEditorHelper, Object); -private: +public: + enum SceneDTSGenerateStrategic + { + SCENE_DTS_GENERATE_STRATEGIC_ORIGIN_NAME_NODE = 1 << 0, + SCENE_DTS_GENERATE_STRATEGIC_UNIQUE_NAME_NODE = 1 << 1, + }; +private: static bool _request_codegen(jsb::JSEnvironment& p_env, GodotJSScript* p_script, const Dictionary& p_request, Dictionary& p_result); static StringName _get_exposed_node_class_name(const StringName& class_name); - static Dictionary _build_node_type_descriptor(jsb::JSEnvironment& p_env, Node* p_node, const String& p_scene_resource_path = String()); + static Dictionary _build_node_type_descriptor(const BitField p_strategic, jsb::JSEnvironment& p_env, Node* p_node, const Node* p_root_node, Dictionary& r_unique_name_nodes, const String& p_scene_resource_path = String()); static void _log_load_error(const String &p_file, const String &p_type, Error p_error); protected: static void _bind_methods(); public: + virtual ~GodotJSEditorHelper() override = default; static Dictionary get_resource_type_descriptor(const String &p_path); @@ -24,4 +31,5 @@ class GodotJSEditorHelper : public Object static void show_toast(const String& p_text, int p_severity); }; +VARIANT_BITFIELD_CAST(GodotJSEditorHelper::SceneDTSGenerateStrategic) #endif