diff --git a/src/SConstruct b/src/SConstruct index ca6847e..4ff0b69 100644 --- a/src/SConstruct +++ b/src/SConstruct @@ -1,5 +1,11 @@ env = SConscript("godot-cpp/SConstruct") env.Append(CPPPATH="liborng/") +env.Append(CPPPATH="liborng/data_assets") +env.Append(CPPPATH="liborng/nodes") +env.Append(CPPPATH="liborng/nodes/character_nodes") +env.Append(CPPPATH="liborng/resources") +env.Append(CPPPATH="liborng/singletons") +env.Append(CPPPATH="liborng/singletons/vendor_service") src = Glob('liborng/*.cpp') src += Glob('liborng/**/*.cpp') diff --git a/src/liborng/nodes/character_nodes/character_3d.cpp b/src/liborng/nodes/character_nodes/character_3d.cpp new file mode 100644 index 0000000..37e6b44 --- /dev/null +++ b/src/liborng/nodes/character_nodes/character_3d.cpp @@ -0,0 +1,34 @@ +/* + * ©2023 Batty Bovine Productions, LLC. All Rights Reserved. + * + * If this source code makes it to the public internet, this software can be + * considered to be protected by the MIT licence. Have fun with it. + */ + +#include "character_3d.h" + +#include "orng_macros.h" + +#include +#include + +using namespace godot; + + +void Character3D::_ready() +{ + set_animation_tree_path(this->animation_tree_path); +} + + +void Character3D::set_animation_tree_path(NodePath at) +{ + this->animation_tree_path = at; + this->animation_tree = cast_to(Node::get_node_or_null(this->animation_tree_path)); +} + + +void Character3D::_on_fell_out_of_world() +{ + this->emit_signal("fell_out_of_world"); +} diff --git a/src/liborng/nodes/character_nodes/character_3d.h b/src/liborng/nodes/character_nodes/character_3d.h new file mode 100644 index 0000000..8f41054 --- /dev/null +++ b/src/liborng/nodes/character_nodes/character_3d.h @@ -0,0 +1,53 @@ +/* + * ©2023 Batty Bovine Productions, LLC. All Rights Reserved. + * + * If this source code makes it to the public internet, this software can be + * considered to be protected by the MIT licence. Have fun with it. + */ + +#pragma once + +#include "orng_macros.h" + +#include +#include +#include +using namespace godot; + +#define CHARACTER3D_TAG "Character3D" + + +class Character3D : public CharacterBody3D +{ + GDCLASS(Character3D, CharacterBody3D); + +public: + virtual void _ready() override; + + virtual void _on_fell_out_of_world(); + +protected: + void set_animation_tree_path(NodePath at); + NodePath get_animation_tree_path() const { return this->animation_tree_path; } + +private: + AnimationTree *get_animation_tree() const { return this->animation_tree; } + + NodePath animation_tree_path; + AnimationTree *animation_tree = nullptr; + +// Godot boilerplate below +protected: + static void _bind_methods() + { + BIND_METHOD(Character3D, _on_fell_out_of_world); + + ADD_SIGNAL(MethodInfo("fell_out_of_world")); + + ClassDB::bind_method(D_METHOD("get_animation_tree_path"), &Character3D::get_animation_tree_path); + ClassDB::bind_method(D_METHOD("set_animation_tree_path", "animation_tree"), &Character3D::set_animation_tree_path); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "animation_tree", PROPERTY_HINT_NODE_TYPE, "AnimationTree"), "set_animation_tree_path", "get_animation_tree_path"); + + ClassDB::bind_method(D_METHOD("get_animation_tree"), &Character3D::get_animation_tree); + } +}; diff --git a/src/liborng/nodes/level_scene.cpp b/src/liborng/nodes/level_scene.cpp index 1adfe31..3d7ba1c 100644 --- a/src/liborng/nodes/level_scene.cpp +++ b/src/liborng/nodes/level_scene.cpp @@ -7,6 +7,7 @@ #include "level_scene.h" +#include "character_3d.h" #include "nodes/player_spawn.h" #include "singletons/save_manager.h" @@ -38,11 +39,11 @@ void LevelScene::_scene_ready() #ifdef DEBUG_ENABLED if (!this->game_classes.is_valid()) { - UtilityFunctions::push_error("No GameClasses resource attached to level."); + PRINT_ERROR(LEVEL_SCENE_TAG, "No GameClasses resource attached to level."); return; } #endif - + this->level_death_plane_node = cast_to(this->get_node_or_null(this->level_death_plane)); if (this->level_death_plane_node) { @@ -62,7 +63,7 @@ void LevelScene::_scene_ready() #ifdef DEBUG_ENABLED if (!spawn_point) { - UtilityFunctions::push_error("Could not find a spawn point named ", current_checkpoint, "; defaulting to origin..."); + PRINT_ERROR(LEVEL_SCENE_TAG, "Could not find a spawn point named ", current_checkpoint, "; defaulting to origin..."); spawn_point = spawn_points[PLAYER_ORIGIN_TAG]; DEV_ASSERT(spawn_point); } @@ -97,12 +98,12 @@ void LevelScene::_find_player_spawns_recursive(const Node *node, SpawnPointMap & void LevelScene::_body_fell_out_of_world(Node3D *body) { - if (body->has_method("on_fell_out_of_world")) + if (Character3D *character3d = cast_to(body)) { - body->call("on_fell_out_of_world"); + character3d->emit_signal(FELL_OUT_OF_WORLD_SIGNAL); } - else + else if (body->has_method(FELL_OUT_OF_WORLD_METHOD)) { - body->queue_free(); + body->call(FELL_OUT_OF_WORLD_METHOD); } } diff --git a/src/liborng/nodes/level_scene.h b/src/liborng/nodes/level_scene.h index 25954ee..aeaf151 100644 --- a/src/liborng/nodes/level_scene.h +++ b/src/liborng/nodes/level_scene.h @@ -15,6 +15,11 @@ #include using namespace godot; +#define LEVEL_SCENE_TAG "LevelScene" + +#define FELL_OUT_OF_WORLD_SIGNAL "fell_out_of_world" +#define FELL_OUT_OF_WORLD_METHOD "_on_fell_out_of_world" + typedef std::map SpawnPointMap; diff --git a/src/liborng/nodes/mesh_editing_library.cpp b/src/liborng/nodes/mesh_editing_library.cpp index c269e6a..9c289ea 100644 --- a/src/liborng/nodes/mesh_editing_library.cpp +++ b/src/liborng/nodes/mesh_editing_library.cpp @@ -28,15 +28,15 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(const MeshInstance3D *original { const Time *time = Time::get_singleton(); - UtilityFunctions::print("Started slicing mesh at ", time->get_ticks_msec(), "ms"); + PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Started slicing mesh at ", time->get_ticks_msec(), "ms"); const Mesh *original_mesh = original_mesh_instance->get_mesh().ptr(); const uint8_t num_surfaces = original_mesh->get_surface_count(); - TypedArray bone_transforms; - const SkinnedSurfaces &skinned_vertex_positions = MeshEditingLibrary::get_skinned_vertex_positions(original_mesh, original_skeleton, bone_transforms); + std::vector> skinned_vertex_transforms; + const SkinnedSurfaces &skinned_vertex_positions = MeshEditingLibrary::get_skinned_vertex_positions(original_mesh, original_skeleton, skinned_vertex_transforms); - UtilityFunctions::print("Got skinned vertices at ", time->get_ticks_msec(), "ms"); + PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Got skinned vertices at ", time->get_ticks_msec(), "ms"); PackedVector3Array impact_points; @@ -166,7 +166,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(const MeshInstance3D *original PackedInt32Array other_half_section_indices; const PackedInt32Array &surface_index_array = surface_arrays[ArrayMesh::ARRAY_INDEX]; - UtilityFunctions::print("Surface ", surface, " sorted by plane distance at ", time->get_ticks_msec(), "ms"); + PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Surface ", surface, " sorted by plane distance at ", time->get_ticks_msec(), "ms"); if (!(first_half_section_vertices.size() > 0 && other_half_section_vertices.size() > 0)) { @@ -463,7 +463,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(const MeshInstance3D *original out_other_half->surface_set_material(surface, original_mesh->surface_get_material(surface)); } - UtilityFunctions::print("Surface ", surface, " split edges at ", time->get_ticks_msec(), "ms"); + PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Surface ", surface, " split edges at ", time->get_ticks_msec(), "ms"); if (clip_edges.size() > 0) { @@ -501,9 +501,10 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(const MeshInstance3D *original for (const MeshEditVert2D &vertex : polygon_set[polygon_index].vertices) { const Vector3 &position = first_half_section_vertices[vertex.index]; + const Vector3 &local_plane_transformed_normal = skinned_vertex_transforms[surface][vertex.index].xform(local_plane_normal).normalized(); cap_section_vertices.append(position); - if (has_normal) { cap_section_normals.append(local_plane_normal * -1.0f); cap_section_flipped_normals.append(local_plane_normal); } + if (has_normal) { cap_section_normals.append(local_plane_transformed_normal); cap_section_flipped_normals.append(local_plane_transformed_normal * -1.0f); } if (has_colour) { cap_section_colours.append(first_half_section_colours[vertex.index]); } if (has_uv) { cap_section_uvs.append(MeshEditingLibrary::calculate_planar_uv(position, mesh_bounds, uv_plane)); } if (has_uv2) { cap_section_uv2s.append(first_half_section_uv2s[vertex.index]); } @@ -548,7 +549,7 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(const MeshInstance3D *original } } - UtilityFunctions::print("Surface ", surface, " created cap surface at ", time->get_ticks_msec(), "ms"); + PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Surface ", surface, " created cap surface at ", time->get_ticks_msec(), "ms"); } if (cap_section_vertices.size() > 0 && cap_section_indices.size() > 0) @@ -590,12 +591,12 @@ PackedVector3Array MeshEditingLibrary::slice_mesh(const MeshInstance3D *original out_other_half->surface_set_material(out_other_half->get_surface_count()-1, cap_material); } - UtilityFunctions::print("Generated final cap surface at ", time->get_ticks_msec(), "ms"); + PRINT_LOG(MESH_EDITING_LIBRARY_TAG, "Generated final cap surface at ", time->get_ticks_msec(), "ms"); return impact_points; } -SkinnedSurfaces MeshEditingLibrary::get_skinned_vertex_positions(const Mesh *mesh, const Skeleton3D *skeleton, TypedArray &bone_transforms) +SkinnedSurfaces MeshEditingLibrary::get_skinned_vertex_positions(const Mesh *mesh, const Skeleton3D *skeleton, std::vector> &vertex_transforms) { const uint8_t num_surfaces = mesh->get_surface_count(); SkinnedSurfaces skinned_vertex_surfaces; @@ -604,12 +605,15 @@ SkinnedSurfaces MeshEditingLibrary::get_skinned_vertex_positions(const Mesh *mes if (skeleton) { const uint16_t bone_count = skeleton->get_bone_count(); + std::vector bone_transforms; bone_transforms.resize(bone_count); for (uint8_t bone_index = 0; bone_index < bone_count; bone_index++) { bone_transforms[bone_index] = skeleton->get_bone_global_pose(bone_index) * skeleton->get_bone_global_rest(bone_index).inverse(); } + vertex_transforms.resize(num_surfaces); + for (uint8_t surface = 0; surface < num_surfaces; surface++) { const Array &mesh_arrays = mesh->surface_get_arrays(surface); @@ -620,6 +624,9 @@ SkinnedSurfaces MeshEditingLibrary::get_skinned_vertex_positions(const Mesh *mes SkinnedVertices skinned_vertex_array; skinned_vertex_array.resize(mesh_vertex_array_size); + std::vector skinned_vertex_transforms; + skinned_vertex_transforms.resize(mesh_vertex_array_size); + const PackedInt32Array &mesh_bones_array = mesh_arrays[ArrayMesh::ARRAY_BONES]; const PackedFloat32Array &mesh_weights_array = mesh_arrays[ArrayMesh::ARRAY_WEIGHTS]; const uint8_t num_bones_per_vertex = mesh_bones_array.size() / mesh_vertex_array_size; @@ -644,21 +651,19 @@ SkinnedSurfaces MeshEditingLibrary::get_skinned_vertex_positions(const Mesh *mes origin += transforms[transform].origin; } - const Vector3 &transformed_vertex = Vector3( - x_basis.dot(vertex) + origin.x, - y_basis.dot(vertex) + origin.y, - z_basis.dot(vertex) + origin.z); - skinned_vertex_array[vertex_index] = transformed_vertex; - // The above is identical to the code seen below, except the below code does not work. - // This is fucking stupid. - // - // const Transform3D &final_transform = Transform3D(x_basis, y_basis, z_basis, origin); - // skinned_vertex_array[vertex_index] = final_transform.xform(vertex); + const Transform3D &final_bone_transform = Transform3D( + x_basis.x, x_basis.y, x_basis.z, + y_basis.x, y_basis.y, y_basis.z, + z_basis.x, z_basis.y, z_basis.z, + origin.x, origin.y, origin.z); + skinned_vertex_transforms[vertex_index] = final_bone_transform; + skinned_vertex_array[vertex_index] = final_bone_transform.xform(vertex); delete transforms; } skinned_vertex_surfaces[surface] = skinned_vertex_array; + vertex_transforms[surface] = skinned_vertex_transforms; } return skinned_vertex_surfaces; diff --git a/src/liborng/nodes/mesh_editing_library.h b/src/liborng/nodes/mesh_editing_library.h index d20c9fb..e7c6877 100644 --- a/src/liborng/nodes/mesh_editing_library.h +++ b/src/liborng/nodes/mesh_editing_library.h @@ -17,6 +17,8 @@ using namespace godot; #include +#define MESH_EDITING_LIBRARY_TAG "MeshEditingLibrary" + typedef std::vector SkinnedVertices; typedef std::vector SkinnedSurfaces; @@ -79,7 +81,7 @@ protected: private: static const Vector2 calculate_planar_uv(const Vector3 &vertex, const Vector3 &mesh_bounds, const MeshSlicePlaneOrientation &axis); - static SkinnedSurfaces get_skinned_vertex_positions(const Mesh *mesh, const Skeleton3D *skeleton = nullptr, TypedArray &bone_transforms = TypedArray()); + static SkinnedSurfaces get_skinned_vertex_positions(const Mesh *mesh, const Skeleton3D *skeleton = nullptr, std::vector> &bone_transforms = std::vector>()); static void project_edges(std::vector &out_2d_edges, const Transform3D &to_node_space, const std::vector &in_3d_edges, const Plane &plane); static void build_2d_polygons_from_edges(std::vector &out_polygons, const std::vector &in_edges, std::vector &error_polygons); diff --git a/src/liborng/nodes/player_spawn.cpp b/src/liborng/nodes/player_spawn.cpp index b1e18ed..15a3238 100644 --- a/src/liborng/nodes/player_spawn.cpp +++ b/src/liborng/nodes/player_spawn.cpp @@ -41,6 +41,18 @@ void PlayerSpawn::_on_area_3d_body_entered(Node3D *body) } +void PlayerOrigin::_ready() +{ +#ifdef DEBUG_ENABLED + if (Engine::get_singleton()->is_editor_hint()) + { + this->unload_editor_preview(); + this->load_editor_preview(); + } +#endif // DEBUG_ENABLED +} + + bool PlayerOrigin::spawn_player(Node3D *parent, Ref player) const { Ref player_scene_to_unpack = this->player_scene.is_valid() ? this->player_scene : player; @@ -70,3 +82,46 @@ bool PlayerOrigin::spawn_player(Node3D *parent, Ref player) const return false; } + + +void PlayerOrigin::set_player_scene(Ref s) +{ + this->player_scene = s; + +#ifdef DEBUG_ENABLED + if (Engine::get_singleton()->is_editor_hint()) + { + this->unload_editor_preview(); + this->load_editor_preview(); + } +#endif // DEBUG_ENABLED +} + + +void PlayerOrigin::load_editor_preview() +{ + if (this->player_preview_node) + return; + + if (SceneLoader *scene_loader = SceneLoader::get_singleton()) + { + scene_loader->load_scene(this->player_scene->get_path(), callable_mp(this, &PlayerOrigin::_threaded_load_callback)); + } +} +void PlayerOrigin::_threaded_load_callback(Ref loaded_scene) +{ + if (loaded_scene.is_valid()) + { + this->player_preview_node = cast_to(loaded_scene->instantiate()); + this->add_child(this->player_preview_node); + } +} + +void PlayerOrigin::unload_editor_preview() +{ + if (this->player_preview_node) + { + this->player_preview_node->queue_free(); + this->player_preview_node = nullptr; + } +} diff --git a/src/liborng/nodes/player_spawn.h b/src/liborng/nodes/player_spawn.h index d76a3c9..c325cab 100644 --- a/src/liborng/nodes/player_spawn.h +++ b/src/liborng/nodes/player_spawn.h @@ -8,6 +8,7 @@ #pragma once #include "orng_macros.h" +#include "singletons/scene_loader.h" #include #include @@ -24,6 +25,8 @@ class PlayerOrigin : public Node3D GDCLASS(PlayerOrigin, Node3D); public: + virtual void _ready() override; + // Spawn the player at the spawn point's location. If the spawn point has // no player scene set, the passed in player scene will be used. Function // returns false if no player could be spawned. @@ -31,12 +34,15 @@ public: virtual StringName get_tag() const { return this->tag; } - void set_player_scene(Ref s) { this->player_scene = s; } + void set_player_scene(Ref s); Ref get_player_scene() const { return this->player_scene; } void set_sublevel_scenes_to_load(TypedArray scenes) { this->sublevel_scenes_to_load = scenes; } TypedArray get_sublevel_scenes_to_load() const { return this->sublevel_scenes_to_load; } + void load_editor_preview(); + void unload_editor_preview(); + protected: StringName tag = StringName(PLAYER_ORIGIN_TAG); @@ -45,6 +51,10 @@ protected: // List of sublevels that need to be loaded along with the player. TypedArray sublevel_scenes_to_load; + +private: + void _threaded_load_callback(Ref loaded_scene); + Node3D *player_preview_node = nullptr; // Godot boilerplate below protected: diff --git a/src/liborng/nodes/sublevel_scene.cpp b/src/liborng/nodes/sublevel_scene.cpp index 9c79f8f..fecae18 100644 --- a/src/liborng/nodes/sublevel_scene.cpp +++ b/src/liborng/nodes/sublevel_scene.cpp @@ -16,12 +16,12 @@ using namespace godot; void SublevelScene::_ready() { -#ifdef DEBUG_ENABLED - if (Engine::get_singleton()->is_editor_hint()) - { - this->load_sublevel(); - } -#endif // DEBUG_ENABLED +// #ifdef DEBUG_ENABLED +// if (Engine::get_singleton()->is_editor_hint()) +// { +// this->load_sublevel(); +// } +// #endif // DEBUG_ENABLED } void SublevelScene::set_sublevel(StringName s) diff --git a/src/liborng/orng_macros.h b/src/liborng/orng_macros.h index bd5328e..fb27c9f 100644 --- a/src/liborng/orng_macros.h +++ b/src/liborng/orng_macros.h @@ -36,3 +36,27 @@ */ #define CALL_NEXT_FRAME(C) \ this->get_tree()->create_timer(SMALL_NUMBER)->connect("timeout", C) + + +/** + * Editor hint helpers + */ +#ifdef DEBUG_ENABLED + #define RETURN_IF_EDITOR() if(Engine::get_singleton()->is_editor_hint()) { return; } +#else + #define RETURN_IF_EDITOR() +#endif // DEBUG_ENABLED + + +/** + * Logging helpers + */ +#ifdef DEBUG_ENABLED + #define PRINT_LOG(tag, ...) UtilityFunctions::print("[" tag "] " __VA_ARGS__); + #define PRINT_WARNING(tag, ...) UtilityFunctions::push_warning("[" tag "] " __VA_ARGS__); + #define PRINT_ERROR(tag, ...) UtilityFunctions::printerr("[" tag "] " __VA_ARGS__); +#else + #define PRINT_LOG(tag, ...) + #define PRINT_WARNING(tag, ...) + #define PRINT_ERROR(tag, ...) +#endif // DEBUG_ENABLED diff --git a/src/liborng/register_types.cpp b/src/liborng/register_types.cpp index 2c03116..729eda2 100644 --- a/src/liborng/register_types.cpp +++ b/src/liborng/register_types.cpp @@ -21,6 +21,7 @@ #include "nodes/player_spawn.h" #include "nodes/sublevel_loader.h" #include "nodes/sublevel_scene.h" +#include "nodes/character_nodes/character_3d.h" #include "resources/level_metadata_map.h" #include "resources/level_metadata_resource.h" @@ -62,6 +63,7 @@ void initialize_orng_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -82,9 +84,9 @@ void uninitialize_orng_module(ModuleInitializationLevel p_level) { if (p_level == ModuleInitializationLevel::MODULE_INITIALIZATION_LEVEL_SCENE) { // GDSINGLETON_UNREGISTER_CLASS(_vendor_service_singleton); - GDSINGLETON_UNREGISTER_CLASS(_scene_loader_singleton); - GDSINGLETON_UNREGISTER_CLASS(_save_manager_singleton); - GDSINGLETON_UNREGISTER_CLASS(_input_handler_singleton); + // GDSINGLETON_UNREGISTER_CLASS(_scene_loader_singleton); + // GDSINGLETON_UNREGISTER_CLASS(_save_manager_singleton); + // GDSINGLETON_UNREGISTER_CLASS(_input_handler_singleton); } } diff --git a/src/liborng/resources/input_resource.cpp b/src/liborng/resources/input_resource.cpp index 66e28f0..3803326 100644 --- a/src/liborng/resources/input_resource.cpp +++ b/src/liborng/resources/input_resource.cpp @@ -65,7 +65,7 @@ void InputResource::update_axes_mouse_event(const Ref eve for (uint8_t i = 0; i < this->input_axes.size(); i++) { const InputAxis *axis = cast_to(this->input_axes[i]); - const StringName signal = StringName("_on_") + axis->get_axis_name() + INPUTAXIS_TWO_DIMENSIONAL_SUFFIX + INPUTHANDLER_SUFFIX_SIGNAL; + const StringName signal = StringName("_on_") + axis->get_axis_name() + INPUTAXIS_MOUSE_INPUT_SUFFIX + INPUTHANDLER_SUFFIX_SIGNAL; if (axis->get_include_mouse() && this->has_signal(signal)) { this->emit_signal(signal, delta, event->get_relative() * 0.0001f / delta); diff --git a/src/liborng/resources/input_resource.h b/src/liborng/resources/input_resource.h index 41c26d0..87113c9 100644 --- a/src/liborng/resources/input_resource.h +++ b/src/liborng/resources/input_resource.h @@ -28,6 +28,7 @@ using namespace godot; #define INPUTAXIS_ONE_DIMENSIONAL_SUFFIX StringName("_1d") #define INPUTAXIS_TWO_DIMENSIONAL_SUFFIX StringName("_2d") #define INPUTAXIS_THREE_DIMENSIONAL_SUFFIX StringName("_3d") +#define INPUTAXIS_MOUSE_INPUT_SUFFIX StringName("_mouse") class InputAxis2D : public Resource diff --git a/src/liborng/singletons/input_handler.cpp b/src/liborng/singletons/input_handler.cpp index 5456e80..63df071 100644 --- a/src/liborng/singletons/input_handler.cpp +++ b/src/liborng/singletons/input_handler.cpp @@ -148,6 +148,15 @@ void InputHandler::add_input_resource(Node *target, InputResource *resource) { Engine *engine = Engine::get_singleton(); this->call_deferred("_enable_mouse_capture"); + + const StringName callback_name = StringName("_on_") + axis->get_axis_name() + INPUTAXIS_MOUSE_INPUT_SUFFIX; + if (target->has_method(callback_name)) + { + const StringName signal_name = callback_name + INPUTHANDLER_SUFFIX_SIGNAL; + if (!resource->has_signal(signal_name)) resource->add_user_signal(signal_name); + const Callable &callable = Callable(target, callback_name); + if (!resource->is_connected(signal_name, callable)) resource->connect(signal_name, callable); + } } } } @@ -238,6 +247,16 @@ void InputHandler::remove_input_resource(Node *target, InputResource *resource) if (target->has_method(callback_name_three)) target->call(callback_name_three, this->get_process_delta_time(), Vector3(0.0f, 0.0f, 0.0f)); } + + const StringName &callback_name_mouse = StringName("_on_") + axis->get_axis_name() + INPUTAXIS_MOUSE_INPUT_SUFFIX; + const StringName &signal_name_mouse = callback_name_three + INPUTHANDLER_SUFFIX_SIGNAL; + if (target->has_method(callback_name_mouse)) + { + if (resource->has_signal(signal_name_mouse)) + resource->disconnect(signal_name_mouse, Callable(target, callback_name_mouse)); + if (target->has_method(callback_name_mouse)) + target->call(callback_name_mouse, this->get_process_delta_time(), Vector2(0.0f, 0.0f)); + } /* * This part would be a good, safe precaution to take, but it seems diff --git a/src/liborng/singletons/scene_loader.cpp b/src/liborng/singletons/scene_loader.cpp index 465e7fe..bc4e47c 100644 --- a/src/liborng/singletons/scene_loader.cpp +++ b/src/liborng/singletons/scene_loader.cpp @@ -165,9 +165,10 @@ void SceneLoader::load_scene(const StringName path, Callable callback) if (path.is_empty()) return; + if (!this->resource_loader) return; if (this->resource_loader->load_threaded_request(path, "PackedScene", true) != Error::OK) { - UtilityFunctions::printerr("Scene ", path, " does not exist."); + PRINT_ERROR("SceneLoader", "Scene ", path, " does not exist."); return; }