/* =========================================================================== 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. // #pragma once #include "g_local.h" #include "entity.h" #include "bspline.h" #include "container.h" #include "level.h" #define CAMERA_SWITCHTIME 0.5f #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) 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 { 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(¤tNode); 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); } class Camera : public Entity { 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 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); virtual void bind(Entity *master, qboolean use_my_angles = false) override; 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); bool ShowQuakes(void) const; Vector GetPositionOffset(void); void SetPositionOffset(Vector vNewOfs); void Archive(Archiver& arc) override; }; inline bool Camera::ShowQuakes(void) const { return m_bShowquakes; } inline Vector Camera::GetPositionOffset(void) { return m_vPosOffset; } inline void Camera::SetPositionOffset(Vector vNewOfs) { m_vPosOffset = vNewOfs; } 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); typedef SafePtr CameraPtr; class CameraManager : public Listener { protected: Container 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) { Listener::Archive(arc); pathList.Archive(arc); // no need to archive the cameraPath arc.ArchiveSafePointer(&path); arc.ArchiveSafePointer(¤t); arc.ArchiveFloat(&speed); arc.ArchiveInteger(&watch); arc.ArchiveString(&pathName); arc.ArchiveSafePointer(&cam); // make sure the cameraPath gets rebuilt cameraPath_dirty = qtrue; } extern CameraManager CameraMan;