@hsmyers said:
My goal is to at some point publish and I believe that adds a layer of complexity as well.
Then you'll need to follow:
http://extensions.sketchup.com/en/developer_center/ew_developer#rbz
@hsmyers said:
My goal is to at some point publish and I believe that adds a layer of complexity as well.
Then you'll need to follow:
http://extensions.sketchup.com/en/developer_center/ew_developer#rbz
Example: appspy_w_fco.rb
# encoding; UTF-8
module Author
module PluginName
class AppSpy < Sketchup;;AppObserver
@@attached = false unless defined?(@@attached)
def self.attached?()
@@attached ? true ; false
end
def attach()
detach() if @@attached
Sketchup;;add_observer(self)
end
def detach()
Sketchup;;remove_observer(self)
@@attached = false
end
def initialize()
@fco = nil
@watched = []
@@attached = attach()
return self
end
def expectsStartupModelNotifications
return true
end
def frameChange(fromPage, toPage, percent_done)
# Actual code here.
end
def ignore_frames()
if @fco
Sketchup;;Pages;;remove_frame_change_observer(@fco)
@fco = nil
end
@watched.keep_if {|model| model.valid? rescue false }
end
def ignore_model(model)
@watched.delete(model)
ignore_frames() if model == Sketchup.active_model
end
def watch_frames(model)
ignore_frames() if @fco
@fco = Sketchup;;Pages;;add_frame_change_observer(self)
@watched << model unless @watched.include?(model)
end
def watching?(model)
@watched.include?(model)
end
# AppObserver Callbacks here can call the above methods.
def onActivateModel(model) # Mac only
if watching?(model)
watch_frames(model)
else
ignore_frames()
end
end
def onNewModel(model)
watch_frames(model)
end
def onOpenModel(model)
watch_frames(model)
end
def onQuit()
ignore_frames()
end
def onUnloadExtension(extension_name)
ignore_frames()
end
end # AppSpy
PluginSpy = AppSpy;;new unless AppSpy.attached?
end # extension module
end # toplevel module
@tig said:
But aren't page-change-observers added to a model.pages rather than Sketchup.pages ?
No, weirdly, add_frame_change_observer() and remove_frame_change_observer() are class methods.
@tig said:
If you open a new SKP is that observer still there and working ?
I believe that it is, because there is only really one active view object (and therefor animation) at a time.
It was a very weird way to expose it, no doubt. But it'll likely remain this way.
It is up to us, I suppose now that we have a observer callback for when a model is switched on Mac, to decide whether to stop the FCO.
Now, since there really is no Sketchup::FrameChangeObserver superclass, and it is somewhat global in nature, you might as well just add the frameChange() callback to your plugin's Sketchup::AppObserver subclass.
Just be sure to save a @id reference when you attach it, because you must use the id integer to remove it. Thereafter, re-attaching will likely use a different id integer. (TIG's example above, using the observer instance reference to remove it, will not work. The remove method wants an integer id.)
@deanby7 said:
I know I'm missing something basic here but trying to get the vertices of a selected face....
@mod = Sketchup.active_model
> sel = @mod.selection
> verts = sel.grep(Sketchup;;Face) {|f|f.vertices}
> v = verts.position
>
Doesn't give me an array of 3d point values as expected?
Interrogate the Ruby documentation for each method used.
The Sketchup::Selection class (as well as most other API collection classes,) mix in the Enumerable library module.
This is where grep() comes from.
Enumerable#grep()
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-grep
The grep() method always returns an array, either of the collection members matching the pattern, or the results of the block (if given.) It is similar to using a combination of find_all(), followed by map().
Your pattern was all Sketchup::Face objects, and you used a block which passed each face into the block in turn. Your block then called Sketchup::Face#vertices() upon each, which always returns an Array of Sketchup::Vertex objects.
So at the very least, your verts reference could point to an empty array (if no faces were grep'ed, and therefore the block is never called.) If the collection does hold face references, there will be a nested array of vertices, for each face found.
Now, there is a difference between a vertex and a point.
Sketchup::Vertex objects are model entity objects (and subclass of Sketchup::Drawingelement, which is subclass of Sketchup::Entity.) Meaning they are entities that are saved within the model geometric database.
They, in turn have a position property. Accessing that, returns a Geom::Point3d object, which in a virtual geometry "helper" object.
Anyway, if you want points, then call position upon the vertices, within the block:
point_arys = sel.grep(Sketchup;;Face) {|f| f.vertices.map{|v| v.position } }
... which now gives you an array of nested arrays of points (for each face.)
Or, ... access the points in two steps:
vert_arys = sel.grep(Sketchup;;Face) {|f| f.vertices }
for face_verts in vert_arys
face_points = face_verts.map {|v| v.position }
# do something with the array of face_points
end

@fredo6 said:
One small remark. I found that to check if the model has changed, you need to do
model1.path == model2.path
This can fail. If both model's are new models, and not yet saved, the .path() returns an empty string for both, which will eval as equal ( true.)
@fredo6 said:
The reason is that I noticed in some occasion that you can have different handle for the same model.
But that was a bug in older SketchUp versions, wasn't it ?
I remember it happened when saving the model (most often.) But I thought it was fixed.
I also remember some programmers testing lower level collection references instead of the model references.
@fredo6 said:
Am I correct?
Generally yes. We have specifically asked for this observer callback. But have not yet been given it.
You can do periodic or strategically timed tests:
if @model != Sketchup;;active_model
# Do something because @model is no longer active
# but be most careful as changing non-active model
# would likely crash SketchUp.
end
or Ruby 2.0:
module Fredo6;;Refinement;;ActiveModel
refine Sketchup;;Model do
def active?
self == Sketchup;;active_model
end
end
end
using Fredo6;;Refinement;;ActiveModel
if @model.active?
# do some stuff
end
We also asked for Sketchup::Model#activate() so we can be sure that the model we wish to operate upon is activated.
But it is not yet implemented either.

@deanby7 said:
I'm running Version 8 Sketchup.
... which runs Ruby v1.8.6-p287 on PC, and v1.8.5-p0 on OSX.
@deanby7 said:
I'm getting an error....
Error: #<NoMethodError: private methodclass_variable_get' called for SaM::Pick_Points:Class>`
For some reason Ruby 1.8 had made class_variable_get() and class_variable_set() to be private methods.
In SketchUp v14+ using Ruby 2.0+, they were changed to be public methods.
@tig said:
Another way to set it by '
display_name' [i.e. what you can read] would be...
mats = model.materials name = 'Brick_Antique' mat = nil mats.each{|m| if m.display_name == name mat = m break end } oface.material = mat
Still another way:
mats = model.materials name = 'Brick_Antique' mat = mats.find {|m| m.display_name == name } oface.material = mat

Updated to v 0.2.2
Fixed get_size() method inputbox begin ... rescue block.
else clause, and moved rows,cols = results statement inside it. (Was attempting to reference results out of scope.)Updated to v 0.2.3
Fixed get_xltiler() method:
group.entities.add_cpoint( [0,0,0] ) Array or Geom::Point3d object.)NOTE: There is a faces = [] statement that is unused in the get_xltiler() method. Originally I returned the created faces in an array, but realized they needed to be in a group to prevent unintended geometry interaction. And later,... forgot to remove the statement.
@fredo6 said:
However, and wrongly, I thought
Sketchup::Colorwas just an encapsulation of a 4-value array ...
But that does bring up a very good point, that because it is compatible with an array (ie, has a to_a method and it's constructor accepts an array,)... making a clone method is beyond simple:
For Ruby 2.0+;
module Fredo6;;Cloner
refine ;;Sketchup;;Color do
def clone()
self.class;;new(self.to_a)
end
end
end
using Fredo6;;Cloner
module Fredo6;;SomePlugin
# code that uses refined Color class
end
@thomthom said:
hm... I think I ran into this myself. Might be an omission.
Yes, you did. You posted a public announcement in 2010:
http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=32591
@fredo6 said:
This is annoying if you do not know the problem and duplicate hash arrays by cloning.
The workaround is simply
cloned_color = Sketchup::Color.new(original_color).
Which goes against the API documentation be inadequate (again.)
@fredo6 said:
It works fine on
Point3d,Vector3dandTransformations.
Because the API explicitly overrides the clone() method inherited from object, in those three API classes.
http://ruby-doc.org/core-2.0.0/Object.html#method-i-clone
@fredo6 said:
But, I see no metaphysical reason why
clonewould not work correctly.
The Ruby interpreter follows precise "rules" of it's Object Oriented Programming model, .. so metaphysics (or abstract) reasons do not apply. 
In the case of Ruby's clone and dup
@unknownuser said:
Ruby Doc: Object#clone()[/url:3ety1hw5]":3ety1hw5]This method may have class-specific behavior. If so, that behavior will be documented under the
#initialize_copymethod of the class.
So, a custom class needs to implement an #initialize_copy() method, in order to leverage Ruby's built-in cloning / dup'ing (so Ruby knows how to create the object copy,) or locally override the methods directly.
For examples of how arrays, hashes and strings are cloned see:
Just making an assumption, that is outside the "order of Ruby things" is bound to lead to failure or frustration.
So the historical correct assumption has been, "If API classes (especially those that are model entity classes,) have not published a specific cloning method overrides,.. then don't use clone() or dup() with them."
How do you know when API classes implement clone()?
Refer to the API method index for "c":
http://www.sketchup.com/intl/en/developer/docs/methods#index_c
@fredo6 said:
So I logged a bug to the Sketchup team.
Which I also did like 7/8 years ago. So, it is already logged.
Other old threads on this:
2010: http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=29138%26amp;p=253940#p253787
2011: http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=40201%26amp;p=355527#p355527
2014: http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=58083%26amp;hilit=clone%26amp;p=530348#p530015
Related... concerning lack of Geom::PolygonMesh clone() & dup() methods:
http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=58080%26amp;p=530014#p530014
@bentet said:
Can anyone give me some pointers on where I can start? I can write a few simple things in ruby, but this kind of functionality is somewhat beyond my scope at the moment. A tutorial link and a few pointers from more experienced developers would go a long way.
--> topic: SketchUp-Ruby Resources
Before you can use the SketchUp API with Ruby, you need to learn the basics of Ruby, including how to look up methods for the Ruby Base classes.
Updated to v 0.2.1
Changes to get_size() method:
begin... rescue to trap and retry input type errors. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |--<<< RUBY RESOURCES >>>--|
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Ruby Newbie's Guide to Getting Started
viewtopic.php?f=180&t=10142&start=15#p298780
TUTORIALS & PRIMERS
~ Ruby (Generic) ~
Introduction to Ruby
http://www.ruby-doc.org/docs/Tutorial/
Ruby User's Guide
by Mark Slagell, Iowa State University
http://www.rubyist.net/~slagell/ruby/
Ruby Study Notes
by Satish Talim
http://rubylearning.com/satishtalim/tutorial.html
Learn to Program
by Chris Pine
http://pine.fm/LearnToProgram/
~ Sketchup Specific ~
Edges to Rubies - The Complete SketchUp Tutorial
by Martin Rinehart
http://www.martinrinehart.com/models/tutorial/
Ruby Tutorials
SketchUcation Forums
http://forums.sketchucation.com/viewtopic.php?p=52665#p52665
Tutorial Index
SketchUcation Forums
http://forums.sketchucation.com/viewtopic.php?f=18%26amp;t=8767
BOOKS
~ Offline (PDF, CHM, TAR, etc.) ~
The Book of Ruby
by Huw Collingbourne
** PDF
http://www.sapphiresteel.com/IMG/zip/book-of-ruby.zip
The Little Book of Ruby
by Huw Collingbourne
** PDF
http://www.sapphiresteel.com/IMG/pdf/LittleBookOfRuby.pdf
Mr. Neighborly's Humble Little Ruby Book
by Jeremy McAnally
** PDF
http://www.humblelittlerubybook.com/book/hlrb.pdf
Programming Ruby - The Pragmatic Programmer's Guide, 1st Ed.
(aka "The Old Pick-Axe Book" circa Ruby ver 1.6.x)
by David Thomas and Andrew Hunt
** TAR archive of website
http://phrogz.net/ProgrammingRuby/ProgrammingRuby_20061016.tar.gz
** CHM edition file is included w/ Win 1.8.6 One-click install
see your /ruby/doc directory OR
[url=http://forums.sketchucation.com/viewtopic.php?f=180%26amp;t=10142%26amp;p=431798#p431798:23sdyhrr]download from SketchUcation[/url:23sdyhrr]
Extending Ruby 1.9 - The Pragmatic Programmer's Guide
by David Thomas
[url:23sdyhrr]http://media.pragprog.com/titles/ruby3/ext_ruby.pdf[/url:23sdyhrr]
Ruby Best Practices
by Gregory T. Brown
** PDF
http://sandal.github.com/rbp-book/pdfs/rbp_1-0.pdf
Automatic SketchUp
by Matthew Scarpino, Eclipse Engineering LLC
[url:23sdyhrr]http://www.autosketchup.com/downloads/Automatic_SketchUp.pdf[/url:23sdyhrr]
~ Online ~
[i:23sdyhrr]Ruby Essentials[/i:23sdyhrr]
Techotopia
[url:23sdyhrr]http://www.techotopia.com/index.php/Ruby_Essentials[/url:23sdyhrr]
Programming Ruby - The Pragmatic Programmer's Guide, 1st Ed.
(aka "The Old Pick-Axe Book" circa Ruby ver 1.6.x)
by David Thomas and Andrew Hunt
[url:23sdyhrr]http://phrogz.net/ProgrammingRuby/frameset.html[/url:23sdyhrr] OR
[url=http://forums.sketchucation.com/viewtopic.php?f=180%26amp;t=10142%26amp;p=431798#p431798:23sdyhrr]download from SketchUcation[/url:23sdyhrr]
~ Previews of Ruby Books for Sale ~
[i:23sdyhrr]Learn to Program, 2nd Ed.[/i:23sdyhrr]
by Chris Pine
(expanded from the original tutorial)
[url:23sdyhrr]http://www.pragprog.com/titles/ltp2/learn-to-program-2nd-edition[/url:23sdyhrr]
[i:23sdyhrr]Programming Ruby - The Pragmatic Programmer's Guide, 2nd Ed.[/i:23sdyhrr]
(aka "The New Pick-Axe Book" circa Ruby ver 1.8.x)
by David Thomas, with Chad Fowler and Andrew Hunt
[url:23sdyhrr]http://pragprog.com/titles/ruby/programming-ruby[/url:23sdyhrr]
[i:23sdyhrr]Programming Ruby 1.9: The Pragmatic Programmers' Guide[/i:23sdyhrr]
by David Thomas, with Chad Fowler and Andrew Hunt
http://pragprog.com/titles/ruby3/programming-ruby-1-9
[i:23sdyhrr]The Ruby Programming Language[/i:23sdyhrr]
by David Flanagan and Yukihiro Matsumoto
http://books.google.com/books?id=jcUbTcr5XWwC%26amp;lpg=PA98%26amp;ots=fHGordbwjC...
TECHNICAL REFERENCES
[i:23sdyhrr]Ruby Cheatsheet[/i:23sdyhrr]
[url:23sdyhrr]http://www.zenspider.com/Languages/Ruby/QuickRef.html[/url:23sdyhrr]
[i:23sdyhrr]Ruby Base Classes - circa ver 1.6.x[/i:23sdyhrr]
(but most still OK for 1.8.x which has more methods)
[url:23sdyhrr]http://phrogz.net/ProgrammingRuby/builtins.html[/url:23sdyhrr]
[i:23sdyhrr]Ruby Core Documentation[/i:23sdyhrr]
(may be ver 1.9.x)
[url:23sdyhrr]http://www.ruby-doc.org/core/[/url:23sdyhrr]
[i:23sdyhrr]RDoc Documentation[/i:23sdyhrr]
[url:23sdyhrr]http://rdoc.rubyforge.org/[/url:23sdyhrr]
[i:23sdyhrr]RubyGems User Guide[/i:23sdyhrr]
[url:23sdyhrr]http://rubygems.org/read/chapter/1[/url:23sdyhrr]
[i:23sdyhrr]RubyGems Manuals[/i:23sdyhrr]
[url:23sdyhrr]http://docs.rubygems.org/[/url:23sdyhrr]
INDEXES
[i:23sdyhrr]Resources[/i:23sdyhrr]
(SketchUp Sage)
[url:23sdyhrr]http://sites.google.com/site/sketchupsage/resources[/url:23sdyhrr]
SKETCHUP SPECIFIC
~ API ~
[i:23sdyhrr]SketchUp Ruby API Cheatsheet[/i:23sdyhrr]
by Alex Schreyer
[url:23sdyhrr]http://www.alexschreyer.net/cad/sketchup-ruby-api-cheatsheet/[/url:23sdyhrr]
[i:23sdyhrr]SketchUp Ruby API[/i:23sdyhrr]
[url:23sdyhrr]http://code.google.com/apis/sketchup/[/url:23sdyhrr]
[i:23sdyhrr]SketchUp Ruby API - Class Index[/i:23sdyhrr]
[url:23sdyhrr]http://code.google.com/apis/sketchup/docs/classes.html[/url:23sdyhrr]
[i:23sdyhrr]SketchUp Ruby API - Method Index[/i:23sdyhrr]
[url:23sdyhrr]http://code.google.com/apis/sketchup/docs/methods.html[/url:23sdyhrr]
[i:23sdyhrr]SketchUp Ruby API - Class Diagram[/i:23sdyhrr]
[url:23sdyhrr]http://code.google.com/apis/sketchup/docs/diagram.html[/url:23sdyhrr]
[i:23sdyhrr]Sketchup Ruby API Class Diagrams[/i:23sdyhrr]
by Jim Foltz
[url:23sdyhrr]http://sketchuptips.blogspot.com/2008/08/sketchup-ruby-api-class-diagrams.html[/url:23sdyhrr]
[i:23sdyhrr]Google SketchUp API Blog[/i:23sdyhrr]
[url:23sdyhrr]http://sketchupapi.blogspot.com/[/url:23sdyhrr]
[i:23sdyhrr]PickHelper - Visual Guide[/i:23sdyhrr]
by Thomas Thomassen
[url=http://forums.sketchucation.com/viewtopic.php?f=180%26amp;t=30232%26amp;p=266685:23sdyhrr]http://forums.sketchucation.com/viewtopic.php?f=180&t=30232&p=266685[/url:23sdyhrr]
[i:23sdyhrr]WebDialogs - The Lost Manual[/i:23sdyhrr]
by Thomas Thomassen
[url:23sdyhrr]http://forums.sketchucation.com/download/file.php?id=36664[/url:23sdyhrr]
~ Indexes ~
[i:23sdyhrr]SketchUp-Ruby Resources[/i:23sdyhrr]
[url:23sdyhrr]http://forums.sketchucation.com/viewtopic.php?f=180%26amp;t=10142[/url:23sdyhrr]
~ BBs / Forums ~
[i:23sdyhrr]Developers Forum - Google Groups[/i:23sdyhrr]
[url:23sdyhrr]http://groups.google.com/group/google-sketchup-developers[/url:23sdyhrr]
[i:23sdyhrr]Developers Forum - SketchUcation Community Forums[/i:23sdyhrr]
[url:23sdyhrr]http://forums.sketchucation.com/viewforum.php?f=180[/url:23sdyhrr]
~ Code Snippets ~
[i:23sdyhrr]Code Snippets Index - SketchUcation Developers Forum[/i:23sdyhrr]
[url:23sdyhrr]http://forums.sketchucation.com/viewtopic.php?f=180%26amp;t=28846[/url:23sdyhrr]
~ Plugins ~
[i:23sdyhrr]Plugins Index (by author) - SketchUcation Plugins Forum[/i:23sdyhrr]
[url:23sdyhrr]http://forums.sketchucation.com/viewtopic.php?f=323%26amp;t=28782[/url:23sdyhrr]
[i:23sdyhrr]Plugins Visual Index - SketchUcation Plugins Forum[/i:23sdyhrr]
[url:23sdyhrr]http://forums.sketchucation.com/viewtopic.php?f=323%26amp;t=16909[/url:23sdyhrr]
[i:23sdyhrr]Trimble SketchUp - Plugins (Download Page)[/i:23sdyhrr]
[url:23sdyhrr]http://www.sketchup.com/intl/en/download/plugins.html[/url:23sdyhrr]
[i:23sdyhrr]Trimble SketchUp - Ruby Scripts (Download Page)[/i:23sdyhrr]
[url:23sdyhrr]http://www.sketchup.com/intl/en/download/rubyscripts.html[/url:23sdyhrr]
[i:23sdyhrr]Jim Foltz SketchUp Plugins[/i:23sdyhrr]
[url:23sdyhrr]http://sketchuptips.blogspot.com/2007/09/plugin-index-page.html[/url:23sdyhrr]
[i:23sdyhrr]Ruby Libray Depot[/i:23sdyhrr]
! URL Removed due to too many outdated plugins !
[i:23sdyhrr]Smustard(TM) - Plugins and Scripts[/i:23sdyhrr]
[url:23sdyhrr]http://www.smustard.com/scripts/[/url:23sdyhrr]
[i:23sdyhrr]JohnJ - Plugins for Sketchup[/i:23sdyhrr]
[url:23sdyhrr]http://www.johnj.com/drawing/sketchup/ruby-plugins-for-sketchup/[/url:23sdyhrr]
@tig said:
Using a bald 'Test' Class is asking for problems...
You can't. Test is a pre-defined Ruby standard module at the toplevel. (Edit: It's actually a library module, as Thomas points out below. But it's always defined, I will counter.)
Test.class %(#000000)[>> Module]
class Test; def what(); puts "testing...": end; end %(#000000)[>> Error: #<TypeError: Test is not a class>]
@thomthom said:
Testis a module in the StdLib.
true !
Ref: http://ruby-doc.org/stdlib-2.0.0/libdoc/test/unit/rdoc/Test.html
@thomthom said:
If it's not loaded the Ruby core won't have defined it.
Not quite correct.
Since the SketchUp API Core adds methods to the Test module, it will always be defined.
Test.methods(false).sort %(#000000)[>> [:AutoClickTime, :AutoClickTime=, :AutoDragDistance, :AutoDragDistance=, :CorruptModel, :FindFile, :diff, :eat_mem, :export_animation, :flip_images_for_origami, :project_textures_from_photo, :repair_model, :show_fps, :suppress_warnings=, :suppress_warnings?, :time_display, :time_pick, :use_sg_off_screen, :use_sg_on_screen]]
@josephkim626 said:
Above is the parts of the code that you have included perhaps better explains your plugin.
I have short experience in translating programs/documents. I think this would do.The description of Vistools didn't really mean anything as the sentences were in shuffled order. I've kept the name in English as I am not sure direct translation really gives you any benefit.
Just so you know, you didn't really offend anyone
Okay, thank you Joseph. You have been entered in the halls of VisTools fame !
The patch RBZ for your Korean language strings has been posted in the OP of this thread:
http://sketchucation.com/forums/viewtopic.php?f=323%26amp;t=49662%26amp;p=446865#p446865
You just install it in the normal manner, and it should overwrite the old "VisTools_ko.rb" file.
You need to restart SketchUp to load the new strings.
@marthmatica said:
So as an example I did a SkecthUp cafe creator, driven from Excel face point data per row.
Maybe someone will find this useful, or a better way to do it, or improve my Ruby, since I am just starting on the Ruby end.
Ruby improved.
See new topic: [Code] Geometry Creation from Excel worksheet data
Here is Marthmatica's example, cleaned up and properly namespace wrapped.
(ref: http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=23441%26amp;p=589250#p589171)
Basically if you use it as a template, you replace the outermost namespace module name "Author" with your own toplevel namespace module name. (And you can also rename the plugin module to whatever you wish, as well.)
I cannot test it currently as I have LibreOffice installed (instead of MS Office.)
# encoding; UTF-8
#
# Example SketchUp extension; Geometry creation from Excel worksheet data
require 'sketchup.rb'
require 'win32ole'
module Author # outer Author namespace module
module XLTiler # this particular plugin module
VERSION = '0.2.3'
EXCEL = 'Excel.Application'
@@loaded = false unless defined?(@@loaded)
class << self # anonymous singleton proxy class instance
def init()
#
@xl = nil
#
end ### init()
def connect_to_excel()
#
if @xl.nil?
# Use WIN320LE.new to start a new spreadsheet instance.
@xl = WIN32OLE;;new(EXCEL)
else
# Connect to an already open spreadsheet application.
# Use WIN320LE.connect to connect to an already open Excel instance.
@xl = WIN32OLE;;connect(EXCEL)
end
#
@xl.visible = TRUE
#
rescue
false
end ### connect_to_excel()
def get_value(row,col)
#
@xl.activesheet.cells(row,col).value
#
end ### get_value()
def get_size( *size )
@rows = 24 if @rows.nil? # Rows are face count to create
@cols = 12 if @cols.nil? # Columns have all 4 face points
# Note cols is the face pts x1,y1,z1; x2,y2,z2... 1 through 4 xyz points; or 12 cols
# XL row 1= pt1; 1, 1, 0 pt2; 1, 2, 0 pt3; 2, 2, 0 pt4; 2, 1, 0
# XL row 2= pt1; 2, 1, 0 pt2; 2, 2, 0 pt3; 3, 2, 0 pt4; 3, 1, 0
# and so on...
if size.empty?
# Use defaults
rows = @rows # Rows are face count to create
cols = @cols # Columns have all 4 face points
# Now prompt user to change or confirm size;
begin
result = UI.inputbox(["Rows","Cols"],[rows,cols],"Matrix Size")
rescue => e
UI.messagebox(e.message)
retry
else
rows, cols = result
end
else
rows, cols = size
end
#
return rows,cols
#
end ### get_size()
# Define the method that is activated from that added menu item click
def get_xltiler()
unless connect_to_excel()
UI.messagebox("Could not connect to Excel !")
return
end
# Instantiate tile matrix origin for Excel rows and columns reference.
# We'll use a hash whose keys are the integer row numbers. The values
# will be arrays consisting of #{cols} number of values.
matrix = {}
# A return array of faces created;
faces = []
# Set row and column count
result = get_size()
return if !result # false if user cancelled inputbox.
@rows, @cols = result
# rows is how many face tiles you are creating in SketchUp, 1 face tile, per each row
# BUILD matrix
# step through all the XL rows
for r in 1..@rows
# Each row is an array of #{cols} number of values
matrix[r]= []
# In every row populate the matrix from Excel cell values;
for c in 1..@cols
matrix[r] << get_value(r,c)
end
# Advance loop to next row.
end
# THE MAIN FACE CREATING ROUTINE
# stepping through rows, as how many tiles you are creating is total rows,
# then stepping through cols to populate all 4 face pts per row
# Get handles to our model and the Entities collection it contains.
model = Sketchup.active_model
act = model.active_entities
group = act.add_group
cpt = group.entities.add_cpoint( [0,0,0] )
# We add a cpoint to keep group from garbage collection
ents = group.entities
pts = []
for r in 1..@rows
row = matrix[r]
pts.clear
row.each_slice(3) {|ary| pts << Geom;;Point3d;;new(ary) }
# Add new face per this row;
ents.add_face( *pts )
# Advance loop to next row.
end
cpt.erase! # no longer needed
@xl = nil # release Excel reference
return group # an group of the face objects created
end ### get_xltiler()
end # anonymous singleton proxy class instance
### RUN ONCE CODE
#
if !@@loaded
# Add a menu item to launch our plugin,
# in its SketchUp menu default name target,
# and the name we are giving our function in the "Tools" menu.
UI.menu("Tools").add_item("Get XLTiler") {
# UI.messagebox("Ye Excel! come up from hell!")
get_xltiler()
}
init()
@@loaded = true
end
end # this particular plugin module
end # outer Author namespace module