Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Active Game Camera Detection #2

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.sig
*.sh
125 changes: 125 additions & 0 deletions CamDetection.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#if TMNEXT

void RenderMenuMain()
{
if (!Setting_DebugShowActiveCamInMenu) {
return;
}
UI::TextDisabled("Active Cam: " + tostring(g_activeCameraType));
}

const Reflection::MwClassInfo@ tmTy = Reflection::GetType("CTrackMania");
const Reflection::MwMemberInfo@ gameSceneMember = tmTy.GetMember("GameScene");
const uint GameCameraNodOffset = gameSceneMember.Offset + 0x10;

void UpdateActiveGameCam()
{
g_activeCameraType = ActiveCam::None;

auto gameCameraNod = Dev::GetOffsetNod(GetApp(), GameCameraNodOffset);

// This is null in the menu and when cameras aren't being used.
if (gameCameraNod is null) {
return;
}

auto camModelNod = Dev::GetOffsetNod(gameCameraNod, 0x58);
auto camControlNod = Dev::GetOffsetNod(gameCameraNod, 0x68);
// 0x1 for std, 0x2 for alt.
bool cam1Alt = Dev::GetOffsetUint8(gameCameraNod, 0x24) == 0x2;
bool cam2Alt = Dev::GetOffsetUint8(gameCameraNod, 0x25) == 0x2;
bool cam3Alt = Dev::GetOffsetUint8(gameCameraNod, 0x26) == 0x2;

// Always 4 when backwards, and seemingly always 0 otherwise
bool isBackwards = Dev::GetOffsetUint32(gameCameraNod, 0xB0) == 0x4;
Comment on lines +26 to +34
Copy link
Member

@codecat codecat Jul 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still not a fan of all these offsets tbh. Have you checked these offsets across game updates? How stable are they?

I'm afraid that Nadeo is going to release an update and make these offsets moot, and we will be forced to spend a long time on updating the offsets, or finding different methods of getting this information, or maybe we even need to remove the feature altogether. (And maybe only 1 plugin will ever need to use this functionality.)

This is my general view of using the Dev API btw, nothing specifically against this. I'm just wondering how stable it is, because it will add a lot of maintenance work. (Perhaps we need a checklist that we manually go through every game update.)


if (isBackwards) {
g_activeCameraType = ActiveCam::Backwards;
} else if (camModelNod !is null) {
auto ty = Reflection::TypeOf(camModelNod);
if (ty.ID == ClsId_CPlugVehicleCameraRace2Model) {
g_activeCameraType = cam1Alt ? ActiveCam::Cam1Alt : ActiveCam::Cam1;
} else if (ty.ID == ClsId_CPlugVehicleCameraRace3Model) {
g_activeCameraType = cam2Alt ? ActiveCam::Cam2Alt : ActiveCam::Cam2;
} else if (ty.ID == ClsId_CPlugVehicleCameraInternalModel) {
g_activeCameraType = cam3Alt ? ActiveCam::Cam3Alt : ActiveCam::Cam3;
} else if (ty.ID == ClsId_CPlugVehicleCameraHelicoModel) {
// this happens with CharacterPilot maps
g_activeCameraType = ActiveCam::Helico;
} else {
#if SIG_DEVELOPER
trace('1 Got cam of unknown type: ' + ty.ID + ', ' + ty.Name);
UI::ShowNotification('1 Got cam of unknown type: ' + ty.ID + ', ' + ty.Name);
#endif
g_activeCameraType = ActiveCam::Other;
}
} else if (camControlNod !is null) {
auto ty = Reflection::TypeOf(camControlNod);
if (ty.ID == ClsId_CGameControlCameraFree) {
g_activeCameraType = ActiveCam::FreeCam;
} else if (ty.ID == ClsId_CGameControlCameraEditorOrbital) {
g_activeCameraType = ActiveCam::EditorOrbital;
} else if (ty.ID == ClsId_CGameControlCameraOrbital3d) {
g_activeCameraType = ActiveCam::Orbital3d;
} else if (ty.ID == ClsId_CGameControlCameraHelico) {
g_activeCameraType = ActiveCam::Helico;
} else if (ty.ID == ClsId_CGameControlCameraHmdExternal) {
g_activeCameraType = ActiveCam::HmdExternal;
} else if (ty.ID == ClsId_CGameControlCameraThirdPerson) {
g_activeCameraType = ActiveCam::ThirdPerson;
} else if (ty.ID == ClsId_CGameControlCameraFirstPerson) {
g_activeCameraType = ActiveCam::FirstPerson;
} else if (ty.ID == ClsId_CGameControlCameraTarget) {
g_activeCameraType = ActiveCam::Target;
} else if (ty.ID == ClsId_CGameControlCameraTrackManiaRace) {
g_activeCameraType = ActiveCam::Cam0;
} else if (ty.ID == ClsId_CGameControlCameraTrackManiaRace2) {
g_activeCameraType = ActiveCam::Cam1;
} else if (ty.ID == ClsId_CGameControlCameraTrackManiaRace3) {
g_activeCameraType = ActiveCam::Cam2;
} else if (ty.ID == ClsId_CGameControlCameraVehicleInternal) {
g_activeCameraType = ActiveCam::Cam3;
} else if (ty.ID == ClsId_CGameControlCamera) {
// We probably won't ever end up here, but just in case.
g_activeCameraType = ActiveCam::Other;
} else {
// debug so we know that a cam is unknown
#if SIG_DEVELOPER
trace('2 Got cam of unknown type: ' + ty.ID + ', ' + ty.Name);
UI::ShowNotification('2 Got cam of unknown type: ' + ty.ID + ', ' + ty.Name);
#endif
g_activeCameraType = ActiveCam::Other;
}
} else {
// initalizing editor, when in mediatracker
g_activeCameraType = ActiveCam::Loading;
}
}

