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

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