Files
gtav-src/tools_ng/dcc/current/max2012/scripts/pipeline/ui/ObjectPosChecker.ms
T
2025-09-29 00:52:08 +02:00

1226 lines
36 KiB
Plaintext
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--
-- File:: pipeline/ui/ObjectPosChecker.ms
-- Description:: GTA Object Position Checker Import MAXScript
-- This imports the output of the Object Position Checker that runs in-game.
-- Once the text file has been read it provides a preview of the affected
-- objects and then object position can be automatically changed for the
-- loaded blocks.
--
-- 25 June 2007
-- by David Muir <david.muir@rockstarnorth.com>
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Uses
-----------------------------------------------------------------------------
filein "pipeline/export/maps/globals.ms"
filein "pipeline/helpers/animation/hierarchyBB.ms"
filein "pipeline/util/RSProcess.ms"
-----------------------------------------------------------------------------
-- Rollouts
-----------------------------------------------------------------------------
rollout GtaObjectPosCheckerInitiatorRoll "Object Position Checker Initiator"
(
-------------------------------------------------------------------------------
-- constants
-------------------------------------------------------------------------------
local debug = true
local connectionTimerInterval = 5000 --Tick every 5 seconds
local sweepTimerInterval = 2500 --Tick every 2.5 seconds
local RagSectorToolsStart = "Sector Tools/Start X Y Z World Coordinates:"
local RagSectorToolsEnd = "Sector Tools/End X Y Z World Coordinates:"
local RagObjPosCheckerBank = "Sector Tools/Physical Object Position Checker"
local RagObjPosCheckerOutputDir = "Sector Tools/Physical Object Position Checker/Output directory:"
local RagObjPosCheckerRestrictToEntities = "Sector Tools/Physical Object Position Checker/Restrict to Specific Entities"
local RagObjPosCheckerEntityFile = "Sector Tools/Physical Object Position Checker/Entity Restriction File:"
local RagObjPosCheckerScanArea = "Sector Tools/Physical Object Position Checker/Scan and Export Area"
local RagObjPosCheckerScanInProgress = "Sector Tools/Physical Object Position Checker/Scan In Progress (read-only)"
local RagObjPosCheckerAbort = "Sector Tools/Physical Object Position Checker/Abort Running Scan"
local ps3BatchFile = "game_psn_bankrelease_snc.bat"
local xboxBatchFile = "game_xenon_bankrelease.bat"
local defaultCommandlineArgs = "-rag nopeds nocars novehs -maponly -invincible -sectortools"
local inputFilename = "object_position_sectors.txt"
local entitiesFilename = "object_position_entities.txt"
local responseFilename = "additional_game_args.txt"
-------------------------------------------------------------------------------
-- Data
-------------------------------------------------------------------------------
local connectionTimer = undefined
local sweepTimer = undefined
local buildDir = undefined
-------------------------------------------------------------------------------
-- UI
-------------------------------------------------------------------------------
dropDownList lstPlatforms "Platform:" items:#("PS3","Xbox360") width:200 across:2
dropDownList lstSweepMode "Sweep Mode:" items:#("Open Containers","Selected Containers","Selected Entities") width:200
label lblOutputDirHeader "Output Directory:" across:3 align:#left
label lblOutputDir "c:\\temp" offset:[-90,0] align:#left
button btnBrowse "Browse" width:80 align:#right
label lblAdditionalArgsHeader "Commandline Args:" width:120 across:3 align:#left
edittext edtAdditionalArgs text:defaultCommandlineArgs offset:[-90,0] width:400 align:#left
label lblDummy width:1 align:#right
button btnStart "Start In-Game Checker" width:200
label lblConnectionHeader "Game Connection Status:" across:2 align:#left
label lblConnectionStatus "Not connected" align:#left offset:[-100,0]
label lblSweepHeader "Sweep Status:" across:3 align:#left
label lblSweepStatus "" width:300 align:#left
button btnAbort "Abort" width:100 align:#right
-------------------------------------------------------------------------------
-- Functions
-------------------------------------------------------------------------------
-- Helper method for printing debug messages.
fn PrintDebug message =
(
if (debug == true) then
(
print message
)
)
-- Retrieves list of selected entity guids.
fn GetSelectedEntityGuids =
(
local selectedObjectGuids = #()
local mapContainers = RsMapGetMapContainers()
local maps = for map in RsMapGetMapContainers doingExport:true where map.is_exportable() and (map.selCount() != 0) collect map
if (maps.count > 0) then
(
for map in maps do
(
local mapSectionMapNode = RsProjectContentFind (toLower map.name) type:"map"
local containerAttrGuid = getattrguid map.cont
containerAttrGuid = trimLeft containerAttrGuid "{"
containerAttrGuid = trimRight containerAttrGuid "}"
local containerHash32 = atStringHash containerAttrGuid seed:mapSectionMapNode.Seed
PrintDebug (format "map section seed:%, guid:%, hash:%" mapSectionMapNode.Seed containerAttrGuid containerHash32)
RsMapSetupGlobals map
for obj in map.selObjects do
(
local objAttrGuid = getattrguid obj
objAttrGuid = trimLeft objAttrGuid "{"
objAttrGuid = trimRight objAttrGuid "}"
local objectHash32 = atStringHash objAttrGuid seed:containerHash32
PrintDebug (format "object:%, guid:%, hash:%" obj.name objAttrGuid objectHash32)
append selectedObjectGuids objectHash32
)
)
)
return selectedObjectGuids
)
-- Returns a list of export objects for a particular map container.
fn GetExportObjects maps =
(
local objs = #()
for map in maps do
(
for obj in map.exportObjects do
(
if (GetAttrClass obj) == "Gta Object" then
(
append objs obj
)
)
)
return objs
)
-- Returns the bounds that we need to send to the game.
fn GetBounds =
(
local bbox = undefined
if (lstSweepMode.selected == "Open Containers") then
(
local maps = for map in RsMapGetMapContainers doingExport:true where map.is_exportable() collect map
if (maps.count > 0) then
(
local expObjs = GetExportObjects maps
if (expObjs.count > 0) then
(
bbox = RsGetHierarchyBB expObjs[1] restrictToClass:"Gta Object"
for obj in expObjs do
(
RsExpandBB bbox (::RsGetHierarchyBB obj restrictToClass:"Gta Object")
)
)
)
)
else if (lstSweepMode.selected == "Selected Containers") then
(
local maps = for map in RsMapGetMapContainers doingExport:true where map.is_exportable() and (map.selCount() != 0) collect map
if (maps.count > 0) then
(
local expObjs = GetExportObjects maps
if (expObjs.count > 0) then
(
bbox = RsGetHierarchyBB expObjs[1] restrictToClass:"Gta Object"
for obj in expObjs do
(
RsExpandBB bbox (::RsGetHierarchyBB obj restrictToClass:"Gta Object")
)
)
)
)
else if (lstSweepMode.selected == "Selected Entities") then
(
local maps = for map in RsMapGetMapContainers doingExport:true where map.is_exportable() and (map.selCount() != 0) collect map
if (maps.count > 0) then
(
local expObjs = #()
for map in maps do
(
for obj in map.selObjects do
(
if (GetAttrClass obj) == "Gta Object" then
(
append expObjs obj
)
)
)
if (expObjs.count > 0) then
(
bbox = RsGetHierarchyBB expObjs[1] restrictToClass:"Gta Object"
for obj in expObjs do
(
RsExpandBB bbox (::RsGetHierarchyBB obj restrictToClass:"Gta Object")
)
)
)
)
PrintDebug bbox
return bbox
)
-- Helper method that checks whether the game is already running with the sector tools enabled
fn IsGameRunningWithSectorTools =
(
local retVal = false
if (RemoteConnection.IsConnected() == true) then
(
retVal = RemoteConnection.WidgetExists(RagObjPosCheckerBank)
)
return retVal
)
-- Helper method that checks whether a object position sweep is already in progress.
fn IsSweepInProgress =
(
local retVal = false
if (RemoteConnection.IsConnected() == true) then
(
retVal = RemoteConnection.ReadBoolWidget(RagObjPosCheckerScanInProgress)
)
return retVal
)
-- Writes a file containing a single line per entity guid.
fn CreateEntityGuidFile guids filepath =
(
local guidStream = stringStream ""
for guid in guids do
(
local guidString = formattedPrint guid
format "%\n" guidString to:guidStream
)
PrintDebug guidStream
local file = fopen filepath "wt"
WriteString file guidStream
fclose file
)
-- Writes a file containing the start/end coords.
fn CreateSectorInputFile bounds filepath =
(
local coords = stringStream ""
format "% % % %" bounds[1].x bounds[1].y bounds[2].x bounds[2].y to:coords
PrintDebug coords
local file = fopen filepath "wt"
WriteString file coords
fclose file
)
-- Writes a file containing the additional arguments the game should use when booting.
fn CreateResponseFile arguments filepath =
(
local file = fopen filepath "wt"
WriteString file arguments
fclose file
)
-- Starts the object position checker when the game is already running.
fn StartObjectPositionChecker =
(
-- Make sure we can determine some valid bounds to work with.
local bounds = GetBounds()
if (bounds == undefined) then
(
messageBox "Nothing to do for the selected sweep mode. Have you selected some exportable entities?"
)
else
(
-- Set all the appropriate RAG widget values.
local outputDir = lblOutputDir.text
RemoteConnection.WriteStringWidget RagObjPosCheckerOutputDir outputDir
local startStream = stringStream ""
format "% % %" bounds[1].x bounds[1].y bounds[1].z to:startStream
RemoteConnection.WriteStringWidget RagSectorToolsStart (startStream as string)
local endStream = stringStream ""
format "% % %" bounds[2].x bounds[2].y bounds[2].z to:endStream
RemoteConnection.WriteStringWidget RagSectorToolsEnd (endStream as string)
RemoteConnection.WriteBoolWidget RagObjPosCheckerRestrictToEntities (lstSweepMode.selected == "Selected Entities")
-- Create the entities file (if required).
if (lstSweepMode.selected == "Selected Entities") then
(
local entitiesFilepath = buildDir + entitiesFilename
CreateEntityGuidFile (GetSelectedEntityGuids()) entitiesFilepath
RemoteConnection.WriteStringWidget RagObjPosCheckerEntityFile entitiesFilepath
)
-- Start the object position checker process.
RemoteConnection.SendCommand("widget \"" + RagObjPosCheckerScanArea + "\"")
sweepTimer.Start()
btnStart.Enabled = false
lblSweepStatus.Text = "Sweep in Progress"
)
)
-- Boots the game with the object position checker commandline parameters.
fn BootAndStartObjectPositionChecker =
(
-- Make sure we can determine some valid bounds to work with.
local bounds = GetBounds()
if (bounds == undefined) then
(
messageBox "Nothing to do for the selected sweep mode. Have you selected some exportable entities?"
)
else
(
-- Use the appropriate batch file
local batFilename = buildDir
if (lstPlatforms.selected == "PS3") then
(
batFilename += ps3BatchFile
)
else
(
batFilename += xboxBatchFile
)
-- Build up the commandline args
local arguments = defaultCommandlineArgs
-- Create the intput sector tool files.
local inputFilepath = buildDir + inputFilename
CreateSectorInputFile (GetBounds()) inputFilepath
local outputDir = lblOutputDir.text
arguments += " -sectortools_input \"" + inputFilepath + "\" -sectortools_output \"" + outputDir + "\""
-- Create the entities file (if required).
if (lstSweepMode.selected == "Selected Entities") then
(
local entitiesFilepath = buildDir + entitiesFilename
CreateEntityGuidFile (GetSelectedEntityGuids()) entitiesFilepath
arguments += " -sectortools_entities \"" + entitiesFilepath + "\""
)
-- Create the arugments response file.
local responseFilepath = buildDir + responseFilename
CreateResponseFile arguments responseFilepath
-- If it's 360, check to see whether watson is running and kill it.
if (lstPlatforms.selected == "Xbox360") then
(
local xboxSDKDir = "%xedk%\bin\win32"
local cmd = ( "TASKKILL /F /IM \"xbwatson.exe\"" )
doscommand cmd
)
-- Kick off the game with those files as inputs.
PrintDebug (format "Running: % %" batFilename arguments)
local gameBatchProcess = RsProcess()
gameBatchProcess.RunProcess batFilename ("@" + responseFilepath) silent:false waitForExit:false workingDir:buildDir
btnStart.Enabled = false
-- Inform the user of what is happening
progressStart "Establishing game connection (waiting for game to boot)."
-- Times in seconds
local timePassed = 0
local maxTimeToWait = 30
local checkFrequency = 0.25
local waitingForConnection = true
while (waitingForConnection == true) do
(
-- Offer to cancel if the user has been waiting too long
if (timePassed >= maxTimeToWait) then
(
keepGoing = queryBox "Unable to establish a game connection\n\nContinue waiting?" title:"Warning: Connection Error"
-- If the user chooses to continue to wait, reset the timer.
if keepGoing then
(
timePassed = 0
)
else
(
btnStart.Enabled = true
waitingForConnection = false
)
)
if waitingForConnection then
(
if (RemoteConnection.IsConnected() == true and IsSweepInProgress() == true) then
(
sweepTimer.Start()
lblSweepStatus.Text = "Sweep in Progress"
waitingForConnection = false
)
else if (RemoteConnection.IsConnected() == false and RemoteConnection.Connect() == true) then
(
lblConnectionStatus.Text = "Connected"
connectionTimer.Start()
)
else
(
if not (progressUpdate (100.0 * timePassed / maxTimeToWait)) then
(
btnStart.Enabled = true
waitingForConnection = false
)
else
(
sleep checkFrequency
timePassed += checkFrequency
)
)
)
)
progressEnd()
)
)
-------------------------------------------------------------------------------
-- Events
-------------------------------------------------------------------------------
-- Tick called at regular intervals to check the game connection.
fn ConnectionTimer_OnTick s e =
(
if (RemoteConnection.IsConnected() == false) then
(
--If connection has faltered, then notify the UI.
PrintDebug ("Lost connection to the game!")
if (btnStart.Enabled == false) then
(
btnStart.Enabled = true
lblSweepStatus.Text = "Unknown"
sweepTimer.Stop()
)
lblConnectionStatus.Text = "Lost connection."
connectionTimer.Stop()
)
)
-- Tick called at regular intervals to check whether the object position checker has completed.
fn SweepTimer_OnTick s e =
(
if (btnStart.Enabled == false) then
(
-- Check whether the sweep's completed.
if (IsSweepInProgress() == false) then
(
btnStart.Enabled = true
lblSweepStatus.Text = "Sweep Completed"
sweepTimer.Stop()
)
)
)
-- Called when the rollout is opened.
on GtaObjectPosCheckerInitiatorRoll open do
(
-- Get the projects build directory.
buildDir = ( RsConfigGetProjRootDir() + "build/dev/" )
-- Initialise the two timers
connectionTimer = dotNetObject "System.Windows.Forms.Timer"
dotnet.addEventHandler connectionTimer "tick" ConnectionTimer_OnTick
connectionTimer.Interval = connectionTimerInterval
sweepTimer = dotNetObject "System.Windows.Forms.Timer"
dotnet.addEventHandler sweepTimer "tick" SweepTimer_OnTick
sweepTimer.Interval = sweepTimerInterval
-- Attempt to connect to the game.
if (RemoteConnection.Connect() == true) then
(
lblConnectionStatus.Text = "Connected"
connectionTimer.Start()
-- Is a sweep already in progress?
if (IsSweepInProgress() == true) then
(
sweepTimer.Start()
btnStart.Enabled = false
lblSweepStatus.Text = "Sweep in Progress"
)
)
)
-- Called when the rollout closes.
on GtaObjectPosCheckerInitiatorRoll close do
(
sweepTimer.Stop()
connectionTimer.Stop()
)
-- Called when the user wishes to browse for the output directory.
on btnBrowse pressed do
(
lblOutputDir.Text = getSavePath caption:"Select output directory:" initialDir:lblOutputDir.Text
)
-- Called when the user wants to kick off the object position checker in game.
on btnStart pressed do
(
-- Attempt to connect to the game.
if (RemoteConnection.Connect() == true) then
(
lblConnectionStatus.Text = "Connected"
connectionTimer.Start()
)
-- Check whether the game is already running.
if (IsGameRunningWithSectorTools() == true) then
(
-- Is a sweep already in progress?
if (IsSweepInProgress() == true) then
(
-- Tell the user to wait for the current sweep to complete.
messageBox "Object position check sweep already in progress.\nEither abort it or wait for it to complete before kicking off another one." title:"Sweep in Progress"
sweepTimer.Start()
btnStart.Enabled = false
lblSweepStatus.Text = "Sweep in Progress"
)
else
(
PrintDebug "Using existing game"
StartObjectPositionChecker()
)
)
else
(
PrintDebug "Booting game"
BootAndStartObjectPositionChecker()
)
)
-- Called when the user hits the abort button.
on btnAbort pressed do
(
if (btnStart.Enabled == false) then
(
PrintDebug "Aborting sweep"
RemoteConnection.SendCommand("widget \"" + RagObjPosCheckerAbort + "\"")
btnStart.Enabled = true
lblSweepStatus.Text = "Aborted"
sweepTimer.Stop()
)
)
)
rollout GtaObjectPosCheckerImportRoll "Object Position Checker Import"
(
-------------------------------------------------------------------------------
-- Structures
-------------------------------------------------------------------------------
struct ObjectCheckerDef
(
objName, -- Object name (string)
initialPos, -- Initial position of object (Point3)
initialRot, -- Initial rotation of object (Quat)
finalPos, -- Final position of object (Point3)
finalRot, -- Final rotation of object (Quat)
-- Function to compare two ObjectCheckerDef structs
fn cmp o1 o2 =
(
stricmp o1.objName o2.objName
)
)
-------------------------------------------------------------------------------
-- constants
-------------------------------------------------------------------------------
local degThreshold = 1.0
local useFullMatrixIdx = GetAttrIndex "Gta Object" "Use Full Matrix"
-------------------------------------------------------------------------------
-- Data
-------------------------------------------------------------------------------
local posZero = [ 0.0, 0.0, 0.0 ]
local checkedObjects = #()
local checkedObjectIndices = #() -- checkedObjects item indices shown
local checkedObjectsInMap = #()
-- Autorun stuff
local mode = 0 -- [0 == normal, 1 == autorun]
local autoRunObjIdx = undefined
-- Used to draw the extents of the objchk file
local rectangleArray = #()
-------------------------------------------------------------------------------
-- UI
-------------------------------------------------------------------------------
hyperlink lnkHelp "Help?" address:"https://devstar.rockstargames.com/wiki/index.php/Physical_Object_Position_Checker" align:#right color:(color 0 0 255) hoverColor:(color 0 0 255) visitedColor:(color 0 0 255)
button btnImport "Import File..." across:6
button btnImportDir "Import Directory..."
button btnAutoRun "Auto-Run..."
button btnCheckAll "Check All"
button btnInvChecked "Invert Checked"
button btnFindObject "Find Checked"
button btnFindSelObject "Find Selected Object"
dotNetControl lstViewObjects "System.Windows.Forms.ListView" width:180 height:525 across:2
dotNetControl lstView "System.Windows.Forms.ListView" width:400 height:125 offset:[-100,0]
groupbox grpAutoRun "Auto-Run" width:555 height:55
label lblInfo "" align:#left offset:[5,-45]
button btnInitial "Initial" enabled:false width:100 across:5
button btnFinal "Final" enabled:false width:100
button btnBack "Back" enabled:false width:100
button btnNext "Next" enabled:false width:100
button btnStop "Stop" enabled:false width:100
progressbar barProgress across:2 offset:[0,10]
button btnClose "Close" align:#right width:100 offset:[0,10]
-------------------------------------------------------------------------------
-- Functions
-------------------------------------------------------------------------------
local fEpsilon = 0.01
fn PosEqual a b = (
if ( a.x <= ( b.x + fEpsilon ) and a.x >= ( b.x - fEpsilon ) ) then
if ( a.y <= ( b.y + fEpsilon ) and a.y >= ( b.y - fEpsilon ) ) then
if ( a.z <= ( b.z + fEpsilon ) and a.z >= ( b.z - fEpsilon ) ) then
return true
return false
)
fn RefreshTreeView = (
checkedObjectIndices = #()
local i = 1
local n = 0
lvops.ClearLvItems lstView
lvops.ClearLvItems lstViewObjects
lstViewObjects.BeginUpdate()
for o in checkedObjects do
(
barProgress.value = 100.0 * i / checkedObjects.count
i += 1
n += 1
lstViewObjects.Items.Add o.objName
append checkedObjectIndices n
)
lstViewObjects.EndUpdate()
-- DEBUG
--print checkedObjectIndices
--print checkedObjects
)
fn RefreshListView o = (
lstView.BeginUpdate()
local xdiff = ( o.initialPos.x - o.finalPos.x ) as string
local ydiff = ( o.initialPos.y - o.finalPos.y ) as string
local zdiff = ( o.initialPos.z - o.finalPos.z ) as string
lvops.ClearLvItems lstView
lvops.AddLvItem lstView pTextItems:#( "1. Position Difference", "[ " + xdiff + ", " + ydiff + ", " + zdiff + " ]" )
lvops.AddLvItem lstView pTextItems:#( "2. Initial Position", o.initialPos as string )
lvops.AddLvItem lstView pTextItems:#( "3. Final Position", o.finalPos as string )
lvops.AddLvItem lstView pTextItems:#( "4. Initial Orientation", o.initialRot as string )
lvops.AddLvItem lstView pTextItems:#( "5. Final Orientation", o.finalRot as string )
lstView.EndUpdate()
)
fn GetCheckedObjects = (
local items = ( lvops.GetLvItems lstViewObjects )
objDefs = #()
for o in items do
(
local idx = checkedObjectIndices[o.index+1]
-- DEBUG
--format "Item % checked: %; real item index: %\n" o.index (lvops.GetLvItemCheck lstView o.index ) idx
if ( lvops.GetLvItemCheck lstViewObjects o.index ) then
(
-- DEBUG
-- format "Item % is checked, object: %\n" o.index checkedObjects[idx]
append objDefs checkedObjects[idx]
)
)
objDefs
)
-- Build object definition cache for loaded objects
fn BuildCache = (
checkedObjectsInMap = #()
-- Ensure our list is initialised undefined for all
for co in checkedObjects do
(
append checkedObjectsInMap undefined
)
-- Loop through all objects trying to find the checkedObjects
local numObjects = $objects.count
local i = 0
for o in $objects do
(
barProgress.value = 100.0 * i / numObjects
i += 1
if ( "Gta Object" != GetAttrClass o ) then
continue
local objName = undefined
objName = if ( isRefObj o ) then ( toLower o.objectName ) else ( toLower o.name )
-- Loop through all checkedObjects
local nCheckedObj = 1
for co in checkedObjects do
(
if ( objName == (toLower co.objName) ) and ( PosEqual o.pos co.initialPos ) then
(
checkedObjectsInMap[nCheckedObj] = o
break
)
nCheckedObj += 1
)
)
print checkedObjectsInMap
)
fn Import filename = (
-- Open file and process lines, constructing checkedObjects data
if ( undefined != filename ) then
(
fp = openFile filename mode:"rt"
local rectMin, rectMax, rectCentre
while ( not ( eof fp ) ) do
(
local dataLine = readLine fp
-- Skip empty lines
if ( 0 == dataLine.count ) then
continue
if ( matchPattern dataLine pattern:"# Actual Player Pos*" ) then
(
centreArray = filterString (filterString dataLine ":")[2] " "
rectCentre = Point3 (centreArray[1] as float) (centreArray[2] as float) (centreArray[3] as float)
continue
)
if ( matchPattern dataLine pattern:"# Sector Min Coords*" ) then
(
minArray = filterString (filterString dataLine ":")[2] " "
rectMin = Point2 (minArray[1] as float) (minArray[2] as float)
continue
)
if ( matchPattern dataLine pattern:"# Sector Max Coords*" ) then
(
maxArray = filterString (filterString dataLine ":")[2] " "
rectMax = Point2 (maxArray[1] as float) (maxArray[2] as float)
continue
)
-- Skip comment "#" lines
if ( matchPattern dataLine pattern:"#*" ) then
continue
-- Filter data line as comma separated data
local filtLine = filterString dataLine ","
local posA = [ filtLine[2] as float, filtLine[3] as float, filtLine[4] as float ]
local posB = [ filtLine[5] as float, filtLine[6] as float, filtLine[7] as float ]
local rotA = undefined
local rotB = undefined
if ( filtLine.count > 7 ) then
(
rotA = quat (filtLine[8] as float) (filtLine[9] as float) (filtLine[10] as float) (filtLine[11] as float)
rotB = quat (filtLine[12] as float) (filtLine[13] as float) (filtLine[14] as float) (filtLine[15] as float)
)
obj = ObjectCheckerDef objName:filtLine[1] initialPos:posA initialRot:rotA finalPos:posB finalRot:rotB
append checkedObjects obj
)
if ( rectMin != undefined and rectMax != undefined and rectCentre != undefined ) do
(
r = Rectangle length:(abs (rectMax.x - rectMin.x)) width:(abs (rectMax.y - rectMin.y)) pos:rectCentre
append rectangleArray r
)
close fp
)
)
-- Find previous checked object
fn FindBackCheckedObject currIdx = (
local items = ( lvops.GetLvItems lstViewObjects )
local idx = currIdx
for o in items do
(
if ( o.index >= currIdx ) then
continue
if ( not o.checked ) then
continue
-- Skip objects not in our map section
if ( undefined == checkedObjectsInMap[o.index+1] ) then
continue
idx = o.index
)
idx
)
-- Find next checked object
fn FindNextCheckedObject currIdx = (
local items = ( lvops.GetLvItems lstViewObjects )
for o in items do
(
if ( o.index <= currIdx ) then
continue
if ( not o.checked ) then
continue
-- Skip objects not in our map section
if ( undefined == checkedObjectsInMap[o.index+1] ) then
continue
return ( o.index )
)
undefined
)
fn UpdateInfoLabel = (
local ss = stringStream ""
format "Object % of %." autoRunObjIdx checkedObjects.count to:ss
lblInfo.text = ( ss as string )
)
-------------------------------------------------------------------------------
-- Events
-------------------------------------------------------------------------------
-- Dialog open event
on GtaObjectPosCheckerImportRoll open do
(
-- Initialise TreeView
lvops.InitListView lstViewObjects pLabelEdit:false pAllowReorder:false pCheckBoxes:true
lvops.AddLvColumnHeader lstViewObjects pCaption:"Object" pWidth:150
-- Initialise ListView
lvops.InitListView lstView pLabelEdit:false pAllowReorder:false pCheckBoxes:false
lvops.AddLvColumnHeader lstView pCaption:"Parameter" pWidth:120
lvops.AddLvColumnHeader lstView pCaption:"Value" pWidth:260
)
on GtaObjectPosCheckerImportRoll close do
(
for o in rectangleArray do ( if classof o == Rectangle then delete o )
rectangleArray = #()
)
-- Import File Button Event Handler
on btnImport pressed do
(
for o in rectangleArray do ( if classof o == Rectangle then delete o )
rectangleArray = #()
-- Initialisation
fileName = getOpenFileName caption:"Select Object Checker output file:" \
types:"Object Checker Sector Files (*.objchk)|*.objchk|All Files (*.*)|*.*"
checkedObjectIndices = #()
checkedObjects = #()
Import fileName
-- Before refreshing our view, lets sort out objects so our view indicies
-- match when they are sorted in the damn listview.
qsort checkedObjects ObjectCheckerDef.cmp
BuildCache()
RefreshTreeView()
local ss = stringStream ""
format "% objects loaded." checkedObjects.count to:ss
lblInfo.text = ( ss as string )
)
-- Import Directory Button Event Handler
on btnImportDir pressed do
(
for o in rectangleArray do ( if classof o == Rectangle then delete o )
rectangleArray = #()
-- Initialisation
fileName = getOpenFileName caption:"Select Object Checker output file:" \
types:"Object Checker Sector Files (*.objchk)|*.objchk|All Files (*.*)|*.*"
checkedObjectIndices = #()
checkedObjects = #()
local filepath = RsRemoveFile fileName
local files = getFiles ( filepath + "\\*.objchk" )
for file in files do
Import file
-- Before refreshing our view, lets sort out objects so our view indicies
-- match when they are sorted in the damn listview.
qsort checkedObjects ObjectCheckerDef.cmp
BuildCache()
RefreshTreeView()
local ss = stringStream ""
format "% objects loaded." checkedObjects.count to:ss
lblInfo.text = ( ss as string )
)
-- On autorun start do
on btnAutoRun pressed do
(
if ( 0 != mode ) then
return false
-- Setup first object
autoRunObjIdx = FindNextCheckedObject -1
if ( undefined == autoRunObjIdx ) then
(
MessageBox "No objects in loaded list are in this map section."
return false
)
-- Initialise UI controls for AutoRun Mode
mode = 1
btnInitial.enabled = true
btnFinal.enabled = true
btnNext.enabled = true
btnBack.enabled = true
btnStop.enabled = true
-- Select object and zoom into it
clearSelection()
selectMore checkedObjectsInMap[autoRunObjIdx+1]
max zoomext sel
redrawViews()
UpdateInfoLabel()
)
-- On node click
on lstViewObjects ItemSelectionChanged e do
(
-- Find objectDef struct this node references
local idx = e.itemindex + 1
RefreshListView checkedObjects[idx]
)
-- Check All Button Event Handler
on btnCheckAll pressed do
(
for i = 0 to lstViewObjects.Items.Count-1 do
(
lvops.SetLvItemCheck lstViewObjects i true
)
)
-- Invert checked status Button Event Handler
on btnInvChecked pressed do
(
for i = 0 to lstViewObjects.Items.Count-1 do
(
lvops.SetLvItemCheck lstViewObjects i ( not ( lvops.GetLvItemCheck lstViewObjects i ) )
)
)
-- Find Checked object(s)
on btnFindObject pressed do
(
local items = ( lvops.GetLvItems lstViewObjects )
clearSelection()
for o in items do
(
if ( lvops.GetLvItemCheck lstViewObjects o.index ) then
(
if ( undefined != checkedObjectsInMap[o.index+1] ) then
selectMore checkedObjectsInMap[o.index+1]
)
)
if ( 0 == $selection.count ) then
MessageBox "No objects found. They will be in a different map section."
else
max zoomext sel
)
on btnFindSelObject pressed do
(
if ( selection.count == 1 ) do
(
objNameSelected = toLower $.objectName
objPosSelected = $.pos
for idx = 1 to checkedObjects.count do
(
-- Might find multiple matches, so then check the positions to make sure right one found
if (objNameSelected == (toLower checkedObjects[idx].objName)) do
(
if (PosEqual objPosSelected checkedObjects[idx].initialPos ) do
(
lvops.SetLvItemCheck lstViewObjects (idx - 1) true
RefreshListView checkedObjects[idx]
)
)
)
)
)
-- Close Button Event Handler
on btnClose pressed do
(
closeRolloutFloater GtaObjectPosCheckerImportUtil
)
-----------------------------------------------------------------------------
-- Auto-Run Mode Event Handlers
-----------------------------------------------------------------------------
on btnInitial pressed do
(
if ( 1 != mode ) then
return false
in coordsys world
(
-- DEBUG
--format "Moving to %\n\tobject def: %\n" checkedObjects[autoRunObjIdx+1].initialPos checkedObjects[autoRunObjIdx+1]
local orientMat = inverse( checkedObjects[autoRunObjIdx+1].initialRot ) as Matrix3
orientMat.translation = checkedObjects[autoRunObjIdx+1].initialPos
checkedObjectsInMap[autoRunObjIdx+1].transform = orientMat
-- DEBUG
--local angles = quatToEuler ( inverse( checkedObjects[autoRunObjIdx+1].finalRot ) )
--format "Object %\n\tX Rotation: %\n\tY Rotation:%\n\tZ Rotation: %\n\n" checkedObjects[autoRunObjIdx+1].objName angles.x angles.y angles.z
)
)
on btnFinal pressed do
(
if ( 1 != mode ) then
return false
in coordsys world
(
-- DEBUG
--format "Moving to %\n\tobject def: %\n" checkedObjects[autoRunObjIdx+1].finalPos checkedObjects[autoRunObjIdx+1]
local orientMat = inverse( checkedObjects[autoRunObjIdx+1].finalRot ) as Matrix3
orientMat.translation = checkedObjects[autoRunObjIdx+1].finalPos
checkedObjectsInMap[autoRunObjIdx+1].transform = orientMat
local angles = quatToEuler ( inverse( checkedObjects[autoRunObjIdx+1].finalRot ) )
-- DEBUG
--format "Object %\n\tX Rotation: %\n\tY Rotation:%\n\tZ Rotation: %\n\n" checkedObjects[autoRunObjIdx+1].objName angles.x angles.y angles.z
-- If our X or Y angle is greater than our threshold then set our Use Full Matrix attribute
if ( angles.x > degThreshold ) or ( angles.y > degThreshold ) or
( angles.x < ( -degThreshold ) ) or ( angles.y < ( -degThreshold ) ) then
SetAttr checkedObjectsInMap[autoRunObjIdx+1] useFullMatrixIdx true
)
)
on btnBack pressed do
(
if ( 1 != mode ) then
return false
autoRunObjIdx = FindBackCheckedObject autoRunObjIdx
-- Select object and zoom into it
clearSelection()
selectMore checkedObjectsInMap[autoRunObjIdx+1]
max zoomext sel
redrawViews()
UpdateInfoLabel()
)
on btnNext pressed do
(
if ( 1 != mode ) then
return false
autoRunObjIdx = FindNextCheckedObject autoRunObjIdx
if ( undefined == autoRunObjIdx ) then
(
MessageBox "All objects processed."
autoRunObjIdx = undefined
mode = 0
btnInitial.enabled = false
btnFinal.enabled = false
btnBack.enabled = false
btnNext.enabled = false
btnStop.enabled = false
local ss = stringStream ""
format "% objects loaded." checkedObjects.count to:ss
lblInfo.text = ( ss as string )
return false
)
-- Select object and zoom into it
clearSelection()
selectMore checkedObjectsInMap[autoRunObjIdx+1]
max zoomext sel
redrawViews()
UpdateInfoLabel()
)
on btnStop pressed do
(
if ( 1 != mode ) then
return false
autoRunObjIdx = undefined
mode = 0
btnInitial.enabled = false
btnFinal.enabled = false
btnBack.enabled = false
btnNext.enabled = false
btnStop.enabled = false
local ss = stringStream ""
format "% objects loaded." checkedObjects.count to:ss
lblInfo.text = ( ss as string )
)
)
try closeRolloutFloater GtaObjectPosCheckerImportUtil catch()
GtaObjectPosCheckerImportUtil = newRolloutFloater "Physical Object Position Checker" 600 730 0 50
addRollout GtaObjectPosCheckerInitiatorRoll GtaObjectPosCheckerImportUtil
addRollout GtaObjectPosCheckerImportRoll GtaObjectPosCheckerImportUtil
-- End of GtaObjectPositionChecker.ms MAXScript