I notice this was last updated for SU 2015, last commit Nov 7 2014 - does it still work with SU 2016?
Posts
-
RE: Call C++ from ruby in Sketchup
-
RE: SU2015 gives NoMethodError for Length class #abs method
Thanks for quick reply TIG.
we were testing on 15.2.685 Windows 64-bit and 15.2.686 Mac 64-bit
didn't know there was an update out - will try that... -
SU2015 gives NoMethodError for Length class #abs method
Since SU 2015, there seems to be a difference in the way the Length class handles the #abs method.
Up to and including SU 2014, it would return the absolute value as would be expected.However, in SU 2015 it is now generating Error: #<NoMethodError: undefined method `abs' for nil:NilClass>
eg. in SU 2014;
> 2.m.abs
78.740157480315but in SU 2015;
> 2.m.abs
gives the NoMethodErrorThis is pretty bad (it has broken my plugin for SU 2015) and means I now need to go hunting through the code for all occurrences of <Length>.abs replacing them with <Length>.to_f.abs and building-in extra validation where the class is not intrinsically known, just in case there could be a Length instead of a Float.
Anybody know why this has been changed? it seems pretty unhelpful
Dave
-
RE: Start and commit operation: how they work?
Hi all,
I've been trying to get to grips with Sketchup operations for some time now and reading the comments above from Dan and Thomas and also these older posts has really helped shed some light on it for me.
<code> wrapping operations
Model Operation blockform methods
Ruby, Undo Stack and dynamic components
start/commit_operationI realised part of the problems I was experiencing was due to nested operations, however I was still left with a conundrum; I need nested operations - because I have some code in low-level methods that works with Dynamic Components for example, and not encapsulating it with an operation either leads to very slow operation or littering the undo stack with "Properties". Putting an operation inside these methods fixed all the problems I was having there. However, these low-level methods can sometimes be called inside other methods with their own operation wrappers, for example when an action is invoked from the user-interface
I believe I have come up with a solution that allows low-level methods to have their own operation when they are called in isolation, but when they are called as part of a larger chain of operations, they become appended to the larger operation. When a
start_operation
is called, the operation name is also pushed on to the module's own stack. If there is already a higher level operation on the stack, the new operation is made transparent. When the operation finishes,commit_operation
is only called if the stack is empty, so that the whole composite operation is committed as the highest first (highest level) operation called.
This seems to work well in the trivial example below. Would appreciate your comments! Can you see any potential problems?cheers
Davemodule DME_Test @@op_stack = [] @@model = Sketchup.active_model def self.model # could handle changes of active_model here @@model end def self.error(op_name, err, call_stack=nil) model.commit_operation if !@@op_stack.empty? # should it abort_operation or commit_operation that was executed so far? @@op_stack.clear ;;UI.beep Sketchup.status_text="ERROR; #{op_name}" ;;UI.messagebox("ERROR; #{op_name} - Operation did not complete due to an error.") raise if $DEBUG # or module specific debug flag end # command level operations - directly called by user through menu items or toolbar def self.cmd1 op_name = "Cmd1" begin @@op_stack.push(op_name) if model.start_operation(op_name, disable_ui=false) macro_op(0,0,1,1) puts @@op_stack.pop model.commit_operation if @@op_stack.empty? rescue => err self.error(op_name, err, caller) else # ensure # end end def self.cmd2 op_name = "Cmd2" begin @@op_stack.push(op_name) if model.start_operation(op_name, disable_ui=false) # -- statements macro_op(1,1,1.5,1.5) # -- end statements puts @@op_stack.pop model.commit_operation if @@op_stack.empty? rescue => err self.error(op_name, err, caller) else # return result ensure # end end # A macro operation method, which may be combined with others in macro operations def self.macro_op(x,y,x_dim,y_dim) begin op_name = "draw square (#{x_dim} x #{y_dim})" prev_trans = !@@op_stack.empty? @@op_stack.push(op_name) if model.start_operation(op_name, disable_ui=false, trans=false, prev_trans) # -- statements grp = model.active_entities.add_group pt1 = minor_op(x,y) pt2 = minor_op(x,y+y_dim) pt3 = minor_op(x+x_dim,y+y_dim) pt4 = minor_op(x+x_dim,y) grp.entities.add_line(pt1,pt2) grp.entities.add_line(pt2,pt3) grp.entities.add_line(pt3,pt4) grp.entities.add_line(pt4,pt1) # -- end statements puts @@op_stack.pop model.commit_operation if @@op_stack.empty? rescue => err self.error(op_name, err, caller) else # return result return grp ensure # end end # A minor operation method, which may be combined with others in macro operations def self.minor_op(x,y) begin op_name = "add point (#{x},#{y})" prev_trans = !@@op_stack.empty? @@op_stack.push(op_name) if model.start_operation(op_name, disable_ui=true, trans=false, prev_trans) # -- statements pt = Geom;;Point3d.new(x,y,0) model.active_entities.add_cpoint(pt) # -- end statements puts @@op_stack.pop model.commit_operation if @@op_stack.empty? rescue => err self.error(op_name, err, caller) else # return result return pt ensure # end end end
-
RE: Start and commit operation: how they work?
Thanks Dan, useful to know, have edited.
Do you have any comments on the validity of the scheme above?
I've made some further changes in trying to implement this into my plugin - for handling multiple models on Mac, a separate stack is required for each model.
Also as an alternative: rather than making subsequent operations transparent, when there is already an op on the stack, both the start_operation and commit_operation could be conditional on the stack being empty. -
RE: Webdlg debugging on Mac using WebKit inspector
Does anyone know how to enable something like this on a Windows machine? The WebKit inspector on Mac is brilliant for debugging webdialogs, but I need to debug a problem that seems to be occurring on Windows only.
Is there a way to enable Firebug within the SketchUp webdialogs or some kind of native DOM inspector for IE?thanks
Dave -
RE: Puts inconsistency & machine epsilon management
Thanks all,
Thom, that link looks very useful thanks, makes me think I should dig out my A-level computer science notes too ...
Dan, I still get
> r1 = (20.0/1000)/0.8 0.025 > puts r1 0.025
How do you output the full precision in order to understand what is going on?
I don't have the Rational class in SU8 (I'm on OS X 10.6.8 so can't go any higher for the time being)
FYI;RUBY_VERSION
1.8.5
Do I need Ruby 2.0 for that?Dave
-
RE: Puts inconsistency & machine epsilon management
Hi,
I have come across a problem which seems to be related to this issue.> r1 = (20.0/1000)/0.8 0.025 > r1.class Float > "%.2f" % r1 0.02
=> INCORRECT
However;
> "%.2f" % (20.0/(0.8*1000)) 0.03
=> CORRECT
> r2 = 0.025 0.025 > r2.class Float > "%.2f" % r2 0.03
=> CORRECT
> "%.2f" % 0.025 0.03
=> CORRECT
Also:
> r1 <=> 0.025 -1
=> INCORRECT
> r2 <=> 0.025 0
=> CORRECT
> r1 <=> r2 -1
=> INCORRECT
So it is clearly something to do with how the number is stored in binary and the order of operators can affect the result as alluded to above in this thread.
Any ideas on how to manage this? - it seems quite a fundamental flaw if this comes up when making calculations at a pretty basic level of precision. It doesn't seem practical to re-order potential calculations to push the precision one way or another because the values of variables may not be known in advance. -
RE: A few newbie questions...
Do you know if this is still the case?
I'm trying to reload an rbs file to perform a live patch of some methods;Sketchup.load('file_path.rbs') returns 0 the first time, then false on subsequent calls, same as Sketchup::require
Is there a global equivalent to $" that SU stores the list of files in, that I can delete the file name from to force a reload?
thanks
SU 8.0 M2, Mac
-
RE: Organising namespaces and loading scripts on demand
Hi Thomthom, Dan
Many thanks for your replies, that seems to have cleared up the problem. (NB I've changed the subject slightly to be more useful to anyone searching the forum)@thomthom said:
You are loading scrambled files, correct?
Yes that is correct, I want to be able to load scrambled library files, hence the use of Sketchup::require().
@thomthom said:
There is a known issue where scrambled files are not evaluated into the top level namespace.
Place your require statements outside your modules - on the top level code and it will be ok.@dan rathbun said:
This is a bug with the
Sketchup
module's override of therequire
method, and as Thomas says, happens most often with rbs files.This does seem to be the key to the problem, and thanks for clarifying Dan (I have realised now that this issue only started to occur after I tested some scrambled scripts).
@thomthom said:
Note that if you are using the SketchupExtension class you probably need to use an unscrambled proxy .rb file to load the .rbs files.
Yes, I currently do so there was no problem there.After some more testing it seems that there is no problem with the libraries themselves being scrambled, but the script that loads those libraries must be unscrambled, then it works fine. So to load scrambled libraries from within a module, they must be loaded by a proxy script that itself is unscrambled.
I don't really want to useeval('Sketchup::require("my_library")',TOPLEVEL_BINDING)
unless I have to, but good to know that option exists too.So using my abstract example again, it works ok if it is structured like this:
"my_toolbars.rbs" (can be scrambled)
module My_library module Mod_A # various classes, method defs, statements etc cmd = ;;UI;;Command.new("Launch…") { … require("Load_libraries.rb") # load unscrambled proxy script } … end end
"Load_libraries.rb" (must be plain text Ruby)
Sketchup;;require("Library_1") Sketchup;;require("Library_2") Sketchup;;require("Library_3") Sketchup;;require("Library_4") Sketchup;;require("Library_5") Sketchup;;require("Library_n")
"Library_n.rbs" (can be scrambled)
module My_library module Mod_A # various classes, method defs, statements etc end module Mod_B # various classes, method defs, statements etc end … end
-
Organising namespaces and loading scripts on demand
Hi,
Trying to follow good practice for creating namespaces, I have some code which is structured along the lines given below:
"File_A.rb" is loaded when Sketchup is launched if the plugin is active, amongst other things this a creates a menu / toolbar command which loads further libraries and code if required. The problem I am having is that since "File_B" is loaded from within the "My_library::Mod_A namespace", the files loaded by "File_B" create a set of nested namespaces such as "My_library::Mod_A::My_library::Mod_A" & "My_library::Mod_A::My_library::Mod_B". This is not of course the intention, the code should all sit in the same namespaces.
Do I need to prepend all my module definitions with "::" in the loaded files to avoid this happening or is there a better way to organise this?
thanksDave
"File_A.rb"
module My_library module Mod_A # various classes, method defs, statements etc cmd = ;;UI;;Command.new("Launch…") { … Sketchup;;require("File_B") } … end end
"File_B.rb"
Sketchup;;require("File_B1") Sketchup;;require("File_B2") Sketchup;;require("File_B3") Sketchup;;require("File_B4") Sketchup;;require("File_B5") Sketchup;;require("File_B6") # some other stuff
"File_Bn.rb"
module My_library module Mod_A # various classes, method defs, statements etc end module Mod_B # various classes, method defs, statements etc end … end
-
RE: Toolbars and contextual menus
Hi,
Does anyone have any further insights into this issue?I have encountered a very similar problem:
- Tooltips do not show when the toolbar is moved to the horizontal position (Mac OSX)
This seems to be particular to Mac OSX, but it is happening in both SU7 & SU8. At first I noticed it for the toolbars of a plugin I am developing, but I also tested the Dynamic Components toolbar and the same thing happens. When the toolbar is moved to a horizontal position the tooltips stop appearing. If I move the toolbar back to vertical, then restart Sketchup, tooltips start appearing again.
I've trashed the preferences files and still the same thing is happening.
I've quarantined all my plugins and it still happens.Any ideas?
This is really quite annoying as I want to be able to use tooltips for my plugin and horizontal toolbars are much more convenient.thanks
Dave -
RE: Webdialogs: Debugging Javascript on Mac
Perfect!! Thanks Thomthom that's exactly what I needed.
Strange that other post didn't come up in my search, especially as it is so recent. -
Webdialogs: Debugging Javascript on Mac
Hi,
I am working on a plugin that makes extensive use of SU Webdialogs for its UI which use various bits of Javascript code for hiding blocks of HTML, generating callbacks to Ruby and other required interactivity.
I am working on Mac, and never see any JS errors from the Webdialogs, however my co-developer working on Windows does get JS errors for a number of issues which can sometimes stall the rendering of the page.
Does anyone know how I can view JS errors on Mac Webdialogs?
Is there a way to access something like Firebug or the Safari developer tools through the SU Webdialog implementation of Safari?
Or is the only way to test in a browser using a mockup of the same JS/HTML code that is generated by Ruby?thanks
DaveThe plugin is being developed on SU 7.1 to ensure backward compatibility.
-
RE: Multiple attribute dictionaries created
Hi TIG,
Thanks for your reply.
I agree, creating a centralised dictionary with hashes and arrays does sound rather convoluted.The way I am using the attributes is similar to instance variables and methods for a class; creating a standard set of attributes for a building element such as, say a wall, so in addition to the
face.area
,face.normal
methods etc I can store other properties about the geometry and construction. Since I was thinking along these lines, I was expecting the attribute dictionaries to behave in a similar way to creating instance variables; creating a standard dictionary for an object type such as walls, with a number of pre-defined attribute names, so they are standard across all instances of walls.
The way attributes are implemented does seem a bit inefficient because if I want to add or change the names of attributes in future, I will have to audit every entity (that has attributes) in old models to make them compliant with the latest attribute scheme, rather than being able to modify those attributes (but not their instance values) in one place. Looks like I will have to learn to live with this though - it would be a relatively simple script, so just something I need to be aware of.I hadn't appreciated that attributes applied to a face would be lost if it is deleted and restored by undo, so thanks for bringing that to my attention! I can see there would be a benefit to only attaching attributes to container objects, but there will be cases where this is not practicable without making the model more complicated by adding extra levels of containers.
cheers
Dave -
Multiple attribute dictionaries created
Hi,
I am working on a plugin that adds a standard set of attributes (representing building element properties) to selected entities in the model. I want to be able to save this meta-data with the model, so attributes would seem to be the correct way to go.When I add an attribute dictionary to a number of different entities, using
entity.set_attribute(dictName, attrName, attrValue)
a different AttributeDictionary object is created for each entity (eg#<Sketchup::AttributeDictionary:0x11f60408>, #<Sketchup::AttributeDictionary:0x11fb7488>
), even though I am using the same dictionary name every time.
I am planning to cascade these attributes to all entities with groups etc, which could amount to a considerable number of entities. Is there any concern with the amount of memory taken up by all these separate AttributeDictionary objects in terms of performance and if so is there any way around it? Can I create a global attribute dictionary that applies to the whole model or would there be no benefit doing that? - it just seems it would be a neater solution.many thanks
Dave