const uint ClsId_CPlugVehicleCameraRace2Model = Reflection::GetType("CPlugVehicleCameraRace2Model").ID;
const uint ClsId_CPlugVehicleCameraRace3Model = Reflection::GetType("CPlugVehicleCameraRace3Model").ID;
const uint ClsId_CPlugVehicleCameraInternalModel = Reflection::GetType("CPlugVehicleCameraInternalModel").ID;
const uint ClsId_CPlugVehicleCameraHelicoModel = Reflection::GetType("CPlugVehicleCameraHelicoModel").ID;

const uint ClsId_CGameControlCameraFree = Reflection::GetType("CGameControlCameraFree").ID;
const uint ClsId_CGameControlCameraEditorOrbital = Reflection::GetType("CGameControlCameraEditorOrbital").ID;
const uint ClsId_CGameControlCameraOrbital3d = Reflection::GetType("CGameControlCameraOrbital3d").ID;
const uint ClsId_CGameControlCameraHelico = Reflection::GetType("CGameControlCameraHelico").ID;
const uint ClsId_CGameControlCameraHmdExternal = Reflection::GetType("CGameControlCameraHmdExternal").ID;
const uint ClsId_CGameControlCameraThirdPerson = Reflection::GetType("CGameControlCameraThirdPerson").ID;
const uint ClsId_CGameControlCameraFirstPerson = Reflection::GetType("CGameControlCameraFirstPerson").ID;
const uint ClsId_CGameControlCameraTarget = Reflection::GetType("CGameControlCameraTarget").ID;
const uint ClsId_CGameControlCameraTrackManiaRace = Reflection::GetType("CGameControlCameraTrackManiaRace").ID;
const uint ClsId_CGameControlCamera = Reflection::GetType("CGameControlCamera").ID;
const uint ClsId_CGameControlCameraTrackManiaRace2 = Reflection::GetType("CGameControlCameraTrackManiaRace2").ID;
const uint ClsId_CGameControlCameraTrackManiaRace3 = Reflection::GetType("CGameControlCameraTrackManiaRace3").ID;
const uint ClsId_CGameControlCameraVehicleInternal = Reflection::GetType("CGameControlCameraVehicleInternal").ID;

#else

void UpdateActiveGameCam()
{
// not supported yet in MP4 / Turbo
}

