I have a plugin which functions differently in SketchUp 8 versus SketchUp 2015 Make. This is most likely caused by the different underlying Ruby versions and not a SketchUp problem, per se, but I thought I would mention it here (perhaps this is already a well-known issue and I’m simply being redundant).
I open a text file and read it line-by-line using ‘gets’. For each line, I iterate through the characters as an array and test each value, For example:
fh = File.open('test.txt','r')
t = fh.gets
if(t[0] == 65) do something # returns true in 8 / false in 2015
if(t[0] == 'A') do something # returns true in 2015 / false in 8
fh.close
In SketchUp 8, the class type for ‘t’ is String and the class type for ‘t[0]’ is FixNum. In 2015, they are both of class String. This got me to wondering about other “minor” differences between versions that might cause issues as well.
Is there documentation somewhere that identifies these little quirks?
This is a difference between Ruby 1.8 and 2.0. Between those two versions string handling in particular had some changes - like this. In this case the change is due to Ruby 1.8 not being Unicode aware. In Ruby 2.0 you want to make sure you deal with the correct encoding for your strings and when you iterate files that you iterate per character and not per byte (unless you deal with binary files off course.)
We haven’t documented this in the SketchUp API pages because this is a Ruby change which is well documented in general in the Ruby community. If you look up what’s new in Ruby 2.0 you should find several good resources which outline the most significant changes.
(p.s. I edited your post to mark your code up as Preformatted Text so it reads easier.)
They are called “breaking changes” because they can break code.
Yes the issue you speak of was on the list. Specifically the subscript method of String, using one index argument, returning different types in the two versions.
The workaround is to use the 2 argument form: str[ start_pos, length ]
ie: t[0,1] will return a one character String in all versions.
I remember reading the list of changes a few months ago, but this part didn’t particularly stand out in my mind at the time:
'test'[0] returns 't' under 2.0 and 116 under 1.8.
Use 'test'[0,1] for compatibility.
SketchUp is my only exposure to Ruby and I’m admittedly ignorant of most of it. I’m surprised at how much broke between releases … it must make the job of upgrading the underlying code quite interesting.
BTW, I’m working to upgrade my plugins to make them play friendlier with others … I’ve attached the example code I wrote for “Desk Activity” and would appreciate some critiquing of the structure as it relates to SketchUp. I’ve tried to follow Dan’s suggested template, but I’m not sure how well I understand it. Any advice is greatly appreciated.
I should have realized that attachments were misbehaving before I attached my file …
# desk_activity.rb - (C) 2015 by Aqualung -- Permission granted to freely use this code
# as long as this line and the preceding line are included in any derivative work(s)JRH
#
# 5/23/2015 Version 1.0
# 5/24/2015 Version 1.1 - replaced groups with component instances
# 5/25/2015 Version 2.0 - wrapped plugin with DR's suggested module framework
# 6/1/2015 Version 2.1 - modified string array test to work with 2015
#--------------------------------------------------------------------------------------
require 'sketchup.rb'
module Jimhami42
module Desks
class << self
# CLASS VARIABLES -----------------------------------------------------------------
@@num_desks = 0
@@s = []
@@scene = 0
@@compdef = 0
# MAIN BODY -----------------------------------------------------------------------
def spirix_desk_activity()
Sketchup.active_model.start_operation("Desk Activity")
puts "Starting... (" + Time.now.to_s + ")"
spirix_get_desk_data("c:/desks.txt")
puts "Activities... (" + Time.now.to_s + ")"
spirix_get_activity_data("c:/activity.txt")
puts "Scenes... (" + Time.now.to_s + ")"
spirix_create_desk_scenes()
puts "Done! (" + Time.now.to_s + ")"
Sketchup.active_model.commit_operation
end
# GET DESK DATA -------------------------------------------------------------------
def spirix_get_desk_data(filename)
desks = File.open(filename,"r")
t = desks.gets.chomp
num_desks,dx,dy = t.split(',')
@@num_desks = num_desks.to_i
dx = dx.to_f
dy = dy.to_f
for i in 0...@@num_desks do
t = desks.gets.chomp
x,y = t.split(',')
@@s[i] = [x.to_f,y.to_f,0.0]
end
desks.close
comp = Sketchup.active_model.entities.add_group
comp.entities.add_face([0,0,0],[dx,0,0],[dx,dy,0],[0,dy,0])
comp.layer = Sketchup.active_model.layers.add("Component")
comp.layer.visible = false
@@compdef = comp.to_component.definition
end
# GET ACTIVITY DATA AND CREATE INSTANCES ------------------------------------------
def spirix_get_activity_data(filename)
act = File.open(filename,"r")
t = act.gets
while(t)
layer = Sketchup.active_model.layers.add("Scene " + @@scene.to_s)
layer.visible = false
for i in 0...@@num_desks do
vec = Geom::Vector3d.new(@@s[i].x,@@s[i].y,@@s[i].z)
trans = Geom::Transformation.translation(vec)
inst = Sketchup.active_model.entities.add_instance(@@compdef,trans)
inst.layer = layer
if(t[i,1] == 'A')
inst.material = "green"
else
inst.material = "red"
end
end
t = act.gets
@@scene += 1
end
act.close
end
# CREATE SCENES -------------------------------------------------------------------
def spirix_create_desk_scenes()
for i in 0...@@scene
Sketchup.active_model.layers["Scene " + i.to_s].visible = true
Sketchup.active_model.pages.add("Scene " + i.to_s)
Sketchup.active_model.layers["Scene " + i.to_s].visible = false
end
end
end
# STARTUP -------------------------------------------------------------------------
unless file_loaded?("desk_activity.rb")
menu = UI.menu("PlugIns").add_item("Desk Activity") { spirix_desk_activity() }
file_loaded("desk_activity.rb")
end
#--------------------------------------------------------------------------------------
end
end
I’d actually feared more - going from Ruby 1.8 to 2.0. Though it appear most issues people had was related to strings. For the guys that used Ruby for the web this probably hurt more as they deal with nothing but strings. Though for the SketchUp devs which in large part deal with the SketchUp API the impact was reduced.
Fortunately Ruby has switched to semantic versioning - so the Ruby 2.x branch should remain compatible. (excluding Ruby binaries off course.)
I strongly recommend setting the second argument to true in order to obtain significant performance boost when creating operations. The fact that it’s left to default to false is just a compatibility thing with SU6 and older.