by tomot » Tue Mar 06, 2012 8:38 pm
I've been digging through scripts, and while doing some module script incorporation, I'm of the opinion that using the Registry provides a cleaner less error prone way of dealing with this Subject: The following code is part of the 1st menu- Code: Select all
reg_key = "TNT::Bookshelf" prompts = ["Width", "Height", "Depth"] values = [2.feet, 2.feet, 1.feet] #---read registry values v = Sketchup.read_default(reg_key, "values") unless v.nil? values = eval(v) values[0] = values[0].to_l values[1] = values[1].to_l values[2] = values[2].to_l end
Am I correct in assuming that a 2nd menu ALWAYS needs its own new Registry entry? (like the following which does work) - Code: Select all
reg_key = "TNT::Bookshelf1" prompts = [ "No. of shelves wide ", "No. of shelves high ", "shelf thickness"] values = [ 5, 5, 1.inch ] #---read registry values v = Sketchup.read_default(reg_key, "values") unless v.nil? values = eval(v) values[0] = values[0].to_i values[1] = values[1].to_i values[2] = values[2].to_l end
BTW: if I use only one registry entry for both menus and increment the values in the 2nd menu ie. values[4] etc. I get a console error
-
tomot
-
- Posts: 610
- Joined: Mon Apr 07, 2008 12:18 am
- Operating system: Windows
- SketchUp version: 8
- License type: Free
- SketchUp use: architecture
- Level of SketchUp: Advanced
-
by Dan Rathbun » Tue Mar 06, 2012 9:38 pm
You are confusing terms again. They are input dialog boxes, NOT menus. NO. Each one of your plugins should only use ONE registry key. - Please begin all your keys with "Plugin_"
Reason.. this sets them apart from all other Sketchup subkeys, but still grouped together. And it follows the convention used by the WebDialog keys, which are always (automatically,) prefixed with "WebDialog_" - Whitespace (and '::') in keynames should be replaced with "_"
. like: REGKEY = 'Plugin_'<<Module.nesting[0].name.split('::').join('_')notice I use a constant (all caps,) because it will never change. It would produce for your example: 'Plugin_TNT_Bookshelf'BUT ... Each "set" of values OR special setting has it's own ATTRIBUTE name (under the common plugin KEY.) "RightHandDoorParams""LeftHandDoorParams"
-

Dan Rathbun
- Top SketchUcator
-
- Posts: 4069
- Joined: Tue Oct 06, 2009 3:06 am
- Location: Florida, USA
- Name: Dan Rathbun
- Operating system: Windows
- SketchUp version: 8
- License type: Pro
- SketchUp use: education
- Level of SketchUp: Advanced
by Dan Rathbun » Tue Mar 06, 2012 9:59 pm
Next issue. I gave you a couple of basic saving and loading option methods, in this thread's code sample: viewtopic.php?f=180&t=43673&p=390107#p389920What do you want to do differently ?? We can tweak the process. For example.. if you still wanted to use unique @@ names, like @@lhd_width, @@lhd_height, @@lhd_style, etc., instead of @@opts[:lhd_width], etc. everywhere in your code ... ... you CAN do that and still use the @@opts hash of saving and restoring. The trick is to collect ALL module variables (also called class variables,) into a array of var name strings, using the standard method class_variables()then iterate that array thus: - Code: Select all
vars = class_variables() vars.each do |var| eval("@@opts[#{var.gsub('@@',':')}]= #{var}") end # Now we can save the opts hash: set_saved_opts()
The reverse, after calling get_saved_opts(), to distribute the saved settings back to your module variables: - Code: Select all
get_saved_opts() @@opts.each do |attr,val| eval("@@#{attr.to_s} = @@opts[#{attr}]") end
-

