Files
2025-09-29 00:52:08 +02:00

1796 lines
70 KiB
Plaintext
Executable File

------------------------------------------------------------------------------------
--
-- File:: EditIPLCullBoxes.ms
-- Description:: IPL Cull Box Management - Edit, move, enable/disable, etc.
--
-- Author:: Martin Good <martin.good@rockstarnorth.com
-- Date:: 16/01/2014
--
------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
-- FILE IN
--------------------------------------------------------------------------------------------------------------------------------
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms")
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/FN_RSTA_XML.ms")
fileIn "pipeline/util/RAG_funcs.ms"
filein "pipeline/util/assert.ms"
--------------------------------------------------------------------------------------------------------------------------------
-- STRUCTS
--------------------------------------------------------------------------------------------------------------------------------
struct BBox (xmin, xmax, ymin, ymax, zmin, zmax)
--struct BoxParam (width, height, length, xpos, ypos, zpos)
struct IPLCullBox (name, state, bounds, oldbounds, culledNames, state, marker)
--------------------------------------------------------------------------------------------------------------------------------
-- ROLLOUT
--------------------------------------------------------------------------------------------------------------------------------
try (DestroyDialog RsEditCullBoxFiles) catch()
rollout RsEditCullBoxFiles "Edit IPL Cull Boxes" width:460
(
Local LibertyNames =#()
Local LibertyHashes =#()
Local VNames = #()
Local VHashes = #()
Local projectNames = #()
Local projectHashes = #()
local LosSantos = 1
local Liberty = 2
local projectPath= #("X:\\gta5\\build\\dev\\common\\data\\", "X:\\gta5_liberty\\build\\dev\\common\\data\\")
local NGProjectPath = #("X:\\gta5\\build\\dev_ng\\common\\data\\", "X:\\gta5_liberty\\build\\dev_ng\\common\\data\\")
local loadIPL_name = "mapdatacullboxes.meta"
local saveIPL_name = "mapdatacullboxes.meta"
local DefaultLoadIPLName = "mapdatacullboxes.meta"
local DefaultSaveIPLName = "mapdatacullboxes.meta"
local iniFile = (RsConfigGetWildWestDir() + @"script\3dsMax\Optimisation\ContainerHashData.ini")
local CullBoxes = #()
local IPLHeader = ""
local InitialSeed = random 0 255
local OffColour = color 240 30 20
local ChangedColour = color 245 195 40
local ChangedOffColour = color 100 10 5
local RenamedColour = color 255 138 20
local NewBoxColour = color 255 249 170
local NoColour = color 128 128 128
local ProgressColour = color 60 230 20
local precisionValue = 0.001 -- Maximum allowable deviation from the loaded bounds values... to stop unmodified boxes getting flagged as changed.
local WidgetsOn = false
local RAGConnected = false
--------------------------------------------------------------------------------------------------------------------------------
-- CONTROLS
--------------------------------------------------------------------------------------------------------------------------------
dotNetControl rsBannerPanel "System.Windows.Forms.Panel" height:32 pos:[0,0] width:RsEditCullBoxFiles.width
local banner = makeRsBanner dn_Panel:rsBannerPanel versionNum:1.0 versionName:"Calculating Creature" colourScheme:#eval filename:(getThisScriptFilename())
group "Cull Box Files"
(
dropdownlist ActiveProject "" items:#("V (Los Santos)", "Liberty") selection:2 across:3 width:96 height:20 align:#left offset:[-5,-2]
checkbox ActiveGen "NG" checked:false align:#left offset:[-54,0]
editText ActiveProjectPath "" text:projectPath[2]width:322 height:16 offset:[5,0] align:#right enabled:true readonly:true
button LoadCullBoxFile "LOAD" across:3 width:54 height:20 align:#left offset:[-5,0] tooltip:"Load an IPL Cull Box meta file."
editText ReadCullBoxFileName "" text:loadIPL_name width:356 offset:[104,1] align:#right enabled:true readonly:false tooltip:"IPL Cull Box meta file to load." -- height:20 makes it multiline which isn't clever
button ChangeLoadCullBoxFile "Browse" width:48 height:20 align:#right offset:[5,0] tooltip:"Change LOAD IPL Cull Box meta file."
button SaveCullBoxFile "SAVE" across:3 width:54 height:20 align:#left offset:[-5,0] enabled:false tooltip:"Save an IPL Cull Box meta file."
editText SaveCullBoxFileName "" text:saveIPL_name width:356 offset:[104,1] align:#right readonly:false tooltip:"IPL Cull Box meta file to save." enabled:false -- height:20 makes it multiline which isn't clever
button ChangeSaveCullBoxFile "Browse" width:48 height:20 align:#right offset:[5,0] tooltip:"Change SAVE IPL Cull Box meta file." enabled:false
progressBar Progress "" color:ProgressColour value:0 align:#left width:460 height:10 offset:[-5,0]
)
group "IPL Cull Boxes"
(
-- Box / Cull / Container Lists
listbox BoxList " Cull Boxes" items:#() height:46 across:3 align:#left width:167 offset:[110,-4] readonly:false -- adding widgets above : y -= (widget height + 4)
listbox CullList " Culled Areas" items:#() height:46 align:#left width:88 offset:[128,-4] readonly:true
multilistbox ContainerList " All Containers" items:LibertyNames height:46 align:#right width:88 offset:[5,-4] readonly:true enabled:false
button RAGConnect "Connect" align:#left height:60 width:110 offset:[-4,-610] enabled:false
-- Position / Size widgets
spinner XMinVal "X Min" range:[-10000,10000,0] scale:1 type:#float align:#right fieldwidth:64 offset:[-344,8] enabled:false
spinner XMaxVal "X Max" range:[-10000,10000,0] scale:1 type:#float align:#right fieldwidth:64 offset:[-344,0] enabled:false
spinner YMinVal "Y Min" range:[-10000,10000,0] scale:1 type:#float align:#right fieldwidth:64 offset:[-344,0] enabled:false
spinner YMaxVal "Y Max" range:[-10000,10000,0] scale:1 type:#float align:#right fieldwidth:64 offset:[-344,0] enabled:false
spinner ZMinVal "Z Min" range:[-10000,10000,0] scale:1 type:#float align:#right fieldwidth:64 offset:[-344,0] enabled:false
spinner ZMaxVal "Z Max" range:[-10000,10000,0] scale:1 type:#float align:#right fieldwidth:64 offset:[-344,0] enabled:false
spinner XPosVal "X Pos" range:[-10000,10000,0] scale:1 type:#float align:#right fieldwidth:64 offset:[-344,5] enabled:false
spinner YPosVal "Y Pos" range:[-10000,10000,0] scale:1 type:#float align:#right fieldwidth:64 offset:[-344,0] enabled:false
spinner ZPosVal "Z Pos" range:[-10000,10000,0] scale:1 type:#float align:#right fieldwidth:64 offset:[-344,0] enabled:false
edittext XRelVal "X Rel" align:#right fieldwidth:62 offset:[-356,3] enabled:false
edittext YRelVal "Y Rel" align:#right fieldwidth:62 offset:[-356,-1] enabled:false
edittext ZRelVal "Z Rel" align:#right fieldwidth:62 offset:[-356,-1] enabled:false
-- Box Info / Toggles N Shit
progressBar ActiveBoxColour "" color:NoColour value:100 align:#left width:24 height:24 offset:[82,8] enabled:true
label ActiveBoxState "" align:#left width:72 height:24 offset:[5,-25]
edittext ActiveBoxName "" text:"" width:114 height:17 align:#left offset:[-8, -5] enabled:false
button ResetBox "Reset X/Y/Z" align:#left height:30 width:110 offset:[-4,4] enabled:false
button UpdateAllBoxes "Fix Box Positions" align:#left height:24 width:110 offset:[-4,-1] enabled:false
button ToggleBox "Toggle On/Off" align:#left height:24 width:110 offset:[-4,9] enabled:false
button ShowHideBox "Hide/Unhide" align:#left height:24 width:110 offset:[-4,0] enabled:false
button ShowAll "Unhide All Boxes" align:#left height:24 width:110 offset:[-4,0] enabled:false
button CreateBox "New Cull Box" align:#left height:40 width:110 offset:[-4,8] enabled:false
button DeleteBox "Delete Box" align:#left height:24 width:110 offset:[-4,0] enabled:false
--button RAGConnect "Connect" align:#left height:60 width:110 offset:[-4,8] enabled:false
-- Bottom Container Buttons
button AddContainers "Add" across:2 align:#right width:87 height:24 offset:[141,-29] enabled:false
button RemoveContainers "Remove" align:#right width:87 height:24 offset:[5,-29] enabled:false
button SelectCulled "Select Culled Areas" align:#right width:166 height:24 offset:[-173,-29] enabled:false
button SelectAtCamera "Select Boxes At Camera" align:#right width:166 offset:[-173,-0] enabled:false
dropdownlist MultiSelectType "" items:#("Common Culled Areas", "All Culled Areas") selection:1 align:#right width:135 offset:[-35,-26] enabled:true
edittext CulledCount "" text:"" width:42 height:22 align:#right offset:[5,-28] enabled:true readonly:true
checkbox ShowCurrentlyCulled "Show Culled" checked:false width:110 align:#left offset:[-4,-20] enabled:false
dropdownlist CleanType "" items:#("Selected", "All") selection:2 width:66 align:#right offset:[-173,0] enabled:false
checkbox PadCulled "Space Out Culled Areas" checked:true align:#right enabled:false offset:[-10,-22]
checkbox CullAtCameraPos "Cull At Camera Pos" checked:true align:#left offset:[-4, -22] enabled:false
button CleanBoxes "Clean Boxes" align:#right width:97 offset:[-242,-23] enabled:false
)
group "Camera Control"
(
spinner CamOffset "Offset " range:[-10.0,10.0,-0.1] scale:0.1 type:#float align:#right fieldwidth:62 offset:[4,2] enabled:false
slider CamXSlider "Camera X" range:[0.0,1.0,0.0] across:3 align:#left offset:[0,-2] orient:#horizontal enabled:false
slider CamYSlider "Camera Y" range:[0.0,1.0,0.0] align:#left offset:[0,-2] orient:#horizontal enabled:false
slider CamZSlider "Camera Z" range:[0.0,1.0,1.0] align:#left offset:[0,-2] orient:#horizontal enabled:false
)
group "Debug"
(
button Diagnosis "!!! DEBUG - Dump Cullbox Status !!!" align:#center width:450 enabled:false tooltip:"Dumps the cull box details to the listener."
button HashDump "!!! DEBUG - Dump Hash Table !!!" align:#center width:450 enabled:false tooltip:"Scans the cull boxes for unknown hashes. Dumps the list to HashTable.txt in the active project folders and POTENTIALLY DESTROYS THE BOX LIST..."
)
--------------------------------------------------------------------------------------------------------------------------------
-- FUNCTIONS
--------------------------------------------------------------------------------------------------------------------------------
fn SetStateWidgets boxNum =
(
ActiveBoxColour.color = CullBoxes[boxNum].marker.wirecolor
case CullBoxes[boxNum].marker.wirecolor of
(
OffColour: (ActiveBoxState.text = " Disabled")
ChangedColour: (ActiveBoxState.text = " Editted")
ChangedOffColour: (ActiveBoxState.text = "Edit + Disabled")
--RenamedColour: (ActiveBoxState.text = " Renamed")
NewBoxColour: (ActiveBoxState.text = " New Box")
default: (ActiveBoxState.text = " Unchanged")
)
)
--------------------------------------------------------------------------------------------------------------------------------
fn turnOffWidgets =
(
WidgetsOn = false
XMinVal.enabled = XMaxVal.enabled = YMinVal.enabled = YMaxVal.enabled = ZMinVal.enabled = ZMaxVal.enabled = false
XPosVal.enabled = YPosVal.enabled = ZPosVal.enabled = false
XRelVal.enabled = YRelVal.enabled = ZRelVal.enabled = false
ResetBox.enabled = ShowHideBox.enabled = ToggleBox.enabled = DeleteBox.enabled = false
ToggleBox.caption = "Toggle On/Off"
ShowHideBox.caption = "Show/Hide"
case selection.count of
(
0:
(
ActiveBoxColour.color = NoColour
ActiveBoxState.text = "Nothing Picked"
)
1:
(
ActiveBoxColour.color = OffColour
ActiveBoxState.text = "Not a CullBox !"
)
default:
(
ActiveBoxColour.color = selection[1].wirecolor
ActiveBoxState.text = "Multiple Select"
)
)
ActiveBoxName.text = ""
ActiveBoxName.enabled = CamXSlider.enabled = CamYSlider.enabled = CamZSlider.enabled = CamOffset.enabled = SelectCulled.enabled = PadCulled.enabled = Diagnosis.enabled = false
CleanType.selection = 2
BoxList.selection = 0
CullList.items = #()
)
--------------------------------------------------------------------------------------------------------------------------------
fn turnOnWidgets =
(
WidgetsOn = true
XMinVal.enabled = true
XMaxVal.enabled = true
YMinVal.enabled = true
YMaxVal.enabled = true
ZMinVal.enabled = true
ZMaxVal.enabled = true
XPosVal.enabled = true
YPosVal.enabled = true
ZPosVal.enabled = true
XRelVal.enabled = true
YRelVal.enabled = true
ZRelVal.enabled = true
ShowHideBox.enabled = true
ToggleBox.enabled = true
DeleteBox.enabled = true
Diagnosis.enabled = true
if RAGConnected then
(
CamXSlider.enabled = true
CamYSlider.enabled = true
CamZSlider.enabled = true
CamOffset.enabled = true
)
if BoxList.selection != 0 then
(
if CullBoxes[BoxList.selection].state then
(
ToggleBox.caption = "Switch Off"
CullList.enabled = true
)
else
(
ToggleBox.caption = "Switch On"
CullList.enabled = false
)
/*
ActiveBoxColour.color = CullBoxes[BoxList.selection].marker.wirecolor
case ActiveBoxColour.color of
(
OffColour: (ActiveBoxState.text = " Disabled")
ChangedColour: (ActiveBoxState.text = " Editted")
ChangedOffColour: (ActiveBoxState.text = "Edit + Disabled")
RenamedColour: (ActiveBoxState.text = " Renamed")
NewBoxColour: (ActiveBoxState.text = " New Box")
default: (ActiveBoxState.text = " Unchanged")
)*/
ActiveBoxName.text = BoxList.selected
ActiveBoxName.enabled = true
SetStateWidgets BoxList.selection
)
SelectCulled.enabled = true
PadCulled.enabled = true
)
--------------------------------------------------------------------------------------------------------------------------------
fn BuildCullList cnamelist =
(
cpadnamelist = deepcopy ContainerList.items
index =1
listLength = cpadnamelist.count
while index <= listLength do
(
FindIndex = findItem cnamelist cpadnamelist[index]
if FindIndex == 0 then
(
if PadCulled.state then
(
cpadnamelist[index] = " "
index += 1
)
else
(
deleteItem cpadnamelist index
listLength -= 1
)
)
else index+= 1
)
-- Catch hashes that aren't in the known hash table
for index = 1 to cnamelist.count do
(
FindIndex = findItem cpadnamelist cnamelist[index]
if FindIndex == 0 then append cpadnamelist cnamelist[index]
)
return cpadnamelist
)
--------------------------------------------------------------------------------------------------------------------------------
fn RandomColour SeedString NewSeed =
(
-- Generate a colour using the first character of each section of the CullBox Names to build a seed (ignoring the digits and postfixes).
Local SeedArray = filterstring SeedString "_0123456789 "
for index = 1 to SeedArray.count do
(
if SeedArray[index][1] != "(" then
(
NewSeed = (NewSeed * 256) + (bit.charAsInt SeedArray[index][1])
)
)
seed NewSeed
Local h = random 2.2 4.2 ; s = random 0.4 1.0 ; v = (random 205 255) as integer -- Hue should run from 0.0 to 6.0
Local i = floor h ; f = h - i
Local p = ( v * ( 1 - s ) ) as integer
Local q = ( v * ( 1 - s * f ) ) as integer
Local t = ( v * ( 1 - s * ( 1 - f ) ) ) as integer
case i of
(
0: ( r = v ; g = t ; b = p )
1: ( r = q ; g = v ; b = p )
2: ( r = p ; g = v ; b = t )
3: ( r = p ; g = q ; b = v )
4: ( r = t ; g = p ; b = v )
default: ( r = v ; g = p ; b = q )
)
--format "H: %, R: %, G: %, B: %\n" h r g b
return (color r g b)
)
--------------------------------------------------------------------------------------------------------------------------------
fn CheckForBoundsChange boxNum=
(
if ResetBox.enabled then
(
xminDiff = abs (CullBoxes[boxNum].bounds.xmin - CullBoxes[boxNum].oldbounds.xmin)
xmaxDiff = abs (CullBoxes[boxNum].bounds.xmax - CullBoxes[boxNum].oldbounds.xmax)
yminDiff = abs (CullBoxes[boxNum].bounds.ymin - CullBoxes[boxNum].oldbounds.ymin)
ymaxDiff = abs (CullBoxes[boxNum].bounds.ymax - CullBoxes[boxNum].oldbounds.ymax)
zminDiff = abs (CullBoxes[boxNum].bounds.zmin - CullBoxes[boxNum].oldbounds.zmin)
zmaxDiff = abs (CullBoxes[boxNum].bounds.zmax - CullBoxes[boxNum].oldbounds.zmax)
if ((xminDiff > 0.001) or (xmaxDiff > 0.001) or (yminDiff > 0.001) or (ymaxDiff > 0.001) or (zminDiff > 0.001) or (zmaxDiff > 0.001) ) then
(
case CullBoxes[boxNum].marker.wirecolor of
(
OffColour: CullBoxes[boxNum].marker.wirecolor = ChangedOffColour
ChangedOffColour: CullBoxes[boxNum].marker.wirecolor = ChangedOffColour
NewBoxColour: CullBoxes[boxNum].marker.wirecolor = NewBoxColour
default: CullBoxes[boxNum].marker.wirecolor = ChangedColour
)
)
else
(
ResetBox.enabled = false
case CullBoxes[boxNum].marker.wirecolor of
(
OffColour: CullBoxes[boxNum].marker.wirecolor = OffColour
ChangedOffColour: CullBoxes[boxNum].marker.wirecolor = OffColour
NewBoxColour: CullBoxes[boxNum].marker.wirecolor = NewBoxColour
default: CullBoxes[boxNum].marker.wirecolor = RandomColour CullBoxes[boxNum].name InitialSeed
)
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
fn UpdateBoxParams =
(
xsize = CullBoxes[BoxList.selection].bounds.xmax - CullBoxes[BoxList.selection].bounds.xmin
ysize = CullBoxes[BoxList.selection].bounds.ymax - CullBoxes[BoxList.selection].bounds.ymin
zsize = CullBoxes[BoxList.selection].bounds.zmax - CullBoxes[BoxList.selection].bounds.zmin
x = (CullBoxes[BoxList.selection].bounds.xmin + CullBoxes[BoxList.selection].bounds.xmax) / 2.0
y = (CullBoxes[BoxList.selection].bounds.ymin + CullBoxes[BoxList.selection].bounds.ymax) / 2.0
z = CullBoxes[BoxList.selection].bounds.zmin
CullBoxes[BoxList.selection].marker.pos = [x, y, z]
CullBoxes[BoxList.selection].marker.width = xsize
CullBoxes[BoxList.selection].marker.length = ysize
CullBoxes[BoxList.selection].marker.height = zsize
XPosVal.value = CullBoxes[BoxList.selection].marker.pos.x
YPosVal.value = CullBoxes[BoxList.selection].marker.pos.y
ZPosVal.value = CullBoxes[BoxList.selection].marker.pos.z
CheckForBoundsChange BoxList.selection
SetStateWidgets BoxList.selection
)
--------------------------------------------------------------------------------------------------------------------------------
fn UpdateBBox boxNum=
(
XMinVal.value = CullBoxes[boxNum].bounds.xmin = CullBoxes[boxNum].marker.pos.x - (CullBoxes[boxNum].marker.width / 2.0)
XMaxVal.value = CullBoxes[boxNum].bounds.xmax = CullBoxes[boxNum].marker.pos.x + (CullBoxes[boxNum].marker.width / 2.0)
YMinVal.value = CullBoxes[boxNum].bounds.ymin = CullBoxes[boxNum].marker.pos.y - (CullBoxes[boxNum].marker.length / 2.0)
YMaxVal.value = CullBoxes[boxNum].bounds.ymax = CullBoxes[boxNum].marker.pos.y + (CullBoxes[boxNum].marker.length / 2.0)
ZMinVal.value = CullBoxes[boxNum].bounds.zmin = CullBoxes[boxNum].marker.pos.z
ZMaxVal.value = CullBoxes[boxNum].bounds.zmax = CullBoxes[boxNum].marker.pos.z + CullBoxes[boxNum].marker.height
XPosVal.value = CullBoxes[boxNum].marker.pos.x
YPosVal.value = CullBoxes[boxNum].marker.pos.y
ZPosVal.value = CullBoxes[boxNum].marker.pos.z
CheckForBoundsChange boxNum
SetStateWidgets boxNum
)
--------------------------------------------------------------------------------------------------------------------------------
fn BuildContainerSelection =
(
sharedContainers = deepCopy ContainerList.items
if (MultiSelectType.selection < 3) then
(
for boxnum = 1 to selection.count do
(
cbox = findItem BoxList.items selection[boxnum].name
if cbox != 0 then
(
for index = 1 to sharedContainers.count do
(
ContainerSet = findItem CullBoxes[cbox].culledNames sharedContainers[index]
case MultiSelectType.selection of
(
1: ( if ContainerSet == 0 then sharedContainers[index] = " " )
2: ( if ContainerSet != 0 then sharedContainers[index] = " " )
)
)
)
)
)
else
(
boxName = MultiSelectType.selected
cbox = findItem BoxList.items boxName
if cbox != 0 then
(
for index = 1 to sharedContainers.count do
(
if (findItem CullBoxes[cbox].culledNames sharedContainers[index]) == 0 then sharedContainers[index] = " "
)
)
)
sharedList = #()
for index = 1 to sharedContainers.count do
(
case MultiSelectType.selection of
(
1: ( if sharedContainers[index] != " " then append sharedList index ) -- Set Intersection
2: ( if sharedContainers[index] == " " then append sharedList index ) -- Set Union (inverted)
default: (if sharedContainers[index] != " " then append sharedList index ) -- Individual cullbox
)
)
ContainerList.selection = sharedList
CulledCount.text = sharedList.count as string
)
--------------------------------------------------------------------------------------------------------------------------------
fn GenerateNewName NewBoxName =
(
checkBoxNames = #()
if NewBoxName == "CullBox" then append checkBoxNames "CullBox" -- include default root name so new boxes always have an incremental postfix
for index = 1 to CullBoxes.count do
(
if (findString CullBoxes[index].name NewBoxName) == 1 then append checkBoxNames CullBoxes[index].name
)
if ((checkBoxNames.count > 0) and (findItem checkBoxNames NewBoxName != 0)) then
(
nameDuped = true
postNum = 0 as integer
while nameDuped do
(
postNum += 1
nameDuped = false
postStr = postNum as string
postStr = replace "_New000" (8 - postStr.count) postStr.count postStr
for index = 1 to checkBoxNames.count while (not nameDuped) do
(
if (NewBoxName + postStr) == checkBoxNames[index] then
(
nameDuped = true
)
)
)
NewBoxName += postStr
)
return NewBoxName
)
--------------------------------------------------------------------------------------------------------------------------------
fn renameActiveBox NewName =
(
if CullBoxes[BoxList.selection].name != NewName then
(
callbacks.removeScripts #nodeRenamed id:#EditIPLCullBoxes
nameCheck = GenerateNewName NewName
format "Original = % : NewName = % -> Checked = %\n" CullBoxes[BoxList.selection].name NewName nameCheck
if nameCheck != NewName then
(
warningText = NewName+" : name already used.\nRename as '"+nameCheck+"' instead?"
if (queryBox warningText) then
(
CullBoxes[BoxList.selection].name = nameCheck
)
ActiveBoxName.text = CullBoxes[BoxList.selection].marker.name = CullBoxes[BoxList.selection].name
)
else
(
CullBoxes[BoxList.selection].marker.name = nameCheck
)
CullBoxes[BoxList.selection].name = BoxList.selected = CullBoxes[BoxList.selection].marker.name
callbacks.addScript #nodeRenamed "RsEditCullBoxFiles.BoxRenameCallBack()" id:#EditIPLCullBoxes
)
)
--------------------------------------------------------------------------------------------------------------------------------
fn SelectCallBack =
(
deleteAllChangeHandlers id:#RsEditCullBoxesTransforms
if ContainerList.enabled then
( -- Only if ContainerList is enabled == there's data loaded
BoxList.enabled = true
BoxFound = false
BoxCount = 0
if selection.count == 1 then
(
for index = 1 to CullBoxes.count do
(
if selection[1].name == Cullboxes[index].name then
(
BoxList.selection = index
CullList.items = BuildCullList CullBoxes[index].culledNames
BoxFound = true
turnOnWidgets()
if (CullBoxes[BoxList.selection].marker.wirecolor == ChangedColour) or (CullBoxes[BoxList.selection].marker.wirecolor == ChangedOffColour) then
(
ResetBox.enabled = true
)
else
(
ResetBox.enabled = false
)
if CullBoxes[BoxList.selection].marker.ishidden then
(
ShowHideBox.caption = "Show"
)
else
(
ShowhideBox.caption = "Hide"
)
if CullBoxes[BoxList.selection].state then
(
ToggleBox.caption = "Switch Off"
CullList.enabled = true
)
else
(
ToggleBox.caption = "Switch On"
CullList.enabled = false
)
XminVal.value = CullBoxes[index].bounds.xmin
XmaxVal.value = CullBoxes[index].bounds.xmax
YminVal.value = CullBoxes[index].bounds.ymin
YmaxVal.value = CullBoxes[index].bounds.ymax
ZminVal.value = CullBoxes[index].bounds.zmin
ZmaxVal.value = CullBoxes[index].bounds.zmax
XPosVal.value = CullBoxes[index].marker.pos.x
YPosVal.value = CullBoxes[index].marker.pos.y
ZPosVal.value = CullBoxes[index].marker.pos.z
if RAGConnected and (RemoteConnection.IsConnected()) then
(
RemoteConnection.WriteStringWidget "Scene/IPL Cull Boxes/Find box by name" selection[1].name
--RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Find next" true
)
)
)
/* -- More useful to keep previous multi-selection active
if MultiSelectType.items.count > 2 then
(
MultiSelectType.selection = 1
MultiSelectType.items = #("Common Culled Areas", "All Culled Areas")
)*/
)
else
(
if selection.count > 1 then
(
--BoxList.enabled = false
-- Build shared Culled Area list for ContainerList.items
MultiSelectList = #("Common Culled Areas", "All Culled Areas")
SelectedContainerList = #()
for boxnum = 1 to selection.count do
(
append SelectedContainerList selection[boxnum].name
)
sort SelectedContainerList
join MultiSelectList SelectedContainerList
MultiSelectType.items = MultiSelectList
BuildContainerSelection()
)
)
if (ContainerList.selection.isempty) or (selection.count != 1) then
(
AddContainers.enabled = false
RemoveContainers.enabled = false
)
else
(
AddContainers.enabled = true
RemoveContainers.enabled = true
)
if (BoxFound == false) then --and (WidgetsOn == true) then
(
turnOffWidgets()
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
fn BoxRenameCallBack =
(
if BoxList.selection != 0 then
(
renameActiveBox selection[1].name
)
)
--------------------------------------------------------------------------------------------------------------------------------
fn FloatToString val =
(
-- Not strictly necessary... used to retain the 6 decimal places in the original XML
valString = val as string
valSplit = filterstring valString "."
if valSplit[2] != undefined then valSixDP = valSplit[2]+"000000" else valSixDP = "000000"
valString = valSplit[1]+"."+(substring valSixDP 1 6)
return valString
)
--------------------------------------------------------------------------------------------------------------------------------
fn SaveCullBoxes =
(
saveIPLFile = ActiveProjectPath.text + SaveCullBoxFileName.text
if saveIPLFile != undefined then
(
if (RsIsFileReadOnly saveIPLFile) then
(
errorMsg = "File not saved !!!\n\n" + saveIPLFile + " is Read Only"
messageBox errorMsg title:"File is Read Only"
)
else
(
local xml_io = rsta_xml_io()
xml_io.new "CIplCullBoxFile"
local entries_xn = rsta_xml.makeNode "entries" xml_io.root
for index = 1 to CullBoxes.count do
(
local item_xn = rsta_xml.makeNode "Item" entries_xn
local name_xn = rsta_xml.makeNode "name" item_xn innerText:CullBoxes[index].name
local aabb_xn = rsta_xml.makeNode "aabb" item_xn
local min_xn = rsta_xml.makeNode "min" aabb_xn
min_xn.setAttribute "x" (FloatToString CullBoxes[index].bounds.xmin)
min_xn.setAttribute "y" (FloatToString CullBoxes[index].bounds.ymin)
min_xn.setAttribute "z" (FloatToString CullBoxes[index].bounds.zmin)
min_xn.setAttribute "w" (FloatToString CullBoxes[index].bounds.xmin)
local max_xn = rsta_xml.makeNode "max" aabb_xn
max_xn.setAttribute "x" (FloatToString CullBoxes[index].bounds.xmax)
max_xn.setAttribute "y" (FloatToString CullBoxes[index].bounds.ymax)
max_xn.setAttribute "z" (FloatToString CullBoxes[index].bounds.zmax)
max_xn.setAttribute "w" (FloatToString CullBoxes[index].bounds.xmax)
local cullContHashes_xn = rsta_xml.makeNode "culledContainerHashes" item_xn
cullContHashes_xn.setAttribute "content" "int_array"
if (not RAGConnected) then
(
-- Change the OLD bounds to the new values only if not connected to RAG (ie. guaranteed to be a manual SAVE)... could move this section to Save button presed event
CullBoxes[index].oldbounds = CullBoxes[index].bounds
if CullBoxes[index].state then BoxColour = RandomColour CullBoxes[index].name InitialSeed
else BoxColour = OffColour
CullBoxes[index].marker.wirecolor = BoxColour
)
-- MAKE INT ARRAY STRING ------------------------------------------------------
int_array_string = "\n"
for hashindex = 1 to CullBoxes[index].culledNames.count do
(
hashname = (CullBoxes[index].culledNames[hashindex])
nhash = findItem projectNames[ActiveProject.selection] hashname
--format "%[%] : %, %\n" CullBoxes[index].name hashname CullBoxes[index].culledNames[hashindex] nhash -- !!! Trace for hash fuck ups
if (nhash == 0) then int_array_string += CullBoxes[index].culledNames[hashindex] + "\n"
else int_array_string += projectHashes[ActiveProject.selection][nhash] + "\n"
)
cullContHashes_xn.InnerText = int_array_string
if CullBoxes[index].state then rsta_xml.makeNode "bEnabled" item_xn attr:"value" value:"true"
else rsta_xml.makeNode "bEnabled" item_xn attr:"value" value:"false"
Progress.value = index * 100.0 / CullBoxes.count
)
Progress.value = 0
if RAGConnected and (RemoteConnection.IsConnected()) then
(
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Load box list" true
if BoxList.selection != 0 then
(
RemoteConnection.WriteStringWidget "Scene/IPL Cull Boxes/Find box by name" CullBoxes[BoxList.selection].name
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Find next" true
)
)
else
(
xml_io.saveas saveIPLFile
messageString = "Cull Boxes saved in " + SaveCullBoxFileName.text
messageBox messageString title:"Edit Cull Boxes"
)
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
fn LoadCullBoxes =
(
errorMessage = ""
loadIPLFile = ActiveProjectPath.text + ReadCullBoxFileName.text --loadIPL_name
print loadIPLFile
if loadIPLFile != undefined then
(
if (doesFileExist loadIPLFile) then
(
local xml_io = rsta_xml_io xmlFile:loadIPLFile
if CullBoxes.count > 0 then
(
oldMarkers = #()
for index = 1 to CullBoxes.count do
(
if (not isDeleted CullBoxes[index].marker) then append oldMarkers CullBoxes[index].marker
)
delete oldMarkers
)
CullBoxes = #()
CullBoxNames = #()
DuplicateBoxes = #()
clearselection()
BoxList.selection = 0
CullList.items = #()
turnOffWidgets()
local items_xn_array = rsta_xml.getChildren xml_io.root name:"entries/Item"
local pb_ammount = 100.0/items_xn_array.count
local pb_total = 0.0
for item_xn in items_xn_array do
(
-- BOX ------------------------------------------------------------------
Local boxName = (item_xn.SelectSingleNode "name").InnerText
Local nextmarker = getNodeByName boxname exact:true
if nextmarker == undefined then
(
nextmarker = box length:4 width:4 height:4 -- Box is missing, so make a new one
nextmarker.name = boxname
nextmarker.pos = [0,0,0]
)
local min_xn = item_xn.selectSingleNode "aabb/min"
local max_xn = item_xn.selectSingleNode "aabb/max"
xmax = (max_xn.getAttribute "x") as float
ymax = (max_xn.getAttribute "y") as float
zmax = (max_xn.getAttribute "z") as float
xmin = (min_xn.getAttribute "x") as float
ymin = (min_xn.getAttribute "y") as float
zmin = (min_xn.getAttribute "z") as float
local nextBB = BBox xmin:xmin xmax:xmax ymin:ymin ymax:ymax zmin:zmin zmax:zmax
local nextOldBB = BBox xmin:xmin xmax:xmax ymin:ymin ymax:ymax zmin:zmin zmax:zmax
local xsize = xmax - xmin
local ysize = ymax - ymin
local zsize = zmax - zmin
nextmarker.width = xsize
nextmarker.length = ysize
nextmarker.height = zsize
local xpos = (xmax + xmin) / 2.0
local ypos = (ymax + ymin) / 2.0
local zpos = zmin
nextmarker.pos = [xpos, ypos, zpos]
nextmarker.rotation = (quat 0 0 0 1)
nextmarker.scale = [1,1,1]
local boxon = rsta_xml.get_bool (item_xn.selectSingleNode "bEnabled")
if (boxon) then nextmarker.wirecolor = RandomColour nextmarker.name InitialSeed
else nextmarker.wirecolor = OffColour
-- CULL HASH --------------------------------------------------------------------
local cnamelist = #()
local hash_string = (item_xn.selectSingleNode "culledContainerHashes").InnerText
local hash_array = filterString hash_string "\n "
for hash in hash_array do
(
cname = hash
FindIndex = findItem projectHashes[ActiveProject.selection] cname
if FindIndex != 0 then
(
cname = projectNames[ActiveProject.selection][FindIndex]
)
append cnamelist cname
)
-- IPLCULL BOX --------------------------------------------------------------------
local nextbox = IPLCullBox name:boxname bounds:nextBB oldbounds:nextOldBB culledNames:cnamelist state:boxon marker:nextmarker
append CullBoxes nextbox
append CullBoxNames boxname
Progress.value = (pb_total + pb_ammount) as integer
)
ItemRead = true
BoxList.items = CullBoxNames
SaveCullBoxFile.enabled = true
ChangeSaveCullBoxFile.enabled = true
SaveCullBoxFileName.enabled = true
ContainerList.enabled = true
HashDump.enabled = true
CleanBoxes.enabled = true
CleanType.enabled = true
RAGConnect.enabled = true
UpdateAllBoxes.enabled = true
ShowAll.enabled = true
--if RAGConnected then UpdateChanges.enabled = true
CreateBox.enabled = true
if (RAGConnected and RemoteConnection.IsConnected()) do SaveCullBoxes()
)
else errorMessage += loadIPLFile = " doesn't exist \n"
)
else errorMessage += "loadIPLFile is undefined\n"
-- SHOW ERROR MESSAGE
if (errorMessage == "") then SaveCullBoxFile.enabled = true
else messageBox errorMessage title:"Edit Cull Boxes"
)
--------------------------------------------------------------------------------------------------------------------------------
fn RemoteConnectionUpdate =
(
if RAGConnected and (RemoteConnection.IsConnected()) then
(
SaveCullBoxes()
if BoxList.selection != 0 then
(
RemoteConnection.WriteStringWidget "Scene/IPL Cull Boxes/Find box by name" CullBoxes[BoxList.selection].name
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Find next" true
)
)
else
(
if RAGConnected then
(
messageBox "Connection To RAG Lost\n\nIf the game is still running, try 'Launch RAG UI', and hit 'Connect' again."
RAGConnected = false
RAGConnect.caption = "Connect"
CamXSlider.enabled = false
CamYSlider.enabled = false
CamZSlider.enabled = false
CamOffset.enabled = false
--UpdateChanges.enabled = false
SelectAtCamera.enabled = false
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
-- EVENTS
--------------------------------------------------------------------------------------------------------------------------------
on ContainerList selectionEnd do
(
if (ContainerList.selection.isempty) or (selection.count != 1) then
(
AddContainers.enabled = false
RemoveContainers.enabled = false
)
else
(
AddContainers.enabled = true
RemoveContainers.enabled = true
)
)
--------------------------------------------------------------------------------------------------------------------------------
on AddContainers pressed do
(
if BoxList.selection != 0 then
(
previousPadState = PadCulled.state
PadCulled.state = true
CBoxList = BuildCullList CullBoxes[BoxList.selection].culledNames
for index = 1 to ContainerList.selection.count do
(
if ContainerList.selection[index] then
(
CBoxList[index] = ContainerList.items[index]
)
)
--format "\n\n"
PadCulled.state = false
CullBoxes[BoxList.selection].culledNames = BuildCullList CBoxList
PadCulled.state = previousPadState
if PadCulled.state then CullList.items = CBoxList else CullList.items = CullBoxes[BoxList.selection].culledNames
RemoteConnectionUpdate()
)
)
--------------------------------------------------------------------------------------------------------------------------------
on RemoveContainers pressed do
(
if BoxList.selection != 0 then
(
for index = 1 to ContainerList.selection.count do
(
if ContainerList.selection[index] then
(
FindIndex = findItem CullBoxes[BoxList.selection].culledNames ContainerList.items[index]
if FindIndex != 0 then deleteItem CullBoxes[BoxList.selection].culledNames FindIndex
)
)
CullList.items = BuildCullList CullBoxes[BoxList.selection].culledNames
RemoteConnectionUpdate()
)
)
--------------------------------------------------------------------------------------------------------------------------------
on SelectCulled pressed do
(
if BoxList.selection != 0 then
(
previousPadState = PadCulled.state
PadCulled.state = true
CBoxList = BuildCullList CullBoxes[BoxList.selection].culledNames
sharedList = #()
sharedCount = 0
MaxContainerIndex = ContainerList.items.count
if CBoxList.count < MaxContainerIndex then MaxContainerIndex = CBoxList.count
for index = 1 to MaxContainerIndex do
(
if CBoxList[index] != " " then
(
sharedCount += 1
append sharedList index
)
)
ContainerList.selection = sharedList
CulledCount.text = sharedCount as string
PadCulled.state = previousPadState
)
)
--------------------------------------------------------------------------------------------------------------------------------
on MultiSelectType selected Arg do
(
BuildContainerSelection()
)
--------------------------------------------------------------------------------------------------------------------------------
on CleanType selected Arg do
(
case Arg of
(
1: (CleanBoxes.text = "Clean Box")
default: (CleanBoxes.text = "Clean Boxes")
)
)
--------------------------------------------------------------------------------------------------------------------------------
on CleanBoxes pressed do
(
fn CleanBox index =
(
cpadnamelist = deepcopy ContainerList.items
cindex =1
listLength = cpadnamelist.count
while cindex <= listLength do
(
FindIndex = findItem CullBoxes[index].culledNames cpadnamelist[cindex]
if FindIndex == 0 then
(
if PadCulled.state then
(
cpadnamelist[cindex] = " "
cindex += 1
)
else
(
deleteItem cpadnamelist cindex
listLength -= 1
)
)
else cindex+= 1
)
CullBoxes[index].culledNames = cpadnamelist
)
case CleanType.selection of
(
1:
(
if BoxList.selection !=0 then CleanBox BoxList.selection
)
default:
(
for index = 1 to CullBoxes.count do
(
CleanBox index
Progress.value = index * 100.0 / CullBoxes.count
)
Progress.value = 0
)
)
if BoxList.selection != 0 then CullList.items = CullBoxes[BoxList.selection].culledNames
)
--------------------------------------------------------------------------------------------------------------------------------
on SelectAtCamera pressed do
(
if RAGConnected and (RemoteConnection.IsConnected()) then
(
if (RemoteConnection.ReadStringWidget "Camera/Debug director/Active mode" == "Free") then
(
camXPos = RemoteConnection.ReadFloatWidget "Camera/Free camera/Position X"
camYPos = RemoteConnection.ReadFloatWidget "Camera/Free camera/Position Y"
camZPos = RemoteConnection.ReadFloatWidget "Camera/Free camera/Position Z"
CamInBoxes = #()
format "[%,%,%] : " camXPos camYPos camZPos
for index = 1 to CullBoxes.count do
(
if ((camXPos > CullBoxes[index].bounds.xmin) and (camXPos < CullBoxes[index].bounds.xmax)) and ((camYPos > CullBoxes[index].bounds.ymin) and (camYPos < CullBoxes[index].bounds.ymax)) and ((camZPos > CullBoxes[index].bounds.zmin) and (camZPos < CullBoxes[index].bounds.zmax)) then
(
if CullBoxes[index].state then append CamInBoxes CullBoxes[index].marker
format "% " CullBoxes[index].name
)
)
format "\n"
select CamInBoxes
)
else
(
messageBox "Game isn't in Free camera mode...\nYou need to switch to get the camera coords."
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
fn DoesIPLFileExist =
(
if (doesFileExist (ActiveProjectPath.text + ReadCullBoxFileName.text)) then LoadCullBoxFile.enabled = true
else LoadCullBoxFile.enabled = false
)
--------------------------------------------------------------------------------------------------------------------------------
on ActiveProject selected Arg do
(
if ActiveGen.state then ActiveProjectPath.text = NGProjectPath[Arg]
else ActiveProjectPath.text = projectPath[Arg]
ContainerList.items = projectNames[Arg]
DoesIPLFileExist()
)
--------------------------------------------------------------------------------------------------------------------------------
on ActiveGen changed Arg do
(
if Arg then ActiveProjectPath.text = NGProjectPath[ActiveProject.selection]
else ActiveProjectPath.text = projectPath[ActiveProject.selection]
DoesIPLFileExist()
)
--------------------------------------------------------------------------------------------------------------------------------
on LoadCullBoxFile pressed do LoadCullBoxes()
--------------------------------------------------------------------------------------------------------------------------------
on ChangeLoadCullBoxFile pressed do
(
loadIPL_name = ActiveProjectPath.text --+ ReadCullBoxFileName.text
loadIPLFile = getOpenFileName caption:"Select IPL Cull Box file to load." filename:loadIPL_name types:"meta (*.meta)|*.meta|All Files (*.*)|*.*|"
if (doesFileExist loadIPLFile) then ReadCullBoxFileName.text = ((getFilenameFile loadIPLFile) + (getFilenameType loadIPLFile))
)
--------------------------------------------------------------------------------------------------------------------------------
on ReadCullBoxFileName changed Arg do DoesIPLFileExist()
--------------------------------------------------------------------------------------------------------------------------------
on ReadCullBoxFileName entered Arg do if LoadCullBoxFile.enabled then LoadCullBoxes()
--------------------------------------------------------------------------------------------------------------------------------
on SaveCullBoxFile pressed do
(
saveIPL_name = ActiveProjectPath.text + SAveCullBoxFileName.text
if (RsIsFileReadOnly saveIPL_name) then
(
errorMsg = "Meta file not saved !!!\n\n"+saveIPL_name+" is Read Only"
messageBox errorMsg title:"File is Read Only"
)
else
(
SaveCullBoxes()
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ChangeSaveCullBoxFile pressed do
(
saveIPL_name = ActiveProjectPath.text + "mapdatacullboxes.meta"
saveIPLFile = getSaveFileName caption:"Select IPL Cull Box file to save." filename:saveIPL_name types:"meta (*.meta)|*.meta|All Files (*.*)|*.*|"
if (saveIPLFile != undefined) then SaveCullBoxFileName.text = ((getFilenameFile saveIPLFile) + (getFilenameType saveIPLFile))
)
--------------------------------------------------------------------------------------------------------------------------------
on SaveCullBoxFileName entered Arg do
(
if Arg != "" then
(
saveIPL_name = ActiveProjectPath.text + Arg
if (RsIsFileReadOnly saveIPL_name) then
(
errorMsg = "Can't save meta file !!!\n\n"+saveIPL_name+" is Read Only"
messageBox errorMsg title:"File is Read Only"
)
else
(
saveMsg = "Save Cull Boxes?\n\n"+saveIPL_name
if (queryBox saveMsg) then SaveCullBoxes()
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
on BoxList selected Arg do
(
-- Assume that the lists are in synch... Arg should be the correct index...
CullList.items = CullBoxes[Arg].culledNames
if isDeleted CullBoxes[Arg].marker then
(
newmarker = box length:4 width:4 height:4 name:CullBoxes[Arg].name
newmarker.pos = [0,0,0]
newmarker.width = 200.0 ; newmarker.length = 200.0 ; newmarker.height = 200.0
BoxColour = RandomColour newmarker.name InitialSeed
newmarker.wirecolor = BoxColour
CullBoxes[Arg].marker = newmarker
UpdateBoxParams()
)
select CullBoxes[Arg].marker
)
--------------------------------------------------------------------------------------------------------------------------------
on PadCulled changed Arg do CullList.items = BuildCullList CullList.items
--------------------------------------------------------------------------------------------------------------------------------
on XMinVal changed Arg do
(
if BoxList.selection != 0 then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].bounds.xmin = Arg
UpdateBoxParams()
)
)
--------------------------------------------------------------------------------------------------------------------------------
on XMinVal entered do RemoteConnectionUpdate()
--------------------------------------------------------------------------------------------------------------------------------
on XMaxVal changed Arg do
(
if BoxList.selection != 0 then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].bounds.xmax = Arg
UpdateBoxParams()
)
)
--------------------------------------------------------------------------------------------------------------------------------
on XMaxVal entered do RemoteConnectionUpdate()
--------------------------------------------------------------------------------------------------------------------------------
on YMinVal changed Arg do
(
if BoxList.selection != 0 then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].bounds.ymin = Arg
UpdateBoxParams()
)
)
--------------------------------------------------------------------------------------------------------------------------------
on YMinVal entered do
(
RemoteConnectionUpdate()
)
--------------------------------------------------------------------------------------------------------------------------------
on YMaxVal changed Arg do
(
if BoxList.selection != 0 then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].bounds.ymax = Arg
UpdateBoxParams()
)
)
--------------------------------------------------------------------------------------------------------------------------------
on YMaxVal entered do RemoteConnectionUpdate()
--------------------------------------------------------------------------------------------------------------------------------
on ZMinVal changed Arg do
(
if BoxList.selection != 0 then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].bounds.zmin = Arg
UpdateBoxParams()
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ZMinVal entered do RemoteConnectionUpdate()
--------------------------------------------------------------------------------------------------------------------------------
on ZMaxVal changed Arg do
(
if BoxList.selection != 0 then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].bounds.zmax = Arg
UpdateBoxParams()
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ZMaxVal entered do RemoteConnectionUpdate()
--------------------------------------------------------------------------------------------------------------------------------
on XPosVal changed Arg do
(
if BoxList.selection != 0 then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].marker.pos.x = Arg
UpdateBBox BoxList.selection
)
)
--------------------------------------------------------------------------------------------------------------------------------
on XPosVal entered do RemoteConnectionUpdate()
--------------------------------------------------------------------------------------------------------------------------------
on YPosVal changed Arg do
(
if BoxList.selection != 0 then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].marker.pos.y = Arg
UpdateBBox BoxList.selection
)
)
--------------------------------------------------------------------------------------------------------------------------------
on YPosVal entered do RemoteConnectionUpdate()
--------------------------------------------------------------------------------------------------------------------------------
on ZPosVal changed Arg do
(
if BoxList.selection != 0 then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].marker.pos.z = Arg
UpdateBBox BoxList.selection
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ZPosVal entered do RemoteConnectionUpdate()
--------------------------------------------------------------------------------------------------------------------------------
on XRelVal entered Val do
(
if BoxList.selection != 0 then
(
XAdd = Val as float
if XAdd != undefined then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].marker.pos.x += XAdd
UpdateBBox BoxList.selection
RemoteConnectionUpdate()
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
on YRelVal entered Val do
(
if BoxList.selection != 0 then
(
YAdd = Val as float
if YAdd != undefined then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].marker.pos.y += YAdd
UpdateBBox BoxList.selection
RemoteConnectionUpdate()
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ZRelVal entered Val do
(
if BoxList.selection != 0 then
(
ZAdd = Val as float
if ZAdd != undefined then
(
ResetBox.enabled = true
CullBoxes[BoxList.selection].marker.pos.z += ZAdd
UpdateBBox BoxList.selection
RemoteConnectionUpdate()
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ResetBox pressed do
(
ResetBox.enabled = false
CullBoxes[BoxList.selection].bounds.xmin = CullBoxes[BoxList.selection].oldbounds.xmin
CullBoxes[BoxList.selection].bounds.xmax = CullBoxes[BoxList.selection].oldbounds.xmax
CullBoxes[BoxList.selection].bounds.ymin = CullBoxes[BoxList.selection].oldbounds.ymin
CullBoxes[BoxList.selection].bounds.ymax = CullBoxes[BoxList.selection].oldbounds.ymax
CullBoxes[BoxList.selection].bounds.zmin = CullBoxes[BoxList.selection].oldbounds.zmin
CullBoxes[BoxList.selection].bounds.zmax = CullBoxes[BoxList.selection].oldbounds.zmax
case CullBoxes[BoxList.selection].marker.wirecolor of
(
ChangedOffColour: CullBoxes[BoxList.selection].marker.wirecolor = OffColour
ChangedColour: CullBoxes[BoxList.selection].marker.wirecolor = RandomColour CullBoxes[BoxList.selection].name InitialSeed
)
XminVal.value = CullBoxes[BoxList.selection].bounds.xmin
XmaxVal.value = CullBoxes[BoxList.selection].bounds.xmax
YminVal.value = CullBoxes[BoxList.selection].bounds.ymin
YmaxVal.value = CullBoxes[BoxList.selection].bounds.ymax
ZminVal.value = CullBoxes[BoxList.selection].bounds.zmin
ZmaxVal.value = CullBoxes[BoxList.selection].bounds.zmax
UpdateBoxParams()
)
--------------------------------------------------------------------------------------------------------------------------------
on UpdateAllBoxes pressed do
(
previousSelection = BoxList.selection
BoxList.selection = 0
for index = 1 to BoxList.items.count do
(
ResetBox.enabled = true
UpdateBBox index
Progress.value = index * 100.0 / BoxList.items.count
)
if previousSelection != 0 then
(
BoxList.selection = previousSelection
SetStateWidgets BoxList.selection
)
Progress.value = 0
)
--------------------------------------------------------------------------------------------------------------------------------
on ActiveBoxColour clicked Arg do
(
if BoxList.selection != 0 then
(
boxesByColour = #()
for index = 1 to BoxList.items.count do
(
if CullBoxes[index].marker.wirecolor == ActiveBoxColour.color then
(
nextbox = CullBoxes[index].marker
append boxesByColour nextbox
)
)
select boxesByColour
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ActiveBoxName entered Arg do renameActiveBox Arg
--------------------------------------------------------------------------------------------------------------------------------
on ToggleBox pressed do
(
if ToggleBox.caption == "Switch Off" then
(
CullBoxes[BoxList.selection].state = false
CullList.enabled = false
ToggleBox.caption = "Switch On"
)
else
(
CullBoxes[BoxList.selection].state = true
CullList.enabled = true
ToggleBox.caption = "Switch Off"
)
case CullBoxes[BoxList.selection].marker.wirecolor of
(
OffColour: CullBoxes[BoxList.selection].marker.wirecolor = RandomColour CullBoxes[BoxList.selection].name InitialSeed
ChangedOffColour: CullBoxes[BoxList.selection].marker.wirecolor = ChangedColour
ChangedColour: CullBoxes[BoxList.selection].marker.wirecolor = ChangedOffColour
NewBoxColour: CullBoxes[BoxList.selection].marker.wirecolor = NewBoxColour
default: CullBoxes[BoxList.selection].marker.wirecolor = OffColour
)
SetStateWidgets BoxList.selection
if RAGConnected and (RemoteConnection.IsConnected()) then
(
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Toggle box enabled" true
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ShowHideBox pressed do
(
if CullBoxes[BoxList.selection].marker.ishidden then
(
CullBoxes[BoxList.selection].marker.ishidden = false
ShowHideBox.caption = "Hide"
)
else
(
CullBoxes[BoxList.selection].marker.ishidden = true
ShowHideBox.caption = "Show"
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ShowAll pressed do
(
for index = 1 to CullBoxes.count do
(
CullBoxes[index].marker.ishidden = false
)
)
--------------------------------------------------------------------------------------------------------------------------------
fn MakeNewCullBox =
(
newmarker = box length:4 width:4 height:4
if BoxList.selection != 0 then
(
newname = CullBoxes[BoxList.selection].marker.name
xmin = CullBoxes[BoxList.selection].bounds.xmin ; xmax = CullBoxes[BoxList.selection].bounds.xmax
ymin = CullBoxes[BoxList.selection].bounds.ymin ; ymax = CullBoxes[BoxList.selection].bounds.ymax
zmin = CullBoxes[BoxList.selection].bounds.zmin ; zmax = CullBoxes[BoxList.selection].bounds.zmax
newBB = BBox xmin:xmin xmax:xmax ymin:ymin ymax:ymax zmin:zmin zmax:zmax
newOldBB = BBox xmin:xmin xmax:xmax ymin:ymin ymax:ymax zmin:zmin zmax:zmax
newmarker.pos = CullBoxes[BoxList.selection].marker.pos
newmarker.width = CullBoxes[BoxList.selection].marker.width
newmarker.length = CullBoxes[BoxList.selection].marker.length
newmarker.height = CullBoxes[BoxList.selection].marker.height
cnamelist = CullBoxes[BoxList.selection].culledNames -- #()
)
else
(
newname = "CullBox_New001"
xmax = 100.0 ; ymax = 100.0 ; zmax = 50.0
xmin = -100.0 ; ymin = -100.0 ; zmin = 0.0
newBB = BBox xmin:xmin xmax:xmax ymin:ymin ymax:ymax zmin:zmin zmax:zmax
newOldBB = BBox xmin:xmin xmax:xmax ymin:ymin ymax:ymax zmin:zmin zmax:zmax
newmarker.pos = [0.0, 0.0, 0.0]
newmarker.width = 200.0 ; newmarker.length = 200.0 ; newmarker.height = 50.0
cnamelist = #()
)
checkBoxNames = #()
-- strip existing "_NewXXX" postfix
if (newname.count > 6) then
(
if (substring newname (newname.count - 6) 4) == "_New" then newname = substring newname 1 (newname.count - 7)
)
newname = GenerateNewName newname
newmarker.name = newname
--BoxColour = RandomColour newmarker.name InitialSeed
newmarker.wirecolor = NewBoxColour
newbox = IPLCullBox name:newname bounds:newBB oldbounds:newOldBB culledNames:cnamelist state:true marker:newmarker
CullBoxNames = deepCopy BoxList.items
append CullBoxes newbox
append CullBoxNames newname
BoxList.items = CullBoxNames
BoxList.selection = CullBoxNames.count -- should be the new box
--format "New box : %\n" newbox
select newmarker
)
--------------------------------------------------------------------------------------------------------------------------------
on CreateBox pressed do
(
MakeNewCullBox()
RemoteConnectionUpdate()
)
--------------------------------------------------------------------------------------------------------------------------------
on RAGConnect pressed do
(
if RAGConnected then
(
RAGConnected = false
RAGConnect.caption = "Connect"
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Draw boxes" false
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Show boxes at camera pos" false
CamXSlider.enabled = false
CamYSlider.enabled = false
CamZSlider.enabled = false
CamOffset.enabled = false
--UpdateChanges.enabled = false
SelectAtCamera.enabled = false
ShowCurrentlyCulled.enabled = false
CullAtCameraPos.enabled = false
)
else
(
messageText = "This will overwrite \n"+ActiveProjectPath.text+"mapdatacullboxes.meta"+ "\n\nDo you still want to procede?"
if (queryBox messageText title:"Connect To Game") then
(
--PreviousSelection = BoxList.selection
BoxList.selection = 0 -- Selected boxes causes problems if meta file out of synch
RemoteConnection.Connect()
if ( RemoteConnection.IsConnected() ) then
(
SaveIPLFileName = "mapdatacullboxes.meta"
RAGConnected = true
RAGConnect.caption = "CONNECTED"
SelectAtCamera.enabled = true
ShowCurrentlyCulled.enabled = true
CullAtCameraPos.enabled = true
RemoteConnection.WriteBoolWidget "Scene/Create Scene widgets" true
RemoteConnection.WriteBoolWidget "Camera/Create camera widgets" true
--RemoteConnection.WriteStringWidget "Camera/Debug director/Active mode" "Free" -- This plain doesn't work... though it looks like it's connected to the debug cam switch
SaveCullBoxes()
--BoxList.selection = PreviousSelection
RemoteConnection.SendSyncCommand()
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Draw boxes" true
--RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Show currently culled" true -- annoying, have added toggle button
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Show boxes at camera pos" CullAtCameraPos.state
--RemoteConnection.SendSyncCommand()
/*if BoxList.selection != 0 then
(
CamXSlider.enabled = true
CamYSlider.enabled = true
CamZSlider.enabled = true
CamOffset.enabled = true
UpdateChanges.enabled = true
)*/
)
else
(
messageBox "Couldn't connect to game.\nMake sure it's running..." beep:true
)
)
)
)
--------------------------------------------------------------------------------------------------------------------------------
on CullAtCameraPos changed Arg do
(
if RAGConnected and (RemoteConnection.IsConnected()) then
(
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Show boxes at camera pos" Arg
)
)
--------------------------------------------------------------------------------------------------------------------------------
on ShowCurrentlyCulled changed Arg do
(
if RAGConnected and (RemoteConnection.IsConnected()) then
(
RemoteConnection.WriteBoolWidget "Scene/IPL Cull Boxes/Show currently culled" Arg
)
)
--------------------------------------------------------------------------------------------------------------------------------
fn CameraWarp =
(
warpX = CullBoxes[BoxList.selection].bounds.xmin + (((CullBoxes[BoxList.selection].bounds.xmax - CullBoxes[BoxList.selection].bounds.xmin) + (CamOffset.value * 2)) * CamXSlider.value)
warpY = CullBoxes[BoxList.selection].bounds.ymin + (((CullBoxes[BoxList.selection].bounds.ymax - CullBoxes[BoxList.selection].bounds.ymin) + (CamOffset.value * 2)) * CamYSlider.value)
warpZ = CullBoxes[BoxList.selection].bounds.zmin + (((CullBoxes[BoxList.selection].bounds.zmax - CullBoxes[BoxList.selection].bounds.zmin) + (CamOffset.value * 2)) * CamZSlider.value)
if RAGConnected and (RemoteConnection.IsConnected()) then
(
::RsRagFuncs.setGameDebugCamPos [warpX, warpY, warpZ]
)
)
--------------------------------------------------------------------------------------------------------------------------------
on CamXSlider changed Arg do
(
if CamYSlider.value < 0.5 then CamYSlider.value = 0.0 else CamYSlider.value = 1.0
if CamZSlider.value < 0.5 then CamZSlider.value = 0.0 else CamZSlider.value = 1.0
CameraWarp()
)
--------------------------------------------------------------------------------------------------------------------------------
on CamYSlider changed Arg do
(
if CamXSlider.value < 0.5 then CamXSlider.value = 0.0 else CamXSlider.value = 1.0
if CamZSlider.value < 0.5 then CamZSlider.value = 0.0 else CamZSlider.value = 1.0
CameraWarp()
)
--------------------------------------------------------------------------------------------------------------------------------
on CamZSlider changed Arg do
(
if CamXSlider.value < 0.5 then CamXSlider.value = 0.0 else CamXSlider.value = 1.0
if CamYSlider.value < 0.5 then CamYSlider.value = 0.0 else CamYSlider.value = 1.0
CameraWarp()
)
--------------------------------------------------------------------------------------------------------------------------------
on CamOffset changed Arg do CameraWarp()
--------------------------------------------------------------------------------------------------------------------------------
on DeleteBox pressed do
(
-- Maybe do this by wirecolour... black for deleted.. so it can be undeleted again...
-- One for another day...
KillBox = BoxList.selection
if KillBox != 0 then
(
newBoxList = deepcopy BoxList.items
deleteItem newBoxList KillBox
delete CullBoxes[KillBox].marker
deleteItem CullBoxes KillBox
BoxList.items = newBoxList
select CullBoxes[KillBox - 1].marker
remoteConnectionUpdate()
)
else
(
messageBox "Pick a box in the Cull Boxes list to the right."
)
)
--------------------------------------------------------------------------------------------------------------------------------
--- Diagnostic/Maintenance events ---
on Diagnosis pressed do
(
if BoxList.selection != 0 then
(
format "Name : %, Active : %,\nBounds : %,\nOldBounds : %,\nCulled : %\n\n" CullBoxes[BoxList.selection].name CullBoxes[BoxList.selection].state CullBoxes[BoxList.selection].bounds CullBoxes[BoxList.selection].oldbounds CullBoxes[BoxList.selection].culledNames
--format "Container List : %\n" ContainerList.selection
)
)
--------------------------------------------------------------------------------------------------------------------------------
on HashDump pressed do
(
saveHash_name = ActiveProjectPath.text + "HashDump.txt"
messageText = "USE WITH CAUTION\n\nThis dumps all unknown container hashes to \n"+saveHash_name+"\n\nand adds a cullbox for every unknown area (potentailly 100s of spurious boxes) so I can maintain the project hash tables.\n\nAre you sure you want to procede?"
if (queryBox messageText title:"Dump Hash Table" beep:true) then
(
messageText = "Add a cullbox for each unknown container hash?\nPotentially adds 100s of spurious boxes for maintaining the project hash tables."
if RAGConnected then messageText += "Will overwrite the meta file!!!\n"
boxDump = queryBox messageText title:"Add Unknown Hash Cull Boxes"
output_file = createfile saveHash_name
KnownBoxNames = deepCopy ContainerList.items
UnknownHashes = #()
newName = ""
projectName = case ActiveProject.selection of
(
1: "V"
2: "Liberty"
default: "Unknown"
)
NumBoxes = CullBoxes.count
for index = 1 to NumBoxes do
(
if CullBoxes[index].culledNames.count > 0 then
(
for cindex = 1 to CullBoxes[index].culledNames.count do
(
newName = CullBoxes[index].culledNames[cindex]
debugName = substituteString CullBoxes[index].name "New Box_" ""
found = findItem KnownBoxNames newName
if found == 0 then
(
append KnownBoxNames newName
nextline = "\t\tappend "+projectName+"Names \""+ debugName+"\" ; append "+projectName+"Hashes \""+newName+"\"\n"
format nextline to:output_file
if boxDump then
(
newmarker = box length:4 width:4 height:4 name:newName
xmax = 100.0 ; ymax = 100.0 ; zmax = 50.0
xmin = -100.0 ; ymin = -100.0 ; zmin = 0.0
newBB = BBox xmin:xmin xmax:xmax ymin:ymin ymax:ymax zmin:zmin zmax:zmax
newOldBB = BBox xmin:xmin xmax:xmax ymin:ymin ymax:ymax zmin:zmin zmax:zmax
newmarker.pos = [0.0, 0.0, 0.0]
newmarker.width = 200.0 ; newmarker.length = 200.0 ; newmarker.height = 50.0
BoxColour = RandomColour newmarker.name InitialSeed
newmarker.wirecolor = BoxColour
newbox = IPLCullBox name:newName bounds:newBB oldbounds:newOldBB culledNames:#(newName) state:true marker:newmarker
append CullBoxes newbox
)
if boxDump then
(
append UnknownHashes newName
)
)
)
)
Progress.value = index * 100.0 / CullBoxes.count
)
if boxDump and (numBoxes < CullBoxes.count) then
(
newBoxList = deepcopy BoxList.items
for index = (BoxList.items.count + 1) to CullBoxes.count do
(
append newBoxList CullBoxes[index].name
)
BoxList.items = newBoxList
ContainerList.items = KnownBoxNames
RemoteConnectionUpdate()
)
Progress.value = 0
close output_file
)
)
--------------------------------------------------------------------------------------------------------------------------------
on RsEditCullBoxFiles open do
(
banner.setup()
-- CALL BACKS -----------------------------------------------------------------------------------------------
callbacks.addScript #selectionSetChanged "RsEditCullBoxFiles.SelectCallBack()" id:#EditIPLCullBoxes
callbacks.addScript #nodeRenamed "RsEditCullBoxFiles.BoxRenameCallBack()" id:#EditIPLCullBoxes
-- LOAD IN DATA ---------------------------------------------------------------------------------------------
LibertyNames = getINISetting iniFile "Liberty"
ContainerList.items = LibertyNames
for n in LibertyNames do append LibertyHashes (getINISetting iniFile "Liberty" n)
VNames = getINISetting iniFile "GTAV"
for n in VNames do append VHashes (getINISetting iniFile "GTAV" n)
projectNames =#(VNames, LibertyNames)
projectHashes =#(VHashes, LibertyHashes)
)
--------------------------------------------------------------------------------------------------------------------------------
on RsEditCullBoxFiles close do
(
callbacks.removeScripts id:#EditIPLCullBoxes
)
)
CreateDialog RsEditCullBoxFiles width:476 style:#(#style_titlebar, #style_border, #style_sysmenu,#style_toolwindow)