Skip to content

Commit 222c03e

Browse files
feat: Godot 4.7 (dev/pre-release) build
1 parent b597480 commit 222c03e

9 files changed

Lines changed: 289 additions & 170 deletions

File tree

.changeset/shaggy-sloths-report.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@godot-js/editor": minor
3+
---
4+
5+
feat: Godot 4.7 (dev/pre-release) build.

.github/workflows/runner.yml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ jobs:
3737
- version: 4.6.1
3838
version_mm: 4.6
3939
version_ref: 4.6.1-stable
40-
# - version: 4.7dev
41-
# version_mm: 4.7
42-
# version_ref: master
40+
- version: 4.7dev
41+
version_mm: 4.7
42+
version_ref: master
4343
uses: ./.github/workflows/build_engine_version.yml
4444
with:
4545
version: ${{ matrix.version }}
@@ -56,7 +56,7 @@ jobs:
5656
matrix:
5757
include:
5858
- version: 4.6.1
59-
# - version: 4.7dev
59+
- version: 4.7dev
6060
with:
6161
version: ${{ matrix.version }}
6262

@@ -79,8 +79,7 @@ jobs:
7979
uses: ./.github/workflows/misc_release.yml
8080
secrets: inherit
8181
with:
82-
versions: '4.6.1'
83-
# versions: '4.6.1, 4.7'
82+
versions: '4.6.1, 4.7'
8483

8584
upload-assets:
8685
name: 📁 Upload Assets
@@ -95,6 +94,6 @@ jobs:
9594
matrix:
9695
include:
9796
- version: 4.6.1
98-
# - version: 4.7dev
97+
- version: 4.7dev
9998
with:
10099
version: ${{ matrix.version }}

bridge/jsb_editor_utility_funcs.cpp

Lines changed: 107 additions & 137 deletions
Large diffs are not rendered by default.

bridge/jsb_environment.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1474,7 +1474,7 @@ namespace jsb
14741474
return nullptr;
14751475
}
14761476

1477-
String class_name = internal::NamingUtil::get_class_name(p_class_info->name);
1477+
String class_name = internal::NamingUtil::get_class_name(internal::ClassUtil::get_internal_class_name(*p_class_info));
14781478

14791479
if (const NativeClassID* it = godot_classes_index_.getptr(class_name))
14801480
{

bridge/jsb_object_bindings.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "jsb_object_bindings.h"
22
#include "jsb_transpiler.h"
33
#include "jsb_type_convert.h"
4+
#include "../internal/jsb_class_util.h"
45
// TODO: Refactor. Violates isolation of bridge.
56
#include "../weaver/jsb_script_instance.h"
67
#include "../weaver/jsb_script_language.h"
@@ -14,17 +15,18 @@ namespace jsb
1415

1516
jsb_check(p_class_info);
1617

17-
String class_name = internal::NamingUtil::get_class_name(p_class_info->name);
18+
const StringName& internal_class_name = internal::ClassUtil::get_internal_class_name(*p_class_info);
19+
String class_name = internal::NamingUtil::get_class_name(internal_class_name);
1820
const NativeClassID class_id = p_env->add_native_class(NativeClassType::GodotObject, class_name);
19-
JSB_LOG(VeryVerbose, "expose godot type %s(%d) as %s", p_class_info->name, class_id, class_name);
21+
JSB_LOG(VeryVerbose, "expose godot type %s(%d) as %s", internal_class_name, class_id, class_name);
2022

2123
// construct type template
2224
{
2325

2426
impl::ClassBuilder class_builder = ObjectTemplate::create(p_env, class_id);
2527

2628
//NOTE all singleton object will overwrite the class itself in 'godot' module, so we need make all things defined on PrototypeTemplate.
27-
const bool is_singleton_class = Engine::get_singleton()->has_singleton(p_class_info->name);
29+
const bool is_singleton_class = Engine::get_singleton()->has_singleton(internal_class_name);
2830
auto static_builder = is_singleton_class ? class_builder.Instance() : class_builder.Static();
2931

3032
#if JSB_EXCLUDE_GETSET_METHODS
@@ -85,14 +87,14 @@ namespace jsb
8587
}
8688
}
8789

