Антон АксёновФорум

Delphi 3DSMAX SDK for export plugin, экспортный плагин к 3DSMAX8 на Delphi (комментарии) (4 стр)

Страницы: 1 2 3 4 5 6 Следующая »
#45
12:30, 17 июля 2008

ПЗ
>Да нифига ты реальный "боевой" плагин на делфи через c++ посредника не сможешь писать.
Да, спорить не могу - еще не писал плагин "реальный боевой". Однако, в примере вполне рабочий плагин, который экспортит всё как надо, всё 1:1 как в максе. Анимации в этом плагине нет, но экспортить её можно - посмотри описание возможностей (да и в плагине она выгружается в текстовом виде).
Короче, к вопросу сможешь/не сможешь я готов вернуться через пол-года, когда продолжу писать свой двиг :) Сильно сомневаюсь что буду что-то переделывать в существующем, правда. А вот из дописывания - наверно с шойдерами что-то надо будет сделать, вроде в максе есть такой модификатор. Однако, я не позиционирую это SDK как профессиональную тулзу. Я хочу помочь начинающим Delphi программистам, которые решили написать что-то своё и уткнулусь в проблему экспорта из макса. А для начинающего этого SDK за глаза. Если хочешь - можем продолжить спор в направлении "это SDK фигня, там нет того-то того-то того-то" - я почерпну для себя много инфы ;)

>Подключение лишней DLL, переадресация вызовов, получение указателей на внутренние процедуры и т.д. – все это время, память и ресурсы.
Еще раз утверждаю - это всё фигня :) Это не время, это не память, это не ресурсы - это ничто для современных (и не очень) компов. :)

>По нынешним мощностям конечно не существенно,
ну и я о чем, если сам понимаешь - что заладил-то - "затраты, затраты"?

>но стилистически не очень красиво.
К чёрту стилистику - это 100% стабильно работает, причем вся т.н. "некрасивость" от впечатлительных идеалистов-программистов спрятана - на дельфи всё мягко и пушисто (что и требовалось).

>Посему, согласись, куда заманчивее было бы написать целиком всю DLL на пасе. Попробовать хотя бы стоит.
Соглашусь что заманчиво, но не из-за твоих доводов, а просто из-за того что работы системному программеру вроде как меньше - для прикладника один фиг одианоково будет выглядеть.
Хоть *vmr уверен что это всё утопия, я бы попробовал. Времени только вот нет, к сожалению.

#46
20:57, 18 июля 2008

Vmr*: Оценил остроумие. А по делу есть мысли? Я не могу позвонить в автодеск и попросить их импортировать методы моего плагина как обычные функции.

Coriolis: Начинающему программисту на Delphi ты поможешь только тем, что заставишь его учить С++. Первое, с чего надо начинать написание «боевого» плагина – изучить исходники твоего SDK. Потом ставить студию и начинать затачивать их под себя. Если возможно написать все одной DLL на одном Delphi, почему бы не попробовать? Если мы убедимся, что это невозможно, тогда пойдем дальше. Одна DLL хуже чем две?
Есть предложение отказаться от терминов «наезд» и т.п. Я сюда не пиписьками меряться пришел и наезжать ни на кого не собираюсь. У меня тоже мало времени. На работе комп запаролен и программировать на нем нельзя. А дома я бываю 2 часа в день и данным вопросом занимаюсь на интерес.

#47
22:38, 18 июля 2008

ПЗ
>возможно написать все одной DLL на одном Delphi, почему бы не попробовать?
Это будет похоже на взлом черного ящика....

Ты отталкиваешся от примитивных экспериментов на классах в три метода.... и удивляешся почему так не делают...
Побробуй сначала сделать какой-либо РЕАЛЬНЫЙ порт, сразу подобные желания отпадут....


Зачем писать порт на _недокументированный_ интерфейс (бинарное представление классов), когда есть хорошо изученная штука как С++?
Жалко лишней ДЛЛ-ки?

#48
16:34, 19 июля 2008

>Есть предложение отказаться от терминов «наезд» и т.п.
Да я ж так, по доброму :) Шутя.

>Начинающему программисту на Delphi ты поможешь только тем, что заставишь его учить С++. Первое, с чего надо начинать написание «боевого» плагина – изучить исходники твоего SDK.
Зачем ему исходняки СДК? Я же написал - новичку функционала за глаза. Ненужна ему студия.

#49
20:32, 21 июля 2008

>Зачем ему исходняки СДК?

Я на всякий случай напомню название твоей статьи: "Delphi 3DSMAX SDK for ...."

>Я же написал - новичку функционала за глаза

Очень спорное заявление.

