// Copyright 2019 Diffuse Logic, all rights reserved.

#ifndef BELLA_SDK_SCENEAPI_H
#define BELLA_SDK_SCENEAPI_H

#include "bella_types.h"
#include "../dl_core/dl_string.h"

// This file defines the interfaces for the system. These are designed similarly to COM interfaces,
// so any non-leaf interfaces (IRefCounted, IAttr, IInputContainer) must never be changed, and leaf
// interfaces must keep all methods unchanged and in the same order. They cannot be made final, as
// they must be implemented internally, but you should never derive from them, since we are using
// these pure abstract interfaces not for typical inheritance purposes, but rather to ensure that
// nodelib code can know nothing about them.
// 
// Pointers to these interfaces are passed to nodelib functions and may be wrapped in bella_scene.h
// types; those types wrap the interface pointers and provide comfortable usage and refcounting
// support, ensuring that instances can never be deleted while in use. It is really only when using
// the Node SDK that these interfaces are encountered, since when using the Scene or Engine SDKs,
// you are linking a full implementation and own the scene, and will simply use the bella_sdk.h
// Scene wrapper to begin with. In contrast, with the Node SDK, your library is being loaded into
// some instance of the engine, which itself contains the implementations, and from which you are
// only passed pointers to these interfaces in your nodelib functions.
//
// Regarding the actual design of these classes, you will note that we avoid any overloads in the
// interfaces, so you will see additional force-inlined helpers added in some places to provide
// convenience overloads.

namespace dl {
namespace bella_sdk {

//=================================================================================================
// Forwards.
//=================================================================================================

struct EvalCtx;
struct NodeObserver;
struct SceneObserver;
struct SceneProgress;

namespace interfaces {

class INode;
class IPath;
class IScene;
class ILibInfo;

//=================================================================================================
// IEnumItem.
//=================================================================================================

class IEnumItem /* final */ : public IRefCounted
{
public:
    // API Version 26.1.0.0
    virtual Int                 DL_STDCALL index() const = 0;
    virtual Bool                DL_STDCALL isValid() const = 0;

    virtual Int                 DL_STDCALL intValue() const = 0;
    virtual Real                DL_STDCALL realValue() const = 0;
    virtual String              DL_STDCALL strValue() const = 0;
    virtual String              DL_STDCALL label( String lang = "auto" ) const = 0;
    virtual String              DL_STDCALL help( String lang = "auto" ) const = 0;
};

//=================================================================================================
// IAttrInfo. Used by both IInput and IOutput.
//=================================================================================================

class IAttrInfo /* final */ : public IRefCounted
{
public:
    // API Version 26.1.0.0
    virtual AttrType            DL_STDCALL type() const = 0;
    virtual AttrType            DL_STDCALL arrayType() const = 0;
    virtual DataType            DL_STDCALL bufferType() const = 0;

    virtual Bool                DL_STDCALL acceptsType( String type ) const = 0;
    virtual Bool                DL_STDCALL acceptsNode( INode* node ) const = 0;

    DL_FI Bool                  accepts( String type ) const { return acceptsType( type ); }
    DL_FI Bool                  accepts( INode* node ) const { return acceptsNode( node ); }

    virtual StringVector        DL_STDCALL accepted() const = 0;
    virtual Bool                DL_STDCALL setAccepted( StringVector accepted ) = 0;

    virtual String              DL_STDCALL label( String lang = "auto" ) const = 0;
    virtual Bool                DL_STDCALL setLabel( String label, String lang = "auto" ) = 0;

    virtual String              DL_STDCALL help( String lang = "auto" ) const = 0;
    virtual Bool                DL_STDCALL setHelp( String help, String lang = "auto" ) = 0;

    virtual UInt                DL_STDCALL precision() const = 0;
    virtual Bool                DL_STDCALL setPrecision( UInt precision ) = 0;

    virtual Real                DL_STDCALL step() const = 0;
    virtual Bool                DL_STDCALL setStep( Real step ) = 0;

    virtual Bool                DL_STDCALL realtime() const = 0;
    virtual Bool                DL_STDCALL setRealtime( Bool realtime ) = 0;

    virtual String              DL_STDCALL units() const = 0;
    virtual Bool                DL_STDCALL setUnits( String units ) = 0;

    virtual Bool                DL_STDCALL isEnum() const = 0;
    virtual UInt                DL_STDCALL enumItemCount() const = 0;
    virtual IEnumItem*          DL_STDCALL enumItem( UInt index ) const = 0;

    virtual IEnumItem*          DL_STDCALL findEnumItemInt( Int intValue ) const = 0;
    virtual IEnumItem*          DL_STDCALL findEnumItemReal( Real realValue ) const = 0;
    virtual IEnumItem*          DL_STDCALL findEnumItemString( String strValue ) const = 0;

    DL_FI IEnumItem*            findEnumItem( Int intValue ) const { return findEnumItemInt( intValue ); }
    DL_FI IEnumItem*            findEnumItem( Real realValue ) const { return findEnumItemReal( realValue ); }
    DL_FI IEnumItem*            findEnumItem( String strValue ) const { return findEnumItemString( strValue ); }

    virtual IEnumItem*          DL_STDCALL addEnumItemInt( Int value, String label = "", String help = "", String lang = "auto" ) = 0;
    virtual IEnumItem*          DL_STDCALL addEnumItemReal( Real value, String label = "", String help = "", String lang = "auto" ) = 0;
    virtual IEnumItem*          DL_STDCALL addEnumItemString( String value, String label = "", String help = "", String lang = "auto" ) = 0;

