Split view controller to it's own class, added InputFrame code.
This conforms better to the new Input paradigm, and fixes a number of bugs relating to the ship view incorrectly rotating while in another view.master
parent
f4186dacb1
commit
34e896550a
|
@ -80,6 +80,7 @@ list(APPEND SRC_FOLDERS
|
|||
src/graphics/opengl
|
||||
src/gui
|
||||
src/scenegraph
|
||||
src/ship
|
||||
src/terrain
|
||||
src/text
|
||||
src/ui
|
||||
|
|
|
@ -66,7 +66,7 @@ static sigc::connection onChangeCamTypeConnection;
|
|||
|
||||
void AmbientSounds::Init()
|
||||
{
|
||||
onChangeCamTypeConnection = Pi::game->GetWorldView()->onChangeCamType.connect(sigc::ptr_fun(&AmbientSounds::UpdateForCamType));
|
||||
onChangeCamTypeConnection = Pi::game->GetWorldView()->shipView.onChangeCamType.connect(sigc::ptr_fun(&AmbientSounds::UpdateForCamType));
|
||||
}
|
||||
|
||||
void AmbientSounds::Uninit()
|
||||
|
@ -76,7 +76,7 @@ void AmbientSounds::Uninit()
|
|||
|
||||
void AmbientSounds::Update()
|
||||
{
|
||||
const float v_env = (Pi::game->GetWorldView()->GetCameraController()->IsExternal() ? 1.0f : 0.5f) * Sound::GetSfxVolume();
|
||||
const float v_env = (Pi::game->GetWorldView()->shipView.GetCameraController()->IsExternal() ? 1.0f : 0.5f) * Sound::GetSfxVolume();
|
||||
|
||||
if (Pi::player->GetFlightState() == Ship::DOCKED) {
|
||||
if (s_starNoise.IsPlaying()) {
|
||||
|
@ -264,8 +264,8 @@ void AmbientSounds::Update()
|
|||
|
||||
void AmbientSounds::UpdateForCamType()
|
||||
{
|
||||
const WorldView::CamType cam = Pi::game->GetWorldView()->GetCamType();
|
||||
float v_env = (cam == WorldView::CAM_EXTERNAL ? 1.0f : 0.5f) * Sound::GetSfxVolume();
|
||||
const ShipViewController::CamType cam = Pi::game->GetWorldView()->shipView.GetCamType();
|
||||
float v_env = (cam == ShipViewController::CAM_EXTERNAL ? 1.0f : 0.5f) * Sound::GetSfxVolume();
|
||||
|
||||
if (s_stationNoise.IsPlaying())
|
||||
s_stationNoise.SetVolume(0.3f * v_env, 0.3f * v_env);
|
||||
|
|
|
@ -31,6 +31,54 @@ void Input::InitGame()
|
|||
}
|
||||
}
|
||||
|
||||
InputResponse Input::InputFrame::ProcessSDLEvent(SDL_Event &event)
|
||||
{
|
||||
bool matched = false;
|
||||
|
||||
for (KeyBindings::ActionBinding *action : actions) {
|
||||
auto resp = action->CheckSDLEventAndDispatch(&event);
|
||||
if (resp == RESPONSE_MATCHED) return resp;
|
||||
matched = matched || resp > RESPONSE_NOMATCH;
|
||||
}
|
||||
|
||||
for (KeyBindings::AxisBinding *axis : axes) {
|
||||
auto resp = axis->CheckSDLEventAndDispatch(&event);
|
||||
if (resp == RESPONSE_MATCHED) return resp;
|
||||
matched = matched || resp > RESPONSE_NOMATCH;
|
||||
}
|
||||
|
||||
return matched ? RESPONSE_PASSTHROUGH : RESPONSE_NOMATCH;
|
||||
}
|
||||
|
||||
bool Input::PushInputFrame(Input::InputFrame *frame)
|
||||
{
|
||||
if (HasInputFrame(frame)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inputFrames.push_front(frame);
|
||||
frame->onFrameAdded();
|
||||
return true;
|
||||
}
|
||||
|
||||
Input::InputFrame *Input::PopInputFrame()
|
||||
{
|
||||
if (inputFrames.size() > 0) {
|
||||
auto frame = inputFrames.front();
|
||||
inputFrames.pop_front();
|
||||
frame->onFrameRemoved();
|
||||
return frame;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Input::RemoveInputFrame(Input::InputFrame *frame)
|
||||
{
|
||||
inputFrames.remove(frame);
|
||||
frame->onFrameRemoved();
|
||||
}
|
||||
|
||||
KeyBindings::ActionBinding *Input::AddActionBinding(std::string id, BindingGroup *group, KeyBindings::ActionBinding binding)
|
||||
{
|
||||
// TODO: should we throw an error if we attempt to bind over an already-bound action?
|
||||
|
@ -109,6 +157,11 @@ void Input::HandleSDLEvent(SDL_Event &event)
|
|||
joysticks[event.jhat.which].hats[event.jhat.hat] = event.jhat.value;
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto inputFrame : inputFrames) {
|
||||
auto resp = inputFrame->ProcessSDLEvent(event);
|
||||
if (resp == RESPONSE_MATCHED) break;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::InitJoysticks()
|
||||
|
|
40
src/Input.h
40
src/Input.h
|
@ -7,6 +7,9 @@
|
|||
#include "KeyBindings.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
|
||||
class Input {
|
||||
// TODO: better decouple these two classes.
|
||||
friend class Pi;
|
||||
|
@ -36,6 +39,41 @@ public:
|
|||
BindingPage *GetBindingPage(std::string id) { return &bindingPages[id]; }
|
||||
std::map<std::string, BindingPage> GetBindingPages() { return bindingPages; }
|
||||
|
||||
struct InputFrame {
|
||||
std::vector<KeyBindings::ActionBinding *> actions;
|
||||
std::vector<KeyBindings::AxisBinding *> axes;
|
||||
|
||||
// Call this at startup to register all the bindings associated with the frame.
|
||||
virtual void RegisterBindings(){};
|
||||
|
||||
// Called when the frame is added to the stack.
|
||||
virtual void onFrameAdded(){};
|
||||
|
||||
// Called when the frame is removed from the stack.
|
||||
virtual void onFrameRemoved(){};
|
||||
|
||||
// Check the event against all the inputs in this frame.
|
||||
InputResponse ProcessSDLEvent(SDL_Event &event);
|
||||
};
|
||||
|
||||
// Pushes an InputFrame onto the input stack.
|
||||
bool PushInputFrame(InputFrame *frame);
|
||||
|
||||
// Pops the most-recently pushed InputFrame from the stack.
|
||||
InputFrame *PopInputFrame();
|
||||
|
||||
// Get a read-only list of input frames.
|
||||
const std::list<InputFrame *> &GetInputFrames() { return inputFrames; }
|
||||
|
||||
// Check if a specific input frame is currently on the stack.
|
||||
bool HasInputFrame(InputFrame *frame)
|
||||
{
|
||||
return std::count(inputFrames.begin(), inputFrames.end(), frame) > 0;
|
||||
}
|
||||
|
||||
// Remove an arbitrary input frame from the input stack.
|
||||
void RemoveInputFrame(InputFrame *frame);
|
||||
|
||||
// Creates a new action binding, copying the provided binding.
|
||||
// The returned binding pointer points to the actual binding.
|
||||
KeyBindings::ActionBinding *AddActionBinding(std::string id, BindingGroup *group, KeyBindings::ActionBinding binding);
|
||||
|
@ -115,6 +153,8 @@ private:
|
|||
std::map<std::string, BindingPage> bindingPages;
|
||||
std::map<std::string, KeyBindings::ActionBinding> actionBindings;
|
||||
std::map<std::string, KeyBindings::AxisBinding> axisBindings;
|
||||
|
||||
std::list<InputFrame *> inputFrames;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -368,9 +368,9 @@ namespace KeyBindings {
|
|||
return binding1.Matches(sym) || binding2.Matches(sym);
|
||||
}
|
||||
|
||||
void ActionBinding::CheckSDLEventAndDispatch(const SDL_Event *event)
|
||||
InputResponse ActionBinding::CheckSDLEventAndDispatch(const SDL_Event *event)
|
||||
{
|
||||
if (m_disableBindings) return;
|
||||
if (m_disableBindings) return RESPONSE_NOMATCH;
|
||||
switch (event->type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP: {
|
||||
|
@ -379,6 +379,7 @@ namespace KeyBindings {
|
|||
onPress.emit();
|
||||
else if (event->key.state == SDL_RELEASED)
|
||||
onRelease.emit();
|
||||
return RESPONSE_MATCHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -389,6 +390,7 @@ namespace KeyBindings {
|
|||
onPress.emit();
|
||||
else if (event->jbutton.state == SDL_RELEASED)
|
||||
onRelease.emit();
|
||||
return RESPONSE_MATCHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -397,11 +399,13 @@ namespace KeyBindings {
|
|||
onPress.emit();
|
||||
// XXX to emit onRelease, we need to have access to the state of the joystick hat prior to this event,
|
||||
// so that we can detect the case of switching from a direction that matches the binding to some other direction
|
||||
return RESPONSE_MATCHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
return RESPONSE_NOMATCH;
|
||||
}
|
||||
|
||||
bool JoyAxisBinding::IsActive() const
|
||||
|
@ -587,15 +591,16 @@ namespace KeyBindings {
|
|||
return axis.IsActive() ? axis.GetValue() : value;
|
||||
}
|
||||
|
||||
void AxisBinding::CheckSDLEventAndDispatch(const SDL_Event *event)
|
||||
InputResponse AxisBinding::CheckSDLEventAndDispatch(const SDL_Event *event)
|
||||
{
|
||||
if (m_disableBindings) return;
|
||||
if (m_disableBindings) return RESPONSE_NOMATCH;
|
||||
float value = GetValue();
|
||||
switch (event->type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP: {
|
||||
if (positive.Matches(&event->key.keysym) && negative.Matches(&event->key.keysym)) {
|
||||
onAxis.emit(value);
|
||||
return RESPONSE_MATCHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -603,6 +608,7 @@ namespace KeyBindings {
|
|||
case SDL_JOYBUTTONUP: {
|
||||
if (positive.Matches(&event->jbutton) || negative.Matches(&event->jbutton)) {
|
||||
onAxis.emit(value);
|
||||
return RESPONSE_MATCHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -611,14 +617,20 @@ namespace KeyBindings {
|
|||
onAxis.emit(value);
|
||||
// XXX to emit onRelease, we need to have access to the state of the joystick hat prior to this event,
|
||||
// so that we can detect the case of switching from a direction that matches the binding to some other direction
|
||||
return RESPONSE_MATCHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_JOYAXISMOTION: {
|
||||
if (axis.Matches(event)) onAxis.emit(value);
|
||||
if (axis.Matches(event)) {
|
||||
onAxis.emit(value);
|
||||
return RESPONSE_MATCHED;
|
||||
}
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return RESPONSE_NOMATCH;
|
||||
}
|
||||
|
||||
void DispatchSDLEvent(const SDL_Event *event)
|
||||
|
|
|
@ -7,6 +7,15 @@
|
|||
#include "libs.h"
|
||||
#include <iosfwd>
|
||||
|
||||
enum InputResponse {
|
||||
// None of the inputs match the event.
|
||||
RESPONSE_NOMATCH = 0,
|
||||
// An input matched, but won't consume the event.
|
||||
RESPONSE_PASSTHROUGH,
|
||||
// An input matched and consumed the event.
|
||||
RESPONSE_MATCHED
|
||||
};
|
||||
|
||||
namespace KeyBindings {
|
||||
enum Type {
|
||||
BINDING_DISABLED,
|
||||
|
@ -104,7 +113,7 @@ namespace KeyBindings {
|
|||
std::string ToString() const;
|
||||
|
||||
bool IsActive() const;
|
||||
void CheckSDLEventAndDispatch(const SDL_Event *event);
|
||||
InputResponse CheckSDLEventAndDispatch(const SDL_Event *event);
|
||||
|
||||
bool Matches(const SDL_Keysym *sym) const;
|
||||
};
|
||||
|
@ -192,7 +201,7 @@ namespace KeyBindings {
|
|||
|
||||
bool IsActive() const;
|
||||
float GetValue() const;
|
||||
void CheckSDLEventAndDispatch(const SDL_Event *event);
|
||||
InputResponse CheckSDLEventAndDispatch(const SDL_Event *event);
|
||||
};
|
||||
|
||||
struct BindingPrototype {
|
||||
|
|
|
@ -22,7 +22,7 @@ static int l_dev_set_camera_offset(lua_State *l)
|
|||
{
|
||||
if (!Pi::game || !Pi::game->GetWorldView())
|
||||
return luaL_error(l, "Dev.SetCameraOffset only works when there is a game running");
|
||||
CameraController *cam = Pi::game->GetWorldView()->GetCameraController();
|
||||
CameraController *cam = Pi::game->GetWorldView()->shipView.GetCameraController();
|
||||
const float x = luaL_checknumber(l, 1);
|
||||
const float y = luaL_checknumber(l, 2);
|
||||
const float z = luaL_checknumber(l, 3);
|
||||
|
|
|
@ -576,11 +576,11 @@ static int l_game_set_view(lua_State *l)
|
|||
|
||||
static int l_game_get_world_cam_type(lua_State *l)
|
||||
{
|
||||
switch (Pi::game->GetWorldView()->GetCamType()) {
|
||||
case WorldView::CAM_INTERNAL: lua_pushstring(l, "internal"); break;
|
||||
case WorldView::CAM_EXTERNAL: lua_pushstring(l, "external"); break;
|
||||
case WorldView::CAM_SIDEREAL: lua_pushstring(l, "sidereal"); break;
|
||||
case WorldView::CAM_FLYBY: lua_pushstring(l, "flyby"); break;
|
||||
switch (Pi::game->GetWorldView()->shipView.GetCamType()) {
|
||||
case ShipViewController::CAM_INTERNAL: lua_pushstring(l, "internal"); break;
|
||||
case ShipViewController::CAM_EXTERNAL: lua_pushstring(l, "external"); break;
|
||||
case ShipViewController::CAM_SIDEREAL: lua_pushstring(l, "sidereal"); break;
|
||||
case ShipViewController::CAM_FLYBY: lua_pushstring(l, "flyby"); break;
|
||||
default: Output("Unknown world view cam type\n"); break;
|
||||
}
|
||||
return 1;
|
||||
|
@ -596,13 +596,13 @@ static int l_game_set_world_cam_type(lua_State *l)
|
|||
{
|
||||
std::string cam = luaL_checkstring(l, 1);
|
||||
if (!cam.compare("internal"))
|
||||
Pi::game->GetWorldView()->SetCamType(WorldView::CAM_INTERNAL);
|
||||
Pi::game->GetWorldView()->shipView.SetCamType(ShipViewController::CAM_INTERNAL);
|
||||
else if (!cam.compare("external"))
|
||||
Pi::game->GetWorldView()->SetCamType(WorldView::CAM_EXTERNAL);
|
||||
Pi::game->GetWorldView()->shipView.SetCamType(ShipViewController::CAM_EXTERNAL);
|
||||
else if (!cam.compare("sidereal"))
|
||||
Pi::game->GetWorldView()->SetCamType(WorldView::CAM_SIDEREAL);
|
||||
Pi::game->GetWorldView()->shipView.SetCamType(ShipViewController::CAM_SIDEREAL);
|
||||
else if (!cam.compare("flyby"))
|
||||
Pi::game->GetWorldView()->SetCamType(WorldView::CAM_FLYBY);
|
||||
Pi::game->GetWorldView()->shipView.SetCamType(ShipViewController::CAM_FLYBY);
|
||||
else {
|
||||
// TODO else error
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "galaxy/StarSystem.h"
|
||||
#include "gameui/Lua.h"
|
||||
#include "libs.h"
|
||||
#include "ship/ShipViewController.h"
|
||||
|
||||
#include "graphics/Renderer.h"
|
||||
|
||||
|
@ -421,6 +422,8 @@ void RegisterInputBindings()
|
|||
{
|
||||
PlayerShipController::RegisterInputBindings();
|
||||
|
||||
ShipViewController::InputBindings.RegisterBindings();
|
||||
|
||||
WorldView::RegisterInputBindings();
|
||||
}
|
||||
|
||||
|
|
|
@ -897,7 +897,7 @@ void Ship::DoThrusterSounds() const
|
|||
|
||||
// XXX sound logic could be part of a bigger class (ship internal sounds)
|
||||
/* Ship engine noise. less loud inside */
|
||||
float v_env = (Pi::game->GetWorldView()->GetCameraController()->IsExternal() ? 1.0f : 0.5f) * Sound::GetSfxVolume();
|
||||
float v_env = (Pi::game->GetWorldView()->shipView.GetCameraController()->IsExternal() ? 1.0f : 0.5f) * Sound::GetSfxVolume();
|
||||
static Sound::Event sndev;
|
||||
float volBoth = 0.0f;
|
||||
volBoth += 0.5f * fabs(GetPropulsion()->GetLinThrusterState().y);
|
||||
|
@ -1459,7 +1459,7 @@ void Ship::SetShipType(const ShipType::Id &shipId)
|
|||
Init();
|
||||
onFlavourChanged.emit();
|
||||
if (IsType(Object::PLAYER))
|
||||
Pi::game->GetWorldView()->SetCamType(Pi::game->GetWorldView()->GetCamType());
|
||||
Pi::game->GetWorldView()->shipView.SetCamType(Pi::game->GetWorldView()->shipView.GetCamType());
|
||||
InitEquipSet();
|
||||
|
||||
LuaEvent::Queue("onShipTypeChanged", this);
|
||||
|
|
|
@ -43,7 +43,7 @@ void ShipCockpit::Render(Graphics::Renderer *renderer, const Camera *camera, con
|
|||
|
||||
inline void ShipCockpit::resetInternalCameraController()
|
||||
{
|
||||
m_icc = static_cast<InternalCameraController *>(Pi::game->GetWorldView()->GetCameraController());
|
||||
m_icc = static_cast<InternalCameraController *>(Pi::game->GetWorldView()->shipView.GetCameraController());
|
||||
}
|
||||
|
||||
void ShipCockpit::Update(const Player *player, float timeStep)
|
||||
|
|
|
@ -141,17 +141,6 @@ void PlayerShipController::StaticUpdate(const float timeStep)
|
|||
int mouseMotion[2];
|
||||
SDL_GetRelativeMouseState(mouseMotion + 0, mouseMotion + 1); // call to flush
|
||||
|
||||
// external camera mouselook
|
||||
if (Pi::input.MouseButtonState(SDL_BUTTON_MIDDLE)) {
|
||||
MoveableCameraController *mcc = static_cast<MoveableCameraController *>(Pi::game->GetWorldView()->GetCameraController());
|
||||
const double accel = 0.01; // XXX configurable?
|
||||
mcc->RotateLeft(mouseMotion[0] * accel);
|
||||
mcc->RotateUp(mouseMotion[1] * accel);
|
||||
// only mouselook if the player presses both mmb and rmb
|
||||
mouseMotion[0] = 0;
|
||||
mouseMotion[1] = 0;
|
||||
}
|
||||
|
||||
if (m_ship->GetFlightState() == Ship::FLYING) {
|
||||
switch (m_flightControlState) {
|
||||
case CONTROL_FIXSPEED:
|
||||
|
|
|
@ -33,8 +33,6 @@
|
|||
const double WorldView::PICK_OBJECT_RECT_SIZE = 20.0;
|
||||
namespace {
|
||||
static const Color s_hudTextColor(0, 255, 0, 230);
|
||||
static const float ZOOM_SPEED = 1.f;
|
||||
static const float WHEEL_SENSITIVITY = .05f; // Should be a variable in user settings.
|
||||
static const float HUD_CROSSHAIR_SIZE = 8.0f;
|
||||
static const Color white(255, 255, 255, 204);
|
||||
static const Color green(0, 255, 0, 204);
|
||||
|
@ -44,27 +42,26 @@ namespace {
|
|||
|
||||
WorldView::WorldView(Game *game) :
|
||||
UIView(),
|
||||
m_game(game)
|
||||
m_game(game),
|
||||
shipView(this)
|
||||
{
|
||||
m_camType = CAM_INTERNAL;
|
||||
InitObject();
|
||||
}
|
||||
|
||||
WorldView::WorldView(const Json &jsonObj, Game *game) :
|
||||
UIView(),
|
||||
m_game(game)
|
||||
m_game(game),
|
||||
shipView(this)
|
||||
{
|
||||
if (!jsonObj["world_view"].is_object()) throw SavedGameCorruptException();
|
||||
Json worldViewObj = jsonObj["world_view"];
|
||||
|
||||
if (!worldViewObj["cam_type"].is_number_integer()) throw SavedGameCorruptException();
|
||||
m_camType = CamType(worldViewObj["cam_type"]);
|
||||
shipView.m_camType = worldViewObj["cam_type"];
|
||||
|
||||
InitObject();
|
||||
|
||||
m_internalCameraController->LoadFromJson(worldViewObj);
|
||||
m_externalCameraController->LoadFromJson(worldViewObj);
|
||||
m_siderealCameraController->LoadFromJson(worldViewObj);
|
||||
m_flybyCameraController->LoadFromJson(worldViewObj);
|
||||
shipView.LoadFromJson(jsonObj);
|
||||
}
|
||||
|
||||
WorldView::InputBinding WorldView::InputBindings;
|
||||
|
@ -85,23 +82,6 @@ void WorldView::RegisterInputBindings()
|
|||
KEY_BINDING(toggleHudMode, "BindToggleHudMode", SDLK_TAB, 0)
|
||||
KEY_BINDING(increaseTimeAcceleration, "BindIncreaseTimeAcceleration", SDLK_PAGEUP, 0)
|
||||
KEY_BINDING(decreaseTimeAcceleration, "BindDecreaseTimeAcceleration", SDLK_PAGEDOWN, 0)
|
||||
|
||||
BINDING_GROUP(GENERAL_VIEW_CONTROLS)
|
||||
AXIS_BINDING(viewZoom, "BindViewZoom", SDLK_EQUALS, SDLK_MINUS)
|
||||
|
||||
BINDING_GROUP(INTERNAL_VIEW)
|
||||
KEY_BINDING(frontCamera, "BindFrontCamera", SDLK_KP_8, SDLK_UP)
|
||||
KEY_BINDING(rearCamera, "BindRearCamera", SDLK_KP_2, SDLK_DOWN)
|
||||
KEY_BINDING(leftCamera, "BindLeftCamera", SDLK_KP_4, SDLK_LEFT)
|
||||
KEY_BINDING(rightCamera, "BindRightCamera", SDLK_KP_6, SDLK_RIGHT)
|
||||
KEY_BINDING(topCamera, "BindTopCamera", SDLK_KP_9, 0)
|
||||
KEY_BINDING(bottomCamera, "BindBottomCamera", SDLK_KP_3, 0)
|
||||
|
||||
BINDING_GROUP(EXTERNAL_VIEW)
|
||||
AXIS_BINDING(cameraRoll, "BindCameraRoll", SDLK_KP_1, SDLK_KP_3)
|
||||
AXIS_BINDING(cameraPitch, "BindCameraPitch", SDLK_KP_2, SDLK_KP_8)
|
||||
AXIS_BINDING(cameraYaw, "BindCameraYaw", SDLK_KP_4, SDLK_KP_6)
|
||||
KEY_BINDING(resetCamera, "BindResetCamera", SDLK_HOME, 0)
|
||||
}
|
||||
|
||||
void WorldView::InitObject()
|
||||
|
@ -165,18 +145,11 @@ void WorldView::InitObject()
|
|||
|
||||
m_cameraContext.Reset(new CameraContext(Graphics::GetScreenWidth(), Graphics::GetScreenHeight(), fovY, znear, zfar));
|
||||
m_camera.reset(new Camera(m_cameraContext, Pi::renderer));
|
||||
m_internalCameraController.reset(new InternalCameraController(m_cameraContext, Pi::player));
|
||||
m_externalCameraController.reset(new ExternalCameraController(m_cameraContext, Pi::player));
|
||||
m_siderealCameraController.reset(new SiderealCameraController(m_cameraContext, Pi::player));
|
||||
m_flybyCameraController.reset(new FlyByCameraController(m_cameraContext, Pi::player));
|
||||
SetCamType(m_camType); //set the active camera
|
||||
shipView.Init();
|
||||
|
||||
m_onPlayerChangeTargetCon =
|
||||
Pi::onPlayerChangeTarget.connect(sigc::mem_fun(this, &WorldView::OnPlayerChangeTarget));
|
||||
m_onMouseWheelCon =
|
||||
Pi::input.onMouseWheel.connect(sigc::mem_fun(this, &WorldView::MouseWheel));
|
||||
|
||||
Pi::player->GetPlayerController()->SetMouseForRearView(GetCamType() == CAM_INTERNAL && m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR);
|
||||
m_onToggleHudModeCon = InputBindings.toggleHudMode->onPress.connect(sigc::mem_fun(this, &WorldView::OnToggleLabels));
|
||||
m_onIncTimeAccelCon = InputBindings.increaseTimeAcceleration->onPress.connect(sigc::mem_fun(this, &WorldView::OnRequestTimeAccelInc));
|
||||
m_onDecTimeAccelCon = InputBindings.decreaseTimeAcceleration->onPress.connect(sigc::mem_fun(this, &WorldView::OnRequestTimeAccelDec));
|
||||
|
@ -185,7 +158,6 @@ void WorldView::InitObject()
|
|||
WorldView::~WorldView()
|
||||
{
|
||||
m_onPlayerChangeTargetCon.disconnect();
|
||||
m_onMouseWheelCon.disconnect();
|
||||
m_onToggleHudModeCon.disconnect();
|
||||
m_onIncTimeAccelCon.disconnect();
|
||||
m_onDecTimeAccelCon.disconnect();
|
||||
|
@ -195,57 +167,11 @@ void WorldView::SaveToJson(Json &jsonObj)
|
|||
{
|
||||
Json worldViewObj = Json::object(); // Create JSON object to contain world view data.
|
||||
|
||||
worldViewObj["cam_type"] = int(m_camType);
|
||||
m_internalCameraController->SaveToJson(worldViewObj);
|
||||
m_externalCameraController->SaveToJson(worldViewObj);
|
||||
m_siderealCameraController->SaveToJson(worldViewObj);
|
||||
m_flybyCameraController->SaveToJson(worldViewObj);
|
||||
shipView.SaveToJson(worldViewObj);
|
||||
|
||||
jsonObj["world_view"] = worldViewObj; // Add world view object to supplied object.
|
||||
}
|
||||
|
||||
void WorldView::SetCamType(enum CamType c)
|
||||
{
|
||||
Pi::BoinkNoise();
|
||||
|
||||
// don't allow external cameras when docked inside space stations.
|
||||
// they would clip through the station model
|
||||
//if (Pi::player->GetFlightState() == Ship::DOCKED && !Pi::player->GetDockedWith()->IsGroundStation())
|
||||
// c = CAM_INTERNAL;
|
||||
|
||||
m_camType = c;
|
||||
|
||||
switch (m_camType) {
|
||||
case CAM_INTERNAL:
|
||||
m_activeCameraController = m_internalCameraController.get();
|
||||
Pi::player->OnCockpitActivated();
|
||||
break;
|
||||
case CAM_EXTERNAL:
|
||||
m_activeCameraController = m_externalCameraController.get();
|
||||
break;
|
||||
case CAM_SIDEREAL:
|
||||
m_activeCameraController = m_siderealCameraController.get();
|
||||
break;
|
||||
case CAM_FLYBY:
|
||||
m_activeCameraController = m_flybyCameraController.get();
|
||||
break;
|
||||
}
|
||||
|
||||
Pi::player->GetPlayerController()->SetMouseForRearView(m_camType == CAM_INTERNAL && m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR);
|
||||
|
||||
m_activeCameraController->Reset();
|
||||
|
||||
onChangeCamType.emit();
|
||||
}
|
||||
|
||||
void WorldView::ChangeInternalCameraMode(InternalCameraController::Mode m)
|
||||
{
|
||||
if (m_internalCameraController->GetMode() != m)
|
||||
Pi::BoinkNoise();
|
||||
m_internalCameraController->SetMode(m);
|
||||
Pi::player->GetPlayerController()->SetMouseForRearView(m_camType == CAM_INTERNAL && m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR);
|
||||
}
|
||||
|
||||
/* This is UI click to change flight control state (manual, speed ctrl) */
|
||||
void WorldView::ChangeFlightState()
|
||||
{
|
||||
|
@ -308,9 +234,9 @@ void WorldView::Draw3D()
|
|||
|
||||
Body *excludeBody = nullptr;
|
||||
ShipCockpit *cockpit = nullptr;
|
||||
if (GetCamType() == CAM_INTERNAL) {
|
||||
if (shipView.GetCamType() == ShipViewController::CAM_INTERNAL) {
|
||||
excludeBody = Pi::player;
|
||||
if (m_internalCameraController->GetMode() == InternalCameraController::MODE_FRONT)
|
||||
if (shipView.m_internalCameraController->GetMode() == InternalCameraController::MODE_FRONT)
|
||||
cockpit = Pi::player->GetCockpit();
|
||||
}
|
||||
m_camera->Draw(excludeBody, cockpit);
|
||||
|
@ -414,42 +340,7 @@ void WorldView::Update()
|
|||
// show state-appropriate buttons
|
||||
RefreshButtonStateAndVisibility();
|
||||
|
||||
// XXX ugly hack checking for console here
|
||||
if (!Pi::IsConsoleActive()) {
|
||||
if (GetCamType() == CAM_INTERNAL) {
|
||||
if (InputBindings.frontCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_FRONT);
|
||||
else if (InputBindings.rearCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_REAR);
|
||||
else if (InputBindings.leftCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_LEFT);
|
||||
else if (InputBindings.rightCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_RIGHT);
|
||||
else if (InputBindings.topCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_TOP);
|
||||
else if (InputBindings.bottomCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_BOTTOM);
|
||||
} else {
|
||||
MoveableCameraController *cam = static_cast<MoveableCameraController *>(m_activeCameraController);
|
||||
vector3d rotate = vector3d(
|
||||
-InputBindings.cameraPitch->GetValue(),
|
||||
InputBindings.cameraYaw->GetValue(),
|
||||
InputBindings.cameraRoll->GetValue());
|
||||
|
||||
// Horribly abuse our knowledge of the internals of cam->RotateUp/Down.
|
||||
if (rotate.x != 0.0) cam->RotateUp(frameTime * rotate.x);
|
||||
if (rotate.y != 0.0) cam->RotateLeft(frameTime * rotate.y);
|
||||
if (rotate.z != 0.0) cam->RollLeft(frameTime * rotate.z);
|
||||
|
||||
if (InputBindings.viewZoom->IsActive())
|
||||
cam->ZoomEvent(-InputBindings.viewZoom->GetValue() * ZOOM_SPEED * frameTime);
|
||||
if (InputBindings.resetCamera->IsActive())
|
||||
cam->Reset();
|
||||
cam->ZoomEventUpdate(frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
m_activeCameraController->Update();
|
||||
shipView.Update();
|
||||
|
||||
m_cameraContext->BeginFrame();
|
||||
m_camera->Update();
|
||||
|
@ -498,10 +389,12 @@ void WorldView::OnSwitchTo()
|
|||
{
|
||||
UIView::OnSwitchTo();
|
||||
RefreshButtonStateAndVisibility();
|
||||
shipView.Activated();
|
||||
}
|
||||
|
||||
void WorldView::OnSwitchFrom()
|
||||
{
|
||||
shipView.Deactivated();
|
||||
Pi::DrawGUI = true;
|
||||
}
|
||||
|
||||
|
@ -545,13 +438,14 @@ void WorldView::OnPlayerChangeTarget()
|
|||
|
||||
int WorldView::GetActiveWeapon() const
|
||||
{
|
||||
switch (GetCamType()) {
|
||||
case CAM_INTERNAL:
|
||||
return m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR ? 1 : 0;
|
||||
using CamType = ShipViewController::CamType;
|
||||
switch (shipView.GetCamType()) {
|
||||
case CamType::CAM_INTERNAL:
|
||||
return shipView.m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR ? 1 : 0;
|
||||
|
||||
case CAM_EXTERNAL:
|
||||
case CAM_SIDEREAL:
|
||||
case CAM_FLYBY:
|
||||
case CamType::CAM_EXTERNAL:
|
||||
case CamType::CAM_SIDEREAL:
|
||||
case CamType::CAM_FLYBY:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -585,8 +479,8 @@ void WorldView::UpdateProjectedObjects()
|
|||
// calculate firing solution and relative velocity along our z axis
|
||||
int laser = -1;
|
||||
double projspeed = 0;
|
||||
if (GetCamType() == CAM_INTERNAL) {
|
||||
switch (m_internalCameraController->GetMode()) {
|
||||
if (shipView.GetCamType() == ShipViewController::CAM_INTERNAL) {
|
||||
switch (shipView.m_internalCameraController->GetMode()) {
|
||||
case InternalCameraController::MODE_FRONT: laser = 0; break;
|
||||
case InternalCameraController::MODE_REAR: laser = 1; break;
|
||||
default: break;
|
||||
|
@ -907,19 +801,6 @@ void WorldView::DrawEdgeMarker(const Indicator &marker, const Color &c)
|
|||
m_edgeMarker.Draw(m_renderer, m_blendState);
|
||||
}
|
||||
|
||||
void WorldView::MouseWheel(bool up)
|
||||
{
|
||||
if (this == Pi::GetView()) {
|
||||
if (m_activeCameraController->IsExternal()) {
|
||||
MoveableCameraController *cam = static_cast<MoveableCameraController *>(m_activeCameraController);
|
||||
|
||||
if (!up) // Zoom out
|
||||
cam->ZoomEvent(ZOOM_SPEED * WHEEL_SENSITIVITY);
|
||||
else
|
||||
cam->ZoomEvent(-ZOOM_SPEED * WHEEL_SENSITIVITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
NavTunnelWidget::NavTunnelWidget(WorldView *worldview, Graphics::RenderState *rs) :
|
||||
Widget(),
|
||||
m_worldView(worldview),
|
||||
|
@ -935,7 +816,7 @@ void NavTunnelWidget::Draw()
|
|||
if (navtarget) {
|
||||
const vector3d navpos = navtarget->GetPositionRelTo(Pi::player);
|
||||
const matrix3x3d &rotmat = Pi::player->GetOrient();
|
||||
const vector3d eyevec = rotmat * m_worldView->m_activeCameraController->GetOrient().VectorZ();
|
||||
const vector3d eyevec = rotmat * m_worldView->shipView.GetCameraController()->GetOrient().VectorZ();
|
||||
if (eyevec.Dot(navpos) >= 0.0) return;
|
||||
|
||||
const double distToDest = Pi::player->GetPositionRelTo(navtarget).Length();
|
||||
|
@ -1091,7 +972,7 @@ static vector3d projectToScreenSpace(const vector3d &pos, RefCountedPtr<CameraCo
|
|||
// needs to run inside m_cameraContext->Begin/EndFrame();
|
||||
vector3d WorldView::WorldSpaceToScreenSpace(const Body *body) const
|
||||
{
|
||||
if (body->IsType(Object::PLAYER) && GetCamType() == CAM_INTERNAL)
|
||||
if (body->IsType(Object::PLAYER) && shipView.GetCamType() == ShipViewController::CAM_INTERNAL)
|
||||
return vector3d(0, 0, 0);
|
||||
const Frame *cam_frame = m_cameraContext->GetCamFrame();
|
||||
vector3d pos = body->GetInterpPositionRelTo(cam_frame);
|
||||
|
@ -1126,7 +1007,7 @@ vector3d WorldView::CameraSpaceToScreenSpace(const vector3d &pos) const
|
|||
// needs to run inside m_cameraContext->Begin/EndFrame();
|
||||
vector3d WorldView::GetTargetIndicatorScreenPosition(const Body *body) const
|
||||
{
|
||||
if (body->IsType(Object::PLAYER) && GetCamType() == CAM_INTERNAL)
|
||||
if (body->IsType(Object::PLAYER) && shipView.GetCamType() == ShipViewController::CAM_INTERNAL)
|
||||
return vector3d(0, 0, 0);
|
||||
const Frame *cam_frame = m_cameraContext->GetCamFrame();
|
||||
vector3d pos = body->GetTargetIndicatorPosition(cam_frame);
|
||||
|
@ -1140,7 +1021,7 @@ vector3d WorldView::GetMouseDirection() const
|
|||
const Frame *cam_frame = m_cameraContext->GetCamFrame();
|
||||
matrix3x3d cam_rot = cam_frame->GetInterpOrient();
|
||||
vector3d mouseDir = Pi::player->GetPlayerController()->GetMouseDir() * cam_rot;
|
||||
if (GetCamType() == CAM_INTERNAL && m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR)
|
||||
if (shipView.GetCamType() == ShipViewController::CAM_INTERNAL && shipView.m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR)
|
||||
mouseDir = -mouseDir;
|
||||
return (Pi::player->GetPhysRadius() * 1.5) * mouseDir;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "SpeedLines.h"
|
||||
#include "UIView.h"
|
||||
#include "gui/GuiWidget.h"
|
||||
#include "ship/ShipViewController.h"
|
||||
|
||||
class Body;
|
||||
class Frame;
|
||||
|
@ -54,15 +55,10 @@ public:
|
|||
static const double PICK_OBJECT_RECT_SIZE;
|
||||
virtual void SaveToJson(Json &jsonObj);
|
||||
virtual void HandleSDLEvent(SDL_Event &event);
|
||||
enum CamType {
|
||||
CAM_INTERNAL,
|
||||
CAM_EXTERNAL,
|
||||
CAM_SIDEREAL,
|
||||
CAM_FLYBY
|
||||
};
|
||||
void SetCamType(enum CamType);
|
||||
enum CamType GetCamType() const { return m_camType; }
|
||||
CameraController *GetCameraController() const { return m_activeCameraController; }
|
||||
|
||||
RefCountedPtr<CameraContext> GetCameraContext() const { return m_cameraContext; }
|
||||
|
||||
ShipViewController shipView;
|
||||
|
||||
/* start deprecated */
|
||||
void ChangeFlightState();
|
||||
|
@ -71,8 +67,6 @@ public:
|
|||
int GetActiveWeapon() const;
|
||||
void OnClickBlastoff();
|
||||
|
||||
sigc::signal<void> onChangeCamType;
|
||||
|
||||
std::tuple<double, double, double> CalculateHeadingPitchRoll(enum PlaneType);
|
||||
|
||||
vector3d WorldSpaceToScreenSpace(const Body *body) const;
|
||||
|
@ -97,8 +91,6 @@ private:
|
|||
|
||||
void RefreshButtonStateAndVisibility();
|
||||
|
||||
void ChangeInternalCameraMode(InternalCameraController::Mode m);
|
||||
|
||||
enum IndicatorSide {
|
||||
INDICATOR_HIDDEN,
|
||||
INDICATOR_ONSCREEN,
|
||||
|
@ -135,7 +127,7 @@ private:
|
|||
void OnRequestTimeAccelInc();
|
||||
/// Handler for "requestTimeAccelerationDec" event
|
||||
void OnRequestTimeAccelDec();
|
||||
void MouseWheel(bool up);
|
||||
void SelectBody(Body *, bool reselectIsDeselect);
|
||||
|
||||
Game *m_game;
|
||||
|
||||
|
@ -144,7 +136,6 @@ private:
|
|||
|
||||
Gui::Label *m_pauseText;
|
||||
bool m_labelsOn;
|
||||
enum CamType m_camType;
|
||||
|
||||
/* Only use #if WITH_DEVKEYS */
|
||||
Gui::Label *m_debugInfo;
|
||||
|
@ -158,18 +149,12 @@ private:
|
|||
sigc::connection m_onHyperspaceTargetChangedCon;
|
||||
sigc::connection m_onPlayerChangeTargetCon;
|
||||
sigc::connection m_onChangeFlightControlStateCon;
|
||||
sigc::connection m_onMouseWheelCon;
|
||||
sigc::connection m_onToggleHudModeCon;
|
||||
sigc::connection m_onIncTimeAccelCon;
|
||||
sigc::connection m_onDecTimeAccelCon;
|
||||
|
||||
RefCountedPtr<CameraContext> m_cameraContext;
|
||||
std::unique_ptr<Camera> m_camera;
|
||||
std::unique_ptr<InternalCameraController> m_internalCameraController;
|
||||
std::unique_ptr<ExternalCameraController> m_externalCameraController;
|
||||
std::unique_ptr<SiderealCameraController> m_siderealCameraController;
|
||||
std::unique_ptr<FlyByCameraController> m_flybyCameraController;
|
||||
CameraController *m_activeCameraController; //one of the above
|
||||
|
||||
Indicator m_combatTargetIndicator;
|
||||
Indicator m_targetLeadIndicator;
|
||||
|
@ -186,20 +171,6 @@ private:
|
|||
ActionBinding *toggleHudMode;
|
||||
ActionBinding *increaseTimeAcceleration;
|
||||
ActionBinding *decreaseTimeAcceleration;
|
||||
|
||||
AxisBinding *viewZoom;
|
||||
|
||||
ActionBinding *frontCamera;
|
||||
ActionBinding *rearCamera;
|
||||
ActionBinding *leftCamera;
|
||||
ActionBinding *rightCamera;
|
||||
ActionBinding *topCamera;
|
||||
ActionBinding *bottomCamera;
|
||||
|
||||
AxisBinding *cameraRoll;
|
||||
AxisBinding *cameraPitch;
|
||||
AxisBinding *cameraYaw;
|
||||
ActionBinding *resetCamera;
|
||||
} InputBindings;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
class WorldView;
|
||||
|
||||
class InteractionController {
|
||||
public:
|
||||
InteractionController(WorldView *v) :
|
||||
parentView(v) {}
|
||||
|
||||
virtual void Activated() = 0;
|
||||
virtual void Deactivated() = 0;
|
||||
virtual void Update() = 0;
|
||||
|
||||
WorldView *parentView;
|
||||
};
|
|
@ -0,0 +1,214 @@
|
|||
|
||||
#include "ShipViewController.h"
|
||||
#include "CameraController.h"
|
||||
#include "WorldView.h"
|
||||
|
||||
#include "Pi.h"
|
||||
#include "Player.h"
|
||||
|
||||
namespace {
|
||||
static const float ZOOM_SPEED = 1.f;
|
||||
static const float WHEEL_SENSITIVITY = .05f; // Should be a variable in user settings.
|
||||
} // namespace
|
||||
|
||||
ShipViewController::InputBinding ShipViewController::InputBindings;
|
||||
|
||||
void ShipViewController::InputBinding::RegisterBindings()
|
||||
{
|
||||
using namespace KeyBindings;
|
||||
|
||||
Input::BindingPage *page = Pi::input.GetBindingPage("VIEW");
|
||||
Input::BindingGroup *group;
|
||||
|
||||
#define BINDING_GROUP(n) group = page->GetBindingGroup(#n);
|
||||
#define KEY_BINDING(n, id, k1, k2) \
|
||||
n = \
|
||||
Pi::input.AddActionBinding(id, group, ActionBinding(k1, k2)); \
|
||||
actions.push_back(n);
|
||||
#define AXIS_BINDING(n, id, k1, k2) \
|
||||
n = \
|
||||
Pi::input.AddAxisBinding(id, group, AxisBinding(k1, k2)); \
|
||||
axes.push_back(n);
|
||||
|
||||
BINDING_GROUP(GENERAL_VIEW_CONTROLS)
|
||||
KEY_BINDING(cycleCameraMode, "BindCycleCameraMode", SDLK_F1, 0)
|
||||
|
||||
AXIS_BINDING(cameraRoll, "BindCameraRoll", SDLK_KP_1, SDLK_KP_3)
|
||||
AXIS_BINDING(cameraPitch, "BindCameraPitch", SDLK_KP_2, SDLK_KP_8)
|
||||
AXIS_BINDING(cameraYaw, "BindCameraYaw", SDLK_KP_4, SDLK_KP_6)
|
||||
AXIS_BINDING(cameraZoom, "BindViewZoom", SDLK_EQUALS, SDLK_MINUS)
|
||||
|
||||
KEY_BINDING(frontCamera, "BindFrontCamera", SDLK_KP_8, SDLK_UP)
|
||||
KEY_BINDING(rearCamera, "BindRearCamera", SDLK_KP_2, SDLK_DOWN)
|
||||
KEY_BINDING(leftCamera, "BindLeftCamera", SDLK_KP_4, SDLK_LEFT)
|
||||
KEY_BINDING(rightCamera, "BindRightCamera", SDLK_KP_6, SDLK_RIGHT)
|
||||
KEY_BINDING(topCamera, "BindTopCamera", SDLK_KP_9, 0)
|
||||
KEY_BINDING(bottomCamera, "BindBottomCamera", SDLK_KP_3, 0)
|
||||
|
||||
KEY_BINDING(resetCamera, "BindResetCamera", SDLK_HOME, 0)
|
||||
|
||||
#undef BINDING_GROUP
|
||||
#undef KEY_BINDING
|
||||
#undef AXIS_BINDING
|
||||
}
|
||||
|
||||
void ShipViewController::LoadFromJson(const Json &jsonObj)
|
||||
{
|
||||
m_internalCameraController->LoadFromJson(jsonObj);
|
||||
m_externalCameraController->LoadFromJson(jsonObj);
|
||||
m_siderealCameraController->LoadFromJson(jsonObj);
|
||||
m_flybyCameraController->LoadFromJson(jsonObj);
|
||||
}
|
||||
|
||||
void ShipViewController::SaveToJson(Json &jsonObj)
|
||||
{
|
||||
jsonObj["cam_type"] = int(m_camType);
|
||||
m_internalCameraController->SaveToJson(jsonObj);
|
||||
m_externalCameraController->SaveToJson(jsonObj);
|
||||
m_siderealCameraController->SaveToJson(jsonObj);
|
||||
m_flybyCameraController->SaveToJson(jsonObj);
|
||||
}
|
||||
|
||||
void ShipViewController::Init()
|
||||
{
|
||||
RefCountedPtr<CameraContext> m_cameraContext = parentView->GetCameraContext();
|
||||
m_internalCameraController.reset(new InternalCameraController(m_cameraContext, Pi::player));
|
||||
m_externalCameraController.reset(new ExternalCameraController(m_cameraContext, Pi::player));
|
||||
m_siderealCameraController.reset(new SiderealCameraController(m_cameraContext, Pi::player));
|
||||
m_flybyCameraController.reset(new FlyByCameraController(m_cameraContext, Pi::player));
|
||||
SetCamType(m_camType); //set the active camera
|
||||
}
|
||||
|
||||
void ShipViewController::Activated()
|
||||
{
|
||||
Pi::input.PushInputFrame(&InputBindings);
|
||||
|
||||
m_onMouseWheelCon =
|
||||
Pi::input.onMouseWheel.connect(sigc::mem_fun(this, &ShipViewController::MouseWheel));
|
||||
|
||||
Pi::player->GetPlayerController()->SetMouseForRearView(GetCamType() == CAM_INTERNAL && m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR);
|
||||
}
|
||||
|
||||
void ShipViewController::Deactivated()
|
||||
{
|
||||
Pi::input.RemoveInputFrame(&InputBindings);
|
||||
|
||||
m_onMouseWheelCon.disconnect();
|
||||
}
|
||||
|
||||
void ShipViewController::SetCamType(enum CamType c)
|
||||
{
|
||||
Pi::BoinkNoise();
|
||||
|
||||
// don't allow external cameras when docked inside space stations.
|
||||
// they would clip through the station model
|
||||
//if (Pi::player->GetFlightState() == Ship::DOCKED && !Pi::player->GetDockedWith()->IsGroundStation())
|
||||
// c = CAM_INTERNAL;
|
||||
|
||||
m_camType = c;
|
||||
|
||||
switch (m_camType) {
|
||||
case CAM_INTERNAL:
|
||||
m_activeCameraController = m_internalCameraController.get();
|
||||
Pi::player->OnCockpitActivated();
|
||||
break;
|
||||
case CAM_EXTERNAL:
|
||||
m_activeCameraController = m_externalCameraController.get();
|
||||
break;
|
||||
case CAM_SIDEREAL:
|
||||
m_activeCameraController = m_siderealCameraController.get();
|
||||
break;
|
||||
case CAM_FLYBY:
|
||||
m_activeCameraController = m_flybyCameraController.get();
|
||||
break;
|
||||
}
|
||||
|
||||
Pi::player->GetPlayerController()->SetMouseForRearView(m_camType == CAM_INTERNAL && m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR);
|
||||
|
||||
m_activeCameraController->Reset();
|
||||
|
||||
onChangeCamType.emit();
|
||||
}
|
||||
|
||||
void ShipViewController::ChangeInternalCameraMode(InternalCameraController::Mode m)
|
||||
{
|
||||
if (m_internalCameraController->GetMode() != m)
|
||||
Pi::BoinkNoise();
|
||||
m_internalCameraController->SetMode(m);
|
||||
Pi::player->GetPlayerController()->SetMouseForRearView(m_camType == CAM_INTERNAL && m_internalCameraController->GetMode() == InternalCameraController::MODE_REAR);
|
||||
}
|
||||
|
||||
void ShipViewController::Update()
|
||||
{
|
||||
auto *cam = static_cast<MoveableCameraController *>(m_activeCameraController);
|
||||
auto frameTime = Pi::GetFrameTime();
|
||||
|
||||
vector3d rotate = vector3d(
|
||||
-InputBindings.cameraPitch->GetValue(),
|
||||
InputBindings.cameraYaw->GetValue(),
|
||||
InputBindings.cameraRoll->GetValue());
|
||||
|
||||
// Horribly abuse our knowledge of the internals of cam->RotateUp/Down.
|
||||
if (rotate.x != 0.0) cam->RotateUp(frameTime * rotate.x);
|
||||
if (rotate.y != 0.0) cam->RotateLeft(frameTime * rotate.y);
|
||||
if (rotate.z != 0.0) cam->RollLeft(frameTime * rotate.z);
|
||||
|
||||
// XXX ugly hack checking for console here
|
||||
if (!Pi::IsConsoleActive()) {
|
||||
if (GetCamType() == CAM_INTERNAL) {
|
||||
if (InputBindings.frontCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_FRONT);
|
||||
else if (InputBindings.rearCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_REAR);
|
||||
else if (InputBindings.leftCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_LEFT);
|
||||
else if (InputBindings.rightCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_RIGHT);
|
||||
else if (InputBindings.topCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_TOP);
|
||||
else if (InputBindings.bottomCamera->IsActive())
|
||||
ChangeInternalCameraMode(InternalCameraController::MODE_BOTTOM);
|
||||
} else {
|
||||
MoveableCameraController *cam = static_cast<MoveableCameraController *>(m_activeCameraController);
|
||||
vector3d rotate = vector3d(
|
||||
-InputBindings.cameraPitch->GetValue(),
|
||||
InputBindings.cameraYaw->GetValue(),
|
||||
InputBindings.cameraRoll->GetValue());
|
||||
|
||||
// Horribly abuse our knowledge of the internals of cam->RotateUp/Down.
|
||||
if (rotate.x != 0.0) cam->RotateUp(frameTime * rotate.x);
|
||||
if (rotate.y != 0.0) cam->RotateLeft(frameTime * rotate.y);
|
||||
if (rotate.z != 0.0) cam->RollLeft(frameTime * rotate.z);
|
||||
|
||||
if (InputBindings.cameraZoom->IsActive())
|
||||
cam->ZoomEvent(-InputBindings.cameraZoom->GetValue() * ZOOM_SPEED * frameTime);
|
||||
if (InputBindings.resetCamera->IsActive())
|
||||
cam->Reset();
|
||||
cam->ZoomEventUpdate(frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
int mouseMotion[2];
|
||||
Pi::input.GetMouseMotion(mouseMotion);
|
||||
|
||||
// external camera mouselook
|
||||
if (Pi::input.MouseButtonState(SDL_BUTTON_MIDDLE)) {
|
||||
const double accel = 0.01; // XXX configurable?
|
||||
cam->RotateLeft(mouseMotion[0] * accel);
|
||||
cam->RotateUp(mouseMotion[1] * accel);
|
||||
}
|
||||
|
||||
m_activeCameraController->Update();
|
||||
}
|
||||
|
||||
void ShipViewController::MouseWheel(bool up)
|
||||
{
|
||||
if (m_activeCameraController->IsExternal()) {
|
||||
MoveableCameraController *cam = static_cast<MoveableCameraController *>(m_activeCameraController);
|
||||
|
||||
if (!up) // Zoom out
|
||||
cam->ZoomEvent(ZOOM_SPEED * WHEEL_SENSITIVITY);
|
||||
else
|
||||
cam->ZoomEvent(-ZOOM_SPEED * WHEEL_SENSITIVITY);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "CameraController.h"
|
||||
#include "Input.h"
|
||||
#include "InteractionController.h"
|
||||
#include "KeyBindings.h"
|
||||
#include "utils.h"
|
||||
|
||||
class ShipViewController : public InteractionController {
|
||||
public:
|
||||
ShipViewController(WorldView *v) :
|
||||
InteractionController(v),
|
||||
m_camType(CAM_INTERNAL) {}
|
||||
|
||||
virtual void Update();
|
||||
virtual void Activated();
|
||||
virtual void Deactivated();
|
||||
|
||||
enum CamType {
|
||||
CAM_INTERNAL,
|
||||
CAM_EXTERNAL,
|
||||
CAM_SIDEREAL,
|
||||
CAM_FLYBY
|
||||
};
|
||||
void SetCamType(enum CamType);
|
||||
enum CamType GetCamType() const { return m_camType; }
|
||||
CameraController *GetCameraController() const { return m_activeCameraController; }
|
||||
|
||||
sigc::signal<void> onChangeCamType;
|
||||
|
||||
private:
|
||||
friend class WorldView;
|
||||
void ChangeInternalCameraMode(InternalCameraController::Mode m);
|
||||
|
||||
enum CamType m_camType;
|
||||
|
||||
sigc::connection m_onMouseWheelCon;
|
||||
|
||||
std::unique_ptr<InternalCameraController> m_internalCameraController;
|
||||
std::unique_ptr<ExternalCameraController> m_externalCameraController;
|
||||
std::unique_ptr<SiderealCameraController> m_siderealCameraController;
|
||||
std::unique_ptr<FlyByCameraController> m_flybyCameraController;
|
||||
CameraController *m_activeCameraController; //one of the above
|
||||
|
||||
void MouseWheel(bool up);
|
||||
|
||||
public:
|
||||
void Init();
|
||||
void LoadFromJson(const Json &jsonObj);
|
||||
void SaveToJson(Json &jsonObj);
|
||||
|
||||
static struct InputBinding : public Input::InputFrame {
|
||||
using Action = KeyBindings::ActionBinding;
|
||||
using Axis = KeyBindings::AxisBinding;
|
||||
|
||||
Axis *cameraYaw;
|
||||
Axis *cameraPitch;
|
||||
Axis *cameraRoll;
|
||||
Axis *cameraZoom;
|
||||
|
||||
Action *frontCamera;
|
||||
Action *rearCamera;
|
||||
Action *leftCamera;
|
||||
Action *rightCamera;
|
||||
Action *topCamera;
|
||||
Action *bottomCamera;
|
||||
|
||||
Action *cycleCameraMode;
|
||||
Action *resetCamera;
|
||||
|
||||
virtual void RegisterBindings();
|
||||
} InputBindings;
|
||||
};
|
Loading…
Reference in New Issue