2724 lines
84 KiB
Plaintext
Executable File
2724 lines
84 KiB
Plaintext
Executable File
--
|
|
-- Description:: Data driven utilities for manipulating the terrain shader
|
|
--
|
|
-- Author:: Luke Openshaw <luke.openshaw@rockstarnorth.com>
|
|
-- Author:: Marissa Warner-Wu <marissa.warner-wu@rockstarnorth.com>
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
-- HISTORY
|
|
-- 11/11/2009
|
|
-- by Stuart Macdonald
|
|
-- Added undo to vert and face colouring
|
|
-- Fixed bitmap resize load ( line 399 )
|
|
--
|
|
-- 9/11/2009
|
|
-- by Marissa Warner-Wu
|
|
-- Incorporated terrain texture palette tool from Aaron/Stu.
|
|
--
|
|
-- 4/12/2008
|
|
-- by Luke Openshaw
|
|
-- Update: Hack in Multisub support
|
|
--
|
|
-- 16/05/2014
|
|
-- by Neal D Corbett
|
|
-- Update: UI rewritten to completely use DotNet controls.
|
|
-- Now compatible with RDR UberTerrain shaders.
|
|
-----------------------------------------------------------------------------
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Uses
|
|
-----------------------------------------------------------------------------
|
|
|
|
try (gRsTerrainPalette.ToolForm.Close()) catch ()
|
|
Callbacks.RemoveScripts id:#RsTerrainPaint
|
|
global gRsTerrainPalette = undefined
|
|
|
|
RSTA_LoadCommonFunction #("fn_RSTA_vertexColours.ms")
|
|
filein (RsConfigGetWildwestDir() + "Script/3dsMax/Maps/Materials/terrain_helperFunctions.ms")
|
|
filein (RsConfigGetWildWestDir() + "/script/3dsMax/_common_functions/fn_RSTA_ThumbsMgr.ms")
|
|
filein (RsConfigGetWildWestDir() + "script/3dsMax/General_tools/Selection_Funcs.ms")
|
|
|
|
|
|
-- Struct for passing options to 'ev_SelSubObjsMenuItem_Clicked'
|
|
struct RsTerrPal_SelSubObjOpts (SubObjName, AddSel = False, RemSel = False, IgnoreBitmaps = False, Dominant = False)
|
|
|
|
--------------------------------------------------------------
|
|
-- Terrain texture palette:
|
|
--------------------------------------------------------------
|
|
struct RsTerrainPalette
|
|
(
|
|
RsBannerPanel = DotNetObject "Panel",
|
|
BannerStruct = makeRsBanner dn_Panel:RsBannerPanel wiki:"Terrain_Paint" versionNum:1.53 versionName:"Miraculous Tern",
|
|
|
|
FormSize = [574, 804],
|
|
|
|
TerrainObj, -- Currently-selected mesh-object
|
|
TerrainMatInfoList = #(), -- Terrain-material info-list taken from current 'TerrainObj'
|
|
TerrainMatIds, -- MatId lookup-list for 'TerrainMatInfoList'
|
|
SelMatInfo, -- Currently-selected material-info
|
|
vPaintTool, -- Active instance of VertexPaint
|
|
DoneVertChecks = #(), -- Used to track which objects/channels have had 'RsHasCompressedVertChan' run on them.
|
|
|
|
-- Tool's form and defined controls (so functions can quickly find them)
|
|
ToolForm = dotNetObject "MaxCustomControls.MaxForm",
|
|
ObjEditPanels = #(),
|
|
|
|
ScrollPanel, ShowChansPanel, TexmapPanel, MatPanels = #(),
|
|
CboShaderType, ChkPickMat, SpnDeselPercent, ChkVertPaint, SpnFillStrength, SldLookupMask, SldTintMask, SldDisplaceMask,
|
|
|
|
-- Texmap rightclick-menus, per shadertype:
|
|
TexmapRCMenus = (DataPair ShaderTypes:#() Menus:#()),
|
|
|
|
-- Mask-options control-panel is collapsed by default:
|
|
MaskDropdownActive = False,
|
|
MaskCtrlPanel,
|
|
|
|
-- Local aliases to hold button-functions:
|
|
TexmapBtnFunc, TexmapBtnPaintFunc, SetMaskBtnFunc,
|
|
|
|
-- Thumbnail-manager:
|
|
ToolName = #TerrainPainter,
|
|
Thumbs = (RSTA_ThumbsMgr.GetThumbsStruct ToolName),
|
|
|
|
dnTooltip = (dotNetObject "ToolTip"),
|
|
dnColour = (dotNetClass "System.Drawing.Color"),
|
|
SizeType_AutoSize = (dotNetClass "SizeType").AutoSize,
|
|
SizeType_Absolute = (dotNetClass "SizeType").Absolute,
|
|
SizeType_Percent = (dotNetClass "SizeType").Percent,
|
|
|
|
-- Suspend/ResumeRedraw:
|
|
-- Disable/Enable tool's window-redraw functionality:
|
|
WM_SETREDRAW=0xB,
|
|
fn SuspendRedraw =
|
|
(
|
|
Windows.Sendmessage ToolForm.Handle WM_SETREDRAW 0 0
|
|
),
|
|
fn ResumeRedraw =
|
|
(
|
|
Windows.Sendmessage ToolForm.Handle WM_SETREDRAW 1 0
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- isBtnChecked:
|
|
-- Returns 'True' if a button has been set to 'Flat' style:
|
|
------------------------------------------------------------------------------
|
|
fn isBtnChecked ThisBtn =
|
|
(
|
|
return (ThisBtn.FlatStyle == ThisBtn.FlatStyle.Flat)
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- SetBtnChecked:
|
|
-- Sets button style to make it look checked or not
|
|
------------------------------------------------------------------------------
|
|
fn SetBtnChecked ThisBtn Checked =
|
|
(
|
|
if Checked then
|
|
(
|
|
-- Don't allow button to autosize in this mode:
|
|
local BtnWidth = ThisBtn.Width
|
|
local BtnHeight = ThisBtn.Height
|
|
ThisBtn.AutoSize = False
|
|
ThisBtn.Width = BtnWidth
|
|
ThisBtn.Height = BtnHeight
|
|
|
|
-- These colours are only shown if button is set to 'Flat' style,
|
|
ThisBtn.BackColor = dnColour.Orange
|
|
ThisBtn.ForeColor = dnColour.Black
|
|
|
|
ThisBtn.FlatStyle = ThisBtn.FlatStyle.Flat
|
|
)
|
|
else
|
|
(
|
|
ThisBtn.FlatStyle = ThisBtn.FlatStyle.System
|
|
ThisBtn.AutoSize = True
|
|
)
|
|
|
|
ThisBtn.Refresh()
|
|
),
|
|
|
|
---------------------------------------------------------------------------------------
|
|
-- GetSelMatInfo:
|
|
-- Returns currently-selected terrain-material (or 'undefined' if none)
|
|
---------------------------------------------------------------------------------------
|
|
fn GetSelMatInfo UpdateData:False =
|
|
(
|
|
-- Ensure that material-faces are still up-to-date:
|
|
if UpdateData do
|
|
(
|
|
::gRsTerrainPalette.PopulateMaterialList()
|
|
)
|
|
|
|
if (TexmapPanel.Tag == undefined) then undefined else
|
|
(
|
|
TexmapPanel.Tag.Value.MatInfo
|
|
)
|
|
),
|
|
---------------------------------------------------------------------------------------
|
|
-- GetSelTexNum:
|
|
-- Returns currently-selected texmap-index (or '0' if none)
|
|
---------------------------------------------------------------------------------------
|
|
fn GetSelTexNum =
|
|
(
|
|
local TexNum = 0
|
|
|
|
if (TexmapPanel.Tag != undefined) do
|
|
(
|
|
TexNum = (TexmapPanel.Tag.Value.TexNum)
|
|
)
|
|
|
|
return TexNum
|
|
),
|
|
---------------------------------------------------------------------------------------
|
|
-- GetSelShaderTypeInfo:
|
|
-- Returns currently-selected shadertype-info (with material-list)
|
|
---------------------------------------------------------------------------------------
|
|
fn GetSelShaderTypeInfo =
|
|
(
|
|
local SelNum = (CboShaderType.SelectedIndex + 1)
|
|
|
|
if (SelNum == 0) then undefined else TerrainMatInfoList[SelNum]
|
|
),
|
|
---------------------------------------------------------------------------------------
|
|
-- GetSelShaderTypeDef:
|
|
-- Returns currently-active shadertype-definition (or 'undefined' if none)
|
|
---------------------------------------------------------------------------------------
|
|
fn GetSelShaderTypeDef =
|
|
(
|
|
local TypeDef = undefined
|
|
|
|
local SelTypeInfo = GetSelShaderTypeInfo()
|
|
|
|
if (SelTypeInfo != undefined) do
|
|
(
|
|
local MatInfo = SelTypeInfo.MatInfoList[1]
|
|
|
|
if (MatInfo != undefined) do
|
|
(
|
|
TypeDef = MatInfo.TypeDef
|
|
)
|
|
)
|
|
|
|
return TypeDef
|
|
),
|
|
---------------------------------------------------------------------------------------
|
|
-- GetSelShaderMatInfoList:
|
|
-- Returns material-info list for currently-active shadertype-definition
|
|
---------------------------------------------------------------------------------------
|
|
fn GetSelShaderMatInfoList =
|
|
(
|
|
local MatInfoList = #()
|
|
|
|
local SelTypeInfo = GetSelShaderTypeInfo()
|
|
|
|
if (SelTypeInfo != undefined) do
|
|
(
|
|
MatInfoList = SelTypeInfo.MatInfoList
|
|
)
|
|
|
|
return MatInfoList
|
|
),
|
|
---------------------------------------------------------------------------------------
|
|
-- GetTexmapsCount:
|
|
-- Returns maximum texturemap-slot count for shown materials:
|
|
---------------------------------------------------------------------------------------
|
|
fn GetTexmapsCount =
|
|
(
|
|
-- Get current shadertype's material-info list:
|
|
local MatInfoList = GetSelShaderMatInfoList()
|
|
|
|
-- Collect texcounts for materials
|
|
local TexCounts = for MatInfo in MatInfoList collect MatInfo.TexCount
|
|
|
|
-- Return highest texcount:
|
|
return (aMax TexCounts)
|
|
),
|
|
|
|
-- DoWeldCheck:
|
|
-- Check obj for compressed (welded) verts - these will go wrong when painted.
|
|
-- tracks objects/channels this has been done for this session, as we shouldn't have to repeat)
|
|
fn DoWeldCheck Obj Chans =
|
|
(
|
|
for Chan in Chans do
|
|
(
|
|
-- Build string from object-handle and specific channel-number:
|
|
local CheckString = ((Obj.Handle as String) + "|" + (Chan as String))
|
|
|
|
-- Only run check/fix welded verts if object's channel hasn't been checked already:
|
|
if (appendIfUnique DoneVertChecks CheckString) do
|
|
(
|
|
RsHasCompressedVertChan Obj.BaseObject Chan fix:True
|
|
)
|
|
)
|
|
|
|
return OK
|
|
),
|
|
|
|
---------------------------------------------------------------------------------------
|
|
-- AddGrpBox:
|
|
-- Function for adding Max-like dotnet group-boxes:
|
|
---------------------------------------------------------------------------------------
|
|
fn AddGrpBox AddToPanel Title:"" Size:1 PanelType: =
|
|
(
|
|
local GrpBox = dotNetObject "GroupBox"
|
|
GrpBox.FlatStyle = GrpBox.FlatStyle.System
|
|
GrpBox.Text = Title
|
|
GrpBox.Dock = GrpBox.Dock.Fill
|
|
GrpBox.AutoSize = True
|
|
GrpBox.Padding = (dotNetObject "Padding" 1)
|
|
|
|
-- Add groupbox-panel to parent:
|
|
AddToPanel.Controls.Add GrpBox
|
|
|
|
-- Add subpanel for holding controls:
|
|
local SubPanel = GrpBox
|
|
if (PanelType != unsupplied) do
|
|
(
|
|
SubPanel = dotnetobject PanelType
|
|
SubPanel.Width = 0
|
|
SubPanel.Height = 0
|
|
SubPanel.AutoSize = True
|
|
SubPanel.Dock = SubPanel.Dock.Fill
|
|
|
|
GrpBox.Controls.Add SubPanel
|
|
)
|
|
|
|
-- Return inner-panel that'll hold grouped controls:
|
|
return SubPanel
|
|
),
|
|
|
|
--------------------------------------------------------------
|
|
-- GetMaskColour:
|
|
-- Returns colour defined by mask-sliders
|
|
--------------------------------------------------------------
|
|
fn GetMaskColour TypeDef: =
|
|
(
|
|
if (TypeDef == unsupplied) do
|
|
(
|
|
TypeDef = GetSelShaderTypeDef()
|
|
)
|
|
|
|
-- Get mask-value from slider(s) if shown:
|
|
local MaskVals = for Item in
|
|
#(
|
|
(dataPair Slider:SldLookupMask Default:TypeDef.DefLookupMaskVal),
|
|
(dataPair Slider:SldTintMask Default:TypeDef.DefTintMaskVal),
|
|
(dataPair Slider:SldDisplaceMask Default:TypeDef.DefDisplaceMaskVal)
|
|
) collect
|
|
(
|
|
local MaskVal = undefined
|
|
local MaskSlider = Item.Slider
|
|
|
|
if (MaskSlider == undefined) then
|
|
(
|
|
MaskVal = Item.Default
|
|
)
|
|
else
|
|
(
|
|
MaskVal = MaskSlider.Value / (Float MaskSlider.Maximum)
|
|
)
|
|
|
|
MaskVal
|
|
)
|
|
|
|
local MaskColour
|
|
|
|
if (TypeDef.LookupMaskSubChan == undefined) then
|
|
(
|
|
-- Lookup-mask using full greyscale channel:
|
|
MaskColour = (White * MaskVals[1])
|
|
)
|
|
else
|
|
(
|
|
-- Build mask-colour from slider-values:
|
|
MaskColour = [0,0,0]
|
|
MaskColour[TypeDef.LookupMaskSubChan] = MaskVals[1] * 255
|
|
MaskColour[TypeDef.TintMaskSubChan] = MaskVals[2] * 255
|
|
MaskColour[TypeDef.DisplaceMaskSubChan] = MaskVals[3] * 255
|
|
MaskColour = (MaskColour as Color)
|
|
)
|
|
|
|
return MaskColour
|
|
),
|
|
|
|
-- Remove/Add callbacks:
|
|
fn RemoveCallbacks =
|
|
(
|
|
Callbacks.RemoveScripts id:#RsTerrainPaint
|
|
),
|
|
fn AddCallbacks =
|
|
(
|
|
-- Set up selection-change callback:
|
|
Callbacks.AddScript #SelectionSetChanged "gRsTerrainPalette.UpdateCtrls()" id:#RsTerrainPaint
|
|
),
|
|
|
|
--------------------------------------------------------------
|
|
-- PaintSelection:
|
|
-- Paints selected colour to selected subobjects
|
|
--------------------------------------------------------------
|
|
fn PaintSelection MaskColour: MaskSubChans: =
|
|
(
|
|
-- 'MaskSubChans' argument is only supplied by mask-edit buttons:
|
|
local JustMask = (MaskSubChans != unsupplied)
|
|
|
|
-- Set default mask-subchannels:
|
|
if (not JustMask) do (MaskSubChans = #{1,2,3})
|
|
|
|
-- Get selected-texmap index from panel-tag:
|
|
local TexNum = if JustMask then -1 else (GetSelTexNum())
|
|
|
|
-- Abort if no material-selection has been made:
|
|
if (TexNum == undefined) or (TexNum == 0) do return False
|
|
|
|
if not ((isValidNode TerrainObj) and (isEditPolyMesh TerrainObj)) do return False
|
|
|
|
local TypeDef = GetSelShaderTypeDef()
|
|
if (TypeDef == undefined) do return False
|
|
|
|
local TexClrList = TypeDef.LookupColours
|
|
local LookupChan = TypeDef.LookupClrChan
|
|
local MaskChan = TypeDef.MaskChan
|
|
|
|
-- Colour-edit definitions:
|
|
local EditDefs = #()
|
|
|
|
-- Does this shader use a lookup-texture mask-channel?
|
|
local HasMask = (MaskChan != undefined)
|
|
|
|
if HasMask do
|
|
(
|
|
-- Get 'MaskColour' rgb values from sliders/defaults:
|
|
if (not isKindOf MaskColour Color) do
|
|
(
|
|
MaskColour = GetMaskColour TypeDef:TypeDef
|
|
)
|
|
|
|
-- Add mask-edit to list:
|
|
local ModName = ("T-Mask [chan " + (MaskChan as string) + "]")
|
|
local MaskEdit = (RsVertClrsEditDef Chan:MaskChan Action:#Set InputVal:MaskColour ModName:ModName SubChans:MaskSubChans)
|
|
append EditDefs MaskEdit
|
|
)
|
|
|
|
-- Define colour-edit definition for lookup:
|
|
if (not JustMask) do
|
|
(
|
|
local ModName = ("T-Lookup [chan " + (LookupChan as string) + "]")
|
|
local LookupEdit = (RsVertClrsEditDef Chan:LookupChan Action:#Set InputVal:TexClrList[TexNum] ModName:ModName)
|
|
append EditDefs LookupEdit
|
|
)
|
|
|
|
-- We'll trigger multiple redraws for face-edits:
|
|
local DidFaces = False
|
|
|
|
case (GetSelectionLevel TerrainObj) of
|
|
(
|
|
#Object:
|
|
(
|
|
DidFaces = True
|
|
)
|
|
#face:
|
|
(
|
|
DidFaces = True
|
|
)
|
|
#vertex:
|
|
(
|
|
-- Vertex-editing will go wrong if channels have uvs used by multiple verts - fix if requried:
|
|
-- (once per channel per object per tool-session)
|
|
(
|
|
local CheckChans = #(LookupChan)
|
|
if HasMask do (append CheckChans MaskChan)
|
|
|
|
-- Check for compressed (welded) verts:
|
|
DoWeldCheck TerrainObj CheckChans
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Apply edits to selection:
|
|
-- (with selection-change callbacks disabled)
|
|
RemoveCallbacks()
|
|
RsApplyVertClrChanges EditDefs doCollapse:True
|
|
AddCallbacks()
|
|
|
|
return OK
|
|
),
|
|
|
|
--------------------------------------------------------------
|
|
-- Functions for dealing with VertexPaint modifier:
|
|
--------------------------------------------------------------
|
|
-- Sets state of control 'ChkVertPaint':
|
|
fn SetChkVertPaintState State =
|
|
(
|
|
SetBtnChecked ChkVertPaint State
|
|
ChkVertPaint.Text = if State then "Stop Vertex Paint" else "Start Vertex Paint"
|
|
|
|
-- Clear link to modifier if deactivating vpaint-mode:
|
|
if (not State) do
|
|
(
|
|
vPaintTool = undefined
|
|
)
|
|
),
|
|
fn SetVertPaintColour =
|
|
(
|
|
local SelNum = GetSelTexNum()
|
|
|
|
if (SelNum == 0) or (vPaintTool == undefined) do return False
|
|
|
|
local SelMatInfo = GetSelMatInfo()
|
|
if (SelMatInfo == undefined) do return False
|
|
|
|
local TexClrList = SelMatInfo.TypeDef.LookupColours
|
|
|
|
vPaintTool.PaintColor = TexClrList[SelNum]
|
|
vPaintTool.CurPaintMode = 1
|
|
|
|
-- Trigger toolkit-update:
|
|
vPaintTool.keepToolboxOpen = vPaintTool.keepToolboxOpen
|
|
),
|
|
fn SetupVertPaintMod =
|
|
(
|
|
-- Get currently-selected shadertype-definition:
|
|
local TypeDef = GetSelShaderTypeDef()
|
|
|
|
-- Abort if TypeDef is undefined or terrain-object is invalid:
|
|
if (TypeDef == undefined) or (not (isValidNode TerrainObj)) or (not (isEditPolyMesh TerrainObj)) do
|
|
(
|
|
-- Deactivate button:
|
|
SetChkVertPaintState False
|
|
return False
|
|
)
|
|
|
|
-- Get lookup-colour channel:
|
|
local LookupClrChan = TypeDef.LookupClrChan
|
|
|
|
-- Make sure that object doesn't have welded lookup-verts:
|
|
DoWeldCheck TerrainObj #(LookupClrChan)
|
|
|
|
-- Search for lookup-vertexpaint modifier:
|
|
local vPaintMod = undefined
|
|
for ThisMod in TerrainObj.Modifiers while (vPaintMod == undefined) do
|
|
(
|
|
-- Is this a vertexpaint modifier, set up to edit the lookup-channel?
|
|
if (isKindOf ThisMod VertexPaint) and (ThisMod.MapChannel == LookupClrChan) do
|
|
(
|
|
vPaintMod = ThisMod
|
|
)
|
|
)
|
|
|
|
-- Add modifier if one wasn't found:
|
|
if (vPaintMod == undefined) do
|
|
(
|
|
vPaintMod = VertexPaint MapChannel:LookupClrChan
|
|
AddModifier TerrainObj vPaintMod
|
|
)
|
|
|
|
-- Get link to vertexpaint-tool:
|
|
vPaintTool = VertexPaintTool()
|
|
|
|
-- Set vertexpaint-colour to currently-active lookup-colour, if any:
|
|
SetVertPaintColour()
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Functions for dealing with 'Select Channel' controls:
|
|
------------------------------------------------------------------------------
|
|
-- GetShowChanCtrls:
|
|
-- Get list of 'Show Channel' buttons:
|
|
------------------------------------------------------------------------------
|
|
fn GetShowChanCtrls =
|
|
(
|
|
for n = 0 to (ShowChansPanel.Controls.Count - 1) collect
|
|
(
|
|
ShowChansPanel.Controls.Item[n]
|
|
)
|
|
),
|
|
------------------------------------------------------------------------------
|
|
-- GetCurrShowChan:
|
|
-- Get name of objects' currently-shown terrain-channel:
|
|
------------------------------------------------------------------------------
|
|
fn GetShownChan =
|
|
(
|
|
local ChanNum = undefined
|
|
|
|
local SelObjs = for Obj in (GetCurrentSelection()) where (isEditPolyMesh Obj) collect Obj
|
|
|
|
for Obj in SelObjs do
|
|
(
|
|
local ObjChan = False
|
|
|
|
case of
|
|
(
|
|
(DisplayColor.Shaded == #Material):
|
|
(
|
|
if (not Obj.ShowVertexColors) do
|
|
(
|
|
ObjChan = -3
|
|
)
|
|
)
|
|
(not Obj.ShowVertexColors):()
|
|
(Obj.VertexColorType == #Alpha):
|
|
(
|
|
ObjChan = -2
|
|
)
|
|
(Obj.VertexColorType == #Color):
|
|
(
|
|
ObjChan = 0
|
|
)
|
|
(Obj.VertexColorType == #Map_Channel):
|
|
(
|
|
ObjChan = Obj.VertexColorMapChannel
|
|
)
|
|
)
|
|
|
|
case of
|
|
(
|
|
-- Stop looping objects if one returns undefined channel-number:
|
|
(ObjChan == undefined):(exit)
|
|
-- Keep first channel-number found:
|
|
(ChanNum == undefined):(ChanNum = ObjChan)
|
|
-- Clear ChanNum and stop looping if objects don't share channel-number
|
|
(ChanNum != ObjChan):
|
|
(
|
|
ChanNum = undefined
|
|
exit
|
|
)
|
|
)
|
|
)
|
|
|
|
return ChanNum
|
|
),
|
|
------------------------------------------------------------------------------
|
|
-- SetShowChanClicked:
|
|
-- Set matching channel-button to clicked, if applicable.
|
|
------------------------------------------------------------------------------
|
|
fn SetShowChanClicked ShownChan: =
|
|
(
|
|
-- Get name of currently-shown channel:
|
|
if (ShownChan == unsupplied) do
|
|
(
|
|
ShownChan = GetShownChan()
|
|
)
|
|
|
|
-- Uncheck all buttons, apart from one with matching name:
|
|
|
|
for ThisBtn in (GetShowChanCtrls()) do
|
|
(
|
|
SetBtnChecked ThisBtn (ThisBtn.Tag == ShownChan)
|
|
)
|
|
),
|
|
------------------------------------------------------------------------------
|
|
-- ShowChannel:
|
|
-- Show a particular vertex-colour channel on 'TerrainObj':
|
|
------------------------------------------------------------------------------
|
|
fn ShowChannel chan =
|
|
(
|
|
RsShowObjVertChannel chan
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- ev_SwapMenuItem_Clicked:
|
|
-- Used by texmap-swapper menu-items
|
|
-- Swaps two texmap-lookup colours for the current material:
|
|
------------------------------------------------------------------------------
|
|
fn ev_SwapMenuItem_Clicked Sender Args =
|
|
(
|
|
-- Get swap-options from control's tag:
|
|
local SwapOpts = Sender.Tag.Value
|
|
|
|
-- Get selected material-data, with updated face-list:
|
|
local TheTool = ::gRsTerrainPalette
|
|
local SelMatInfo = (TheTool.GetSelMatInfo UpdateData:True)
|
|
local SelTexNum = (TheTool.GetSelTexNum())
|
|
local SwapTexNum = (SwapOpts.SwapTexNum)
|
|
|
|
if (SelMatInfo == undefined) or (SelTexNum == 0) or (SelTexNum == SwapTexNum) do return False
|
|
|
|
-- Alter material/mesh:
|
|
SelMatInfo.SwapTexmaps SelTexNum SwapTexNum SwapMatSlots:(SwapOpts.SwapMatSlots) SwapLookups:(SwapOpts.SwapLookups)
|
|
|
|
-- Update UI buttons if required:
|
|
if (SwapOpts.SwapMatSlots) do
|
|
(
|
|
local SelMat = SelMatInfo.TerrainMat
|
|
|
|
-- Find material-panel whose tag-value's material matches selected material:
|
|
local MatPanel = undefined
|
|
for ThisPanel in TheTool.MatPanels while (MatPanel == undefined) do
|
|
(
|
|
local PanelMatInfo = ThisPanel.Tag.Value
|
|
|
|
if (PanelMatInfo.TerrainMat == SelMat) do
|
|
(
|
|
MatPanel = ThisPanel
|
|
)
|
|
)
|
|
|
|
-- Get the buttons for the swapped textures:
|
|
if (MatPanel != undefined) do
|
|
(
|
|
-- Get buttons for swap's two texmaps:
|
|
local Btns = for TexNum in #(SelTexNum, SwapTexNum) collect
|
|
(
|
|
-- Get button's highlight-colour panel:
|
|
local Ctrl = MatPanel.Controls.Item[TexNum - 1]
|
|
|
|
-- Get coloured-outline panel:
|
|
Ctrl = Ctrl.Controls.Item[0]
|
|
|
|
-- Collect button:
|
|
Ctrl.Controls.Item[0]
|
|
)
|
|
|
|
-- Swap button-images:
|
|
local BtnA = Btns[1]
|
|
local BtnB = Btns[2]
|
|
local ImgA = BtnA.BackgroundImage
|
|
BtnA.BackgroundImage = BtnB.BackgroundImage
|
|
BtnB.BackgroundImage = ImgA
|
|
)
|
|
)
|
|
),
|
|
|
|
----------------------------------------------------------------------------------
|
|
-- SelSubObjs:
|
|
-- Triggers subobject-selection functions with passed options
|
|
----------------------------------------------------------------------------------
|
|
fn SelSubObjs Opts =
|
|
(
|
|
local SubObjName = (Opts.SubObjName as Name)
|
|
|
|
local TheTool = ::gRsTerrainPalette
|
|
|
|
-- Get selected material-data, with updated face-list:
|
|
local SelMatInfo = (TheTool.GetSelMatInfo UpdateData:True)
|
|
local SelTexNum = (TheTool.GetSelTexNum())
|
|
|
|
if (SelMatInfo == undefined) do return False
|
|
|
|
local BaseObj = SelMatInfo.Obj.BaseObject
|
|
|
|
if not ((isKindOf BaseObj Editable_Poly) or (isKindOf BaseObj Editable_Mesh)) do return False
|
|
|
|
SetWaitCursor()
|
|
|
|
-- Get current subobject-selection, if it's going to be modified:
|
|
local SelItems = #{}
|
|
if (Opts.AddSel or Opts.RemSel) do
|
|
(
|
|
local SubObjLevel = RsGetSubObjLevelName()
|
|
|
|
case of
|
|
(
|
|
((SubObjName == #Verts) and (SubObjLevel == #Vertex)):
|
|
(
|
|
SelItems = if (isKindOf BaseObj Editable_Poly) then (PolyOp.GetVertSelection BaseObj) else (GetVertSelection BaseObj)
|
|
)
|
|
((SubObjName == #Faces) and (SubObjLevel == #Face)):
|
|
(
|
|
SelItems = if (isKindOf BaseObj Editable_Poly) then (PolyOp.GetFaceSelection BaseObj) else (GetFaceSelection BaseObj)
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Get verts/faces using selected texmap-index:
|
|
local GetSubObjsFunc = case SubObjName of
|
|
(
|
|
#Verts:(SelMatInfo.GetVertsUsingTexmap)
|
|
#Faces:(SelMatInfo.GetFacesUsingTexmap)
|
|
)
|
|
|
|
-- Selects all faces/verts if 'SelTexNum' is zero:
|
|
local NewSelItems = GetSubObjsFunc SelTexNum IgnoreBitmaps:Opts.IgnoreBitmaps Dominant:Opts.Dominant
|
|
|
|
-- Modify select-array:
|
|
if Opts.RemSel then
|
|
(
|
|
SelItems -= NewSelItems
|
|
)
|
|
else
|
|
(
|
|
SelItems += NewSelItems
|
|
)
|
|
|
|
SetCommandPanelTaskMode #Modify
|
|
ModPanel.SetCurrentObject BaseObj ui:True
|
|
|
|
-- Select those verts/faces:
|
|
case (classOf BaseObj) of
|
|
(
|
|
(Editable_Poly):
|
|
(
|
|
case SubObjName of
|
|
(
|
|
#Verts:
|
|
(
|
|
SubObjectLevel = 1
|
|
PolyOp.SetVertSelection BaseObj SelItems
|
|
)
|
|
#Faces:
|
|
(
|
|
SubObjectLevel = 4
|
|
PolyOp.SetFaceSelection BaseObj SelItems
|
|
)
|
|
)
|
|
)
|
|
(Editable_Mesh):
|
|
(
|
|
case SubObjName of
|
|
(
|
|
#Verts:
|
|
(
|
|
SubObjectLevel = 1
|
|
SetVertSelection BaseObj.Mesh SelItems
|
|
)
|
|
#Faces:
|
|
(
|
|
SubObjectLevel = 3
|
|
SetFaceSelection BaseObj.Mesh SelItems
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
CompleteRedraw()
|
|
SetArrowCursor()
|
|
|
|
return OK
|
|
),
|
|
|
|
----------------------------------------------------------------------------------
|
|
-- ev_SelSubObjsMenuItem_Clicked:
|
|
-- Triggers subobject-selection with options passed from control-tag
|
|
----------------------------------------------------------------------------------
|
|
fn ev_SelSubObjsMenuItem_Clicked Sender Args =
|
|
(
|
|
local SelOpts = (Sender.Tag.Value)
|
|
::gRsTerrainPalette.SelSubObjs SelOpts
|
|
),
|
|
|
|
-- Copies selected texmap's path to clipboard:
|
|
fn ev_CopyPathMenuItem_Clicked Sender Args =
|
|
(
|
|
local TheTool = ::gRsTerrainPalette
|
|
local SelMatInfo = (TheTool.GetSelMatInfo())
|
|
local SelTexNum = (TheTool.GetSelTexNum())
|
|
|
|
if (SelMatInfo == undefined) or (SelTexNum < 1) do return False
|
|
|
|
local ThisPath = SelMatInfo.DiffuseTexPaths[SelTexNum]
|
|
SetClipboardText (ThisPath as string)
|
|
),
|
|
|
|
fn ev_ApplyClrMenuItem_Clicked Sender Args =
|
|
(
|
|
local TheTool = Sender.Tag.Value
|
|
TheTool.PaintSelection()
|
|
),
|
|
|
|
-- Select faces used by a specific material:
|
|
fn ev_BtnMatSelFaces_Clicked Sender Args =
|
|
(
|
|
-- Set selected-material value from button's tag:
|
|
gRsTerrainPalette.SetSelLookupTex Sender.Tag
|
|
|
|
local SelOpts = (RsTerrPal_SelSubObjOpts SubObjName:"Faces")
|
|
::gRsTerrainPalette.SelSubObjs SelOpts
|
|
),
|
|
|
|
-- Apply selected material to selected faces:
|
|
fn ev_BtnApplyMat_Clicked Sender Args =
|
|
(
|
|
-- Get selected-material value from button's tag:
|
|
gRsTerrainPalette.SetSelLookupTex Sender.Tag
|
|
|
|
local SelMatInfo = Sender.Tag.Value.MatInfo
|
|
|
|
-- Get object and MatId for selected material:
|
|
local Obj = SelMatInfo.Obj
|
|
local SelMatId = SelMatInfo.MatId
|
|
|
|
local ObjOp = RsMeshPolyOp Obj
|
|
local ObjSetFaceMatID = RsSetFaceMatIDFunc Obj
|
|
|
|
-- Change face matids:
|
|
for FaceNum in (Obj.SelectedFaces as BitArray) do
|
|
(
|
|
ObjSetFaceMatID Obj FaceNum SelMatId
|
|
)
|
|
|
|
-- Update mesh in viewport:
|
|
case ObjOp of
|
|
(
|
|
polyOp:(polyOp.collapseDeadStructs Obj)
|
|
meshOp:(update Obj)
|
|
)
|
|
),
|
|
|
|
-- Open/Close mask-sliders panel:
|
|
fn ev_ChkMaskOptions_Clicked Sender Args =
|
|
(
|
|
local TheTool = Sender.Tag.Value
|
|
TheTool.MaskDropdownActive = (not TheTool.MaskDropdownActive)
|
|
|
|
-- Stop redraws while tweaking layout:
|
|
local FormHeight = TheTool.ToolForm.Height
|
|
TheTool.ToolForm.Height += 1000
|
|
|
|
local ScrollPanel = TheTool.ScrollPanel
|
|
ScrollPanel.Parent.SuspendLayout()
|
|
ScrollPanel.SuspendLayout()
|
|
|
|
-- Toggle checkbutton's appearance:
|
|
TheTool.SetBtnChecked Sender TheTool.MaskDropdownActive
|
|
|
|
-- Rebuild controls in masks-panel:
|
|
TheTool.UpdateMaskingControls()
|
|
|
|
-- Allow form to redraw:
|
|
TheTool.ToolForm.Height = FormHeight
|
|
ScrollPanel.ResumeLayout()
|
|
ScrollPanel.Parent.ResumeLayout()
|
|
),
|
|
|
|
-----------------------------------------------------------------------------------------
|
|
-- GetTexmapRCMenu:
|
|
-- Generates a rightclick-menu to be applied to texmap-id buttons:
|
|
-----------------------------------------------------------------------------------------
|
|
fn GetTexmapRCMenu TypeDef: =
|
|
(
|
|
if (TypeDef == unsupplied) do
|
|
(
|
|
TypeDef = GetSelShaderTypeDef()
|
|
)
|
|
|
|
-- Have we already generated a rightclick-menu for this shadertype?
|
|
local MenuNum = FindItem TexmapRCMenus.ShaderTypes TypeDef.Type
|
|
if (MenuNum != 0) do
|
|
(
|
|
-- Re-use pre-generated menu:
|
|
return TexmapRCMenus.Menus[MenuNum]
|
|
)
|
|
|
|
local NewMenu = (DotNetObject "ContextMenuStrip")
|
|
|
|
-- Add 'Copy texmap path' menuitem:
|
|
(
|
|
local CmdItem = DotNetObject "ToolStripMenuItem" "Copy Filename to Clipboard"
|
|
NewMenu.Items.Add CmdItem
|
|
|
|
CmdItem.Tag = (DotNetMxsValue This)
|
|
DotNet.SetLifetimeControl CmdItem #Dotnet
|
|
DotNet.AddEventHandler CmdItem "Click" ev_CopyPathMenuItem_Clicked
|
|
)
|
|
|
|
NewMenu.Items.Add (DotNetObject "ToolStripSeparator")
|
|
|
|
-- Add selection-menus to 'NewMenu':
|
|
(
|
|
-- Does this material use a lookup-bitmap?
|
|
local UseLookupMask = (TypeDef.MaskChan != undefined)
|
|
|
|
for SubObjName in #("Verts", "Faces") do
|
|
(
|
|
local SelSubObjText = ("Select " + SubObjName + ":")
|
|
local TypeMenu = (DotNetObject "ToolStripMenuItem" SelSubObjText)
|
|
NewMenu.Items.Add TypeMenu
|
|
DotNet.SetLifetimeControl TypeMenu #Dotnet
|
|
|
|
for DomItem in #(DataPair Text:"Using this material/texmap" Val:False, DataPair Text:"Where material/texmap is Dominant" Val:True) do
|
|
(
|
|
local DomMenu = (DotNetObject "ToolStripMenuItem" DomItem.Text)
|
|
TypeMenu.DropDownItems.Add DomMenu
|
|
DotNet.SetLifetimeControl DomMenu #Dotnet
|
|
|
|
-- Bitmap-Ignore menu is only used if shader actually uses a lookup-bitmap...
|
|
local IgBmpItems = #(DataPair Text:"Just Vertex Lookup" Val:True)
|
|
if UseLookupMask do
|
|
(
|
|
append IgBmpItems (DataPair Text:"Include Texture Lookup" Val:False)
|
|
)
|
|
|
|
local PrevMenu = DomMenu
|
|
for IgBmpItem in IgBmpItems do
|
|
(
|
|
-- Add Bitmap-Ignore menu, if valid:
|
|
if UseLookupMask do
|
|
(
|
|
PrevMenu = (DotNetObject "ToolStripMenuItem" IgBmpItem.Text)
|
|
DomMenu.DropDownItems.Add PrevMenu
|
|
DotNet.SetLifetimeControl PrevMenu #Dotnet
|
|
)
|
|
|
|
-- Add selection-commands:
|
|
local SelItems = for SelOptItem in
|
|
#(
|
|
DataPair Text:("Select " + SubObjName) Val:#Sel,
|
|
DataPair Text:"Add to selection" Val:#Add,
|
|
DataPair Text:"Remove from selection" Val:#Rem) do
|
|
(
|
|
-- Create menuitem:
|
|
local CmdItem = (DotNetObject "ToolStripMenuItem" SelOptItem.Text)
|
|
PrevMenu.DropDownItems.Add CmdItem
|
|
DotNet.SetLifetimeControl CmdItem #Dotnet
|
|
|
|
-- Store options to tag:
|
|
local SelOpts = (RsTerrPal_SelSubObjOpts SubObjName:SubObjName IgnoreBitmaps:IgBmpItem.Val Dominant:DomItem.Val)
|
|
case SelOptItem.Val of
|
|
(
|
|
#Add:(SelOpts.AddSel = True)
|
|
#Rem:(SelOpts.RemSel = True)
|
|
)
|
|
CmdItem.Tag = (DotNetMxsValue SelOpts)
|
|
|
|
DotNet.AddEventHandler CmdItem "Click" ev_SelSubObjsMenuItem_Clicked
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
NewMenu.Items.Add (DotNetObject "ToolStripSeparator")
|
|
|
|
-- Add texmap-swaps submenu:
|
|
(
|
|
local SubMenu = DotNetObject "ToolStripMenuItem" "Swap Texmap with:"
|
|
NewMenu.Items.Add SubMenu
|
|
|
|
local ClrNames = TypeDef.LookupColourNames
|
|
local TexCount = GetTexmapsCount()
|
|
|
|
-- Options for swap-event function:
|
|
struct SwapOptsDef (Text, SwapTexNum, SwapMatSlots = True, SwapLookups = True)
|
|
|
|
for SwapTexNum = 1 to TexCount do
|
|
(
|
|
local ClrName = ClrNames[SwapTexNum]
|
|
|
|
local MenuName = StringStream ""
|
|
format "%: (%)" SwapTexNum ClrName To:MenuName
|
|
|
|
-- Create menuitem:
|
|
local SwapItem = DotNetObject "ToolStripMenuItem" (MenuName as String)
|
|
SubMenu.DropDownItems.Add SwapItem
|
|
DotNet.SetLifetimeControl SwapItem #Dotnet
|
|
|
|
-- Add submenu-options:
|
|
for SwapOpts in
|
|
#(
|
|
(SwapOptsDef Text:"Swap texmaps/vertex-colours" SwapTexNum:SwapTexNum SwapMatSlots:True SwapLookups:True),
|
|
(SwapOptsDef Text:"Just swap texmap-slots" SwapTexNum:SwapTexNum SwapMatSlots:True SwapLookups:False),
|
|
(SwapOptsDef Text:"Just swap vertex-colours" SwapTexNum:SwapTexNum SwapMatSlots:False SwapLookups:True)
|
|
) do
|
|
(
|
|
local CmdItem = DotNetObject "ToolStripMenuItem" SwapOpts.Text
|
|
SwapItem.DropDownItems.Add CmdItem
|
|
|
|
CmdItem.Tag = (DotNetMxsValue SwapOpts)
|
|
DotNet.AddEventHandler CmdItem "Click" ev_SwapMenuItem_Clicked
|
|
DotNet.SetLifetimeControl CmdItem #Dotnet
|
|
)
|
|
)
|
|
)
|
|
|
|
NewMenu.Items.Add (DotNetObject "ToolStripSeparator")
|
|
|
|
-- Add 'Apply to Selection' menuitem:
|
|
(
|
|
local CmdItem = DotNetObject "ToolStripMenuItem" "Apply to Selection"
|
|
|
|
NewMenu.Items.Add CmdItem
|
|
DotNet.SetLifetimeControl NewMenu #Dotnet
|
|
|
|
CmdItem.Tag = (DotNetMxsValue This)
|
|
DotNet.SetLifetimeControl CmdItem #Dotnet
|
|
DotNet.AddEventHandler CmdItem "Click" ev_ApplyClrMenuItem_Clicked
|
|
)
|
|
|
|
-- Store menu for later retrieval:
|
|
append TexmapRCMenus.ShaderTypes TypeDef.Type
|
|
append TexmapRCMenus.Menus NewMenu
|
|
|
|
return NewMenu
|
|
),
|
|
|
|
-- Adds/updates controls in panel 'MaskCtrlPanel'
|
|
fn UpdateMaskingControls =
|
|
(
|
|
MaskCtrlPanel.Controls.Clear()
|
|
MaskCtrlPanel.RowCount = 0
|
|
|
|
-- Get TypeDef for currently-shown shadertype:
|
|
local TypeDef = GetSelShaderTypeDef()
|
|
|
|
-- Does this shader-type use a texturemap-mask?
|
|
local HasMaskChan = (TypeDef.MaskChan != undefined)
|
|
|
|
if (MaskDropdownActive) do
|
|
(
|
|
if HasMaskChan do
|
|
(
|
|
-- Collect items for deciding which mask-controls to show:
|
|
local MaskItems = #()
|
|
|
|
-- Collect mask-slider definitions:
|
|
(
|
|
struct MaskCtrlDef (CtrlName, Text, DefaultVal, ChanText, RangeText, SubChan)
|
|
|
|
local LookupMaskDef = (MaskCtrlDef CtrlName:#SldLookupMask SubChan:TypeDef.LookupMaskSubChan Text:"Lookup" DefaultVal:TypeDef.DefLookupMaskVal ChanText:TypeDef.LookupMaskChanText RangeText:TypeDef.LookupMaskRangeText)
|
|
append MaskItems LookupMaskDef
|
|
|
|
-- Add definition for tint-mask controls, if used:
|
|
if (TypeDef.TintMaskSubChan != undefined) do
|
|
(
|
|
append MaskItems (MaskCtrlDef CtrlName:#SldTintMask Text:"Tint" SubChan:TypeDef.TintMaskSubChan DefaultVal:TypeDef.DefTintMaskVal ChanText:TypeDef.TintMaskChanText RangeText:TypeDef.TintMaskRangeText)
|
|
)
|
|
|
|
-- Add definition for displacement-mask controls, if used:
|
|
if (TypeDef.DisplaceMaskSubChan != undefined) do
|
|
(
|
|
append MaskItems (MaskCtrlDef CtrlName:#SldDisplaceMask Text:"Displacement" SubChan:TypeDef.DisplaceMaskSubChan DefaultVal:TypeDef.DefDisplaceMaskVal ChanText:TypeDef.DisplaceMaskChanText RangeText:TypeDef.DisplaceMaskRangeText)
|
|
)
|
|
)
|
|
|
|
-- Set number of rows in hideable panel's table:
|
|
MaskCtrlPanel.RowCount = (MaskItems.Count + 1)
|
|
|
|
-- Add mask-opacity sliders:
|
|
for MaskDef in MaskItems do
|
|
(
|
|
-- Table to hold slider/labels:
|
|
(
|
|
local MaskLblText = (MaskDef.Text + " Mask: [" + MaskDef.ChanText + "]")
|
|
local MaskTable = AddGrpBox MaskCtrlPanel Title:MaskLblText PanelType:"TableLayoutPanel"
|
|
|
|
MaskTable.Parent.Margin = (dotNetObject "Padding" 0)
|
|
MaskTable.Padding = (dotNetObject "Padding" 0)
|
|
MaskTable.Dock = MaskTable.Dock.Fill
|
|
MaskTable.AutoSize = True
|
|
|
|
MaskTable.ColumnCount = 3
|
|
MaskTable.RowCount = 2
|
|
|
|
MaskTable.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_Absolute 115)
|
|
MaskTable.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_Percent 100)
|
|
MaskTable.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_Absolute 115)
|
|
MaskTable.RowStyles.Add (dotNetObject "RowStyle" SizeType_Absolute 25)
|
|
MaskTable.RowStyles.Add (dotNetObject "RowStyle" SizeType_Absolute 25)
|
|
|
|
-- Which sub-channel (rgb) is this mask on? (greyscale if undefined)
|
|
local maskSubChans = if (maskDef.subChan == Undefined) then #{1,2,3} else #{maskDef.subChan}
|
|
|
|
-- Add 0%/100% buttons:
|
|
for Item in #(DataPair Text:("[0% - " + MaskDef.RangeText.Min + "]") ColIdx:0, DataPair Text:("[100% - " + MaskDef.RangeText.Max + "]") ColIdx:2) do
|
|
(
|
|
local NewBtn = DotNetObject "Button"
|
|
NewBtn.Text = Item.Text
|
|
NewBtn.Tag = (DotNetMxsValue maskSubChans)
|
|
|
|
NewBtn.FlatStyle = NewBtn.FlatStyle.System
|
|
NewBtn.Width = 110
|
|
dnTooltip.SetToolTip NewBtn "Set this mask-channel value for selected subobjects"
|
|
|
|
MaskTable.Controls.Add NewBtn Item.ColIdx 0
|
|
dotNet.addEventHandler NewBtn "MouseUp" SetMaskBtnFunc
|
|
dotNet.setLifetimeControl NewBtn #dotnet
|
|
)
|
|
|
|
-- Mask-value slider:
|
|
(
|
|
local MaskSlider = (dotNetObject "TrackBar")
|
|
|
|
MaskSlider.Margin = (dotNetObject "Padding" 0)
|
|
MaskSlider.Padding = (dotNetObject "Padding" 0)
|
|
MaskSlider.Dock = MaskSlider.Dock.Fill
|
|
MaskSlider.Height -= 12
|
|
|
|
MaskSlider.Minimum = 0
|
|
MaskSlider.Maximum = 4
|
|
MaskSlider.Value = (MaskSlider.Maximum * MaskDef.DefaultVal)
|
|
MaskSlider.TickFrequency = 1
|
|
MaskTable.Controls.Add MaskSlider 1 0
|
|
|
|
local ToolText = ("Set proportion of " + MaskDef.Text + " that comes from vertex-colours\n(when texmap-buttons are clicked)\n\nThis masks out material's '" + MaskDef.Text + "' texture.")
|
|
dnTooltip.SetToolTip MaskTable ToolText
|
|
|
|
-- Store slider value to SldLookupMask or SldTintMask:
|
|
SetProperty This MaskDef.CtrlName MaskSlider
|
|
)
|
|
|
|
-- Add set-from-slider button:
|
|
(
|
|
local NewBtn = DotNetObject "Button"
|
|
NewBtn.Text = ("^ Apply slider value ^")
|
|
NewBtn.Tag = (DotNetMxsValue maskSubChans)
|
|
|
|
NewBtn.FlatStyle = NewBtn.FlatStyle.System
|
|
NewBtn.AutoSize = True
|
|
NewBtn.Dock = NewBtn.Dock.Fill
|
|
NewBtn.Margin = (dotNetObject "Padding" 0 3 0 6)
|
|
dnTooltip.SetToolTip NewBtn "Set slider's mask-channel value for selected subobjects"
|
|
|
|
MaskTable.Controls.Add NewBtn 1 1
|
|
dotNet.addEventHandler NewBtn "MouseUp" SetMaskBtnFunc
|
|
dotNet.setLifetimeControl NewBtn #dotnet
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Add all-subchannels mask-edit button: (centred)
|
|
(
|
|
local BtnTable = AddGrpBox MaskCtrlPanel PanelType:"TableLayoutPanel"
|
|
|
|
BtnTable.Parent.Margin = (dotNetObject "Padding" 0)
|
|
BtnTable.Padding = (dotNetObject "Padding" 0)
|
|
BtnTable.Dock = BtnTable.Dock.Fill
|
|
BtnTable.AutoSize = True
|
|
BtnTable.ColumnCount = 3
|
|
|
|
BtnTable.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_Absolute 115)
|
|
BtnTable.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_Percent 100)
|
|
BtnTable.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_Absolute 115)
|
|
BtnTable.RowStyles.Add (dotNetObject "RowStyle" SizeType_Absolute 25)
|
|
|
|
local NewBtn = DotNetObject "Button"
|
|
NewBtn.Text = "^ Apply all slider values ^"
|
|
NewBtn.Tag = DotNetMxsValue #{1,2,3}
|
|
NewBtn.FlatStyle = NewBtn.FlatStyle.System
|
|
NewBtn.Dock = NewBtn.Dock.Fill
|
|
NewBtn.Margin = (dotNetObject "Padding" 0 0 0 6)
|
|
dnTooltip.SetToolTip NewBtn "Applies mask-slider values to selected subobjects' mask-channel\n(doesn't touch the Lookup channel)"
|
|
|
|
BtnTable.Controls.Add NewBtn 1 0
|
|
dotNet.addEventHandler NewBtn "MouseUp" SetMaskBtnFunc
|
|
dotNet.setLifetimeControl NewBtn #dotnet
|
|
)
|
|
)
|
|
)
|
|
),
|
|
|
|
--------------------------------------------------------------
|
|
-- Update texmap-button selection:
|
|
--------------------------------------------------------------
|
|
fn SetSelLookupTex SelTexInfoVal =
|
|
(
|
|
-- Store material/texmap-index info:
|
|
TexmapPanel.Tag = SelTexInfoVal
|
|
|
|
if (SelTexInfoVal == undefined) do return OK
|
|
|
|
-- Extract selected-material/texmap info from tag-data:
|
|
local SelTexInfo = SelTexInfoVal.Value
|
|
local MatInfo = SelTexInfo.MatInfo
|
|
local SelNum = SelTexInfo.TexNum
|
|
|
|
-- These colours are safe to use with this colour-index:
|
|
local SafeBlends = undefined
|
|
if (SelNum != 0) and (MatInfo != undefined) do
|
|
(
|
|
SafeBlends = MatInfo.TypeDef.LookupSafeCombos[SelNum]
|
|
)
|
|
|
|
if (SelNum != 0) do
|
|
(
|
|
local FormBackClr = TexmapPanel.BackColor
|
|
local SelClr = FormBackClr.Yellow
|
|
|
|
-- Update texmap-selectedness colours:
|
|
for TexmapsPanel in MatPanels do
|
|
(
|
|
-- Get matinfo from this panel's tag-value:
|
|
local PanelMatInfo = TexmapsPanel.Tag.Value
|
|
|
|
-- Does this panel's matinfo match the newly-selected one?
|
|
local isSelMat = (PanelMatInfo == SelTexInfo.MatInfo)
|
|
|
|
for n = 1 to TexmapsPanel.Controls.Count do
|
|
(
|
|
-- Highlight texmaps if they match selected MatInfo/TexNum:
|
|
local ThisClr = if (isSelMat) and (n == SelNum) then SelClr else FormBackClr
|
|
local HiliteBox = TexmapsPanel.Controls.Item[n - 1]
|
|
HiliteBox.BackColor = ThisClr
|
|
|
|
if (SafeBlends != undefined) do
|
|
(
|
|
local ClrBtn = HiliteBox.Controls.Item[0].Controls.Item[0]
|
|
ClrBtn.Text = if SafeBlends[n] then "Safe" else "Artifact"
|
|
)
|
|
)
|
|
|
|
-- Make sure yellow bits aren't left behind:
|
|
TexmapsPanel.Refresh()
|
|
)
|
|
)
|
|
|
|
return OK
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- AddMatCmdPanel:
|
|
-- Add select/apply buttons for a given MatInfo:
|
|
------------------------------------------------------------------------------
|
|
fn AddMatCmdPanel AddToPanel ThisMatInfo =
|
|
(
|
|
local BtnWidth = Thumbs.ThumbSize
|
|
local MatCmdPanelHeight = (BtnWidth + 3)
|
|
local CmdBtnSize = [90,18]
|
|
|
|
local MatBtnsPanel = (AddGrpBox AddToPanel PanelType:"TableLayoutPanel")
|
|
AddToPanel.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_AutoSize)
|
|
|
|
local MatBtnsOutPanel = MatBtnsPanel.Parent--.Parent
|
|
MatBtnsOutPanel.Dock = MatBtnsOutPanel.Dock.None
|
|
|
|
MatBtnsPanel.Margin = (dotNetObject "Padding" 2 2 2 2)
|
|
|
|
struct CtrlDef (Text, Tooltip, Func, ifHasMat = False)
|
|
for Item in
|
|
#(
|
|
CtrlDef Text:"Select Faces" Tooltip:"Select faces using this material" Func:ev_BtnMatSelFaces_Clicked,
|
|
CtrlDef Text:"Apply Material" Tooltip:"Apply this material to selected faces" Func:ev_BtnApplyMat_Clicked ifHasMat:True
|
|
)
|
|
do
|
|
(
|
|
if (not Item.ifHasMat) or (ThisMatInfo.TerrainMat != undefined) do
|
|
(
|
|
local NewBtn = DotNetObject "Button"
|
|
NewBtn.Text = Item.Text
|
|
NewBtn.FlatStyle = NewBtn.FlatStyle.System
|
|
NewBtn.Width = CmdBtnSize.X
|
|
NewBtn.Height = CmdBtnSize.Y
|
|
NewBtn.Margin = (dotNetObject "Padding" 4 0 4 6)
|
|
|
|
-- Tag button with material-info:
|
|
NewBtn.Tag = (DotNetMxsValue (DataPair MatInfo:ThisMatInfo TexNum:0))
|
|
|
|
dnTooltip.SetToolTip NewBtn Item.Tooltip
|
|
|
|
MatBtnsPanel.Controls.Add NewBtn
|
|
dotNet.addEventHandler NewBtn "MouseUp" Item.Func
|
|
dotNet.setLifetimeControl NewBtn #dotnet
|
|
)
|
|
)
|
|
|
|
return MatBtnsOutPanel
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- UpdateTexmapCtrls:
|
|
-- Set up controls in 'TexmapPanel'
|
|
------------------------------------------------------------------------------
|
|
fn UpdateTexmapCtrls =
|
|
(
|
|
local TimeStart = TimeStamp()
|
|
SetWaitCursor()
|
|
PushPrompt "Redrawing Controls..."
|
|
|
|
SuspendRedraw()
|
|
ScrollPanel.SuspendLayout()
|
|
|
|
-- Reset groupbox-label:
|
|
TexmapPanel.Parent.Text = "Texturemaps:"
|
|
|
|
-- Clear existing button-panels:
|
|
(
|
|
for TexPanel in MatPanels do
|
|
(
|
|
TexPanel.Controls.Clear()
|
|
)
|
|
MatPanels.Count = 0
|
|
)
|
|
|
|
-- Clear panel:
|
|
TexmapPanel.Controls.Clear()
|
|
|
|
SldLookupMask = undefined
|
|
SldTintMask = undefined
|
|
SldDisplaceMask = undefined
|
|
|
|
-- Tag-value is used to store active material/colour-index - clear selection:
|
|
TexmapPanel.Tag = undefined
|
|
|
|
-- Get shadertype:
|
|
local TypeDef = GetSelShaderTypeDef()
|
|
local HelperText = undefined
|
|
|
|
-- Add per-material panels:
|
|
if (TypeDef != undefined) do
|
|
(
|
|
-- Get shadertype's material-info list:
|
|
local MatInfoList = GetSelShaderMatInfoList()
|
|
|
|
-- Add shader-name to groupbox-label:
|
|
TexmapPanel.Parent.Text += (" [" + TypeDef.Pattern + "]")
|
|
|
|
-- Does this shader-type use a texturemap-mask?
|
|
local HasMaskChan = (TypeDef.MaskChan != undefined)
|
|
|
|
-- This shadertype's lookup-colours:
|
|
local LookupClrs = TypeDef.LookupColours
|
|
|
|
local BtnWidth = Thumbs.ThumbSize
|
|
local ScrollPanelHeight = 270
|
|
local ScrollPanelWidth = 10 + (BtnWidth * 4)
|
|
|
|
-- Generate/get rightclick-menu to apply to texmap-buttons...
|
|
local TexMapRCmenu = (GetTexmapRCMenu TypeDef:TypeDef)
|
|
|
|
-- Add groupbox to surround material-panels:
|
|
local MatsOuterPanel = (AddGrpBox TexmapPanel PanelType:"TableLayoutPanel")
|
|
|
|
-- Collect list of texmap-panels per material:
|
|
MatPanels = for ThisMatInfo in MatInfoList collect
|
|
(
|
|
-- Add groupbox-panel to hold texmap-thumbnails:
|
|
local MatPanel = AddGrpBox MatsOuterPanel Title:(ThisMatInfo.GetNameString()) PanelType:"TableLayoutPanel"
|
|
MatsOuterPanel.RowStyles.Add (dotNetObject "RowStyle" SizeType_AutoSize)
|
|
MatPanel.Tag = (DotNetMxsValue ThisMatInfo)
|
|
|
|
-- Add columns for texmap-buttons, and material-buttons panel:
|
|
local TexCount = ThisMatInfo.TexCount
|
|
MatPanel.ColumnCount = (TexCount + 1)
|
|
|
|
-- Add per-texmap panels - background-colour will be changed if texmap is selected:
|
|
for ClrNum = 1 to TexCount do
|
|
(
|
|
-- Add sub-panel to hold colour's controls:
|
|
local TexHilitePanel = DotNetObject "FlowLayoutPanel"
|
|
TexHilitePanel.AutoSize = True
|
|
TexHilitePanel.Margin = (dotNetObject "Padding" 0 0 2 0)
|
|
TexHilitePanel.Padding = (dotNetObject "Padding" 2 2 2 2)
|
|
|
|
-- Tag panel with material-info and texmap-index:
|
|
TexHilitePanel.Tag = DotNetMxsValue (dataPair MatInfo:ThisMatInfo TexNum:ClrNum)
|
|
|
|
MatPanel.Controls.Add TexHilitePanel
|
|
MatPanel.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_Absolute (BtnWidth + 12))
|
|
|
|
local TexPath = ThisMatInfo.DiffuseTexPaths[ClrNum]
|
|
|
|
-- Get colour from list, and make colour for overlaid text:
|
|
local LookupClr = LookupClrs[ClrNum]
|
|
|
|
-- Add Texture-button:
|
|
(
|
|
-- Add lookup-colour outline:
|
|
local ClrPanel = DotNetObject "FlowLayoutPanel"
|
|
TexHilitePanel.Controls.Add ClrPanel
|
|
ClrPanel.AutoSize = True
|
|
ClrPanel.Margin = (dotNetObject "Padding" 0 0 2 0)
|
|
ClrPanel.Padding = (dotNetObject "Padding" 2 2 2 2)
|
|
|
|
-- Set button-background to lookup-colour:
|
|
ClrPanel.BackColor = dnColour.FromArgb LookupClr.r LookupClr.g LookupClr.b
|
|
|
|
local TexBtn = DotNetObject "Button"
|
|
TexBtn.FlatStyle = TexBtn.FlatStyle.Flat
|
|
TexBtn.Margin = (dotNetObject "Padding" 0)
|
|
TexBtn.Padding = (dotNetObject "Padding" 3 3 3 3)
|
|
--TexBtn.ForeColor = TexBtn.ForeColor.Yellow
|
|
|
|
-- Tag button with material-info and texmap-index:
|
|
TexBtn.Tag = TexHilitePanel.Tag
|
|
|
|
-- Add rightclick-menu:
|
|
if (TexMapRCmenu != undefined) do
|
|
(
|
|
TexBtn.ContextMenuStrip = TexMapRCmenu
|
|
)
|
|
|
|
TexBtn.Width = BtnWidth
|
|
TexBtn.Height = TexBtn.Width
|
|
TexBtn.BackColor = ClrPanel.BackColor
|
|
|
|
ClrPanel.Controls.Add TexBtn
|
|
dotNet.addEventHandler TexBtn "MouseUp" TexmapBtnFunc -- Click-event
|
|
dotNet.addEventHandler TexBtn "Paint" TexmapBtnPaintFunc -- Paint-event triggers thumbnail-loader thread
|
|
dotNet.setLifetimeControl TexBtn #DotNet
|
|
|
|
local TooltipText = "Click to apply lookup-colour"
|
|
if (TexPath != undefined) and (TexPath != "") do
|
|
(
|
|
TooltipText += (":\n" + TexPath)
|
|
)
|
|
|
|
-- Show tooltip on texture-button:
|
|
dnTooltip.SetToolTip TexBtn TooltipText
|
|
)
|
|
|
|
-- Collect texmap's highlighter-panel:
|
|
TexHilitePanel
|
|
)
|
|
|
|
-- Add select/apply buttons for a given MatInfo:
|
|
(
|
|
AddMatCmdPanel MatPanel ThisMatInfo
|
|
)
|
|
|
|
-- Collect texmaps-panel:
|
|
MatPanel
|
|
)
|
|
|
|
-- Set up materials-list panel for scrolling, now its contents have been added:
|
|
(
|
|
MatsOuterPanel.AutoScroll = True
|
|
MatsOuterPanel.MaximumSize = (DotNetObject "System.Drawing.Size" 0 ScrollPanelHeight)
|
|
)
|
|
|
|
-- Add mask-controls panel, and its toggle-button::
|
|
(
|
|
-- Set up toggle-button:
|
|
local ToggleBtn = (dotNetObject "Button")
|
|
ToggleBtn.Text = "Masking Options"
|
|
ToggleBtn.AutoSize = True
|
|
ToggleBtn.Location.X += 10
|
|
|
|
-- Tag button with this struct:
|
|
ToggleBtn.Tag = (dotNetMxsValue This)
|
|
|
|
-- Sets button's flatstyle:
|
|
SetBtnChecked ToggleBtn MaskDropdownActive
|
|
|
|
-- Create empty subgroup-box, with button instead of label:
|
|
local MaskBoxPanel = AddGrpBox TexmapPanel
|
|
MaskBoxPanel.Controls.Add ToggleBtn
|
|
|
|
dnTooltip.SetToolTip ToggleBtn "Show/hide extra options for lookup/tint masking"
|
|
dotNet.addEventHandler ToggleBtn "MouseUp" ev_ChkMaskOptions_Clicked
|
|
dotNet.setLifetimeControl ToggleBtn #dotnet
|
|
|
|
MaskCtrlPanel = dotNetObject "TableLayoutPanel"
|
|
MaskCtrlPanel.AutoSize = True
|
|
MaskCtrlPanel.Dock = MaskCtrlPanel.Dock.Fill
|
|
MaskCtrlPanel.Padding = (dotNetObject "Padding" 3 16 3 3)
|
|
MaskBoxPanel.Controls.Add MaskCtrlPanel
|
|
|
|
UpdateMaskingControls()
|
|
)
|
|
|
|
-- Generate text for help-label:
|
|
(
|
|
HelperText = StringStream ""
|
|
format "Click textures to set Lookup" To:HelperText
|
|
if HasMaskChan do
|
|
(
|
|
format "/Mask" To:HelperText
|
|
)
|
|
format "-channel colour%.\n" (if HasMaskChan then "s" else "") To:HelperText
|
|
format "Rightclick textures for more commands." To:HelperText
|
|
HelperText = (HelperText as String)
|
|
)
|
|
)
|
|
|
|
-- Add extra-info label:
|
|
(
|
|
local SelObjs = GetCurrentSelection()
|
|
|
|
-- Choose appropriate label-text:
|
|
local Msg = case of
|
|
(
|
|
(HelperText != undefined):(HelperText)
|
|
(SelObjs.Count == 0):("NO OBJECT SELECTED")
|
|
(SelObjs.Count != 1):("Please select only one object")
|
|
Default:"Object doesn't use any valid terrain-shaders."
|
|
)
|
|
|
|
local LblExtraInfo = dotNetObject "Label"
|
|
TexmapPanel.Controls.Add LblExtraInfo
|
|
LblExtraInfo.Margin = (dotNetObject "Padding" 6 6 6 6)
|
|
LblExtraInfo.AutoSize = True
|
|
LblExtraInfo.Text = Msg
|
|
)
|
|
|
|
-- Turn dialog's redraw back on:
|
|
ScrollPanel.ResumeLayout()
|
|
ResumeRedraw()
|
|
ScrollPanel.Refresh()
|
|
|
|
PopPrompt()
|
|
SetArrowCursor()
|
|
|
|
--format "Took % seconds to redraw (%)\n" ((TimeStamp() - TimeStart) / 1000.0) (Val as string)
|
|
|
|
return OK
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- SelListMat:
|
|
-- Select combobox-item for material with matching matid :
|
|
------------------------------------------------------------------------------
|
|
fn SelListMat MatId =
|
|
(
|
|
-- Skip if no matid was passed in:
|
|
if (MatId == 0) do return False
|
|
|
|
local SelNum = 0
|
|
for n = 1 to TerrainMatIds.Count while (SelNum == 0) do
|
|
(
|
|
if (findItem TerrainMatIds[n] MatId != 0) do
|
|
(
|
|
SelNum = n
|
|
)
|
|
)
|
|
|
|
-- Skip if no terrain-material had this matid:
|
|
if (SelNum == 0) do return False
|
|
|
|
-- Set combobox to show that list-item, and update texmap buttons:
|
|
CboShaderType.SelectedIndex = (SelNum - 1)
|
|
UpdateTexmapCtrls()
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- PopulateMaterialList:
|
|
-- Update terrain-materials list:
|
|
------------------------------------------------------------------------------
|
|
fn PopulateMaterialList =
|
|
(
|
|
SetWaitCursor()
|
|
|
|
-- Get the material for the previously-selected item:
|
|
-- (we're going to re-select this, if it's still in the list later)
|
|
local SelMatInfo = GetSelMatInfo()
|
|
local SelTexNum = GetSelTexNum()
|
|
local PrevSelMat = undefined
|
|
if (SelMatInfo != undefined) do
|
|
(
|
|
PrevSelMat = SelMatInfo.TerrainMat
|
|
)
|
|
SelMatInfo = undefined
|
|
|
|
local NewSelInfo = undefined
|
|
|
|
-- Get data on terrain-object's compatible terrain-materials:
|
|
local AllTerrainMatInfoList = gRsTerrainHelpers.GetObjTerrainFaceData TerrainObj
|
|
|
|
-- Collect materials by terrainshader-type: (i.e. the name-pattern used to distinguish between them)
|
|
TerrainMatInfoList = #()
|
|
local ShaderTypes = #()
|
|
for MatInfo in AllTerrainMatInfoList do
|
|
(
|
|
local ShaderType = MatInfo.TypeDef.Pattern
|
|
local TypeNum = FindItem ShaderTypes ShaderType
|
|
|
|
if (TypeNum == 0) do
|
|
(
|
|
append ShaderTypes ShaderType
|
|
append TerrainMatInfoList (dataPair ShaderType:ShaderType MatInfoList:#())
|
|
TypeNum = ShaderTypes.Count
|
|
)
|
|
|
|
append TerrainMatInfoList[TypeNum].MatInfoList MatInfo
|
|
)
|
|
|
|
-- Sort shadertype-items by name:
|
|
fn TypeSorter v1 v2 = (striCmp v1.ShaderType v2.ShaderType)
|
|
qsort TerrainMatInfoList TypeSorter
|
|
|
|
-- Collect MatId lookup-lists:
|
|
TerrainMatIds = for Item in TerrainMatInfoList collect
|
|
(
|
|
for MatInfo in Item.MatInfoList collect MatInfo.MatId
|
|
)
|
|
|
|
-- Set combobox-items to Material Ids/Names:
|
|
CboShaderType.Items.Clear()
|
|
|
|
if (TerrainMatInfoList.Count != 0) do
|
|
(
|
|
-- Set first selection-index by default:
|
|
local SelIdx = 0
|
|
|
|
for n = 1 to TerrainMatInfoList.Count do
|
|
(
|
|
local ShaderTypeItem = TerrainMatInfoList[n]
|
|
|
|
local ItemText = StringStream ""
|
|
format "% (% materials)" ShaderTypeItem.ShaderType ShaderTypeItem.MatInfoList.Count To:ItemText
|
|
|
|
local ItemIdx = CboShaderType.Items.Add (ItemText as String)
|
|
CboShaderType.Items.Item[ItemIdx]
|
|
|
|
-- We'll want to select this item if it includes the previously-selected texmap's material:
|
|
for MatItem in ShaderTypeItem.MatInfoList do
|
|
(
|
|
if (MatItem.TerrainMat == PrevSelMat) do
|
|
(
|
|
NewSelInfo = MatItem
|
|
SelIdx = (n - 1)
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Set combobox-selection:
|
|
CboShaderType.SelectedIndex = SelIdx
|
|
|
|
-- Set selection-info on main panel's tag to equivalent of what it was before:
|
|
if (NewSelInfo != undefined) do
|
|
(
|
|
NewSelInfo = DotNetMxsValue (DataPair MatInfo:NewSelInfo TexNum:SelTexNum)
|
|
)
|
|
TexmapPanel.Tag = NewSelInfo
|
|
)
|
|
|
|
SetArrowCursor()
|
|
|
|
return OK
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- UpdateCtrls:
|
|
-- Update controls to match current selection:
|
|
------------------------------------------------------------------------------
|
|
fn UpdateCtrls =
|
|
(
|
|
local SelObjs = GetCurrentSelection()
|
|
|
|
-- Set 'TerrainObj' value if selection is valid:
|
|
TerrainObj = if (SelObjs.Count == 1) and (isProperty SelObjs[1] #mesh) then SelObjs[1] else undefined
|
|
|
|
local HasObj = (TerrainObj != undefined)
|
|
|
|
-- Set enabledness of controls in panels that need a valid object to work:
|
|
for ThisPanel in ObjEditPanels do
|
|
(
|
|
local CtrlList = ThisPanel.Controls
|
|
|
|
for n = 0 to (CtrlList.Count - 1) do
|
|
(
|
|
CtrlList.Item[n].Enabled = HasObj
|
|
)
|
|
)
|
|
|
|
SetShowChanClicked()
|
|
PopulateMaterialList()
|
|
|
|
-- Enable material-picker if object uses multiple terrain-shaders:
|
|
ChkPickMat.Enabled = (HasObj and (TerrainMatInfoList.Count > 1))
|
|
|
|
-- Update texmap-buttons to match selected terrain-material:
|
|
UpdateTexmapCtrls()
|
|
|
|
return true
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- TexClick:
|
|
-- Called when a texmap-button is left-clicked:
|
|
------------------------------------------------------------------------------
|
|
fn TexClick =
|
|
(
|
|
if (isBtnChecked ChkVertPaint) then
|
|
(
|
|
SetVertPaintColour()
|
|
)
|
|
else
|
|
(
|
|
PaintSelection()
|
|
)
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- UI EVENTS:
|
|
------------------------------------------------------------------------------
|
|
|
|
-- 'Vertex Colour Toolkit' button clicked:
|
|
fn ev_BtnVertColTools_Clicked Sender Args =
|
|
(
|
|
filein (::RsConfigGetWildwestDir() + "Script/3dsMax/Maps/Materials/vertexColour_ui.ms")
|
|
),
|
|
|
|
-- 'Terrain Shader Editor' button clicked:
|
|
fn ev_BtnTerrShadEdit_Clicked Sender Args =
|
|
(
|
|
filein (::RsConfigGetWildwestDir() + "Script/3dsMax/Maps/Materials/terrain_ShaderEditor.ms")
|
|
),
|
|
|
|
-- 'MapId Projector' button clicked:
|
|
fn ev_BtnMapIdProj_Clicked Sender Args =
|
|
(
|
|
fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Maps/Materials/RSTA_mapIDProjector.ms")
|
|
),
|
|
|
|
-- 'Init Terrain Chans' clicked:
|
|
fn ev_BtnInitChannels_Clicked Sender Args =
|
|
(
|
|
undo "Init Terrain Channels" on
|
|
(
|
|
for Obj in (GetCurrentSelection()) where (isEditPolyMesh Obj) do
|
|
(
|
|
-- Collapse and convert:
|
|
ConvertToPoly Obj
|
|
|
|
-- Make sure channels are turned on - if not, set to black:
|
|
for Chan in #(5, 9) where not (PolyOp.GetMapSupport Obj Chan) do
|
|
(
|
|
PolyOp.SetFaceColor Obj Chan #all black
|
|
)
|
|
)
|
|
)
|
|
),
|
|
|
|
-- 'Remove Non-Terrain Chans' clicked:
|
|
fn ev_BtnDelChannels_Clicked Sender Args =
|
|
(
|
|
local TerrainChans = #(-2, 0, 1, 2, 5, 9, 13)
|
|
|
|
local HasNonTerrainMats = False
|
|
local SelObjs = for Obj in (GetCurrentSelection()) where (isEditPolyMesh Obj) collect Obj
|
|
|
|
if (SelObjs.Count == 0) do return False
|
|
|
|
-- Check for non-terrain materials on object-faces:
|
|
for Obj in SelObjs while (not HasNonTerrainMats) do
|
|
(
|
|
-- Get descriptors for materials used on object:
|
|
local ObjMatInfos = gRsMaterials.GetObjMatData Obj FlatList:True
|
|
|
|
-- Do any of these materials use non-terrain shaders?
|
|
for MatInfo in ObjMatInfos while (not HasNonTerrainMats) do
|
|
(
|
|
HasNonTerrainMats = not (MatchPattern MatInfo.ShaderName Pattern:"*terrain*")
|
|
)
|
|
)
|
|
|
|
if HasNonTerrainMats do
|
|
(
|
|
local Msg = "Selection uses non-terrain materials.\nAre you sure you want to remove non-terrain channels?\n\nThese channels will NOT be removed:\n"
|
|
append Msg (TerrainChans as string)
|
|
|
|
if not (QueryBox Msg Title:"WARNING: Non-terrain materials found") do
|
|
(
|
|
return False
|
|
)
|
|
)
|
|
|
|
SetWaitCursor()
|
|
local Msg = ("Removing channels from selection, keeping: " + (TerrainChans as string))
|
|
format "%\n" Msg
|
|
PushPrompt Msg
|
|
|
|
undo "Delete Channels" on
|
|
(
|
|
gRsTerrainPalette.RemoveCallbacks()
|
|
ClearSelection()
|
|
|
|
RsRemoveClrChans (SelObjs) KeepChans:TerrainChans
|
|
|
|
Select SelObjs
|
|
gRsTerrainPalette.AddCallbacks()
|
|
)
|
|
|
|
PopPrompt()
|
|
DisplayTempPrompt Msg 1000 -- Leave message up a little longer...
|
|
SetArrowCursor()
|
|
),
|
|
|
|
-- 'Deselect % Verts' button clicked:
|
|
fn ev_BtnDeselVerts_Clicked Sender Args =
|
|
(
|
|
if (RsGetSubObjLevelName() != #vertex) do return False
|
|
|
|
local SelObjs = GetCurrentSelection()
|
|
local Obj = SelObjs[1]
|
|
if (SelObjs.Count != 1) or (not isEditPolyMesh Obj) do return False
|
|
|
|
local TheTool = Sender.Tag.Value
|
|
local DeselPercent = TheTool.SpnDeselPercent.Value
|
|
|
|
gRsSelectionTools.RandomlyDeselectVerts Obj DeselPercent
|
|
),
|
|
|
|
fn ev_BtnFixSeamVerts_Clicked Sender Args =
|
|
(
|
|
Filein (RsConfigGetWildwestDir() + "Script/3dsMax/Maps/Materials/RSTA_TerrainSeamFixer_UI.ms")
|
|
),
|
|
|
|
-- Function used by various face-border-selection commands:
|
|
fn SelBorderVerts BordersFunc UndoText:"Select Border Verts" =
|
|
(
|
|
local SelObjs = GetCurrentSelection()
|
|
local Obj = SelObjs[1]
|
|
if (SelObjs.Count != 1) or (not isEditPolyMesh Obj) do return False
|
|
|
|
local DoConvert = False
|
|
|
|
if (not IsKindOf Obj Editable_Poly) do
|
|
(
|
|
if (QueryBox "Selected object needs to be an Editable Poly.\n\nConvert/Collapse object to Poly?" Title:"Warning: Non-Editable Poly Selected") then
|
|
(
|
|
DoConvert = True
|
|
)
|
|
else
|
|
(
|
|
return False
|
|
)
|
|
)
|
|
|
|
undo UndoText on
|
|
(
|
|
if DoConvert do
|
|
(
|
|
ConvertToPoly Obj
|
|
)
|
|
|
|
-- Store current face/edge selection:
|
|
local FaceSel = GetFaceSelection Obj
|
|
local EdgeSel = GetEdgeSelection Obj
|
|
|
|
local BorderEdges = (BordersFunc Obj)
|
|
|
|
-- Set vert-selection to border-verts:
|
|
SetCommandPanelTaskMode #Modify
|
|
SetSelectionLevel Obj #Vertex
|
|
PolyOp.SetEdgeSelection Obj BorderEdges
|
|
Obj.EditablePoly.ConvertSelection #Edge #Vertex
|
|
|
|
-- Revert face/edge-selection:
|
|
SetFaceSelection Obj FaceSel
|
|
SetEdgeSelection Obj EdgeSel
|
|
)
|
|
|
|
return True
|
|
),
|
|
|
|
-- 'Select MatId Borders' button clicked:
|
|
fn ev_BtnSelMatBorders_Clicked Sender Args =
|
|
(
|
|
local selObjs = GetCurrentSelection()
|
|
if (selObjs.count != 1) do return False
|
|
|
|
local obj = selObjs[1]
|
|
local ObjOp = (RsMeshPolyOp obj)
|
|
|
|
if (ObjOp == Undefined) do return False
|
|
|
|
-- Collect object's faces per matId:
|
|
local faceCount = obj.numFaces
|
|
local ObjGetMatID = RsGetFaceMatIDFunc obj
|
|
local facesPerMatId = #()
|
|
for faceNum = 1 to faceCount do
|
|
(
|
|
local faceMatId = (ObjGetMatID obj faceNum)
|
|
|
|
local matIdFaces = facesPerMatId[faceMatId]
|
|
if (matIdFaces == Undefined) do
|
|
(
|
|
matIdFaces = #{}
|
|
matIdFaces.count = faceCount
|
|
facesPerMatId[faceMatId] = matIdFaces
|
|
)
|
|
|
|
matIdFaces[faceNum] = True
|
|
)
|
|
|
|
-- Collect non-open border-edges for each matId:
|
|
local borderVerts = #{}
|
|
for faces in facesPerMatId where (faces != Undefined) do
|
|
(
|
|
borderVerts += (RsGeom_GetFaceBorderVerts obj faces onlyBetween:True)
|
|
)
|
|
|
|
-- Select verts:
|
|
undo "Select MatId Border Verts" on
|
|
(
|
|
local ObjSetVertSelection = if (ObjOp == MeshOp) then SetVertSelection else PolyOp.SetVertSelection
|
|
ObjSetVertSelection obj borderVerts
|
|
SubobjectLevel = 1
|
|
)
|
|
),
|
|
|
|
-- 'Select Borders Between Selected MatIds' button clicked:
|
|
fn ev_BtnSelBetweenSelMats_Clicked Sender Args =
|
|
(
|
|
local selObjs = GetCurrentSelection()
|
|
if (selObjs.count != 1) do return False
|
|
|
|
local obj = selObjs[1]
|
|
local ObjOp = (RsMeshPolyOp obj)
|
|
|
|
if (ObjOp == Undefined) do return False
|
|
|
|
-- Get MatIds used on object's selected faces:
|
|
local matIds = #{}
|
|
local ObjGetMatID = (RsGetFaceMatIDFunc obj)
|
|
for faceNum in (GetFaceSelection obj) do
|
|
(
|
|
local matId = (ObjGetMatID obj faceNum)
|
|
matIds[matId] = True
|
|
)
|
|
|
|
-- Abort if insufficient matIds are selected:
|
|
matIds = (matIds as Array)
|
|
if (matIds.count < 2) do
|
|
(
|
|
local msg = "Please select faces with more than one Material ID.\n\nThis tool finds verts on border between selected mat ids."
|
|
Messagebox msg title:"Warning: Needs multiple MatIds selected"
|
|
|
|
return False
|
|
)
|
|
|
|
-- Collect object's faces per matId:
|
|
local faceCount = obj.numFaces
|
|
local facesPerMatId = #()
|
|
for matId in matIds do
|
|
(
|
|
local faces = #{}
|
|
faces.count = faceCount
|
|
facesPerMatId[matId] = faces
|
|
)
|
|
|
|
for faceNum = 1 to faceCount do
|
|
(
|
|
local faceMatId = (ObjGetMatID obj faceNum)
|
|
local faces = facesPerMatId[faceMatId]
|
|
if (faces != Undefined) do
|
|
(
|
|
faces[faceNum] = True
|
|
)
|
|
)
|
|
|
|
-- Collect verts shared by adjacent matIds:
|
|
local borderVerts = #{}
|
|
for idxA = 1 to (matIds.count - 1) do
|
|
(
|
|
local matIdA = matIds[idxA]
|
|
local matFacesA = facesPerMatId[matIdA]
|
|
local matVertsA = ObjOp.GetVertsUsingFace obj matFacesA
|
|
|
|
for idxB = (idxA + 1) to matIds.count do
|
|
(
|
|
local matIdB = matIds[idxB]
|
|
local matFacesB = facesPerMatId[matIdB]
|
|
local matVertsB = ObjOp.GetVertsUsingFace obj matFacesB
|
|
|
|
-- Collect verts shared by these two sets of faces:
|
|
borderVerts += (matVertsA * matVertsB)
|
|
)
|
|
)
|
|
|
|
-- Select verts:
|
|
undo "Select Verts Between Selected MatIds" on
|
|
(
|
|
local ObjSetVertSelection = if (ObjOp == MeshOp) then SetVertSelection else PolyOp.SetVertSelection
|
|
ObjSetVertSelection obj borderVerts
|
|
SubobjectLevel = 1
|
|
)
|
|
|
|
return OK
|
|
),
|
|
|
|
-- 'Select DPM Borders' button clicked:
|
|
fn ev_BtnSelDpmBorders_Clicked Sender Args =
|
|
(
|
|
local TheTool = Sender.Tag.Value
|
|
|
|
-- This function is passed to 'SelBorderVerts'
|
|
fn GetDpmBorderEdges Obj =
|
|
(
|
|
-- Get faces using DPM shaders:
|
|
local Faces = gRsMaterials.GetObjFacesUsingShaders Obj #("*dpm*", "*uber*snow*")
|
|
|
|
-- Select faces using this MatId:
|
|
Obj.EditablePoly.SetSelection #Face Faces
|
|
|
|
-- Convert matid-selection to border-edge selection:
|
|
Obj.EditablePoly.ConvertSelectionToBorder #Face #Edge
|
|
|
|
-- Collect selected vert-numbers:
|
|
local BorderEdges = (GetEdgeSelection Obj)
|
|
|
|
return BorderEdges
|
|
)
|
|
|
|
TheTool.SelBorderVerts GetDpmBorderEdges UndoText:"Select DPM-Shader Border Verts"
|
|
),
|
|
-- 'Select PXM Borders' button clicked:
|
|
fn ev_BtnSelPxmBorders_Clicked Sender Args =
|
|
(
|
|
local TheTool = Sender.Tag.Value
|
|
|
|
-- This function is passed to 'SelBorderVerts'
|
|
fn GetPxmBorderEdges Obj =
|
|
(
|
|
-- Get faces using PXM shaders:
|
|
local Faces = gRsMaterials.GetObjFacesUsingShaders Obj #("*pxm*")
|
|
|
|
-- Select faces using this MatId:
|
|
Obj.EditablePoly.SetSelection #Face Faces
|
|
|
|
-- Convert matid-selection to border-edge selection:
|
|
Obj.EditablePoly.ConvertSelectionToBorder #Face #Edge
|
|
|
|
-- Collect selected vert-numbers:
|
|
local BorderEdges = (GetEdgeSelection Obj)
|
|
|
|
return BorderEdges
|
|
)
|
|
|
|
TheTool.SelBorderVerts GetPxmBorderEdges UndoText:"Select PXM-Shader Border Verts"
|
|
),
|
|
|
|
-- Combobox selection changed:
|
|
fn ev_CboShaderType_Selected Sender Args =
|
|
(
|
|
local TheTool = Sender.Tag.Value
|
|
|
|
-- Change the button images to match the textures
|
|
TheTool.UpdateTexmapCtrls()
|
|
),
|
|
|
|
-- 'Refresh' button clicked:
|
|
fn ev_Refresh_Clicked Sender Args =
|
|
(
|
|
local TheTool = ::gRsTerrainPalette
|
|
TheTool.UpdateCtrls()
|
|
),
|
|
|
|
-- 'Pick' button clicked:
|
|
fn ev_PickMat_Clicked Sender Args =
|
|
(
|
|
local TheTool = ::gRsTerrainPalette
|
|
|
|
-- Show button as checked:
|
|
TheTool.SetBtnChecked Sender True
|
|
|
|
-- Picker-tool:
|
|
Tool RsMatIdPickerTool
|
|
(
|
|
local obj, rayMesh
|
|
|
|
on start do
|
|
(
|
|
-- Update material/face-lists:
|
|
local SelMatInfo = gRsTerrainPalette.GetSelMatInfo UpdateData:True
|
|
Obj = gRsTerrainPalette.TerrainObj
|
|
|
|
if (isProperty Obj #mesh) then
|
|
(
|
|
replacePrompt "Pick Face"
|
|
|
|
-- Set up RayMesh for object:
|
|
rayMesh = RayMeshGridIntersect()
|
|
rayMesh.Initialize 10
|
|
rayMesh.addNode Obj
|
|
rayMesh.BuildGrid()
|
|
)
|
|
else
|
|
(
|
|
#stop
|
|
)
|
|
)
|
|
|
|
on mousePoint clickNum do
|
|
(
|
|
-- Cast ray at object:
|
|
local mouseRay = (mapScreenToWorldRay mouse.pos)
|
|
local hits = rayMesh.intersectRay mouseRay.pos mouseRay.dir False
|
|
|
|
local hitIdx = rayMesh.getClosestHit() -- Get index of closest ray-hit:
|
|
local hitFace = rayMesh.getHitFace hitIdx
|
|
|
|
local matId = 0
|
|
if (hitFace != 0) do
|
|
(
|
|
matId = getFaceMatID obj.mesh hitFace
|
|
)
|
|
|
|
-- Tell tool to select the material with this matId:
|
|
gRsTerrainPalette.SelListMat matId
|
|
)
|
|
)
|
|
|
|
-- Start picker-tool:
|
|
StartTool RsMatIdPickerTool
|
|
|
|
-- Uncheck button once tool stops:
|
|
TheTool.SetBtnChecked Sender False
|
|
),
|
|
|
|
-- Texmap-button clicked:
|
|
fn ev_TexmapBtn_Clicked Sender Args =
|
|
(
|
|
-- Set current material/texmap:
|
|
gRsTerrainPalette.SetSelLookupTex Sender.Tag
|
|
|
|
-- Was this a rightclick?
|
|
local RightClick = Args.Button.Equals Args.Button.Right
|
|
|
|
-- Apply texmap to mesh if left-clicking:
|
|
if (not rightClick) do
|
|
(
|
|
gRsTerrainPalette.TexClick()
|
|
)
|
|
),
|
|
|
|
-- Texmap-button paint-event:
|
|
fn ev_TexmapBtn_Paint Sender Args =
|
|
(
|
|
-- Request thumbnail for button if this hasn't been set yet:
|
|
if (Sender.ImageIndex == -1) do
|
|
(
|
|
local ButtonTag = Sender.Tag.Value
|
|
local TexPath = ButtonTag.MatInfo.GetTexPath ButtonTag.TexNum
|
|
|
|
-- Queue control for thumbnail-update:
|
|
::gRsTerrainPalette.Thumbs.SetThumb Sender TexPath
|
|
)
|
|
),
|
|
|
|
-- Set-mask button clicked:
|
|
-- (this function is added to controls as value 'SetMaskBtnFunc')
|
|
fn ev_SetMaskBtn_Clicked Sender Args =
|
|
(
|
|
-- Highlight button while it's working...
|
|
gRsTerrainPalette.SetBtnChecked Sender True
|
|
|
|
-- Button is tagged with bitarray denoting rgb-subchannel(s) to edit:
|
|
local SubChans = Sender.Tag.Value
|
|
|
|
-- Get table-column this control comes from:
|
|
local ColIdx
|
|
for n = 0 to 2 while (ColIdx == undefined) do
|
|
(
|
|
if (Sender == (Sender.Parent.GetControlFromPosition n 0)) do
|
|
(
|
|
ColIdx = n
|
|
)
|
|
)
|
|
|
|
local MaskColour = case ColIdx of
|
|
(
|
|
0:(Black)
|
|
1:(gRsTerrainPalette.GetMaskColour())
|
|
2:(White)
|
|
)
|
|
|
|
-- Paint mask-colour to requested subchannels:
|
|
gRsTerrainPalette.PaintSelection MaskSubChans:SubChans MaskColour:MaskColour
|
|
|
|
-- Unhighlight button:
|
|
gRsTerrainPalette.SetBtnChecked Sender False
|
|
),
|
|
|
|
-- 'Show Channel' buttons clicked:
|
|
fn ev_ShowChan_Clicked Sender Args =
|
|
(
|
|
::gRsTerrainPalette.ShowChannel (Sender.Tag)
|
|
),
|
|
|
|
fn ev_ChkVertPaint_Clicked Sender Args =
|
|
(
|
|
local TheTool = Sender.Tag.Value
|
|
|
|
-- Set new checked-state:
|
|
local NewState = (not TheTool.isBtnChecked Sender)
|
|
TheTool.SetChkVertPaintState NewState
|
|
|
|
-- If vertex painting has been switched on:
|
|
if NewState do
|
|
(
|
|
if (TheTool.TerrainMatInfoList.Count == 0) then
|
|
(
|
|
messagebox "Object is not setup with a compatible terrain-shader." Title:"Invalid materials"
|
|
)
|
|
else
|
|
(
|
|
-- Add/retrieve VertexPaint modifier:
|
|
TheTool.SetupVertPaintMod()
|
|
)
|
|
|
|
-- Set fill-strength from spinner:
|
|
if (TheTool.vPainttool != undefined) do
|
|
(
|
|
TheTool.vPaintTool.BrushOpacity = TheTool.SpnFillStrength.Value
|
|
)
|
|
)
|
|
),
|
|
|
|
-- Change VertexPaint brush-opacity if 'Fill Strength' spinner is changed:
|
|
fn ev_SpnFillStrength_Changed Sender Args =
|
|
(
|
|
local TheTool = Sender.Tag.Value
|
|
|
|
if (TheTool.vPainttool != undefined) do
|
|
(
|
|
TheTool.vPainttool.BrushOpacity = Sender.Value
|
|
)
|
|
),
|
|
|
|
-----------------------------------------------------------------------------
|
|
fn selectBorderVerts chan =
|
|
(
|
|
local obj = selection[1]
|
|
if (obj != undefined) and ((isKindOf obj EditablePolyMesh) or (isKindOf obj Editable_mesh)) then
|
|
(
|
|
local borderVerts = RsGeometry_GetUVBorders obj chan
|
|
if (borderVerts.count > 0) then
|
|
(
|
|
if(classof obj == Editable_mesh) then
|
|
(
|
|
setvertselection obj borderVerts
|
|
)
|
|
else
|
|
(
|
|
polyop.setvertselection obj borderVerts
|
|
)
|
|
subobjectlevel = 1
|
|
)
|
|
)
|
|
),
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
fn ev_BtnSelUV1Verts_Clicked =
|
|
(
|
|
::gRsTerrainPalette.selectBorderVerts 1
|
|
),
|
|
|
|
-----------------------------------------------------------------------------
|
|
fn ev_BtnSelUV2Verts_Clicked =
|
|
(
|
|
::gRsTerrainPalette.selectBorderVerts 2
|
|
),
|
|
|
|
-- Form closed:
|
|
fn ToolClose =
|
|
(
|
|
-- Remove selection-change callback:
|
|
RemoveCallbacks()
|
|
|
|
-- Deregister tool from thumbnails-system
|
|
if (gRSTA_ThumbsMgr != undefined) do
|
|
(
|
|
gRSTA_ThumbsMgr.DeregisterTool ToolName
|
|
)
|
|
|
|
-- Dispose of struct's dotnetobjects:
|
|
for PropName in (getPropNames This) do
|
|
(
|
|
local ThisVal = (getProperty This PropName)
|
|
if (isKindOf ThisVal DotNetObject) and (isProperty ThisVal #Dispose) do
|
|
(
|
|
ThisVal.Dispose()
|
|
)
|
|
)
|
|
|
|
gRsTerrainPalette = undefined
|
|
),
|
|
fn ev_ToolForm_Close Sender Args =
|
|
(
|
|
Sender.Tag.Value.ToolClose()
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- InitForm:
|
|
-- Initial form-setup steps
|
|
------------------------------------------------------------------------------
|
|
fn InitForm =
|
|
(
|
|
PushPrompt "Initialising Terrain Painter..."
|
|
|
|
-- Set local aliases for event-functions:
|
|
TexmapBtnFunc = ev_TexmapBtn_Clicked
|
|
TexmapBtnPaintFunc = ev_TexmapBtn_Paint
|
|
SetMaskBtnFunc = ev_SetMaskBtn_Clicked
|
|
|
|
-- Get dotnet colours for current Max colourscheme:
|
|
FormClr = (ColorMan.GetColor #background) * 255
|
|
FormClr = (dnColour.FromArgb FormClr[1] FormClr[2] FormClr[3])
|
|
WindowClr = (ColorMan.GetColor #window) * 255
|
|
WindowClr = (dnColour.FromArgb WindowClr[1] WindowClr[2] WindowClr[3])
|
|
TextClr = (ColorMan.GetColor #windowText) * 255;
|
|
TextClr = (dnColour.FromArgb TextClr[1] TextClr[2] TextClr[3])
|
|
|
|
ToolForm.Tag = (DotNetMxsValue This)
|
|
ToolForm.Text = "Terrain Painter"
|
|
ToolForm.Size = DotNetObject "System.Drawing.Size" FormSize.X FormSize.Y
|
|
ToolForm.BackColor = FormClr
|
|
ToolForm.MinimumSize = (DotNetObject "System.Drawing.Size" FormSize.X 0)
|
|
|
|
-- Show the tool-form, with redraw deactivated:
|
|
(
|
|
ToolForm.ShowModeless()
|
|
ToolForm.Refresh()
|
|
SuspendRedraw()
|
|
)
|
|
|
|
DotNet.addEventHandler ToolForm "Closing" ev_ToolForm_Close
|
|
|
|
-- Struct for generating lists of controls:
|
|
struct CtrlDef (Name, Text, Tooltip, TagVal, Func, Width, FlowBreak = False)
|
|
|
|
-- Main layout-table:
|
|
(
|
|
local MainTable = dotNetObject "TableLayoutPanel"
|
|
ToolForm.Controls.Add MainTable
|
|
MainTable.Dock = MainTable.Dock.Fill
|
|
MainTable.CellBorderStyle = MainTable.CellBorderStyle.None
|
|
MainTable.BackColor = FormClr
|
|
|
|
-- Add banner:
|
|
(
|
|
-- Set fixed row-height:
|
|
MainTable.RowStyles.Add (dotNetObject "RowStyle" SizeType_AutoSize)
|
|
RsBannerPanel.Margin = (dotNetObject "Padding" 0)
|
|
RsBannerPanel.Dock = RsBannerPanel.Dock.Fill
|
|
|
|
MainTable.Controls.Add RsBannerPanel
|
|
)
|
|
|
|
-- Add scroll-panel:
|
|
ScrollPanel = DotNetObject "TableLayoutPanel"
|
|
MainTable.Controls.Add ScrollPanel
|
|
ScrollPanel.Dock = ScrollPanel.Dock.Fill
|
|
ScrollPanel.CellBorderStyle = ScrollPanel.CellBorderStyle.None
|
|
ScrollPanel.Padding = (dotNetObject "Padding" 0 0 (dotNetClass "SystemInformation").VerticalScrollBarWidth 0)
|
|
ScrollPanel.AutoScroll = True
|
|
|
|
-- Add shadertype-selection panel:
|
|
(
|
|
local GrpBox = AddGrpBox ScrollPanel Title:"Select Terrain Shader Type:"
|
|
ScrollPanel.RowStyles.Add (dotNetObject "RowStyle" SizeType_AutoSize)
|
|
|
|
local ThisPanel = dotNetObject "FlowLayoutPanel"
|
|
ThisPanel.Padding = (dotNetObject "Padding" 6 6 6 6)
|
|
ThisPanel.Dock = ThisPanel.Dock.Fill
|
|
ThisPanel.AutoSize = True
|
|
GrpBox.Controls.Add ThisPanel
|
|
|
|
-- Collect object-reliant panel:
|
|
-- (controls here are disabled if terrain-object is not selected)
|
|
append ObjEditPanels ThisPanel
|
|
|
|
-- Add Combobox:
|
|
(
|
|
CboShaderType = dotNetObject "ComboBox"
|
|
CboShaderType.Margin = (dotNetObject "Padding" 1 0 4 4)
|
|
CboShaderType.Width = 234
|
|
CboShaderType.DropDownWidth = 600
|
|
CboShaderType.DropDownStyle = CboShaderType.DropDownStyle.DropDownList
|
|
CboShaderType.FlatStyle = CboShaderType.FlatStyle.Flat
|
|
CboShaderType.BackColor = WindowClr
|
|
CboShaderType.ForeColor = TextClr
|
|
|
|
CboShaderType.Tag = (dotNetMxsValue This)
|
|
dotNet.addEventHandler CboShaderType "SelectionChangeCommitted" ev_CboShaderType_Selected
|
|
|
|
ThisPanel.Controls.Add CboShaderType
|
|
)
|
|
|
|
-- Add material-buttons:
|
|
for Item in
|
|
#(
|
|
CtrlDef Name:#ChkPickMat Text:"Pick" Tooltip:"Pick material from terrain-object" Func:ev_PickMat_Clicked Width:60,
|
|
CtrlDef Name:#BtnRefresh Text:"Refresh" Tooltip:"Refresh the terrain-material list" Func:ev_Refresh_Clicked Width:60
|
|
)
|
|
do
|
|
(
|
|
local NewBtn = DotNetObject "Button"
|
|
NewBtn.Text = Item.Text
|
|
NewBtn.FlatStyle = NewBtn.FlatStyle.System
|
|
if (Item.Width == undefined) then
|
|
(
|
|
NewBtn.AutoSize = True
|
|
)
|
|
else
|
|
(
|
|
NewBtn.Width = Item.Width
|
|
)
|
|
NewBtn.Height = 22
|
|
NewBtn.Margin = (dotNetObject "Padding" 0 0 3 0)
|
|
|
|
-- Tag button with this struct:
|
|
NewBtn.Tag = Item.TagVal
|
|
|
|
-- Store reference to pick-button:
|
|
if (Item.Name == #ChkPickMat) then
|
|
(
|
|
This.ChkPickMat = NewBtn
|
|
)
|
|
else
|
|
(
|
|
-- Non-stored buttons should have DotNet lifetime-control:
|
|
dotNet.setLifetimeControl NewBtn #dotnet
|
|
)
|
|
|
|
ThisPanel.Controls.Add NewBtn
|
|
dnTooltip.SetToolTip NewBtn Item.Tooltip
|
|
dotNet.addEventHandler NewBtn "MouseUp" Item.Func
|
|
)
|
|
)
|
|
|
|
-- Add texmap-buttons panel: (filled out by 'fn UpdateTexmapCtrls')
|
|
(
|
|
TexmapPanel = AddGrpBox ScrollPanel Title:"Texturemaps:" PanelType:"TableLayoutPanel"
|
|
ScrollPanel.RowStyles.Add (dotNetObject "RowStyle" SizeType_AutoSize)
|
|
)
|
|
|
|
-- Add 'Show Channel' controls:
|
|
(
|
|
local GrpBox = AddGrpBox ScrollPanel Title:"Show Channel:"
|
|
ScrollPanel.RowStyles.Add (dotNetObject "RowStyle" SizeType_AutoSize)
|
|
|
|
local ThisPanel = dotNetObject "FlowLayoutPanel"
|
|
ShowChansPanel = ThisPanel
|
|
|
|
ThisPanel.Dock = ThisPanel.Dock.Fill
|
|
ThisPanel.Padding = (dotNetObject "Padding" 6 6 6 6)
|
|
ThisPanel.AutoSize = True
|
|
GrpBox.Controls.Add ThisPanel
|
|
|
|
-- Add show-channel buttons:
|
|
for Item in
|
|
#(
|
|
CtrlDef Text:"Off" Tooltip:"Don't show vertex-colours" TagVal:-3,
|
|
CtrlDef Text:"Alpha [-2]" Tooltip:"Show Vertex Alpha channel" TagVal:-2,
|
|
CtrlDef Text:"VColour [0]" Tooltip:"Show default Vertex Colours channel" TagVal:0,
|
|
CtrlDef Text:"Lookup [9]" Tooltip:"Show Terrain Paint lookup-colour channel" TagVal:9,
|
|
CtrlDef Text:"Uber Mask [5]" Tooltip:"Show Uber Terrain Shader lookup/tint mask-channel" TagVal:5
|
|
)
|
|
do
|
|
(
|
|
local NewBtn = DotNetObject "Button"
|
|
NewBtn.Text = Item.Text
|
|
NewBtn.Tag = Item.TagVal
|
|
|
|
NewBtn.FlatStyle = NewBtn.FlatStyle.System
|
|
NewBtn.AutoSize = True
|
|
NewBtn.Width = 0
|
|
NewBtn.Height = 26
|
|
NewBtn.Margin = (dotNetObject "Padding" 0 0 3 0)
|
|
|
|
ThisPanel.Controls.Add NewBtn
|
|
dnTooltip.SetToolTip NewBtn Item.Tooltip
|
|
dotNet.addEventHandler NewBtn "MouseUp" ev_ShowChan_Clicked
|
|
dotNet.setLifetimeControl NewBtn #dotnet
|
|
)
|
|
)
|
|
|
|
-- Add sub-table row:
|
|
(
|
|
local SubTable = DotNetObject "TableLayoutPanel"
|
|
SubTable.Dock = SubTable.Dock.Fill
|
|
SubTable.Margin = (dotNetObject "Padding" 0)
|
|
SubTable.ColumnCount = 2
|
|
SubTable.AutoSize = True
|
|
|
|
ScrollPanel.RowStyles.Add (dotNetObject "RowStyle" SizeType_AutoSize)
|
|
ScrollPanel.Controls.Add SubTable
|
|
|
|
SubTable.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_Percent 50)
|
|
SubTable.ColumnStyles.Add (dotNetObject "ColumnStyle" SizeType_Percent 50)
|
|
SubTable.RowStyles.Add (dotNetObject "RowStyle" SizeType_AutoSize)
|
|
|
|
-- Add VertexPaint panel:
|
|
(
|
|
local ThisPanel = AddGrpBox SubTable Title:"VertexPaint:" PanelType:"FlowLayoutPanel"
|
|
|
|
-- Collect object-reliant panel:
|
|
append ObjEditPanels ThisPanel
|
|
|
|
-- Add 'Start Vertex Paint' checkbutton:
|
|
(
|
|
local NewBtn = DotNetObject "Button"
|
|
ChkVertPaint = NewBtn
|
|
|
|
NewBtn.Text = "Start Vertex Paint"
|
|
NewBtn.FlatStyle = NewBtn.FlatStyle.System
|
|
NewBtn.AutoSize = True
|
|
NewBtn.Width = 0
|
|
NewBtn.Height = 26
|
|
NewBtn.Margin = (dotNetObject "Padding" 6 3 0 6)
|
|
|
|
-- Tag button with this struct:
|
|
NewBtn.Tag = (dotNetMxsValue This)
|
|
|
|
ThisPanel.Controls.Add NewBtn
|
|
dnTooltip.SetToolTip NewBtn "Toggle vertex painting"
|
|
dotNet.addEventHandler NewBtn "MouseUp" ev_ChkVertPaint_Clicked
|
|
)
|
|
|
|
-- Add VertexPaint/mask fill-strength spinner:
|
|
(
|
|
local LblFillStr = dotNetObject "Label"
|
|
LblFillStr.Text = "Fill Strength:"
|
|
LblFillStr.Margin = (dotNetObject "Padding" 6 8 0 6)
|
|
LblFillStr.AutoSize = True
|
|
|
|
SpnFillStrength = dotNetObject "NumericUpDown"
|
|
SpnFillStrength.Tag = (dotNetMxsValue This)
|
|
SpnFillStrength.Margin = (dotNetObject "Padding" 2 6 0 6)
|
|
SpnFillStrength.Width = 50
|
|
SpnFillStrength.BackColor = WindowClr
|
|
SpnFillStrength.ForeColor = TextClr
|
|
SpnFillStrength.DecimalPlaces = 0
|
|
SpnFillStrength.Increment = 1
|
|
SpnFillStrength.Minimum = 1
|
|
SpnFillStrength.Maximum= 100
|
|
SpnFillStrength.Value = 100
|
|
SpnFillStrength.ReadOnly = False
|
|
|
|
ThisPanel.Controls.Add LblFillStr
|
|
ThisPanel.Controls.Add SpnFillStrength
|
|
dotNet.addEventHandler SpnFillStrength "ValueChanged" ev_SpnFillStrength_Changed
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Add mesh-selection panel:
|
|
(
|
|
local GrpBox = AddGrpBox ScrollPanel Title:"Vertex Selection:"
|
|
SubTable.RowStyles.Add (dotNetObject "RowStyle" SizeType_AutoSize)
|
|
|
|
MeshSelectPanel = dotNetObject "FlowLayoutPanel"
|
|
MeshSelectPanel.Dock = MeshSelectPanel.Dock.Fill
|
|
MeshSelectPanel.Padding = (dotNetObject "Padding" 6 6 6 6)
|
|
MeshSelectPanel.AutoSize = True
|
|
GrpBox.Controls.Add MeshSelectPanel
|
|
|
|
-- Add channel-shower buttons:
|
|
for Item in
|
|
#(
|
|
CtrlDef Name:#BtnSelMatBorders Text:"MatId Borders (All)" Tooltip:"Select verts joining faces with different MatIds" Func:ev_BtnSelMatBorders_Clicked,
|
|
CtrlDef Name:#BtnSelBetweenSelMats Text:"MatId Borders (Selected)" Tooltip:"Select verts joining faces using MatIds used on selected faces" Func:ev_BtnSelBetweenSelMats_Clicked,
|
|
CtrlDef Name:#BtnSelDpmBorders Text:"DPM/Snow Borders" Tooltip:"Select verts joining non/tesselation-shader faces" Func:ev_BtnSelDpmBorders_Clicked,
|
|
CtrlDef Name:#BtnSelPxmBorders Text:"PXM Borders" Tooltip:"Select verts joining non-PXM/PXM-shader faces" Func:ev_BtnSelPxmBorders_Clicked FlowBreak:True,
|
|
CtrlDef Name:#BtnDeselVerts Text:"Deselect % Verts:" Tooltip:"Deselect a portion of current vertex-selection" Func:ev_BtnDeselVerts_Clicked--,
|
|
--CtrlDef Name:#BtnSelUV1Verts Text:"Select UV 1 Border" Tooltip:"Select verts on the UV1 border" Func:ev_BtnSelUV1Verts_Clicked,
|
|
--CtrlDef Name:#BtnSelUV2Verts Text:"Select UV 2 Border" Tooltip:"Select verts on the UV2 border" Func:ev_BtnSelUV2Verts_Clicked
|
|
)
|
|
do
|
|
(
|
|
local NewBtn = DotNetObject "Button"
|
|
NewBtn.Text = Item.Text
|
|
NewBtn.FlatStyle = NewBtn.FlatStyle.System
|
|
--NewBtn.Width = 60
|
|
NewBtn.Height = 23
|
|
NewBtn.AutoSize = True
|
|
NewBtn.Margin = (dotNetObject "Padding" 0 0 4 0)
|
|
|
|
-- Tag button with this struct:
|
|
NewBtn.Tag = (dotNetMxsValue This)
|
|
|
|
dotNet.addEventHandler NewBtn "MouseUp" Item.Func
|
|
MeshSelectPanel.Controls.Add NewBtn
|
|
dnTooltip.SetToolTip NewBtn Item.Tooltip
|
|
|
|
-- Set layout-flow break, or not:
|
|
ThisPanel.SetFlowBreak NewBtn Item.FlowBreak
|
|
|
|
dotNet.setLifetimeControl NewBtn #dotnet
|
|
|
|
-- Add percentage-spinner after 'Deselect Verts' button:
|
|
if (Item.Name == #BtnDeselVerts) do
|
|
(
|
|
SpnDeselPercent = dotNetObject "NumericUpDown"
|
|
SpnDeselPercent.Margin = (dotNetObject "Padding" 1 1 0 0)
|
|
SpnDeselPercent.Width = 50
|
|
SpnDeselPercent.BackColor = WindowClr
|
|
SpnDeselPercent.ForeColor = TextClr
|
|
SpnDeselPercent.DecimalPlaces = 0
|
|
SpnDeselPercent.Increment = 1
|
|
SpnDeselPercent.Minimum = 1
|
|
SpnDeselPercent.Maximum= 100
|
|
SpnDeselPercent.Value = 50
|
|
SpnDeselPercent.ReadOnly = False
|
|
|
|
MeshSelectPanel.Controls.Add SpnDeselPercent
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Add Tools panel:
|
|
(
|
|
local GrpBox = AddGrpBox ScrollPanel Title:"More Tools:"
|
|
ScrollPanel.RowStyles.Add (dotNetObject "RowStyle" SizeType_AutoSize)
|
|
|
|
local ThisPanel = dotNetObject "FlowLayoutPanel"
|
|
ThisPanel.Dock = ThisPanel.Dock.Fill
|
|
ThisPanel.Padding = (dotNetObject "Padding" 6 6 6 6)
|
|
ThisPanel.AutoSize = True
|
|
GrpBox.Controls.Add ThisPanel
|
|
|
|
-- Give last box a bottom-margin
|
|
GrpBox.Parent.Parent.Margin = (dotNetObject "Padding" 4 4 4 4)
|
|
|
|
-- Add extra tool-buttons:
|
|
for Item in
|
|
#(
|
|
CtrlDef Name:#BtnVertColTools Text:"Vertex Colour Toolkit" Func:ev_BtnVertColTools_Clicked \
|
|
Tooltip:"Open Vertex Colour Toolkit",
|
|
CtrlDef Name:#BtnTerrShadEdit Text:"Terrain Shader Editor" Func:ev_BtnTerrShadEdit_Clicked \
|
|
Tooltip:"Terrain Shader Editor\nSimplifies editing of shaders' per-texmap values.",
|
|
CtrlDef Name:#BtnMapIdProj Text:"MapId Projector" Func:ev_BtnMapIdProj_Clicked FlowBreak:True \
|
|
Tooltip:"Open 'MapID Projector/Render' toolkit",
|
|
CtrlDef Name:#BtnInitChannels Text:"Init Terrain Chans" Func:ev_BtnInitChannels_Clicked \
|
|
Tooltip:"Activate terrain-related vertex-colour channels for selected geometry,\nif they're not already active.\n\n(Channels 5, 9)" ,
|
|
CtrlDef Name:#BtnDelChannels Text:"Remove Non-Terrain Chans" Func:ev_BtnDelChannels_Clicked \
|
|
Tooltip:"Deactivate non-terrain-related vertex-colour channels for selected geometry.\nAsks user for permission if object uses non-terrain materials.\n\nKeeps channels -2, 0, 1, 2, 5, 9, 13\n\n(This command can't be undone)",
|
|
CtrlDef name:#BtnFixSeamVerts Text:"Find/Fix Seams" func:ev_BtnFixSeamVerts_Clicked \
|
|
tooltip:("Find verts between faces with non-blended texmaps, and auto-fix where possible")
|
|
)
|
|
do
|
|
(
|
|
local NewBtn = DotNetObject "Button"
|
|
NewBtn.Text = Item.Text
|
|
NewBtn.FlatStyle = NewBtn.FlatStyle.System
|
|
NewBtn.AutoSize = True
|
|
NewBtn.Height = 30
|
|
NewBtn.Margin = (dotNetObject "Padding" 0 0 3 3)
|
|
|
|
-- Add tooltip:
|
|
dnTooltip.SetToolTip NewBtn Item.Tooltip
|
|
|
|
dotNet.addEventHandler NewBtn "MouseUp" Item.Func
|
|
|
|
-- Set layout-flow break, or not:
|
|
ThisPanel.SetFlowBreak NewBtn Item.FlowBreak
|
|
|
|
ThisPanel.Controls.Add NewBtn
|
|
dotNet.setLifetimeControl NewBtn #dotnet
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Set up banner:
|
|
BannerStruct.Setup()
|
|
|
|
-- Update the tool-form:
|
|
(
|
|
ResumeRedraw()
|
|
ToolForm.Refresh()
|
|
)
|
|
|
|
PopPrompt()
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Initialise Terrain Palette tool:
|
|
------------------------------------------------------------------------------
|
|
fn Create =
|
|
(
|
|
PushPrompt "Initialising Terrain Painter"
|
|
|
|
-- Initial form-setup:
|
|
InitForm()
|
|
|
|
-- Update controls for current selection:
|
|
UpdateCtrls()
|
|
|
|
-- Set up selection-change callback:
|
|
AddCallbacks()
|
|
|
|
PopPrompt()
|
|
)
|
|
)
|
|
|
|
-- Start tool:
|
|
gRsTerrainPalette = RsTerrainPalette()
|
|
gRsTerrainPalette.Create()
|
|
|
|
--- TEST:
|
|
--gRsTerrainPalette.GetTexmapVerts()
|
|
--gRsTerrainPalette.DeconstructColour (128*[1,1,1]/255)
|