Google SketchUp关闭文件

时间:2011-02-13 03:36:15

标签: ruby macos api sketchup

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

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

我使用的是Mac OS X,我愿意使用AppleScript函数来指示窗口关闭。

修改

到目前为止,我正在考虑一些已证明无效的方法。

  1. 使用appscript Ruby gem,如this question中所述。这里的问题是I cannot get SketchUp to recognize my installed gems
  2. 以类似的方式,我试图使用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控制台窗口保持打开状态,很好)。

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

  4.   

    错误: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中提到的“最严重的问题”,但其他问题仍然存在。

5 个答案:

答案 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

希望这会有所帮助