Notifications
Clear all

[Closed] Randomize Scale – Scripting-noob has questions

Hi guys,

I’m new to this forum and maxscripting but decided to take the plunge and learn. I’m trying to write a script that randomly scales objects between two values, using the very basic Maxscript-knowledge I have right now.

I run into two problems:

  • When the rollout opens, I’d like the default values to be set to 0.9 for ‘min’ and 1.1 for ‘max’, but can’t get it to work.
  • When I use the current rollout, and don’t change the values, the scaling goes hopelessly wrong. Even though the spinners say 0.9 by default, it seems to be using ‘0.0’ as a default
  • Is there a way to use three digits after the komma?

Thanks a lot, I’ll post the code below.


MacroScript Randomize_Hanging_Product category:“Swillie’s Scripts” buttonText:“Randomize Hanging Product” tooltip:“Randomize Hanging Product”
(
rollout RandomizeRollout “Randomize Hanging Product” width:226 height:150
(
spinner spn1 “Min” pos:[15,59] width:58 height:16 range:[0.9,1.1,0]
spinner spn2 “Max” pos:[15,78] width:58 height:16 range:[0.9,1.1,0]
spinner spn7 “Min” pos:[90,59] width:58 height:16 range:[0.9,1.1,0]
spinner spn8 “Max” pos:[90,78] width:58 height:16 range:[0.9,1.1,0]
spinner spn9 “Min” pos:[165,59] width:58 height:16 range:[0.9,1.1,0]
spinner spn10 “Max” pos:[165,78] width:58 height:16 range:[0.9,1.1,0]
label lbl6 “X” pos:[43,35] width:16 height:18
label lbl7 “Y” pos:[118,35] width:16 height:18
label lbl8 “Z” pos:[193,35] width:16 height:18
button btn8 “Randomize!” pos:[43,108] width:140 height:18
button btn9 “Clear” pos:[43,130] width:140 height:18

           on btn8 pressed do
           (
           for obj in $ do
               (
               if (selection.count > 0) then
                   (
                   randXscale = random spn1.value spn2.value
                   randYscale = random spn7.value spn8.value
                   randZscale = random spn9.value spn10.value
                   scale obj [randXscale,randYscale,randZscale]
                   )
               else
                   (
                   messagebox "Je hebt niks geselecteerd, joker!"
                   )
               )
           )

           on btn9 pressed do
           (
           spn1.value = 0.0
               spn2.value = 0.0
               spn7.value = 0.0
               spn8.value = 0.0
               spn9.value = 0.0
               spn10.value = 0.0
           )
       )
   createDialog RandomizeRollout 226 150
   )
9 Replies

From the max help file on spinner control: range:[min,max,val]

so what’s happing with your range:[0.9,1.1,0] is that the min value allowed (the value you can set via user input) on the spinner is 0.9 but the default value is actually 0. What it should be is
range:[0.9,1.1,0.9] giving it a value of 0.9 by default as well as setting the min value the spinner can use.

But – just noticed – your ‘clear’ button sets the spinners to 0 as well… so if you mean to have the spinners alowed to go below 0.9 then you should be using something like range:[0,1000000,0.9]

Thank! That works! I didn’t understand what that third value was for (like I said, I just started) but I did notice I couldn’t do without it, so I just set it to 0.0 :). And the Çlear’ I just didn’t set yet, but thanks.

Any way to get three digits after the komma?

Ok, so on another forum I found that to set the decimals to three, I should use ‘preferences.spinnerPrecision’ I just don’t understand where and how to use it in my code…?

– Edit: found a solution, thanks.

And another thing:

  I am looking for a script to organize selected objects in an array according to their location, so that I can then adjust every 4th or 3rd etc. Browsing and using the Help section helped me a little, but I feel it's not close to working yet. This script is close to what I need, but can't get it to work:
[color=White][/color][left]positions=for i=1 to 10 collect (random [0,0,0] [100,100,0])
     
     fn compareFN  v1 v2 =
     (
     local d = (length v1)-(length v2)
     case[font=Courier New]of
     (
     (d  < 0.): -1
     (d  > 0.): 1
     default: 0
     )[/font]
      [/left]
       [left][color=White])
   
   qsort positions compareFN[/color]
   for p in positions do print p
  

[/left]

  I tried something like this:

  MyArr=#()
  
  for obj in $ do
  	(   
  	insertItem $[($.count - MyArr.count)] MyArr 1
  )
  ---- So now I have an array with all of my selected objects, correct? Then the next part is not even close to working:
  fn MyFunc  v1 v2 =
  
      [left](
  local dist = (obj.pos.x v1)-(obj.pos.x v2)
  caseof
  (
  (dist  < 0.): -1
  (dist  > 0.): 1
  default: 0
  )
  )
  
  qsort MyArr MyFunc
  