>Ты отталкиваешся от примитивных экспериментов на классах в три метода....
Понится, кто-то тельняху рвал, что они не заработают.

>Зачем писать порт на _недокументированный_ интерфейс

Я пока не использовал ни одной недокументированной функции.

Очень жаль, что не получилось найти взаимопонимание. Конструктивные советы были бы куда полезнее. Ну что ж, может оно и к лучшему. Буду продолжать потихоньку эксперименты, авось куда выгребу...

#50
21:54, 21 июля 2008

ПЗ
>Понится, кто-то тельняху рвал, что они не заработают.
Oo

>Я пока не использовал ни одной недокументированной функции.
Ты использовал недокументированную VMT

>Конструктивные советы были бы куда полезнее
Но какой сдесь совет можно дать? :)

>Буду продолжать потихоньку эксперименты, авось куда выгребу...
А выгребеш ты бесценный опыт, да.  Но увы еще и потратиш уйму времени....

#51
11:15, 22 июля 2008

>>Зачем ему исходняки СДК?
>Я на всякий случай напомню название твоей статьи: "Delphi 3DSMAX SDK for ...."
Ты чего-то не понимаешь :) Еще раз спрашиваю - зачем пользователю моего SDK исходняки max SDK и ковыряние в них? Его плагин будет компилиться и работать и без SDK :) Из max SDK ему понадобится только справка.

>>Я же написал - новичку функционала за глаза
>Очень спорное заявление.
Ну дык оспорь :) А то просто так говорить все могут. :)

>Очень жаль, что не получилось найти взаимопонимание. Конструктивные советы были бы куда полезнее. Ну что ж, может оно и к лучшему. Буду продолжать потихоньку эксперименты, авось куда выгребу...
Я тебе имхо дал конструктивный совет - забей на вызов Delphi класса из cpp. Займись вызовом реализации Cpp класса из Delphi - это намного важней. И не принимай всё так в штыки.

#52
4:06, 24 июля 2008

Передо мной стоит задача написать полноценный плагин, для моделлеров (не игровых) занимающихся фотореалистичным рендером. Писать хочется на дельфи :). Но "чесать пяткой ухо", как было сказано выше, желания абсолютно не какого :).

Поэтому хотелось бы какнибудь поспособствовать решению задачи поставленной ПЗ, хоть и придется плагин на сипипи писать :(.

Мои контакты:
icq:278-110-470
мыло: venumsl {sobaаkaа] gmail ( toоchkaа } ком

#53
10:58, 24 июля 2008

Ну есессно, для фотореалистичного рендера этого СДК мало. :)

>Но "чесать пяткой ухо", как было сказано выше, желания абсолютно не какого :).
Да нормальный это способ блин, ничего извращенного. Всё что заявлено в статье - работает "на ура". Лишь бы словом ярким броситься блин.

#54
21:20, 24 июля 2008

Я именно Coriolis-SDK имел в виду. Не хотел больше докучать, но специально для нового интересанта, еще одна ремарка. То, что юзеру придется копаться в SDK Autodesk и так понятно, без этого вообще о каких плагинах речь? По Coriolis- SDK, если угодно, навскидку: DllEntry.cpp

 BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
{
  hInstance = hinstDLL;        // Hang on to this DLL's instance handle.

  if (!controlsInit) {
    controlsInit = TRUE;
    InitCustomControls(hInstance);  // Initialize MAX's custom controls
    InitCommonControls();      // Initialize Win95 controls
  }
  
  return TRUE;
}

Читаем хелп Autodesk`SDK на InitCustomControls – “This method has been deprecated. Plugins used to be required to call this method from their DllMain in order to initialize 3ds Max custom controls used by the plugin. Plugins no longer need to call this method from their DllMain or other code. The custom controls are initialized by 3ds Max automatically.”
Едем дальше - Required DLL Functions:

 BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved) {
    switch(fdwReason) {
        case DLL_PROCESS_ATTACH:
            hInstance = hinstDLL;
            DisableThreadLibraryCalls(hInstance);
            break;
    }
    return(TRUE);
} 

Без вызова DisableThreadLibraryCalls Coriolis`s SDK-Proxy-Dll-Plugin в двух попытках из трех вызывает крэш 3ds при загрузке. У меня, по-крайней мере. И это только то, что всплыло сразу же, навскидку. А дальше, как и в любой уважающей себя программе (включая саму 3dsMAX), пойдут менее очевидные баги и усовершенствования, которые периодически будут всплывать и требовать устранения. Это нормально. Ненормально то, что для этого надо будет вникать в тонкости кода самой Proxy на С++ и держать под рукой соответствующий инструментарий. А тем временем, на выходе уже новая версия 3dsMAX и ее SDK, где вообще все может стать по-другому и опять придется править, менять, дополнять.

