ch之前我们已经创建了两个工具用来创建带窗洞的墙,两个工具位于一个画墙工具条中。在SketchUp的扩展管理器中,也可以看到我们的plugin_demo已经作为一个扩展插件存在了。但是与其他插件不同的是,我们的插件没有任何相关信息,仅仅只有一个名字,而其他成熟正式的插件则显示有各种插件相关的版本、作者、描述等相关信息。
plugin_manager.png
这些信息实际上是在开发插件时通过SketchUp的插件类SketchupExtension提供的接口设置的。
SketchupExtension类
在SketchupExtension类的文档介绍中可以了解到,一般情况下应该使用SketchupExtension对插件进行管理,这样可以使用插件管理器方便的加载和卸载插件,并可以对插件的行为进行多方面的控制。在实际使用时,往往都是在/Plugins目录之外的目录中创建插件的脚本,例如/Plugins/plugin_demo中,然后在/Plugins目录下添加扩展项,在用户打开扩展时同时加载插件的脚本。
以前面创建的画墙工具为例,我们可以把它命名为free_wall,我们可以创建一个/Plugins/free_wall/目录并把我们之前的代码命名为core.rb放到该目录下,然后在/Plugins目录下添加一个free_wall.rb文件用来设置扩展项
1 2 3 4 5 6 7 | require 'sketchup.rb' require'extensions.rb' wall_extension = SketchupExtension.new('Free Wall', 'free_wall/core.rb') wall_extension.version = '1.0' wall_extension.description = 'Tools to create wall with hole.' Sketchup.register_extension(wall_extension, true) |
这时候,重启SketchUp后就可以在其扩展管理器窗口中看到我们的Free Wall插件,并且有了版本和描述信息
free_wall_plugin.png
除此之外,还可以设置和获取插件的作者、版权等信息。如果把我们的插件发布到插件商店中,可能还会涉及插件的ID、版本ID等。
更好的插件目录结构
上面对扩展的讲述中把扩展入口和具体的插件分成了两部分,这样我们的插件代码可以更换到任意位置和目录中,只要修改扩展入口中的插件目录位置就可以了。实际上,我们的插件代码也应该设计成更合理的目录结构,以便于扩展和复用,而不能像现在的结构,所有的代码都放到一个文件中。比如我们的代码粗略的可以分为3部分:
- 画墙工具
- 开洞工具
- 工具条和菜单栏
所以,至少我们可以分成3个文件来组织代码,再加上一个插件的核心文件,共4个文件。两个工具属于同一类,可以放到同一目录专门用来存放工具类。所以我们的目录结构可以组织为
1 2 3 4 5 6 7 | Plugins/ free_wall/ core.rb tool_manager.rb tool/ draw_wall_tool.rb create_hole_tool.rb |
其中
- core.rb用来统一对插件内容进行管理,也是我们插件的入口。
- tool_manager.rb用来管件工具、创建工具条和菜单栏,我们可以封装一个类ToolManager来做这件事。
- draw_wall_tool.rb和create_hole_tool.rb用来定义画墙工具和开洞工具类。
更好的代码结构
模块
类似于C++的命名空间,Ruby中使用模块来管理代码的结构、防止命名冲突等。比如我们可以把我们所有的代码都放到模块FreeWall中来管理
1 2 3 | module FreeWall # 插件代码 end |
ToolManager类
为方便管理,我们可以封装一个ToolManager类对工具条来创建和管理(菜单栏暂不处理)。通过前面创建工具条的经历,可以知道ToolManager类的几个职能
- 加载工具类定义
- 创建工具对象
- 创建工具激活命令
- 创建工具条并添加工具激活命令
所以我们可以这样设计ToolManager类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | require 'free_wall/tool/draw_wall_tool.rb' require 'free_wall/tool/create_hole_tool.rb' module FreeWall # 工具条 class ToolManager # 初始化 def initialize @draw_wall_tool = DrawWallTool.new @create_hole_tool = CreateHoleTool.new end # 创建工具条 def create_toolbar draw_wall_cmd = create_cmd(@draw_wall_tool, '画墙工具') create_hole_cmd = create_cmd(@create_hole_tool, '开洞工具') toolbar = UI::Toolbar.new('画墙工具条') toolbar.add_item(draw_wall_cmd) toolbar.add_item(create_hole_cmd) toolbar.show end private # 创建激活工具命令 def create_cmd(tool, name) UI::Command.new(name) { model = Sketchup.active_model model.select_tool(tool) } end end end |
核心文件core.rb
核心文件一般用来管理代码的加载,关键对象的创建等。上面我们只创建了工具条的管理类,在核心文件中需要对工具条进行实例化并创建SketchUp的工具条。
1 2 3 4 5 6 | require 'free_wall/tool_manager.rb' module FreeWall tool_manager = ToolManager.new tool_manager.create_toolbar end |
这样的代码结构设计好之后就清晰多了。
加载路径
在上面的代码中,我们在加载依赖代码的时候使用了ruby的require方法,其后面的参数文件路径,一般都是绝对路径或ruby加载路径中的目录的相对路径。在SketchUp的ruby解释器中,加载路径设置成了几个SketchUp安装路径相关的目录,其中当前也包含了/Plugins目录。所以我们在加载代码的时候,需要把从/Plugins之后开始的所有的路径都包含到路径中才可以。
如果我们修改了插件目录位置到计算机中的任意一个位置,一个很好的实践是在扩展入口文件中把我们插件的目录添加到加载路径中,这样,我们插件的代码不必有任何的修改就可以正确加载我们的插件。比如我们把插件目录放到了D盘根目录下,则扩展入口文件可以这样写
1 2 3 4 5 6 7 8 9 | require 'sketchup.rb' require'extensions.rb' $LOAD_PATH << 'd:/' wall_extension = SketchupExtension.new('Free Wall', 'free_wall/core.rb') wall_extension.version = '1.0' wall_extension.description = 'Tools to create wall with hole.' Sketchup.register_extension(wall_extension, true) |
只是在其中增加了一行加载路径的添加操作,其他的任何代码都不需要修改,我们的插件也可以正常加载使用。