Thanks for your help so far, I understand that for experienced scripters my questions might be a bit annoying

[/left]

 JHN

Hi Swillie,

Something to digest:


(
	-- delete all previously created objects
	delete $'bbbox*'
	-- reversing creation proces to make sure the created objects are created at the fartest point first
	for i = 49 to 0 by -1 do box pos:[(acos (i / 50.)) * i / 2.,(asin (i / 50.)) * i / 2., 0] wirecolor:black name:(uniqueName #bbbox_)
	select $'bbbox*'

	fn sortDistance obj1 obj2 =
	(
		-- use pos vector as length to compare, we only need to know if an object has to shift down or up in the array
		if length obj1.pos >= length obj2.pos then
			1
		else 
			-1
	)

	local myObjects = selection as array
	
	-- comparison is based on world zero coordinates
	qSort myObjects sortDistance
-- 	print myObjects
	
	-- move every 4th object up
	for i = 1 to myObjects.count by 4 do myObjects[i].pos.z = 25
)

Hope it helps,
-Johan

Bedankt Johan, indeed something to digest :). Thanks though!

Alright, I got it to work… Thanks a lot for your help so far, I’m learning a lot.



(
-- Globals

global sortDistance

-- Variables

myObjects = $ as array

-- Functions
	
function sortDistance obj1 obj2 =
	(
		if length obj1.pos >= length obj2.pos then -- use pos vector as length to compare, we only need to know if an object has to shift down or up in the array
		1
		else 
		-1
	)
	
-- Script:

qSort myObjects sortDistance

for i = 1 to myObjects.count do 	
	(
		divisor1 =
		(
			local a = 4.0
			local b = i
			
			while b > 0 do
				(
				c = mod a b
				a = b
				b = c
				)
			abs a
		)
		
		divisor2 =
		(
			local a = 4.0
			local b = i+1
			
			while b > 0 do
				(
				c = mod a b
				a = b
					b = c
				)
			abs a
		)
		
		divisor3 =
		(
			local a = 4.0
			local b = i+2
			
			while b > 0 do
				(
				c = mod a b
				a = b
				b = c
				)
			abs a
		)
		
		divisor4 =
		(
			local a = 4.0
			local b = i+3
			
			while b > 0 do
				(
				c = mod a b
				a = b
				b = c
				)
			abs a
		)
		
		case of
		(
			(divisor1 == 4) : move myObjects[i] [0,0,25]
			(divisor2 == 4) : move myObjects[i] [0,0,50]
			(divisor3 == 4) : move myObjects[i] [0,0,75]
			(divisor4 == 4) : move myObjects[i] [0,0,100]
		)
	)
)

Probably not be the easiest way, but it gets me there. Tips on how to do do this easier are welcome.

For instance, I couldn’t get Johan’s script to move every 4th object to work in my script (and apply it like above). I found a script that finds the greatest common divisor between numbers and used that. So to be short: when I have 10 objects selected, I organized the array by location from [0,0,0], moved every 4th and 8th 25, moved every 3rd and 7th 50, moved every 2nd, 6th and 10th 75 and every 1st, 5th and 9th 100.

More questions:

  • I noticed that the above script doesn’t handle groups as one, but per object. How can I get around this?
  • Even better would be that the script automatically detects which objects are intersecting/extremely close-by, and handle those as 1 entity. (For instance, I want to use the above script on a collection of hanging clothing, and for that I want the hanger and item of product simultaneously)

And @Johan: Weet jij toevallig van een goede basis MaxScript-cursus in Nederland? Tutorials zijn een goed begin, maar ik vind het lastig om alleen, zonder dat ik andere MaxScripters ken, al het overige uit te vogelen. Alls andere tips voor boeken/goede tutorials zijn ook welkom.

Bump

Anyone that can help me with the following questions? I still haven’t found a solution…

  • I noticed that the above script doesn’t handle groups as one, but per object. How can I get around this?
  • Even better would be that the script automatically detects which objects are intersecting/extremely close-by, and handle those as 1 entity. (For instance, I want to use the above script on a collection of hanging clothing, and for that I want the hanger and item of product simultaneously)
 JHN

isGroupHead <node>
--Returns true if node is group head, false otherwise.

isGroupMember <node>
--Returns true if node is in a group, false otherwise.

This way you could possibly ignore group members and just go straight for the groupheads.
Testing for real intersection is not that trivial but testing for bounding box intersections isn’t that hard.


intersects <node> <node>
--Returns true if the bounding boxes of the two specified nodes overlap, or false if they do not overlap.

That’s the easy part, the hard part for you is to come up with a logical way to group objects that are close by/intersecting. If I where you and groups would suffice, I’d just go for that.

-Johan