Я, тем временем, продолжаю опыты. Вчера, наконец, удалось сваять на Delphi PLUGIN.DLU, которую 3dsMAX заглатывает без Access Violation. Вместо ClassDesc2 пока возвращает nil. Следующая остановка – реализация ClassDesc2 на Delphi. Дежурная проблема на сегодня – как МАХ вызывает НЕВИРТУАЛЬНЫЕ методы объекта из DLL? Умные статьи по ООП, DLL и С++, вообще-то делать это запрещают! КАК?!
ЗЫ. К размышлению: http://www.citforum.ru/programming/delphi/vcpp_classes_in_delphi/

#55
21:41, 24 июля 2008

ПЗ, у тебя точно SDK к восьмой студии? Тестовый плагин (который в SDK в качестве примра) тестила куча народу - всё окей, никаких вылетов. Может ты намудрил где? Версия дельфи у тебя какая? Патч последний к SDK и на сам 3DSMax стоит?

Потом, код корый в DllEntry.cpp - сгенерила сама SDK, через вижуал студию.  Когда ставишь SDK в студии появляется такой тип проекта (с мастером создания) - 3dsMax export plugin.

Потом, это всё системные вещи, Delphi программер должен морочиться только на счет своего SuperFormat'а и структуры классов MaxStudio, как их подружить вместе.

PS за ссылку спасибо, оч интересно, тоже буду курить в эту тему.

#56
21:15, 5 авг 2008

Заинтересованным лицам. Требуется помощь для продолжения экспериментов.
1. За основу взят C++ -плагин http://www.gamedev.ru/users/wat/forum/?id=57426
2. Методом братьев Монгольфье, все лишнее выброшено за борт: LibClassDesc возвращает ClassDesc вместо ClassDesc2. Метод ClassDesc.Create возвращает NULL, все методы перегружены, в каждый вставлен MessageBox для контроля последовательности вызовов при загрузке плагина. Последовательность следующая:

ClassDesc.SuperClassID
ClassDesc.ClassID
ClassDesc.SuperClassID
ClassDesc.IsPublic
ClassDesc.ClassID
ClassDesc.ClassName
ClassDesc.Category
ClassDesc.InitialRollupState
ClassDesc.NumActionTables
=========================< Появление меню и окон 3dsMAX
ClassDesc.Category
ClassDesc.SuperClassID
ClassDesc.ClassID
ClassDesc.ClassName
ClassDesc.ClassName
ClassDesc.InternalName
ClassDesc.InternalName
ClassDesc.InternalName
ClassDesc.Category
ClassDesc.Category
ClassDesc.Category
=========================< Окончание загрузки 3dsMAX

3. Из покдлючаемых библиотек (Project Options\Linker\Input) изъяты все библиотеки 3ds SDK и оставлен только стандартный COMCTRL32.LIB. MyUtilityClassDesc объявлен независимым, самостоятельным классом, НЕ НАСЛЕДУЕМЫМ от ClassDesc из SDK:

class MyUtilityClassDesc 
{
private:
    Tab<FPInterface*>    interfaces;                        
public:
  virtual void UnknownMethod1() {}
  virtual void UnknownMethod2() {}

  virtual ~MyUtilityClassDesc() {MessageBox(0,"ClassDesc.~ClassDesc","",MB_OK);}

  virtual int IsPublic()
  {
    MessageBox(0,"ClassDesc.IsPublic","",MB_OK);
    return 1;
  }

  virtual void * Create(BOOL loading = FALSE)
  {
    MessageBox(0,"ClassDesc.Create","",MB_OK);
    return NULL;//&theMyUtility;
  }
  int       BeginCreate(Interface *i) {MessageBox(0,"ClassDesc.BeginCreate","",MB_OK); return 0;}
  int       EndCreate(Interface *i) {MessageBox(0,"ClassDesc.EndCreate","",MB_OK); return 0;};

  virtual const TCHAR *  ClassName()
  {
    MessageBox(0,"ClassDesc.ClassName","",MB_OK);
    return "MyUtility"; 
  }

  virtual SClass_ID SuperClassID()
  {
    MessageBox(0,"ClassDesc.SuperClassID","",MB_OK);
    return UTILITY_CLASS_ID;
  }
  
  virtual CClassID ClassID()
  {
    MessageBox(0,"ClassDesc.ClassID","",MB_OK);
    return cid;//MYUTILITY_CLASS_ID;
  }



  virtual const TCHAR * Category()
  {
    MessageBox(0,"ClassDesc.Category","",MB_OK);
    return "Utility";
  }

