--- /dev/null
+device KEYBOARD;
+device MOUSE;
+binding "pointer"
+{
+ horizontal { mouse X; };
+ vertical { mouse Y; };
+};
+binding "pick"
+{
+ button { mouse LEFT; };
+};
--- /dev/null
+#include "controls.h"
+
+Controls::Controls()
+{
+ add("pointer", pointer);
+ add("pick", pick);
+}
--- /dev/null
+#ifndef CONTROLS_H_
+#define CONTROLS_H_
+
+#include <msp/input/control.h>
+#include <msp/input/controlscheme.h>
+
+struct Controls: public Msp::Input::ControlScheme
+{
+ Msp::Input::PlanarControl pointer;
+ Msp::Input::BinaryControl pick;
+
+ Controls();
+};
+
+#endif
--- /dev/null
+#include "mousepicker.h"
+#include <msp/game/camera.h>
+#include <msp/game/entity.h>
+#include <msp/game/transform.h>
+#include "controls.h"
+#include "toy.h"
+
+using namespace std;
+using namespace Msp;
+
+MousePicker::MousePicker(Game::Stage &s, Game::PhysicsSystem &p):
+ System(s),
+ physics(p)
+{
+ declare_dependency<Game::Transform>(UPDATE);
+ declare_dependency<Game::Camera>(READ_OLD);
+ declare_dependency<Game::RigidBody>(WRITE);
+}
+
+void MousePicker::set_controls(Controls *c)
+{
+ controls = c;
+}
+
+void MousePicker::tick(Time::TimeDelta)
+{
+ if(!controls)
+ return;
+
+ Game::Handle<Game::Camera> camera = stage.get_active_camera();
+ if(!camera)
+ return;
+
+ const Geometry::AffineTransform<float, 3> &cam_world_tf = camera->get_entity()->get_transform()->get_world_transform();
+ Geometry::Ray<float, 3> ray = camera->create_ray(controls->pointer.get_value());
+ ray = cam_world_tf.transform(ray);
+
+ if(controls->pick.was_activated())
+ {
+ Game::RaycastHit hit = physics.cast_ray(ray);
+ if(hit)
+ {
+ drag_origin = hit.position;
+ drag_normal = normalize(compose(cam_world_tf.transform(LinAl::Vector<float, 3>(0.0f, 0.0f, 1.0f)).slice<2>(0), 0.0f));
+ Game::Handle<Toy> toy = dynamic_handle_cast<Toy>(hit.shape->get_entity());
+ if(toy)
+ {
+ held_toy = toy;
+ hold_offset = hit.position-toy->get_transform()->get_position();
+ held_toy->get_rigid_body()->set_kinematic(true);
+ }
+ }
+ }
+ else if(held_toy)
+ {
+ if(controls->pick.was_released())
+ {
+ held_toy->get_rigid_body()->set_kinematic(false);
+ held_toy = nullptr;
+ }
+ else
+ {
+ float d = dot(drag_origin-ray.get_start(), drag_normal)/dot(ray.get_direction(), drag_normal);
+ held_toy->get_transform()->set_position(ray.get_start()+ray.get_direction()*d-hold_offset);
+ }
+ }
+
+ controls->reset_edges();
+}
--- /dev/null
+#ifndef MOUSEPICKER_H_
+#define MOUSEPICKER_H_
+
+#include <msp/game/physicssystem.h>
+#include <msp/game/system.h>
+#include <msp/gameview/events.h>
+#include <msp/linal/vector.h>
+
+struct Controls;
+class Toy;
+
+class MousePicker: public Msp::Game::System
+{
+private:
+ Msp::Game::PhysicsSystem &physics;
+ Controls *controls = nullptr;
+ Msp::Game::Handle<Toy> held_toy;
+ Msp::LinAl::Vector<float, 3> hold_offset;
+ Msp::LinAl::Vector<float, 3> drag_origin;
+ Msp::LinAl::Vector<float, 3> drag_normal;
+
+public:
+ MousePicker(Msp::Game::Stage &, Msp::Game::PhysicsSystem &);
+
+ void set_controls(Controls *);
+
+ void tick(Msp::Time::TimeDelta) override;
+};
+
+#endif
#include <msp/game/physicssystem.h>
#include <msp/game/root.h>
#include <msp/game/stageplan.h>
+#include "controls.h"
#include "fixture.h"
+#include "mousepicker.h"
#include "playground/setups.h"
#include "toy.h"
using namespace Msp;
Playground::Playground(int, char **):
+ event_observer(director.get_event_bus()),
stage(director.create_stage("playground")),
cam_entity(stage.get_root(), Game::TransformValues({ 0.0f, -1.5f, 1.5f }, Geometry::make_quat(45.0f*Geometry::degrees, { 1.0f, 0.0f, 0.0f }))),
camera(cam_entity, resources.get<Game::CameraSetup>("playground.camera.setup")),
{
Game::StagePlan::register_entity_type<Fixture>("fixture");
- stage.add_system<Game::PhysicsSystem>();
+ event_observer.observe<GameView::Events::LocalPlayerArrived>([this](auto &e){ player_arrived(e); });
+
+ Game::PhysicsSystem &physics = stage.add_system<Game::PhysicsSystem>();
+ mouse_picker = &stage.add_system<MousePicker>(physics);
stage.apply_plan(resources.get<Game::StagePlan>("playground.stage"));
vector<ToySetup *> toy_setups = resources.get_all<ToySetup>();
toys.emplace_back(stage.get_root(), setup, Game::TransformValues(pos, Geometry::Quaternion<float>::one()));
}
+ player_input.set_control_scheme_type<Controls>();
+
director.activate_stage(stage);
}
+void Playground::player_arrived(const GameView::Events::LocalPlayerArrived &e)
+{
+ mouse_picker->set_controls(dynamic_cast<Controls *>(&e.controls));
+}
+
PlaygroundResources::PlaygroundResources()
{
#include <msp/gameview/application.h>
#include <msp/gameview/resources.h>
+class MousePicker;
class Toy;
class PlaygroundResources: public Msp::Game::ApplicationResources, public Msp::GameView::Resources
class Playground: public Msp::GameView::Application<Playground, PlaygroundResources>
{
private:
+ Msp::Game::EventObserver event_observer;
Msp::Game::Stage &stage;
+ MousePicker *mouse_picker = nullptr;
Msp::Game::Owned<Msp::Game::Entity> cam_entity;
Msp::Game::Owned<Msp::Game::Camera> camera;
Msp::Game::ShadowTargetSetup shadow_setup;
public:
Playground(int, char **);
+
+private:
+ void player_arrived(const Msp::GameView::Events::LocalPlayerArrived &);
};
#endif
public:
Toy(Msp::Game::Handle<Msp::Game::Entity>, const Setup &, const Msp::Game::TransformValues &);
+
+ Msp::Game::Handle<Msp::Game::RigidBody> get_rigid_body() { return rigid_body; }
};
#endif