PDA

View Full Version : CgTalk Maxscript Challenge 020: "Build a Better Tool"


erilaz
06-23-2008, 01:22 AM
CgTalk Maxscript Challenge 020: "Build a Better Tool"

DESCRIPTION: A simple task, but with complicated implications. Pick a tool in max (any tool; extrude, array, rename, save etc.) and make it better. This could be as simple as adding a new feature, or go as far as replacing the entire system behind the tool with something more optimised.
Keep in mind that there are a lot of tools out there that are built for this very purpose, so try to be original or expand on already existing concepts.

DEADLINE: 01/07/2008

RULES:

Do NOT post your code until the deadline!
Code from scratch. Try not to use pre-exisitng functions or plugins.
Show your script references, if any (eg. Looking at another script to assist you).
You are encouraged to ask for help where needed, but try to do it on your own. The maxscript reference is an invaluable resource.
Post your final script inside [CODE] tags (located on your posting toolbar).
Post all code into THIS thread.
Post the max version you coded in, plus any maxscript extensions you used. (Thanks galagast!)
Try to finish the challenge in the proscribed time. There is no definite time limit.
NOTES: Enjoy! This should be diverse!

erilaz
06-24-2008, 02:23 AM
I've decided to shorten the deadline. I think I give you guys way too much time to work on these. The challenges should be short and sharp. :)

muzbee3d
06-24-2008, 04:44 AM
CgTalk Maxscript Challenge 020: "Build a Better Tool"


DEADLINE: 01/07/2008



G-DAY mate....

Here in the USA we see your date as January 1st 2008
I presume that you mean to us up here, the deadline is 07-01-08 /
July 1st 2008

Good on Ya http://forums.cgsociety.org/images/icons/icon11.gif

MB

erilaz
06-24-2008, 05:00 AM
G-DAY mate....

Here in the USA we see your date as January 1st 2008
I presume that you mean to us up here, the deadline is 07-01-08 /
July 1st 2008

Good on Ya http://forums.cgsociety.org/images/icons/icon11.gif

MB

Well, I see the middle endian system of date as ambiguous, especially for programmers. Date progression should logically be by little endian form; day->month->year (Actually, if we were to really split hairs, big endian form is the most logical system).

If it confuses you, I can always make the date alphanumerically instead, but since the rest of the world predominantly uses the little endian method, i'm sure you can adapt. :D

LoneRobot
06-24-2008, 09:28 AM
oh no!! i missed the deadline! ;)

salmonmoose
06-25-2008, 04:17 AM
Well, I see the middle endian system of date as ambiguous, especially for programmers. Date progression should logically be by little endian form; day->month->year (Actually, if we were to really split hairs, big endian form is the most logical system).

If it confuses you, I can always make the date alphanumerically instead, but since the rest of the world predominantly uses the little endian method, i'm sure you can adapt. :D

Yeah, internally I always use YYYYMMDDHHMMSS :) (or seconds since 1 jan 1970)

MMDDYYYY is not only confusing it's not very useful :)

erilaz
06-30-2008, 04:44 PM
Well, I might as well be the first:

It's not all that robust, but I decided to try and expand the clone tool. This script creates an option to clone evenly along a picked spline, or clone randomly outward from the selection based on a maximum unit distance. I was going to add the normal cloner, but ran out of time:

[Max 2009 SP1]



(

-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
fn cloneRandom obj method num maxD =
(
for i = 1 to num do
(
offst = random (obj.pos-[maxD,maxD,MaxD]) (obj.pos+[maxD,maxD,MaxD])
maxOps.CloneNodes obj offset:offst cloneType:method
)
)
-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
fn cloneToSpline splineObj obj method num =
(
newArray = #()
spacing = 1.00/num as float
for i = 1 to num do
(
interpValue = spacing*i
offst = pathInterp splineObj interpValue
maxOps.CloneNodes obj cloneType:method actualNodeList:obj newNodes:&newArray
obj = newArray
obj.pos = offst
)
)
-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
rollout cloneToSplineRollout "Clone to Spline" width:160 height:200
(
local pickedSpline = "" ---local picked object
pickbutton pickSpline "Pick Spline" pos:[19,14] width:120 height:30
spinner numClones "Number of Copies" pos:[15,129] width:132 height:16 range:[1,10000,1] type:#integer scale:1
radiobuttons cloneType "" pos:[41,68] width:73 height:48 labels:#("Copy", "Instance", "Reference")

groupBox Object "Object" pos:[31,51] width:93 height:71
button okButton_spline "OK" pos:[37,162] width:81 height:23

on pickSpline picked obj do
(
pickedSpline = obj
pickSpline.text = pickedSpline.name
)

on okButton_spline pressed do
(
if pickedSpline != "" then
(
cloneMethod = case cloneType.state of
(
1:#copy
2:#instance
3:#reference
)
try
cloneToSpline pickedSpline $ cloneMethod numClones.value
catch
messageBox "No object to clone"
)
else
(
messageBox "You must pick a spline path to clone to"
)
)
)
-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
rollout cloneRandomRollout "Clone Randomly" width:160 height:200
(
spinner numClones "Number of Copies" pos:[15,129] width:132 height:16 range:[1,10000,1] type:#integer scale:1
radiobuttons cloneType "" pos:[41,27] width:73 height:48 labels:#("Copy", "Instance", "Reference")
GroupBox object "Object" pos:[31,13] width:93 height:71
button okButton_spline "OK" pos:[37,162] width:81 height:23
spinner maxDist "Max Dist from Obj" pos:[15,105] width:132 height:16 range:[1,10000,1] type:#integer scale:1
on okButton_spline pressed do
(
cloneMethod = case cloneType.state of
(
1:#copy
2:#instance
3:#reference
)
try
cloneRandom $ cloneMethod numClones.value maxDist.value
catch
messageBox "No object to clone"
)
)
-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
cloneDialog = newRolloutFloater "Attack of the Cloned" 160 450
addRollout cloneToSplineRollout cloneDialog
addRollout cloneRandomRollout cloneDialog

-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
-----TestCode-----
--cloneToSpline $Line01 $ #copy 50
--cloneRandom $ #copy 50 50

)


