Merge branch 'develop' of https://github.com/cocos2d/cocos2d-x into develop_new_fix

This commit is contained in:
samuele3hu 2014-03-04 10:27:25 +08:00
commit 987afe2272
349 changed files with 2951 additions and 13782 deletions

View File

@ -770,6 +770,12 @@ Developers:
seemk seemk
Fixed crash if invoking Director::end() on WINDOWS. Fixed crash if invoking Director::end() on WINDOWS.
odedsh
Fixed a bug that loading custom fonts from ttf file fails on windows.
Wilhansen
Fixed a bug that spine::Skeleton would not be updated after re-adding to scene.
Retired Core Developers: Retired Core Developers:
WenSheng Yang WenSheng Yang

View File

@ -3,6 +3,8 @@ cocos2d-x-3.0rc0 Feb.?? 2014
[NEW] Action: RotateBy supports 3D rotations [NEW] Action: RotateBy supports 3D rotations
[NEW] Bindings: Using python to automatically generate script bindings [NEW] Bindings: Using python to automatically generate script bindings
[NEW] Bindings: Added JS bindings support for Linux [NEW] Bindings: Added JS bindings support for Linux
[NEW] ccConfig.h: removed support for CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
[NEW] Console: Added command: 'autotest run|main|next|back|restart'.
[NEW] Console: Added 'resolution', 'projection' commands. Improved API [NEW] Console: Added 'resolution', 'projection' commands. Improved API
[NEW] Console: Added more commands: director resume|pause|stopanimation|startanimation. [NEW] Console: Added more commands: director resume|pause|stopanimation|startanimation.
[NEW] Console: Added command: 'touch tap|swipe' to simulating touch events. [NEW] Console: Added command: 'touch tap|swipe' to simulating touch events.
@ -13,9 +15,13 @@ cocos2d-x-3.0rc0 Feb.?? 2014
Node: set/get VertexZ() -> set/get PositionZ() Node: set/get VertexZ() -> set/get PositionZ()
Node: setRotationX() -> setRotationSkewX() Node: setRotationX() -> setRotationSkewX()
Node: setRotationY() -> setRotationSkewY() Node: setRotationY() -> setRotationSkewY()
Node: visit() and draw() new arguments: Renderer, parentTransform, and whether or not the parentTransform has changed since the last frame
[NEW] Language: Added Dutch support. [NEW] Language: Added Dutch support.
[NEW] Sprite: Added auto-culling support [NEW] Sprite: Added auto-culling support. Performance increased in about 100% when many sprites are outside the screen
[FIX] EditBox's position would not be updated if its parent's position changed.
[FIX] spine::Skeleton would not be updated after being re-added to scene.
[FIX] Loading custom fonts from ttf file fails on windows.
[FIX] FadeIn and FadeOut behaviours is incorrect if it doesn't start from an edge value( 0 or 255). [FIX] FadeIn and FadeOut behaviours is incorrect if it doesn't start from an edge value( 0 or 255).
[FIX] Renderer: Expand textureID bit from 18bits to 32bits. Resolves probably crash on Linux / Android. [FIX] Renderer: Expand textureID bit from 18bits to 32bits. Resolves probably crash on Linux / Android.
[FIX] Potential crash by switching repeatly between HttpClientTest, WebSocketTest, SocketIOTest. [FIX] Potential crash by switching repeatly between HttpClientTest, WebSocketTest, SocketIOTest.
@ -45,6 +51,8 @@ cocos2d-x-3.0rc0 Feb.?? 2014
[FIX] EGLView improvements: renamed to GLView, no longer a singleton, easier to customize [FIX] EGLView improvements: renamed to GLView, no longer a singleton, easier to customize
[FIX] Removes samples except testcpp|testjavascript|testlua. Moves sample games to `cocos2d/samples` repo. [FIX] Removes samples except testcpp|testjavascript|testlua. Moves sample games to `cocos2d/samples` repo.
[FIX] cc.BuilderReader.load( path, null, parentSize ); was not allowed. [FIX] cc.BuilderReader.load( path, null, parentSize ); was not allowed.
[FIX] Node: setAdditionalTransform receives a pointer and not a const reference
cocos2d-x-3.0beta2 Jan.24 2014 cocos2d-x-3.0beta2 Jan.24 2014
[All] [All]

View File

@ -1 +1 @@
3e5af93e674100c3fcff441051ba5d9d6f3be7bb 8fad051dc33d390c01df304fee2a78e22785136f

View File

@ -122,7 +122,7 @@ void ActionCamera::updateTransform()
// But that operation needs to be done after all the 'updates'. // But that operation needs to be done after all the 'updates'.
// So the Director should emit an 'director_after_update' event. // So the Director should emit an 'director_after_update' event.
// And this object should listen to it // And this object should listen to it
_target->setAdditionalTransform(mv); _target->setAdditionalTransform(&mv);
} }
// //

View File

@ -35,7 +35,6 @@ THE SOFTWARE.
#include "CCDirector.h" #include "CCDirector.h"
#include "TransformUtils.h" #include "TransformUtils.h"
#include "renderer/CCRenderer.h" #include "renderer/CCRenderer.h"
#include "renderer/CCQuadCommand.h"
// external // external
#include "kazmath/GL/matrix.h" #include "kazmath/GL/matrix.h"
@ -110,8 +109,7 @@ bool AtlasNode::initWithTexture(Texture2D* texture, int tileWidth, int tileHeigh
_quadsToDraw = itemsToRender; _quadsToDraw = itemsToRender;
// shader stuff // shader stuff
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_U_COLOR)); setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP));
_uniformColor = glGetUniformLocation( getShaderProgram()->getProgram(), "u_color");
return true; return true;
} }
@ -138,30 +136,18 @@ void AtlasNode::updateAtlasValues()
} }
// AtlasNode - draw // AtlasNode - draw
void AtlasNode::draw(void) void AtlasNode::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
// CC_NODE_DRAW_SETUP();
//
// GL::blendFunc( _blendFunc.src, _blendFunc.dst );
//
// GLfloat colors[4] = {_displayedColor.r / 255.0f, _displayedColor.g / 255.0f, _displayedColor.b / 255.0f, _displayedOpacity / 255.0f};
// getShaderProgram()->setUniformLocationWith4fv(_uniformColor, colors, 1);
//
// _textureAtlas->drawNumberOfQuads(_quadsToDraw, 0);
auto shader = ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP);
_quadCommand.init( _quadCommand.init(
_globalZOrder, _globalZOrder,
_textureAtlas->getTexture()->getName(), _textureAtlas->getTexture()->getName(),
shader, _shaderProgram,
_blendFunc, _blendFunc,
_textureAtlas->getQuads(), _textureAtlas->getQuads(),
_quadsToDraw, _quadsToDraw,
_modelViewTransform); transform);
Director::getInstance()->getRenderer()->addCommand(&_quadCommand); renderer->addCommand(&_quadCommand);
} }

View File

@ -69,7 +69,7 @@ public:
// Overrides // Overrides
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual Texture2D* getTexture() const override; virtual Texture2D* getTexture() const override;
virtual void setTexture(Texture2D *texture) override; virtual void setTexture(Texture2D *texture) override;
virtual bool isOpacityModifyRGB() const override; virtual bool isOpacityModifyRGB() const override;

View File

@ -199,17 +199,24 @@ void ClippingNode::drawFullScreenQuadClearStencil()
kmGLPopMatrix(); kmGLPopMatrix();
} }
void ClippingNode::visit() void ClippingNode::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
if(!_visible) if(!_visible)
return; return;
bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
_modelViewTransform = transform(parentTransform);
_transformUpdated = false;
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix(); kmGLPushMatrix();
transform(); kmGLLoadMatrix(&_modelViewTransform);
//Add group command //Add group command
Renderer* renderer = Director::getInstance()->getRenderer();
_groupCommand.init(_globalZOrder); _groupCommand.init(_globalZOrder);
renderer->addCommand(&_groupCommand); renderer->addCommand(&_groupCommand);
@ -236,7 +243,7 @@ void ClippingNode::visit()
#endif #endif
} }
_stencil->visit(); _stencil->visit(renderer, _modelViewTransform, dirty);
_afterDrawStencilCmd.init(_globalZOrder); _afterDrawStencilCmd.init(_globalZOrder);
_afterDrawStencilCmd.func = CC_CALLBACK_0(ClippingNode::onAfterDrawStencil, this); _afterDrawStencilCmd.func = CC_CALLBACK_0(ClippingNode::onAfterDrawStencil, this);
@ -253,19 +260,19 @@ void ClippingNode::visit()
auto node = _children.at(i); auto node = _children.at(i);
if ( node && node->getLocalZOrder() < 0 ) if ( node && node->getLocalZOrder() < 0 )
node->visit(); node->visit(renderer, _modelViewTransform, dirty);
else else
break; break;
} }
// self draw // self draw
this->draw(); this->draw(renderer, _modelViewTransform, dirty);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(); (*it)->visit(renderer, _modelViewTransform, dirty);
} }
else else
{ {
this->draw(); this->draw(renderer, _modelViewTransform, dirty);
} }
_afterVisitCmd.init(_globalZOrder); _afterVisitCmd.init(_globalZOrder);

View File

@ -95,7 +95,7 @@ public:
* @lua NA * @lua NA
*/ */
virtual void onExit() override; virtual void onExit() override;
virtual void visit() override; virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
protected: protected:
ClippingNode(); ClippingNode();

View File

@ -140,9 +140,7 @@ bool Director::init(void)
_scheduler = new Scheduler(); _scheduler = new Scheduler();
// action manager // action manager
_actionManager = new ActionManager(); _actionManager = new ActionManager();
_scheduler->scheduleUpdate([this](float dt){ _scheduler->scheduleUpdate(_actionManager, Scheduler::PRIORITY_SYSTEM, false);
this->_actionManager->update(dt);
}, _actionManager, Scheduler::PRIORITY_SYSTEM, false);
_eventDispatcher = new EventDispatcher(); _eventDispatcher = new EventDispatcher();
_eventAfterDraw = new EventCustom(EVENT_AFTER_DRAW); _eventAfterDraw = new EventCustom(EVENT_AFTER_DRAW);
@ -275,17 +273,21 @@ void Director::drawScene()
kmGLPushMatrix(); kmGLPushMatrix();
// global identity matrix is needed... come on kazmath!
kmMat4 identity;
kmMat4Identity(&identity);
// draw the scene // draw the scene
if (_runningScene) if (_runningScene)
{ {
_runningScene->visit(); _runningScene->visit(_renderer, identity, false);
_eventDispatcher->dispatchEvent(_eventAfterVisit); _eventDispatcher->dispatchEvent(_eventAfterVisit);
} }
// draw the notifications node // draw the notifications node
if (_notificationNode) if (_notificationNode)
{ {
_notificationNode->visit(); _notificationNode->visit(_renderer, identity, false);
} }
if (_displayStats) if (_displayStats)
@ -870,9 +872,13 @@ void Director::showStats()
prevVerts = currentVerts; prevVerts = currentVerts;
} }
_drawnVerticesLabel->visit(); // global identity matrix is needed... come on kazmath!
_drawnBatchesLabel->visit(); kmMat4 identity;
_FPSLabel->visit(); kmMat4Identity(&identity);
_drawnVerticesLabel->visit(_renderer, identity, false);
_drawnBatchesLabel->visit(_renderer, identity, false);
_FPSLabel->visit(_renderer, identity, false);
} }
} }

View File

@ -239,11 +239,11 @@ void DrawNode::render()
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
} }
void DrawNode::draw() void DrawNode::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
_customCommand.init(_globalZOrder); _customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(DrawNode::onDraw, this); _customCommand.func = CC_CALLBACK_0(DrawNode::onDraw, this);
Director::getInstance()->getRenderer()->addCommand(&_customCommand); renderer->addCommand(&_customCommand);
} }
void DrawNode::onDraw() void DrawNode::onDraw()

View File

@ -92,7 +92,7 @@ public:
void onDraw(); void onDraw();
// Overrides // Overrides
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
protected: protected:
DrawNode(); DrawNode();

View File

@ -33,6 +33,7 @@
#include "CCNode.h" #include "CCNode.h"
#include "CCDirector.h" #include "CCDirector.h"
#include "CCEventType.h"
#include <algorithm> #include <algorithm>
@ -184,10 +185,18 @@ EventDispatcher::EventDispatcher()
, _nodePriorityIndex(0) , _nodePriorityIndex(0)
{ {
_toAddedListeners.reserve(50); _toAddedListeners.reserve(50);
// fixed #4129: Mark the following listener IDs for internal use.
// Therefore, internal listeners would not be cleaned when removeAllEventListeners is invoked.
_internalCustomListenerIDs.insert(EVENT_COME_TO_FOREGROUND);
_internalCustomListenerIDs.insert(EVENT_COME_TO_BACKGROUND);
} }
EventDispatcher::~EventDispatcher() EventDispatcher::~EventDispatcher()
{ {
// Clear internal custom listener IDs from set,
// so removeAllEventListeners would clean internal custom listeners.
_internalCustomListenerIDs.clear();
removeAllEventListeners(); removeAllEventListeners();
} }
@ -258,9 +267,9 @@ void EventDispatcher::visitTarget(Node* node, bool isRootNode)
} }
} }
void EventDispatcher::pauseTarget(Node* node) void EventDispatcher::pauseEventListenersForTarget(Node* target, bool recursive/* = false */)
{ {
auto listenerIter = _nodeListenersMap.find(node); auto listenerIter = _nodeListenersMap.find(target);
if (listenerIter != _nodeListenersMap.end()) if (listenerIter != _nodeListenersMap.end())
{ {
auto listeners = listenerIter->second; auto listeners = listenerIter->second;
@ -269,11 +278,20 @@ void EventDispatcher::pauseTarget(Node* node)
l->setPaused(true); l->setPaused(true);
} }
} }
if (recursive)
{
const auto& children = target->getChildren();
for (const auto& child : children)
{
pauseEventListenersForTarget(child, true);
}
}
} }
void EventDispatcher::resumeTarget(Node* node) void EventDispatcher::resumeEventListenersForTarget(Node* target, bool recursive/* = false */)
{ {
auto listenerIter = _nodeListenersMap.find(node); auto listenerIter = _nodeListenersMap.find(target);
if (listenerIter != _nodeListenersMap.end()) if (listenerIter != _nodeListenersMap.end())
{ {
auto listeners = listenerIter->second; auto listeners = listenerIter->second;
@ -282,12 +300,21 @@ void EventDispatcher::resumeTarget(Node* node)
l->setPaused(false); l->setPaused(false);
} }
} }
setDirtyForNode(node); setDirtyForNode(target);
if (recursive)
{
const auto& children = target->getChildren();
for (const auto& child : children)
{
resumeEventListenersForTarget(child, true);
}
}
} }
void EventDispatcher::cleanTarget(Node* node) void EventDispatcher::removeEventListenersForTarget(Node* target, bool recursive/* = false */)
{ {
auto listenerIter = _nodeListenersMap.find(node); auto listenerIter = _nodeListenersMap.find(target);
if (listenerIter != _nodeListenersMap.end()) if (listenerIter != _nodeListenersMap.end())
{ {
auto listeners = listenerIter->second; auto listeners = listenerIter->second;
@ -297,6 +324,15 @@ void EventDispatcher::cleanTarget(Node* node)
removeEventListener(l); removeEventListener(l);
} }
} }
if (recursive)
{
const auto& children = target->getChildren();
for (const auto& child : children)
{
removeEventListenersForTarget(child, true);
}
}
} }
void EventDispatcher::associateNodeAndEventListener(Node* node, EventListener* listener) void EventDispatcher::associateNodeAndEventListener(Node* node, EventListener* listener)
@ -355,12 +391,12 @@ void EventDispatcher::forceAddEventListener(EventListener* listener)
{ {
EventListenerVector* listeners = nullptr; EventListenerVector* listeners = nullptr;
EventListener::ListenerID listenerID = listener->getListenerID(); EventListener::ListenerID listenerID = listener->getListenerID();
auto itr = _listeners.find(listenerID); auto itr = _listenerMap.find(listenerID);
if (itr == _listeners.end()) if (itr == _listenerMap.end())
{ {
listeners = new EventListenerVector(); listeners = new EventListenerVector();
_listeners.insert(std::make_pair(listenerID, listeners)); _listenerMap.insert(std::make_pair(listenerID, listeners));
} }
else else
{ {
@ -380,7 +416,7 @@ void EventDispatcher::forceAddEventListener(EventListener* listener)
if (node->isRunning()) if (node->isRunning())
{ {
resumeTarget(node); resumeEventListenersForTarget(node);
} }
} }
else else
@ -421,7 +457,7 @@ void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener,
addEventListener(listener); addEventListener(listener);
} }
EventListenerCustom* EventDispatcher::addCustomEventListener(const std::string &eventName, std::function<void(EventCustom*)> callback) EventListenerCustom* EventDispatcher::addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback)
{ {
EventListenerCustom *listener = EventListenerCustom::create(eventName, callback); EventListenerCustom *listener = EventListenerCustom::create(eventName, callback);
addEventListenerWithFixedPriority(listener, 1); addEventListenerWithFixedPriority(listener, 1);
@ -434,7 +470,7 @@ void EventDispatcher::removeEventListener(EventListener* listener)
return; return;
bool isFound = false; bool isFound = false;
auto removeListenerInVector = [&](std::vector<EventListener*>* listeners){ auto removeListenerInVector = [&](std::vector<EventListener*>* listeners){
if (listeners == nullptr) if (listeners == nullptr)
return; return;
@ -463,23 +499,32 @@ void EventDispatcher::removeEventListener(EventListener* listener)
} }
}; };
for (auto iter = _listeners.begin(); iter != _listeners.end();) for (auto iter = _listenerMap.begin(); iter != _listenerMap.end();)
{ {
auto listeners = iter->second; auto listeners = iter->second;
auto fixedPriorityListeners = listeners->getFixedPriorityListeners(); auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners(); auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
removeListenerInVector(sceneGraphPriorityListeners); removeListenerInVector(sceneGraphPriorityListeners);
if (!isFound) if (isFound)
{
// fixed #4160: Dirty flag need to be updated after listeners were removed.
setDirty(listener->getListenerID(), DirtyFlag::SCENE_GRAPH_PRIORITY);
}
else
{ {
removeListenerInVector(fixedPriorityListeners); removeListenerInVector(fixedPriorityListeners);
if (isFound)
{
setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRIORITY);
}
} }
if (iter->second->empty()) if (iter->second->empty())
{ {
_priorityDirtyFlagMap.erase(listener->getListenerID()); _priorityDirtyFlagMap.erase(listener->getListenerID());
auto list = iter->second; auto list = iter->second;
iter = _listeners.erase(iter); iter = _listenerMap.erase(iter);
CC_SAFE_DELETE(list); CC_SAFE_DELETE(list);
} }
else else
@ -514,7 +559,7 @@ void EventDispatcher::setPriority(EventListener* listener, int fixedPriority)
if (listener == nullptr) if (listener == nullptr)
return; return;
for (auto iter = _listeners.begin(); iter != _listeners.end(); ++iter) for (auto iter = _listenerMap.begin(); iter != _listenerMap.end(); ++iter)
{ {
auto fixedPriorityListeners = iter->second->getFixedPriorityListeners(); auto fixedPriorityListeners = iter->second->getFixedPriorityListeners();
if (fixedPriorityListeners) if (fixedPriorityListeners)
@ -535,7 +580,7 @@ void EventDispatcher::setPriority(EventListener* listener, int fixedPriority)
} }
} }
void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, std::function<bool(EventListener*)> onEvent) void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent)
{ {
bool shouldStopPropagation = false; bool shouldStopPropagation = false;
auto fixedPriorityListeners = listeners->getFixedPriorityListeners(); auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
@ -545,14 +590,18 @@ void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, s
// priority < 0 // priority < 0
if (fixedPriorityListeners) if (fixedPriorityListeners)
{ {
bool isEmpty = fixedPriorityListeners->empty(); CCASSERT(listeners->getGt0Index() <= fixedPriorityListeners->size(), "Out of range exception!");
for (; !isEmpty && i < listeners->getGt0Index(); ++i)
if (!fixedPriorityListeners->empty())
{ {
auto l = fixedPriorityListeners->at(i); for (; i < listeners->getGt0Index(); ++i)
if (!l->isPaused() && l->isRegistered() && onEvent(l))
{ {
shouldStopPropagation = true; auto l = fixedPriorityListeners->at(i);
break; if (!l->isPaused() && l->isRegistered() && onEvent(l))
{
shouldStopPropagation = true;
break;
}
} }
} }
} }
@ -613,8 +662,8 @@ void EventDispatcher::dispatchEvent(Event* event)
sortEventListeners(listenerID); sortEventListeners(listenerID);
auto iter = _listeners.find(listenerID); auto iter = _listenerMap.find(listenerID);
if (iter != _listeners.end()) if (iter != _listenerMap.end())
{ {
auto listeners = iter->second; auto listeners = iter->second;
@ -652,7 +701,7 @@ void EventDispatcher::dispatchTouchEvent(EventTouch* event)
bool isNeedsMutableSet = (oneByOneListeners && allAtOnceListeners); bool isNeedsMutableSet = (oneByOneListeners && allAtOnceListeners);
std::vector<Touch*> originalTouches = event->getTouches(); const std::vector<Touch*>& originalTouches = event->getTouches();
std::vector<Touch*> mutableTouches(originalTouches.size()); std::vector<Touch*> mutableTouches(originalTouches.size());
std::copy(originalTouches.begin(), originalTouches.end(), mutableTouches.begin()); std::copy(originalTouches.begin(), originalTouches.end(), mutableTouches.begin());
@ -835,8 +884,8 @@ void EventDispatcher::updateListeners(Event* event)
{ {
auto onUpdateListeners = [this](const EventListener::ListenerID& listenerID) auto onUpdateListeners = [this](const EventListener::ListenerID& listenerID)
{ {
auto listenersIter = _listeners.find(listenerID); auto listenersIter = _listenerMap.find(listenerID);
if (listenersIter == _listeners.end()) if (listenersIter == _listenerMap.end())
return; return;
auto listeners = listenersIter->second; auto listeners = listenersIter->second;
@ -891,7 +940,7 @@ void EventDispatcher::updateListeners(Event* event)
{ {
_priorityDirtyFlagMap.erase(listenersIter->first); _priorityDirtyFlagMap.erase(listenersIter->first);
delete listenersIter->second; delete listenersIter->second;
_listeners.erase(listenersIter); _listenerMap.erase(listenersIter);
} }
}; };
@ -1027,8 +1076,8 @@ void EventDispatcher::sortEventListenersOfFixedPriority(const EventListener::Lis
EventDispatcher::EventListenerVector* EventDispatcher::getListeners(const EventListener::ListenerID& listenerID) EventDispatcher::EventListenerVector* EventDispatcher::getListeners(const EventListener::ListenerID& listenerID)
{ {
auto iter = _listeners.find(listenerID); auto iter = _listenerMap.find(listenerID);
if (iter != _listeners.end()) if (iter != _listenerMap.end())
{ {
return iter->second; return iter->second;
} }
@ -1038,8 +1087,8 @@ EventDispatcher::EventListenerVector* EventDispatcher::getListeners(const EventL
void EventDispatcher::removeEventListenersForListenerID(const EventListener::ListenerID& listenerID) void EventDispatcher::removeEventListenersForListenerID(const EventListener::ListenerID& listenerID)
{ {
auto listenerItemIter = _listeners.find(listenerID); auto listenerItemIter = _listenerMap.find(listenerID);
if (listenerItemIter != _listeners.end()) if (listenerItemIter != _listenerMap.end())
{ {
auto listeners = listenerItemIter->second; auto listeners = listenerItemIter->second;
auto fixedPriorityListeners = listeners->getFixedPriorityListeners(); auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
@ -1073,12 +1122,15 @@ void EventDispatcher::removeEventListenersForListenerID(const EventListener::Lis
removeAllListenersInVector(sceneGraphPriorityListeners); removeAllListenersInVector(sceneGraphPriorityListeners);
removeAllListenersInVector(fixedPriorityListeners); removeAllListenersInVector(fixedPriorityListeners);
// Remove the dirty flag according the 'listenerID'.
// No need to check whether the dispatcher is dispatching event.
_priorityDirtyFlagMap.erase(listenerID);
if (!_inDispatch) if (!_inDispatch)
{ {
listeners->clear(); listeners->clear();
delete listeners; delete listeners;
_listeners.erase(listenerItemIter); _listenerMap.erase(listenerItemIter);
_priorityDirtyFlagMap.erase(listenerID);
} }
} }
@ -1096,7 +1148,7 @@ void EventDispatcher::removeEventListenersForListenerID(const EventListener::Lis
} }
} }
void EventDispatcher::removeEventListeners(EventListener::Type listenerType) void EventDispatcher::removeEventListenersForType(EventListener::Type listenerType)
{ {
if (listenerType == EventListener::Type::TOUCH_ONE_BY_ONE) if (listenerType == EventListener::Type::TOUCH_ONE_BY_ONE)
{ {
@ -1131,11 +1183,19 @@ void EventDispatcher::removeCustomEventListeners(const std::string& customEventN
void EventDispatcher::removeAllEventListeners() void EventDispatcher::removeAllEventListeners()
{ {
std::vector<EventListener::ListenerID> types(_listeners.size()); bool cleanMap = true;
std::vector<EventListener::ListenerID> types(_listenerMap.size());
for (const auto& e : _listeners)
for (const auto& e : _listenerMap)
{ {
types.push_back(e.first); if (_internalCustomListenerIDs.find(e.first) != _internalCustomListenerIDs.end())
{
cleanMap = false;
}
else
{
types.push_back(e.first);
}
} }
for (const auto& type : types) for (const auto& type : types)
@ -1143,9 +1203,9 @@ void EventDispatcher::removeAllEventListeners()
removeEventListenersForListenerID(type); removeEventListenersForListenerID(type);
} }
if (!_inDispatch) if (!_inDispatch && cleanMap)
{ {
_listeners.clear(); _listenerMap.clear();
} }
} }

View File

@ -56,6 +56,8 @@ dispatched.
class EventDispatcher : public Ref class EventDispatcher : public Ref
{ {
public: public:
// Adds event listener
/** Adds a event listener for a specified event with the priority of scene graph. /** Adds a event listener for a specified event with the priority of scene graph.
* @param listener The listener of a specified event. * @param listener The listener of a specified event.
* @param node The priority of the listener is based on the draw order of this node. * @param node The priority of the listener is based on the draw order of this node.
@ -76,22 +78,41 @@ public:
It will use a fixed priority of 1. It will use a fixed priority of 1.
@return the generated event. Needed in order to remove the event from the dispather @return the generated event. Needed in order to remove the event from the dispather
*/ */
EventListenerCustom* addCustomEventListener(const std::string &eventName, std::function<void(EventCustom*)> callback); EventListenerCustom* addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback);
/////////////////////////////////////////////
// Removes event listener
/** Remove a listener /** Remove a listener
* @param listener The specified event listener which needs to be removed. * @param listener The specified event listener which needs to be removed.
*/ */
void removeEventListener(EventListener* listener); void removeEventListener(EventListener* listener);
/** Removes all listeners with the same event listener type */ /** Removes all listeners with the same event listener type */
void removeEventListeners(EventListener::Type listenerType); void removeEventListenersForType(EventListener::Type listenerType);
/** Removes all listeners which are associated with the specified target. */
void removeEventListenersForTarget(Node* target, bool recursive = false);
/** Removes all custom listeners with the same event name */ /** Removes all custom listeners with the same event name */
void removeCustomEventListeners(const std::string& customEventName); void removeCustomEventListeners(const std::string& customEventName);
/** Removes all listeners */ /** Removes all listeners */
void removeAllEventListeners(); void removeAllEventListeners();
/////////////////////////////////////////////
// Pauses / Resumes event listener
/** Pauses all listeners which are associated the specified target. */
void pauseEventListenersForTarget(Node* target, bool recursive = false);
/** Resumes all listeners which are associated the specified target. */
void resumeEventListenersForTarget(Node* target, bool recursive = false);
/////////////////////////////////////////////
/** Sets listener's priority with fixed value. */ /** Sets listener's priority with fixed value. */
void setPriority(EventListener* listener, int fixedPriority); void setPriority(EventListener* listener, int fixedPriority);
@ -101,6 +122,8 @@ public:
/** Checks whether dispatching events is enabled */ /** Checks whether dispatching events is enabled */
bool isEnabled() const; bool isEnabled() const;
/////////////////////////////////////////////
/** Dispatches the event /** Dispatches the event
* Also removes all EventListeners marked for deletion from the * Also removes all EventListeners marked for deletion from the
* event dispatcher list. * event dispatcher list.
@ -108,8 +131,10 @@ public:
void dispatchEvent(Event* event); void dispatchEvent(Event* event);
/** Dispatches a Custom Event with a event name an optional user data */ /** Dispatches a Custom Event with a event name an optional user data */
void dispatchCustomEvent(const std::string &eventName, void *optionalUserData); void dispatchCustomEvent(const std::string &eventName, void *optionalUserData = nullptr);
/////////////////////////////////////////////
/** Constructor of EventDispatcher */ /** Constructor of EventDispatcher */
EventDispatcher(); EventDispatcher();
/** Destructor of EventDispatcher */ /** Destructor of EventDispatcher */
@ -121,15 +146,6 @@ protected:
/** Sets the dirty flag for a node. */ /** Sets the dirty flag for a node. */
void setDirtyForNode(Node* node); void setDirtyForNode(Node* node);
/** Notifys event dispatcher that the node has been paused. */
void pauseTarget(Node* node);
/** Notifys event dispatcher that the node has been resumed. */
void resumeTarget(Node* node);
/** Notifys event dispatcher that the node has been deleted. */
void cleanTarget(Node* node);
/** /**
* The vector to store event listeners with scene graph based priority and fixed priority. * The vector to store event listeners with scene graph based priority and fixed priority.
*/ */
@ -202,7 +218,7 @@ protected:
void dissociateNodeAndEventListener(Node* node, EventListener* listener); void dissociateNodeAndEventListener(Node* node, EventListener* listener);
/** Dispatches event to listeners with a specified listener type */ /** Dispatches event to listeners with a specified listener type */
void dispatchEventToListeners(EventListenerVector* listeners, std::function<bool(EventListener*)> onEvent); void dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent);
/// Priority dirty flag /// Priority dirty flag
enum class DirtyFlag enum class DirtyFlag
@ -220,7 +236,7 @@ protected:
void visitTarget(Node* node, bool isRootNode); void visitTarget(Node* node, bool isRootNode);
/** Listeners map */ /** Listeners map */
std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listeners; std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;
/** The map of dirty flag */ /** The map of dirty flag */
std::unordered_map<EventListener::ListenerID, DirtyFlag> _priorityDirtyFlagMap; std::unordered_map<EventListener::ListenerID, DirtyFlag> _priorityDirtyFlagMap;
@ -247,6 +263,8 @@ protected:
bool _isEnabled; bool _isEnabled;
int _nodePriorityIndex; int _nodePriorityIndex;
std::set<std::string> _internalCustomListenerIDs;
}; };

View File

@ -48,8 +48,8 @@ public:
EventTouch(); EventTouch();
EventCode getEventCode() { return _eventCode; }; inline EventCode getEventCode() const { return _eventCode; };
std::vector<Touch*> getTouches() { return _touches; }; inline const std::vector<Touch*>& getTouches() const { return _touches; };
#if TOUCH_PERF_DEBUG #if TOUCH_PERF_DEBUG
void setEventCode(EventCode eventCode) { _eventCode = eventCode; }; void setEventCode(EventCode eventCode) { _eventCode = eventCode; };

View File

@ -679,24 +679,32 @@ void Label::onDraw()
CC_PROFILER_STOP("Label - draw"); CC_PROFILER_STOP("Label - draw");
} }
void Label::draw() void Label::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
_customCommand.init(_globalZOrder); _customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(Label::onDraw, this); _customCommand.func = CC_CALLBACK_0(Label::onDraw, this);
Director::getInstance()->getRenderer()->addCommand(&_customCommand); renderer->addCommand(&_customCommand);
} }
void Label::visit() void Label::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
if (! _visible) if (! _visible)
{ {
return; return;
} }
kmGLPushMatrix(); bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
_modelViewTransform = transform(parentTransform);
_transformUpdated = false;
transform(); // IMPORTANT:
draw(); // To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix();
kmGLLoadMatrix(&_modelViewTransform);
draw(renderer, _modelViewTransform, dirty);
kmGLPopMatrix(); kmGLPopMatrix();

View File

@ -128,8 +128,8 @@ public:
void addChild(Node * child, int zOrder=0, int tag=0) override; void addChild(Node * child, int zOrder=0, int tag=0) override;
virtual std::string getDescription() const override; virtual std::string getDescription() const override;
virtual void visit() override; virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
virtual void draw(void) override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual void onDraw(); virtual void onDraw();
virtual FontAtlas* getFontAtlas() const {return _fontAtlas;} virtual FontAtlas* getFontAtlas() const {return _fontAtlas;}

View File

@ -581,11 +581,11 @@ void LayerColor::updateColor()
} }
} }
void LayerColor::draw() void LayerColor::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
_customCommand.init(_globalZOrder); _customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(LayerColor::onDraw, this); _customCommand.func = CC_CALLBACK_0(LayerColor::onDraw, this);
Director::getInstance()->getRenderer()->addCommand(&_customCommand); renderer->addCommand(&_customCommand);
for(int i = 0; i < 4; ++i) for(int i = 0; i < 4; ++i)
{ {

View File

@ -37,7 +37,6 @@ THE SOFTWARE.
#include "CCEventKeyboard.h" #include "CCEventKeyboard.h"
#include "renderer/CCCustomCommand.h" #include "renderer/CCCustomCommand.h"
#include "renderer/CCQuadCommand.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -266,7 +265,7 @@ public:
// //
// Overrides // Overrides
// //
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual void onDraw(); virtual void onDraw();
virtual void setContentSize(const Size & var) override; virtual void setContentSize(const Size & var) override;

View File

@ -328,7 +328,7 @@ void MotionStreak::reset()
void MotionStreak::onDraw() void MotionStreak::onDraw()
{ {
getShaderProgram()->use(); getShaderProgram()->use();
getShaderProgram()->setUniformsForBuiltins(_cachedMV); getShaderProgram()->setUniformsForBuiltins(_modelViewTransform);
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX ); GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX );
GL::blendFunc( _blendFunc.src, _blendFunc.dst ); GL::blendFunc( _blendFunc.src, _blendFunc.dst );
@ -352,16 +352,16 @@ void MotionStreak::onDraw()
#endif // EMSCRIPTEN #endif // EMSCRIPTEN
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)_nuPoints*2); glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)_nuPoints*2);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _nuPoints*2);
} }
void MotionStreak::draw() void MotionStreak::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
if(_nuPoints <= 1) if(_nuPoints <= 1)
return; return;
kmGLGetMatrix(KM_GL_MODELVIEW,&_cachedMV);
_customCommand.init(_globalZOrder); _customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(MotionStreak::onDraw, this); _customCommand.func = CC_CALLBACK_0(MotionStreak::onDraw, this);
Director::getInstance()->getRenderer()->addCommand(&_customCommand); renderer->addCommand(&_customCommand);
} }