   virtual BOOL      OkToCreate(Interface *i) {MessageBox(0,"ClassDesc.OkToCreate","",MB_OK); return TRUE; }
   virtual BOOL      HasClassParams() {MessageBox(0,"ClassDesc.HasClassParams","",MB_OK); return FALSE;}
   virtual void      EditClassParams(HWND hParent) {MessageBox(0,"ClassDesc.EditClassParams","",MB_OK);}
   virtual void      ResetClassParams(BOOL fileReset=FALSE) {MessageBox(0,"ClassDesc.ResetClassParams","",MB_OK);}
   virtual int          NumActionTables() {MessageBox(0,"ClassDesc.NumActionTables","",MB_OK); return 0; }
   virtual ActionTable*  GetActionTable(int i) {MessageBox(0,"ClassDesc.GetActionTable","",MB_OK); return NULL; }
   virtual BOOL IsManipulator() {MessageBox(0,"ClassDesc.IsManipulator","",MB_OK); return FALSE; }
   virtual BOOL CanManipulate(ReferenceTarget* hTarget) {MessageBox(0,"ClassDesc.CanManipulate","",MB_OK); return FALSE; }
   virtual BOOL CanManipulateNode(INode* pNode) {MessageBox(0,"ClassDesc.CanManipulateNode","",MB_OK); return FALSE; }
   virtual Manipulator* CreateManipulator(
          ReferenceTarget* hTarget,
          INode* pNode) {MessageBox(0,"ClassDesc.CreateManipulator","",MB_OK); return NULL; }
   virtual Manipulator* CreateManipulator(INode* pNode) {MessageBox(0,"ClassDesc.CreateManipulator2","",MB_OK); return NULL;}
   virtual BOOL      NeedsToSave() {MessageBox(0,"ClassDesc.NeedsToSave","",MB_OK); return FALSE; }
   virtual IOResult     Save(ISave *isave) {MessageBox(0,"ClassDesc.Save","",MB_OK); return IO_OK; }
   virtual IOResult     Load(ILoad *iload) {MessageBox(0,"ClassDesc.Load","",MB_OK); return IO_OK; }
   virtual DWORD      InitialRollupPageState()  {MessageBox(0,"ClassDesc.InitialRollupPageState","",MB_OK);  return 0x7fffffff;}


  // возвращает имя для MaxScript
  virtual const TCHAR * InternalName()
  {
    MessageBox(0,"ClassDesc.InternalName","",MB_OK);
    return _T("MyUtility");
  }

  // возвращает hInstance модуля
  virtual HINSTANCE HInstance()
  {
    MessageBox(0,"ClassDesc.HInstance","",MB_OK);
    return hInstance;
  }

  virtual int  NumParamBlockDescs() {MessageBox(0,"ClassDesc.NumParamBlockDescs","",MB_OK); return 0; }
  virtual ParamBlockDesc2* GetParamBlockDesc(int i) {MessageBox(0,"ClassDesc.GetParamBlockDesc","",MB_OK); return NULL; }
  virtual ParamBlockDesc2* GetParamBlockDescByID(BlockID id) {MessageBox(0,"ClassDesc.GetParamBlockDescByID","",MB_OK); return NULL; }
  virtual void  AddParamBlockDesc(ParamBlockDesc2* pbd) {MessageBox(0,"ClassDesc.AddParamBlockDesc","",MB_OK); }
  virtual void  BeginEditParams(IObjParam *ip, ReferenceMaker* obj, ULONG flags, Animatable *prev) {MessageBox(0,"ClassDesc.BeginEditParams","",MB_OK); }
  virtual void  EndEditParams(IObjParam *ip, ReferenceMaker* obj, ULONG flags, Animatable *prev) {MessageBox(0,"ClassDesc.EndEditParams","",MB_OK); }
  virtual void  InvalidateUI(ParamBlockDesc2* pbd) {MessageBox(0,"ClassDesc.InvalidateUI","",MB_OK); }
  virtual MCHAR* GetRsrcString(INT_PTR id){MessageBox(0,"ClassDesc.GetRsrcString","",MB_OK); return NULL;};  
  virtual void  MakeAutoParamBlocks(ReferenceMaker* owner) {MessageBox(0,"ClassDesc.MakeAutoParamBlocks","",MB_OK); }
  virtual int  NumParamMaps() {MessageBox(0,"ClassDesc.NumParamMaps","",MB_OK); return 0; }
  virtual IParamMap2* GetParamMap(int i) {MessageBox(0,"ClassDesc.GetParamMap","",MB_OK); return NULL; }
  virtual IParamMap2* GetParamMap(ParamBlockDesc2* pbd) {MessageBox(0,"ClassDesc.GetParamMap2","",MB_OK); return NULL; }
  virtual void  SetUserDlgProc(ParamBlockDesc2* pbd, ParamMap2UserDlgProc* proc=NULL) {MessageBox(0,"ClassDesc.SetUserDlgProc","",MB_OK); }
  virtual ParamMap2UserDlgProc* GetUserDlgProc(ParamBlockDesc2* pbd) {MessageBox(0,"ClassDesc.GetUserDlgProc","",MB_OK); return NULL; }
  virtual bool DrawRepresentation(COLORREF bkColor, HDC hDC, Rect &rect) {MessageBox(0,"ClassDesc.DrawRepresentation","",MB_OK); return FALSE; }
  virtual int  NumInterfaces() {MessageBox(0,"ClassDesc.NumInterfaces","",MB_OK); return 0; }
  virtual FPInterface*  GetInterfaceAt(int i) {MessageBox(0,"ClassDesc.GetInterfaceAt","",MB_OK); return NULL; }
  virtual FPInterface*  GetInterface(Interface_ID id){MessageBox(0,"ClassDesc.GetInterface","",MB_OK); return NULL; }
  virtual FPInterface*  GetInterface(MCHAR* name){MessageBox(0,"ClassDesc.GetInterface2","",MB_OK); return NULL; }
  virtual void  AddInterface(FPInterface* fpi){MessageBox(0,"ClassDesc.AddInterface","",MB_OK); };
  virtual void  ClearInterfaces() { MessageBox(0,"ClassDesc.ClearInterfaces","",MB_OK); }
  virtual Class_ID  SubClassID() {MessageBox(0,"ClassDesc.SubClassID","",MB_OK); return Class_ID(); }
  virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) {MessageBox(0,"ClassDesc.Execute","",MB_OK); return 0; } 

};

