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
    • Login

    Crash when calling TreeViewFunctions::DrawCell

    Cinema 4D SDK
    r23 c++
    2
    4
    786
    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.
    • A
      AiMiDi
      last edited by

      I'm going to set a tree view as shown below. After adding items into the tree view for several times, it suddenly crashed in DrawText. This issue happens stably.
      f0cdc856-582a-4526-b216-0ae3845dc2f9-image.png

      42bad5c9-0d59-4ab2-b051-43baf46948f5-image.png

      struct MyItem
      {
      	enum
      	{
      		MATERIAL,
      		MESH,
      		CAMERA,
      		LIGTH
      	};
      
      	enum
      	{
      		OK,
      		WARNING,
      		ERROR
      	};
      
      	Int32 state = OK;
      	Int32 type = MATERIAL;
      	BaseList2D* element;
      	String parameter;
      	String problem;
      };
      
      struct MyItem
      {
      	Int32 state = OK;
      	Int32 type = MATERIAL;
      	BaseList2D* element;
      	String parameter;
      	String problem;
      };
      
      struct MyItemNode
      {
      	MyItem item; //data
      	MyItemNode* down = nullptr;
      	MyItemNode* next = nullptr;
      };
      
      using MyItemArray = maxon::BaseArray<MyItemNode>;
      
      class MyTreeViewFunctions final : public TreeViewFunctions
      {
      	void* m_selected_node = nullptr;
      public:
      	static MyTreeViewFunctions& GetFunction()
      	{
      		static MyTreeViewFunctions func;
      		return func;
      	}
      
      	void* GetFirst(void* root, void* userdata) override
      	{
      		return static_cast<MyItemArray*>(root)->GetFirst();
      	}
      
      	void* GetDown(void* root, void* userdata, void* obj) override
      	{
      		return nullptr;
      	}
      
      	void* GetNext(void* root, void* userdata, void* obj) override
      	{
      		if (const auto node = static_cast<MyItemNode*>(obj))
      			return node->next;
      		return nullptr;
      	}
      
      	Bool IsSelected(void* root, void* userdata, void* obj) override
      	{
      		return m_selected_node == obj;
      	}
      
      	Int32 GetLineHeight(void* root, void* userdata, void* obj, Int32 col, GeUserArea* area) override
      	{
      		return 20;
      	}
      
      	Int32 GetColumnWidth(void* root, void* userdata, void* obj, Int32 col, GeUserArea* area) override
      	{
      		return 65;
      	}
      
      	void DrawCell(void* root, void* userdata, void* obj, const Int32 col, DrawInfo* drawinfo, const GeData& bgColor) override
      	{
      		if(!obj)
      			return;
      		const auto& item = static_cast<MyItemNode*>(obj)->item;
      		switch (col)
      		{
      		case MyDialog::LIST_COL_TYPE:
      		{
      			BaseBitmap* bm = nullptr;
      			switch (item.type)
      			{
      			case MyItem::MATERIAL:
      				bm = m_material_bitmap;
      				break;
      			case MyItem::MESH:
      				bm = m_mesh_bitmap;
      				break;
      			case MyItem::CAMERA:
      				bm = m_camera_bitmap;
      				break;
      			case MyItem::LIGTH:
      				bm = m_light_bitmap;
      				break;
      			default:;
      			}
      			drawinfo->frame->DrawBitmap(bm, drawinfo->xpos + drawinfo->width / 4, drawinfo->ypos + 2, ICON_SIZE, ICON_SIZE, 0, 0, bm->GetBw(), bm->GetBh(), BMP_NORMALSCALED);
      			break;
      		}
      		case MyDialog::LIST_COL_ELEMENT:
      		{
      			if (item.type == MyItem::MATERIAL)
      			{
      				if (auto* mat = reinterpret_cast<BaseMaterial*>(item.element); mat) 
      				{
      					if (BaseBitmap* bm = mat->GetPreview(0); bm)
      					{
      						drawinfo->frame->DrawBitmap(bm, drawinfo->xpos, drawinfo->ypos + 2, ICON_SIZE, ICON_SIZE, 0, 0, bm->GetBw(), bm->GetBh(), BMP_NORMALSCALED);
      					}
      				}
      			}
      			drawinfo->frame->DrawSetTextCol(IsSelected(root, userdata, obj) ? COLOR_TEXT_SELECTED : COLOR_TEXT, COLOR_TRANS);
      			drawinfo->frame->DrawText(item.GetName(), drawinfo->xpos + ICON_SIZE + 2,drawinfo->ypos + drawinfo->height / 2, DRAWTEXT_VALIGN_CENTER);
      			break;
      		}
      		case MyDialog::LIST_COL_PARAMETER:
      		{
      			drawinfo->frame->DrawSetTextCol(IsSelected(root, userdata, obj) ? COLOR_TEXT_SELECTED : COLOR_TEXT, COLOR_TRANS);
      			drawinfo->frame->DrawText(item.parameter, drawinfo->xpos + 2,
      				drawinfo->ypos + (drawinfo->height - drawinfo->frame->DrawGetFontHeight()) / 2 + 2);
      			break;
      		}
      		case MyDialog::LIST_COL_PROBLEM:
      		{
      			drawinfo->frame->DrawSetTextCol(IsSelected(root, userdata, obj) ? COLOR_TEXT_SELECTED : COLOR_TEXT, COLOR_TRANS);
      			drawinfo->frame->DrawText(item.problem, drawinfo->xpos + 2, drawinfo->ypos + drawinfo->height / 2, DRAWTEXT_VALIGN_CENTER);
      			break;
      		}
      		default:;
      		}
      	}
      
      	Bool IsOpened(void* root, void* userdata, void* obj) override
      	{
      		return true;
      	}
      
      	String GetName(void* root, void* userdata, void* obj) override
      	{
      		return {};
      	}
      
      	Int	GetId(void* root, void* userdata, void* obj) override
      	{
      		return 0;
      	}
      
      	Int32 GetDragType(void* root, void* userdata, void* obj) override
      	{
      		return NOTOK;
      	}
      
      	void Select(void* root, void* userdata, void* obj, Int32 mode) override
      	{
      		if(mode == SELECTION_SUB)
      			m_selected_node = nullptr;
      		else
      			m_selected_node = obj;
      	}
      };
      
      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi @AiMiDi we are currently busy with other thing I will get to your topic as soon as possible, in the meantime I would say it is most likely the access of item.GetName() that went wrong since your item does not have a GetName method. (It is just a gut feeling I did not try your code).

        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • M
          m_adam
          last edited by m_adam

          Hi @AiMiDi if you need more help, please provide us a code that can compile so this means something that include the dialog as well, since this have an impact on how the treeview behave. On the same topic you do not provide the icon/ neither show how the m_xxx_bitmap are initialized.

          Cheers,
          Maxime.

          MAXON SDK Specialist

          Development Blog, MAXON Registered Developer

          A 1 Reply Last reply Reply Quote 0
          • A
            AiMiDi @m_adam
            last edited by

            Hi @m_adam , thanks for your apply. I have solved this problem. The reason is I used maxon::BaseArray to store tree node data. When I append the array, the address of node may change, but the next pointer in node remain unchanged. And this cause the crash.

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