#endif
6 changes: 6 additions & 0 deletions Export.as
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ namespace Camera
// Gets the current camera position.
import vec3 GetCurrentPosition() from "Camera";

// Gets the current camera looking direction.
import vec3 GetCurrentLookingDirection() from "Camera";

// In the editor, sets the currently focused camera position of the orbital camera.
import void SetEditorOrbitalTarget(const vec3 &in pos) from "Camera";

// Gets the currently active game camera.
import ActiveCam GetCurrentGameCamera() from "Camera";
}
21 changes: 21 additions & 0 deletions ExportShared.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
shared enum ActiveCam {
None = 0,
Cam1 = 1,
Cam2 = 2,
Cam3 = 3,
Cam1Alt = 4,
Cam2Alt = 5,
Cam3Alt = 6,
FreeCam = 7,
Backwards = 8,
EditorOrbital,
Orbital3d,
Helico,
HmdExternal,
ThirdPerson,
FirstPerson,
Target,
Cam0,
Other,
Loading
}
XertroV marked this conversation as resolved.
Show resolved Hide resolved
10 changes: 10 additions & 0 deletions Impl.as
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ namespace Camera
return g_position;
}

vec3 GetCurrentLookingDirection()
{
return g_direction;
}

void SetEditorOrbitalTarget(const vec3 &in pos)
{
auto editor = cast<CGameCtnEditorCommon>(GetApp().Editor);
Expand Down Expand Up @@ -72,4 +77,9 @@ namespace Camera
Dev::SetOffset(orbital, 0x44, newCameraPos);
#endif
}

ActiveCam GetCurrentGameCamera()
{
return g_activeCameraType;
}
}
12 changes: 10 additions & 2 deletions Main.as
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
CHmsCamera@ g_currentCamera = null;

mat4 g_projection = mat4::Identity();
mat4 g_rotation = mat4::Identity();
vec3 g_position = vec3();
vec3 g_direction = vec3();

vec2 g_displayPos;
vec2 g_displaySize;

ActiveCam g_activeCameraType = ActiveCam::None;

void RenderEarly()
{
UpdateActiveGameCam();

auto viewport = GetApp().Viewport;

@g_currentCamera = null;
Expand All @@ -28,6 +34,7 @@ void RenderEarly()

if (g_currentCamera !is null) {
iso4 camLoc = g_currentCamera.Location;
mat4 camLocMat = mat4(camLoc);
float camFov = g_currentCamera.Fov;
float camNearZ = g_currentCamera.NearZ;
float camFarZ = g_currentCamera.FarZ;
Expand All @@ -39,15 +46,16 @@ void RenderEarly()

mat4 projection = mat4::Perspective(camFov, camAspect, camNearZ, camFarZ);
mat4 translation = mat4::Translate(vec3(camLoc.tx, camLoc.ty, camLoc.tz));
mat4 rotation = mat4::Inverse(mat4::Inverse(translation) * mat4(camLoc));
g_rotation = mat4::Inverse(mat4::Inverse(translation) * camLocMat);

g_projection = projection * mat4::Inverse(translation * rotation);
g_projection = projection * mat4::Inverse(translation * g_rotation);
g_position = vec3(camLoc.tx, camLoc.ty, camLoc.tz);

vec2 topLeft = 1 - (g_currentCamera.DrawRectMax + 1) / 2;
vec2 bottomRight = 1 - (g_currentCamera.DrawRectMin + 1) / 2;
g_displaySize = vec2(Draw::GetWidth(), Draw::GetHeight());
g_displayPos = topLeft * g_displaySize;
g_displaySize *= bottomRight - topLeft;
g_direction = vec3(camLoc.xz, camLoc.yz, camLoc.zz);
}
}
2 changes: 2 additions & 0 deletions Settings.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Setting category="Debug" name="Debug: Show Active Cam in the Menu Bar"]
bool Setting_DebugShowActiveCamInMenu = false;
1 change: 1 addition & 0 deletions info.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ essential = true

[script]
exports = [ "Export.as" ]
shared_exports = [ "ExportShared.as" ]
timeout = 0