From 09a2ceb7df6391041db212548ff161fda6e52089 Mon Sep 17 00:00:00 2001 From: 2youyou2 Date: Wed, 11 Jun 2014 11:10:07 +0800 Subject: [PATCH] add TimelineAction --- cocos/editor-support/cocostudio/CocoStudio.h | 5 + .../cocostudio/TimelineAction/CCFrame.cpp | 636 ++++++++++++++++++ .../cocostudio/TimelineAction/CCFrame.h | 330 +++++++++ .../cocostudio/TimelineAction/CCNodeCache.cpp | 368 ++++++++++ .../cocostudio/TimelineAction/CCNodeCache.h | 82 +++ .../cocostudio/TimelineAction/CCTimeLine.cpp | 255 +++++++ .../cocostudio/TimelineAction/CCTimeLine.h | 89 +++ .../TimelineAction/CCTimelineAction.cpp | 258 +++++++ .../TimelineAction/CCTimelineAction.h | 144 ++++ .../TimelineAction/CCTimelineActionCache.cpp | 373 ++++++++++ .../TimelineAction/CCTimelineActionCache.h | 89 +++ .../proj.win32/libCocosStudio.vcxproj | 21 +- .../proj.win32/libCocosStudio.vcxproj.filters | 38 +- .../TimelineActionTestScene.cpp | 225 +++++++ .../TimelineActionTestScene.h | 57 ++ .../Classes/ExtensionsTest/ExtensionsTest.cpp | 6 + tests/cpp-tests/proj.win32/cpp-tests.vcxproj | 2 + .../proj.win32/cpp-tests.vcxproj.filters | 9 + 18 files changed, 2977 insertions(+), 10 deletions(-) create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCFrame.cpp create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCFrame.h create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCNodeCache.cpp create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCNodeCache.h create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCTimeLine.cpp create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCTimeLine.h create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCTimelineAction.cpp create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCTimelineAction.h create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCTimelineActionCache.cpp create mode 100644 cocos/editor-support/cocostudio/TimelineAction/CCTimelineActionCache.h create mode 100644 tests/cpp-tests/Classes/ExtensionsTest/CocoStudioTimelineActionTest/TimelineActionTestScene.cpp create mode 100644 tests/cpp-tests/Classes/ExtensionsTest/CocoStudioTimelineActionTest/TimelineActionTestScene.h diff --git a/cocos/editor-support/cocostudio/CocoStudio.h b/cocos/editor-support/cocostudio/CocoStudio.h index 65f66fc686..5a8a2e9c9a 100644 --- a/cocos/editor-support/cocostudio/CocoStudio.h +++ b/cocos/editor-support/cocostudio/CocoStudio.h @@ -58,5 +58,10 @@ THE SOFTWARE. #include "cocostudio/CCSGUIReader.h" #include "cocostudio/CCSSceneReader.h" #include "cocostudio/TriggerBase.h" +#include "cocostudio/TimelineAction/CCFrame.h" +#include "cocostudio/TimelineAction/CCNodeCache.h" +#include "cocostudio/TimelineAction/CCTimeLine.h" +#include "cocostudio/TimelineAction/CCTimelineAction.h" +#include "cocostudio/TimelineAction/CCTimelineActionCache.h" #endif diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCFrame.cpp b/cocos/editor-support/cocostudio/TimelineAction/CCFrame.cpp new file mode 100644 index 0000000000..285a853aff --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCFrame.cpp @@ -0,0 +1,636 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#include "CCFrame.h" +#include "CCTimeLine.h" +#include "CCTimelineAction.h" + +using namespace cocos2d; + +namespace cocostudio { +namespace timeline{ + +// Frame +Frame::Frame() + : _frameIndex(0) + , _tween(false) + , _timeline(nullptr) + , _node(nullptr) +{ +} + +Frame::~Frame() +{ +} + +void Frame::cloneProperty(Frame* frame) +{ + _frameIndex = frame->getFrameIndex(); + _tween = frame->isTween(); +} + + +// VisibleFrame +VisibleFrame* VisibleFrame::create() +{ + VisibleFrame* frame = new VisibleFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +VisibleFrame::VisibleFrame() + : _visible(true) +{ +} + +void VisibleFrame::onEnter(Frame *nextFrame) +{ + _node->setVisible(_visible); +} + + +Frame* VisibleFrame::clone() +{ + VisibleFrame* frame = VisibleFrame::create(); + frame->setVisible(_visible); + + frame->cloneProperty(this); + + return frame; +} + + + +// TextureFrame +TextureFrame* TextureFrame::create() +{ + TextureFrame* frame = new TextureFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +TextureFrame::TextureFrame() + : _texture("") +{ +} + +void TextureFrame::setNode(cocos2d::CCNode* node) +{ + Frame::setNode(node); + + _sprite = dynamic_cast(node); +} + +void TextureFrame::onEnter(Frame *nextFrame) +{ + if(_sprite) + { + _sprite->setTexture(_texture.c_str()); + } +} + + +Frame* TextureFrame::clone() +{ + TextureFrame* frame = TextureFrame::create(); + frame->setTexture(_texture); + + frame->cloneProperty(this); + + return frame; +} + + + +// RotationFrame +RotationFrame* RotationFrame::create() +{ + RotationFrame* frame = new RotationFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +RotationFrame::RotationFrame() + : _rotation(0) +{ +} + +void RotationFrame::onEnter(Frame *nextFrame) +{ + if (!_tween || nextFrame == this) + { + _node->setRotation(_rotation); + } + + if(_tween) + { + _betwennRotation = static_cast(nextFrame)->_rotation - _rotation; + } +} + +void RotationFrame::apply(float percent) +{ + if (_tween && _betwennRotation != 0) + { + float rotation = _rotation + percent * _betwennRotation; + _node->setRotation(rotation); + } +} + +Frame* RotationFrame::clone() +{ + RotationFrame* frame = RotationFrame::create(); + frame->setRotation(_rotation); + + frame->cloneProperty(this); + + return frame; +} + + + +// SkewFrame +SkewFrame* SkewFrame::create() +{ + SkewFrame* frame = new SkewFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +SkewFrame::SkewFrame() + : _skewX(0) + , _skewY(0) +{ +} + +void SkewFrame::onEnter(Frame *nextFrame) +{ + if (!_tween || nextFrame == this) + { + _node->setSkewX(_skewX); + _node->setSkewY(_skewY); + } + + if(_tween) + { + _betweenSkewX = static_cast(nextFrame)->_skewX - _skewX; + _betweenSkewY = static_cast(nextFrame)->_skewY - _skewY; + } +} + +void SkewFrame::apply(float percent) +{ + if (_tween && (_betweenSkewX != 0 || _betweenSkewY != 0)) + { + float skewx = _skewX + percent * _betweenSkewX; + float skewy = _skewY + percent * _betweenSkewY; + + _node->setSkewX(skewx); + _node->setSkewY(skewy); + } +} + +Frame* SkewFrame::clone() +{ + SkewFrame* frame = SkewFrame::create(); + frame->setSkewX(_skewX); + frame->setSkewY(_skewY); + + frame->cloneProperty(this); + + return frame; +} + + + + +// RotationSkewFrame +RotationSkewFrame* RotationSkewFrame::create() +{ + RotationSkewFrame* frame = new RotationSkewFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +RotationSkewFrame::RotationSkewFrame() +{ +} + +void RotationSkewFrame::onEnter(Frame *nextFrame) +{ + if (!_tween || nextFrame == this) + { + _node->setRotationSkewX(_skewX); + _node->setRotationSkewY(_skewY); + } + + if (_tween) + { + _betweenSkewX = static_cast(nextFrame)->_skewX - _skewX; + _betweenSkewY = static_cast(nextFrame)->_skewY - _skewY; + } +} + +void RotationSkewFrame::apply(float percent) +{ + if (_tween && (_betweenSkewX != 0 || _betweenSkewY != 0)) + { + float skewx = _skewX + percent * _betweenSkewX; + float skewy = _skewY + percent * _betweenSkewY; + + _node->setRotationSkewX(skewx); + _node->setRotationSkewY(skewy); + } +} + +Frame* RotationSkewFrame::clone() +{ + RotationSkewFrame* frame = RotationSkewFrame::create(); + frame->setSkewX(_skewX); + frame->setSkewY(_skewY); + + frame->cloneProperty(this); + + return frame; +} + + +// PositionFrame +PositionFrame* PositionFrame::create() +{ + PositionFrame* frame = new PositionFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +PositionFrame::PositionFrame() + : _position(0,0) +{ +} + +void PositionFrame::onEnter(Frame *nextFrame) +{ + if (!_tween || nextFrame == this) + { + _node->setPosition(_position); + } + + if(_tween) + { + _betweenX = static_cast(nextFrame)->_position.x - _position.x; + _betweenY = static_cast(nextFrame)->_position.y - _position.y; + } +} + +void PositionFrame::apply(float percent) +{ + if (_tween && (_betweenX != 0 || _betweenY != 0)) + { + Point p; + p.x = _position.x + _betweenX * percent; + p.y = _position.y + _betweenY * percent; + + _node->setPosition(p); + } +} + +Frame* PositionFrame::clone() +{ + PositionFrame* frame = PositionFrame::create(); + frame->setPosition(_position); + + frame->cloneProperty(this); + + return frame; +} + + +// ScaleFrame +ScaleFrame* ScaleFrame::create() +{ + ScaleFrame* frame = new ScaleFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +ScaleFrame::ScaleFrame() + : _scaleX(1) + , _scaleY(1) +{ +} + +void ScaleFrame::onEnter(Frame *nextFrame) +{ + if (!_tween || nextFrame == this) + { + _node->setScaleX(_scaleX); + _node->setScaleY(_scaleY); + } + + if(_tween) + { + _betweenScaleX = static_cast(nextFrame)->_scaleX - _scaleX; + _betweenScaleY = static_cast(nextFrame)->_scaleY - _scaleY; + } +} + +void ScaleFrame::apply(float percent) +{ + if (_tween && (_betweenScaleX != 0 || _betweenScaleY != 0)) + { + float scaleX = _scaleX + _betweenScaleX * percent; + float scaleY = _scaleY + _betweenScaleY * percent; + + _node->setScaleX(scaleX); + _node->setScaleY(scaleY); + } +} + +Frame* ScaleFrame::clone() +{ + ScaleFrame* frame = ScaleFrame::create(); + frame->setScaleX(_scaleX); + frame->setScaleY(_scaleY); + + frame->cloneProperty(this); + + return frame; +} + + +// AnchorPointFrame +AnchorPointFrame* AnchorPointFrame::create() +{ + AnchorPointFrame* frame = new AnchorPointFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +AnchorPointFrame::AnchorPointFrame() + : _anchorPoint(0.5f,0.5f) +{ +} + +void AnchorPointFrame::onEnter(Frame *nextFrame) +{ + _node->setAnchorPoint(_anchorPoint); +} + + +Frame* AnchorPointFrame::clone() +{ + AnchorPointFrame* frame = AnchorPointFrame::create(); + frame->setAnchorPoint(_anchorPoint); + + frame->cloneProperty(this); + + return frame; +} + + + +// InnerActionFrame +InnerActionFrame* InnerActionFrame::create() +{ + InnerActionFrame* frame = new InnerActionFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +InnerActionFrame::InnerActionFrame() + : _innerActionType(LoopAction) + , _startFrameIndex(0) +{ +} + +void InnerActionFrame::onEnter(Frame *nextFrame) +{ +} + + +Frame* InnerActionFrame::clone() +{ + InnerActionFrame* frame = InnerActionFrame::create(); + frame->setInnerActionType(_innerActionType); + frame->setStartFrameIndex(_startFrameIndex); + + frame->cloneProperty(this); + + return frame; +} + + +// ColorFrame +ColorFrame* ColorFrame::create() +{ + ColorFrame* frame = new ColorFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +ColorFrame::ColorFrame() + : _alpha(255) + , _color(Color3B(255, 255, 255)) +{ +} + +void ColorFrame::onEnter(Frame *nextFrame) +{ + if (!_tween || nextFrame == this) + { + if(_alpha != _node->getOpacity()) + _node->setOpacity(_alpha); + + Color3B color = _node->getColor(); + if(color.r != _color.r || color.g != _color.r || color.b != _color.b) + _node->setColor(_color); + } + + if(_tween) + { + _betweenAlpha = static_cast(nextFrame)->_alpha - _alpha; + + const cocos2d::Color3B& color = static_cast(nextFrame)->_color; + _betweenRed = color.r - _color.r; + _betweenGreen = color.g - _color.g; + _betweenBlue = color.b - _color.b; + } + + _node->setCascadeColorEnabled(true); + _node->setCascadeOpacityEnabled(true); +} + +void ColorFrame::apply(float percent) +{ + if (_tween && (_betweenAlpha !=0 || _betweenRed != 0 || _betweenGreen != 0 || _betweenBlue != 0)) + { + GLubyte alpha = _alpha + _betweenAlpha * percent; + + cocos2d::Color3B color; + color.r = _color.r+ _betweenRed * percent; + color.g = _color.g+ _betweenGreen * percent; + color.b = _color.b+ _betweenBlue * percent; + + _node->setOpacity(alpha); + _node->setColor(color); + } +} + +Frame* ColorFrame::clone() +{ + ColorFrame* frame = ColorFrame::create(); + frame->setAlpha(_alpha); + frame->setColor(_color); + + frame->cloneProperty(this); + + return frame; +} + + +// EventFrame +EventFrame* EventFrame::create() +{ + EventFrame* frame = new EventFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +EventFrame::EventFrame() + : _event("") +{ +} + +void EventFrame::onEnter(Frame *nextFrame) +{ + if (_timeline) + { + _timeline->getTimelineAction()->emitFrameEvent(this); + } +} + + +Frame* EventFrame::clone() +{ + EventFrame* frame = EventFrame::create(); + frame->setEvent(_event); + + frame->cloneProperty(this); + + return frame; +} + + +// ZOrderFrame +ZOrderFrame* ZOrderFrame::create() +{ + ZOrderFrame* frame = new ZOrderFrame(); + if (frame) + { + frame->autorelease(); + return frame; + } + CC_SAFE_DELETE(frame); + return NULL; +} + +ZOrderFrame::ZOrderFrame() + : _zorder(0) +{ +} + +void ZOrderFrame::onEnter(Frame *nextFrame) +{ + if(_node) + _node->setZOrder(_zorder); +} + + +Frame* ZOrderFrame::clone() +{ + ZOrderFrame* frame = ZOrderFrame::create(); + frame->setZOrder(_zorder); + + frame->cloneProperty(this); + + return frame; +} + +} +} \ No newline at end of file diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCFrame.h b/cocos/editor-support/cocostudio/TimelineAction/CCFrame.h new file mode 100644 index 0000000000..2f32ba824e --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCFrame.h @@ -0,0 +1,330 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#ifndef __CCFRAME_H__ +#define __CCFRAME_H__ + +#include "CCTimeLine.h" + +namespace cocostudio { +namespace timeline{ + + +class Frame : public cocos2d::Object +{ +public: + + virtual void setFrameIndex(unsigned int frameIndex) { _frameIndex = frameIndex; } + virtual unsigned int getFrameIndex()const { return _frameIndex; } + + virtual void setTimeline(Timeline* timeline) { _timeline = timeline; } + virtual Timeline* getTimeline() { return _timeline; } + + virtual void setNode(cocos2d::Node* node) { _node = node; } + virtual cocos2d::Node* getTimelineNode() const { return _node; } + + virtual void setTween(bool tween) { _tween = tween; } + virtual bool isTween()const { return _tween; } + + virtual void onEnter(Frame *nextFrame) = 0; + virtual void apply(float percent) {} + + virtual Frame* clone() = 0; +protected: + Frame(); + virtual ~Frame(); + + void cloneProperty(Frame* frame); +protected: + friend class Timeline; + + unsigned int _frameIndex; + bool _tween; + + Timeline* _timeline; + cocos2d::Node* _node; +}; + + +class VisibleFrame : public Frame +{ +public: + static VisibleFrame* create(); + + VisibleFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual Frame* clone() override; + + inline void setVisible(bool visible) { _visible = visible;} + inline bool isVisible() const { return _visible; } + +protected: + bool _visible; +}; + + +class TextureFrame : public Frame +{ +public: + static TextureFrame* create(); + + TextureFrame(); + + virtual void setNode(cocos2d::CCNode* node); + + virtual void onEnter(Frame *nextFrame) override; + virtual Frame* clone() override; + + inline void setTexture(std::string texture) { _texture = texture;} + inline std::string getTexture() const { return _texture; } + +protected: + cocos2d::CCSprite* _sprite; + std::string _texture; +}; + +class RotationFrame : public Frame +{ +public: + static RotationFrame* create(); + + RotationFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual void apply(float percent) override; + virtual Frame* clone() override; + + inline void setRotation(float rotation) { _rotation = rotation; } + inline float getRotation() const { return _rotation; } + +protected: + float _rotation; + float _betwennRotation; +}; + +class SkewFrame : public Frame +{ +public: + static SkewFrame* create(); + + SkewFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual void apply(float percent) override; + virtual Frame* clone() override; + + inline void setSkewX(float skewx) { _skewX = skewx; } + inline float getSkewX() const { return _skewX; } + + inline void setSkewY(float skewy) { _skewY = skewy; } + inline float getSkewY() const { return _skewY; } + +protected: + float _skewX; + float _skewY; + float _betweenSkewX; + float _betweenSkewY; +}; + + +class RotationSkewFrame : public SkewFrame +{ +public: + static RotationSkewFrame* create(); + + RotationSkewFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual void apply(float percent) override; + virtual Frame* clone() override; +}; + + +class PositionFrame : public Frame +{ +public: + static PositionFrame* create(); + + PositionFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual void apply(float percent) override; + virtual Frame* clone() override; + + inline void setPosition(const cocos2d::Point& position) { _position = position; } + inline cocos2d::Point getPosition() const { return _position; } + + inline void setX(float x) { _position.x = x; } + inline void setY(float y) { _position.y = y; } + + inline float getX() { return _position.x; } + inline float getY() { return _position.y; } +protected: + cocos2d::Point _position; + float _betweenX; + float _betweenY; +}; + + +class ScaleFrame : public Frame +{ +public: + static ScaleFrame* create(); + + ScaleFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual void apply(float percent) override; + virtual Frame* clone() override; + + inline void setScale(float scale) { _scaleX = scale; _scaleY = scale; } + + inline void setScaleX(float scaleX) { _scaleX = scaleX; } + inline float getScaleX() const { return _scaleX; } + + inline void setScaleY(float scaleY) { _scaleY = scaleY;} + inline float getScaleY() const { return _scaleY; } + +protected: + float _scaleX; + float _scaleY; + float _betweenScaleX; + float _betweenScaleY; +}; + + +class AnchorPointFrame : public Frame +{ +public: + static AnchorPointFrame* create(); + + AnchorPointFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual Frame* clone() override; + + inline void setAnchorPoint(const cocos2d::Point& point) { _anchorPoint = point; } + inline cocos2d::Point getAnchorPoint() const { return _anchorPoint; } + +protected: + cocos2d::Point _anchorPoint; +}; + + + +enum InnerActionType +{ + LoopAction, + NoLoopAction, + SingleFrame +}; + +class InnerActionFrame : public Frame +{ +public: + static InnerActionFrame* create(); + InnerActionFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual Frame* clone() override; + + inline void setInnerActionType(InnerActionType type) { _innerActionType = type; } + inline InnerActionType getInnerActionType() const { return _innerActionType; } + + inline void setStartFrameIndex(int frameIndex) { _startFrameIndex = frameIndex; } + inline int getStartFrameIndex() const { return _startFrameIndex; } + +protected: + InnerActionType _innerActionType; + int _startFrameIndex; +}; + + +class ColorFrame : public Frame +{ +public: + static ColorFrame* create(); + ColorFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual void apply(float percent) override; + virtual Frame* clone() override; + + inline void setAlpha(GLubyte alpha) { _alpha = alpha; } + inline GLubyte getAlpha() const { return _alpha; } + + inline void setColor(const cocos2d::Color3B& color) { _color = color; } + inline cocos2d::Color3B getColor() const { return _color; } + +protected: + GLubyte _alpha; + cocos2d::Color3B _color; + + int _betweenAlpha; + int _betweenRed; + int _betweenGreen; + int _betweenBlue; +}; + + +class EventFrame : public Frame +{ +public: + static EventFrame* create(); + + EventFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual Frame* clone() override; + + inline void setEvent(std::string event) { _event = event;} + inline std::string getEvent() const { return _event; } + +protected: + std::string _event; +}; + +class ZOrderFrame : public Frame +{ +public: + static ZOrderFrame* create(); + + ZOrderFrame(); + + virtual void onEnter(Frame *nextFrame) override; + virtual Frame* clone() override; + + inline void setZOrder(int zorder) { _zorder = zorder;} + inline int getZOrder() const { return _zorder; } + +protected: + int _zorder; +}; + +} +} + + +#endif /*__CCFRAME_H__*/ diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCNodeCache.cpp b/cocos/editor-support/cocostudio/TimelineAction/CCNodeCache.cpp new file mode 100644 index 0000000000..61a60a02c3 --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCNodeCache.cpp @@ -0,0 +1,368 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#include "CCNodeCache.h" +#include "CCTimelineActionCache.h" +#include "CCFrame.h" + +#include "../CCSGUIReader.h" + +using namespace cocos2d; +using namespace cocos2d::ui; + +namespace cocostudio { +namespace timeline{ + + +static const char* ClassName_Node = "Node"; +static const char* ClassName_SubGraph = "SubGraph"; +static const char* ClassName_Sprite = "Sprite"; +static const char* ClassName_Particle = "Particle"; + +static const char* ClassName_Panel = "Panel"; +static const char* ClassName_Button = "Button"; +static const char* ClassName_CheckBox = "CheckBox"; +static const char* ClassName_ImageView = "ImageView"; +static const char* ClassName_TextAtlas = "TextAtlas"; +static const char* ClassName_TextBMFont = "TextBMFont"; +static const char* ClassName_Text = "Text"; +static const char* ClassName_LoadingBar = "LoadingBar"; +static const char* ClassName_TextField = "TextField"; +static const char* ClassName_Slider = "Slider"; +static const char* ClassName_Layout = "Layout"; +static const char* ClassName_ScrollView = "ScrollView"; +static const char* ClassName_ListView = "ListView"; +static const char* ClassName_PageView = "PageView"; +static const char* ClassName_Widget = "Widget"; + + +static const char* NODE = "nodeTree"; +static const char* CHILDREN = "children"; +static const char* CLASSNAME = "classname"; +static const char* FILE_PATH = "filePath"; +static const char* PLIST_FILE = "plistFile"; +static const char* ACTION_TAG = "actionTag"; + +static const char* OPTIONS = "options"; + +static const char* WIDTH = "width"; +static const char* HEIGHT = "height"; +static const char* X = "x"; +static const char* Y = "y"; +static const char* SCALE_X = "scaleX"; +static const char* SCALE_Y = "scaleY"; +static const char* SKEW_X = "skewX"; +static const char* SKEW_Y = "skewY"; +static const char* ROTATION = "rotation"; +static const char* ROTATION_SKEW_X = "rotationSkewX"; +static const char* ROTATION_SKEW_Y = "rotationSkewY"; +static const char* ANCHOR_X = "anchorPointX"; +static const char* ANCHOR_Y = "anchorPointY"; +static const char* ALPHA = "opacity"; +static const char* RED = "colorR"; +static const char* GREEN = "colorG"; +static const char* BLUE = "colorB"; +static const char* PARTICLE_NUM = "particleNum"; + +static const char* MULRESPOSITION = "mulResPosition"; +static const char* POSITIONTYPE = "positionType"; +static const char* MUL_POSITION = "position"; +static const char* MUL_POSITIONX = "x"; +static const char* MUL_POSITIONY = "y"; +static const char* MUL_POSITIONPERCENTAGE = "percentagepos"; +static const char* MUL_POSITIONPERCENTAGEX = "x"; +static const char* MUL_POSITIONPERCENTAGEY = "y"; +static const char* MUL_RELATIVEALIGN = "mulpositionpercentage"; +static const char* MUL_MARGIN = "margin"; +static const char* MUL_MARGIN_LEFT = "left"; +static const char* MUL_MARGIN_TOP = "top"; +static const char* MUL_MARGIN_RIGHT = "right"; +static const char* MUL_MARGIN_BOTTOM = "bottom"; + + +static NodeCache* _sharedNodeCache = nullptr; + +NodeCache* NodeCache::getInstance() +{ + if (! _sharedNodeCache) + { + _sharedNodeCache = new NodeCache(); + _sharedNodeCache->init(); + } + + return _sharedNodeCache; +} + +void NodeCache::destroyInstance() +{ + CC_SAFE_DELETE(_sharedNodeCache); +} + +void NodeCache::purge() +{ + _nodes.clear(); +} + +void NodeCache::init() +{ + using namespace std::placeholders; + + _funcs.insert(Pair(ClassName_Node, std::bind(&NodeCache::loadSimpleNode, this, _1))); + _funcs.insert(Pair(ClassName_SubGraph, std::bind(&NodeCache::loadSubGraph, this, _1))); + _funcs.insert(Pair(ClassName_Sprite, std::bind(&NodeCache::loadSprite, this, _1))); + _funcs.insert(Pair(ClassName_Particle, std::bind(&NodeCache::loadParticle, this, _1))); + + _funcs.insert(Pair(ClassName_Panel, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_Button, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_CheckBox, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_ImageView, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_TextAtlas, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_TextBMFont,std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_Text, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_LoadingBar,std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_TextField, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_Slider, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_Layout, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_ScrollView,std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_ListView, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_PageView, std::bind(&NodeCache::loadWidget, this, _1))); + _funcs.insert(Pair(ClassName_Widget, std::bind(&NodeCache::loadWidget, this, _1))); + + _guiReader = new WidgetPropertiesReader0300(); +} + +cocos2d::Node* NodeCache::createNode(const std::string& filename) +{ + cocos2d::Node* node = _nodes.at(filename); + if (node == nullptr) + { + node = loadNodeWithFile(filename); + +// if(cache) +// _nodes.insert(filename, node); + } + + return node; +} + +cocos2d::Node* NodeCache::loadNodeWithFile(const std::string& fileName) +{ + // Read content from file + std::string fullPath = CCFileUtils::getInstance()->fullPathForFilename(fileName); + std::string contentStr = FileUtils::getInstance()->getStringFromFile(fullPath); + + // Load animation data from file + TimelineActionCache::getInstance()->loadAnimationActionWithContent(fileName, contentStr); + + return loadNodeWithContent(contentStr); +} + +cocos2d::Node* NodeCache::loadNodeWithContent(const std::string& content) +{ + rapidjson::Document doc; + doc.Parse<0>(content.c_str()); + if (doc.HasParseError()) { + CCLOG("GetParseError %s\n", doc.GetParseError()); + } + + const rapidjson::Value& subJson = DICTOOL->getSubDictionary_json(doc, NODE); + return loadNode(subJson); +} + +cocos2d::Node* NodeCache::loadNode(const rapidjson::Value& json) +{ + cocos2d::Node* node = nullptr; + std::string nodeType = DICTOOL->getStringValue_json(json, CLASSNAME); + + NodeCreateFunc func = _funcs.at(nodeType); + if (func != nullptr) + { + const rapidjson::Value& options = DICTOOL->getSubDictionary_json(json, OPTIONS); + node = func(options); + } + + if(node) + { + int length = DICTOOL->getArrayCount_json(json, CHILDREN, 0); + for (int i = 0; igetSubDictionary_json(json, CHILDREN, i); + cocos2d::Node* child = loadNode(dic); + if (child) { + node->addChild(child); + } + } + } + else + { + CCLOG("Not supported NodeType: %s", nodeType.c_str()); + } + + return node; +} + +void NodeCache::initNode(cocos2d::Node* node, const rapidjson::Value& json) +{ + float width = DICTOOL->getFloatValue_json(json, WIDTH); + float height = DICTOOL->getFloatValue_json(json, HEIGHT); + float x = DICTOOL->getFloatValue_json(json, X); + float y = DICTOOL->getFloatValue_json(json, Y); + float scalex = DICTOOL->getFloatValue_json(json, SCALE_X, 1); + float scaley = DICTOOL->getFloatValue_json(json, SCALE_Y, 1); + float rotation = DICTOOL->getFloatValue_json(json, ROTATION); + float rotationSkewX = DICTOOL->getFloatValue_json(json, ROTATION_SKEW_X); + float rotationSkewY = DICTOOL->getFloatValue_json(json, ROTATION_SKEW_Y); + float skewx = DICTOOL->getFloatValue_json(json, SKEW_X); + float skewy = DICTOOL->getFloatValue_json(json, SKEW_Y); + float anchorx = DICTOOL->getFloatValue_json(json, ANCHOR_X, 0.5f); + float anchory = DICTOOL->getFloatValue_json(json, ANCHOR_Y, 0.5f); + GLubyte alpha = (GLubyte)DICTOOL->getIntValue_json(json, ALPHA, 255); + GLubyte red = (GLubyte)DICTOOL->getIntValue_json(json, RED, 255); + GLubyte green = (GLubyte)DICTOOL->getIntValue_json(json, GREEN, 255); + GLubyte blue = (GLubyte)DICTOOL->getIntValue_json(json, BLUE, 255); + int tag = DICTOOL->getIntValue_json(json, ACTION_TAG); + + if(x != 0 || y != 0) + node->setPosition(CCPoint(x, y)); + if(scalex != 1) + node->setScaleX(scalex); + if(scaley != 1) + node->setScaleY(scaley); + if (rotation != 0) + node->setRotation(rotation); + if(rotationSkewX != 0) + node->setRotationX(rotationSkewX); + if(rotationSkewY != 0) + node->setRotationY(rotationSkewY); + if(skewx != 0) + node->setSkewX(skewx); + if(skewy != 0) + node->setSkewY(skewy); + if(anchorx != 0.5f || anchory != 0.5f) + node->setAnchorPoint(CCPoint(anchorx, anchory)); + if(width != 0 || height != 0) + node->setContentSize(Size(width, height)); + + CCRGBAProtocol *rgbaProtocaol = dynamic_cast(node); + if(rgbaProtocaol) + { + if(alpha != 255) + rgbaProtocaol->setOpacity(alpha); rgbaProtocaol->setCascadeOpacityEnabled(true); + if(red != 255 || green != 255 || blue != 255) + rgbaProtocaol->setColor(ccc3(red, green, blue)); + } + + node->setTag(tag); +} + +Node* NodeCache::loadSimpleNode(const rapidjson::Value& json) +{ + Node* node = Node::create(); + initNode(node, json); + + return node; +} + +cocos2d::Node* NodeCache::loadSubGraph(const rapidjson::Value& json) +{ + const char* filePath = DICTOOL->getStringValue_json(json, FILE_PATH); + + Node* node = nullptr; + if (filePath && strcmp("", filePath) != 0) + { + node = createNode(filePath); + } + else + { + node = Node::create(); + } + + initNode(node, json); + + return node; +} + +Node* NodeCache::loadSprite(const rapidjson::Value& json) +{ + const char* filePath = DICTOOL->getStringValue_json(json, FILE_PATH); + Sprite *sprite = nullptr; + + if(filePath != nullptr) + { + SpriteFrame* spriteFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName(filePath); + if(!spriteFrame) + { + sprite = Sprite::create(filePath); + } + else + { + sprite = Sprite::createWithSpriteFrame(spriteFrame); + } + + if(!sprite) + { + sprite = CCSprite::create(); + CCLOG("filePath is empty. Create a sprite with no texture"); + } + } + else + { + sprite = Sprite::create(); + } + + initNode(sprite, json); + + return sprite; +} + +Node* NodeCache::loadParticle(const rapidjson::Value& json) +{ + const char* filePath = DICTOOL->getStringValue_json(json, PLIST_FILE); + int num = DICTOOL->getIntValue_json(json, PARTICLE_NUM); + + ParticleSystemQuad* particle = ParticleSystemQuad::create(filePath); + particle->setTotalParticles(num); + + initNode(particle, json); + + return particle; +} + +cocos2d::Node* NodeCache::loadWidget(const rapidjson::Value& json) +{ + const char* classname = DICTOOL->getStringValue_json(json, CLASSNAME); + + std::string readerName = classname; + readerName.append("Reader"); + + Widget* widget = dynamic_cast(ObjectFactory::getInstance()->createObject(classname)); + WidgetReaderProtocol* reader = dynamic_cast(ObjectFactory::getInstance()->createObject(readerName)); + + _guiReader->setPropsForAllWidgetFromJsonDictionary(reader, widget, json); + + return widget; +} + +} +} diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCNodeCache.h b/cocos/editor-support/cocostudio/TimelineAction/CCNodeCache.h new file mode 100644 index 0000000000..be04b85a78 --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCNodeCache.h @@ -0,0 +1,82 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#ifndef __CC_NODE_CACHE_H__ +#define __CC_NODE_CACHE_H__ + +#include "CCTimeLine.h" +#include "cocostudio/DictionaryHelper.h" + + +namespace cocostudio { + +class WidgetPropertiesReader0300; + +namespace timeline{ + +class NodeCache +{ +public: + static NodeCache* getInstance(); + static void destroyInstance(); + + void purge(); + + void init(); + + cocos2d::Node* createNode(const std::string& filename); + + cocos2d::Node* loadNodeWithFile(const std::string& fileName); + cocos2d::Node* loadNodeWithContent(const std::string& content); +protected: + + cocos2d::Node* loadNode(const rapidjson::Value& json); + + void locateNodeWithMulresPosition(cocos2d::Node* node, const rapidjson::Value& json); + + void initNode(cocos2d::Node* node, const rapidjson::Value& json); + + // load nodes + cocos2d::Node* loadSimpleNode(const rapidjson::Value& json); + cocos2d::Node* loadSubGraph (const rapidjson::Value& json); + cocos2d::Node* loadSprite (const rapidjson::Value& json); + cocos2d::Node* loadParticle (const rapidjson::Value& json); + + // load gui + cocos2d::Node* loadWidget(const rapidjson::Value& json); + + typedef std::function NodeCreateFunc; + typedef std::pair Pair; + + std::unordered_map _funcs; + cocos2d::Map _nodes; + + WidgetPropertiesReader0300* _guiReader; +}; + +} +} + + +#endif /*__CC_NODE_CACHE_H__*/ diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCTimeLine.cpp b/cocos/editor-support/cocostudio/TimelineAction/CCTimeLine.cpp new file mode 100644 index 0000000000..d9b34e4524 --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCTimeLine.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#include "CCTimeLine.h" +#include "CCTimelineAction.h" +#include "CCFrame.h" + +using namespace cocos2d; + +namespace cocostudio { +namespace timeline{ + +Timeline* Timeline::create() +{ + Timeline* object = new Timeline(); + if (object) + { + object->autorelease(); + return object; + } + CC_SAFE_DELETE(object); + return nullptr; +} + +Timeline::Timeline() + : _currentKeyFrame(nullptr) + , _currentKeyFrameIndex(0) + , _fromIndex(0) + , _toIndex(0) + , _betweenDuration(0) + , _actionTag(0) + , _timelineAction(nullptr) + , _node(nullptr) +{ +} + +Timeline::~Timeline() +{ +} + +void Timeline::gotoFrame(int frameIndex) +{ + if(_frames.size() == 0) + return; + + binarySearchKeyFrame(frameIndex); + apply(frameIndex); +} + +void Timeline::stepToFrame(int frameIndex) +{ + if(_frames.size() == 0) + return; + + updateCurrentKeyFrame(frameIndex); + apply(frameIndex); +} + +Timeline* Timeline::clone() +{ + Timeline* timeline = Timeline::create(); + timeline->_actionTag = _actionTag; + + for (auto frame : _frames) + { + Frame* newFrame = frame->clone(); + timeline->getFrames().pushBack(newFrame); + } + + return timeline; +} + +void Timeline::addFrame(Frame* frame) +{ + _frames.pushBack(frame); + frame->setTimeline(this); +} + +void Timeline::insertFrame(Frame* frame, int index) +{ + _frames.insert(index, frame); + frame->setTimeline(this); +} + +void Timeline::removeFrame(Frame* frame) +{ + _frames.eraseObject(frame); + frame->setTimeline(NULL); +} + +void Timeline::setNode(cocos2d::Node* node) +{ + for (auto frame : _frames) + { + frame->setNode(node); + } +} + +cocos2d::Node* Timeline::getNode() +{ + return _node; +} + +void Timeline::apply(int frameIndex) +{ + if (_currentKeyFrame) + { + float currentPercent = _betweenDuration == 0 ? 0 : (frameIndex - _currentKeyFrameIndex) / (float)_betweenDuration; + _currentKeyFrame->apply(currentPercent); + } +} + +void Timeline::binarySearchKeyFrame(int frameIndex) +{ + Frame *from = NULL; + Frame *to = NULL; + + int step = 2; + int target = 0; + long length = _frames.size(); + + bool needEnterFrame = false; + + do + { + if (frameIndex < _frames.at(0)->getFrameIndex()) + { + if(_currentKeyFrameIndex >= _frames.at(0)->getFrameIndex()) + needEnterFrame = true; + + from = to = _frames.at(0); + _currentKeyFrameIndex = 0; + _betweenDuration = _frames.at(0)->getFrameIndex(); + break; + } + else if(frameIndex >= _frames.at(length - 1)->getFrameIndex()) + { + from = to = _frames.at(length - 1); + _currentKeyFrameIndex = _frames.at(length - 1)->getFrameIndex(); + _betweenDuration = 0; + break; + } + + int target = -1; + int low=0,high=length-1,mid; + while(low<=high){ + mid=(low+high)/2; + if(frameIndex >= _frames.at(mid)->getFrameIndex() && frameIndex < _frames.at(mid+1)->getFrameIndex()) + { + target = mid; + break; + } + if(_frames.at(mid)->getFrameIndex()>frameIndex) + high=mid-1; + else + low=mid+1; + } + + from = _frames.at(target); + to = _frames.at(target+1); + + if(target == 0 && _currentKeyFrameIndexgetFrameIndex()) + needEnterFrame = true; + + _currentKeyFrameIndex = from->getFrameIndex(); + _betweenDuration = to->getFrameIndex() - from->getFrameIndex(); + } while (0); + + if(needEnterFrame || _currentKeyFrame != from) + { + _currentKeyFrame = from; + _currentKeyFrame->onEnter(to); + } +} + +void Timeline::updateCurrentKeyFrame(int frameIndex) +{ + //! If play to current frame's front or back, then find current frame again + if (frameIndex < _currentKeyFrameIndex || frameIndex >= _currentKeyFrameIndex + _betweenDuration) + { + Frame *from = nullptr; + Frame *to = nullptr; + + do + { + long length = _frames.size(); + + if (frameIndex < _frames.at(0)->getFrameIndex()) + { + from = to = _frames.at(0); + _currentKeyFrameIndex = 0; + _betweenDuration = _frames.at(0)->getFrameIndex(); + break; + } + else if(frameIndex >= _frames.at(length - 1)->getFrameIndex()) + { + from = to = _frames.at(length - 1); + _currentKeyFrameIndex = _frames.at(length - 1)->getFrameIndex(); + _betweenDuration = 0; + break; + } + + do + { + _fromIndex = _toIndex; + from = _frames.at(_fromIndex); + _currentKeyFrameIndex = from->getFrameIndex(); + + _toIndex = _fromIndex + 1; + if (_toIndex >= length) + { + _toIndex = 0; + } + + to = _frames.at(_toIndex); + + if (frameIndex == from->getFrameIndex()) + { + break; + } + } + while (frameIndex < from->getFrameIndex() || frameIndex >= to->getFrameIndex()); + + _betweenDuration = to->getFrameIndex() - from->getFrameIndex(); + + } while (0); + + _currentKeyFrame = from; + _currentKeyFrame->onEnter(to); + } +} + +} +} diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCTimeLine.h b/cocos/editor-support/cocostudio/TimelineAction/CCTimeLine.h new file mode 100644 index 0000000000..97c82a9a6b --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCTimeLine.h @@ -0,0 +1,89 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#ifndef __CCTIMELINE_H__ +#define __CCTIMELINE_H__ + +#include "cocos2d.h" + +namespace cocostudio { +namespace timeline{ + +class Frame; +class TimelineAction; + +class Timeline : public cocos2d::Ref +{ +public: + static Timeline* create(); + + Timeline(); + virtual ~Timeline(); + + virtual void gotoFrame(int frameIndex); + virtual void stepToFrame(int frameIndex); + + virtual cocos2d::Vector& getFrames() { return _frames; } + virtual const cocos2d::Vector& getFrames() const { return _frames; } + + virtual void addFrame(Frame* frame); + virtual void insertFrame(Frame* frame, int index); + virtual void removeFrame(Frame* frame); + + virtual void setActionTag(int tag) { _actionTag = tag; } + virtual int getActionTag() { return _actionTag; } + + virtual void setNode(cocos2d::Node* node); + virtual cocos2d::Node* getNode(); + + virtual void setTimelineAction(TimelineAction* action) { _timelineAction = action; } + virtual TimelineAction* getTimelineAction() { return _timelineAction; } + + virtual Timeline* clone(); + + +protected: + virtual void apply(int frameIndex); + + virtual void binarySearchKeyFrame (int frameIndex); + virtual void updateCurrentKeyFrame(int frameIndex); + + cocos2d::Vector _frames; + Frame* _currentKeyFrame; + int _currentKeyFrameIndex; + + int _fromIndex; + int _toIndex; + int _betweenDuration; + int _actionTag; + + TimelineAction* _timelineAction; + cocos2d::Node* _node; +}; + +} +} + + +#endif /*__CCTIMELINE_H__*/ diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCTimelineAction.cpp b/cocos/editor-support/cocostudio/TimelineAction/CCTimelineAction.cpp new file mode 100644 index 0000000000..61b08e0a0a --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCTimelineAction.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#include "CCTimelineAction.h" + +using namespace cocos2d; + +namespace cocostudio { +namespace timeline{ + +TimelineAction* TimelineAction::create() +{ + TimelineAction* object = new TimelineAction(); + if (object && object->init()) + { + object->autorelease(); + return object; + } + CC_SAFE_DELETE(object); + return nullptr; +} + +TimelineAction::TimelineAction() + : _duration(0) + , _time(0) + , _timeSpeed(1) + , _frameInternal(1/60.0f) + , _playing(false) + , _currentFrame(0) + , _endFrame(0) + , _frameEventListener(nullptr) +{ +} + +TimelineAction::~TimelineAction() +{ +} + +bool TimelineAction::init() +{ + return true; +} + +void TimelineAction::gotoFrameAndPlay(int startIndex) +{ + gotoFrameAndPlay(startIndex, true); +} + +void TimelineAction::gotoFrameAndPlay(int startIndex, bool loop) +{ + gotoFrameAndPlay(startIndex, _duration, loop); +} + +void TimelineAction::gotoFrameAndPlay(int startIndex, int endIndex, bool loop) +{ + _endFrame = endIndex; + _loop = loop; + _currentFrame = startIndex; + _time = _currentFrame*_frameInternal; + + resume(); + gotoFrame(_currentFrame); +} + +void TimelineAction::gotoFrameAndPause(int startIndex) +{ + _time =_currentFrame = startIndex; + + pause(); + gotoFrame(_currentFrame); +} + +void TimelineAction::pause() +{ + _playing = false; +} + +void TimelineAction::resume() +{ + _playing = true; +} + +bool TimelineAction::isPlaying() +{ + return _playing; +} + +void TimelineAction::setTimeSpeed(float speed) +{ + _timeSpeed = speed; +} + +float TimelineAction::getTimeSpeed() +{ + return _timeSpeed; +} + +TimelineAction* TimelineAction::clone() const +{ + TimelineAction* newAction = TimelineAction::create(); + newAction->setDuration(_duration); + newAction->setTimeSpeed(_timeSpeed); + + for (auto timelines : _timelineMap) + { + for(auto timeline : timelines.second) + { + Timeline* newTimeline = timeline->clone(); + newAction->addTimeline(newTimeline); + } + } + + return newAction; +} + +void TimelineAction::step(float delta) +{ + if (!_playing || _timelineMap.size() == 0 || _duration == 0) + { + return; + } + + _time += delta * _timeSpeed; + _currentFrame = (int)(_time / _frameInternal); + + if (_currentFrame > _endFrame) + { + _playing = _loop; + if(!_playing) + _currentFrame = _time = _endFrame; + else + _currentFrame = _time = 0; + } + + stepToFrame(_currentFrame); +} + +typedef std::function tCallBack; +void foreachNodeDescendant(Node* parent, tCallBack callback) +{ + callback(parent); + + auto children = parent->getChildren(); + for (auto child : children) + { + foreachNodeDescendant(child, callback); + } +} + +void TimelineAction::startWithTarget(Node *target) +{ + Action::startWithTarget(target); + + foreachNodeDescendant(target, + [this, target](Node* child) + { + int actionTag = child->getTag(); + if(_timelineMap.find(actionTag) != _timelineMap.end()) + { + auto timelines = this->_timelineMap[actionTag]; + for (auto timeline : timelines) + { + timeline->setNode(child); + } + } + }); +} + +void TimelineAction::addTimeline(Timeline* timeline) +{ + int tag = timeline->getActionTag(); + if (_timelineMap.find(tag) == _timelineMap.end()) + { + _timelineMap[tag] = cocos2d::Vector(); + } + + if (!_timelineMap[tag].contains(timeline)) + { + _timelineList.pushBack(timeline); + _timelineMap[tag].pushBack(timeline); + timeline->setTimelineAction(this); + } +} + +void TimelineAction::removeTimeline(Timeline* timeline) +{ + int tag = timeline->getActionTag(); + if (_timelineMap.find(tag) != _timelineMap.end()) + { + if(_timelineMap[tag].contains(timeline)) + { + _timelineMap[tag].eraseObject(timeline); + _timelineList.eraseObject(timeline); + timeline->setTimelineAction(nullptr); + } + } +} + +void TimelineAction::setFrameEventCallFunc(std::function listener) +{ + _frameEventListener = listener; +} + +void TimelineAction::clearFrameEventCallFunc() +{ + _frameEventListener = nullptr; +} + + +void TimelineAction::emitFrameEvent(Frame* frame) +{ + if(_frameEventListener) + { + _frameEventListener(frame); + } +} + +void TimelineAction::gotoFrame(int frameIndex) +{ + int size = _timelineList.size(); + for(int i = 0; igotoFrame(frameIndex); + } +} + +void TimelineAction::stepToFrame(int frameIndex) +{ + int size = _timelineList.size(); + for(int i = 0; istepToFrame(frameIndex); + } +} + +} +} diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCTimelineAction.h b/cocos/editor-support/cocostudio/TimelineAction/CCTimelineAction.h new file mode 100644 index 0000000000..54be1c8571 --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCTimelineAction.h @@ -0,0 +1,144 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#ifndef __CCTIMELINE_ACTION_H__ +#define __CCTIMELINE_ACTION_H__ + +#include "cocos2d.h" +#include "CCTimeLine.h" +#include "renderer/CCRenderer.h" + +namespace cocostudio { +namespace timeline{ + +typedef void (cocos2d::Ref::*SEL_FrameEventCallFunc)(Frame *); +#define frameEvent_selector(_SELECTOR) (cocostudio::SEL_FrameEventCallFunc)(&_SELECTOR) + +class TimelineAction : public cocos2d::Action +{ +public: + static TimelineAction* create(); + + TimelineAction(); + virtual ~TimelineAction(); + + virtual bool init(); + + /** Goto the specified frame index, and start playing from this index. + * @param startIndex The animation will play from this index. + */ + virtual void gotoFrameAndPlay(int startIndex); + + /** Goto the specified frame index, and start playing from this index. + * @param startIndex The animation will play from this index. + * @param loop Whether or not the animation need loop. + */ + virtual void gotoFrameAndPlay(int startIndex, bool loop); + + /** Goto the specified frame index, and start playing from start index, end at end index. + * @param startIndex The animation will play from this index. + * @param endIndex The animation will end at this index. + * @param loop Whether or not the animation need loop. + */ + virtual void gotoFrameAndPlay(int startIndex, int endIndex, bool loop); + + /** Goto the specified frame index, and pause at this index. + * @param startIndex The animation will pause at this index. + */ + virtual void gotoFrameAndPause(int startIndex); + + /** Pause the animation. */ + virtual void pause(); + /** Resume the animation. */ + virtual void resume(); + + /** Whether or not Action is playing. */ + virtual bool isPlaying(); + + /** Set the animation speed, this will speed up or slow down the speed. */ + virtual void setTimeSpeed(float speed); + /** Get current animation speed. */ + virtual float getTimeSpeed(); + + /** duration of the whole action*/ + virtual void setDuration(int duration) { _duration = duration; } + virtual int getDuration() { return _duration; } + + /** End frame of this action. + * When action play to this frame, if action is not loop, then it will stop, + * or it will play from start frame again. */ + virtual void setEndFrame(int endFrame) { _endFrame = endFrame; } + virtual int getEndFrame() { return _endFrame; } + + /** Get current frame. */ + virtual int getCurrentFrame() { return _currentFrame; } + + /** add Timeline to TimelineAction */ + virtual void addTimeline(Timeline* timeline); + virtual void removeTimeline(Timeline* timeline); + + /** Set TimelineAction's frame event callback function */ + void setFrameEventCallFunc(std::function listener); + void clearFrameEventCallFunc(); + + /** emit frame event, call it when enter a frame*/ + void emitFrameEvent(Frame* frame); + + /** Inherit from cocos2d::Action. */ + + /** Returns a clone of TimelineAction */ + virtual TimelineAction* clone() const override; + + /** Returns a reverse of TimelineAction. + * Not implement yet. + */ + virtual TimelineAction* reverse() const override { return nullptr; } + + virtual void step(float delta) override; + virtual void startWithTarget(cocos2d::Node *target) override; + virtual bool isDone() const override { return false; } +protected: + virtual void gotoFrame(int frameIndex); + virtual void stepToFrame(int frameIndex); + + std::map> _timelineMap; + cocos2d::Vector _timelineList; + + int _duration; + double _time; + float _timeSpeed; + float _frameInternal; + bool _playing; + int _currentFrame; + int _endFrame; + bool _loop; + + std::function _frameEventListener; +}; + +} +} + + +#endif /*__CCTIMELINE_ACTION_H__*/ diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCTimelineActionCache.cpp b/cocos/editor-support/cocostudio/TimelineAction/CCTimelineActionCache.cpp new file mode 100644 index 0000000000..d37a967f8b --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCTimelineActionCache.cpp @@ -0,0 +1,373 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#include "CCTimelineActionCache.h" +#include "CCTimelineAction.h" +#include "CCFrame.h" + +using namespace cocos2d; + +namespace cocostudio { +namespace timeline{ + +static const char* FrameType_VisibleFrame = "VisibleFrame"; +static const char* FrameType_PositionFrame = "PositionFrame"; +static const char* FrameType_ScaleFrame = "ScaleFrame"; +static const char* FrameType_RotationFrame = "RotationFrame"; +static const char* FrameType_SkewFrame = "SkewFrame"; +static const char* FrameType_RotationSkewFrame = "RotationSkewFrame"; +static const char* FrameType_AnchorFrame = "AnchorFrame"; +static const char* FrameType_InnerActionFrame = "InnerActionFrame"; +static const char* FrameType_ColorFrame = "ColorFrame"; +static const char* FrameType_TextureFrame = "TextureFrame"; +static const char* FrameType_EventFrame = "EventFrame"; +static const char* FrameType_ZOrderFrame = "ZOrderFrame"; + +static const char* ACTION = "action"; +static const char* NAME = "name"; +static const char* DURATION = "duration"; +static const char* NODES = "nodes"; +static const char* TIMELINES = "timelines"; +static const char* FRAME_TYPE = "frameType"; +static const char* FRAMES = "frames"; +static const char* FRAME_INDEX = "frameIndex"; +static const char* VISIBLE = "visible"; +static const char* TWEEN = "tween"; +static const char* TIME_SPEED = "speed"; +static const char* ACTION_TAG = "actionTag"; +static const char* INNER_ACTION = "innerActionType"; +static const char* START_FRAME = "startFrame"; + +static const char* X = "x"; +static const char* Y = "y"; +static const char* SCALE_X = "scaleX"; +static const char* SCALE_Y = "scaleY"; +static const char* SKEW_X = "skewX"; +static const char* SKEW_Y = "skewY"; +static const char* ROTATION = "rotation"; +static const char* ROTATION_SKEW_X = "rotationSkewX"; +static const char* ROTATION_SKEW_Y = "rotationSkewY"; +static const char* ANCHOR_X = "anchorPointX"; +static const char* ANCHOR_Y = "anchorPointY"; +static const char* ALPHA = "alpha"; +static const char* RED = "red"; +static const char* GREEN = "green"; +static const char* BLUE = "blue"; +static const char* Value = "value"; + + +static TimelineActionCache* _sharedActionCache = nullptr; + +TimelineActionCache* TimelineActionCache::getInstance() +{ + if (! _sharedActionCache) + { + _sharedActionCache = new TimelineActionCache(); + _sharedActionCache->init(); + } + + return _sharedActionCache; +} + +void TimelineActionCache::destroyInstance() +{ + CC_SAFE_DELETE(_sharedActionCache); +} + +void TimelineActionCache::purge() +{ + _animationActions.clear(); +} + +void TimelineActionCache::init() +{ + using namespace std::placeholders; + _funcs.insert(Pair(FrameType_VisibleFrame, std::bind(&TimelineActionCache::loadVisibleFrame, this, _1))); + _funcs.insert(Pair(FrameType_PositionFrame, std::bind(&TimelineActionCache::loadPositionFrame, this, _1))); + _funcs.insert(Pair(FrameType_ScaleFrame, std::bind(&TimelineActionCache::loadScaleFrame, this, _1))); + _funcs.insert(Pair(FrameType_RotationFrame, std::bind(&TimelineActionCache::loadRotationFrame, this, _1))); + _funcs.insert(Pair(FrameType_SkewFrame, std::bind(&TimelineActionCache::loadSkewFrame, this, _1))); + _funcs.insert(Pair(FrameType_RotationSkewFrame, std::bind(&TimelineActionCache::loadRotationSkewFrame, this, _1))); + _funcs.insert(Pair(FrameType_AnchorFrame, std::bind(&TimelineActionCache::loadAnchorPointFrame, this, _1))); + _funcs.insert(Pair(FrameType_InnerActionFrame, std::bind(&TimelineActionCache::loadInnerActionFrame, this, _1))); + _funcs.insert(Pair(FrameType_ColorFrame, std::bind(&TimelineActionCache::loadColorFrame, this, _1))); + _funcs.insert(Pair(FrameType_TextureFrame, std::bind(&TimelineActionCache::loadTextureFrame, this, _1))); + _funcs.insert(Pair(FrameType_EventFrame, std::bind(&TimelineActionCache::loadEventFrame, this, _1))); + _funcs.insert(Pair(FrameType_ZOrderFrame, std::bind(&TimelineActionCache::loadZOrderFrame, this, _1))); + +} + +void TimelineActionCache::removeAction(const std::string& fileName) +{ + if (_animationActions.find(fileName) != _animationActions.end()) + { + _animationActions.erase(fileName); + } +} + +TimelineAction* TimelineActionCache::createAction(const std::string& fileName) +{ + TimelineAction* action = _animationActions.at(fileName); + if (action == nullptr) + { + action = loadAnimationActionWithFile(fileName); + } + return action->clone(); +} + +TimelineAction* TimelineActionCache::loadAnimationActionWithFile(const std::string& fileName) +{ + // Read content from file + std::string fullPath = CCFileUtils::getInstance()->fullPathForFilename(fileName); + std::string contentStr = FileUtils::getInstance()->getStringFromFile(fullPath); + + return loadAnimationActionWithContent(fileName, contentStr); +} + +TimelineAction* TimelineActionCache::loadAnimationActionWithContent(const std::string&fileName, const std::string& content) +{ + // if already exists an action with filename, then return this action + TimelineAction* action = _animationActions.at(fileName); + if(action) + return action; + + rapidjson::Document doc; + doc.Parse<0>(content.c_str()); + if (doc.HasParseError()) + { + CCLOG("GetParseError %s\n", doc.GetParseError()); + } + + const rapidjson::Value& json = DICTOOL->getSubDictionary_json(doc, ACTION); + + action = TimelineAction::create(); + + action->setDuration(DICTOOL->getIntValue_json(json, DURATION)); + action->setTimeSpeed(DICTOOL->getFloatValue_json(json, TIME_SPEED, 1.0f)); + + int timelineLength = DICTOOL->getArrayCount_json(json, TIMELINES); + for (int i = 0; igetSubDictionary_json(json, TIMELINES, i); + Timeline* timeline = loadTimeline(dic); + + if(timeline) + action->addTimeline(timeline); + } + + _animationActions.insert(fileName, action); + + return action; +} + + +Timeline* TimelineActionCache::loadTimeline(const rapidjson::Value& json) +{ + Timeline* timeline = nullptr; + + // get frame type + const char* frameType = DICTOOL->getStringValue_json(json, FRAME_TYPE); + if(frameType == nullptr) + return nullptr; + + if(frameType && _funcs.find(frameType) != _funcs.end()) + { + timeline = Timeline::create(); + + int actionTag = DICTOOL->getIntValue_json(json, ACTION_TAG); + timeline->setActionTag(actionTag); + + FrameCreateFunc func = _funcs.at(frameType); + + int length = DICTOOL->getArrayCount_json(json, FRAMES); + for (int i = 0; igetSubDictionary_json(json, FRAMES, i); + + Frame* frame = nullptr; + + if (func != nullptr) + { + frame = func(dic); + + int frameIndex = DICTOOL->getIntValue_json(dic, FRAME_INDEX); + frame->setFrameIndex(frameIndex); + + bool tween = DICTOOL->getBooleanValue_json(dic, TWEEN, false); + frame->setTween(tween); + } + + timeline->addFrame(frame); + } + } + + return timeline; +} + +Frame* TimelineActionCache::loadVisibleFrame(const rapidjson::Value& json) +{ + VisibleFrame* frame = VisibleFrame::create(); + + bool visible = DICTOOL->getBooleanValue_json(json, Value); + frame->setVisible(visible); + + return frame; +} + +Frame* TimelineActionCache::loadPositionFrame(const rapidjson::Value& json) +{ + PositionFrame* frame = PositionFrame::create(); + + float x = DICTOOL->getFloatValue_json(json, X); + float y = DICTOOL->getFloatValue_json(json, Y); + frame->setPosition(Point(x,y)); + + return frame; +} + +Frame* TimelineActionCache::loadScaleFrame(const rapidjson::Value& json) +{ + ScaleFrame* frame = ScaleFrame::create(); + + float scalex = DICTOOL->getFloatValue_json(json, X); + float scaley = DICTOOL->getFloatValue_json(json, Y); + + frame->setScaleX(scalex); + frame->setScaleY(scaley); + + return frame; +} + +Frame* TimelineActionCache::loadSkewFrame(const rapidjson::Value& json) +{ + SkewFrame* frame = SkewFrame::create(); + + float skewx = DICTOOL->getFloatValue_json(json, X); + float skewy = DICTOOL->getFloatValue_json(json, Y); + + frame->setSkewX(skewx); + frame->setSkewY(skewy); + + return frame; +} + +Frame* TimelineActionCache::loadRotationSkewFrame(const rapidjson::Value& json) +{ + RotationSkewFrame* frame = RotationSkewFrame::create(); + + float skewx = DICTOOL->getFloatValue_json(json, X); + float skewy = DICTOOL->getFloatValue_json(json, Y); + + frame->setSkewX(skewx); + frame->setSkewY(skewy); + + return frame; +} + +Frame* TimelineActionCache::loadRotationFrame(const rapidjson::Value& json) +{ + RotationFrame* frame = RotationFrame::create(); + + float rotation = DICTOOL->getFloatValue_json(json, ROTATION); + frame->setRotation(rotation); + + return frame; +} + +Frame* TimelineActionCache::loadAnchorPointFrame (const rapidjson::Value& json) +{ + AnchorPointFrame* frame = AnchorPointFrame::create(); + + float anchorx = DICTOOL->getFloatValue_json(json, X); + float anchory = DICTOOL->getFloatValue_json(json, Y); + + frame->setAnchorPoint(Point(anchorx, anchory)); + + return frame; +} + +Frame* TimelineActionCache::loadInnerActionFrame(const rapidjson::Value& json) +{ + InnerActionFrame* frame = InnerActionFrame::create(); + + InnerActionType type = (InnerActionType)DICTOOL->getIntValue_json(json, INNER_ACTION); + int startFrame = DICTOOL->getIntValue_json(json, START_FRAME); + + frame->setInnerActionType(type); + frame->setStartFrameIndex(startFrame); + + return frame; +} + +Frame* TimelineActionCache::loadColorFrame(const rapidjson::Value& json) +{ + ColorFrame* frame = ColorFrame::create(); + + GLubyte alpha = (GLubyte)DICTOOL->getIntValue_json(json, ALPHA); + GLubyte red = (GLubyte)DICTOOL->getIntValue_json(json, RED); + GLubyte green = (GLubyte)DICTOOL->getIntValue_json(json, GREEN); + GLubyte blue = (GLubyte)DICTOOL->getIntValue_json(json, BLUE); + + frame->setAlpha(alpha); + frame->setColor(Color3B(red, green, blue)); + + return frame; +} + +Frame* TimelineActionCache::loadTextureFrame(const rapidjson::Value& json) +{ + TextureFrame* frame = TextureFrame::create(); + + const char* texture = DICTOOL->getStringValue_json(json, Value); + + if(texture != NULL) + frame->setTexture(texture); + + return frame; +} + +Frame* TimelineActionCache::loadEventFrame(const rapidjson::Value& json) +{ + EventFrame* frame = EventFrame::create(); + + const char* evnt = DICTOOL->getStringValue_json(json, Value); + + if(evnt != NULL) + frame->setEvent(evnt); + + return frame; +} + +Frame* TimelineActionCache::loadZOrderFrame(const rapidjson::Value& json) +{ + ZOrderFrame* frame = ZOrderFrame::create(); + + int zorder = DICTOOL->getIntValue_json(json, Value); + frame->setZOrder(zorder); + + return frame; +} + +} +} \ No newline at end of file diff --git a/cocos/editor-support/cocostudio/TimelineAction/CCTimelineActionCache.h b/cocos/editor-support/cocostudio/TimelineAction/CCTimelineActionCache.h new file mode 100644 index 0000000000..2d32b415a1 --- /dev/null +++ b/cocos/editor-support/cocostudio/TimelineAction/CCTimelineActionCache.h @@ -0,0 +1,89 @@ +/**************************************************************************** +Copyright (c) 2013 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +****************************************************************************/ + +#ifndef __CCTIMELINE_ACTION_CACHE_H__ +#define __CCTIMELINE_ACTION_CACHE_H__ + +#include "cocos2d.h" +#include "cocostudio/DictionaryHelper.h" + +#include "CCTimeLine.h" + +namespace cocostudio { +namespace timeline{ + +class TimelineAction; + +class TimelineActionCache +{ +public: + /** Gets the singleton */ + static TimelineActionCache* getInstance(); + + /** Destroys the singleton */ + static void destroyInstance(); + + void purge(); + + void init(); + + /** Remove action with filename, and also remove other resource relate with this file */ + void removeAction(const std::string& fileName); + + /** Clone a action with the specified name from the container. */ + TimelineAction* createAction(const std::string& fileName); + + TimelineAction* loadAnimationActionWithFile(const std::string& fileName); + TimelineAction* loadAnimationActionWithContent(const std::string&fileName, const std::string& content); +protected: + + Timeline* loadTimeline(const rapidjson::Value& json); + + Frame* loadVisibleFrame (const rapidjson::Value& json); + Frame* loadPositionFrame (const rapidjson::Value& json); + Frame* loadScaleFrame (const rapidjson::Value& json); + Frame* loadSkewFrame (const rapidjson::Value& json); + Frame* loadRotationSkewFrame(const rapidjson::Value& json); + Frame* loadRotationFrame (const rapidjson::Value& json); + Frame* loadAnchorPointFrame (const rapidjson::Value& json); + Frame* loadInnerActionFrame (const rapidjson::Value& json); + Frame* loadColorFrame (const rapidjson::Value& json); + Frame* loadTextureFrame (const rapidjson::Value& json); + Frame* loadEventFrame (const rapidjson::Value& json); + Frame* loadZOrderFrame (const rapidjson::Value& json); + +protected: + + typedef std::function FrameCreateFunc; + typedef std::pair Pair; + + std::unordered_map _funcs; + cocos2d::Map _animationActions; +}; + +} +} + + +#endif /*__CCTIMELINE_ACTION_CACHE_H__*/ diff --git a/cocos/editor-support/cocostudio/proj.win32/libCocosStudio.vcxproj b/cocos/editor-support/cocostudio/proj.win32/libCocosStudio.vcxproj index bcd24723d6..b745923b5b 100644 --- a/cocos/editor-support/cocostudio/proj.win32/libCocosStudio.vcxproj +++ b/cocos/editor-support/cocostudio/proj.win32/libCocosStudio.vcxproj @@ -42,6 +42,11 @@ + + + + + @@ -103,7 +108,11 @@ - + + + + + @@ -134,8 +143,8 @@ v100 v110 v110_xp - v120 - v120_xp + v120 + v120_xp Unicode @@ -144,8 +153,8 @@ v100 v110 v110_xp - v120 - v120_xp + v120 + v120_xp true Unicode @@ -206,4 +215,4 @@ - + \ No newline at end of file diff --git a/cocos/editor-support/cocostudio/proj.win32/libCocosStudio.vcxproj.filters b/cocos/editor-support/cocostudio/proj.win32/libCocosStudio.vcxproj.filters index 655cb64627..8983cd9162 100644 --- a/cocos/editor-support/cocostudio/proj.win32/libCocosStudio.vcxproj.filters +++ b/cocos/editor-support/cocostudio/proj.win32/libCocosStudio.vcxproj.filters @@ -82,6 +82,9 @@ {bc251d28-036e-4272-852b-bd25fd110b33} + + {2d371825-3c46-4901-850c-3bccf6b49efc} + @@ -228,6 +231,21 @@ reader\WidgetReader\PageViewReader + + TimelineAction + + + TimelineAction + + + TimelineAction + + + TimelineAction + + + TimelineAction + @@ -353,9 +371,6 @@ action - - trigger - trigger @@ -413,5 +428,20 @@ reader\WidgetReader\PageViewReader + + TimelineAction + + + TimelineAction + + + TimelineAction + + + TimelineAction + + + TimelineAction + - + \ No newline at end of file diff --git a/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioTimelineActionTest/TimelineActionTestScene.cpp b/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioTimelineActionTest/TimelineActionTestScene.cpp new file mode 100644 index 0000000000..9c5fc3bb1c --- /dev/null +++ b/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioTimelineActionTest/TimelineActionTestScene.cpp @@ -0,0 +1,225 @@ +#include "TimelineActionTestScene.h" +#include "../../testResource.h" +#include "renderer/CCRenderer.h" +#include "renderer/CCCustomCommand.h" + + +using namespace cocos2d; +using namespace cocostudio; + +Layer *NextAnimationTest(); +Layer *BackAnimationTest(); +Layer *RestartAnimationTest(); + +static int s_nActionIdx = -1; + + +Layer *CreateAnimationLayer(int index) +{ + Layer *pLayer = nullptr; + switch(index) + { + case TEST_ANIMATIONELEMENT: + pLayer = new TestTimelineAction(); + break; + default: + break; + } + + return pLayer; +} + + +Layer *NextAnimationTest() +{ + ++s_nActionIdx; + s_nActionIdx = s_nActionIdx % TEST_ANIMATION_LAYER_COUNT; + + Layer *pLayer = CreateAnimationLayer(s_nActionIdx); + pLayer->autorelease(); + + return pLayer; +} + +Layer *BackAnimationTest() +{ + --s_nActionIdx; + if( s_nActionIdx < 0 ) + s_nActionIdx += TEST_ANIMATION_LAYER_COUNT; + + Layer *pLayer = CreateAnimationLayer(s_nActionIdx); + pLayer->autorelease(); + + return pLayer; +} + +Layer *RestartAnimationTest() +{ + Layer *pLayer = CreateAnimationLayer(s_nActionIdx); + pLayer->autorelease(); + + return pLayer; +} + + +TimelineActionTestScene::TimelineActionTestScene(bool bPortrait) +{ + TestScene::init(); + + Sprite *bg = Sprite::create("armature/bg.jpg"); + bg->setPosition(VisibleRect::center()); + + float scaleX = VisibleRect::getVisibleRect().size.width / bg->getContentSize().width; + float scaleY = VisibleRect::getVisibleRect().size.height / bg->getContentSize().height; + + bg->setScaleX(scaleX); + bg->setScaleY(scaleY); + + addChild(bg); +} + +void TimelineActionTestScene::runThisTest() +{ + s_nActionIdx = -1; + addChild(NextAnimationTest()); + + Director::getInstance()->replaceScene(this); +} + +void TimelineActionTestScene::MainMenuCallback(Ref *pSender) +{ + //TestScene::MainMenuCallback(pSender); + + removeAllChildren(); +} + + + +void TimelineActionTestLayer::onEnter() +{ + + Layer::onEnter(); + + // add title and subtitle + std::string str = title(); + const char *pTitle = str.c_str(); + LabelTTF *label = LabelTTF::create(pTitle, "Arial", 18); + label->setColor(Color3B(0, 0, 0)); + addChild(label, 1, 10000); + label->setPosition( Point(VisibleRect::center().x, VisibleRect::top().y - 30) ); + + std::string strSubtitle = subtitle(); + if( ! strSubtitle.empty() ) + { + LabelTTF *l = LabelTTF::create(strSubtitle.c_str(), "Arial", 18); + l->setColor(Color3B(0, 0, 0)); + addChild(l, 1, 10001); + l->setPosition( Point(VisibleRect::center().x, VisibleRect::top().y - 60) ); + } + + // add menu + backItem = MenuItemImage::create(s_pathB1, s_pathB2, CC_CALLBACK_1(TimelineActionTestLayer::backCallback, this) ); + restartItem = MenuItemImage::create(s_pathR1, s_pathR2, CC_CALLBACK_1(TimelineActionTestLayer::restartCallback, this) ); + nextItem = MenuItemImage::create(s_pathF1, s_pathF2, CC_CALLBACK_1(TimelineActionTestLayer::nextCallback, this) ); + + Menu *menu = Menu::create(backItem, restartItem, nextItem, nullptr); + + menu->setPosition(Point::ZERO); + backItem->setPosition(Point(VisibleRect::center().x - restartItem->getContentSize().width * 2, VisibleRect::bottom().y + restartItem->getContentSize().height / 2)); + restartItem->setPosition(Point(VisibleRect::center().x, VisibleRect::bottom().y + restartItem->getContentSize().height / 2)); + nextItem->setPosition(Point(VisibleRect::center().x + restartItem->getContentSize().width * 2, VisibleRect::bottom().y + restartItem->getContentSize().height / 2)); + + addChild(menu, 100); + + setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR)); + +} +void TimelineActionTestLayer::onExit() +{ + removeAllChildren(); + + backItem = restartItem = nextItem = nullptr; + + TimelineActionCache::getInstance()->purge(); + NodeCache::getInstance()->purge(); + + Layer::onExit(); +} + +std::string TimelineActionTestLayer::title() const +{ + return "Armature Test Bed"; +} +std::string TimelineActionTestLayer::subtitle() const +{ + return ""; +} + +void TimelineActionTestLayer::restartCallback(Ref *pSender) +{ + Scene *s = new TimelineActionTestScene(); + s->addChild( RestartAnimationTest() ); + Director::getInstance()->replaceScene(s); + s->release(); +} + +Node* node = nullptr; +TimelineAction* action = nullptr; + +void TimelineActionTestLayer::nextCallback(Ref *pSender) +{ + // Scene *s = new TimelineActionTestScene(); + // s->addChild( NextAnimationTest() ); + // Director::getInstance()->replaceScene(s); + // s->release(); + + int frameIndex = action->getCurrentFrame(); + int duration = action->getDuration(); + + ++frameIndex; + frameIndex = frameIndex == duration ? 0 : frameIndex; + + action->gotoFrameAndPause(frameIndex); +} +void TimelineActionTestLayer::backCallback(Ref *pSender) +{ + // Scene *s = new TimelineActionTestScene(); + // s->addChild( BackAnimationTest() ); + // Director::getInstance()->replaceScene(s); + // s->release(); + + int frameIndex = action->getCurrentFrame(); + int duration = action->getDuration(); + + --frameIndex; + frameIndex = frameIndex == -1 ? duration-1 : frameIndex; + + action->gotoFrameAndPause(frameIndex); +} + +void TestTimelineAction::onEnter() +{ + TimelineActionTestLayer::onEnter(); + + FileUtils::getInstance()->addSearchPath("E:/cocos2d-x/cocos2d-x/tests/cpp-tests/Resources/TimelineAction"); + + for(int i=0; i<1; i++) + { + node = NodeCache::getInstance()->createNode("NewUi11123_1.json"); + action = TimelineActionCache::getInstance()->createAction("NewUi11123_1.json"); + + node->runAction(action); + action->gotoFrameAndPlay(0); + + //node->setScale(0.4f); + node->setPosition(100+i*5,160); + + addChild(node); + } + +} + +std::string TestTimelineAction::title() const +{ + return "Test AnimationElement"; +} \ No newline at end of file diff --git a/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioTimelineActionTest/TimelineActionTestScene.h b/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioTimelineActionTest/TimelineActionTestScene.h new file mode 100644 index 0000000000..a0501811b1 --- /dev/null +++ b/tests/cpp-tests/Classes/ExtensionsTest/CocoStudioTimelineActionTest/TimelineActionTestScene.h @@ -0,0 +1,57 @@ +#ifndef __ANIMATION_TEST_SCENE_H__ +#define __ANIMATION_TEST_SCENE_H__ + +#include "cocos2d.h" +#include "../../VisibleRect.h" +#include "../../testBasic.h" +#include "cocostudio/CocoStudio.h" + +using namespace cocostudio::timeline; + + +class TimelineActionTestScene : public TestScene +{ +public: + TimelineActionTestScene(bool bPortrait = false); + + virtual void runThisTest(); + + // The CallBack for back to the main menu scene + virtual void MainMenuCallback(Ref* pSender); +}; + +enum { + TEST_ANIMATIONELEMENT = 0, + + TEST_ANIMATION_LAYER_COUNT +}; + +class TimelineActionTestLayer : public Layer +{ +public: + virtual std::string title() const; + virtual std::string subtitle() const; + + virtual void restartCallback(Ref* pSender); + virtual void nextCallback(Ref* pSender); + virtual void backCallback(Ref* pSender); + + // overrides + virtual void onEnter() override; + virtual void onExit() override; + +protected: + MenuItemImage *restartItem; + MenuItemImage *nextItem; + MenuItemImage *backItem; +}; + + +class TestTimelineAction : public TimelineActionTestLayer +{ +public: + virtual void onEnter(); + virtual std::string title() const override; +}; + +#endif // __ANIMATION_SCENE_H__ \ No newline at end of file diff --git a/tests/cpp-tests/Classes/ExtensionsTest/ExtensionsTest.cpp b/tests/cpp-tests/Classes/ExtensionsTest/ExtensionsTest.cpp index 0f1d1dd795..d2a9a8d9a0 100644 --- a/tests/cpp-tests/Classes/ExtensionsTest/ExtensionsTest.cpp +++ b/tests/cpp-tests/Classes/ExtensionsTest/ExtensionsTest.cpp @@ -9,6 +9,7 @@ #include "TableViewTest/TableViewTestScene.h" #include "CocoStudioArmatureTest/ArmatureScene.h" +#include "CocoStudioTimelineActionTest/TimelineActionTestScene.h" #include "CocoStudioComponentsTest/ComponentsTestScene.h" #include "CocoStudioSceneTest/SceneEditorTest.h" @@ -78,6 +79,11 @@ static struct { scene->release(); } }, + { "CocoStudioTimelineActionTest", [](Ref *sender) { TimelineActionTestScene *scene = new TimelineActionTestScene(); + scene->runThisTest(); + scene->release(); + } + }, { "CocoStudioComponentsTest", [](Ref *sender) { runComponentsTestLayerTest(); } }, { "CocoStudioSceneTest", [](Ref *sender) { SceneEditorTestScene *scene = new SceneEditorTestScene(); diff --git a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj index 237d58b5ac..9c8e8daf26 100644 --- a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj +++ b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj @@ -159,6 +159,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\external\websockets\prebuilt\win32\*.*" "$(Ou + @@ -340,6 +341,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\external\websockets\prebuilt\win32\*.*" "$(Ou + diff --git a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters index 0429dd329f..f1b0a28bd5 100644 --- a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters +++ b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters @@ -325,6 +325,9 @@ {45e9becf-58e5-424e-903d-9bc7f9999d5b} + + {fa88df83-76d7-4f41-ad48-801dafd44889} + @@ -840,6 +843,9 @@ Classes\Sprite3DTest + + Classes\ExtensionsTest\CocoStudioTimelineActionTest + @@ -1553,5 +1559,8 @@ Classes\Sprite3DTest + + Classes\ExtensionsTest\CocoStudioTimelineActionTest + \ No newline at end of file