openmohaa/code/fgame/camera.h

453 lines
12 KiB
C
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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 2 of the License,
or (at your option) any later version.
OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// camera.h: Camera. Duh.
2023-10-13 19:11:51 +02:00
//
2016-03-27 11:49:47 +02:00
2023-10-13 19:11:51 +02:00
#pragma once
2016-03-27 11:49:47 +02:00
#include "g_local.h"
#include "entity.h"
#include "bspline.h"
#include "container.h"
2023-01-29 20:59:31 +01:00
#include "level.h"
2016-03-27 11:49:47 +02:00
#define CAMERA_SWITCHTIME 0.5f
2023-10-13 19:11:51 +02:00
#define ORBIT (1 << 0)
#define START_ON (1 << 1)
#define AUTOMATIC (1 << 2)
#define NO_TRACE (1 << 3)
#define NO_WATCH (1 << 4)
#define LEVEL_EXIT (1 << 5)
2016-03-27 11:49:47 +02:00
extern Event EV_Camera_CameraThink;
extern Event EV_Camera_StartMoving;
extern Event EV_Camera_Pause;
extern Event EV_Camera_Continue;
extern Event EV_Camera_StopMoving;
extern Event EV_Camera_SetSpeed;
extern Event EV_Camera_SetFollowDistance;
extern Event EV_Camera_SetOrbitHeight;
extern Event EV_Camera_SetYaw;
extern Event EV_Camera_AbsoluteYaw;
extern Event EV_Camera_RelativeYaw;
extern Event EV_Camera_SetFOV;
extern Event EV_Camera_Orbit;
extern Event EV_Camera_Follow;
extern Event EV_Camera_Watch;
extern Event EV_Camera_WatchPath;
extern Event EV_Camera_LookAt;
extern Event EV_Camera_TurnTo;
extern Event EV_Camera_MoveToEntity;
extern Event EV_Camera_MoveToPos;
extern Event EV_Camera_NoWatch;
extern Event EV_Camera_FadeTime;
extern Event EV_Camera_Cut;
class Camera;
class CameraMoveState : public Class
2023-10-13 19:11:51 +02:00
{
public:
Vector pos;
Vector movedir; // direction of travel
Vector angles; // angles from spline camera
BSpline cameraPath;
SplinePathPtr splinePath;
SplinePathPtr currentNode;
SplinePathPtr loopNode;
float cameraTime;
int lastTime;
int newTime;
qboolean followingpath;
EntityPtr followEnt;
EntityPtr orbitEnt;
void operator=(CameraMoveState& newstate);
void Evaluate(Camera *camera);
void Initialize(Camera *camera);
void DoNodeEvents(Camera *camera);
void Archive(Archiver& arc) override;
};
inline void CameraMoveState::operator=(CameraMoveState& newstate)
{
movedir = newstate.movedir;
pos = newstate.pos;
angles = newstate.angles;
cameraPath = newstate.cameraPath;
splinePath = newstate.splinePath;
currentNode = newstate.currentNode;
loopNode = newstate.loopNode;
cameraTime = newstate.cameraTime;
lastTime = newstate.lastTime;
newTime = newstate.newTime;
followEnt = newstate.followEnt;
orbitEnt = newstate.orbitEnt;
followingpath = newstate.followingpath;
}
inline void CameraMoveState::Archive(Archiver& arc)
{
arc.ArchiveVector(&movedir);
arc.ArchiveVector(&pos);
arc.ArchiveVector(&angles);
cameraPath.Archive(arc);
arc.ArchiveSafePointer(&splinePath);
arc.ArchiveSafePointer(&currentNode);
arc.ArchiveSafePointer(&loopNode);
arc.ArchiveFloat(&cameraTime);
arc.ArchiveInteger(&lastTime);
arc.ArchiveInteger(&newTime);
arc.ArchiveSafePointer(&followEnt);
arc.ArchiveSafePointer(&orbitEnt);
arc.ArchiveBoolean(&followingpath);
}
class CameraWatchState : public Class
{
public:
Vector watchAngles;
EntityPtr watchEnt;
qboolean watchNodes;
qboolean watchPath;
void Evaluate(Camera *camera, CameraMoveState *move);
void Initialize(Camera *camera);
void Archive(Archiver& arc) override;
};
inline void CameraWatchState::Archive(Archiver& arc)
{
arc.ArchiveVector(&watchAngles);
arc.ArchiveSafePointer(&watchEnt);
arc.ArchiveBoolean(&watchNodes);
arc.ArchiveBoolean(&watchPath);
}
class CameraState : public Class
{
public:
CameraMoveState move;
CameraWatchState watch;
float fov;
void Evaluate(Camera *camera);
void Initialize(Camera *camera);
void Archive(Archiver& arc) override;
};
inline void CameraState::Archive(Archiver& arc)
{
move.Archive(arc);
watch.Archive(arc);
arc.ArchiveFloat(&fov);
}
2016-03-27 11:49:47 +02:00
class Camera : public Entity
{
2023-10-13 19:11:51 +02:00
private:
friend class CameraState;
friend class CameraWatchState;
friend class CameraMoveState;
//
// follow parameters
//
float follow_yaw;
qboolean follow_yaw_fixed;
float follow_dist;
int follow_mask;
// camera speed
float camera_speed;
// current camera fov
float camera_fov;
// orbit height
float orbit_height;
// orbit_dotrace
qboolean orbit_dotrace;
// whether or not auto calculate fov, a non-zero value means yes
float auto_fov;
// automatic variables
float automatic_startTime;
float automatic_stopTime;
float automatic_radius;
float automatic_maxFOV;
qboolean automatic_active;
Container<str> automatic_states;
// Miscellaneous
Vector m_vPosOffset;
protected:
CameraState currentstate;
CameraState newstate;
float watchTime; // if non-zero, camera view is transitioning
float followTime; // if non-zero, camera position is tranisitioning
float fovTime; // if non-zero, fov is being lerped
float fadeTime; // time to transition over
float fovFadeTime; // time for fov transition
float followFadeTime; // time for fov transition
float watchFadeTime; // time for fov transition
bool m_bShowquakes;
str nextCamera;
qboolean showcamera;
void SetupCamera(Event *ev);
void CameraThink(Event *ev);
void CreateOrbit(Vector pos, float radius, Vector &forward, Vector &left);
void CreatePath(SplinePath *path, splinetype_t type);
void UpdateStates(void);
Vector CalculatePosition(void);
Vector CalculateOrientation(void);
float CalculateFov(void);
2024-04-11 00:30:00 +02:00
virtual void bind(Entity *master, qboolean use_my_angles = false) override;
2023-10-13 19:11:51 +02:00
void unbind(void) override;
public:
CLASS_PROTOTYPE(Camera);
Camera();
void Stop(void);
void FollowPath(SplinePath *path, qboolean loop, Entity *watch);
void Orbit(Entity *ent, float dist, Entity *watch, float yaw_offset = 0, qboolean dotrace = qtrue);
void FollowEntity(Entity *ent, float dist, int mask, Entity *watch = NULL);
void Watch(str watch, float time);
void Watch(Entity *ent, float time);
void SetFOV(float fov, float time);
void StartMoving(Event *ev);
void StopMoving(Event *ev);
void Pause(Event *ev);
void Continue(Event *ev);
void SetAnglesEvent(Event *ev);
void SetSpeed(Event *ev);
void SetFollowDistance(Event *ev);
void SetOrbitHeight(float height);
void SetOrbitHeight(Event *ev);
void SetFollowYaw(Event *ev);
void AbsoluteYaw(Event *ev);
void RelativeYaw(Event *ev);
void SetFOV(Event *ev);
void OrbitEvent(Event *ev);
void FollowEvent(Event *ev);
void WatchEvent(Event *ev);
void WatchStringEvent(Event *ev);
void WatchPathEvent(Event *ev);
void WatchNodesEvent(Event *ev);
void NoWatchEvent(Event *ev);
void EventShowQuakes(Event *ev);
void LookAt(Event *ev);
void MoveToEntity(Event *ev);
void MoveToPos(Event *ev);
void Cut(Event *ev);
void FadeTime(Event *ev);
void TurnTo(Event *ev);
void SetNextCamera(Event *ev);
float CalculateScore(Entity *player, str state);
float AutomaticStart(Entity *player);
float AutomaticStop(Entity *player);
qboolean IsAutomatic(void);
qboolean IsLevelExit(void);
void SetAutoStateEvent(Event *ev);
void SetAutoRadiusEvent(Event *ev);
void SetAutoStartTimeEvent(Event *ev);
void SetAutoStopTimeEvent(Event *ev);
void SetMaximumAutoFOVEvent(Event *ev);
void SetAutoActiveEvent(Event *ev);
str & NextCamera(void);
float Fov(void);
void Reset(Vector org, Vector ang);
2023-10-13 19:14:37 +02:00
bool ShowQuakes(void) const;
2023-10-13 19:11:51 +02:00
Vector GetPositionOffset(void);
void SetPositionOffset(Vector vNewOfs);
void Archive(Archiver& arc) override;
};
2023-10-13 19:14:37 +02:00
inline bool Camera::ShowQuakes(void) const
{
return m_bShowquakes;
}
2023-10-13 19:11:51 +02:00
inline Vector Camera::GetPositionOffset(void)
{
return m_vPosOffset;
2016-03-27 11:49:47 +02:00
}
2023-10-13 19:11:51 +02:00
inline void Camera::SetPositionOffset(Vector vNewOfs)
2016-03-27 11:49:47 +02:00
{
2023-10-13 19:11:51 +02:00
m_vPosOffset = vNewOfs;
2016-03-27 11:49:47 +02:00
}
2023-10-13 19:11:51 +02:00
inline void Camera::Archive(Archiver& arc)
{
Entity::Archive(arc);
arc.ArchiveFloat(&follow_yaw);
arc.ArchiveBoolean(&follow_yaw_fixed);
arc.ArchiveFloat(&follow_dist);
arc.ArchiveInteger(&follow_mask);
arc.ArchiveFloat(&camera_speed);
arc.ArchiveFloat(&camera_fov);
arc.ArchiveFloat(&orbit_height);
arc.ArchiveBoolean(&orbit_dotrace);
arc.ArchiveFloat(&auto_fov);
arc.ArchiveFloat(&automatic_startTime);
arc.ArchiveFloat(&automatic_stopTime);
arc.ArchiveFloat(&automatic_radius);
arc.ArchiveFloat(&automatic_maxFOV);
arc.ArchiveBoolean(&automatic_active);
automatic_states.Archive(arc);
// currentstate
currentstate.Archive(arc);
// newstate
newstate.Archive(arc);
arc.ArchiveFloat(&watchTime);
arc.ArchiveFloat(&followTime);
arc.ArchiveFloat(&fovTime);
arc.ArchiveFloat(&fadeTime);
arc.ArchiveFloat(&fovFadeTime);
arc.ArchiveFloat(&followFadeTime);
arc.ArchiveFloat(&watchFadeTime);
arc.ArchiveString(&nextCamera);
arc.ArchiveBoolean(&showcamera);
if (arc.Loading()) {
if (spawnflags & AUTOMATIC) {
level.AddAutomaticCamera(this);
}
}
}
void SetCamera(Entity *ent, float switchTime);
Entity *GetWatchEntity(str watch);
2016-03-27 11:49:47 +02:00
typedef SafePtr<Camera> CameraPtr;
class CameraManager : public Listener
2023-10-13 19:11:51 +02:00
{
protected:
Container<str> pathList;
BSpline cameraPath;
SplinePathPtr path;
SplinePathPtr current;
float speed;
int watch;
str pathName;
CameraPtr cam;
qboolean cameraPath_dirty;
void NewPath(Event *ev);
void SetPath(Event *ev);
void SetTargetName(Event *ev);
void SetTarget(Event *ev);
void AddPoint(Event *ev);
void ReplacePoint(Event *ev);
void DeletePoint(Event *ev);
void MovePlayer(Event *ev);
void NextPoint(Event *ev);
void PreviousPoint(Event *ev);
void ShowingPath(Event *ev);
void ShowPath(Event *ev);
void HidePath(Event *ev);
void StopPlayback(Event *ev);
void PlayPath(Event *ev);
void LoopPath(Event *ev);
void Watch(Event *ev);
void NoWatch(Event *ev);
void Fov(Event *ev);
void FadeTime(Event *ev);
void Speed(Event *ev);
void Save(Event *ev);
void Load(Event *ev);
void SaveMap(Event *ev);
void UpdateEvent(Event *ev);
void NextPath(Event *ev);
void PreviousPath(Event *ev);
void RenamePath(Event *ev);
void ShowPath(void);
void UpdateUI(void);
void SetPathName(str name);
void SavePath(str pathName);
public:
CLASS_PROTOTYPE(CameraManager);
CameraManager();
void SetPath(str pathName);
void Archive(Archiver& arc) override;
};
inline void CameraManager::Archive(Archiver& arc)
2016-03-27 11:49:47 +02:00
2023-10-13 19:11:51 +02:00
{
Listener::Archive(arc);
2016-03-27 11:49:47 +02:00
2023-10-13 19:11:51 +02:00
pathList.Archive(arc);
// no need to archive the cameraPath
arc.ArchiveSafePointer(&path);
arc.ArchiveSafePointer(&current);
arc.ArchiveFloat(&speed);
arc.ArchiveInteger(&watch);
arc.ArchiveString(&pathName);
arc.ArchiveSafePointer(&cam);
// make sure the cameraPath gets rebuilt
cameraPath_dirty = qtrue;
}
extern CameraManager CameraMan;