Notifications
Clear all

[Closed] Getting and setting value by string

Okay so I’m trying to assign a value to different label’s .text value inside a for loop, Say I have 3 labels and an array –


label FN_Time_1 "0" style_sunkenedge:true
label FN_Time_2 "0" style_sunkenedge:true
label FN_Time_3 "0" style_sunkenedge:true

FN_Times = #(1,3,5)

and I need to assign each array items to the labels.text values later in my script. Instead of doing this manually –


FN_Time_1.text = FN_Times[1]
FN_Time_2.text = FN_Times[2]
FN_Time_3.text = FN_Times[3]

I figured since the names are the same, except for the incrementing number, I could use a for loop to assign the value by splitting the name ito different strings and adding them together by executing that string. I tried using –


for i = 1 to FN_Times.count do
(
	local Str1 = ("FN_Time_"+ (i as string) + ".text")
	(execute (Str1)) = FN_Times[i]
)

But I get an error in my script trying to assign this with a button –

-- No ""="" function for (Global:execute Local:str1) <<

After reading the reference about execute I think its because it works only with global variables. So is there a different method for assigning a variable to a ui element’s value using strings? I obviously can’t use – FN_Time_i.text = FN_Times[i].

Anyone know what I should do in this case?

15 Replies

Well, it would have to be something like execute (“rolloutName.FN_Time_”+ (i as string) + “.text = ” + FN_Times[i] as string) for it to work. However, most of the time you think you need to use execute, you should think again as there is usually some other way where you don’t have to constrain yourself all that much. In this case, if you want to do it dynamically (say that you have around 50 controls like this, not tested):

rollout rolloutName ""
(
	label FN_Time_1 "0" style_sunkenedge:true
	label FN_Time_2 "0" style_sunkenedge:true
	label FN_Time_3 "0" style_sunkenedge:true
	...
	button btn "Change them all"

	local FN_Times = #(1,3,5)
	local FN_Times_labels = for ctrl in rolloutName.controls where matchPattern ctrl.name pattern:"FN_Time_*" collect ctrl

	on btn pressed do
		for i = 1 to FN_Times_labels.count do
			FN_Times_labels[i].text = FN_Times[i] as string
)

Well thanks for the reply, I’ll have to test that. Before reading your reply, I already posted my script on scriptspot – http://www.scriptspot.com/3ds-max/scripts/expression-benchmark Which is a script for benchmarking expression times. If you look at the script, I ended up using a more compact way of manually setting the values by checking the loop’s index with if, then statements, so I can keep everything in the loop –


      if (i == 1) then (Time_1.text = ((AverageTimes[i] as string) + " ") ; Memory_1.text = ((AverageMems[i] as string) + " ") ; Result_1.text = Results[i]) else --Assign array variables on loop 1
      if (i == 2) then (Time_2.text = ((AverageTimes[i] as string) + " ") ; Memory_2.text = ((AverageMems[i] as string) + " ") ; Result_2.text = Results[i]) else --Assign array variables on loop 2
      if (i == 3) then (Time_3.text = ((AverageTimes[i] as string) + " ") ; Memory_3.text = ((AverageMems[i] as string) + " ") ; Result_3.text = Results[i]) else --Assign array variables on loop 3
      if (i == 4) then (Time_4.text = ((AverageTimes[i] as string) + " ") ; Memory_4.text = ((AverageMems[i] as string) + " ") ; Result_4.text = Results[i]) else --Assign array variables on loop 4
      if (i == 5) then (Time_5.text = ((AverageTimes[i] as string) + " ") ; Memory_5.text = ((AverageMems[i] as string) + " ") ; Result_5.text = Results[i]) else --Assign array variables on loop 5
      if (i == 6) then (Time_6.text = ((AverageTimes[i] as string) + " ") ; Memory_6.text = ((AverageMems[i] as string) + " ") ; Result_6.text = Results[i]) else --Assign array variables on loop 6
      if (i == 7) then (Time_7.text = ((AverageTimes[i] as string) + " ") ; Memory_7.text = ((AverageMems[i] as string) + " ") ; Result_7.text = Results[i]) else --Assign array variables on loop 7
      if (i == 8) then (Time_8.text = ((AverageTimes[i] as string) + " ") ; Memory_8.text = ((AverageMems[i] as string) + " ") ; Result_8.text = Results[i]) else --Assign array variables on loop 8
      if (i == 9) then (Time_9.text = ((AverageTimes[i] as string) + " ") ; Memory_9.text = ((AverageMems[i] as string) + " ") ; Result_9.text = Results[i]) else --Assign array variables on loop 9
      if (i == 10) then (Time_10.text = ((AverageTimes[i] as string) + " ") ; Memory_10.text = AverageMems[i] ; Result_10.text = Results[i]) --Assign array variables on loop 10
       
   If I can get your method to work, then I wouldn't even need a separate array because I was getting other controls' values and putting them to an array, to read. I could probably even eventually find a way of even dynamically changing the number of expressions and labels.