    DL_FI IEnumItem*            addEnumItem( Int intValue, String label = "", String help = "", String lang = "auto" ) { return addEnumItemInt( intValue, label, help, lang ); }
    DL_FI IEnumItem*            addEnumItem( Real realValue, String label = "", String help = "", String lang = "auto" ) { return addEnumItemReal( realValue, label, help, lang ); }
    DL_FI IEnumItem*            addEnumItem( String strValue, String label = "", String help = "", String lang = "auto" ) { return addEnumItemString( strValue, label, help, lang ); }

#define DL_DECL_ATTRINFO_GET(GET) \
    virtual Bool DL_STDCALL GET##Bool  ( Bool&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Int   ( Int&    out ) const = 0; \
    virtual Bool DL_STDCALL GET##UInt  ( UInt&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Real  ( Real&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Vec2  ( Vec2&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Vec3  ( Vec3&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Vec4  ( Vec4&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Pos2  ( Pos2&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Pos3  ( Pos3&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Quat  ( Quat&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Rgba  ( Rgba&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Mat3  ( Mat3&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Mat4  ( Mat4&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##String( String& out ) const = 0; \
    virtual Bool DL_STDCALL GET##Node  ( INode*& out ) const = 0; \
    virtual Bool DL_STDCALL GET##Buffer( BufRef& out ) const = 0; \
    \
    DL_FI Bool GET( Bool&   out ) const { return GET##Bool  ( out ); } \
    DL_FI Bool GET( Int&    out ) const { return GET##Int   ( out ); } \
    DL_FI Bool GET( UInt&   out ) const { return GET##UInt  ( out ); } \
    DL_FI Bool GET( Real&   out ) const { return GET##Real  ( out ); } \
    DL_FI Bool GET( Vec2&   out ) const { return GET##Vec2  ( out ); } \
    DL_FI Bool GET( Vec3&   out ) const { return GET##Vec3  ( out ); } \
    DL_FI Bool GET( Vec4&   out ) const { return GET##Vec4  ( out ); } \
    DL_FI Bool GET( Pos2&   out ) const { return GET##Pos2  ( out ); } \
    DL_FI Bool GET( Pos3&   out ) const { return GET##Pos3  ( out ); } \
    DL_FI Bool GET( Quat&   out ) const { return GET##Quat  ( out ); } \
    DL_FI Bool GET( Rgba&   out ) const { return GET##Rgba  ( out ); } \
    DL_FI Bool GET( Mat3&   out ) const { return GET##Mat3  ( out ); } \
    DL_FI Bool GET( Mat4&   out ) const { return GET##Mat4  ( out ); } \
    DL_FI Bool GET( String& out ) const { return GET##String( out ); } \
    DL_FI Bool GET( INode*& out ) const { return GET##Node  ( out ); } \
    DL_FI Bool GET( BufRef& out ) const { return GET##Buffer( out ); }

    DL_DECL_ATTRINFO_GET( value )
    DL_DECL_ATTRINFO_GET( hardMin )
    DL_DECL_ATTRINFO_GET( hardMax )
    DL_DECL_ATTRINFO_GET( softMin )
    DL_DECL_ATTRINFO_GET( softMax )

#undef DL_DECL_ATTRINFO_GET

#define DL_DECL_ATTRINFO_SET(SET) \
    virtual Bool DL_STDCALL set##SET##Bool  ( Bool   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Int   ( Int    val ) = 0; \
    virtual Bool DL_STDCALL set##SET##UInt  ( UInt   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Real  ( Real   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Vec2  ( Vec2   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Vec3  ( Vec3   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Vec4  ( Vec4   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Pos2  ( Pos2   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Pos3  ( Pos3   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Quat  ( Quat   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Rgba  ( Rgba   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Mat3  ( Mat3   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Mat4  ( Mat4   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##String( String val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Node  ( INode* val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Buffer( BufRef val ) = 0; \
    \
    DL_FI Bool set##SET( Bool   val ) { return set##SET##Bool  ( val ); } \
    DL_FI Bool set##SET( Int    val ) { return set##SET##Int   ( val ); } \
    DL_FI Bool set##SET( UInt   val ) { return set##SET##UInt  ( val ); } \
    DL_FI Bool set##SET( Real   val ) { return set##SET##Real  ( val ); } \
    DL_FI Bool set##SET( Vec2   val ) { return set##SET##Vec2  ( val ); } \
    DL_FI Bool set##SET( Vec3   val ) { return set##SET##Vec3  ( val ); } \
    DL_FI Bool set##SET( Vec4   val ) { return set##SET##Vec4  ( val ); } \
    DL_FI Bool set##SET( Pos2   val ) { return set##SET##Pos2  ( val ); } \
    DL_FI Bool set##SET( Pos3   val ) { return set##SET##Pos3  ( val ); } \
    DL_FI Bool set##SET( Quat   val ) { return set##SET##Quat  ( val ); } \
    DL_FI Bool set##SET( Rgba   val ) { return set##SET##Rgba  ( val ); } \
    DL_FI Bool set##SET( Mat3   val ) { return set##SET##Mat3  ( val ); } \
    DL_FI Bool set##SET( Mat4   val ) { return set##SET##Mat4  ( val ); } \
    DL_FI Bool set##SET( String val ) { return set##SET##String( val ); } \
    DL_FI Bool set##SET( INode* val ) { return set##SET##Node  ( val ); } \
    DL_FI Bool set##SET( BufRef val ) { return set##SET##Buffer( val ); }

    DL_DECL_ATTRINFO_SET( Value )
    DL_DECL_ATTRINFO_SET( HardMin )
    DL_DECL_ATTRINFO_SET( HardMax )
    DL_DECL_ATTRINFO_SET( SoftMin )
    DL_DECL_ATTRINFO_SET( SoftMax )

#undef DL_DECL_ATTRINFO_SET
};

//=================================================================================================
// IAttr. Used by both IInput and IOutput.
//=================================================================================================

class IAttr
{
public:
    // API Version 26.1.0.0
    virtual String              DL_STDCALL name() const = 0;
    virtual AttrType            DL_STDCALL type() const = 0;
    virtual String              DL_STDCALL typeString() const = 0;
    virtual String              DL_STDCALL desc() const = 0;

    virtual INode*              DL_STDCALL node() const = 0;
    virtual String              DL_STDCALL path() const = 0;
    virtual UInt                DL_STDCALL index() const = 0;

    virtual Bool                DL_STDCALL isInput() const = 0;
    virtual Bool                DL_STDCALL isOutput() const = 0;

    virtual Bool                DL_STDCALL isBool() const = 0;
    virtual Bool                DL_STDCALL isInt() const = 0;
    virtual Bool                DL_STDCALL isUInt() const = 0;
    virtual Bool                DL_STDCALL isReal() const = 0;
    virtual Bool                DL_STDCALL isVec2() const = 0;
    virtual Bool                DL_STDCALL isVec3() const = 0;
    virtual Bool                DL_STDCALL isVec4() const = 0;
    virtual Bool                DL_STDCALL isPos2() const = 0;
    virtual Bool                DL_STDCALL isPos3() const = 0;
    virtual Bool                DL_STDCALL isQuat() const = 0;
    virtual Bool                DL_STDCALL isRgba() const = 0;
    virtual Bool                DL_STDCALL isMat3() const = 0;
    virtual Bool                DL_STDCALL isMat4() const = 0;
    virtual Bool                DL_STDCALL isString() const = 0;
    virtual Bool                DL_STDCALL isNode() const = 0;
    virtual Bool                DL_STDCALL isBuffer( DataType ofType = DataType_Null ) const = 0;

    virtual IAttrInfo*          DL_STDCALL info() const = 0;
    virtual Bool                DL_STDCALL setInfo( IAttrInfo* info ) = 0;

    virtual Bool                DL_STDCALL acceptsType( String type ) const = 0;
    virtual Bool                DL_STDCALL acceptsNode( INode* node ) const = 0;

    DL_FI Bool                  accepts( String type ) const { return acceptsType( type ); }
    DL_FI Bool                  accepts( INode* node ) const { return acceptsNode( node ); }

    virtual StringVector        DL_STDCALL accepted() const = 0;
    virtual Bool                DL_STDCALL setAccepted( StringVector accepted ) = 0;

    virtual String              DL_STDCALL label( String lang = "auto" ) const = 0;
    virtual Bool                DL_STDCALL setLabel( String label, String lang = "auto" ) = 0;

    virtual String              DL_STDCALL help( String lang = "auto" ) const = 0;
    virtual Bool                DL_STDCALL setHelp( String help, String lang = "auto" ) = 0;
};

//=================================================================================================
// IInputContainer. Used by both IInput and INode.
//=================================================================================================

class IInputContainer
{
public:
    // API Version 26.1.0.0
    virtual IInput*             DL_STDCALL createInput( String name, AttrType type ) = 0;
    virtual IInput*             DL_STDCALL createArray( String name, AttrType type ) = 0;

    virtual Bool                DL_STDCALL hasInputNamed( String name, AttrType type = AttrType_Null ) const = 0;
    virtual Bool                DL_STDCALL hasInputAt( UInt index, AttrType type = AttrType_Null ) const = 0;

    DL_FI Bool                  hasInput( String name, AttrType type = AttrType_Null ) const { return hasInputNamed( name, type ); }
    DL_FI Bool                  hasInput( UInt index, AttrType type = AttrType_Null ) const { return hasInputAt( index, type ); }

    virtual UInt                DL_STDCALL inputCount() const = 0;
    virtual IInput*             DL_STDCALL inputNamed( String name ) = 0;
    virtual IInput*             DL_STDCALL inputAt( UInt index ) const = 0;

    DL_FI IInput*               input( String name ) { return inputNamed( name ); }
    DL_FI IInput*               input( UInt index ) const { return inputAt( index ); }

    virtual Bool                DL_STDCALL removeInputNamed( String name ) = 0;
    virtual Bool                DL_STDCALL removeInputAt( UInt index ) = 0;

    DL_FI Bool                  removeInput( String name ) { return removeInputNamed( name ); }
    DL_FI Bool                  removeInput( UInt index ) { return removeInputAt( index ); }

    virtual Bool                DL_STDCALL removeLastInput() = 0;
    virtual Bool                DL_STDCALL clearInputs() = 0;
};

//=================================================================================================
// IInput.
//=================================================================================================

class IInput /* final */ : public IRefCounted, public IAttr, public IInputContainer
{
public:
    // API Version 26.1.0.0
    virtual UInt64              DL_STDCALL hash( StringVector excludes = { } ) const = 0;

    virtual IInput*             DL_STDCALL meta( String name = "", AttrType type = AttrType_Null ) = 0;
    virtual Bool                DL_STDCALL isMeta() const = 0;
    virtual IInput*             DL_STDCALL parent() const = 0;

    virtual Bool                DL_STDCALL canConnect( IOutput* output ) const = 0;
    virtual Bool                DL_STDCALL connect( IOutput* output ) = 0;
    virtual void                DL_STDCALL disconnect() = 0;

    virtual Bool                DL_STDCALL connected() const = 0;
    virtual IOutput*            DL_STDCALL output() const = 0;

    virtual Bool                DL_STDCALL canDisableOutput() const = 0;
    virtual Bool                DL_STDCALL outputDisabled() const = 0;
    virtual Bool                DL_STDCALL disableOutput( Bool disable ) = 0;
    virtual IOutput*            DL_STDCALL disabledOutput() const = 0;

    virtual Bool                DL_STDCALL isDisabledOutputMeta() const = 0;
    virtual IInput*             DL_STDCALL disabledInput() const = 0;

    virtual AttrType            DL_STDCALL arrayType() const = 0;
    virtual DataType            DL_STDCALL bufferType() const = 0;

    virtual IInput*             DL_STDCALL appendElement() = 0;
    virtual Bool                DL_STDCALL containsElement( IInput* input ) const = 0;

    virtual Bool                DL_STDCALL getBool( Bool& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getInt( Int& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getUInt( UInt& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getReal( Real& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getVec2( Vec2& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getVec3( Vec3& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getVec4( Vec4& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getPos2( Pos2& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getPos3( Pos3& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getQuat( Quat& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getRgba( Rgba& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getMat3( Mat3& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getMat4( Mat4& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getString( String& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getNode( INode*& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL getBuffer( BufRef& out, Bool eval, EvalCtx* ctx = nullptr ) const = 0;

    DL_FI Bool                  get( Bool& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getBool( out, eval, ctx ); }
    DL_FI Bool                  get( Int& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getInt( out, eval, ctx ); }
    DL_FI Bool                  get( UInt& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getUInt( out, eval, ctx ); }
    DL_FI Bool                  get( Real& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getReal( out, eval, ctx ); }
    DL_FI Bool                  get( Vec2& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getVec2( out, eval, ctx ); }
    DL_FI Bool                  get( Vec3& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getVec3( out, eval, ctx ); }
    DL_FI Bool                  get( Vec4& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getVec4( out, eval, ctx ); }
    DL_FI Bool                  get( Pos2& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getPos2( out, eval, ctx ); }
    DL_FI Bool                  get( Pos3& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getPos3( out, eval, ctx ); }
    DL_FI Bool                  get( Quat& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getQuat( out, eval, ctx ); }
    DL_FI Bool                  get( Rgba& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getRgba( out, eval, ctx ); }
    DL_FI Bool                  get( Mat3& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getMat3( out, eval, ctx ); }
    DL_FI Bool                  get( Mat4& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getMat4( out, eval, ctx ); }
    DL_FI Bool                  get( String& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getString( out, eval, ctx ); }
    DL_FI Bool                  get( INode*& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getNode( out, eval, ctx ); }
    DL_FI Bool                  get( BufRef& out, Bool eval, EvalCtx* ctx = nullptr ) const { return getBuffer( out, eval, ctx ); }

    virtual Bool                DL_STDCALL setFrom( IInput* input ) = 0;
    virtual Bool                DL_STDCALL setBool( Bool value ) = 0;
    virtual Bool                DL_STDCALL setInt ( Int value ) = 0;
    virtual Bool                DL_STDCALL setUInt( UInt value ) = 0;
    virtual Bool                DL_STDCALL setReal( Real value ) = 0;
    virtual Bool                DL_STDCALL setVec2( Vec2 value ) = 0;
    virtual Bool                DL_STDCALL setVec3( Vec3 value ) = 0;
    virtual Bool                DL_STDCALL setVec4( Vec4 value ) = 0;
    virtual Bool                DL_STDCALL setPos2( Pos2 value ) = 0;
    virtual Bool                DL_STDCALL setPos3( Pos3 value ) = 0;
    virtual Bool                DL_STDCALL setQuat( Quat value ) = 0;
    virtual Bool                DL_STDCALL setRgba( Rgba value ) = 0;
    virtual Bool                DL_STDCALL setMat3( Mat3 value ) = 0;
    virtual Bool                DL_STDCALL setMat4( Mat4 value ) = 0;
    virtual Bool                DL_STDCALL setString( String value ) = 0;
    virtual Bool                DL_STDCALL setCstring( const char* value ) = 0;
    virtual Bool                DL_STDCALL setNode( INode* value ) = 0;
    virtual Bool                DL_STDCALL setBuffer( BufRef buffer ) = 0;

    DL_FI Bool                  set( IInput* value ) { return setFrom( value ); }
    DL_FI Bool                  set( Bool value ) { return setBool( value ); }
    DL_FI Bool                  set( Int value ) { return setInt( value ); }
    DL_FI Bool                  set( UInt value ) { return setUInt( value ); }
    DL_FI Bool                  set( Real value ) { return setReal( value ); }
    DL_FI Bool                  set( Vec2 value ) { return setVec2( value ); }
    DL_FI Bool                  set( Vec3 value ) { return setVec3( value ); }
    DL_FI Bool                  set( Vec4 value ) { return setVec4( value ); }
    DL_FI Bool                  set( Pos2 value ) { return setPos2( value ); }
    DL_FI Bool                  set( Pos3 value ) { return setPos3( value ); }
    DL_FI Bool                  set( Quat value ) { return setQuat( value ); }
    DL_FI Bool                  set( Rgba value ) { return setRgba( value ); }
    DL_FI Bool                  set( Mat3 value ) { return setMat3( value ); }
    DL_FI Bool                  set( Mat4 value ) { return setMat4( value ); }
    DL_FI Bool                  set( String value ) { return setString( value ); }
    DL_FI Bool                  set( const char* value ) { return setCstring( value ); }
    DL_FI Bool                  set( INode* value ) { return setNode( value ); }
    DL_FI Bool                  set( BufRef value ) { return setBuffer( value ); }

    virtual String              DL_STDCALL valueToString() const = 0;
    virtual String              DL_STDCALL defaultToString() const = 0;

    virtual Bool                DL_STDCALL isArray( AttrType ofType = AttrType_Null ) const = 0;
    virtual Bool                DL_STDCALL isArrayElement( AttrType ofType = AttrType_Null ) const = 0;
    virtual Bool                DL_STDCALL isObject() const = 0;
    virtual Bool                DL_STDCALL isObjectArray() const = 0;

#define DL_DECL_INPUT_GET(GET) \
    virtual Bool DL_STDCALL GET##Bool  ( Bool&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Int   ( Int&    out ) const = 0; \
    virtual Bool DL_STDCALL GET##UInt  ( UInt&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Real  ( Real&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Vec2  ( Vec2&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Vec3  ( Vec3&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Vec4  ( Vec4&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Pos2  ( Pos2&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Pos3  ( Pos3&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Quat  ( Quat&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Rgba  ( Rgba&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Mat3  ( Mat3&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##Mat4  ( Mat4&   out ) const = 0; \
    virtual Bool DL_STDCALL GET##String( String& out ) const = 0; \
    virtual Bool DL_STDCALL GET##Node  ( INode*& out ) const = 0; \
    virtual Bool DL_STDCALL GET##Buffer( BufRef& out ) const = 0; \
    \
    DL_FI Bool GET( Bool&   out ) const { return GET##Bool  ( out ); } \
    DL_FI Bool GET( Int&    out ) const { return GET##Int   ( out ); } \
    DL_FI Bool GET( UInt&   out ) const { return GET##UInt  ( out ); } \
    DL_FI Bool GET( Real&   out ) const { return GET##Real  ( out ); } \
    DL_FI Bool GET( Vec2&   out ) const { return GET##Vec2  ( out ); } \
    DL_FI Bool GET( Vec3&   out ) const { return GET##Vec3  ( out ); } \
    DL_FI Bool GET( Vec4&   out ) const { return GET##Vec4  ( out ); } \
    DL_FI Bool GET( Pos2&   out ) const { return GET##Pos2  ( out ); } \
    DL_FI Bool GET( Pos3&   out ) const { return GET##Pos3  ( out ); } \
    DL_FI Bool GET( Quat&   out ) const { return GET##Quat  ( out ); } \
    DL_FI Bool GET( Rgba&   out ) const { return GET##Rgba  ( out ); } \
    DL_FI Bool GET( Mat3&   out ) const { return GET##Mat3  ( out ); } \
    DL_FI Bool GET( Mat4&   out ) const { return GET##Mat4  ( out ); } \
    DL_FI Bool GET( String& out ) const { return GET##String( out ); } \
    DL_FI Bool GET( INode*& out ) const { return GET##Node  ( out ); } \
    DL_FI Bool GET( BufRef& out ) const { return GET##Buffer( out ); }

    DL_DECL_INPUT_GET( defaultVal )
    DL_DECL_INPUT_GET( hardMin )
    DL_DECL_INPUT_GET( hardMax )
    DL_DECL_INPUT_GET( softMin )
    DL_DECL_INPUT_GET( softMax )

#undef DL_DECL_INPUT_GET

#define DL_DECL_INPUT_SET(SET) \
    virtual Bool DL_STDCALL set##SET##Bool  ( Bool   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Int   ( Int    val ) = 0; \
    virtual Bool DL_STDCALL set##SET##UInt  ( UInt   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Real  ( Real   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Vec2  ( Vec2   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Vec3  ( Vec3   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Vec4  ( Vec4   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Pos2  ( Pos2   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Pos3  ( Pos3   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Quat  ( Quat   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Rgba  ( Rgba   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Mat3  ( Mat3   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Mat4  ( Mat4   val ) = 0; \
    virtual Bool DL_STDCALL set##SET##String( String val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Node  ( INode* val ) = 0; \
    virtual Bool DL_STDCALL set##SET##Buffer( BufRef val ) = 0; \
    \
    DL_FI Bool set##SET( Bool   val ) { return set##SET##Bool  ( val ); } \
    DL_FI Bool set##SET( Int    val ) { return set##SET##Int   ( val ); } \
    DL_FI Bool set##SET( UInt   val ) { return set##SET##UInt  ( val ); } \
    DL_FI Bool set##SET( Real   val ) { return set##SET##Real  ( val ); } \
    DL_FI Bool set##SET( Vec2   val ) { return set##SET##Vec2  ( val ); } \
    DL_FI Bool set##SET( Vec3   val ) { return set##SET##Vec3  ( val ); } \
    DL_FI Bool set##SET( Vec4   val ) { return set##SET##Vec4  ( val ); } \
    DL_FI Bool set##SET( Pos2   val ) { return set##SET##Pos2  ( val ); } \
    DL_FI Bool set##SET( Pos3   val ) { return set##SET##Pos3  ( val ); } \
    DL_FI Bool set##SET( Quat   val ) { return set##SET##Quat  ( val ); } \
    DL_FI Bool set##SET( Rgba   val ) { return set##SET##Rgba  ( val ); } \
    DL_FI Bool set##SET( Mat3   val ) { return set##SET##Mat3  ( val ); } \
    DL_FI Bool set##SET( Mat4   val ) { return set##SET##Mat4  ( val ); } \
    DL_FI Bool set##SET( String val ) { return set##SET##String( val ); } \
    DL_FI Bool set##SET( INode* val ) { return set##SET##Node  ( val ); } \
    DL_FI Bool set##SET( BufRef val ) { return set##SET##Buffer( val ); }

    DL_DECL_INPUT_SET( DefaultVal )
    DL_DECL_INPUT_SET( HardMin )
    DL_DECL_INPUT_SET( HardMax )
    DL_DECL_INPUT_SET( SoftMin )
    DL_DECL_INPUT_SET( SoftMax )

#undef DL_DECL_INPUT_SET
};

//=================================================================================================
// IOutput.
//=================================================================================================

class IOutput /* final */ : public IRefCounted, public IAttr
{
public:
    // API Version 26.1.0.0
    virtual UInt64              DL_STDCALL hash( StringVector excludes = { } ) const = 0;

    virtual Bool                DL_STDCALL canConnect( IInput* input ) const = 0;
    virtual Bool                DL_STDCALL connect( IInput* input ) = 0;
    virtual void                DL_STDCALL disconnect( IInput* input ) = 0;

    virtual Bool                DL_STDCALL connected() const = 0;
    virtual Bool                DL_STDCALL connectedTo( IInput* input ) = 0;

    virtual DataType            DL_STDCALL bufferType() const = 0;

    virtual UInt                DL_STDCALL inputCount() const = 0;
    virtual IInput*             DL_STDCALL inputNamed( String name ) const = 0;
    virtual IInput*             DL_STDCALL inputAt( UInt index ) const = 0;

    DL_FI IInput*               input( String name ) const { return inputNamed( name ); }
    DL_FI IInput*               input( UInt index ) const { return inputAt( index ); }

    virtual Bool                DL_STDCALL evalBool( Bool& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalInt( Int& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalUInt( UInt& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalReal( Real& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalVec2( Vec2& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalVec3( Vec3& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalVec4( Vec4& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalPos2( Pos2& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalPos3( Pos3& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalQuat( Quat& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalRgba( Rgba& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalMat3( Mat3& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalMat4( Mat4& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalString( String& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalNode( INode*& out, EvalCtx* ctx = nullptr ) const = 0;
    virtual Bool                DL_STDCALL evalBuffer( BufRef& out, EvalCtx* ctx = nullptr ) const = 0;

    DL_FI Bool                  eval( Bool& out, EvalCtx* ctx = nullptr ) const { return evalBool( out, ctx ); }
    DL_FI Bool                  eval( Int& out, EvalCtx* ctx = nullptr ) const { return evalInt( out, ctx ); }
    DL_FI Bool                  eval( UInt& out, EvalCtx* ctx = nullptr ) const { return evalUInt( out, ctx ); }
    DL_FI Bool                  eval( Real& out, EvalCtx* ctx = nullptr ) const { return evalReal( out, ctx ); }
    DL_FI Bool                  eval( Vec2& out, EvalCtx* ctx = nullptr ) const { return evalVec2( out, ctx ); }
    DL_FI Bool                  eval( Vec3& out, EvalCtx* ctx = nullptr ) const { return evalVec3( out, ctx ); }
    DL_FI Bool                  eval( Vec4& out, EvalCtx* ctx = nullptr ) const { return evalVec4( out, ctx ); }
    DL_FI Bool                  eval( Pos2& out, EvalCtx* ctx = nullptr ) const { return evalPos2( out, ctx ); }
    DL_FI Bool                  eval( Pos3& out, EvalCtx* ctx = nullptr ) const { return evalPos3( out, ctx ); }
    DL_FI Bool                  eval( Quat& out, EvalCtx* ctx = nullptr ) const { return evalQuat( out, ctx ); }
    DL_FI Bool                  eval( Rgba& out, EvalCtx* ctx = nullptr ) const { return evalRgba( out, ctx ); }
    DL_FI Bool                  eval( Mat3& out, EvalCtx* ctx = nullptr ) const { return evalMat3( out, ctx ); }
    DL_FI Bool                  eval( Mat4& out, EvalCtx* ctx = nullptr ) const { return evalMat4( out, ctx ); }
    DL_FI Bool                  eval( String& out, EvalCtx* ctx = nullptr ) const { return evalString( out, ctx ); }
    DL_FI Bool                  eval( INode*& out, EvalCtx* ctx = nullptr ) const { return evalNode( out, ctx ); }
    DL_FI Bool                  eval( BufRef& out, EvalCtx* ctx = nullptr ) const { return evalBuffer( out, ctx ); }
};

//=================================================================================================
// ILayout.
//=================================================================================================

class ILayout /* final */ : public IRefCounted
{
public:
    // API Version 26.1.0.0
    virtual LayoutType          DL_STDCALL type() const = 0;
    virtual String              DL_STDCALL name() const = 0;
    virtual String              DL_STDCALL path() const = 0;
    virtual String              DL_STDCALL label( String lang = "auto" ) const = 0;
    virtual Bool                DL_STDCALL expand() const = 0;
    virtual AttrType            DL_STDCALL attrType() const = 0;
    virtual AttrType            DL_STDCALL arrayType() const = 0;
    virtual UInt                DL_STDCALL layoutCount() const = 0;
    virtual ILayout*            DL_STDCALL layout( UInt idx ) const = 0;

    virtual Bool                DL_STDCALL isInvalid() const = 0;
    virtual Bool                DL_STDCALL isLayout() const = 0;
    virtual Bool                DL_STDCALL isHeader() const = 0;
    virtual Bool                DL_STDCALL isInput() const = 0;
    virtual Bool                DL_STDCALL isObject() const = 0;
    virtual Bool                DL_STDCALL isObjectArray() const = 0;
    virtual Bool                DL_STDCALL isSeparator() const = 0;
};

//=================================================================================================
// INodeIterator.
//=================================================================================================

class INodeIterator /* final */ : public IRefCounted
{
public:
    // API Version 26.1.0.0
    virtual UInt                DL_STDCALL count() const = 0;
    virtual Bool                DL_STDCALL contains( INode* node ) const = 0;

    virtual INode*              DL_STDCALL first() = 0;
    virtual INode*              DL_STDCALL next() = 0;
};

//=================================================================================================
// IPathIterator.
//=================================================================================================

class IPathIterator /* final */ : public IRefCounted
{
public:
    // API Version 26.1.0.0
    virtual UInt                DL_STDCALL count() const = 0;

    virtual Bool                DL_STDCALL containsPath( IPath* path ) const = 0;
    virtual Bool                DL_STDCALL containsNode( INode* node ) const = 0;

    DL_FI Bool                  contains( IPath* path ) const { return containsPath( path ); }
    DL_FI Bool                  contains( INode* node ) const { return containsNode( node ); }

    virtual IPath*              DL_STDCALL first() = 0;
    virtual IPath*              DL_STDCALL next() = 0;
};

//=================================================================================================
// ModifyFlags.
//=================================================================================================

enum ModifyFlags
{
    // API Version 26.1.0.0
    ModifyFlags_None            = 0,
    ModifyFlags_Materials       = ( 1 << 1 ),
    ModifyFlags_Assignments     = ( 1 << 2 ),
    ModifyFlags_Environment     = ( 1 << 3 ),
    ModifyFlags_Sun             = ( 1 << 4 ),
    ModifyFlags_GroundPlane     = ( 1 << 5 ),
    ModifyFlags_Hierarchy       = ( 1 << 6 ),  // Anything affecting hierarchy changed.
    ModifyFlags_Xforms          = ( 1 << 7 ),  // Only xforms have been changed.
    ModifyFlags_Visibility      = ( 1 << 8 ),
    ModifyFlags_References      = ( 1 << 9 ),
    ModifyFlags_Camera          = ( 1 << 10 ), // Only the active camera changed.
    ModifyFlags_CameraXform     = ( 1 << 11 ), // Only the active camera xform changed.
    ModifyFlags_Geometry        = ( 1 << 12 ),
    ModifyFlags_Generators      = ( 1 << 13 ),
    ModifyFlags_Modifiers       = ( 1 << 14 ),
    ModifyFlags_Lights          = ( 1 << 15 ),
    ModifyFlags_LiveLights      = ( 1 << 16 ),
    ModifyFlags_Passes          = ( 1 << 17 )
};
DL_FLAGS_FUNCTIONS( ModifyFlags )

//=================================================================================================
// INode.
//=================================================================================================

class INode /* final */ : public IRefCounted, public IInputContainer
{
public:
    // API Version 26.1.0.0
    virtual Bool                DL_STDCALL subscribe( NodeObserver* observer ) = 0;
    virtual Bool                DL_STDCALL unsubscribe( NodeObserver* observer ) = 0;
    virtual Bool                DL_STDCALL unsubscribeAll() = 0;

    virtual IInput*             DL_STDCALL meta() const = 0;
    virtual IScene*             DL_STDCALL scene( Bool local = false ) const = 0;
    virtual UInt64              DL_STDCALL hash( StringVector excludes = { } ) const = 0;

    virtual Bool                DL_STDCALL dirty( Bool checkDeps = true ) const = 0;
    virtual void                DL_STDCALL setDirty( Bool dirty = true ) = 0;

    virtual String              DL_STDCALL type() const = 0;
    virtual String              DL_STDCALL typeDesc() const = 0;
    virtual StringVector        DL_STDCALL bases() const = 0;
    virtual INode*              DL_STDCALL convertTo( String type ) = 0;

    virtual Bool                DL_STDCALL isAbstract() const = 0;
    virtual Bool                DL_STDCALL isInternal() const = 0;

    virtual Bool                DL_STDCALL isTypeOf( String type ) const = 0;
    virtual Bool                DL_STDCALL isTypeOfAny( StringVector types ) const = 0;

    DL_FI Bool                  isTypeOf( StringVector types ) const { return isTypeOfAny( types ); }

    virtual String              DL_STDCALL id() const = 0;
    virtual String              DL_STDCALL name() const = 0; // NOTE: this is deprecated, use id().
    virtual String              DL_STDCALL label( String lang = "auto" ) const = 0;
    virtual String              DL_STDCALL help( String lang = "auto" ) const = 0;

    virtual ILayout*            DL_STDCALL layout() const = 0;
    virtual void                DL_STDCALL setLayout( ILayout* layout ) = 0;

    virtual String              DL_STDCALL displayName() const = 0;
    virtual Bool                DL_STDCALL setDisplayName( String name ) = 0;

    virtual IInput*             DL_STDCALL findInput( String path ) const = 0;
    virtual IOutput*            DL_STDCALL findOutput( String path ) const = 0;

    virtual IInput*             DL_STDCALL parseInputPath( String path ) = 0;

    virtual Bool                DL_STDCALL hasOutputNamed( String name, AttrType type = AttrType_Null ) const = 0;
    virtual Bool                DL_STDCALL hasOutputAt( UInt index, AttrType type = AttrType_Null ) const = 0;

    DL_FI Bool                  hasOutput( String name, AttrType type = AttrType_Null ) const { return hasOutputNamed( name, type ); }
    DL_FI Bool                  hasOutput( UInt index, AttrType type = AttrType_Null ) const { return hasOutputAt( index, type ); }

    virtual UInt                DL_STDCALL outputCount() const = 0;
    virtual IOutput*            DL_STDCALL outputNamed( String name ) const = 0;
    virtual IOutput*            DL_STDCALL outputAt( UInt index ) const = 0;

    DL_FI IOutput*              output( String name ) const { return outputNamed( name ); }
    DL_FI IOutput*              output( UInt index ) const { return outputAt( index ); }

    virtual IOutput*            DL_STDCALL createOutput( String name, AttrType type ) = 0;
    virtual Bool                DL_STDCALL removeOutputNamed( String name ) = 0;
    virtual Bool                DL_STDCALL removeOutputAt( UInt index ) = 0;
    virtual Bool                DL_STDCALL removeLastOutput() = 0;
    virtual Bool                DL_STDCALL clearOutputs() = 0;

    DL_FI Bool                  removeOutput( String name ) { return removeOutputNamed( name ); }
    DL_FI Bool                  removeOutput( UInt index ) { return removeOutputAt( index ); }

    virtual Bool                DL_STDCALL isPath() const = 0;
    virtual String              DL_STDCALL asPath() const = 0;
    virtual Bool                DL_STDCALL setPath( String path ) = 0;
    virtual Bool                DL_STDCALL setPathByParts( String dir, String file, String ext ) = 0;

    DL_FI Bool                  setPath( String dir, String file, String ext ) { return setPathByParts( dir, file, ext ); }

    virtual INodeIterator*      DL_STDCALL children( Int depth = -1 ) const = 0;
    virtual Int                 DL_STDCALL indexIn( INode* parent ) const = 0;
    virtual Bool                DL_STDCALL parentTo( INode* parent ) = 0;
    virtual Bool                DL_STDCALL unparentFrom( INode* parent ) = 0;

    virtual IPathIterator*      DL_STDCALL pathsForType( String type = "", Bool excludeHidden = false) const = 0;
    virtual IPathIterator*      DL_STDCALL pathsForTypes( StringVector types, Bool excludeHidden = false ) const = 0;

    DL_FI IPathIterator*        paths( String type = "", Bool excludeHidden = false) const { return pathsForType(type, excludeHidden); }
    DL_FI IPathIterator*        paths( StringVector types, Bool excludeHidden = false ) const { return pathsForTypes( types, excludeHidden ); }

    virtual IPathIterator*      DL_STDCALL pathsToNode( INode* node, Bool excludeHidden = false ) const = 0;
    virtual IPathIterator*      DL_STDCALL pathsToID( String id, Bool excludeHidden = false ) const = 0;

    DL_FI IPathIterator*        pathsTo( INode* node, Bool excludeHidden = false ) const { return pathsToNode( node, excludeHidden ); }
    DL_FI IPathIterator*        pathsTo( String id, Bool excludeHidden = false ) const { return pathsToID( id, excludeHidden ); }

    virtual IPath*              DL_STDCALL firstPathToNode( INode* node, Bool excludeHidden = false ) const = 0;
    virtual IPath*              DL_STDCALL firstPathToID( String id, Bool excludeHidden = false ) const = 0;

    DL_FI IPath*                firstPathTo( INode* node, Bool excludeHidden = false ) const { return firstPathToNode( node, excludeHidden ); }
    DL_FI IPath*                firstPathTo( String id, Bool excludeHidden = false ) const { return firstPathToID( id, excludeHidden ); }

    virtual ILibInfo*           DL_STDCALL libInfo() const = 0;
    virtual String              DL_STDCALL libPath() const = 0;
    virtual String              DL_STDCALL libID() const = 0;

    virtual Bool                DL_STDCALL hasNodeInit() const = 0;
    virtual Bool                DL_STDCALL hasNodePrep() const = 0;
    virtual Bool                DL_STDCALL hasNodeEval() const = 0;
    virtual Bool                DL_STDCALL hasNodeModify() const = 0;
    virtual Bool                DL_STDCALL hasNodeChanged() const = 0;
    virtual Bool                DL_STDCALL hasNodeFree() const = 0;

    virtual Bool                DL_STDCALL nodeInit() = 0;
    virtual Bool                DL_STDCALL nodePrep() = 0;
    virtual Bool                DL_STDCALL nodeEval( EvalCtx* ctx, Ptr output ) const = 0;
    virtual Bool                DL_STDCALL nodeModify( ModifyFlags* flags, INode* target = nullptr ) = 0;
    virtual Bool                DL_STDCALL nodeChanged( IInput* input ) = 0;
    virtual Bool                DL_STDCALL nodeFree() = 0;

    virtual Ptr                 DL_STDCALL fnNodeInit() const = 0;
    virtual Ptr                 DL_STDCALL fnNodePrep() const = 0;
    virtual Ptr                 DL_STDCALL fnNodeEval() const = 0;
    virtual Ptr                 DL_STDCALL fnNodeModify() const = 0;
    virtual Ptr                 DL_STDCALL fnNodeChanged() const = 0;

    virtual const Ptr           DL_STDCALL data() const = 0;

    virtual String              DL_STDCALL svgIcon( Bool returnEmptyStringIfMissing = false ) const = 0;
    virtual String              DL_STDCALL htmlHelp( Bool asStandaloneDoc = false, String lang = "auto" ) const = 0;

    virtual INodeIterator*      DL_STDCALL dependencies( Bool topoSort = false, Bool followOutputs = false ) const = 0;
    virtual String              DL_STDCALL serialize( Bool withDeps = true, Bool writeDefaults = false ) const = 0;
    virtual INode*              DL_STDCALL clone( Bool withDeps = true ) = 0;

    virtual String              DL_STDCALL checkMesh() const = 0;

    virtual UInt                DL_STDCALL pointCloudCount() const = 0;
    virtual BufRef              DL_STDCALL pointCloud( Real detail = 1.0, Int maxPoints = -1 ) = 0;
};

//=================================================================================================
// IPath.
//=================================================================================================

class IPath /* final */ : public IRefCounted
{
public:
    // API Version 26.1.0.0
    virtual String              DL_STDCALL path() const = 0;
    virtual UInt64              DL_STDCALL hash() const = 0;
    virtual Bool                DL_STDCALL dirty() const = 0;

    virtual INodeIterator*      DL_STDCALL nodes() const = 0;
    virtual UInt                DL_STDCALL count() const = 0;
    virtual Bool                DL_STDCALL contains( INode* node ) const = 0;

    virtual INode*              DL_STDCALL root() const = 0;
    virtual INode*              DL_STDCALL leaf() const = 0;
    virtual INode*              DL_STDCALL parent( UInt revIdx = 0 ) const = 0;

    virtual Mat4                DL_STDCALL transform( Real time = 0.0, UInt instancerIdx = ( UInt )-1 ) const = 0;

    virtual Bool                DL_STDCALL visible() const = 0;
    virtual INode*              DL_STDCALL material() const = 0;
    virtual INode*              DL_STDCALL subdivision() const = 0;
};

//=================================================================================================
// IScene.
//=================================================================================================

class IScene /* final */ : public IRefCounted
{
public:
    // API Version 26.1.0.0
    virtual Int64               DL_STDCALL id() const = 0;
    virtual UInt64              DL_STDCALL hash( StringVector excludes = { } ) const = 0;

    virtual UInt64              DL_STDCALL fileVersion() const = 0;
    virtual String              DL_STDCALL fileTime() const = 0;
    virtual StringVector        DL_STDCALL fileComments() const = 0;

    virtual Bool                DL_STDCALL subscribe( SceneObserver* observer ) = 0;
    virtual Bool                DL_STDCALL unsubscribe( SceneObserver* observer ) = 0;
    virtual Bool                DL_STDCALL unsubscribeAll() = 0;

    virtual StringVector        DL_STDCALL libIDs() const = 0;
    virtual StringVector        DL_STDCALL libPaths() const = 0;
    virtual ILibInfo*           DL_STDCALL libInfo( String pathOrID ) const = 0;

    virtual UInt                DL_STDCALL defCount() const = 0;
    virtual StringVector        DL_STDCALL defCategories() const = 0;
    virtual INodeIterator*      DL_STDCALL defs( String category = "" ) const = 0;
    virtual INodeIterator*      DL_STDCALL defsForLib( const ILibInfo* lib ) const = 0;

    DL_FI INodeIterator*        defs( const ILibInfo* lib ) const { return defsForLib( lib ); }

    virtual UInt                DL_STDCALL clearDefs() = 0;
    virtual Bool                DL_STDCALL parseDefs( String bndText ) = 0;
    virtual Bool                DL_STDCALL loadDefs( String path = "" ) = 0;

    virtual INode*              DL_STDCALL defineNode( String type ) = 0;
    virtual INode*              DL_STDCALL findDefType( String type ) const = 0;
    virtual INode*              DL_STDCALL findDefAt( UInt index ) const = 0;

    DL_FI INode*                findDef( String type ) const { return findDefType( type ); }
    DL_FI INode*                findDef( UInt index ) const { return findDefAt( index ); }

    virtual UInt                DL_STDCALL nodeCount() const = 0;
    virtual INode*              DL_STDCALL createNode( String type, String id = "", String displayName = "" ) = 0;
    virtual INode*              DL_STDCALL convertNode( INode* node, String newType ) = 0;

    virtual INode*              DL_STDCALL cloneNode( INode* node, Bool withDeps = true, Bool adjustDisplayNames = true ) = 0;
    virtual INode*              DL_STDCALL cloneNodeByID( String id, Bool withDeps = true, Bool adjustDisplayNames = true ) = 0;
    virtual INodeIterator*      DL_STDCALL cloneNodesByID( StringVector ids, Bool withDeps = true, Bool adjustDisplayNames = true ) = 0;

    DL_FI INode*                cloneNode( String id, Bool withDeps = true, Bool adjustDisplayNames = true ) { return cloneNodeByID( id, withDeps, adjustDisplayNames ); }
    DL_FI INodeIterator*        cloneNodes( StringVector ids, Bool withDeps = true, Bool adjustDisplayNames = true ) { return cloneNodesByID( ids, withDeps, adjustDisplayNames ); }

    virtual UInt                DL_STDCALL clearNodes( Bool unreferencedOnly = false, StringVector unrefTypesToKeep = StringVector() ) = 0;
    virtual Bool                DL_STDCALL canRemoveNode( INode* node ) const = 0;
    virtual Bool                DL_STDCALL removeNode( INode* node ) = 0;
    virtual Bool                DL_STDCALL removeNodeByID( String id ) = 0;
    virtual StringVector        DL_STDCALL removeNodes( String ofType ) = 0;
    virtual StringVector        DL_STDCALL removeNodesByID( StringVector ids ) = 0;
    virtual INode*              DL_STDCALL restoreNode( String name ) = 0;

    DL_FI Bool                  removeNode( String id ) { return removeNodeByID( id ); }
    DL_FI StringVector          removeNodes( StringVector ids ) { return removeNodesByID( ids ); }

    virtual INode*              DL_STDCALL findNode( String id ) const = 0;
    virtual INodeIterator*      DL_STDCALL findNodes( StringVector ids, Bool topoSort = false, Bool withDeps = false ) const = 0;

    virtual StringVector        DL_STDCALL nodeTypes() const = 0;
    virtual StringVector        DL_STDCALL nodeNamesByType( String type = "" ) const = 0; // TODO: change to nodeIDs()
    virtual StringVector        DL_STDCALL nodeNamesByTypes( StringVector types ) const = 0;

    DL_FI StringVector          nodeNames( String type = "" ) const { return nodeNamesByType( type ); }
    DL_FI StringVector          nodeNames( StringVector types ) const { return nodeNamesByTypes( types ); }

    virtual INodeIterator*      DL_STDCALL nodesByType( String type = "", Bool topoSort = false ) const = 0;
    virtual INodeIterator*      DL_STDCALL nodesByTypes( StringVector types, Bool topoSort = false ) const = 0;
    virtual INodeIterator*      DL_STDCALL nodesForLib( const ILibInfo* lib ) const = 0;

    DL_FI INodeIterator*        nodes( String type = "", Bool topoSort = false ) const { return nodesByType( type, topoSort ); }
    DL_FI INodeIterator*        nodes( StringVector types, Bool topoSort = false ) const { return nodesByTypes( types, topoSort ); }
    DL_FI INodeIterator*        nodes( const ILibInfo* lib ) const { return nodesForLib( lib ); }

    virtual IPathIterator*      DL_STDCALL pathsByType( String type = "", Bool excludeHidden = false ) const = 0;
    virtual IPathIterator*      DL_STDCALL pathsByTypes( StringVector types, Bool excludeHidden = false ) const = 0;

    DL_FI IPathIterator*        paths( String type = "", Bool excludeHidden = false ) const { return pathsByType( type, excludeHidden ); }
    DL_FI IPathIterator*        paths( StringVector types, Bool excludeHidden = false ) const { return pathsByTypes( types, excludeHidden ); }

    virtual IPathIterator*      DL_STDCALL pathsToNode( INode* node, Bool excludeHidden = false ) const = 0;
    virtual IPathIterator*      DL_STDCALL pathsToID( String id, Bool excludeHidden = false ) const = 0;

    DL_FI IPathIterator*        pathsTo( INode* node, Bool excludeHidden = false ) const { return pathsToNode( node, excludeHidden ); }
    DL_FI IPathIterator*        pathsTo( String id, Bool excludeHidden = false ) const { return pathsToID( id, excludeHidden ); }

    virtual IPath*              DL_STDCALL firstPathToNode( INode* node, Bool excludeHidden = false ) const = 0;
    virtual IPath*              DL_STDCALL firstPathToID( String id, Bool excludeHidden = false ) const = 0;

    DL_FI IPath*                firstPathTo( INode* node, Bool excludeHidden = false ) const { return firstPathToNode( node, excludeHidden ); }
    DL_FI IPath*                firstPathTo( String id, Bool excludeHidden = false ) const { return firstPathToID( id, excludeHidden ); }
    
    virtual IInput*             DL_STDCALL parseInputPath( String path ) = 0;

    virtual INode*              DL_STDCALL global( Bool create = true ) const = 0;
    virtual INode*              DL_STDCALL state( Bool create = true ) const = 0;
    virtual INode*              DL_STDCALL world( Bool create = true ) const = 0;
    virtual INode*              DL_STDCALL settings( Bool create = true ) const = 0;

    virtual String              DL_STDCALL ocioConfig() const = 0;
    virtual String              DL_STDCALL applyOcioConfig() const = 0;
    virtual String              DL_STDCALL colorSpace() const = 0;

    virtual INode*              DL_STDCALL camera() const = 0;
    virtual INode*              DL_STDCALL environment() const = 0;
    virtual INode*              DL_STDCALL sun() const = 0;
    virtual INode*              DL_STDCALL solarContext() const = 0;
    virtual INode*              DL_STDCALL groundPlane() const = 0;

    virtual Mat4                DL_STDCALL axisSystem() const = 0;
    virtual Vec3                DL_STDCALL scale() const = 0;

    virtual INode*              DL_STDCALL beautyPass() const = 0;
    virtual INodeIterator*      DL_STDCALL beautyPasses() const = 0;
    virtual INodeIterator*      DL_STDCALL extraPasses() const = 0;
    virtual INodeIterator*      DL_STDCALL allPasses() const = 0;

    virtual INode*              DL_STDCALL defaultMaterial() const = 0;
    virtual INode*              DL_STDCALL overrideMaterial() const = 0;

    virtual INodeIterator*      DL_STDCALL stateDependencies( StringVector types = { }, Bool topoSort = false ) const = 0;
    virtual INodeIterator*      DL_STDCALL unreferencedNodes( StringVector types = { } ) const = 0;

    virtual Bool                DL_STDCALL parse( String text ) = 0;
    virtual String              DL_STDCALL serialize( Bool writeDefaults = false, SceneProgress* progress = nullptr ) const = 0;
    virtual StringVector        DL_STDCALL supportedFileTypes() const = 0;
    virtual Bool                DL_STDCALL canRead( String path ) const = 0;
    virtual INode*              DL_STDCALL read( String path, Bool asFragment = false, SceneProgress* progress = nullptr ) = 0;
    virtual INode*              DL_STDCALL import( String pathOrFragment, SceneProgress * progress = nullptr, Bool adjustDisplayNames = true ) = 0;
    virtual Bool                DL_STDCALL write( String path, SceneProgress* progress = nullptr ) = 0;
    virtual IScene*             DL_STDCALL clone() const = 0;

    virtual String              DL_STDCALL applyMacros( String path ) const = 0;

    virtual String              DL_STDCALL location( Bool applyMacros = true ) const = 0;
    virtual String              DL_STDCALL setLocation( String path ) = 0;

    virtual String              DL_STDCALL outputName( Bool applyMacros = true ) const = 0;
    virtual String              DL_STDCALL outputDir( Bool useFallbacks = true ) const = 0;
    virtual String              DL_STDCALL outputPath( INode* pass ) const = 0;

    virtual String              DL_STDCALL resolveInputPath( INode* inputPath, Bool updateNode = true ) = 0;
    virtual Bool                DL_STDCALL resolveInputPaths( Bool updateNodes = true ) = 0;

    virtual UInt                DL_STDCALL numThreads( Bool forIPR = false ) const = 0;

    virtual String              DL_STDCALL bsiPath( INode* beautyPass ) const = 0;
    virtual String              DL_STDCALL bsiTempPath( INode* beautyPass ) const = 0;
    virtual Bool                DL_STDCALL canResumeBsi( INode* beautyPass ) const = 0;

    virtual String              DL_STDCALL htmlHelp( String lang = "auto" ) const = 0;
    virtual String              DL_STDCALL writeHtmlHelp( String& status, String lang = "auto" ) = 0;
    virtual Bool                DL_STDCALL showHtmlHelp( String& status, String lang = "auto" ) = 0;

    virtual void                DL_STDCALL enableUndo() = 0;
    virtual void                DL_STDCALL disableUndo() = 0;
    virtual Bool                DL_STDCALL undoEnabled() const = 0;

    virtual Int                 DL_STDCALL undoLimit() const = 0;
    virtual void                DL_STDCALL setUndoLimit( Int num = -1 ) = 0;
    virtual void                DL_STDCALL clearUndo() = 0;

    virtual Bool                DL_STDCALL canUndo() const = 0;
    virtual Bool                DL_STDCALL canRedo() const = 0;

    virtual Bool                DL_STDCALL undo( UInt num = 1 ) = 0;
    virtual Bool                DL_STDCALL redo( UInt num = 1 ) = 0;

    virtual StringVector        DL_STDCALL undoList() const = 0;
    virtual StringVector        DL_STDCALL redoList() const = 0;

    virtual void                DL_STDCALL pushUndoGroup() = 0;
    virtual void                DL_STDCALL popUndoGroup( String undoDesc = "", String redoDesc = "" ) = 0;
    virtual Bool                DL_STDCALL inUndoGroup() const = 0;

    virtual void                DL_STDCALL enableEvents() = 0;
    virtual void                DL_STDCALL disableEvents() = 0;
    virtual Bool                DL_STDCALL eventsEnabled() const = 0;

    virtual void                DL_STDCALL pushEventGroup() = 0;
    virtual void                DL_STDCALL popEventGroup() = 0;
    virtual Bool                DL_STDCALL inEventGroup() const = 0;

    virtual Bool                DL_STDCALL isDirty() const = 0;

    virtual StringVector        DL_STDCALL allResources( Bool includeMissing = true ) = 0;
    virtual StringVector        DL_STDCALL referencedResources( Bool includeMissing = false ) = 0;
    virtual StringVector        DL_STDCALL missingResources( Bool referencedOnly = true ) = 0;
    virtual Bool                DL_STDCALL gatherResources( Bool referencedOnly = true ) = 0;
};

//=================================================================================================
// ILibInfo.
//=================================================================================================

#define DL_NODES_DIRNAME    "nodes"
#define DL_NODELIB_EXT_BND  ".bnd"
#define DL_NODELIB_EXT_BNL  ".bnl"

class ILibInfo /* final */ : public IRefCounted
{
public:
    // API Version 26.1.0.0
    virtual Bool                DL_STDCALL load( String path ) = 0;
    virtual Bool                DL_STDCALL ok() const = 0;
    virtual String              DL_STDCALL status() const = 0;
    virtual String              DL_STDCALL summary( const IScene* scene = nullptr ) const = 0;

    virtual String              DL_STDCALL name() const = 0;
    virtual String              DL_STDCALL author() const = 0;
    virtual String              DL_STDCALL description() const = 0;
    virtual String              DL_STDCALL url() const = 0;
    virtual String              DL_STDCALL prefix() const = 0;
    virtual String              DL_STDCALL version() const = 0;
    virtual String              DL_STDCALL sdkVersion() const = 0;

    virtual String              DL_STDCALL id() const = 0;
    virtual String              DL_STDCALL file() const = 0;
    virtual String              DL_STDCALL libPath() const = 0;
    virtual String              DL_STDCALL libHash() const = 0;
    virtual String              DL_STDCALL bndText() const = 0;
    virtual String              DL_STDCALL svgIcon() const = 0;
};

//=================================================================================================
// IPbrTextureSet.
//=================================================================================================

class IPbrTextureSet /* final */ : public IRefCounted
{
public:
    // API Version 26.1.0.0
    virtual UInt                DL_STDCALL resolve( String path, INode* pbr = nullptr  ) = 0;
    virtual String              DL_STDCALL summary() const = 0;

    virtual void                DL_STDCALL addMatch( String type, String match ) = 0;
    virtual void                DL_STDCALL setMatches( String type, StringVector matches ) = 0;
    virtual StringVector        DL_STDCALL getMatches( String type ) const = 0;

    virtual String              DL_STDCALL inputPath() const = 0;
    virtual StringVector        DL_STDCALL resolvedPaths() const = 0;
    virtual UInt                DL_STDCALL numResolvedPaths() const = 0;

    virtual Bool                DL_STDCALL applyTo( INode* node, Bool setPath = true ) const = 0;

    virtual String              DL_STDCALL opacity() const = 0;
    virtual String              DL_STDCALL color() const = 0;

    virtual String              DL_STDCALL metallic() const = 0;
    virtual String              DL_STDCALL roughness() const = 0;

    virtual String              DL_STDCALL specular() const = 0;
    virtual String              DL_STDCALL glossiness() const = 0;

    virtual String              DL_STDCALL aniso() const = 0;
    virtual String              DL_STDCALL anisoRotation() const = 0;

    virtual String              DL_STDCALL bump() const = 0;
    virtual String              DL_STDCALL normal() const = 0;
    virtual String              DL_STDCALL displacement() const = 0;

    virtual String              DL_STDCALL emission() const = 0;
    virtual String              DL_STDCALL scattering() const = 0;
    virtual String              DL_STDCALL ao() const = 0;
};

} // interfaces
} // bella_sdk
} // dl

#endif // BELLA_SDK_SCENEAPI_H
