Skip to content
2 changes: 1 addition & 1 deletion SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ void ImGuiGUIEngine::startFrame(sofaglfw::SofaGLFWBaseGUI* baseGUI)
/***************************************
* Scene graph window
**************************************/
static std::set<core::objectmodel::BaseObject*> openedComponents;
static std::set<core::objectmodel::Base*> openedComponents;
static std::set<core::objectmodel::BaseObject*> focusedComponents;
static std::set<core::objectmodel::Base*> currentSelection;
windows::showSceneGraph(groot, windowNameSceneGraph, openedComponents,
Expand Down
2 changes: 1 addition & 1 deletion SofaImGui/src/SofaImGui/ObjectColor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

namespace sofaimgui
{
ImVec4 getObjectColor(sofa::core::objectmodel::BaseObject* object)
ImVec4 getObjectColor(sofa::core::objectmodel::Base* object)
{
unsigned int objectType=sofa::simulation::Colors::OBJECT;
if(object->toContextObject())
Expand Down
4 changes: 2 additions & 2 deletions SofaImGui/src/SofaImGui/ObjectColor.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@

namespace sofa::core::objectmodel
{
class BaseObject;
class Base;
}

namespace sofaimgui
{

ImVec4 getObjectColor(sofa::core::objectmodel::BaseObject* object);
ImVec4 getObjectColor(sofa::core::objectmodel::Base* object);

} //namespace sofaimgui
270 changes: 146 additions & 124 deletions SofaImGui/src/SofaImGui/windows/SceneGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,119 @@
namespace windows
{

bool drawExpandableObject(sofa::core::objectmodel::Base * obj, bool isNodeHighlighted, const char* icon, const ImVec4 objectColor, std::set<sofa::core::objectmodel::Base*>& componentToOpen, const std::set<sofa::core::objectmodel::Base*>& currentSelection, sofa::core::objectmodel::Base* &clickedObject)
{
const auto& objName = obj->getName();

ImGui::PushStyleColor(ImGuiCol_Text, objectColor);

//Tree expand drawing (tick + icon)
ImGui::PushID(obj);
const bool open = ImGui::TreeNode((std::string(icon) + std::string(" ")) .c_str());
ImGui::PopID();

//Name drawing to be able to select the node for inspection
ImGui::PushID(&objName);
ImGui::SameLine();
auto XPos = ImGui::GetCursorPosX();
//We don't write anything to just get the "clickable" space, the name is writent after we know if it is clicked or not
ImGui::TreeNodeEx("",ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Leaf);
if (ImGui::IsItemClicked())
{
if (ImGui::IsMouseDoubleClicked(0))
{
componentToOpen.insert(obj);
clickedObject = nullptr;
}
else
{
clickedObject = obj;
}
}

ImGui::SameLine();
//Now actually write the name
bool doHighLight = isNodeHighlighted || ((clickedObject == obj) != currentSelection.contains(obj));
if (doHighLight)
{
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1,1,0,1));
}

ImGui::SetCursorPosX(XPos);

ImGui::Text(obj->getName().c_str());
if (doHighLight)
{
ImGui::PopStyleColor();
}

ImGui::TableNextColumn();
ImGui::TextDisabled(obj->getClassName().c_str());
if (isNodeHighlighted)
{
ImGui::PopStyleColor();
}
ImGui::PopStyleColor();

ImGui::PopID();
return open;
}

bool drawNonExpandableObject(sofa::core::objectmodel::Base * obj, bool isObjectHighlighted, const char* icon, const ImVec4 objectColor, std::set<sofa::core::objectmodel::Base*>& componentToOpen, const std::set<sofa::core::objectmodel::Base*>& currentSelection, sofa::core::objectmodel::Base* &clickedObject)
{
ImGui::PushID(obj);

ImGuiTreeNodeFlags objectFlags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Leaf;;

const auto& objectName = obj->getName();
const auto objectClassName = obj->getClassName();

ImGui::PushStyleColor(ImGuiCol_Text, objectColor);

const auto objectOpen = ImGui::TreeNodeEx(icon, objectFlags);
ImGui::PopStyleColor();

if (ImGui::IsItemClicked())
{
if (ImGui::IsMouseDoubleClicked(0))
{
componentToOpen.insert(obj);
clickedObject = nullptr;
}
else
{
clickedObject = obj;
}
}

ImGui::SameLine();

bool doHighLight = isObjectHighlighted || ((clickedObject == obj) != currentSelection.contains(obj));
if (doHighLight)
{
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1,1,0,1));
}
ImGui::Text(objectName.c_str());
ImGui::TableNextColumn();
ImGui::TextDisabled(objectClassName.c_str());
ImGui::PopID();

if (doHighLight)
{
ImGui::PopStyleColor();
}

return objectOpen;
}