View File

@ -78,7 +78,7 @@ public:
* @js NA * @js NA
* @lua NA * @lua NA
*/ */
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
/** /**
* @js NA * @js NA
* @lua NA * @lua NA
@ -102,19 +102,9 @@ public:
virtual bool isOpacityModifyRGB() const override; virtual bool isOpacityModifyRGB() const override;
protected: protected:
kmMat4 _cachedMV;
//renderer callback //renderer callback
void onDraw(); void onDraw();
protected:
/**
* @js ctor
*/
MotionStreak(); MotionStreak();
/**
* @js NA
* @lua NA
*/
virtual ~MotionStreak(); virtual ~MotionStreak();
/** initializes a motion streak with fade in seconds, minimum segments, stroke's width, color and texture filename */ /** initializes a motion streak with fade in seconds, minimum segments, stroke's width, color and texture filename */

View File

@ -92,6 +92,7 @@ Node::Node(void)
, _useAdditionalTransform(false) , _useAdditionalTransform(false)
, _transformDirty(true) , _transformDirty(true)
, _inverseDirty(true) , _inverseDirty(true)
, _transformUpdated(true)
// children (lazy allocs) // children (lazy allocs)
// lazy alloc // lazy alloc
, _localZOrder(0) , _localZOrder(0)
@ -156,7 +157,7 @@ Node::~Node()
CC_SAFE_RELEASE(_actionManager); CC_SAFE_RELEASE(_actionManager);
CC_SAFE_RELEASE(_scheduler); CC_SAFE_RELEASE(_scheduler);
_eventDispatcher->cleanTarget(this); _eventDispatcher->removeEventListenersForTarget(this);
CC_SAFE_RELEASE(_eventDispatcher); CC_SAFE_RELEASE(_eventDispatcher);
// attributes // attributes
@ -193,7 +194,7 @@ void Node::setSkewX(float skewX)
return; return;
_skewX = skewX; _skewX = skewX;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
float Node::getSkewY() const float Node::getSkewY() const
@ -207,7 +208,7 @@ void Node::setSkewY(float skewY)
return; return;
_skewY = skewY; _skewY = skewY;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
@ -255,8 +256,8 @@ void Node::setRotation(float rotation)
return; return;
_rotationZ_X = _rotationZ_Y = rotation; _rotationZ_X = _rotationZ_Y = rotation;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
#if CC_USE_PHYSICS #if CC_USE_PHYSICS
if (_physicsBody) if (_physicsBody)
{ {
@ -277,7 +278,7 @@ void Node::setRotation3D(const Vertex3F& rotation)
_rotationZ_X == rotation.z) _rotationZ_X == rotation.z)
return; return;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
_rotationX = rotation.x; _rotationX = rotation.x;
_rotationY = rotation.y; _rotationY = rotation.y;
@ -307,7 +308,7 @@ void Node::setRotationSkewX(float rotationX)
return; return;
_rotationZ_X = rotationX; _rotationZ_X = rotationX;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
float Node::getRotationSkewY() const float Node::getRotationSkewY() const
@ -321,7 +322,7 @@ void Node::setRotationSkewY(float rotationY)
return; return;
_rotationZ_Y = rotationY; _rotationZ_Y = rotationY;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
/// scale getter /// scale getter
@ -336,9 +337,9 @@ void Node::setScale(float scale)
{ {
if (_scaleX == scale) if (_scaleX == scale)
return; return;
_scaleX = _scaleY = scale; _scaleX = _scaleY = _scaleZ = scale;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
/// scaleX getter /// scaleX getter
@ -355,7 +356,7 @@ void Node::setScale(float scaleX,float scaleY)
_scaleX = scaleX; _scaleX = scaleX;
_scaleY = scaleY; _scaleY = scaleY;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
/// scaleX setter /// scaleX setter
@ -365,7 +366,7 @@ void Node::setScaleX(float scaleX)
return; return;
_scaleX = scaleX; _scaleX = scaleX;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
/// scaleY getter /// scaleY getter
@ -381,7 +382,7 @@ void Node::setScaleZ(float scaleZ)
return; return;
_scaleZ = scaleZ; _scaleZ = scaleZ;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
/// scaleY getter /// scaleY getter
@ -397,7 +398,7 @@ void Node::setScaleY(float scaleY)
return; return;
_scaleY = scaleY; _scaleY = scaleY;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
@ -414,12 +415,14 @@ void Node::setPosition(const Point& position)
return; return;
_position = position; _position = position;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
#if CC_USE_PHYSICS #if CC_USE_PHYSICS
if (_physicsBody) if (_physicsBody)
{ {
_physicsBody->setPosition(position); Node* parent = getParent();
Point pos = parent != nullptr ? parent->convertToWorldSpace(getPosition()) : getPosition();
_physicsBody->setPosition(pos);
} }
#endif #endif
} }
@ -480,7 +483,7 @@ void Node::setPositionZ(float positionZ)
if (_positionZ == positionZ) if (_positionZ == positionZ)
return; return;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
_positionZ = positionZ; _positionZ = positionZ;
@ -489,21 +492,6 @@ void Node::setPositionZ(float positionZ)
setGlobalZOrder(positionZ); setGlobalZOrder(positionZ);
} }
void Node::setNormalizedPosition(const cocos2d::Point &position)
{
_normalizedPosition = position;
Size s = Director::getInstance()->getVisibleSize();
Point p;
p.x = s.width * position.x;
p.y = s.height * position.y;
setPosition(p);
}
const Point& Node::getNormalizedPosition() const
{
return _normalizedPosition;
}
ssize_t Node::getChildrenCount() const ssize_t Node::getChildrenCount() const
{ {
return _children.size(); return _children.size();
@ -534,11 +522,19 @@ const Point& Node::getAnchorPoint() const
void Node::setAnchorPoint(const Point& point) void Node::setAnchorPoint(const Point& point)
{ {
#if CC_USE_PHYSICS
if (_physicsBody != nullptr && !point.equals(Point::ANCHOR_MIDDLE))
{
CCLOG("Node warning: This node has a physics body, the anchor must be in the middle, you cann't change this to other value.");
return;
}
#endif
if( ! point.equals(_anchorPoint)) if( ! point.equals(_anchorPoint))
{ {
_anchorPoint = point; _anchorPoint = point;
_anchorPointInPoints = Point(_contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y ); _anchorPointInPoints = Point(_contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y );
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
} }
@ -555,7 +551,7 @@ void Node::setContentSize(const Size & size)
_contentSize = size; _contentSize = size;
_anchorPointInPoints = Point(_contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y ); _anchorPointInPoints = Point(_contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y );
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
} }
@ -582,7 +578,7 @@ void Node::ignoreAnchorPointForPosition(bool newValue)
if (newValue != _ignoreAnchorPointForPosition) if (newValue != _ignoreAnchorPointForPosition)
{ {
_ignoreAnchorPointForPosition = newValue; _ignoreAnchorPointForPosition = newValue;
_transformDirty = _inverseDirty = true; _transformUpdated = _transformDirty = _inverseDirty = true;
} }
} }
@ -719,6 +715,11 @@ void Node::addChild(Node *child, int zOrder, int tag)
this->insertChild(child, zOrder); this->insertChild(child, zOrder);
#if CC_USE_PHYSICS #if CC_USE_PHYSICS
if (child->getPhysicsBody() != nullptr)
{
child->getPhysicsBody()->setPosition(this->convertToWorldSpace(child->getPosition()));
}
for (Node* node = this->getParent(); node != nullptr; node = node->getParent()) for (Node* node = this->getParent(); node != nullptr; node = node->getParent())
{ {
if (dynamic_cast<Scene*>(node) != nullptr) if (dynamic_cast<Scene*>(node) != nullptr)
@ -899,26 +900,44 @@ void Node::sortAllChildren()
} }
} }
void Node::draw()
{
auto renderer = Director::getInstance()->getRenderer();
draw(renderer, _modelViewTransform, true);
}
void Node::draw() void Node::draw(Renderer* renderer, const kmMat4 &transform, bool transformUpdated)
{ {
//CCASSERT(0); }
// override me
// Only use- this function to draw your stuff.
// DON'T draw your stuff outside this method
}
void Node::visit() void Node::visit()
{
auto renderer = Director::getInstance()->getRenderer();
kmMat4 parentTransform;
kmGLGetMatrix(KM_GL_MODELVIEW, &parentTransform);
visit(renderer, parentTransform, true);
}
void Node::visit(Renderer* renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
// quick return if not visible. children won't be drawn. // quick return if not visible. children won't be drawn.
if (!_visible) if (!_visible)
{ {
return; return;
} }
kmGLPushMatrix();
this->transform(); bool dirty = _transformUpdated || parentTransformUpdated;
if(dirty)
_modelViewTransform = this->transform(parentTransform);
_transformUpdated = false;
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix();
kmGLLoadMatrix(&_modelViewTransform);
int i = 0; int i = 0;
if(!_children.empty()) if(!_children.empty())
@ -930,19 +949,19 @@ void Node::visit()
auto node = _children.at(i); auto node = _children.at(i);
if ( node && node->_localZOrder < 0 ) if ( node && node->_localZOrder < 0 )
node->visit(); node->visit(renderer, _modelViewTransform, dirty);
else else
break; break;
} }
// self draw // self draw
this->draw(); this->draw(renderer, _modelViewTransform, dirty);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(); (*it)->visit(renderer, _modelViewTransform, dirty);
} }
else else
{ {
this->draw(); this->draw(renderer, _modelViewTransform, dirty);
} }
// reset for next frame // reset for next frame
@ -951,23 +970,12 @@ void Node::visit()
kmGLPopMatrix(); kmGLPopMatrix();
} }
void Node::transformAncestors() kmMat4 Node::transform(const kmMat4& parentTransform)
{ {
if( _parent != nullptr ) kmMat4 ret = this->getNodeToParentTransform();
{ kmMat4Multiply(&ret, &parentTransform, &ret);
_parent->transformAncestors();
_parent->transform();
}
}
void Node::transform() return ret;
{
kmMat4 transfrom4x4 = this->getNodeToParentTransform();
kmGLMultMatrix( &transfrom4x4 );
// saves the MV matrix
kmGLGetMatrix(KM_GL_MODELVIEW, &_modelViewTransform);
} }
void Node::onEnter() void Node::onEnter()
@ -1050,7 +1058,7 @@ void Node::setEventDispatcher(EventDispatcher* dispatcher)
{ {
if (dispatcher != _eventDispatcher) if (dispatcher != _eventDispatcher)
{ {
_eventDispatcher->cleanTarget(this); _eventDispatcher->removeEventListenersForTarget(this);
CC_SAFE_RETAIN(dispatcher); CC_SAFE_RETAIN(dispatcher);
CC_SAFE_RELEASE(_eventDispatcher); CC_SAFE_RELEASE(_eventDispatcher);
_eventDispatcher = dispatcher; _eventDispatcher = dispatcher;
@ -1115,7 +1123,7 @@ void Node::setScheduler(Scheduler* scheduler)
bool Node::isScheduled(SEL_SCHEDULE selector) bool Node::isScheduled(SEL_SCHEDULE selector)
{ {
return _scheduler->isScheduled(this, schedule_selector_to_key(selector)); return _scheduler->isScheduled(selector, this);
} }
void Node::scheduleUpdate() void Node::scheduleUpdate()
@ -1125,9 +1133,7 @@ void Node::scheduleUpdate()
void Node::scheduleUpdateWithPriority(int priority) void Node::scheduleUpdateWithPriority(int priority)
{ {
_scheduler->scheduleUpdate([this](float dt){ _scheduler->scheduleUpdate(this, priority, !_running);
this->update(dt);
}, this, priority, !_running);
} }
void Node::scheduleUpdateWithPriorityLua(int nHandler, int priority) void Node::scheduleUpdateWithPriorityLua(int nHandler, int priority)
@ -1137,9 +1143,8 @@ void Node::scheduleUpdateWithPriorityLua(int nHandler, int priority)
#if CC_ENABLE_SCRIPT_BINDING #if CC_ENABLE_SCRIPT_BINDING
_updateScriptHandler = nHandler; _updateScriptHandler = nHandler;
#endif #endif
_scheduler->scheduleUpdate([this](float dt){
this->update(dt); _scheduler->scheduleUpdate(this, priority, !_running);
}, this, priority, !_running);
} }
void Node::unscheduleUpdate() void Node::unscheduleUpdate()
@ -1170,9 +1175,7 @@ void Node::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat,
CCASSERT( selector, "Argument must be non-nil"); CCASSERT( selector, "Argument must be non-nil");
CCASSERT( interval >=0, "Argument must be positive"); CCASSERT( interval >=0, "Argument must be positive");
_scheduler->schedule([=](float dt){ _scheduler->schedule(selector, this, interval , repeat, delay, !_running);
(this->*selector)(dt);
}, this, schedule_selector_to_key(selector), interval , repeat, delay, !_running);
} }
void Node::scheduleOnce(SEL_SCHEDULE selector, float delay) void Node::scheduleOnce(SEL_SCHEDULE selector, float delay)
@ -1186,7 +1189,7 @@ void Node::unschedule(SEL_SCHEDULE selector)
if (selector == nullptr) if (selector == nullptr)
return; return;
_scheduler->unschedule(this, schedule_selector_to_key(selector)); _scheduler->unschedule(selector, this);
} }
void Node::unscheduleAllSelectors() void Node::unscheduleAllSelectors()
@ -1198,14 +1201,14 @@ void Node::resume()
{ {
_scheduler->resumeTarget(this); _scheduler->resumeTarget(this);
_actionManager->resumeTarget(this); _actionManager->resumeTarget(this);
_eventDispatcher->resumeTarget(this); _eventDispatcher->resumeEventListenersForTarget(this);
} }
void Node::pause() void Node::pause()
{ {
_scheduler->pauseTarget(this); _scheduler->pauseTarget(this);
_actionManager->pauseTarget(this); _actionManager->pauseTarget(this);
_eventDispatcher->pauseTarget(this); _eventDispatcher->pauseEventListenersForTarget(this);
} }
void Node::resumeSchedulerAndActions() void Node::resumeSchedulerAndActions()
@ -1348,20 +1351,25 @@ void Node::setNodeToParentTransform(const kmMat4& transform)
{ {
_transform = transform; _transform = transform;
_transformDirty = false; _transformDirty = false;
_transformUpdated = true;
} }
void Node::setAdditionalTransform(const AffineTransform& additionalTransform) void Node::setAdditionalTransform(const AffineTransform& additionalTransform)
{ {
CGAffineToGL(additionalTransform, _additionalTransform.mat); kmMat4 tmp;
_transformDirty = true; CGAffineToGL(additionalTransform, tmp.mat);
_useAdditionalTransform = true; setAdditionalTransform(&tmp);
} }
void Node::setAdditionalTransform(const kmMat4& additionalTransform) void Node::setAdditionalTransform(kmMat4* additionalTransform)
{ {
_additionalTransform = additionalTransform; if(additionalTransform == nullptr) {
_transformDirty = true; _useAdditionalTransform = false;
_useAdditionalTransform = true; } else {
_additionalTransform = *additionalTransform;
_useAdditionalTransform = true;
}
_transformUpdated = _transformDirty = _inverseDirty = true;
} }
@ -1511,6 +1519,14 @@ void Node::setPhysicsBody(PhysicsBody* body)
{ {
body->_node = this; body->_node = this;
body->retain(); body->retain();
// physics rotation based on body position, but node rotation based on node anthor point
// it cann't support both of them, so I clear the anthor point to default.
if (!getAnchorPoint().equals(Point::ANCHOR_MIDDLE))
{
CCLOG("Node warning: setPhysicsBody sets anchor point to Point::ANCHOR_MIDDLE.");
setAnchorPoint(Point::ANCHOR_MIDDLE);
}
} }
if (_physicsBody != nullptr) if (_physicsBody != nullptr)
@ -1529,7 +1545,9 @@ void Node::setPhysicsBody(PhysicsBody* body)
_physicsBody = body; _physicsBody = body;
if (body != nullptr) if (body != nullptr)
{ {
_physicsBody->setPosition(getPosition()); Node* parent = getParent();
Point pos = parent != nullptr ? parent->convertToWorldSpace(getPosition()) : getPosition();
_physicsBody->setPosition(pos);
_physicsBody->setRotation(getRotation()); _physicsBody->setRotation(getRotation());
} }
} }

View File

