Notifications
Clear all

[Closed] speedup simple code

you guys have to understand that trackbar methods return just keys currently shown in trackbak. it depends on current filters. if no key was caught doesn’t mean that a node doesn’t have them at all.

4 Replies
(@polytools3d)
Joined: 11 months ago

Posts: 0

As Piotr mentioned in the original post “getNextKeyTime” was working for him so I assumed the needed keys where visible. In case there are some filter applyied, do you think this could help?

trackbar.filter = #all
(@denist)
Joined: 11 months ago

Posts: 0

not in all cases. there two types of filter: show and hide. the setting #all you ask for showing, but might be some other filters that hide the result.
so to be safe you have to set #all and disable all other. after all return everything back in a previous state.

(@polytools3d)
Joined: 11 months ago

Posts: 0

Thanks Denis. Yes, painful if not impossible. So checking if every custom filter does actually hide the keys, then disabling it and enabling it back does not look like a good approach.

(@denist)
Joined: 11 months ago

Posts: 0

you don’t have to check what filters do. just set them off.

another way of doing it possibly


  (
  fn isItAnimated anim =
    (
    	res = false;
    	if try(anim.isAnimated)catch(false) then
    		res = true;
    	else
    		for i = 1 to anim.numSubs while res == false do res = isItAnimated anim[i];
    	res;		
    )
    		
    fn enumerateNodes tnode =
    (
    	if tnode != rootNode and tnode.isSelected and  isItAnimated tnode then
    		print tnode;	
    	for n in tnode.children do
    		enumerateNodes n;
    )	
    
    enumerateNodes rootnode;
    )
left it incomplete but you get the gist

it’s a shame that theres already a recursive function to check whether max entity is animated in the SDK, but as far as I know it’s not been exposed to mxs. It’s a relatively simple to do if you have your own script extension…

def_visible_primitive(isNodeAnimated, "isNodeAnimated");

Value* isNodeAnimated_cf(Value **arg_list, int count)
{
	check_arg_count(isNodeAnimated, 1, count);
	INode* node = arg_list[0]->to_node();
	
	return bool_result(node->IsAnimated());
}

Thank all of you. I think this part of my work is already complete
This is absolutely free question.
I’m not maxscript specialist but when I put function insite my code, no matter what script, sooner or latter there is conflict – errors for instance:

rollout “” …
buttons …
on button open do
(

FUNCTION <—
)

so I declare all functions as very first lines of code, before create rollout and it work, like this:

FUNCTION <—
rollout “” …
buttons …
on button open do
(

CALL FUNCTION <—
)

I know it may be parenthesis issue but is there right place to declare functions and places where functions shuldn’t be declare like in buttons, etc?

here is a complete solution… probably the fastest way i know. first time it was suggested by lo: http://forums.cgsociety.org/showpost.php?p=7176944&postcount=19


  fn getActiveFilters = 
  (
  	for k=1 to maxOps.trackBar.filterCount() where maxOps.trackBar.isFilterActive k collect k
  )
  fn setActiveFilters active = 
  (
  	for k=1 to maxOps.trackBar.filterCount() do maxOps.trackBar.setFilterActive k (finditem active k > 0)
  )
  
  keyednodes = #()
  fn callbackFilterFunction theAnimatable theParent theSubAnimIndex theGrandParent theNode = 
  (	
  	if isController theAnimatable and theAnimatable.keys.count > 0 do
  		if isvalidnode theNode do appendifunique keyednodes theNode
  	true
  )
  with redraw off undo off 
  (
  	current = selection as array
  	keyednodes = #()
  	
  	active = getActiveFilters()
  	filter = trackbar.filter
  	trackbar.filter = #all
  	setActiveFilters #()
  	select objects
  	maxOps.trackBar.visible = on
  	index = maxops.trackbar.registerFilter callbackFilterFunction undefined "." 1 active:on
  	maxops.trackbar.redraw forceRedraw:on		
  	maxops.trackbar.unregisterfilter index
  	trackbar.filter = filter
  	setActiveFilters active
  	if current.count == 0 then clearselection() else select current
  	maxops.trackbar.redraw forceRedraw:on		
  )
  keyednodes
  

