Skip to content

Commit 9618ea6

Browse files
committed
feat: Improved hot reloading
Improved hot reloading of scripts by notifying the editor of property changes. Improved "Global Class" loading by having the generator keep a list of global classes. Added a "hot reload" button specifically to assist in pushing global classes into the editor.
1 parent 2f6b9f7 commit 9618ea6

23 files changed

+225
-94
lines changed

src/assets/godot_dart.gdextension

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ compatibility_minimum = 4.2
55

66
[icons]
77

8-
DartScript = "res://logo_dart.svg"
8+
DartScript = "res://godot_dart/logo_dart.svg"
9+
DartHotReload = "res://godot_dart/hot_reload.svg"
910

1011
[libraries]
1112

File renamed without changes.

src/assets/src/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ environment:
88

99
dependencies:
1010
ffi: ^2.0.1
11-
godot_dart: ^0.3.0
11+
godot_dart: ^0.4.0
1212
collection: ^1.17.2
1313

1414
dev_dependencies:
1515
lints: ^2.0.0
1616
build_runner: ^2.3.3
17-
godot_dart_build: ^0.2.0
17+
godot_dart_build: ^0.3.0

src/cpp/CMakeLists.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ add_library(godot_dart SHARED
1919
dart_instance_binding.cpp
2020
dart_instance_binding.h
2121
dart_helpers.h
22-
dart_script_instance.cpp
23-
dart_script_instance.h
22+
"script/dart_script_instance.cpp"
23+
"script/dart_script_instance.h"
2424
gde_c_interface.cpp
2525
gde_c_interface.h
2626
gde_dart_converters.cpp
@@ -46,13 +46,14 @@ add_library(godot_dart SHARED
4646
script/dart_script.cpp
4747
script/dart_resource_format.h
4848
script/dart_resource_format.cpp
49-
)
49+
)
5050

5151
target_include_directories(godot_dart PUBLIC
5252
"${GODOT_CPP_DIR}/include"
5353
"${GODOT_CPP_DIR}/gen/include"
5454
"${GODOT_CPP_DIR}/gdextension"
5555
"${DART_DIR}/include"
56+
"${PROJECT_SOURCE_DIR}"
5657
)
5758

