home
StrataCafe Forums
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 StrataCafe
 Strata Design 3D CX: Lua Scripting
 Random Replication - Enhancements
 Forum Locked  Topic Locked
 Printer Friendly
Author Previous Topic Topic Next Topic  

jbradley
Inquisitive

USA
64 Posts

Posted - 06/19/2006 :  15:39:28  Show Profile
This post is to add some enhancements to the Random Replication script, covered in Part I - III of the tutorials on this fourm.

note: rotation is now updated to work with the settings

Here's a snapshot of the dialog:



What was changed:
Lots actually. This module is much more robust than that covered in the tutorials. This includes a full dialog to adjust minimum and maximum values on position, scale, and rotation. It also allows you to save the settings for the numbers you enter for the current application session (until you quit CX). This will allow you to replicate all selected instances in your scene or only the first instance selected. Finally, enhancements were added to perform selection checking to ensure that the script is unavailable until the user actually has something selected.

As always, additional enhancements could be added. Support for autofilling in the input fields with numbers from selected objects or for turning on and off features are possibilities that you could explore.

Copy/Paste the code below into a new text file and save it as "ReplicateModule.lua". Place this file in your Scripts/Autoload directory.

--	=========================================================================
--	Random Replicate Lua Module for Strata CX 5
--
--	MODULE		ReplicateModule
--	VERSION		1.0
--	AUTHOR		Jon Bradley
--	DATE		06.18.2006
--	
--	DESCRIPTION
--	
--	This module is to randomly replicate either the first or all in
--	the list of selected instances in your model view of CX 5.
--  
--	LICENSE
--  
--	This work is licensed under the Creative Commons Attribution 2.5 License.
--	http://creativecommons.org/licenses/by/2.5/legalcode
--	=========================================================================


module("ReplicateModule", package.seeall)

--  Internal constants for minimum and maximum
--  translation, scale and rotation
local pMin = { x=-5, y=-5, z=-5 }
local pMax = { x=5, y=5, z=5 }
local sMin = { x=0.1, y=0.1, z=0.1 }
local sMax = { x=1, y=1, z=1 }
local rMin ={ x=-360, y=-360, z=-360 }
local rMax ={ x=360, y=360, z=360 }

function Replicate(numCopies, doAll, values)

    local c = s3d.database.GetActiveContext()
    local m = c and c:GetManipulatorManager()
    local size = m and m:GetSize()

    if size > 0 then

        -- A local function inside our Replicate function call that
        -- sets the properties of the duplicated instance.

        -- Note: We use this function instead of having to write out all
        -- of this code twice - once if we're duplicating the first
        -- selected instance, and second if we're duplicating all
        local function setProperties(v,inst)
        
            --	Random translation within defined limits
            local tx = v.position.min.x + math.random()*( v.position.max.x - v.position.min.x )
            local ty = v.position.min.y + math.random()*( v.position.max.y - v.position.min.y )
            local tz = v.position.min.z + math.random()*( v.position.max.z - v.position.min.z )
            local position = s3d.vec.Point3d(tx,ty,tz)
            
            --	Random scale within defined limits
            local sx = v.scale.min.x + math.random()*( v.scale.max.x - v.scale.min.x )
            local sy = v.scale.min.y + math.random()*( v.scale.max.y - v.scale.min.y )
            local sz = v.scale.min.z + math.random()*( v.scale.max.z - v.scale.min.z )
            local scale = s3d.vec.Point3d(sx,sy,sz)
            
             --  Random rotation within defined limits
            local rx = math.rad(v.rotation.min.x + math.random()*( v.rotation.max.x - v.rotation.min.x ) )
            local ry = math.rad(v.rotation.min.y + math.random()*( v.rotation.max.y - v.rotation.min.y ) )
            local rz = math.rad(v.rotation.min.z + math.random()*( v.rotation.max.z - v.rotation.min.z ) )
            local c1 = math.cos(ry/2)
            local s1 = math.sin(ry/2)
            local c2 = math.cos(rz/2)
            local s2 = math.sin(rz/2)
            local c3 = math.cos(rx/2)
            local s3 = math.sin(rx/2)

            local qx = s1*s2*c3 + c1*c2*s3
            local qy = s1*c2*c3 + c1*s2*s3
            local qz = c1*s2*c3 + s1*c2*s3
            local w = c1*c2*c3 - s1*s2*s3
            local rotation = s3d.vec.Quaternion(qx,qy,qz,w)
            
            --  Set values on the instance
            inst:SetTranslationAt(0,position)
            inst:SetScaleAt(0,scale)
            inst:SetRotationAt(0, rotation )
            
         end

        if doAll == 1 then

            --  Create a table to contain all our selected instances
            --  and loop over all selected instances to store them
            local instList = {}
            for s=1, size do
                instList[s] = m:GetIndexedInstance(s)
            end
            --  Finally, for all the instances we've got, duplicate
            --  each one requested number of times
            for s=1, size do
                for t=1, numCopies do
                    local inst = instList[s]:Clone()
                    c:AddInstance(inst)
                    setProperties(values,inst)    
                end
            end

        else

            i = m:GetIndexedInstance(size)
            for t=1, numCopies do
                local inst = i:Clone()
                c:AddInstance(inst)
                setProperties(values,inst)
            end

        end

        c:Refresh()

	else
		s3d.ui.Alert ("You must select an object.")
	end