4. Для совместимости добавлены два пустых виртуальных метода, которые, очевидно, заменяют конструктор по-умолчанию и конструктор копий (в SDK не прописаны, но без них не работает).  Последовательность вызовов осталась прежней, 3ds запускается, плагин загружается, название его отображается  в свитке UTILITIES\MORE.

#57
21:17, 5 авг 2008

5. Создан аналогичный ClassDesc на Delphi:

ClassDesc=class {MaxHeapOperators}
  private
    interfaces:Tab;
  public
    destructor          ClassDesc();virtual;
    function IsPublic():integer;virtual;cdecl;  // Show this in create branch?
    function Creat(loading:Boolean=FALSE):Pointer;virtual;cdecl;   // return a pointer to an instance of the class.
    function BeginCreate(i:IUnknown):Integer;virtual;cdecl; {return 0;}
    function EndCreate(i:IUnknown):Integer;virtual;cdecl; {return 0;}
    function ClassName():PAnsiChar;virtual;cdecl;
    function SuperClassID():SClass_ID;virtual;cdecl;
    function ClassID():MClass_ID;virtual;cdecl;
    function Category():PAnsiChar;virtual;cdecl;   // primitive/spline/loft/ etc
    function OkToCreate(i:IUnknown):Boolean;virtual;cdecl; { return TRUE; }  // return FALSE to disable create button
    function HasClassParams():Boolean;virtual;cdecl; {return FALSE;}
    procedure EditClassParams(hParent:HWND);virtual;cdecl; {}
    procedure ResetClassParams(fileReset:Boolean=FALSE);virtual;cdecl; {}
    function NumActionTables():Integer;virtual;cdecl; { return 0; }
    function GetActionTable(i:Integer):TActionTable;virtual;cdecl;  { return NULL; }
    function IsManipulator():Boolean;virtual;cdecl; { return FALSE; }
    function CanManipulate(hTarget:TReferenceTarget):Boolean;virtual;cdecl; { return FALSE; }
    function CanManipulateNode(pNode:INode):Boolean;virtual;cdecl; { return FALSE; }
    function CreateManipulator(hTarget:TReferenceTarget;pNode:INode):TManipulator;overload;virtual;cdecl; { return NULL; }
    function CreateManipulator(pNode:INode):TManipulator;overload;virtual;cdecl; {return NULL;}
    function NeedsToSave():Boolean;virtual;cdecl; { return FALSE; }
    function Save(isave:ISave):TIOResult;virtual;cdecl; { return IO_OK; }
    function Load(iload:ILoad):TIOResult;virtual;cdecl; { return IO_OK; }
    function InitialRollupPageState():DWord;virtual;cdecl; { return 0x7fffffff; }
    function InternalName():PAnsiChar;virtual;cdecl; { return NULL; }
    function HInstance():Cardinal;virtual;cdecl; { return NULL; }
    function NumParamBlockDescs():Integer;virtual;cdecl; { return 0; }
    function GetParamBlockDesc(i:Integer):TParamBlockDesc2;virtual;cdecl; { return NULL; }
    function GetParamBlockDescByID(id:BlockID):TParamBlockDesc2;virtual;cdecl; { return NULL; }
    procedure  AddParamBlockDesc(pbd:TParamBlockDesc2);virtual;cdecl; { }
    procedure  BeginEditParams(ip:IObjParam; obj:TReferenceMaker; flags:Longword; prev:TAnimatable);virtual;cdecl; { }
    procedure  EndEditParams(ip:IObjParam; obj:TReferenceMaker; flags:Longword; prev:TAnimatable);virtual;cdecl; { }
    procedure  InvalidateUI(pbd:TParamBlockDesc2);virtual;cdecl; { }
    {CoreExport} function GetRsrcString(id:INT_PTR):PAnsiChar;virtual;cdecl;
    procedure  MakeAutoParamBlocks(owner:TReferenceMaker);virtual;cdecl; { }
    function NumParamMaps():Integer;virtual;cdecl; { return 0; }
    function GetParamMap(i:Integer):IParamMap2;overload;virtual;cdecl; { return NULL; }
    function GetParamMap(pbd:TParamBlockDesc2):IParamMap2;overload;virtual;cdecl; { return NULL; }
    procedure SetUserDlgProc(pbd:TParamBlockDesc2; proc:TParamMap2UserDlgProc=nil);virtual;cdecl; { }
    function GetUserDlgProc(pbd:TParamBlockDesc2):TParamMap2UserDlgProc;virtual;cdecl; { return NULL; }
    function DrawRepresentation(bkColor:COLORREF; DC:HDC; Rect:TRect):Boolean;virtual;cdecl; { return FALSE; }
    function NumInterfaces():integer;virtual;cdecl; { return interfaces.Count(); }
    function GetInterfaceAt(i:Integer):FPInterface;virtual;cdecl; { return interfaces[i]; }
    {CoreExport} function GetInterface(id:TInterface_ID):FPInterface;overload;virtual;cdecl;
    {CoreExport} function GetInterface(name:PAnsiChar):FPInterface;overload;virtual;cdecl;
    {CoreExport} procedure AddInterface(fpi:FPInterface);virtual;cdecl;
    procedure  ClearInterfaces();virtual;cdecl; { interfaces.ZeroCount(); }
    function SubClassID():TClass_ID;virtual;cdecl; { return Class_ID(); }
    function Execute(cmd:Integer; arg1:ULONG_PTR=0; arg2:ULONG_PTR=0; arg3:ULONG_PTR=0):INT_PTR;virtual;cdecl; { return 0; }
