前面我们创建的画墙工具已经很好用了,但是从细节上我们还可以进一步优化,下面从几个方面入手对画墙工具进行优化。
工具退出
当前我们实现的画墙工具有个缺陷,就是如果我们用视图画出一段线,这时候如果切换到其他工具,比如按空格切换到选择工具,在绘图区还会残留我们刚才画出的线,直到变换视角或有其他刷新视图的操作之后才会消失。实际上,这是因为工具退出的时候没有通过绘制刷新把视图上绘制的图形刷掉,要想达到这个目的,就需要响应工具退出事件,也就是实现工具的deactivate方法,在这个方法中通知视图刷新,也就是调用view.invalidate就可以了。这次的通知刷新会在切换到的工具的视图绘制方法中进行一次绘制。
def deactivate(view)
view.invalidate
end
这样,在切换到其他工具的时候,就不会再保留我们的画墙工具的视图绘制结果了。
工具激活
到目前为止,我们还没有用到工具激活的事件响应接口,实际上这个接口也很重要,像工具中一些变量的初始化,都应该在这里进行,只是我们的实现放到了工具构造方法中。这样就会导致我们想在工具对象中保留修改的数据不能保存下来,比如前面我们的墙的尺寸参数,这次绘制我们修改了尺寸之后,下次工具激活的时候我们还想要继续使用这个参数。要实现这个功能,可以按下面的方法修改。
首先激活工具的时候,我们不再重新实例化工具,而是使用已有的,这样就需要把工具对象定义成一个常量或全局变量。
DRAW_WALL_TOOL = DrawWallTool.new
cmd = UI::Command.new('画墙工具') {
model = Sketchup.active_model
model.select_tool(DRAW_WALL_TOOL)
}
然后把除墙尺寸之外的变量的初始化移到工具的激活接口中
def initialize
@thickness = 200
@height = 3000
end
def activate
@start_pt = nil
@end_pt = nil
@status = :start
end
这样,我们修改了尺寸之后,下次再激活工具的时候,这个尺寸就是上次修改之后的尺寸了。
右键菜单
前面我们修改墙的尺寸是通过按Ctrl键来弹出修改墙尺寸的对话框的,这个操作很隐蔽,不容易被发现还有这个功能。除了可以在状态栏进行提示外,我们还可以把修改尺寸的操作添加到右键菜单中,这样的功能很容易发现,使用起来也方便。
右键菜单需要实现工具的getMenu接口,在方法定义中定义菜单。
def getMenu(menu, flags, x, y, view)
menu.add_item('修改尺寸') {
change_wall
}
end
这样,在工具中点击右键的时候就可以弹我们的右键菜单,使用它可以直接修改尺寸了。

用户输入接口
在SketchUp的画线工具中,有一个非常实用的功能,就是在绘制第2个点的时候直接输入长度,工具就会沿我们绘制的方向直接绘制出输入长度的线。这个功能是通过用户输入接口onUserText实现的,onUserText接口中可以接收到工具激活后的键盘字符输入,我们可以把这个输入转成实际的距离,然后计算出最终点的位置来创建墙。
def onUserText(text, view)
return unless @status == :end
vector = @end_pt - @start_pt
return unless vector.valid? && vector.perpendicular?(Z_AXIS)
length = text.to_i
@end_pt = @start_pt.offset(vector, length.mm)
create_wall
@start_pt = nil
@end_pt = nil
@status = :start
view.invalidate
end
这样,我们在画墙的时候就可以通过输入长度值然后回车,来直接绘制出指定长度的墙了。输入的过程中,在右下角的VCB(value control box)中可以看到我们的输入。

取消操作接口
如果在绘制第2个点的过程中,发现第1个点就绘制错了,除了可以退出工具再激活重新绘制外,实际上更普遍的操作是按ESC键恢复到最初状态,然后重新绘制。这是通过实现onCancel接口实现的,当然,我们也可以通过响应键盘按钮来实现任意键作为取消操作键,但是一般情况我们都是实现onCancel接口实现的。
def onCancel(reason, view)
@status = :start
@start_pt = nil
@end_pt = nil
view.invalidate
end
这样,我们就可以随时在工具中取消我们的当前操作,重新进行绘制了。
现在我们的工具已经优化得差不多,已经算是一个很好用的画墙工具了,如果还有特定的优化需求,可以通过查询API实现特定的功能,这里就不再进一步优化了。
画墙工具的完整代码可以关注“小众程序员”公众号,回复“draw_wall_tool”获取。