end

function RandomReplicateUI()
    
	local d = s3d.ui.Dialog("Random Replicate")

    local transCluster = d:BeginCluster("Transformations", false, 225)

        d:AddStaticText("")
        d:AddStaticText("Position Min:")
        d:AddStaticText("Position Max:")
        d:AddStaticText("Scale Min:")
        d:AddStaticText("Scale Max:")
        d:AddStaticText("Rotation Min:")
        d:AddStaticText("Rotation Max:")
        
        --  Create input fields, populated with local min/max constants        
        d:AddColumn()
        d:AddStaticText("X")
        local txMin = d:AddNumberText( pMin.x,2,50 )
        local txMax = d:AddNumberText( pMax.x,2,50 )
        local sxMin = d:AddNumberText( sMin.x,2,50 )
        local sxMax = d:AddNumberText( sMax.x,2,50 )
        local rxMin = d:AddNumberText( rMin.x,2,50 )
        local rxMax = d:AddNumberText( rMax.x,2,50 )
        d:AddColumn()
        d:AddStaticText("Y")
        local tyMin = d:AddNumberText( pMin.y,2,50 )
        local tyMax = d:AddNumberText( pMax.y,2,50 )
        local syMin = d:AddNumberText( sMin.y,2,50 )
        local syMax = d:AddNumberText( sMax.y,2,50 )
        local ryMin = d:AddNumberText( rMin.y,2,50 )
        local ryMax = d:AddNumberText( rMax.y,2,50 )
        d:AddColumn()
        d:AddStaticText("Z")
        local tzMin = d:AddNumberText( pMin.z,2,50 )
        local tzMax = d:AddNumberText( pMax.z,2,50 )
        local szMin = d:AddNumberText( sMin.z,2,50 )
        local szMax = d:AddNumberText( sMax.z,2,50 )
        local rzMin = d:AddNumberText( rMin.z,2,50 )
        local rzMax = d:AddNumberText( rMax.z,2,50 )
        d:AddColumn()
    d:EndCluster()
    
    d:AddStaticText("")
    
    d:BeginCluster("Settings", true, 225)
        -- Handle UI input for number of copies of each selected instance
        d:AddStaticText("Number of Copies:")
        local doAll = d:AddCheckbox("Replicate All Selected")
        local saveSettings = d:AddCheckbox("Save settings for this session")
        d:SetValue(saveSettings, 1)
        
        d:AddColumn()
        local numCopies = d:AddNumberText(0,0,40)
        --  Use all selected instances or only the first
    d:EndCluster()
	
	d:SetLabel(s3d.ui.Dialog.kOkay, "Replicate")
	d:SetLabel(s3d.ui.Dialog.kCancel, "Cancel")

	local function checkUI(id)
		if id == s3d.ui.Dialog.kOkay then
			local num = d:GetValue(numCopies)
			local dupAll = d:GetValue(doAll)
			if num ~= 0 then

                --  Now, have some fun grabbing all the values and converting them
                --  to internal CX units.
                local c = s3d.database.GetActiveContext()
                local u = c:GetUnits()
                
                local values = {
                    --  position min/max
                    position = {
                            min = {
                                    x=u:ConvertToStrataUnits( d:GetValue(txMin) ),
                                    y=u:ConvertToStrataUnits( d:GetValue(tyMin) ),
                                    z=u:ConvertToStrataUnits( d:GetValue(tzMin) )
                                },
                            max = {
                                    x=u:ConvertToStrataUnits( d:GetValue(txMax) ),
                                    y=u:ConvertToStrataUnits( d:GetValue(tyMax) ),
                                    z=u:ConvertToStrataUnits( d:GetValue(tzMax) )
                                }
                        },
                    --  scale min/max
                    scale = {
                            min = {
                                    x=u:ConvertToStrataUnits( d:GetValue(sxMin) ),
                                    y=u:ConvertToStrataUnits( d:GetValue(syMin) ),
                                    z=u:ConvertToStrataUnits( d:GetValue(szMin) )
                                },
                            max = {
                                    x=u:ConvertToStrataUnits( d:GetValue(sxMax) ),
                                    y=u:ConvertToStrataUnits( d:GetValue(syMax) ),
                                    z=u:ConvertToStrataUnits( d:GetValue(szMax) )
                                }
                        },
                    --  rotation min/max
                    rotation = {
                            min = {
                                    x=d:GetValue(rxMin),
                                    y=d:GetValue(ryMin),
                                    z=d:GetValue(rzMin)
                                },
                            max = {
                                    x=d:GetValue(rxMax),
                                    y=d:GetValue(ryMax),
                                    z=d:GetValue(rzMax)
                                }
                        }
                }
                
                --  If user requested to save settings for this application session
                --  save the settings.
                if d:GetValue(saveSettings) == 1 then
                    pMin = { x=d:GetValue(txMin), y=d:GetValue(tyMin), z=d:GetValue(tzMin) }
                    pMax = { x=d:GetValue(txMax), y=d:GetValue(tyMax), z=d:GetValue(tzMax) }
                    sMin = { x=d:GetValue(sxMin), y=d:GetValue(syMin), z=d:GetValue(szMin) }
                    sMax = { x=d:GetValue(sxMax), y=d:GetValue(syMax), z=d:GetValue(szMax) }
                    rMin ={ x=d:GetValue(rxMin), y=d:GetValue(ryMin), z=d:GetValue(rzMin) }
                    rMax ={ x=d:GetValue(rxMax), y=d:GetValue(ryMax), z=d:GetValue(rzMax) }
                end
                
                --  Finally, perform the replication
				Replicate(num, dupAll, values)
			end
		end
	end
	
	d:Present( checkUI )
	
