天天看點

CC插件初探

1、實作一個應用程式插架架構關鍵點有:

一個插件的标準接口,在主程式中存在一個插件的集合。主程式通過循環讀取每個插件,将插件對象通過多态的機制轉換為插件接口,實作插件的裝載。

主程式對象或者主程式接口需要作為參數傳遞到插件對象中,以友善插件對象調用主程式的内容,如主視圖、工具欄、樹視圖、狀态欄等。

2、開源點雲處理軟體CloudCompare也是一個插件架構,是以也必然包括這些内容。

插件接口:ccPluginInterface,每個插件對象有在ccPluginInterface基礎上定義了一個新的接口類class ccStdPluginInterface : public ccPluginInterface

具體的插件則繼承自ccStdPluginInterface 累,比如這樣,class qMyPlugin : public QObject, public ccStdPluginInterface

主程式對象:class ccMainAppInterface,MainWindow主窗體類實作了ccMainAppInterface接口。

MainWindow::loadPlugins()方法負責插件的調用。(mainwindow.cpp檔案中)

複制代碼

1 void MainWindow::loadPlugins()

2 {

3 menuPlugins->setEnabled(false);

4 menuShadersAndFilters->setEnabled(false);

5 toolBarPluginTools->setVisible(false);

6 toolBarGLFilters->setVisible(false);

7

8 //“static” plugins

9 foreach (QObject plugin, QPluginLoader::staticInstances())

10 dispatchPlugin(plugin);

11

12 ccConsole::Print(QString(“Application path: “)+QCoreApplication::applicationDirPath());

13

14 #if defined(Q_OS_MAC)

15 // plugins are in the bundle

16 QString path = QCoreApplication::applicationDirPath();

17 path.remove( “MacOS” );

18 m_pluginsPath = path + “Plugins/ccPlugins”;

19 #else

20 //plugins are in bin/plugins

21 m_pluginsPath = QCoreApplication::applicationDirPath()+QString(”/plugins”);

22 #endif

23

24 ccConsole::Print(QString(“Plugins lookup dir.: %1”).arg(m_pluginsPath));

25

26 QStringList filters;

27 #if defined(Q_OS_WIN)

28 filters << ".dll";

29 #elif defined(Q_OS_LINUX)

30 filters << “.so";

31 #elif defined(Q_OS_MAC)

32 filters << ".dylib”;

33 #endif

34 QDir pluginsDir(m_pluginsPath);

35 pluginsDir.setNameFilters(filters);

36 foreach (QString filename, pluginsDir.entryList(filters))

37 {

38 QPluginLoader loader(pluginsDir.absoluteFilePath(filename));

39 QObject* plugin = loader.instance();

40 if (plugin)

41 {

42 ccConsole::Print(QString(“Found new plugin: ‘%1’”).arg(filename));

43 if (dispatchPlugin(plugin))

44 {

45 m_pluginFileNames += filename;

46 }

47 else

48 {

49 delete plugin;

50 plugin = 0;

51 ccConsole::Warning("\tUnsupported or invalid plugin type");

52 }

53 }

54 else

55 {

56 delete plugin;

57 plugin = 0;

58 ccConsole::Warning(QString("[Plugin] %1")/.arg(pluginsDir.absoluteFilePath(filename))/.arg(loader.errorString()));

59 }

60 }

61

62 if (menuPlugins)

63 {

64 menuPlugins->setEnabled(!m_stdPlugins.empty());

65 }

66

67 if (toolBarPluginTools->isEnabled())

68 {

69 actionDisplayPluginTools->setEnabled(true);

70 actionDisplayPluginTools->setChecked(true);

71 }

72 else

73 {

74 //DGM: doesn’t work ?

75 //actionDisplayPluginTools->setChecked(false);

76 }

77

78 if (toolBarGLFilters->isEnabled())

79 {

80 actionDisplayGLFiltersTools->setEnabled(true);

81 actionDisplayGLFiltersTools->setChecked(true);

82 }

83 else

84 {

85 //DGM: doesn’t work ?

86 //actionDisplayGLFiltersTools->setChecked(false);

87 }

88 }

複制代碼

      主程式在加載插件時會調用插件的setMainAppInterface方法,将主程式參數傳入,這樣插件就可以擷取主程式的内容了。

1 //! Sets application entry point

2 /** Called just after plugin creation by qCC

3 */

4 virtual void setMainAppInterface(ccMainAppInterface app);

3、擷取主窗體中的點雲圖層

在doAction中的代碼:

複制代碼

1 const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();

2 size_t selNum = selectedEntities.size();

3 if (selNum!=1)

4 {

5 m_app->dispToConsole(“Select only one cloud!”,ccMainAppInterface::ERR_CONSOLE_MESSAGE);

6 return;

7 }

8

9 ccHObject* ent = selectedEntities[0];

10 assert(ent);

11 if (!ent || !ent->isA(CC_TYPES::POINT_CLOUD))

12 {

13 m_app->dispToConsole(“Select a real point cloud!”,ccMainAppInterface::ERR_CONSOLE_MESSAGE);

14 return;

15 }

16

17 ccPointCloud* pc = static_cast<ccPointCloud*>(ent);

18

19 //input cloud

20 unsigned count = pc->size();

21 bool hasNorms = pc->hasNormals();

22 CCVector3 bbMin, bbMax;

23 pc->getBoundingBox(bbMin,bbMax);

24 const CCVector3d& globalShift = pc->getGlobalShift();

25 double globalScale = pc->getGlobalScale();

複制代碼