Tuesday, October 14, 2008

Sample Plugin 1

Overview:

This is a generic template tool which places an empty docking window on the screen. It can respond to events such as when items are deleted, inserted, or when items intersect with each other. The tool can also respond to any of the signals in the main window or in any of the other plugins; I have just selected these for demonstration. 

If you want to use features from another plugin, you will need to check whether or not that plugin has already been loaded. If it has not been loaded, you will need to listen to the pluginsLoaded signal. Note how the collision detection plugin is detected using the pluginsLoaded function.

The very last function, loadTCTool, is what actually loads the plugin into Tinkercell. 

Loading the plugin into Tinkercell:

In order to compile and run the example plug-in, follow these steps:
  1. Download and install Qt toolkit.
  2. Download the TinkerCell source:                                                                                                svn checkout http://tinkercell.googlecode.com/svn/trunk/ tinkercell-read-only
  3. Create three files in your Tinkercell folder: MyPlugin.h, MyPlugin.cpp and MyPlugin.pro. 
  4. Copy & paste the code for each from this blog (below)
  5. Execute the following commands: qmake -config release MyPlugin.pro and make
  6. You can add the line "MyPlugin" to the DefaultLibraries.txt file.
  7. OR You can drag-and-drog the library file on TinkerCell's toolbar

CODE:

--------------------
MyPlugin.h
--------------------
#ifndef TINKERCELL_MYTOOL_H
#define TINKERCELL_MYTOOL_H

#include "Core/MainWindow.h"
#include "Core/GraphicsScene.h"
#include "Core/ItemHandle.h"
#include "Core/Tool.h"
#include "BasicTools/CollisionDetection.h"

namespace Tinkercell
{

 class MyTool: public Tool
 {
     Q_OBJECT

 public:
     MyTool();
     ~MyTool();
     bool setMainWindow(MainWindow * main);
     QSize sizeHint() const;
 public slots:
     void itemsSelected(GraphicsScene * , QList< QGraphicsItem* >& , QPointF point, Qt::KeyboardModifiers );
     void itemsRemoved(GraphicsScene * , QList< QGraphicsItem* >& , QList< ItemHandle* > &);
     void partCollided(QList< QGraphicsItem* >& , PartGraphicsItem * , QPointF , Qt::KeyboardModifiers );
     void pluginLoaded(const QString&);
private:
     void connectCollisionDetector();
 };

} //end namespace

#endif

#ifdef Q_WS_WIN
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif

extern "C" MY_EXPORT void loadTCTool(Tinkercell::MainWindow * main);


--------------------
MyPlugin.cpp
--------------------
#include "MyPlugin.h"

namespace Tinkercell
{

MyTool:: MyTool() : Tool(tr("My Great Tool"))
{
     //initialize your variables
}

MyTool::~MyTool() { }

bool MyTool::setMainWindow(MainWindow * main)
{
 Tool::setMainWindow(main);
 if (mainWindow)
 {
  connect(mainWindow,SIGNAL(itemsSelected(GraphicsScene*, QList< QGraphicsItem* >&, QPointF, Qt::KeyboardModifiers)),
    this,SLOT(itemsSelected(GraphicsScene*, QList < QGraphicsItem* >&, QPointF, Qt::KeyboardModifiers)));

  connect(mainWindow,SIGNAL(itemsRemoved(GraphicsScene *, QList < QGraphicsItem* >&, QList < ItemHandle* >&)),
    this,SLOT(itemsRemoved(GraphicsScene *, QList< QGraphicsItem* >&, QList< ItemHandle* >&)));

  QDockWidget* dock = mainWindow->addDockingWindow(name,this,Qt::RightDockWidgetArea);

  connectCollisionDetector();

  connect(mainWindow,SIGNAL(pluginLoaded(const QString&)),this,SLOT(pluginLoaded(const QString&)));

  return true;
 }
 return false;
}

void MyTool::pluginLoaded(const QString&)
{
    connectCollisionDetector();
}

void MyTool::connectCollisionDetector()
{
 static bool alreadyConnected = false;
 if (alreadyConnected || !mainWindow) return;
 if (mainWindow->tools.contains(tr("Collision Detection")))
 {
   QWidget * widget = mainWindow->tools[tr("Collision Detection")];
   CollisionDetection * collisionDetection = static_cast <  CollisionDetection* >(widget);
    if (collisionDetection)
    { 
      alreadyConnected = true;
      connect(collisionDetection,SIGNAL(partCollided(QList < QGraphicsItem* >& , PartGraphicsItem * , QPointF , Qt::KeyboardModifiers )),
          this, SLOT( partCollided(QList < QGraphicsItem* >& , PartGraphicsItem * , QPointF , Qt::KeyboardModifiers )));
    }
  }
}

void MyTool::itemsSelected(GraphicsScene * scene, QList < QGraphicsItem* >& items, QPointF , Qt::KeyboardModifiers )
{
    if (!scene || items.isEmpty()) return;
    //do something when items are selected
}

void MyTool::partCollided(QList < QGraphicsItem* >& movingItems, PartGraphicsItem * partHit, QPointF , Qt::KeyboardModifiers )
{
   if (!mainWindow || !partHit) return;
   GraphicsScene * scene = currentScene();
   if (!scene) return;

   ItemHandle * handle = getHandle(partHit);

   //do something when two parts collide
}

void MyTool::itemsRemoved(GraphicsScene * scene, QList < QGraphicsItem* >&, QList< ItemHandle* >& handles)
{
 if (!mainWindow || !scene) return;
 //do something when items are removed
}

QSize MyTool::sizeHint() const
{
    //set size of docking window
    return QSize(100, 300);
}

}


extern "C" MY_EXPORT void loadTCTool(Tinkercell::MainWindow * main)
{
   if (!main) return;
 
   if (!main->tools.contains("My Great Tool"))
   {
      Tinkercell::MyTool * mytool = new Tinkercell:: MyTool ;
      mytool->setMainWindow(main);
   }
} //end namespace


--------------------
MyPlugin.pro
--------------------

TEMPLATE = lib
DEPENDPATH += . debug tmp\rcc\debug_shared tmp\rcc\release_shared
INCLUDEPATH += . Core PartsTree BasicTools
CONFIG += release debug
unix:CONFIG += warn_off
RESOURCES   = Tinkercell.qrc
unix:LIBS += -L. -lTinkercell
win32:LIBS += Tinkercell.dll
mac:QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.4u.sdk
mac:CONFIG+=x86 ppc
# Input
HEADERS += MyPlugin.h
   
SOURCES += MyPlugin.cpp
   
QT += xml

No comments: