TextPlus animation not works as expected


#1

Hi!

The goal is to animate textPlus objects so on every frame of animation to show different text.
This is the code that I use:

(
	tp1 = textPlus size:25 pos:[0,0,0]
	tp2 = textPlus size:25 pos:[0,50,0]
	
	textObjsArr = #(tp1, tp2)
	
	strArr = #(#("Monday", "Tuesday ", "Wednesday ", "Thursday", "Friday", "Saturday", "Sunday"), #("Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
		
	animationRange = (interval 1 12)
	
	slidertime = 1
	for i = 1 to textObjsArr.count where isValidNode textObjsArr[i] do
	(
		t = textObjsArr[i]
		theCtrl = float_script()
		theCtrl.addNode "TheText" t
		theCtrl.addConstant "strArr" strArr[i] 
		theCtrl.SetExpression "if F != 0.0 then TheText.SetPlaintextString strArr[F]\n0"
		t.tracking.controller = theCtrl
	)	
)

But, when I run it and then I move the animation slider the text that both textPlus objects shows is not correct.
On frame 1 it shows Feb and Tuesday, nex time it may show Mar and Wednesday, etc.
Just play with the animation slider and you will see what I mean.

Is my code wrong?


#2

Set the FPS to 1 (in Viewport - Time configuration) and check.


#3

Do you mean to set the FPS here:

The same problem exist when I set FPS to 1.


#4

Yes, but that’s just quick way to normalize time, check for problems in expression…

You have to set time range after that again.

Best would be to debug it in controller window, I think you have probs with S variable.


#5

Here is updated code:

(
	tp1 = textPlus size:25 pos:[0,0,0]
	tp2 = textPlus size:25 pos:[0,50,0]
	
	textObjsArr = #(tp1, tp2)
	
	strArr = #(#("Monday", "Tuesday ", "Wednesday ", "Thursday", "Friday", "Saturday", "Sunday"), #("Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
		
	animationRange = (interval 1 12)
	
	slidertime = 1
	for i = 1 to textObjsArr.count where isValidNode textObjsArr[i] do
	(
		t = textObjsArr[i]
		theCtrl = float_script()
		theCtrl.addNode "TheText" t
		theCtrl.addConstant "strArr" strArr[i] 
		theCtrl.SetExpression "print F\n print strArr[F]\n if F != 0.0 then TheText.SetPlaintextString strArr[F]\n0"
		t.tracking.controller = theCtrl
	)	
)

In the maxscript listener it shows proper F and strArr[F] which means that the code reads the proper day and month, but the TextPlus objects shows wrong day and month.
No matter if I set FPS to 1 and then I set the time range again and after that I run the script - the problem exist.


#6

Tried for a while without success, sorry.


#7

Hi, Andres!

Thank you.
Yes, no mater what I do it not works. But if a regular Text object is used then everything works fine.

(
	tp1 = text pos:[0,0,0]
	tp2 = text pos:[0,50,0]
	
	textObjsArr = #(tp1, tp2)
	
	strArr = #(#("Monday", "Tuesday ", "Wednesday ", "Thursday", "Friday", "Saturday", "Sunday","Monday", "Tuesday ", "Wednesday ", "Thursday", "Friday"), #("Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
		
	animationRange = (interval 1 12)
	
	slidertime = 1
	for i = 1 to textObjsArr.count where isValidNode textObjsArr[i] do
	(
		t = textObjsArr[i]
		theCtrl = float_script()
		theCtrl.addNode "TheText" t
		theCtrl.addConstant "strArr" strArr[i] 
		theCtrl.SetExpression "if F != 0.0 then TheText.text  = strArr[F]\n0"
		t.kerning.controller = theCtrl
	)	
)

It is time to find workaround. :slight_smile:


#8

