Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/loud-camels-sink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@godot-js/editor": minor
---

feat:Implement Scene DTS generate strategic.
37 changes: 37 additions & 0 deletions internal/jsb_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()
{
Expand Down Expand Up @@ -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<Pair<String, GodotJSEditorHelper::SceneDTSGenerateStrategic>> 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<String> 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::SceneDTSGenerateStrategic>(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
}
}

Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions internal/jsb_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
62 changes: 51 additions & 11 deletions weaver-editor/jsb_editor_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SceneDTSGenerateStrategic> 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();
Expand Down Expand Up @@ -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<AnimationMixer>(p_node);

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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<SceneDTSGenerateStrategic> 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";
Expand Down Expand Up @@ -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<SceneDTSGenerateStrategic> 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;
}

Expand Down
12 changes: 10 additions & 2 deletions weaver-editor/jsb_editor_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,30 @@ 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<SceneDTSGenerateStrategic> 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);
static Dictionary get_scene_nodes(const String &p_path);
static void show_toast(const String& p_text, int p_severity);
};

VARIANT_BITFIELD_CAST(GodotJSEditorHelper::SceneDTSGenerateStrategic)
#endif
Loading