Detecting active model switches on OS X
-
Hi all,
While working on a rendering plugin/exporter, I noticed that errors appear when having multiple SketchUp models open on OS X. This is no surprise as the plugin has been written assuming there would always just be one active model per session, but it is a clear usability issue and I would like to solve it.
So far, I haven't found any observer that triggers on switching from one model to another when both models are already open. Is there any observer that I may have overlooked that keeps track of Sketchup.active_model?
If no observer is available, what would be a good way to detect that the active model has changed? I could of course check for changes in Sketchup.active_model when any of the existing observers is triggered (including ViewObserver), but this would still miss the scenario where the user just clicks on a different SketchUp window to activate it. And perhaps more importantly, I'm always worried about slowing down SketchUp when using observers.
-
On a PC every open SKP window is a separate process - so a reference to the 'active_model' is fixed, but on a MAC there is only one process with multiple windows - so on a MAC the SKP window at the from is the 'active_model' - so make sure your reference to your model is fixed...
Assuming your code is in a module set
@model=Sketchup.active_model
at every critical step...
This ensures that you don't get 'cross-threaded' references to another MAC model.Without seeing all of your code it's hard to say what needs adjusting - but I have had similar issues - which were resolved by making sure the model's reference was always set properly at specific stages in the code...
-
No observer for that as yet.
But I personally have filed Feature Requests for a Sketchup::ModelSet collection, as well as onFocus() and onBlur() observer callbacks for the
Sketchup::ModelObserver
class.Some coders try to create their own collection of models (by using
Sketchup::AppObserver
callbacks.) But there have been bugs with regard to the model instance's Ruby reference.We have discussed this at length here in this forum. Do forum search.
-
The issue was discussed in this topic (among others.):
-
Here is another topic where we discuss the bugs in detail (it had a link in the [Code Snippets] Index.):
-
Thank you both for the constructive replies. Somehow yesterday I couldn't find any relevant threads, but earlier today I did with slightly different search terms and I've looked at them in detail. From what I understand, I can get a unique id for each model and check for that at critical moments (when opening dialogs, or when changing settings), but there is no way to catch the exact moment when a user switches files on OS X. So the technical situation is clear.
The script I'm working on is SU2LUX (https://bitbucket.org/luxrender/su2lux/src), the exporter for LuxRender. Render settings are stored in attribute dictionaries, so when multiple files are open there are multiple sets of settings that can be accessed. However, there is always only one settings dialog.
The main design issue I need to solve is this: When two models are open and my exporting options dialog shows the values from model 1, then the user switches to model 2 and changes a value in the dialog, what do I do? One approach would be to check for a change in active_model and update all values in the dialog as soon as anything is changed. Another is to create a collection of open models and display them in a dropdown (or just a text) at the top of the dialog, so one can always see what model one is working on, regardless of which one is active_model. A third possibility is to create one settings dialog per file.
None of these options seems ideal, but I'll just have to decide which one is the best one. If anybody has input on this or can think of a better solution, I would much appreciate it.
-
@tig said:
Assuming your code is in a module set
@model=Sketchup.active_model
at every critical step...
This ensures that you don't get 'cross-threaded' references to another MAC model.+1
Remember many classes related to the model will have a.model
method to return the model that given object belong to.That being said, we do need a way to iterate open models.
-
Try to only open 1 Settings dialog per model.
Display it's name/path in the caption bar.
Whatever changes are done, save them to the model that "belongs" to the dialog.The user may wish to open the settings for 2 separate models, in order to compare the settings.
The actual command to begin the export should be independent of the settings (but of course will use them.) Meaning that opening the Settings dialog, and launching the export would be two distinct commands.
The export would act upon the currently active model, and you could display a confirmation dialog that displays the model name/title/path etc., just in case the user had the wrong model active.
Also you can "grab" a list of all models from the Ruby environment, and check each to be sure they are valid.
models = [] ObjectSpace.each_object(Sketchup;;Model) {|o| models << o if o.valid? }
.. just in case you wanted to build a selection set, in a inputbox (or WebDialog) dropdown list.
-
@dan rathbun said:
Try to only open 1 Settings dialog per model.
Display its name/path in the caption bar.
Whatever changes are done, save them to the model that "belongs" to the dialog.That sounds like the best solution, thanks! It took a while, but I have now implemented this behaviour. Unless somebody finds a showstopper within the coming days, I'll announce the new version of the plugin here on the sketchUcation forum.
Now that I have settings windows for all individual opened files, I would like to be able to close the relevant ones automatically when the user closes one of the files. I expected there to be an observer that notifies me when files are being closed, but again I get the impression I'm looking for something that isn't there. I could use onPreSaveModel, but that won't work if the user saves manually before closing. This is not a critical issue, but if anybody knows of a workaround that would be very helpful.
-
Attach a model observer and provide
onDeleteModel
andonEraseAll
callbacks that output something to the console.Then test, by closing a model.
I think one of them will fire (one does on the PC when I open a new model.)
-
And, BTW, I am purty sure we have already requested a
onCloseModel
observer callback. -
@dan rathbun said:
Attach a model observer and provide
onDeleteModel
andonEraseAll
callbacks that output something to the console.Thanks again!
onEraseAll does fire on Windows when opening another model, but not on OS X unfortunately. Interestingly enough, I also can't get it to fire on erasing all objects. onDeleteModel doesn't seem to ever trigger. I'll focus on other issues for now, this one can wait.
Advertisement