void showSceneGraph(sofa::core::sptr<sofa::simulation::Node> groot,
const char* const& windowNameSceneGraph,
std::set<sofa::core::objectmodel::BaseObject*>& openedComponents,
std::set<sofa::core::objectmodel::Base*>& openedComponents,
std::set<sofa::core::objectmodel::BaseObject*>& focusedComponents,
std::set<sofa::core::objectmodel::Base*>& currentSelection,
WindowState& winManagerSceneGraph, WindowState& winManagerSelectionDescription)
{
std::set<sofa::core::objectmodel::BaseObject*> componentToOpen;
std::set<sofa::core::objectmodel::Base*> componentToOpen;
if (*winManagerSceneGraph.getStatePtr())
{
if (ImGui::Begin(windowNameSceneGraph, winManagerSceneGraph.getStatePtr()))
Expand All @@ -71,11 +176,11 @@ namespace windows
}

unsigned int treeDepth {};
static sofa::core::objectmodel::Base* clickedObject { nullptr };
sofa::core::objectmodel::Base* clickedObject = nullptr ;

std::function<void(sofa::simulation::Node*)> showNode;
showNode = [&showNode, &treeDepth, expand, collapse, &openedComponents,
&componentToOpen, &currentSelection, &winManagerSelectionDescription](sofa::simulation::Node* node)
showNode = [&showNode, &treeDepth, expand, collapse,
&componentToOpen, &currentSelection, &clickedObject](sofa::simulation::Node* node)
{
if (node == nullptr) return;
if (treeDepth == 0)
Expand All @@ -87,48 +192,16 @@ namespace windows
ImGui::TableNextRow();
ImGui::TableNextColumn();

const auto& nodeName = node->getName();
const bool isNodeHighlighted = !filter.Filters.empty() && filter.PassFilter(nodeName.c_str());
if (isNodeHighlighted)
{
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1,1,0,1));
}
////Label and tree expand drawing
const bool isNodeHighlighted = !filter.Filters.empty() && filter.PassFilter(node->getName().c_str());
bool open = drawExpandableObject(node, isNodeHighlighted, ICON_FA_CUBES, ImVec4(1,1,1,1), componentToOpen, currentSelection, clickedObject);

const bool open = ImGui::TreeNode(std::string(ICON_FA_CUBES " " + nodeName).c_str());
ImGui::TableNextColumn();
ImGui::TextDisabled("Node");
if (isNodeHighlighted)
{
ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked())
clickedObject = node;
if (open)
{
for (const auto object : node->getNodeObjects())
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::PushID(object);

ImGuiTreeNodeFlags objectFlags = ImGuiTreeNodeFlags_SpanFullWidth;

const auto& slaves = object->getSlaves();
if (slaves.empty())
{
objectFlags |= ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Leaf;
}
else
{
if (expand)
ImGui::SetNextItemOpen(true);
if (collapse)
ImGui::SetNextItemOpen(false);
}

const auto& objectName = object->getName();
const auto objectClassName = object->getClassName();
const bool isObjectHighlighted = !filter.Filters.empty() && (filter.PassFilter(objectName.c_str()) || filter.PassFilter(objectClassName.c_str()));

ImVec4 objectColor;

Expand All @@ -153,101 +226,34 @@ namespace windows
objectColor = sofaimgui::getObjectColor(object);
}

ImGui::PushStyleColor(ImGuiCol_Text, objectColor);

const auto objectOpen = ImGui::TreeNodeEx(icon, objectFlags);
ImGui::PopStyleColor();

if (ImGui::IsItemClicked())
const auto& slaves = object->getSlaves();
if (!slaves.empty())
{
if (ImGui::IsMouseDoubleClicked(0))
{
componentToOpen.insert(object);
clickedObject = nullptr;
}
else
{
clickedObject = object;
if(!currentSelection.contains(clickedObject)){
currentSelection.clear();
currentSelection.insert(clickedObject);
winManagerSelectionDescription.setState(true);
}
else{
currentSelection.erase(clickedObject);
winManagerSelectionDescription.setState(false);
}
}
}

ImGui::SameLine();
if (expand)
ImGui::SetNextItemOpen(true);
if (collapse)
ImGui::SetNextItemOpen(false);

bool doHighLight = isObjectHighlighted || currentSelection.contains(object);
if (doHighLight)
{
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1,1,0,1));
}
ImGui::Text(object->getName().c_str());
ImGui::TableNextColumn();
ImGui::TextDisabled(objectClassName.c_str());
ImGui::PopID();

