diff --git a/.gitignore b/.gitignore index 4e54622..16cf513 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.sig +*.sh diff --git a/CamDetection.as b/CamDetection.as new file mode 100644 index 0000000..b457273 --- /dev/null +++ b/CamDetection.as @@ -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; + + 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 diff --git a/Export.as b/Export.as index 1d404e8..a27a848 100644 --- a/Export.as +++ b/Export.as @@ -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"; } diff --git a/ExportShared.as b/ExportShared.as new file mode 100644 index 0000000..cc687ff --- /dev/null +++ b/ExportShared.as @@ -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 +} diff --git a/Impl.as b/Impl.as index 7b9a3ed..069a04e 100644 --- a/Impl.as +++ b/Impl.as @@ -41,6 +41,11 @@ namespace Camera return g_position; } + vec3 GetCurrentLookingDirection() + { + return g_direction; + } + void SetEditorOrbitalTarget(const vec3 &in pos) { auto editor = cast(GetApp().Editor); @@ -72,4 +77,9 @@ namespace Camera Dev::SetOffset(orbital, 0x44, newCameraPos); #endif } + + ActiveCam GetCurrentGameCamera() + { + return g_activeCameraType; + } } diff --git a/Main.as b/Main.as index 252e890..6256035 100644 --- a/Main.as +++ b/Main.as @@ -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; @@ -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; @@ -39,9 +46,9 @@ 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; @@ -49,5 +56,6 @@ void RenderEarly() 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); } } diff --git a/Settings.as b/Settings.as new file mode 100644 index 0000000..f5b4af8 --- /dev/null +++ b/Settings.as @@ -0,0 +1,2 @@ +[Setting category="Debug" name="Debug: Show Active Cam in the Menu Bar"] +bool Setting_DebugShowActiveCamInMenu = false; diff --git a/info.toml b/info.toml index 4f3e7b8..c01709f 100644 --- a/info.toml +++ b/info.toml @@ -6,4 +6,5 @@ essential = true [script] exports = [ "Export.as" ] +shared_exports = [ "ExportShared.as" ] timeout = 0