|
struct Test_EditGuidesModifier
|
|
(
|
|
-- Tests that a bug which caused Max to hang when edit guides are added to a skinned wrapped spline on shape modifier is fixed
|
|
function Test_EditGuidesDoesntCrashWithGuidesOnSplineAndSkinWrappedShape =
|
|
(
|
|
local distributionObject = Circle()
|
|
select distributionObject
|
|
|
|
max modify mode
|
|
|
|
modPanel.addModToSelection (Edit_Spline ())
|
|
modPanel.addModToSelection (Skin_Wrap ())
|
|
modPanel.addModToSelection (Ox_Guides_on_Spline ())
|
|
modPanel.addModToSelection (Ox_Edit_Guides ())
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
-- Tests that changes made to shape of guides are loaded along with the scene
|
|
function Test_SaveAndLoadShapeChanges =
|
|
(
|
|
-- Create a plane with 1x1 segments
|
|
distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
distributionObjectName = distributionObject.name
|
|
max modify mode
|
|
select distributionObject
|
|
|
|
-- Add a guides from mesh modifier with per-vertex guide distribution, which should make the total number of guides 4
|
|
guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.numSegs = 3
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
editGuidesInstance = Ox_Edit_Guides()
|
|
modPanel.addModToSelection editGuidesInstance
|
|
|
|
-- Modify the first strand's shape
|
|
editGuidesInstance.SetStrandShape 0 #( [0,0,0], [1,1,1], [5,5,5] )
|
|
|
|
pointsBeforeSaving = editGuidesInstance.GetStrandShape 0
|
|
|
|
-- Save and reload the scene
|
|
holdMaxFile()
|
|
fetchMaxFile quiet:true
|
|
|
|
-- Make sure that the change we made persists
|
|
distributionObject = GetNodeByName distributionObjectName
|
|
|
|
max modify mode
|
|
select distributionObject
|
|
|
|
editGuidesInstance = distributionObject.modifiers[1]
|
|
strandPoints = editGuidesInstance.GetStrandShape 0
|
|
|
|
EAssert.AreEqual pointsBeforeSaving[1] strandPoints[1]
|
|
EAssert.AreEqual pointsBeforeSaving[2] strandPoints[2]
|
|
EAssert.AreEqual pointsBeforeSaving[3] strandPoints[3]
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
function Test_SoftSelection =
|
|
(
|
|
-- Create a plane with 1x1 segments
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
local distributionObjectName = distributionObject.name
|
|
max modify mode
|
|
select distributionObject
|
|
|
|
-- Add a guides from mesh modifier with per-vertex guide distribution, which should make the total number of guides 4
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.numSegs = 3
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
local editGuidesInstance = Ox_Edit_Guides()
|
|
modPanel.addModToSelection editGuidesInstance
|
|
|
|
-- Select first strand only
|
|
editGuidesInstance.SelectRoots #{1}
|
|
|
|
-- By default only one guide should be selected in the result
|
|
local guidesCopy = instance distributionObject
|
|
convertTo guidesCopy GuidesObject
|
|
strandSelection = ( guidesCopy.GetGuides() ).GetStrandSelection()
|
|
EAssert.AreEqual 4 (strandSelection.count)
|
|
EAssert.AreEqual true strandSelection[1]
|
|
EAssert.AreEqual false strandSelection[2]
|
|
EAssert.AreEqual false strandSelection[3]
|
|
EAssert.AreEqual false strandSelection[4]
|
|
delete guidesCopy
|
|
|
|
-- Turn on soft selection
|
|
editGuidesInstance.useSoftSelection = true
|
|
|
|
-- All guides should now be selected due to soft selection
|
|
guidesCopy = instance distributionObject
|
|
convertTo guidesCopy GuidesObject
|
|
strandSelection = ( guidesCopy.GetGuides() ).GetStrandSelection()
|
|
EAssert.AreEqual 4 (strandSelection.count)
|
|
EAssert.AreEqual true strandSelection[1]
|
|
EAssert.AreEqual true strandSelection[2]
|
|
EAssert.AreEqual true strandSelection[3]
|
|
EAssert.AreEqual true strandSelection[4]
|
|
delete guidesCopy
|
|
|
|
delete distributionObject
|
|
),
|
|
|
|
function Test_SubObjectNamedSelectionSets =
|
|
(
|
|
-- Create a plane with 1x1 segments, 4 vertices
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
distributionObjectName = distributionObject.name
|
|
max modify mode
|
|
select distributionObject
|
|
|
|
-- Add a guides from mesh modifier with per-vertex guide distribution, which should make the total number of guides 4
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.numSegs = 3
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
local editGuidesInstance = Ox_Edit_Guides()
|
|
modPanel.addModToSelection editGuidesInstance
|
|
subObjectLevel = 1
|
|
|
|
-- No named selection sets by default
|
|
EAssert.AreEqual 0 (editGuidesInstance.NamedSelectionSetCount())
|
|
|
|
-- Select first two strands and record them as a named selection set
|
|
editGuidesInstance.SelectRoots #{1,2}
|
|
editGuidesInstance.AddNamedSelectionSetFromSelection "guides1"
|
|
EAssert.AreEqual 1 (editGuidesInstance.NamedSelectionSetCount())
|
|
|
|
-- TODO: Undoing will undo this whole function, find a way to only undo the last action
|
|
---- Undo, set should be deleted
|
|
--max undo
|
|
--EAssert.AreEqual 0 (editGuidesInstance.NamedSelectionSetCount())
|
|
|
|
---- Redo, set should be restored
|
|
--max redo
|
|
--EAssert.AreEqual 1 (editGuidesInstance.NamedSelectionSetCount())
|
|
|
|
-- Change strand selection and then activate the state to ensure strand selection was restored
|
|
editGuidesInstance.SelectRoots #{3,4}
|
|
strandSelection = editGuidesInstance.GetSelected()
|
|
EAssert.IsFalse strandSelection[1]
|
|
EAssert.IsFalse strandSelection[2]
|
|
EAssert.IsTrue strandSelection[3]
|
|
EAssert.IsTrue strandSelection[4]
|
|
|
|
editGuidesInstance.ActivateNamedSelectionSet "guides1"
|
|
strandSelection = editGuidesInstance.GetSelected()
|
|
EAssert.IsTrue strandSelection[1]
|
|
EAssert.IsTrue strandSelection[2]
|
|
EAssert.IsFalse strandSelection[3]
|
|
EAssert.IsFalse strandSelection[4]
|
|
|
|
-- Select other two strands and create a second set
|
|
editGuidesInstance.SelectRoots #{3,4}
|
|
editGuidesInstance.AddNamedSelectionSetFromSelection "guides2"
|
|
|
|
-- Hold/fetch the scene and make sure the two selection sets are still there
|
|
holdMaxFile()
|
|
fetchMaxFile quiet:true
|
|
|
|
distributionObject = GetNodeByName distributionObjectName
|
|
max modify mode
|
|
select distributionObject
|
|
editGuidesInstance = distributionObject.modifiers[1]
|
|
subObjectLevel = 1
|
|
|
|
EAssert.AreEqual 2 (editGuidesInstance.NamedSelectionSetCount())
|
|
editGuidesInstance.ActivateNamedSelectionSet "guides2"
|
|
strandSelection = editGuidesInstance.GetSelected()
|
|
EAssert.IsFalse strandSelection[1]
|
|
EAssert.IsFalse strandSelection[2]
|
|
EAssert.IsTrue strandSelection[3]
|
|
EAssert.IsTrue strandSelection[4]
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
function Test_EditGuidesModifierGroupsOnFirstRootChannelSetThePropagationStrandGroupValue =
|
|
(
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
|
|
max modify mode
|
|
|
|
-- Set up the mesh from strands modifier, use per vertex distribution
|
|
select distributionObject
|
|
|
|
-- Guides from surface modifier with vertex distribution and 2 points per strand, no randomness in length, and strand length of 1
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.NumSegs = 2
|
|
|
|
-- Edit guides modifier which sets the first two strands to use group #2
|
|
local editGuidesInstance = Ox_Edit_Guides()
|
|
modPanel.addModToSelection editGuidesInstance
|
|
editGuidesInstance.CreateChannel true "Groups"
|
|
|
|
editGuidesInstance.SelectRoots #{1,2}
|
|
editGuidesInstance.SetChannelValueToSelection true 1 2.0f
|
|
|
|
editGuidesInstance.SelectRoots #{3,4}
|
|
editGuidesInstance.SetChannelValueToSelection true 1 3.0f
|
|
|
|
-- Render settings modifier with global radius of 2 for group 2
|
|
local renderSettingsModifier = Ox_Render_Settings()
|
|
modPanel.addModToSelection renderSettingsModifier
|
|
renderSettingsModifier.radius = 2
|
|
renderSettingsModifier.groupID = 2
|
|
|
|
-- Render settings modifier with global radius of 3 for group 3
|
|
local renderSettingsModifier = Ox_Render_Settings()
|
|
modPanel.addModToSelection renderSettingsModifier
|
|
renderSettingsModifier.radius = 3
|
|
renderSettingsModifier.groupID = 3
|
|
|
|
-- Mesh from strands modifier should respect the resulting strand widths
|
|
local meshFromStrandsModifier = Ox_Mesh_from_Strands()
|
|
modPanel.addModToSelection meshFromStrandsModifier
|
|
meshFromStrandsModifier.type = 1
|
|
|
|
EAssert.AreNearEqual 4 ( distance $.mesh.verts[1].position $.mesh.verts[2].position )
|
|
EAssert.AreNearEqual 6 ( distance $.mesh.verts[9].position $.mesh.verts[10].position )
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
-- Tests that "push away from mesh" functionality can be invoked while editing guides without crashing them
|
|
function Test_PushAwayFromMeshInSubObjectModeWithoutCrash =
|
|
(
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
|
|
max modify mode
|
|
|
|
-- Set up the mesh from strands modifier, use per vertex distribution
|
|
select distributionObject
|
|
|
|
-- Guides from surface modifier with vertex distribution and 2 points per strand, no randomness in length, and strand length of 1
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.NumSegs = 2
|
|
|
|
-- Edit guides modifier which sets the first two strands to use group #2
|
|
local editGuidesInstance = Ox_Edit_Guides()
|
|
modPanel.addModToSelection editGuidesInstance
|
|
|
|
-- Go into sub-object mode
|
|
subobjectLevel = 2
|
|
|
|
editGuidesInstance.PushAwayFromMesh false
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
function Test_DeletingGuidesClearsSelection =
|
|
(
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
|
|
max modify mode
|
|
|
|
-- Set up the mesh from strands modifier, use per vertex distribution
|
|
select distributionObject
|
|
|
|
-- Guides from surface modifier with vertex distribution and 2 points per strand, no randomness in length, and strand length of 1
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.NumSegs = 2
|
|
|
|
-- Edit guides modifier which sets the first two strands to use group #2
|
|
local editGuidesInstance = Ox_Edit_Guides()
|
|
modPanel.addModToSelection editGuidesInstance
|
|
|
|
-- Go into sub-object mode
|
|
subobjectLevel = 1
|
|
editGuidesInstance.SelectRoots #{1,2}
|
|
|
|
-- Delete selected roots
|
|
actionMan.executeAction 0 "40020"
|
|
|
|
-- Remaining two strands are not selected after deletion
|
|
local strandSelection = editGuidesInstance.GetSelected()
|
|
EAssert.IsFalse strandSelection[1]
|
|
EAssert.IsFalse strandSelection[2]
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
function Test_MoveControlPoints =
|
|
(
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
max modify mode
|
|
|
|
-- Set up the mesh from strands modifier, use per vertex distribution
|
|
select distributionObject
|
|
|
|
-- Guides from surface modifier with vertex distribution and 2 points per strand, no randomness in length, and strand length of 1
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.randomness = 0
|
|
guidesFromSurfaceModifier.NumSegs = 2
|
|
|
|
local editGuidesInstance = Ox_Edit_Guides()
|
|
modPanel.addModToSelection editGuidesInstance
|
|
|
|
-- Go into control points sub-object mode
|
|
subobjectLevel = 2
|
|
editGuidesInstance.SelectRoots #{1,2}
|
|
|
|
-- Move the selected control points
|
|
editGuidesInstance.MoveSelectedControlPoints [10,0,0]
|
|
|
|
-- Make sure tips of guides match the control point positions
|
|
local myHair = ( editGuidesInstance.GetGuides() ).AsHair()
|
|
EAssert.ArePointsNearEqual ( editGuidesInstance.GetControlPointPosition 0 ) ( myHair.GetPointT 0 1 )
|
|
EAssert.ArePointsNearEqual ( editGuidesInstance.GetControlPointPosition 1 ) ( myHair.GetPointT 1 1 )
|
|
EAssert.ArePointsNearEqual ( editGuidesInstance.GetControlPointPosition 2 ) ( myHair.GetPointT 2 1 )
|
|
EAssert.ArePointsNearEqual ( editGuidesInstance.GetControlPointPosition 3 ) ( myHair.GetPointT 3 1 )
|
|
|
|
delete distributionObject
|
|
),
|
|
|
|
function Test_PaintRootSelection =
|
|
(
|
|
local guidesFromSurfaceModifier = undefined
|
|
undo "Setup" on
|
|
(
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
max modify mode
|
|
|
|
-- Set up the mesh from strands modifier, use per vertex distribution
|
|
select distributionObject
|
|
|
|
-- Guides from surface modifier with vertex distribution and 2 points per strand, no randomness in length, and strand length of 1
|
|
guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.randomness = 0
|
|
guidesFromSurfaceModifier.NumSegs = 2
|
|
|
|
local editGuidesInstance = Ox_Edit_Guides()
|
|
modPanel.addModToSelection editGuidesInstance
|
|
)
|
|
|
|
-- Go into control points sub-object mode
|
|
subobjectLevel = 3
|
|
|
|
editGuidesInstance.SetBrushType 6
|
|
|
|
-- Set active viewport to be the front view nd zoom to extents
|
|
viewport.activeViewport = 2
|
|
max tool zoomextents
|
|
local viewSize = getViewSize()
|
|
|
|
-- Set brush strength to maximum and drag brush along first two strands
|
|
editGuidesInstance.SetBrushSize (viewSize.x/10) (viewSize.x/10)
|
|
editGuidesInstance.SetBrushStrength 10
|
|
|
|
-- At this point no strandsshould have root selection
|
|
local myGuides = editGuidesInstance.GetGuides()
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 0)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 1)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 2)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 3)
|
|
|
|
-- Paint first two strands
|
|
undo "First drag" on
|
|
(
|
|
editGuidesInstance.DragBrush [viewSize.x/3, viewSize.y/2] [viewSize.x/2, viewSize.y/2] 3
|
|
)
|
|
|
|
-- Two roots should have some weight
|
|
EAssert.IsTrue ((myGuides.GetRootData 0 0) > 0.1)
|
|
EAssert.IsTrue ((myGuides.GetRootData 0 1) > 0.1)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 2)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 3)
|
|
|
|
-- Paint last two strands
|
|
undo "Second drag" on
|
|
(
|
|
editGuidesInstance.DragBrush [viewSize.x/2, viewSize.y/2] [viewSize.x*3/4, viewSize.y/2] 3
|
|
)
|
|
|
|
undo "Third drag" on
|
|
(
|
|
editGuidesInstance.DragBrush [viewSize.x/2, viewSize.y/2] [viewSize.x*3/4, viewSize.y/2] 3
|
|
)
|
|
|
|
-- All roots should have some weight
|
|
EAssert.IsTrue ((myGuides.GetRootData 0 0) > 0.1)
|
|
EAssert.IsTrue ((myGuides.GetRootData 0 1) > 0.1)
|
|
EAssert.IsTrue ((myGuides.GetRootData 0 2) > 0.1)
|
|
EAssert.IsTrue ((myGuides.GetRootData 0 3) > 0.1)
|
|
|
|
-- Undo once to revert last change
|
|
max undo
|
|
|
|
myGuides = editGuidesInstance.GetGuides()
|
|
EAssert.IsTrue ((myGuides.GetRootData 0 0) > 0.1)
|
|
EAssert.IsTrue ((myGuides.GetRootData 0 1) > 0.1)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 2)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 3)
|
|
|
|
max undo
|
|
|
|
myGuides = editGuidesInstance.GetGuides()
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 0)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 1)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 2)
|
|
EAssert.AreEqual 0 (myGuides.GetRootData 0 3)
|
|
|
|
delete distributionObject
|
|
)
|
|
)
|
|
|
|
EUnit.AddTestClass Test_EditGuidesModifier
|
|
ok
|