end;
#58
21:18, 5 авг 2008

Реализация класса полнотью аналогична сишной выше, но в данном случае никаких дополнительных методов не понадобилось - 3ds все воспринимает и вызывает правильно, как и должно быть согласно MSDN:

destructor ClassDesc.ClassDesc();
begin
  inherited;
end;
function ClassDesc.IsPublic():integer;cdecl;  // Show this in create branch?
begin
  MessageBox(0,'IsPublic','ClassDesc',MB_OK);
  Result:=1;
end;
function ClassDesc.Creat(loading:Boolean=FALSE):Pointer;cdecl;   // return a pointer to an instance of the class.
begin
  MessageBox(0,'Creat','ClassDesc',MB_OK);

  Result:=nil;
end;
function ClassDesc.BeginCreate(i:IUnknown):Integer;cdecl; {return 0;}
begin
  MessageBox(0,'BeginCreate','ClassDesc',MB_OK);
  Result:=0;
end;
function ClassDesc.EndCreate(i:IUnknown):Integer;cdecl; {return 0;}
begin
  MessageBox(0,'EndCreate','ClassDesc',MB_OK);
  Result:=0;
end;
function ClassDesc.ClassName():PAnsiChar;cdecl;
begin
  MessageBox(0,'ClassName','ClassDesc',MB_OK);
  Result:=pchClassName;
  Result:=nil;
end;
function ClassDesc.SuperClassID():SClass_ID;cdecl;
begin
  MessageBox(0,'SuperClassID','ClassDesc',MB_OK);
  Result:=UTILITY_CLASS_ID;
end;
function ClassDesc.ClassID():MClass_ID;cdecl;
begin
  MessageBox(0,'ClassID','ClassDesc',MB_OK);
  Result:=m_id;
end;
function ClassDesc.Category():PAnsiChar;cdecl;   // primitive/spline/loft/ etc
begin
  MessageBox(0,'Category','ClassDesc',MB_OK);
  Result:=nil;
  Result:=pchCategory;
