1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#ifndef _CAMERA_CONTROLLER_H
#define _CAMERA_CONTROLLER_H
#include <algorithm>
#include <array>
#include <string>
#include "System/float3.h"
class CCameraController
{
public:
struct StateMap {
public:
typedef std::pair<std::string, float> MapPair;
typedef std::array<MapPair, 32> ArrayMap;
typedef ArrayMap::iterator iterator;
typedef ArrayMap::const_iterator const_iterator;
iterator begin() { return (pairsMap.begin()); }
iterator end() { return (pairsMap.begin() + numPairs); }
const_iterator cbegin() const { return (pairsMap.cbegin()); }
const_iterator cend() const { return (pairsMap.cbegin() + numPairs); }
const_iterator find(const std::string& s) const {
const auto pair = std::make_pair(s, 0.0f);
const auto pred = [](const MapPair& a, const MapPair& b) { return (a.first < b.first); };
const auto iter = std::lower_bound(cbegin(), cend(), pair, pred);
if (iter == cend() || iter->first != s)
return (cend());
return iter;
}
float operator [](const std::string& s) const {
const auto iter = find(s);
if (iter == cend())
return 0.0f;
return iter->second;
}
float& operator [](const std::string& s) {
const auto iter = find(s);
if (iter == cend()) {
// Spring.SetCameraState might be handed a table larger than we can hold
if (numPairs == pairsMap.size())
return dummyPair.second;
pairsMap[numPairs++] = std::make_pair(s, 0.0f);
// inefficient on repeated insertions, but map size is a small constant
for (size_t i = numPairs - 1; i > 0; i--) {
if (pairsMap[i - 1].first < pairsMap[i].first)
return pairsMap[i].second;
std::swap(pairsMap[i - 1], pairsMap[i]);
}
return pairsMap[0].second;
}
return pairsMap[iter - cbegin()].second;
}
bool operator == (const StateMap& sm) const {
return (numPairs == sm.numPairs && pairsMap == sm.pairsMap);
}
bool empty() const { return (numPairs == 0); }
void clear() {
numPairs = 0;
for (auto& pair: pairsMap) {
pair = {};
}
}
private:
ArrayMap pairsMap;
MapPair dummyPair;
size_t numPairs = 0;
};
public:
CCameraController();
virtual ~CCameraController() {}
virtual const std::string GetName() const = 0;
virtual void KeyMove(float3 move) = 0;
virtual void MouseMove(float3 move) = 0;
virtual void ScreenEdgeMove(float3 move) = 0;
virtual void MouseWheelMove(float move) = 0;
virtual void Update() {}
float GetFOV() const { return fov; } //< In degrees!
virtual float3 GetPos() const { return pos; }
virtual float3 GetDir() const { return dir; }
virtual float3 GetRot() const;
virtual void SetPos(const float3& newPos) { pos = newPos; }
virtual void SetDir(const float3& newDir) { dir = newDir; }
virtual bool DisableTrackingByKey() { return true; }
// return the position to send to new controllers SetPos
virtual float3 SwitchFrom() const = 0;
virtual void SwitchTo(const int oldCam, const bool showText = true) = 0;
virtual void GetState(StateMap& sm) const;
virtual bool SetState(const StateMap& sm);
virtual void SetTrackingInfo(const float3& pos, float radius) { SetPos(pos); }
/**
* Whether the camera's distance to the ground or to the units
* should be used to determine whether to show them as icons or normal.
* This is called every frame, so it can be dynamically,
* eg depend on the current position/angle.
*/
virtual bool GetUseDistToGroundForIcons();
/// should this mode appear when we toggle the camera controller?
bool enabled;
protected:
bool SetStateBool(const StateMap& sm, const std::string& name, bool& var);
bool SetStateFloat(const StateMap& sm, const std::string& name, float& var);
float fov;
float3 pos;
float3 dir;
/**
* @brief scrollSpeed
* scales the scroll speed in general
* (includes middleclick, arrowkey, screenedge scrolling)
*/
float scrollSpeed;
/**
* @brief switchVal
* Where to switch from Camera-Unit-distance to Camera-Ground-distance
* for deciding whether to draw 3D view or icon of units.
* * 1.0 = 0 degree = overview
* * 0.0 = 90 degree = first person
*/
float switchVal;
float pixelSize;
};
#endif // _CAMERA_CONTROLLER_H
|