@ -54,6 +54,7 @@ class Component;
class ComponentContainer; class ComponentContainer;
class EventDispatcher; class EventDispatcher;
class Scene; class Scene;
class Renderer;
#if CC_USE_PHYSICS #if CC_USE_PHYSICS
class PhysicsBody; class PhysicsBody;
#endif #endif
@ -386,15 +387,6 @@ public:
virtual float getPositionZ() const; virtual float getPositionZ() const;
CC_DEPRECATED_ATTRIBUTE virtual float getVertexZ() const { return getPositionZ(); } CC_DEPRECATED_ATTRIBUTE virtual float getVertexZ() const { return getPositionZ(); }
/** Sets the position using normalized coordinates.
- (0,0) means bottom,left corner
- (1,1) means top,right corner
- (0.5,0.5) means center
*/
virtual void setNormalizedPosition(const Point& position);
/** returns the normalized position */
const Point& getNormalizedPosition() const;
/** /**
* Changes the X skew angle of the node in degrees. * Changes the X skew angle of the node in degrees.
* *
@ -449,6 +441,7 @@ public:
* The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner. * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
* But you can use values higher than (1,1) and lower than (0,0) too. * But you can use values higher than (1,1) and lower than (0,0) too.
* The default anchorPoint is (0.5,0.5), so it starts in the center of the node. * The default anchorPoint is (0.5,0.5), so it starts in the center of the node.
* @note If node has a physics body, the anchor must be in the middle, you cann't change this to other value.
* *
* @param anchorPoint The anchor point of node. * @param anchorPoint The anchor point of node.
*/ */
@ -990,12 +983,15 @@ public:
* AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE * AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE
* But if you enable any other GL state, you should disable it after drawing your node. * But if you enable any other GL state, you should disable it after drawing your node.
*/ */
virtual void draw(); virtual void draw(Renderer *renderer, const kmMat4& transform, bool transformUpdated);
virtual void draw() final;
/** /**
* Visits this node's children and draw them recursively. * Visits this node's children and draw them recursively.
*/ */
virtual void visit(); virtual void visit(Renderer *renderer, const kmMat4& parentTransform, bool parentTransformUpdated);
virtual void visit() final;
/** Returns the Scene that contains the Node. /** Returns the Scene that contains the Node.
It returns `nullptr` if the node doesn't belong to any Scene. It returns `nullptr` if the node doesn't belong to any Scene.
@ -1249,16 +1245,6 @@ public:
/// @{ /// @{
/// @name Transformations /// @name Transformations
/**
* Performs OpenGL view-matrix transformation based on position, scale, rotation and other attributes.
*/
void transform();
/**
* Performs OpenGL view-matrix transformation of it's ancestors.
* Generally the ancestors are already transformed, but in certain cases (eg: attaching a FBO)
* It's necessary to transform the ancestors again.
*/
void transformAncestors();
/** /**
* Calls children's updateTransform() method recursively. * Calls children's updateTransform() method recursively.
* *
@ -1309,7 +1295,7 @@ public:
virtual AffineTransform getWorldToNodeAffineTransform() const; virtual AffineTransform getWorldToNodeAffineTransform() const;
/** @deprecated Use worldToNodeTransform() instead */ /** @deprecated Use getWorldToNodeTransform() instead */
CC_DEPRECATED_ATTRIBUTE inline virtual AffineTransform worldToNodeTransform() const { return getWorldToNodeAffineTransform(); } CC_DEPRECATED_ATTRIBUTE inline virtual AffineTransform worldToNodeTransform() const { return getWorldToNodeAffineTransform(); }
/// @} end of Transformations /// @} end of Transformations
@ -1353,55 +1339,13 @@ public:
/** /**
* Sets an additional transform matrix to the node. * Sets an additional transform matrix to the node.
* *
* In order to remove it, set the Identity Matrix to the additional transform. * In order to remove it, call it again with the argument `nullptr`
* *
* @note The additional transform will be concatenated at the end of getNodeToParentTransform. * @note The additional transform will be concatenated at the end of getNodeToParentTransform.
* It could be used to simulate `parent-child` relationship between two nodes (e.g. one is in BatchNode, another isn't). * It could be used to simulate `parent-child` relationship between two nodes (e.g. one is in BatchNode, another isn't).
@code
// create a batchNode
SpriteBatchNode* batch= SpriteBatchNode::create("Icon-114.png");
this->addChild(batch);
// create two sprites, spriteA will be added to batchNode, they are using different textures.
Sprite* spriteA = Sprite::createWithTexture(batch->getTexture());
Sprite* spriteB = Sprite::create("Icon-72.png");
batch->addChild(spriteA);
// We can't make spriteB as spriteA's child since they use different textures. So just add it to layer.
// But we want to simulate `parent-child` relationship for these two node.
this->addChild(spriteB);
//position
spriteA->setPosition(Point(200, 200));
// Gets the spriteA's transform.
auto t = spriteA->getNodeToParentTransform();
// Sets the additional transform to spriteB, spriteB's postion will based on its pseudo parent i.e. spriteA.
spriteB->setAdditionalTransform(t);
//scale
spriteA->setScale(2);
// Gets the spriteA's transform.
t = spriteA->getNodeToParentTransform();
// Sets the additional transform to spriteB, spriteB's scale will based on its pseudo parent i.e. spriteA.
spriteB->setAdditionalTransform(t);
//rotation
spriteA->setRotation(20);
// Gets the spriteA's transform.
t = spriteA->getNodeToParentTransform();
// Sets the additional transform to spriteB, spriteB's rotation will based on its pseudo parent i.e. spriteA.
spriteB->setAdditionalTransform(t);
@endcode
*/ */
void setAdditionalTransform(kmMat4* additionalTransform);
void setAdditionalTransform(const AffineTransform& additionalTransform); void setAdditionalTransform(const AffineTransform& additionalTransform);
void setAdditionalTransform(const kmMat4& additionalTransform);
/// @} end of Coordinate Converters /// @} end of Coordinate Converters
@ -1432,6 +1376,7 @@ public:
#if CC_USE_PHYSICS #if CC_USE_PHYSICS
/** /**
* set the PhysicsBody that let the sprite effect with physics * set the PhysicsBody that let the sprite effect with physics
* @note This method will set anchor point to Point::ANCHOR_MIDDLE if body not null, and you cann't change anchor point if node has a physics body.
*/ */
void setPhysicsBody(PhysicsBody* body); void setPhysicsBody(PhysicsBody* body);
@ -1477,7 +1422,9 @@ protected:
/// Convert cocos2d coordinates to UI windows coordinate. /// Convert cocos2d coordinates to UI windows coordinate.
Point convertToWindowSpace(const Point& nodePoint) const; Point convertToWindowSpace(const Point& nodePoint) const;
kmMat4 transform(const kmMat4 &parentTransform);
virtual void updateCascadeOpacity(); virtual void updateCascadeOpacity();
virtual void disableCascadeOpacity(); virtual void disableCascadeOpacity();
virtual void updateCascadeColor(); virtual void updateCascadeColor();
@ -1497,37 +1444,36 @@ protected:
Point _position; ///< position of the node Point _position; ///< position of the node
float _positionZ; ///< OpenGL real Z position float _positionZ; ///< OpenGL real Z position
Point _normalizedPosition; ///< position in normalized coordinates
float _skewX; ///< skew angle on x-axis float _skewX; ///< skew angle on x-axis
float _skewY; ///< skew angle on y-axis float _skewY; ///< skew angle on y-axis
Point _anchorPointInPoints; ///< anchor point in points Point _anchorPointInPoints; ///< anchor point in points
Point _anchorPoint; ///< anchor point normalized (NOT in points) Point _anchorPoint; ///< anchor point normalized (NOT in points)
Size _contentSize; ///< untransformed size of the node Size _contentSize; ///< untransformed size of the node
kmMat4 _modelViewTransform; ///< ModelView transform of the Node. kmMat4 _modelViewTransform; ///< ModelView transform of the Node.
// "cache" variables are allowed to be mutable // "cache" variables are allowed to be mutable
mutable kmMat4 _transform; ///< transform
mutable bool _transformDirty; ///< transform dirty flag
mutable kmMat4 _inverse; ///< inverse transform
mutable bool _inverseDirty; ///< inverse transform dirty flag
mutable kmMat4 _additionalTransform; ///< transform mutable kmMat4 _additionalTransform; ///< transform
mutable kmMat4 _transform; ///< transform
mutable kmMat4 _inverse; ///< inverse transform
bool _useAdditionalTransform; ///< The flag to check whether the additional transform is dirty bool _useAdditionalTransform; ///< The flag to check whether the additional transform is dirty
mutable bool _transformDirty; ///< transform dirty flag bool _transformUpdated; ///< Whether or not the Transform object was updated since the last frame
mutable bool _inverseDirty; ///< inverse transform dirty flag
int _localZOrder; ///< Local order (relative to its siblings) used to sort the node
float _globalZOrder; ///< Global order used to sort the node
int _localZOrder; ///< Local order (relative to its siblings) used to sort the node Vector<Node*> _children; ///< array of children nodes
float _globalZOrder; ///< Global order used to sort the node
Vector<Node*> _children; ///< array of children nodes
Node *_parent; ///< weak reference to parent node Node *_parent; ///< weak reference to parent node
int _tag; ///< a tag. Can be any number you assigned just to identify this node int _tag; ///< a tag. Can be any number you assigned just to identify this node
void *_userData; ///< A user assingned void pointer, Can be point to any cpp object void *_userData; ///< A user assingned void pointer, Can be point to any cpp object
Ref *_userObject; ///< A user assigned Object Ref *_userObject; ///< A user assigned Object
GLProgram *_shaderProgram; ///< OpenGL shader GLProgram *_shaderProgram; ///< OpenGL shader
@ -1539,9 +1485,9 @@ protected:
EventDispatcher* _eventDispatcher; ///< event dispatcher used to dispatch all kinds of events EventDispatcher* _eventDispatcher; ///< event dispatcher used to dispatch all kinds of events
bool _running; ///< is running bool _running; ///< is running
bool _visible; ///< is this node visible bool _visible; ///< is this node visible
bool _ignoreAnchorPointForPosition; ///< true if the Anchor Point will be (0,0) when you position the Node, false otherwise. bool _ignoreAnchorPointForPosition; ///< true if the Anchor Point will be (0,0) when you position the Node, false otherwise.
///< Used by Layer and Scene. ///< Used by Layer and Scene.

View File

@ -82,7 +82,7 @@ void NodeGrid::onGridEndDraw()
} }
} }
void NodeGrid::visit() void NodeGrid::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
// quick return if not visible. children won't be drawn. // quick return if not visible. children won't be drawn.
if (!_visible) if (!_visible)
@ -90,13 +90,21 @@ void NodeGrid::visit()
return; return;
} }
Renderer* renderer = Director::getInstance()->getRenderer();
_groupCommand.init(_globalZOrder); _groupCommand.init(_globalZOrder);
renderer->addCommand(&_groupCommand); renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID()); renderer->pushGroup(_groupCommand.getRenderQueueID());
bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
_modelViewTransform = this->transform(parentTransform);
_transformUpdated = false;
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix(); kmGLPushMatrix();
kmGLLoadMatrix(&_modelViewTransform);
Director::Projection beforeProjectionType; Director::Projection beforeProjectionType;
if(_nodeGrid && _nodeGrid->isActive()) if(_nodeGrid && _nodeGrid->isActive())
{ {
@ -108,11 +116,10 @@ void NodeGrid::visit()
_gridBeginCommand.func = CC_CALLBACK_0(NodeGrid::onGridBeginDraw, this); _gridBeginCommand.func = CC_CALLBACK_0(NodeGrid::onGridBeginDraw, this);
renderer->addCommand(&_gridBeginCommand); renderer->addCommand(&_gridBeginCommand);
this->transform();
if(_gridTarget) if(_gridTarget)
{ {
_gridTarget->visit(); _gridTarget->visit(renderer, _modelViewTransform, dirty);
} }
int i = 0; int i = 0;
@ -126,20 +133,20 @@ void NodeGrid::visit()
auto node = _children.at(i); auto node = _children.at(i);
if ( node && node->getLocalZOrder() < 0 ) if ( node && node->getLocalZOrder() < 0 )
node->visit(); node->visit(renderer, _modelViewTransform, dirty);
else else
break; break;
} }
// self draw,currently we have nothing to draw on NodeGrid, so there is no need to add render command // self draw,currently we have nothing to draw on NodeGrid, so there is no need to add render command
this->draw(); this->draw(renderer, _modelViewTransform, dirty);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) { for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) {
(*it)->visit(); (*it)->visit(renderer, _modelViewTransform, dirty);
} }
} }
else else
{ {
this->draw(); this->draw(renderer, _modelViewTransform, dirty);
} }
// reset for next frame // reset for next frame

View File

@ -55,7 +55,7 @@ public:
void setTarget(Node *target); void setTarget(Node *target);
// overrides // overrides
virtual void visit() override; virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
protected: protected:
NodeGrid(); NodeGrid();

View File

@ -145,7 +145,7 @@ The positions are updated at visit because:
- using a timer is not guaranteed that it will called after all the positions were updated - using a timer is not guaranteed that it will called after all the positions were updated
- overriding "draw" will only precise if the children have a z > 0 - overriding "draw" will only precise if the children have a z > 0
*/ */
void ParallaxNode::visit() void ParallaxNode::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
// Point pos = position_; // Point pos = position_;
// Point pos = [self convertToWorldSpace:Point::ZERO]; // Point pos = [self convertToWorldSpace:Point::ZERO];
@ -161,7 +161,7 @@ void ParallaxNode::visit()
} }
_lastPosition = pos; _lastPosition = pos;
} }
Node::visit(); Node::visit(renderer, parentTransform, parentTransformUpdated);
} }
NS_CC_END NS_CC_END

View File