if (doHighLight)
{
ImGui::PopStyleColor();
}
const bool isObjectHighlighted = !filter.Filters.empty() && (filter.PassFilter(object->getName().c_str()) || filter.PassFilter(object->getClassName().c_str()));
bool objectOpen;
if (slaves.empty())
objectOpen = drawNonExpandableObject(object,isObjectHighlighted, icon, objectColor, componentToOpen, currentSelection, clickedObject );
else
objectOpen = drawExpandableObject(object,isObjectHighlighted, icon, objectColor, componentToOpen, currentSelection, clickedObject );


if (objectOpen && !slaves.empty())
{
for (const auto slave : slaves)
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::PushID(slave.get());

const auto& slaveName = slave->getName();
const auto slaveClassName = slave->getClassName();
const bool isSlaveHighlighted = !filter.Filters.empty() && (filter.PassFilter(slaveName.c_str()) || filter.PassFilter(slaveClassName.c_str()));

ImGui::TreeNodeEx(std::string(ICON_FA_CUBE " ").c_str(), ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth);
if (ImGui::IsItemClicked())
{
if (ImGui::IsMouseDoubleClicked(0))
{
componentToOpen.insert(slave.get());
clickedObject = nullptr;
}
else
{
clickedObject = slave.get();
if(!currentSelection.contains(clickedObject)){
currentSelection.clear();
currentSelection.insert(clickedObject);
winManagerSelectionDescription.setState(true);
}
else{
currentSelection.erase(clickedObject);
winManagerSelectionDescription.setState(false);
}
}
}
ImGui::SameLine();
const bool isSlaveHighlighted = !filter.Filters.empty() && (filter.PassFilter(slave->getName().c_str()) || filter.PassFilter(slave->getClassName().c_str()));
drawNonExpandableObject(slave.get(), isSlaveHighlighted, ICON_FA_CUBE, ImVec4(1,1,1,1), componentToOpen, currentSelection, clickedObject );

doHighLight = isSlaveHighlighted || currentSelection.contains(slave.get());
if (doHighLight)
{
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1,1,0,1));
}
ImGui::Text(slave->getName().c_str());
ImGui::TableNextColumn();
ImGui::TextDisabled(slave->getClassName().c_str());

if (doHighLight)
{
ImGui::PopStyleColor();
}

ImGui::PopID();
}
ImGui::TreePop();
}
Expand Down Expand Up @@ -277,16 +283,32 @@ namespace windows
ImGui::EndTable();
}

if (clickedObject)
{
if(!currentSelection.contains(clickedObject)){
currentSelection.clear();
currentSelection.insert(clickedObject);
winManagerSelectionDescription.setState(true);
}
else
{
currentSelection.erase(clickedObject);
winManagerSelectionDescription.setState(false);
}
}

}
ImGui::End();

}



openedComponents.insert(componentToOpen.begin(), componentToOpen.end());
openedComponents.insert(focusedComponents.begin(), focusedComponents.end());

sofa::type::vector<sofa::core::objectmodel::BaseObject*> toRemove;
static std::map<sofa::core::objectmodel::BaseObject*, int> resizeWindow;
sofa::type::vector<sofa::core::objectmodel::Base*> toRemove;
static std::map<sofa::core::objectmodel::Base*, int> resizeWindow;
for (auto* component : openedComponents)
{
bool isOpen = true;
Expand Down
7 changes: 6 additions & 1 deletion SofaImGui/src/SofaImGui/windows/SceneGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ namespace windows
*/
void showSceneGraph(sofa::core::sptr<sofa::simulation::Node> groot,
const char* const& windowNameSceneGraph,
std::set<sofa::core::objectmodel::BaseObject*>& openedComponents,
std::set<sofa::core::objectmodel::Base*>& openedComponents,
std::set<sofa::core::objectmodel::BaseObject*>& focusedComponents,
std::set<sofa::core::objectmodel::Base*>& currentSelection,
WindowState& winManagerSceneGraph, WindowState& winManagerSelectionDescription);
Expand All @@ -62,5 +62,10 @@ namespace windows
std::set<sofa::core::objectmodel::BaseObject*>& focusedComponents,
WindowState& winSelectionDescription);

//Utilitaries to draw the graph
bool drawExpandableObject(sofa::core::objectmodel::Base * obj, bool isNodeHighlighted, const char* icon, const ImVec4 objectColor, std::set<sofa::core::objectmodel::Base*>& componentToOpen, const std::set<sofa::core::objectmodel::Base*>& currentSelection, sofa::core::objectmodel::Base* &clickedObject);
bool drawNonExpandableObject(sofa::core::objectmodel::Base * obj, bool isObjectHighlighted, const char* icon, const ImVec4 objectColor, std::set<sofa::core::objectmodel::Base*>& componentToOpen, const std::set<sofa::core::objectmodel::Base*>& currentSelection, sofa::core::objectmodel::Base* &clickedObject);



} // namespace sofaimgui
Loading