diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..955bdbf --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required( VERSION 3.0 ) + +# CloudCompare example for standard plugins + +# REPLACE ALL 'ExamplePlugin' OCCURENCES BY YOUR PLUGIN NAME +# AND ADAPT THE CODE BELOW TO YOUR OWN NEEDS! + +# Add an option to CMake to control whether we build this plugin or not +option( PLUGIN_SEGMENTER "Check to install segmenter plugin" OFF ) + +if ( PLUGIN_SEGMENTER ) + # Name the plugin + project( SegmenterPlugin ) + + # load any subdirectories (see qAdditionalIO for an example) + # add_subdirectory( LIB1 ) + + include( ../../CMakePluginTpl.cmake ) + + # set dependencies to necessary libraries (see qPCV for an example) + # target_link_libraries( ${PROJECT_NAME} LIB1 ) + # include_directories( ${LIB1_INCLUDE_DIR} ) +endif() diff --git a/SegmenterPlugin.cpp b/SegmenterPlugin.cpp new file mode 100644 index 0000000..30896ab --- /dev/null +++ b/SegmenterPlugin.cpp @@ -0,0 +1,123 @@ +//########################################################################## +//# # +//# CLOUDCOMPARE PLUGIN: ExamplePlugin # +//# # +//# This program is free software; you can redistribute it and/or modify # +//# it under the terms of the GNU General Public License as published by # +//# the Free Software Foundation; version 2 of the License. # +//# # +//# This program is distributed in the hope that it will be useful, # +//# but WITHOUT ANY WARRANTY; without even the implied warranty of # +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +//# GNU General Public License for more details. # +//# # +//# COPYRIGHT: XXX # +//# # +//########################################################################## + +// First: +// Replace all occurrences of 'ExamplePlugin' by your own plugin class name in this file. +// This includes the resource path to info.json in the constructor. + +// Second: +// Open ExamplePlugin.qrc, change the "prefix" and the icon filename for your plugin. +// Change the name of the file to .qrc + +// Third: +// Open the info.json file and fill in the information about the plugin. +// "type" should be one of: "Standard", "GL", or "I/O" (required) +// "name" is the name of the plugin (required) +// "icon" is the Qt resource path to the plugin's icon (from the .qrc file) +// "description" is used as a tootip if the plugin has actions and is displayed in the plugin dialog +// "authors", "maintainers", and "references" show up in the plugin dialog as well + +#include + +#include "SegmenterPlugin.h" + +// Default constructor: +// - pass the Qt resource path to the info.json file (from .qrc file) +// - constructor should mainly be used to initialize actions and other members +SegmenterPlugin::SegmenterPlugin( QObject *parent ) + : QObject( parent ) + , ccStdPluginInterface( ":/CC/plugin/SegmenterPlugin/info.json" ) + , m_action( nullptr ) +{ +} + +// This method should enable or disable your plugin actions +// depending on the currently selected entities ('selectedEntities'). +void SegmenterPlugin::onNewSelection( const ccHObject::Container &selectedEntities ) +{ + if ( m_action == nullptr ) + { + return; + } + + // If you need to check for a specific type of object, you can use the methods + // in ccHObjectCaster.h or loop and check the objects' classIDs like this: + // + // for ( ccHObject *object : selectedEntities ) + // { + // if ( object->getClassID() == CC_TYPES::VIEWPORT_2D_OBJECT ) + // { + // // ... do something with the viewports + // } + // } + + // For example - only enable our action if something is selected. + m_action->setEnabled( !selectedEntities.empty() ); +} + +// This method returns all the 'actions' your plugin can perform. +// getActions() will be called only once, when plugin is loaded. +QList SegmenterPlugin::getActions() +{ + // default action (if it has not been already created, this is the moment to do it) + if ( !m_action ) + { + // Here we use the default plugin name, description, and icon, + // but each action should have its own. + m_action = new QAction( getName(), this ); + m_action->setToolTip( getDescription() ); + m_action->setIcon( getIcon() ); + + // Connect appropriate signal + connect( m_action, &QAction::triggered, this, &SegmenterPlugin::doAction ); + } + + return { m_action }; +} + +// This is an example of an action's method called when the corresponding action +// is triggered (i.e. the corresponding icon or menu entry is clicked in CC's +// main interface). You can access most of CC's components (database, +// 3D views, console, etc.) via the 'm_app' variable (see the ccMainAppInterface +// class in ccMainAppInterface.h). +void SegmenterPlugin::doAction() +{ + if ( m_app == nullptr ) + { + // m_app should have already been initialized by CC when plugin is loaded + Q_ASSERT( false ); + + return; + } + + /*** HERE STARTS THE ACTION ***/ + + // Put your code here + // --> you may want to start by asking for parameters (with a custom dialog, etc.) + + // This is how you can output messages + // Display a standard message in the console + m_app->dispToConsole( "[ExamplePlugin] Hello world!", ccMainAppInterface::STD_CONSOLE_MESSAGE ); + + // Display a warning message in the console + m_app->dispToConsole( "[ExamplePlugin] Warning: example plugin shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE ); + + // Display an error message in the console AND pop-up an error box + m_app->dispToConsole( "Example plugin shouldn't be used - it doesn't do anything!", ccMainAppInterface::ERR_CONSOLE_MESSAGE ); + + /*** HERE ENDS THE ACTION ***/ +} diff --git a/SegmenterPlugin.h b/SegmenterPlugin.h new file mode 100644 index 0000000..5f6d187 --- /dev/null +++ b/SegmenterPlugin.h @@ -0,0 +1,71 @@ +#ifndef EXAMPLE_PLUGIN_HEADER +#define EXAMPLE_PLUGIN_HEADER + +//########################################################################## +//# # +//# CLOUDCOMPARE PLUGIN: ExamplePlugin # +//# # +//# This program is free software; you can redistribute it and/or modify # +//# it under the terms of the GNU General Public License as published by # +//# the Free Software Foundation; version 2 of the License. # +//# # +//# This program is distributed in the hope that it will be useful, # +//# but WITHOUT ANY WARRANTY; without even the implied warranty of # +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +//# GNU General Public License for more details. # +//# # +//# COPYRIGHT: XXX # +//# # +//########################################################################## + +#include "ccStdPluginInterface.h" + +//! Example qCC plugin +/** Replace 'ExamplePlugin' by your own plugin class name throughout and then + check 'ExamplePlugin.cpp' for more directions. + + Each plugin requires an info.json file to provide information about itself - + the name, authors, maintainers, icon, etc.. + + The one method you are required to implement is 'getActions'. This should + return all actions (QAction objects) for the plugin. CloudCompare will + automatically add these with their icons in the plugin toolbar and to the + plugin menu. If your plugin returns several actions, CC will create a + dedicated toolbar and a sub-menu for your plugin. You are responsible for + connecting these actions to methods in your plugin. + + Use the ccStdPluginInterface::m_app variable for access to most of the CC + components (database, 3D views, console, etc.) - see the ccMainAppInterface + class in ccMainAppInterface.h. +**/ +class SegmenterPlugin : public QObject, public ccStdPluginInterface +{ + Q_OBJECT + Q_INTERFACES(ccStdPluginInterface) + + // Replace "Example" by your plugin name (IID should be unique - let's hope your plugin name is unique ;) + // The info.json file provides information about the plugin to the loading system and + // it is displayed in the plugin information dialog. + Q_PLUGIN_METADATA(IID "cccorp.cloudcompare.plugin.ColorimetricSegmenter" FILE "info.json") + +public: + explicit SegmenterPlugin( QObject *parent = nullptr ); + ~SegmenterPlugin() override = default; + + // inherited from ccStdPluginInterface + void onNewSelection( const ccHObject::Container &selectedEntities ) override; + QList getActions() override; + +private: + /*** ADD YOUR CUSTOM ACTIONS HERE ***/ + void doAction(); + + //! Default action + /** You can add as many actions as you want in a plugin. + Each action will correspond to an icon in the dedicated + toolbar and an entry in the plugin menu. + **/ + QAction* m_action; +}; + +#endif diff --git a/SegmenterPlugin.qrc b/SegmenterPlugin.qrc new file mode 100644 index 0000000..ca21554 --- /dev/null +++ b/SegmenterPlugin.qrc @@ -0,0 +1,6 @@ + + + images/icon.png + info.json + + diff --git a/images/icon.png b/images/icon.png new file mode 100644 index 0000000..2c923cc Binary files /dev/null and b/images/icon.png differ diff --git a/info.json b/info.json new file mode 100644 index 0000000..c53558f --- /dev/null +++ b/info.json @@ -0,0 +1,34 @@ +{ + "type" : "Standard", + "name" : "Colorimetric Segmenter", + "icon" : ":/CC/plugin/ExamplePlugin/images/icon.png", + "description": "This is a description of the marvelous Example plugin. It does nothing.", + "authors" : [ + { + "name" : "Daniel Girardeau-Montaut", + "email" : "daniel.girardeau@gmail.com" + } + ], + "maintainers" : [ + { + "name" : "Andy Maloney", + "email" : "asmaloney@gmail.com" + }, + { + "name" : "Example NoEmail" + } + ], + "references" : [ + { + "text" : "The unsuccessful self-treatment of a case of “writer's block”", + "url" : "https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1311997/" + }, + { + "text" : "Sword swallowing and its side effects", + "url" : "http://www.bmj.com/content/333/7582/1285" + }, + { + "text" : "I thought of creating this wonderful plugin while I was hiking up ⛰ Mont Blanc" + } + ] +}