88-
if (p_class_info->name == jsb_string_name(Object))
90+
if (internal_class_name == jsb_string_name(Object))
8991
{
9092
// class: special methods
9193
class_builder.Instance().Method(jsb_literal(free), _godot_object_free);
9294
}
9395

9496
// class: signals
95-
for (const KeyValue<StringName, MethodInfo>& pair : p_class_info->signal_map)
97+
for (auto& pair : internal::ClassUtil::get_class_signal_map(*p_class_info))
9698
{
9799
v8::HandleScope handle_scope_for_signal(isolate);
98100
String signal_name = internal::NamingUtil::get_member_name(pair.key);
@@ -103,23 +105,21 @@ namespace jsb
103105
HashSet<StringName> enum_consts;
104106

105107
// class: enum (nested in class)
106-
for (const KeyValue<StringName, ClassDB::ClassInfo::EnumInfo>& pair : p_class_info->enum_map)
107-
{
108+
internal::ClassUtil::for_class_enums(*p_class_info, [&](const StringName& enum_name, const internal::ClassEnumInfo& enum_info) {
108109
v8::HandleScope handle_scope_for_enum(isolate);
109-
impl::ClassBuilder::EnumDeclaration enumeration = static_builder.Enum(internal::NamingUtil::get_enum_name(pair.key));
110-
for (const StringName& enum_value_name : pair.value.constants)
111-
{
112-
const String& js_enum_name = internal::NamingUtil::get_enum_value_name(enum_value_name);
110+
impl::ClassBuilder::EnumDeclaration enumeration = static_builder.Enum(internal::NamingUtil::get_enum_name(enum_name));
111+
112+
const internal::ClassConstantMap& enum_map = internal::ClassUtil::get_class_enum_constants(*p_class_info, enum_name);
113+
internal::ClassUtil::for_enum_internal_names(enum_info, [&](const StringName& internal_name) {
114+
const String& js_enum_name = internal::NamingUtil::get_enum_value_name(internal_name);
113115
jsb_not_implemented(js_enum_name.contains("."), "hierarchically nested definition is currently not supported");
114-
const auto& const_it = p_class_info->constant_map.find(enum_value_name);
115-
jsb_check(const_it);
116-
enumeration.Value(js_enum_name, const_it->value);
117-
enum_consts.insert(enum_value_name);
118-
}
119-
}
116+
enumeration.Value(js_enum_name, enum_map[internal_name]);
117+
enum_consts.insert(internal_name);
118+
});
119+
});
120120

121121
// class: constants
122-
for (const KeyValue<StringName, int64_t>& pair : p_class_info->constant_map)
122+
for (const KeyValue<StringName, int64_t>& pair : internal::ClassUtil::get_class_constant_map(*p_class_info))
123123
{
124124
if (enum_consts.has(pair.key)) continue;
125125
const String& js_const_name = (String) internal::NamingUtil::get_constant_name(pair.key);
@@ -138,7 +138,7 @@ namespace jsb
138138
// It's safe to expect that the base class is fully built,
139139
// because single inheritance is used in Godot (which means a reflect_bind class will only be accessed until it's fully built).
140140
class_builder.Inherit(super_class_info->clazz);
141-
JSB_LOG(VeryVerbose, "%s (%d) extends %s (%d)", p_class_info->name, class_id, p_class_info->inherits_ptr->name, super_class_id);
141+
JSB_LOG(VeryVerbose, "%s (%d) extends %s (%d)", internal_class_name, class_id, internal::ClassUtil::get_class_super_type_internal_name(*p_class_info), super_class_id);
142142
}
143143

144144
// preparation for return
@@ -147,8 +147,8 @@ namespace jsb
147147

148148
class_info->clazz = class_builder.Build();
149149
jsb_check(!class_info->clazz.IsEmpty());
150-
jsb_check(class_info->name == internal::NamingUtil::get_class_name(p_class_info->name));
151-
JSB_LOG(VeryVerbose, "build class info %s (%d) exposed as %s, addr: %s", p_class_info->name, class_id, class_info->name, class_info.ptr());
150+
jsb_check(class_info->name == internal::NamingUtil::get_class_name(internal_class_name));
151+
JSB_LOG(VeryVerbose, "build class info %s (%d) exposed as %s, addr: %s", internal_class_name, class_id, class_info->name, class_info.ptr());
152152
if (r_class_id) *r_class_id = class_id;
153153
return class_info;
154154
}