(Just for fun, you get some quite cool patterns if you clone the spline you picked to clone to as well).

martroyx
06-30-2008, 07:41 PM
Well, that was a short deadline...I just saw the challenge today, so here a little try with random selection, it take a selection and split it into layer that you can select to assign material or whatever :-P


(
Global SDx
Try Destroydialog SDx catch()
Local Do_Randomize,Do_Reset,Do_Select,Do_Rename
Local TsArray = #()
Local Pfix = "SD"

fn Do_Randomize =
(
if selection.count != 0 then
(
Do_Reset()
TsArray=selection as array
---------------------------------------------------
Local Tnumb = TsArray.count
Local kk = (Tnumb/(SDx.spn_lv1.value as float))
Local SubArray = #{1..(Tnumb)}
Local NbArray = #()
---------------------------------------------------
for f in 1 to SDx.spn_lv1.value do
(
layermanager.newLayerFromName (Pfix+"_Level"+(f as string))
append NbArray 0
)
---------------------------------------------------
While SubArray.isEmpty == false do
(
Tx = Random 1 SubArray.count
Vx = (ceil ((TsArray.count-Tnumb)/kk))as integer
if Vx == 0 then Vx = 1
if SubArray[Tx] == true then
(
Sx = LayerManager.getLayerFromName (Pfix+"_Level"+(Vx as string))
Sx.addNode TsArray[Tx]
deleteItem SubArray Tx
NbArray[Vx] += 1
Tnumb -= 1
)
)
---------------------------------------------------
for f in 1 to SDx.spn_lv1.value do
(
execute ("SDx.bt_S"+(f as string)+".enabled = true")
execute ("SDx.bt_S"+(f as string)+".text = "+"\""+(NbArray[f] as string)+"\"")
)
---------------------------------------------------
SDx.btn2.enabled = true
)
)

fn Do_Reset =
(
lDefault = layermanager.getlayer 0
for f in 1 to TsArray.count do
(
lDefault.addNode TsArray[f]
)
for f in 1 to 20 do
(
LayerManager.deleteLayerByName (Pfix+"_Level"+(f as string))
execute ("SDx.bt_S"+(f as string)+".enabled = false")
execute ("SDx.bt_S"+(f as string)+".text = \"\"")
)
)

fn Do_Select x =
(
if x!="x" then
(
clearselection()
Sx = LayerManager.getLayerFromName (SDx.Eprx.text+"_Level"+x)
Sx.select true
)
else
(
clearselection()
Sx = (for f in TsArray where (isvalidnode f) collect f)
Select Sx
)
)

fn Do_Rename x =
(
for f in 1 to 20 do
(
Sx = LayerManager.getLayerFromName (Pfix+"_Level"+(f as string))
try (Sx.setName (x+"_Level"+(f as string))) catch (exit loop)
)
Pfix=x
)

(
rollout SDx "Random Selection" width:287 height:265
(
GroupBox grp1 "" pos:[74,0] width:112 height:59
editText Eprx "Prefix: " text:"SD" pos:[83,15] width:91 height:17
-----------------------------------------------------------
button btn1 "Randomize" pos:[6,6] width:62 height:24
button btn2 "Total" pos:[6,35] width:62 height:24 enabled:false
spinner spn_lv1 "Level " pos:[94,35] width:81 height:16 range:[2,20,5] type:#integer
-----------------------------------------------------------
button bt_S1 "" pos:[6,67] width:84 height:18 enabled:false
button bt_S2 "" pos:[6,85] width:84 height:18 enabled:false
button bt_S3 "" pos:[6,103] width:84 height:18 enabled:false
button bt_S4 "" pos:[6,121] width:84 height:18 enabled:false
button bt_S5 "" pos:[6,139] width:84 height:18 enabled:false
button bt_S6 "" pos:[6,157] width:84 height:18 enabled:false
button bt_S7 "" pos:[6,175] width:84 height:18 enabled:false
button bt_S8 "" pos:[6,193] width:84 height:18 enabled:false
button bt_S9 "" pos:[6,211] width:84 height:18 enabled:false
button bt_S10 "" pos:[6,229] width:84 height:18 enabled:false
button bt_S11 "" pos:[102,67] width:84 height:18 enabled:false
button bt_S12 "" pos:[102,85] width:84 height:18 enabled:false
button bt_S13 "" pos:[102,103] width:84 height:18 enabled:false
button bt_S14 "" pos:[102,121] width:84 height:18 enabled:false
button bt_S15 "" pos:[102,139] width:84 height:18 enabled:false
button bt_S16 "" pos:[102,157] width:84 height:18 enabled:false
button bt_S17 "" pos:[102,175] width:84 height:18 enabled:false
button bt_S18 "" pos:[102,193] width:84 height:18 enabled:false
button bt_S19 "" pos:[102,211] width:84 height:18 enabled:false
button bt_S20 "" pos:[102,229] width:84 height:18 enabled:false
-----------------------------------------------------------
on btn1 pressed do Do_Randomize()
on btn2 pressed do (Do_Select "x")
on Eprx entered s do (Do_Rename s)
-----------------------------------------------------------
on bt_S1 pressed do (Do_Select "1")
on bt_S2 pressed do (Do_Select "2")
on bt_S3 pressed do (Do_Select "3")
on bt_S4 pressed do (Do_Select "4")
on bt_S5 pressed do (Do_Select "5")
on bt_S6 pressed do (Do_Select "6")
on bt_S7 pressed do (Do_Select "7")
on bt_S8 pressed do (Do_Select "8")
on bt_S9 pressed do (Do_Select "9")
on bt_S10 pressed do (Do_Select "10")
on bt_S11 pressed do (Do_Select "11")
on bt_S12 pressed do (Do_Select "12")
on bt_S13 pressed do (Do_Select "13")
on bt_S14 pressed do (Do_Select "14")
on bt_S15 pressed do (Do_Select "15")
on bt_S16 pressed do (Do_Select "16")
on bt_S17 pressed do (Do_Select "17")
on bt_S18 pressed do (Do_Select "18")
on bt_S19 pressed do (Do_Select "19")
on bt_S20 pressed do (Do_Select "20")
)
)
on execute do (createDialog SDx 192 254 100 100)
)


