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

212 lines
5.8 KiB
Plaintext
Executable File

rollout RsModelToolAlignRoll "Align Object" width:300
(
hyperlink lnkHelp "Help?" address:"https://devstar.rockstargames.com/wiki/index.php/Modelling_Toolkit#Align_Object" align:#right color:(color 0 0 255) hoverColor:(color 0 0 255) visitedColor:(color 0 0 255)
local storedItem
group "Store/Restore Transforms:"
(
button btnStoreXform "Store" across:3 align:#left tooltip:"Remember selected object's transforms:\nUse to revert changes after aligning"
label lblStoredXform "" offset:[-4,4]
button btnRestoreXform "Restore" align:#right enabled:false tooltip:"Apply stored transforms back onto object"
)
group "Align Object-Edge To Axis:"
(
button btnAlignObj "Align:" width:52 height:30 across:5 offset:[0,7] align:#left tooltip:"Rotate selected object around chosen axis, to align selected edge to another axis"
label lblRot "Rotate in:" align:#right offset:[16,14]
radiobuttons btnsRotAxis "" labels:#("X","Y","Z") columns:1 default:3 align:#left offset:[20,0]
label lblAlign "Align Edge to:" align:#right offset:[22,14]
radiobuttons btnAlignX "" labels:#("X") pos:[lblAlign.pos.x + 72, btnsRotAxis.pos.y]
radiobuttons btnAlignY "" labels:#("Y") pos:(btnAlignX.pos + [0, 15])
radiobuttons btnAlignZ "" labels:#("Z") pos:(btnAlignY.pos + [0, 15])
)
local alignCtrls = #(btnAlignX, btnAlignY, btnAlignZ)
fn RsAlignObjToEdge obj rotAxis:3 alignAxis:1 =
(
local otherAxis = ((#{1..3} - #{rotAxis, alignAxis}) as array)[1]
/*
local axises = #("X","Y","Z")
format "Rotate:%,% Align:%,% Other:%,% %\n" rotAxis axises[rotAxis] alignAxis axises[alignAxis] otherAxis axises[otherAxis] edgeVec
*/
local selType = RsGetSubObjLevelName()
if (selType != #edge) do
(
messageBox "Non-edge selection!\n\nPlease select an edge on a mesh/poly object" title:"Error: Non-edge selection"
return false
)
if (isKindOf obj objectSet) do (obj = obj[1])
local objXform = obj.transform
local objMesh = copy obj.mesh
local edgeSel = getEdgeSelection objMesh
if (edgeSel.numberSet == 0) do
(
messageBox "Empty selection:\n\nPlease select an edge" title:"Error: Nothing selected"
return false
)
local verts = #{}
for edgeNum in edgeSel while (verts.numberSet < 2) do
(
verts += meshOp.getVertsUsingEdge objMesh edgeNum
)
if (verts.numberSet != 2) do
(
messageBox "Multiple edges selected!\n\nPlease select just one edge" title:"Error: Too many selected"
return false
)
-- Get edge-vert positions, transformed to world-space:
local vertPosList = for vertNum in verts collect
(
((getVert objMesh vertNum) * objXform) --- objXform.pos
)
--for pos in vertPosList do (point pos:pos)
local edgeVec = normalize (vertPosList[1] - vertPosList[2])
edgeVec[rotAxis] = 0
-- Stop processing if edge-vector is already aligned:
if (close_enough edgeVec[otherAxis] 0 10) do
(
return false
)
-- Vector to align to:
local alignVec = [0,0,0]
alignVec[alignAxis] = 1
/*
Tape pos:vertPosList[1] target:(targetObject pos:(vertPosList[1] + (10 * edgeVec)))
Tape pos:vertPosList[1] target:(targetObject pos:(vertPosList[1] + (5 * alignVec)))
*/
local angleAxes = #(alignAxis, otherAxis)
sort angleAxes
-- Find angle between vectors:
local vecAngle = (atan2 alignVec[angleAxes[2]] alignVec[angleAxes[1]]) - (atan2 edgeVec[angleAxes[2]] edgeVec[angleAxes[1]])
-- Correct direction for y-axis rotation:
if (rotAxis == 2) do
(
vecAngle *= -1
)
-- Always rotate less than 90 degrees:
local rotAngle = vecAngle
local angleSign = if (vecAngle < 0) then 1 else -1
if (abs vecAngle) > 90 do
(
rotAngle += (angleSign * 180)
)
--format "% -> % : % (%)\n" edgeVec alignVec vecAngle rotAngle
local changeRot = (eulerAngles 0 0 0)
case rotAxis of
(
1:(changeRot.x = rotAngle)
2:(changeRot.y = rotAngle)
3:(changeRot.z = rotAngle)
)
in coordSys world rotate obj changeRot
)
fn setViewAxis num =
(
local enabledAligns = #{1..3}
enabledAligns -= #{num}
-- Disable view-axis as align-option:
for alignNum = 1 to 3 do
(
alignCtrls[alignNum].enabled = enabledAligns[alignNum]
alignCtrls[alignNum].state = 0
)
-- Set first enabled axis state:
alignCtrls[(enabledAligns as array)[1]].state = 1
)
fn setAlignAxis num =
(
for alignNum = 1 to 3 where (alignNum != num) do
(
alignCtrls[alignNum].state = 0
)
)
on btnsRotAxis changed val do (setViewAxis val)
on btnAlignX changed val do (setAlignAxis 1)
on btnAlignY changed val do (setAlignAxis 2)
on btnAlignZ changed val do (setAlignAxis 3)
on btnAlignObj pressed do
(
local rotAxis = btnsRotAxis.state
local alignAxis = case of
(
(btnAlignX.state == 1):1
(btnAlignY.state == 1):2
(btnAlignZ.state == 1):3
)
undo "rotate object edge to axis" on
(
RsAlignObjToEdge selection rotAxis:rotAxis alignAxis:alignAxis
)
)
on btnStoreXform pressed do
(
if (selection.count != 1) then
(
storedItem = undefined
lblStoredXform.text = ""
btnRestoreXform.enabled = false
)
else
(
local obj = selection[1]
storedItem = datapair obj:obj transform:obj.transform
lblStoredXform.text = obj.name
btnRestoreXform.enabled = true
)
)
on btnRestoreXform pressed do
(
if (storedItem != undefined) and (isValidNode storedItem.obj) then
(
storedItem.obj.transform = storedItem.transform
)
else
(
btnRestoreXform.enabled = false
storedItem = undefined
)
)
on RsModelToolAlignRoll open do
(
setViewAxis btnsRotAxis.state
)
on RsModelToolAlignRoll rolledUp down do
(
RsSettingWrite "RsModelToolAlignRoll" "rollup" (not down)
)
)