everything can be much easier and more compact.
there is the base function:


  	fn updateUITextControl controlName data id dialog: = 
  	(
  		(getproperty dialog (controlName + "_" + id as string)).text = data[id] as string
  	)
  

here is a sample implementation:


  try(destroydialog monitor) catch()
rollout monitor "Monitor" width:200
(	
	local AverageTimes = #()
	local AverageMems = #()
	local Results = #()

	fn updateUITextControl controlName data id dialog:monitor = 
	(
		(getproperty dialog (controlName + "_" + id as string)).text = data[id] as string
	)
	
	fn updateUI id dialog:monitor = 
	(
		updateUITextControl "Time" AverageTimes id
		updateUITextControl "Memory" AverageMems id
		updateUITextControl "Result" Results id
	)
	
	label time_1 "?" width:60 across:3
	label memory_1 "?" width:60
	label result_1 "?" width:60
	
	label time_2 "?" width:60 across:3
	label memory_2 "?" width:60
	label result_2 "?" width:60

	label time_3 "?" width:60 across:3
	label memory_3 "?" width:60
	label result_3 "?" width:60
	
	button update_bt "Update" width:90 across:2 align:#left offset:[-10,0]
	spinner id_sp "Test ID: " type:#integer range:[1,3,1] fieldwidth:40 offset:[10,4]
	on update_bt pressed do 
	(
		id = id_sp.value
		AverageTimes[id] = random -1000 1000
		AverageMems[id] = random -1000 1000
		Results[id] = random -1000 1000
		updateUI id
	)
)
createdialog monitor
  
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

when you create any rollout control it becomes the rollout’s property. and we can get it by name as any other property of any other mxs node.

your ui update is organized as ‘indexed array member corresponds to an indexed ui control value’.
my function binds control and its data by index.

Haven’t tried your method yet but, Swordslayer’s looks like its easier, denis your version looks like its more complicated, for what I’m trying to do. I tried evaluating Swordslayer’s test, and the listener says

-- Unknown property: "controls" in undefined

It seems to work if I evaluate the rollout with just the labels in the rollout, and try it again. Which seems pretty weird. I tried putting this in my script an I get ** system exception **. Not sure what’s going but here’s my full script with the changes –