@ -67,7 +67,7 @@ public:
virtual void addChild(Node * child, int zOrder, int tag) override; virtual void addChild(Node * child, int zOrder, int tag) override;
virtual void removeChild(Node* child, bool cleanup) override; virtual void removeChild(Node* child, bool cleanup) override;
virtual void removeAllChildrenWithCleanup(bool cleanup) override; virtual void removeAllChildrenWithCleanup(bool cleanup) override;
virtual void visit(void) override; virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
protected: protected:
/** Adds a child to the container with a z-order, a parallax ratio and a position offset /** Adds a child to the container with a z-order, a parallax ratio and a position offset

View File

@ -120,7 +120,7 @@ bool ParticleBatchNode::initWithFile(const std::string& fileImage, int capacity)
// override visit. // override visit.
// Don't call visit on it's children // Don't call visit on it's children
void ParticleBatchNode::visit() void ParticleBatchNode::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
// CAREFUL: // CAREFUL:
// This visit is almost identical to Node#visit // This visit is almost identical to Node#visit
@ -134,11 +134,18 @@ void ParticleBatchNode::visit()
return; return;
} }
bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
_modelViewTransform = transform(parentTransform);
_transformUpdated = false;
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix(); kmGLPushMatrix();
kmGLLoadMatrix(&_modelViewTransform);
transform(); draw(renderer, _modelViewTransform, dirty);
draw();
kmGLPopMatrix(); kmGLPopMatrix();
} }
@ -373,7 +380,7 @@ void ParticleBatchNode::removeAllChildrenWithCleanup(bool doCleanup)
_textureAtlas->removeAllQuads(); _textureAtlas->removeAllQuads();
} }
void ParticleBatchNode::draw(void) void ParticleBatchNode::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
CC_PROFILER_START("CCParticleBatchNode - draw"); CC_PROFILER_START("CCParticleBatchNode - draw");
@ -388,7 +395,7 @@ void ParticleBatchNode::draw(void)
_blendFunc, _blendFunc,
_textureAtlas, _textureAtlas,
_modelViewTransform); _modelViewTransform);
Director::getInstance()->getRenderer()->addCommand(&_batchCommand); renderer->addCommand(&_batchCommand);
CC_PROFILER_STOP("CCParticleBatchNode - draw"); CC_PROFILER_STOP("CCParticleBatchNode - draw");
} }

View File

@ -97,13 +97,13 @@ public:
inline void setTextureAtlas(TextureAtlas* atlas) { _textureAtlas = atlas; }; inline void setTextureAtlas(TextureAtlas* atlas) { _textureAtlas = atlas; };
// Overrides // Overrides
void visit(); virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
using Node::addChild; using Node::addChild;
virtual void addChild(Node * child, int zOrder, int tag) override; virtual void addChild(Node * child, int zOrder, int tag) override;
virtual void removeChild(Node* child, bool cleanup) override; virtual void removeChild(Node* child, bool cleanup) override;
virtual void reorderChild(Node * child, int zOrder) override; virtual void reorderChild(Node * child, int zOrder) override;
virtual void draw(void) override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual Texture2D* getTexture(void) const override; virtual Texture2D* getTexture(void) const override;
virtual void setTexture(Texture2D *texture) override; virtual void setTexture(Texture2D *texture) override;
/** /**

View File

@ -72,7 +72,7 @@ bool ParticleSystemQuad::initWithTotalParticles(int numberOfParticles)
setupVBO(); setupVBO();
} }
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR)); setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP));
#if CC_ENABLE_CACHE_TEXTURE_DATA #if CC_ENABLE_CACHE_TEXTURE_DATA
// Need to listen the event only when not use batchnode, because it will use VBO // Need to listen the event only when not use batchnode, because it will use VBO
@ -358,103 +358,15 @@ void ParticleSystemQuad::postStep()
} }
// overriding draw method // overriding draw method
//void ParticleSystemQuad::draw() void ParticleSystemQuad::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
//{
// CCASSERT(!_batchNode,"draw should not be called when added to a particleBatchNode");
//
// CC_NODE_DRAW_SETUP();
//
// GL::bindTexture2D( _texture->getName() );
// GL::blendFunc( _blendFunc.src, _blendFunc.dst );
//
// CCASSERT( _particleIdx == _particleCount, "Abnormal error in particle quad");
//
// if (Configuration::getInstance()->supportsShareableVAO())
// {
// //
// // Using VBO and VAO
// //
// GL::bindVAO(_VAOname);
//
//#if CC_REBIND_INDICES_BUFFER
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
//#endif
//
// glDrawElements(GL_TRIANGLES, (GLsizei) _particleIdx*6, GL_UNSIGNED_SHORT, 0);
//
//#if CC_REBIND_INDICES_BUFFER
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//#endif
// }
// else
// {
// //
// // Using VBO without VAO
// //
//
// #define kQuadSize sizeof(_quads[0].bl)
//
// GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX );
//
// glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
// // vertices
// glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( V3F_C4B_T2F, vertices));
// // colors
// glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof( V3F_C4B_T2F, colors));
// // tex coords
// glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORDS, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( V3F_C4B_T2F, texCoords));
//
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
//
// glDrawElements(GL_TRIANGLES, (GLsizei) _particleIdx*6, GL_UNSIGNED_SHORT, 0);
//
// glBindBuffer(GL_ARRAY_BUFFER, 0);
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// }
//
// CC_INCREMENT_GL_DRAWS(1);
// CHECK_GL_ERROR_DEBUG();
//}
void ParticleSystemQuad::draw()
{ {
CCASSERT( _particleIdx == _particleCount, "Abnormal error in particle quad"); CCASSERT( _particleIdx == _particleCount, "Abnormal error in particle quad");
//quad command //quad command
if(_particleIdx > 0) if(_particleIdx > 0)
{ {
// //transform vertices _quadCommand.init(_globalZOrder, _texture->getName(), _shaderProgram, _blendFunc, _quads, _particleIdx, transform);
// std::vector<V3F_C4B_T2F_Quad> drawQuads(_particleIdx); renderer->addCommand(&_quadCommand);
// memcpy(&drawQuads[0], _quads, sizeof(V3F_C4B_T2F_Quad) * _particleIdx);
// AffineTransform worldTM = getNodeToWorldTransform();
// for(int index = 0; index <_particleIdx; ++index)
// {
// V3F_C4B_T2F_Quad* quad = _quads + index;
//
// Point pt(0,0);
// pt = PointApplyAffineTransform( Point(quad->bl.vertices.x, quad->bl.vertices.y), worldTM);
// drawQuads[index].bl.vertices.x = pt.x;
// drawQuads[index].bl.vertices.y = pt.y;
//
// pt = PointApplyAffineTransform( Point(quad->br.vertices.x, quad->br.vertices.y), worldTM);
// drawQuads[index].br.vertices.x = pt.x;
// drawQuads[index].br.vertices.y = pt.y;
//
// pt = PointApplyAffineTransform( Point(quad->tl.vertices.x, quad->tl.vertices.y), worldTM);
// drawQuads[index].tl.vertices.x = pt.x;
// drawQuads[index].tl.vertices.y = pt.y;
//
// pt = PointApplyAffineTransform( Point(quad->tr.vertices.x, quad->tr.vertices.y), worldTM);
// drawQuads[index].tr.vertices.x = pt.x;
// drawQuads[index].tr.vertices.y = pt.y;
//
// }
auto shader = ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP);
_quadCommand.init(_globalZOrder, _texture->getName(), shader, _blendFunc, _quads, _particleIdx, _modelViewTransform);
Director::getInstance()->getRenderer()->addCommand(&_quadCommand);
} }
} }
void ParticleSystemQuad::setTotalParticles(int tp) void ParticleSystemQuad::setTotalParticles(int tp)

View File

@ -104,7 +104,7 @@ public:
* @js NA * @js NA
* @lua NA * @lua NA
*/ */
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
/** /**
* @js NA * @js NA
@ -151,15 +151,12 @@ protected:
bool allocMemory(); bool allocMemory();
V3F_C4B_T2F_Quad *_quads; // quads to be rendered V3F_C4B_T2F_Quad *_quads; // quads to be rendered
GLushort *_indices; // indices GLushort *_indices; // indices
GLuint _VAOname;
GLuint _VAOname; GLuint _buffersVBO[2]; //0: vertex 1: indices
GLuint _buffersVBO[2]; //0: vertex 1: indices QuadCommand _quadCommand; // quad command
kmMat4 _transformMatrix;
QuadCommand _quadCommand; // quad command
private: private:
CC_DISALLOW_COPY_AND_ASSIGN(ParticleSystemQuad); CC_DISALLOW_COPY_AND_ASSIGN(ParticleSystemQuad);
}; };

View File

@ -532,7 +532,8 @@ void ProgressTimer::onDraw()
if(_type == Type::RADIAL) if(_type == Type::RADIAL)
{ {
glDrawArrays(GL_TRIANGLE_FAN, 0, _vertexDataCount); glDrawArrays(GL_TRIANGLE_FAN, 0, _vertexDataCount);
} CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_vertexDataCount);
}
else if (_type == Type::BAR) else if (_type == Type::BAR)
{ {
if (!_reverseDirection) if (!_reverseDirection)
@ -550,14 +551,14 @@ void ProgressTimer::onDraw()
} }
} }
void ProgressTimer::draw() void ProgressTimer::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
if( ! _vertexData || ! _sprite) if( ! _vertexData || ! _sprite)
return; return;
_customCommand.init(_globalZOrder); _customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(ProgressTimer::onDraw, this); _customCommand.func = CC_CALLBACK_0(ProgressTimer::onDraw, this);
Director::getInstance()->getRenderer()->addCommand(&_customCommand); renderer->addCommand(&_customCommand);
} }

View File

@ -111,7 +111,7 @@ public:
inline Point getBarChangeRate() const { return _barChangeRate; } inline Point getBarChangeRate() const { return _barChangeRate; }
// Overrides // Overrides
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual void setAnchorPoint(const Point& anchorPoint) override; virtual void setAnchorPoint(const Point& anchorPoint) override;
virtual void setColor(const Color3B &color) override; virtual void setColor(const Color3B &color) override;
virtual const Color3B& getColor() const override; virtual const Color3B& getColor() const override;

View File

@ -361,7 +361,7 @@ void RenderTexture::clearStencil(int stencilValue)
glClearStencil(stencilClearValue); glClearStencil(stencilClearValue);
} }
void RenderTexture::visit() void RenderTexture::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
// override visit. // override visit.
// Don't call visit on its children // Don't call visit on its children
@ -370,11 +370,19 @@ void RenderTexture::visit()
return; return;
} }
kmGLPushMatrix(); bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
transform(); _modelViewTransform = transform(parentTransform);
_sprite->visit(); _transformUpdated = false;
draw();
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix();
kmGLLoadMatrix(&_modelViewTransform);
_sprite->visit(renderer, _modelViewTransform, dirty);
draw(renderer, _modelViewTransform, dirty);
kmGLPopMatrix(); kmGLPopMatrix();
@ -610,7 +618,7 @@ void RenderTexture::onClearDepth()
glClearDepth(depthClearValue); glClearDepth(depthClearValue);
} }
void RenderTexture::draw() void RenderTexture::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
if (_autoDraw) if (_autoDraw)
{ {
@ -620,7 +628,7 @@ void RenderTexture::draw()
//clear screen //clear screen
_clearCommand.init(_globalZOrder); _clearCommand.init(_globalZOrder);
_clearCommand.func = CC_CALLBACK_0(RenderTexture::onClear, this); _clearCommand.func = CC_CALLBACK_0(RenderTexture::onClear, this);
Director::getInstance()->getRenderer()->addCommand(&_clearCommand); renderer->addCommand(&_clearCommand);
//! make sure all children are drawn //! make sure all children are drawn
sortAllChildren(); sortAllChildren();
@ -628,7 +636,7 @@ void RenderTexture::draw()
for(const auto &child: _children) for(const auto &child: _children)
{ {
if (child != _sprite) if (child != _sprite)
child->visit(); child->visit(renderer, transform, transformUpdated);
} }
//End will pop the current render group //End will pop the current render group

View File

@ -154,8 +154,8 @@ public:
}; };
// Overrides // Overrides
virtual void visit() override; virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
public: public:
// XXX should be procted. // XXX should be procted.

View File

@ -33,28 +33,16 @@ THE SOFTWARE.
#include "CCArray.h" #include "CCArray.h"
#include "CCScriptSupport.h" #include "CCScriptSupport.h"
using namespace std;
NS_CC_BEGIN NS_CC_BEGIN
long schedule_selector_to_key(SEL_SCHEDULE selector)
{
static union{
SEL_SCHEDULE func;
long key;
};
func = selector;
return key;
}
// data structures // data structures
// A list double-linked list used for "updates with priority" // A list double-linked list used for "updates with priority"
typedef struct _listEntry typedef struct _listEntry
{ {
struct _listEntry *prev, *next; struct _listEntry *prev, *next;
void *target;
ccSchedulerFunc callback; ccSchedulerFunc callback;
void *target;
int priority; int priority;
bool paused; bool paused;
bool markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick bool markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick
@ -84,65 +72,24 @@ typedef struct _hashSelectorEntry
// implementation Timer // implementation Timer
Timer::Timer() Timer::Timer()
: _target(nullptr) : _elapsed(-1)
, _elapsed(-1)
, _runForever(false) , _runForever(false)
, _useDelay(false) , _useDelay(false)
, _timesExecuted(0) , _timesExecuted(0)
, _repeat(0) , _repeat(0)
, _delay(0.0f) , _delay(0.0f)
, _interval(0.0f) , _interval(0.0f)
, _callback(nullptr)
, _key(0)
#if CC_ENABLE_SCRIPT_BINDING
, _scriptHandler(0)
#endif
{ {
} }
Timer* Timer::create(const ccSchedulerFunc& callback, void *target, long key, float seconds/* = 0 */) void Timer::setupTimerWithInterval(float seconds, unsigned int repeat, float delay)
{ {
Timer *timer = new Timer(); _elapsed = -1;
_interval = seconds;
timer->initWithTarget(callback, target, key, seconds, kRepeatForever, 0.0f); _delay = delay;
timer->autorelease(); _useDelay = (_delay > 0.0f) ? true : false;
_repeat = repeat;
return timer; _runForever = (_repeat == kRepeatForever) ? true : false;
}
#if CC_ENABLE_SCRIPT_BINDING
Timer* Timer::createWithScriptHandler(int handler, float seconds)
{
Timer *timer = new Timer();
timer->initWithScriptHandler(handler, seconds);
timer->autorelease();
return timer;
}
bool Timer::initWithScriptHandler(int handler, float seconds)
{
_scriptHandler = handler;
_elapsed = -1;
_interval = seconds;
return true;
}
#endif
bool Timer::initWithTarget(const ccSchedulerFunc& callback, void *target, long key, float seconds, unsigned int repeat, float delay)
{
_target = target;
_callback = callback;
_key = key;
_elapsed = -1;
_interval = seconds;
_delay = delay;
_useDelay = (delay > 0.0f) ? true : false;
_repeat = repeat;
_runForever = (repeat == kRepeatForever) ? true : false;
return true;
} }
void Timer::update(float dt) void Timer::update(float dt)
@ -159,18 +106,8 @@ void Timer::update(float dt)
_elapsed += dt; _elapsed += dt;
if (_elapsed >= _interval) if (_elapsed >= _interval)
{ {
if (_target && _key != 0 && _callback) trigger();
{
_callback(_elapsed);
}
#if CC_ENABLE_SCRIPT_BINDING
if (0 != _scriptHandler)
{
SchedulerScriptData data(_scriptHandler,_elapsed);
ScriptEvent event(kScheduleEvent,&data);
ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
}
#endif
_elapsed = 0; _elapsed = 0;
} }
} }
@ -181,19 +118,8 @@ void Timer::update(float dt)
{ {
if( _elapsed >= _delay ) if( _elapsed >= _delay )
{ {
if (_target && _key != 0 && _callback) trigger();
{
_callback(_elapsed);
}
#if CC_ENABLE_SCRIPT_BINDING
if (0 != _scriptHandler)
{
SchedulerScriptData data(_scriptHandler,_elapsed);
ScriptEvent event(kScheduleEvent,&data);
ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
}
#endif
_elapsed = _elapsed - _delay; _elapsed = _elapsed - _delay;
_timesExecuted += 1; _timesExecuted += 1;
_useDelay = false; _useDelay = false;
@ -203,19 +129,7 @@ void Timer::update(float dt)
{ {
if (_elapsed >= _interval) if (_elapsed >= _interval)
{ {
if (_target && _key != 0 && _callback) trigger();
{
_callback(_elapsed);
}
#if CC_ENABLE_SCRIPT_BINDING
if (0 != _scriptHandler)
{
SchedulerScriptData data(_scriptHandler,_elapsed);
ScriptEvent event(kScheduleEvent,&data);
ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
}
#endif
_elapsed = 0; _elapsed = 0;
_timesExecuted += 1; _timesExecuted += 1;
@ -225,12 +139,106 @@ void Timer::update(float dt)
if (!_runForever && _timesExecuted > _repeat) if (!_runForever && _timesExecuted > _repeat)
{ //unschedule timer { //unschedule timer
Director::getInstance()->getScheduler()->unschedule(_target, _key); cancel();
} }
} }
} }
} }
// TimerTargetSelector
TimerTargetSelector::TimerTargetSelector()
: _target(nullptr)
, _selector(nullptr)
{
}
bool TimerTargetSelector::initWithSelector(SEL_SCHEDULE selector, Ref* target, float seconds, unsigned int repeat, float delay)
{
_target = target;
_selector = selector;
setupTimerWithInterval(seconds, repeat, delay);
return true;
}
void TimerTargetSelector::trigger()
{
if (_target && _selector)
{
(_target->*_selector)(_elapsed);
}
}
void TimerTargetSelector::cancel()
{
Director::getInstance()->getScheduler()->unschedule(_selector, _target);
}
// TimerTargetCallback
TimerTargetCallback::TimerTargetCallback()
: _target(nullptr)
, _callback(nullptr)
{
}
bool TimerTargetCallback::initWithCallback(const ccSchedulerFunc& callback, void *target, const std::string& key, float seconds, unsigned int repeat, float delay)
{
_target = target;
_callback = callback;
_key = key;
setupTimerWithInterval(seconds, repeat, delay);
return true;
}
void TimerTargetCallback::trigger()
{
if (_callback)
{
_callback(_elapsed);
}
}
void TimerTargetCallback::cancel()
{
Director::getInstance()->getScheduler()->unschedule(_key, _target);
}
#if CC_ENABLE_SCRIPT_BINDING
// TimerScriptHandler
bool TimerScriptHandler::initWithScriptHandler(int handler, float seconds)
{
_scriptHandler = handler;
_elapsed = -1;
_interval = seconds;
return true;
}
void TimerScriptHandler::trigger()
{
if (0 != _scriptHandler)
{
SchedulerScriptData data(_scriptHandler,_elapsed);
ScriptEvent event(kScheduleEvent,&data);
ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
}
}
void TimerScriptHandler::cancel()
{
if (0 != _scriptHandler)
{
ScriptEngineManager::getInstance()->getScriptEngine()->removeScriptHandler(_scriptHandler);
_scriptHandler = 0;
}
}
#endif
// implementation of Scheduler // implementation of Scheduler
// Priority level reserved for system services. // Priority level reserved for system services.
@ -269,15 +277,15 @@ void Scheduler::removeHashElement(_hashSelectorEntry *element)
free(element); free(element);
} }
void Scheduler::schedule(const ccSchedulerFunc& callback, void *target, long key, float interval, bool paused) void Scheduler::schedule(const ccSchedulerFunc& callback, void *target, float interval, bool paused, const std::string& key)
{ {
this->schedule(callback, target, key, interval, kRepeatForever, 0.0f, paused); this->schedule(callback, target, interval, kRepeatForever, 0.0f, paused, key);
} }
void Scheduler::schedule(const ccSchedulerFunc& callback, void *target, long key, float interval, unsigned int repeat, float delay, bool paused) void Scheduler::schedule(const ccSchedulerFunc& callback, void *target, float interval, unsigned int repeat, float delay, bool paused, const std::string& key)
{ {
CCASSERT(target, "Argument target must be non-nullptr"); CCASSERT(target, "Argument target must be non-nullptr");
CCASSERT(key != 0, "key should not be empty!"); CCASSERT(!key.empty(), "key should not be empty!");
tHashTimerEntry *element = nullptr; tHashTimerEntry *element = nullptr;
HASH_FIND_PTR(_hashForTimers, &target, element); HASH_FIND_PTR(_hashForTimers, &target, element);
@ -305,7 +313,7 @@ void Scheduler::schedule(const ccSchedulerFunc& callback, void *target, long key
{ {
for (int i = 0; i < element->timers->num; ++i) for (int i = 0; i < element->timers->num; ++i)
{ {
Timer *timer = (Timer*)element->timers->arr[i]; TimerTargetCallback *timer = static_cast<TimerTargetCallback*>(element->timers->arr[i]);
if (key == timer->getKey()) if (key == timer->getKey())
{ {
@ -317,16 +325,16 @@ void Scheduler::schedule(const ccSchedulerFunc& callback, void *target, long key
ccArrayEnsureExtraCapacity(element->timers, 1); ccArrayEnsureExtraCapacity(element->timers, 1);
} }
Timer *timer = new Timer(); TimerTargetCallback *timer = new TimerTargetCallback();
timer->initWithTarget(callback, target, key, interval, repeat, delay); timer->initWithCallback(callback, target, key, interval, repeat, delay);
ccArrayAppendObject(element->timers, timer); ccArrayAppendObject(element->timers, timer);
timer->release(); timer->release();
} }
void Scheduler::unschedule(void *target, long key) void Scheduler::unschedule(const std::string &key, void *target)
{ {
// explicity handle nil arguments when removing an object // explicity handle nil arguments when removing an object
if (target == nullptr || key == 0) if (target == nullptr || key.empty())
{ {
return; return;
} }
@ -341,7 +349,7 @@ void Scheduler::unschedule(void *target, long key)
{ {
for (int i = 0; i < element->timers->num; ++i) for (int i = 0; i < element->timers->num; ++i)
{ {
Timer *timer = static_cast<Timer*>(element->timers->arr[i]); TimerTargetCallback *timer = static_cast<TimerTargetCallback*>(element->timers->arr[i]);
if (key == timer->getKey()) if (key == timer->getKey())
{ {
@ -453,7 +461,7 @@ void Scheduler::appendIn(_listEntry **list, const ccSchedulerFunc& callback, voi
HASH_ADD_PTR(_hashForUpdates, target, hashElement); HASH_ADD_PTR(_hashForUpdates, target, hashElement);
} }
void Scheduler::scheduleUpdate(const ccSchedulerFunc& callback, void *target, int priority, bool paused) void Scheduler::schedulePerFrame(const ccSchedulerFunc& callback, void *target, int priority, bool paused)
{ {
tHashUpdateEntry *hashElement = nullptr; tHashUpdateEntry *hashElement = nullptr;
HASH_FIND_PTR(_hashForUpdates, &target, hashElement); HASH_FIND_PTR(_hashForUpdates, &target, hashElement);
@ -485,9 +493,9 @@ void Scheduler::scheduleUpdate(const ccSchedulerFunc& callback, void *target, in
} }
} }
bool Scheduler::isScheduled(void *target, long key) bool Scheduler::isScheduled(const std::string& key, void *target)
{ {
CCASSERT(key != 0, "Argument key must be empty"); CCASSERT(!key.empty(), "Argument key must not be empty");
CCASSERT(target, "Argument target must be non-nullptr"); CCASSERT(target, "Argument target must be non-nullptr");
tHashTimerEntry *element = nullptr; tHashTimerEntry *element = nullptr;
@ -501,11 +509,12 @@ bool Scheduler::isScheduled(void *target, long key)
if (element->timers == nullptr) if (element->timers == nullptr)
{ {
return false; return false;
}else }
else
{ {
for (int i = 0; i < element->timers->num; ++i) for (int i = 0; i < element->timers->num; ++i)
{ {
Timer *timer = (Timer*)element->timers->arr[i]; TimerTargetCallback *timer = static_cast<TimerTargetCallback*>(element->timers->arr[i]);
if (key == timer->getKey()) if (key == timer->getKey())
{ {
@ -536,7 +545,7 @@ void Scheduler::removeUpdateFromHash(struct _listEntry *entry)
} }
} }
void Scheduler::unscheduleUpdate(void* target) void Scheduler::unscheduleUpdate(void *target)
{ {
if (target == nullptr) if (target == nullptr)
{ {
@ -959,38 +968,146 @@ void Scheduler::update(float dt)
} }
} }
//OLD METHODS: void Scheduler::schedule(SEL_SCHEDULE selector, Ref *target, float interval, unsigned int repeat, float delay, bool paused)
void Scheduler::scheduleSelector(SEL_SCHEDULE selector, Ref *target, float interval, unsigned int repeat, float delay, bool paused)
{ {
target->retain(); CCASSERT(target, "Argument target must be non-nullptr");
this->schedule([=](float dt){
(target->*selector)(dt); tHashTimerEntry *element = nullptr;
}, target, schedule_selector_to_key(selector), interval , repeat, delay, paused); HASH_FIND_PTR(_hashForTimers, &target, element);
if (! element)
{
element = (tHashTimerEntry *)calloc(sizeof(*element), 1);
element->target = target;
HASH_ADD_PTR(_hashForTimers, target, element);
// Is this the 1st element ? Then set the pause level to all the selectors of this target
element->paused = paused;
}
else
{
CCASSERT(element->paused == paused, "");
}
if (element->timers == nullptr)
{
element->timers = ccArrayNew(10);
}
else
{
for (int i = 0; i < element->timers->num; ++i)
{
TimerTargetSelector *timer = static_cast<TimerTargetSelector*>(element->timers->arr[i]);
if (selector == timer->getSelector())
{
CCLOG("CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f", timer->getInterval(), interval);
timer->setInterval(interval);
return;
}
}
ccArrayEnsureExtraCapacity(element->timers, 1);
}
TimerTargetSelector *timer = new TimerTargetSelector();
timer->initWithSelector(selector, target, interval, repeat, delay);
ccArrayAppendObject(element->timers, timer);
timer->release();
} }
void Scheduler::scheduleSelector(SEL_SCHEDULE selector, Ref *target, float interval, bool paused) void Scheduler::schedule(SEL_SCHEDULE selector, Ref *target, float interval, bool paused)
{ {
target->retain(); this->schedule(selector, target, interval, kRepeatForever, 0.0f, paused);
this->schedule([=](float dt){
(target->*selector)(dt);
}, target, schedule_selector_to_key(selector), interval, paused);
} }
bool Scheduler::isScheduledForTarget(SEL_SCHEDULE selector, Ref *target) bool Scheduler::isScheduled(SEL_SCHEDULE selector, Ref *target)
{ {
return this->isScheduled(target, schedule_selector_to_key(selector)); CCASSERT(selector, "Argument selector must be non-nullptr");
CCASSERT(target, "Argument target must be non-nullptr");
tHashTimerEntry *element = nullptr;
HASH_FIND_PTR(_hashForTimers, &target, element);
if (!element)
{
return false;
}
if (element->timers == nullptr)
{
return false;
}
else
{
for (int i = 0; i < element->timers->num; ++i)
{
TimerTargetSelector *timer = static_cast<TimerTargetSelector*>(element->timers->arr[i]);
if (selector == timer->getSelector())
{
return true;
}
}
return false;
}
return false; // should never get here
} }
void Scheduler::unscheduleSelector(SEL_SCHEDULE selector, Ref *target) void Scheduler::unschedule(SEL_SCHEDULE selector, Ref *target)
{ {
this->unschedule(target, schedule_selector_to_key(selector)); // explicity handle nil arguments when removing an object
target->release(); if (target == nullptr || selector == nullptr)
{
return;
}
//CCASSERT(target);
//CCASSERT(selector);
tHashTimerEntry *element = nullptr;
HASH_FIND_PTR(_hashForTimers, &target, element);
if (element)
{
for (int i = 0; i < element->timers->num; ++i)
{
TimerTargetSelector *timer = static_cast<TimerTargetSelector*>(element->timers->arr[i]);
if (selector == timer->getSelector())
{
if (timer == element->currentTimer && (! element->currentTimerSalvaged))
{
element->currentTimer->retain();
element->currentTimerSalvaged = true;
}
ccArrayRemoveObjectAtIndex(element->timers, i, true);
// update timerIndex in case we are in tick:, looping over the actions
if (element->timerIndex >= i)
{
element->timerIndex--;
}
if (element->timers->num == 0)
{
if (_currentTarget == element)
{
_currentTargetSalvaged = true;
}
else
{
removeHashElement(element);
}
}
return;
}
}
}
} }
void Scheduler::unscheduleUpdateForTarget(Ref *target)
{
this->unscheduleUpdate(target);
target->release();
};
NS_CC_END NS_CC_END

View File

@ -43,8 +43,6 @@ NS_CC_BEGIN
* @{ * @{
*/ */
long schedule_selector_to_key(SEL_SCHEDULE selector);
typedef std::function<void(float)> ccSchedulerFunc; typedef std::function<void(float)> ccSchedulerFunc;
// //
// Timer // Timer
@ -53,46 +51,24 @@ typedef std::function<void(float)> ccSchedulerFunc;
// //
class CC_DLL Timer : public Ref class CC_DLL Timer : public Ref
{ {
protected:
Timer();
public: public:
/** Allocates a timer with a target, a selector and an interval in seconds. */
static Timer* create(const ccSchedulerFunc& callback, void *target, long key, float seconds = 0.0f);
#if CC_ENABLE_SCRIPT_BINDING
/** Allocates a timer with a script callback function and an interval in seconds.
* @js NA
* @lua NA
*/
static Timer* createWithScriptHandler(int handler, float seconds);
/** Initializes a timer with a script callback function and an interval in seconds. */
bool initWithScriptHandler(int handler, float seconds);
#endif
Timer(void);
/** Initializes a timer with a target, a selector and an interval in seconds, repeat in number of times to repeat, delay in seconds. */
bool initWithTarget(const ccSchedulerFunc& callback, void *target, long key, float seconds, unsigned int repeat, float delay);
/** get interval in seconds */ /** get interval in seconds */
inline float getInterval() const { return _interval; }; inline float getInterval() const { return _interval; };
/** set interval in seconds */ /** set interval in seconds */
inline void setInterval(float interval) { _interval = interval; }; inline void setInterval(float interval) { _interval = interval; };
/**
* @js NA void setupTimerWithInterval(float seconds, unsigned int repeat, float delay);
* @lua NA
*/ virtual void trigger() = 0;
inline const ccSchedulerFunc& getCallback() const { return _callback; }; virtual void cancel() = 0;
inline long getKey() const { return _key; };
/** triggers the timer */ /** triggers the timer */
void update(float dt); void update(float dt);
#if CC_ENABLE_SCRIPT_BINDING
inline int getScriptHandler() const { return _scriptHandler; };
#endif
protected: protected:
void *_target;
float _elapsed; float _elapsed;
bool _runForever; bool _runForever;
bool _useDelay; bool _useDelay;
@ -100,13 +76,69 @@ protected:
unsigned int _repeat; //0 = once, 1 is 2 x executed unsigned int _repeat; //0 = once, 1 is 2 x executed
float _delay; float _delay;
float _interval; float _interval;
ccSchedulerFunc _callback;
long _key;
#if CC_ENABLE_SCRIPT_BINDING
int _scriptHandler;
#endif
}; };
class CC_DLL TimerTargetSelector : public Timer
{
public:
TimerTargetSelector();
/** Initializes a timer with a target, a selector and an interval in seconds, repeat in number of times to repeat, delay in seconds. */
bool initWithSelector(SEL_SCHEDULE selector, Ref* target, float seconds, unsigned int repeat, float delay);
inline SEL_SCHEDULE getSelector() const { return _selector; };
virtual void trigger() override;
virtual void cancel() override;
protected:
Ref* _target;
SEL_SCHEDULE _selector;
};
class CC_DLL TimerTargetCallback : public Timer
{
public:
TimerTargetCallback();
/** Initializes a timer with a target, a lambda and an interval in seconds, repeat in number of times to repeat, delay in seconds. */
bool initWithCallback(const ccSchedulerFunc& callback, void *target, const std::string& key, float seconds, unsigned int repeat, float delay);
/**
* @js NA
* @lua NA
*/
inline const ccSchedulerFunc& getCallback() const { return _callback; };
inline const std::string& getKey() const { return _key; };
virtual void trigger() override;
virtual void cancel() override;
protected:
void* _target;
ccSchedulerFunc _callback;
std::string _key;
};
#if CC_ENABLE_SCRIPT_BINDING
class CC_DLL TimerScriptHandler : public Timer
{
public:
bool initWithScriptHandler(int handler, float seconds);
inline int getScriptHandler() const { return _scriptHandler; };
virtual void trigger() override;
virtual void cancel() override;
private:
int _scriptHandler;
};
#endif
// //
// Scheduler // Scheduler
// //
@ -119,7 +151,7 @@ class SchedulerScriptHandlerEntry;
#endif #endif
/** @brief Scheduler is responsible for triggering the scheduled callbacks. /** @brief Scheduler is responsible for triggering the scheduled callbacks.
You should not use NSTimer. Instead use this class. You should not use system timer for your game logic. Instead, use this class.
There are 2 different types of callbacks (selectors): There are 2 different types of callbacks (selectors):
@ -145,7 +177,7 @@ public:
* @js NA * @js NA
* @lua NA * @lua NA
*/ */
~Scheduler(void); virtual ~Scheduler();
inline float getTimeScale() { return _timeScale; } inline float getTimeScale() { return _timeScale; }
/** Modifies the time of all scheduled callbacks. /** Modifies the time of all scheduled callbacks.
@ -164,115 +196,126 @@ public:
*/ */
void update(float dt); void update(float dt);
/////////////////////////////////////
// schedule
/** The scheduled method will be called every 'interval' seconds. /** The scheduled method will be called every 'interval' seconds.
If paused is true, then it won't be called until it is resumed. If paused is true, then it won't be called until it is resumed.
If 'interval' is 0, it will be called every frame, but if so, it's recommended to use 'scheduleUpdateForTarget:' instead. If 'interval' is 0, it will be called every frame, but if so, it's recommended to use 'scheduleUpdate' instead.
If the 'callback' is already scheduled, then only the interval parameter will be updated without re-scheduling it again.
repeat let the action be repeated repeat + 1 times, use kRepeatForever to let the action run continuously
delay is the amount of time the action will wait before it'll start
@param key The key to identify the callback
@since v3.0
*/
void schedule(const ccSchedulerFunc& callback, void *target, float interval, unsigned int repeat, float delay, bool paused, const std::string& key);
/** Calls scheduleCallback with kRepeatForever and a 0 delay
@since v3.0
*/
void schedule(const ccSchedulerFunc& callback, void *target, float interval, bool paused, const std::string& key);
/** The scheduled method will be called every 'interval' seconds.
If paused is true, then it won't be called until it is resumed.
If 'interval' is 0, it will be called every frame, but if so, it's recommended to use 'scheduleUpdate' instead.
If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again. If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again.
repeat let the action be repeated repeat + 1 times, use kRepeatForever to let the action run continuously repeat let the action be repeated repeat + 1 times, use kRepeatForever to let the action run continuously
delay is the amount of time the action will wait before it'll start delay is the amount of time the action will wait before it'll start
@since v3.0 @since v3.0, repeat and delay added in v1.1
*/ */
void schedule(const ccSchedulerFunc& callback, void *target, long key, float interval, unsigned int repeat, float delay, bool paused); void schedule(SEL_SCHEDULE selector, Ref *target, float interval, unsigned int repeat, float delay, bool paused);
/** calls scheduleSelector with kRepeatForever and a 0 delay */ /** calls scheduleSelector with kRepeatForever and a 0 delay */
void schedule(const ccSchedulerFunc& callback, void *target, long key, float interval, bool paused); void schedule(SEL_SCHEDULE selector, Ref *target, float interval, bool paused);
/** Schedules the 'update' selector for a given target with a given priority. /** Schedules the 'update' selector for a given target with a given priority.
The 'update' selector will be called every frame. The 'update' selector will be called every frame.
The lower the priority, the earlier it is called. The lower the priority, the earlier it is called.
@since v3.0 @since v3.0
@lua NA
*/ */
void scheduleUpdate(const ccSchedulerFunc& callback, void *target, int priority, bool paused);
/** Checks whether a selector for a given taget is scheduled.
@since v3.0.0
*/
bool isScheduled(void *target, long key);
/** Unschedule a selector for a given target.
If you want to unschedule the "update", use unscheudleUpdateForTarget.
@since v3.0
*/
void unschedule(void *target, long key);
/** Unschedules the update selector for a given target
@since v3.0
*/
void unscheduleUpdate(void *target);
/** Unschedules all selectors for a given target.
This also includes the "update" selector.
@since v3.0
*/
void unscheduleAllForTarget(void *target);
// OLD METHODS
/** The scheduled method will be called every 'interval' seconds.
If paused is true, then it won't be called until it is resumed.
If 'interval' is 0, it will be called every frame, but if so, it's recommended to use 'scheduleUpdateForTarget:' instead.
If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again.
repeat let the action be repeated repeat + 1 times, use kRepeatForever to let the action run continuously
delay is the amount of time the action will wait before it'll start
@since v0.99.3, repeat and delay added in v1.1
*/
void scheduleSelector(SEL_SCHEDULE selector, Ref *target, float interval, unsigned int repeat, float delay, bool paused);
/** calls scheduleSelector with kRepeatForever and a 0 delay */
void scheduleSelector(SEL_SCHEDULE selector, Ref *target, float interval, bool paused);
template <class T> template <class T>
void scheduleUpdateForTarget(T *target, int priority, bool paused) void scheduleUpdate(T *target, int priority, bool paused)
{ {
target->retain(); this->schedulePerFrame([target](float dt){
this->scheduleUpdate([=](float dt){
target->update(dt); target->update(dt);
}, target, priority, paused); }, target, priority, paused);
} }
/** Checks whether a selector for a given taget is scheduled.
@since v3.0.0
*/
bool isScheduledForTarget(SEL_SCHEDULE selector, Ref *target);
/** Unschedule a selector for a given target.
If you want to unschedule the "update", use unscheudleUpdateForTarget.
@since v0.99.3
*/
void unscheduleSelector(SEL_SCHEDULE selector, Ref *target);
/** Unschedules the update selector for a given target
@since v0.99.3
*/
void unscheduleUpdateForTarget(Ref *target);
///
/** Unschedules all selectors from all targets.
You should NEVER call this method, unless you know what you are doing.
@since v0.99.3
*/
void unscheduleAll(void);
/** Unschedules all selectors from all targets with a minimum priority.
You should only call this with kPriorityNonSystemMin or higher.
@since v2.0.0
*/
void unscheduleAllWithMinPriority(int minPriority);
#if CC_ENABLE_SCRIPT_BINDING #if CC_ENABLE_SCRIPT_BINDING
// schedule for script bindings
/** The scheduled script callback will be called every 'interval' seconds. /** The scheduled script callback will be called every 'interval' seconds.
If paused is true, then it won't be called until it is resumed. If paused is true, then it won't be called until it is resumed.
If 'interval' is 0, it will be called every frame. If 'interval' is 0, it will be called every frame.
return schedule script entry ID, used for unscheduleScriptFunc(). return schedule script entry ID, used for unscheduleScriptFunc().
*/ */
unsigned int scheduleScriptFunc(unsigned int handler, float interval, bool paused); unsigned int scheduleScriptFunc(unsigned int handler, float interval, bool paused);
#endif
/////////////////////////////////////
// unschedule
/** Unschedules a callback for a key and a given target.
If you want to unschedule the 'callbackPerFrame', use unscheduleUpdate.
@since v3.0
*/
void unschedule(const std::string& key, void *target);
/** Unschedule a selector for a given target.
If you want to unschedule the "update", use unscheudleUpdate.
@since v3.0
*/
void unschedule(SEL_SCHEDULE selector, Ref *target);
/** Unschedules the update selector for a given target
@since v0.99.3
*/
void unscheduleUpdate(void *target);
/** Unschedules all selectors for a given target.
This also includes the "update" selector.
@since v0.99.3
@js unscheduleCallbackForTarget
@lua NA
*/
void unscheduleAllForTarget(void *target);
/** Unschedules all selectors from all targets.
You should NEVER call this method, unless you know what you are doing.
@since v0.99.3
*/
void unscheduleAll(void);
/** Unschedules all selectors from all targets with a minimum priority.
You should only call this with kPriorityNonSystemMin or higher.
@since v2.0.0
*/
void unscheduleAllWithMinPriority(int minPriority);
#if CC_ENABLE_SCRIPT_BINDING
/** Unschedule a script entry. */ /** Unschedule a script entry. */
void unscheduleScriptEntry(unsigned int scheduleScriptEntryID); void unscheduleScriptEntry(unsigned int scheduleScriptEntryID);
#endif #endif
/////////////////////////////////////
// isScheduled
/** Checks whether a callback associated with 'key' and 'target' is scheduled.
@since v3.0.0
*/
bool isScheduled(const std::string& key, void *target);
/** Checks whether a selector for a given taget is scheduled.
@since v3.0
*/
bool isScheduled(SEL_SCHEDULE selector, Ref *target);
/////////////////////////////////////
/** Pauses the target. /** Pauses the target.
All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed. All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed.
If the target is not present, nothing happens. If the target is not present, nothing happens.
@ -317,8 +360,71 @@ public:
@since v3.0 @since v3.0
*/ */
void performFunctionInCocosThread( const std::function<void()> &function); void performFunctionInCocosThread( const std::function<void()> &function);
/////////////////////////////////////
// Deprecated methods:
/** The scheduled method will be called every 'interval' seconds.
If paused is true, then it won't be called until it is resumed.
If 'interval' is 0, it will be called every frame, but if so, it's recommended to use 'scheduleUpdateForTarget:' instead.
If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again.
repeat let the action be repeated repeat + 1 times, use kRepeatForever to let the action run continuously
delay is the amount of time the action will wait before it'll start
@deprecated Please use 'Scheduler::schedule' instead.
@since v0.99.3, repeat and delay added in v1.1
*/
CC_DEPRECATED_ATTRIBUTE void scheduleSelector(SEL_SCHEDULE selector, Ref *target, float interval, unsigned int repeat, float delay, bool paused)
{
schedule(selector, target, interval, repeat, delay, paused);
};
/** calls scheduleSelector with kRepeatForever and a 0 delay
* @deprecated Please use 'Scheduler::schedule' instead.
*/
CC_DEPRECATED_ATTRIBUTE void scheduleSelector(SEL_SCHEDULE selector, Ref *target, float interval, bool paused)
{
schedule(selector, target, interval, paused);
};
/** Schedules the 'update' selector for a given target with a given priority.
The 'update' selector will be called every frame.
The lower the priority, the earlier it is called.
@deprecated Please use 'Scheduler::scheduleUpdate' instead.
@since v0.99.3
*/
template <class T>
CC_DEPRECATED_ATTRIBUTE void scheduleUpdateForTarget(T* target, int priority, bool paused) { scheduleUpdate(target, priority, paused); };
/** Unschedule a selector for a given target.
If you want to unschedule the "update", use unscheudleUpdateForTarget.
@deprecated Please use 'Scheduler::unschedule' instead.
@since v0.99.3
*/
CC_DEPRECATED_ATTRIBUTE void unscheduleSelector(SEL_SCHEDULE selector, Ref *target) { unschedule(selector, target); };
/** Checks whether a selector for a given taget is scheduled.
@deprecated Please use 'Scheduler::isScheduled' instead.
@since v0.99.3
*/
CC_DEPRECATED_ATTRIBUTE bool isScheduledForTarget(Ref *target, SEL_SCHEDULE selector) { return isScheduled(selector, target); };
/** Unschedules the update selector for a given target
@deprecated Please use 'Scheduler::unscheduleUpdate' instead.
@since v0.99.3
*/
CC_DEPRECATED_ATTRIBUTE void unscheduleUpdateForTarget(Ref *target) { return unscheduleUpdate(target); };
protected: protected:
/** Schedules the 'callback' function for a given target with a given priority.
The 'callback' selector will be called every frame.
The lower the priority, the earlier it is called.
@note This method is only for internal use.
@since v3.0
*/
void schedulePerFrame(const ccSchedulerFunc& callback, void *target, int priority, bool paused);
void removeHashElement(struct _hashSelectorEntry *element); void removeHashElement(struct _hashSelectorEntry *element);
void removeUpdateFromHash(struct _listEntry *entry); void removeUpdateFromHash(struct _listEntry *entry);

View File

@ -74,10 +74,8 @@ SchedulerScriptHandlerEntry* SchedulerScriptHandlerEntry::create(int handler, fl
bool SchedulerScriptHandlerEntry::init(float interval, bool paused) bool SchedulerScriptHandlerEntry::init(float interval, bool paused)
{ {
_timer = new Timer(); _timer = new TimerScriptHandler();
_timer->initWithScriptHandler(_handler, interval); _timer->initWithScriptHandler(_handler, interval);
_timer->autorelease();
_timer->retain();
_paused = paused; _paused = paused;
LUALOG("[LUA] ADD script schedule: %d, entryID: %d", _handler, _entryId); LUALOG("[LUA] ADD script schedule: %d, entryID: %d", _handler, _entryId);
return true; return true;

View File

@ -42,7 +42,7 @@ typedef struct lua_State lua_State;
NS_CC_BEGIN NS_CC_BEGIN
class Timer; class TimerScriptHandler;
class Layer; class Layer;
class MenuItem; class MenuItem;
class CallFunc; class CallFunc;
@ -108,7 +108,7 @@ public:
* @js NA * @js NA
* @lua NA * @lua NA
*/ */
cocos2d::Timer* getTimer(void) { TimerScriptHandler* getTimer(void) {
return _timer; return _timer;
} }
/** /**
@ -143,7 +143,7 @@ private:
} }
bool init(float interval, bool paused); bool init(float interval, bool paused);
cocos2d::Timer* _timer; TimerScriptHandler* _timer;
bool _paused; bool _paused;
bool _markedForDeletion; bool _markedForDeletion;
}; };

View File

@ -277,6 +277,7 @@ bool Sprite::initWithTexture(Texture2D *texture, const Rect& rect, bool rotated)
Sprite::Sprite(void) Sprite::Sprite(void)
: _shouldBeHidden(false) : _shouldBeHidden(false)
, _texture(nullptr) , _texture(nullptr)
, _insideBounds(true)
{ {
} }
@ -586,16 +587,19 @@ void Sprite::updateTransform(void)
// draw // draw
void Sprite::draw(void) void Sprite::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
if(isInsideBounds()) // Don't do calculate the culling if the transform was not updated
_insideBounds = transformUpdated ? isInsideBounds() : _insideBounds;
if(_insideBounds)
{ {
_quadCommand.init(_globalZOrder, _texture->getName(), _shaderProgram, _blendFunc, &_quad, 1, _modelViewTransform); _quadCommand.init(_globalZOrder, _texture->getName(), _shaderProgram, _blendFunc, &_quad, 1, transform);
Director::getInstance()->getRenderer()->addCommand(&_quadCommand); renderer->addCommand(&_quadCommand);
#if CC_SPRITE_DEBUG_DRAW #if CC_SPRITE_DEBUG_DRAW
_customDebugDrawCommand.init(_globalZOrder); _customDebugDrawCommand.init(_globalZOrder);
_customDebugDrawCommand.func = CC_CALLBACK_0(Sprite::drawDebugData, this); _customDebugDrawCommand.func = CC_CALLBACK_0(Sprite::drawDebugData, this);
Director::getInstance()->getRenderer()->addCommand(&_customDebugDrawCommand); renderer->addCommand(&_customDebugDrawCommand);
#endif //CC_SPRITE_DEBUG_DRAW #endif //CC_SPRITE_DEBUG_DRAW
} }
} }

View File

@ -424,7 +424,7 @@ public:
virtual void setAnchorPoint(const Point& anchor) override; virtual void setAnchorPoint(const Point& anchor) override;
virtual void ignoreAnchorPointForPosition(bool value) override; virtual void ignoreAnchorPointForPosition(bool value) override;
virtual void setVisible(bool bVisible) override; virtual void setVisible(bool bVisible) override;
virtual void draw(void) override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual void setOpacityModifyRGB(bool modify) override; virtual void setOpacityModifyRGB(bool modify) override;
virtual bool isOpacityModifyRGB(void) const override; virtual bool isOpacityModifyRGB(void) const override;
/// @} /// @}
@ -573,6 +573,8 @@ protected:
bool _flippedX; /// Whether the sprite is flipped horizontally or not bool _flippedX; /// Whether the sprite is flipped horizontally or not
bool _flippedY; /// Whether the sprite is flipped vertically or not bool _flippedY; /// Whether the sprite is flipped vertically or not
bool _insideBounds; /// whether or not the sprite was inside bounds the previous frame
private: private:
CC_DISALLOW_COPY_AND_ASSIGN(Sprite); CC_DISALLOW_COPY_AND_ASSIGN(Sprite);
}; };

View File

@ -131,7 +131,7 @@ SpriteBatchNode::~SpriteBatchNode()
// override visit // override visit
// don't call visit on it's children // don't call visit on it's children
void SpriteBatchNode::visit(void) void SpriteBatchNode::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
CC_PROFILER_START_CATEGORY(kProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit"); CC_PROFILER_START_CATEGORY(kProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");
@ -147,12 +147,20 @@ void SpriteBatchNode::visit(void)
return; return;
} }
kmGLPushMatrix();
sortAllChildren(); sortAllChildren();
transform();
draw(); bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
_modelViewTransform = transform(parentTransform);
_transformUpdated = false;
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix();
kmGLLoadMatrix(&_modelViewTransform);
draw(renderer, _modelViewTransform, dirty);
kmGLPopMatrix(); kmGLPopMatrix();
setOrderOfArrival(0); setOrderOfArrival(0);
@ -345,7 +353,7 @@ void SpriteBatchNode::reorderBatch(bool reorder)
_reorderChildDirty=reorder; _reorderChildDirty=reorder;
} }
void SpriteBatchNode::draw() void SpriteBatchNode::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
// Optimization: Fast Dispatch // Optimization: Fast Dispatch
if( _textureAtlas->getTotalQuads() == 0 ) if( _textureAtlas->getTotalQuads() == 0 )
@ -361,8 +369,8 @@ void SpriteBatchNode::draw()
_shaderProgram, _shaderProgram,
_blendFunc, _blendFunc,
_textureAtlas, _textureAtlas,
_modelViewTransform); transform);
Director::getInstance()->getRenderer()->addCommand(&_batchCommand); renderer->addCommand(&_batchCommand);
} }
void SpriteBatchNode::increaseAtlasCapacity(void) void SpriteBatchNode::increaseAtlasCapacity(void)

View File

@ -155,7 +155,7 @@ public:
*/ */
virtual const BlendFunc& getBlendFunc() const override; virtual const BlendFunc& getBlendFunc() const override;
virtual void visit() override; virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
using Node::addChild; using Node::addChild;
virtual void addChild(Node * child, int zOrder, int tag) override; virtual void addChild(Node * child, int zOrder, int tag) override;
@ -164,7 +164,7 @@ public:
virtual void removeChild(Node *child, bool cleanup) override; virtual void removeChild(Node *child, bool cleanup) override;
virtual void removeAllChildrenWithCleanup(bool cleanup) override; virtual void removeAllChildrenWithCleanup(bool cleanup) override;
virtual void sortAllChildren() override; virtual void sortAllChildren() override;
virtual void draw(void) override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual std::string getDescription() const override; virtual std::string getDescription() const override;
/** Inserts a quad at a certain index into the texture atlas. The Sprite won't be added into the children array. /** Inserts a quad at a certain index into the texture atlas. The Sprite won't be added into the children array.

View File

@ -242,7 +242,7 @@ const std::string& TextFieldTTF::getContentText()
return _inputText; return _inputText;
} }
void TextFieldTTF::draw() void TextFieldTTF::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
if (_delegate && _delegate->onDraw(this)) if (_delegate && _delegate->onDraw(this))
{ {
@ -250,14 +250,14 @@ void TextFieldTTF::draw()
} }
if (_inputText.length()) if (_inputText.length())
{ {
LabelTTF::draw(); LabelTTF::draw(renderer, transform, transformUpdated);
return; return;
} }
// draw placeholder // draw placeholder
Color3B color = getColor(); Color3B color = getColor();
setColor(_colorSpaceHolder); setColor(_colorSpaceHolder);
LabelTTF::draw(); LabelTTF::draw(renderer, transform, transformUpdated);
setColor(color); setColor(color);
} }

View File

@ -173,7 +173,7 @@ protected:
bool _secureTextEntry; bool _secureTextEntry;
protected: protected:
virtual void draw(); virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// IMEDelegate interface // IMEDelegate interface

View File

@ -240,14 +240,6 @@ void TextureAtlas::setupIndices()
for( int i=0; i < _capacity; i++) for( int i=0; i < _capacity; i++)
{ {
#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
_indices[i*6+0] = i*4+0;
_indices[i*6+1] = i*4+0;
_indices[i*6+2] = i*4+2;
_indices[i*6+3] = i*4+1;
_indices[i*6+4] = i*4+3;
_indices[i*6+5] = i*4+3;
#else
_indices[i*6+0] = i*4+0; _indices[i*6+0] = i*4+0;
_indices[i*6+1] = i*4+1; _indices[i*6+1] = i*4+1;
_indices[i*6+2] = i*4+2; _indices[i*6+2] = i*4+2;
@ -256,7 +248,6 @@ void TextureAtlas::setupIndices()
_indices[i*6+3] = i*4+3; _indices[i*6+3] = i*4+3;
_indices[i*6+4] = i*4+2; _indices[i*6+4] = i*4+2;
_indices[i*6+5] = i*4+1; _indices[i*6+5] = i*4+1;
#endif
} }
} }
@ -648,11 +639,7 @@ void TextureAtlas::drawNumberOfQuads(ssize_t numberOfQuads, ssize_t start)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
#endif #endif
#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) numberOfQuads*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])) );
#else
glDrawElements(GL_TRIANGLES, (GLsizei) numberOfQuads*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])) ); glDrawElements(GL_TRIANGLES, (GLsizei) numberOfQuads*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])) );
#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
#if CC_REBIND_INDICES_BUFFER #if CC_REBIND_INDICES_BUFFER
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@ -689,11 +676,7 @@ void TextureAtlas::drawNumberOfQuads(ssize_t numberOfQuads, ssize_t start)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
glDrawElements(GL_TRIANGLE_STRIP, (GLsizei)numberOfQuads*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])));
#else
glDrawElements(GL_TRIANGLES, (GLsizei)numberOfQuads*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0]))); glDrawElements(GL_TRIANGLES, (GLsizei)numberOfQuads*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])));
#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

View File

@ -55,6 +55,9 @@ Supported features:
* OpenGL component: V3F, C4B, T2F. * OpenGL component: V3F, C4B, T2F.
The quads are rendered using an OpenGL ES VBO. The quads are rendered using an OpenGL ES VBO.
To render the quads using an interleaved vertex array list, you should modify the ccConfig.h file To render the quads using an interleaved vertex array list, you should modify the ccConfig.h file
@warning If you want to use TextureAtlas, you'd better setup GL status before it's rendered.
Otherwise, the effect of TextureAtlas will be affected by the GL status of other nodes.
*/ */
class CC_DLL TextureAtlas : public Ref class CC_DLL TextureAtlas : public Ref
{ {

View File

@ -123,7 +123,7 @@ void TextureCache::addImageAsync(const std::string &path, std::function<void(Tex
if (0 == _asyncRefCount) if (0 == _asyncRefCount)
{ {
Director::getInstance()->getScheduler()->schedule(CC_CALLBACK_1(TextureCache::addImageAsyncCallBack, this), this, schedule_selector_to_key(schedule_selector(TextureCache::addImageAsyncCallBack)), 0, false); Director::getInstance()->getScheduler()->schedule(schedule_selector(TextureCache::addImageAsyncCallBack), this, 0, false);
} }
++_asyncRefCount; ++_asyncRefCount;
@ -277,7 +277,7 @@ void TextureCache::addImageAsyncCallBack(float dt)
--_asyncRefCount; --_asyncRefCount;
if (0 == _asyncRefCount) if (0 == _asyncRefCount)
{ {
Director::getInstance()->getScheduler()->unschedule(this, schedule_selector_to_key(schedule_selector(TextureCache::addImageAsyncCallBack))); Director::getInstance()->getScheduler()->unschedule(schedule_selector(TextureCache::addImageAsyncCallBack), this);
} }
} }
} }

View File

@ -97,36 +97,33 @@ void TransitionScene::sceneOrder()
_isInSceneOnTop = true; _isInSceneOnTop = true;
} }
void TransitionScene::draw() void TransitionScene::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
Scene::draw(); Scene::draw(renderer, transform, transformUpdated);
if( _isInSceneOnTop ) { if( _isInSceneOnTop ) {
_outScene->visit(); _outScene->visit(renderer, transform, transformUpdated);
_inScene->visit(); _inScene->visit(renderer, transform, transformUpdated);
} else { } else {
_inScene->visit(); _inScene->visit(renderer, transform, transformUpdated);
_outScene->visit(); _outScene->visit(renderer, transform, transformUpdated);
} }
} }
void TransitionScene::finish() void TransitionScene::finish()
{ {
kmMat4 identity;
kmMat4Identity(&identity);
// clean up // clean up
_inScene->setVisible(true); _inScene->setVisible(true);
_inScene->setPosition(Point(0,0)); _inScene->setPosition(Point(0,0));
_inScene->setScale(1.0f); _inScene->setScale(1.0f);
_inScene->setRotation(0.0f); _inScene->setRotation(0.0f);
_inScene->setAdditionalTransform(identity); _inScene->setAdditionalTransform(nullptr);
_outScene->setVisible(false); _outScene->setVisible(false);
_outScene->setPosition(Point(0,0)); _outScene->setPosition(Point(0,0));
_outScene->setScale(1.0f); _outScene->setScale(1.0f);
_outScene->setRotation(0.0f); _outScene->setRotation(0.0f);
_outScene->setAdditionalTransform(identity); _outScene->setAdditionalTransform(nullptr);
//[self schedule:@selector(setNewScene:) interval:0]; //[self schedule:@selector(setNewScene:) interval:0];
this->schedule(schedule_selector(TransitionScene::setNewScene), 0); this->schedule(schedule_selector(TransitionScene::setNewScene), 0);
@ -1258,7 +1255,7 @@ TransitionCrossFade* TransitionCrossFade::create(float t, Scene* scene)
return nullptr; return nullptr;
} }
void TransitionCrossFade::draw() void TransitionCrossFade::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
// override draw since both scenes (textures) are rendered in 1 scene // override draw since both scenes (textures) are rendered in 1 scene
} }
@ -1407,19 +1404,19 @@ void TransitionTurnOffTiles::onExit()
TransitionScene::onExit(); TransitionScene::onExit();
} }
void TransitionTurnOffTiles::draw() void TransitionTurnOffTiles::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
Scene::draw(); Scene::draw(renderer, transform, transformUpdated);
if( _isInSceneOnTop ) if( _isInSceneOnTop )
{ {
_outSceneProxy->visit(); _outSceneProxy->visit(renderer, transform, transformUpdated);
_inScene->visit(); _inScene->visit(renderer, transform, transformUpdated);
} }
else else
{ {
_inScene->visit(); _inScene->visit(renderer, transform, transformUpdated);
_outSceneProxy->visit(); _outSceneProxy->visit(renderer, transform, transformUpdated);
} }
} }
@ -1487,10 +1484,10 @@ void TransitionSplitCols::switchTargetToInscene()
_gridProxy->setTarget(_inScene); _gridProxy->setTarget(_inScene);
} }
void TransitionSplitCols::draw() void TransitionSplitCols::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
Scene::draw(); Scene::draw(renderer, transform, transformUpdated);
_gridProxy->visit(); _gridProxy->visit(renderer, transform, transformUpdated);
} }
void TransitionSplitCols::onExit() void TransitionSplitCols::onExit()
@ -1603,19 +1600,19 @@ void TransitionFadeTR::onExit()
TransitionScene::onExit(); TransitionScene::onExit();
} }
void TransitionFadeTR::draw() void TransitionFadeTR::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
Scene::draw(); Scene::draw(renderer, transform, transformUpdated);
if( _isInSceneOnTop ) if( _isInSceneOnTop )
{ {
_outSceneProxy->visit(); _outSceneProxy->visit(renderer, transform, transformUpdated);
_inScene->visit(); _inScene->visit(renderer, transform, transformUpdated);
} }
else else
{ {
_inScene->visit(); _inScene->visit(renderer, transform, transformUpdated);
_outSceneProxy->visit(); _outSceneProxy->visit(renderer, transform, transformUpdated);
} }
} }

View File

@ -91,7 +91,7 @@ public:
// //
// Overrides // Overrides
// //
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual void onEnter() override; virtual void onEnter() override;
virtual void onExit() override; virtual void onExit() override;
virtual void cleanup() override; virtual void cleanup() override;
@ -609,7 +609,7 @@ public :
* @js NA * @js NA
* @lua NA * @lua NA
*/ */
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
/** /**
* @js NA * @js NA
* @lua NA * @lua NA
@ -647,7 +647,7 @@ public :
virtual void onEnter() override; virtual void onEnter() override;
virtual void onExit() override; virtual void onExit() override;
virtual ActionInterval * easeActionWithAction(ActionInterval * action) override; virtual ActionInterval * easeActionWithAction(ActionInterval * action) override;
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
protected: protected:
TransitionTurnOffTiles(); TransitionTurnOffTiles();
@ -680,7 +680,7 @@ public:
virtual void onEnter() override; virtual void onEnter() override;
virtual ActionInterval * easeActionWithAction(ActionInterval * action) override; virtual ActionInterval * easeActionWithAction(ActionInterval * action) override;
virtual void onExit() override; virtual void onExit() override;
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
protected: protected:
TransitionSplitCols(); TransitionSplitCols();
virtual ~TransitionSplitCols(); virtual ~TransitionSplitCols();
@ -731,7 +731,7 @@ public:
virtual void onEnter() override; virtual void onEnter() override;
virtual ActionInterval* easeActionWithAction(ActionInterval * action) override; virtual ActionInterval* easeActionWithAction(ActionInterval * action) override;
virtual void onExit() override; virtual void onExit() override;
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
protected: protected:
TransitionFadeTR(); TransitionFadeTR();
virtual ~TransitionFadeTR(); virtual ~TransitionFadeTR();

View File

@ -92,31 +92,31 @@ void TransitionPageTurn::onDisablePolygonOffset()
glPolygonOffset(0, 0); glPolygonOffset(0, 0);
} }
void TransitionPageTurn::draw() void TransitionPageTurn::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
Scene::draw(); Scene::draw(renderer, transform, transformUpdated);
if( _isInSceneOnTop ) { if( _isInSceneOnTop ) {
_outSceneProxy->visit(); _outSceneProxy->visit(renderer, transform, transformUpdated);
_enableOffsetCmd.init(_globalZOrder); _enableOffsetCmd.init(_globalZOrder);
_enableOffsetCmd.func = CC_CALLBACK_0(TransitionPageTurn::onEnablePolygonOffset, this); _enableOffsetCmd.func = CC_CALLBACK_0(TransitionPageTurn::onEnablePolygonOffset, this);
Director::getInstance()->getRenderer()->addCommand(&_enableOffsetCmd); renderer->addCommand(&_enableOffsetCmd);
_inSceneProxy->visit(); _inSceneProxy->visit(renderer, transform, transformUpdated);
_disableOffsetCmd.init(_globalZOrder); _disableOffsetCmd.init(_globalZOrder);
_disableOffsetCmd.func = CC_CALLBACK_0(TransitionPageTurn::onDisablePolygonOffset, this); _disableOffsetCmd.func = CC_CALLBACK_0(TransitionPageTurn::onDisablePolygonOffset, this);
Director::getInstance()->getRenderer()->addCommand(&_disableOffsetCmd); renderer->addCommand(&_disableOffsetCmd);
} else { } else {
_inSceneProxy->visit(); _inSceneProxy->visit(renderer, transform, transformUpdated);
_enableOffsetCmd.init(_globalZOrder); _enableOffsetCmd.init(_globalZOrder);
_enableOffsetCmd.func = CC_CALLBACK_0(TransitionPageTurn::onEnablePolygonOffset, this); _enableOffsetCmd.func = CC_CALLBACK_0(TransitionPageTurn::onEnablePolygonOffset, this);
Director::getInstance()->getRenderer()->addCommand(&_enableOffsetCmd); renderer->addCommand(&_enableOffsetCmd);
_outSceneProxy->visit(); _outSceneProxy->visit(renderer, transform, transformUpdated);
_disableOffsetCmd.init(_globalZOrder); _disableOffsetCmd.init(_globalZOrder);
_disableOffsetCmd.func = CC_CALLBACK_0(TransitionPageTurn::onDisablePolygonOffset, this); _disableOffsetCmd.func = CC_CALLBACK_0(TransitionPageTurn::onDisablePolygonOffset, this);
Director::getInstance()->getRenderer()->addCommand(&_disableOffsetCmd); renderer->addCommand(&_disableOffsetCmd);
} }
} }

View File

@ -72,7 +72,7 @@ public:
// //
// Overrides // Overrides
// //
virtual void draw() override; virtual void draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
/** /**
* Creates a base transition with duration and incoming scene. * Creates a base transition with duration and incoming scene.

View File

@ -161,17 +161,6 @@ Only valid for cocos2d-mac. Not supported on cocos2d-ios.
#define CC_SPRITEBATCHNODE_RENDER_SUBPIXEL 1 #define CC_SPRITEBATCHNODE_RENDER_SUBPIXEL 1
#endif #endif
/** @def CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
Use GL_TRIANGLE_STRIP instead of GL_TRIANGLES when rendering the texture atlas.
It seems it is the recommend way, but it is much slower, so, enable it at your own risk
To enable set it to a value different than 0. Disabled by default.
*/
#ifndef CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
#define CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP 0
#endif
/** @def CC_TEXTURE_ATLAS_USE_VAO /** @def CC_TEXTURE_ATLAS_USE_VAO
By default, TextureAtlas (used by many cocos2d classes) will use VAO (Vertex Array Objects). By default, TextureAtlas (used by many cocos2d classes) will use VAO (Vertex Array Objects).
Apple recommends its usage but they might consume a lot of memory, specially if you use many of them. Apple recommends its usage but they might consume a lot of memory, specially if you use many of them.

View File

@ -154,11 +154,11 @@ void ActionObject::play()
} }
if (_loop) if (_loop)
{ {
_pScheduler->scheduleSelector(schedule_selector(ActionObject::simulationActionUpdate), this, 0.0f , kRepeatForever, 0.0f, false); _pScheduler->schedule(schedule_selector(ActionObject::simulationActionUpdate), this, 0.0f , kRepeatForever, 0.0f, false);
} }
else else
{ {
_pScheduler->scheduleSelector(schedule_selector(ActionObject::simulationActionUpdate), this, 0.0f, false); _pScheduler->schedule(schedule_selector(ActionObject::simulationActionUpdate), this, 0.0f, false);
} }
} }
@ -178,7 +178,7 @@ void ActionObject::stop()
{ {
e->stopAction(); e->stopAction();
} }
_pScheduler->unscheduleSelector(schedule_selector(ActionObject::simulationActionUpdate), this); _pScheduler->unschedule(schedule_selector(ActionObject::simulationActionUpdate), this);
_bPause = false; _bPause = false;
} }

View File

@ -29,7 +29,6 @@ THE SOFTWARE.
#include "cocostudio/CCDatas.h" #include "cocostudio/CCDatas.h"
#include "cocostudio/CCSkin.h" #include "cocostudio/CCSkin.h"
#include "renderer/CCQuadCommand.h"
#include "renderer/CCRenderer.h" #include "renderer/CCRenderer.h"
#include "renderer/CCGroupCommand.h" #include "renderer/CCGroupCommand.h"
#include "CCShaderCache.h" #include "CCShaderCache.h"
@ -378,7 +377,7 @@ void Armature::update(float dt)
_armatureTransformDirty = false; _armatureTransformDirty = false;
} }
void Armature::draw() void Armature::draw(cocos2d::Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
if (_parentBone == nullptr && _batchNode == nullptr) if (_parentBone == nullptr && _batchNode == nullptr)
{ {
@ -408,17 +407,17 @@ void Armature::draw()
{ {
skin->setBlendFunc(bone->getBlendFunc()); skin->setBlendFunc(bone->getBlendFunc());
} }
skin->draw(); skin->draw(renderer, transform, transformUpdated);
} }
break; break;
case CS_DISPLAY_ARMATURE: case CS_DISPLAY_ARMATURE:
{ {
node->draw(); node->draw(renderer, transform, transformUpdated);
} }
break; break;
default: default:
{ {
node->visit(); node->visit(renderer, transform, transformUpdated);
CC_NODE_DRAW_SETUP(); CC_NODE_DRAW_SETUP();
} }
break; break;
@ -426,7 +425,7 @@ void Armature::draw()
} }
else if(Node *node = dynamic_cast<Node *>(object)) else if(Node *node = dynamic_cast<Node *>(object))
{ {
node->visit(); node->visit(renderer, transform, transformUpdated);
CC_NODE_DRAW_SETUP(); CC_NODE_DRAW_SETUP();
} }
} }
@ -445,18 +444,27 @@ void Armature::onExit()
} }
void Armature::visit() void Armature::visit(cocos2d::Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
// quick return if not visible. children won't be drawn. // quick return if not visible. children won't be drawn.
if (!_visible) if (!_visible)
{ {
return; return;
} }
kmGLPushMatrix();
transform(); bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
_modelViewTransform = transform(parentTransform);
_transformUpdated = false;
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix();
kmGLLoadMatrix(&_modelViewTransform);
sortAllChildren(); sortAllChildren();
draw(); draw(renderer, _modelViewTransform, dirty);
// reset for next frame // reset for next frame
_orderOfArrival = 0; _orderOfArrival = 0;

View File

@ -156,9 +156,9 @@ public:
* @js NA * @js NA
* @lua NA * @lua NA
*/ */
virtual void visit() override; virtual void visit(cocos2d::Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
virtual void draw(cocos2d::Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
virtual void update(float dt) override; virtual void update(float dt) override;
virtual void draw() override;
virtual void onEnter() override; virtual void onEnter() override;
virtual void onExit() override; virtual void onExit() override;

View File

@ -101,18 +101,27 @@ void BatchNode::removeChild(Node* child, bool cleanup)
Node::removeChild(child, cleanup); Node::removeChild(child, cleanup);
} }
void BatchNode::visit() void BatchNode::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
// quick return if not visible. children won't be drawn. // quick return if not visible. children won't be drawn.
if (!_visible) if (!_visible)
{ {
return; return;
} }
kmGLPushMatrix();
transform(); bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
_modelViewTransform = transform(parentTransform);
_transformUpdated = false;
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix();
kmGLLoadMatrix(&_modelViewTransform);
sortAllChildren(); sortAllChildren();
draw(); draw(renderer, _modelViewTransform, dirty);
// reset for next frame // reset for next frame
_orderOfArrival = 0; _orderOfArrival = 0;
@ -120,7 +129,7 @@ void BatchNode::visit()
kmGLPopMatrix(); kmGLPopMatrix();
} }
void BatchNode::draw() void BatchNode::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
if (_children.empty()) if (_children.empty())
{ {
@ -141,14 +150,14 @@ void BatchNode::draw()
pushed = true; pushed = true;
} }
armature->visit(); armature->visit(renderer, transform, transformUpdated);
} }
else else
{ {
Director::getInstance()->getRenderer()->popGroup(); renderer->popGroup();
pushed = false; pushed = false;
((Node *)object)->visit(); ((Node *)object)->visit(renderer, transform, transformUpdated);
} }
} }
} }