It doesn't seam to be that much post for this one...what about 1 more week ?

Martin Dufour

MatanH
06-30-2008, 08:15 PM
martroyx - that's a cool little toy. I think you should use a list box or a drop down list
instead of all this buttons, that way you will have theoretically infinit number of groups.

erilaz - I tried your tool (in max 2008) and it looks like you have a problem with the
offset definition on your cloneRandom function. If you use the offset property, it is already
being cloned on the position of the original object and then being offset from there.
So your offst variable should look like that:

offst = random [-maxD,-maxD,-MaxD] [maxD,maxD,MaxD]


Good job guys:beer:

martroyx
06-30-2008, 10:00 PM
martroyx - that's a cool little toy. I think you should use a list box or a drop down list
instead of all this buttons, that way you will have theoretically infinit number of groups.


That's a good idea I added some seed to, thank! :-P


(
Global SDx
Try Destroydialog SDx catch()
Local Do_Randomize,Do_Reset,Do_Select,Do_Rename
Local TsArray = #()
Local Pfix = "SD"

fn Do_Randomize =
(
if (selection.count >= SDx.spn_lv1.value) then
(
Do_Reset()
TsArray=selection as array
---------------------------------------------------
Local Tnumb = TsArray.count
Local kk = (Tnumb/(SDx.spn_lv1.value as float))
Local SubArray = #{1..(Tnumb)}
Local NbArray = #()
Local DropArray = #()
Local NbSeed = 0
---------------------------------------------------
for f in 1 to SDx.spn_lv1.value do
(
layermanager.newLayerFromName (Pfix+"_Level"+(f as string))
append DropArray (Pfix+"_Level"+(f as string))
append NbArray 0
)
---------------------------------------------------
While SubArray.isEmpty == false do
(
Tx = (
seed (SDx.spn_seed.value+NbSeed)
Random 1 SubArray.count
)
Vx = (ceil ((TsArray.count-Tnumb)/kk))as integer
if Vx == 0 then Vx = 1
if SubArray[Tx] == true then
(
Sx = LayerManager.getLayerFromName (Pfix+"_Level"+(Vx as string))
Sx.addNode TsArray[Tx]
deleteItem SubArray Tx
NbArray[Vx] += 1
Tnumb -= 1
) else (NbSeed += (random 1 100))
)
---------------------------------------------------
SDx.ddl1.items = DropArray
SDx.btn2.enabled = true
SDx.ddl1.enabled = true
Do_Select "1"
)
else (messagebox "Select more object or try to lower level" beep:false)
)

fn Do_Reset =
(
lDefault = layermanager.getlayer 0
for f in 1 to TsArray.count do
(
lDefault.addNode TsArray[f]
)
for f in 1 to 20 do
(
LayerManager.deleteLayerByName (Pfix+"_Level"+(f as string))
)
)

fn Do_Select x =
(
if x!="x" then
(
clearselection()
Sx = LayerManager.getLayerFromName (SDx.Eprx.text+"_Level"+x)
Sx.select true
SDx.ddl1.text = ("Selected Obj -"+(selection.count as string)+" -")
)
else
(
clearselection()
Sx = (for f in TsArray where (isvalidnode f) collect f)
Select Sx
SDx.ddl1.text = ("Selected Obj -"+(selection.count as string)+" -")
)
)

fn Do_Rename x =
(
Local DropArray = #()
for f in 1 to 20 do
(
Sx = LayerManager.getLayerFromName (Pfix+"_Level"+(f as string))
try(
Sx.setName (x+"_Level"+(f as string))
append DropArray (x+"_Level"+(f as string))
) catch (exit loop)
)
SDx.ddl1.items = DropArray
Pfix=x
)

(
rollout SDx "Random Selection" width:287 height:265
(
GroupBox grp1 "" pos:[6,0] width:181 height:115
edittext Eprx "prefix " text:"SD" pos:[89,51] width:91 height:17
button btn1 "Randomize" pos:[12,12] width:62 height:24
button btn2 "Total" pos:[12,38] width:62 height:24 enabled:false
spinner spn_lv1 "level " pos:[99,13] width:81 height:16 range:[2,400,5] type:#integer
spinner spn_seed "seed " pos:[99,32] width:81 height:16 range:[1,99999,1] type:#integer
dropDownList ddl1 "Selected Obj -0- " pos:[11,69] width:171 height:40 enabled:false
-----------------------------------------------------------
on btn1 pressed do Do_Randomize()
on btn2 pressed do (Do_Select "x")
on Eprx entered s do (Do_Rename s)
on ddl1 selected s do (Do_Select (s as string))
)
)
on execute do (createDialog SDx 192 120 100 100)
)

