【问题标题】:Google SketchUp close file谷歌 SketchUp 关闭文件
【发布时间】:2011-02-13 03:36:14
【问题描述】:

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 '告诉应用程序“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。但是,当我尝试在 SketchUp 中要求 drb 时,我收到以下消息:

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

【问题讨论】:

    标签: ruby macos api sketchup


    【解决方案1】:

    使用外部 AppleScript 强制 SketchUp 执行某些操作有一个重要限制。 SketchUp 在菜单脚本运行时不会接受任何用户输入。

    我在尝试设置自动渲染解决方案时发现了这一点。我添加了一个菜单项,它打开一个 WebDialog 以获取要从服务器下载的模型列表。然后它会逐步浏览列表并使用 cURL 下载每个模型。下载后,它会加载模型、渲染模型、再次使用 cURL 上传图像,然后转到下一个模型。

    我想要的是在渲染每个模型后激活 AppleScript(使用上面显示的“互斥”文件解决方案)并让它关闭模型窗口。不幸的是,由于菜单脚本仍在运行,SketchUp 不会响应 AppleScript 告诉它做的任何事情。只有在处理完所有模型并退出菜单脚本后,AppleScript 才会最终运行。

    如果所有对 AppleScript 的调用都排队等候,这不会那么糟糕,但事实并非如此。似乎只有最后两个得到了尊重(这个数字可能只是一个意外,取决于我对 AppleScript 的调用相对于菜单脚本完成的时间)。

    由于这个限制,我无法在我的菜单 Ruby 代码中使用 mutex wait() 函数。由于 AppleScript 无法执行,因此它从未创建过“我完成了”互斥文件,因此 Ruby 中的 wait() 函数从未收到可以继续执行的信号。结果是 AppleScript 和 SketchUp 之间出现了死锁,以至于 SketchUp 只是冻结了(实际上它只是卡在 wait() 函数中的一个非常紧密的循环中)。

    因此,在处理此问题时,请将 AppleScript 视为您可以在所有处理完成后调用的清理工具。

    【讨论】:

      【解决方案2】:

      一种解决方案是让一个单独的进程持续运行,该进程将在收到信号时使用 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 中关闭文件了。

      【讨论】:

        【解决方案3】:

        您可以使用 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% 的成功。 [成功可以全选,右键,创建图标,预览]

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

        【讨论】:

        • 我使用 AppleScript Editor 将您的脚本保存在一个名为 /temp/closeWindow.scpt 的文件中。然后我尝试在 Sketchup 中运行%x[osascript /temp/closeWindow.scpt],Sketchup 冻结了。您正在运行什么版本,可以在 Sketchup 的 ruby​​ 控制台中执行关闭窗口的 AppleScript?
        【解决方案4】:

        成功,在 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 我,我会向您发送所有内容的开放副本我已经开始工作了..

        约翰

        【讨论】:

        • 这听起来很有希望。您可以发布开发者论坛帖子的链接吗?
        • 希望这行得通-link
        【解决方案5】:

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

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

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

        希望对你有帮助

        【讨论】:

          猜你喜欢
          • 2011-10-29
          • 1970-01-01
          • 2021-10-16
          • 2015-04-27
          • 1970-01-01
          • 1970-01-01
          • 2012-05-28
          • 1970-01-01
          • 2014-12-31
          相关资源
          最近更新 更多