end

local function GetActiveSelectionSize ()
	local c = s3d.database.GetActiveContext()
	local m = c and c:GetManipulatorManager()
	return m and m:GetSize()
end

local function EnableWithSelection (item)
	local size = GetActiveSelectionSize()
	return size and size > 0
end

local separator = { "-" }
local randReplicateMenuItem = { "Random Replicate", 
        function (menuItem)
            RandomReplicateUI()
        end,
        EnableWithSelection
    }
    
-- Insert this menu item (and a separator) into the Scripting Menu
table.insert(s3d.ui.scripting_menu, separator)
table.insert(s3d.ui.scripting_menu, randReplicateMenuItem)


Good luck!



Jon Bradley
Animator / VFX Artist

Edited by - jbradley on 06/19/2006 16:46:25

jbradley
Inquisitive

USA
64 Posts

Posted - 07/27/2006 :  12:52:26  Show Profile
This just in:
Unfortunately, the autoloading mechanism in CX 5 does not support Mac line endings in the text file. To alleviate this, ensure that the line endings are either Unix or DOS (Windows) line endings.

You will need to check your text or code editor to make sure that it has the capability to modify the line endings in the file.

We found this after the last 3d Power bulletin which included this script. If you were one of the users that downloaded the script and it wouldn't work for you, just adjust the line endings in the file and it should then autoload properly.

As always, feel free to post any questions.

Jon Bradley
Animator / VFX Artist
Go to Top of Page

Michael
Admin

Canada
2688 Posts

Posted - 07/27/2006 :  14:28:24  Show Profile  Visit Michael's Homepage  Send Michael an AOL message
The download we had up for the Random Replication script and the latest one for the Fresnel Shader have both been updated with the correct line endings, if anyone wants to redownload the scripts.

http://register.strata.com/bulletins/sb062706/ReplicateModule.zip

http://register.strata.com/bulletins/sb072506/Fresnel_ScriptFX_Shader.zip

Michael Luscombe
Go to Top of Page
  Previous Topic Topic Next Topic  
 Forum Locked  Topic Locked
 Printer Friendly
Jump To:
StrataCafe Forums © 2009 StrataCafe Go To Top Of Page
Snitz Forums 2000