rollout ExpressionBenchmark "Expression Benchmark"
(
	group "Settings"
	(
		button Execution "Execute!" align:#left across:12 offset:[0,-3] tooltip:"Run expressions and calculate their runtimes and memory usage."
		spinner Iterations "Iterations:" range:[0,99999,1] type:#integer align:#left across:11 offset:[-10,0] fieldWidth:40 tooltip:"The number of times to execute each function. This will be used to average the resultimg execution times and memory sizes"
		label GCollectionLabel "Garbage Collection:" align:#left across:10 offset:[20,0]
		dropdownlist GCollection items:#("Auto","Manual","Manual Light","Manual All","Manual Light All","None") across:9 offset:[35,-3] tooltip:"The type of garbage collection to perform during execution"
		label TimeMeasureLabel "Time Units:" align:#left across:8 offset:[43,0]
		dropdownlist TimeMeasure items:#("Milliseconds","Seconds","Minutes","Hours") across:7 offset:[16,-3] tooltip:"The time units to dsplay"
		label MemoryMeasureLabel "Memory Units:" align:#left across:6 offset:[24,0]
		dropdownlist MemoryMeasure items:#("Bytes","Kilobytes","MegaBytes","Gigabytes") across:5 offset:[14,-3] tooltip:"The memory units to dsplay"
		label Total_TimeLabel "Total:" across:4 offset:[-5,0]
		label Total_Time "0 " align:#right across:3 offset:[-5,0] style_sunkenedge:true
		label Total_MemoryLabel "Total:" across:2 offset:[-10,0]
		label Total_Memory "0 " align:#right offset:[0,0] style_sunkenedge:true
	) -- Settings parameter group
	group "Expressions"
	(
		edittext Text_1 "01:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_1 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_1 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_1 "| Time:" across:4 offset:[195,0]
		label Time_1 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_1 "| Memory:" across:2 offset:[65,0]
		label Memory_1 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_1 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
		edittext Text_2 "02:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_2 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_2 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_2 "| Time:" across:4 offset:[195,0]
		label Time_2 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_2 "| Memory:" across:2 offset:[65,0]
		label Memory_2 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_2 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
		edittext Text_3 "03:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_3 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_3 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_3 "| Time:" across:4 offset:[195,0]
		label Time_3 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_3 "| Memory:" across:2 offset:[65,0]
		label Memory_3 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_3 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
		edittext Text_4 "04:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_4 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_4 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_4 "| Time:" across:4 offset:[195,0]
		label Time_4 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_4 "| Memory:" across:2 offset:[65,0]
		label Memory_4 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_4 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
		edittext Text_5 "05:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_5 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_5 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_5 "| Time:" across:4 offset:[195,0]
		label Time_5 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_5 "| Memory:" across:2 offset:[65,0]
		label Memory_5 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_5 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
		edittext Text_6 "06:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_6 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_6 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_6 "| Time:" across:4 offset:[195,0]
		label Time_6 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_6 "| Memory:" across:2 offset:[65,0]
		label Memory_6 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_6 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
		edittext Text_7 "07:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_7 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_7 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_7 "| Time:" across:4 offset:[195,0]
		label Time_7 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_7 "| Memory:" across:2 offset:[65,0]
		label Memory_7 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_7 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
		edittext Text_8 "08:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_8 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_8 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_8 "| Time:" across:4 offset:[195,0]
		label Time_8 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_8 "| Memory:" across:2 offset:[65,0]
		label Memory_8 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_8 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
		edittext Text_9 "09:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_9 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_9 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_9 "| Time:" across:4 offset:[195,0]
		label Time_9 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_9 "| Memory:" across:2 offset:[65,0]
		label Memory_9 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_9 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
		edittext Text_10 "10:" across:7 fieldWidth:485 tooltip:"Enter single-line expression to evaluate."
		checkbox Redraw_10 "Redraw Off" across:6 offset:[375,0] checked:false tooltip:"Keep redraw off during execution"
		checkbox Undo_10 "Undo Off" across:5 offset:[320,0] checked:false tooltip:"Keep undo off during execution"
		label TimeLabel_10 "| Time:" across:4 offset:[195,0]
		label Time_10 "0 " align:#right across:3 offset:[110,0] style_sunkenedge:true
		label MemoryLabel_10 "| Memory:" across:2 offset:[65,0]
		label Memory_10 "0 " align:#right offset:[0,0] style_sunkenedge:true
		label Result_10 "Returned:	undefined " align:#right offset:[0,0] style_sunkenedge:true
	) -- Function evaluation group
	local Texts = for ctrl1 in ExpressionBenchmark.controls where matchPattern ctrl1.name pattern:"Text_*" collect ctrl1 -- Get array of text controls
	local Redraws = for ctrl2 in ExpressionBenchmark.controls where matchPattern ctrl2.name pattern:"Redraw_*" collect ctrl2 -- Get array of redraw off controls
	local Undos = for ctrl3 in ExpressionBenchmark.controls where matchPattern ctrl3.name pattern:"Undo_*" collect ctrl3 -- Get array of undo off controls
	local Times = for ctrl4 in ExpressionBenchmark.controls where matchPattern ctrl4.name pattern:"Time_*" collect ctrl4 -- Get array of time controls
	local Mems = for ctrl5 in ExpressionBenchmark.controls where matchPattern ctrl5.name pattern:"Memory_*" collect ctrl5 -- Get array of time controls
	local Results = for ctrl6 in ExpressionBenchmark.controls where matchPattern ctrl6.name pattern:"Result_*" collect ctrl6 -- Get array of time controls
	on Execution pressed do 
	(
		local Count1 = Iterations.value -- Get number of times to average execution times
		local TotalTimes = 0 --Initial total time value
		local TotalMems = 0 --Initial total memory value
		local TimeNum = 1 -- Initial number to divide to convert time measurement
		local MemNum = 1 -- Initial number to divide to convert time measurement
		if (GCollection.selection == 1) then gc light:true delayed:true else -- Perform auto garbage collection
		if (GCollection.selection == 2) then gc() else -- Perform manual garbage collection
		if (GCollection.selection == 3) then gc light:true -- Perform manual light garbage collection
		if (TimeMeasure.selection == 2) then TimeNum = 1000 else -- Convert to seconds
		if (TimeMeasure.selection == 3) then TimeNum = 60000 else -- Convert to minutes
		if (TimeMeasure.selection == 4) then TimeNum = 360000 else -- Convert to hours
		if (MemoryMeasure.selection == 2) then MemNum = 1000 else -- Convert to kilobytes
		if (MemoryMeasure.selection == 3) then MemNum = 1000000 else -- Convert to megabytes
		if (MemoryMeasure.selection == 4) then MemNum = 1000000000 -- Convert to gigabytes
		for i = 1 to 10 do
		(
			if (Texts[i].text != "" and Iterations.value >= 1) then
			(
				local AverageTime = 0 -- Initial average time
				local AverageMem = 0 -- Initial average memory
				local Result = undefined -- Initial expression result
				if (GCollection.selection == 4) then gc() else -- Perform manual garbage collection for all expressions
				if (GCollection.selection == 5) then gc light:true -- Perform manual light garbage collection for all expressions
				for j = 1 to Count1 do
				(
					local Start_Time = timeStamp() -- Start timer
					local Start_Mem = heapfree -- Start memory size
					if (Undos[i].checked == true) then (undo off (if (Redraws[i].checked == true) then (with redraw off (local Result = execute Texts[i].text)) else (local Result = execute Texts[i].text))) else (if (Redraws[i].checked == true) then (with redraw off (local Result = execute Texts[i].text)) else (local Result = execute Texts[i].text)) -- Execute input text)
					AverageTime += (timeStamp() - Start_Time) -- Add time to average 01 time
					AverageMem += (Start_Mem - heapfree) -- Add time to average 01 time
					if (j == 1) then Results[i] = "Returned:	" + (Result as string) + " " -- Get execution result on first pass
				) -- Execute and add to average times
				if (TimeMeasure.selection == 1) then AverageTime = (AverageTime / Count1) else AverageTime = double((AverageTime / Count1)) / TimeNum -- Get averaged time
				if (MemoryMeasure.selection == 1) then AverageMem = (AverageMem / Count1) else AverageMem = double((AverageMem / Count1)) / MemNum -- Get averaged memory
				TotalTimes += AverageTime -- Add to total time
				TotalMems += AverageMem -- Add to total memory
				Times[i].text = ((AverageTime as string) + " ") ; Mems[i].text = ((AverageMem as string) + " ") ; Results[i].text = Result --Assign label values
				Total_Time.text = ((TotalTimes as string) + " ") --Assign variable to total time text
				Total_Memory.text = ((TotalMems as string) + " ") --Assign variable to total memory text
			) -- If current execution text is not empty and the passes count is at least 1
		) -- Loop through expressions
	) -- Press execute button
) -- Rollout
createDialog ExpressionBenchmark 1000 480 style:#(#style_titlebar, #style_border, #style_sysmenu, #style_minimizebox, #style_resizing) lockWidth:true
 
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

