[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.
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
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.
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.
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
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.
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!).