who is interested can read all that thread. it tells about some other solutions and some probable problems of different methods.

now it’s nicely wrapped


struct CollectAnimationDataStruct
(
	tb = maxOps.gettrackbar(),
	fn getActiveFilters = (for k=1 to tb.filterCount() where tb.isFilterActive k collect k),
	fn setActiveFilters active = (for k=1 to tb.filterCount() do tb.setFilterActive k (finditem active k > 0)),

	keyednodes = #(),
	fn callbackCollectKeyed theAnimatable theParent theSubAnimIndex theGrandParent theNode = 
	(	
		if isController theAnimatable and theAnimatable.keys.count > 0 do
			if isvalidnode theNode do appendifunique this.keyednodes theNode
		true
	),
	fn getKeyedNodes = with redraw off undo off 
	(
		current = selection as array
		keyednodes = #()
		
		active = getActiveFilters()
		filter = trackbar.filter
		trackbar.filter = #all
		setActiveFilters #()
		select objects
		tb.visible = on
		index = tb.registerFilter callbackCollectKeyed undefined "." 1 active:on
		tb.redraw forceRedraw:on		
		tb.unregisterfilter index
		trackbar.filter = filter
		setActiveFilters active
		if current.count == 0 then clearselection() else select current
		tb.redraw forceRedraw:on		
		keyednodes
	)
)
d = CollectAnimationDataStruct()
d.getKeyedNodes()

IsAnimated in sdk has some specific meaning. it doesn't mean the animatable has keys. it means that the animatable has a timeranded controller.
so all expression, script, constraint,  ... maybe some other type controllers are always shown as animated but doesn't support keys at all.

Here is another function. This one should take care of the Filters I hope:

(
 fn GetAnimatedNodes nodes:#() =
 (
 	_getNextKeyTime = trackbar.getNextKeyTime
 
 	disableRefMsgs()
 
 	-- Turn off Filters
 	currentfilter = trackbar.filter
 	trackbar.filter = #all
 	
 	filterscount = maxOps.trackBar.filterCount()
 	filtersstate = for j = 1 to filterscount collect
 	(
 		active = maxOps.trackBar.isFilterActive j
 		maxOps.trackBar.setFilterActive j false
 		active
 	)
 
 	-- Collect the animated nodes
 	arr = for node in (nodes as array) collect
 	(
 		select node
 		if _getNextKeyTime() == undefined then dontcollect else node
 	)
 
 	-- Restore Filters
 	trackbar.filter = currentfilter
 	for j = 1 to filterscount do maxOps.trackBar.setFilterActive j filtersstate[j]		
 	
 	enableRefMsgs()
 
 	return arr
 )
 )

i don’t think that disableRefMsgs() helps anyhow in this case. but it doesn’t do anything bad.
but you have to know that disableRefMsgs and enableRefMsgs work together only and must be paired. so you have to be 100% sure that code in-between is absolutely safe

2 Replies
(@polytools3d)
Joined: 11 months ago

Posts: 0

I tested the code with 900 nodes, 450 animated (position), and disableRefMsgs() makes the it run around 12 times faster. So perhaps it worth it to add try/catch somewhere to make the code safer I suppose.

(@denist)
Joined: 11 months ago

Posts: 0

it’s because you are changing selection… if there are now registered callbacks on this event it shouldn’t make so dramatic effect.

IsAnimated in sdk has some specific meaning. it doesn’t mean the animatable has keys. it means that the animatable has a timeranded controller.
so all expression, script, constraint, … maybe some other type controllers are always shown as animated but doesn’t support keys at all.

I did know that denis, I was just offering up another possible approach, a noise controller would be another type that registers as animated with no keys. Also constraints do not register as animated using this method apart from path constraint for obvious reasons (as long as it has it’s keys!).

Page 2 / 2