internal/jsb_class_util.h

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,27 @@
33

44
namespace jsb::internal
55
{
6+
7+
#if GODOT_4_6_OR_NEWER
8+
using ClassConstantMap = AHashMap<StringName, int64_t>;
9+
#else
10+
using ClassConstantMap = HashMap<StringName, int64_t>;
11+
#endif
12+
13+
#if GODOT_4_7_OR_NEWER
14+
using ClassEnumInfo = GDType::EnumInfo;
15+
#else
16+
using ClassEnumInfo = ClassDB::ClassInfo::EnumInfo;
17+
#endif
18+
19+
#if GODOT_4_7_OR_NEWER
20+
using ClassSignalMap = AHashMap<StringName, const MethodInfo*>;
21+
#elif GODOT_4_6_OR_NEWER
22+
using ClassSignalMap = AHashMap<StringName, MethodInfo>;
23+
#else
24+
using ClassSignalMap = HashMap<StringName, MethodInfo>;
25+
#endif
26+
627
struct ClassUtil
728
{
829
// jsb_force_inline static bool check_class(const StringName& p_class_name, const StringName& p_expected_class_name)
@@ -18,6 +39,121 @@ namespace jsb::internal
1839
// return get_method_info_recursively(*p_class_info.inherits_ptr, method_name);
1940
// }
2041

42+
template <typename T>
43+
static constexpr decltype(auto) get_value(T&& arg)
44+
{
45+
if constexpr (std::is_pointer_v<std::remove_reference_t<T>>)
46+
{
47+
return *arg;
48+
}
49+
else
50+
{
51+
return std::forward<T>(arg);
52+
}
53+
}
54+
55+
#if GODOT_4_7_OR_NEWER
56+
57+
static const StringName& get_internal_class_name(const ClassDB::ClassInfo& class_info)
58+
{
59+
return class_info.gdtype->get_name();
60+
}
61+
62+
template <typename Lambda>
63+
static void for_enum_internal_names(const ClassEnumInfo &enum_info, Lambda callback)
64+
{
65+
for (auto it = enum_info.values.begin(); it != enum_info.values.end(); ++it)
66+
{
67+
callback(it->key);
68+
}
69+
}
70+
71+
template <typename Lambda>
72+
static void for_class_enums(const ClassDB::ClassInfo& class_info, Lambda callback)
73+
{
74+
for (auto it : class_info.gdtype->get_enum_map(true))
75+
{
76+
callback(it.key, *it.value);
77+
}
78+
}
79+
80+
static const ClassConstantMap& get_class_constant_map(const ClassDB::ClassInfo& class_info)
81+
{
82+
return class_info.gdtype->get_integer_constant_map(true);
83+
}
84+
85+
static const AHashMap<StringName, const ClassEnumInfo*>& get_class_enum_map(const ClassDB::ClassInfo& class_info)
86+
{
87+
return class_info.gdtype->get_enum_map(true);
88+
}
89+
90+
static const ClassSignalMap& get_class_signal_map(const ClassDB::ClassInfo& class_info)
91+
{
92+
return class_info.gdtype->get_signal_map(true);
93+
}
94+
95+
static const ClassConstantMap& get_class_enum_constants(const ClassDB::ClassInfo& class_info, const StringName& enum_name)
96+
{
97+
return class_info.gdtype->get_enum_map(true)[enum_name]->values;
98+
}
99+
100+
static String get_class_super_type_internal_name(const ClassDB::ClassInfo& class_info)
101+
{
102+
return class_info.gdtype->get_super_type_name();
103+
}
104+
105+
#else
106+
107+
static constexpr const StringName& get_internal_class_name(const ClassDB::ClassInfo& class_info)
108+
{
109+
return class_info.name;
110+
}
111+
112+
template <typename Lambda>
113+
static void for_enum_internal_names(const ClassEnumInfo &enum_info, Lambda callback)
114+
{
115+
for (List<StringName>::ConstIterator it = enum_info.constants.begin(); it != enum_info.constants.end(); ++it)
116+
{
117+
callback(*it);
118+
}
119+
}
120+
121+
template <typename Lambda>
122+
static void for_class_enums(const ClassDB::ClassInfo& class_info, Lambda callback)
123+
{
124+
for (auto it : class_info.enum_map)
125+
{
126+
callback(it.key, it.value);
127+
}
128+
}
129+
130+
static const ClassConstantMap& get_class_constant_map(const ClassDB::ClassInfo& class_info)
131+
{
132+
return class_info.constant_map;
133+
}
134+
135+
static const HashMap<StringName, ClassEnumInfo>& get_class_enum_map(const ClassDB::ClassInfo& class_info)
136+
{
137+
return class_info.enum_map;
138+
}
139+
140+
static const ClassSignalMap& get_class_signal_map(const ClassDB::ClassInfo& class_info)
141+
{
142+
return class_info.signal_map;
143+
}
144+
145+
static const ClassConstantMap& get_class_enum_constants(const ClassDB::ClassInfo& class_info, const StringName& _enum_name)
146+
{
147+
return class_info.constant_map;
148+
}
149+
150+
static String get_class_super_type_internal_name(const ClassDB::ClassInfo& class_info)
151+
{
152+
return class_info.inherits;
153+
}
154+
155+
#endif
156+
21157
};
22158
}
23159
#endif

