From 7682dba2c91198acf4f56525d317366be182d938 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Wed, 18 Feb 2026 17:00:56 -0600 Subject: [PATCH] feat(ui): add CGCamera --- lib/typhoon | 2 +- src/ui/game/CGCamera.cpp | 97 +++++++++++++++++++++++++++++++++ src/ui/game/CGCamera.hpp | 48 ++++++++++++++++ src/ui/game/CGGameUI.cpp | 5 ++ src/ui/game/Types.hpp | 12 ++++ src/ui/simple/CSimpleCamera.cpp | 12 ++-- src/ui/simple/CSimpleCamera.hpp | 1 + 7 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 src/ui/game/CGCamera.cpp create mode 100644 src/ui/game/CGCamera.hpp diff --git a/lib/typhoon b/lib/typhoon index 1f8bf13..1e5366b 160000 --- a/lib/typhoon +++ b/lib/typhoon @@ -1 +1 @@ -Subproject commit 1f8bf1370dc1cf13da5965be99803633d82a524f +Subproject commit 1e5366bbc6935e3363abf5921f0be12f902e790a diff --git a/src/ui/game/CGCamera.cpp b/src/ui/game/CGCamera.cpp new file mode 100644 index 0000000..f278f6e --- /dev/null +++ b/src/ui/game/CGCamera.cpp @@ -0,0 +1,97 @@ +#include "ui/game/CGCamera.hpp" +#include "ui/game/Types.hpp" +#include "console/CVar.hpp" +#include "world/World.hpp" +#include +#include +#include + +static CVar* s_cameraView; + +CGCamera::CameraViewData CGCamera::s_cameraViewDataDefault[MAX_CAMERA_VIEWS] = { + { "0.0", "0.0", "0.0" }, // VIEW_FIRST_PERSON + { "0.0", "0.0", "0.0" }, // VIEW_THIRD_PERSON_A + { "5.55", "10.0", "0.0" }, // VIEW_THIRD_PERSON_B + { "5.55", "20.0", "0.0" }, // VIEW_THIRD_PERSON_C + { "13.88", "30.0", "0.0" }, // VIEW_THIRD_PERSON_D + { "13.88", "10.0", "0.0" }, // VIEW_THIRD_PERSON_E + { "0.0", "0.0", "0.0" }, // VIEW_COMMENTATOR + { "5.0", "10.0", "0.0" }, // VIEW_BARBER_SHOP +}; + +namespace { + +bool ValidateCameraView(CVar* var, const char* oldValue, const char* value, void* arg) { + auto view = SStrToFloat(value); + auto min = static_cast(VIEW_FIRST_PERSON); + auto max = static_cast(VIEW_BARBER_SHOP); + + if (view >= min && view <= max) { + return true; + } + + // TODO ConsoleWriteA("Value out of range (%f - %f)\n", DEFAULT_COLOR, min, max); + + return false; +} + +} + +CGCamera::CGCamera() : CSimpleCamera(CWorld::GetNearClip(), CWorld::GetFarClip(), 90.0f * CMath::DEG2RAD) { + this->m_relativeTo = 0; + + this->m_view = s_cameraView->GetInt(); + + this->m_distance = SStrToFloat(CGCamera::s_cameraViewDataDefault[this->m_view].m_distance); + this->m_yaw = 0.0f; + this->m_pitch = SStrToFloat(CGCamera::s_cameraViewDataDefault[this->m_view].m_pitch); + this->m_roll = 0.0f; + + this->m_fovOffset = 0.0f; +} + +float CGCamera::FOV() const { + // Clamp offset-adjusted FOV between 0pi and 1pi + return std::min(std::max(this->m_fov + this->m_fovOffset, 0.0f), CMath::PI); +} + +C3Vector CGCamera::Forward() const { + if (this->m_relativeTo) { + return this->CSimpleCamera::Forward() * this->ParentToWorld(); + } + + return this->CSimpleCamera::Forward(); +} + +C33Matrix CGCamera::ParentToWorld() const { + // TODO + return {}; +} + +C3Vector CGCamera::Right() const { + if (this->m_relativeTo) { + return this->CSimpleCamera::Right() * this->ParentToWorld(); + } + + return this->CSimpleCamera::Right(); +} + +void CGCamera::SetupWorldProjection(const CRect& projRect) { + this->SetGxProjectionAndView(projRect); +} + +C3Vector CGCamera::Up() const { + if (this->m_relativeTo) { + return this->CSimpleCamera::Up() * this->ParentToWorld(); + } + + return this->CSimpleCamera::Up(); +} + +void CameraRegisterCVars() { + // TODO + + s_cameraView = CVar::Register("cameraView", nullptr, 0x10, "2", &ValidateCameraView, DEFAULT); + + // TODO +} diff --git a/src/ui/game/CGCamera.hpp b/src/ui/game/CGCamera.hpp new file mode 100644 index 0000000..b0aafb7 --- /dev/null +++ b/src/ui/game/CGCamera.hpp @@ -0,0 +1,48 @@ +#ifndef UI_GAME_C_G_CAMERA_HPP +#define UI_GAME_C_G_CAMERA_HPP + +#include "ui/simple/CSimpleCamera.hpp" +#include "util/GUID.hpp" + +class CGCamera : public CSimpleCamera { + public: + // Public structs + struct CameraViewData { + const char* m_distance; + const char* m_pitch; + const char* m_yaw; + }; + + // Public static variables + static CameraViewData s_cameraViewDataDefault[]; + + // Virtual public member functions + virtual ~CGCamera() = default; + virtual float FOV() const; + virtual C3Vector Forward() const; + virtual C3Vector Right() const; + virtual C3Vector Up() const; + + // Public member functions + CGCamera(); + C33Matrix ParentToWorld() const; + void SetupWorldProjection(const CRect& projRect); + + private: + // Private member variables + // TODO + WOWGUID m_relativeTo; + // TODO + int32_t m_view; + // TODO + float m_distance; + float m_yaw; + float m_pitch; + float m_roll; + // TODO + float m_fovOffset; +}; + +void CameraRegisterCVars(); + +#endif diff --git a/src/ui/game/CGGameUI.cpp b/src/ui/game/CGGameUI.cpp index a92b41f..791b850 100644 --- a/src/ui/game/CGGameUI.cpp +++ b/src/ui/game/CGGameUI.cpp @@ -8,6 +8,7 @@ #include "ui/game/ActionBarScript.hpp" #include "ui/game/BattlefieldInfoScript.hpp" #include "ui/game/BattlenetUI.hpp" +#include "ui/game/CGCamera.hpp" #include "ui/game/CGCharacterModelBase.hpp" #include "ui/game/CGCooldown.hpp" #include "ui/game/CGDressUpModelFrame.hpp" @@ -284,4 +285,8 @@ void CGGameUI::RegisterGameCVars() { CVar::Register("fullSizeFocusFrame", "Increases the size of the focus frame to that of the target frame", 0x20, "0", nullptr, GAME); // TODO + + CameraRegisterCVars(); + + // TODO } diff --git a/src/ui/game/Types.hpp b/src/ui/game/Types.hpp index a54dce4..78d1696 100644 --- a/src/ui/game/Types.hpp +++ b/src/ui/game/Types.hpp @@ -13,4 +13,16 @@ enum SCRIPTEVENT { // TODO }; +enum CAMERA_VIEW { + VIEW_FIRST_PERSON = 0, + VIEW_THIRD_PERSON_A = 1, + VIEW_THIRD_PERSON_B = 2, + VIEW_THIRD_PERSON_C = 3, + VIEW_THIRD_PERSON_D = 4, + VIEW_THIRD_PERSON_E = 5, + VIEW_COMMENTATOR = 6, + VIEW_BARBER_SHOP = 7, + MAX_CAMERA_VIEWS, +}; + #endif diff --git a/src/ui/simple/CSimpleCamera.cpp b/src/ui/simple/CSimpleCamera.cpp index 990c982..15a0dc6 100644 --- a/src/ui/simple/CSimpleCamera.cpp +++ b/src/ui/simple/CSimpleCamera.cpp @@ -104,10 +104,6 @@ void CSimpleCamera::SetFieldOfView(float fov) { this->m_fov = fov; } -void CSimpleCamera::SetNearZ(float nearZ) { - this->m_nearZ = nearZ; -} - void CSimpleCamera::SetGxProjectionAndView(const CRect& projRect) { // Projection @@ -127,6 +123,14 @@ void CSimpleCamera::SetGxProjectionAndView(const CRect& projRect) { GxXformSetView(viewMat); } +void CSimpleCamera::SetNearZ(float nearZ) { + this->m_nearZ = nearZ; +} + +void CSimpleCamera::SetScreenAspect(const CRect& screenRect) { + this->m_aspect = (screenRect.maxX - screenRect.minX) / (screenRect.maxY - screenRect.minY); +} + C3Vector CSimpleCamera::Up() const { return { this->m_facing.c0, this->m_facing.c1, this->m_facing.c2 }; } diff --git a/src/ui/simple/CSimpleCamera.hpp b/src/ui/simple/CSimpleCamera.hpp index 407cdb6..3387a35 100644 --- a/src/ui/simple/CSimpleCamera.hpp +++ b/src/ui/simple/CSimpleCamera.hpp @@ -25,6 +25,7 @@ class CSimpleCamera { void SetFieldOfView(float fov); void SetGxProjectionAndView(const CRect& projRect); void SetNearZ(float nearZ); + void SetScreenAspect(const CRect& screenRect); protected: // Protected member variables