upd not really working ;(


#9

I am testing it on max2020 and it not works.

Here is a video that shows what happen on my PC.

" https://drive.google.com/file/d/10alphEdBwlMNZXIHZ_kIdbJiQPlMyc7o/view?usp=sharing "


#10

You have “array index must be positive number” thingy.
That means integer also. I dont know why it’s not getting those values only from yours frames but I think that you’ll have to define it “precisely” - as a whole, positive numbers.
Try google that expectation, there are some results for Max.

My FPS thing can be quick’n’dirty help in some places, but not here, obviously.


#11
delete objects

t = textplus dir:-y_axis isselected:on
s = t.tracking.controller = float_script()
s.addnode "self" t
s.addconstant "list" #("A:","B:","C:","D:","E:","F:") 
s.setexpression "text = formattedPrint (int T) format:\"06X\"; self.setPlaintextString (list[mod F 6 + 1] + text); 0"

all works for me (MAX 2018 and MAX 2020)


#12

here is a “PRO” version - keeps #tracking controller animatable

delete objects

t = textplus dir:-y_axis isselected:on
	
c = t.tracking.controller = float_list()
f = c.available.controller = linear_float()

s = c.available.controller = float_script()
c.active = 1
s.addnode "self" t
s.addconstant "list" #("A:","B:","C:","D:","E:","F:") 
s.setexpression \
@"
	text = formattedPrint (int T) format:#'06X'
	if not self.isselected do self.setPlaintextString (list[mod F 6 + 1] + text)
	0
"

I disabled the setting text when the node is selected… it’s just to prevent continuous updating the modifier panel


#13

Same runtime error.
Open tracking/script controller (window) to get it.


#14

Thank you, Denis,

I modified your code to this:

(
	delete objects

	tp1 = textPlus size:25 pos:[0,0,0]
	tp2 = textPlus size:25 pos:[0,50,0]
	
	textObjsArr = #(tp1, tp2)
	
	strArr = #(#("Monday", "Tuesday ", "Wednesday ", "Thursday", "Friday", "Saturday", "Sunday"), #("Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
		
	animationRange = (interval 0 12)
	
	slidertime = 0
	for i = 1 to textObjsArr.count where isValidNode textObjsArr[i] do
	(
		t = textObjsArr[i]
		c = t.tracking.controller = float_list()
		f = c.available.controller = linear_float()
		s = c.available.controller = float_script()
		c.active = 1
		s.addnode "self" t
		s.addconstant "list" strArr[i] 
		s.setexpression \
		@"
			cnt = list.count
			if not self.isselected do self.setPlaintextString (list[mod F cnt + 1])
			0
		"
	)
)

It works in one direction only. When I move the time slider from left to right the proper month and day is shown. When I move the time slider from right to left - the wrong month and day is shown. For example, moving the slider:
frame 1 -> Jan
frame 2 -> Feb
frame 3 -> Mar
frame 4 -> Apr
frame 3 -> Maj instead of Mar
frame 2 -> Apr instead of Feb
frame 1 -> Mar instead of Jan

When I use this:

(
	delete objects

	tp1 = textPlus size:25 pos:[0,0,0]
	tp2 = textPlus size:25 pos:[0,50,0]
	
	textObjsArr = #(tp1, tp2)
	
	strArr = #(#("Monday", "Tuesday ", "Wednesday ", "Thursday", "Friday", "Saturday", "Sunday"), #("Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
		
	animationRange = (interval 1 12)
	
	slidertime = 1
	for i = 1 to textObjsArr.count where isValidNode textObjsArr[i] do
	(
		t = textObjsArr[i]
		c = t.tracking.controller = float_list()
		f = c.available.controller = linear_float()
		s = c.available.controller = float_script()
		c.active = 1
		s.addnode "self" t
		s.addconstant "list" strArr[i] 
		s.setexpression \
		@"
			cnt = list.count
			if not self.isselected do self.setPlaintextString (list[mod F cnt + 1])
			0
		"
	)
)

Animation is from frames 1 to 12. The frame 1 never shows the correct month/day. And the same problem when slider is moved from right to left exist.

I tried to assign the flaotList to other animatable controllers(not TextPlus.tracking) but the result is the same.

When Text objects are used the problem with the wrong month/day not exist no matter how I move the animation slider. For example this code shows proper month/day no matter that the animation starts from frame 3.

(
	tp1 = text pos:[0,0,0]
	tp2 = text pos:[0,50,0]
	
	textObjsArr = #(tp1, tp2)
	
	strArr = #(#("Monday", "Tuesday ", "Wednesday ", "Thursday", "Friday", "Saturday", "Sunday","Monday", "Tuesday ", "Wednesday ", "Thursday", "Friday"), #("Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
		
	animationRange = (interval 3 12)
	
	slidertime = 3
	for i = 1 to textObjsArr.count where isValidNode textObjsArr[i] do
	(
		t = textObjsArr[i]
		theCtrl = float_script()
		theCtrl.addNode "TheText" t
		theCtrl.addConstant "strArr" strArr[i] 
		theCtrl.SetExpression "if F != 0.0 then TheText.text  = strArr[F]\n0"
		t.kerning.controller = theCtrl
	)	
)

#15

And no more errors :wink:
Yeah, now “isselected” makes good sense


#16
delete objects
(
	t = textplus name:#test dir:-y_axis isselected:on
	s = t.tracking.controller = float_script()
	s.addnode "self" t
	strs = #(#("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"), #("Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))

	animationrange = interval 1 12.9	
	s.addconstant "list" strs[1] 
	s.setexpression "tx = list[int F]; self.setPlaintextString tx; self.getPlaintextString &_tx; format \"% #% = %\\n\" F tx _tx;\n 0"
)

i see the issue now… but as you can see text matches frames (see print)…
we have to force somehow mesh update…


#17

After you “Set Value as Text” everything works as expected. But I don’t see a way to do it with a script yet (excluding direct access to the UI)


#18

after updating 3ds max to 2020.2 we have SetValueAsText in MaxScript. but … it doesn’t work for me. Always returns FALSE with any options. If anyone has time or an emergency, welcome to the game … I pass.

BTW 2020.3 update is available but I have not tried it.


#19

Yes, the text matches the frames, but the mesh is not updated properly.


#20

In the TextPlus’s method that builds the object, the string to display is acquired and shape buffers are built from that before the tracking value (or any other value) is acquired. Changing the text in the controller doesn’t affect the current object currently being built. Without some changes in the code (acquire animated values before acquiring the string), what you are trying to do will simply not work.

Larry Minton