tests/test_jsb_any_runtime.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ console.assert(!gd.is_instance_valid(inst));
475475

476476
TEST_CASE("[jsb] RefCounted objects")
477477
{
478-
WeakRef* weak_ref = memnew(WeakRef);
478+
Ref<WeakRef> weak_ref = memnew(WeakRef);
479479
{
480480
GodotJSScriptLanguageIniter initer;
481481

@@ -506,7 +506,6 @@ file = undefined;
506506
}
507507
// There is no strong reference anymore, therefore the FileAccess object should have been deleted by JS GC.
508508
CHECK(weak_ref->get_ref().is_null());
509-
memdelete(weak_ref);
510509
}
511510
}
512511

weaver-editor/jsb_editor_helper.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,12 @@ Dictionary GodotJSEditorHelper::_build_node_type_descriptor(jsb::JSEnvironment&
159159

160160
if (animation_mixer)
161161
{
162+
#if GODOT_4_7_OR_NEWER
163+
LocalVector<StringName> library_names;
164+
#else
162165
List<StringName> library_names;
166+
#endif
167+
163168
animation_mixer->get_animation_library_list(&library_names);
164169

165170
Dictionary animation_libraries_object_literal;
@@ -173,7 +178,12 @@ Dictionary GodotJSEditorHelper::_build_node_type_descriptor(jsb::JSEnvironment&
173178

174179
Array animation_names_union_array;
175180

181+
#if GODOT_4_7_OR_NEWER
182+
LocalVector<StringName> animation_names;
183+
#else
176184
List<StringName> animation_names;
185+
#endif
186+
177187
library->get_animation_list(&animation_names);
178188

179189
for (const StringName& animation_name : animation_names)
@@ -316,7 +326,7 @@ Dictionary GodotJSEditorHelper::get_resource_type_descriptor(const String& p_pat
316326
return descriptor;
317327
}
318328

319-
PackedScene* scene = Object::cast_to<PackedScene>(resource.ptr());
329+
PackedScene* scene = Object::cast_to<PackedScene>(resource.ptr());
320330

321331
if (scene)
322332
{

weaver-editor/jsb_export_plugin.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class GodotJSExportPlugin: public EditorExportPlugin
1919
virtual String get_name() const override;
2020
virtual bool supports_platform(const Ref<EditorExportPlatform>& p_export_platform) const override;
2121

22-
static const HashSet<String> get_ignored_paths() { return ignored_paths_; }
22+
static const HashSet<String>& get_ignored_paths() { return ignored_paths_; }
2323

2424
protected:
2525
virtual void _export_begin(const HashSet<String>& p_features, bool p_debug, const String& p_path, int p_flags) override;

0 commit comments

Comments
 (0)