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 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Definition for the game viewports and cameras.
//
//=============================================================================
#ifndef AGS_ENGINE_GAME_VIEWPORT_H
#define AGS_ENGINE_GAME_VIEWPORT_H
#include "common/std/memory.h"
#include "common/std/vector.h"
#include "ags/shared/util/geometry.h"
#include "ags/shared/util/scaling.h"
namespace AGS3 {
class Camera;
class Viewport;
typedef std::shared_ptr<Camera> PCamera;
typedef std::shared_ptr<Viewport> PViewport;
typedef std::weak_ptr<Camera> CameraRef;
typedef std::weak_ptr<Viewport> ViewportRef;
// TODO: move to utility header
// From https://stackoverflow.com/questions/45507041/how-to-check-if-weak-ptr-is-empty-non-assigned
// Tests that weak_ptr is empty (was not initialized with valid reference)
template <typename T>
bool is_uninitialized(std::weak_ptr<T> const &weak) {
using wt = std::weak_ptr<T>;
return !weak.owner_before(wt{}) &&!wt{} .owner_before(weak);
}
// Camera defines a "looking eye" inside the room, its position and size.
// It does not render anywhere on its own, instead it is linked to a viewport
// and latter draws what that camera sees.
// One camera may be linked to multiple viewports.
// Camera does not move on its own, this is performed by separate behavior
// algorithm. But it provides "lock" property that tells if its position is
// currently owned by user script.
class Camera {
public:
// Gets camera ID (serves as an index)
inline int GetID() const {
return _id;
}
// Sets new camera ID
void SetID(int id);
// Returns Room camera position and size inside the room (in room coordinates)
const Rect &GetRect() const;
// Sets explicit room camera's orthographic size
void SetSize(const Size sz);
// Puts room camera to the new location in the room
void SetAt(int x, int y);
// Tells if camera is currently locked at custom position
bool IsLocked() const;
// Locks room camera at its current position
void Lock();
// Similar to SetAt, but also locks camera preventing it from following player character
void LockAt(int x, int y);
// Releases camera lock, letting it follow player character
void Release();
// Link this camera to a new viewport; this does not unlink any linked ones
void LinkToViewport(ViewportRef viewport);
// Unlinks this camera from a given viewport; does nothing if link did not exist
void UnlinkFromViewport(int id);
// Get the array of linked viewport references
const std::vector<ViewportRef> &GetLinkedViewports() const;
// Tell if this camera has changed recently
inline bool HasChangedPosition() const {
return _hasChangedPosition;
}
inline bool HasChangedSize() const {
return _hasChangedSize;
}
// Clears the changed flags
void ClearChangedFlags() {
_hasChangedPosition = false;
_hasChangedSize = false;
}
private:
int _id = -1;
// Actual position and orthographic size
Rect _position;
// Locked or following player automatically
bool _locked = false;
// Linked viewport refs, used to notify viewports of camera changes
std::vector<ViewportRef> _viewportRefs;
// Flags that tell whether this camera's position on screen has changed recently
bool _hasChangedPosition = false;
bool _hasChangedSize = false;
};
// A result of coordinate conversion between screen and the room,
// tells which viewport was used to pass the "touch" through.
typedef std::pair<Point, int> VpPoint;
// Viewport class defines a rectangular area on game screen where the contents
// of a Camera are rendered.
// Viewport may have one linked camera at a time.
class Viewport {
public:
// Gets viewport ID (serves as an index)
inline int GetID() const {
return _id;
}
// Sets new viewport ID
void SetID(int id);
// Returns viewport's position on screen
inline const Rect &GetRect() const {
return _position;
}
// Returns viewport's room-to-screen transformation
inline const AGS::Shared::PlaneScaling &GetTransform() const {
return _transform;
}
// Set viewport's rectangle on screen
void SetRect(const Rect &rc);
// Sets viewport size
void SetSize(const Size sz);
// Sets viewport's position on screen
void SetAt(int x, int y);
// Tells whether viewport content is rendered on screen
bool IsVisible() const {
return _visible;
}
// Changes viewport visibility
void SetVisible(bool on);
// Gets the order viewport is displayed on screen
int GetZOrder() const {
return _zorder;
}
// Sets the viewport's z-order on screen
void SetZOrder(int zorder);
// Calculates room-to-viewport coordinate conversion.
void AdjustTransformation();
// Returns linked camera
PCamera GetCamera() const;
// Links new camera to this viewport, overriding existing link;
// pass nullptr to leave viewport without a camera link
void LinkCamera(PCamera cam);
// TODO: provide a Transform object here that does these conversions instead
// Converts room coordinates to the game screen coordinates through this viewport;
// if clipping is on, the function will fail for room coordinates outside of camera
VpPoint RoomToScreen(int roomx, int roomy, bool clip = false) const;
// Converts game screen coordinates to the room coordinates through this viewport;
// if clipping is on, the function will fail for screen coordinates outside of viewport;
// convert_cam_to_data parameter converts camera "game" coordinates to "data" units (legacy mode)
VpPoint ScreenToRoom(int scrx, int scry, bool clip = false, bool convert_cam_to_data = false) const;
// Following functions tell if this viewport has changed recently
inline bool HasChangedPosition() const {
return _hasChangedPosition;
}
inline bool HasChangedSize() const {
return _hasChangedSize;
}
inline bool HasChangedVisible() const {
return _hasChangedVisible;
}
inline void SetChangedVisible() {
_hasChangedVisible = true;
}
// Clears the changed flags
inline void ClearChangedFlags() {
_hasChangedPosition = false;
_hasChangedSize = false;
_hasChangedVisible = false;
}
private:
// Parameterized implementation of screen-to-room coordinate conversion
VpPoint ScreenToRoomImpl(int scrx, int scry, bool clip, bool convert_cam_to_data);
int _id = -1;
// Position of the viewport on screen
Rect _position;
// TODO: Camera reference (when supporting multiple cameras)
// Coordinate transform between camera and viewport
// TODO: need to add rotate conversion to let script API support that;
// (maybe use full 3D matrix for that)
AGS::Shared::PlaneScaling _transform;
// Linked camera reference
CameraRef _camera;
bool _visible = true;
int _zorder = 0;
// Flags that tell whether this viewport's position on screen has changed recently
bool _hasChangedPosition = false;
bool _hasChangedOffscreen = false;
bool _hasChangedSize = false;
bool _hasChangedVisible = false;
};
} // namespace AGS3
#endif // AGS_ENGINE_AC_VIEWPORT_H
|