Pull to refresh

Пишем плагин для Google SketchUp

Reading time5 min
Views26K
Google SketchUp — программа для быстрого создания и редактирования трёхмерной графики. Удобство и простоту SketchUp оценят, как начинающие работу с трёхмерным моделированием, так и профессионалы.

Но не все знают, что SketchUp обладает мощным API, с помощью которого можно создавать модули, добавляя в программу новый функционал. В этом посте я попытаюсь объяснить общие принципы архитектуры SketchUp и процесс разработки плагина. Перед написанием нового велосипеда плагина стоит поискать на сайте Sketchucation уже готовые реализации с необходимой для Вас функциональностью. Найдя подходящий плагин с открытым исходным кодом, можно реализовать требуемый функционал, оставив основную часть кода нетронутой. Например, плагин делает какие-то расчеты и построения, а вы только изменяете их применение или визуализацию.

Плагины для SketchUp пишутся на языке Ruby.

На Google Code представлена официальная документация по разработке. Она состоит из 3 разделов: Introduction, Quick Reference и Object Reference.

1) Introduction – вводный раздел, в котором показан пример создания простого плагина.
2) Quick Reference – справочный раздел по классам, методам.
3) Object Reference – справочный раздел по объектной модели SketchUp. Объектная иерархия очень удобно разбита по группам, что позволяет быстро искать необходимые для написания кода классы.

Пример разработки плагина я возьму из собственной практики. Для удобства работы требовался дополнительный функционал, отсутствующий в SketchUp. Задача состояла в быстром и удобном определении размеров объекта (ширина, высота, толщина). Готовый плагин с данной функциональностью был найден — GetDimensions, но у него был большой минус: он показывал размеры в MessageBox’e, который необходимо было постоянно закрывать, что создавало определенное неудобство. Я решил исследовать его код и изменить вывод результата.

Код плагина GetDimensions:

require 'sketchup.rb'
def get_dimensions
  model = Sketchup.active_model
  mname = model.title
  Sketchup::set_status_text(("GET COMPONENT DIMENSIONS..." ), SB_PROMPT)
  Sketchup::set_status_text(" ", SB_VCB_LABEL)
  Sketchup::set_status_text(" ", SB_VCB_VALUE)
  boundingBox = model.selection[0].bounds
  dims = [ boundingBox.height,
     boundingBox.width,
     boundingBox.depth ]
  dims.sort!

  UI.messagebox("Thickness: " + dims[0].to_s + "\nWidth: " + dims[1].to_s +"\nLength: " + dims[2].to_s)
end

if( not file_loaded?("GetDimensions.rb") )
  add_separator_to_menu("Plugins")
  UI.menu("Plugins").add_item("Get Dimensions") { get_dimensions }
end

file_loaded("GetDimensions.rb")


* This source code was highlighted with Source Code Highlighter.


Код состоит из логики плагина (get_dimensions), добавления пункта меню (Plugins -> Get Dimensions) и загрузка самого файла плагина в систему (GetDimensions.rb).

Для установки, плагин необходимо скопировать в директорию “C:\Program Files\Google\Google SketchUp\Plugins\”, а программа автоматически подгрузит все скрипты из этой папки при запуске.

Главным объектом, хранящим в себе структуру рисунка, является model.

В данном плагине берется первый выделенный объект и его размеры. Размеры сортируются в порядке возрастания и показываются в MessageBox’е, а в панели состояния отображается название плагина.

Панель состояния меня сразу заинтересовала, и я решил перенести в нее вывод полученных размеров.

После небольшой модификации плагина мне удалось этого достичь:

def get_dimensions
  model = Sketchup.active_model
  entities = model.entities
  boundingBox = model.selection[0].bounds
 
  dims = [ boundingBox.height,
         boundingBox.width,
         boundingBox.depth ]
  dims.sort!
 
  Sketchup::set_status_text(("Thickness: " + dims[0].to_s + ". Width: " + dims[1].to_s + ". Length: " + dims[2].to_s ), SB_PROMPT)
end


* This source code was highlighted with Source Code Highlighter.


После выбора элемента, с помощью инструмента Select, выбираем в меню команду Get Dimensions. В результате на панели состояния будут отображаться размеры выбранного элемента. Для более удобного вызова команды следует назначить горячую клавишу.

