2277 lines
77 KiB
Plaintext
Executable File
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
|
|
---------------------------------------------------------------------------------------------------------------- |