这篇文章将是SketchUp Ruby教程的第一篇,将介绍如何在SU的Ruby控制台中通过编写代码实现添加一个“Hello World”文字图元,并以这样一个例子展开介绍可以用怎样的方法自学SU Ruby。一切将从两三行的代码开始,并通过代码产生的效果引出一些基本的内容,并且顺便介绍一个简单的类,SketchUp::Text(文本图元类)。
第一部分:完成一个Hello World实验
第①步:打开SketchUp,在“窗口”菜单中选择“Ruby控制台”。这个选项默认是没有快捷键的,如果有需要可以像下图所示增加一个快捷键。
第②步:在Ruby控制台中逐行输入以下代码,每一行使用回车键结尾:
ents=Sketchup.active_model.entities
text=ents.add_text "Hello World",[0,0,0]
需要注意,Ruby是大小写敏感的,也就是说这里的代码大小写是不能随意替换的。如果是第一次接触代码一类的还需要注意不要使用中文输入法,否则输入法自带的全角符号是不能被识别的。(不过对标点符号上的不上心似乎是当代的一种风气,就比如很多人在抄写公文发文字号的时候不会使用六角括号。)
另外,直接从此处复制代码似乎有可能多复制一些不可打印字符,不知道是不是插入代码功能的特性,还是建议手工输入。
然后就成功的在原点处创建了一个“Hello World”的标签。代码中的ents.add_text是一个类似于指令的存在,其后有两个参数,第一个是文字信息,第二个则是生成位置信息。因为刚刚的代码中使用了“[0,0,0]”所以这个文字图元就生成在了原点处。
以上就是一个“Hello World”的全部内容,但这仅是第一部分,接下来的第二部分将会对其产生的结果做进一步延伸。
第二部分:对“Hello World”进行修改
第①步:选择刚刚生成文字图元,在图元信息窗口中查看这个文字图元的属性:
不同的版本窗口可能有些许不同,但是我们都可以看到这个图元的一些属性,包括图元的类型、图层、可见性和其他一些个性化的属性。比如说这里的文本图元还有文字、箭头、引线、字体等属性。不像前面列举的那些属性,这些属性在其它类型的图元中是看不到的。在第二部分的铺垫之后,第三部分将介绍如何使用Ruby修改其中的某些属性。
第②步:使用Ruby查看文字图元可以使用的方法:
还记得刚刚第二行代码中开头的的“text=”吗,如果去掉这五个字符,并不会影响生成这个文字图元,但是因此Ruby代码很可能需要花费很大的代价才能重新找到这个刚生成的文字图元。与之类似的还有第一行代码中的“ents=”,他被用来指代之后很长的一串代码,所以在第一行代码执行以后,以下两行代码的执行效果将完全一致:
ents.add_text "Apiglio",[0,0,0]
Sketchup.active_model.entities.add_text "Apiglio",[0,0,0]
所以我们可以用“text”来指代刚刚创建的那个文字图元,对这个图元进行其他操作。尝试继续输入以下代码:
text.class
text.typename
text.text
text.methods
输入这些代码后可以得到下图的结果。
其中第一行“text.class”返回的是text所代表的这个图元的类型,即“Sketchup::Text”;第二行“text.typename”返回的是“Text”这个文字信息(也就是字符串),在所有图元中,它和前一个的类型是一一对应的,只不过是换了一种数据形式;第三行“text.text”返回的是这个文字图元的文字信息,也就是之前“ents.add_text”之后的第一个参数;最后一行则是SU Ruby自学的核心,它返回了所有text对应的类可以使用的公共方法,或者说直观一点来说就是“text.”之后可以接着的内容。
前三行可能是在举例,最后一行的内容则将贯穿Ruby学习始终,虽然它不能作为自学的全部,但是也绝对举足轻重。有句话叫做“当你手上有一把锤子的时候,看所有的东西都是钉子”,这句话本是贬义,但是对于这个.methods方法来说却再合适不过,它不会让人失望。不信的话可以尝试以下代码,它们将展示不同的数据类型可以使用的方法:
"string".methods
123.methods
Sketchup.methods
ents.methods
ents[0].methods
回到文字图元,有了.methods方法以后,就可以根据它的返回结果来推测和尝试这些方法,方法很多,但大多数都很简单。有这么几种方法是成对出现的,通常用于显示引用或者修改自身的属性,例如“text”&“text=”、“arrow_type”&“arrow_type=”、“point”&“point=”、“vector”&“vector=”和“layer”&“layer=”,又或者例如“visible?”&“visible=”、“hidden?”&“hidden=”和“casts_shadows?”&“casts_shadows=”。通常是这个图元具有一个这样名称的属性,前一个方法用于引用这个属性,后一个方法用于更改这个属性。“xxx”和“xxx?”的区别在于后者返回的属性是一个布尔值变量,即只有“真”或“假”两种状态,使用问号来引用这样的属性可以让代码更加具有可读性。
以下列举了文本图元的其中一些方法,这里头有一些方法并不是文本图元所特有的,而是文本图元类继承自图元实体类的(在表格中以红色字体注明),但是在这里将暂时不区分他们,只需要知道这些方法在其他图元中也可以使用。
方法名
| 解释 |
text | 返回文本的文字内容
|
text= "str"
| 修改文本的文字内容 |
arrow_type | 返回当前箭头的样式 (0=无箭头; 1=斜短划线; 2=圆点; 3=箭头; 4=大箭头) |
arrow_type= n | 修改箭头的样式 (0=无箭头; 1=斜短划线; 2=圆点; 3=箭头; 4=大箭头) |
leader_type | 返回当前引线的样式 (1=基于视角调整; 2=固定) |
leader_type= n | 修改引线的样式 (1=基于视角调整; 2=固定) |
display_leader? | 返回是否显示引线 (true=是; false=否) |
display_leader= bool | 设置是否显示引线 (true=是; false=否) |
vector
| 返回引线的向量[x,y,z]
|
vector= [x,y,z] | 设置引线的向量 |
point
| 返回标注的原点[x,y,z] |
point= [x,y,z] | 设置标注的原点 |
hidden?
| 返回是否被隐藏
|
hidden= boo
| 设置实体是否隐藏 (true=隐藏; false=不隐藏) |
erase!
| 删除实体
|
deleted?
| 返回实体是否被删除 |
第③步:使用Ruby修改文字图元的属性:
在第一部分“Hello World”的基础上,可以接着使用“text”调用上面那些方法,例如要删除text图元,就需要使用.erase!方法,因此就需要在“text”之后加“.”在接上“erase!”来表示删除这个对象的意图,对于其他方法也是同理的。以下是其中一些方法效果的展示:
所以“.”是ruby中非常重要的语法,它表示调用一个对象所拥有的方法,而方法有可能返回一个他的一个成员(子对象),从而可以继续使用“.”来调用这个子对象的方法。现在回过头看刚开始的Hello World的实现:
ents=Sketchup.active_model.entities
text=ents.add_text "Hello World",[0,0,0]
“Sketchup”是整个SU的功能模块,Sketchup中有一个“active_model”的方法,这个方法返回了一个对象(这个对象具体是什么会在随后的教程中介绍),这个对象又有一个“entities”方法,这个方法也返回了一个对象,并且代码将它定义为“ents”以便接下来的使用。后面我们就会知道这个ents就是SU模型中所有图元的容器类,是一个类似于数组的存在,它同时也有属于自己的方法,而第二行的代码调用了这个对象中的“add_text”方法。这个方法同样返回对象,但是不同于前几个层次返回既有的对象,它是先创建再返回对象的,因此可以看到SU的界面中“凭空”出现一个文字图元,最后将刚创建的图元返回给了“text”。
第三部分:自学SU Ruby的建议
第①点:初步了解Ruby
尤其是使用.methods和.class之类的方法了解未知的对象,这些方法是所有ruby对象所具有的;当然一些基础的数据类型的表达也是需要了解的,不然定会有些弯路要走。Ruby的基础内容可以在菜鸟教程中找到,非常的便捷。
https://www.runoob.com/ruby/ruby-tutorial.html
第②点:找到一个解惑的字典
这个字典可以是具体的教材(本人看的是一本叫做Automatic SketchUp - Creating 3-D Models in Ruby的教材,似乎现在也能找到中文的教材了),也可以是SketchUp官方的文档。这个可比第一点更加有效。
https://ruby.sketchup.com
第③点:需求是最好的动力
尝试一些自定义的小工具,这会很好地鼓舞自己继续的。
最后放一个不用“text”来指代新建文字图元的例子聊以消遣。
Sketchup.active_model.entities.each{|ent|
if ent.typename=="Text" then
if ent.text=="Hello World" then
ent.erase!
end
end
}
text.erase!