diff --git a/Documentation/README.md b/Documentation/README.md index dcbea8f4..38b08b15 100755 --- a/Documentation/README.md +++ b/Documentation/README.md @@ -2,16 +2,27 @@ This is the documentation directory for OFX, the open visual effects standard. -# Building Docs +## Documentation Architecture + +The OpenFX documentation system combines several tools: + +1. **Doxygen** - Parses C/C++ header files in the `include` directory to extract API documentation from comments +2. **Breathe** - A Sphinx extension that bridges Doxygen XML output with Sphinx +3. **Sphinx** - Processes ReStructured Text (.rst) files and Doxygen output to generate the final HTML documentation +4. **Python scripts** - Custom scripts like `genPropertiesReference.py` extract property definitions from source files + +The documentation is organized into: +- **Reference manual** - API documentation generated from Doxygen comments in the header files +- **Guide** - Tutorial content with examples in ReStructured Text +- **Release notes** - Version-specific information + +## Building Docs Buildthedocs.io will auto-build whenever changes are pushed to master. But to build the docs yourself, e.g. to check that your updates look right, you can do your own doc build. -Right now building the docs is somewhat manual. The below assumes -Linux, but Mac is similar. - -## Prerequisites +### Prerequisites * Install doxygen (Linux: `sudo apt install doxygen`) * Create a python3 virtualenv: `python -mvenv ofx-docgen` (may need to do `apt install python3.8-venv` first) @@ -21,47 +32,143 @@ Linux, but Mac is similar. (Virtualenv is recommended, but not required; you could install the reqs into your system python if you like.) -## Build: - -* Make sure your virtualenv above is activated: `source ofx-docgen/bin/activate` -* Generate references: - `python Documentation/genPropertiesReference.py -i include -o Documentation/sources/Reference/ofxPropertiesReference.rst -r` -* Build the doxygen docs: `cd include; doxygen ofx.doxy; cd -` (you'll see - some warnings) -* Build the sphinx docs: - `cd Documentation; sphinx-build -b html sources build` -* Note that you can do all the above using the build script in `Documentation/build.sh`. -* Now open - file:///path/to/your/ofx/openfx/Documentation/build/index.html in - your browser; your changes should be there. - -# Doxygen notes: - -Doxygen is used in the source and headers. The doc build process -parses the doxygen comments to build docs, then breathe to merge them -with the `.rst` sphinx docs. See the [Doxygen docs](https://www.doxygen.nl/manual/docblocks.html) - -* Params/Actions/etc. should be added to groups using `\defgroup`, `\ingroup` and `\addtogroup`. Use `@{` / `@}` to add multiple items. -* Use `\ref` to refer to entities in doxygen. - - -# RST Notes: - -RST (ReStructured Text) is used for the prose documentation in the `/Documentation` subtree, using Sphinx and Breathe. - -* Internal links: - - Define: `.. _target-name:` (must be *globally unique*!) - - Reference: ``:ref:`target-name` `` - - Good to put these just before section headers; the link will refer to the header in that case. - - See [Sphinx Docs](https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-ref) - - Links to structs/etc.: - - ``:ref:`OfxHost` `` - - Links to documents: - - ``:doc:`docname` `` (if docname starts with `/` it's absolute, otherwise rel to current file) - - C macros: `` :c:macro:`kOfxParamPropChoiceOrder` `` (struct/var/func/member/enum/type/... work too), - see the [Doc](https://www.sphinx-doc.org/en/master/usage/domains/c.html#c-roles) - - You can also reference `#define`s using this syntax: ``.. doxygendefine:: kOfxImageEffectRenderUnsafe`` on its own line, - which pulls in the whole doxygen block for that `#define`. -* Useful macros: - - `` .. literalinclude:: README.txt `` - +### Build Process + +The simplest way to build the documentation is to run the build script: + +```bash +cd Documentation +./build.sh +``` + +This script performs the following steps: + +1. Generates property references using `genPropertiesReference.py` +2. Builds Doxygen documentation from the header files +3. Uses Breathe to collect Doxygen API docs +4. Builds the final HTML documentation with Sphinx + +After building, you can view the documentation at: +`file:///path/to/your/ofx/openfx/Documentation/build/index.html` + +If you want to run the steps manually, you can follow the steps in `build.sh`. + +## Documentation Writing Guide + +### Doxygen Documentation + +Doxygen is used to document C/C++ code in the source and headers. The main Doxygen configuration is in `include/ofx.doxy`. + +#### Key Doxygen Features Used in OpenFX + +* **Groups** - Organize related items together + ```c + /** \defgroup PropertiesAll Property Suite */ + /** \ingroup PropertiesAll */ + /** \addtogroup PropertiesAll @{ ... @} */ + ``` + +* **Documentation Comments** - Document functions, structs, defines, etc. + ```c + /** + * \brief Brief description + * + * Detailed description that can span + * multiple lines + * + * \param paramName Description of parameter + * \return Description of return value + */ + ``` + +* **Cross-references** - Link to other documentation elements + ```c + /** See \ref kOfxImageEffectPropSupportedPixelDepths */ + ``` + +### ReStructured Text (RST) Documentation + +RST files are used for the prose documentation in the `/Documentation/sources` directory. + +#### Key RST Features Used in OpenFX + +* **Section Headers** - Create hierarchy with underlines + ```rst + Section Title + ============ + + Subsection Title + --------------- + ``` + +* **Internal Links** - Create references between sections + ```rst + .. _target-name: + + Section Title + ============ + + See :ref:`target-name` for more information. + ``` + +* **Code Blocks** - Display code examples + ```rst + .. code-block:: c + + #define kOfxImageEffectPluginRenderThreadSafety "OfxImageEffectPluginRenderThreadSafety" + ``` + +* **Including Files** - Embed external file content + ```rst + .. literalinclude:: ../examples/basic.cpp + :language: cpp + :lines: 10-20 + ``` + +* **Doxygen Integration** - Include Doxygen-documented items + ```rst + .. doxygendefine:: kOfxImageEffectPropSupportsMultiResolution + + .. doxygenfunction:: OfxGetPropertySet + + .. doxygenstruct:: OfxRectD + :members: + ``` + +* **Cross-domain References** - Link to C/C++ elements + ```rst + :c:macro:`kOfxImageEffectPropSupportsOverlays` + :cpp:class:`OfxImageEffectStruct` + :c:struct:`OfxRectD` + :c:func:`OfxGetPropertySet` + ``` + +### Breathe Integration + +The Breathe extension bridges Doxygen and Sphinx, enabling: + +* Automatic generation of API documentation pages +* Full cross-referencing between RST and Doxygen content +* Consistent styling across all documentation + +## Documentation Maintenance Tips + +1. **Common Issues** + - Missing cross-references - Check spelling of target names + - Doxygen parse errors - Check comment formatting + - Breathe integration issues - Check Doxygen XML output + +2. **Adding New Documentation** + - For new API elements: Add Doxygen comments to header files + - For new concepts/guides: Create new RST files in `sources/Guide` + - For property references: They're automatically generated from headers + +3. **Property Documentation** + - Property definitions are extracted automatically by `genPropertiesReference.py` + - Format should be: `#define kOfxPropName "OfxPropName"` + - Add Doxygen comments above property definitions + +4. **Testing Changes** + - Always build documentation locally before submitting changes + - Check for warning messages during the build process + - Review the HTML output to ensure proper formatting and cross-references \ No newline at end of file diff --git a/Documentation/sources/Guide/ofxExample5_Circle.rst b/Documentation/sources/Guide/ofxExample5_Circle.rst index cd8c418a..21678395 100644 --- a/Documentation/sources/Guide/ofxExample5_Circle.rst +++ b/Documentation/sources/Guide/ofxExample5_Circle.rst @@ -360,11 +360,12 @@ where we set the **gHostSupportsMultiRes** global variable. Get Region Of Definition Action =============================== -What is this region of definition action? Easy, an effect and a clip -have a region of definition (RoD). This is the maximum rectangle for -which an effect or clip can produce pixels. You can ask for RoD of a -clip via the :cpp:func:`OfxImageEffectSuiteV1::clipGetRegionOfDefinition` function in the image -effect suite. The RoD is currently defined in canonical coordinates [4]_. +An effect and a clip each have a region of definition (RoD). This is +the maximum rectangle for which an effect or clip can produce pixels. +You can ask for the RoD of a clip via the +:cpp:func:`OfxImageEffectSuiteV1::clipGetRegionOfDefinition` function +in the image effect suite. The RoD is defined in canonical coordinates +[4]_. Note that the RoD is independent of the **bounds** of a image, an image’s bounds may be less than, more than or equal to the RoD. It is up @@ -378,9 +379,9 @@ drawing. Whether we do that or not is controlled by the "growRoD" parameter which is conditionally defined in the describe in context action. -To set the output rod, we need to trap the -:c:macro:`kOfxImageEffectActionGetRegionOfDefinition` action. Our MainEntry -function now has an extra conditional in there…. +To set the plugin's output RoD, the plugin must to handle the +:c:macro:`kOfxImageEffectActionGetRegionOfDefinition` action. The +MainEntry function now has an extra conditional in there…. `circle.cpp `__ diff --git a/Documentation/sources/Reference/ofxInteracts.rst b/Documentation/sources/Reference/ofxInteracts.rst index d5add773..225732a5 100644 --- a/Documentation/sources/Reference/ofxInteracts.rst +++ b/Documentation/sources/Reference/ofxInteracts.rst @@ -7,46 +7,47 @@ may optionally give it the chance to draw its own custom GUI tools and to be able to interact with pen and keyboard input. In OFX this is done via the OfxInteract suite, which is found in the file `ofxInteract.h `_. -OFX interacts by default use openGL to perform all drawing in -interacts, due to its portabilty, robustness and wide implementation. -As of 2022, some systems are moving away from OpenGL support in favor -of more modern graphics drawing APIs. So as of OFX 1.5, effects may -use the :cpp:class:`OfxDrawSuiteV1` instead of OpenGL if the host supports it. - -Each object that can have their own interact a pointer property in it -which should point to a separate `main entry point <#mainEntryPoint>`__. -This entry point is *not* the same as the one in the OfxPlugin struct, -as it needs to respond to a different set of actions to the effect. - -There are two things in an image effect can have their own interact, -these are... - -- as on overlay on the image being currently viewed in any image +OFX Interacts use openGL by default to perform all drawing, due to its +portabilty, robustness and wide implementation. As of 2022, some +systems are moving away from OpenGL support in favor of more modern +graphics drawing APIs. So as of OFX 1.5, effects may use the +:cpp:class:`OfxDrawSuiteV1` instead of OpenGL, if the host supports it, +by requesting :c:macro:`kOfxImageEffectPluginPropOverlayInteractV2` +instead of :c:macro:`kOfxImageEffectPluginPropOverlayInteractV1`. + +Each plugin implementing interacts sets up a pointer property which +should point to a separate "InteractMain"" entry point. This entry +point is *not* the same as the one in the OfxPlugin struct, as it +needs to respond to a different set of actions to the effect. + +There are two things an image effect can draw via its interact: + +- An overlay on the image being currently viewed in any image viewer, set via the effect descriptor's :c:macro:`kOfxImageEffectPluginPropOverlayInteractV1` - property -- as a replacement for any parameter's standard GUI object, set this + property. +- Replacement for any parameter's standard GUI object. set this via the parameter descriptor's :c:macro:`kOfxParamPropInteractV1` property. -Hosts might not be able to support interacts, to indicate this, two +Hosts might not be able to support interacts. To indicate this, two properties exist on the host descriptor which an effect should examine -at description time so as to determine its own behaviour. These are... +at description time so as to determine its own behaviour. These are: - :c:macro:`kOfxImageEffectPropSupportsOverlays` - :c:macro:`kOfxParamHostPropSupportsCustomInteract` -Interacts are separate objects to the effect they are associated with, -they have their own descriptor and instance handles passed into their -separate :ref:`main entry point `. +Interacts are separate objects from the effect they are associated with. +They have their own descriptor and instance handles passed into their +separate main entry point. -An interact instance cannot exist without a plugin instance, an +An interact instance cannot exist without a plugin instance. An interact's instance, once created, is bound to a single instance of a plugin until the interact instance is destroyed. -All interacts of the same type share openGL display lists, even if they -are in different openGL contexts. +When using OpenGL, all interacts of the same type share openGL display +lists, even if they are in different openGL contexts. All interacts of the same type will have the same pixel types (this is a side effect of the last point), this will always be double buffered with @@ -77,9 +78,16 @@ Hosts will generally display images (both input and output) in user their interfaces. A plugin can put an interact in this display by setting the effect descriptor :c:macro:`kOfxImageEffectPluginPropOverlayInteractV1` +or +:c:macro:`kOfxImageEffectPluginPropOverlayInteractV2` property to point to a main entry. -The viewport for such interacts will depend completely on the host. +If the plugin requests OverlayInteractV2 and the host supports it, then the plugin *must* do all drawing with the DrawSuite, not OpenGL. + +OpenGL +^^^^^^^ + +In OpenGL, the viewport for such interacts will depend completely on the host. The ``GL_PROJECTION`` matrix will be set up so that it maps openGL coordinates to canonical image coordinates. @@ -91,6 +99,11 @@ openGL context and viewport with other objects that belong to the host. It should not blank the background and it should never swap buffers, that is for the host to do. +DrawSuite +^^^^^^^^^ + +For info on using DrawSuite, see :c:struct:`OfxDrawSuiteV1`. + .. _ParametersInteracts: Parameter Interacts @@ -105,7 +118,10 @@ completely replace the parameters default user interface in the 'paged' and *hierarchical* interfaces, but it will not replace the parameter's interface in any animation sheet. -Properties affecting custom interacts for parameters are... +Note that not all hosts implement custom parameter interacts. See +:c:macro:`kOfxParamHostPropSupportsCustomInteract`. + +Properties affecting custom interacts for parameters are: - :c:macro:`kOfxParamPropInteractSizeAspect` - :c:macro:`kOfxParamPropInteractMinimumSize` @@ -127,53 +143,49 @@ A parameter's interact draw function will have full responsibility for drawing the interact, including clearing the background and swapping buffers. + Interact Actions ---------------- -The following actions are passed to any interact entry point in an image -effect plug-in. - -- The Generic Describe Action - called to describe the specific - interact - , -- The Create Instance Action - called just after an instance of the - interact - is created, -- The Generic Destroy Instance Action - called just before of the - interact - is destroyed, -- The Draw Action - called to have the interact draw itself, -- :c:macro:`kOfxInteractActionPenMotion` +The following actions may be passed to the interact entry point in an +image effect plug-in. + +- **The Generic Describe Action**, :c:macro:`KOfxActionDescribe` - + called to describe the specific interact. +- **The Create Instance Action**, :c:macro:`KOfxActionCreateInstance` - + called just after an instance of the interact is created. +- **The Generic Destroy Instance Action**, :c:macro:`KOfxActionDestroyInstance` - + called just before the interact is destroyed. +- **The Draw Action**, :c:macro:`kOfxInteractActionDraw` - + called to have the interact draw itself. +- :c:macro:`kOfxInteractActionPenMotion` - called whenever the interact has the input focus and the pen has - moved, regardless of whether the pen is up or down, -- :c:macro:`kOfxInteractActionPenDown` + moved, regardless of whether the pen is up or down. +- :c:macro:`kOfxInteractActionPenDown` - called whenever the interact has the input focus and the pen has - changed state to 'down', -- :c:macro:`kOfxInteractActionPenUp` + changed state to 'down'. +- :c:macro:`kOfxInteractActionPenUp` - called whenever the interact has the input focus and the pen has - changed state to 'up, -- :c:macro:`kOfxInteractActionKeyDown` + changed state to 'up'. +- :c:macro:`kOfxInteractActionKeyDown` - called whenever the interact has the input focus and a key has gone - down, -- :c:macro:`kOfxInteractActionKeyUp` + down. +- :c:macro:`kOfxInteractActionKeyUp` - called whenever the interact has the input focus and a key has gone - up, -- :c:macro:`kOfxInteractActionKeyRepeat` + up. +- :c:macro:`kOfxInteractActionKeyRepeat` - called whenever the interact has the input focus and a key has gone - down and a repeat key sequence has been sent, -- :c:macro:`kOfxInteractActionGainFocus` - called whenever the interact gains input focus, -- :c:macro:`kOfxInteractActionLoseFocus` - called whenever the interact loses input focus, + down and a repeat key sequence has been sent. +- :c:macro:`kOfxInteractActionGainFocus` - + called whenever the interact gains input focus. +- :c:macro:`kOfxInteractActionLoseFocus` - + called whenever the interact loses input focus. -An interact cannot be described until an effect has been described. +The host must first call the effect's Describe action before calling its interact Describe action. -An interact instance must always be associated with an effect instance. -So it gets created after an effect and destroyed before one. +An interact instance must always be associated with an effect instance, +so it gets created after the effect and destroyed before the effect. -An interact instance should be issued a gain focus action before any key -or pen actions are issued, and a lose focus action when it goes. +An interact instance should be issued a "gain focus" action before +any key or pen actions are issued, and a "lose focus" action when it +goes. diff --git a/include/ofxDrawSuite.h b/include/ofxDrawSuite.h index 874d0719..61702876 100644 --- a/include/ofxDrawSuite.h +++ b/include/ofxDrawSuite.h @@ -80,7 +80,7 @@ typedef enum OfxDrawTextAlignment } OfxDrawTextAlignment; /** @brief OFX suite that allows an effect to draw to a host-defined display context. - + To use this, the plugin must use kOfxImageEffectPluginPropOverlayInteractV2. */ typedef struct OfxDrawSuiteV1 { /** @brief Retrieves the host's desired draw colour for diff --git a/include/ofxImageEffect.h b/include/ofxImageEffect.h index f30ca473..89dd2e06 100644 --- a/include/ofxImageEffect.h +++ b/include/ofxImageEffect.h @@ -106,7 +106,7 @@ These are the list of actions passed to an image effect plugin's main function. definition see \ref ImageEffectArchitectures "Image Effect Architectures" Note that hosts that have constant sized imagery need not call this - action, only hosts that allow image sizes to vary need call this. + action. Only hosts that allow image sizes to vary need call this. @param handle handle to the instance, cast to an \ref OfxImageEffectHandle @@ -117,12 +117,12 @@ These are the list of actions passed to an image effect plugin's main function. action - \ref kOfxImageEffectPropThumbnailRender (optional) if the host considers this render a "thumbnail" - @param outArgs has the following property which the plug-in may set + @param outArgs has the following property which the plug-in may set: - \ref kOfxImageEffectPropRegionOfDefinition the calculated region of definition, initially set by the host to the default RoD (see below), in Canonical Coordinates. - If the effect did not trap this, it means the host should use the + If the effect does not handle this action, the host should use the default RoD instead, which depends on the context. This is... - generator context - defaults to the project window, @@ -155,15 +155,13 @@ These are the list of actions passed to an image effect plugin's main function. way, depending on the host architecture, a host can fetch the minimal amount of the image needed as input. Note that there is a region of interest to be set in ``outArgs`` for each input clip that exists on the - effect. For more details see \ref ImageEffectArchitectures "Image Effect - Architectures" - + effect. For more details see + \ref ImageEffectArchitectures "Image Effect Architectures" The default RoI is simply the value passed in on the \ref kOfxImageEffectPropRegionOfInterest - ``inArgs`` property set. All the RoIs in the ``outArgs`` property set - must initialised to this value before the action is called. - + ``inArgs`` property set. The host must initalize all the RoIs in the ``outArgs`` property set + to this value before the action is called. @param handle handle to the instance, cast to an \ref OfxImageEffectHandle @param inArgs has the following properties @@ -173,7 +171,7 @@ These are the list of actions passed to an image effect plugin's main function. - \ref kOfxImageEffectPropThumbnailRender (optional) if the host considers this render a "thumbnail" @param outArgs has a set of 4 dimensional double properties, one for each of the input clips to the effect. - The properties are each named ``OfxImageClipPropRoI_`` with the clip name post pended, for example + The properties are each named ``OfxImageClipPropRoI_`` with the clip name postpended, for example ``OfxImageClipPropRoI_Source``. These are initialised to the default RoI. @@ -190,8 +188,9 @@ These are the list of actions passed to an image effect plugin's main function. /** @brief This action allows a host to ask an effect what range of frames it can - produce images over. Only effects instantiated in the \ref generalContext "General - Context" can have this called on them. In all other + produce images over. Only effects instantiated in the + \ref generalContext "General Context" + can have this called on them. In all other the host is in strict control over the temporal duration of the effect. The default is: @@ -1627,18 +1626,11 @@ If clipGetImage is called twice with the same parameters, then two separate imag */ OfxStatus (*clipReleaseImage)(OfxPropertySetHandle imageHandle); - /** @brief Returns the spatial region of definition of the clip at the given time - \arg \c clipHandle clip to extract the image from - \arg \c time time to fetch the image at - \arg \c region region to fetch the image from (optional, set to NULL to get a 'default' region) - this is in the \ref CanonicalCoordinates. - \arg \c imageHandle handle where the image is returned - - An image is fetched from a clip at the indicated time for the given region and returned in the imageHandle. - - If the \e region parameter is not set to NULL, then it will be clipped to the clip's Region of Definition for the given time. The returned image will be \em at \em least as big as this region. If the region parameter is not set, then the region fetched will be at least the Region of Interest the effect has previously specified, clipped the clip's Region of Definition. + \arg \c clipHandle return this clip's region of definition + \arg \c time time to use when determining clip's region of definition + \arg \c bounds (out) bounds are returned here -- in \ref CanonicalCoordinates \pre - clipHandle was returned by clipGetHandle @@ -1647,13 +1639,10 @@ If clipGetImage is called twice with the same parameters, then two separate imag - bounds will be filled the RoD of the clip at the indicated time @returns -- ::kOfxStatOK - the image was successfully fetched and returned in the handle, -- ::kOfxStatFailed - the image could not be fetched because it does not exist in the clip at the indicated time, the plugin - should continue operation, but assume the image was black and transparent. +- ::kOfxStatOK - the region was successfully found and returned in the handle, +- ::kOfxStatFailed - the region could not be determined, - ::kOfxStatErrBadHandle - the clip handle was invalid, - ::kOfxStatErrMemory - the host had not enough memory to complete the operation, plugin should abort whatever it was doing. - - */ OfxStatus (*clipGetRegionOfDefinition)(OfxImageClipHandle clip, OfxTime time, diff --git a/include/ofxInteract.h b/include/ofxInteract.h index b9f9de1a..26660a5c 100644 --- a/include/ofxInteract.h +++ b/include/ofxInteract.h @@ -229,7 +229,9 @@ These are the list of actions passed to an interact's entry point function. For This action is issued to an interact whenever the host needs the plugin to redraw the given interact. - The interact should either issue OpenGL calls to draw itself, or use DrawSuite calls. + The interact should either issue OpenGL calls (if the plugin is using + OverlayInteractV1) to draw itself, or use DrawSuite calls (if using + OverlayInteractV2). If this is called via kOfxImageEffectPluginPropOverlayInteractV2, drawing MUST use DrawSuite.