Dan Rathbun
- Top SketchUcator
-
- Posts: 4069
- Joined: Tue Oct 06, 2009 3:06 am
- Location: Florida, USA
- Name: Dan Rathbun
- Operating system: Windows
- SketchUp version: 8
- License type: Pro
- SketchUp use: education
- Level of SketchUp: Advanced
by tomot » Tue Mar 06, 2012 11:18 pm
Dan Rathbun wrote:You are confusing terms again. They are input dialog boxes, NOT menus.
yes, menus my bad!... been a long day so far, could not sleep, I started coding at 3:30 am this morning, with good intentions trying your outline, finally had to sideline that effort, it in favor of a simpler older script of mine in need of a module. Regardless this small demonstration script, is a starting point, for going forward.  using module & registry works!..........comments welcome!
Please, register (free) to access all the attachments on the forums.
-
tomot
-
- Posts: 610
- Joined: Mon Apr 07, 2008 12:18 am
- Operating system: Windows
- SketchUp version: 8
- License type: Free
- SketchUp use: architecture
- Level of SketchUp: Advanced
-
by Dan Rathbun » Wed Mar 07, 2012 12:01 am
OK looking at it... and making a few quick changes. ADD: Here's version '1.1.1'Fixed line 65: forgot to paste in the new attribute name "BookshelfDimensions" .. sorry.
TNT_1_1_1.zip
I fixed it so there is only ONE key for the plugin, and each dialog has a separate attribute beneath that key. viz: Plugin_TNT_Bookshelf_REGKEY.png Also:- Put the plugin inside a plugin submodule: TNT::BookShelf.
- Plugin now resides with the path "tnt/bookshelf/"
- Added a VERSION constant.
- Wrapped the undo operation in a begin ... rescue ... end block.
- Moved the "BookShelf Details" dialog before the undo operation.
- Moved the last line: file_loaded(filepath) inside the file_loaded? conditional block. (Just to be sure it only gets pushed into $loaded_files once. Although file_loaded() may test for this, there's no sense calling it if not needed to.)
- Made note (in file header,) that on XP the REGKEY path differs from Win6+.
Please, register (free) to access all the attachments on the forums.
-

Dan Rathbun
- Top SketchUcator
-
- Posts: 4069
- Joined: Tue Oct 06, 2009 3:06 am
- Location: Florida, USA
- Name: Dan Rathbun
- Operating system: Windows
- SketchUp version: 8
- License type: Pro
- SketchUp use: education
- Level of SketchUp: Advanced
by Dan Rathbun » Wed Mar 07, 2012 12:43 am
Bumped: version '1.1.1'Fixed line 65: forgot to paste in the new attribute name "BookshelfDimensions" .. sorry.
-

Dan Rathbun
- Top SketchUcator
-
- Posts: 4069
- Joined: Tue Oct 06, 2009 3:06 am
- Location: Florida, USA
- Name: Dan Rathbun
- Operating system: Windows
- SketchUp version: 8
- License type: Pro
- SketchUp use: education
- Level of SketchUp: Advanced
by tomot » Wed Mar 07, 2012 12:59 am
Dan thanks for your patience! I'm going to digest your changes...tomorrow. After 12 hrs of sitting,... my ass is developing flat spots In the next stage I will be tackling how the incorporating of the rectangle.rb code which is used in my doortool ruby works with the module & registry stuff I have learned to implement today. ttyl!
-
tomot
-
- Posts: 610
- Joined: Mon Apr 07, 2008 12:18 am
- Operating system: Windows
- SketchUp version: 8
- License type: Free
- SketchUp use: architecture
- Level of SketchUp: Advanced
-
by tomot » Wed Mar 07, 2012 4:20 pm
Looks great Dan! Now unless I'm missing something, (which happens quite often), does the storing of last used dialog values in the registry not make for a more elegant solution then using the @@ approach?
-
tomot
-
- Posts: 610
- Joined: Mon Apr 07, 2008 12:18 am
- Operating system: Windows
- SketchUp version: 8
- License type: Free
- SketchUp use: architecture
- Level of SketchUp: Advanced
-
by Dan Rathbun » Wed Mar 07, 2012 5:28 pm
Firstly... the difference between @ vars and @@ vars in modules are subtle. (Save that issue for later.)
Elegant? Well your really doing the same thing ... but dialog by dialog, instead of the plugin's whole set of saved values.
Also you're doing it in a sort of brute force manner. You are accessing the stored values in the registry (whether you need to not,) and always saving them (without really testing if they are good values. Relying on the user to input values they wish to save.) Also you are creating the literal strings for the inputboxes each time the 'main' method is called. But that's OK for now... you can understand what's happening.
Later on you (when you're ready to get fancier,) you might move the defaults, prompts etc out of the method into module vars. But it's not that important for a really simple single command plugin module. As your plugins get more complex and bigger, you will want to centralize common functions like loading and saving defaults into one method ... rather than have them scattered throughout your code. (Easier maintenance!)
Ruby is multi-paradigm... "there is more that one way to skin a cat."
The BIG lessons you have learned, is module wrapping, using variables that have namespace scope, and saving default values. Also take note of the operation block.
I have noticed problems with the API's read_default() on PC when it tries to read REG_SZ strings values. We need to store quotes with the value in the registry. Using the inspect() method is a good idea, because it will escape embedded ' or " if used for unit symbols. If I try to read the "SnapLength" attribute in the "Preferences" key, I get nil, because it's set to 1" instead of '1"' or "1\"" Also it cannot see any keys with spaces in their names, and just returns nil.
-

Dan Rathbun
- Top SketchUcator
-
- Posts: 4069
- Joined: Tue Oct 06, 2009 3:06 am
- Location: Florida, USA
- Name: Dan Rathbun
- Operating system: Windows
- SketchUp version: 8
- License type: Pro
- SketchUp use: education
- Level of SketchUp: Advanced
by tomot » Wed Mar 07, 2012 5:53 pm
Nice explanation! if I continue for now to go down the registry path How does or can values accept strings ? such as door open, or door closed?
Please, register (free) to access all the attachments on the forums.
-
tomot
-
- Posts: 610
- Joined: Mon Apr 07, 2008 12:18 am
- Operating system: Windows
- SketchUp version: 8
- License type: Free
- SketchUp use: architecture
- Level of SketchUp: Advanced
-
by Dan Rathbun » Wed Mar 07, 2012 9:11 pm
tomot wrote:Nice explanation! if I continue for now to go down the registry path How does or can values accept strings ? such as door open, or door closed?
OK just tested a bit ... the write_default and read_default have no problems if you feed a string (or most simple class types,) to them. The write stores it so it can be read OK. The problem arrises when there is more than one double quote char ( ") in sequence, AND they are not escaped. Because write_default always surrounds a string argument, perhaps by calling inspect() internally to the method. so this was wrong, on my part: - Code: Select all
# set_saved_opts() # def set_saved_opts() @@opts.each_pair {|attr,val| if val.is_a?(String) Sketchup.write_default( REGKEY, attr.to_s, val.inspect ) else Sketchup.write_default( REGKEY, attr.to_s, val ) end } end#def set_saved_opts()
I knew we needed to handle strings specially, but I went the opposite way. (The inspect method adds quotes.) We really do not want to ADD any more quotes chars... ... we want to either strip them off of strings, or be sure they are escaped. Let's go with option 2, and use the gsub method, to escape all internal double quotes, like: gsub(34.chr,92.chr<<34.chr)- Code: Select all
# set_saved_opts() # def set_saved_opts() @@opts.each_pair {|attr,val| if val.is_a?(String) Sketchup.write_default( REGKEY, attr.to_s, val.gsub(34.chr,92.chr<<34.chr) ) else Sketchup.write_default( REGKEY, attr.to_s, val ) end } end#def set_saved_opts()
In your case if you had a results array that had an embedded string: [1, 2, "door closed", 2.54]and you use inspect() on it, you get this: "[1, 2, "door closed", 2.54]"and read_default cannot eval it, so it returns nilAlso, you cannot double inspect it, because that will result in the whole registry value delimited by 2 double quotes: [1, 2, "door closed", 2.54].inspect.inspectputs this: ""[1, 2, \"door closed\", 2.54]"" into the registry, and read_default will poop out again, (returning nil.) So... you need to use: results.inspect.gsub(34.chr,92.chr<<34.chr)You can try it at the console: Sketchup.write_default("Plugin_TNT_Bookshelf", "Array", [1,2,"door closed",2.54].inspect.gsub(34.chr,92.chr<<34.chr))and then to test retrieving it: arr = Sketchup.read_default("Plugin_TNT_Bookshelf", "Array")which if all goes well, should return: '[1,2,"door closed",2.54]' which can be eval'd back into an array. OK?However... write_default and read_default can ALSO write and read arrays directly if you DON'T inspect them. This is because the 'write' converts them to a string, before storing them in the registry,... and then the 'read' evals those strings back into an Array. But.. to confuse the issue... they do not handle hashes well. We have to resort to the .inspect.gsub(34.chr,92.chr<<34.chr) treatment for any hash arguments to write_default, and eval the return strings from read_default.
Now.. (if your dizzy trying to absorb this,) perhaps, you'll understand why I like to write one method to get all this proper handling correct, and then reuse that method in multiple plugins. (Say via a mixin module.) Trying to remember all the quirky issues, when it comes time to write and read values, is a pain in the butt.
You don't run into this 'nested string' in hashes and arrays problem, if all your variables are saved into individual attributes in the registry. (... And they are all single value types, ie, not arrays, hashes, structs, etc.) - Code: Select all
def save_my_vars() vars = instance_variables + class_variables vars.each{|var| eval("Sketchup.write_default(#{REGKEY}, '#{var}', #{var}") end
def load_my_vars() vars = instance_variables + class_variables vars.each{|var| eval("#{var} = Sketchup.read_default(#{REGKEY}, '#{var}'") end
But.. that will save ALL of your variables... even iterators, and ones you do not really need to save. This is why I collect only the ones I wish to save, into an @@opts hash, and then write only those values to the registry. Example.. at the top of your Bookshelf module, where you define your instance @ variables... you could just as easily define them AND an @@opts hash, all in one go: - Code: Select all
# default bookshelf values used for script development unless defined?(@@opts) @@opts = { :height => @height = 2.feet, :width => @width = 2.feet, :depth => @depth = 1.inch, :ny => @ny = 5, :nz => @nz = 5, :dist => @dist = 1.inch } end
Anyway... as long as the simple way works.. use it. When things get more complex... and you need to centralize your default value handling... you've got a topic thread here to mine for ideas.
-

Dan Rathbun
- Top SketchUcator
-
- Posts: 4069
- Joined: Tue Oct 06, 2009 3:06 am
- Location: Florida, USA
- Name: Dan Rathbun
- Operating system: Windows
- SketchUp version: 8
- License type: Pro
- SketchUp use: education
- Level of SketchUp: Advanced
by ktkoh » Thu Mar 08, 2012 2:01 pm
I have been following this topic as I have in the past used a file to store variables between sessions and my question is does the registry storing of variables only work on Win based computers and not on the Apple OS?
Keith
-
ktkoh
-
- Posts: 147
- Joined: Mon Mar 31, 2008 1:40 am
- Location: Bellefontaine OH
- Name: Keith Krueger
- Operating system: Windows
- SketchUp version: 8
- License type: Free
- SketchUp use: woodworking
- Level of SketchUp: Intermediate
by TIG » Thu Mar 08, 2012 2:40 pm
The Sketchup.read_defaults and Sketchup.write_defaults use each PC's Sketchup 'Registry' entries OR a MAC's Sketchup 'plist' file entries... so they should work cross-platform. The main issue with using the Registry is storing data restructured into a format that can be recovered and then converted back into the required 'class' later - e.g. a string/float/integer/length/boolean/array/hash etc will need some 'manipulation' before writing - but if you have been using a 'file' to store such things then you've been writing them as strings already - when you reread the file you presumably convert the strings back with say string.to_f to make the value a number etc... [like an 'ini' file]. The Registry data exists across sessions globally for Sketchup on each PC, not just the current SKP. So if you want SKP specific data saving then it's best to use model-attributes to save things with the SKP [you can save attributes as most common data types directly - except a hash] - the data is thereby accessible to all uses on the network when you script reads the attributes as it runs, and later updates the attributes as it closes, this can all be done independent of each PC's Registry entries.
Horses for courses...
TIG
-

TIG
- Global Moderator
-
- Posts: 13949
- Joined: Mon Nov 12, 2007 7:24 pm
- Location: Northumbria UK
- Name: TIG
- Operating system: Windows
- SketchUp version: 8
- License type: Pro
- SketchUp use: architecture
- Level of SketchUp: Advanced
Return to Developers' Forum
|