Files
gtav-src/tools_ng/wildwest/script/3dsMax/Maps/SeamFixer.ms
T
2025-09-29 00:52:08 +02:00

258 lines
9.6 KiB
Plaintext
Executable File

--SeamFixer.ms
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms") --wildwest header
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/RSL_dotNetUIOps.ms") --RS_dotNetPreset structure
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/COVERT.ms") --coincident vertex functions
RsCollectToolUsageData (getThisScriptFilename())
global SeamFixer
struct NormalData
(
vertID,
normals = #(),
vectors = #()
)
struct ObjectNormalSettings
(
obj,
normalSettingList = #()
)
struct NormalSetting
(
vector,
vertList = #{}
)
struct SeamFixerStruct
(
Form,
ToolTip,
InfoPanel,
PositionThreshold,
AngleThreshold,
ProgBar,
ProgressValue = 0,
SeamFixerButton,
PreserveCheckBox,
IniFilePath = (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/RSL_Tools.ini"),
NormalList = #(),
------------------------------------------------------------------------------------------------------------------------------------------
--GENERAL FUNCTIONS
------------------------------------------------------------------------------------------------------------------------------------------
fn FixSeam s e =
(
local infoString = ""
local meshObjects = for this in selection where superClassOf this == GeometryClass collect this
local originalSelection = selection as array
if (meshObjects.Count > 1) then
(
local thistime = timestamp()
local objectProcessingList = #() --array of values to set normals to on a per object level
local editNorms = Edit_Normals() --edit normals modifier
rollout temprollout "Finding matching vertices"
(
label myLabel "Processing"
)
--find the border vertices
theNewFloater = createDialog temprollout 200 30
COVERT = COVERT_List tolerance:(SeamFixer.PositionThreshold.Text as float)
COVERT.InitCOVERT_List meshObjects
destroyDialog temprollout
meshObjects = COVERT.objList --reduced set of objects that have coincident vertices
infoString = "Coincident vertices found on " + meshObjects.count as string + " objects."
addModifier meshObjects editNorms
max modify mode --neccessary or the modifier operations have no effect
select meshObjects --required to refresh the scene
for match in COVERT.matchList do
(
--get the average vector
local vector = [0,0,0]
for object in match.objectList do
(
for vert in object.vertList do
(
local normal = RSNorm_GetVertexNormal object.obj vert
vector += normal
)
)
local averageVector = (normalize vector)
--set the vectors to the average value
for object in match.objectList do
(
local normalIDs = #{}
editNorms.ConvertVertexSelection object.vertList normalIDs node:object.obj
--adjust the averageVector to account for objects with rotaton values
local outputVector = averageVector * (object.obj.rotation as matrix3)
for normalID in normalIDs as array do
editNorms.SetNormal normalID outputVector node:object.obj
--make normals explicit to preserve the normals after stack collapse
editNorms.MakeExplicit selection:normalIDs node:object.obj true
)
SeamFixer.ProgressValue += 100.0 / COVERT.matchList.count
SeamFixer.ProgBar.Value = SeamFixer.ProgressValue as integer
)
if (not SeamFixer.PreserveCheckBox.Checked) then convertToPoly meshObjects
infoString = "Normals averaged at " + (COVERT.matchList.count as string) + " locations."
)
else
(
infoString = "Please select two or more objects for seam matching."
)
SeamFixer.InfoPanel.Text = infoString
SeamFixer.ProgressValue = 0
SeamFixer.ProgBar.Value = 0
local finalTime = timeStamp() - thisTime
local timeString = ("Operation took " + (finalTime/1000.0) as string + " seconds")
format "%\n" timeString
select originalSelection
),
------------------------------------------------------------------------------------------------------------------------------------------
--LOAD/SAVE FUNCTIONS
------------------------------------------------------------------------------------------------------------------------------------------
fn SaveIniFile =
(
setINISetting SeamFixer.IniFilePath "SeamFixer" "WinLocX" (SeamFixer.Form.Location.x as string)
setINISetting SeamFixer.IniFilePath "SeamFixer" "WinLocY" (SeamFixer.Form.Location.y as string)
setINISetting SeamFixer.IniFilePath "SeamFixer" "WinWidth" (SeamFixer.Form.Width as string)
setINISetting SeamFixer.IniFilePath "SeamFixer" "WinHeight" (SeamFixer.Form.Height as string)
setINISetting SeamFixer.IniFilePath "SeamFixer" "PositionThreshold" (SeamFixer.PositionThreshold.Text as string)
setINISetting SeamFixer.IniFilePath "SeamFixer" "PreserveCheckState" (SeamFixer.PreserveCheckBox.Checked as string)
--nb: have to use .Text property for numericUpDown controls because of http://forums.cgsociety.org/archive/index.php/t-763277.html
--max converts the numeric values to floats, so we have to grab the .Text value instead of .Value
),
fn LoadIniFile =
(
--default values
local WinLocX = 0
local WinLocY = 40
local WinWidth = 230
local WinHeight = 210
local PThresh = 0.001
local PreserveCheckState = false
try
(
WinLocX = getINISetting SeamFixer.IniFilePath "SeamFixer" "WinLocX" as integer
WinLocY = getINISetting SeamFixer.IniFilePath "SeamFixer" "WinLocY" as integer
WinWidth = getINISetting SeamFixer.IniFilePath "SeamFixer" "WinWidth" as integer
WinHeight = getINISetting SeamFixer.IniFilePath "SeamFixer" "WinHeight" as integer
PThresh = getINISetting SeamFixer.IniFilePath "SeamFixer" "PositionThreshold" as float
PreserveCheckState = getINISetting SeamFixer.IniFilePath "SeamFixer" "PreserveCheckState" as BooleanClass
)
catch()
SeamFixer.Form.Location = dotNetObject "system.drawing.point" WinLocX WinLocY
SeamFixer.Form.Size = dotNetObject "System.Drawing.Size" WinWidth WinHeight
SeamFixer.PositionThreshold.Value = PThresh
SeamFixer.PreserveCheckBox.Checked = PreserveCheckState
),
------------------------------------------------------------------------------------------------------------------------------------------
--UI
------------------------------------------------------------------------------------------------------------------------------------------
fn CreateUI =
(
-- form setup
Form = dotNetObject "maxCustomControls.maxForm"
Form.Text = "Seam Fixer"
Form.StartPosition = (dotNetClass "System.Windows.Forms.FormStartPosition").manual
Form.Location = dotNetObject "system.drawing.point" 0 80
Form.MaximumSize = dotNetObject "System.Drawing.Size" 1600 1200
Form.MinimumSize = dotNetObject "System.Drawing.Size" 230 210
Form.FormBorderStyle = RS_dotNetPreset.FBS.Sizable
dotNet.AddEventHandler Form "Load" LoadIniFile
dotNet.AddEventHandler Form "Closing" SaveIniFile
--content
ToolTip = dotnetobject "ToolTip"
Table = dotNetObject "TableLayoutPanel"
Table.Dock = RS_dotNetPreset.DS.Fill
Table.RowCount = 6
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 40) --banner
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 32) --input table
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 30) --preserve modifier stack
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 30) --SeamFixer button
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "percent" 100) --infoPanel
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 20) --progress bar
Table.ColumnCount = 1
Table.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
Form.Controls.Add Table
RSBannerPanel = dotNetObject "System.Windows.Forms.Panel"
RSBannerPanel.BorderStyle = (dotnetClass "System.Windows.Forms.BorderStyle").FixedSingle
RSBannerPanel.Dock = RS_dotNetPreset.DS.Fill
local banner = makeRsBanner dn_Panel:RSBannerPanel width:395 studio:"london" mail:"andy.davis@rockstarlondon.com" wiki:"Map_Art_Tech"
banner.setup()
Table.Controls.Add RSBannerPanel 0 0
InputTable = dotNetObject "TableLayoutPanel"
InputTable.Dock = RS_dotNetPreset.DS.Fill
InputTable.RowCount = 1
InputTable.RowStyles.add (RS_dotNetObject.rowStyleObject "percent" 100)
InputTable.ColumnCount = 2
InputTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "absolute" 150)
InputTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
Table.Controls.Add InputTable 0 1
PositionLabel = RS_dotNetUI.InitLabel "Vertex position threshold:" RS_dotNetPreset.TA_Left
InputTable.Controls.Add PositionLabel 0 0
PositionThreshold = RS_dotNetUI.InitNumericUpDown 0 1.0 0.001
PositionThreshold.Increment = 0.001
PositionThreshold.DecimalPlaces = 3
InputTable.Controls.Add PositionThreshold 1 0
PreserveCheckBox = RS_dotNetUI.InitCheckBox "Preserve modifier stack"
Table.Controls.Add PreserveCheckBox 0 2
SeamFixerButton = RS_dotNetUI.InitButton "Fix Seam"
dotNet.AddEventHandler SeamFixerButton "Click" FixSeam
Table.Controls.Add SeamFixerButton 0 3
InfoPanel = RS_dotNetUI.InitLabel "Select two objects for seam fixing." RS_dotNetPreset.TA.MiddleLeft
Table.Controls.Add InfoPanel 0 4
ProgBar = RS_dotNetUI.InitProgressBar()
Table.Controls.Add ProgBar 0 5
--draw form
Form.ShowModeless()
Form
)
)
if SeamFixer != undefined then
(
SeamFixer.Form.Close()
)
SeamFixer = SeamFixerStruct()
SeamFixer.CreateUI()