1

Google SketchUp的Ruby API有一个函数open_file,但我找不到close_file函数。由于我必须批处理许多文件,因此我想在继续下一个文件之前关闭每个文件,否则程序将因内存耗尽而崩溃。

以编程方式关闭 SketchUp 文件的最佳方法是什么?

我正在使用 Mac OS X 并且愿意使用 AppleScript 函数来指示窗口关闭。

编辑

我正在考虑一些迄今为止被证明没有结果的方法。

  1. 本问题所述,使用 appscript Ruby gem 。这里的问题是我无法让 SketchUp 识别我安装的 gems
  2. 同样,我正在尝试使用osascript(一个从 shell 执行 AppleScripts 的 bash 程序)来关闭窗口。也就是说,我使用以下方法之一从 SketchUp 的 Ruby 控制台窗口调用 shell:

    %x[osascript -e '告诉应用程序“SketchUp”关闭窗口 1']

    %x[osascript -e '告诉应用程序“SketchUp”关闭窗口 1' &]

    %x[osascript -e '告诉应用程序“SketchUp”关闭每个窗口']

    %x[osascript -e '告诉应用程序“SketchUp”关闭每个窗口'&]

    每当我尝试第二种方法时,SketchUp 就会冻结。但是,当我 从 IRB 或直接从 SketchUp 外部的 Bash 提示符执行任何这些命令时,我会得到所需的行为:模型窗口关闭(顺便说一下,R​​uby 控制台窗口保持打开状态,这很好)。

  3. 有一个主脚本,它启动一个从脚本来处理每个模型。在主设备等待期间,从设备将在 Google SketchUp 程序中运行。从站完成后,它会向主站发出信号,然后主站关闭 SketchUp 文件。为了进行这种进程间通信,我尝试使用drb。但是,当我尝试drb在 SketchUp 中请求时,我收到以下消息:

错误:LoadError: (eval):5:in 'require': no such file to load -- drb

编辑 2

有一个单独的进程持续运行,在收到信号时使用 AppleScript 关闭 Google Sketchup 窗口,这是很笨拙的,原因有很多。首先,必须有一个单独的进程专门用于关闭 Sketchup 窗口,这很难看。其次,与外部脚本通信的唯一有效方式是通过创建文件,这很浪费,而且磁盘访问可能会减慢速度。

然而,最严重的问题是 Sketchup 对 AppleScript 命令的响应速度很慢。我有一个在 Sketchup 中运行的计算密集型脚本,它似乎使 AppleScript 响应饿死,这意味着 osascript 在窗口关闭之前超时。当 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

这种修改是一种改进。它纠正了 EDIT 2 中提到的“最严重的问题”,但其他问题仍然存在。

4

5 回答 5

2

There is an important limitation with using an external AppleScript to force SketchUp to do something. SketchUp will not accept any user input while a menu script is running.

I found this out trying to setup an automated rendering solution. I added a menu item which opens a WebDialog to get a list of models to download from a server. It then steps through the list and uses cURL to download each model. Once downloaded it loads the model, renders it out, uploads the images using cURL again, and goes to the next model.

What I wanted was to activate the AppleScript after each model is rendered (using the "mutex" file solution shown above) and have it close the model window. Unfortunately, since the menu script is still running, SketchUp will not respond to anything the AppleScript tells it to do. Only once all of the models have been processed and the menu script exits, will the AppleScript finally run.

This would not be so bad if all of the calls to the AppleScript were queued up, but they aren't. It seems that only the last two get honored (that number may be just an accident dependent on the timing of when my calls to the AppleScript were made relative to when the menu script finished).

Because of this limitation, I was not able to use the mutex wait() function in my menu Ruby code. Since the AppleScript was not able to execute, it never created its "I'm done" mutex file, and therefore the wait() function in Ruby never got the signal that it could continue. The result was a deadlock between AppleScript and SketchUp, such that SketchUp just freezes up (well, actually it is just stuck in a really tight loop in the wait() function).

So, when approaching this problem, think of AppleScript as a cleanup tool you can call when all of your processing is done.

于 2011-08-20T23:02:57.073 回答
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% 的成功。【成功可以全选,右键,创建图标,预览。】

不幸的是,我随后将工作流程分箱,但如果您想看看,可以重新创建它。

于 2011-02-21T01:44:48.147 回答
0

一种解决方案是让一个单独的进程持续运行,在收到信号时使用 AppleScript 关闭 Google Sketchup 窗口。此处描述的方法使用文件进行进程间通信(drb 似乎不起作用)。

首先,您必须确保 Sketchup支持 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 中关闭文件。

于 2011-02-14T08:08:31.760 回答
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 我,我会向您发送我所有位的开放副本有工作了..

约翰

于 2011-02-26T04:34:59.807 回答
0

我不得不使用批处理脚本转换数百个 .skp 文件。我遇到了类似的问题,因为每次我打开一个新文件时它都保持打开状态。对我来说,关闭文件就足够了active_model

这适用于 SketchUp 2019 Pro Mac OS X 版本。

model = Sketchup.active_model
model.save(filename, Sketchup::Model::VERSION_2015)
model.close

希望它会有所帮助

于 2020-05-04T15:00:03.607 回答