ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
59.75k stars 10.17k forks source link

ImGui::IsMouseReleased(0) conflict with drag and drop #2209

Open ngminteck opened 5 years ago

ngminteck commented 5 years ago

Version/Branch of Dear ImGui:

165

Back-end file/Renderer/OS: (or specify if you are using a custom engine back-end)

Back-ends: imgui_impl_win32.cpp + imgui_implopengl3.cpp OS: XXX Compiler: XXX (if the question is related to building)_

My Issue/Question: (please provide context)

Hello i trying implement of drag selected object which is selected tree node and add to the child of tree node.

however it conflict with my ImGui::IsMouseReleased(0) as when i drag and release, it actually clear the selection, end out add nothing.

it work fine only when i drag and drop upward, but drag and drag downward will have conflict.

below is a rough ideas of how my code implement

Standalone, minimal, complete and verifiable example: (see CONTRIBUTING.md)

#include <vector>

struct TestObject
{
bool selected;
std::string name;
std::vector<TestObject*> test_object_child;
};

struct Test
{
std::vector<TestObject*> test_object;

void ClearAllSelection()
{
 for (auto & elem :test_object)
{
test_object->selected = false;
}

}

}

// can be in constructor or init
void Init()
{

TestObject * test1 = new TestObject();
test1->selected= "false;
test1->name = "test1";
test_object.push_back(test1 );

TestObject * test2 = new TestObject();
test2->selected= "false;
test2->name = "test2";
test_object.push_back(test2 );

TestObject * test3 = new TestObject();
test3->selected= "false;
test3->name = "test3";
test_object.push_back(test3 );
}

