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

601 lines
17 KiB
Plaintext
Executable File

--
-- 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\\util\\file.ms"
-----------------------------------------------------------------------------
-- Rollouts
-----------------------------------------------------------------------------
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
function 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
-------------------------------------------------------------------------------
-- 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"
dotNetControl lstViewObjects "System.Windows.Forms.ListView" width:180 height:100 across:2
dotNetControl lstView "System.Windows.Forms.ListView" width:375 height:100 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
-- Loop through all checkedObjects
local nCheckedObj = 1
for co in checkedObjects do
(
if ( XRefObject == classof o ) then
(
if ( o.objectName == co.objName ) and ( PosEqual o.pos co.initialPos ) then
(
checkedObjectsInMap[nCheckedObj] = o
break
)
)
else
(
if ( o.name == 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"
while ( not ( eof fp ) ) do
(
local dataLine = readLine fp
-- Skip empty lines
if ( 0 == dataLine.count ) then
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
)
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:230
)
-- Import File Button Event Handler
on btnImport pressed do
(
-- 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
(
-- 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
)
-- 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 285 0 50
addRollout GtaObjectPosCheckerImportRoll GtaObjectPosCheckerImportUtil
-- End of GtaObjectPositionChecker.ms MAXScript