Ruby API to Google SketchUp有一个函数open_file
,但我找不到close_file
函数。由于我必须批量处理许多文件,我想在继续下一个之前关闭每个文件,否则程序将因内存耗尽而崩溃。
以编程方式关闭SketchUp文件的最佳方法是什么?
我使用的是Mac OS X,我愿意使用AppleScript函数来指示窗口关闭。
修改
到目前为止,我正在考虑一些已证明无效的方法。
以类似的方式,我试图使用osascript(从shell执行AppleScripts的bash程序)来关闭窗口。也就是说,我使用以下之一从SketchUp的Ruby控制台窗口调用shell:
%x [osascript -e' tell application“SketchUp”关闭窗口1']
%x [osascript -e'告诉应用程序“SketchUp”关闭窗口1'&]
%x [osascript -e'告诉应用程序“SketchUp”关闭每个窗口']
%x [osascript -e'告诉应用程序“SketchUp”关闭每个窗口'&]
每当我尝试第二种方法时,SketchUp就会冻结。但是,当我从IRB执行这些命令的任何或直接从SketchUp之外的Bash提示符执行时,我得到了所需的行为:模型窗口关闭(顺便提一下,Ruby控制台窗口保持打开状态,很好)。
使用主脚本启动从属脚本来处理每个模型。当主人等待时,奴隶将在Google SketchUp程序中运行。当从机完成时,它向主机发出信号,主机关闭SketchUp文件。为了进行这种进程间通信,我尝试使用drb。但是,当我尝试在SketchUp中要求drb
时,我收到以下消息:
错误:LoadError:(eval):5:在'require'中:没有要加载的文件 - drb
编辑2
由于多种原因,在发出信号时,使用AppleScript关闭Google Sketchup窗口的单独进程会持续运行。首先,必须有一个专门用于关闭Sketchup窗口的单独进程是很难看的。其次,与外部脚本通信的唯一有效方法是通过创建文件,这是浪费的,磁盘访问可能会减慢速度。
然而,最严重的问题是Sketchup响应AppleScript命令的速度很慢。我有一个在Sketchup中运行的计算密集型脚本,它似乎使AppleScript响应挨饿,这意味着osascript在Windows关闭之前超时。当Sketchup中有一个暂停执行我的计算密集型脚本的对话框提示时,Sketchup仅响应AppleScript。
编辑3
我修改了close_file
函数,通过显示一个对话框来暂停执行脚本。这实际上产生了当前线程,并允许响应AppleScript命令的线程执行:
def close_file()
f = '/temp/mutex.txt' # for finer control, use different mutex for each window you want closed
File.new(f, 'w').close
result = UI.messagebox "Click OK when window has closed."
end
然后通过AppleScript关闭窗口的单独ruby脚本还必须在对话框中单击“确定”。 AppleScript就是这样做的:
tell application "System Events"
tell process "SketchUp"
set frontmost to true
keystroke return
end tell
end tell
这种修改是一种改进。它纠正了编辑部2中提到的“最严重的问题”,但其他问题仍然存在。
答案 0 :(得分:2)
使用外部AppleScript强制SketchUp执行某项操作时存在一个重要限制。当菜单脚本运行时,SketchUp将不接受任何用户输入。
我发现了这个尝试设置自动渲染解决方案。我添加了一个菜单项,打开WebDialog以获取要从服务器下载的模型列表。然后逐步浏览列表并使用cURL下载每个模型。下载后,它会加载模型,将其渲染出来,再次使用cURL上传图像,然后转到下一个模型。
我想要的是在渲染每个模型后激活AppleScript(使用上面显示的“互斥”文件解决方案)并让它关闭模型窗口。遗憾的是,由于菜单脚本仍在运行,因此SketchUp不会响应AppleScript要求它执行的任何操作。只有处理完所有模型并退出菜单脚本后,AppleScript才会最终运行。
如果对AppleScript的所有调用都排队等待,那就不会那么糟糕,但事实并非如此。似乎只有最后两个得到尊重(这个数字可能只是一个意外,取决于我对AppleScript的调用时间相对于菜单脚本完成的时间)。
由于这个限制,我无法在菜单Ruby代码中使用mutex wait()函数。由于AppleScript无法执行,因此它从未创建其“我已完成”的互斥文件,因此Ruby中的wait()函数从未得到可以继续的信号。结果是AppleScript和SketchUp之间出现了僵局,因此SketchUp只是冻结(好吧,实际上它只是停留在wait()函数的一个非常紧密的循环中)。
因此,在解决此问题时,请将AppleScript视为可在完成所有处理后调用的清理工具。
答案 1 :(得分:0)
一种解决方案是让一个单独的进程持续运行,以便在发出信号时使用AppleScript关闭Google Sketchup窗口。这里描述的方法使用文件进行进程间通信(drb似乎不起作用)。
首先,您必须确保Sketchup supports AppleScripting。为此,请在命令提示符处执行以下命令(对不同的Sketchup版本进行适当的替换等):
$ defaults write /Applications/Google\ SketchUp\ 8/SketchUp.app/Contents/Info NSAppleScriptEnabled -bool YES
现在,创建一个单独的文件来关闭Sketchup窗口。这是我的closer.rb
文件:
#!/usr/bin/ruby
## closer.rb ##
def wait(f)
while !File::exists?(f)
end
File.delete(f)
end
def signal(f)
File.new(f, 'w').close
end
while true
wait('~/temp/mutex.txt')
msg = %x[osascript -e 'tell application "SketchUp" to close every window']
signal('~/temp/conf.txt')
end
从shell运行此脚本。它等待,直到创建文件~/temp/mutex.txt
。创建文件后,它会运行osascript
(基本上是AppleScript)来关闭Sketchup中的所有窗口,然后通过创建~/temp/conf.txt
文件来表示窗口已关闭。
以下是客户端代码(可放置在Sketchup插件中),表示更接近的脚本:
def wait(f)
while !File::exists?(f)
end
File.delete(f)
end
def signal(f)
File.new(f, 'w').close
end
def close_file
signal('~/temp/mutex.txt')
wait('~/temp/conf.txt')
end
close_file
向较近的脚本发出信号,然后在返回之前等待确认文件已关闭。现在,您可以在Sketchup中关闭文件。
答案 2 :(得分:0)
你可以使用applescript和/或Automator为SketchUp做很多事情。
tell application "SketchUp"
activate
tell application "System Events"
delay 1.0 --close window, adjust delay to suit
--key code 13 using command down -- Press ⌘W or you can use
keystroke "w" using command down
end tell
告诉
我有许多状态栏项目用于打开新的,粘贴到控制台,关闭,杀死SU等。
它们是触发SU快捷键的小文件,可以在“Ruby控制台”外部使用,也可以作为插件的一部分使用。
我不确定你试图实现什么样的'批量转换',但是 我今天使用Automator将我的大部分旧版v5,V6,v7文件转换为v8 ... 其中100个, 并且您可能知道,在打开时,您会收到“警告”警告,保存会将文件转换为最新版本(这就是我想要的)。
以编程方式单击此“确定”非常棘手。
它自己的Automator是非常有限的,但你可以在工作流程中添加一个AppleScript,我发现如果你使用它的'记录功能'来演示你需要做什么。
然后,您可以将该代码复制/粘贴到“脚本编辑器”中,删除“dowithTimeout”位,将其复制回工作流程,任何一方都有延迟并让它运行。
我不得不玩延迟,以容纳一些较大的文件,但取得了> 95%的成功。 [成功选择全部,右键单击,创建图标和预览。]
不幸的是,我随后将工作流分类,但如果你想看看,可以重新创建它。
答案 3 :(得分:0)
成功,在Ruby控制台中
system("osascript -e 'tell application \"suoff\"' -e 'activate' -e 'end tell'")
这个脚本位于应用程序文件夹中的Automator.app ....
on run
-- Make sure SU is foremost, don't click on anything else either
tell application "System Events"
tell process "SketchUp"
set frontmost to true
-- gives a message if you try to select when SU's not running
delay 0.2
tell application "SketchUp" to quit saving no
-- no dialog box etc...
delay 0.1
end tell
end tell
end run
问题是SU有一个反自毁的红宝石,它可以挖掘任何链接的文件并中止所有关闭它的工作......从内部开始。
所以你需要埋葬它......
此组合适用于10.5.8与SU8.1。
如果你看看SketchUcation [开发者]论坛,我就打电话给mac / applescript测试人员......从那时起我就重写了应用程序但如果你PM我,我会给你发一份所有的我工作的那些......
约翰
答案 4 :(得分:0)
我不得不使用批处理脚本转换数百个.skp文件。我遇到了类似的问题,因为每次我打开一个新文件时,它始终保持打开状态。对我来说,关闭active_model
就足够了,文件也随之而来。
SketchUp 2019 Pro Mac OS X版本确实如此。
model = Sketchup.active_model
model.save(filename, Sketchup::Model::VERSION_2015)
model.close
希望这会有所帮助