View File

@ -56,15 +56,8 @@ public:
virtual void addChild(cocos2d::Node *pChild, int zOrder) override; virtual void addChild(cocos2d::Node *pChild, int zOrder) override;
virtual void addChild(cocos2d::Node *pChild, int zOrder, int tag) override; virtual void addChild(cocos2d::Node *pChild, int zOrder, int tag) override;
virtual void removeChild(cocos2d::Node* child, bool cleanup) override; virtual void removeChild(cocos2d::Node* child, bool cleanup) override;
/** virtual void visit(cocos2d::Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
* @js NA virtual void draw(cocos2d::Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
* @lua NA
*/
virtual void visit() override;
/**
* @js NA
*/
void draw() override;
protected: protected:
void generateGroupCommand(); void generateGroupCommand();

View File

@ -363,7 +363,7 @@ void DataReaderHelper::addDataFromFileAsync(const std::string& imagePath, const
if (0 == _asyncRefCount) if (0 == _asyncRefCount)
{ {
Director::getInstance()->getScheduler()->scheduleSelector(schedule_selector(DataReaderHelper::addDataAsyncCallBack), this, 0, false); Director::getInstance()->getScheduler()->schedule(schedule_selector(DataReaderHelper::addDataAsyncCallBack), this, 0, false);
} }
++_asyncRefCount; ++_asyncRefCount;
@ -466,7 +466,7 @@ void DataReaderHelper::addDataAsyncCallBack(float dt)
if (0 == _asyncRefCount) if (0 == _asyncRefCount)
{ {
_asyncRefTotalCount = 0; _asyncRefTotalCount = 0;
Director::getInstance()->getScheduler()->unscheduleSelector(schedule_selector(DataReaderHelper::addDataAsyncCallBack), this); Director::getInstance()->getScheduler()->unschedule(schedule_selector(DataReaderHelper::addDataAsyncCallBack), this);
} }
} }
} }