end;
function ClassDesc.OkToCreate(i:IUnknown):Boolean;cdecl; { return TRUE; }  // return FALSE to disable create button
begin
  MessageBox(0,'OKCreate','ClassDesc',MB_OK);
  Result:=True;
end;
function ClassDesc.HasClassParams():Boolean;cdecl; {return FALSE;}
begin
  MessageBox(0,'HasClassParams','ClassDesc',MB_OK);
  Result:=False;
end;
procedure ClassDesc.EditClassParams(hParent:HWND);cdecl; {}
begin
  MessageBox(0,'EditClassParams','ClassDesc',MB_OK);
end;
procedure ClassDesc.ResetClassParams(fileReset:Boolean=FALSE);cdecl; {}
begin
  MessageBox(0,'ResetClassParams','ClassDesc',MB_OK);
end;
function ClassDesc.NumActionTables():Integer;cdecl; { return 0; }
begin
  MessageBox(0,'NewActTable','ClassDesc',MB_OK);
  Result:=0;
end;
function ClassDesc.GetActionTable(i:Integer):TActionTable;cdecl;  { return NULL; }
begin
  MessageBox(0,'GetActTable','ClassDesc',MB_OK);
  Result:=nil;
end;
function ClassDesc.IsManipulator():Boolean;cdecl; { return FALSE; }
begin
  MessageBox(0,'IsManip','ClassDesc',MB_OK);
  Result:=False;
end;
function ClassDesc.CanManipulate(hTarget:TReferenceTarget):Boolean;cdecl; { return FALSE; }
begin
  MessageBox(0,'CanManipulate','ClassDesc',MB_OK);
  Result:=False;
end;
function ClassDesc.CanManipulateNode(pNode:INode):Boolean;cdecl; { return FALSE; }
begin
  MessageBox(0,'CanManipulateNode','ClassDesc',MB_OK);
  Result:=False;
end;
function ClassDesc.CreateManipulator(hTarget:TReferenceTarget;pNode:INode):TManipulator;cdecl; { return NULL; }
begin
  MessageBox(0,'CreateManipulator','ClassDesc',MB_OK);
  Result:=nil;
end;
function ClassDesc.CreateManipulator(pNode:INode):TManipulator;cdecl; {return NULL;}
begin
  MessageBox(0,'CreateManipulator','ClassDesc',MB_OK);
  Result:=nil;
end;
function ClassDesc.NeedsToSave():Boolean;cdecl; { return FALSE; }
begin
  MessageBox(0,'NeedsToSave','ClassDesc',MB_OK);
  Result:=False;
end;
function ClassDesc.Save(isave:ISave):TIOResult;cdecl; { return IO_OK; }
begin
  MessageBox(0,'Save','ClassDesc',MB_OK);
  result:=IO_OK;
end;
function ClassDesc.Load(iload:ILoad):TIOResult;cdecl; { return IO_OK; }
begin
  MessageBox(0,'Load','ClassDesc',MB_OK);
  result:=IO_OK;
end;
function ClassDesc.InitialRollupPageState():Longword;cdecl; { return 0x7fffffff; }
begin
  MessageBox(0,'InitialRollupPageState','ClassDesc',MB_OK);
  result:=$7fffffff;
end;

function ClassDesc.InternalName():PAnsiChar;cdecl; { return NULL; }
begin
  MessageBox(0,'IntName','ClassDesc',MB_OK);
  Result:=pchClassName;
end;
function ClassDesc.HInstance():Cardinal;cdecl; { return NULL; }
begin
  MessageBox(0,'hInstance','ClassDesc',MB_OK);
  Result:=hInstance;
end;
function ClassDesc.NumParamBlockDescs():Integer;cdecl; { return 0; }
begin
  MessageBox(0,'NumParamBlockDescs','ClassDesc',MB_OK);
  Result:=0;
end;
function ClassDesc.GetParamBlockDesc(i:Integer):TParamBlockDesc2;cdecl; { return NULL; }
begin
  MessageBox(0,'GetParamBlockDesc','ClassDesc',MB_OK);
  result:=nil;
end;
function ClassDesc.GetParamBlockDescByID(id:BlockID):TParamBlockDesc2;cdecl; { return NULL; }
begin
  MessageBox(0,'GetParamBlockDescByID','ClassDesc',MB_OK);
  result:=nil;
end;
procedure  ClassDesc.AddParamBlockDesc(pbd:TParamBlockDesc2);cdecl; { }
begin
  MessageBox(0,'AddParamBlockDesc','ClassDesc',MB_OK);
end;
procedure  ClassDesc.BeginEditParams(ip:IObjParam; obj:TReferenceMaker; flags:Longword; prev:TAnimatable);cdecl; { }
begin
  MessageBox(0,'BeginEditParams','ClassDesc',MB_OK);
