#include <EffectI.h>
Inheritance diagram for Composition::EffectI:
The effect interface is one of the most import interfaces in Demopaja for the coder. Every effect to be shown on screen have to be derived from this class.
In normal play mode there are two metods which are called every frame: eval_state() and do_frame(). The first evaluates the state of the specified frame, calculates all data that can be calculated before hand. The latter renders the effect to the screen.
The reason to cut the rendering in tow parts is that sometimes the Demopaja editor needs some information about the effect but there is no need to render the object. Also a frame can be rendered multiple time while editing and there's no reason to update the data, only to draw it.
To create a new instace of the effect class a static member should be created, which takes care of the instantiating. The member could look like this:
TestEffectC* TestEffectC::create_new() { return new TestEffectC; }
|
Default constructor.
|
|
Default constructor with reference to the original.
|
|
Default destructor.
|
|
Sets only specified flags. Implemented by the EffectI class. |
|
Deep copy from a data block, see Edit::DataBlockI::copy(). When overriding this method the base class member should be called first. Example: void TestEffectC::copy( DataBlockI* pBlock ) { EffectI::copy( pBlock ); TestEffectC* pEffect = (TestEffectC*)pBlock; m_pGizmo->copy( pEffect->m_pGizmo ); } Reimplemented from Edit::EditableI. |
|
Removes only specified flags. Implemented by the EffectI class. |
|
Execute (draws, plays, etc.) the current state of the effect. All the rendering code goes in this method. Example: void PlasmaEffectC::do_frame( DeviceContextC* pContext ) { // Query the interface to use. OpenGLInterfaceC* pInterface = (OpenGLInterfaceC*)pContext->query_interface( INTERFACE_OPENGL ); if( !pInterface ) return; // Use the interface to set the rendering area. pInterface->set_ortho( m_rBBox, m_rBBox.width(), m_rBBox.height() ); // Render the effect ... } |
|
Evaluate the state of this effect at specified time. All the calculation should be done in this method. The eval_state() and do_frame() have been separated to allow the user interface to update the state of the effect only once and draw the effect many times. The eval_state() method may also be called to update the data (such as the transformation matrix), but not to draw it. Example:
void TestEffectC::eval_state( int32 i32Time, TimeContextC* pTimeContext ) { Matrix2C rPosMat, rRotMat, rScaleMat, rPivotMat; Vector2C rPivot = m_pGizmo->get_pivot( i32Time ); // Calc matrix. rPivotMat.set_trans( -rPivot ); rPosMat.set_trans( m_pGizmo->get_pos( i32Time ) + rPivot ); rRotMat.set_rot( m_pGizmo->get_rot( i32Time ) / 180.0f * M_PI ); rScaleMat.set_scale( m_pGizmo->get_scale( i32Time ) ) ; // Store matrix. m_rTM = rPivotMat * rRotMat * rScaleMat * rPosMat; // Calc bounding box float32 f32Width = 25, f32Height = 25; Vector2C rMin, rMax, rVec; m_rVertices[0][0] = -f32Width; // top-left m_rVertices[0][1] = -f32Height; m_rVertices[1][0] = f32Width; // top-right m_rVertices[1][1] = -f32Height; m_rVertices[2][0] = f32Width; // bottom-right m_rVertices[2][1] = f32Height; m_rVertices[3][0] = -f32Width; // bottom-left m_rVertices[3][1] = f32Height; for( uint32 i = 0; i < 4; i++ ) { rVec = m_rTM * m_rVertices[i]; m_rVertices[i] = rVec; if( !i ) rMin = rMax = rVec; else { if( rVec[0] < rMin[0] ) rMin[0] = rVec[0]; if( rVec[1] < rMin[1] ) rMin[1] = rVec[1]; if( rVec[0] > rMax[0] ) rMax[0] = rVec[0]; if( rVec[1] > rMax[1] ) rMax[1] = rVec[1]; } } // Store bounding box. m_rBBox[0] = rMin; m_rBBox[1] = rMax; } |
|
Returns axis-aligned bounding box of the effect.
|
|
Returns unique class ID of the effect.
|
|
Returns effect's class name as NULL terminated string.
|
|
Returns default parameter. Default parameters are commonly used parameters such as position and scale. Example: ParamI* TestEffectC::get_default_param( PajaTypes::int32 i32Param ) { if( i32Param == DEFAULT_PARAM_POSITION ) return m_pGizmo->get_parameter( TEST_PARAM_POS ); else if( i32Param == DEFAULT_PARAM_ROTATION ) return m_pGizmo->get_parameter( TEST_PARAM_ROT ); return 0; }
|
|
Returns effect flags. Implemented by the EffectI class. |
|
Returns gizmo at specified index.
|
|
Returns number of gizmos in the effect.
|
|
Returns the name of the effect. Implemented by the EffectI class. |
|
Returns super class ID of the effect (should be SUPERCLASS_EFFECT for effects).
|
|
Returns the timesegment of this effect. Implemented by the EffectI class. |
|
Returns transformaion matrix of the effect.
|
|
Returns true if the given point is inside the region of the effect. Example: bool TestEffectC::hit_test( const PajaTypes::Vector2C& rPoint ) { // Point in polygon test (from comp.graphics.algorithms FAQ). int32 i, j; bool bInside = false; for( i = 0, j = 4 - 1; i < 4; j = i++ ) { if( ( ((m_rVertices[i][1] <= rPoint[1]) && (rPoint[1] < m_rVertices[j][1])) || ((m_rVertices[j][1] <= rPoint[1]) && (rPoint[1] < m_rVertices[i][1])) ) && (rPoint[0] < (m_rVertices[j][0] - m_rVertices[i][0]) * (rPoint[1] - m_rVertices[i][1]) / (m_rVertices[j][1] - m_rVertices[i][1]) + m_rVertices[i][0]) ) bInside = !bInside; } return bInside; } |
|
Initialize effect. This method is called after all data is passed to the effect. That is, after the effect has been loaded from file or after the effect is created, and all the possible data is set. Usually there is no need to do anything in this method. |
|
Serialize effect from a Demopaja input stream. The base class implementation of this method has to be called in the overridden method. Example: uint32 TestEffectC::load( LoadC* pLoad ) { uint32 ui32Error = IO_OK; while( (ui32Error = pLoad->open_chunk()) == IO_OK ) { switch( pLoad->get_chunk_id() ) { case CHUNK_TESTEFFECT_EFFECTI: if( pLoad->get_chunk_version() == TESTEFFECT_VERSION ) ui32Error = EffectI::load( pLoad ); break; default: assert( 0 ); } pLoad->close_chunk(); if( ui32Error != IO_OK && ui32Error != IO_END ) return ui32Error; } return ui32Error; } Reimplemented from Edit::EditableI. |
|
Shallow copy from a editable, see Edit::EditableI::restore(). When overriding this method the base class member should be called first. Example: void TestEffectC::restore( EditableI* pEditable ) { EffectI::restore( pEditable ); TestEffectC* pEffect = (TestEffectC*)pEditable; m_pGizmo = pEffect->m_pGizmo; } Reimplemented from Edit::EditableI. |
|
Serialize effect to a Demopaja output stream. The base class implementation of this method has to be called in the overridden method. Example: uint32 TestEffectC::save( SaveC* pSave ) { uint32 ui32Error = IO_OK; // EffectI stuff pSave->begin_chunk( CHUNK_TESTEFFECT_EFFECTI, TESTEFFECT_VERSION ); ui32Error = EffectI::save( pSave ); pSave->end_chunk(); return ui32Error; } Reimplemented from Edit::EditableI. |
|
Sets the default file if effect has a default file. If the effect uses file parameters one of the file parameters has to be set as default file parameter. This is used for example is a file is dragged from File Inspector window to the Timeline Window. That causes new effect to be created and the dragged file to be set as default file. This method does not have to accept the file. |
|
Sets the effect flags. Be careful to use this method. There are some flags, which have to be in place to make the effect work correctly. Use add, del or toggle flags methods instead. |
|
Sets the name of the effect. Implemented by the EffectI class. |
|
Toggles only specified flags. Implemented by the EffectI class. |
|
This method is called when a parameter is changed. Do not call the rendering methods from this method. The system will automatically update the state effect if a parameter is changed. |