View File

@ -93,7 +93,8 @@ void DisplayFactory::updateDisplay(Bone *bone, float dt, bool dirty)
break; break;
default: default:
{ {
display->setAdditionalTransform(bone->getNodeToArmatureTransform()); kmMat4 transform = bone->getNodeToArmatureTransform();
display->setAdditionalTransform(&transform);
} }
break; break;
} }
@ -262,6 +263,7 @@ void DisplayFactory::createParticleDisplay(Bone *bone, DecorativeDisplay *decoDi
ParticleSystem *system = ParticleSystemQuad::create(displayData->displayName.c_str()); ParticleSystem *system = ParticleSystemQuad::create(displayData->displayName.c_str());
system->removeFromParent(); system->removeFromParent();
system->cleanup();
Armature *armature = bone->getArmature(); Armature *armature = bone->getArmature();
if (armature) if (armature)

View File

@ -170,6 +170,7 @@ void DisplayManager::addDisplay(Node *display, int index)
displayData = ParticleDisplayData::create(); displayData = ParticleDisplayData::create();
display->removeFromParent(); display->removeFromParent();
display->cleanup();
Armature *armature = _bone->getArmature(); Armature *armature = _bone->getArmature();
if (armature) if (armature)

View File

@ -474,7 +474,7 @@ void WidgetPropertiesReader0250::setPropsForCheckBoxFromJsonDictionary(Widget*wi
{ {
checkBox->loadTextures(backGroundFileName_tp, backGroundSelectedFileName_tp, frontCrossFileName_tp,backGroundDisabledFileName_tp,frontCrossDisabledFileName_tp); checkBox->loadTextures(backGroundFileName_tp, backGroundSelectedFileName_tp, frontCrossFileName_tp,backGroundDisabledFileName_tp,frontCrossDisabledFileName_tp);
} }
checkBox->setSelectedState(DICTOOL->getBooleanValue_json(options, "selectedState"));
setColorPropsForWidgetFromJsonDictionary(widget,options); setColorPropsForWidgetFromJsonDictionary(widget,options);
} }
@ -1364,7 +1364,7 @@ void WidgetPropertiesReader0300::setPropsForCheckBoxFromJsonDictionary(Widget*wi
default: default:
break; break;
} }
checkBox->setSelectedState(DICTOOL->getBooleanValue_json(options, "selectedState"));
setColorPropsForWidgetFromJsonDictionary(widget,options); setColorPropsForWidgetFromJsonDictionary(widget,options);
} }

View File

@ -219,14 +219,14 @@ kmMat4 Skin::getNodeToWorldTransformAR() const
return TransformConcat( _bone->getArmature()->getNodeToWorldTransform(),displayTransform); return TransformConcat( _bone->getArmature()->getNodeToWorldTransform(),displayTransform);
} }
void Skin::draw() void Skin::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
kmMat4 mv; kmMat4 mv;
kmGLGetMatrix(KM_GL_MODELVIEW, &mv); kmGLGetMatrix(KM_GL_MODELVIEW, &mv);
//TODO implement z order //TODO implement z order
_quadCommand.init(_globalZOrder, _texture->getName(), _shaderProgram, _blendFunc, &_quad, 1, mv); _quadCommand.init(_globalZOrder, _texture->getName(), _shaderProgram, _blendFunc, &_quad, 1, mv);
Director::getInstance()->getRenderer()->addCommand(&_quadCommand); renderer->addCommand(&_quadCommand);
} }
void Skin::setBone(Bone *bone) void Skin::setBone(Bone *bone)

View File

@ -54,7 +54,7 @@ public:
kmMat4 getNodeToWorldTransform() const override; kmMat4 getNodeToWorldTransform() const override;
kmMat4 getNodeToWorldTransformAR() const; kmMat4 getNodeToWorldTransformAR() const;
virtual void draw() override; virtual void draw(cocos2d::Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
/** /**
* @js NA * @js NA

View File

@ -70,7 +70,6 @@ void Skeleton::initialize () {
setOpacityModifyRGB(true); setOpacityModifyRGB(true);
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR)); setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
scheduleUpdate();
} }
void Skeleton::setSkeletonData (spSkeletonData *skeletonData, bool isOwnsSkeletonData) { void Skeleton::setSkeletonData (spSkeletonData *skeletonData, bool isOwnsSkeletonData) {
@ -126,22 +125,16 @@ void Skeleton::update (float deltaTime) {
spSkeleton_update(skeleton, deltaTime * timeScale); spSkeleton_update(skeleton, deltaTime * timeScale);
} }
void Skeleton::draw() void Skeleton::draw(cocos2d::Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{ {
kmGLMatrixMode(KM_GL_MODELVIEW);
kmGLGetMatrix(KM_GL_MODELVIEW, &_oldTransMatrix);
_customCommand.init(_globalZOrder); _customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(Skeleton::onDraw, this); _customCommand.func = CC_CALLBACK_0(Skeleton::onDraw, this);
Director::getInstance()->getRenderer()->addCommand(&_customCommand); renderer->addCommand(&_customCommand);
} }
void Skeleton::onDraw () void Skeleton::onDraw ()
{ {
kmGLMatrixMode(KM_GL_MODELVIEW);
kmGLPushMatrix();
kmGLLoadMatrix(&_oldTransMatrix);
CC_NODE_DRAW_SETUP(); CC_NODE_DRAW_SETUP();
GL::blendFunc(blendFunc.src, blendFunc.dst); GL::blendFunc(blendFunc.src, blendFunc.dst);
@ -198,46 +191,50 @@ void Skeleton::onDraw ()
textureAtlas->removeAllQuads(); textureAtlas->removeAllQuads();
} }
if (debugSlots) { if(debugBones || debugSlots) {
// Slots. kmGLPushMatrix();
DrawPrimitives::setDrawColor4B(0, 0, 255, 255); kmGLLoadMatrix(&_modelViewTransform);
glLineWidth(1);
Point points[4]; if (debugSlots) {
V3F_C4B_T2F_Quad tmpQuad; // Slots.
for (int i = 0, n = skeleton->slotCount; i < n; i++) { DrawPrimitives::setDrawColor4B(0, 0, 255, 255);
spSlot* slot = skeleton->drawOrder[i]; glLineWidth(1);
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue; Point points[4];
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment; V3F_C4B_T2F_Quad tmpQuad;
spRegionAttachment_updateQuad(attachment, slot, &tmpQuad); for (int i = 0, n = skeleton->slotCount; i < n; i++) {
points[0] = Point(tmpQuad.bl.vertices.x, tmpQuad.bl.vertices.y); spSlot* slot = skeleton->drawOrder[i];
points[1] = Point(tmpQuad.br.vertices.x, tmpQuad.br.vertices.y); if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
points[2] = Point(tmpQuad.tr.vertices.x, tmpQuad.tr.vertices.y); spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
points[3] = Point(tmpQuad.tl.vertices.x, tmpQuad.tl.vertices.y); spRegionAttachment_updateQuad(attachment, slot, &tmpQuad);
DrawPrimitives::drawPoly(points, 4, true); points[0] = Point(tmpQuad.bl.vertices.x, tmpQuad.bl.vertices.y);
} points[1] = Point(tmpQuad.br.vertices.x, tmpQuad.br.vertices.y);
} points[2] = Point(tmpQuad.tr.vertices.x, tmpQuad.tr.vertices.y);
if (debugBones) { points[3] = Point(tmpQuad.tl.vertices.x, tmpQuad.tl.vertices.y);
// Bone lengths. DrawPrimitives::drawPoly(points, 4, true);
glLineWidth(2); }
DrawPrimitives::setDrawColor4B(255, 0, 0, 255); }
for (int i = 0, n = skeleton->boneCount; i < n; i++) { if (debugBones) {
spBone *bone = skeleton->bones[i]; // Bone lengths.
float x = bone->data->length * bone->m00 + bone->worldX; glLineWidth(2);
float y = bone->data->length * bone->m10 + bone->worldY; DrawPrimitives::setDrawColor4B(255, 0, 0, 255);
DrawPrimitives::drawLine(Point(bone->worldX, bone->worldY), Point(x, y)); for (int i = 0, n = skeleton->boneCount; i < n; i++) {
} spBone *bone = skeleton->bones[i];
// Bone origins. float x = bone->data->length * bone->m00 + bone->worldX;
DrawPrimitives::setPointSize(4); float y = bone->data->length * bone->m10 + bone->worldY;
DrawPrimitives::setDrawColor4B(0, 0, 255, 255); // Root bone is blue. DrawPrimitives::drawLine(Point(bone->worldX, bone->worldY), Point(x, y));
for (int i = 0, n = skeleton->boneCount; i < n; i++) { }
spBone *bone = skeleton->bones[i]; // Bone origins.
DrawPrimitives::drawPoint(Point(bone->worldX, bone->worldY)); DrawPrimitives::setPointSize(4);
if (i == 0) DrawPrimitives::setDrawColor4B(0, 255, 0, 255); DrawPrimitives::setDrawColor4B(0, 0, 255, 255); // Root bone is blue.
} for (int i = 0, n = skeleton->boneCount; i < n; i++) {
} spBone *bone = skeleton->bones[i];
DrawPrimitives::drawPoint(Point(bone->worldX, bone->worldY));
kmGLMatrixMode(KM_GL_MODELVIEW); if (i == 0) DrawPrimitives::setDrawColor4B(0, 255, 0, 255);
kmGLPopMatrix(); }
}
kmGLPopMatrix();
}
} }
TextureAtlas* Skeleton::getTextureAtlas (spRegionAttachment* regionAttachment) const { TextureAtlas* Skeleton::getTextureAtlas (spRegionAttachment* regionAttachment) const {
@ -275,6 +272,16 @@ Rect Skeleton::getBoundingBox () const {
return Rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY); return Rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY);
} }
void Skeleton::onEnter() {
Node::onEnter();
scheduleUpdate();
}
void Skeleton::onExit() {
Node::onExit();
unscheduleUpdate();
}
// --- Convenience methods for Skeleton_* functions. // --- Convenience methods for Skeleton_* functions.
void Skeleton::updateWorldTransform () { void Skeleton::updateWorldTransform () {

View File

@ -67,8 +67,10 @@ public:
virtual ~Skeleton (); virtual ~Skeleton ();
virtual void update (float deltaTime) override; virtual void update (float deltaTime) override;
virtual void draw() override; virtual void draw(cocos2d::Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
void onDraw(); void onDraw();
void onEnter() override;
void onExit() override;
virtual cocos2d::Rect getBoundingBox () const override; virtual cocos2d::Rect getBoundingBox () const override;
// --- Convenience methods for common Skeleton_* functions. // --- Convenience methods for common Skeleton_* functions.
@ -109,9 +111,7 @@ private:
// Util function that setting blend-function by nextRenderedTexture's premultiplied flag // Util function that setting blend-function by nextRenderedTexture's premultiplied flag
void setFittedBlendingFunc(cocos2d::TextureAtlas * nextRenderedTexture); void setFittedBlendingFunc(cocos2d::TextureAtlas * nextRenderedTexture);
cocos2d::CustomCommand _customCommand; cocos2d::CustomCommand _customCommand;
kmMat4 _oldTransMatrix;
}; };
} }

View File

@ -152,6 +152,11 @@ void Button::setScale9Enabled(bool able)
setCapInsetsDisabledRenderer(_capInsetsDisabled); setCapInsetsDisabledRenderer(_capInsetsDisabled);
setBright(_bright); setBright(_bright);
} }
bool Button::isScale9Enabled()
{
return _scale9Enabled;
}
void Button::ignoreContentAdaptWithSize(bool ignore) void Button::ignoreContentAdaptWithSize(bool ignore)
{ {
@ -326,6 +331,11 @@ void Button::setCapInsetsNormalRenderer(const Rect &capInsets)
} }
static_cast<extension::Scale9Sprite*>(_buttonNormalRenderer)->setCapInsets(capInsets); static_cast<extension::Scale9Sprite*>(_buttonNormalRenderer)->setCapInsets(capInsets);
} }
const Rect& Button::getCapInsetsNormalRenderer()
{
return _capInsetsNormal;
}
void Button::setCapInsetsPressedRenderer(const Rect &capInsets) void Button::setCapInsetsPressedRenderer(const Rect &capInsets)
{ {
@ -336,6 +346,11 @@ void Button::setCapInsetsPressedRenderer(const Rect &capInsets)
} }
static_cast<extension::Scale9Sprite*>(_buttonClickedRenderer)->setCapInsets(capInsets); static_cast<extension::Scale9Sprite*>(_buttonClickedRenderer)->setCapInsets(capInsets);
} }
const Rect& Button::getCapInsetsPressedRenderer()
{
return _capInsetsPressed;
}
void Button::setCapInsetsDisabledRenderer(const Rect &capInsets) void Button::setCapInsetsDisabledRenderer(const Rect &capInsets)
{ {
@ -346,6 +361,11 @@ void Button::setCapInsetsDisabledRenderer(const Rect &capInsets)
} }
static_cast<extension::Scale9Sprite*>(_buttonDisableRenderer)->setCapInsets(capInsets); static_cast<extension::Scale9Sprite*>(_buttonDisableRenderer)->setCapInsets(capInsets);
} }
const Rect& Button::getCapInsetsDisabledRenderer()
{
return _capInsetsDisabled;
}
void Button::onPressStateChangedToNormal() void Button::onPressStateChangedToNormal()
{ {
@ -366,8 +386,7 @@ void Button::onPressStateChangedToNormal()
else else
{ {
_buttonNormalRenderer->stopAllActions(); _buttonNormalRenderer->stopAllActions();
Action *zoomAction = ScaleTo::create(0.05f, _normalTextureScaleXInSize, _normalTextureScaleYInSize); _buttonNormalRenderer->setScale(_normalTextureScaleXInSize, _normalTextureScaleYInSize);
_buttonNormalRenderer->runAction(zoomAction);
} }
} }
@ -393,8 +412,7 @@ void Button::onPressStateChangedToPressed()
_buttonClickedRenderer->setVisible(true); _buttonClickedRenderer->setVisible(true);
_buttonDisableRenderer->setVisible(false); _buttonDisableRenderer->setVisible(false);
_buttonNormalRenderer->stopAllActions(); _buttonNormalRenderer->stopAllActions();
Action *zoomAction = ScaleTo::create(0.05f, _pressedTextureScaleXInSize + 0.1f, _pressedTextureScaleYInSize + 0.1f); _buttonNormalRenderer->setScale(_normalTextureScaleXInSize + 0.1f, _normalTextureScaleYInSize + 0.1f);
_buttonNormalRenderer->runAction(zoomAction);
} }
} }

View File

@ -107,6 +107,8 @@ public:
*/ */
void setCapInsetsNormalRenderer(const Rect &capInsets); void setCapInsetsNormalRenderer(const Rect &capInsets);
const Rect& getCapInsetsNormalRenderer();
/** /**
* Sets capinsets for button, if button is using scale9 renderer. * Sets capinsets for button, if button is using scale9 renderer.
* *
@ -114,6 +116,8 @@ public:
*/ */
void setCapInsetsPressedRenderer(const Rect &capInsets); void setCapInsetsPressedRenderer(const Rect &capInsets);
const Rect& getCapInsetsPressedRenderer();
/** /**
* Sets capinsets for button, if button is using scale9 renderer. * Sets capinsets for button, if button is using scale9 renderer.
* *
@ -121,6 +125,8 @@ public:
*/ */
void setCapInsetsDisabledRenderer(const Rect &capInsets); void setCapInsetsDisabledRenderer(const Rect &capInsets);
const Rect& getCapInsetsDisabledRenderer();
//override "setAnchorPoint" of widget. //override "setAnchorPoint" of widget.
virtual void setAnchorPoint(const Point &pt) override; virtual void setAnchorPoint(const Point &pt) override;
@ -131,6 +137,8 @@ public:
*/ */
virtual void setScale9Enabled(bool able); virtual void setScale9Enabled(bool able);
bool isScale9Enabled();
//override "setFlipX" of widget. //override "setFlipX" of widget.
virtual void setFlipX(bool flipX) override; virtual void setFlipX(bool flipX) override;

View File

@ -206,6 +206,11 @@ void ImageView::setScale9Enabled(bool able)
} }
setCapInsets(_capInsets); setCapInsets(_capInsets);
} }
bool ImageView::isScale9Enabled()
{
return _scale9Enabled;
}
void ImageView::ignoreContentAdaptWithSize(bool ignore) void ImageView::ignoreContentAdaptWithSize(bool ignore)
{ {
@ -226,6 +231,11 @@ void ImageView::setCapInsets(const Rect &capInsets)
STATIC_CAST_SCALE9SPRITE->setCapInsets(capInsets); STATIC_CAST_SCALE9SPRITE->setCapInsets(capInsets);
} }
const Rect& ImageView::getCapInsets()
{
return _capInsets;
}
void ImageView::setAnchorPoint(const Point &pt) void ImageView::setAnchorPoint(const Point &pt)
{ {
Widget::setAnchorPoint(pt); Widget::setAnchorPoint(pt);

View File

@ -75,6 +75,8 @@ public:
*/ */
void setScale9Enabled(bool able); void setScale9Enabled(bool able);
bool isScale9Enabled();
/** /**
* Sets capinsets for imageview, if imageview is using scale9 renderer. * Sets capinsets for imageview, if imageview is using scale9 renderer.
* *
@ -82,6 +84,8 @@ public:
*/ */
void setCapInsets(const Rect &capInsets); void setCapInsets(const Rect &capInsets);
const Rect& getCapInsets();
//override "setFlipX" method of widget. //override "setFlipX" method of widget.
virtual void setFlipX(bool flipX) override; virtual void setFlipX(bool flipX) override;

View File

@ -67,6 +67,7 @@ _scissorRectDirty(false),
_clippingRect(Rect::ZERO), _clippingRect(Rect::ZERO),
_clippingParent(nullptr), _clippingParent(nullptr),
_doLayoutDirty(true), _doLayoutDirty(true),
_clippingRectDirty(true),
_currentStencilEnabled(GL_FALSE), _currentStencilEnabled(GL_FALSE),
_currentStencilWriteMask(~0), _currentStencilWriteMask(~0),
_currentStencilFunc(GL_ALWAYS), _currentStencilFunc(GL_ALWAYS),
@ -95,6 +96,8 @@ void Layout::onEnter()
{ {
_clippingStencil->onEnter(); _clippingStencil->onEnter();
} }
_doLayoutDirty = true;
_clippingRectDirty = true;
} }
void Layout::onExit() void Layout::onExit()
@ -150,6 +153,23 @@ void Layout::addChild(Node *child, int zOrder, int tag)
Widget::addChild(child, zOrder, tag); Widget::addChild(child, zOrder, tag);
_doLayoutDirty = true; _doLayoutDirty = true;
} }
void Layout::removeChild(Node *child, bool cleanup)
{
Widget::removeChild(child, cleanup);
_doLayoutDirty = true;
}
void Layout::removeAllChildren()
{
Widget::removeAllChildren();
}
void Layout::removeAllChildrenWithCleanup(bool cleanup)
{
Widget::removeAllChildrenWithCleanup(cleanup);
_doLayoutDirty = true;
}
bool Layout::isClippingEnabled() bool Layout::isClippingEnabled()
{ {
@ -167,7 +187,7 @@ bool Layout::hitTest(const Point &pt)
return false; return false;
} }
void Layout::visit() void Layout::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
if (!_enabled) if (!_enabled)
{ {
@ -178,10 +198,10 @@ void Layout::visit()
switch (_clippingType) switch (_clippingType)
{ {
case LAYOUT_CLIPPING_STENCIL: case LAYOUT_CLIPPING_STENCIL:
stencilClippingVisit(); stencilClippingVisit(renderer, parentTransform, parentTransformUpdated);
break; break;
case LAYOUT_CLIPPING_SCISSOR: case LAYOUT_CLIPPING_SCISSOR:
scissorClippingVisit(); scissorClippingVisit(renderer, parentTransform, parentTransformUpdated);
break; break;
default: default:
break; break;
@ -189,7 +209,7 @@ void Layout::visit()
} }
else else
{ {
Node::visit(); Node::visit(renderer, parentTransform, parentTransformUpdated);
} }
} }
@ -199,17 +219,24 @@ void Layout::sortAllChildren()
doLayout(); doLayout();
} }
void Layout::stencilClippingVisit() void Layout::stencilClippingVisit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
if(!_visible) if(!_visible)
return; return;
bool dirty = parentTransformUpdated || _transformUpdated;
if(dirty)
_modelViewTransform = transform(parentTransform);
_transformUpdated = false;
// IMPORTANT:
// To ease the migration to v3.0, we still support the kmGL stack,
// but it is deprecated and your code should not rely on it
kmGLPushMatrix(); kmGLPushMatrix();
transform(); kmGLLoadMatrix(&_modelViewTransform);
//Add group command //Add group command
Renderer* renderer = Director::getInstance()->getRenderer();
_groupCommand.init(_globalZOrder); _groupCommand.init(_globalZOrder);
renderer->addCommand(&_groupCommand); renderer->addCommand(&_groupCommand);
@ -219,7 +246,7 @@ void Layout::stencilClippingVisit()
_beforeVisitCmdStencil.func = CC_CALLBACK_0(Layout::onBeforeVisitStencil, this); _beforeVisitCmdStencil.func = CC_CALLBACK_0(Layout::onBeforeVisitStencil, this);
renderer->addCommand(&_beforeVisitCmdStencil); renderer->addCommand(&_beforeVisitCmdStencil);
_clippingStencil->visit(); _clippingStencil->visit(renderer, _modelViewTransform, dirty);
_afterDrawStencilCmd.init(_globalZOrder); _afterDrawStencilCmd.init(_globalZOrder);
_afterDrawStencilCmd.func = CC_CALLBACK_0(Layout::onAfterDrawStencil, this); _afterDrawStencilCmd.func = CC_CALLBACK_0(Layout::onAfterDrawStencil, this);
@ -236,19 +263,19 @@ void Layout::stencilClippingVisit()
auto node = _children.at(i); auto node = _children.at(i);
if ( node && node->getLocalZOrder() < 0 ) if ( node && node->getLocalZOrder() < 0 )
node->visit(); node->visit(renderer, _modelViewTransform, dirty);
else else
break; break;
} }
// self draw // self draw
this->draw(); this->draw(renderer, _modelViewTransform, dirty);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(); (*it)->visit(renderer, _modelViewTransform, dirty);
} }
else else
{ {
this->draw(); this->draw(renderer, _modelViewTransform, dirty);
} }
_afterVisitCmdStencil.init(_globalZOrder); _afterVisitCmdStencil.init(_globalZOrder);
@ -333,15 +360,13 @@ void Layout::onAfterVisitScissor()
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
} }
void Layout::scissorClippingVisit() void Layout::scissorClippingVisit(Renderer *renderer, const kmMat4& parentTransform, bool parentTransformUpdated)
{ {
Renderer* renderer = Director::getInstance()->getRenderer();
_beforeVisitCmdScissor.init(_globalZOrder); _beforeVisitCmdScissor.init(_globalZOrder);
_beforeVisitCmdScissor.func = CC_CALLBACK_0(Layout::onBeforeVisitScissor, this); _beforeVisitCmdScissor.func = CC_CALLBACK_0(Layout::onBeforeVisitScissor, this);
renderer->addCommand(&_beforeVisitCmdScissor); renderer->addCommand(&_beforeVisitCmdScissor);
Node::visit(); Node::visit(renderer, parentTransform, parentTransformUpdated);
_afterVisitCmdScissor.init(_globalZOrder); _afterVisitCmdScissor.init(_globalZOrder);
_afterVisitCmdScissor.func = CC_CALLBACK_0(Layout::onAfterVisitScissor, this); _afterVisitCmdScissor.func = CC_CALLBACK_0(Layout::onAfterVisitScissor, this);
@ -405,6 +430,11 @@ void Layout::setClippingType(LayoutClippingType type)
setClippingEnabled(clippingEnabled); setClippingEnabled(clippingEnabled);
} }
LayoutClippingType Layout::getClippingType()
{
return _clippingType;
}
void Layout::setStencilClippingSize(const Size &size) void Layout::setStencilClippingSize(const Size &size)
{ {
if (_clippingEnabled && _clippingType == LAYOUT_CLIPPING_STENCIL) if (_clippingEnabled && _clippingType == LAYOUT_CLIPPING_STENCIL)
@ -422,79 +452,83 @@ void Layout::setStencilClippingSize(const Size &size)
const Rect& Layout::getClippingRect() const Rect& Layout::getClippingRect()
{ {
Point worldPos = convertToWorldSpace(Point::ZERO); if (_clippingRectDirty)
AffineTransform t = getNodeToWorldAffineTransform();
float scissorWidth = _size.width*t.a;
float scissorHeight = _size.height*t.d;
Rect parentClippingRect;
Layout* parent = this;
bool firstClippingParentFounded = false;
while (parent)
{ {
parent = dynamic_cast<Layout*>(parent->getParent()); Point worldPos = convertToWorldSpace(Point::ZERO);
if(parent) AffineTransform t = getNodeToWorldAffineTransform();
float scissorWidth = _size.width*t.a;
float scissorHeight = _size.height*t.d;
Rect parentClippingRect;
Layout* parent = this;
bool firstClippingParentFounded = false;
while (parent)
{ {
if (parent->isClippingEnabled()) parent = dynamic_cast<Layout*>(parent->getParent());
if(parent)
{ {
if (!firstClippingParentFounded) if (parent->isClippingEnabled())
{ {
_clippingParent = parent; if (!firstClippingParentFounded)
firstClippingParentFounded = true; {
break; _clippingParent = parent;
firstClippingParentFounded = true;
break;
}
} }
} }
} }
}
if (_clippingParent)
{
parentClippingRect = _clippingParent->getClippingRect();
float finalX = worldPos.x - (scissorWidth * _anchorPoint.x);
float finalY = worldPos.y - (scissorHeight * _anchorPoint.y);
float finalWidth = scissorWidth;
float finalHeight = scissorHeight;
float leftOffset = worldPos.x - parentClippingRect.origin.x; if (_clippingParent)
if (leftOffset < 0.0f)
{ {
finalX = parentClippingRect.origin.x; parentClippingRect = _clippingParent->getClippingRect();
finalWidth += leftOffset; float finalX = worldPos.x - (scissorWidth * _anchorPoint.x);
float finalY = worldPos.y - (scissorHeight * _anchorPoint.y);
float finalWidth = scissorWidth;
float finalHeight = scissorHeight;
float leftOffset = worldPos.x - parentClippingRect.origin.x;
if (leftOffset < 0.0f)
{
finalX = parentClippingRect.origin.x;
finalWidth += leftOffset;
}
float rightOffset = (worldPos.x + scissorWidth) - (parentClippingRect.origin.x + parentClippingRect.size.width);
if (rightOffset > 0.0f)
{
finalWidth -= rightOffset;
}
float topOffset = (worldPos.y + scissorHeight) - (parentClippingRect.origin.y + parentClippingRect.size.height);
if (topOffset > 0.0f)
{
finalHeight -= topOffset;
}
float bottomOffset = worldPos.y - parentClippingRect.origin.y;
if (bottomOffset < 0.0f)
{
finalY = parentClippingRect.origin.x;
finalHeight += bottomOffset;
}
if (finalWidth < 0.0f)
{
finalWidth = 0.0f;
}
if (finalHeight < 0.0f)
{
finalHeight = 0.0f;
}
_clippingRect.origin.x = finalX;
_clippingRect.origin.y = finalY;
_clippingRect.size.width = finalWidth;
_clippingRect.size.height = finalHeight;
} }
float rightOffset = (worldPos.x + scissorWidth) - (parentClippingRect.origin.x + parentClippingRect.size.width); else
if (rightOffset > 0.0f)
{ {
finalWidth -= rightOffset; _clippingRect.origin.x = worldPos.x - (scissorWidth * _anchorPoint.x);
_clippingRect.origin.y = worldPos.y - (scissorHeight * _anchorPoint.y);
_clippingRect.size.width = scissorWidth;
_clippingRect.size.height = scissorHeight;
} }
float topOffset = (worldPos.y + scissorHeight) - (parentClippingRect.origin.y + parentClippingRect.size.height); _clippingRectDirty = false;
if (topOffset > 0.0f)
{
finalHeight -= topOffset;
}
float bottomOffset = worldPos.y - parentClippingRect.origin.y;
if (bottomOffset < 0.0f)
{
finalY = parentClippingRect.origin.x;
finalHeight += bottomOffset;
}
if (finalWidth < 0.0f)
{
finalWidth = 0.0f;
}
if (finalHeight < 0.0f)
{
finalHeight = 0.0f;
}
_clippingRect.origin.x = finalX;
_clippingRect.origin.y = finalY;
_clippingRect.size.width = finalWidth;
_clippingRect.size.height = finalHeight;
}
else
{
_clippingRect.origin.x = worldPos.x - (scissorWidth * _anchorPoint.x);
_clippingRect.origin.y = worldPos.y - (scissorHeight * _anchorPoint.y);
_clippingRect.size.width = scissorWidth;
_clippingRect.size.height = scissorHeight;
} }
return _clippingRect; return _clippingRect;
} }
@ -505,6 +539,7 @@ void Layout::onSizeChanged()
setContentSize(_size); setContentSize(_size);
setStencilClippingSize(_size); setStencilClippingSize(_size);
_doLayoutDirty = true; _doLayoutDirty = true;
_clippingRectDirty = true;
if (_backGroundImage) if (_backGroundImage)
{ {
_backGroundImage->setPosition(Point(_size.width/2.0f, _size.height/2.0f)); _backGroundImage->setPosition(Point(_size.width/2.0f, _size.height/2.0f));
@ -612,6 +647,11 @@ void Layout::setBackGroundImageCapInsets(const Rect &capInsets)
static_cast<extension::Scale9Sprite*>(_backGroundImage)->setCapInsets(capInsets); static_cast<extension::Scale9Sprite*>(_backGroundImage)->setCapInsets(capInsets);
} }
} }
const Rect& Layout::getBackGroundImageCapInsets()
{
return _backGroundImageCapInsets;
}
void Layout::supplyTheLayoutParameterLackToChild(Widget *child) void Layout::supplyTheLayoutParameterLackToChild(Widget *child)
{ {
@ -739,6 +779,11 @@ void Layout::setBackGroundColorType(LayoutBackGroundColorType type)
break; break;
} }
} }
LayoutBackGroundColorType Layout::getBackGroundColorType()
{
return _colorType;
}
void Layout::setBackGroundColor(const Color3B &color) void Layout::setBackGroundColor(const Color3B &color)
{ {
@ -748,6 +793,11 @@ void Layout::setBackGroundColor(const Color3B &color)
_colorRender->setColor(color); _colorRender->setColor(color);
} }
} }
const Color3B& Layout::getBackGroundColor()
{
return _cColor;
}
void Layout::setBackGroundColor(const Color3B &startColor, const Color3B &endColor) void Layout::setBackGroundColor(const Color3B &startColor, const Color3B &endColor)
{ {
@ -762,6 +812,16 @@ void Layout::setBackGroundColor(const Color3B &startColor, const Color3B &endCol
_gradientRender->setEndColor(endColor); _gradientRender->setEndColor(endColor);
} }
} }
const Color3B& Layout::getBackGroundStartColor()
{
return _gStartColor;
}
const Color3B& Layout::getBackGroundEndColor()
{
return _gEndColor;
}
void Layout::setBackGroundColorOpacity(int opacity) void Layout::setBackGroundColorOpacity(int opacity)
{ {
@ -780,6 +840,11 @@ void Layout::setBackGroundColorOpacity(int opacity)
break; break;
} }
} }
int Layout::getBackGroundColorOpacity()
{
return _cOpacity;
}
void Layout::setBackGroundColorVector(const Point &vector) void Layout::setBackGroundColorVector(const Point &vector)
{ {
@ -789,6 +854,11 @@ void Layout::setBackGroundColorVector(const Point &vector)
_gradientRender->setVector(vector); _gradientRender->setVector(vector);
} }
} }
const Point& Layout::getBackGroundColorVector()
{
return _alongVector;
}
const Size& Layout::getBackGroundImageTextureSize() const const Size& Layout::getBackGroundImageTextureSize() const
{ {
@ -1192,128 +1262,50 @@ void Layout::doLayout()
case RELATIVE_LOCATION_ABOVE_LEFTALIGN: case RELATIVE_LOCATION_ABOVE_LEFTALIGN:
finalPosY += mg.bottom; finalPosY += mg.bottom;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_CENTER_HORIZONTAL
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_LEFT
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_NONE
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_RIGHT)
{
finalPosY += relativeWidgetMargin.top;
}
finalPosX += mg.left; finalPosX += mg.left;
break; break;
case RELATIVE_LOCATION_ABOVE_RIGHTALIGN: case RELATIVE_LOCATION_ABOVE_RIGHTALIGN:
finalPosY += mg.bottom; finalPosY += mg.bottom;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_CENTER_HORIZONTAL
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_LEFT
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_NONE
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_RIGHT)
{
finalPosY += relativeWidgetMargin.top;
}
finalPosX -= mg.right; finalPosX -= mg.right;
break; break;
case RELATIVE_LOCATION_ABOVE_CENTER: case RELATIVE_LOCATION_ABOVE_CENTER:
finalPosY += mg.bottom; finalPosY += mg.bottom;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_CENTER_HORIZONTAL
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_LEFT
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_NONE
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_RIGHT)
{
finalPosY += relativeWidgetMargin.top;
}
break; break;
case RELATIVE_LOCATION_LEFT_OF_TOPALIGN: case RELATIVE_LOCATION_LEFT_OF_TOPALIGN:
finalPosX -= mg.right; finalPosX -= mg.right;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_LEFT
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_NONE
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_LEFT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_LEFT_CENTER_VERTICAL)
{
finalPosX -= relativeWidgetMargin.left;
}
finalPosY -= mg.top; finalPosY -= mg.top;
break; break;
case RELATIVE_LOCATION_LEFT_OF_BOTTOMALIGN: case RELATIVE_LOCATION_LEFT_OF_BOTTOMALIGN:
finalPosX -= mg.right; finalPosX -= mg.right;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_LEFT
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_NONE
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_LEFT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_LEFT_CENTER_VERTICAL)
{
finalPosX -= relativeWidgetMargin.left;
}
finalPosY += mg.bottom; finalPosY += mg.bottom;
break; break;
case RELATIVE_LOCATION_LEFT_OF_CENTER: case RELATIVE_LOCATION_LEFT_OF_CENTER:
finalPosX -= mg.right; finalPosX -= mg.right;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_LEFT
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_NONE
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_LEFT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_LEFT_CENTER_VERTICAL)
{
finalPosX -= relativeWidgetMargin.left;
}
break; break;
case RELATIVE_LOCATION_RIGHT_OF_TOPALIGN: case RELATIVE_LOCATION_RIGHT_OF_TOPALIGN:
finalPosX += mg.left; finalPosX += mg.left;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_RIGHT
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_RIGHT_CENTER_VERTICAL)
{
finalPosX += relativeWidgetMargin.right;
}
finalPosY -= mg.top; finalPosY -= mg.top;
break; break;
case RELATIVE_LOCATION_RIGHT_OF_BOTTOMALIGN: case RELATIVE_LOCATION_RIGHT_OF_BOTTOMALIGN:
finalPosX += mg.left; finalPosX += mg.left;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_RIGHT
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_RIGHT_CENTER_VERTICAL)
{
finalPosX += relativeWidgetMargin.right;
}
finalPosY += mg.bottom; finalPosY += mg.bottom;
break; break;
case RELATIVE_LOCATION_RIGHT_OF_CENTER: case RELATIVE_LOCATION_RIGHT_OF_CENTER:
finalPosX += mg.left; finalPosX += mg.left;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_TOP_RIGHT
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_RIGHT_CENTER_VERTICAL)
{
finalPosX += relativeWidgetMargin.right;
}
break; break;
case RELATIVE_LOCATION_BELOW_LEFTALIGN: case RELATIVE_LOCATION_BELOW_LEFTALIGN:
finalPosY -= mg.top; finalPosY -= mg.top;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_LEFT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL)
{
finalPosY -= relativeWidgetMargin.bottom;
}
finalPosX += mg.left; finalPosX += mg.left;
break; break;
case RELATIVE_LOCATION_BELOW_RIGHTALIGN: case RELATIVE_LOCATION_BELOW_RIGHTALIGN:
finalPosY -= mg.top; finalPosY -= mg.top;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_LEFT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL)
{
finalPosY -= relativeWidgetMargin.bottom;
}
finalPosX -= mg.right; finalPosX -= mg.right;
break; break;
case RELATIVE_LOCATION_BELOW_CENTER: case RELATIVE_LOCATION_BELOW_CENTER:
finalPosY -= mg.top; finalPosY -= mg.top;
if (relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_LEFT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM
&& relativeWidgetLP->getAlign() != RELATIVE_ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL)
{
finalPosY -= relativeWidgetMargin.bottom;
}
break; break;
default: default:
break; break;