grabjacket
06-30-2008, 10:22 PM
Well, here's my first challenge entry ever. So i'm likely to overdo it a bit. this one renames an object by doubleclicking on an item in a list. I've prefilled the list with dutch construction-elements. you also get a wirecolor (optionally).
A cool thing i learned is using a callback to trigger the script to pop up.
Use:
Execute the script
Select a single object
Enter a questionmark in the name of the object
Script pops up
Doubleclick on a name in the script


This is easily also implemented as macro. Well here it is

--the main body
(
--put an item in one of these arrays to associate a color with it
local redWire = #("gevel","straat")
local greenWire = #("gras","raam","boom")
local blueWire = #("kozijn","water","rand","dakrand")
local cyanWire = #("glas")
local magentaWire = #("vloer","dorpel")
local yellowWire = #("rollaag")
local blackWire = #("trasraam","plafond")
local whiteWire = #("Script by Klaas","stoeprand","lamp")
local defaultWire = #("wand","binnenwand","balkon","stoep",
"dak","boeibord","waterslag","hek","spijl","beschoeiing",
"deur")

--the list of names, will be sorted alphabetically later on
local nameListArray = #()
local wireAssignArrays = #(redWire,greenWire,blueWire,cyanWire,magentaWire,yellowWire,blackWire,whiteWire,defaultWire)
for arr in wireAssignArrays do join nameListArray arr --combine the different arrays with names to a single one

local defaultColor = color 180 180 158 --use this color if the name is put in the defaultWire array

--associate a name with a wirecolor
function fn_getWireColor myName =
(
theRightColor = undefined
for arr in wireAssignArrays do
(
found = findItem arr myName
if found != 0 do
(
case arr of
(
redWire:theRightColor = red
greenWire:theRightColor = green
blueWire:theRightColor = blue
cyanWire:theRightColor = color 0 255 255
magentaWire:theRightColor = color 255 0 255
yellowWire:theRightColor = yellow
blackWire:theRightColor = black
whiteWire:theRightColor = white
defaultWire:theRightColor = defaultColor
)
)
)
theRightColor
)

--initialize the listView
function fn_initListview lv =
(
lv.columns.add "" 16 --the color column
lv.columns.add "" 80 --the name column
lv.View = (dotNetClass "System.Windows.Forms.View").Details
lv.HeaderStyle = lv.Headerstyle.none --i don't want to see the columnheader
lv.fullRowSelect = true
lv.multiselect = false
)

--populate the listview
function fn_populateListview names lv doColor =
(
lv.items.clear()
--sort the names alphabetically
sort names
local theItemArray = #()
for o in names do
(
--the first item is the color
theItem = dotNetObject "listViewItem"
theItem.text = ""
theItem.UseItemStyleForSubItems = false--don't use colors of the main item in the subitem
theItem.subItems.add o --the subItem hold the actual name

--if the user wants to see the wires: change the color of the text of the items in the list
if doColor == true do
(
theColor = fn_getWireColor o
theItem.backColor = (dotNetClass "System.Drawing.Color").fromARGB theColor.r theColor.g theColor.b
)
append theItemArray theItem
)
lv.items.addrange theItemArray
)

--define the rollout
rollout theWhatsMyNameRollout "whatsmyname"
(
label theLabel "Doubleclick to apply" align:#center --pos:[2,2]
label theLabel1 "the objectname." align:#center --pos:[2,18]
checkBox chkDefaultWire "Use wirecolor" checked:true offset:[-11,0]
checkBox chkCloseOnRename "Close on rename" offset:[-11,0] checked:true
dotNetControl lvNameList "System.Windows.Forms.ListView" width:120 height:450 offset:[-11,0]--pos:[2,35]

--init and populate the list when the rollout opens
on theWhatsMyNameRollout open do
(
fn_initListview lvNameList
fn_populateListview nameListArray lvNameList (chkDefaultWire.checked)
)

--reflect the use of color in the UI
on chkDefaultWire changed state do
(
case state of
(
true:fn_populateListview nameListArray lvNameList true
false:fn_populateListview nameListArray lvNameList false
)
)

--apply name and wirecolor when an item is doubleclicked
on lvNameList doubleclick control eventArgs do
(
--get the name of the clicked item
theName = control.selectedItems.item[0].subItems.item[1].text
--get the right wirecolor for a name and paint it on an object
if chkDefaultWire.checked == true do
(
theColor = fn_getWireColor theName
for o in selection where isProperty o #Wirecolor do o.wirecolor = theColor
)

--apply the doubleclicked name to every selected item
for o = 1 to selection.count do
(
--create a three-digit number with leading zeros
theNumber = o as string
if theNumber.count < 3 do
(
leadingZero = ""
for n = 1 to 3 - theNumber.count do append leadingZero "0"
theNumber = leadingZero + theNumber
)
--apply the name
selection[o].name = (theName + "_" + theNumber)
)
if chkCloseOnRename.checked == true do destroyDialog theWhatsMyNameRollout
)
)--end rollout
)--end body


