wasm test
This commit is contained in:
@@ -58,3 +58,4 @@ tools/binding_generator/binding_statistics_report.md
|
|||||||
|
|
||||||
.cache
|
.cache
|
||||||
project/leanclr/live_reload.txt
|
project/leanclr/live_reload.txt
|
||||||
|
project/deploy/
|
||||||
+6
-1
@@ -110,11 +110,16 @@ else()
|
|||||||
-Wl,-dead_strip
|
-Wl,-dead_strip
|
||||||
-Wl,-exported_symbols_list,${LEANCLR_GODOT_EXPORTED_SYMBOLS}
|
-Wl,-exported_symbols_list,${LEANCLR_GODOT_EXPORTED_SYMBOLS}
|
||||||
)
|
)
|
||||||
elseif(UNIX)
|
elseif(UNIX AND NOT EMSCRIPTEN)
|
||||||
target_link_options(leanclr_godot PRIVATE -Wl,--gc-sections)
|
target_link_options(leanclr_godot PRIVATE -Wl,--gc-sections)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
target_link_options(leanclr_godot PRIVATE -sSIDE_MODULE=1)
|
||||||
|
set_target_properties(leanclr_godot PROPERTIES SUFFIX ".wasm")
|
||||||
|
endif()
|
||||||
|
|
||||||
set_target_properties(leanclr_godot PROPERTIES
|
set_target_properties(leanclr_godot PROPERTIES
|
||||||
CXX_VISIBILITY_PRESET hidden
|
CXX_VISIBILITY_PRESET hidden
|
||||||
VISIBILITY_INLINES_HIDDEN YES
|
VISIBILITY_INLINES_HIDDEN YES
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
[preset.0]
|
||||||
|
|
||||||
|
name="Web"
|
||||||
|
platform="Web"
|
||||||
|
runnable=true
|
||||||
|
dedicated_server=false
|
||||||
|
custom_features=""
|
||||||
|
export_filter="all_resources"
|
||||||
|
include_filter="leanclr/*.dll,leanclr/live_reload.txt"
|
||||||
|
exclude_filter=""
|
||||||
|
export_path="deploy/html/index.html"
|
||||||
|
patches=PackedStringArray()
|
||||||
|
patch_delta_encoding=false
|
||||||
|
patch_delta_compression_level_zstd=19
|
||||||
|
patch_delta_min_reduction=0.1
|
||||||
|
patch_delta_include_filters="*"
|
||||||
|
patch_delta_exclude_filters=""
|
||||||
|
encryption_include_filters=""
|
||||||
|
encryption_exclude_filters=""
|
||||||
|
seed=0
|
||||||
|
encrypt_pck=false
|
||||||
|
encrypt_directory=false
|
||||||
|
script_export_mode=2
|
||||||
|
|
||||||
|
[preset.0.options]
|
||||||
|
|
||||||
|
custom_template/debug="/Volumes/External/Misc/templates_4.6/web_dlink_nothreads_debug.zip"
|
||||||
|
custom_template/release="/Volumes/External/Misc/templates_4.6/web_dlink_nothreads_release.zip"
|
||||||
|
variant/extensions_support=true
|
||||||
|
variant/thread_support=false
|
||||||
|
vram_texture_compression/for_desktop=true
|
||||||
|
vram_texture_compression/for_mobile=false
|
||||||
|
html/export_icon=true
|
||||||
|
html/custom_html_shell=""
|
||||||
|
html/head_include=""
|
||||||
|
html/canvas_resize_policy=2
|
||||||
|
html/focus_canvas_on_start=true
|
||||||
|
html/experimental_virtual_keyboard=false
|
||||||
|
progressive_web_app/enabled=false
|
||||||
|
progressive_web_app/ensure_cross_origin_isolation_headers=true
|
||||||
|
progressive_web_app/offline_page=""
|
||||||
|
progressive_web_app/display=1
|
||||||
|
progressive_web_app/orientation=0
|
||||||
|
progressive_web_app/icon_144x144=""
|
||||||
|
progressive_web_app/icon_180x180=""
|
||||||
|
progressive_web_app/icon_512x512=""
|
||||||
|
progressive_web_app/background_color=Color(0, 0, 0, 1)
|
||||||
|
threads/emscripten_pool_size=8
|
||||||
|
threads/godot_pool_size=4
|
||||||
|
dotnet/include_scripts_content=false
|
||||||
|
dotnet/include_debug_symbols=true
|
||||||
|
dotnet/embed_build_outputs=false
|
||||||
@@ -12,3 +12,4 @@ linux.debug.x86_64 = "res://bin/Debug/libleanclr_godot.so"
|
|||||||
linux.release.x86_64 = "res://bin/Release/libleanclr_godot.so"
|
linux.release.x86_64 = "res://bin/Release/libleanclr_godot.so"
|
||||||
macos.debug = "res://bin/Debug/libleanclr_godot.dylib"
|
macos.debug = "res://bin/Debug/libleanclr_godot.dylib"
|
||||||
macos.release = "res://bin/Release/libleanclr_godot.dylib"
|
macos.release = "res://bin/Release/libleanclr_godot.dylib"
|
||||||
|
web.release.wasm32 = "res://bin/Release/libleanclr_godot.wasm"
|
||||||
|
|||||||
@@ -74,5 +74,8 @@ Name = &"FlappyScript"
|
|||||||
|
|
||||||
[node name="HotReloadInputRelay" type="Node" parent="." unique_id=394620894]
|
[node name="HotReloadInputRelay" type="Node" parent="." unique_id=394620894]
|
||||||
script = ExtResource("4_input_relay")
|
script = ExtResource("4_input_relay")
|
||||||
|
attached_assembly_name = "Game"
|
||||||
|
reload_type_name = "Game.HotReloadSmoke"
|
||||||
|
script_owner_path = NodePath("../FlappyScript")
|
||||||
|
|
||||||
[node name="RuntimeCSharpEditor" parent="." unique_id=56462960 instance=ExtResource("3_editor_scene")]
|
[node name="RuntimeCSharpEditor" parent="." unique_id=56462960 instance=ExtResource("3_editor_scene")]
|
||||||
|
|||||||
@@ -1,10 +1,46 @@
|
|||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
|
@export var marker_path := "res://leanclr/live_reload.txt"
|
||||||
|
@export var attached_assembly_name := ""
|
||||||
|
@export var reload_type_name := ""
|
||||||
|
@export var script_owner_path: NodePath
|
||||||
|
@export var reload_poll_seconds := 0.25
|
||||||
|
|
||||||
@onready var hot_reload_host: Node = get_node("../LiveHotReloadHost")
|
@onready var hot_reload_host: Node = get_node("../LiveHotReloadHost")
|
||||||
|
|
||||||
|
var _elapsed := 0.0
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
if hot_reload_host != null:
|
||||||
|
hot_reload_host.set_script_owner_path(script_owner_path)
|
||||||
|
reload_from_marker()
|
||||||
|
set_process(reload_poll_seconds > 0.0)
|
||||||
set_process_input(true)
|
set_process_input(true)
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
_elapsed += delta
|
||||||
|
if _elapsed >= reload_poll_seconds:
|
||||||
|
_elapsed = 0.0
|
||||||
|
reload_from_marker()
|
||||||
|
|
||||||
func _input(event: InputEvent) -> void:
|
func _input(event: InputEvent) -> void:
|
||||||
if hot_reload_host != null:
|
if hot_reload_host != null:
|
||||||
hot_reload_host.forward_input(event)
|
hot_reload_host.forward_input(event)
|
||||||
|
|
||||||
|
func reload_from_marker() -> void:
|
||||||
|
if hot_reload_host == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
var assembly_name := attached_assembly_name
|
||||||
|
if marker_path != "" and FileAccess.file_exists(marker_path):
|
||||||
|
assembly_name = FileAccess.get_file_as_string(marker_path).strip_edges()
|
||||||
|
if assembly_name == "":
|
||||||
|
assembly_name = attached_assembly_name
|
||||||
|
|
||||||
|
if assembly_name == "" or assembly_name == hot_reload_host.get_loaded_assembly_name():
|
||||||
|
return
|
||||||
|
|
||||||
|
if assembly_name == attached_assembly_name:
|
||||||
|
hot_reload_host.use_attached_script(assembly_name)
|
||||||
|
else:
|
||||||
|
hot_reload_host.reload_assembly(assembly_name, reload_type_name)
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ func _ready() -> void:
|
|||||||
run_button.pressed.connect(compile_and_reload)
|
run_button.pressed.connect(compile_and_reload)
|
||||||
show()
|
show()
|
||||||
|
|
||||||
|
if OS.has_feature("web"):
|
||||||
|
run_button.disabled = true
|
||||||
|
_set_status("Web export is read-only; runtime build is desktop only.")
|
||||||
|
return
|
||||||
|
|
||||||
if OS.has_environment(AUTORUN_ENVIRONMENT) and not autorun_started:
|
if OS.has_environment(AUTORUN_ENVIRONMENT) and not autorun_started:
|
||||||
autorun_started = true
|
autorun_started = true
|
||||||
var code := editor.text
|
var code := editor.text
|
||||||
@@ -69,6 +74,9 @@ func compile_and_reload() -> void:
|
|||||||
if editor == null:
|
if editor == null:
|
||||||
_set_status("Editor is not ready.")
|
_set_status("Editor is not ready.")
|
||||||
return
|
return
|
||||||
|
if OS.has_feature("web"):
|
||||||
|
_set_status("Web export is read-only; runtime build is desktop only.")
|
||||||
|
return
|
||||||
|
|
||||||
if not _write_text_file(EDIT_SOURCE_PATH, editor.text):
|
if not _write_text_file(EDIT_SOURCE_PATH, editor.text):
|
||||||
_set_status("Failed to write HotReloadSmoke.cs")
|
_set_status("Failed to write HotReloadSmoke.cs")
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "leanclr_runtime_bridge.h"
|
#include "leanclr_runtime_bridge.h"
|
||||||
|
|
||||||
#include <godot_cpp/classes/engine.hpp>
|
#include <godot_cpp/classes/engine.hpp>
|
||||||
#include <godot_cpp/classes/file_access.hpp>
|
|
||||||
#include <godot_cpp/classes/input_event.hpp>
|
#include <godot_cpp/classes/input_event.hpp>
|
||||||
#include <godot_cpp/classes/os.hpp>
|
#include <godot_cpp/classes/os.hpp>
|
||||||
#include <godot_cpp/classes/scene_tree.hpp>
|
#include <godot_cpp/classes/scene_tree.hpp>
|
||||||
@@ -17,9 +16,6 @@ namespace godot
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const char* RELOAD_MARKER_PATH = "res://leanclr/live_reload.txt";
|
|
||||||
const char* RELOAD_TYPE_NAME = "Game.HotReloadSmoke";
|
|
||||||
|
|
||||||
bool is_editor_scene_context()
|
bool is_editor_scene_context()
|
||||||
{
|
{
|
||||||
Engine* engine = Engine::get_singleton();
|
Engine* engine = Engine::get_singleton();
|
||||||
@@ -43,6 +39,13 @@ bool is_editor_scene_context()
|
|||||||
void LeanCLRHotReloadHost::_bind_methods()
|
void LeanCLRHotReloadHost::_bind_methods()
|
||||||
{
|
{
|
||||||
ClassDB::bind_method(D_METHOD("forward_input", "event"), &LeanCLRHotReloadHost::forward_input);
|
ClassDB::bind_method(D_METHOD("forward_input", "event"), &LeanCLRHotReloadHost::forward_input);
|
||||||
|
ClassDB::bind_method(D_METHOD("use_attached_script", "assembly_name"), &LeanCLRHotReloadHost::use_attached_script);
|
||||||
|
ClassDB::bind_method(D_METHOD("reload_assembly", "assembly_name", "type_name"), &LeanCLRHotReloadHost::reload_assembly);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_script_owner_path", "script_owner_path"), &LeanCLRHotReloadHost::set_script_owner_path);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_script_owner_path"), &LeanCLRHotReloadHost::get_script_owner_path);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_loaded_assembly_name"), &LeanCLRHotReloadHost::get_loaded_assembly_name);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "script_owner_path"), "set_script_owner_path", "get_script_owner_path");
|
||||||
}
|
}
|
||||||
|
|
||||||
LeanCLRHotReloadHost::~LeanCLRHotReloadHost()
|
LeanCLRHotReloadHost::~LeanCLRHotReloadHost()
|
||||||
@@ -55,18 +58,17 @@ void LeanCLRHotReloadHost::_notification(int p_what)
|
|||||||
{
|
{
|
||||||
if (p_what == NOTIFICATION_READY)
|
if (p_what == NOTIFICATION_READY)
|
||||||
{
|
{
|
||||||
if (is_editor_scene_context() || !is_inside_tree() || (get_tree() != nullptr && get_tree()->get_edited_scene_root() != nullptr))
|
if (should_skip_runtime())
|
||||||
{
|
{
|
||||||
set_process(false);
|
set_process(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_process(true);
|
set_process(true);
|
||||||
check_reload_marker();
|
|
||||||
}
|
}
|
||||||
else if (p_what == NOTIFICATION_PROCESS)
|
else if (p_what == NOTIFICATION_PROCESS)
|
||||||
{
|
{
|
||||||
if (is_editor_scene_context() || !is_inside_tree() || (get_tree() != nullptr && get_tree()->get_edited_scene_root() != nullptr))
|
if (should_skip_runtime())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -76,80 +78,96 @@ void LeanCLRHotReloadHost::_notification(int p_what)
|
|||||||
{
|
{
|
||||||
LeanCLRRuntimeBridge::invoke_script_process(managed_object, delta);
|
LeanCLRRuntimeBridge::invoke_script_process(managed_object, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed += delta;
|
|
||||||
if (elapsed >= 0.25)
|
|
||||||
{
|
|
||||||
elapsed = 0.0;
|
|
||||||
check_reload_marker();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeanCLRHotReloadHost::forward_input(const Ref<InputEvent>& p_event)
|
void LeanCLRHotReloadHost::forward_input(const Ref<InputEvent>& p_event)
|
||||||
{
|
{
|
||||||
if (managed_object == nullptr || !p_event.is_valid() || is_editor_scene_context() || !is_inside_tree() ||
|
if (!p_event.is_valid() || should_skip_runtime())
|
||||||
(get_tree() != nullptr && get_tree()->get_edited_scene_root() != nullptr))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LeanCLRRuntimeBridge::invoke_script_method(managed_object, "_Input", p_event.ptr());
|
void* target_object = get_active_script_object();
|
||||||
|
if (target_object != nullptr)
|
||||||
|
{
|
||||||
|
LeanCLRRuntimeBridge::invoke_script_method(target_object, "_Input", p_event.ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeanCLRHotReloadHost::check_reload_marker()
|
void LeanCLRHotReloadHost::use_attached_script(const String& p_assembly_name)
|
||||||
{
|
{
|
||||||
String assembly_name = "Game";
|
LeanCLRRuntimeBridge::release_script_object(managed_object);
|
||||||
if (FileAccess::file_exists(RELOAD_MARKER_PATH))
|
managed_object = nullptr;
|
||||||
|
loaded_assembly_name = p_assembly_name;
|
||||||
|
UtilityFunctions::print("LeanCLR live reload: using attached script assembly = ", loaded_assembly_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeanCLRHotReloadHost::set_script_owner_path(const NodePath& p_script_owner_path)
|
||||||
|
{
|
||||||
|
script_owner_path = p_script_owner_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodePath LeanCLRHotReloadHost::get_script_owner_path() const
|
||||||
|
{
|
||||||
|
return script_owner_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
String LeanCLRHotReloadHost::get_loaded_assembly_name() const
|
||||||
|
{
|
||||||
|
return loaded_assembly_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LeanCLRHotReloadHost::should_skip_runtime() const
|
||||||
|
{
|
||||||
|
return is_editor_scene_context() || !is_inside_tree() || (get_tree() != nullptr && get_tree()->get_edited_scene_root() != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object* LeanCLRHotReloadHost::get_script_owner() const
|
||||||
|
{
|
||||||
|
if (!script_owner_path.is_empty())
|
||||||
{
|
{
|
||||||
assembly_name = FileAccess::get_file_as_string(RELOAD_MARKER_PATH).strip_edges();
|
Node* owner = get_node_or_null(script_owner_path);
|
||||||
if (assembly_name.is_empty())
|
if (owner != nullptr)
|
||||||
{
|
{
|
||||||
assembly_name = "Game";
|
return owner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assembly_name == loaded_assembly_name)
|
return const_cast<LeanCLRHotReloadHost*>(this);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
reload_managed_object(assembly_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeanCLRHotReloadHost::reload_managed_object(const String& p_assembly_name)
|
void* LeanCLRHotReloadHost::get_attached_script_object() const
|
||||||
{
|
{
|
||||||
if (p_assembly_name == String("Game"))
|
Object* owner = get_script_owner();
|
||||||
|
return owner != nullptr ? LeanCLRRuntimeBridge::get_script_object_for_owner(owner) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* LeanCLRHotReloadHost::get_active_script_object() const
|
||||||
|
{
|
||||||
|
return managed_object != nullptr ? managed_object : get_attached_script_object();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LeanCLRHotReloadHost::reload_assembly(const String& p_assembly_name, const String& p_type_name)
|
||||||
|
{
|
||||||
|
if (p_assembly_name.is_empty() || p_type_name.is_empty())
|
||||||
{
|
{
|
||||||
LeanCLRRuntimeBridge::release_script_object(managed_object);
|
UtilityFunctions::printerr("LeanCLR live reload: assembly_name and type_name are required.");
|
||||||
managed_object = nullptr;
|
return false;
|
||||||
loaded_assembly_name = p_assembly_name;
|
|
||||||
UtilityFunctions::print("LeanCLR live reload: using attached script assembly = ", loaded_assembly_name);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object* owner = this;
|
Object* owner = get_script_owner();
|
||||||
Node* parent = get_parent();
|
void* previous_object = get_active_script_object();
|
||||||
if (parent != nullptr)
|
|
||||||
{
|
|
||||||
Node* script_owner = parent->get_node_or_null(NodePath("FlappyScript"));
|
|
||||||
if (script_owner != nullptr)
|
|
||||||
{
|
|
||||||
owner = script_owner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void* previous_object = managed_object != nullptr ? managed_object : LeanCLRRuntimeBridge::get_script_object_for_owner(owner);
|
|
||||||
Variant custom_state;
|
Variant custom_state;
|
||||||
const bool has_custom_state = previous_object != nullptr &&
|
const bool has_custom_state = previous_object != nullptr &&
|
||||||
LeanCLRRuntimeBridge::has_script_method(previous_object, "CaptureHotReloadState", 0) &&
|
LeanCLRRuntimeBridge::has_script_method(previous_object, "CaptureHotReloadState", 0) &&
|
||||||
LeanCLRRuntimeBridge::invoke_script_method(previous_object, "CaptureHotReloadState", nullptr, 0, &custom_state);
|
LeanCLRRuntimeBridge::invoke_script_method(previous_object, "CaptureHotReloadState", nullptr, 0, &custom_state);
|
||||||
|
|
||||||
void* next_object = LeanCLRRuntimeBridge::create_script_object(p_assembly_name, RELOAD_TYPE_NAME, owner);
|
void* next_object = LeanCLRRuntimeBridge::create_script_object(p_assembly_name, p_type_name, owner);
|
||||||
if (next_object == nullptr)
|
if (next_object == nullptr)
|
||||||
{
|
{
|
||||||
UtilityFunctions::printerr("LeanCLR live reload: failed to load ", p_assembly_name, ": ", LeanCLRRuntimeBridge::get_last_error());
|
UtilityFunctions::printerr("LeanCLR live reload: failed to load ", p_assembly_name, ": ", LeanCLRRuntimeBridge::get_last_error());
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t migrated_fields = LeanCLRRuntimeBridge::migrate_script_state(previous_object, next_object);
|
const int32_t migrated_fields = LeanCLRRuntimeBridge::migrate_script_state(previous_object, next_object);
|
||||||
@@ -169,6 +187,7 @@ void LeanCLRHotReloadHost::reload_managed_object(const String& p_assembly_name)
|
|||||||
UtilityFunctions::print("LeanCLR live reload: migrated fields = ", migrated_fields);
|
UtilityFunctions::print("LeanCLR live reload: migrated fields = ", migrated_fields);
|
||||||
LeanCLRRuntimeBridge::invoke_script_ready(managed_object);
|
LeanCLRRuntimeBridge::invoke_script_ready(managed_object);
|
||||||
LeanCLRRuntimeBridge::invoke_script_method(managed_object, "OnHotReloaded");
|
LeanCLRRuntimeBridge::invoke_script_method(managed_object, "OnHotReloaded");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <godot_cpp/classes/node.hpp>
|
#include <godot_cpp/classes/node.hpp>
|
||||||
#include <godot_cpp/classes/input_event.hpp>
|
#include <godot_cpp/classes/input_event.hpp>
|
||||||
|
#include <godot_cpp/variant/node_path.hpp>
|
||||||
#include <godot_cpp/variant/string.hpp>
|
#include <godot_cpp/variant/string.hpp>
|
||||||
|
|
||||||
namespace godot
|
namespace godot
|
||||||
@@ -14,18 +15,26 @@ class LeanCLRHotReloadHost : public Node
|
|||||||
public:
|
public:
|
||||||
~LeanCLRHotReloadHost();
|
~LeanCLRHotReloadHost();
|
||||||
void forward_input(const Ref<InputEvent>& p_event);
|
void forward_input(const Ref<InputEvent>& p_event);
|
||||||
|
void use_attached_script(const String& p_assembly_name);
|
||||||
|
bool reload_assembly(const String& p_assembly_name, const String& p_type_name);
|
||||||
|
|
||||||
|
void set_script_owner_path(const NodePath& p_script_owner_path);
|
||||||
|
NodePath get_script_owner_path() const;
|
||||||
|
String get_loaded_assembly_name() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void check_reload_marker();
|
bool should_skip_runtime() const;
|
||||||
void reload_managed_object(const String& p_assembly_name);
|
Object* get_script_owner() const;
|
||||||
|
void* get_attached_script_object() const;
|
||||||
|
void* get_active_script_object() const;
|
||||||
|
|
||||||
|
NodePath script_owner_path;
|
||||||
void* managed_object = nullptr;
|
void* managed_object = nullptr;
|
||||||
String loaded_assembly_name;
|
String loaded_assembly_name;
|
||||||
double elapsed = 0.0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "vm/settings.h"
|
#include "vm/settings.h"
|
||||||
#include "interp/eval_stack_op.h"
|
#include "interp/eval_stack_op.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -62,9 +63,19 @@ bool& godot_icalls_registered()
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<Object*, leanclr::vm::RtObject*>& script_objects_by_owner()
|
struct GodotObjectPtrHasher
|
||||||
{
|
{
|
||||||
static std::unordered_map<Object*, leanclr::vm::RtObject*>* objects = new std::unordered_map<Object*, leanclr::vm::RtObject*>;
|
std::size_t operator()(const Object* p_object) const noexcept
|
||||||
|
{
|
||||||
|
return static_cast<std::size_t>(reinterpret_cast<uintptr_t>(p_object));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ScriptObjectByOwnerMap = std::unordered_map<Object*, leanclr::vm::RtObject*, GodotObjectPtrHasher>;
|
||||||
|
|
||||||
|
ScriptObjectByOwnerMap& script_objects_by_owner()
|
||||||
|
{
|
||||||
|
static ScriptObjectByOwnerMap* objects = new ScriptObjectByOwnerMap;
|
||||||
return *objects;
|
return *objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user