View File

@ -91,6 +91,8 @@ public:
*/ */
void setBackGroundImageCapInsets(const Rect& capInsets); void setBackGroundImageCapInsets(const Rect& capInsets);
const Rect& getBackGroundImageCapInsets();
/** /**
* Sets Color Type for layout. * Sets Color Type for layout.
* *
@ -98,6 +100,8 @@ public:
*/ */
void setBackGroundColorType(LayoutBackGroundColorType type); void setBackGroundColorType(LayoutBackGroundColorType type);
LayoutBackGroundColorType getBackGroundColorType();
/** /**
* Sets background iamge use scale9 renderer. * Sets background iamge use scale9 renderer.
* *
@ -105,6 +109,8 @@ public:
*/ */
void setBackGroundImageScale9Enabled(bool enabled); void setBackGroundImageScale9Enabled(bool enabled);
bool isBackGroundImageScale9Enabled();
/** /**
* Sets background color for layout, if color type is LAYOUT_COLOR_SOLID * Sets background color for layout, if color type is LAYOUT_COLOR_SOLID
* *
@ -112,6 +118,8 @@ public:
*/ */
void setBackGroundColor(const Color3B &color); void setBackGroundColor(const Color3B &color);
const Color3B& getBackGroundColor();
/** /**
* Sets background color for layout, if color type is LAYOUT_COLOR_GRADIENT * Sets background color for layout, if color type is LAYOUT_COLOR_GRADIENT
* *
@ -121,6 +129,10 @@ public:
*/ */
void setBackGroundColor(const Color3B &startColor, const Color3B &endColor); void setBackGroundColor(const Color3B &startColor, const Color3B &endColor);
const Color3B& getBackGroundStartColor();
const Color3B& getBackGroundEndColor();
/** /**
* Sets background opacity layout. * Sets background opacity layout.
* *
@ -128,6 +140,8 @@ public:
*/ */
void setBackGroundColorOpacity(int opacity); void setBackGroundColorOpacity(int opacity);
int getBackGroundColorOpacity();
/** /**
* Sets background color vector for layout, if color type is LAYOUT_COLOR_GRADIENT * Sets background color vector for layout, if color type is LAYOUT_COLOR_GRADIENT
* *
@ -135,6 +149,8 @@ public:
*/ */
void setBackGroundColorVector(const Point &vector); void setBackGroundColorVector(const Point &vector);
const Point& getBackGroundColorVector();
/** /**
* Remove the background image of layout. * Remove the background image of layout.
*/ */
@ -158,6 +174,8 @@ public:
void setClippingType(LayoutClippingType type); void setClippingType(LayoutClippingType type);
LayoutClippingType getClippingType();
/** /**
* Gets if layout is clipping enabled. * Gets if layout is clipping enabled.
* *
@ -209,8 +227,25 @@ public:
*/ */
virtual void addChild(Node* child, int zOrder, int tag) override; virtual void addChild(Node* child, int zOrder, int tag) override;
virtual void visit(); virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
virtual void removeChild(Node* child, bool cleanup = true) override;
/**
* Removes all children from the container with a cleanup.
*
* @see `removeAllChildrenWithCleanup(bool)`
*/
virtual void removeAllChildren() override;
/**
* Removes all children from the container, and do a cleanup to all running actions depending on the cleanup parameter.
*
* @param cleanup true if all running actions on all children nodes should be cleanup, false oterwise.
* @js removeAllChildren
* @lua removeAllChildren
*/
virtual void removeAllChildrenWithCleanup(bool cleanup) override;
virtual void sortAllChildren() override; virtual void sortAllChildren() override;
void requestDoLayout(); void requestDoLayout();
@ -234,8 +269,8 @@ protected:
virtual void copySpecialProperties(Widget* model) override; virtual void copySpecialProperties(Widget* model) override;
virtual void copyClonedWidgetChildren(Widget* model) override; virtual void copyClonedWidgetChildren(Widget* model) override;
void stencilClippingVisit(); void stencilClippingVisit(Renderer *renderer, const kmMat4& parentTransform, bool parentTransformUpdated);
void scissorClippingVisit(); void scissorClippingVisit(Renderer *renderer, const kmMat4& parentTransform, bool parentTransformUpdated);
void setStencilClippingSize(const Size& size); void setStencilClippingSize(const Size& size);
const Rect& getClippingRect(); const Rect& getClippingRect();
@ -273,6 +308,7 @@ protected:
Rect _clippingRect; Rect _clippingRect;
Layout* _clippingParent; Layout* _clippingParent;
bool _doLayoutDirty; bool _doLayoutDirty;
bool _clippingRectDirty;
//clipping //clipping

View File

@ -1,26 +1,26 @@
/**************************************************************************** /****************************************************************************
Copyright (c) 2013-2014 Chukong Technologies Inc. Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
#include "gui/UILayoutParameter.h" #include "gui/UILayoutParameter.h"
#include "gui/UILayout.h" #include "gui/UILayout.h"
@ -56,6 +56,23 @@ LayoutParameterType LayoutParameter::getLayoutType() const
{ {
return _layoutParameterType; return _layoutParameterType;
} }
LayoutParameter* LayoutParameter::clone()
{
LayoutParameter* clonedParameter = createCloneInstance();
clonedParameter->copyProperties(this);
return clonedParameter;
}
LayoutParameter* LayoutParameter::createCloneInstance()
{
return LayoutParameter::create();
}
void LayoutParameter::copyProperties(LayoutParameter *model)
{
_margin = model->_margin;
}
LinearLayoutParameter* LinearLayoutParameter::create() LinearLayoutParameter* LinearLayoutParameter::create()
{ {
@ -78,6 +95,21 @@ LinearGravity LinearLayoutParameter::getGravity() const
{ {
return _linearGravity; return _linearGravity;
} }
LayoutParameter* LinearLayoutParameter::createCloneInstance()
{
return LinearLayoutParameter::create();
}
void LinearLayoutParameter::copyProperties(LayoutParameter *model)
{
LayoutParameter::copyProperties(model);
LinearLayoutParameter* parameter = dynamic_cast<LinearLayoutParameter*>(model);
if (parameter)
{
setGravity(parameter->_linearGravity);
}
}
RelativeLayoutParameter* RelativeLayoutParameter::create() RelativeLayoutParameter* RelativeLayoutParameter::create()
{ {
@ -120,6 +152,23 @@ const char* RelativeLayoutParameter::getRelativeName() const
{ {
return _relativeLayoutName.c_str(); return _relativeLayoutName.c_str();
} }
LayoutParameter* RelativeLayoutParameter::createCloneInstance()
{
return RelativeLayoutParameter::create();
}
void RelativeLayoutParameter::copyProperties(LayoutParameter *model)
{
LayoutParameter::copyProperties(model);
RelativeLayoutParameter* parameter = dynamic_cast<RelativeLayoutParameter*>(model);
if (parameter)
{
setAlign(parameter->_relativeAlign);
setRelativeName(parameter->_relativeLayoutName.c_str());
setRelativeToWidgetName(parameter->_relativeWidgetName.c_str());
}
}
} }

View File

@ -1,26 +1,26 @@
/**************************************************************************** /****************************************************************************
Copyright (c) 2013-2014 Chukong Technologies Inc. Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
#ifndef __LAYOUTPARMETER_H__ #ifndef __LAYOUTPARMETER_H__
#define __LAYOUTPARMETER_H__ #define __LAYOUTPARMETER_H__
@ -86,6 +86,10 @@ public:
* @return LayoutParameterType * @return LayoutParameterType
*/ */
LayoutParameterType getLayoutType() const; LayoutParameterType getLayoutType() const;
LayoutParameter* clone();
virtual LayoutParameter* createCloneInstance();
virtual void copyProperties(LayoutParameter* model);
protected: protected:
Margin _margin; Margin _margin;
LayoutParameterType _layoutParameterType; LayoutParameterType _layoutParameterType;
@ -130,6 +134,8 @@ public:
* @return LinearGravity * @return LinearGravity
*/ */
LinearGravity getGravity() const; LinearGravity getGravity() const;
virtual LayoutParameter* createCloneInstance() override;
virtual void copyProperties(LayoutParameter* model) override;
protected: protected:
LinearGravity _linearGravity; LinearGravity _linearGravity;
}; };
@ -202,6 +208,9 @@ public:
* @return name * @return name
*/ */
const char* getRelativeName() const; const char* getRelativeName() const;
virtual LayoutParameter* createCloneInstance() override;
virtual void copyProperties(LayoutParameter* model) override;
protected: protected:
RelativeAlign _relativeAlign; RelativeAlign _relativeAlign;
std::string _relativeWidgetName; std::string _relativeWidgetName;

View File

@ -347,6 +347,11 @@ void ListView::setItemsMargin(float margin)
_itemsMargin = margin; _itemsMargin = margin;
_refreshViewDirty = true; _refreshViewDirty = true;
} }
float ListView::getItemsMargin()
{
return _itemsMargin;
}
void ListView::setDirection(SCROLLVIEW_DIR dir) void ListView::setDirection(SCROLLVIEW_DIR dir)
{ {

View File

@ -150,6 +150,8 @@ public:
*/ */
void setItemsMargin(float margin); void setItemsMargin(float margin);
float getItemsMargin();
virtual void sortAllChildren() override; virtual void sortAllChildren() override;
ssize_t getCurSelectedIndex() const; ssize_t getCurSelectedIndex() const;

View File

@ -196,6 +196,11 @@ void LoadingBar::setScale9Enabled(bool enabled)
setCapInsets(_capInsets); setCapInsets(_capInsets);
} }
bool LoadingBar::isScale9Enabled()
{
return _scale9Enabled;
}
void LoadingBar::setCapInsets(const Rect &capInsets) void LoadingBar::setCapInsets(const Rect &capInsets)
{ {
_capInsets = capInsets; _capInsets = capInsets;
@ -206,6 +211,11 @@ void LoadingBar::setCapInsets(const Rect &capInsets)
static_cast<extension::Scale9Sprite*>(_barRenderer)->setCapInsets(capInsets); static_cast<extension::Scale9Sprite*>(_barRenderer)->setCapInsets(capInsets);
} }
const Rect& LoadingBar::getCapInsets()
{
return _capInsets;
}
void LoadingBar::setPercent(int percent) void LoadingBar::setPercent(int percent)
{ {
if ( percent < 0 || percent > 100) if ( percent < 0 || percent > 100)
@ -334,6 +344,7 @@ void LoadingBar::copySpecialProperties(Widget *widget)
loadTexture(loadingBar->_textureFile.c_str(), loadingBar->_renderBarTexType); loadTexture(loadingBar->_textureFile.c_str(), loadingBar->_renderBarTexType);
setCapInsets(loadingBar->_capInsets); setCapInsets(loadingBar->_capInsets);
setPercent(loadingBar->_percent); setPercent(loadingBar->_percent);
setDirection(loadingBar->_barType);
} }
} }

View File

@ -106,6 +106,8 @@ public:
*/ */
void setScale9Enabled(bool enabled); void setScale9Enabled(bool enabled);
bool isScale9Enabled();
/** /**
* Sets capinsets for loadingbar, if loadingbar is using scale9 renderer. * Sets capinsets for loadingbar, if loadingbar is using scale9 renderer.
* *
@ -113,6 +115,8 @@ public:
*/ */
void setCapInsets(const Rect &capInsets); void setCapInsets(const Rect &capInsets);
const Rect& getCapInsets();
//override "ignoreContentAdaptWithSize" method of widget. //override "ignoreContentAdaptWithSize" method of widget.
virtual void ignoreContentAdaptWithSize(bool ignore) override; virtual void ignoreContentAdaptWithSize(bool ignore) override;

View File