function fn_popItUp =
(
local theParam = callbacks.notificationParam()
local triggerCharacter = "?"
triggered = findString theParam[2] triggerCharacter
if triggered != undefined do
(
thePos = mouse.screenpos
thePos += [-200,0]
if thePos.x < 0 do thePos.x = 0
if thePos.y > 600 do thePos.y = 600

global theWhatsMyNameRollout
try(destroyDialog theWhatsMyNameRollout)catch()
createDialog theWhatsMyNameRollout 125 535 pos:thePos modal:false
)
)
--callback mechanism
callbacks.removeScripts id:#klaasRenamer --remove the callback
callbacks.addScript #nodeNameSet "fn_popItUp()" id:#klaasRenamer --add the callback


Klaas

MatanH
07-01-2008, 02:03 PM
Here is my small contribution for this challenge.
I call it the 'Distance tool' or 'Position scale tool'.


(
tool disTool prompt:"Distance Tool started (Alt - Change center object, Ctrl - Average center)" numPoints:2
(
local objs, center, objsPos, mp, centerObj
local xRayBitArr = #{}

fn getCenter ctrlMode:true =
(
if not ctrlMode then (
center = centerObj.pos
) else (
center = [0,0,0]
for o in objs do (
center += o.pos
)
center *= 1.0 / objs.count
)
)

fn moveObj o p1 p2 ctrlMode:true =
(
v = center - objsPos[o]
objs[o].pos = objsPos[o] - v * (p1.y - p2.y) / 100
)

fn getCenterByRay lastObj =
(
local mRay = mapScreenToWorldRay mouse.pos
local lastDist = 9999999
for o in objs where o != lastObj do (
local newInt = intersectRay o mRay
if newInt != undefined do (
local newDist = distance mRay.pos newInt.pos
if newDist < lastDist do (
lastDist = newDist
lastObj = o
)
)
)
lastObj
)

fn init =
(
objs = selection as array
if objs.count > 1 then (
for g = 1 to geometry.count do (
xRayBitArr[g] = geometry[g].xRay
geometry[g].xRay = if not geometry[g].isSelected then true else false
)
deselect objects
centerObj = objs[1]
objsPos = #()
for o in objs do (
append objsPos o.pos
)
) else (
pushPrompt "Distance Tool stoped because less then two objects are selected."
#stop
)
)

fn done =
(
for g = 1 to geometry.count do (
geometry[g].xRay = xRayBitArr[g]
)
select objs
gc light:true
)

on start do init()

on freeMove do (
if not ctrlKey and altKey then (
if not mouse.buttonStates[1] and not mouse.buttonStates[1] and not mouse.buttonStates[1] then (
centerObj = getCenterByRay centerObj
flashNodes #(centerObj)
)
)
)

on mousePoint n do (
getCenter ctrlMode:ctrlKey
mp = viewPoint
)

on mouseMove n do (
if n == 2 then (
for o = 1 to objs.count do (
moveObj o mp viewPoint ctrlMode:ctrlKey
)
)
)

on mouseAbort aborted do (
for o = 1 to objs.count do (
objs[o].pos = objsPos[o]
)
)

on stop do done()
)

startTool disTool
)


select a couple of objects and evaluate the tool.
press left mouse button, hold and drag the mouse up and down to move
the selected object closer or further away from the first selected object.
use Alt to change the center object by ray hitting before you press the left mouse button.
use Ctrl while you press and hold left mouse button to move the selected objects relative to their average position.

martroyx
07-01-2008, 02:31 PM
Wow !!! this is a nice tool, very well done :applause:

DaveWortley
07-01-2008, 03:08 PM
rollout rollout1 "Selection Batch Renamer" width:243 height:44
(
editText edt1 "" pos:[7,8] width:140 height:27
button btn1 "Rename" pos:[158,9] width:74 height:25
on edt1 entered text do
(

)
on btn1 pressed do
(
for i = 1 to selection.count do

(
--objname = Execute (edt1 as String)

Selection[i].name=uniquename edt1.text



)
)
)
rollout about_ro "About..." (
label l0 "Written by Dave Wortley"
label l1 "Renames selected objects based on" align:#left
label l2 "selection order. Numbering will" align:#left
label l3 "automatically start from the first" align:#left
label l35 "free incrimental." align:#left

)


Renamer = newRolloutFloater "Renamer v 1.2" 250 95
addRollout rollout1 Renamer rolledUp:false
addRollout about_ro Renamer rolledUp:true

Simplicity and speed, key Functionality, the Renaming tool in max is slow, this is quick, doesn't do anything fancy but works much better.