5859
set(DART_DLL_NAMES

src/cpp/dart_bindings.cpp

Lines changed: 9 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,17 @@
1010
#include <dart_tools_api.h>
1111

1212
#include <gdextension_interface.h>
13-
#include <godot_cpp/variant/string.hpp>
14-
#include <godot_cpp/variant/string_name.hpp>
1513
#include <godot_cpp/classes/editor_file_system.hpp>
1614
#include <godot_cpp/classes/editor_interface.hpp>
17-
15+
#include <godot_cpp/variant/string.hpp>
16+
#include <godot_cpp/variant/string_name.hpp>
1817

1918
#include "dart_helpers.h"
2019
#include "dart_instance_binding.h"
21-
#include "dart_script_instance.h"
2220
#include "gde_dart_converters.h"
2321
#include "gde_wrapper.h"
2422
#include "ref_counted_wrapper.h"
23+
#include "script/dart_script_instance.h"
2524
#include "script/dart_script_language.h"
2625

2726
// Forward declarations for Dart callbacks and helpers
@@ -143,8 +142,8 @@ bool GodotDartBindings::initialize(const char *script_path, const char *package_
143142
Dart_Handle print = Dart_Invoke(godot_dart_library, Dart_NewStringFromCString("_getPrintClosure"), 0, NULL);
144143
Dart_Handle result = Dart_SetField(internal_lib, Dart_NewStringFromCString("_printClosure"), print);
145144
if (Dart_IsError(result)) {
146-
GD_PRINT_WARNING("GodotDart: Error setting print closure");
147-
GD_PRINT_WARNING(Dart_GetError(result));
145+
GD_PRINT_ERROR("GodotDart: Error setting print closure");
146+
GD_PRINT_ERROR(Dart_GetError(result));
148147
}
149148
}
150149

@@ -175,21 +174,6 @@ bool GodotDartBindings::initialize(const char *script_path, const char *package_
175174
return true;
176175
}
177176

178-
void GodotDartBindings::add_pending_reload(const godot::String &path) {
179-
_pending_reloads.insert(path);
180-
reload_code();
181-
}
182-
183-
void GodotDartBindings::perform_pending_reloads() {
184-
for (const auto &str : _pending_reloads) {
185-
auto editor_interface = godot::EditorInterface::get_singleton();
186-
if (editor_interface) {
187-
editor_interface->get_resource_filesystem()->update_file(str);
188-
}
189-
}
190-
_pending_reloads.clear();
191-
}
192-
193177
void GodotDartBindings::reload_code() {
194178
if (_is_reloading) {
195179
return;
@@ -283,10 +267,11 @@ void GodotDartBindings::perform_frame_maintanance() {
283267
// If we're reloading, check to see if we're done.
284268
if (_is_reloading) {
285269
Dart_Handle root_library = Dart_HandleFromPersistent(_godot_dart_library);
286-
DART_CHECK(dart_is_reloading, Dart_GetField(root_library, Dart_NewStringFromCString("_isReloading")), "Failed to get _isReloading");
270+
DART_CHECK(dart_is_reloading, Dart_GetField(root_library, Dart_NewStringFromCString("_isReloading")),
271+
"Failed to get _isReloading");
287272
Dart_BooleanValue(dart_is_reloading, &_is_reloading);
288273
if (!_is_reloading) {
289-
perform_pending_reloads();
274+
DartScriptLanguage::instance()->did_finish_hot_reload();
290275
}
291276
}
292277

@@ -318,28 +303,6 @@ void GodotDartBindings::perform_pending_ref_changes() {
318303
_pending_ref_changes.clear();
319304
}
320305

321-
void *GodotDartBindings::create_script_instance(Dart_Handle type, const DartScript *script, void *godot_object,
322-
bool is_placeholder, bool is_refcounted) {
323-
GDExtensionScriptInstancePtr godot_script_instance = nullptr;
324-
325-
execute_on_dart_thread([&] {
326-
DartBlockScope scope;
327-
328-
Dart_Handle dart_pointer = new_dart_void_pointer(godot_object);
329-
Dart_Handle args[1] = {dart_pointer};
330-
DART_CHECK_RET(dart_object, Dart_New(type, Dart_NewStringFromCString("withNonNullOwner"), 1, args), nullptr,
331-
"Error creating bindings");
332-
333-
DartScriptInstance *script_instance = new DartScriptInstance(dart_object, const_cast<DartScript *>(script),
334-
godot_object, is_placeholder, is_refcounted);
335-
godot_script_instance =
336-
gde_script_instance_create2(DartScriptInstance::get_script_instance_info(),
337-
reinterpret_cast<GDExtensionScriptInstanceDataPtr>(script_instance));
338-
});
339-
340-
return godot_script_instance;
341-
}
342-
343306
void GodotDartBindings::bind_method(const TypeInfo &bind_type, const char *method_name, const TypeInfo &ret_type_info,
344307
Dart_Handle args_list, MethodFlags method_flags) {
345308
MethodInfo *info = new MethodInfo();
@@ -700,8 +663,7 @@ void dart_print(Dart_NativeArguments args) {
700663
Dart_Handle arg = Dart_GetNativeArgument(args, 1);
701664
DART_CHECK(result, Dart_StringToCString(arg, &cstring), "Error getting printable string.");
702665

703-
// TODO - Find a nice way to log
704-
GD_PRINT_WARNING(cstring);
666+
__print_verbose(cstring);
705667
}
706668

707669
void bind_class(Dart_NativeArguments args) {

src/cpp/dart_bindings.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,20 @@
99

1010
#include <dart_api.h>
1111
#include <gdextension_interface.h>
12+
#include <godot_cpp/classes/ref.hpp>
1213
#include <godot_cpp/variant/string.hpp>
14+
#include <godot_cpp/classes/wrapped.hpp>
1315

1416
#include "dart_instance_binding.h"
1517
#include "gde_dart_converters.h"
18+
#include "script/dart_script.h"
1619

1720
enum class MethodFlags : int32_t {
1821
None,
1922
PropertyGetter,
2023
PropertySetter,
2124
};
2225

23-
class DartScript;
24-
2526
class GodotDartBindings {
2627
public:
2728
static GodotDartBindings *instance() {
@@ -38,8 +39,7 @@ class GodotDartBindings {
3839
return _fully_initialized;
3940
}
4041
void shutdown();
41-
42-
void add_pending_reload(const godot::String& path);
42+
4343
void reload_code();
4444

4545
void bind_method(const TypeInfo &bind_type, const char *method_name, const TypeInfo &ret_type_info,
@@ -53,17 +53,14 @@ class GodotDartBindings {
5353
void remove_pending_ref_change(DartGodotInstanceBinding *bindings);
5454
void perform_pending_ref_changes();
5555

56-
void *create_script_instance(Dart_Handle type, const DartScript *script, void *godot_object, bool is_placeholder,
57-
bool is_refcounted);
58-
5956
static GDExtensionObjectPtr class_create_instance(void *p_userdata);
6057
static void class_free_instance(void *p_userdata, GDExtensionClassInstancePtr p_instance);
6158
static void *get_virtual_call_data(void *p_userdata, GDExtensionConstStringNamePtr p_name);
6259
static void call_virtual_func(void *p_instance, GDExtensionConstStringNamePtr p_name, void *p_userdata,
6360
const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
6461

6562
private:
66-
void perform_pending_reloads();
63+
void did_finish_hot_reload();
6764

6865
static void bind_call(void *method_userdata, GDExtensionClassInstancePtr instance,
6966
const GDExtensionConstVariantPtr *args, GDExtensionInt argument_count,
@@ -74,14 +71,14 @@ class GodotDartBindings {
7471
static GodotDartBindings *_instance;
7572

7673
public:
77-
bool _fully_initialized;
74+
bool _fully_initialized;
7875
bool _is_stopping;
7976
bool _is_reloading;
8077
int32_t _pending_messages;
8178
std::mutex _work_lock;
8279
Dart_Isolate _isolate;
8380
std::thread::id _isolate_current_thread;
84-
std::set<godot::String> _pending_reloads;
81+
std::set<godot::Ref<DartScript>> _pending_reloads;
8582
std::set<DartGodotInstanceBinding *> _pending_ref_changes;
8683

8784
Dart_PersistentHandle _godot_dart_library;

src/cpp/dart_helpers.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,31 @@
33
#include <dart_api.h>
44

55
#include "gde_c_interface.h"
6+
#include <godot_cpp/classes/os.hpp>
7+
#include <godot_cpp/variant/utility_functions.hpp>
8+
9+
inline bool is_print_verbose_enabled() {
10+
auto os_singleton = godot::OS::get_singleton();
11+
if (os_singleton && os_singleton->is_stdout_verbose()) return true;
12+
return false;
13+
}
14+
15+
inline void __print_verbose(const char *msg) {
16+
if (is_print_verbose_enabled()) {
17+
godot::String godot_msg(msg);
18+
godot::UtilityFunctions::print(msg);
19+
}
20+
}
621

722
#define GD_PRINT_ERROR(msg) \
823
{ gde_print_error(msg, __func__, __FILE__, __LINE__, true); }
924

1025
#define GD_PRINT_WARNING(msg) \
1126
{ gde_print_warning(msg, __func__, __FILE__, __LINE__, true); }
1227

28+
#define GD_PRINT_VERBOSE(msg) \
29+
{ __print_verbose(msg); }
30+
1331
#define DART_CHECK_RET(var, expr, ret, message) \
1432
Dart_Handle var = (expr); \
1533
if (Dart_IsError(var)) { \

src/cpp/editor/godot_dart_editor_plugin.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
#include <sstream>
44

5+
#include <godot_cpp/classes/button.hpp>
56
#include <godot_cpp/classes/confirmation_dialog.hpp>
67
#include <godot_cpp/classes/dir_access.hpp>
8+
#include <godot_cpp/classes/editor_interface.hpp>
79
#include <godot_cpp/classes/file_access.hpp>
810
#include <godot_cpp/classes/os.hpp>
911
#include <godot_cpp/classes/popup.hpp>
1012
#include <godot_cpp/classes/thread.hpp>
13+
#include <godot_cpp/classes/theme.hpp>
1114
#include <godot_cpp/core/class_db.hpp>
1215

1316
#include "../dart_helpers.h"
@@ -18,7 +21,7 @@
1821

1922
using namespace godot;
2023

21-
GodotDartEditorPlugin::GodotDartEditorPlugin() {
24+
GodotDartEditorPlugin::GodotDartEditorPlugin() : _reload_button(nullptr) {
2225
_progress_dialog = memnew(DartProgressDialog);
2326
add_child(_progress_dialog);
2427
}
@@ -27,16 +30,16 @@ GodotDartEditorPlugin::~GodotDartEditorPlugin() {
2730
}
2831

2932
void GodotDartEditorPlugin::_bind_methods() {
30-
3133
ClassDB::bind_method(godot::D_METHOD("confirm_create_project"), &GodotDartEditorPlugin::confirm_create_project);
3234
ClassDB::bind_method(godot::D_METHOD("confirm_pub_get"), &GodotDartEditorPlugin::confirm_pub_get);
3335
ClassDB::bind_method(godot::D_METHOD("run_work"), &GodotDartEditorPlugin::run_work);
36+
ClassDB::bind_method(godot::D_METHOD("dart_hot_reload"), &GodotDartEditorPlugin::hot_reload);
3437
}
3538

3639
void GodotDartEditorPlugin::_enter_tree() {
3740
GodotDartRuntimePlugin *runtime_plugin = GodotDartRuntimePlugin::get_instance();
3841
if (!runtime_plugin) {
39-
GD_PRINT_ERROR("godot_dart was loaded bug didn't initialize!")
42+
GD_PRINT_ERROR("godot_dart was loaded but didn't initialize!")
4043
return;
4144
}
4245

@@ -45,9 +48,27 @@ void GodotDartEditorPlugin::_enter_tree() {
4548
} else if (!runtime_plugin->has_package_config()) {
4649
show_pub_get_dialog();
4750
}
51+
52+
_reload_button = memnew(Button);
53+
_reload_button->set_flat(false);
54+
auto icon =
55+
EditorInterface::get_singleton()->get_editor_theme()->get_icon(StringName("Reload"), StringName("EditorIcons"));
56+
_reload_button->set_button_icon(icon);
57+
_reload_button->set_focus_mode(Control::FOCUS_NONE);
58+
_reload_button->set_theme_type_variation(StringName("RunBarButton"));
59+
_reload_button->set_tooltip_text(String("Perform a Dart Hot Reload"));
60+
61+
62+
_reload_button->connect(StringName("pressed"), Callable(this, StringName("dart_hot_reload")));
63+
add_control_to_container(EditorPlugin::CONTAINER_TOOLBAR, _reload_button);
64+
auto parent = _reload_button->get_parent();
65+
int num_buttons = parent->get_child_count();
66+
// Move over next to run buttons
67+
_reload_button->get_parent()->move_child(_reload_button, num_buttons - 2);
4868
}
4969

5070
void GodotDartEditorPlugin::_exit_tree() {
71+
5172
}
5273

5374
void GodotDartEditorPlugin::show_create_project_dialog() {
@@ -213,6 +234,10 @@ bool GodotDartEditorPlugin::run_pub_get() {
213234
return true;
214235
}
215236

237+
void GodotDartEditorPlugin::hot_reload() {
238+
GodotDartBindings::instance()->reload_code();
239+
}
240+
216241
bool GodotDartEditorPlugin::run_build_runner() {
217242
GodotDartRuntimePlugin *rtplugin = GodotDartRuntimePlugin::get_instance();
218243

src/cpp/editor/godot_dart_editor_plugin.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,13 @@ class GodotDartEditorPlugin : public godot::EditorPlugin {
3939
void show_pub_get_dialog();
4040
void confirm_pub_get();
4141

42-
// Reload dialog
43-
void show_reload_dialog();
44-
void confirm_reload();
42+
void hot_reload();
4543

4644
void run_work();
4745

4846
std::vector<WorkStep> _work_steps;
4947

5048
DartProgressDialog *_progress_dialog;
5149
godot::Ref<godot::Thread> _plugin_work_thread;
50+
godot::Button* _reload_button;
5251
};

src/cpp/godot_dart.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
#include "godot_dart_runtime_plugin.h"
1111

1212
#include "dart_instance_binding.h"
13-
#include "dart_script_instance.h"
1413
#include "ref_counted_wrapper.h"
14+
#include "script/dart_script_instance.h"
1515

1616
#include "editor/godot_dart_editor_plugin.h"
1717
#include "editor/dart_progress_dialog.h"

src/cpp/godot_dart_runtime_plugin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
#include <godot_cpp/classes/object.hpp>
1111

1212
#include "dart_helpers.h"
13-
#include "dart_script_instance.h"
1413
#include "gde_wrapper.h"
1514
#include "godot_string_wrappers.h"
1615
#include "ref_counted_wrapper.h"
1716

17+
#include "script/dart_script_instance.h"
1818
#include "script/dart_script_language.h"
1919
#include "script/dart_resource_format.h"
2020

0 commit comments

Comments
 (0)