Files
gtav-src/tools_ng/wildwest/script/max/rockstar_london/grabcovertool/spatialutils.ms
T
2025-09-29 00:52:08 +02:00

513 lines
14 KiB
Plaintext
Executable File

-- contains project directory information.
include "rockstar\\export\\settings.ms"
-- Used by certain Spatial data types that don't want the rollout to disappear.
global g_FREEZE_ROLLOUT = false
global g_LOCKOUT_cb_CoverLineSelectionChanged = false
global g_COVER_BOX_LENGTH = 0.25
global g_COVER_BOX_WIDTH = 0.25
-- Purpose: Called By the Main Spatial Data Rollout to confirm that all the coverLines in the scene are properly initiated.
-- Params: None.
-- Returns: Will Select an uninitialized coverspline.
function CheckCoverLines=
(
)
function HasCustomAttribute obj attributeName=
(
if obj == undefined then
(
return false
)
attributeCount = custAttributes.count obj
for i = 1 to attributeCount do
(
if (custAttributes.get obj i).name == attributeName then
(
return true
)
)
return false
)
function IsCoverMesh obj=
(
if obj == undefined then
return false
if( obj.layer.name == "CoverHeightMesh" ) then
(
return true
)
return false
)
function IsStairMesh obj=
(
if obj == undefined then
return false
if( obj.layer.name == "StairSurfaces" ) then
(
return true
)
return false
)
function IsSoftCoverMesh obj=
(
if obj == undefined then
return false
if( obj.layer.name == "SoftCoverMeshes" ) then
(
return true
)
return false
)
function IsHardCoverMesh obj=
(
if obj == undefined then
return false
if( obj.layer.name == "HardCoverMeshes" ) then
(
return true
)
return false
)
function IsCoverLine obj=
(
if obj == undefined then
return false
if( obj.layer.name == "CoverLine" ) or ( (classOf (obj)) == Cover_Line ) then
(
return true
)
return false
)
function Reset_SoftCoverColor=
(
local layer = undefined
layer = layermanager.getLayerFromName "SoftCoverMeshes"
if( layer != undefined ) then
(
local layerNodes
layer.nodes &layerNodes
for obj in layerNodes do
(
if( obj != undefined ) then
(
obj.wirecolor = orange
)
)
)
)
function Reset_HardCoverColor=
(
local layer = undefined
layer = layermanager.getLayerFromName "HardCoverMeshes"
if( layer != undefined ) then
(
local layerNodes
layer.nodes &layerNodes
for obj in layerNodes do
(
if( obj != undefined ) then
(
obj.wirecolor = red
)
)
)
)
function Lockout_CoverLineSelectionChanged lockIt=
(
g_LOCKOUT_cb_CoverLineSelectionChanged = lockIt
)
-- Purpose: Callback Function for selection set changes, when the scene is frozen, we only want the tool to remain
-- Locked while the Cover_Line Edge is selected, or a spatial mesh object is selected.
-- Params: None
-- Returns: None
function cb_CoverLineSelectionChanged=
(
if g_LOCKOUT_cb_CoverLineSelectionChanged then
(
return false
)
--print "Calling cb_CoverLineSelectionChanged()"
--print selection
Reset_SoftCoverColor()
Reset_HardCoverColor()
for obj in selection do
(
objectClass = classOf obj
--print objectClass
-- If the object is a Cover_Line different than the active one.
-- Enable Rollout Changing again.
if objectClass == Cover_Line then
(
--print "Cover_Line Detected"
if g_CURRENT_COVER_LINE != undefined then
(
--print "g_CURRENT_NORMAL is Valid"
if g_CURRENT_COVER_LINE.name != obj.name then
(
print "Non-Active Cover_Line Selected"
freezeRollout false
select obj
)
)
)
else if obj.layer.name == "CoverHeightMesh" then
(
if (g_COVER_HEIGHT_SPINNER_A != undefined) and (g_COVER_HEIGHT_SPINNER_B != undefined) then
(
g_COVER_HEIGHT_SPINNER_A.value = Cover_Line.GetEdgeHeight g_CURRENT_COVER_LINE obj.MeshIndex 1
g_COVER_HEIGHT_SPINNER_B.value = Cover_Line.GetEdgeHeight g_CURRENT_COVER_LINE obj.MeshIndex 2
)
)
else if (IsSoftCoverMesh (obj)) then
(
-- Populate Rollout Values
if g_SOFT_COVER_RADIUS_SPINNER != undefined then
(
g_SOFT_COVER_RADIUS_SPINNER.value = obj.SoftCoverRadius
obj.wirecolor = blue
)
)
else if (IsHardCoverMesh (obj)) then
(
-- Populate Rollout Values
if g_HARD_COVER_RADIUS_SPINNER != undefined then
(
g_HARD_COVER_RADIUS_SPINNER.value = obj.HardCoverRadius
obj.wirecolor = blue
)
)
-- If the object is a CoverMesh
else
(
--print "Non Cover-Height Mesh selected"
--freezeRollout false
--select obj
)
)
)
-- Global Var used to track how many times someone will freeze a scene, it will only activate the callback if the the counter = 0
-- The reason being is that if we are editing soft and hardcover at the same time. We don't want the tool to reactivate the selection
-- call back. Essentially when the freezeRollout Stack is empty, or when no one is freezing the scene we can enable the the callback again.
global g_FreezeCount = 0
-- Purpose: Certain types, like cover, need to keep their rollout active regardless if another type is selected.
-- Params: Bool, True if you want to freeze the rollout, False if not. The Cover System appends it's own callback when the regular system
-- is frozen.
-- Returns: n/a
function freezeRollout freezeIt=
(
if ( freezeIt )then
(
-- If we want to freeze the scene just set the flag to freeze the scene immediately.
--print ("Debug: Freezing Rollout - Enabling Cover Selection Callback - "+ (g_FreezeCount as string))
if g_FreezeCount == 0 then
(
callbacks.addScript #selectionSetChanged "cb_CoverLineSelectionChanged()" id:#COVER_LINE_SELECTION
--print ("Debug: Actually Adding Callback")
)
g_FreezeCount = g_FreezeCount + 1
g_FREEZE_ROLLOUT = freezeIt
)
else
(
-- Only unfreeze the scene when all objects who have frozen it have allowed it to be unfrozen.
--print ("Debug: UnFreezing Rollout - Removing Cover Selection Callback - "+ (g_FreezeCount as string))
if g_FreezeCount == 1 then
(
callbacks.removeScripts id:#COVER_LINE_SELECTION
g_FREEZE_ROLLOUT = freezeIt
--print ("Debug: Actually Removing Callback")
)
g_FreezeCount = g_FreezeCount - 1
)
)
function ResetUIFreezeState=
(
g_FreezeCount = 0
)
-- Purpose: Draws a normal with fins.
-- Params: PointA - The Origin of the Arrow
-- PointB - The Tip of the Arrow
-- Returns: Nothing, but rasterizes an arrow in the scene.
function DrawArrow PointA PointB=
(
SLOPE_BACK = 0.25
FIN_WIDTH = 0.125
gw.enlargeUpdateRect #whole
lim = gw.getRndLimits()
-- Add another limit
append lim #zBuffer
-- Set the new rendering limits
gw.setRndLimits lim
--redrawViews()
completeRedraw()
-- Draw the shaft of the arrow.
gw.polyline #(PointA, PointB) false
-- Draw the fins.
lineVector = PointB - PointA
lineVector = normalize lineVector
-- fin slope back is the distance backwards on the arrow the
-- fins will be.
finSlopeback = PointB - (lineVector * SLOPE_BACK)
leftVector = cross lineVector [0,0,1]
leftVector = normalize leftVector
upVector = cross lineVector leftVector
upVector = normalize upVector
TopFinPoint = finSlopeback + ( upVector * FIN_WIDTH )
gw.polyline #(PointB, TopFinPoint) false
BottomFinPoint = finSlopeback - ( upVector * FIN_WIDTH )
gw.polyline #(PointB, BottomFinPoint) false
LeftFinPoint = finSlopeback + ( leftVector * FIN_WIDTH )
gw.polyline #(PointB, LeftFinPoint) false
RightFinPoint = finSlopeback - ( leftVector * FIN_WIDTH )
gw.polyline #(PointB, RightFinPoint) false
gw.updateScreen()
--redrawViews()
)
-- Purpose: Encapsulation for the Normal Drawing for Cover Lines.
function DrawCoverLineNormals coverLine normalDrawLength=
(
if coverLine == undefined then
return true
gw.setTransform (coverLine.transform)
splineEdgeCount = Cover_Line.GetEdgeCount g_CURRENT_COVER_LINE
for i = 1 to splineEdgeCount do
(
currentNormal = Cover_line.GetEdgeNormal g_CURRENT_COVER_LINE i
-- if the current vector is zero... Who gives a darn.
if( ( length ( currentNormal )) == 0 ) then
continue
if (i == splineEdgeCount) and (Cover_Line.IsClosed g_CURRENT_COVER_LINE) then
(
PointA = Cover_line.GetKnot g_CURRENT_COVER_LINE i
PointB = Cover_line.GetKnot g_CURRENT_COVER_LINE 1
)
else
(
PointA = Cover_line.GetKnot g_CURRENT_COVER_LINE i
PointB = Cover_line.GetKnot g_CURRENT_COVER_LINE (i + 1)
)
-- Take the Vector from i to i-1, half it and then add it to i-1
splineMidPoint = ((PointB - PointA)/2)+ PointA
gw.setColor #line green
DrawArrow splineMidPoint (splineMidPoint + (currentNormal * normalDrawLength ))
)
)
-- Purpose: Will create a cover box, from a given line and a normal, and mesh height.
function CreateCoverBoxFromLine lineOrigin lineVector lineNormal boxHeight=
(
print "==============================================="
-- Defaults for Calculation
local yAxis = [0.0, 1.0, 0.0]
local zAxis = [0.0, 0.0, 1.0]
local xAxis = [1.0, 0.0, 0.0]
boxRotation = 0.0
lineVector = normalize lineVector
lineNormal = normalize lineNormal
print "lineVector"
print lineVector
print "lineNormal"
print lineNormal
-- Get the box center point, which is dictated by the moving half the box width up the line, and
-- then half the length along the line normal.
BoxCenterPoint = lineOrigin + (lineVector * (g_COVER_BOX_WIDTH/2))
BoxCenterPoint = BoxCenterPoint + (lineNormal * (g_COVER_BOX_LENGTH/2))
NewCoverBox = Cover_Box Length_Segments:1 Width_Segments:1 Height_Segments:1 length:g_COVER_BOX_LENGTH width:g_COVER_BOX_WIDTH height:boxHeight pos:BoxCenterPoint
-- The arc cos of the dot product will give the angle between the box forward, and the line normal.
dotProd = dot(lineNormal) (yAxis)
print "dotProd"
print dotProd
boxRotation = acos( dotProd )
print "boxRotation"
print boxRotation
RotateRight = dot (xAxis) (lineNormal)
-- Since the angle will never be greater than 180, we need to test what side it is on, based on the dot result.
-- If it's negative then we need to add the rotation, negative if not.
if RotateRight > 0 then
(
NewCoverBox.rotation.z_rotation = NewCoverBox.rotation.z_rotation - boxRotation
)
else
(
NewCoverBox.rotation.z_rotation = NewCoverBox.rotation.z_rotation + boxRotation
)
-- If we cross product the zaxis(up) and the line normal we'll know which direction the a left wall would travel.
coverRightVector = cross zAxis lineNormal
coverRightVector = normalize coverRightVector
-- By dotting the right vector with the line vector we can tell what side the cover is on.
dotResult = dot coverRightVector lineVector
if dotResult < 0 then
(
Cover_Box.SetAsLeftCover NewCoverBox false
)
NewCoverBox.name = uniquename "CoverBox"
local layer = undefined
layer = layermanager.getLayerFromName "CoverBoxes"
if( layer == undefined ) then
(
layermanager.newLayerFromName "CoverBoxes"
layer = layermanager.getLayerFromName "CoverBoxes"
)
layer.addnode NewCoverBox
return NewCoverBox
)
-- Purpose: Generate Cover Boxes from a CoverLine Object.
-- Params: A Coverline to create the objects from.
-- Returns: Will Create two Cover Boxes aligned on the end of the line, or it will do nothing.
function GenerateCoverBoxesFromCoverLine coverLine=
(
-- If the Cover_Line isn't defined just break out of the function.
if (coverLine == undefined) or ( (classOf coverLine) != Cover_Line ) then
(
print "GenerateCoverBoxesFromCoverLine() - CoverLine is incorrect type, or undefined!"
return false
)
if (Cover_Line.IsClosed coverLine) or not (Cover_Line.CoverDataIsInitialized coverLine) then
(
Messagebox "GenerateCoverBoxesFromCoverLine() - Cannot Generate Cover Boxes from a closed Cover_Line!"
return false
)
-- Get the absolute position of the first knot.
StartPoint = Cover_Line.GetKnot coverLine 1
StartPoint = StartPoint * coverLine.transform
-- Get the absolute position of the second knot
SecondPoint = Cover_Line.GetKnot coverLine 2
SecondPoint = SecondPoint * coverLine.transform
-- Get the Vector going from that knot to the second knot.
lineVector = SecondPoint - StartPoint
lineVector = normalize lineVector
-- Get the normal of the associated Edge.
lineNormal = Cover_Line.GetEdgeNormal coverLine 1
lineNormal = lineNormal * coverLine.rotation
lineNormal = normalize lineNormal
-- Get the height associated to the first knot and first edge.
boxHeight = Cover_Line.GetEdgeHeight coverLine 1 1
tempBox1 = CreateCoverBoxFromLine StartPoint lineVector lineNormal boxHeight
temp = coverLine
select tempBox1
select coverLine
----------------------------------------------------------------------------------------------
-- Get the index of the last knot.
lastKnotIndex = Cover_Line.GetKnotCount coverLine
-- Get the absolute position of the last knot.
EndPoint = Cover_Line.GetKnot coverLine lastKnotIndex
EndPoint = EndPoint * coverLine.transform
-- Get the absolute position of the second to last knot.
SecondToLastPoint = Cover_Line.GetKnot coverLine (lastKnotIndex - 1)
SecondToLastPoint = SecondToLastPoint * coverLine.transform
-- Get the vector from the last knot to the second to last knot.
lineVector2 = SecondToLastPoint - EndPoint
lineVector2 = normalize lineVector2
-- Get the normal of the last edge
lineNormal2 = Cover_Line.GetEdgeNormal coverLine (Cover_Line.GetEdgeCount coverLine)
lineNormal2 = lineNormal2 * coverLine.rotation
lineNormal2 = normalize lineNormal2
-- Get the height of the last Knot
boxHeight2 = Cover_Line.GetEdgeHeight coverLine (Cover_Line.GetEdgeCount coverLine) 2
tempBox2 = CreateCoverBoxFromLine EndPoint lineVector2 lineNormal2 boxHeight2
temp = coverLine
select tempBox2
select coverLine
return true
)