DaveWortley
07-01-2008, 03:34 PM
rollout QRender_rollout "Draft Renderer" width:150 height:20
(
--button btn_store "Store" pos: [5,5] width:40 height:17 enabled:false
button btn_Render "Render" pos:[5,5] width:70 height:17 enabled:true
editText edt1 "" pos:[75,4] width:60 height:17 text:"500"
--button btn_restore "Restore" pos:[155,4] width:56 height:17 enabled:false


fn store =
(
renderSceneDialog.close()
--renderers.current = RendererClass.classes[4]()
global i = renderers.current
global m = i.gi_on
global a = i.imagesampler_type
global b = i.filter_on
global c = i.gi_primary_type
global d = i.gi_irradmap_preset
global l = i.gi_irradmap_subdivs
global f = i.gi_irradmap_showCalcPhase
global g = i.gi_secondary_type
global h = i.lightcache_subdivs
global j = i.lightcache_sampleSize
global k = i.lightcache_showCalcPhase
global n = i.qmc_earlyTermination_threshold
global p = i.system_frameStamp_on

--btn_store.enabled = false
--btn_render.enabled = true


)

fn restore =
(
i = renderers.current
i.gi_on = m
i.imagesampler_type = a
i.filter_on = b
i.gi_primary_type = c
i.gi_irradmap_preset = d
i.gi_irradmap_subdivs = l
i.gi_irradmap_showCalcPhase = f
i.gi_secondary_type = g
i.lightcache_subdivs = h
i.lightcache_sampleSize = j
i.lightcache_showCalcPhase = k
i.qmc_earlyTermination_threshold = n
i.system_frameStamp_on = false

--btn_store.enabled = true
--btn_render.enabled = false
--btn_restore.enabled = false
--renderSceneDialog.open()
gc()
)

on btn_Render pressed do
(
store()
renderSceneDialog.cancel()
renderSceneDialog.close()



i = renderers.current



--set
i.gi_on = true
i.imagesampler_type = 0
i.filter_on = false
i.gi_primary_type = 0
i.gi_irradmap_preset = 3
i.gi_irradmap_subdivs = 30
i.gi_irradmap_showCalcPhase = true
i.gi_secondary_type = 3
i.lightcache_subdivs = 100
i.lightcache_sampleSize = 0.01
i.lightcache_showCalcPhase = 1
i.qmc_earlyTermination_threshold = 1.0
--to stop errors
i.options_defaultLights = false
i.system_frameStamp_on = true
i.system_frameStamp_string = "file: %filename | render time: %rendertime | %date"
RA = getRendImageAspect()
Rw = edt1.text as integer
Rh = Rw / RA


render outputwidth: Rw outputheight: Rh vfb: true progressbar: true --renderType: #region
--btn_restore.enabled = true
restore()

)
on edt1 entered text do
(
Rw = edt1.text
)
on btn_restore pressed do
(


)
)

Vray_Quick_render = newRolloutFloater "Vray Quick Render" 160 60
addRollout qrender_rollout Vray_quick_render rolledUp:false

Vray Quick Render

Quickly adjust Vray Render settings to low GI settings, antialiasing off, sampling low etc. Then restores settings after render. Ability to specify render size as well.

erilaz
07-02-2008, 02:43 PM
Great stuff guys, really good to see the brains ticking into new uses for max tools.

TzMtN: Nice catch on the offset fix. I think I was originally moving the objects after the cloning, then got lazy and pasted it into the offset. :D I like the tool interaction of your script, but I couldn't get the alt and ctrl keys to work for the objects. Perhaps i was doing it wrong!

Dave: Nice and succinct! I can't test it unfortunately (no Vray), but I love clean readable code! :) Good one on the renamer too... you're right about the built in tool. You'd think with all the other speed improvements in max a simple object namer would be faster.

martroyx: Really clean interface! I like! I like the fact that you've made the randomness easy to understand and organise.

grabjacket: Very cool idea! I'd love to see it implemented with a double click on the object, but the concept of a predefined tagger is great!

Gravey
07-03-2008, 03:17 AM
I have a couple of tools i created at work so i know it's not from scratch but i thought this would still be a good place to share them.

First one:

