Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Register
    • Login

    GeDialog Failing To Open

    Cinema 4D SDK
    c++ s26 sdk
    2
    6
    742
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      JohnTerenece
      last edited by JohnTerenece

      Hello.

      I am encountering a problem when I insert my object plugin into a scene in R26, save the document and then reopen the file. When I click the button to open the GeDialog Cinema immediately crashes on me.

      I stripped down the code for my GeDialog to the bare minimum that was still similar to the examples in the sdk and the problem is still occurring.

      #include "c4d_general.h"
      #include "c4d.h"
      #include "c4d_symbols.h"
      #include "main.h"
      
      #define ID_RUNDIALOG 1059364
      enum Controls
      {
      	idSendMessageLinkObject = 1000,
      	idLinkedObject,
      	idGatherChildren,
      
      	idOverallScrollGroup = 2000,
      	idGroupToFlush,
      	idControls,
      
      	idLaunchDialogWindow = 1500,
      	idBasicControlGroup,
      };
      
      class ObjDialog : public GeDialog
      {
      public:
      	ObjDialog() {}
      	virtual ~ObjDialog() {}
      	virtual Bool CreateLayout();
      	virtual Bool InitValues();
      	virtual void DestroyWindow();
      	virtual Bool Command(Int32 id, const BaseContainer& msg);
      	virtual Int32 Message(const BaseContainer& msg, BaseContainer& result);
      };
      
      
      Bool ObjDialog::CreateLayout()
      {
      	Bool res = GeDialog::CreateLayout();
      
      	SetTitle("Dialog Window"_s);
      
      	ScrollGroupBegin(idOverallScrollGroup, BFH_SCALEFIT | BFV_SCALEFIT, SCROLLGROUP_VERT | SCROLLGROUP_HORIZ);
      	{
      		GroupBegin(idGroupToFlush, BFH_SCALEFIT | BFV_SCALEFIT, 1, 0, String(), 0);
      		{
      			GroupBegin(idControls, BFH_SCALEFIT | BFV_SCALEFIT, 5, 0, String(), 0);
      			{
      			}
      			GroupEnd();
      		}
      		GroupEnd();
      	}
      	GroupEnd();
      
      	return res;
      }
      
      Bool ObjDialog::InitValues()
      {
      	if (!GeDialog::InitValues())
      		return false;
      	return true;
      }
      
      void ObjDialog::DestroyWindow() {}
      
      Bool ObjDialog::Command(Int32 id, const BaseContainer& msg)
      {
      	return true;
      }
      
      
      Int32 ObjDialog::Message(const BaseContainer& msg, BaseContainer& result)
      {
      	return GeDialog::Message(msg, result);
      }
      
      
      class RunDialog : public ObjectData
      {
      public:
      	virtual Bool Init(GeListNode* node);
      
      	virtual BaseObject* GetVirtualObjects(BaseObject* op, HierarchyHelp* hh);
      	virtual Bool Message(GeListNode* node, Int32 type, void* t_data);
      	virtual Bool GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags);
      
      	static NodeData* Alloc() { return NewObjClear(RunDialog); }
      
      	maxon::BaseArray<BaseObject*> objArrayToCheckForMatch;
      private:
      	ObjDialog dlg;
      };
      
      
      Bool RunDialog::GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags)
      {
      	BaseContainer *dataInstance;
      	const DescID *singleid;
      	if (!description->LoadDescription(node->GetType()))
      	{
      	}
      
      	dataInstance = ((BaseList2D*)node)->GetDataInstance(); // Get the container for the tag
      	if (!dataInstance)
      		return FALSE;
      	singleid = description->GetSingleDescID();
      	DescID cid;
      
      
      	DescID DescHelperControlGroup = DescLevel(idBasicControlGroup, DTYPE_GROUP, 0);
      	if (!singleid || DescHelperControlGroup.IsPartOf(*singleid, NULL))
      	{
      		BaseContainer bc;
      		bc = GetCustomDataTypeDefault(DTYPE_GROUP);
      		bc.SetString(DESC_NAME, "Run Dialog"_s);
      		bc.SetInt32(DESC_COLUMNS, 1);
      		bc.SetInt32(DESC_DEFAULT, 1);
      		bc.SetBool(DESC_SCALEH, TRUE);
      
      		if (!description->SetParameter(DescHelperControlGroup, bc, DescLevel(ID_RUNDIALOG)))
      			return TRUE;
      	}
      
      
      	cid = DescLevel(idLaunchDialogWindow, DTYPE_BUTTON, 0);
      	if (!singleid || cid.IsPartOf(*singleid, NULL))  //  important to check for speedup c4d!
      	{
      		BaseContainer bc;
      		bc = GetCustomDataTypeDefault(DTYPE_BUTTON);
      		bc.SetInt32(DESC_CUSTOMGUI, CUSTOMGUI_BUTTON);
      		bc.SetString(DESC_NAME, "Open Dialog"_s);
      		if (!description->SetParameter(cid, bc, DescHelperControlGroup))
      			return TRUE;
      	}
      
      
      
      
      	flags |= DESCFLAGS_DESC::LOADED;
      
      	return TRUE;
      }
      
      Bool RunDialog::Init(GeListNode* node)
      {
      	return true;
      }
      
      
      Bool RunDialog::Message(GeListNode* node, Int32 type, void* t_data)
      {
      	if (type == MSG_DESCRIPTION_COMMAND)
      	{
      		DescriptionCommand *dc = (DescriptionCommand*)t_data;
      		if (!dc)
      			return TRUE;
      		Int32 ID = Int32(dc->_descId[0].id);
      		BaseDocument* doc = node->GetDocument();
      		if (!doc)
      			return TRUE;
      
      		switch (ID)
      		{
      			// Problem occurs here
      			case idLaunchDialogWindow:
      			{
      				if (dlg.IsOpen() == false)
      					dlg.Open(DLG_TYPE::ASYNC, ID_RUNDIALOG, -1, -1, 300, 200, 0, OPENDIALOGFLAGS::IGNORELAYOUT);
      				break;
      			}
      		}
      	}
      
      	return true;
      }
      
      BaseObject* RunDialog::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh)
      {
      	BaseObject *nullReturn = BaseObject::Alloc(Onull);
      
      	return nullReturn;
      }
      
      Bool RegisterRunDialog()
      {
      
      	return RegisterObjectPlugin(ID_RUNDIALOG, "Run Dialog"_s, OBJECT_GENERATOR | OBJECT_INPUT, RunDialog::Alloc, "ORunDialog"_s, AutoBitmap("atom.tif"_s), 0);
      }
      
      

      I've used this same code in R20 and R25 and haven't had a single issue with opening the GeDialog, I only started encountering the problem in R26.

      Looking at the examples in the sdk that deal with GeDialogs they are all opened via a CommandData plugin and the GeDialog manual specifically mentions that GeDialog based windows are typically owned by a CommandData plugin.

      Is it now a requirement to use a CommandData plugin to open a GeDialog?

      Any help would be greatly appreciated.

      John Terenece

      1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by

        hi,
        I am not able to reproduce the issue. Are you compiling in debug or release mode?

        Cheers
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • J
          JohnTerenece
          last edited by

          Release mode.

          1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by

            hi, sorry i missed the fact it is mandatory to save the file and reopen it.

            I was able to reproduce the issue. I need to ask ours devs the best way to fix this.

            Cheers,
            Manuel

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • ManuelM
              Manuel
              last edited by Manuel

              The issue is happening because no dialog operation should be done from a thread. Loading the scene is now done asynchronously and the object creation is done in a thread. The GeDialog constructor will be called from a thread and fail.

              My suggestion is to replace the GeDialog variable by a pointer and be sure that the allocation and the deletion is done in the mainthread.

              Because the GeDialog was not initialised correctly, the CDIalog was not defined so the function dlg.IsOpen() was crashing.
              For extra check, you can check CDialog against nullptr like so

              CDialog* intern = dlg->Get();
              

              I also change the TRUE to true. TRUE should be avoided.

              #include "c4d_general.h"
              #include "c4d.h"
              #include "c4d_symbols.h"
              
              #include "maxon/thread.h"
              
              #define ID_RUNDIALOG 1059364
               
              
              enum Controls
              {
              	idSendMessageLinkObject = 1000,
              	idLinkedObject,
              	idGatherChildren,
              
              	idOverallScrollGroup = 2000,
              	idGroupToFlush,
              	idControls,
              
              	idLaunchDialogWindow = 1500,
              	idBasicControlGroup,
              };
              
              class ObjDialog : public GeDialog
              {
              public:
              	virtual Bool CreateLayout();
              	virtual Bool InitValues();
              	virtual void DestroyWindow();
              	virtual Bool Command(Int32 id, const BaseContainer& msg);
              	virtual Int32 Message(const BaseContainer& msg, BaseContainer& result);
              };
              
              
              Bool ObjDialog::CreateLayout()
              {
              	Bool res = GeDialog::CreateLayout();
              	SetTitle("Dialog Window"_s);
              	ScrollGroupBegin(idOverallScrollGroup, BFH_SCALEFIT | BFV_SCALEFIT, SCROLLGROUP_VERT | SCROLLGROUP_HORIZ);
              	{
              		GroupBegin(idGroupToFlush, BFH_SCALEFIT | BFV_SCALEFIT, 1, 0, String(), 0);
              		{
              			GroupBegin(idControls, BFH_SCALEFIT | BFV_SCALEFIT, 5, 0, String(), 0);
              			{
              			}
              			GroupEnd();
              		}
              		GroupEnd();
              	}
              	GroupEnd();
              
              	return res;
              }
              
              Bool ObjDialog::InitValues()
              {
              	if (!GeDialog::InitValues())
              		return false;
              	return true;
              }
              
              void ObjDialog::DestroyWindow() {}
              
              Bool ObjDialog::Command(Int32 id, const BaseContainer& msg)
              {
              	return true;
              }
              
              
              Int32 ObjDialog::Message(const BaseContainer& msg, BaseContainer& result)
              {
              	return GeDialog::Message(msg, result);
              }
              
              
              
              
              class RunDialog : public ObjectData
              {
              public:
              	virtual Bool Init(GeListNode* node);
              
              	virtual BaseObject* GetVirtualObjects(BaseObject* op, HierarchyHelp* hh);
              	virtual Bool Message(GeListNode* node, Int32 type, void* t_data);
              	virtual Bool GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags);
              
              	static NodeData* Alloc() { return NewObjClear(RunDialog); }
              
              	maxon::BaseArray<BaseObject*> objArrayToCheckForMatch;
              
              	void Free(GeListNode* node) override;
              private:
              	ObjDialog *dlg = nullptr;
              
              
              };
              
              Bool RunDialog::Init(GeListNode* node)
              {
              	if (dlg == nullptr)
              	{
              		maxon::ExecuteOnMainThread([this]() 
              			{
              				dlg = NewObjClear(ObjDialog);
              			});
              	}
              	
              	return true;
              }
              
              void RunDialog::Free(GeListNode* node) 
              {
              	if (dlg)
              	{
              		maxon::ExecuteOnMainThread([this]()
              			{
              				DeleteObj(dlg);
              				dlg = nullptr;
              			});
              	}
              }
              
              Bool RunDialog::GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags)
              {
              	BaseContainer* dataInstance;
              	const DescID* singleid;
              	if (!description->LoadDescription(node->GetType()))
              	{
              	}
              
              	dataInstance = ((BaseList2D*)node)->GetDataInstance(); // Get the container for the tag
              	if (!dataInstance)
              		return FALSE;
              	singleid = description->GetSingleDescID();
              	DescID cid;
              
              
              	DescID DescHelperControlGroup = DescLevel(idBasicControlGroup, DTYPE_GROUP, 0);
              	if (!singleid || DescHelperControlGroup.IsPartOf(*singleid, NULL))
              	{
              		BaseContainer bc;
              		bc = GetCustomDataTypeDefault(DTYPE_GROUP);
              		bc.SetString(DESC_NAME, "Run Dialog"_s);
              		bc.SetInt32(DESC_COLUMNS, 1);
              		bc.SetInt32(DESC_DEFAULT, 1);
              		bc.SetBool(DESC_SCALEH, true);
              
              		if (!description->SetParameter(DescHelperControlGroup, bc, DescLevel(ID_RUNDIALOG)))
              			return true;
              	}
              
              
              	cid = DescLevel(idLaunchDialogWindow, DTYPE_BUTTON, 0);
              	if (!singleid || cid.IsPartOf(*singleid, NULL))  //  important to check for speedup c4d!
              	{
              		BaseContainer bc;
              		bc = GetCustomDataTypeDefault(DTYPE_BUTTON);
              		bc.SetInt32(DESC_CUSTOMGUI, CUSTOMGUI_BUTTON);
              		bc.SetString(DESC_NAME, "Open Dialog"_s);
              		if (!description->SetParameter(cid, bc, DescHelperControlGroup))
              			return true;
              	}
              
              
              
              
              	flags |= DESCFLAGS_DESC::LOADED;
              
              	return true;
              }
              
              
              
              
              Bool RunDialog::Message(GeListNode* node, Int32 type, void* t_data)
              {
              	if (type == MSG_DESCRIPTION_COMMAND)
              	{
              		DescriptionCommand* dc = (DescriptionCommand*)t_data;
              		if (!dc)
              			return true;
              		Int32 ID = Int32(dc->_descId[0].id);
              		BaseDocument* doc = node->GetDocument();
              		if (!doc)
              			return true;
              
              		switch (ID)
              		{
              			// Problem occurs here
              			case idLaunchDialogWindow:
              			{
              				if (dlg)
              				{
              					CDialog* intern = dlg->Get();
              					if (intern)
              					{
              						if (dlg->IsOpen() == false)
              							dlg->Open(DLG_TYPE::ASYNC, ID_RUNDIALOG, -1, -1, 300, 200, 0, OPENDIALOGFLAGS::IGNORELAYOUT);
              					}
              				}
              				break;
              			}
              		}
              	}
              
              	return true;
              }
              
              BaseObject* RunDialog::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh)
              {
              	BaseObject* nullReturn = BaseObject::Alloc(Onull);
              
              	return nullReturn;
              }
              Bool RegisterRunDialog();
              Bool RegisterRunDialog()
              {
              
              	return RegisterObjectPlugin(ID_RUNDIALOG, "Run Dialog"_s, OBJECT_GENERATOR | OBJECT_INPUT, RunDialog::Alloc, ""_s, AutoBitmap("atom.tif"_s), 0);
              }
              

              Cheers,
              Manuel

              MAXON SDK Specialist

              MAXON Registered Developer

              1 Reply Last reply Reply Quote 0
              • J
                JohnTerenece
                last edited by

                Thanks for the response. This seems to have solved the problem.

                John Terenece

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post