Dev:Source/Node Editor/Plug-in API

提供: wiki
移動先: 案内検索

Shotgun blast of ideas, please be gentle

Concept of Operations

In an effort to create a more flexible node system that allows for the dynamic loading of nodes for shared libraries, I propose that refactor the node creation system to use a factory pattern to create (and load) nodes and an abstract interface to access the nodes. This will allow us to separate out each node into its own file (or header/source file). We could also then have a node plugin directory for plugins to be set in the settings panel (with the texture/sequence plugin directory path settings).

Build Changes

Since the plugin nodes will need to be able to draw themselves, use library functions, and handle events they will need access to library functions that are part of blender. To make all of these functions available to a plugin by exporting pointers to the functions may not be the easiest way due to the large number of functions that would have to be exported in the API. It might be better to make the functions/data (symbols) available to any loaded shared libraries through compiler flags.


Linux

A loaded node will need to use the functionality in blender so on linux blender should be compiled with the -rdynamic and -export-dynamic flags so that loaded .so files (loaded with dload) will be able to resolve symbols that are in the application after they are loaded.

Mac

I think it's the same as linux, but I need an experts input.

Windows

???-Can't we just drop this platform? I don't think anybody uses it anyways. Use the same trick that the gimp guys used by making the DLL's think that the .exe is a DLL and they can link back into it. Example at: http://edll.sourceforge.net/

Node DNA

will have to be changed to a type ID and a void* storage space to be given to the node class which then will recast to it's own storage type within the class. The void* storage space will have to be big enough to accommodate any node (plus some room for growth). I think 128 bytes is enough (but 256 bytes shouldn't be unreasonable).

Node plug-in API

The node plugin API will need extern C wrappers for each of the public functions.

Abstract Base class

The node base class should have the interface that all nodes will use. Minimal and complete.

This is pseudo code. This will probably need an "extern C" wrapper for integration.

class compositNode
{
public:
	compositNode();
	virtual ~compositNode();
	
	virtual compositNode& composit_node(const compositNode& input);
	virtual compositNode& operator=(const compositNode& input); 
	
	virtual bNodeSocetType* inputs();
	virtual bNodeSocetType* outputs();

	virtual void exec();
	virtual void update();
	virtual int buttons(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr);

	
	virtual const char* ApiVersion() const;
	virtual const char* name() const;
	virtual const char* group()const; 
	virtual int type() const;
	virtual int flags() const; 
	virtual int stackIndex() const;
	virtual int nodeNumber() const;	

	virtual void viewButtonsArea(bool input);
	virtual void viewPreviewArea(bool input);

	virtual void draw();
	virtual int width();

	virtual void setStorage(bNodeStorage* storage);
	virtual bNodeStorage* storage() const;
	
	virtual bNodePreview* preview();
	
protected:
	virtual void generatePreview();
	
	char myName[32];
	int myType
	int myFlags;
	int myNclass;
	
	bNodeSocketType *myInputs, *myOutputs;
	bNodeStorage *myStorage;		/* custom data, must be cast as a struct, for storage in file */
	
	float myWidth, myMinwidth, myMaxwidth;			
	
	bNodePreview *myPreview;	/* optional preview image */
};

Node Factory

The node factory is what the new nodes register themselves with. The register process (of the factory) is as follows:

  • check the API versions to make sure they are compatible (probably should be based on blender version since they are sharing symbols between the two).
  • create a test node and check the menu/group to see if they exist, add the categories if they do not. (these could be static functions and not need the test node)
  • delete test node
  • push node creator into factory map

There will need to be extern C functions to call all the functions of the node factory to interface with the rest of blender. It needs to be a static class (singleton?) created at blenders start.

class node_factory
{
public: 
	node_factory();
	virtual node_factory();

	virtual register(node_creator* creator());

	virtual compositNode* create(std::string);
	virtual void delete(compositNode* node);  //use factory to delete a node
	virtual compositNode* copy(compositNode* node); //use factory to copy a node

protected:
	std::map<std::string, *node_creator()> creatorMap;

	virtual bool checkApiVersion(compositNode* testNode);
	virtual void checkMenus(compositeNode* testNode);
};

Pixel Editing

We should look at the functions that we have for manipulating pixels and processing them to allow for more flexibility. Is it possible to do this in a pixel type independent way?

pixel processors

The pixel processors that we have work great. However, when there is additional information that we would want to give the pixel processor, we need to shoehorn it in to the pixel processors in a way that is not very intuitive (difference matte node for example).

  • Bob for all of this pixel stuff - why not look at Krita, Gimp/GEGL and other advanced open source image processing tools? It probably makes sense to adapt stuff from others instead of reinvent our own. LetterRip 08:41, 31 December 2006 (CET)

get/set pixel

We have a get pixel function, but no set pixel function (that I found).

get/set convolve

The ability to get and set a group of pixels surrounding a specific pixel would be useful for emboss/sharpen effects. I think we would need to look at the pixel processors to see if we can rethink how they pull information. Most convolves are 3x3 but this should be user configurable.

node input/outputs