you are probably missing something. it’s your version more complicated

[left]Okay so, I didn’t know you could use just the label’s name (LabelControl) in a variable, and assign values through it, which I probably would’ve used from the start, if I knew that. Instead of collecting the labels using a filter into an array, I could just explicitly put the label controls manually into an array. So using –


local Texts = #(Text_1,Text_2,Text_3,Text_4,Text_5,Text_6,Text_7,Text_8,Text_9,Text_10) -- Get array of text controls
local Redraws = #(Redraw_1,Redraw_2,Redraw_3,Redraw_4,Redraw_5,Redraw_6,Redraw_7,Redraw_8,Redraw_9,Redraw_10) -- Get array of redraw off controls
local Undos = #(Undo_1,Undo_2,Undo_3,Undo_4,Undo_5,Undo_6,Undo_7,Undo_8,Undo_9,Undo_10) -- Get array of undo off controls
local Times = #(Time_1,Time_2,Time_3,Time_4,Time_5,Time_6,Time_7,Time_8,Time_9,Time_10) -- Get array of time controls
local Mems = #(Memory_1,Memory_2,Memory_3,Memory_4,Memory_5,Memory_6,Memory_7,Memory_8,Memory_9,Memory_10) -- Get array of time controls
local Results = #(Result_1,Result_2,Result_3,Result_4,Result_5,Result_6,Result_7,Result_8,Result_9,Result_10) -- Resulting array of result controls
 