Draw()
{
        ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_None;
        for(auto & elem: test_object)
        {
          ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_None;

               bool node_open = ImGui::TreeNodeEx(elem->name.c_str(), node_flags, 
                                                                             elem->name.c_str());
               if (ImGui::BeginDragDropTarget())
        {
            if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MoveToAdd"))
            {
                                TestObject * test = new TestObject();
                                test->selected = false;
                                test->name = *(static_cast<std::string *>(payload->Data());
                elem->test_object_child.push_back(test);
            }
            ImGui::EndDragDropTarget();
        }
               if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
        {
                        std::string sent_data = elem->name;
                ImGui::SetDragDropPayload("MoveToAdd", &add_name , sent_data .size());
                ImGui::Text("Move to...");
            ImGui::EndDragDropSource();
        }
               if (ImGui::IsItemHovered())
        {
              if (ImGui::GetIO().KeyShift && ImGui::IsMouseReleased(0))
            {
               // some shift click
            }
            else if (ImGui::GetIO().KeyCtrl && ImGui::IsMouseReleased(0))
            {
                // some control click function
            }
            else if (ImGui::IsMouseReleased(0))
            {
                       ClearAllSelection();
                           elem->selected = true;
            }
        }
              if (node_open)
          {
            for(auto & child_elem : elem.second->test_object_child)
                        {
                               DrawChild(child_elem.second);
                        }
                ImGui::TreePop();
          }
          }
}
DrawChild(TestObject * obj)
{
// same as draw funciton as it allow recurrsive draw for the child item
}

Screenshots/Video (you can drag files here)

ocornut commented 5 years ago

I cannot compile the code and it's hard to understand your question. Please provide a Standalone, minimal, complete and verifiable example and maybe a printf log of what is going on.

ngminteck commented 5 years ago

hello here the gif about my situation capture

ngminteck commented 5 years ago

one part of my school project code for the treenode ex branch

below is for draw imgui child tree node ex as it is recurssive

`void EditorWorldOutliner::ChildObjectBranch(std::unordered_map<unsigned, SceneActor *> child_object)
{
    ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_None;
    if (child_object.size() > 0)
    {
        for (auto & elem : child_object)
        {
            node_flags = (elem.second->GetSceneActorSelection() == true ? ImGuiTreeNodeFlags_Selected : 0);

            if (elem.second->GetChildSceneActors().size() == 0)
            {
                node_flags |= ImGuiTreeNodeFlags_Leaf;
            }
            else
            {
                node_flags |= ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
            }
            bool node_open = ImGui::TreeNodeEx(elem.second->GetSceneActorName().c_str(), node_flags, elem.second->GetSceneActorName().c_str());
            if (ImGui::BeginDragDropTarget())
            {
                if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("PrefabToScene"))
                {
                    m_ResourceFactoryManager->GetSceneActorFactory()->NewSceneActor(*(static_cast<unsigned *>(payload->Data)), elem.second);
                    m_ev->PublishEvent(new SwitchLevelEvent{});
                }
                if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MoveActor"))
                {
                    dest = elem.second;
                    moving = true;
                }
                ImGui::EndDragDropTarget();
            }
            if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
            {
                ImGui::SetDragDropPayload("MoveActor", NULL, NULL);
                ImGui::Text("Move to...");
                ImGui::EndDragDropSource();
            }
            if (ImGui::IsItemHovered())
            {
                if (ImGui::GetIO().KeyShift && ImGui::IsMouseReleased(0))
                {
                    m_ResourceFactoryManager->GetSceneActorFactory()->SceneActorShiftSelection(elem.second);
                }
                else if (ImGui::GetIO().KeyCtrl && ImGui::IsMouseReleased(0))
                {
                    elem.second->SelectWithControlKey();
                }
                else if (ImGui::IsMouseReleased(0))
                {
                    m_ResourceFactoryManager->GetSceneActorFactory()->ClearWholeSceneActorSelection();

                    if (elem.second->GetSceneActorSelection() == true)
                        elem.second->SetSceneActorSelection(false);
                    else
                        elem.second->SetSceneActorSelection(true);

                    m_cam->ViewObject(elem.second);
                }

            }
            std::string BeginPopupContextItem_label = "Options##" + elem.second->GetSceneActorName();
            if (ImGui::BeginPopupContextItem(BeginPopupContextItem_label.c_str()))
            {
                ImGui::PushItemWidth(-1);
                if (ImGui::MenuItem("Duplicate All Selected"))
                {
                    m_ResourceFactoryManager->GetSceneActorFactory()->SceneActorSelectionDuplicate();

                }
                std::string OpenPopup_label = "Rename##OpenPopup" + elem.second->GetSceneActorName();
                ImGui::PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true);
                if (ImGui::MenuItem("Rename All Selected"))
                {
                    ImGui::OpenPopup(OpenPopup_label.c_str());
                }
                if (ImGui::BeginPopupModal(OpenPopup_label.c_str()))
                {
                    static char buf2[64] = "";
                    ImGuiInputTextFlags text_flag1 = ImGuiInputTextFlags_None;
                    ImGui::PushItemWidth(100);
                    ImGui::InputText("##EditorContentBrowser", buf2, 64, text_flag1, NULL, NULL);
                    ImGui::PopItemWidth();
                    new_name = buf2;
                    ImGui::Separator();

                    if (ImGui::Button("Apply", ImVec2(120, 0)))
                    {
                        m_ResourceFactoryManager->GetSceneActorFactory()->SceneActorSelectionRename(new_name);
                        new_name = "";
                        ImGui::CloseCurrentPopup();
                    }
                    ImGui::SetItemDefaultFocus();
                    ImGui::SameLine();
                    if (ImGui::Button("Cancel", ImVec2(120, 0)))
                    {
                        new_name = "";
                        ImGui::CloseCurrentPopup();
                    }
                    ImGui::EndPopup();
                }
                ImGui::PopItemFlag();
                if (ImGui::MenuItem("Move Selected to this scene actor"))
                {
                    dest = elem.second;
                    moving = true;
                }
                if (ImGui::MenuItem("Delete All Selected"))
                {
                    deleting = true;
                }
                ImGui::PopItemWidth();
                ImGui::EndPopup();
            }

            if (node_open)
            {
                ChildObjectBranch(elem.second->GetChildSceneActors());
                ImGui::TreePop();
            }
        }
    }
}`
ngminteck commented 5 years ago

the problem i think it might be

if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("PrefabToScene")) { m_ResourceFactoryManager->GetSceneActorFactory()->NewSceneActor(*(static_cast<unsigned *>(payload->Data)), elem.second); m_ev->PublishEvent(new SwitchLevelEvent{}); } if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MoveActor")) { dest = elem.second; moving = true; } ImGui::EndDragDropTarget(); }

code is above your drag and drop target node.

in code run wise below is still not draw , so you can't drag and drop to the item below? but only above tree node

ocornut commented 5 years ago

@ngminteck It would tremendously increase the likehood that someone looks at this if you provided a "Standalone, minimal, complete and verifiable example" that we can paste into the example app.