Spline Aligner
Draw a spline and create a bunch of objects.
Select the objects.
Run the script to create the dialog.
pick the Spline and the selected objects should be spaced evenly along the spline
play with the other options to re-position the objects along the spline
NOTE: if you check the 'Follow' checkbox, the objects will become oriented to the spline but they will not be reset to their original rotations if you uncheck it. Maybe something for the future...
(
global splineAligner

try(destroyDialog splineAligner)catch()

local dWidth = 250
local al = #Center
local os = [3,0]

local sel

fn splineFilter s =
(
if classof s == SplineShape OR s.category == #Splines then true else false
)

rollout splineAligner "Spline Aligner"
(
Group "Alignment"
(
pickButton pic_spline "Pick Spline Object" align:al across:2 width:(dWidth/2 - 8) \
offset:-os autoDisplay:true filter:splineFilter
button btn_align "Align" align:al width:(dWidth/2 - 10) offset:os enabled:false
radioButtons rdo_side "" labels:#("Left","Right","Center") align:#Right offset:[-10,3]
label lab_rdo "Align to:" align:#Left offset:[20,-20]
spinner spn_space "Spacing %: " fieldwidth:50 type:#float align:#Right across:2 range:[0,100,100] offset:[0,2]
spinner spn_offset "Offset: " fieldwidth:50 type:#float align:#Right offset:((os*2)+[0,2]) range:[-100,100,0]
checkbox chk_orient "Follow" across:2 checked:false
checkbox chk_flip "Reverse Order"
radioButtons rdo_orientAxis "" labels:#("X", "Y", "Z") align:#Left across:2
checkbox chk_flipAxis "Flip"
)

fn orientTo o tangent orientAxis flipAxis startDeg:0 endDeg:0 =
(
o.dir = tangent
case orientAxis of
(
1:
(
rotate o -90 o.transform[2]
rotate o -90 o.transform[1]
--in coordsys o rotate o -90 y_axis
if flipAxis then rotate o 180 o.transform[3]
)
2:
(
rotate o -90 o.transform[1]
if NOT flipAxis then rotate o 180 o.transform[3]
)
3:
(
if flipAxis then rotate o 180 o.transform[1]
)
)
)

fn fixFraction f =
(
if f > 1.0 then 1.0
else if f < 0.0 then 0
else f
)

fn alignToSpline arr s spc side flip ofs orient:false orientAxis:3 flipAxis:false startDeg:0 endDeg:0 =
(
spc /= 100.0
ofs /= 100.0
cnt = (arr.count - 1) as float
rotateOffset = eulerangles 0 0 0
if flip then
arr = for i = arr.count to 1 by -1 collect arr[i]

for a = 0 to cnt where isValidNode arr[a+1] do
(
case side of
(
1: -- #Left
(
frac = ((a / cnt) * spc)
arr[a+1].pos = interpCurve3D s 1 (fixFraction (frac + ofs))
if orient then
(
orientTo arr[a+1] (tangentCurve3D s 1 (fixFraction (frac + ofs))) orientAxis flipAxis
)
)
2: -- #Right
(
frac = ((a / cnt) * spc) + (1.0 - spc)
arr[a+1].pos = interpCurve3D s 1 (fixFraction (frac + ofs))
if orient then
(
orientTo arr[a+1] (tangentCurve3D s 1 (fixFraction (frac + ofs))) orientAxis flipAxis
)
)
3: -- #Center
(
frac = ((a / cnt) * spc) + ((1.0 - spc) / 2)
arr[a+1].pos = interpCurve3D s 1 (fixFraction (frac + ofs))
if orient then
(
orientTo arr[a+1] (tangentCurve3D s 1 (fixFraction (frac + ofs))) orientAxis flipAxis
)
)
)
)
)

on btn_align pressed do
(
sel = for s in selection where s != pic_spline.object collect s
if sel.count > 0 AND isValidNode pic_spline.object then
alignToSpline sel pic_spline.object spn_space.value rdo_side.state chk_flip.checked spn_offset.value \
orient:chk_orient.checked orientAxis:rdo_orientAxis.state flipAxis:chk_flipAxis.checked
)

on spn_space changed val do
(
sel = for s in selection where s != pic_spline.object collect s
if sel.count > 0 AND isValidNode pic_spline.object then
alignToSpline sel pic_spline.object val rdo_side.state chk_flip.checked spn_offset.value \
orient:chk_orient.checked orientAxis:rdo_orientAxis.state flipAxis:chk_flipAxis.checked
)

on spn_offset changed val do
(
sel = for s in selection where s != pic_spline.object collect s
if sel.count > 0 AND isValidNode pic_spline.object then
alignToSpline sel pic_spline.object spn_space.value rdo_side.state chk_flip.checked val \
orient:chk_orient.checked orientAxis:rdo_orientAxis.state flipAxis:chk_flipAxis.checked
)

on rdo_side changed state do
(
sel = for s in selection where s != pic_spline.object collect s
if sel.count > 0 AND isValidNode pic_spline.object then
alignToSpline sel pic_spline.object spn_space.value state chk_flip.checked spn_offset.value \
orient:chk_orient.checked orientAxis:rdo_orientAxis.state flipAxis:chk_flipAxis.checked
)

on chk_orient changed state do
(
sel = for s in selection where s != pic_spline.object collect s
if sel.count > 0 AND isValidNode pic_spline.object then
alignToSpline sel pic_spline.object spn_space.value rdo_side.state chk_flip.checked spn_offset.value \
orient:state orientAxis:rdo_orientAxis.state flipAxis:chk_flipAxis.checked
)

on chk_flip changed state do
(
sel = for s in selection where s != pic_spline.object collect s
if sel.count > 0 AND isValidNode pic_spline.object then
alignToSpline sel pic_spline.object spn_space.value rdo_side.state state spn_offset.value \
orient:chk_orient.checked orientAxis:rdo_orientAxis.state flipAxis:chk_flipAxis.checked
)

on chk_flipAxis changed state do
(
sel = for s in selection where s != pic_spline.object collect s
if sel.count > 0 AND isValidNode pic_spline.object then
alignToSpline sel pic_spline.object spn_space.value rdo_side.state chk_flip.checked spn_offset.value \
orient:chk_orient.checked orientAxis:rdo_orientAxis.state flipAxis:state
)

on rdo_orientAxis changed state do
(
sel = for s in selection where s != pic_spline.object collect s
if sel.count > 0 AND isValidNode pic_spline.object then
alignToSpline sel pic_spline.object spn_space.value rdo_side.state chk_flip.checked spn_offset.value \
orient:chk_orient.checked orientAxis:state flipAxis:chk_flipAxis.checked
)

on pic_spline picked arg do
(
btn_align.enabled = true
sel = for s in selection where s != pic_spline.object collect s
if sel.count > 0 then
alignToSpline sel pic_spline.object spn_space.value rdo_side.state chk_flip.checked spn_offset.value \
orient:chk_orient.checked orientAxis:rdo_orientAxis.state flipAxis:chk_flipAxis.checked
)
)

createDialog splineAligner width:dWidth
)
EDIT: there seems to be some redundent arguments in the alignToSpline function. I guess i intended to add more functionality but never got around to it...

Gravey
07-03-2008, 03:26 AM
Second one:

Scale Objects Positions
Allows you to 'scale' the positions of selected objects about the selection center or average pivot position, in any combination of axes without affecting the actual scale of the objects.
TzMtN has already posted something similar but i think this one is still fairly different as you have a floating dialog to work with as needed.
Run the script select a bunch of objects and play with the spinners!

