OSX MDI confusion
-
Hello everyone,
I am about to start working on improving our OSX support for V-Ray for SketchUp. The biggest issue we have on that platform, is the way SketchUp handles multiple documents being open at the same time. We make our own materials that correspond to SketchUp materials that are in the model, and we also have a set of render options which we attach to the model. On Windows, it's simple, each model gets it's own instance of SketchUp, so inherently everything is separate and clean. On OSX, since our plugin gets loaded once, regardless of how many models are open, our information gets rather confused.
So I am not sure how to fix this. We need to do 2 things:
-
know how many models are open, and how to identify each one in a unique and per-session constant way. The model guid changes when the model is modified or saved, and the path is empty if the user has never saved the model to disk. Both of those are useless for this case.
-
know when a user switches from working in one model, to the next, so we can update our UI and show the proper render options and materials for that current scene.
We have been scratching our heads about this for the past couple of years, and now that we are approaching a final release candidate, we would like to try to tackle this issue if we can. Does anyone have any ideas?
For a possible workaround for #2, we could check the SketchUp.active_model when our UI gets focus. For a possible workaround for #1, we could perhaps attach a guid string that we make, to the model's attribute dictionary. I was really hoping that there would be some sort of built in SketchUp functionality that would let us know what is going on though.
Best Regards,
Devin Kendig
Developer
Chaos Group -
-
-
As long as you don't need a reference that is persistent over sessions (closing/restarting of SketchUp), a simple object reference to the active model should be enough. Use active_model only the first time when the user selects a tool for a specific model and then store a reference to it so that it doesn't matter whether the user switches focus before completing the action.
I use for example something like
@@models = { <Sketchup::Model:0x3456> => <MyToolInstance:0x85698>, <Sketchup::Model:0x478043> => <MyToolInstance:0x946932>… }
Does that work for your situation? -
Would ideally require an onActiveModelChanged AppObserver which does not exist. I don't know if someone has any other trick, but the UI focus event seems like a good work-around (although it would not happen in sync with the model focus change).
I don't know if a ViewObserver with a check of view.model would be called too often.
-
-
it is possible to create a unique per model cache, for any number of open windows.
this is part of working out what I could and couldn't do
it could defiantly do with a review, but it does work.
##################################################################### ## # Apple Pudding Wed Jan 11 00;12;31 +0000 2012 # ## ##################################################################### # require('sketchup.rb') #Sketchup.send_action("openRubyConsole;") #module JcB # later dan... def proof # just type proof after loading #--------------------------------------------------------------------- su_Id=true begin model = Sketchup.active_model() su_Id = model.definitions.object_id() has_title = model.title() add_title = "Unsaved_" + su_Id.to_s # First check if there's an active model name if has_title.to_a.length == 1 then current_title = has_title else current_title = add_title end rescue # .. handle error # UI.messagebox("You need an open .skp for this to work") puts "You need an open .skp for this to work" else #check puts "model name is; " + current_title.to_s ensure puts "current_title " + "is a " + defined? current_title puts "Congratulations no errors!" end #-------------------------------------------------------------------- begin path = "/tmp/" # our Directory current_path? If not make one. cacheDir = "/tmp/macSUcache" # is CLEARED after a system Shut Down not Restart which is all I normally do. if not File.exists? cacheDir then Dir.mkdir(path + 'macSUcache') end #check puts "current path is; " + cacheDir.to_s puts "cacheDir " + "is a " + defined? cacheDir rescue puts "what now???" else puts "Congratulations no errors!" end #-------------------------------------------------------------------- ## begin unique_Id =(cacheDir + "/" + current_title.to_s + "_su.txt") #check puts "this models cache ID; " + unique_Id.to_s puts "unique_Id " + "is a " + defined? unique_Id rescue puts "again?...what now???" else puts "Congratulations no errors!" end #-------------------------------------------------------------------- ## Proof ####################################################################### begin # Create/open a current model file in read-write [adds new to end of existing] mode, use "w" for over-writing f = File.open unique_Id, "a+" # # Write an array of Strings to the file nums = [["\n"] + [Time.now] + ["", "", "", "", "", ""].sort_by { rand }] f.puts nums #check # puts "the File; " + unique_Id.to_s + " is now open? " + File.exists?(unique_Id).to_s puts "f " + "is a " + defined? f rescue puts "again?...what now???" else puts "Congratulations no errors!" #should return true is now writen # ## # Rewind the file, read its lines, and print the third line # # # f.rewind f.readlines.join ensure f.close unless f.nil? #check puts "Congratulations no errors!" puts "this File; " + unique_Id.to_s + " now closed? " + f.closed?.to_s end #begin end #def ############################################################################## ##--------------------------------------------------------------------------
when you enter 'proof' it returns individually identified windows in the same session.
proof model name is; Unsaved_143187840 current_title is a local-variable Congratulations no errors! current path is; /tmp/macSUcache cacheDir is a local-variable Congratulations no errors! this models cache ID; /tmp/macSUcache/Unsaved_143187840_su.txt unique_Id is a local-variable Congratulations no errors! f is a local-variable Congratulations no errors! Congratulations no errors! this File; /tmp/macSUcache/Unsaved_143187840_su.txt now closed? true Tue Jul 09 01;56;30 +0100 2013
as a further experiment I attached to the v8 Undo Log and it would bring up the individual models tool history.It's a rough experiment, but it worked with v8's undolog
-
The definitions object_id never changes in a given session? I just tried to find a case where it changes, and I can't find one, but I'm scared to make that assumption if it's not true 100% of the time. I don't want to use the window title, because you can have two files with the same title, or no title at all. None of this needs to be human readable, I just need to be able to differentiate between the windows reliably, quickly, and with as little code as possible. I do like just using a value in the SU model, rather than having to modify or retrieve an attribute dictionary value. I prefer to avoid modifying attribute dictionaries when possible, as that can lead to some plugin conflicts.
-
Just got a reply form Paul on the SketchUp Extensibility Team:
@unknownuser said:
Yes, I believe that would work fine. However, I recommend using the Entity member entityID instead, like this: Sketchup.active_model.definitions.entityID. This one also doesn't persist between sessions, but it is a unique index across all entities Sketchup has loaded (even with multiple models), and active_model.definitions is a SketchUp entity.
So there we go, a unique (even across multiple models) ID that we can rely upon! Thanks for pointing me in that direction.
-
also just noticed that this topic has already been discussed in this thread: http://sketchucation.com/forums/viewtopic.php?t=43219 ::blushes:: whoops!
-
that does seem to work
if you want a persistent reference you can add an
xattr
to the active model file...def only_iff model = Sketchup.active_model modName = Sketchup.active_model.title modPath = Sketchup.active_model.path modEntID = Sketchup.active_model.definitions.entityID case when modName.to_a.length == 1 then remove_old = %x(xattr -d test "#{modPath}" 2>&1) if (%x(xattr -p test "#{modPath}" 2>&1)).length > 0 perSistent = %x(xattr -w test "#{modEntID}" "#{modPath}" 2>&1) puts modEntID # but could be any persistent reference when modName.to_a.length == 0 then Sketchup.send_action('saveDocument;') UI.messagebox "Save model and retry" end #case end # def only_iff
then in another session you can check if it's been thru your mill before.
modPath = Sketchup.active_model.path %x(xattr -p test "#{modPath}" )
just thoughts
john
Advertisement