did seem to work for me. Its not a big deal if I use that instead, because my expression script uses only 10 expressions. Although if I want to have a script that has a dynamic number of expressions, where the user chooses how many expressions there are, which I believe you can do, by creating and destroying ui controls, I will probably have to use denis’ method.

Anyways thanks guys for your help. If you have any other ideas about this, or ideas about my script, let me know.
[/left]

I completely agree with Denis, his solution is much simpler and universal (and less prone to human error), it avoids creating arrays of controls altogether.

Have a look at case expression

1 Reply
(@ian31r)
Joined: 11 months ago

Posts: 0

Well I agree that its probably more universal and less prone to human error and I’m not a maxscript pro, but in my opinion, it doesn’t seem simpler, since an array is just one line, and, with denis’ method, you have to create two separate functions just to achieve the same thing. Now if I had a 100 labels to update, I would probably use denis’ method, because that would be a really long array Maybe you could explain in depth how the functions work.

What’s case expression?

i’m a mxs pro, and i don’t define two functions just to achieve the same things.

Wait a minute, denis I think you are misunderstanding what I’m saying. I’m not saying your two functions are achieving the same thing as each other, our methods are trying to achieve the same thing.

Most of the time, if code is shorter in the number of lines, I see it as simpler and more compact. Also I’m not really used to using functions for one purpose, only when I need to use it many times throughout the script. Also, because I don’t fully understand your functions, it seems more complicated.

ok. it makes sense. just try to understand to make it seems simple.

1 Reply
(@ian31r)
Joined: 11 months ago

Posts: 0

Yeah, I’ll try to figure out your functions, piece by piece, and how I can use it in different cases.

Page 1 / 2