1 /**************************************************************************** 2 * MeshLab o o * 3 * A versatile mesh processing toolbox o o * 4 * _ O _ * 5 * Copyright(C) 2005-2008 \/)\/ * 6 * Visual Computing Lab /\/| * 7 * ISTI - Italian National Research Council | * 8 * \ * 9 * All rights reserved. * 10 * * 11 * This program is free software; you can redistribute it and/or modify * 12 * it under the terms of the GNU General Public License as published by * 13 * the Free Software Foundation; either version 2 of the License, or * 14 * (at your option) any later version. * 15 * * 16 * This program is distributed in the hope that it will be useful, * 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * 20 * for more details. * 21 * * 22 ****************************************************************************/ 23 24 #ifndef MESHLAB_INTERFACES_H 25 #define MESHLAB_INTERFACES_H 26 //#include <GL/glew.h> 27 28 #include "filterparameter.h" 29 #include "GLLogStream.h" 30 //#include "meshmodel.h" 31 #include "scriptinterface.h" 32 #include "xmlfilterinfo.h" 33 34 #include <QtCore> 35 #include <QApplication> 36 #include <QAction> 37 #include <QGLContext> 38 #include <QGLFormat> 39 #include <QMessageBox> 40 #include <QTabletEvent> 41 #include <QDebug> 42 43 44 class QWidget; 45 class QGLWidget; 46 class QString; 47 class QVariant; 48 class QMouseEvent; 49 class QTreeWidgetItem; 50 class MeshModel; 51 class RenderMode; 52 class GLArea; 53 class GLAreaReg; 54 class QScriptEngine; 55 56 class MeshModel; 57 58 /** The MainWindowInterface class defines just the executeFilter() callback function 59 that is invoked by the standard parameter input dialog. 60 It is used as base class of the MainWindow. 61 */ 62 class MainWindowInterface 63 { 64 public: 65 virtual void executeFilter(QAction *, RichParameterSet &, bool = false) {} 66 //parexpval is a string map containing the parameter expression values set in the filter's dialog. 67 //These parameter expression values will be evaluated when the filter will start. 68 virtual void executeFilter(MeshLabXMLFilterContainer*, const QMap<QString, QString>&, bool = false) {} 69 //virtual void executeFilter(MeshLabXMLFilterContainer*,Env& envcode , bool isPreview = false) {} 70 71 //virtual void getCurrentPersistentParsMap(QMap<QString, QString>&) const {} 72 }; 73 74 /** \brief The MeshLabInterface class is the base of all the plugin interfaces. 75 76 The main idea common to all the framework is that each plugin export a set of actions, 77 internally each action is associated to a FilterIDType, and for each action a name and a formatted INFO is defined. 78 79 For coding easyness ID are more practical (you can use them in switches). 80 Using action on the other hand is practical because it simplify their management in menus/toolbars and it allows to define icons and other things in a automatic way. 81 Moreover ID are UNSAFE (different plugin can have same id) so they should be used only INTERNALLY 82 83 \todo There is inconsistency in the usage of ID and actions for retrieving particular filters. Remove. 84 85 */ 86 class MeshLabInterface 87 { 88 public: 89 /** the type used to identify plugin actions; there is a one-to-one relation between an ID and an Action. 90 \todo To be renamed as ActionIDType 91 */ 92 MeshLabInterface()93 MeshLabInterface() :log(0) {} ~MeshLabInterface()94 virtual ~MeshLabInterface() {} 95 private: 96 GLLogStream *log; 97 public: 98 99 /// Standard stuff that usually should not be redefined. setLog(GLLogStream * log)100 void setLog(GLLogStream *log) { this->log = log; } 101 102 // This function must be used to communicate useful information collected in the parsing/saving of the files. 103 // NEVER EVER use a msgbox to say something to the user. 104 template <typename... Ts> Log(const char * f,Ts &&...ts)105 void Log(const char * f, Ts&&... ts ) 106 { 107 if(log != nullptr) 108 { 109 log->Logf(GLLogStream::FILTER, f, std::forward<Ts>(ts)...); 110 } 111 } 112 Log(const char * s)113 void Log(const char * s) 114 { 115 if(log != nullptr) 116 { 117 log->Log(GLLogStream::FILTER, s); 118 } 119 } 120 Log(const std::string & s)121 void Log(const std::string& s) 122 { 123 if(log != nullptr) 124 { 125 log->Log(GLLogStream::FILTER, s); 126 } 127 } 128 129 template <typename... Ts> Log(GLLogStream::Levels Level,const char * f,Ts &&...ts)130 void Log(GLLogStream::Levels Level, const char * f, Ts&&... ts ) 131 { 132 if(log != nullptr) 133 { 134 log->Logf(Level, f, std::forward<Ts>(ts)...); 135 } 136 } 137 Log(GLLogStream::Levels level,const char * s)138 void Log(GLLogStream::Levels level, const char * s) 139 { 140 if(log != nullptr) 141 { 142 log->Log(level, s); 143 } 144 } 145 Log(GLLogStream::Levels level,const std::string & s)146 void Log(GLLogStream::Levels level, const std::string& s) 147 { 148 if(log != nullptr) 149 { 150 log->Log(level, s); 151 } 152 } 153 RealTimeLog(QString Id,const QString & meshName,const char * f)154 void RealTimeLog(QString Id, const QString &meshName, const char * f) 155 { 156 if(log != nullptr) 157 { 158 log->RealTimeLog(Id, meshName, f); 159 } 160 } 161 162 template <typename... Ts> RealTimeLog(QString Id,const QString & meshName,const char * f,Ts &&...ts)163 void RealTimeLog(QString Id, const QString &meshName, const char * f, Ts&&... ts ) 164 { 165 if(log != nullptr) 166 { 167 log->RealTimeLogf(Id, meshName, f, std::forward<Ts>(ts)...); 168 } 169 } 170 }; 171 172 class MeshCommonInterface : public MeshLabInterface 173 { 174 public: 175 typedef int FilterIDType; MeshCommonInterface()176 MeshCommonInterface() {} ~MeshCommonInterface()177 virtual ~MeshCommonInterface() {} 178 pluginName(void)179 virtual QString pluginName(void) const { return ""; } 180 181 /** \brief This function is called by the framework, for each plugin that has global parameters (e.g. \ref MeshDecorateInterface) at the start of the application. 182 The rationale is to allow to each plugin to have a list of global persistent parameters that can be changed from the meshlab itself and whose value is persistent between different meshlab invocations. 183 A typical example is the background color. 184 185 For the global parameters the following rules apply: 186 187 \li there is a <b>hardwired</b> default value: a safe consistent value that is directly coded into the plugin and to which the user can always revert if needed. 188 \li there is a <b>saved</b> value: a value that is stored into a persistent location into the user space (registry/home/library) and it is presented as default value of the parameter at each MeshLab invocation. 189 \li there is a <b>current</b> value: a value that is currently used, different for each document instance and that is not stored permanently. 190 191 The plugin use the current value to draw its decoration. 192 at startup the current value is always silently initialized to the saved value. 193 User can revert current value to the saved values and to the hardwired values. 194 In the dialog for each parameter some buttons should be present: 195 196 \li apply: use the currently edited parameter value without saving it anywhere. After the closure of the document these values will be lost. 197 \li load: load from the saved values 198 \li save: save to a permanent location the current value (to the registry), 199 \li reset: revert to the hardwired values 200 201 If your plugins/action has no GlobalParameter, do nothing. 202 The RichParameterSet comes to the StartDecorate already initialized with the values stored on the permanent storage. 203 At the start up the initGlobalParameterSet function is called with an empty RichParameterSet (to collect the default values) 204 If a filter wants to save some permanent stuff should set the permanent default values. 205 */ initGlobalParameterSet(QAction *,RichParameterSet &)206 virtual void initGlobalParameterSet(QAction * /*format*/, RichParameterSet & /*globalparam*/) {} 207 }; 208 /** \brief The MeshIOInterface is the base class for all the single mesh loading plugins. 209 */ 210 class MeshIOInterface : public MeshCommonInterface 211 { 212 public: 213 class Format 214 { 215 public: Format(QString description,QString ex)216 Format(QString description, QString ex) : description(description) { extensions << ex; } 217 QString description; 218 QStringList extensions; 219 }; 220 MeshIOInterface()221 MeshIOInterface() : MeshCommonInterface() { } ~MeshIOInterface()222 virtual ~MeshIOInterface() {} 223 224 virtual QList<Format> importFormats() const = 0; 225 virtual QList<Format> exportFormats() const = 0; 226 227 // This function is called to initialize the list of additional parameters that a OPENING filter could require 228 // it is called by the framework BEFORE the actual mesh loading to perform to determine how parse the input file 229 // The instanced parameters are then passed to the open at the loading time. 230 // Typical example of use to decide what subportion of a mesh you have to load. 231 // If you do not need any additional processing simply do not override this and ignore the parameterSet in the open initPreOpenParameter(const QString &,const QString &,RichParameterSet &)232 virtual void initPreOpenParameter(const QString &/*format*/, const QString &/*fileName*/, RichParameterSet & /*par*/) {} 233 234 // This function is called to initialize the list of additional parameters that a OPENING filter could require 235 // it is called by the framework AFTER the mesh is already loaded to perform more or less standard processing on the mesh. 236 // typical example: unifying vertices in stl models. 237 // If you do not need any additional processing do nothing. initOpenParameter(const QString &,MeshModel &,RichParameterSet &)238 virtual void initOpenParameter(const QString &/*format*/, MeshModel &/*m*/, RichParameterSet & /*par*/) {} 239 240 // This is the corresponding function that is called after the mesh is loaded with the initialized parameters applyOpenParameter(const QString &,MeshModel &,const RichParameterSet &)241 virtual void applyOpenParameter(const QString &/*format*/, MeshModel &/*m*/, const RichParameterSet &/*par*/) {} 242 243 // This function is called to initialize the list of additional parameters that a SAVING filter could require 244 // it is called by the framework after the mesh is loaded to perform more or less standard processing on the mesh. 245 // typical example: ascii or binary format for ply or stl 246 // If you do not need any additional parameter simply do nothing. initSaveParameter(const QString &,MeshModel &,RichParameterSet &)247 virtual void initSaveParameter(const QString &/*format*/, MeshModel &/*m*/, RichParameterSet & /*par*/) {} 248 249 250 virtual void GetExportMaskCapability(QString &format, int &capability, int &defaultBits) const = 0; 251 252 /// callback used to actually load a mesh from a file 253 virtual bool open( 254 const QString &format, /// the extension of the format e.g. "PLY" 255 const QString &fileName, /// The name of the file to be opened 256 MeshModel &m, /// The mesh that is filled with the file content 257 int &mask, /// a bit mask that will be filled reporting what kind of data we have found in the file (per vertex color, texture coords etc) 258 const RichParameterSet & par, /// The parameters that have been set up in the initPreOpenParameter() 259 vcg::CallBackPos *cb = 0, /// standard callback for reporting progress in the loading 260 QWidget *parent = 0) = 0; /// you should not use this... 261 262 virtual bool save( 263 const QString &format, // the extension of the format e.g. "PLY" 264 const QString &fileName, 265 MeshModel &m, 266 const int mask, // a bit mask indicating what kind of the data present in the mesh should be saved (e.g. you could not want to save normals in ply files) 267 const RichParameterSet & par, 268 vcg::CallBackPos *cb = 0, 269 QWidget *parent = 0) = 0; 270 271 /// This function is invoked by the framework when the import/export plugin fails to give some info to the user about the failure 272 /// io plugins should avoid using QMessageBox for reporting errors. 273 /// Failure should put some meaningful information inside the errorMessage string. errorMsg()274 virtual QString &errorMsg() { return this->errorMessage; } clearErrorString()275 void clearErrorString() { errorMessage.clear(); } 276 277 // this string is used to pass back to the framework error messages in case of failure of a filter apply. 278 // NEVER EVER use a msgbox to say something to the user. 279 QString errorMessage; 280 281 }; 282 283 /** 284 \brief The MeshFilterInterface class provide the interface of the filter plugins. 285 286 */ 287 class MeshFilterInterface : public MeshCommonInterface 288 { 289 public: 290 /** The FilterClass enum represents the set of keywords that must be used to categorize a filter. 291 Each filter can belong to one or more filtering class, or-ed together. 292 */ 293 enum FilterClass 294 { 295 Generic = 0x00000, /*!< Should be avoided if possible. */ // 296 Selection = 0x00001, /*!< select or de-select something, basic operation on selections (like deleting)*/ 297 Cleaning = 0x00002, /*!< Filters that can be used to clean meshes (duplicated vertices etc)*/ 298 Remeshing = 0x00004, /*!< Simplification, Refinement, Reconstruction and mesh optimization*/ 299 FaceColoring = 0x00008, 300 VertexColoring = 0x00010, 301 MeshColoring = 0x00020, 302 MeshCreation = 0x00040, 303 Smoothing = 0x00080, /*!< Stuff that does not change the topology, but just the vertex positions*/ 304 Quality = 0x00100, 305 Layer = 0x00200, /*!< Layers, attributes */ 306 RasterLayer = 0x00400, /*!< Raster Layers, attributes */ 307 Normal = 0x00800, /*!< Normal, Curvature, orientation (rotations and transformations fall here)*/ 308 Sampling = 0x01000, 309 Texture = 0x02000, 310 RangeMap = 0x04000, /*!< filters specific for range map processing*/ 311 PointSet = 0x08000, 312 Measure = 0x10000, /*!< Filters that compute measures and information on meshes.*/ 313 Polygonal = 0x20000, /*!< Filters that works on polygonal and quad meshes.*/ 314 Camera = 0x40000 /*!< Filters that works on shot of mesh and raster.*/ 315 }; 316 317 318 MeshFilterInterface()319 MeshFilterInterface() : MeshCommonInterface(), glContext(NULL) 320 { 321 } ~MeshFilterInterface()322 virtual ~MeshFilterInterface() {} 323 324 325 /** The very short string (a few words) describing each filtering action 326 // This string is used also to define the menu entry 327 */ 328 virtual QString filterName(FilterIDType) const = 0; 329 330 /** The long, formatted string describing each filtering action. 331 // This string is printed in the top of the parameter window 332 // so it should be at least one or two paragraphs long. The more the better. 333 // you can use simple html formatting tags (like "<br>" "<b>" and "<i>") to improve readability. 334 // This string is used in the 'About plugin' dialog and by meshlabserver to create the filter list wiki page and the doxygen documentation of the filters. 335 // Here is the place where you should put you bibliographic references in a form like this: 336 <br> 337 See: <br /> 338 <i>Luiz Velho, Denis Zorin </i><br/> 339 <b>"4-8 Subdivision"</b><br/> 340 CAGD, volume 18, Issue 5, Pages 397-427.<br/> 341 <br> 342 e.g. italic for authors, bold for title (quoted) and plain for bib ref. 343 */ 344 virtual QString filterInfo(FilterIDType filter) const = 0; 345 346 /** The FilterClass describes in which generic class of filters it fits. 347 // This choice affect the submenu in which each filter will be placed 348 // For example filters that perform an action only on the selection will be placed in the Selection Class 349 */ getClass(QAction *)350 virtual FilterClass getClass(QAction *) { return MeshFilterInterface::Generic; } 351 352 /** 353 The filters can have some additional requirements on the mesh capabiliteis. 354 // For example if a filters requires Face-Face Adjacency you should re-implement 355 // this function making it returns MeshModel::MM_FACEFACETOPO. 356 // The framework will ensure that the mesh has the requirements satisfied before invoking the applyFilter function 357 // 358 // Furthermore, requirements are checked just before the invocation of a filter. If your filter 359 // outputs a never used before mesh property (e.g. face colors), it will be allocated by a call 360 // to MeshModel::updateDataMask(...) 361 */ getRequirements(QAction *)362 virtual int getRequirements(QAction *) { return MeshModel::MM_NONE; } 363 364 /** The FilterPrecondition mask is used to explicitate what kind of data a filter really needs to be applied. 365 // For example algorithms that compute per face quality have as precondition the existence of faces 366 // (but quality per face is not a precondition, because quality per face is created by these algorithms) 367 // on the other hand an algorithm that deletes faces according to the stored quality has both FaceQuality 368 // and Face as precondition. 369 // These conditions do NOT include computed properties like borderFlags, manifoldness or watertightness. 370 // They are also used to grayout menus un-appliable entries. 371 */ getPreConditions(QAction *)372 virtual int getPreConditions(QAction *) const { return MeshModel::MM_NONE; } 373 374 /** Function used by the framework to get info about the mesh properties changed by the filter. 375 // It is widely used by the meshlab's preview system. 376 //TO BE REPLACED WITH = 0 377 */ postCondition(QAction *)378 virtual int postCondition(QAction*) const { return MeshModel::MM_ALL; } 379 380 /** \brief applies the selected filter with the already stabilished parameters 381 * This function is called by the framework after getting values for the parameters specified in the \ref InitParameterSet 382 * NO GUI interaction should be done here. No dialog asking, no messagebox errors. 383 * Think that his function will also be called by the commandline framework. 384 * If you want report errors, use the \ref errorMsg() string. It will displayed in case of filters returning false. 385 * When implementing your applyFilter, you should use the cb function to report to the framework the current state of the processing. 386 * During your (long) processing you should call from time to time cb(perc,descriptiveString), where perc is an int (0..100) 387 * saying what you are doing and at what point of the computation you currently are. 388 * \sa errorMsg 389 * \sa initParameterSet 390 */ 391 virtual bool applyFilter(QAction * filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb) = 0; 392 393 /** \brief tests if a filter is applicable to a mesh. 394 This function is a handy wrapper used by the framework for the \a getPreConditions callback; 395 For instance a colorize by quality filter cannot be applied to a mesh without per-vertex-quality. 396 On failure (returning false) the function fills the MissingItems list with strings describing the missing items. 397 */ 398 bool isFilterApplicable(QAction *act, const MeshModel& m, QStringList &MissingItems) const; 399 400 401 enum FILTER_ARITY { NONE = 0, SINGLE_MESH = 1, FIXED = 2, VARIABLE = 3, UNKNOWN_ARITY = 4 }; 402 403 /** \brief this function informs the MeshLab core on how many meshes the filter will work on. 404 Valid value: 405 - SINGLE_MESH: the filter works just on the current mesh 406 - FIXED: the number (and the names) of the meshes involved in the filter computation is determined by the parameters selected in the filter's parameters form 407 - VARIABLE: the filter works on a not predetermined number of meshes. The meshes involved are typically selected by the user checking on the correspondent layer on the layer dialog 408 */ 409 virtual FILTER_ARITY filterArity(QAction *act) const = 0; 410 411 // This function is called to initialized the list of parameters. 412 // it is always called. If a filter does not need parameter it leave it empty and the framework 413 // will not create a dialog (unless for previewing) initParameterSet(QAction *,MeshModel &,RichParameterSet &)414 virtual void initParameterSet(QAction *, MeshModel &/*m*/, RichParameterSet & /*par*/) {} initParameterSet(QAction * filter,MeshDocument & md,RichParameterSet & par)415 virtual void initParameterSet(QAction *filter, MeshDocument &md, RichParameterSet &par) 416 { 417 initParameterSet(filter, *(md.mm()), par); 418 } 419 420 /** \brief is invoked by the framework when the applyFilter fails to give some info to the user about the filter failure 421 * Filters \b must never use QMessageBox for reporting errors. 422 * Failing filters should put some meaningful information inside the errorMessage string and return false with the \ref applyFilter 423 */ errorMsg()424 const QString &errorMsg() { return this->errorMessage; } filterInfo(QAction * a)425 virtual QString filterInfo(QAction *a) const { return this->filterInfo(ID(a)); } filterName(QAction * a)426 virtual QString filterName(QAction *a) const { return this->filterName(ID(a)); } filterScriptFunctionName(FilterIDType)427 virtual QString filterScriptFunctionName(FilterIDType /*filterID*/) { return ""; } 428 ID(QAction * a)429 virtual FilterIDType ID(QAction *a) const 430 { 431 QString aa=a->text(); 432 foreach(FilterIDType tt, types()) 433 if (a->text() == this->filterName(tt)) return tt; 434 aa.replace("&",""); 435 foreach(FilterIDType tt, types()) 436 if (aa == this->filterName(tt)) return tt; 437 438 qDebug("unable to find the id corresponding to action '%s'", qUtf8Printable(a->text())); 439 assert(0); 440 return -1; 441 } 442 AC(FilterIDType filterID)443 virtual QAction *AC(FilterIDType filterID) 444 { 445 QString idName = this->filterName(filterID); 446 return AC(idName); 447 } 448 AC(QString idName)449 virtual QAction *AC(QString idName) 450 { 451 QString i=idName; 452 foreach(QAction *tt, actionList) 453 if (idName == tt->text()) return tt; 454 i.replace("&",""); 455 foreach(QAction *tt, actionList) 456 if (i == tt->text()) return tt; 457 458 qDebug("unable to find the action corresponding to action '%s'", qUtf8Printable(idName)); 459 assert(0); 460 return 0; 461 } 462 actions()463 virtual QList<QAction *> actions() const { return actionList; } types()464 virtual QList<FilterIDType> types() const { return typeList; } 465 466 /** Generate the mask of attributes would be created IF the MeshFilterInterface filt would has been called on MeshModel mm 467 BE CAREFUL! this function does NOT change in anyway the state of the MeshModel!!!! **/ 468 int previewOnCreatedAttributes(QAction* act, const MeshModel& mm); 469 QString generatedScriptCode; 470 471 MLPluginGLContext* glContext; 472 protected: 473 // Each plugins exposes a set of filtering possibilities. 474 // Each filtering procedure corresponds to a single QAction with a corresponding FilterIDType id. 475 // 476 477 // The list of actions exported by the plugin. Each actions strictly corresponds to 478 QList <QAction *> actionList; 479 480 QList <FilterIDType> typeList; 481 482 // this string is used to pass back to the framework error messages in case of failure of a filter apply. 483 QString errorMessage; 484 }; 485 486 487 /** 488 Used to customized the rendering process. 489 Rendering plugins are now responsible of the rendering of the whole MeshDocument and not only of a single MeshModel. 490 491 The Render function is called in with the ModelView and Projection Matrices already set up, screen cleared and background drawn. 492 After the Render call the MeshLab frawework draw on the opengl context other decorations and the trackball, so it there is the 493 requirement for a rendering plugin is that it should leave the z-buffer in a coherent state. 494 495 The typical rendering loop of a Render plugin is something like, : 496 497 <your own opengl setup> 498 499 foreach(MeshModel * mp, meshDoc.meshList) 500 { 501 if(mp->visible) mp->Render(rm.drawMode,rm.colorMode,rm.textureMode); 502 } 503 504 */ 505 506 class MeshRenderInterface : public MeshCommonInterface 507 { 508 public: MeshRenderInterface()509 MeshRenderInterface() :MeshCommonInterface() {} ~MeshRenderInterface()510 virtual ~MeshRenderInterface() {} 511 Init(QAction *,MeshDocument &,MLSceneGLSharedDataContext::PerMeshRenderingDataMap &,GLArea *)512 virtual void Init(QAction *, MeshDocument &, MLSceneGLSharedDataContext::PerMeshRenderingDataMap& /*mp*/, GLArea *) {} 513 virtual void Render(QAction *, MeshDocument &, MLSceneGLSharedDataContext::PerMeshRenderingDataMap& mp, GLArea *) = 0; Finalize(QAction *,MeshDocument *,GLArea *)514 virtual void Finalize(QAction *, MeshDocument *, GLArea *) {} 515 virtual bool isSupported() = 0; 516 virtual QList<QAction *> actions() = 0; 517 }; 518 /** 519 MeshDecorateInterface is the base class of all <b> decorators </b> 520 Decorators are 'read-only' visualization aids that helps to show some data about a document. 521 Decorators can make some permesh precomputation but the rendering has to be efficient. 522 Decorators should save the additional data into per-mesh attribute. 523 524 525 There are two classes of Decorations 526 - PerMesh 527 - PerDocument 528 529 PerMesh Decorators are associated to each mesh/view 530 Some example of PerDocument Decorations 531 - backgrounds 532 - trackball icon 533 - axis 534 - shadows 535 - screen space Ambient occlusion (think it as a generic 'darkner') 536 537 Some example of PerMesh Decorations 538 - coloring of selected vertex/face 539 - displaying of normals/curvature directions 540 - display of specific tagging 541 */ 542 543 class MeshDecorateInterface : public MeshCommonInterface 544 { 545 public: 546 547 /** The DecorationClass enum represents the set of keywords that must be used to categorize a filter. 548 Each filter can belong to one or more filtering class, or-ed together. 549 */ 550 enum DecorationClass 551 { 552 Generic = 0x00000, /*!< Should be avoided if possible. */ // 553 PerMesh = 0x00001, /*!< Decoration that are applied on a single mesh */ 554 PerDocument = 0x00002, /*!< Decoration that are applied on a single mesh */ 555 PreRendering = 0x00004, /*!< Decoration that are applied <i>before</i> the rendering of the document/mesh */ 556 PostRendering = 0x00008 /*!< Decoration that are applied <i>after</i> the rendering of the document/mesh */ 557 }; 558 MeshDecorateInterface()559 MeshDecorateInterface() : MeshCommonInterface() {} ~MeshDecorateInterface()560 virtual ~MeshDecorateInterface() {} 561 /** The very short string (a few words) describing each filtering action 562 // This string is used also to define the menu entry 563 */ 564 virtual QString decorationName(FilterIDType) const = 0; 565 virtual QString decorationInfo(FilterIDType) const = 0; 566 decorationName(QAction * a)567 virtual QString decorationName(QAction *a) const { return decorationName(ID(a)); } decorationInfo(QAction * a)568 virtual QString decorationInfo(QAction *a) const { return decorationInfo(ID(a)); } 569 570 startDecorate(QAction *,MeshDocument &,RichParameterSet *,GLArea *)571 virtual bool startDecorate(QAction *, MeshDocument &, RichParameterSet *, GLArea *) { return false; } startDecorate(QAction *,MeshModel &,RichParameterSet *,GLArea *)572 virtual bool startDecorate(QAction *, MeshModel &, RichParameterSet *, GLArea *) { return false; } 573 virtual void decorateMesh(QAction *, MeshModel &, RichParameterSet *, GLArea *, QPainter *, GLLogStream &) = 0; 574 virtual void decorateDoc(QAction *, MeshDocument &, RichParameterSet *, GLArea *, QPainter *, GLLogStream &) = 0; endDecorate(QAction *,MeshModel &,RichParameterSet *,GLArea *)575 virtual void endDecorate(QAction *, MeshModel &, RichParameterSet *, GLArea *) {} endDecorate(QAction *,MeshDocument &,RichParameterSet *,GLArea *)576 virtual void endDecorate(QAction *, MeshDocument &, RichParameterSet *, GLArea *) {} 577 578 /** \brief tests if a decoration is applicable to a mesh. 579 * used only for PerMesh Decorators. 580 For instance curvature cannot be shown on a mesh without curvature. 581 On failure (returning false) the function fills the MissingItems list with strings describing the missing items. 582 It is invoked only for decoration of \i PerMesh class; 583 */ isDecorationApplicable(QAction *,const MeshModel &,QString &)584 virtual bool isDecorationApplicable(QAction *, const MeshModel&, QString&) const { return true; } 585 586 virtual int getDecorationClass(QAction *) const = 0; 587 actions()588 virtual QList<QAction *> actions() const { return actionList; } types()589 virtual QList<FilterIDType> types() const { return typeList; } 590 protected: 591 QList <QAction *> actionList; 592 QList <FilterIDType> typeList; ID(QAction * a)593 virtual FilterIDType ID(QAction *a) const 594 { 595 QString aa=a->text(); 596 foreach(FilterIDType tt, types()) 597 if (a->text() == this->decorationName(tt)) return tt; 598 aa.replace("&",""); 599 foreach(FilterIDType tt, types()) 600 if (aa == this->decorationName(tt)) return tt; 601 602 qDebug("unable to find the id corresponding to action '%s'", qUtf8Printable(a->text())); 603 assert(0); 604 return -1; 605 } ID(QString name)606 virtual FilterIDType ID(QString name) const 607 { 608 QString n = name; 609 foreach(FilterIDType tt, types()) 610 if (name == this->decorationName(tt)) return tt; 611 n.replace("&",""); 612 foreach(FilterIDType tt, types()) 613 if (n == this->decorationName(tt)) return tt; 614 615 qDebug("unable to find the id corresponding to action '%s'", qUtf8Printable(name)); 616 assert(0); 617 return -1; 618 } 619 public: action(QString name)620 virtual QAction *action(QString name) const 621 { 622 QString n = name; 623 foreach(QAction *tt, actions()) 624 if (name == this->decorationName(ID(tt))) return tt; 625 n.replace("&",""); 626 foreach(QAction *tt, actions()) 627 if (n == this->decorationName(ID(tt))) return tt; 628 629 qDebug("unable to find the id corresponding to action '%s'", qUtf8Printable(name)); 630 return 0; 631 } 632 }; 633 634 635 /* 636 Editing Interface 637 Used to provide tools that needs some kind of interaction with the mesh. 638 Editing tools are exclusive (only one at a time) and can grab the mouse events and customize the rendering process. 639 */ 640 641 class MeshEditInterface : public MeshCommonInterface 642 { 643 public: MeshEditInterface()644 MeshEditInterface() : MeshCommonInterface() {} ~MeshEditInterface()645 virtual ~MeshEditInterface() {} 646 647 //should return a sentence describing what the editing tool does 648 static const QString Info(); 649 suggestedRenderingData(MeshModel &,MLRenderingData &)650 virtual void suggestedRenderingData(MeshModel &/*m*/, MLRenderingData& /*dt*/) {} 651 652 // Called when the user press the first time the button StartEdit(MeshModel &,GLArea *,MLSceneGLSharedDataContext *)653 virtual bool StartEdit(MeshModel &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/) { return true; } StartEdit(MeshDocument & md,GLArea * parent,MLSceneGLSharedDataContext * cont)654 virtual bool StartEdit(MeshDocument &md, GLArea *parent, MLSceneGLSharedDataContext* cont) 655 { 656 //assert(NULL != md.mm()); 657 if (md.mm() != NULL) 658 return (StartEdit(*(md.mm()), parent, cont)); 659 else return false; 660 } 661 // Called when the user press the second time the button EndEdit(MeshModel &,GLArea *,MLSceneGLSharedDataContext *)662 virtual void EndEdit(MeshModel &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/) {} EndEdit(MeshDocument &,GLArea *,MLSceneGLSharedDataContext *)663 virtual void EndEdit(MeshDocument &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/) {} 664 665 // There are two classes of editing tools, the one that works on a single layer at a time 666 // and the ones that works on all layers and have to manage in a correct way the action of changing the current layer. 667 // For the edit tools that works ona single layer changing the layer means the restart of the edit tool. isSingleMeshEdit()668 virtual bool isSingleMeshEdit() const { return true; } 669 670 // Called when the user changes the selected layer 671 //by default it calls end edit with the layer that was selected and start with the new layer that is 672 //selected. This ensures that plugins who don't support layers do not get sent pointers to meshes 673 //they are not expecting. 674 // If your editing plugins is not singleMesh you MUST reimplement this to correctly handle the change of layer. LayerChanged(MeshDocument & md,MeshModel & oldMeshModel,GLArea * parent,MLSceneGLSharedDataContext * cont)675 virtual void LayerChanged(MeshDocument &md, MeshModel &oldMeshModel, GLArea *parent, MLSceneGLSharedDataContext* cont) 676 { 677 assert(this->isSingleMeshEdit()); 678 EndEdit(oldMeshModel, parent, cont); 679 StartEdit(md, parent, cont); 680 } 681 Decorate(MeshModel & m,GLArea * parent,QPainter *)682 virtual void Decorate(MeshModel &m, GLArea *parent, QPainter * /*p*/) { Decorate(m, parent); } Decorate(MeshModel &,GLArea *)683 virtual void Decorate(MeshModel &/*m*/, GLArea * /*parent*/) {} 684 685 virtual void mousePressEvent(QMouseEvent *event, MeshModel &/*m*/, GLArea *) = 0; 686 virtual void mouseMoveEvent(QMouseEvent *event, MeshModel &/*m*/, GLArea *) = 0; 687 virtual void mouseReleaseEvent(QMouseEvent *event, MeshModel &/*m*/, GLArea *) = 0; keyReleaseEvent(QKeyEvent *,MeshModel &,GLArea *)688 virtual void keyReleaseEvent(QKeyEvent *, MeshModel &/*m*/, GLArea *) {} keyPressEvent(QKeyEvent *,MeshModel &,GLArea *)689 virtual void keyPressEvent(QKeyEvent *, MeshModel &/*m*/, GLArea *) {} wheelEvent(QWheelEvent *,MeshModel &,GLArea *)690 virtual void wheelEvent(QWheelEvent*, MeshModel &/*m*/, GLArea *) {} tabletEvent(QTabletEvent * e,MeshModel &,GLArea *)691 virtual void tabletEvent(QTabletEvent * e, MeshModel &/*m*/, GLArea *) { e->ignore(); } 692 }; 693 694 695 /** MeshEditInterfaceFactory 696 \short The MeshEditInterfaceFactory class is a <i>factory</i> is used to generate a object for each starting of an editing filter. 697 698 This is needed because editing filters have a internal state, so if you want to have an editing tool for two different documents you have to instance two objects. 699 This class is used by the framework to generate an independent MeshEditInterface for each document. 700 */ 701 class MeshEditInterfaceFactory 702 { 703 public: ~MeshEditInterfaceFactory()704 virtual ~MeshEditInterfaceFactory() {} 705 706 //gets a list of actions available from this plugin 707 virtual QList<QAction *> actions() const = 0; 708 709 //get the edit tool for the given action 710 virtual MeshEditInterface* getMeshEditInterface(QAction *) = 0; 711 712 //get the description for the given action 713 virtual QString getEditToolDescription(QAction *) = 0; 714 715 }; 716 717 718 719 /**************************************************************************************************************************************************************/ 720 /*The new class of filter defined through XML file*/ 721 722 typedef bool SignalCallBack(); 723 724 class MeshLabFilterInterface : public QObject, public MeshLabInterface 725 { 726 Q_OBJECT 727 public: 728 MeshLabFilterInterface(); ~MeshLabFilterInterface()729 virtual ~MeshLabFilterInterface() {} 730 731 MLPluginGLContext* glContext; 732 733 static void initConvertingMap(QMap<QString, MeshModel::MeshElement>& convertingMap); 734 static void initConvertingCategoryMap(QMap<QString, MeshFilterInterface::FilterClass>& convertingMap); 735 static bool arePreCondsValid(const int filterPreConds, const MeshModel& m, QStringList &MissingItems); 736 static int convertStringListToMeshElementEnum(const QStringList& stringListEnum); 737 static int convertStringListToCategoryEnum(const QStringList& stringListEnum); 738 virtual bool applyFilter(const QString& filterName, MeshDocument& md, EnvWrap& env, vcg::CallBackPos* cb) = 0; errorMsg()739 const QString &errorMsg() { return this->errorMessage; } 740 public slots: setInterrupt(const bool & inter)741 inline void setInterrupt(const bool& inter) { intteruptreq = inter; }; 742 743 protected: 744 ////This function has two different aims: 745 ////1) should be invoked by filters in order to request a redraw of a subset of meshes and/or rasters inside the MeshDocument. 746 ////2) like a synchronization point where the filter can safely stop is execution. 747 ////if filter has not a pending interrupt request a render state update request will be sent to the framework. 748 ////return value: true if the request has been sent, false otherwise (filter has an interrupt request). 749 750 //bool sendUpdateRequest(const MeshDocument& md,); 751 752 //QList<int> meshestobeupdated; 753 //int meshmaskattributestobeupdated; 754 //QList<int> rasterstobeupdated; 755 //int rastermaskattributestobeupdated; 756 757 // this string is used to pass back to the framework error messages in case of failure of a filter apply. 758 QString errorMessage; 759 bool intteruptreq; 760 signals: 761 void renderingDataRequested(int); 762 void updateDecorators(int); 763 }; 764 765 #if (QT_VERSION >= 0x050000) 766 #define MESHLAB_PLUGIN_IID_EXPORTER(x) Q_PLUGIN_METADATA(IID x) 767 #define MESHLAB_PLUGIN_NAME_EXPORTER(x) 768 #else 769 #define MESHLAB_PLUGIN_IID_EXPORTER(x) 770 #define MESHLAB_PLUGIN_NAME_EXPORTER(x) Q_EXPORT_PLUGIN(x) 771 #endif 772 773 774 775 #define MESH_IO_INTERFACE_IID "vcg.meshlab.MeshIOInterface/1.0" 776 #define MESH_FILTER_INTERFACE_IID "vcg.meshlab.MeshFilterInterface/1.0" 777 #define MESHLAB_FILTER_INTERFACE_IID "vcg.meshlab.MeshLabFilterInterface/1.0" 778 #define MESH_RENDER_INTERFACE_IID "vcg.meshlab.MeshRenderInterface/1.0" 779 #define MESH_DECORATE_INTERFACE_IID "vcg.meshlab.MeshDecorateInterface/1.0" 780 #define MESH_EDIT_INTERFACE_IID "vcg.meshlab.MeshEditInterface/1.0" 781 #define MESH_EDIT_INTERFACE_FACTORY_IID "vcg.meshlab.MeshEditInterfaceFactory/1.0" 782 783 Q_DECLARE_INTERFACE(MeshIOInterface, MESH_IO_INTERFACE_IID) 784 Q_DECLARE_INTERFACE(MeshFilterInterface, MESH_FILTER_INTERFACE_IID) 785 Q_DECLARE_INTERFACE(MeshLabFilterInterface, MESHLAB_FILTER_INTERFACE_IID) 786 Q_DECLARE_INTERFACE(MeshRenderInterface, MESH_RENDER_INTERFACE_IID) 787 Q_DECLARE_INTERFACE(MeshDecorateInterface, MESH_DECORATE_INTERFACE_IID) 788 Q_DECLARE_INTERFACE(MeshEditInterface, MESH_EDIT_INTERFACE_IID) 789 Q_DECLARE_INTERFACE(MeshEditInterfaceFactory, MESH_EDIT_INTERFACE_FACTORY_IID) 790 791 #endif 792