(
-- Globals

global scaleObjectPositions

try(destroyDialog scaleObjectPositions)catch()

-- Private Globals

local scriptName = "Scale Object Positions"
local version = 1.00

local dWidth = 175
local bw = (dWidth - 20) / 2.08
local fw = 45
local al = #center
local os = [-2,0]
local nowhere = [0,0,0]
local noMove = 100

local ext = 99999999

-- Private Global Functions

fn constructRolloutName =
(
ver = version as string
if ver.count < 4 then ver += "0"
" " + scriptName + " " + ver
)

-- Rollouts

rollout scaleObjectPositions (constructRolloutName())
(
local sel
local mid
local vecs
local starts
local goFlag = false
local count
local allSpinners

Group "Scale Group"
(
spinner spn_x "X:" range:[-ext,ext,100] type:#float fieldwidth:fw across:2 align:al offset:os
spinner spn_xy "XY:" range:[-ext,ext,100] type:#float fieldwidth:fw align:al
spinner spn_y "Y:" range:[-ext,ext,100] type:#float fieldwidth:fw across:2 align:al offset:os
spinner spn_yz "YZ:" range:[-ext,ext,100] type:#float fieldwidth:fw align:al
spinner spn_z "Z:" range:[-ext,ext,100] type:#float fieldwidth:fw across:2 align:al offset:os
spinner spn_zx "XZ:" range:[-ext,ext,100] type:#float fieldwidth:fw align:al
label lab_spacer "" across:2
spinner spn_xyz "XYZ:" range:[-ext,ext,100] type:#float fieldwidth:fw align:al offset:[-4,0]

radiobuttons rdo_mid "Middle Point:" labels:#("Selection Center","Average Pivot Position") align:#Left offset:[0,-20]

button btn_undo "Undo" width:bw align:al across:2
button btn_redo "Redo" width:bw align:al
)

-- Local Rollout Functions

fn resetMove =
(
for i = 1 to count do sel[i].pos = starts[i]
)-- end resetMove function

fn sortLinkedObjs arr = -- needed for when the spinners are zeroed out
(
--collect all unlinked objects
tempArr = for a in arr where a.children.count == 0 AND a.parent == undefined collect a
--collect all objects with parents but no children and join with the array 'tempArr'
join tempArr (for a in arr where a.children.count == 0 AND a.parent != undefined collect a)
--go through all items in tempArr and append their parents to tempArr. Should work recursively.
for t in tempArr where ((findItem arr t.parent) > 0) do append tempArr t.parent
--remove duplicate objects
for i = tempArr.count to 1 by -1 where (index = findItem tempArr tempArr[i]) > 0 AND
index != i do deleteItem tempArr index
--reverse the array order
sortedArray = for i = tempArr.count to 1 by -1 collect tempArr[i]

sortedArray
)-- end sortLinkedObjs function

fn getCenterPoint =
(
if rdo_mid.state == 1 then selection.center
else
(
mid = [0,0,0]
for s in selection do mid += s.pos
mid / selection.count
)
)-- end getCenterPoint function

fn initValues =
(
sel = sortLinkedObjs (selection as array)
mid = getCenterPoint()
vecs = for s in sel collect /*normalize*/ (s.pos - mid)
starts = for s in sel collect s.pos
goFlag = true
count = sel.count
flagForeground sel true
)-- end initValues function

fn scaleMoveObjects factor =
(
factor /= 100.0
for i = 1 to count do sel[i].pos = vecs[i] * factor + mid
)-- end scaleMoveObjects function

mapped fn resetSpinners s = s.value = 100 -- end scaleMoveObjects function

fn btn_up rcFlag =
(
if goFlag AND rcFlag then max undo
goFlag = false
resetSpinners allSpinners
)-- end btn_up function

fn btn_Down =
(
if selection.count > 1 then
(
-- Fake the undo buffer by 'moving' to the same positions
undo "Scale Object Positions" on move selection nowhere
initValues()
)
else goFlag = false
)-- end btn_Down function

-- Rollout Event Handlers

on spn_x changed val do if goFlag do scaleMoveObjects [val,noMove,noMove]
on spn_xy changed val do if goFlag do scaleMoveObjects [val,val,noMove]
on spn_y changed val do if goFlag do scaleMoveObjects [noMove,val,noMove]
on spn_yz changed val do if goFlag do scaleMoveObjects [noMove,val,val]
on spn_z changed val do if goFlag do scaleMoveObjects [noMove,noMove,val]
on spn_zx changed val do if goFlag do scaleMoveObjects [val,noMove,val]
on spn_xyz changed val do if goFlag do scaleMoveObjects [val,val,val]

on spn_x buttondown do btn_Down()
on spn_xy buttondown do btn_Down()
on spn_y buttondown do btn_Down()
on spn_yz buttondown do btn_Down()
on spn_z buttondown do btn_Down()
on spn_zx buttondown do btn_Down()
on spn_xyz buttondown do btn_Down()

on spn_x buttonup rightClickFlag do btn_up rightClickFlag
on spn_xy buttonup rightClickFlag do btn_up rightClickFlag
on spn_y buttonup rightClickFlag do btn_up rightClickFlag
on spn_yz buttonup rightClickFlag do btn_up rightClickFlag
on spn_z buttonup rightClickFlag do btn_up rightClickFlag
on spn_zx buttonup rightClickFlag do btn_up rightClickFlag
on spn_xyz buttonup rightClickFlag do btn_up rightClickFlag

on btn_undo pressed do
(
max undo
)
on btn_redo pressed do
(
max redo
)

on scaleObjectPositions open do
(
allSpinners = for c in scaleObjectPositions.controls where classof c == SpinnerControl collect c
)
)-- end scaleObjectPositions rollout definition

createDialog scaleObjectPositions width:dWidth style:#(#style_toolwindow, #style_border, #style_sysmenu)
)

CGTalk Moderation
07-03-2008, 03:26 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.