end;
procedure  ClassDesc.EndEditParams(ip:IObjParam; obj:TReferenceMaker; flags:Longword; prev:TAnimatable);cdecl; { }
begin
  MessageBox(0,'EndEditParams','ClassDesc',MB_OK);
end;
procedure  ClassDesc.InvalidateUI(pbd:TParamBlockDesc2);cdecl; { }
begin
  MessageBox(0,'InvalidateUI','ClassDesc',MB_OK);
end;
function ClassDesc.GetRsrcString(id:INT_PTR):PAnsiChar;cdecl;
begin
  MessageBox(0,'GetRsrcStr','ClassDesc',MB_OK);
  Result:=nil;
end;
procedure  ClassDesc.MakeAutoParamBlocks(owner:TReferenceMaker);cdecl; { }
begin
  MessageBox(0,'MakeAutoParamBlocks','ClassDesc',MB_OK);
end;
function ClassDesc.NumParamMaps():Integer;cdecl; { return 0; }
begin
  MessageBox(0,'NumParamMaps','ClassDesc',MB_OK);
  Result:=0;
end;
function ClassDesc.GetParamMap(i:Integer):IParamMap2;cdecl; { return NULL; }
begin
  MessageBox(0,'GetParamMap','ClassDesc',MB_OK);
  Result:=nil;
end;
function ClassDesc.GetParamMap(pbd:TParamBlockDesc2):IParamMap2;cdecl; { return NULL; }
begin
  MessageBox(0,'GetParamMap1','ClassDesc',MB_OK);
  Result:=nil;
end;
procedure ClassDesc.SetUserDlgProc(pbd:TParamBlockDesc2; proc:TParamMap2UserDlgProc=nil);cdecl; { }
begin
  MessageBox(0,'SetupDlgProc','ClassDesc',MB_OK);
end;
function ClassDesc.GetUserDlgProc(pbd:TParamBlockDesc2):TParamMap2UserDlgProc;cdecl; { return NULL; }
begin
  MessageBox(0,'GetUserDlgProc','ClassDesc',MB_OK);
  Result:=nil;
end;
function ClassDesc.DrawRepresentation(bkColor:COLORREF; DC:HDC; Rect:TRect):Boolean;cdecl; { return FALSE; }
begin
  MessageBox(0,'DrawRepr','ClassDesc',MB_OK);
  Result:=False;
end;
function ClassDesc.NumInterfaces():integer;cdecl; { return interfaces.Count(); }
begin
  MessageBox(0,'NumInterfaces','ClassDesc',MB_OK);
  Result:=0;
end;
function ClassDesc.GetInterfaceAt(i:Integer):FPInterface;cdecl; { return interfaces[i]; }
begin
  MessageBox(0,'GetInterfaceAt','ClassDesc',MB_OK);
  Result:=nil;
end;
function ClassDesc.GetInterface(id:TInterface_ID):FPInterface;cdecl;
begin
  MessageBox(0,'GetInterface','ClassDesc',MB_OK);
  Result:=nil;
end;
function ClassDesc.GetInterface(name:PAnsiChar):FPInterface;cdecl;
begin
  MessageBox(0,'GetInterface1','ClassDesc',MB_OK);
  Result:=nil;
end;
procedure ClassDesc.AddInterface(fpi:FPInterface);cdecl;
begin
  MessageBox(0,'AddInterface','ClassDesc',MB_OK);
end;
procedure  ClassDesc.ClearInterfaces();cdecl; { interfaces.ZeroCount(); }
begin
  MessageBox(0,'ClearInterface','ClassDesc',MB_OK);
end;
function ClassDesc.SubClassID():TClass_ID;cdecl; { return Class_ID(); }
begin
  MessageBox(0,'SubClassId','ClassDesc',MB_OK);
  Result:=c_id;//self.ClassID();
end;
function ClassDesc.Execute(cmd:Integer; arg1:ULONG_PTR=0; arg2:ULONG_PTR=0; arg3:ULONG_PTR=0):INT_PTR;cdecl; { return 0; }
begin
  MessageBox(0,'Execute','ClassDesc',MB_OK);
  Result:=0;
end;

Последовательность вызовов прежняя, все работает вплоть до вызова InitialRollupState. На этом методе 3ds вылетает. Почему? Где ошибка, что не так? Может с PChar`ами что ему не нравится?

Если проблема решится, половина дела будет сделана.

#59
16:10, 6 авг 2008

InitialRollupPageState ты хотел сказать? Може MessageBox мешает?

Страницы: 1 2 3 4 5 6 Следующая »
Антон АксёновФорум

Тема в архиве.