Also look at how the SketchUp Team makes shapes in the Shapes plugin example:
http://extensions.sketchup.com/en/content/shapes
Posts
-
RE: Create arbitrary shape from list of points
-
RE: Include paths
IN Ruby you can do interpolation in double-quoted strings with the
#{ }operator. The expression between the curlies is evaluated and passed to the result'sto_smethod, then stuffed into the string.So you'd create a string of html:
html = %Q{ <html> <head> <base href="#{myroot}" /> <link rel="stylesheet" href="resources/css/webdialogs.css" /> </head> <body> </body> </html> } my_dialog.set_html(html)You can also use a
HEREDOC.
See: http://ruby-doc.org/core-2.0.0/doc/syntax/literals_rdoc.html -
RE: Include paths
BASE element | base object
[https://msdn.microsoft.com/en-us/library/ms535191(v=vs.85).aspx](https://msdn.microsoft.com/en-us/library/ms535191(v)... but it is more normal to have your plugins resources in a sub-directory of your plugin's sub-directory.
-
RE: Tool: getMenu and toolbar
@bomastudio said:
Inside the myPlugin.rb file I have to embed all code inside the BomaStudio modules?
Inside ALL of your Ruby files.
Files do not separate code into different scopes. It is
modulenamespaces that separate code.Any number of ruby files can open the same module or class and modify it.
The HTML file is special because it only runs in the
UI::WebDialog.
These subjects have already been covered numerous times here in the forum. It is basic Ruby, and covered in any Ruby textbook. I posted an old version of the "PickAxe" Ruby book:
[doc] Programming Ruby (The "Pick-Axe" Book) -
RE: Tool: getMenu and toolbar
Your files need to be set up like:
http://extensions.sketchup.com/en/developer#rbzSo the extension registrar file in "Plugins" would be "BomaStudio_BomaTool.rb", and your plugin sub-folder would have the same name: "BomaStudio_BomaTool".
The loading file in the "Plugins/BomaStudio_BomaTool" sub-directory can be whatever name you like:
"BomaTool_loader.rb", etc., and the other files should likely have the same prefix with descriptive suffix, like:
"BomaTool_core.rb"
"BomaTool_gui.rb"
"BomaTool_tool.rb"
"BomaTool_menu.rb"
In Ruby, the
moduleandclasskeywords, mean "create if not defined, and open for editing".So,
module BomaStudio # make changes like define constants, variables, new methods, or # redefine old methods (method overrides,) or undefine methods. endis the same as:
BomaStudio = Module;;new if !defined?(BomaStudio) BomaStudio.module_eval { # make changes like define constants, variables, new methods, or # redefine old methods (method overrides,) or undefine methods. }
See also the
SketchupExtensionclass:[url=http://www.sketchup.com/intl/en/developer/docs/ourdoc/sketchupextension:3qzf850n]http://www.sketchup.com/intl/en/developer/docs/ourdoc/sketchupextension[/url:3qzf850n]

-
RE: Tool: getMenu and toolbar
@bomastudio said:
P.S.: I saw that you nested in the code of your post two modules:
module BomaStudioand
module CustomTool. Is there a specific reason to do so?
Yes, ALL your code needs to be within a toplevel author (or company) module.
Each one of your plugins need to be within a sub-module of your toplevel module so they do not clash with each other.
Class definitions used by only one plugin should be defined within that plugin sub-module.If you define variables and methods at the toplevel (ie,
TOPLEVEL_BINDING,) they are defined insideObject. EVERYTHING in Ruby is a subclass ofObject, so toplevel objects get inherited by everyone else's modules and classes.
That makes us angry. -
RE: Tool: getMenu and toolbar
Do not create a new toolbar and command object each time the method gets called.
Instead create the toolbar and command at the top of the class defintion, and reference them with class variables.
module BomaStudio module CustomTool class Tool if !defined?(@@tbTOOL1) @@tbTOOL1 = UI;;Toolbar.new("Toolbar 1") @@cmdTOOL1 = UI;;Command.new("Tool 1") { tool1("Right") } @@cmdTOOL1.large_icon = Sketchup;;find_support_file( "muroDX_40x40.png", "Plugins/TECLA_STRUCTURE/icone/" ) @@tbTOOL1.add_item @@cmdTOOL1 end def getMenu(menu) @view = Sketchup.active_model.active_view @@tbTOOL1.show() if !@@tbTOOL1.visible? end def tool1( side ) @@tbTOOL1.hide() if @@tbTOOL1.visible? @side = side @view.invalidate end end # tool @@tool = Tool;;new if !defined?(@@tool) end end -
RE: Are there plugins for Layout?
FYI
IMSI DoubleCAD XT was a 2D CAD application, that could be plugged into SketchUp (like Layout can be.) It ran embedded Ruby, and had a clone of SketchUp's API. It development has been discontinued, but you may still be able the download the latest version.
http://www.doublecad.com/DoubleCAD/DoubleCAD-XT-v5
http://activate.imsisoft.com/doublecad.aspx?productpage=DoubleCAD_XT_v5
QCad is a low cost (~37USD) 2D application, that has Javascript API & Qt GUI toolkit for plugins.
http://www.ribbonsoft.com/en/
There is a free stripped down edition you can tryout. (But it cannot really be used for work. For example trying to add a layer brings up a nag box, saying that is a Pro feature.)
FreeCAD is a 2D/3D Open Source free CAD application, that uses Python for extensions and custom workbenches.
http://www.freecadweb.org/
http://sourceforge.net/projects/free-cad/ -
RE: Help with loading performance using Sketchup C SDK.
You can also ask your question at:
http://forums.sketchup.com/c/developers/sketchup-sdkThe SketchUp Team members are more likely to answer, more quickly.
-
RE: Toolbar position
Everything you see on the screen in Windows is an object subclass of window. So a button is a window. A toolbar is a window, with child button windows. This means you are searching for a child window (toolbar) of the owner window (the SketchUp application main window.)
See this old post:
[code] Win32 Moving/Showing/Hiding Toolbars and DialogsJust be aware that the
Win32APIclass is deprecated, and the old so compiled binary, was replaced in Ruby 2, with a ruby script wrapper (of the same name,) that calls theDLlibrary transparently.
ButDLhas also been deprecated, and produces a warning toSTDOUTwhenever it is first required, ie, arequire("dl")call is first made.The code should be rewritten to use the
Fiddlelibrary.
http://ruby-doc.org/stdlib-2.0.0/libdoc/fiddle/rdoc/index.htmlAs for the Windows API, that documentation is all on MSDN:
Windows API
Windows Reference
[Window Styles](https://msdn.microsoft.com/en-us/library/ms632600(v)
[Window Messages](https://msdn.microsoft.com/en-us/library/ff468921(v)
SendMessage Function
[Using Window Procedures](https://msdn.microsoft.com/en-us/library/ms633570(v)
etc.,
etc. -
RE: Toolbar position
The positioning of
UI::Toolbarobjects, is (currently) not exposed in the Ruby API.On PC, I know how to work around this with Windows system calls, but have no clue how to do this on Mac SketchUp.
-
RE: The zero point of circles changes with their orientation
@august said:
That's a angle, not a point, but it may turn out to be useful.
I changed the text by underlining part of it, to give you a clue.
Basically it means the start point will lie on the local x axis.
Since a circle is a
ArcCurve, "under the hood", and anArcCurveis a subclass ofCurve, there should be several ways of getting the start point.circle[0].curve.first_edge.start.positioncircle[0].curve.vertices[0].start.positionBecause
circleis an array of edges returned froments.add_circle, get any one of the edge members.edge.curvereturns theCurveorArcCurveobject that an edge belongs to.curve.first_edgereturns the curve's first edge, no kidding..
edge.startreturns the starting vertex.vertex.positionreturns aGeom::Point3dequivalent for the vertex. -
RE: Access specifies entity
# Search top and 1st nested level for a named group; grps = Sketchup.active_model.active_entities.grep(Sketchup;;Group) if !grps.empty? found = grps.find {|grp| grp.name = "Target Name" } else found = nil end if !found # found will be nil, if group was not found nested = Sketchup.active_model.entities.find_all {|ent| ent.is_a?(Sketchup;;Group) || ent.is_a?(Sketchup;;ComponentInstance) } nested.each {|ent| ents = ent.is_a?(Sketchup;;Group) ? ent.entities ; ent.definition.entities grps = ents.grep(Sketchup;;Group) found = grps.find {|grp| grp.name = "Target Name" } if !grps.empty? } end # found will be the group reference, if it was found # found will be nil, if group was not found -
RE: Extract 3D information to regenerate the shape
SketchUp is a surface modeler. Everything in SketchUp is basically made up of edges, vertices, and faces.
There are no complex built-in 3D shape classes in the SketchUp Ruby API.
Instead primitives are either grouped into
Groupclass instances, orComponentInstanceclass instances. (Each have a definingComponentDefinitionclass instance.)These mentioned classes are all sub-classes of
Entity, and inherit it's functionality (as well as the intermediateDrawingelementclass functionality.)Any
Entitysubclass instance can have any number ofAttributeDictionaryinstances attached to them. You can put whatever custom data you wish into attributes in a custom dictionary, usually named the same as your plugin. (Ex: "Ruts_Shaper_Properties")Back to the grouped 3D shape. Groups and components have a built-in definition name and each instance of them can have a separate more unique instance name. Group and component instances have built-in transformation property, from which you can query all the translational, rotational, scaling and axial subproperties. See the
Geom::Transformationclass.All
Drawingelementsubclasses (the objects that can be seen in the model,) have an invisible boundingbox, from which you can get the corners and the center. See theGeom::BoundingBoxclass.It would be more efficient to create the basic shapes as an external SKP component library, and insert them into the model, rather than draw each using code, but drawing them adhoc can be done.
You should most likely install the SketchUp Team's example Shapes plugin, and study the code.
http://extensions.sketchup.com/en/search/site/Shapes -
RE: The zero point of circles changes with their orientation
@august said:
P.S. If anyone has a better term for the starting point of the first edge than "zero point", I'll happily use it.
Well let us see what the API docs say:
@unknownuser said:
](http://www.sketchup.com/intl/en/developer/docs/ourdoc/arccurve#start_angle) documentation":5dfj7d1v]
ArcCurve.start_angle
The start_angle method is used to retrieve the angle of the start of the arc,
measured from the X axis in radians. -
RE: ComponentInstance Guid question
They are supposed to be unique. If you can, can you send Thomas (tt_su) the file by PM so he can take a look ?
-
RE: Deleting Component Instance
Your missing the number one rule of iterating collections (in any programming language.)
Do not delete collection members while iterating the collection. The loop will lose it's place, and strange results occur. In that case, always iterate an array copy of the collection, if your loop must remove or add collection members. This is most often seen while modifying Entities collections.
In TIG's example, he used the
selectmethod, which produces a separate new array subset of the original collection.The simplest way to get an array copy, is using the
to_amethod.
The second good thing TIG showed was to always check your API
Entitysub-class objects for validity. -
RE: Variable values in attribute dictionaries
@ssunderland said:
` n=0
i=0Sketchup.active_model.selection[n].set_attribute("Bubble","id",i); n+=1; i+=1`
You are missing some basic knowledge of Ruby.
Most of the API collection classes have the library moduleEnumerablemixed into them.
http://ruby-doc.org/core-2.0.0/Enumerable.htmlIt is usually safer (to avoid fencepost errors, etc.) to use the built-in block form iterator methods.
Sketchup.active_model.selection.each_with_index {|ent,idx| ent.set_attribute("SSU_Bubble","id",idx) }If you want to process in reverse order, make an array copy of the selection, using
to_a
and theArray#reversemethod:Sketchup.active_model.selection.to_a.reverse.each_with_index {|ent,idx| ent.set_attribute("SSU_Bubble","id",idx) }However, there is one major rule. Do not delete collection members while iterating the collection. The loop will lose it's place, and strange results occur. In that case, always iterate an array copy of the collection, if your loop must remove or add collection members. This is most often seen while modifying
Entitiescollections. -
RE: Variable values in attribute dictionaries
Also, as objects are edited and they intersect, SketchUp will destroy and create new objects. So if editing is done sometime after you "mark" the objects, some of them may go away, and new objects created that do not have your dictionary ids.
Dictionary Names. It is unwise to use a simple word like "Bubble". You should approach dictionary naming like you would your plugin sub-module namespace. Say, your toplevel author namespace module, that you have chosen
SSUand the plugin sub-module asBubbler, then it is smart to name the dictionary after the plugin sub-module qualifying identifier, but replacing the::scope operator with an underscore "".
So "SSU_Bubbler" for theSSU::Bubblerplugin module. IF you need more than one dictionary, then the former becomes a prefix, and you add "" and some meaningful suffix.