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

320 lines
8.5 KiB
Plaintext
Executable File

--///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
--------------------------------- DIVIDE
--///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
rollout RsModelToolDivideRoll "Divide Model"
(
local MainFloater
local sub_name
local offset_length = 400
local bDelete = false
local bLOD = false
local bAligned = false
local columns = 0
local rows = 0
--////////////////////////////////////////////////////////////
-- interface
--////////////////////////////////////////////////////////////
hyperlink lnkHelp "Help?" address:"https://devstar.rockstargames.com/wiki/index.php/Modelling_Toolkit#Divide_Model"
offset:[0,-4] align:#right color:(color 0 0 255) hoverColor:(color 0 0 255) visitedColor:(color 0 0 255)
groupBox grpSlicer "Mesh Slicer" pos:[4,20] width:(RsModelToolDivideRoll.width - 8) height:66 across:3
button btnModelSlicer "Start Slicing" align:#left pos:(grpSlicer.pos + [14, 22]) height:30
tooltip:"Chops up selected meshes into smaller chunks, along drawn outlines"
radioButtons btnsSliceObjElem "Slice into:" labels:#("Objects", "Elements") pos:(btnModelSlicer.pos + [90,-10])
tooltip:"Chop object into objects or elements"
checkBox chkRandomClr "Random\nColour" width:60 height:30 pos:(btnModelSlicer.pos + [180,0]) checked:true enabled:(btnsSliceObjElem.state == 1)
tool:"Give new objects random colours, or keep source-object's colour"
label lblSpacer "" height:9
group "Add slice-modifier:"
(
button btnSlice90 "Slice 90" width:118 across:2
button btnSlice180 "Slice 180" width:116
)
group "Chop into blocks:"
(
checkbox chkAligned "World Aligned" width:84 height:21 across:2
spinner spnLength "Size: " tooltip:"Block size in meters" width:136 height:16 range:[0,1e+006,400] type:#integer scale:100 align:#right
checkbox chkLod "LOD Object" width:84 height:21 across:2
editText edtName "Name: " tooltip:"Prefix" width:153 height:18 align:#center align:#right offset:[-12,-4]
checkbox chkDelete "Delete Parent" tooltip:"Deletes original object" width:84 height:21 across:3
button btnGo "Begin" width:103 height:25 offset:[65, 0]
progressBar progBar orient:#vertical height:25 width:10 align:#right color:green
)
--////////////////////////////////////////////////////////////
-- methods
--////////////////////////////////////////////////////////////
fn worldAlign coord =
(
difference = abs(mod coord offset_length)
adjustment = abs(offset_length - difference)
coord -= adjustment
)
fn meshChop obj chopSize:256 namePrefix:"test" =
(
if (obj == undefined) then
(
return false
)
local meshBits = #()
ConvertToPoly obj
local chopBitCount = 0
chopSize = chopSize as Float
local objBB = nodeGetBoundingBox obj (Matrix3 1)
local bbWidth = objBB[2].x - objBB[1].x
local bbHeight = objBB[2].y - objBB[1].y
local widthRatio = bbWidth / chopSize
local heightRatio = bbHeight / chopSize
local halfWidthOffset = (bbWidth/2.0)+(chopSize/2.0)
local halfHeightOffset = (bbHeight/2.0)+(chopSize/2.0)
local columns = (ceil widthRatio) as integer
local rows = (ceil heightRatio) as integer
local totalProcessed = 0
local allToDo = (rows + 1) * (columns + 1)
setCommandPanelTaskMode #modify
modPanel.setCurrentObject obj
CopyAttrs obj
--setup modifiers on source obj
local vs = volumeSelect()
vs.level = 2 --face
vs.type = 1 --crossing
vs.method = 0 --replace
vs.volume = 0 --box
addModifier obj vs
local gizmoScale = [(1.0 / widthRatio), (1.0 / heightRatio), 1]
vs.Gizmo.scale = gizmoScale
--move it for now
vs.gizmo.pos = [(bbWidth * 2.0), (bbHeight * 2.0), 0]
local epMod = Edit_Poly()
epMod.useStackSelection = on
addModifier obj epMod
local newGizmoPos = [0,0,0]
--store previously selected faces to check against
local faceRegister = #{}
-- format "rows: % \n" rows
-- format "Columns: % \n" columns
local gridSeq = spiralArraySequence rows columns
for visitor in gridSeq do
(
row = visitor.x
col = visitor.y
modPanel.setCurrentObject obj
--newGizmoPos = [0, 0, 0]
if bAligned then
(
local objTM = obj.transform
local modTM = getModContextTM obj vs
local newX = worldAlign (((col + 1) * chopSize) - halfWidthOffset)
local newY = worldAlign (((row + 1) * chopSize) - halfHeightOffset)
newGizmoPos = [newX, newY, 0] * modTM * (inverse objTM)
)
else
(
local newX = (col * chopSize) - halfWidthOffset
local newY = (row * chopSize) - halfHeightOffset
newGizmoPos = [newX, newY, 0]
)
vs.gizmo.pos = newGizmoPos
vs.method = 1
modPanel.setCurrentObject obj.modifiers[1]
local facList = EditPolyMod.GetSelection epMod #Face
if (facList.numberSet != 0) and (facList.numberSet != obj.numFaces) then
(
local faceClash = faceRegister * facList
local facesToChop = #{}
if faceClash.numberSet > 0 then
(
facesToChop = facList - faceClash
)
else
(
facesToChop = facList
)
if (facesToChop.numberSet > 0) and (facesToChop.numberSet != obj.numFaces) then
(
local newChop = copy obj
collapseStack newChop
chopBitCount += 1
newChop.name = namePrefix + "_" + (chopBitCount as string )
if bLOD then
(
newChop.name += "_LOD"
)
--apply the orignals Gta Attrs to the chopped pieces
PasteAttrs newChop
polyOp.DeleteFaces newChop -facesToChop
centerPivot newChop
append meshBits newChop
faceRegister += facList
)
)
totalProcessed += 1
progBar.value = (totalProcessed * (100.0 / allToDo))
)
--clean up
if bDelete then
(
delete obj
)
else
(
deleteModifier obj 1
deleteModifier obj 1
)
--return the new pieces
return meshBits
)
--////////////////////////////////////////////////////////////
-- events
--////////////////////////////////////////////////////////////
on btnModelSlicer pressed do
(
undo "mesh slicer" on
(
filein "pipeline/helpers/models/modelSlicer.ms"
)
)
on btnsSliceObjElem changed val do
(
chkRandomClr.enabled = (val == 1)
)
--------------------------------------------------------------
-- Slice
--------------------------------------------------------------
on btnSlice90 pressed do (
if selection.count != 1 then (
messagebox "Please select one object"
)
else (
modPanel.addModToSelection (SliceModifier ()) ui:on
$.modifiers[#Slice].slice_plane.rotation =(quat 1 0 1 0)
)
)
on btnSlice180 pressed do (
if selection.count != 1 then (
messagebox "Please select one object"
)
else (
modPanel.addModToSelection (SliceModifier ()) ui:on
$.modifiers[#Slice].slice_plane.rotation =(quat 1 0 0 1)
)
)
--------------------------------------------------------------
-- Chop
--------------------------------------------------------------
on spnLength changed val do (
offset_length = spnLength.value
)
on edtName entered text do (
sub_name = edtName.text
)
on btnGo pressed do
(
if (selection.count == 0) then
(
messagebox "Nothing Selected" title:"No Selection"
)
if ((getAttrClass selection[1]) != "Gta_Object") and not (isKindOf selection[1] GeometryClass) then
(
messagebox "Please pick a mesh object" title:"Bad Selection"
)
meshChop selection[1] chopSize:spnLength.value namePrefix:edtName.text
progBar.value = 0
)
on chkAligned changed state do
(
if state == true then
(
bAligned = true
)
else
(
bAligned = false
)
)
on chkLod changed state do (
if chkLod.checked == true do
bLOD = true
)
on chkDelete changed state do (
if chkDelete.checked == true do
bDelete = true
)
--------------------------------------------------------------
-- Chop
--------------------------------------------------------------
on RsModelToolDivideRoll open do (
if selection.count == 1 then (
edtName.text = $.name
)
)
on RsModelToolDivideRoll rolledUp down do
(
RsSettingWrite "RsModelToolDivideRoll" "rollup" (not down)
)
)