Экспортёр для XSI

В свете последних тенденций борьбы с пиратством да и просто исходя из экономии денег (или их отсутствия), стало очень актуально переходить с мегадорогих пакетов разработки на что-то более дешёвое. Поэтому было решено написать плагин не для 3DMax или Maya, а для менее популярного XSI, но зато более финансово доступного.

Оказалось что всё очень даже неплохо. С версии 6 (судя по документации), данная среда поддерживает плагины, написанные на C#, а писать на нём подобные вещи – неописуемое удовольствие. Замечу, что написание и отладка базовой функциональности у меня заняла один день, правда пришлось выключить ICQ, IRC и браузер.


Итак, отправной точкой будет установка XSI – проблем с этим возникнуть не должно.
Чем данное приложение хорошо, так это тем, что оно умеет сгенерировать заготовку проекта на том языке, который мы выберем. Такой себе визард, но не в студию встроенный, а в XSI. Поэтому, чтобы облегчить себе жизнь – сгенерим заготовку для проекта на C#

Создание проекта

Запускаем среду, и в ней запускаем plugin manager (File->Plugin Manager). Выбираем закладку plugins, и жмём кнопку new, всплывет предложение выбрать тип плагина, я выбрал command, так как нам нужна кнопка, на которой будет слово “Export to gameformat”. Нам предложат кастомизировать проект – лучшее место для того, чтобы правильно назвать кнопочку, которая будет отвечать за экспорт и выбрать её местоположение в иерархии кнопок среды. Для того, чтобы она лежала в разделе File->Export нам нужно указать значение параметра Add to menu равным siMenuMainFileExport
Дальше вносим параметры по усмотрению и жмём кнопку Generate Code.
После этого запускаем студию, открываем полученный проект и начинаем программировать.

Программирование

XSI API не вызывает дикого отторжения, в отличие от некоторых других, и по началу вообще выглядит очень здорово. Но как и везде – находятся свои подводные камни, которые усложняют нашу жизнь.

Нам предоставляют три основных объекта

CXSIApplicationClass m_xsi;
CXSIFactoryClass m_fact;
CXSIUtilsClass m_utils;

При помощи которых можно получать доступ ко всем внутренностям. Есть, правда, ещё один класс, который нам заботливо забыли подсунуть при генерации проекта – это CXSIUIToolkitClass, штука, позволяющая получить доступ к пользовательскому интерфейсу. В нашем случае – это вызов диалогового окна, которое спросит у пользователя имя файла, в который он хочет экспортировать свою мега модель.
Использование выглядит приблизительно так:


CXSIUIToolkitClass toolkit = new CXSIUIToolkitClass();

FileBrowser fb = toolkit.FileBrowser;

fb.DialogTitle = “Select file to save model”;
fb.InitialDirectory = @”c:\”;

fb.ShowSave();

UberModelSerializer serializer = new UberModelSerializer(fb.FilePathName);

Дальше нам понадобится сцена, которую мы хотим экспортировать, и тут нам пригодится объект класса CXSIApplicationClass, у которого есть в наличии аксессор ActiveSceneRoot


CXSIApplicationClass xsi = new CXSIApplicationClass();
serializer.Serialize(xsi.ActiveSceneRoot);

Объекты, которые нарисовал художник являются детьми сцены, при чём в прямом смысле, поэтому доступ к ним мы получаем через scene.Children, замечу, что среди них ещё будет замешан источник освещения и камера.
Доступ к основным свойствам объекта получить вроде бы просто, но именно здесь нас ожидает первый камешек.
Т.к. физические свойства лежат в “разделе” Kinematics, то и мы пытаемся их извлечь оттуда.


obj.Kinematics.Global.Parameters[“posx”]

Вот так вот у нас должны извлечься глобальные координаты, но не тут-то было, мы получим некий com_object. Чтобы получить числовое значение, нам надо сделать вот так:


float.Parse( obj.Kinematics.Global.Parameters[“posx”].get_Value(0).ToString() )

Вот теперь в наших руках есть нормальное значение.
Ещё у объектов бывают custom параметры – параметры, которые пользователь сам задал, они извлекаются следующим образом:


obj.Properties[“CustomPSet”].Parameters[“speed”].get_Value(0).ToString()

Замечу, что при извлечении параметров, да и вообще во всех случаях нужно учитывать возможность того, что параметра или свойства может не существовать, в таком случае мы напоремся на ArgumentNullException и плагин бесшумно прекратит работу, поэтому нужно уделить внимание валидации значений. XSI при получении необработанного исключения просто тушит выполнение плагина.

Отладка

Отлаживать наш плагин очень легко и удобно. Нам нужно загрузить плагин в XSI, и студией подключиться к процессу, при этом порядок выполняемых действий не играет роли.
Загрузка плагина осуществляется следующим образом: В XSI открываем plugin manager, у нас будет открыта первая же закладка – Tree, жмём кнопку Load и выбираем DLL, которая получилась после сборки нашего проекта в студии.
Подключаемся к процессу XSI вот так: в студии жмём debug->Attach to process, в списке ищем XSI.exe и подключаемся к нему. Студия перейдёт в режим отладки – время расставлять breakpoints и готовиться читать debug log.
После того, как мы отладимся или поймём, что надо вносить изменения – отсоединяемся от процесса и выгружаем плагин из XSI. К счастью для того, чтобы сделать последнее нам не надо перегружать всю среду. Достаточно всё в том же менеджере плагинов в разделе tree выбрать наш и в контекстном меню, которое появляется по нажатию правой кнопки мыши нажать unload.
Сделать это нужно для того, чтобы среда отдала доступ к файлу, т.к. без этого компиляция закончится неудачей – студия не сможет записать новую DLL поверх старой.

Similar Posts

  • Сумбур

    Что-то давно не писал я, мысли вроде бы появляются, но потом хлоп – и нету 🙂 Съездил на праздники к бабушке в Ульяновку, что в 250 км от Киева. Прикольно там, спокойно, компов практически нету. С другой стороны, делать там, по большому счету, нечего. Вот народ и спивается потихоньку, или женится. Для меня было несколько…

  • Навеяно слонменами и бетменами

    Народ, если вы знаете, что бедмена нету, то почему вы решили, что все остальное должно существовать на самом деле? Откуда идет гон на то, что таких костюмов не существует, машины так не прыгают, а телки тают от одного взгляда? ЗЫ: Ну и мысли с бодуна 🙂 Share this post: Share on X (Twitter) Share on…

  • Luabind bugs and fixes

    Сегодня утром на меня возложилась задача перевести проект на рельсы нового буста 1.33. Это не было бы большой проблемой, если бы не луабинд, который с ним не дружит. Во всяком случае версия, лежащая на их сайте, пришлось выкачать из CVS последнюю ревизию и скомпилировать у себя. С этим проблем не было. Проблемы начались, когда я…

  • Октоберфест, Киев

    Вчера ходили на вариацию Октоберфеста, которую проводят в Киеве. Идя туда было ощущение, что приду, посмотрим чего там такого и пойдем куда-нить в другое место. Внутри оказалось на удивление интересно, играла заводная ирландская музыка, бегали “немецкие” мальчики и девочки и царила довольно праздничная атмосфера. Самым большим позитивом были столы – под обоими тентами почти все…

  • Чуток наболело (С++)

    Давно я, что-то не постил ничего 🙂 Вот читаю я разные форумы, каналы чатов и возникает у меня вопрос – почему так много людей зациклились на С++? Это отличный язык для решения своих задач, но когда на нём начинают извращаться метапрограммированием, или пишут адские обёртки, обвязки для типа Pure OOP – зачем? Если очень хочется…