diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index 7c1fcbf..8c6764d 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -1026,6 +1026,22 @@ void setup_controls(game_context* ctx) ctx->input_event_router->add_mapping(key_mapping(ctx->control_system->get_equip_brush_control(), nullptr, scancode::two)); ctx->input_event_router->add_mapping(key_mapping(ctx->control_system->get_equip_lens_control(), nullptr, scancode::three)); + ctx->input_event_router->add_mapping(mouse_button_mapping(ctx->control_system->get_use_tool_control(), nullptr, 1)); + ctx->control_system->get_use_tool_control()->set_activated_callback + ( + [ctx]() + { + ctx->tool_system->set_tool_active(true); + } + ); + ctx->control_system->get_use_tool_control()->set_deactivated_callback + ( + [ctx]() + { + ctx->tool_system->set_tool_active(false); + } + ); + ctx->control_system->get_equip_forceps_control()->set_activated_callback ( [ctx]() diff --git a/src/game/components/tool-component.hpp b/src/game/components/tool-component.hpp index 7404716..a2e1781 100644 --- a/src/game/components/tool-component.hpp +++ b/src/game/components/tool-component.hpp @@ -25,8 +25,11 @@ namespace ecs { struct tool_component { bool active; - float hover_distance; + float idle_distance; + float active_distance; bool heliotropic; + + //float activation_speed; }; } // namespace ecs diff --git a/src/game/entity-commands.cpp b/src/game/entity-commands.cpp index 47782b9..eb7774c 100644 --- a/src/game/entity-commands.cpp +++ b/src/game/entity-commands.cpp @@ -57,6 +57,15 @@ void warp_to(entt::registry& registry, entt::entity eid, const float3& position) } } +void set_scale(entt::registry& registry, entt::entity eid, const float3& scale) +{ + if (registry.has(eid)) + { + transform_component& transform = registry.get(eid); + transform.local.scale = scale; + } +} + void set_transform(entt::registry& registry, entt::entity eid, const math::transform& transform, bool warp) { if (registry.has(eid)) diff --git a/src/game/entity-commands.hpp b/src/game/entity-commands.hpp index 4db74d9..122b920 100644 --- a/src/game/entity-commands.hpp +++ b/src/game/entity-commands.hpp @@ -29,6 +29,7 @@ namespace ec { void translate(entt::registry& registry, entt::entity eid, const float3& translation); void move_to(entt::registry& registry, entt::entity eid, const float3& position); void warp_to(entt::registry& registry, entt::entity eid, const float3& position); +void set_scale(entt::registry& registry, entt::entity eid, const float3& scale); void set_transform(entt::registry& registry, entt::entity eid, const math::transform& transform, bool warp = false); void place(entt::registry& registry, entt::entity eid, const float2& translation); void assign_render_layers(entt::registry& registry, entt::entity eid, unsigned int layers); diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index 4d68ebd..1a53ba5 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -109,13 +109,15 @@ void play_state_enter(game_context* ctx) //ec::bind_transform(ecs_registry, lens_light_cone, ctx->lens_entity); ec::parent(ecs_registry, lens_light_cone, ctx->lens_entity); - // Activate lens tool - auto& active_tool_component = ecs_registry.get(ctx->lens_entity); - active_tool_component.active = true; + // Hide inactive tools ec::assign_render_layers(ecs_registry, ctx->forceps_entity, 0); ec::assign_render_layers(ecs_registry, ctx->brush_entity, 0); + ec::assign_render_layers(ecs_registry, ctx->lens_entity, 0); + + // Activate lens tool + ctx->tool_system->set_active_tool(ctx->lens_entity); // Create ant-hill auto ant_hill_entity = ant_hill_archetype->create(ecs_registry); diff --git a/src/game/systems/control-system.cpp b/src/game/systems/control-system.cpp index bbd20d1..c72757b 100644 --- a/src/game/systems/control-system.cpp +++ b/src/game/systems/control-system.cpp @@ -54,6 +54,7 @@ control_system::control_system(entt::registry& registry): control_set.add_control(&equip_lens_control); control_set.add_control(&equip_brush_control); control_set.add_control(&equip_forceps_control); + control_set.add_control(&use_tool_control); // Set deadzone at 15% for all controls const std::list* controls = control_set.get_controls(); diff --git a/src/game/systems/control-system.hpp b/src/game/systems/control-system.hpp index 10c22e0..9023420 100644 --- a/src/game/systems/control-system.hpp +++ b/src/game/systems/control-system.hpp @@ -74,11 +74,12 @@ public: control* get_equip_lens_control(); control* get_equip_brush_control(); control* get_equip_forceps_control(); + control* get_use_tool_control(); private: virtual void handle_event(const mouse_moved_event& event); virtual void handle_event(const window_resized_event& event); - + control_set control_set; control move_forward_control; control move_back_control; @@ -97,7 +98,8 @@ private: control tool_menu_control; control equip_lens_control; control equip_brush_control; - control equip_forceps_control;; + control equip_forceps_control; + control use_tool_control; float zoom_speed; float min_elevation; @@ -227,5 +229,10 @@ inline control* control_system::get_equip_forceps_control() return &equip_forceps_control; } +inline control* control_system::get_use_tool_control() +{ + return &use_tool_control; +} + #endif // ANTKEEPER_CONTROL_SYSTEM_HPP diff --git a/src/game/systems/tool-system.cpp b/src/game/systems/tool-system.cpp index 5da265b..1ebdbc9 100644 --- a/src/game/systems/tool-system.cpp +++ b/src/game/systems/tool-system.cpp @@ -23,10 +23,12 @@ #include "game/components/transform-component.hpp" #include "scene/camera.hpp" #include "animation/orbit-cam.hpp" +#include "animation/ease.hpp" #include "geometry/mesh.hpp" #include "geometry/intersection.hpp" #include "math/math.hpp" #include "game/entity-commands.hpp" +#include using namespace ecs; @@ -51,12 +53,40 @@ tool_system::tool_system(entt::registry& registry): pick_spring.x0 = pick_spring.x1; pick_spring.v = {0.0f, 0.0f, 0.0f}; + // Create descend animation + animation_channel* channel = descend_animation.add_channel(0); + descend_animation.set_interpolator(ease::out_cubic); + descend_animation.set_frame_callback + ( + [this](int channel, const float& t) + { + this->active_tool_distance = t; + } + ); + + // Create descend animation + channel = ascend_animation.add_channel(0); + ascend_animation.set_interpolator(ease::out_cubic); + ascend_animation.set_frame_callback + ( + [this](int channel, const float& t) + { + this->active_tool_distance = t; + } + ); + active_tool = entt::null; + active_tool_distance = 0.0f; warp = true; + tool_active = false; } void tool_system::update(double t, double dt) { + // Advance animations + ascend_animation.advance(dt); + descend_animation.advance(dt); + if (!camera) return; @@ -116,11 +146,13 @@ void tool_system::update(double t, double dt) } // Determine target hand angle - hand_angle_spring.x1 = math::pi - std::min(0.5f, std::max(-0.5f, ((mouse_position[0] / viewport[2]) - 0.5f) * 1.0f)) * (math::pi + math::half_pi); + hand_angle_spring.x1 = math::pi - std::min(0.5f, std::max(-0.5f, ((mouse_position[0] / viewport[2]) - 0.5f) * 1.0f)) * (math::pi); // Solve springs solve_numeric_spring(hand_angle_spring, dt); solve_numeric_spring(pick_spring, dt); + + // Move active tools to intersection location registry.view().each( @@ -136,10 +168,12 @@ void tool_system::update(double t, double dt) return; active_tool = entity; + + float tool_distance = active_tool_distance;//(tool_active) ? tool.active_distance : tool.idle_distance; if (intersection) { - transform.local.translation = pick_spring.x0 + float3{0, tool.hover_distance, 0}; + transform.local.translation = pick_spring.x0 + float3{0, tool_distance, 0}; } // Interpolate between left and right hand @@ -148,7 +182,7 @@ void tool_system::update(double t, double dt) if (tool.heliotropic) { math::quaternion solar_rotation = math::rotation(float3{0, -1, 0}, sun_direction); - transform.local.translation = pick_spring.x0 + solar_rotation * float3{0, tool.hover_distance, 0}; + transform.local.translation = pick_spring.x0 + solar_rotation * float3{0, tool_distance, 0}; transform.local.rotation = solar_rotation * hand_rotation; } @@ -184,6 +218,8 @@ void tool_system::set_orbit_cam(const ::orbit_cam* orbit_cam) void tool_system::set_viewport(const float4& viewport) { this->viewport = viewport; + mouse_position.x = viewport[2] * 0.5f; + mouse_position.y = viewport[3] * 0.5f; } void tool_system::set_pick(bool enabled) @@ -198,6 +234,12 @@ void tool_system::set_sun_direction(const float3& direction) void tool_system::set_active_tool(entt::entity entity) { + if (active_tool == entity) + return; + + const float descent_time = 0.1f; + const float ascent_time = 0.1f; + if (active_tool != entt::null) { auto& tool = registry.get(active_tool); @@ -211,11 +253,41 @@ void tool_system::set_active_tool(entt::entity entity) { auto& tool = registry.get(active_tool); tool.active = true; + + active_tool_distance = tool.idle_distance; + + ec::warp_to(registry, active_tool, pick_spring.x0 + float3{0.0f, tool.idle_distance, 0.0f}); + + // Adjust descend and ascend animations + animation_channel* channel = descend_animation.get_channel(0); + channel->remove_keyframes(); + channel->insert_keyframe({0.0, tool.idle_distance}); + channel->insert_keyframe({descent_time, tool.active_distance}); + + channel = ascend_animation.get_channel(0); + channel->remove_keyframes(); + channel->insert_keyframe({0.0, tool.active_distance}); + channel->insert_keyframe({ascent_time, tool.idle_distance}); } warp = true; } +void tool_system::set_tool_active(bool active) +{ + tool_active = active; + + if (active) + { + descend_animation.rewind(); + descend_animation.play(); + } + else + { + ascend_animation.rewind(); + ascend_animation.play(); + } +} void tool_system::handle_event(const mouse_moved_event& event) { diff --git a/src/game/systems/tool-system.hpp b/src/game/systems/tool-system.hpp index dbdba16..152cf62 100644 --- a/src/game/systems/tool-system.hpp +++ b/src/game/systems/tool-system.hpp @@ -26,6 +26,7 @@ #include "event/window-events.hpp" #include "utility/fundamental-types.hpp" #include "animation/spring.hpp" +#include "animation/animation.hpp" class camera; class orbit_cam; @@ -47,8 +48,10 @@ public: void set_active_tool(entt::entity entity); + void set_tool_active(bool active); + entt::entity get_active_tool() const; - + private: virtual void handle_event(const mouse_moved_event& event); virtual void handle_event(const window_resized_event& event); @@ -62,9 +65,15 @@ private: float3 sun_direction; entt::entity active_tool; bool warp; + bool tool_active; + numeric_spring hand_angle_spring; numeric_spring pick_spring; + + animation descend_animation; + animation ascend_animation; + float active_tool_distance; }; inline entt::entity tool_system::get_active_tool() const diff --git a/src/resources/entity-archetype-loader.cpp b/src/resources/entity-archetype-loader.cpp index e24a992..ce6d70b 100644 --- a/src/resources/entity-archetype-loader.cpp +++ b/src/resources/entity-archetype-loader.cpp @@ -126,15 +126,16 @@ static bool load_terrain_component(archetype& archetype, const std::vector& parameters) { - if (parameters.size() != 4) + if (parameters.size() != 5) { throw std::runtime_error("load_tool_component(): Invalid parameter count."); } tool_component component; component.active = static_cast(std::stoi(parameters[1])); - component.hover_distance = std::stof(parameters[2]); - component.heliotropic = static_cast(std::stoi(parameters[3])); + component.idle_distance = std::stof(parameters[2]); + component.active_distance = std::stof(parameters[3]); + component.heliotropic = static_cast(std::stoi(parameters[4])); archetype.set(component); return true;