+ Reply to Thread
Page 2 of 2 FirstFirst 1 2
Results 11 to 16 of 16

Thread: Plugin System

  1. #11
    Join Date
    Mar 2005
    Location
    California
    Posts
    2,098

    Default

    I have this fixed. But only by putting a VERY specific ordering of the include directories into the project settings. Which is a little troublesome. There really is no reason the inherited include directories should have to be BEFORE the engine directory (for pulling .h files from the engine code).

    That seems very odd to me (and I hate things that are odd). I'm going to try one more thing to see if I can remove that ordering dependency, which hopefully should work (at least I understand the basic problem now, that was 90% of the battle, trying to figure out why the compiler was unhappy).

    But it does work. That allows us to use things like String and other containers from the engine in our plugins, which is one of the two requirements. The other one (which is grabbing access to our engine's global variables) is much more of a straightforward coding problem, and really not all that big of a deal. I hope. Of course, that's what I said about this entire subsystem a few days ago, isn't it?

    So now that we've lost two days to that stupid directory ordering problem, we can finally advance with new code. Moving on...
    "They laughed when I said I was going to be a comedian ... They're not laughing now." - Bob Monkhouse

  2. #12
    Join Date
    May 2005
    Posts
    390

    Default

    Quote Originally Posted by RonHiler View Post
    I tried that. the .i file I got was over 30,000 lines long. I don't even know what to do with that, heh.
    Compile it and watch for the error. But this time you will have the EXACT text that is giving the compiler fits.

  3. #13
    Join Date
    Mar 2005
    Location
    California
    Posts
    2,098

    Default

    Okay, success guys, this system is in the can.

    When the engine gets out into the wild, and people want to start creating plugins, this is the minimum interface for it:

    Code:
    #pragma once
    
    #include "..\..\PluginManager.h"
    
    namespace Enzyme
        {
        class MyPlugin : public PluginInterface
            {
            public:
                virtual String GetName() const;
                virtual void Execute() const;
                virtual void Destroy() const;
            };
    
        extern "C" { DLLEXPORT PluginInterface* CreatePlugin() { return new MyPlugin(); }}
        }
    Of course, you have to implement those three functions. You can add others, but those are the only three functions (plus the CreatePlugin function) the engine will call (those are your hooks). Naturally, you can replace "MyPlugin" with any name you like (I've already created a "FontBuilder" plugin, for instance).

    You can also instance objects out of the engine classes (like I've done here with String). You would just include the appropriate header file, and link to the engine's lib file in order to pull in any exported functions. That means I have to export functions likely to be used in plugins, but I can do that, it's very simple to do (all I have to do is add the word DLLEXPORT in front of any function definition).

    And it's just that easy. The engine is going to poll the plugin folder (and subdirectories thereof) for any DLLs, and will load them automatically on startup. It doesn't need any pre-knowledge of what is in there or even what they do. It's not going to care. It will load them and look for those four functions. If they are there, you have a working plugin, suitable to be called whenever you like.

    The execute command is really meant to be called only once in a while (like when the user does something to invoke it, such as select the name of the plugin from a menu in the engine). However, I may add another function designed to be run once per game loop. I can see instances where that would be necessary.

    Oh, and this is not meant to be limited ONLY to design features. We could have plugins designed to be loaded and run during game execution. In such cases, the Execute() command could be hooked into from our (currently hypothetical) scripting system. Good stuff
    "They laughed when I said I was going to be a comedian ... They're not laughing now." - Bob Monkhouse

  4. #14
    Join Date
    Mar 2005
    Location
    California
    Posts
    2,098

    Default

    I've made some changes to the plugin system. One, because I like to tinker with stuff to see how much better I can make it. Two (and more importantly) as I was writing the font builder plugin, I was finding the system somewhat inadequate. A bit clunky, to be honest.

    The changes made aren't all that dramatic, but they make the entire system somewhat more friendly (i.e. easier to use). Which is good, because when you are writing a plugin, you want to be focused on the system you are trying to implement rather than fighting with the plugin syntax.

    Anyway, I'll show you guys what I've come up with in a bit. There is one more detail I have to work out before I put this one to rest.
    "They laughed when I said I was going to be a comedian ... They're not laughing now." - Bob Monkhouse

  5. #15
    Join Date
    Mar 2005
    Location
    California
    Posts
    2,098

    Default

    Okay gang. This is the new header for the plugin. This shows the minimum you have to have in order to have a valid plugin for the engine.

    Code:
    #pragma once
    
    #include"..\..\PluginManager.h"
    #include"..\..\PluginBase.h"
    
    namespace Enzyme
    {
    class MyPlugin : public PluginInterface
    {
    public:
      virtual void OnLoad(String *PluginName, bool *AddToEngineMenu, bool *PerFrame);
      virtual void OnExecute();
      virtual void OnFrameDraw();
      virtual void OnDestroy();
    
    private:
    };
    extern"C" { DLLEXPORT PluginInterface* CreatePlugin() { return new MyPlugin(); }}
    }
    
    This may be slightly more complex than the previous version, but it's also quite a bit more powerful.

    Notice we now have two includes. One gives us the definition of our interface (PluginManager.h defines PluginInterface). The other one (PluginBase.h) is our imports for the global variables from the engine. By having this header included, you can use all the manager class instances (GraphicsMgr, ControlWindow, MemoryMgr, and so forth). The plugin writer (which will be me, but also at some point in the future potentially other people) don't need to do anything else in their plugin for this to work. They are automatically set up for you (as long as I remember to export them from the engine and update that header file as needed).

    I've then made some changes to the interface functions. They ought to be pretty self explanatory. The parameters for OnLoad() (which, naturally, is called by the engine when the plugin is first loaded) will tell the engine how to handle the hooks for the plugin. In other words, whether or not to add the plugin name to the engine's plugin menu (which, when selected by the user would call the OnExecute() function), and whether or not to call the OnFrameDraw() function once per frame. It is the responsibility of the OnLoad() function to fill in those values as needed.

    And that's pretty much it. When you want to write a plugin, just use this format, implement those four functions, and you are all set. Of course, you are free to add more to the header as needed for any given plugin.

    So that's the end of that. I'm a pretty good way into getting the font builder plugin written, but that's another thread....
    "They laughed when I said I was going to be a comedian ... They're not laughing now." - Bob Monkhouse

  6. #16
    Join Date
    Mar 2005
    Location
    California
    Posts
    2,098

    Default

    There have been some minor changes to the interface as a result of me messing with the global variables in the engine. I'll post the new interface in a bit. It's actually a bit simpler now. I want to make one more minor change, then it's done...

    [edit]
    Okay, here is the new interface

    Code:
    #pragma once
    
    #include "PluginManager.h"
    
    namespace Enzyme
        {
        class MyPlugin : public PluginInterface
            {
            public:
                virtual void OnLoad(String *PluginName, bool *AddToEngineMenu, bool *PerFrame);
                virtual void OnExecute();
                virtual void OnPerFrame();
                virtual void OnDestroy();
            };
    
        extern "C" { ENZYME_API PluginInterface* CreatePlugin() { return new MyPlugin(); }}
        }
    just a quick couple of notes, because I'm totally out of time today.

    Notice PluginBase.h is now gone. Since we are no longer using copies of global variables, but rather the original variables themselves, that file was rendered superfluous, and has been removed.

    Otherwise, I made some minor nomenclature changes. Hopefully it is very obvious what everything means.
    Last edited by RonHiler; 04-07-2011 at 09:58 AM.
    "They laughed when I said I was going to be a comedian ... They're not laughing now." - Bob Monkhouse

+ Reply to Thread

Similar Threads

  1. Climate Classification System
    By RonHiler in forum General Discussion
    Replies: 6
    Last Post: 04-10-2008, 07:55 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts