Skip to content

Commit

Permalink
Clone button in context menu (#1561)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fedr authored Aug 24, 2023
1 parent 2667c64 commit ae1704c
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 21 deletions.
89 changes: 72 additions & 17 deletions source/MRViewer/MRRibbonMenu.cpp
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
#include "MRRibbonMenu.h"
#include "MRMesh/MRSystem.h"
#include "MRMesh/MRStringConvert.h"
#include "MRMesh/MRSerializer.h"
#include "MRMesh/MRObjectsAccess.h"
#include "MRProgressBar.h"
#include "MRColorTheme.h"
#include "MRAppendHistory.h"
#include "MRCommandLoop.h"
#include "MRMesh/MRChangeSceneObjectsOrder.h"
#include "MRMesh/MRChangeSceneAction.h"
#include "MRPch/MRJson.h"
#include "MRPch/MRSpdlog.h"
#include "MRPch/MRWasm.h"
#include "MRRibbonIcons.h"
#include "MRRibbonConstants.h"
#include "ImGuiHelpers.h"
#include "MRMesh/MRString.h"
#include "MRImGuiImage.h"
#include "MRFileDialog.h"
#include "MRMesh/MRChangeXfAction.h"
#include "MRUIStyle.h"
#include <MRMesh/MRString.h>
#include <MRMesh/MRSystem.h>
#include <MRMesh/MRStringConvert.h>
#include <MRMesh/MRSerializer.h>
#include <MRMesh/MRObjectsAccess.h>
#include <MRMesh/MRChangeXfAction.h>
#include <MRMesh/MRObjectLabel.h>
#include <MRMesh/MRChangeSceneObjectsOrder.h>
#include <MRMesh/MRChangeSceneAction.h>
#include <MRMesh/MRChangeObjectFields.h>
#include <MRPch/MRJson.h>
#include <MRPch/MRSpdlog.h>
#include <MRPch/MRWasm.h>
#include <imgui_internal.h> // needed here to fix items dialogs windows positions
#include <misc/freetype/imgui_freetype.h> // for proper font loading
#include <regex>

#if defined(__APPLE__) && defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-volatile"
#endif

#include <GLFW/glfw3.h>
#include "MRMesh/MRObjectLabel.h"

#if defined(__APPLE__) && defined(__clang__)
#pragma clang diagnostic pop
Expand Down Expand Up @@ -786,14 +788,11 @@ bool RibbonMenu::drawGroupUngroupButton_( const std::vector<std::shared_ptr<Obje
return someChanges;

Object* parentObj = selected[0]->parent();
bool canGroup = parentObj != nullptr;
for ( int i = 1; i < selected.size(); ++i )
bool canGroup = parentObj != nullptr && selected.size() >= 2;
for ( int i = 1; canGroup && i < selected.size(); ++i )
{
if ( selected[i]->parent() != parentObj )
{
canGroup = false;
break;
}
}

if ( canGroup && UI::button( "Group", Vector2f( -1, 0 ) ) )
Expand Down Expand Up @@ -860,6 +859,60 @@ bool RibbonMenu::drawGroupUngroupButton_( const std::vector<std::shared_ptr<Obje
return someChanges;
}

void RibbonMenu::cloneTree( const std::vector<std::shared_ptr<Object>>& selectedObjects )
{
const std::regex pattern( R"(.* Clone(?:| \([0-9]+\))$)" );
SCOPED_HISTORY( "Clone objects" );
for ( const auto& obj : selectedObjects )
{
if ( !obj )
continue;
auto cloneObj = obj->cloneTree();
AppendHistory<ChangeObjectSelectedAction>( "unselect base obj", obj );
obj->select( false );
AppendHistory<ChangeObjectVisibilityAction>( "make base obj invisible", obj );
obj->setVisible( false );
auto name = obj->name();
if ( std::regex_match( name, pattern ) )
{
auto endBracPos = name.rfind( ')' );
if ( endBracPos != int( name.length() ) - 1 )
{
name += " (2)";
}
else
{
auto startNumPos = name.rfind( '(' ) + 1;
auto numStr = name.substr( startNumPos, endBracPos - startNumPos );
int num = std::atoi( numStr.c_str() );
name = name.substr( 0, startNumPos - 1 ) + "(" + std::to_string( num + 1 ) + ")";
}
}
else
{
name += " Clone";
}
cloneObj->setName( name );
AppendHistory<ChangeSceneAction>( "Add cloned obj", cloneObj, ChangeSceneAction::Type::AddObject );
obj->parent()->addChild( cloneObj );
}
}

bool RibbonMenu::drawCloneButton_( const std::vector<std::shared_ptr<Object>>& selected )
{
bool someChanges = false;
if ( selected.empty() )
return someChanges;

if ( UI::button( "Clone", Vector2f( -1, 0 ) ) )
{
cloneTree( selected );
someChanges = true;
}

return someChanges;
}

void RibbonMenu::drawBigButtonItem_( const MenuItemInfo& item )
{
auto width = buttonDrawer_.calcItemWidth( item, DrawButtonParams::SizeType::Big );
Expand Down Expand Up @@ -1409,6 +1462,7 @@ void RibbonMenu::drawSceneContextMenu_( const std::vector<std::shared_ptr<Object
wasChanged |= drawGeneralOptions_( selected );
wasChanged |= drawRemoveButton_( selected );
wasChanged |= drawGroupUngroupButton_( selected );
wasChanged |= drawCloneButton_( selected );
}
else if ( ImGui::BeginTable( "##DrawOptions", 2, ImGuiTableFlags_BordersInnerV ) )
{
Expand All @@ -1420,6 +1474,7 @@ void RibbonMenu::drawSceneContextMenu_( const std::vector<std::shared_ptr<Object
wasChanged |= drawDrawOptionsColors_( selectedVisualObjs );
wasChanged |= drawRemoveButton_( selected );
wasChanged |= drawGroupUngroupButton_( selected );
wasChanged |= drawCloneButton_( selected );
ImGui::EndTable();
}
ImGui::PopStyleVar();
Expand Down
11 changes: 7 additions & 4 deletions source/MRViewer/MRRibbonMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,17 @@ class MRVIEWER_CLASS RibbonMenu : public ImGuiMenu
/// returns index of active tab in RibbonSchemaHolder::schema().tabsOrder
int getActiveTabIndex() const { return activeTabIndex_; }

const RibbonButtonDrawer& getRibbonButtonDrawer() { return buttonDrawer_; }
Toolbar& getToolbar() { return toolbar_; }

/// clones given objects with sub-objects (except for ancillary and unrecognized children) and undo
MRVIEWER_API static void cloneTree( const std::vector<std::shared_ptr<Object>>& selectedObjects );

using TabChangedSignal = boost::signals2::signal<void( int prevTabId, int newTabId )>;
/// this signal is called when active tab changes
TabChangedSignal tabChangedSignal;

const RibbonButtonDrawer& getRibbonButtonDrawer() { return buttonDrawer_; }
Toolbar& getToolbar() { return toolbar_; }

protected:

// draw single item
MRVIEWER_API virtual void drawBigButtonItem_( const MenuItemInfo& item );
// draw set of small text buttons
Expand Down Expand Up @@ -175,6 +177,7 @@ class MRVIEWER_CLASS RibbonMenu : public ImGuiMenu
void drawActiveListButton_( const ImVec2& basePos, float btnSize, float textSize );

bool drawGroupUngroupButton_( const std::vector<std::shared_ptr<Object>>& selected );
bool drawCloneButton_( const std::vector<std::shared_ptr<Object>>& selected );

void beginTopPanel_();
void endTopPanel_();
Expand Down

0 comments on commit ae1704c

Please sign in to comment.