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

    TreeView Multiple Selection With LMB

    Cinema 4D SDK
    2
    13
    2.1k
    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.
    • M
      m_adam
      last edited by

      Hi @Danchyg1337 on our side everything work nicely,
      Unfortunately with the code provided, I can't help you since I don't have everything. So if you could provide us a simplified version that reproduces the issue I could look at it.

      Just a side note looking at your code doing such a SelectObject(&(*res->cell)); is not very safe. Moreover, you seem to never check for nullptr, so please do it and it should resolve the crash.

      Cheers,
      Maxime.

      MAXON SDK Specialist

      Development Blog, MAXON Registered Developer

      Danchyg1337D 1 Reply Last reply Reply Quote 0
      • Danchyg1337D
        Danchyg1337 @m_adam
        last edited by

        @m_adam Thanks for the reply! About SelectObject(&(*res->cell));. Inside of SelectObject() i check for a nullptr at the very start, and i hope this

        TreeNode* res = (TreeNode*)obj;
        if (!res) return;
        

        is enogh to prevent nullptr in Select. Maybe i just misunderstood you about nullptr, correct me then please.

        I'm not sure what should i send you as simpified version, because there is a bunch of code and i don't know which function causes it. I supposed it was Select, but aparently problen is not in it. What about my virtual functions? Could i miss some important virtual function?

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

          Yes, but you don't check for arrayCell.

          If you could provide the minimal piece of code that still reproduce your crash, this way I could reproduce the same issue you are facing and can try to help you (help us to help you).
          So at least GetNext/GetFirst/GetDown/IsSelected/GetName/GetID/GetPred/Select methods.

          If you are interested in Treeview you may find valuable information in:

          • TreeView made simple – Part 1[URL-REMOVED].
          • Treeview made simple – Part 2 – Folding & Selections[URL-REMOVED].
          • Using Custom ListView This is python but you may find some valuable information.

          Cheers,
          Maxime.


          [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

          MAXON SDK Specialist

          Development Blog, MAXON Registered Developer

          Danchyg1337D 1 Reply Last reply Reply Quote 0
          • Danchyg1337D
            Danchyg1337 @m_adam
            last edited by

            @m_adam Here are required functions:

            void* Tree::GetFirst(void* root, void* userdata)
            {
            	TreeNode* obj = (TreeNode*)root;
            	return obj;
            }
            
            void* Tree::GetNext(void* root, void* userdata, void* obj)
            {
            	TreeNode* res = (TreeNode*)obj;
            
            	if (res && res->next)
            		return res->next;
            	return NULL;
            }
            
            void* Tree::GetPred(void* root, void* userdata, void* obj)
            {
            	TreeNode* res = (TreeNode*)obj;
            
            	if (res && res->pred)
            		return res->pred;
            	return NULL;
            }
            
            void* Tree::GetDown(void* root, void* userdata, void* obj)
            {
            	TreeNode* res = (TreeNode*)obj;
            	if (res && res->root && res->down)
            		return res->down;
            
            	return NULL;
            }
            
            String Tree::GetName(void* root, void* userdata, void* obj)
            {
            	if (!obj) return "";
            	TreeNode* res = (TreeNode*)obj;
            	if (res->root) {
            		String name = res->cell->second.GetString(OBJSET_NAME);
            		if (res->cell->second.GetInt32(OBJSET_ID))
            			return name;
            		else {
            			Filename fn(name);
            			return fn.GetFile().GetString();
            		}
            	}
            	return std::get<2>(*(res->arrayCell)).GetString(DESCPREF_NAME);
            }
            
            Int Tree::GetId(void* root, void* userdata, void* obj)
            {
            	return (Int)obj;
            }
            
            Bool Tree::IsSelected(void* root, void* userdata, void* obj)
            {
            	TreeNode* res = (TreeNode*)obj;
            	if (!res) return false;
            	if (res->root) 
            		return std::find(parent->objID.begin(), parent->objID.end(), &(*res->cell)) != parent->objID.end();
            	return std::find(parent->clickID.begin(), parent->clickID.end(), &(*res->arrayCell)) != parent->clickID.end();
            }
            

            And Select() from post above. None of my attempts to check for nullptr helped, so nothing new to provide for that function.
            My code with stuff like &(*res->cell)) and &(*res->arrayCell)) may look unsafe, but it works as intended. If i select with clicking and holding SHIFT button, everything works fine, but when i try to drag LMB i get instant crash even when there are no objects in drag rectangle.

            Thanks!

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

              "When i select with mouse drag, what does Select get as obj?"
              Normally Select shouldn't be called when you hold a click while dragging.

              Just to clarify and I should have asked first, but how do you select multiple items?

              1. By clicking all of them individually.
                • Select will be called each time you click.
              2. By clicking on one entry, then SHIFT + click on another one.
                • For the first click, Select will be called with SELECTION_NEW.
                • For the second click, Select will be called over each other entry with SELECTION_ADD.
              3. By clicking on one entry, holding the click, drag the mouse down/up, and release the mouse.
                • I'm not sure I would need to try. But in any case, DragStart will be called to see what to do with the currently selected object and if they are allowed to be dragged. But you can return only TREEVIEW_DRAGSTART_SELECT this way object will be selected (but I'm not sure) or you will need to directly override MouseDown to implement this behavior.

              Note that I overlooked, the fact you didn't override DragStart. Which define what to do when a drag operation is starting, Selection state, and if the object can be dragged.

              But just to recap the dragging process:

              • Drag is starting from the TreeView:
                • DragStart Called when the Drag operation start, to know what to do. Should return TREEVIEW_DRAGSTART_ALLOW and/or TREEVIEW_DRAGSTART_SELECT to inform what to do.
                • GetDragType Called after DragStart. Should return the drag type the current cell is representing.
                • According to the type returned by GetDragType:
                  • DRAGTYPE_ATOMARRAY: GenerateDragArray will be called.
                  • If another drag type is filled then GenerateDragData is called.
                • SetDragObject is called, so we can store the dragged obj if we want to.
              • Drop received:
                • AcceptDragObject is called to see if we accept the drag object. obj can be any kind, this is why you need to check the value of dragtype. Should return, if obj should be inserted and where it should be.
                • InsertObject is the called (if it's an array-like in the case of DRAGTYPE_ATOMARRAY, the function will be called once, with obj* being an AtomArray). It's up to you to do proper insertion within your structure.
                • A Refresh and a redraw will be done to update the treeview according to the new internal Data Structure.

              In any case I can't really help you more, I still miss, MainMap, MainMapCellArray class InsertObject, AcceptDragObject, GetDragType, DragStart.
              And please provide also the GeDialog or at least the option you used to register the treeview.

              Hope this help a bit more,
              Cheers,
              Maxime.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

              Danchyg1337D 1 Reply Last reply Reply Quote 0
              • Danchyg1337D
                Danchyg1337 @m_adam
                last edited by

                @m_adam I select them with third case, by clicking on one, holding, dragging and releasing mouse.
                Thanks for useful information, i'm gonna try everything what you suggesed and answer on my results here.

                1 Reply Last reply Reply Quote 0
                • Danchyg1337D
                  Danchyg1337
                  last edited by Danchyg1337

                  @m_adam Maybe i'm little misunderstood you. I meant not exactly third case. But a case, when you start holding your mouse at empty space and selecting objects with outcoming rectangle.

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

                    Oki doki, I forget this case, so normally what will happen is:

                    1. Select with SELECTION_SUB will be called for each entry.
                    2. Select with SELECTION_NEW will be called for the uppermost entry
                    3. Select with SELECTION_ADD will be called for each bellow entries.

                    So it should work as expected if your methods are safe.
                    Does unselect by ctrl+click on a selected entry work for you? (Looks like SELECTION_NEW, and SELECTION_ADD works so the only left is SELECTION_SUB).

                    Without your code, I can't help you more.

                    Cheers,
                    Maxime.

                    MAXON SDK Specialist

                    Development Blog, MAXON Registered Developer

                    Danchyg1337D 1 Reply Last reply Reply Quote 0
                    • Danchyg1337D
                      Danchyg1337 @m_adam
                      last edited by

                      @m_adam Yes. I just checked that. A select few items with shift+click, and unselect with ctrl+click. Everything works fine.

                      I want to provide you my code, but there is a messy structure like this

                      typedef std::tuple<DescID, Int32, BaseContainer> MainMapCellArrayCell;
                      typedef std::list<MainMapCellArrayCell> MainMapCellArray;
                      typedef std::list<std::pair<MainMapCellArray, BaseContainer>> MainMap;
                      typedef std::pair<MainMapCellArray, BaseContainer> MainMapCell;
                      

                      And i'm not sure it will be efficient way to help. Can i send you whole project to email?

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

                        Of course, having the whole project would probably more helpful, you can send it to [email protected], and if needed we can sign an NDA.

                        Cheers,
                        Maxime.

                        MAXON SDK Specialist

                        Development Blog, MAXON Registered Developer

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

                          Hi after digging into your code, the main issue is that your root defined by SetRoot is also your first object.
                          So you should rethink how you structure your internal data structure.
                          I know this is misleading, but root, in the treeviewfunction expects an object that hosts the first object(like the dialog) but the root is not the first object.

                          Note the issue is a more general issue that could lead you to other problems, and in fact, you can reproduce your crash when you click on nothing, the drag operation is fine.
                          Since internally there are several places where the next logic is used

                          DoAction(void* pItem)
                          {
                          (pItem == root)
                             pItem = pItem->GetFirst()
                          else
                             pItem = pItem->GetDown()
                          
                          for (; pItem; pItem = functions->GetNext(root, userdata, pItem))
                              DoAction(pItem);
                          }
                          

                          So in your case, this creates an infinite loop and at the end, create a stack overflow.
                          pItem is the root and the first object. So if you call DoAction with pItem == root,
                          pItem == GetFirst == the previous pItem so in fact we didn't changed the object.
                          Then we arrive in the loop, and the first step is to call DoAction with pItem, so we get the infinite loop.

                          Cheers,
                          Maxime

                          MAXON SDK Specialist

                          Development Blog, MAXON Registered Developer

                          Danchyg1337D 1 Reply Last reply Reply Quote 0
                          • Danchyg1337D
                            Danchyg1337 @m_adam
                            last edited by

                            @m_adam Now i see the problem. Thanks alot for helping!

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