calling a function of a plugin from an other plugin [SOLVED]

darkdesiredarkdesire Posts: 39

Hello

is it possible to call a plugin function from an other plugin (2 plugins i'm developping) ? is yes, how can it be ?

thank you

Post edited by darkdesire on

Comments

  • Richard HaseltineRichard Haseltine Posts: 107,953

    Well, if they have exposed their methods or members to scripting certainly - I don'tknow how the SDK would handle the equivalent. But it would be dependent on the other plug-in, not everything will be exposed and in some cases nothing will (aside from things like seriailisation routines, if needed)

  • surrealsurreal Posts: 198

    darkdesire said:

    is it possible to call a plugin function from an other plugin (2 plugins i'm developping) ? is yes, how can it be ?

    A function belongs to some instance of a class.
    Is that class going to be [1] the plugin itself or [2] someting that the plugin creates (ie. a DzAction or a DzPane ...) or [3] is the plugin just going to provide a class that you will need to create an instance of before calling your function, etc...?

        [1] see DzPluginMgr and DzPlugin

        [2] see DzActionMgr or DzPaneMgr, etc...

        [3] create your own manager i.e. how and by who will the created instances/objects be managed? see DzBase

    Some things you may want to think about.
    Who and what should be able to call your function i.e. everybody via plugin or script, everybody but only by other plugins, only your plugins? Is the function going to create any artifacts and how are those artifacts going to be managed and cleaned up? How many times will it be called and can it be called concurrently?

  • darkdesiredarkdesire Posts: 39

    i have a personal plugin and i need to call a function in an other plugn of mine

    thank you

  • surrealsurreal Posts: 198

    darkdesire said:

    i have a personal plugin and i need to call a function in an other plugn of mine

    So you have subclassed DzPlugin and used the DZ_CUSTOM_PLUGIN_DEFINITION() to create the other plugin.     see SDK documentation "DAZ Studio Plug-in Architecture".
    Using DzPluginMgr to find your other plugin and then dynamic casting it to your other plugin class so that you can call the function, is the simple part. 

    I have never found the need to go down that path myself. I have usually chosen to use the simpler process [2] of subclassing DzAction or DzNode or other managed objects,

  • vectorinusvectorinus Posts: 138

    That's right. You create a subclass. In it, you declare the function you need as a SLOT (public:) and associate it with a certain signal. When you are in Daz Studio, get a pointer to the object of your first plugin using the corresponding manager (DzActionMgr or DzPaneMgr, etc...) and call its function from your second plugin by sending the mentioned signal. Although in QT it may not even be necessary to get the pointer to the object of the first plugin. It may be enough to simply send the corresponding signal from the second plugin. I don't remember exactly.

  • darkdesiredarkdesire Posts: 39

    Many thank you, i'll try asap.

  • darkdesiredarkdesire Posts: 39
    edited March 24

    Wll i've tried DzMainWindow::getPaneMgr(). to obtain the panemgr but i dosen't work, the compilation returns 

    Erreur C2352 'DzMainWindow::getPaneMgr' : appel non conforme d'une fonction membre non static autolimb C:\xxxxxxxx\perso\daz3d\mes plugind\autolimb\autolimb.cpp 179

    Post edited by darkdesire on
  • darkdesiredarkdesire Posts: 39

    found: panemgr = dzApp->getInterface()->getPaneMgr();

  • darkdesiredarkdesire Posts: 39

    So, i've a slot function attach to tmy class ManagerGenesis (first plugin):

    public slots:

       void GenereAleaPosition();

    in my second plugin, i've:

    panemgr = dzApp->getInterface()->getPaneMgr();

    if (panemgr)

      {

        dzApp->log("Found a panemgr");

        gg= panemgr->findPane("MAnageGenesis");

        if (gg)

        {

          dzApp->log("Found MAnageGenesis");

        }

    in the log, it writes "found ManageGenesis so ti found it, how call the slot ? connect ? 

  • vectorinusvectorinus Posts: 138
    Dear friend, you have very competently defined the Pane Manager. And it is very gratifying that your plugin was defined in the log file. I will have to climb into my old plugin again, abandoned by me about a year ago, to see how I created calls to functions from foreign classes of my plugin, as well as calls to functions of foreign objects of Daz Studio. Now I do not have time and ask for a day for this. I just want to say that development in Daz SDK assumes preliminary familiarization with programming in QT, on which Daz SDK is based. You should not rack your brains over all the numerous concepts of QT, but the slot-signal concept is one of the most important, allowing you to link objects together both within one plugin and within the entire application, such as DzApp (Daz Studio in essence).
  • darkdesiredarkdesire Posts: 39

    Many thanks again for your help. no problem it's not urgent.

    cheers

  • Richard HaseltineRichard Haseltine Posts: 107,953
    edited March 24

    darkdesire said:

    found: panemgr = dzApp->getInterface()->getPaneMgr();

    Error check - if, for  example, DS is running wityhout a UI then getInterface() will return a null and so getPaneMgr() will crash on being called on a null pointer. It is very rarely a good idea to chain things together without validating the returns from the earlier steps.

    Post edited by Richard Haseltine on
  • Richard HaseltineRichard Haseltine Posts: 107,953

    darkdesire said:

    Wll i've tried DzMainWindow::getPaneMgr(). to obtain the panemgr but i dosen't work, the compilation returns 

    Erreur C2352 'DzMainWindow::getPaneMgr' : appel non conforme d'une fonction membre non static autolimb C:\xxxxxxxx\perso\daz3d\mes plugind\autolimb\autolimb.cpp 179

    You need to distinguiksh static methods, which are always available, and dynamic methods, which may not be - again, you need to check vlaidity and not rely on stuff being there without coinfirmation.

  • Richard HaseltineRichard Haseltine Posts: 107,953

    darkdesire said:

    So, i've a slot function attach to tmy class ManagerGenesis (first plugin):

    public slots:

       void GenereAleaPosition();

    in my second plugin, i've:

    panemgr = dzApp->getInterface()->getPaneMgr();

    if (panemgr)

      {

        dzApp->log("Found a panemgr");

        gg= panemgr->findPane("MAnageGenesis");

        if (gg)

        {

          dzApp->log("Found MAnageGenesis");

        }

    in the log, it writes "found ManageGenesis so ti found it, how call the slot ? connect ? 

    There are numerous discussions in this sub forum on using QMetaObject::invokeMethod() to access functions. See https://doc.qt.io/archives/qt-4.8/metaobjects.html for a general  explanation.

  • surrealsurreal Posts: 198
    edited March 25

    darkdesire said:

    So, i've a slot function attach to tmy class ManagerGenesis (first plugin):

    public slots:

       void GenereAleaPosition();

    in my second plugin, i've:

    panemgr = dzApp->getInterface()->getPaneMgr();

    if (panemgr)

      {

        dzApp->log("Found a panemgr");

        gg= panemgr->findPane("MAnageGenesis");

        if (gg)

        {

          dzApp->log("Found MAnageGenesis");

        }

    in the log, it writes "found ManageGenesis so ti found it, how call the slot ? connect ? 

    panemgr->findPane("MAnageGenesis"); //Returns a DzPane*   thus gg will be a pointer to just the DzPane part. and thus will only be aware of the standard public DzPane functions. It will not include any of the additional functions you defined in your subclass.

    To be able to call any of the additional functions you defined in your subclassing of DzPane, you need to try to cast gg as a pointer to your subclass of DzPane(the DzPane subclass you defined in your firstplugin).

    #include "MAnagerGenesis.h"
    
    ...
    
    void secondPluginFunction() {
         DzPaneMgr* panemgr = dzApp->getInterface()->getPaneMgr();
         if (panemgr) {                                               //If panemgr is valid then
              dzApp->log("Found a panemgr");             //Write debug info to log file
              DzPane* gg= panemgr->findPane("MAnageGenesis");    //Using class name, try to find the pane belonging to the first plugin. 
                                                                      //NOTE: gg will be a pointer to a DzPane* not a pointer to a MAnageGenesis* 
              if (gg) {   //If gg is valid(a MAnageGenesis pane found) then
                   dzApp->log("Found pane");    //Write debug info to log file
    
                   MAnagerGenesis* ggSubclass = qobject_cast<MAnagerGenesis*>(gg); //see reference Richard provided regarding casting
                   if (ggSubclass) {	//if gg is a MAnagerGenesis* (or a subclass of) then
                        dzApp->log("Pane is of type MAnageGenesis");    //Write debug info to log file
    
                        //Now that you have a valid MAnagerGenesis type pointer
                        // you will be able to call any of the additional public functions you defined in your MAnagerGenesis class.
    
                        ggSubclass->GenereAleaPosition();   //call GenereAleaPosition function in first plugin
                   }
              }
         }
    }
    

    NOTE: As Richard mentioned, dynamic_cast<aType*>(obj) (or qobject_cast) will return 0 if obj is not of type aType*
    where as static_cast<aType*>(obj) may return <>0 even if obj is not of type aType.
    Thus you can not use if(static_cast<aType*>(obj)) as a check.

    Post edited by surreal on
  • vectorinusvectorinus Posts: 138
    Yes, in my old plugin all signals and slots connect either different classes of the plugin itself, or they are connected to such global objects, predefined in SDK, as dzApp and dzScene. What if we organize interaction between plugins by catching events in the application. The QEvent class? One plugin creates a certain event, and the other catches it?
  • surrealsurreal Posts: 198

    If you did not have access to "MAnagerGenesis.h"
    then you could use code based on
    QMetaObject::invokeMethod() instead of the cast based code snipit I added in the above code sample.

  • surrealsurreal Posts: 198

    vectorinus said:

    in my old plugin all signals and slots connect either different classes of the plugin itself, or they are connected to such global objects, predefined in SDK, as dzApp and dzScene. What if we organize interaction between plugins by catching events in the application. The QEvent class? One plugin creates a certain event, and the other catches it?

    If I understand you correctly, you are saying that in the first plugin you connect the function to some globally available event. And to run the function you have the second plugin trigger that global event.

  • vectorinusvectorinus Posts: 138

    Yes, I have used global application events in some cases. To do this, you first need to include the QEvent class header file in your own class
    #include <QtGui/qevent.h>
    Then somewhere below the class constructor and destructor, declare the event handling functions
    For example
    protected:
        void paintEvent(QPaintEvent *);
        void mouseMoveEvent(QMouseEvent *event);
        void mousePressEvent(QMouseEvent* event);
        void mouseReleaseEvent(QMouseEvent *event);
        void closeEvent(QCloseEvent *event);        // etc
    Finally, in your .cpp class file, describe how these functions will be implemented
    Example of a mouse click event handler:
    void YouClass::mousePressEvent(QMouseEvent *event)
    {
        switch (event->button())     //which mouse button was pressed?
        {
            case Qt::RightButton: // right button was pressed
            {
                QMessageBox::information
                (
                    dzApp->getDialogParent(), tr("Caught Event"),
                    "Advanced users press the right mouse button to bring up the context menu",  QMessageBox::Close
                );    

            }
            break;
            case Qt::LeftButton: // it was the left button
            {
                QMessageBox::information
                (
                    dzApp->getDialogParent(), tr("Caught Event"),
                    "Stop pressing the left button! You might puncture the monitor screen ;-)",   QMessageBox::Close
                );    
            }
            break;
        }
    }
    However, this is only suitable for handling global events. It is possible to create a custom event in another plugin. This is described in the examples of using the QEvent class. But unfortunately I do not have time to find and test this now.

     

  • darkdesiredarkdesire Posts: 39

    Trying with invokeMethod and it works:

    mw = dzApp->getInterface();

    if (mw)

    {

    panemgr = mw->getPaneMgr();

    if (panemgr)

    {

    dzApp->log("Found a panemgr");

    gg = panemgr->findPane("MAnageGenesis");

    if (gg)

    {

    // MAnageGenesis* ggsubclass;

    const QMetaObject* qmo;

    // ggsubclass= qobject_cast<MAnageGenesis*>(gg);

    qmo = gg->metaObject();

    if (qmo)

    {

    dzApp->log("Found qmo metaobject");

    QMetaObject::invokeMethod(gg,"GenereAleaPosition", Qt::DirectConnection);

    int ind=qmo->methodCount();

    dzApp->log("ind =" + QString::number(ind)+ " methode genealeaposition ;"+QString::number(qmo->indexOfMethod("GenereAleaPosition()"))+" classe : "+qmo->className());

    }

    }

    }

  • darkdesiredarkdesire Posts: 39

    In the log i see trace from other plugin

  • vectorinusvectorinus Posts: 138

    Excellent! Have you tried calling your function in a real program (Daz Studio), does it work?

  • darkdesiredarkdesire Posts: 39

    Yes, launch DazStudio, the 2 plugins loaded too. Calling a function in plugin1 from the plugin2 and it works.

  • darkdesiredarkdesire Posts: 39

    {

    mw = dzApp->getInterface();

    if (mw)

    {

    panemgr = mw->getPaneMgr();

    if (panemgr)

    {

    gg = panemgr->findPane("Plugin2");

    if (gg)

    {

    QMetaObject::invokeMethod(gg, "function1", Qt::DirectConnection);

    }

    }

    }

    }

    functino1 must be declared in the other plugin as a slot and it works

  • darkdesiredarkdesire Posts: 39

    replace plugin2 with the name of the class of your plugin

  • vectorinusvectorinus Posts: 138
    edited March 26

    Short, clear and understandable code. Excellent solution to the problem. You have transmitted your optimism to me. I will soon go to my own plugin in this jungle that I created in it. I did not have the courage to take apart this logging site after a year. I needed a charge, and I got it. Thank you!

    Post edited by vectorinus on
  • surrealsurreal Posts: 198
    edited March 26

    darkdesire said:

    replace plugin2 with the name of the class of your plugin

    One caveat, DzPaneMgr->findPane only finds panes. So your code will work as long as plugin2 has a DzPane subclass.

    i.e. 'replace Plugin2 with the name of the DzPane subclass in your plugin.'

    Post edited by surreal on
  • darkdesiredarkdesire Posts: 39

    Many thanks for your help

  • vectorinusvectorinus Posts: 138
    Not every post in this thread has such a happy ending. You can see for yourself by looking at the latest ones. I came here looking for inspiration. And just in time. Thanks to all of you guys!
  • darkdesiredarkdesire Posts: 39

    Yes you are right but it's what i needed for instance. I think you can test the plugin type to call the right interface.

Sign In or Register to comment.