diff --git a/include/eepp/scene/node.hpp b/include/eepp/scene/node.hpp index aa527b9bd..cdc3042fd 100644 --- a/include/eepp/scene/node.hpp +++ b/include/eepp/scene/node.hpp @@ -1,16 +1,21 @@ #ifndef EE_SCENE_NODE_HPP #define EE_SCENE_NODE_HPP -#include -#include #include #include #include #include -#include -#include -using namespace EE::UI; +#include +using namespace EE::Graphics; + +#include +#include +#include +#include +#include +#include +using namespace EE::Math; namespace EE { namespace Scene { class Action; @@ -22,9 +27,40 @@ namespace EE { namespace UI { class UIWindow; class UIManager; }} +using namespace EE::UI; namespace EE { namespace Scene { +enum NODE_FLAGS_VALUES { + NODE_FLAG_VIEW_DIRTY = (1<<1), + NODE_FLAG_POSITION_DIRTY = (1<<2), + NODE_FLAG_POLYGON_DIRTY = (1<<3), + NODE_FLAG_ROTATED = (1<<4), + NODE_FLAG_SCALED = (1<<5), + NODE_FLAG_CLOSE = (1<<6), + NODE_FLAG_CLOSE_DELAYED = (1<<7), + NODE_FLAG_MOUSEOVER = (1<<8), + NODE_FLAG_HAS_FOCUS = (1<<9), + NODE_FLAG_SELECTED = (1<<10), + NODE_FLAG_DISABLE_DELAYED = (1<<11), + NODE_FLAG_MOUSEOVER_ME_OR_CHILD = (1<<12), + NODE_FLAG_DRAGGING = (1<<13), + NODE_FLAG_SKIN_OWNER = (1<<14), + NODE_FLAG_TOUCH_DRAGGING = (1<<15), + NODE_FLAG_DISABLED_BY_MODAL_WINDOW = (1<<16), + NODE_FLAG_OWNED_BY_WINDOW = (1<<17), + NODE_FLAG_REVERSE_DRAW = (1<<18), + NODE_FLAG_FRAME_BUFFER = (1<<19), + NODE_FLAG_CLIP_ENABLE = (1<<20), + NODE_FLAG_SCENENODE = (1<<21), + NODE_FLAG_UINODE = (1<<22), + NODE_FLAG_WIDGET = (1<<23), + NODE_FLAG_WINDOW = (1<<24), + NODE_FLAG_REPORT_SIZE_CHANGE_TO_CHILDS = (1<<25), + NODE_FLAG_OVER_FIND_ALLOWED = (1<<26), + NODE_FLAG_FREE_USE = (1<<27) +}; + class EE_API Node : public Transformable { public: static Node * New(); diff --git a/include/eepp/scene/scenenode.hpp b/include/eepp/scene/scenenode.hpp new file mode 100644 index 000000000..d1ef3e4ce --- /dev/null +++ b/include/eepp/scene/scenenode.hpp @@ -0,0 +1,65 @@ +#ifndef EE_SCENENODE_HPP +#define EE_SCENENODE_HPP + +#include + +namespace EE { namespace Graphics { +class FrameBuffer; +}} + +namespace EE { namespace Window { +class Window; +}} + +namespace EE { namespace Scene { + +class EE_API SceneNode : public Node { + public: + static SceneNode * New( EE::Window::Window * window = NULL ); + + SceneNode( EE::Window::Window * window = NULL ); + + ~SceneNode(); + + void enableFrameBuffer(); + + void disableFrameBuffer(); + + virtual void draw(); + + virtual void update( const Time& elapsed ); + + bool invalidated(); + + void enableDrawInvalidation(); + + void disableDrawInvalidation(); + protected: + friend class Node; + + EE::Window::Window * mWindow; + FrameBuffer * mFrameBuffer; + std::list mCloseList; + bool mFrameBufferBound; + bool mUseInvalidation; + + virtual void onSizeChange(); + + virtual void matrixSet(); + + virtual void matrixUnset(); + + void addToCloseQueue( Node * Ctrl ); + + void checkClose(); + + void createFrameBuffer(); + + void drawFrameBuffer(); + + Sizei getFrameBufferSize(); +}; + +}} + +#endif diff --git a/include/eepp/ui/uihelper.hpp b/include/eepp/ui/uihelper.hpp index f959f32bf..21b6b4c6b 100644 --- a/include/eepp/ui/uihelper.hpp +++ b/include/eepp/ui/uihelper.hpp @@ -5,35 +5,6 @@ namespace EE { namespace UI { -enum NODE_FLAGS_VALUES { - NODE_FLAG_VIEW_DIRTY = (1<<1), - NODE_FLAG_POSITION_DIRTY = (1<<2), - NODE_FLAG_POLYGON_DIRTY = (1<<3), - NODE_FLAG_ROTATED = (1<<4), - NODE_FLAG_SCALED = (1<<5), - NODE_FLAG_CLOSE = (1<<6), - NODE_FLAG_CLOSE_DELAYED = (1<<7), - NODE_FLAG_MOUSEOVER = (1<<8), - NODE_FLAG_HAS_FOCUS = (1<<9), - NODE_FLAG_SELECTED = (1<<10), - NODE_FLAG_DISABLE_DELAYED = (1<<11), - NODE_FLAG_MOUSEOVER_ME_OR_CHILD = (1<<12), - NODE_FLAG_DRAGGING = (1<<13), - NODE_FLAG_SKIN_OWNER = (1<<14), - NODE_FLAG_TOUCH_DRAGGING = (1<<15), - NODE_FLAG_DISABLED_BY_MODAL_WINDOW = (1<<16), - NODE_FLAG_OWNED_BY_WINDOW = (1<<17), - NODE_FLAG_REVERSE_DRAW = (1<<18), - NODE_FLAG_FRAME_BUFFER = (1<<19), - NODE_FLAG_CLIP_ENABLE = (1<<20), - NODE_FLAG_UINODE = (1<<21), - NODE_FLAG_WIDGET = (1<<22), - NODE_FLAG_WINDOW = (1<<23), - NODE_FLAG_REPORT_SIZE_CHANGE_TO_CHILDS = (1<<24), - NODE_FLAG_OVER_FIND_ALLOWED = (1<<25), - NODE_FLAG_FREE_USE = (1<<26) -}; - #define UI_HALIGN_LEFT TEXT_ALIGN_LEFT #define UI_HALIGN_MASK TEXT_HALIGN_MASK #define UI_VALIGN_TOP TEXT_ALIGN_TOP diff --git a/include/eepp/ui/uinode.hpp b/include/eepp/ui/uinode.hpp index 5034127f3..a67ddd9d1 100644 --- a/include/eepp/ui/uinode.hpp +++ b/include/eepp/ui/uinode.hpp @@ -205,8 +205,6 @@ class EE_API UINode : public Node { virtual void onChildCountChange(); - virtual void clipStart(); - virtual Uint32 onDrag( const Vector2f& position ); virtual Uint32 onDragStart( const Vector2i& position ); @@ -223,8 +221,6 @@ class EE_API UINode : public Node { virtual void internalDraw(); - virtual void clipEnd(); - virtual void onWidgetFocusLoss(); void setPrevSkinState(); diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 7c9fda485..e7adf5a3f 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -1,12 +1,14 @@ ../../include/eepp/scene/event.hpp ../../include/eepp/scene/keyevent.hpp ../../include/eepp/scene/mouseevent.hpp +../../include/eepp/scene/scenenode.hpp ../../include/eepp/window/displaymanager.hpp ../../src/eepp/graphics/renderer/shaders/basegl3cp.gles2.frag.h ../../src/eepp/graphics/renderer/shaders/basegl3cp.gles2.vert.h ../../src/eepp/scene/event.cpp ../../src/eepp/scene/keyevent.cpp ../../src/eepp/scene/mouseevent.cpp +../../src/eepp/scene/scenenode.cpp ../../src/eepp/window/backend/SDL2/displaymanagersdl2.cpp ../../src/eepp/window/backend/SDL2/displaymanagersdl2.hpp ../../src/eepp/window/backend/SFML/displaymanagersfml.cpp diff --git a/src/eepp/scene/node.cpp b/src/eepp/scene/node.cpp index 8f6cb6f55..28b889292 100644 --- a/src/eepp/scene/node.cpp +++ b/src/eepp/scene/node.cpp @@ -479,9 +479,23 @@ void Node::internalDraw() { } void Node::clipStart() { + if ( mVisible && isClipped() ) { + if ( isMeOrParentTreeScaledOrRotatedOrFrameBuffer() ) { + GLi->getClippingMask()->clipPlaneEnable( mScreenPos.x, mScreenPos.y, mSize.getWidth(), mSize.getHeight() ); + } else { + GLi->getClippingMask()->clipEnable( mScreenPos.x, mScreenPos.y, mSize.getWidth(), mSize.getHeight() ); + } + } } void Node::clipEnd() { + if ( mVisible && isClipped() ) { + if ( isMeOrParentTreeScaledOrRotatedOrFrameBuffer() ) { + GLi->getClippingMask()->clipPlaneDisable(); + } else { + GLi->getClippingMask()->clipDisable(); + } + } } void Node::matrixSet() { diff --git a/src/eepp/scene/scenenode.cpp b/src/eepp/scene/scenenode.cpp new file mode 100644 index 000000000..080e1e514 --- /dev/null +++ b/src/eepp/scene/scenenode.cpp @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace EE { namespace Scene { + +SceneNode * SceneNode::New( EE::Window::Window * window ) { + return eeNew( SceneNode, ( window ) ); +} + +SceneNode::SceneNode( EE::Window::Window * window ) : + Node(), + mWindow( window ), + mFrameBuffer( NULL ), + mFrameBufferBound( false ), + mUseInvalidation( false ) +{ + if ( NULL == mWindow ) { + mWindow = Engine::instance()->getCurrentWindow(); + } +} + +SceneNode::~SceneNode() { + onClose(); + + eeSAFE_DELETE( mFrameBuffer ); +} + +void SceneNode::enableFrameBuffer() { + if ( NULL == mFrameBuffer ) + createFrameBuffer(); +} + +void SceneNode::disableFrameBuffer() { + eeSAFE_DELETE( mFrameBuffer ); +} + +void SceneNode::draw() { + GlobalBatchRenderer::instance()->draw(); + + const View& prevView = mWindow->getView(); + + mWindow->setView( mWindow->getDefaultView() ); + + if ( mVisible ) { + if ( mNodeFlags & NODE_FLAG_POSITION_DIRTY ) + updateScreenPos(); + + matrixSet(); + + clipStart(); + + draw(); + + drawChilds(); + + clipEnd(); + + matrixUnset(); + } + + mWindow->setView( prevView ); + + GlobalBatchRenderer::instance()->draw(); +} + +void SceneNode::update( const Time& elapsed ) { + + checkClose(); + + Node::update( elapsed ); +} + +void SceneNode::onSizeChange() { + if ( NULL != mFrameBuffer && ( mFrameBuffer->getWidth() < mSize.getWidth() || mFrameBuffer->getHeight() < mSize.getHeight() ) ) { + if ( NULL == mFrameBuffer ) { + createFrameBuffer(); + } else { + Sizei fboSize( getFrameBufferSize() ); + mFrameBuffer->resize( fboSize.getWidth(), fboSize.getHeight() ); + } + } +} + +void SceneNode::addToCloseQueue( Node * Ctrl ) { + eeASSERT( NULL != Ctrl ); + + std::list::iterator it; + Node * itCtrl = NULL; + + for ( it = mCloseList.begin(); it != mCloseList.end(); ++it ) { + itCtrl = *it; + + if ( NULL != itCtrl && itCtrl->isParentOf( Ctrl ) ) { + // If a parent will be removed, means that the control + // that we are trying to queue will be removed by the father + // so we skip it + return; + } + } + + std::list< std::list::iterator > itEraseList; + + for ( it = mCloseList.begin(); it != mCloseList.end(); ++it ) { + itCtrl = *it; + + if ( NULL != itCtrl && Ctrl->isParentOf( itCtrl ) ) { + // if the control added is parent of another control already added, + // we remove the already added control because it will be deleted + // by its parent + itEraseList.push_back( it ); + } else if ( NULL == itCtrl ) { + itEraseList.push_back( it ); + } + } + + // We delete all the controls that don't need to be deleted + // because of the new added control to the queue + std::list< std::list::iterator >::iterator ite; + + for ( ite = itEraseList.begin(); ite != itEraseList.end(); ++ite ) { + mCloseList.erase( *ite ); + } + + mCloseList.push_back( Ctrl ); +} + +void SceneNode::checkClose() { + if ( !mCloseList.empty() ) { + for ( std::list::iterator it = mCloseList.begin(); it != mCloseList.end(); ++it ) { + eeDelete( *it ); + } + + mCloseList.clear(); + } +} + +Sizei SceneNode::getFrameBufferSize() { + return mSize.ceil().asInt(); +} + +void SceneNode::createFrameBuffer() { + eeSAFE_DELETE( mFrameBuffer ); + Sizei fboSize( getFrameBufferSize() ); + if ( fboSize.getWidth() < 1 ) fboSize.setWidth(1); + if ( fboSize.getHeight() < 1 ) fboSize.setHeight(1); + mFrameBuffer = FrameBuffer::New( fboSize.getWidth(), fboSize.getHeight(), true, false, true ); +} + +void SceneNode::drawFrameBuffer() { + if ( NULL != mFrameBuffer ) { + if ( mFrameBuffer->hasColorBuffer() ) { + mFrameBuffer->draw( Rect( 0, 0, mSize.getWidth(), mSize.getHeight() ), Rect( mScreenPos.x, mScreenPos.y, mScreenPos.x + mSize.getWidth(), mScreenPos.y + mSize.getHeight() ) ); + } else { + TextureRegion textureRegion( mFrameBuffer->getTexture()->getId(), Rect( 0, 0, mSize.getWidth(), mSize.getHeight() ) ); + textureRegion.draw( mScreenPosi.x, mScreenPosi.y, Color::White, getRotation(), getScale() ); + } + } +} + +bool SceneNode::invalidated() { + return 0 != ( mNodeFlags & NODE_FLAG_VIEW_DIRTY ); +} + +void SceneNode::enableDrawInvalidation() { + mUseInvalidation = true; +} + +void SceneNode::disableDrawInvalidation() { + mUseInvalidation = false; +} + +void SceneNode::matrixSet() { + if ( NULL != mFrameBuffer ) { + if ( !mUseInvalidation || invalidated() ) { + mFrameBufferBound = true; + + mFrameBuffer->bind(); + + mFrameBuffer->clear(); + } + + if ( 0.f != mScreenPos ) { + GLi->pushMatrix(); + GLi->translatef( -mScreenPos.x , -mScreenPos.y, 0.f ); + } + } else { + Node::matrixSet(); + } +} + +void SceneNode::matrixUnset() { + if ( NULL != mFrameBuffer ) { + GlobalBatchRenderer::instance()->draw(); + + if ( 0.f != mScreenPos ) + GLi->popMatrix(); + + if ( mFrameBufferBound ) { + mFrameBuffer->unbind(); + + mFrameBufferBound = false; + } + + drawFrameBuffer(); + } else { + Node::matrixUnset(); + } +} + +}} diff --git a/src/eepp/ui/uinode.cpp b/src/eepp/ui/uinode.cpp index 8c0af67bb..8aad6bcab 100644 --- a/src/eepp/ui/uinode.cpp +++ b/src/eepp/ui/uinode.cpp @@ -459,18 +459,6 @@ void UINode::internalDraw() { } } -void UINode::clipStart() { - if ( mVisible && isClipped() ) { - UIManager::instance()->clipSmartEnable( this, mScreenPos.x, mScreenPos.y, mSize.getWidth(), mSize.getHeight() ); - } -} - -void UINode::clipEnd() { - if ( mVisible && isClipped() ) { - UIManager::instance()->clipSmartDisable( this ); - } -} - UIBackground * UINode::getBackground() { if ( NULL == mBackground ) { mBackground = UIBackground::New( this );