Get Dimensions Result

Следующим шагом было сделать так, чтобы размеры автоматически показывались при выделении объекта. В голову пришло два варианта: сделать свой инструмент, который бы выделял элементы как инструмент Select, но при этом показывал внизу размеры, либо модифицировать инструмент Select, что бы он при выделении показывал размеры объекта.

После поиска по Object Reference, родилась идея реализации второго способа.
Как оказалось, с помощью Observer Classes -> SelectionObserver можно подписаться на события инструмента Select.

После модификации логика плагина была разнесена на два файла:

Dimensions_load.rb

require 'sketchup.rb'
require 'Dimensions/GetDimensions.rb'

$PluginMenuName = "Tools"
$DimensionsMenuName = "Dimensions Tool"
$GetDimensionsMenuItem = "Get Dimensions"
$AutoDisplayMenuItem = "Auto Display Dimensions"

if(not file_loaded?("dimensions_load.rb"))
  pluginMenu = UI.menu($PluginMenuName)  
  dimensions = Dimensions.new  
  pluginMenu.add_separator
  getDimensionsSubMenu = pluginMenu.add_submenu($DimensionsMenuName){}
  getDimensionsSubMenu.add_item($GetDimensionsMenuItem){dimensions.get_selection_dimensions}  
  autoDisplayItem = getDimensionsSubMenu.add_item($AutoDisplayMenuItem){dimensions.connect_observer}
  getDimensionsSubMenu.set_validation_proc(autoDisplayItem){dimensions.menu_checked}
end

file_loaded("dimensions_load.rb")


* This source code was highlighted with Source Code Highlighter.


GetDimensions.rb

require 'sketchup.rb'
class Dimensions < Sketchup::SelectionObserver 
  def initialize()
    @usedObserver = false   
  end

  def onSelectionBulkChange(selection)
    get_dimensions(selection)
  end

  def get_selection_dimensions
    get_dimensions(Sketchup.active_model.selection)
  end

  def get_dimensions(selection) 
    boundingBox = selection[0].bounds
    dims = [ boundingBox.height,
    boundingBox.width,
    boundingBox.depth ]
    dims.sort!
    Sketchup::set_status_text(("Thickness: " + dims[0].to_s + ". Width: " + dims[1].to_s + ". Length: " + dims[2].to_s ), SB_PROMPT)
  end

  def connect_observer  
    if(@usedObserver) then
      return remove_observer
    else   
      return add_observer   
    end
  end

  def add_observer
    @usedObserver = true  
    Sketchup.active_model.selection.add_observer self 
    return MF_CHECKED
  end

  def remove_observer
    @usedObserver = false  
    Sketchup.active_model.selection.remove_observer self
    return MF_UNCHECKED
  end

  def menu_checked
    if(@usedObserver) then
      return MF_CHECKED
    else   
      return MF_UNCHECKED   
    end  
  end
end

file_loaded("GetDimensions.rb")


* This source code was highlighted with Source Code Highlighter.


Рассмотрим код подробнее.

Для того, чтобы иметь возможность перехватывать события инструмента Select, необходимо наследоваться от класса SelectionObserver, переопределить у себя метод onSelectionBulkChange(selection), который будет вызываться при выделении объектов, и подписаться на события с помощью Sketchup.active_model.selection.add_observer.

Плагин был перемещен в меню Tool -> Dimensions Tool, которое содержит два подпункта: Get Dimensions и Auto Display Dimensions.

Как я уже говорил ранее, задача плагина сводилась к отображению параметров объекта автоматически при его выделении. Т.к. дополнительный функционал не всегда нужен, решено было сделать его отключаемым. Auto Display Dimensions — позволяет включать его в нужный момент, а Get Dimensions – вызов плагина по запросу — был оставлен для большей гибкости использования.

Get Dimensions Menu

Исходный код плагина.

Как видите, модернизирование существующего плагина намного проще, чем писание его с нуля. Кстати, я впервые писал код на Ruby, но благодаря большому опыту программирования, понять синтаксис не составило труда.

Желаю всем удачи в написании собственных плагинов для SketchUp.
Tags:
Hubs:
Total votes 44: ↑40 and ↓4+36
Comments4

Articles