353 lines
9.9 KiB
Plaintext
Executable File
353 lines
9.9 KiB
Plaintext
Executable File
/*
|
|
Grid Slice
|
|
|
|
Author: Jason Hayes (jason.hayes@rockstarsandiego.com)
|
|
Description: Slices the selected objects based on the specified grid dimensions.
|
|
|
|
*/
|
|
|
|
filein "pipeline/util/rect.ms"
|
|
|
|
try( destroyDialog RsGridSliceUI ) catch ()
|
|
|
|
|
|
struct RsGridSlicePreset
|
|
(
|
|
name = "Default",
|
|
isDefault = false,
|
|
gridMin = Point2 -4096 -4096,
|
|
gridMax = Point2 4096 4096,
|
|
gridSize = Point2 512 512
|
|
)
|
|
|
|
struct RsGridSlice
|
|
(
|
|
--public
|
|
|
|
presets = dotNetObject "System.Collections.Hashtable",
|
|
activePreset = undefined,
|
|
deleteOriginals = false,
|
|
|
|
--private
|
|
|
|
virtualGrid = #(),
|
|
|
|
|
|
fn generateVirtualGrid = (
|
|
this.virtualGrid = #()
|
|
|
|
local numRows = ( ( this.activePreset.gridMax.x - this.activePreset.gridMin.x ) / this.activePreset.gridSize.x ) as integer
|
|
local numColumns = ( ( this.activePreset.gridMax.y - this.activePreset.gridMin.y ) / this.activePreset.gridSize.y ) as integer
|
|
|
|
local x = this.activePreset.gridMin.x
|
|
local y = this.activePreset.gridMin.y
|
|
|
|
for row = 1 to numRows do (
|
|
for column = 1 to numColumns do (
|
|
local rect = RsRect()
|
|
rect.bbox_min = [ x, y ]
|
|
rect.bbox_max = [ x + this.activePreset.gridSize.x, y + this.activePreset.gridSize.y ]
|
|
|
|
append this.virtualGrid rect
|
|
|
|
x += this.activePreset.gridSize.x
|
|
)
|
|
x = this.activePreset.gridMin.x
|
|
y += this.activePreset.gridSize.y
|
|
)
|
|
),
|
|
|
|
|
|
--public
|
|
|
|
fn loadPresets = (
|
|
local presetsFile = RSMakeSafeSlashes ( RsConfigGetWildWestDir() + "etc/config/general/gridSliceSettings.xml" )
|
|
|
|
if ( doesFileExist presetsFile ) then (
|
|
local stream = dotNetObject "System.IO.StreamReader" presetsFile
|
|
local doc = dotNetObject "System.Xml.XmlDocument"
|
|
doc.load stream
|
|
|
|
root = doc.documentElement
|
|
|
|
presetNodes = ( root.SelectNodes ".//preset" )
|
|
|
|
for idx = 0 to ( presetNodes.count - 1 ) do (
|
|
local preset = RsGridSlicePreset()
|
|
local presetNode = presetNodes.item[ idx ]
|
|
|
|
preset.name = presetNode.attributes.itemOf[ 0 ].value
|
|
preset.isDefault = ( presetNode.attributes.itemOf[ 1 ].value ) as BooleanClass
|
|
|
|
local minRaw = ( presetNode.SelectNodes ".//min" ).Item[ 0 ].InnerXml
|
|
local maxRaw = ( presetNode.SelectNodes ".//max" ).Item[ 0 ].InnerXml
|
|
local sizeRaw = ( presetNode.SelectNodes ".//size" ).Item[ 0 ].InnerXml
|
|
|
|
local minData = filterString minRaw ","
|
|
local maxData = filterString maxRaw ","
|
|
local sizeData = filterString sizeRaw ","
|
|
|
|
preset.gridMin = Point2 ( minData[ 1 ] as Double ) ( minData[ 2 ] as Double )
|
|
preset.gridMax = Point2 ( maxData[ 1 ] as Double ) ( maxData[ 2 ] as Double )
|
|
preset.gridSize = Point2 ( sizeData[ 1 ] as Double ) ( sizeData[ 2 ] as Double )
|
|
|
|
this.presets.Add preset.name ( dotNetMXSValue preset )
|
|
|
|
if preset.isDefault == True then (
|
|
this.activePreset = preset
|
|
)
|
|
)
|
|
|
|
doc = undefined
|
|
|
|
) else (
|
|
messageBox ( "Could not locate gridSliceSettings.xml! Was expecting it here:\n\n" + presetsFiles + "\n\nUsing default settings." ) title:"Grid Slice"
|
|
|
|
local preset = RsGridSlicePreset()
|
|
preset.activePreset = preset
|
|
preset.isDefault = True
|
|
|
|
this.presets.Add preset.name ( dotNetMXSValue preset )
|
|
)
|
|
),
|
|
|
|
fn addSlice obj posX posY orientation =
|
|
(
|
|
|
|
undo off
|
|
(
|
|
local objTM = obj.objectTransform
|
|
|
|
local sliceMod = SliceModifier()
|
|
addModifier obj sliceMod
|
|
local modTM = getModContextTM obj sliceMod
|
|
|
|
sliceMod.Slice_Type = 2 --remove top
|
|
|
|
case orientation of
|
|
(
|
|
#left:sliceMod.Slice_Plane.Rotation = (quat 0 -0.707107 0 0.707107)
|
|
#right:sliceMod.Slice_Plane.Rotation = (quat 0 0.707107 0 0.707107)
|
|
#up:sliceMod.Slice_Plane.Rotation = (quat -0.707107 0 0 0.707107)
|
|
#down:sliceMod.Slice_Plane.Rotation = (quat 0.707107 0 0 0.707107)
|
|
)
|
|
|
|
sliceMod.Slice_Plane.Position = [posX, posY, 0] * modTM * (inverse objTM)
|
|
)
|
|
|
|
),
|
|
|
|
fn slice objs =
|
|
(
|
|
if objs.count > 0 then
|
|
(
|
|
max hold
|
|
|
|
suspendEditing()
|
|
|
|
local slicedObjs = #()
|
|
|
|
--undo "Grid Slice" on (
|
|
this.generateVirtualGrid()
|
|
|
|
for obj in objs do (
|
|
if ( superClassOf obj ) == GeometryClass then (
|
|
local objRect = RsRect()
|
|
objRect.createFromObject obj
|
|
|
|
-- TODO: Checking for intersections will not scale very well with this method.
|
|
-- Doing this brute force just to get it in and working.
|
|
local ixRects = #()
|
|
|
|
for gridRect in this.virtualGrid do (
|
|
if ( objRect.intersects gridRect ) then (
|
|
append ixRects gridRect
|
|
)
|
|
)
|
|
|
|
-- Create a copy of the object so that we can slice it up instead of the original.
|
|
local slicedObj = copy obj
|
|
slicedObj.name = obj.name + "_sliced"
|
|
|
|
local objTM = obj.objectTransform
|
|
|
|
-- Slice the object for each grid cell that it intersected.
|
|
for ixRect in ixRects do
|
|
(
|
|
-- North
|
|
local northSliceMod = SliceModifier()
|
|
addModifier slicedObj northSliceMod
|
|
local modTM = getModContextTM slicedObj northSliceMod
|
|
local offsetNorth = ( ixRect.top() ) -- obj.pos.y
|
|
northSliceMod.Slice_Plane.rotation = Quat 1 0 0 1
|
|
northSliceMod.Slice_Plane.position = [slicedObj.pos.x, offsetNorth, 0] * modTM * (inverse objTM)
|
|
northSliceMod.Slice_Type = 1
|
|
|
|
-- East
|
|
local eastSliceMod = SliceModifier()
|
|
addModifier slicedObj eastSliceMod
|
|
local modTM = getModContextTM slicedObj eastSliceMod
|
|
local offsetEast = ( ixRect.left() ) -- obj.pos.x
|
|
eastSliceMod.Slice_Plane.rotation = Quat 0 1 0 1
|
|
eastSliceMod.Slice_Plane.position = [offsetEast, slicedObj.pos.y, 0] * modTM * (inverse objTM)
|
|
eastSliceMod.Slice_Type = 1
|
|
|
|
-- South
|
|
local southSliceMod = SliceModifier()
|
|
addModifier slicedObj southSliceMod
|
|
local modTM = getModContextTM slicedObj southSliceMod
|
|
local offsetSouth = ( ixRect.bottom() ) -- obj.pos.y
|
|
southSliceMod.Slice_Plane.rotation = Quat -1 0 0 1
|
|
southSliceMod.Slice_Plane.position = [slicedObj.pos.x, offsetSouth, 0] * modTM * (inverse objTM)
|
|
southSliceMod.Slice_Type = 1
|
|
|
|
-- West
|
|
local westSliceMod = SliceModifier()
|
|
addModifier slicedObj westSliceMod
|
|
local modTM = getModContextTM slicedObj westSliceMod
|
|
local offsetWest = ( ixRect.right() ) -- obj.pos.x
|
|
westSliceMod.Slice_Plane.rotation = Quat 0 -1 0 1
|
|
westSliceMod.Slice_Plane.position = [offsetWest, slicedObj.pos.y, 0] * modTM * (inverse objTM)
|
|
westSliceMod.Slice_Type = 1
|
|
|
|
collapseStack slicedObj
|
|
)
|
|
|
|
append slicedObjs slicedObj
|
|
|
|
if deleteOriginals then
|
|
(
|
|
delete obj
|
|
)
|
|
else
|
|
(
|
|
slicedObj.parent = obj
|
|
obj.isHidden = true
|
|
)
|
|
)
|
|
--)
|
|
)
|
|
|
|
resumeEditing()
|
|
|
|
slicedObjs
|
|
|
|
) else (
|
|
messageBox "You must supply at least one object to slice!" title:"Grid Slice"
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
rollout RsGridSliceUI "Grid Slice"
|
|
(
|
|
local gridSlice = RsGridSlice()
|
|
|
|
dropDownList ddlPresets "Presets:" width:190 offset:[ -7, 0 ]
|
|
button btnSliceSelected "Slice Selected" width:190 height:24
|
|
checkbox chkDeleteOriginal "Delete Original"
|
|
|
|
group "Grid Dimensions"
|
|
(
|
|
spinner spGridMinX "Min X:" range:[ -99999.0, 99999.0, 0 ] type:#float
|
|
spinner spGridMinY "Min Y:" range:[ -99999.0, 99999.0, 0 ] type:#float
|
|
|
|
spinner spGridMaxX "Max X:" range:[ -99999.0, 99999.0, 0 ] type:#float
|
|
spinner spGridMaxY "Max Y:" range:[ -99999.0, 99999.0, 0 ] type:#float
|
|
|
|
spinner spGridCellWidth "Cell Width:" range:[ -99999.0, 99999.0, 0 ] type:#float
|
|
spinner spGridCellHeight "Cell Height:" range:[ -99999.0, 99999.0, 0 ] type:#float
|
|
)
|
|
|
|
-- Functions
|
|
|
|
fn refresh = (
|
|
local presetNames = #()
|
|
local presetEnum = gridSlice.presets.GetEnumerator()
|
|
|
|
while ( presetEnum.MoveNext() ) do (
|
|
append presetNames presetEnum.Key
|
|
)
|
|
|
|
ddlPresets.items = presetNames
|
|
|
|
local activePreset = gridSlice.activePreset
|
|
|
|
if activePreset != undefined then (
|
|
spGridMinX.value = activePreset.gridMin.x
|
|
spGridMinY.value = activePreset.gridMin.y
|
|
spGridMaxX.value = activePreset.gridMax.x
|
|
spGridMaxY.value = activePreset.gridMax.y
|
|
spGridCellWidth.value = activePreset.gridSize.x
|
|
spGridCellHeight.value = activePreset.gridSize.y
|
|
|
|
) else (
|
|
messageBox "There is no default preset defined for this tool! You really shouldn't see this. Please contact your local Technical Artist." title:"Grid Slice"
|
|
)
|
|
)
|
|
|
|
|
|
-- Event Handlers
|
|
|
|
on RsGridSliceUI open do (
|
|
gridSlice.loadPresets()
|
|
refresh()
|
|
|
|
-- Set drop down list to default preset on load. The initial active preset wil be the default.
|
|
idx = 1
|
|
|
|
for presetName in ddlPresets.items do (
|
|
if presetName == gridSlice.activePreset.name then (
|
|
ddlPresets.selection = idx
|
|
)
|
|
|
|
idx += 1
|
|
)
|
|
)
|
|
|
|
on btnSliceSelected pressed do (
|
|
local objs = selection as array
|
|
|
|
if objs.count > 0 then (
|
|
gridSlice.deleteOriginals = chkDeleteOriginal.checked
|
|
gridSlice.slice objs
|
|
|
|
) else (
|
|
messageBox "Please select at least one object!" title:"Grid Slice"
|
|
)
|
|
)
|
|
|
|
on ddlPresets selected val do (
|
|
local preset = gridSlice.presets.Item[ ddlPresets.Selected ].value
|
|
gridSlice.activePreset = preset
|
|
refresh()
|
|
)
|
|
|
|
on spGridMinX changed val do (
|
|
gridSlice.activePreset.gridMin.x = val
|
|
)
|
|
|
|
on spGridMinY changed val do (
|
|
gridSlice.activePreset.gridMin.y = val
|
|
)
|
|
|
|
on spGridMaxX changed val do (
|
|
gridSlice.activePreset.gridMax.x = val
|
|
)
|
|
|
|
on spGridMaxY changed val do (
|
|
gridSlice.activePreset.gridMax.y = val
|
|
)
|
|
|
|
on spGridCellWidth changed val do (
|
|
gridSlice.activePreset.gridSize.x = val
|
|
)
|
|
|
|
on spGridCellHeight changed val do (
|
|
gridSlice.activePreset.gridSize.y = val
|
|
)
|
|
)
|
|
|
|
createDialog RsGridSliceUI width:200 height:250
|
|
|