@ -273,6 +273,46 @@ Widget* ScrollView::getChildByName(const char *name)
{ {
return _innerContainer->getChildByName(name); return _innerContainer->getChildByName(name);
} }
void ScrollView::addNode(Node* node)
{
Layout::addNode(node);
}
void ScrollView::addNode(Node * node, int zOrder)
{
Layout::addNode(node, zOrder);
}
void ScrollView::addNode(Node* node, int zOrder, int tag)
{
_innerContainer->addNode(node, zOrder, tag);
}
Node* ScrollView::getNodeByTag(int tag)
{
return _innerContainer->getNodeByTag(tag);
}
Vector<Node*>& ScrollView::getNodes()
{
return _innerContainer->getNodes();
}
void ScrollView::removeNode(Node* node)
{
_innerContainer->removeNode(node);
}
void ScrollView::removeNodeByTag(int tag)
{
_innerContainer->removeNodeByTag(tag);
}
void ScrollView::removeAllNodes()
{
_innerContainer->removeAllNodes();
}
void ScrollView::moveChildren(float offsetX, float offsetY) void ScrollView::moveChildren(float offsetX, float offsetY)
{ {

View File

@ -274,6 +274,22 @@ public:
virtual Widget* getChildByName(const char* name) override; virtual Widget* getChildByName(const char* name) override;
virtual void addNode(Node* node) override;
virtual void addNode(Node * node, int zOrder) override;
virtual void addNode(Node* node, int zOrder, int tag) override;
virtual Node * getNodeByTag(int tag) override;
virtual Vector<Node*>& getNodes() override;
virtual void removeNode(Node* node) override;
virtual void removeNodeByTag(int tag) override;
virtual void removeAllNodes() override;
virtual bool onTouchBegan(Touch *touch, Event *unusedEvent) override; virtual bool onTouchBegan(Touch *touch, Event *unusedEvent) override;
virtual void onTouchMoved(Touch *touch, Event *unusedEvent) override; virtual void onTouchMoved(Touch *touch, Event *unusedEvent) override;
virtual void onTouchEnded(Touch *touch, Event *unusedEvent) override; virtual void onTouchEnded(Touch *touch, Event *unusedEvent) override;

View File

@ -216,6 +216,11 @@ void Slider::setScale9Enabled(bool able)
setCapInsetsBarRenderer(_capInsetsBarRenderer); setCapInsetsBarRenderer(_capInsetsBarRenderer);
setCapInsetProgressBarRebderer(_capInsetsProgressBarRenderer); setCapInsetProgressBarRebderer(_capInsetsProgressBarRenderer);
} }
bool Slider::isScale9Enabled()
{
return _scale9Enabled;
}
void Slider::ignoreContentAdaptWithSize(bool ignore) void Slider::ignoreContentAdaptWithSize(bool ignore)
{ {
@ -241,6 +246,11 @@ void Slider::setCapInsetsBarRenderer(const Rect &capInsets)
} }
static_cast<extension::Scale9Sprite*>(_barRenderer)->setCapInsets(capInsets); static_cast<extension::Scale9Sprite*>(_barRenderer)->setCapInsets(capInsets);
} }
const Rect& Slider::getCapInsetsBarRenderer()
{
return _capInsetsBarRenderer;
}
void Slider::setCapInsetProgressBarRebderer(const Rect &capInsets) void Slider::setCapInsetProgressBarRebderer(const Rect &capInsets)
{ {
@ -251,6 +261,11 @@ void Slider::setCapInsetProgressBarRebderer(const Rect &capInsets)
} }
static_cast<extension::Scale9Sprite*>(_progressBarRenderer)->setCapInsets(capInsets); static_cast<extension::Scale9Sprite*>(_progressBarRenderer)->setCapInsets(capInsets);
} }
const Rect& Slider::getCapInsetsProgressBarRebderer()
{
return _capInsetsProgressBarRenderer;
}
void Slider::loadSlidBallTextures(const char* normal,const char* pressed,const char* disabled,TextureResType texType) void Slider::loadSlidBallTextures(const char* normal,const char* pressed,const char* disabled,TextureResType texType)
{ {

View File

@ -77,6 +77,8 @@ public:
*/ */
void setScale9Enabled(bool able); void setScale9Enabled(bool able);
bool isScale9Enabled();
/** /**
* Sets capinsets for slider, if slider is using scale9 renderer. * Sets capinsets for slider, if slider is using scale9 renderer.
* *
@ -91,6 +93,8 @@ public:
*/ */
void setCapInsetsBarRenderer(const Rect &capInsets); void setCapInsetsBarRenderer(const Rect &capInsets);
const Rect& getCapInsetsBarRenderer();
/** /**
* Sets capinsets for slider, if slider is using scale9 renderer. * Sets capinsets for slider, if slider is using scale9 renderer.
* *
@ -98,6 +102,8 @@ public:
*/ */
void setCapInsetProgressBarRebderer(const Rect &capInsets); void setCapInsetProgressBarRebderer(const Rect &capInsets);
const Rect& getCapInsetsProgressBarRebderer();
/** /**
* Load textures for slider ball. * Load textures for slider ball.
* *

View File

@ -98,6 +98,11 @@ void Text::setFontSize(int size)
_labelRenderer->setFontSize(size); _labelRenderer->setFontSize(size);
labelScaleChangedWithSize(); labelScaleChangedWithSize();
} }
int Text::getFontSize()
{
return _fontSize;
}
void Text::setFontName(const std::string& name) void Text::setFontName(const std::string& name)
{ {
@ -105,36 +110,53 @@ void Text::setFontName(const std::string& name)
_labelRenderer->setFontName(name); _labelRenderer->setFontName(name);
labelScaleChangedWithSize(); labelScaleChangedWithSize();
} }
const std::string& Text::getFontName()
{
return _fontName;
}
void Text::setTextAreaSize(const Size &size) void Text::setTextAreaSize(const Size &size)
{ {
_labelRenderer->setDimensions(size); _labelRenderer->setDimensions(size);
labelScaleChangedWithSize(); labelScaleChangedWithSize();
} }
const Size& Text::getTextAreaSize()
{
return _labelRenderer->getDimensions();
}
void Text::setTextHorizontalAlignment(TextHAlignment alignment) void Text::setTextHorizontalAlignment(TextHAlignment alignment)
{ {
_labelRenderer->setHorizontalAlignment(alignment); _labelRenderer->setHorizontalAlignment(alignment);
labelScaleChangedWithSize(); labelScaleChangedWithSize();
} }
TextHAlignment Text::getTextHorizontalAlignment()
{
return _labelRenderer->getHorizontalAlignment();
}
void Text::setTextVerticalAlignment(TextVAlignment alignment) void Text::setTextVerticalAlignment(TextVAlignment alignment)
{ {
_labelRenderer->setVerticalAlignment(alignment); _labelRenderer->setVerticalAlignment(alignment);
labelScaleChangedWithSize(); labelScaleChangedWithSize();
} }
TextVAlignment Text::getTextVerticalAlignment()
{
return _labelRenderer->getVerticalAlignment();
}
void Text::setTouchScaleChangeEnabled(bool enable) void Text::setTouchScaleChangeEnabled(bool enable)
{ {
_touchScaleChangeEnabled = enable; _touchScaleChangeEnabled = enable;
_normalScaleValueX = getScaleX();
_normalScaleValueY = getScaleY();
} }
void Text::setScale(float fScale) void Text::setScale(float fScale)
{ {
Widget::setScale(fScale); Widget::setScale(fScale);
_normalScaleValueX = _normalScaleValueY = fScale;
} }
void Text::setScaleX(float fScaleX) void Text::setScaleX(float fScaleX)
@ -158,7 +180,7 @@ void Text::onPressStateChangedToNormal()
{ {
return; return;
} }
clickScale(_normalScaleValueX, _normalScaleValueY); _labelRenderer->setScale(_normalScaleValueX, _normalScaleValueY);
} }
void Text::onPressStateChangedToPressed() void Text::onPressStateChangedToPressed()
@ -167,9 +189,7 @@ void Text::onPressStateChangedToPressed()
{ {
return; return;
} }
_normalScaleValueX = getScaleX(); _labelRenderer->setScale(_normalScaleValueX + _onSelectedScaleOffset, _normalScaleValueY + _onSelectedScaleOffset);
_normalScaleValueY = getScaleY();
clickScale(_normalScaleValueX + _onSelectedScaleOffset, _normalScaleValueY + _onSelectedScaleOffset);
} }
void Text::onPressStateChangedToDisabled() void Text::onPressStateChangedToDisabled()
@ -177,12 +197,6 @@ void Text::onPressStateChangedToDisabled()
} }
void Text::clickScale(float scaleX, float scaleY)
{
setScaleX(scaleX);
setScaleY(scaleY);
}
void Text::setFlipX(bool flipX) void Text::setFlipX(bool flipX)
{ {
_labelRenderer->setFlippedX(flipX); _labelRenderer->setFlippedX(flipX);
@ -231,6 +245,7 @@ void Text::labelScaleChangedWithSize()
{ {
_labelRenderer->setScale(1.0f); _labelRenderer->setScale(1.0f);
_size = _labelRenderer->getContentSize(); _size = _labelRenderer->getContentSize();
_normalScaleValueX = _normalScaleValueY = 1.0f;
} }
else else
{ {
@ -244,6 +259,8 @@ void Text::labelScaleChangedWithSize()
float scaleY = _size.height / textureSize.height; float scaleY = _size.height / textureSize.height;
_labelRenderer->setScaleX(scaleX); _labelRenderer->setScaleX(scaleX);
_labelRenderer->setScaleY(scaleY); _labelRenderer->setScaleY(scaleY);
_normalScaleValueX = scaleX;
_normalScaleValueY = scaleY;
} }
} }

View File

@ -81,6 +81,8 @@ public:
*/ */
void setFontSize(int size); void setFontSize(int size);
int getFontSize();
/** /**
* Sets the font name of label. * Sets the font name of label.
* *
@ -88,6 +90,8 @@ public:
*/ */
void setFontName(const std::string& name); void setFontName(const std::string& name);
const std::string& getFontName();
/** /**
* Sets the touch scale enabled of label. * Sets the touch scale enabled of label.
* *
@ -157,8 +161,17 @@ public:
virtual std::string getDescription() const override; virtual std::string getDescription() const override;
void setTextAreaSize(const Size &size); void setTextAreaSize(const Size &size);
const Size& getTextAreaSize();
void setTextHorizontalAlignment(TextHAlignment alignment); void setTextHorizontalAlignment(TextHAlignment alignment);
void setTextVerticalAlignment(TextVAlignment alignment);
TextHAlignment getTextHorizontalAlignment();
void setTextVerticalAlignment(TextVAlignment alignment);
TextVAlignment getTextVerticalAlignment();
protected: protected:
virtual bool init() override; virtual bool init() override;
virtual void initRenderer() override; virtual void initRenderer() override;
@ -166,7 +179,6 @@ protected:
virtual void onPressStateChangedToPressed() override; virtual void onPressStateChangedToPressed() override;
virtual void onPressStateChangedToDisabled() override; virtual void onPressStateChangedToDisabled() override;
virtual void onSizeChanged() override; virtual void onSizeChanged() override;
void clickScale(float scaleX, float scaleY);
void labelScaleChangedWithSize(); void labelScaleChangedWithSize();
virtual Widget* createCloneInstance() override; virtual Widget* createCloneInstance() override;
virtual void copySpecialProperties(Widget* model) override; virtual void copySpecialProperties(Widget* model) override;

View File

@ -319,6 +319,11 @@ void TextField::setTouchSize(const Size &size)
_touchWidth = size.width; _touchWidth = size.width;
_touchHeight = size.height; _touchHeight = size.height;
} }
Size TextField::getTouchSize()
{
return Size(_touchWidth, _touchHeight);
}
void TextField::setText(const std::string& text) void TextField::setText(const std::string& text)
{ {
@ -345,18 +350,33 @@ void TextField::setPlaceHolder(const std::string& value)
_textFieldRenderer->setPlaceHolder(value); _textFieldRenderer->setPlaceHolder(value);
textfieldRendererScaleChangedWithSize(); textfieldRendererScaleChangedWithSize();
} }
const std::string& TextField::getPlaceHolder()
{
return _textFieldRenderer->getPlaceHolder();
}
void TextField::setFontSize(int size) void TextField::setFontSize(int size)
{ {
_textFieldRenderer->setFontSize(size); _textFieldRenderer->setFontSize(size);
textfieldRendererScaleChangedWithSize(); textfieldRendererScaleChangedWithSize();
} }
int TextField::getFontSize()
{
return _textFieldRenderer->getFontSize();
}
void TextField::setFontName(const std::string& name) void TextField::setFontName(const std::string& name)
{ {
_textFieldRenderer->setFontName(name); _textFieldRenderer->setFontName(name);
textfieldRendererScaleChangedWithSize(); textfieldRendererScaleChangedWithSize();
} }
const std::string& TextField::getFontName()
{
return _textFieldRenderer->getFontName();
}
void TextField::didNotSelectSelf() void TextField::didNotSelectSelf()
{ {
@ -414,6 +434,11 @@ void TextField::setPasswordStyleText(const char *styleText)
_passwordStyleText = styleText; _passwordStyleText = styleText;
} }
const char* TextField::getPasswordStyleText()
{
return _passwordStyleText.c_str();
}
void TextField::update(float dt) void TextField::update(float dt)
{ {

View File

@ -108,10 +108,14 @@ public:
virtual ~TextField(); virtual ~TextField();
static TextField* create(); static TextField* create();
void setTouchSize(const Size &size); void setTouchSize(const Size &size);
Size getTouchSize();
void setText(const std::string& text); void setText(const std::string& text);
void setPlaceHolder(const std::string& value); void setPlaceHolder(const std::string& value);
const std::string& getPlaceHolder();
void setFontSize(int size); void setFontSize(int size);
int getFontSize();
void setFontName(const std::string& name); void setFontName(const std::string& name);
const std::string& getFontName();
virtual void didNotSelectSelf(); virtual void didNotSelectSelf();
const std::string& getStringValue(); const std::string& getStringValue();
virtual bool onTouchBegan(Touch *touch, Event *unusedEvent) override; virtual bool onTouchBegan(Touch *touch, Event *unusedEvent) override;
@ -122,6 +126,7 @@ public:
void setPasswordEnabled(bool enable); void setPasswordEnabled(bool enable);
bool isPasswordEnabled(); bool isPasswordEnabled();
void setPasswordStyleText(const char* styleText); void setPasswordStyleText(const char* styleText);
const char* getPasswordStyleText();
virtual void update(float dt) override; virtual void update(float dt) override;
bool getAttachWithIME(); bool getAttachWithIME();
void setAttachWithIME(bool attach); void setAttachWithIME(bool attach);

View File

@ -108,11 +108,11 @@ void Widget::onExit()
Node::onExit(); Node::onExit();
} }
void Widget::visit() void Widget::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
if (_enabled) if (_enabled)
{ {
Node::visit(); Node::visit(renderer, parentTransform, parentTransformUpdated);
} }
} }
@ -1065,6 +1065,11 @@ void Widget::copyProperties(Widget *widget)
setOpacity(widget->getOpacity()); setOpacity(widget->getOpacity());
setCascadeOpacityEnabled(widget->isCascadeOpacityEnabled()); setCascadeOpacityEnabled(widget->isCascadeOpacityEnabled());
setCascadeColorEnabled(widget->isCascadeColorEnabled()); setCascadeColorEnabled(widget->isCascadeColorEnabled());
Map<int, LayoutParameter*>& layoutParameterDic = widget->_layoutParameterDictionary;
for (auto iter = layoutParameterDic.begin(); iter != layoutParameterDic.end(); ++iter)
{
setLayoutParameter(iter->second->clone());
}
onSizeChanged(); onSizeChanged();
} }

View File

@ -331,7 +331,7 @@ public:
virtual void removeAllNodes(); virtual void removeAllNodes();
virtual void visit() override; virtual void visit(cocos2d::Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
/** /**
* Sets the touch event target/selector of the menu item * Sets the touch event target/selector of the menu item

View File

@ -481,7 +481,10 @@ void HttpClient::send(HttpRequest* request)
void HttpClient::dispatchResponseCallbacks() void HttpClient::dispatchResponseCallbacks()
{ {
// log("CCHttpClient::dispatchResponseCallbacks is running"); // log("CCHttpClient::dispatchResponseCallbacks is running");
//occurs when cocos thread fires but the network thread has already quited
if (nullptr == s_responseQueue) {
return;
}
HttpResponse* response = nullptr; HttpResponse* response = nullptr;
s_responseQueueMutex.lock(); s_responseQueueMutex.lock();

View File

@ -359,7 +359,7 @@ void SIOClientImpl::onOpen(WebSocket* ws)
iter->second->onOpen(); iter->second->onOpen();
} }
Director::getInstance()->getScheduler()->scheduleSelector(schedule_selector(SIOClientImpl::heartbeat), this, (_heartbeat * .9f), false); Director::getInstance()->getScheduler()->schedule(schedule_selector(SIOClientImpl::heartbeat), this, (_heartbeat * .9f), false);
log("SIOClientImpl::onOpen socket connected!"); log("SIOClientImpl::onOpen socket connected!");
} }

View File

@ -122,7 +122,7 @@ WsThreadHelper::WsThreadHelper()
_UIWsMessageQueue = new std::list<WsMessage*>(); _UIWsMessageQueue = new std::list<WsMessage*>();
_subThreadWsMessageQueue = new std::list<WsMessage*>(); _subThreadWsMessageQueue = new std::list<WsMessage*>();
Director::getInstance()->getScheduler()->scheduleUpdateForTarget(this, 0, false); Director::getInstance()->getScheduler()->scheduleUpdate(this, 0, false);
} }
WsThreadHelper::~WsThreadHelper() WsThreadHelper::~WsThreadHelper()
@ -699,6 +699,8 @@ void WebSocket::onUIThreadReceiveMessage(WsMessage* msg)
break; break;
case WS_MSG_TO_UITHREAD_CLOSE: case WS_MSG_TO_UITHREAD_CLOSE:
{ {
//Waiting for the subThread safety exit
_wsHelper->joinSubThread();
_delegate->onClose(this); _delegate->onClose(this);
} }
break; break;

View File

@ -75,6 +75,7 @@ PhysicsBody::PhysicsBody()
, _group(0) , _group(0)
, _positionResetTag(false) , _positionResetTag(false)
, _rotationResetTag(false) , _rotationResetTag(false)
, _rotationOffset(0)
{ {
} }
@ -347,7 +348,7 @@ void PhysicsBody::setPosition(Point position)
{ {
if (!_positionResetTag) if (!_positionResetTag)
{ {
cpBodySetPos(_info->getBody(), PhysicsHelper::point2cpv(position)); cpBodySetPos(_info->getBody(), PhysicsHelper::point2cpv(position + _positionOffset));
} }
_positionResetTag = false; _positionResetTag = false;
} }
@ -356,7 +357,7 @@ void PhysicsBody::setRotation(float rotation)
{ {
if (!_rotationResetTag) if (!_rotationResetTag)
{ {
cpBodySetAngle(_info->getBody(), -PhysicsHelper::float2cpfloat(rotation * M_PI / 180.0f)); cpBodySetAngle(_info->getBody(), -PhysicsHelper::float2cpfloat((rotation + _rotationOffset) * (M_PI / 180.0f)));
} }
_rotationResetTag = false; _rotationResetTag = false;
@ -365,12 +366,12 @@ void PhysicsBody::setRotation(float rotation)
Point PhysicsBody::getPosition() const Point PhysicsBody::getPosition() const
{ {
cpVect vec = cpBodyGetPos(_info->getBody()); cpVect vec = cpBodyGetPos(_info->getBody());
return PhysicsHelper::cpv2point(vec); return PhysicsHelper::cpv2point(vec) - _positionOffset;
} }
float PhysicsBody::getRotation() const float PhysicsBody::getRotation() const
{ {
return -PhysicsHelper::cpfloat2float(cpBodyGetAngle(_info->getBody()) / M_PI * 180.0f); return -PhysicsHelper::cpfloat2float(cpBodyGetAngle(_info->getBody()) * (180.0f / M_PI)) - _rotationOffset;
} }
PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape, bool addMassAndMoment/* = true*/) PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape, bool addMassAndMoment/* = true*/)
@ -767,27 +768,18 @@ void PhysicsBody::setResting(bool rest) const
void PhysicsBody::update(float delta) void PhysicsBody::update(float delta)
{ {
if (_node != nullptr && _dynamic && !isResting()) if (_node != nullptr)
{ {
cpVect pos = cpBodyGetPos(_info->getBody()); Node* parent = _node->getParent();
cpVect prePos = _info->getPosition();
cpVect rot = cpBodyGetRot(_info->getBody());
cpVect preRot = _info->getRotation();
// only reset the node position when body position/rotation changed. Point position = parent != nullptr ? parent->convertToNodeSpace(getPosition()) : getPosition();
if (std::abs(pos.x - prePos.x) >= 0.3f || std::abs(pos.y - prePos.y) >= 0.3f _positionResetTag = true;
|| std::abs(rot.x - preRot.x) >= 0.01f || std::abs(rot.y - preRot.y) >= 0.01f) _rotationResetTag = true;
{ _node->setPosition(position);
_positionResetTag = true; _node->setRotation(getRotation());
_rotationResetTag = true;
_node->setPosition(getPosition());
_info->setPosition(pos);
_node->setRotation(getRotation());
_info->setRotation(rot);
}
// damping compute // damping compute
if (_isDamping) if (_isDamping && _dynamic && !isResting())
{ {
_info->getBody()->v.x *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f); _info->getBody()->v.x *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f);
_info->getBody()->v.y *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f); _info->getBody()->v.y *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f);
@ -834,6 +826,36 @@ void PhysicsBody::setGroup(int group)
} }
} }
void PhysicsBody::setPositionOffset(const Point& position)
{
if (!_positionOffset.equals(position))
{
Point pos = getPosition();
_positionOffset = position;
setPosition(pos);
}
}
Point PhysicsBody::getPositionOffset() const
{
return _positionOffset;
}
void PhysicsBody::setRotationOffset(float rotation)
{
if (std::abs(_rotationOffset - rotation) > 0.5f)
{
float rot = getRotation();
_rotationOffset = rotation;
setRotation(rot);
}
}
float PhysicsBody::getRotationOffset() const
{
return _rotationOffset;
}
Point PhysicsBody::world2Local(const Point& point) Point PhysicsBody::world2Local(const Point& point)
{ {
return PhysicsHelper::cpv2point(cpBodyWorld2Local(_info->getBody(), PhysicsHelper::point2cpv(point))); return PhysicsHelper::cpv2point(cpBodyWorld2Local(_info->getBody(), PhysicsHelper::point2cpv(point)));

View File

@ -192,6 +192,15 @@ public:
/** get the body rotation. */ /** get the body rotation. */
float getRotation() const; float getRotation() const;
/** set body position offset, it's the position witch relative to node */
void setPositionOffset(const Point& position);
/** get body position offset. */
Point getPositionOffset() const;
/** set body rotation offset, it's the rotation witch relative to node */
void setRotationOffset(float rotation);
/** set the body rotation offset */
float getRotationOffset() const;
/** /**
* @brief test the body is dynamic or not. * @brief test the body is dynamic or not.
* a dynamic body will effect with gravity. * a dynamic body will effect with gravity.
@ -332,6 +341,8 @@ protected:
bool _positionResetTag; /// To avoid reset the body position when body invoke Node::setPosition(). bool _positionResetTag; /// To avoid reset the body position when body invoke Node::setPosition().
bool _rotationResetTag; /// To avoid reset the body rotation when body invoke Node::setRotation(). bool _rotationResetTag; /// To avoid reset the body rotation when body invoke Node::setRotation().
Point _positionOffset;
float _rotationOffset;
friend class PhysicsWorld; friend class PhysicsWorld;
friend class PhysicsShape; friend class PhysicsShape;

View File

@ -39,10 +39,6 @@ class PhysicsBodyInfo
public: public:
inline cpBody* getBody() const { return _body; } inline cpBody* getBody() const { return _body; }
inline void setBody(cpBody* body) { _body = body; } inline void setBody(cpBody* body) { _body = body; }
inline cpVect getPosition() const { return _position; }
inline void setPosition(cpVect& vect) { _position = vect; }
inline cpVect getRotation() const { return _rotation; }
inline void setRotation(cpVect& vect) { _rotation = vect; }
private: private:
PhysicsBodyInfo(); PhysicsBodyInfo();
@ -50,8 +46,6 @@ private:
private: private:
cpBody* _body; cpBody* _body;
cpVect _position;
cpVect _rotation;
friend class PhysicsBody; friend class PhysicsBody;
}; };

View File

@ -769,14 +769,14 @@ void Scale9Sprite::setInsetBottom(float insetBottom)
this->updateCapInset(); this->updateCapInset();
} }
void Scale9Sprite::visit() void Scale9Sprite::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
if(this->_positionsAreDirty) if(this->_positionsAreDirty)
{ {
this->updatePositions(); this->updatePositions();
this->_positionsAreDirty = false; this->_positionsAreDirty = false;
} }
Node::visit(); Node::visit(renderer, parentTransform, parentTransformUpdated);
} }
void Scale9Sprite::setColor(const Color3B& color) void Scale9Sprite::setColor(const Color3B& color)

View File

@ -261,7 +261,7 @@ public:
* @js NA * @js NA
* @lua NA * @lua NA
*/ */
virtual void visit() override; virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
virtual void setOpacityModifyRGB(bool bValue) override; virtual void setOpacityModifyRGB(bool bValue) override;
virtual bool isOpacityModifyRGB(void) const override; virtual bool isOpacityModifyRGB(void) const override;
virtual void setOpacity(GLubyte opacity) override; virtual void setOpacity(GLubyte opacity) override;

View File

@ -28,6 +28,8 @@
NS_CC_EXT_BEGIN NS_CC_EXT_BEGIN
static const float CHECK_EDITBOX_POSITION_INTERVAL = 0.1f;
EditBox::EditBox(void) EditBox::EditBox(void)
: _editBoxImpl(NULL) : _editBoxImpl(NULL)
, _delegate(NULL) , _delegate(NULL)
@ -316,9 +318,9 @@ void EditBox::setAnchorPoint(const Point& anchorPoint)
} }
} }
void EditBox::visit(void) void EditBox::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{ {
ControlButton::visit(); ControlButton::visit(renderer, parentTransform, parentTransformUpdated);
if (_editBoxImpl != NULL) if (_editBoxImpl != NULL)
{ {
_editBoxImpl->visit(); _editBoxImpl->visit();
@ -332,8 +334,19 @@ void EditBox::onEnter(void)
{ {
_editBoxImpl->onEnter(); _editBoxImpl->onEnter();
} }
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
this->schedule(schedule_selector(EditBox::updatePosition), CHECK_EDITBOX_POSITION_INTERVAL);
#endif
} }
void EditBox::updatePosition(float dt)
{
if (nullptr != _editBoxImpl) {
_editBoxImpl->updatePosition(dt);
}
}
void EditBox::onExit(void) void EditBox::onExit(void)
{ {
ControlButton::onExit(); ControlButton::onExit();

View File

@ -379,7 +379,7 @@ public:
* @js NA * @js NA
* @lua NA * @lua NA
*/ */
virtual void visit(void) override; virtual void visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated) override;
/** /**
* @js NA * @js NA
* @lua NA * @lua NA
@ -418,6 +418,7 @@ public:
void touchDownAction(Ref *sender, Control::EventType controlEvent); void touchDownAction(Ref *sender, Control::EventType controlEvent);
protected: protected:
void updatePosition(float dt);
EditBoxImpl* _editBoxImpl; EditBoxImpl* _editBoxImpl;
EditBoxDelegate* _delegate; EditBoxDelegate* _delegate;

View File

@ -69,6 +69,11 @@ public:
virtual void setVisible(bool visible) = 0; virtual void setVisible(bool visible) = 0;
virtual void setContentSize(const Size& size) = 0; virtual void setContentSize(const Size& size) = 0;
virtual void setAnchorPoint(const Point& anchorPoint) = 0; virtual void setAnchorPoint(const Point& anchorPoint) = 0;
/**
* check the editbox's position, update it when needed
*/
virtual void updatePosition(float dt){};
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View File

@ -101,6 +101,7 @@ public:
virtual void setVisible(bool visible); virtual void setVisible(bool visible);
virtual void setContentSize(const Size& size); virtual void setContentSize(const Size& size);
virtual void setAnchorPoint(const Point& anchorPoint); virtual void setAnchorPoint(const Point& anchorPoint);
virtual void updatePosition(float dt) override;
/** /**
* @js NA * @js NA
* @lua NA * @lua NA
@ -116,7 +117,6 @@ public:
virtual void closeKeyboard(); virtual void closeKeyboard();
virtual void onEndEditing(); virtual void onEndEditing();
private: private:
void initInactiveLabels(const Size& size); void initInactiveLabels(const Size& size);
void setInactiveText(const char* pText); void setInactiveText(const char* pText);

View File

@ -614,7 +614,6 @@ void EditBoxImplIOS::setAnchorPoint(const Point& anchorPoint)
void EditBoxImplIOS::visit(void) void EditBoxImplIOS::visit(void)
{ {
} }
void EditBoxImplIOS::onEnter(void) void EditBoxImplIOS::onEnter(void)
@ -626,6 +625,15 @@ void EditBoxImplIOS::onEnter(void)
} }
} }
void EditBoxImplIOS::updatePosition(float dt)
{
if (nullptr != _systemControl) {
this->adjustTextFieldPosition();
}
}
void EditBoxImplIOS::adjustTextFieldPosition() void EditBoxImplIOS::adjustTextFieldPosition()
{ {
Size contentSize = _editBox->getContentSize(); Size contentSize = _editBox->getContentSize();

Some files were not shown because too many files have changed in this diff Show More