Files
gtav-src/tools_ng/wildwest/script/3dsMax/Evaluation/LodEditor_EVAL.ms
T
2025-09-29 00:52:08 +02:00

2277 lines
77 KiB
Plaintext
Executable File

--rsl_lodeditor.ms
--Andy Davis
--version 1.1
--introduction of tabbed section to distinguish between scene lods and drawable lods
--version 1.2
--ammendment of the original code to account for the variation of scene LOD occurences in interior scenes
--version 1.3
--ammendment to include MILO LOD occurences for interior scenes
--edit 09/02/2011
--reduced object list by discounting XRef objects
--window resizable
--size and position of window saved in ini file
--edit 18/02/2011: visible only filter added, reformatted buttons
--edit 19/07/2011: url:bugstar:158316 user defined properties for LOD values set up to work
----------------------------------------------------------------------------------------------------------------
--HEADER INFO
----------------------------------------------------------------------------------------------------------------
/*
DEVELOPMENT STATUS:
bug.... UpdateTreeList doesn't work if you open a new scene file
FUTURE IMPLEMENTATIONS:
drag and drop for LOD parenting
highlighting for the current tab
change cursor to crosshair when in pick parent mode - setSysCur #select
implement the new ValidateSelection() function into other functions to simplify the code
possible introduction of an UpdateFormHeight() function??
highlight objects that are both scene and drawable lods
MILO integration for interior maps
NOTES:
The main difference between Scene LODs and Drawable LODs with reference to this script is that a Scene LOD can have multiple children
A drawable LOD can only have one child.
This is reflected in the branching loops
The branches are distinguished using the variable, currentMode, which is set to either "scene" or "drawable" by the tabPanel eventHandler, TabClicked
The two LOD systems use similar functions to manage LODs:
Scene LODs Drawable LODs
RsSceneLink.GetParent LinkType_LOD RsLodDrawable_GetLowerDetailModel
RsSceneLink.SetParent LinkType_LOD RsLodDrawable_SetLowerDetailModel
getLODChildren RsLodDrawable_GetHigherDetailModel
RsSceneLink.RemoveContainer LinkType_LOD RsSceneLink.RemoveContainer linkType_DRAWLOD
The LOD parenting script error checks the prospective new Scene LOD hierarchy for 3 cases that would result in a bad hierarchy.
There is an extra case for Drawable LODs.
These cases are as follows:
--VALIDATION ALGORITHMS
--Case Solution
--CASE 1: parentObject is in selectedObjects warning message and abort
--CASE 2: parentObject is a child of selectedObjects orphan the parent
--CASE 3: parentObject has a grandparent orphan the parent's parent
--CASE 4: selectedObjects have grandchildren orphan the grandchildren
--CASE 5: parentObject has a parent AND selectedObjects have children orphan the parent
--CASE 6: parentObject has other children resulting in an illegal sibling orphan the illegal sibling (drawable LOD only)
*/
----------------------------------------------------------------------------------------------------------------
--FILE INs
----------------------------------------------------------------------------------------------------------------
filein "pipeline/util/file.ms"
filein "rockstar/export/settings.ms"
filein "pipeline/util/drawablelod.ms"
filein "pipeline/ui/treelodeditor.ms"
filein (RsConfigGetWildWestDir()+"script/3dsMax/_common_functions/RSL_dotNetUIOps.ms")
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms")
RsCollectToolUsageData (getThisScriptFilename())
----------------------------------------------------------------------------------------------------------------
--GLOBAL INSTANCE
----------------------------------------------------------------------------------------------------------------
global LODEditor
--global LinkType_LOD = 0
----------------------------------------------------------------------------------------------------------------
--MAIN STRUCTURE
----------------------------------------------------------------------------------------------------------------
struct LodListStruct
(
----------------------------------------------------------------------------------------------------------------
--VARIABLES
----------------------------------------------------------------------------------------------------------------
--scene variables
objectList, --all gta objects in the scene
selectedObjects, --selected objects from the scene
nodeList, --the tree list nodes in the order they appear in the tree list
selectedNodes, --selected nodes within the tree list
daddyList, --tree list nodes at the root of the list
parentObject, --buffer for selecting LOD parent
pickLodParentMode = false, --flag set to true when picking a LOD parent
showNonLODObjects = true, --set to false to show only LOD objects in the tree list
VisibleOnly = false,
IniFilePath = (RsConfigGetWildWestDir() + "script/max/rockstar_london/config/RSL_LodEditor.ini"),
--UI variables
lodListForm,
borderHeight = 98, --don't modify... this is the fixed height of form border elements
formHeight,
formWidth = 470,
lodListTable,
tabPanel,
tab1, tab2, tab3,
treeListPanel,
treeListRowHeight = 19,
buttonPanel,
buttonHeight = 20,
numButtonColumns = 4,
numRows = 3,
buttonPanelHeight = 120,
buttonWidth = (formWidth - 38)/numButtonColumns,
listPanel,
parentingPanel,
attributePanel,
splayPanel,
infoPanel,
infoPanelHeight = 35,
actionPanel, --table container used for lod and txd panels
lodDistanceLabel, --label to provide info regarding applying lod distances
lodDistanceInput, --control used to set new lod values
txdLabel,
txdInput,
MILOHelpForm,
ToolTip,
showNonLODsCheckBox,
showVisibleOnlyCheckBox,
textCol = (colorMan.getColor #window) * 255,
textColour = (dotNetClass "System.Drawing.Color").FromArgb 63 63 63,
--choose the starting LOD mode as being "scene" or "drawable":
-- currentMode = "scene",
currentMode = "scene",
----------------------------------------------------------------------------------------------------------------
--PRESETS
----------------------------------------------------------------------------------------------------------------
DS_Fill = (dotNetClass "System.Windows.Forms.DockStyle").Fill,
Font_Small = dotNetObject "System.Drawing.Font" "Microsoft sans serif" 7,
Font_Calibri = dotNetObject "System.Drawing.Font" "Calibri" 8,
CA_Center = (dotNetClass "System.Drawing.ContentAlignment").MiddleCenter,
RGB_NeonGreen = (dotNetClass "System.Drawing.Color").FromARGB 204 255 0,
RGB_MidGrey = (dotNetClass "System.Drawing.Color").fromARGB 153 153 153,
RGB_MediumBlue = (dotNetClass "System.Drawing.Color").MediumBlue,
RGB_CornflowerBlue = (DotNetClass "System.Drawing.Color").CornflowerBlue,
RGB_LightGrey = (dotNetClass "System.Drawing.Color").fromARGB 204 204 204,
RGB_OffWhite = (dotNetClass "System.Drawing.Color").fromARGB 232 232 232,
RGB_Gainsboro = (dotNetClass "System.Drawing.Color").Gainsboro,
RGB_GhostWhite = (dotNetClass "System.Drawing.Color").GhostWhite,
RGB_WhiteSmoke = (dotNetClass "System.Drawing.Color").WhiteSmoke,
RGB_White = (dotNetClass "System.Drawing.Color").White,
RGB_PaleOrange = (dotNetClass "System.Drawing.Color").fromARGB 255 245 225,
RGB_PaleBlue = (dotNetClass "System.Drawing.Color").fromARGB 235 245 255,
RGB_YellowOrange = (dotNetClass "System.Drawing.Color").fromARGB 255 204 0,
RGB_Pink = (dotNetClass "System.Drawing.Color").fromARGB 255 216 216,
RGB_BabyBlue = (dotNetClass "System.Drawing.Color").fromARGB 204 224 255,
RGB_Green = (dotNetClass "System.Drawing.Color").fromARGB 64 255 64,
RGB_Red = (dotNetClass "System.Drawing.Color").fromARGB 255 32 32,
RGB_Transparent = (dotNetClass "System.Drawing.Color").transparent,
Padding_None = dotNetObject "System.Windows.Forms.Padding" 0,
TA_Center = (dotNetClass "System.Drawing.ContentAlignment").MiddleCenter,
TA_Left = (dotNetClass "System.Drawing.ContentAlignment").MiddleLeft,
------------------------------------------------------------------------------------------------------------------------------------------
--LOAD/SAVE FUNCTIONS
------------------------------------------------------------------------------------------------------------------------------------------
fn SaveIniFile =
(
setINISetting LODEditor.IniFilePath "LODEditor" "WinLocX" (LODEditor.lodListForm.Location.x as string)
setINISetting LODEditor.IniFilePath "LODEditor" "WinLocY" (LODEditor.lodListForm.Location.y as string)
setINISetting LODEditor.IniFilePath "LODEditor" "WinWidth" (LODEditor.lodListForm.Width as string)
setINISetting LODEditor.IniFilePath "LODEditor" "WinHeight" (LODEditor.lodListForm.Height as string)
setINISetting LODEditor.IniFilePath "LODEditor" "ShowNonLOD" (LODEditor.showNonLODsCheckBox.Checked as string)
setINISetting LODEditor.IniFilePath "LODEditor" "VisibleOnly" (LODEditor.showVisibleOnlyCheckBox.Checked as string)
),
fn LoadIniFile =
(
--default values
local WinLocX = 0
local WinLocY = 40
local WinWidth = 470
local WinHeight = 800
local ShowNonLOD = true
local VisibleOnly = true
try
(
WinLocX = getINISetting LODEditor.IniFilePath "LODEditor" "WinLocX" as integer
WinLocY = getINISetting LODEditor.IniFilePath "LODEditor" "WinLocY" as integer
WinWidth = getINISetting LODEditor.IniFilePath "LODEditor" "WinWidth" as integer
WinHeight = getINISetting LODEditor.IniFilePath "LODEditor" "WinHeight" as integer
ShowNonLOD = getINISetting LODEditor.IniFilePath "LODEditor" "ShowNonLOD" as booleanClass
VisibleOnly = getINISetting LODEditor.IniFilePath "LODEditor" "VisibleOnly" as booleanClass
)
catch()
lodListForm.Location = dotNetObject "system.drawing.point" WinLocX WinLocY
lodListForm.Size = dotNetObject "System.Drawing.Size" WinWidth WinHeight
LODEditor.showNonLODsCheckBox.Checked = ShowNonLOD
LODEditor.showVisibleOnlyCheckBox.Checked = VisibleOnly
),
----------------------------------------------------------------------------------------------------------------
--UI FUNCTIONS
----------------------------------------------------------------------------------------------------------------
fn UpdateObjectList =
--function updates the objectList array based on valid Gta objects in the scene
(
if LODEditor.VisibleOnly == true then
(
objectList = for this in objects where (getAttrClass this == "Gta Object") and (classOf this != XrefObject) and (this.isHidden == false) collect this
MILOObjects = for this in objects where (getAttrClass this == "Gta MILO") and (classOfThis != XrefObject) and (this.isHidden == false) collect this
)
else
(
objectList = for this in objects where (getAttrClass this == "Gta Object") and (classOf this != XrefObject) collect this
MILOObjects = for this in objects where (getAttrClass this == "Gta MILO") and (classOfThis != XrefObject) collect this
)
join objectList MILOObjects
),
----------------------------------------------------------------------------------------------------------------
fn UpdateSelectedObjects =
--function updates the selectedObjects array from objects selected in the scene as opposed to objects selected in the nodeList
(
selectedObjects = for this in selection where (getAttrClass this == "Gta Object") and (classOf this != XrefObject) collect this
MILOObjects = for this in selection where (getAttrClass this == "Gta MILO") and (classOf this != XrefObject) collect this
join selectedObjects MILOObjects
),
----------------------------------------------------------------------------------------------------------------
fn UpdateSelectedObjectsFromSelectedNodes =
--function updates the selectedObjects array from nodes selected in the treelist
(
selectedObjects = for this in nodeList where (this.Selected == true) and (IsValidNode this.Tag.Value == true) collect this.Tag.Value
if (selectedObjects.Count > 0) then
(
select selectedObjects
)
),
----------------------------------------------------------------------------------------------------------------
fn UpdateSelectedNodes =
--function updates the selectedNodes array from objects selected in the treelist
(
selectedNodes = for this in nodeList where (this.Selected == true) and (IsValidNode this.Tag.Value == true) collect this
),
----------------------------------------------------------------------------------------------------------------
fn DeselectMILOObjects =
-- function removes MILO objects from selectedNodes and objects
(
--remove from nodes
for this in nodeList where (this.Selected == true) do
(
if (getAttrClass this.Tag.Value == "Gta MILO") then
(
messagebox ("Removing MILO object " + (this.Tag.Value.name) as string + " from selection")
this.Selected = false
)
)
--remove from scene selection
buffer = for this in selection where (getattrclass this != "Gta MILO") collect this
clearSelection() -- for some weird reason, MILO objects do not deselect unless I clearSelection first
selection = buffer
),
fn CheckForMILONodes =
-- function checks selection for MILO nodes
(
nodeFound = false
UpdateSelectedNodes()
--check nodes
if (selectedNodes.Count > 0) then
(
for this in selectedNodes do
(
if (getAttrClass this.Tag.Value == "Gta MILO") then
(
nodeFound = true
)
)
)
else -- no nodes selected, so check objects
(
for this in selection do
(
if (getAttrClass this == "Gta MILO") then
(
nodeFound = true
)
)
)
return nodeFound
),
----------------------------------------------------------------------------------------------------------------
fn UpdateSelectedNodesFromSelection =
--selects nodes in the treelist based on the selection
(
selectedNodes = #()
for this in nodeList do
(
for thisObject in selection do
(
if (this.Tag.Value == thisObject) then
(
this.Selected = true
append selectedNodes this
)
)
)
),
fn UpdateListNodesFromSelection =
--selects nodes in the treelist based on the selection
(
selectedNodes = treeListPanel.selection
treeNodes = for i = 0 to (treeListPanel.nodes.count - 1) collect treeListPanel.nodes.Item[i]
do
(
tempArr = #()
for node in treeNodes do
(
node.selected = false
if node.HasChildren then
(
kids = for n = 0 to (node.nodes.count - 1) collect node.nodes.item[n]
join tempArr kids
)
)
if tempArr.count > 0 then treeNodes = tempArr else treeNodes = #()
)
while treeNodes.count > 0
treeListPanel.Update()
if selection.count > 0 then
(
visibleNodes = #()
for thisObject in selection do
(
for n = 0 to (treeListPanel.nodes.count - 1) do
(
thisNode = treeListPanel.nodes.Item[n]
if (thisNode.Tag.Value == thisObject) then
(
thisNode.Selected = true
append visibleNodes thisNode
)
)
)
--focus on first selected item
if visibleNodes.count > 0 then
(
treeListPanel.MakeNodeVisible visibleNodes[1]
)
)
),
----------------------------------------------------------------------------------------------------------------
--nb: there is no UpdateNodeList function as this operation is carried out in the function, UpdateTreeList()
----------------------------------------------------------------------------------------------------------------
fn ValidateSelection =
--function checks whether the user has any list nodes selected, and if not, checks for selected scene objects
(
UpdateSelectedNodes()
if (selectedNodes.Count == 0) then
(
--no nodes selected so check for objects instead
UpdateSelectedObjects()
if (selectedObjects.Count == 0) then
(
--no selected objects either
return false
)
else
(
--no selected nodes, but selected objects
UpdateSelectedNodesFromSelection()
return true
)
)
else
(
--we have selected nodes
UpdateSelectedObjectsFromSelectedNodes()
return true
)
),
----------------------------------------------------------------------------------------------------------------
fn GetBiggestDimension thisObject =
--function returns the largest dimension of the object passed to it
-- as used in the splay functions
(
if (thisObject != undefined) then
(
local xdim = thisObject.max.x - thisObject.min.x
local ydim = thisObject.max.y - thisObject.min.y
local zdim = thisObject.max.z - thisObject.min.z
if (xdim > ydim) then
(
if (xdim > zdim) then
(
biggestDimension = xdim
)
else
(
biggestDimension = zdim
)
)
else
(
if (ydim > zdim) then
(
biggestDimension = ydim
)
else
(
biggestDimension = zdim
)
)
return biggestDimension
)
else
(
return undefined
)
),
----------------------------------------------------------------------------------------------------------------
fn UpdateInfoPanel =
--function sets up the info panel at the bottom with the latest information
(
if lodListTable.Controls.Item[2].Name != "infoPanel" then
(
lodListTable.Controls.Remove lodListTable.Controls.Item[2]
LODEditor.InitInfoPanel()
)
if (currentMode == "scene") then
(
modeText = "Scene LOD Mode"
)
else --currentMode == "drawable"
(
modeText = "Drawable LOD Mode"
)
if (showNonLODObjects == false) then
(
modeText = modeText + " (non-LODs hidden)"
)
if (objectList.count > 1) then
(
objectPlural = "s"
)
else objectPlural = ""
if (selectedObjects.Count > 1) then
(
selPlural = "s"
)
else selPlural = ""
infoPanel.Text = modeText + "\n" + (nodeList.Count as string) + " object" + objectPlural + " in list, "
infoPanel.Text = infoPanel.Text + (selectedObjects.Count as string) + " object" + selPlural + " selected"
),
----------------------------------------------------------------------------------------------------------------
fn UpdateTreeList =
--function picks up all the objects in the scene, reads the LOD hierarchy and then places puts the data into the treelist
--this function is the main function for managing the data in the xtratreelist
--selected objects highlighted are those whose scene objects are selected
--objectList updated
--nodeList updated
--selectedObjects updated from their state in the scene
--selected nodes updated as from the selectedObjects
(
UpdateObjectList()
LODObjectList = #()
--init the daddyList according to the currentMode
case currentMode of
(
"scene":
(
daddyList = for this in objectList where (RsSceneLink.GetParent LinkType_LOD this == undefined) collect this
--if we are on drawable tab, need different search pattern
if (showNonLODObjects == false) then
(
LODOnly = for this in daddyList where (getLODChildren this).Count > 0 collect this
daddyList = LODOnly
)
)
"drawable":
(
daddyList = for this in objectList where (RsLodDrawable_GetLowerDetailModel this == undefined) collect this
if (showNonLODObjects == false) then
(
LODOnly = for this in daddyList where (RsLodDrawable_GetHigherDetailModel this != undefined) collect this
daddyList = LODOnly
)
)
"tree":
(
daddyList = for this in objectList where (RsSceneLink.GetParent LinkType_CombinerMesh this == undefined) collect this
if (showNonLODObjects == false) then
(
LODOnly = for this in daddyList where (RsSceneLink.GetParent LinkType_CombinerMesh this != undefined) collect this
daddyList = LODOnly
)
)
)
nodeList = #() --clear node array for updated nodes
treeListPanel.ClearNodes() --clear the nodes from the tree list, should they exist
--add the root objects
treeListPanel.BeginUnboundLoad()
for this in daddyList do
(
if (getattrclass this == "Gta MILO") then --no LOD distance or txd values for MILO object
(
distanceValue = txdValue = "MILO"
)
else
(
distanceValue = getattr this (getattrindex "Gta Object" "LOD distance")
txdValue = getattr this (getattrindex "Gta Object" "TXD")
)
gdaddyNode = treeListPanel.AppendNode #(this.name, distanceValue, txdValue) -1 -- value of -1 sets root object
gdaddyNode.tag = dotNetMXSValue this
append nodeList gdaddyNode
--init childList according to currentMode
case currentMode of
(
"scene":
(
childList = getLODChildren this
if (childList.count > 0) then
(
for thisChild in childList do
(
if (getattrclass thisChild == "Gta MILO") then
(
distanceValue = txdValue = "MILO"
)
else
(
distanceValue = getattr thisChild (getattrindex "Gta Object" "LOD distance")
txdValue = getattr thisChild (getattrindex "Gta Object" "TXD")
)
daddyNode = treeListPanel.AppendNode #(thisChild.name, distanceValue, txdvalue) gdaddyNode
daddyNode.tag = dotNetMXSValue thisChild
append nodeList daddyNode
gchildList = getLODChildren thisChild
if gchildList.count > 0 then
(
for thisgchild in gchildlist do
(
if (getattrclass thisgchild == "Gta MILO") then
(
distanceValue = txdValue = "MILO"
)
else
(
distanceValue = getattr thisgchild (getattrindex "Gta Object" "LOD distance")
txdValue = getattr thisgchild (getattrindex "Gta Object" "TXD")
)
childNode = treeListPanel.AppendNode #(thisgchild.name, distanceValue, txdvalue) daddyNode
childNode.tag = dotNetMXSValue thisgchild
append nodeList childNode
)
)
)
)
)
"drawable":
(
child = RsLodDrawable_GetHigherDetailModel this --we only have one child for Drawable LOD
--so we don't loop through like we did for Scene Lod
if (child != undefined) then
(
distanceValue = getattr child (getattrindex "Gta Object" "LOD distance")
txdValue = getattr child (getattrindex "Gta Object" "TXD")
daddyNode = treeListPanel.AppendNode #(child.name, distanceValue, txdvalue) gdaddyNode
daddynode.tag = dotNetMXSValue child
append nodeList daddyNode
gchild = RsLodDrawable_GetHigherDetailModel child
if (gchild != undefined) then
(
distanceValue = getattr gchild (getattrindex "Gta Object" "LOD distance")
txdValue = getattr gchild (getattrindex "Gta Object" "TXD")
childNode = treeListPanel.AppendNode #(gchild.name, distanceValue, txdvalue) daddyNode
childNode.tag = dotNetMXSValue gchild
append nodeList childNode
)
)
)
"tree":
(
child = (RsSceneLink.GetChildren LinkType_CombinerMesh this &kids)[1]
--child = RsLodDrawable_GetHigherDetailModel this --we only have one child for Drawable LOD
--so we don't loop through like we did for Scene Lod
if (child != undefined) then
(
distanceValue = getattr child (getattrindex "Gta Object" "LOD distance")
txdValue = getattr child (getattrindex "Gta Object" "TXD")
daddyNode = treeListPanel.AppendNode #(child.name, distanceValue, txdvalue) gdaddyNode
daddynode.tag = dotNetMXSValue child
append nodeList daddyNode
gchild = RsLodDrawable_GetHigherDetailModel child
if (gchild != undefined) then
(
distanceValue = getattr gchild (getattrindex "Gta Object" "LOD distance")
txdValue = getattr gchild (getattrindex "Gta Object" "TXD")
childNode = treeListPanel.AppendNode #(gchild.name, distanceValue, txdvalue) daddyNode
childNode.tag = dotNetMXSValue gchild
append nodeList childNode
)
)
)
)
)
treeListPanel.EndUnboundLoad()
--when the table inits, one node is incorrectly selected, so need to deselect all the nodes
for this in nodeList do
(
this.Selected = false
this.Expanded = true
)
--select all nodes whose scene objects are selected
UpdateSelectedObjects()
selectedNodes = #()
for this in nodeList do
(
for thisObject in selectedObjects do
(
if this.Tag.Value == thisObject then
(
this.Selected = true
append selectedNodes this
)
)
)
--resize form to match new treelist size
formHeight = borderHeight + (objectList.count * treeListRowHeight) + buttonPanelHeight + infoPanelHeight
lodListForm.height = formHeight-- - 14 --nb: this is a hack, don't know why I have to adjust the figure by 14... but it works...
),
----------------------------------------------------------------------------------------------------------------
--EVENT HANDLERS
----------------------------------------------------------------------------------------------------------------
--TAB CONTROL
----------------------------------------------------------------------------------------------------------------
fn DispatchTabClicked s e =
(
LODEditor.TabClicked s e
),
fn TabClicked s e =
--this function is triggered on a .SelectedIndexChanged event
(
case tabPanel.selectedIndex of
(
0:
(
currentMode = "scene"
lodListForm.text = "RS LOD Editor - Scene LODs"
tab1.Controls.Add treeListPanel
infoPanel.BackColor = RGB_Pink
UpdateSelectedObjectsFromSelectedNodes()
UpdateTreeList()
)
1:
(
currentMode = "drawable"
lodListForm.text = "RS LOD Editor - Drawable LODs"
tab2.Controls.Add treeListPanel
infoPanel.BackColor = RGB_BabyBlue
UpdateSelectedObjectsFromSelectedNodes()
UpdateTreeList()
)
2:
(
currentMode = "tree"
lodListForm.text = "RS LOD Editor - Tree LODs"
tab3.Controls.Add treeListPanel
infoPanel.BackColor = RGB_Green
UpdateSelectedObjectsFromSelectedNodes()
UpdateTreeList()
)
)
UpdateInfoPanel()
),
----------------------------------------------------------------------------------------------------------------
--BUTTON PANEL
----------------------------------------------------------------------------------------------------------------
--LIST COMMANDS
----------------------------------------------------------------------------------------------------------------
--CLEAR LIST
----------------------------------------------------------------------------------------------------------------
fn ClearList s e =
(
ClearSelection()
LODEditor.UpdateTreeList()
LODEditor.UpdateInfoPanel()
),
----------------------------------------------------------------------------------------------------------------
fn SelectAll =
(
select objects
LODEditor.UpdateTreeList()
LODEditor.UpdateInfoPanel()
),
----------------------------------------------------------------------------------------------------------------
--function updates list based on scene objects and scene selection
fn SceneToList =
(
LODEditor.UpdateTreeList()
LODEditor.UpdateInfoPanel()
),
----------------------------------------------------------------------------------------------------------------
--function selects scene objects based on list selection
fn ListToScene =
(
LODEditor.UpdateSelectedObjectsFromSelectedNodes()
LODEditor.UpdateTreeList()
LODEditor.UpdateInfoPanel()
),
--select list item when selectionChanged callbakc is fired
fn selObjListItemFocus =
(
if $selection[1] != undefined then --find the item in the list and focus on it
(
)
),
----------------------------------------------------------------------------------------------------------------
--LIST EXPANSION/CONTRACTION
----------------------------------------------------------------------------------------------------------------
--exapand all
fn Expand =
(
for this in LODEditor.nodeList do
(
this.expanded = true
)
),
----------------------------------------------------------------------------------------------------------------
--contract all
fn Contract=
(
for this in LODEditor.nodeList do
(
this.expanded = false
)
),
----------------------------------------------------------------------------------------------------------------
--SET ATTRIBUTES PANEL
----------------------------------------------------------------------------------------------------------------
--LOD DISTANCE
----------------------------------------------------------------------------------------------------------------
--set lod distance
fn DispatchSetLodDistance s e =
(
LODEditor.DeselectMILOObjects()
LODEditor.UpdateSelectedNodes()
if LODEditor.selectedNodes.count == 0 then
(
--there are no nodes selected, so check to see if objects are selected instead
LODEditor.UpdateSelectedObjects()
if (LODEditor.selectedObjects.count == 0) then
(
--there are no objects selected either, so provide feedback
case (LODEditor.lodListTable.Controls.Item[2].Name) of
(
"txdPanel": LODEditor.lodDistanceLabel.text = "no nodes selected"
"infoPanel": LODEditor.infoPanel.text = "no nodes selected"
default: messagebox "error - unknown control"
)
)
else
(
if (LODEditor.lodListTable.Controls.Item[2].Name != "lodDistancePanel") then
(
LODEditor.lodListTable.Controls.Remove LODEditor.lodListTable.Controls.Item[2]
LODEditor.InitLodDistancePanel()
)
)
LODEditor.UpdateTreeList()
)
else
(
LODEditor.selectedObjects = for this in LODEditor.selectedNodes collect this.Tag.value
select LODEditor.selectedObjects
if (LODEditor.lodListTable.Controls.Item[2].Name != "lodDistancePanel") then
(
LODEditor.lodListTable.Controls.Remove LODEditor.lodListTable.Controls.Item[2]
LODEditor.InitLodDistancePanel()
)
LODEditor.UpdateTreeList()
)
),
----------------------------------------------------------------------------------------------------------------
--apply LOD distance
fn DispatchApplyLD s e =
(
LODEditor.ApplyLD s e
),
--function applies the lod distance stored in the variable newLodDistanceValue to any selected nodes
fn ApplyLD s e =
(
--find selected nodes and select their objects
UpdateSelectedNodes()
UpdateSelectedObjectsFromSelectedNodes()
if selectedNodes.count == 0 then
(
lodDistanceLabel.text = "no nodes selected"
)
else
(
--apply new value
newLodDistance = lodDistanceInput.Value
for this in selectedNodes do
(
setAttr this.Tag.value (getattrindex "Gta Object" "LOD distance") newLodDistance
)
--update treelist
UpdateTreeList()
formHeight = borderHeight + (objectList.count * treeListRowHeight) + buttonPanelHeight + infoPanelHeight
lodListForm.height = formHeight - 14 --hack
for this in selectedNodes do
(
this.Selected = true
)
)
),
----------------------------------------------------------------------------------------------------------------
--TEXTURE DICTIONARY
----------------------------------------------------------------------------------------------------------------
fn DispatchSetTxd s e =
(
LODEditor.SetTxd s e
),
fn SetTxd s e =
(
DeselectMILOObjects()
UpdateSelectedNodes()
if selectedNodes.count == 0 then
(
--there are no nodes selected, so check to see if objects are selected instead
UpdateSelectedObjects()
if (selectedObjects.count == 0) then
(
--there are no objects selected either, so provide feedback
case (lodListTable.Controls.Item[2].Name) of
(
"txdPanel": lodDistanceLabel.text = "no nodes selected"
"infoPanel": infoPanel.text = "no nodes selected"
default: messagebox "error - unknown control"
)
)
else
(
if (lodListTable.Controls.Item[2].Name != "txdPanel") then
(
lodListTable.Controls.Remove lodListTable.Controls.Item[2]
LODEditor.InitTxdPanel()
)
)
UpdateTreeList()
)
else
(
selectedObjects = for this in selectedNodes collect this.Tag.Value
select selectedObjects
if (lodListTable.Controls.Item[2].Name != "txdPanel") then
(
lodListTable.Controls.Remove lodListTable.Controls.Item[2]
LODEditor.InitTxdPanel()
)
UpdateTreeList()
)
),
----------------------------------------------------------------------------------------------------------------
--function applies the txd stored in the variable newTxd to any selected nodes
fn ApplyTxd =
(
--find selected nodes and select their objects
LODEditor.UpdateSelectedNodes()
LODEditor.UpdateSelectedObjectsFromSelectedNodes()
if LODEditor.selectedNodes.count == 0 then
(
txdLabel.text = "no nodes selected"
)
else
(
--apply new value
newTxd = LODEditor.txdInput.Text
for this in LODEditor.selectedNodes do
(
setAttr this.Tag.Value (getattrindex "Gta Object" "TXD") newTxd
)
--update treelist
LODEditor.UpdateTreeList()
LODEditor.UpdateObjectList()
LODEditor.formHeight = LODEditor.borderHeight + (LODEditor.objectList.count * LODEditor.treeListRowHeight) + LODEditor.buttonPanelHeight + LODEditor.infoPanelHeight
LODEditor.lodListForm.height = LODEditor.formHeight - 14 --hack
for this in LODEditor.selectedNodes do
(
this.Selected = true
)
)
),
----------------------------------------------------------------------------------------------------------------
--LOD PARENTING
----------------------------------------------------------------------------------------------------------------
fn DispatchSetLodParent s e =
(
LODEditor.SetLodParent s e
),
fn SetLodParent s e =
--note: this handler only activates if pickLodParentMode is set to true
(
if pickLodParentMode == true then
(
parentObject = treeListPanel.FocusedNode.Tag.Value
infoPanel.text =(parentObject.name as string) + " picked as LOD parent"
----------------------------------------------------------------------------------------------------------------
--VALIDATION ALGORITHMS
-- Case Solution
-- CASE 1: parentObject is in selectedObjects warning message and abort
-- CASE 2: parentObject is a child of selectedObjects orphan the parent
-- CASE 3: parentObject has a grandparent orphan the parent's parent
-- CASE 4: selectedObjects have grandchildren orphan the grandchildren
-- CASE 5: parentObject has a parent AND selectedObjects have children orphan the parent
-- CASE 6: parentObject has other children resulting in an illegal sibling orphan the illegal sibling (drawable LOD only)
-- MILO CASES:
--
-- MILOCASE A: parentObject is a MILO object warn and abort
-- MILOCASE B: selectedObjects cannot be linked to different MILO rooms warn and abort (scene LOD only)
-- MILOCASE C: MILO objects cannot be linked as drawable LOD parents warn and abort (drawable LOD only)
----------------------------------------------------------------------------------------------------------------
--CASE 1: the parentObject is in selectedObjects warning message and abort
validParent = true
for this in selectedObjects do
(
if (this == parentObject) then
(
validParent = false
)
) --end of CASE 1
if (validParent == false) then --abort
(
--infoPanel.text = "CASE 1: parentObject is in selectedObjects\nObject cannot be it's own LOD"
messagebox "The parent is in the selected objects; object cannot be it's own LOD."
)
else --run the remaining validation algorithms and apply parenting
(
-- MILOCASE A: parentObject is a MILO object warn and abort
if (getAttrClass parentObject == "Gta MILO") then
(
--dialog box: cannot LOD parent to this MILO object because connected to room, break connection to room?
messagebox (parentObject.Name as string + " selected as LOD parent: aborting LOD setup")
) --end of MILOCASE A
else
(
----------------------------------------------------------------------------------------------------------------
--BRANCHING FOR LOD MODES STARTS HERE
case currentMode of
(
"scene":
(
infoPanel.BackColor = RGB_Pink
--note that the case code algorithms are different depending on currentMode
--CASE 2: parentObject is a child of selectedObjects orphan the parent
for this in selectedObjects do
(
childrenBuffer = getLODChildren this
if (childrenBuffer.Count > 0) then
(
for thisChild in childrenBuffer do
(
if (thisChild == parentObject) then
(
RsSceneLink.RemoveContainer LinkType_LOD parentObject
infoPanel.Text = "Warning: LOD parent is a child of a selected object, orphaning to maintain valid LOD hierarchy"
)
)
)
) --end of CASE 2
--CASE 3: parentObject has a grandparent orphan the parent's parent
parentObjectParent = RsSceneLink.GetParent LinkType_LOD parentObject
if (parentObjectParent != undefined) then
(
if (RsSceneLink.GetParent LinkType_LOD parentObjectParent != undefined) then
(
RsSceneLink.RemoveContainer LinkType_LOD parentObjectParent
infoPanel.Text = "Warning: LOD parent has parent, orphaning to maintain valid LOD hierarchy"
)
) -- end of CASE 3
--CASE 4: selectedObjects have grandchildren orphan the grandchildren
for this in selectedObjects do
(
childrenBuffer = getLODChildren this
if (childrenBuffer.Count > 0) then
(
for thisChild in childrenBuffer do
(
gchildrenBuffer = getLODChildren thisChild
if (gchildrenBuffer.Count > 0) then
(
for thisGchild in gchildrenBuffer do
(
RsSceneLink.RemoveContainer LinkType_LOD thisGchild
)
infoPanel.Text = "Warning: LOD children of selected objects orphaned to maintain valid LOD hierarchy"
)
)
)
) -- end of CASE 4
--CASE 5: parentObject has a parent AND selectedObjects have children orphan the parent
parentObjectParent = RsSceneLink.GetParent LinkType_LOD parentObject
if (parentObjectParent != undefined) then
(
for this in selectedObjects do
(
childrenBuffer = getLODChildren this
if (childrenBuffer.Count > 0) then
(
RsSceneLink.RemoveContainer LinkType_LOD parentObject
infoPanel.text = "Warning: LOD parent orphaned to maintain valid LOD hierarchy"
)
)
)--end of CASE 5
-- MILOCASE B: selectedObjects cannot be linked to different MILO rooms warn and abort (scene LOD only)
local roomBuffer
local newRoom
local validSetup = true
if (parentObject.Parent != undefined) then
(
if (getAttrClass parentObject.Parent == "Gta MloRoom") then
(
roomBuffer = parentObject.Parent
)
)
for this in selectedObjects do
(
if (this.parent != undefined) then
(
if (getAttrClass this.parent == "Gta MloRoom") then
(
newRoom = this.Parent
if (roomBuffer != undefined and roomBuffer != newRoom) then
(
validSetup = false
)
else roomBuffer = newRoom
)
)
--also: selected object's LOD children can't be in different rooms
)
if (validSetup == false) then
(
messagebox "Warning: selected objects belong to different MILO rooms: aborting"
) --end of MILOCASE B
else --valid candidates for LOD setup
(
for this in selectedObjects do
(
RsSceneLink.RemoveContainer LinkType_LOD this
RsSceneLink.AddContainer LinkType_LOD this
RsSceneLink.SetParent LinkType_LOD this parentObject
)
)
)
"drawable":
(
infoPanel.BackColor = RGB_BabyBlue
-- MILOCASE C: MILO objects cannot be linked as drawable LOD parents warn and abort (drawable LOD only)
if (getAttrClass parentObject == "Gta MILO" or getAttrClass selectedObjects[1] == "Gta MILO") then
(
messagebox "MILO objects cannot be set up as drawable LODs"
)
else --valid non-MILO parent so can procede
(
child = selectedObjects[1]
-- CASE 2: parentObject is a child of selectedObjects orphan the parent
if (parentObject == RsLodDrawable_GetHigherDetailModel child) then
(
RsSceneLink.RemoveContainer linkType_DRAWLOD parentObject
--infoPanel.text = "CASE 2: parentObject is a child of selectedObjects"
)
-- CASE 3: parentObject has a grandparent orphan the parent's parent
parentObjectParent = RsLodDrawable_GetLowerDetailModel parentObject
if (parentObjectParent != undefined) then
(
if (RsLodDrawable_GetLowerDetailModel parentObjectParent != undefined) then
(
RsSceneLink.RemoveContainer linkType_DRAWLOD parentObjectParent
--infoPanel.text = "CASE 3: parentObject has a grandparent"
)
)
--CASE 4: selectedObjects have grandchildren orphan the grandchildren
childChild = RsLodDrawable_GetHigherDetailModel child
if (childChild != undefined) then
(
gChild = RsLodDrawable_GetHigherDetailModel childChild
if (gChild != undefined) then
(
RsSceneLink.RemoveContainer linkType_DRAWLOD gChild
infoPanel.Text = "Warning: selected objects base models orphaned to maintain valid LOD hierarchy"
)
)
--CASE 5: parentObject has a parent AND selectedObjects have children orphan the parent
parentObjectParent = RsLodDrawable_GetLowerDetailModel parentObject
if (parentObjectParent != undefined) then
(
if (RsLodDrawable_GetHigherDetailModel child != undefined) then
(
RsSceneLink.RemoveContainer linkType_DRAWLOD parentObject
infoPanel.text = "Warning: parent orphaned to maintain valid LOD hierarchy"
)
)
--CASE 6: parentObject has other children resulting in an illegal sibling orphan the illegal sibling (drawable LOD only)
parentObjectChild = RsLodDrawable_GetHigherDetailModel parentObject
if (parentObjectChild != undefined and parentObjectChild != child) then
(
RsSceneLink.RemoveContainer linkType_DRAWLOD parentObjectChild
infoPanel.text = "Warning: parent LOD's other base model orphaned to maintain valid LOD hierarchy"
)
--hook up the selected object to the parent
RsLodDrawable_SetLowerDetailModel child parentObject
)
)
"tree":
(
infoPanel.BackColor = RGB_Green
local selobj = selection[1]
local maps = RsMapGetMapContainers()
-- Make sure the two objects are in the same container
selObjCont = RsMapObjectGetMapContainerFor selobj maps:maps
parentObjectCont = RsMapObjectGetMapContainerFor parentObject maps:maps
if ( selObjCont != undefined and selHiDefCont != undefined and selObjCont.name == selHiDefCont.name ) then
(
RsSceneLink.RemoveContainer LinkType_CombinerMesh selobj
RsSceneLink.AddContainer LinkType_CombinerMesh selobj
RsSceneLink.SetParent LinkType_CombinerMesh parentObjectCont selobj
)
else
(
MessageBox ( parentObjectCont.name + " is not in the same map container so can't be added to the LOD hierarchy" )
)
)
)
) --end of else after MILOCASE A
) --end of else after CASE 1
pickLodParentMode = false
UpdateTreeList()
)
else --just select the object in the scene
(
select treeListPanel.FocusedNode.Tag.Value
max zoomext sel
)
),
--pick parent mode
fn EnterPickParentMode =
(
pickLodParentMode = true
infoPanel.BackColor = infoPanel.BackColor.WhiteSmoke
--cursor change to cross hair
case currentMode of
(
"scene": infoPanel.text = "Pick the Scene LOD parent"
"drawable": infoPanel.text = "Pick the Drawable LOD parent"
"tree": infoPanel.text = "Pick the Tree LOD parent"
)
),
--parent lod
fn DispatchParentLod s e =
(
LODEditor.ParentLod s e
),
fn ParentLod s e =
(
--init info panel if not there
if lodListTable.Controls.Item[2].Name != "infoPanel" then
(
lodListTable.Controls.Remove lodListTable.Controls.Item[2]
LODEditor.InitInfoPanel()
)
--check for selected nodes
UpdateSelectedNodes()
if (selectedNodes.Count == 0) then --we have no selected nodes, so check for selected objects
(
UpdateSelectedObjects()
if (selectedObjects.Count == 0) then
(
infoPanel.Text = "no nodes selected"
)
else --we have objects selected but no nodes
(
UpdateSelectedNodesFromSelection()
if (currentMode == "drawable") then
(
if (SelectedNodes.Count > 1) then
(
infoPanel.Text = "Drawable LOD Mode: please select one node only"
UpdateTreeList()
)
else
(
EnterPickParentMode()
)
)
else --currentMode == "scene"
(
EnterPickParentMode()
)
)
)
else --we have selected nodes
(
UpdateSelectedObjectsFromSelectedNodes()
if (currentMode == "drawable") then
(
if (selectedNodes.Count > 1) then
(
infoPanel.Text = "Drawable LOD Mode: please select one node only"
UpdateTreeList()
)
else
(
EnterPickParentMode()
)
)
else --currentMode == "scene"
(
EnterPickParentMode()
)
)
),
----------------------------------------------------------------------------------------------------------------
--unparent lod
fn DispatchUnparentLod s e =
(
LODEditor.UnparentLod s e
),
fn UnparentLod s e =
(
--init info panel if not there
if lodListTable.Controls.Item[2].Name != "infoPanel" then
(
lodListTable.Controls.Remove lodListTable.Controls.Item[2]
LODEditor.InitInfoPanel()
)
--check for selection
UpdateSelectedNodes()
if (selectedNodes.Count == 0) then
(
UpdateSelectedObjects()
if (selectedObjects.Count ==0) then
(
infoPanel.Text = "no nodes selected"
)
else
-- we have selected objects, so update the nodes
(
UpdateSelectedNodesFromSelection()
for this in selectedObjects do
(
case currentMode of
(
"scene":
(
RsSceneLink.RemoveContainer LinkType_LOD this
)
"drawable":
(
RsSceneLink.RemoveContainer linkType_DRAWLOD this
)
"tree":
(
RsSceneLink.RemoveContainer LinkType_CombinerMesh this
)
)
)
infoPanel.Text = "LOD parents disconnected"
)
)
else --we have selected nodes
(
UpdateSelectedObjectsFromSelectedNodes()
for this in selectedObjects do
(
case currentMode of
(
"scene":
(
RsSceneLink.RemoveContainer LinkType_LOD this
)
"drawable":
(
RsSceneLink.RemoveContainer linkType_DRAWLOD this
)
"tree":
(
RsSceneLink.RemoveContainer LinkType_CombinerMesh this
)
)
)
infoPanel.Text = "LOD parents disconnected"
)
UpdateTreeList()
),
----------------------------------------------------------------------------------------------------------------
--SPLAY FUNCTIONS
----------------------------------------------------------------------------------------------------------------
fn GetLODDaddyListFromSelection =
(
daddyList = #()
UpdateSelectedObjects()
if (selectedObjects.Count > 0) then
(
for this in selectedObjects do
(
--if LOD hierarchy present...add root to daddyList
if (RsSceneLink.GetParent LinkType_LOD this != undefined) then
(
parentBuffer = RsSceneLink.GetParent LinkType_LOD this
if (RsSceneLink.GetParent LinkType_LOD parentBuffer != undefined) then
(
--grandparent is the daddy
appendIfUnique daddyList (RsSceneLink.GetParent LinkType_LOD parentBuffer)
)
else
(
--parent is the daddy
appendIfUnique daddyList parentBuffer
)
)
else --this has no LOD parent... check for LOD children
(
if ((getLODChildren this).Count > 0) then --for some reason (getLODChildren $ != undefined) is always true!!
(
--this must be the daddy... it has no parent but has children
appendIfUnique daddyList this
)
--otherwise, no parent no children, therefore no valid LOD hierarchy
)
)
if (daddyList.Count > 0) then
(
return daddyList
)
else
(
return undefined
)
)
else
(
--no objects in selection
return undefined
)
),
fn SplayAlongAxis axis =
--expands LOD objects along the axis member given by the argument, axis
--currently the axis values are x and y, but could be extended to include z axis too
(
--init info panel if not there
if lodListTable.Controls.Item[2].Name != "infoPanel" then
(
lodListTable.Controls.Remove lodListTable.Controls.Item[2]
LODEditor.InitInfoPanel()
)
--check for selection
if (ValidateSelection() == true) then
(
local LODDaddyList = #()
infoPanel.Text = "Expanding selected objects"
LODDaddyList = GetLODDaddyListFromSelection()
if (LODDaddyList != undefined) then
(
--mode split
if (currentMode == "scene") then
(
local children
local gchildren
--for loop to run through daddyList
for this in LODDaddyList do
(
--work out largest xyz dimension of daddy: expansionValue
expansionValue = GetBiggestDimension this
children = getLODChildren this
for thisChild in children do --loop through children
(
--expand children by expansionValue
if (axis == "x") then
(
thisChild.pos.x += (1.2 * expansionValue) -1.2 --used to make a slight gap between models
)
else --axis == "y"
(
thisChild.pos.y += (1.2 * expansionValue)
)
--expand grandchildren by 2 * expansionValue
gchildren = getLODChildren thisChild
if (gchildren.Count > 0) then
(
for thisgchild in gchildren do
(
if (axis == "x") then
(
thisgchild.pos.x += (2.4 * expansionValue)
)
else --axis == "y"
(
thisgchild.pos.y += (2.4 * expansionValue)
)
)
)
)
)
) --end of scene mode split
else --currentMode == "drawable"
(
local child
local gchild
--for loop to run through daddyList
for this in LODDaddyList do
(
--work out largest xyz dimension of daddy: expansionValue
expansionValue = GetBiggestDimension this
child = RsLodDrawable_GetHigherDetailModel this
--expand child by expansionValue
if (axis == "x") then
(
child.pos.x += expansionValue
)
else --axis == "y"
(
child.pos.y += expansionValue
)
--expand grandchild by 2 * expansionValue
gchild = RsLodDrawable_GetHigherDetailModel child
if (gchild != undefined) then
(
if (axis == "x") then
(
gchild.pos.x += (2 * expansionValue)
)
else --axis == "y"
(
gchild.pos.y += (2 * expansionValue)
)
)
)
)
)
else
(
infoPanel.Text = "no valid LOD hierarchies selected"
)
)
else --nothing selected
(
infoPanel.Text = "no valid nodes/objects selected"
)
UpdateTreeList()
),
fn DispatchSplayX s e =
(
LODEditor.SplayX s e
),
fn SplayX s e =
(
SplayAlongAxis "x"
),
fn DispatchSplayY s e =
(
LODEditor.SplayY s e
),
fn SplayY s e =
(
SplayAlongAxis "y"
),
fn DispatchSplayCollapse s e =
(
LODEditor.SplayCollapse s e
),
fn SplayCollapse s e =
(
--init info panel if not there
if lodListTable.Controls.Item[2].Name != "infoPanel" then
(
lodListTable.Controls.Remove lodListTable.Controls.Item[2]
LODEditor.InitInfoPanel()
)
if (ValidateSelection() == true) then
(
local LODDaddyList = #()
infoPanel.Text = "Collapsing selected LOD objects"
LODDaddyList = GetLODDaddyListFromSelection()
--for loop to run through each selected object
if (LODDaddyList != undefined) then
(
--mode split
if (currentMode == "scene") then
(
local children
local gchildren
--for loop to run through daddyList
for thisDaddy in LODDaddyList do
(
children = getLODChildren thisDaddy
for thisChild in children do
(
thisChild.pos = thisDaddy.pos
gchildren = getLODChildren thisChild
if (gchildren.Count > 0) then
(
for thisGchild in gchildren do
(
thisGchild.pos = thisDaddy.pos
)
)
)
)
)
else --currentMode == "drawable"
(
local child
local gchild
--for loop to run through daddyList
for thisDaddy in LODDaddyList do
(
child = RsLodDrawable_GetHigherDetailModel thisDaddy
child.pos = thisDaddy.pos
gchild = RsLodDrawable_GetHigherDetailModel child
if (gchild != undefined) then
(
gchild.pos = thisDaddy.pos
)
)
)
)
else
(
infoPanel.Text = "no valid LOD hierarchies selected"
)
)
),
----------------------------------------------------------------------------------------------------------------
--SHOW NON LODS TOGGLE
----------------------------------------------------------------------------------------------------------------
fn DispatchToggleShowNonLODs s e = LODEditor.ToggleShowNonLODs s e,
fn ToggleShowNonLODs s e =
(
if showNonLODObjects == true then
(
showNonLODObjects = false
)
else
(
showNonLODObjects = true
)
UpdateTreeList()
UpdateInfoPanel()
),
fn ToggleVisibleOnly =
(
if LODEditor.VisibleOnly == true then LODEditor.VisibleOnly = false
else LODEditor.VisibleOnly = true
LODEditor.UpdateTreeList()
LODEditor.UpdateInfoPanel()
),
----------------------------------------------------------------------------------------------------------------
--HELP
----------------------------------------------------------------------------------------------------------------
fn DispatchHelpLink s e =
(
LODEditor.HelpLink s e
),
--button to open browser
fn HelpLink s e =
(
ShellLaunch "https://mp.rockstargames.com/index.php/LOD_Editor" ""
),
----------------------------------------------------------------------------------------------------------------
--MILO Help Window
----------------------------------------------------------------------------------------------------------------
fn CreateMILOHelp =
(
),
fn DispatchMILOHelp s e =
(
LODEditor.MILOHelp s e
),
fn MILOHelp s e =
(
if (MILOHelpForm != undefined) then
(
MILOHelpForm.Close()
)
MILOHelpForm = dotNetObject "maxCustomControls.maxForm"
MILOHelpForm.Size = dotNetObject "System.Drawing.Size" 490 660
MILOHelpForm.Text = "R* MILO LOD Hierarchies"
MILOHelpForm.startPosition = (dotNetClass "System.Windows.Forms.FormStartPosition").manual
MILOHelpForm.Location = dotNetObject "system.drawing.point" FormWidth 120
MILOHelpForm.FormBorderStyle = (dotNetClass "System.Windows.Forms.FormBorderStyle").FixedToolWindow
MILOHelpForm.BackgroundImage = (dotNetClass "System.Drawing.Image").FromFile("X:\\tools\\dcc\current\\max2009\\scripts\\Payne\\images\\MILO_LODs.jpg")
MILOHelpForm.MaximumSize = dotNetObject "System.Drawing.Size" 490 660
MILOHelpForm.ShowModeless()
-- MILOHelpForm.ShowModal()
),
----------------------------------------------------------------------------------------------------------------
--USER INTERFACE
----------------------------------------------------------------------------------------------------------------
--BUTTONS
----------------------------------------------------------------------------------------------------------------
fn InitLabel Tag Align =
(
local newLabel = dotNetObject "Label"
newLabel.Text = Tag
newLabel.Font = Font_Calibri
newLabel.TextAlign = Align
return newLabel
),
fn InitButton Tag =
(
local newButton = dotNetObject "Button"
newButton.FlatStyle = (dotNetClass "System.Windows.Forms.FlatStyle").Standard
newButton.Margin = Padding_None
newButton.Padding = Padding_None
newButton.Text = Tag
newButton.Dock = DS_Fill
newButton.BackColor = RGB_Transparent
newButton.Font = Font_Calibri
ToolTip.SetToolTip newButton Tag
return newButton
),
fn InitButtons =
(
--List buttons
listButton1 = InitButton "Scene > List"
listPanel.Controls.Add listButton1 0 1
dotNet.addEventHandler listButton1 "Click" SceneToList
listButton2 = InitButton "List > Scene"
listPanel.Controls.Add listButton2 0 2
dotNet.addEventHandler listButton2 "Click" ListToScene
listButton3 = InitButton "Clear Selection"
listPanel.Controls.Add listButton3 1 3
dotNet.addEventHandler listButton3 "Click" ClearList
listButton4 = InitButton "Expand List"
listPanel.Controls.Add listButton4 1 1
dotNet.addEventHandler listButton4 "Click" Expand
listButton5 = InitButton "Contract List"
listPanel.Controls.Add listButton5 1 2
dotNet.addEventHandler listButton5 "Click" Contract
listButton6 = InitButton "Select All"
listPanel.Controls.Add listButton6 0 3
dotNet.addEventHandler listButton6 "Click" SelectAll
--Parenting buttons
parentingButton1 = InitButton "Pick Parent"
parentingPanel.Controls.Add parentingButton1 0 1
dotNet.addEventHandler parentingButton1 "Click" DispatchParentLod
parentingButton2 = InitButton "Remove Parent"
parentingPanel.Controls.Add parentingButton2 0 2
dotNet.addEventHandler parentingButton2 "Click" DispatchUnparentLod
--Attribute buttons
attributeButton1 = InitButton "LOD Distance"
attributePanel.Controls.Add attributeButton1 0 1
dotNet.addEventHandler attributeButton1 "Click" DispatchSetLODDistance
attributeButton2 = InitButton "TXD"
attributePanel.Controls.Add attributeButton2 0 2
dotNet.addEventHandler attributeButton2 "Click" DispatchSetTXD
--Splay buttons
splayButton1 = InitButton "Along X-Axis"
splayPanel.Controls.Add splayButton1 0 1
dotNet.addEventHandler splayButton1 "Click" DispatchSplayX
splayButton2 = InitButton "Along Y-Axis"
splayPanel.Controls.Add splayButton2 0 2
dotNet.addEventHandler splayButton2 "Click" DispatchSplayY
splayButton3 = InitButton "Collapse"
splayPanel.Controls.Add splayButton3 0 3
dotNet.addEventHandler splayButton3 "Click" DispatchSplayCollapse
),
----------------------------------------------------------------------------------------------------------------
--INFO PANEL
----------------------------------------------------------------------------------------------------------------
--this panel initialises at the bottom if it isn't present
fn InitInfoPanel =
(
infoPanel = dotnetobject "Label"
infoPanel.ForeColor = (dotNetClass "System.Drawing.Color").FromArgb 0 0 0
infoPanel.Dock = DS_Fill
infoPanel.TextAlign = TA_Left
infoPanel.Name = "infoPanel"
infoPanel.Font = Font_Calibri
lodListTable.Controls.Add infoPanel 0 2
case (currentMode) of
(
"scene": infoPanel.BackColor = RGB_Pink
"drawable": infoPanel.BackColor = RGB_BabyBlue
)
),
----------------------------------------------------------------------------------------------------------------
--ACTION PANEL
----------------------------------------------------------------------------------------------------------------
--this table is used for the txd and lod distance panels
fn InitActionPanel =
(
actionPanel = dotNetObject "TableLayoutPanel"
actionPanel.Dock = DS_Fill
actionPanel.CellBorderStyle = (dotNetClass "System.Windows.Forms.TableLayoutPanelCellBorderStyle").none
actionPanel.ColumnCount = 3
actionPanel.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 60)
actionPanel.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 25)
actionPanel.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 15)
actionPanel.RowCount = 1
actionPanel.RowStyles.Add (RS_dotNetObject.rowStyleObject "percent" 100)
lodListTable.Controls.Add actionPanel 0 2
),
----------------------------------------------------------------------------------------------------------------
--INIT UI FUNCTIONS
----------------------------------------------------------------------------------------------------------------
--TEXTURE DICTIONARY PANEL
----------------------------------------------------------------------------------------------------------------
fn InitTxdPanel =
(
InitActionPanel()
actionPanel.Name = "txdPanel"
--get the txd of the first selected object as the default value
newTxd = getAttr selectedObjects[1] (getattrindex "Gta Object" "TXD")
txdLabel = dotNetObject "Label"
txdLabel.Text = "Set new texture dictionary:"
txdLabel.Dock = DS_Fill
txdLabel.TextAlign = CA_Center
actionPanel.Controls.Add txdLabel
txdInput = dotNetObject "TextBox"
txdInput.MaxLength = 12
txdInput.Dock = DS_Fill
txdInput.Text = newTxd
actionPanel.Controls.Add txdInput
txdButton = dotNetObject "Button"
txdButton.Dock = DS_Fill
-- txdButton.BackColor = RGB_YellowOrange
txdButton.BackColor = RGB_Transparent
txdButton.ForeColor = textColour
txdButton.Text = "Apply"
actionPanel.Controls.Add txdButton
dotNet.addEventHandler txdButton "Click" ApplyTxd
),
----------------------------------------------------------------------------------------------------------------
--LOD DISTANCE PANEL
----------------------------------------------------------------------------------------------------------------
--this panel initialises at the bottom when the lod distance button is triggered
fn InitLodDistancePanel =
(
InitActionPanel()
actionPanel.Name = "lodDistancePanel"
--get the lod distance of the first selected object as the default value
newLodDistance = getAttr selectedObjects[1] (getattrindex "Gta Object" "LOD distance")
lodDistanceLabel = dotNetObject "Label"
lodDistanceLabel.Text = "Set new LOD distance:"
lodDistanceLabel.Dock = DS_Fill
lodDistanceLabel.TextAlign =CA_Center
actionPanel.Controls.Add lodDistanceLabel
lodDistanceInput = dotNetObject "NumericUpDown"
lodDistanceInput.Minimum = 0
lodDistanceInput.Maximum = 9999
lodDistanceInput.Value = newLodDistance
lodDistanceInput.Increment = 10
lodDistanceInput.Dock = DS_Fill
actionPanel.Controls.Add lodDistanceInput
lodDistanceButton = dotNetObject "Button"
lodDistanceButton.Dock = DS_Fill
lodDistanceButton.BackColor = RGB_Transparent
lodDistanceButton.ForeColor = textColour
lodDistanceButton.Text = "Apply"
actionPanel.Controls.Add lodDistanceButton
dotNet.addEventHandler lodDistanceButton "Click" DispatchApplyLD
),
----------------------------------------------------------------------------------------------------------------
--TREE LIST
----------------------------------------------------------------------------------------------------------------
fn InitTreeList =
--function sets up the initial tree list when the script is triggered
--at the moment, both the scene lod tab and the drawable lod tab can use this same control
--only one tab at a time can store the control
(
treeListPanel = dotNetObject "DevExpress.XtraTreeList.TreeList"
treeListPanel.Dock = DS_Fill
treeListPanel.OptionsSelection.MultiSelect = true
treeListPanel.OptionsView.ShowRoot = true
treeListPanel.OptionsView.ShowIndicator = false
treeListPanel.OptionsBehavior.Editable = false -- set to true on right click...
treeListPanel.OptionsView.EnableAppearanceEvenRow = true --colours the rows alternately
treeListPanel.OptionsView.EnableAppearanceOddRow = true --colours the rows alternately
treeListPanel.Appearance.FocusedCell.BackColor = RGB_CornflowerBlue
treeListPanel.BeginUpdate()
--first column for tree nodes
treeListPanel.Columns.Add()
treeListPanel.Columns.Item[0].Caption = "Object Tree"
treeListPanel.Columns.Item[0].Name = "tree"
treeListPanel.Columns.Item[0].FieldName = "tree"
treeListPanel.Columns.Item[0].VisibleIndex = 0
treeListPanel.Columns.Item[0].Width = 140
treeListPanel.columns.item[0].sortorder = (dotNetClass "SortOrder").ascending
--second column for LOD distances
treeListPanel.Columns.Add()
treeListPanel.Columns.Item[1].Caption = "LOD Distance"
treeListPanel.Columns.Item[1].Name = "distance"
treeListPanel.Columns.Item[1].VisibleIndex = 1
treeListPanel.Columns.Item[1].Width = 25
--third column for TXD
treeListPanel.Columns.Add()
treeListPanel.Columns.Item[2].Caption = "TXD"
treeListPanel.Columns.Item[2].Name = "TXD"
treeListPanel.Columns.Item[2].VisibleIndex = 2
treeListPanel.Columns.Item[2].Width = 35
treeListPanel.EndUpdate()
),
----------------------------------------------------------------------------------------------------------------
--FORM, TABLE AND TABS
----------------------------------------------------------------------------------------------------------------
fn InitLodList =
(
-- Form Setup
UpdateObjectList()
formHeight = borderHeight + (objectList.count * treeListRowHeight) + buttonPanelHeight + infoPanelHeight
lodListForm = RS_dotNetUI.maxForm "LodTL" text:"RS LOD Editor - Scene LODs" size:[formWidth,formHeight] min:[320,100] max:[800,1150]
lodListForm.sizeGripStyle = (dotNetClass "SizeGripStyle").Show
lodListForm.StartPosition = lodListForm.StartPosition.Manual
lodListForm.Location.X = 0
lodListForm.Location.Y = 120
lodListForm.FormBorderStyle = lodListForm.FormBorderStyle.SizableToolWindow
dotNet.AddEventHandler lodListForm "Load" LoadIniFile
dotNet.AddEventHandler lodListForm "Closing" SaveIniFile
ToolTip = dotnetobject "ToolTip"
--Table
lodListTable = dotNetObject "TableLayoutPanel"
lodListTable.Dock = DS_Fill
lodListTable.CellBorderStyle = (dotNetClass "System.Windows.Forms.TableLayoutPanelCellBorderStyle").single
lodListTable.ColumnCount = 1
lodListTable.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 100)
lodListTable.RowCount = 3
lodListTable.RowStyles.Add (RS_dotNetObject.rowStyleObject "percent" 100)
lodListTable.RowStyles.Add (RS_dotNetObject.rowStyleObject "absolute" buttonPanelHeight)
lodListTable.RowStyles.Add (RS_dotNetObject.rowStyleObject "absolute" infoPanelHeight)
lodListForm.Controls.Add lodListTable
--Tab Panel
tabPanel = dotNetObject "System.Windows.Forms.TabControl"
tabPanel.Dock = DS_Fill
tabPanel.Font = Font_Calibri
tab1 = dotNetObject "System.Windows.Forms.TabPage"
tab1.text = "Scene LODs"
tab2 = dotNetObject "System.Windows.Forms.TabPage"
tab2.text = "Drawable LODs"
tab3 = dotNetObject "System.Windows.Forms.TabPage"
tab3.text = "Tree LODs"
dotNet.AddEventHandler tabPanel "SelectedIndexChanged" DispatchTabClicked
tabPanel.Controls.Add tab1
tabPanel.Controls.Add tab2
tabPanel.Controls.Add tab3
lodListTable.Controls.Add tabPanel 0 0
case currentMode of
(
"scene": tabPanel.SelectTab tab1
"drawable": tabPanel.SelectTab tab2
"tree": tabPanel.SelectTab tab3
)
--Tree List View
InitTreeList() --sets up treeListPanel with the XtraTreeList
case currentMode of
(
"scene": tab1.Controls.Add treeListPanel --set up tab1 with the tree list
"drawable": tab2.Controls.Add treeListPanel
"tree": tab3.Controls.Add treeListPanel
)
--need to add the treeListPanel control to the other tab should that be selected
UpdateTreeList()
dotNet.AddEventHandler treeListPanel "Click" DispatchSetLodParent --behaviour to track list selection of lod parent
--Button Panel
local titleHeight = 12
buttonPanel = dotNetObject "TableLayoutPanel"
buttonPanel.Dock = DS_Fill
buttonPanel.BackColor = RGB_LightGrey
buttonPanel.ForeColor = textColour
buttonPanel.CellBorderStyle = (dotNetClass "System.Windows.Forms.TableLayoutPanelCellBorderStyle").none
buttonPanel.ColumnCount = 1
buttonPanel.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 100)
buttonPanel.RowCount = 2
buttonPanel.RowStyles.Add (RS_dotNetObject.rowStyleObject "percent" 100)
buttonPanel.RowStyles.Add (RS_dotNetObject.rowStyleObject "absolute" 25)
lodListTable.Controls.Add buttonPanel 0 1
--Button Strip: this is the top section of the button panel where the main function buttons are
buttonStrip = dotNetObject "TableLayoutPanel"
buttonStrip.Dock = DS_Fill
buttonStrip.CellBorderStyle = (dotNetClass "System.Windows.Forms.TableLayoutPanelCellBorderStyle").Inset
buttonStrip.ColumnCount = 4
buttonStrip.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 40)
buttonStrip.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 20)
buttonStrip.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 20)
buttonStrip.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 20)
buttonStrip.RowCount = 1
buttonStrip.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 100)
buttonPanel.Controls.Add buttonStrip 0 0
--List Buttons: these control the viewing of objects in the treelist
listPanel = dotNetObject"TableLayoutPanel"
listPanel.Dock = DS_Fill
listPanel.CellBorderStyle = (dotNetClass "System.Windows.Forms.TableLayoutPanelCellBorderStyle").none
listPanel.ColumnCount = 2
listPanel.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 50)
listPanel.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 50)
listPanel.RowCount = 4
listPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "absolute" titleHeight)
listPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
listPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
listPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
buttonStrip.Controls.Add listPanel 0 0
listLabel = dotNetObject "Label"
listLabel.Text = "List Commands"
listLabel.Font = Font_Small
listLabel.Dock = DS_Fill
listLabel.TextAlign = listLabel.TextAlign.MiddleCenter
listPanel.Controls.Add listLabel 0 0
listPanel.SetColumnSpan listLabel 2
--Parenting Buttons: control the LOD hierarchies
parentingPanel = dotNetObject "TableLayoutPanel"
parentingPanel.Dock = DS_Fill
parentingPanel.CellBorderStyle = (dotNetClass "System.Windows.Forms.TableLayoutPanelCellBorderStyle").none
parentingPanel.ColumnCount = 1
parentingPanel.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 100)
parentingPanel.RowCount = 4
parentingPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "absolute" titleHeight)
parentingPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
parentingPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
parentingPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
buttonStrip.Controls.Add parentingPanel 1 0
parentingLabel = dotNetObject "Label"
parentingLabel.Text = "LOD Parenting"
parentingLabel.Font = Font_Small
parentingLabel.TextAlign = listLabel.TextAlign.MiddleCenter
parentingPanel.Controls.Add parentingLabel 0 0
--Attribute Buttons: control the LOD hierarchies
attributePanel = dotNetObject "TableLayoutPanel"
attributePanel.Dock = DS_Fill
attributePanel.CellBorderStyle = (dotNetClass "System.Windows.Forms.TableLayoutPanelCellBorderStyle").none
attributePanel.ColumnCount = 1
attributePanel.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 100)
attributePanel.RowCount = 4
attributePanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "absolute" titleHeight)
attributePanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
attributePanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
attributePanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
buttonStrip.Controls.Add attributePanel 2 0
attributeLabel = dotNetObject "Label"
attributeLabel.Text = "Set Attributes"
attributeLabel.Font = Font_Small
attributeLabel.TextAlign = listLabel.TextAlign.MiddleCenter
attributePanel.Controls.Add attributeLabel 0 0
--Splay Buttons: these control the position of the LOD objects in the scene, splaying them for easier viewing
splayPanel = dotNetObject "TableLayoutPanel"
splayPanel.Dock = DS_Fill
splayPanel.CellBorderStyle = (dotNetClass "System.Windows.Forms.TableLayoutPanelCellBorderStyle").none
splayPanel.ColumnCount = 1
splayPanel.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 100)
splayPanel.RowCount = 4
splayPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "absolute" titleHeight)
splayPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
splayPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
splayPanel.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 33)
buttonStrip.Controls.Add splayPanel 3 0
splayLabel = InitLabel "Expand LODs" TA_Center
splayPanel.Controls.Add splayLabel 0 0
InitButtons()
--the help strip contains checkboxes and help controls
helpStrip = dotNetObject "TableLayoutPanel"
helpStrip.Dock = DS_Fill
helpStrip.CellBorderStyle = (dotNetClass "System.Windows.Forms.TableLayoutPanelCellBorderStyle").none
helpStrip.ColumnCount = 4
helpStrip.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "absolute" 110)
helpStrip.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "absolute" 90)
helpStrip.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "percent" 100)
helpStrip.ColumnStyles.Add (RS_dotNetObject.columnStyleObject "absolute" 40)
helpStrip.RowCount = 1
helpStrip.RowStyles.Add (RS_dotNetObject.RowStyleObject "percent" 100)
buttonPanel.Controls.Add helpStrip 1 0
showNonLODsCheckBox = dotNetObject "CheckBox"
showNonLODsCheckBox.Dock = DS_Fill
showNonLODsCheckBox.Text = "Show non-LODs"
showNonLODsCheckBox.Font = Font_Calibri
showNonLODsCheckBox.Checked = showNonLODObjects
dotNet.addEventHandler showNonLODsCheckBox "CheckedChanged" DispatchToggleShowNonLODs
helpStrip.Controls.Add showNonLODsCheckBox 0 0
showVisibleOnlyCheckBox = dotNetObject "CheckBox"
showVisibleOnlyCheckBox.Dock = DS_Fill
showVisibleOnlyCheckBox.Text = "Visible Only"
showVisibleOnlyCheckBox.Font = Font_Calibri
showVisibleOnlyCheckBox.Checked = VisibleOnly
dotNet.addEventHandler showVisibleOnlyCheckBox "CheckedChanged" ToggleVisibleOnly
helpStrip.Controls.Add showVisibleOnlyCheckBox 1 0
MILODiagram = dotNetObject "LinkLabel"
MILODiagram.Dock = DS_Fill
MILODiagram.Text = "MILO LOD diagram"
MILODiagram.Font = Font_Calibri
MILODiagram.LinkBehavior = (dotNetClass "System.Windows.Forms.LinkBehavior").NeverUnderline
MILODiagram.TextAlign = MILODiagram.TextAlign.MiddleCenter
dotNet.addEventHandler MILODiagram "LinkClicked" DispatchMILOHelp
helpStrip.Controls.Add MILODiagram 2 0
helpLabel = dotNetObject "Linklabel"
helpLabel.Dock = DS_Fill
helpLabel.Text = "help"
helpLabel.Font = Font_Calibri
helpLabel.LinkBehavior = (dotNetClass "System.Windows.Forms.LinkBehavior").NeverUnderline
helpLabel.TextAlign = helpLabel.TextAlign.MiddleRight
dotNet.addEventHandler helpLabel "LinkClicked" DispatchHelpLink
helpStrip.Controls.Add helpLabel 3 0
--informationPanel
InitInfoPanel()
UpdateInfoPanel()
--draw form
lodListForm.showModeless()
lodListForm
--setup a selection callback to select the object in the LodList automatically.
callbacks.removeScripts id:#LODEditor
--callbacks.addScript #selectionSetChanged "LODEditor.UpdateListNodesFromSelection()" id:#LODEditor
)
)
----------------------------------------------------------------------------------------------------------------
--STARTUP OPERATIONS
----------------------------------------------------------------------------------------------------------------
try(
if LODEditor != undefined then
(
LODEditor.lodListForm.close()
)
)
catch()
LODEditor = LodListStruct()
LODEditor.InitLodList()
----------------------------------------------------------------------------------------------------------------
--END OF SCRIPT
----------------------------------------------------------------------------------------------------------------