Notifications
Clear all

[Closed] states Manager & persistent globals

All right.
In short, We use persistent global arrays to store object visibility, light on/off states, and xref
enabled/disabled states, and an active camera. (our custom states manager is explicitly for these 3 things).
When a given state is selected and restored, a camera is restored, then all lights turned on or off, xrefs enabled or disabled, and objects visibility turned on or off, based on a camera sequence to be rendered.
Our persistent global vars and callbacks are being totally wiped out by using the
Load Render Presets. Literally, using this feature, all callbacks are disabled, and our persistent arrays are being set to empty. And none of this is being restored when a preset is done loading. HELP. Does anyone know why this is the case, and if so, know of a way to prevent it from happening. The callbacks would be nice as a workaround to temp store the info in a normal array and then restore after the render preset is loaded, but with callbacks also disabled, well…that kills
any automation to this, as well as any good reason to use persistent globals to begin with.
This is affecting any and all of our custom interfaces that use persistents.
Any info would be much appreciated. Thanks

6 Replies

I don’t know exactly why all your persistens are wiped out by the presets but I can suggest different routes. Instead of using persistent globals you can use the “appdata” for each object or the “setIniSetting/getIniSetting”.

With the appdata you’ll save a value for each object and when trying to set up your scene you can build your arrays from the saved appdata. This method is very fast and it’s saved with your file.

The second one, “setIniSetting/getIniSetting”, will need an external .ini file in which you’ll save your arrays and all the other info that you need. The downside of this one is the need for an external file…

For more info on both this you can look in the reference. They are very straightforward and easy to use.

Hope this helps…
Anton.

Thanks Anton for the suggestions.
I was unaware of either of these options.
I’ll have to try converting one of the interfaces to use one of these methods.
This might be a week or two out though. I’ll try this out and let you know the results / pitfalls
etc. Thanks.
Chad

I’m guessing here, but I’m betting that you setup a #filePreOpen callback that undefines your persistent global variable’s value, so that your #filePostOpen callback can check whether the opened file contains another value for that persistent variable?

If this is the case, then I think you are encountering 2 related problems:

  1. The loading of a Render Presets file is triggering your #filePreOpen and #filePostOpen callbacks. When this happens, your callbacks are probably resetting the values of your persistent variables. Look at the callbacks.notificationParam() info under both of these callback types in the MaxScript (6 or later) documentation. You’ll need to modify your callback to detect whether the event is actually just a Render Preset load event, and thus behave differently…maybe do something different, maybe do nothing.

  2. Because your callbacks’ code was written to deal with an actual #filePreOpen or #filePostOpen event, they are probably encountering errors when executed at the Render Preset load event. When any error is encountered in the execution of a callback, that callback is immediately disabled (not removed) for the rest of the current max session. No warning dialogs or messages will be shown when this happens. (The callbacks’ code will execute [color=deepskyblue]until they encounter an error, so I’m betting that your resetting of the persistent value occurs early in your callback code…before the error disables the callback.)[/color]

I’ve used persistents for quite a while, and I use both persistent and temporary (non-persistent) callbacks in my script to deal with #filePreOpen, #filePostOpen, #filePreMerge, #filePostMerge, #systemPreNew, #systemPostNew, #systemPreReset, #systemPostReset, and #preSystemShutdown events. It is quite involved, but you can bulletproof your script’s persistents from events like this…as long as you know about all the possible events!

This one was a surprise to me though, and I’ll eventually have to modify my script as well to avoid this problem…

Some Tips on Persistent Callbacks: If you are using persistent callbacks to protect/deal with this data, you need to be aware that the callbacks will be brought in during file Open, Merge and XREF events just like the persistent global values. This can cause your scene to suddenly have duplicate callbacks in the same file. (I don’t think they’ll be declared as persistent in the current scene, but they will absolutely execute on their assigned event.)

1) I avoided this for file Open events by having the persistent #filePreOpen callback remove all of my persistent callbacks, and my temporary #filePostOpen callback remove them again (from the opened file) and then rebuild the persistent callbacks. (They have to just be removed here, since you can’t actually test for their presence.)

2) For Merge/XREF events, I had my persistent #filePostMerge callback clear and then rebuild the callbacks…the persistent #filePreMerge didn’t touch them, since the #filePostMerge callback is only triggered for the current file (never the one being merged in).

3) For file New/Reset events, duplication was not the problem but the callbacks had to be added as persistent in the new scene. For this I had the persistent #systemPreNew/#systemPreReset callbacks remove all of my persistent callbacks, and the temporary #systemPostNew/#systemPostReset callbacks rebuild them in the new scene.

Shoot John, I think you might be on the right track here.
I am not looking at the program now, but trying to remember, yes, i was using some
callbacks on open reset etc, to make sure new files got the var in question, or if it already
existed and was populated, do nothing, but if empty or non existent, create/redefine.
Basically, as you said, trying to make things air tight. When I can, i will check the error issue
you mentioned that may cause them to be disabled, shut down. Thanks.
I will still probably play some with the things Anton mentioned as well for future stuff. or this
if these suggestions don’t work out.

Okay,

I’ve worked with the code, and you were right on the money.
I had a callback for filePreOpen, where i was setting my var to empty based on a new
file having that var written in (defined). As you said, this was early in the code. The render preset
fired the callback and reset my vars in the current file. Using the notification Param as you mentioned, i captured that to a var so that I may run it through an IF check and perform the proper action, which in the case of render presets, was do nothing.
Thank you very very much.
As a test which worked this is what i used, but later will get exact data on the params values
returned etc.

callbacks.addscript #filepreopen “global opentest = callbacks.notificationParam()

if opentest == 2 then ( messagebox “RenderPreset Loading “)

else ( persistent global stateArray = #() )
etc.

You might already have done this, but I would remove the unnecessary global variable and just insert the test directly in the test expression…I’m never afraid to create globals, but that one is unnecessary. The code below also illustrates how to make very complex callbacks quite readable and editable. You can comment out specific commands without inadvertantly commenting out parentheses or some other syntax.

(
local FilePreOpenString = ( 
"print \"debug_PreOpCBStart\"; "+
"if (callbacks.notificationParam())==2 "+
"then (messageBox \"RenderPreset Loading\")"+
"else (persistent global stateArray = #()); "+
"print \"debug_PreOpCBFinish\""
)
callbacks.addscript #filePreOpen (FilePreOpenString) id:#MyToolsTempCB
)