Войти
Sergei ShaykinСтатьи

Основы плагиностроения к 3D Studio MAX. (2 стр)

Автор:

Plug-in'ы, которые являются утилитными в Max'е, все являются объектами классов порождённых от класса UtilityObj. UtilityObj объявлен в utilapi.h и имеет всего несколько методов. Разработчик создаёт свой класс, порожденный от UtilityObj:

class MyUtility : public UtilityObj
{
  //...
};

В Max'е все утилитные plug-in'ы, как объекты создаются один раз во время загрузки. То есть может существовать только один экземпляр объекта для каждой утилиты. Поэтому этот объект делают глобальным для файла plug-in'а. (Для большинства других типов plug-in'ов это не верно. Например, для модификаторного plug-in'а может существовать множество копий класса модификатора. Для утилит в этом нет необходимости.):

MyUtility theMyUtility;

Базовый класс UtilityObj является виртуальным и имеет пять методов, три из них разработчик должен реализовать в своём порожденном классе. Рассмотрим их.

Виртуальный метод DeleteThis(). Этот метод встречается во многих классах SDK. Он вызывается Max'ом для того, чтобы удалить объект класса plug-in'а. Max пользуется методами виртуальных классов, поэтому он не может просто удалить объект, например оператором delete, потому что попросту не вызовется деструктор для порожденного класса. Тем более, этот объект создаётся в другом модуле (в DLL), то есть, и удаляться он должен там же. Поэтому, если разработчик создаёт свой объект, например, оператором new, то он может в реализации метода DeleteThis() поместить код удаления: delete this;. Но в нашем случае в этом нет необходимости, так как наш объект является глобальным, он автоматически удалится во время выгрузки DLL plug-in'а.

Другие два метода, которые должен предоставить разработчик, связаны друг с другом. Они касаются панели с элементами управления (controls).

Изображение

Это обычное диалоговое окно, которое появляется в панели управления (MAX Control Panel).

Метод BeginEditParams() вызывается Max'ом в тот момент, когда пользователь включает вашу утилиту, здесь вы подготавливаете диалоговую панель и показываете её в панели управления. Второй метод EndEditParams() вызывается, когда пользователь закончил работу с вашей утилитой. Здесь нужно удалить диалог из панели управления.

Для работы с интерфейсом Max'а есть специальный класс, который так и называется class Interface. Этот класс содержит огромнейшее количество методов, которыми вы можете пользоваться. В данном случае он нам нужен для работы с панелью управления. Указатель на объект класса Interface вы получаете, как аргумент в методы BeginEditParams() и EndEditParams(). Чтобы добавить диалог в панель управления используется метод AddRollupPage() класса Interface, соответственно, чтобы удалить — DeleteRollupPage(). Под вашу панель вы используете обычный диалоговый ресурс. Диалог должен иметь определённый стиль окна. А именно:

Style: child
Border: None

Ширина панели должна быть 108 единиц. Высота — любая. Не забудьте выставить Visible.

Поскольку, панель является обычным диалоговым окном, необходимо предоставить функцию, обрабатывающую сообщения, получаемые этим диалогом, как обычно в Windows-программировании:

BOOL CALLBACK MyUtilityDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

Так как высота панели может быть любая, то вся панель может не помещаться на экране. В Max'е вы можете просто тянуть эту панель вверх или вниз, чтобы просмотреть недоступные участки. Эта возможность тоже реализуется через класс Interface. Вы должны вызвать метод RollupMouseMessage(), когда обрабатываете сообщения от мыши, а именно сообщения WM_LBUTTONDOWN, WM_LBUTTONUP и WM_MOUSEMOVE.

Ниже представлен листинг файла MyUtility.h, где мы просто включаем нужные заголовочные файлы и объявляем функцию GetString(), достающую строку из ресурсов (см. пред. часть урока), и переменную hInstance модуля DLL.

// файл MyUtility.h
#ifndef __MYUTILITY__H
#define __MYUTILITY__H

#include "Max.h"
#include "resource.h"
#include "istdplug.h"
#include "iparamb2.h"
#include "iparamm2.h"

#include "utilapi.h"

extern TCHAR *GetString(int id);

extern HINSTANCE hInstance;

#endif // __MYUTILITY__H

Теперь посмотрим на следующий листинг, где реализовано всё то, о чем мы говорили в этой части урока.

// файл MyUtility.cpp

#include "MyUtility.h"

// основной класс plug-in'а
class MyUtility : public UtilityObj
{
  public:
    // hPanel используется для хранения HWND панели
    HWND  hPanel;
    // ip - указатель на интерфейс Max'а
    Interface *ip;
    
    // Обязательные методы из базового класса UtilityObj
    void BeginEditParams(Interface *ip,IUtil *iu);
    void EndEditParams(Interface *ip,IUtil *iu);
    void DeleteThis() { }    
};

// глобальный объект класса plug-in'а
MyUtility theMyUtility;

// стандартный обработчик окна диалога
BOOL CALLBACK MyUtilityDlgProc(HWND hWnd, UINT msg,
                               WPARAM wParam, LPARAM lParam)
{
  switch (msg) {
    case WM_INITDIALOG:
      break;
    case WM_DESTROY:
      break;
    case WM_COMMAND:
      break;
    // поддержка прокрутки панели
    case WM_LBUTTONDOWN:
    case WM_LBUTTONUP:
    case WM_MOUSEMOVE:
      theMyUtility.ip->RollupMouseMessage(hWnd,msg,wParam,lParam); 
      break;
    default:
      return FALSE;
  }
  return TRUE;
}

// реализация методов класса MyUtility

void MyUtility::BeginEditParams(Interface *ip,IUtil *iu) 
{
  // запоминаем указатель для последующего использования
  this->ip = ip;
  // добавляем панель. функция возвращает HWND окна диалога,
  // IDD_PANEL - идентификатор ресурса диалога.
  hPanel = ip->AddRollupPage(
    hInstance,
    MAKEINTRESOURCE(IDD_PANEL),
    MyUtilityDlgProc,
    GetString(IDS_PARAMS),
    0);
}

void MyUtility::EndEditParams(Interface *ip,IUtil *iu) 
{
  this->ip = NULL;
  // удаляем панель
  ip->DeleteRollupPage(hPanel);
  hPanel = NULL;
}

Как указать Max'у на наш plug-in, мы рассмотрим в следующей части урока.

Страницы: 1 2 3 Следующая »

#3D Studio MAX, #plug-in, #плагины, #экспорт

13 июля 2001 (Обновление: 14 мая 2013)

Комментарии [14]