forked from TheSuperHackers/GeneralsGameCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathView.h
More file actions
370 lines (300 loc) · 18.8 KB
/
View.h
File metadata and controls
370 lines (300 loc) · 18.8 KB
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** 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/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// View.h /////////////////////////////////////////////////////////////////////////////////////////
// A "view", or window, into the World
// Author: Michael S. Booth, February 2001
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/GameType.h"
#include "Common/Snapshot.h"
#include "Lib/BaseType.h"
#include "WW3D2/coltype.h" ///< we don't generally do this, but we need the W3D collision types
#define DEFAULT_VIEW_WIDTH 640
#define DEFAULT_VIEW_HEIGHT 480
#define DEFAULT_VIEW_ORIGIN_X 0
#define DEFAULT_VIEW_ORIGIN_Y 0
// FORWARD DECLARATIONS ///////////////////////////////////////////////////////////////////////////
class Drawable;
class ViewLocation;
class Thing;
class Waypoint;
class LookAtTranslator;
enum FilterTypes CPP_11(: Int);
enum FilterModes CPP_11(: Int);
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
enum PickType CPP_11(: Int)
{
PICK_TYPE_TERRAIN = COLL_TYPE_0,
PICK_TYPE_SELECTABLE = COLL_TYPE_1,
PICK_TYPE_SHRUBBERY = COLL_TYPE_2,
PICK_TYPE_MINES = COLL_TYPE_3, // mines aren't normally selectable, but workers/dozers need to
PICK_TYPE_FORCEATTACKABLE = COLL_TYPE_4,
PICK_TYPE_ALL_DRAWABLES = (PICK_TYPE_SELECTABLE | PICK_TYPE_SHRUBBERY | PICK_TYPE_MINES | PICK_TYPE_FORCEATTACKABLE)
};
// ------------------------------------------------------------------------------------------------
/** The implementation of common view functionality. */
// ------------------------------------------------------------------------------------------------
class View : public Snapshot
{
public:
enum
{
ZoomHeightPerSecond = 10,
};
/// Add an impulse force to shake the camera
enum CameraShakeType
{
SHAKE_SUBTLE = 0,
SHAKE_NORMAL,
SHAKE_STRONG,
SHAKE_SEVERE,
SHAKE_CINE_EXTREME, //Added for cinematics ONLY
SHAKE_CINE_INSANE, //Added for cinematics ONLY
SHAKE_COUNT
};
// Return values for worldToScreenTriReturn
enum WorldToScreenReturn CPP_11(: Int)
{
WTS_INSIDE_FRUSTUM = 0, // On the screen (inside frustum of camera)
WTS_OUTSIDE_FRUSTUM, // Return is valid but off the screen (outside frustum of camera)
WTS_INVALID, // No transform possible
};
public:
View();
virtual ~View();
virtual void init();
virtual void reset();
virtual UnsignedInt getID() { return m_id; }
virtual void setZoomLimited( Bool limit ) { m_zoomLimited = limit; } ///< limit the zoom height
virtual Bool isZoomLimited() { return m_zoomLimited; } ///< get status of zoom limit
/// pick drawable given the screen pixel coords. If force attack, picks bridges as well.
virtual Drawable *pickDrawable( const ICoord2D *screen, Bool forceAttack, PickType pickType ) = 0;
/// all drawables in the 2D screen region will call the 'callback'
virtual Int iterateDrawablesInRegion( IRegion2D *screenRegion,
Bool (*callback)( Drawable *draw, void *userData ),
void *userData ) = 0;
/** project the 4 corners of this view into the world and return each point as a parameter,
the world points are at the requested Z */
virtual void getScreenCornerWorldPointsAtZ( Coord3D *topLeft, Coord3D *topRight,
Coord3D *bottomRight, Coord3D *bottomLeft,
Real z );
virtual void setWidth( Int width ) { m_width = width; }
virtual Int getWidth() { return m_width; }
virtual void setHeight( Int height ) { m_height = height; }
virtual Int getHeight() { return m_height; }
virtual void setOrigin( Int x, Int y) { m_originX=x; m_originY=y;} ///< Sets location of top-left view corner on display
virtual void getOrigin( Int *x, Int *y) { *x=m_originX; *y=m_originY;} ///< Return location of top-left view corner on display
virtual void lockViewUntilFrame(UnsignedInt frame); ///< Locks the current view until the given frame is reached.
virtual void forceRedraw() = 0;
virtual void lookAt( const Coord3D *o ); ///< Center the view on the given coordinate
virtual void initHeightForMap() {}; ///< Init the camera height for the map at the current position.
virtual void scrollBy( Coord2D *delta ); ///< Shift the view by the given delta
virtual void moveCameraTo(const Coord3D *o, Int frames, Int shutter, Bool orient, Real easeIn=0.0f, Real easeOut=0.0f) { lookAt( o ); }
virtual void moveCameraAlongWaypointPath(Waypoint *way, Int frames, Int shutter, Bool orient, Real easeIn=0.0f, Real easeOut=0.0f) { }
virtual Bool isCameraMovementFinished() { return TRUE; }
virtual void cameraModFinalZoom(Real finalZoom, Real easeIn=0.0f, Real easeOut=0.0f){}; ///< Final zoom for current camera movement.
virtual void cameraModRollingAverage(Int framesToAverage){}; ///< Number of frames to average movement for current camera movement.
virtual void cameraModFinalTimeMultiplier(Int finalMultiplier){}; ///< Final time multiplier for current camera movement.
virtual void cameraModFinalPitch(Real finalPitch, Real easeIn=0.0f, Real easeOut=0.0f){}; ///< Final pitch for current camera movement.
virtual void cameraModFreezeTime(){ } ///< Freezes time during the next camera movement.
virtual void cameraModFreezeAngle(){ } ///< Freezes time during the next camera movement.
virtual void cameraModLookToward(Coord3D *pLoc){} ///< Sets a look at point during camera movement.
virtual void cameraModFinalLookToward(Coord3D *pLoc){} ///< Sets a look at point during camera movement.
virtual void cameraModFinalMoveTo(Coord3D *pLoc){ }; ///< Sets a final move to.
// (gth) C&C3 animation controlled camera feature
virtual void cameraEnableSlaveMode(const AsciiString & thingtemplateName, const AsciiString & boneName) {}
virtual void cameraDisableSlaveMode() {}
virtual void Add_Camera_Shake(const Coord3D & position,float radius, float duration, float power) {}
virtual FilterModes getViewFilterMode() {return (FilterModes)0;} ///< Turns on viewport special effect (black & white mode)
virtual FilterTypes getViewFilterType() {return (FilterTypes)0;} ///< Turns on viewport special effect (black & white mode)
virtual Bool setViewFilterMode(FilterModes filterMode) { return FALSE; } ///< Turns on viewport special effect (black & white mode)
virtual void setViewFilterPos(const Coord3D *pos) { }; ///< Passes a position to the special effect filter.
virtual Bool setViewFilter( FilterTypes filter) { return FALSE;} ///< Turns on viewport special effect (black & white mode)
virtual void setFadeParameters(Int fadeFrames, Int direction) { };
virtual void set3DWireFrameMode(Bool enable) { };
virtual void resetCamera(const Coord3D *location, Int frames, Real easeIn=0.0f, Real easeOut=0.0f) {}; ///< Move camera to location, and reset to default angle & zoom.
virtual void rotateCamera(Real rotations, Int frames, Real easeIn=0.0f, Real easeOut=0.0f) {}; ///< Rotate camera about current viewpoint.
virtual void rotateCameraTowardObject(ObjectID id, Int milliseconds, Int holdMilliseconds, Real easeIn=0.0f, Real easeOut=0.0f) {}; ///< Rotate camera to face an object, and hold on it
virtual void rotateCameraTowardPosition(const Coord3D *pLoc, Int milliseconds, Real easeIn=0.0f, Real easeOut=0.0f, Bool reverseRotation=FALSE) {}; ///< Rotate camera to face a location.
virtual Bool isTimeFrozen(){ return false;} ///< Freezes time during the next camera movement.
virtual Int getTimeMultiplier() {return 1;}; ///< Get the time multiplier.
virtual void setTimeMultiplier(Int multiple) {}; ///< Set the time multiplier.
virtual void setDefaultView(Real pitch, Real angle, Real maxHeight) {}; // TheSuperHackers @todo Replace with setDefaultPitch(), setMaxHeightScale()
virtual void zoomCamera( Real finalZoom, Int milliseconds, Real easeIn=0.0f, Real easeOut=0.0f ) {};
virtual void pitchCamera( Real finalPitch, Int milliseconds, Real easeIn=0.0f, Real easeOut=0.0f ) {};
virtual void setAngle( Real radians ); ///< Rotate the view around the vertical axis to the given angle (yaw)
virtual Real getAngle() { return m_angle; } ///< Return current camera angle
virtual void setPitch( Real radians ); ///< Rotate the view around the horizontal axis to the given angle (pitch)
virtual Real getPitch() { return m_pitch; } ///< Return current camera pitch
virtual void setAngleToDefault(); ///< Set the view angle back to default
virtual void setPitchToDefault(); ///< Set the view pitch back to default
virtual void getPosition(Coord3D *pos) { *pos=m_pos;} ///< Returns position camera is looking at (z will be zero)
virtual const Coord3D& get3DCameraPosition() const = 0; ///< Returns the actual camera position
virtual Real getZoom() { return m_zoom; }
virtual void setZoom(Real z) { m_zoom = z; }
virtual Real getHeightAboveGround() { return m_heightAboveGround; }
virtual void setHeightAboveGround(Real z);
virtual void zoom( Real height ); ///< Zoom in/out, closer to the ground, limit to min, or farther away from the ground, limit to max
virtual void setZoomToDefault() { m_zoom = 1.0f; } ///< Set zoom to default value
virtual void setOkToAdjustHeight( Bool val ) { m_okToAdjustHeight = val; } ///< Set this to adjust camera height
// for debugging
virtual Real getTerrainHeightAtPivot() { return m_terrainHeightAtPivot; }
virtual Real getCurrentHeightAboveGround() { return m_currentHeightAboveGround; }
virtual void setFieldOfView( Real angle ) { m_FOV = angle; } ///< Set the horizontal field of view angle
virtual Real getFieldOfView() { return m_FOV; } ///< Get the horizontal field of view angle
Bool worldToScreen( const Coord3D *w, ICoord2D *s ) { return worldToScreenTriReturn( w, s ) == WTS_INSIDE_FRUSTUM; } ///< Transform world coordinate "w" into screen coordinate "s"
virtual WorldToScreenReturn worldToScreenTriReturn(const Coord3D *w, ICoord2D *s ) = 0; ///< Like worldToScreen(), but with a more informative return value
virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) = 0; ///< transform screen coord to a point on the 3D terrain
virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) = 0; ///< transform screen point to world point at the specified world Z value
virtual void getLocation ( ViewLocation *location ); ///< write the view's current location in to the view location object
virtual void setLocation ( const ViewLocation *location ); ///< set the view's current location from to the view location object
virtual void drawView() = 0; ///< Render the world visible in this view.
virtual void updateView() = 0; ///<called once per frame to determine the final camera and object transforms
virtual void stepView() = 0; ///< Update view for every fixed time step
virtual ObjectID getCameraLock() const { return m_cameraLock; }
virtual void setCameraLock(ObjectID id) { m_cameraLock = id; m_lockDist = 0.0f; m_lockType = LOCK_FOLLOW; }
virtual void snapToCameraLock() { m_snapImmediate = TRUE; }
enum CameraLockType { LOCK_FOLLOW, LOCK_TETHER };
virtual void setSnapMode( CameraLockType lockType, Real lockDist ) { m_lockType = lockType; m_lockDist = lockDist; }
virtual Drawable *getCameraLockDrawable() const { return m_cameraLockDrawable; }
virtual void setCameraLockDrawable(Drawable *drawable) { m_cameraLockDrawable = drawable; m_lockDist = 0.0f; }
virtual void setMouseLock( Bool mouseLocked ) { m_mouseLocked = mouseLocked; } ///< lock/unlock the mouse input to the tactical view
virtual Bool isMouseLocked() { return m_mouseLocked; } ///< is the mouse input locked to the tactical view?
/// Add an impulse force to shake the camera
virtual void shake( const Coord3D *epicenter, CameraShakeType shakeType ) { };
virtual Real getFXPitch() const { return 1.0f; } ///< returns the FX pitch angle
virtual void forceCameraAreaConstraintRecalc() {}
virtual void setGuardBandBias( const Coord2D *gb ) = 0;
protected:
friend class Display;
// snapshot methods
virtual void crc( Xfer *xfer ) { }
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess() { }
void setPosition( const Coord3D *pos ) { m_pos = *pos; }
const Coord3D *getPosition() const { return &m_pos; }
virtual View *prependViewToList( View *list ); ///< Prepend this view to the given list, return the new list
virtual View *getNextView() { return m_next; } ///< Return next view in the set
// **********************************************************************************************
View *m_next; ///< List links used by the Display class
UnsignedInt m_id; ///< The ID of this view
static UnsignedInt m_idNext; ///< Used for allocating view ID's for all views
UnsignedInt m_viewLockedUntilFrame;
Coord3D m_pos; ///< Pivot of the camera, in world coordinates // TheSuperHackers @todo Make this Coord2D or use the Z component
Int m_width, m_height; ///< Dimensions of the view
Int m_originX, m_originY; ///< Location of top/left view corner
Real m_angle; ///< Angle at which view has been rotated about the Z axis. Expected normalized
Real m_pitch; ///< Rotation of view direction around horizontal (X) axis. Expected normalized
Real m_maxHeightAboveGround; ///< Highest camera above ground value
Real m_minHeightAboveGround; ///< Lowest camera above ground value
Real m_zoom; ///< Current zoom value
Real m_heightAboveGround; ///< User's desired camera height above ground
Bool m_zoomLimited; ///< Camera restricted in zoom height
Real m_defaultAngle; ///< Expected normalized
Real m_defaultPitch; ///< Expected normalized
Real m_currentHeightAboveGround; ///< Actual camera height above ground, or rather height above ground at default pitch
Real m_terrainHeightAtPivot; ///< Actual terrain height at camera pivot
ObjectID m_cameraLock; ///< if nonzero, id of object that the camera should follow
Drawable *m_cameraLockDrawable; ///< if nonzero, drawable of object that camera should follow.
CameraLockType m_lockType; ///< are we following or just tethering?
Real m_lockDist; ///< how far can we be when tethered?
Real m_FOV; ///< the current field of view angle
Bool m_mouseLocked; ///< is the mouse input locked to the tactical view?
Bool m_okToAdjustHeight; ///< Should we attempt to adjust camera height?
Bool m_snapImmediate; ///< Should we immediately snap to the object we're following?
Coord2D m_guardBandBias; ///< Extra beefy margins so huge thins can stay "on-screen"
};
// ------------------------------------------------------------------------------------------------
/** Used to save and restore view position */
// ------------------------------------------------------------------------------------------------
class ViewLocation
{
friend class View;
friend class LookAtTranslator;
protected:
Bool m_valid; ///< Is this location valid
Coord3D m_pos; ///< Position of this view, in world coordinates
Real m_angle; ///< Angle at which view has been rotated about the Z axis
Real m_pitch; ///< Angle at which view has been rotated about the Y axis
Real m_zoom; ///< Current zoom value
public:
ViewLocation()
{
m_valid = FALSE;
m_pos.zero();
m_angle = m_pitch = m_zoom = 0.0;
}
const Coord3D& getPosition() const { return m_pos; }
Bool isValid() const { return m_valid; }
Real getAngle() const { return m_angle; }
Real getPitch() const { return m_pitch; }
Real getZoom() const { return m_zoom; }
void init(Real x, Real y, Real z, Real angle, Real pitch, Real zoom)
{
m_pos.x = x;
m_pos.y = y;
m_pos.z = z;
m_angle = angle;
m_pitch = pitch;
m_zoom = zoom;
m_valid = true;
}
};
// TheSuperHackers @feature bobtista 31/01/2026
// View that does nothing. Used for Headless Mode.
class ViewDummy : public View
{
public:
virtual Drawable *pickDrawable( const ICoord2D *screen, Bool forceAttack, PickType pickType ) override
{
return nullptr;
}
virtual Int iterateDrawablesInRegion( IRegion2D *screenRegion, Bool (*callback)( Drawable *draw, void *userData ), void *userData ) override
{
return 0;
}
virtual void forceRedraw() override {}
virtual const Coord3D& get3DCameraPosition() const override
{
static Coord3D zero = {0,0,0};
return zero;
}
virtual WorldToScreenReturn worldToScreenTriReturn(const Coord3D *w, ICoord2D *s ) override
{
return WTS_INVALID;
}
virtual void screenToWorld( const ICoord2D *s, Coord3D *w ) override {}
virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) override {}
virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) override {}
virtual void drawView( void ) override {}
virtual void updateView(void) override {}
virtual void stepView() override {}
virtual void setGuardBandBias( const Coord2D *gb ) override {}
// TheSuperHackers @bugfix bobtista 03/02/2026 Do not override View::xfer(). The base
// implementation must run to serialize valid view state for save file compatibility.
};
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern View *TheTacticalView; ///< the main tactical interface to the game world