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

884 lines
29 KiB
Plaintext
Executable File

-- VegetationTools.ms
-- 2013 Andy Davis
-- Rockstar London
-- Description: Collection of tools to manage vegetation related geometry tasks
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms") --wildwest header
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/RSL_dotNetUIOps.ms") --RS_dotNetPreset structure
RsCollectToolUsageData (getThisScriptFilename())
global VegToolsUI
struct CustomTreeData
(
ObjectName, --the RSRefObject.objectName value
PivotOffset = [0,0,0], --the value to offset the pivot so that it is placed at the base of the tree
Radius --radius of the base of the tree
)
struct TreePlacementStruct
(
tolerance = 0.5,
maxTrunkRadius = 1,
padding = 0.01,
groundPlane = undefined,
objSet = #(),
debug = false,
progress = 0,
CustomTreeList = #(),
fn PlaceObjects =
(
local originalSelection = selection as array
for obj in originalSelection do
(
if (classOf obj.baseObject == RSrefObject) and (obj != this.groundPlane) then
(
local numModifiers = obj.modifiers.count
this.FixRSRef obj
append this.objSet obj
)
)
select objSet
local GroundPlanes = this.GetGroundPlanes selection
for obj in objSet do
(
local ZRotation = this.GetZRotation obj
local RandomRotation = VegToolsUI.RandomSpinner.text as float
if (RandomRotation > 0.0) then
ZRotation += (random -180 180) * RandomRotation
this.SetRotation obj (eulerAngles 0 0 0)
local downVector = [0,0,-1]
local verticalPad = 3 --height to add to the z value of the ray in order to replant trees
local PivotOffset = [0,0,0]
local treeRadius = 0.03
local IsCustom = false
--check to see if the object is in the CustomTreeList
for item in this.CustomTreeList do
(
if obj.objectName == item.ObjectName then
(
PivotOffset = item.PivotOffset
treeRadius = item.Radius
IsCustom = true
)
)
if (IsCustom) then
(
obj.pivot -= PivotOffset
)
local PivotRay = ray [obj.pivot.x, obj.pivot.y, (obj.pivot.z + verticalPad)] downVector --used to calculate slope angle
local intersection = this.GetIntersection GroundPlanes PivotRay
if intersection != undefined then
(
local ZPoint = intersection.pos.z
local dropHeight = obj.pivot.z - ZPoint + 0.15
--rotate the object to fit it in the direction of the slope
--get the slope angle
local slopeRay = intersection.dir
local slantVector = this.GetProportionalVector slopeRay [0,0,1] (VegToolsUI.slopeSpinner.text as float)
-- print slopeRay
local slantAngle = this.GetAngleFromVector slantVector
rotate obj slantAngle
this.SetZRotation obj ZRotation
--angle between two vectors for slant vector and vertical to determine the extra drop height
obj.position.z -= (dropHeight + this.GetDropHeight slopeRay treeRadius)
)
else
(
local infoString = ("No ground plane found for " + obj.name)
messagebox infoString title:"Tree Placement"
)
--reset the pivot to the original position if the pivot has been offset
if (IsCustom) then
(
local RotationBuffer = obj.rotation as eulerAngles
this.SetRotation obj (eulerAngles 0 0 0)
obj.Pivot += PivotOffset
this.SetRotation obj RotationBuffer
)
this.progress += 100 / objSet.count
)
return objSet.count
),
fn InitCustomTreeList =
(
append this.CustomTreeList (CustomTreeData ObjectName:"Prop_Bush_Lrg_04b" PivotOffset:[-1.0, -0.45, 2.3] Radius:1.65)
-- print this.CustomTreeList
),
--calculates the vertical shift an object must drop by to compensate for a tilt from the vertical
fn GetDropHeight SlopeVector Radius =
(
local AngleToVertical = acos(dot (normalize SlopeVector) [0,0,1])
local DropHeight = sin(AngleToVertical) * Radius
return DropHeight
),
fn GetZRotation InObject =
(
toolMode.coordsys #world
rot = InObject.Rotation as eulerangles
-- messagebox (rot.z as string)
return rot.z
),
fn SetZRotation InObject ZValue =
(
toolMode.coordsys #world
rot = InObject.Rotation as eulerangles
pos = InObject.Position
InObject.Rotation = (eulerangles rot.x rot.y ZValue)
InObject.Position = pos
),
fn GetIntersection TestPlanes InRay =
(
local numPlanes = TestPlanes.count
local found = false
local intersection = undefined
for thisPlane in TestPlanes where found == false do
(
intersection = intersectRay thisPlane InRay
if (intersection != undefined) then found = true
)
return intersection
),
--function collects candidates for ground planes to match a set of passed in nodes
fn GetGroundPlanes InObject =
(
GroundPlanes = for item in geometry where ClassOf item != RSrefObject collect item
GroundPlanes = for item in GroundPlanes where (item.max.x > InObject.min.x) and (item.max.y > InObject.min.y) collect item
GroundPlanes = for item in GroundPlanes where (item.min.x < InObject.max.x) and (item.min.y < InObject.max.y) collect item
GroundPlanes = for item in GroundPlanes where not (getAttr item (getAttrIndex "Gta Object" "Dont Export")) collect item
GroundPlanes = for item in GroundPlanes where not (RSIsLod item) collect item
return GroundPlanes
),
fn SetRotation obj eulerRotation =
(
local objPosition = obj.position
obj.rotation = eulerRotation
obj.position = objPosition
),
fn FixRSRef rsref =
(
local numModifiers = rsref.modifiers.count
if numModifiers > 0 then
(
for i = 1 to numModifiers do
(
deleteModifier rsref rsref.modifiers[1]
)
)
),
--function gets an eulerAngles value for a corresponding vector
fn GetAngleFromVector theNormal =
(
local theZ = normalize theNormal --this is the original vector
if (dot theZ [0,0,1]) > 0.99999 then --if the vector is nearly parallel to Z, assume 0
eulerangles 0 0 0
else
(
local theY = normalize (cross [0,0,1] theZ ) --this is the Y axis orthogonal to the Normal and Up
local theX = normalize (cross theY theZ) --this is the X orthogonal to Normal and Y
local theTM = matrix3 theX theY theZ [0,0,0] --this is the matrix3 describing the orientation of the Normal
theTM.rotationpart as eulerangles --return its Euler rotation
)
),
--finds the vector that is proportionally aligned to the targetVector from a starting reference vector
--amount: number from 0 to 1 representing the proportion
--amount 0 is the refVector, amount 1 is the targetVector
fn GetProportionalVector targetVector refVector amount =
(
return (normalize (amount * targetVector + (1 - amount) * refVector))
),
fn IsNoExportSet obj =
(
local noExport = false
if (getAttr obj (getAttrIndex "Gta Object" "Dont Export")) or (getAttr $ (getAttrIndex "Gta Object" "Dont Add To IPL")) then
noExport = true
return noExport
),
--function prints out the parameters of the struc
fn PrintDetails =
(
clearListener()
format "Tolerance: %\n" this.tolerance
if (this.GroundPlane == undefined) then
format "Ground Plane: undefined\n"
else
format "Ground Plane: %\n" this.groundPlane.name
)
)
--struct to handle the geometry operations
struct TreeBaseGeneratorStruct
(
--treegen varaibles
size = 2,
numSides = 8, --must be 4 or more sides
fill = 0.75,
inset = 0.125,
devMode = false,
jig = undefined,
refPoly = undefined,
topObj = undefined,
infoString,
--function returns the closest of the four edge verts to the mid-point of verts a and b
fn GetClosestEdgeVert obj a b =
(
local midPoint = (obj.verts[a].position + obj.verts[b].position) / 2
local closestVert = 1
local vertDist = distance midPoint obj.verts[1].position
for i = 2 to 4 do
(
if (distance midPoint obj.verts[i].position) < vertDist then
(
closestVert = i
vertDist = distance midPoint obj.verts[i].position
)
)
return closestVert
),
--places the jig to the location of the selected polygon
fn PlaceTreeBase =
(
--Check that selection matches criteria
local objList = for this in selection where superClassOf this == GeometryClass collect this
if (objList.count == 1) then
(
local obj = objList[1]
if obj.modifiers.count > 0 then print "Warning - about to collapse stack"
convertToPoly objList[1]
subObjectLevel = 4
if (obj.selectedFaces.count == 1) then
(
local faceID = obj.selectedFaces[1].index
local vertIDs = polyOp.GetFaceVerts obj faceID
if vertIDs.count == 4 then
(
this.CreateBaseMesh()
select this.jig
--set the smoothing groups
local smoothingGroups = RSGeom_GetSmoothingGroups obj faceID
for face = 1 to this.jig.faces.count do
RSGeom_SetSmoothingGroups this.jig face smoothingGroups
--set the order for the ffd control points to be translated to match the polygon
local ffdCPPairs = #(#(1,2), #(5,6), #(7,8), #(3,4))
local ffd = FFD_2x2x2()
addModifier this.jig ffd
animateAll ffd --required to get access to ffd control points
clearListener()
-- ffdOps = FFDWrapper()
for i = 1 to 4 do
(
RSFFD_SetWorldPos this.jig this.jig.FFD_2x2x2 ffdCPPairs[i][1] obj.verts[vertIDs[i]].position
RSFFD_SetWorldPos this.jig this.jig.FFD_2x2x2 ffdCPPairs[i][2] obj.verts[vertIDs[i]].position
)
--extract quad from mesh
polyop.detachFaces obj obj.faces[faceID] delete:true asNode:true name:"transfer"
this.topObj = obj
this.infoString = "Polygon processed."
true
)
else
(
this.infoString = "Please select a quad."
false
)
)
else
(
this.infoString = "Please select a single face."
false
)
)
else
(
this.infoString = "Please select a polygon on an object."
false
)
),
--callback script for the projection modifier used to transfer the mapping data to the treeBase
fn ProjectionCallback =
(
local hwnd = dialogMonitorOps.getWindowHandle()
if (uiAccessor.getWindowText hwnd == "Add Objects") then
(
--the control IDs below are correct for 3dsMax 2012
--may need to refigure the IDs if the dialog box changes in future versions
--use windows.getChildHWND <hwnd> to get a list of controls
local dotNetPressEnter = dotNetClass "System.Windows.Forms.SendKeys"
local toolStripID = 5
local addButtonID = 19
local editButtonID = 12
local VK_RETURN = 0x0D
local MAXHWND = windows.getMAXHWND()
local AddObjectsHWNDList = UIAccessor.GetChildWindows hwnd
local AddObjectsControls = windows.getChildrenHWND hwnd
local toolStripHWNDControls = windows.getChildrenHWND AddObjectsHWNDList[toolStripID]
UIAccessor.SetWindowText toolStripHWNDControls[editButtonID][1] this.jig.name
dotNetPressEnter.Send "{ENTER}"
)
true
),
--attach the jig to the original object, after transferring the material and mapping
fn AttachTreeBase =
(
local source = objects[objects.count]
--copy materials and transfer mapping
this.jig.material = source.material
addModifier source (Projection())
select source
dialogMonitorOps.unRegisterNotification id:#test
dialogMonitorOps.enabled = true
dialogMonitorOps.interactive = false
dialogMonitorOps.registerNotification ProjectionCallback id:#test
commandHWND = (windows.getChildHWND #max "Pick List")
UIAccessor.pressButtonByName commandHWND[2] "Pick List"
commandHWND = (windows.GetChildHWND #max "Add")
UIAccessor.pressButtonByName commandHWND[2] "Add"
commandHWND = (windows.GetChildHWND #max "Project All")
UIAccessor.pressButtonByName commandHWND[2] "Project All"
dialogMonitorOps.enabled = false
--combine base mesh with original mesh
convertToMesh #(this.topObj, this.jig)
meshop.attach this.topObj this.jig
convertToPoly this.topObj
--weld the vertices
this.topObj.weldThreshold = 0.01
local outerEdges = polyop.getOpenEdges this.topObj
local edgeVerts = polyop.getVertsUsingEdge this.topObj outerEdges
polyop.weldVertsByThreshold this.topObj edgeVerts
delete source
select this.topobj
),
fn CreateBaseMesh =
(
local originalSelection = selection as array
local selectionMode = subObjectLevel
this.CreateJig()
try
(
select originalSelection
subObjectLevel = selectionMode
)
catch(clearSelection())
),
fn CreateJig =
(
if (devMode) then
for this in objects where (this.name == "jig") do delete this
this.jig = Plane width:this.size length:this.size name:"jig" lengthsegs:1 widthsegs:1
local radiusValue = this.jig.width * this.fill * 0.5
local insetValue = radiusValue * this.inset
local base = Cylinder radius:radiusValue height:0.5 sides:this.numSides
convertToMesh base
local baseVerts = for item in base.verts where item.position.z == 0 and item.position != [0,0,0] collect item.position
append baseVerts [0,0,0]
delete base
select this.jig
this.jig.backfacecull = true
convertToMesh this.jig
meshop.setNumVerts this.jig (5 + numSides)
for i = 1 to (numSides + 1) do
(
this.jig.verts[i + 4].position = baseVerts[i]
)
subObjectLevel = 1
for i = 1 to (numSides - 1) do
(
meshop.createPolygon this.jig #(i+4, i+5, numSides + 5)
local edgeVert = GetClosestEdgeVert this.jig (i+4) (i+5)
meshop.createPolygon this.jig #(i+5, i+4, edgeVert)
)
-- create the final center poly
meshop.createPolygon this.jig #(numSides + 4, 5, numSides + 5)
meshOp.createPolygon this.jig #(5, numSides + 4, (GetClosestEdgeVert jig 5 (numSides + 4)))
meshop.deleteFaces this.jig #{1,2} --delete the initial two faces
-- create the final edge polys
-- first get the vertex ids for each of the four triangles
local openEdgeList = meshop.GetOpenEdges this.jig
local nonCornerVerts = #()
local finalEdgePolys = #()
for item in openEdgeList as array do
(
local verts = (meshop.getVertsUsingEdge this.jig item) as array
local innerVert, outerVert
if (verts[1] > 4) then
(
innerVert = verts[1]
outerVert = verts[2]
)
else
(
innerVert = verts[2]
outerVert = verts[1]
)
if finalEdgePolys.count > 0 then
(
local found = false
for poly in finalEdgePolys do
(
if innerVert == poly[1] then
(
found = true
append poly outerVert
)
)
if (not found) then
(
append finalEdgePolys #(innerVert, outerVert)
)
)
else
(
append finalEdgePolys #(innerVert, outerVert)
)
)
-- now create the polys
for item in finalEdgePolys do
(
if (item[1] == 5) then
meshop.createPolygon jig #(item[1], item[3], item[2])
else
meshop.createPolygon jig item
)
--translate the centre vertex so that the ffd is not flat
--this is necessary so that the ffd is not 2-dimensional
jig.verts[jig.verts.count].position.z += 0.2
--inset the centre
convertToPoly jig
subObjectLevel = 4
local centerFaces = polyop.getFacesUsingVert jig #{jig.verts.count}
polyop.setFaceSelection jig centerFaces
jig.insetAmount = insetValue
jig.buttonOp #Inset
polyop.setFaceSelection jig #{}
jig
),
fn SetCommandPanelRedraw State =
(
Args = 0
if( State == on ) then Args = 1
WM_SETREDRAW=0xB
CommandHWND = (Windows.GetChildHWND #Max "Command Panel")
Windows.Sendmessage (CommandHWND[1]) WM_SETREDRAW Args 0
),
fn Process =
(
with undo off
(
this.SetCommandPanelRedraw false
try
(
local success = this.PlaceTreeBase()
if (success) then this.AttachTreeBase()
this.SetCommandPanelRedraw true
)
catch
(
format "Error: problem during execution"
this.SetCommandPanelRedraw true
)
)
return this.infoString
)
)
--struct for the UI
struct VegetationToolsUI
(
Form,
ToolTip,
InfoPanel,
NumSidesSpinner,
FillSpinner,
InsetSpinner,
SlopeSpinner,
RandomSpinner,
ProgBar,
IniFilePath = (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/RSL_Tools.ini"),
TreeGen = TreeBaseGeneratorStruct(),
TreePlacement = TreePlacementStruct(),
numSidesMin = 4,
fillMin = 0.25,
insetMin = 0.05,
ProcessingRollout,
TitleColor = RS_dotNetPreset.ARGB 48 48 48,
ButtonPadding = dotNetObject "System.Windows.Forms.Padding" 2,
------------------------------------------------------------------------------------------------------------------------------------------
--GENERAL FUNCTIONS
------------------------------------------------------------------------------------------------------------------------------------------
fn GenerateTreeBase s e =
(
rollout temprollout "Tree Base Generator"
(
label myLabel "Processing"
)
VegToolsUI.TreeGen.numsides = VegToolsUI.NumSidesSpinner.Text as integer
VegToolsUI.TreeGen.fill = VegToolsUI.FillSpinner.Text as float
VegToolsUI.TreeGen.inset = VegToolsUI.InsetSpinner.Text as float
theNewFloater = createDialog temprollout 200 30
VegToolsUI.InfoPanel.Text = "Processing..."
VegToolsUI.InfoPanel.Text = VegToolsUI.TreeGen.Process()
destroyDialog temprollout
),
fn PlaceTrees s e =
(
rollout temprollout "Tree Placement"
(
label myLabel "Processing"
)
theNewFloater = createDialog temprollout 200 30
VegToolsUI.TreePlacement.objSet = #()
local time = TimeStamp()
local numTrees = VegToolsUI.TreePlacement.PlaceObjects()
local timeTaken = (TimeStamp() - time) / 1000.0
-- print ("Time taken is " + timeTaken as string + " seconds")
if numTrees != undefined then
(
if numTrees == 1 then VegToolsUI.InfoPanel.Text = "1 tree placed."
else
VegToolsUI.InfoPanel.Text = (numTrees as string + " trees placed.")
)
destroyDialog temprollout
),
------------------------------------------------------------------------------------------------------------------------------------------
--LOAD/SAVE FUNCTIONS
------------------------------------------------------------------------------------------------------------------------------------------
fn SaveIniFile =
(
setINISetting VegToolsUI.IniFilePath "VegToolsUI" "WinLocX" (VegToolsUI.Form.Location.x as string)
setINISetting VegToolsUI.IniFilePath "VegToolsUI" "WinLocY" (VegToolsUI.Form.Location.y as string)
setINISetting VegToolsUI.IniFilePath "VegToolsUI" "WinWidth" (VegToolsUI.Form.Width as string)
setINISetting VegToolsUI.IniFilePath "VegToolsUI" "WinHeight" (VegToolsUI.Form.Height as string)
setINISetting VegToolsUI.IniFilePath "VegToolsUI" "NumSides" (VegToolsUI.NumSidesSpinner.Text as string)
setINISetting VegToolsUI.IniFilePath "VegToolsUI" "Fill" (VegToolsUI.FillSpinner.Text as string)
setINISetting VegToolsUI.IniFilePath "VegToolsUI" "Inset" (VegToolsUI.InsetSpinner.Text as string)
setINISetting VegToolsUI.IniFilePath "VegToolsUI" "Slope" (VegToolsUI.SlopeSpinner.Text as string)
setINISetting VegToolsUI.IniFilePath "VegToolsUI" "RandomRotation" (VegToolsUI.RandomSpinner.Text as string)
),
fn LoadIniFile =
(
--default values
local WinLocX = 100
local WinLocY = 100
local WinWidth = 200
local WinHeight = 200
local NumSides = 8
local Fill = 0.8
local Inset = 0.15
local Slope = 0.0
local RandomRotation = 0.0
try
(
WinLocX = getINISetting VegToolsUI.IniFilePath "VegToolsUI" "WinLocX" as integer
WinLocY = getINISetting VegToolsUI.IniFilePath "VegToolsUI" "WinLocY" as integer
WinWidth = getINISetting VegToolsUI.IniFilePath "VegToolsUI" "WinWidth" as integer
WinHeight = getINISetting VegToolsUI.IniFilePath "VegToolsUI" "WinHeight" as integer
NumSides = getINISetting VegToolsUI.IniFilePath "VegToolsUI" "NumSides" as integer
Fill = getINISetting VegToolsUI.IniFilePath "VegToolsUI" "Fill" as float
Inset = getINISetting VegToolsUI.IniFilePath "VegToolsUI" "Inset" as float
Slope = getINISetting VegToolsUI.IniFilePath "VegToolsUI" "Slope" as float
RandomRotation = getINISetting VegToolsUI.IniFilePath "VegToolsUI" "RandomRotation" as float
)
catch()
VegToolsUI.Form.Location = dotNetObject "system.drawing.point" WinLocX WinLocY
VegToolsUI.Form.Size = dotNetObject "System.Drawing.Size" WinWidth WinHeight
-- print VegToolsUI.numSidesMin
-- print VegToolsUI.fillMin
-- print VegToolsUI.insetMin
if (NumSides < VegToolsUI.numSidesMin) then NumSides = 8
if (Fill < VegToolsUI.fillMin) then Fill = 0.75
if (Inset < VegToolsUI.insetMin) then Inset = 0.1
VegToolsUI.NumSidesSpinner.Value = NumSides
VegToolsUI.FillSpinner.Value = Fill
VegToolsUI.InsetSpinner.Value = Inset
VegToolsUI.SlopeSpinner.Value = Slope
VegToolsUI.RandomSpinner.Value = RandomRotation
VegToolsUI.TreePlacement.InitCustomTreeList()
),
------------------------------------------------------------------------------------------------------------------------------------------
--UI
------------------------------------------------------------------------------------------------------------------------------------------
fn CreateUI =
(
-- form setup
Form = dotNetObject "maxCustomControls.maxForm"
Form.Text = "Vegetation Tools"
Form.StartPosition = (dotNetClass "System.Windows.Forms.FormStartPosition").manual
Form.Location = dotNetObject "system.drawing.point" 200 200
Form.MaximumSize = dotNetObject "System.Drawing.Size" 230 376
Form.MinimumSize = dotNetObject "System.Drawing.Size" 230 376
Form.FormBorderStyle = RS_dotNetPreset.FB_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 = 3
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 40) --banner
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 135) --tree base generator
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 116) --tree placement
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "percent" 100) --info panel
Table.ColumnCount = 1
Table.ColumnStyles.add (RS_dotNetObject.columnStyleObject "absolute" 160)
Table.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
Table.Margin = RS_dotNetPreset.Padding_None
Form.Controls.Add Table
RSBannerPanel = dotNetObject "System.Windows.Forms.Panel"
RSBannerPanel.borderstyle = RS_dotNetClass.borderStyleClass.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
Table.SetColumnSpan RSBannerPanel 2
RS_dotNetPreset.Font_Main = dotNetObject "System.Drawing.Font" "Futura" 10
-------------------------------------------------------------------------------
--TREE BASE GENERATOR
-------------------------------------------------------------------------------
TreeGenTable = dotNetObject "TableLayoutPanel"
TreeGenTable.Dock = RS_dotNetPreset.DS_Fill
TreeGenTable.RowCount = 5
TreeGenTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
TreeGenTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
TreeGenTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
TreeGenTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
TreeGenTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
TreeGenTable.ColumnCount = 2
TreeGenTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "absolute" 160)
TreeGenTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
Table.Controls.Add TreeGenTable 0 1
TreeGenLabel = RS_dotNetUI.InitLabel "Tree Base Generator" RS_dotNetPreset.TA.MiddleLeft
TreeGenLabel.BackColor = this.TitleColor
TreeGenLabel.Padding = dotNetObject "System.Windows.Forms.Padding" 4
ToolTip.SetToolTip TreeGenLabel "Create radial geometry for tree bases."
TreeGenTable.Controls.Add TreeGenLabel 0 0
TreeGenTable.SetColumnSpan TreeGenLabel 2
NumSidesLabel = RS_dotNetUI.InitLabel "Number Of sides" RS_dotNetPreset.TA.MiddleLeft
NumSidesLabel.Padding = dotNetObject "System.Windows.Forms.Padding" 4
TreeGenTable.Controls.Add NumSidesLabel 0 1
NumSidesSpinner = dotNetObject "NumericUpDown"
NumSidesSpinner.Dock = RS_dotNetPreset.DS.Fill
NumSidesSpinner.value = 4
NumSidesSpinner.Minimum = VegToolsUI.numSidesMin
NumSidesSpinner.Maximum = 32
TreeGenTable.Controls.Add NumSidesSpinner 1 1
FillLabel = RS_dotNetUI.InitLabel "Fill" RS_dotNetPreset.TA.MiddleLeft
FillLabel.Padding = dotNetObject "System.Windows.Forms.Padding" 4
TreeGenTable.Controls.Add FillLabel 0 2
FillSpinner = dotNetObject "NumericUpDown"
FillSpinner.Dock = RS_dotNetPreset.DS.Fill
FillSpinner.Minimum = VegToolsUI.fillMin
FillSpinner.Maximum = 0.95
FillSpinner.Increment = 0.05
FillSpinner.Value = 0.75
FillSpinner.DecimalPlaces = 2
TreeGenTable.Controls.Add FillSpinner 1 2
InsetLabel = RS_dotNetUI.InitLabel "Inset" RS_dotNetPreset.TA.MiddleLeft
InsetLabel.Padding = dotNetObject "System.Windows.Forms.Padding" 4
TreeGenTable.Controls.Add InsetLabel 0 3
InsetSpinner = dotNetObject "NumericUpDown"
InsetSpinner.Dock = RS_dotNetPreset.DS.Fill
InsetSpinner.Minimum = VegToolsUI.insetMin
InsetSpinner.Maximum = 0.2
InsetSpinner.Increment = 0.05
InsetSpinner.Value = 0.1
InsetSpinner.DecimalPlaces = 2
TreeGenTable.Controls.Add InsetSpinner 1 3
TreeGenButton = RS_dotNetUI.InitButton "Generate Tree Base"
TreeGenButton.Margin = this.ButtonPadding
dotNet.AddEventHandler TreeGenButton "Click" GenerateTreeBase
TreeGenTable.SetColumnSpan TreeGenButton 2
TreeGenTable.Controls.Add TreeGenButton 0 4
-------------------------------------------------------------------------------
--TREE PLACEMENT
-------------------------------------------------------------------------------
TreePlacementTable = dotNetObject "TableLayoutPanel"
TreePlacementTable.Dock = RS_dotNetPreset.DS_Fill
TreePlacementTable.RowCount = 4
TreePlacementTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 28)
TreePlacementTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 28)
TreePlacementTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 28)
TreePlacementTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 28)
TreePlacementTable.ColumnCount = 2
TreePlacementTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "absolute" 160)
TreePlacementTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
Table.Controls.Add TreePlacementTable 0 2
TreePlacementLabel = RS_dotNetUI.InitLabel "Tree Placement" RS_dotNetPreset.TA.MiddleLeft
TreePlacementLabel.Padding = dotNetObject "System.Windows.Forms.Padding" 4
TreePlacementLabel.BackColor = this.TitleColor
ToolTip.SetToolTip TreePlacementLabel "Vertically place trees on ground planes below."
TreePlacementTable.Controls.Add TreePlacementLabel 0 0
TreePlacementTable.SetColumnSpan TreePlacementLabel 2
SlopeLabel = RS_dotNetUI.InitLabel "Inherit Slope Angle" RS_dotNetPreset.TA.MiddleLeft
SlopeLabel.Padding = dotNetObject "System.Windows.Forms.Padding" 4
TreePlacementTable.Controls.Add SlopeLabel 0 1
SlopeSpinner = dotNetObject "NumericUpDown"
SlopeSpinner.Dock = RS_dotNetPreset.DS.Fill
SlopeSpinner.value = 0
SlopeSpinner.Minimum = 0
SlopeSpinner.Maximum = 1
SlopeSpinner.Increment = 0.1
SlopeSpinner.DecimalPlaces = 2
TreePlacementTable.Controls.Add SlopeSpinner 1 1
RandomLabel = RS_dotNetUI.InitLabel "Random Rotation" RS_dotNetPreset.TA.MiddleLeft
RandomLabel.Padding = dotNetObject "System.Windows.Forms.Padding" 4
TreePlacementTable.Controls.Add RandomLabel 0 2
RandomSpinner = dotNetObject "NumericUpDown"
RandomSpinner.Dock = RS_dotNetPreset.DS.Fill
RandomSpinner.value = 0
RandomSpinner.Minimum = 0
RandomSpinner.Maximum = 1
RandomSpinner.Increment = 0.1
RandomSpinner.DecimalPlaces = 2
TreePlacementTable.Controls.Add RandomSpinner 1 2
TreePlacementButton = RS_dotNetUI.InitButton "Place Selected Trees"
TreePlacementButton.Margin = this.ButtonPadding
dotNet.AddEventHandler TreePlacementButton "Click" PlaceTrees
TreePlacementTable.Controls.Add TreePlacementButton 0 3
TreePlacementTable.SetColumnSpan TreePlacementButton 2
-------------------------------------------------------------------------------
--INFO PANEL
-------------------------------------------------------------------------------
InfoPanel = RS_dotNetUI.InitLabel "Vegetation tools" RS_dotNetPreset.TA.MiddleLeft
InfoPanel.Padding = dotNetObject "System.Windows.Forms.Padding" 8
InfoPanel.BackColor = RS_dotNetPreset.ColorClass.black
Table.Controls.Add InfoPanel 0 3
--draw form
Form.ShowModeless()
Form
)
)
if VegToolsUI != undefined then
VegToolsUI.Form.Close()
VegToolsUI = VegetationToolsUI()
VegToolsUI.CreateUI()