diff --git a/spine-cpp/includes/spine-cc/Atlas.h b/spine-cpp/includes/spine-cc/Atlas.h new file mode 100644 index 000000000..9f0d7b406 --- /dev/null +++ b/spine-cpp/includes/spine-cc/Atlas.h @@ -0,0 +1,42 @@ +#ifndef SPINE_ATLAS_H_ +#define SPINE_ATLAS_H_ + +#include "cocos2d.h" +#include + +USING_NS_CC; + +namespace spine { + +class AtlasPage: public BaseAtlasPage { +public: + ~AtlasPage (); + + CCTexture2D *texture; +}; + +// + +class AtlasRegion: public BaseAtlasRegion { +public: + AtlasPage *page; +}; + +// + +class Atlas: public BaseAtlas { +public: + Atlas (std::ifstream &file); + Atlas (std::istream &input); + Atlas (const std::string &text); + Atlas (const char *begin, const char *end); + + AtlasRegion* findRegion (const std::string &name); + +private: + virtual BaseAtlasPage* newAtlasPage (const std::string &name); + virtual BaseAtlasRegion* newAtlasRegion (BaseAtlasPage* page); +}; + +} /* namespace spine */ +#endif /* SPINE_ATLAS_H_ */ diff --git a/spine-cpp/includes/spine-cc/AtlasAttachmentLoader.h b/spine-cpp/includes/spine-cc/AtlasAttachmentLoader.h new file mode 100644 index 000000000..180effd0e --- /dev/null +++ b/spine-cpp/includes/spine-cc/AtlasAttachmentLoader.h @@ -0,0 +1,20 @@ +#ifndef SPINE_ATLASATTACHMENTLOADER_H_ +#define SPINE_ATLASATTACHMENTLOADER_H_ + +#include + +namespace spine { + +class Atlas; + +class AtlasAttachmentLoader: public BaseAttachmentLoader { +public: + Atlas *atlas; + + AtlasAttachmentLoader (Atlas *atlas); + + virtual Attachment* newAttachment (AttachmentType type, const std::string &name); +}; + +} /* namespace spine */ +#endif /* SPINE_ATLASATTACHMENTLOADER_H_ */ diff --git a/spine-cpp/includes/spine-cc/RegionAttachment.h b/spine-cpp/includes/spine-cc/RegionAttachment.h new file mode 100644 index 000000000..9aea4e813 --- /dev/null +++ b/spine-cpp/includes/spine-cc/RegionAttachment.h @@ -0,0 +1,26 @@ +#ifndef SPINE_REGIONATTACHMENT_H_ +#define SPINE_REGIONATTACHMENT_H_ + +#include "cocos2d.h" +#include + +USING_NS_CC; + +namespace spine { + +class Bone; +class AtlasRegion; + +class RegionAttachment: public BaseRegionAttachment { +public: + ccV3F_C4B_T2F_Quad vertices; + CCTexture2D *texture; + + RegionAttachment (AtlasRegion *region); + + virtual void updateWorldVertices (Bone *bone); + virtual void draw (Slot *slot); +}; + +} /* namespace spine */ +#endif /* SPINE_REGIONATTACHMENT_H_ */ diff --git a/spine-cpp/includes/spine-cc/Skeleton.h b/spine-cpp/includes/spine-cc/Skeleton.h new file mode 100644 index 000000000..10a51e248 --- /dev/null +++ b/spine-cpp/includes/spine-cc/Skeleton.h @@ -0,0 +1,23 @@ +#ifndef SPINE_SKELETON_H_ +#define SPINE_SKELETON_H_ + +#include "cocos2d.h" +#include + +USING_NS_CC; + +namespace spine { + +class Skeleton: public BaseSkeleton { +public: + std::vector vertexArray; + CCTexture2D *texture; // This is a bit ugly and means all region attachments must use the same textures. + CCTextureAtlas* texAtlas; + + Skeleton (SkeletonData *skeletonData); + + virtual void draw () ; +}; + +} /* namespace spine */ +#endif /* SPINE_SKELETON_H_ */ diff --git a/spine-cpp/includes/spine-cc/SkeletonJson.h b/spine-cpp/includes/spine-cc/SkeletonJson.h new file mode 100644 index 000000000..5d848bb43 --- /dev/null +++ b/spine-cpp/includes/spine-cc/SkeletonJson.h @@ -0,0 +1,18 @@ +#ifndef SKELETONJSON_H_ +#define SKELETONJSON_H_ + +#include + +namespace spine { + +class Atlas; + +class SkeletonJson: public BaseSkeletonJson { +public: + SkeletonJson (Atlas *atlas); + /** The SkeletonJson owns the attachmentLoader */ + SkeletonJson (BaseAttachmentLoader *attachmentLoader); +}; + +} /* namespace spine */ +#endif /* SKELETONJSON_H_ */ diff --git a/spine-cpp/includes/spine-cc/spine.h b/spine-cpp/includes/spine-cc/spine.h new file mode 100644 index 000000000..2be7d2098 --- /dev/null +++ b/spine-cpp/includes/spine-cc/spine.h @@ -0,0 +1,19 @@ +#ifndef SPINE_SPINE_H_ +#define SPINE_SPINE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#endif /* SF_SPINE_H_ */ diff --git a/spine-cpp/src/cocos2dx/CCSpineNode.cpp b/spine-cpp/src/cocos2dx/CCSpineNode.cpp new file mode 100644 index 000000000..13095b98a --- /dev/null +++ b/spine-cpp/src/cocos2dx/CCSpineNode.cpp @@ -0,0 +1,84 @@ +// +// CCSpineNode.cpp +// SpineExample +// +// Created by wu shengjin on 13-3-18. +// +// + +#include "CCSpineNode.h" +#include +#include + +#define FULL_PATH(a) CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(a) + + +CCSpineNode* CCSpineNode::createWithFileNames(const char* skeletonFileName, const char* atlasFileName) +{ + CCSpineNode* node = new CCSpineNode(); + if (node && node->initWithFiles(skeletonFileName, atlasFileName)) { + node->autorelease(); + return node; + } + + CC_SAFE_DELETE(node); + return NULL; +} + +bool CCSpineNode::initWithFiles(const char* skeletonFileName, const char* atlasFileName) +{ + std::ifstream atlasFile(FULL_PATH(atlasFileName)); + Atlas *atlas = new Atlas(atlasFile); + + m_skeletonJson = new SkeletonJson(atlas); + + std::ifstream skeletonFile(FULL_PATH(skeletonFileName)); + SkeletonData *skeletonData = m_skeletonJson->readSkeletonData(skeletonFile); + + + m_skeleton = new Skeleton(skeletonData); + m_skeleton->setToBindPose(); + m_skeleton->updateWorldTransform(); + + m_animTimer = 0.0f; + m_animation = 0; + m_loop = true; + + setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor)); + + scheduleUpdate(); + + return true; +} + +void CCSpineNode::playAnimation(const char* fileName, bool loop) +{ + CC_SAFE_DELETE(m_animation); + + std::ifstream animationFile(FULL_PATH(fileName)); + m_animation = m_skeletonJson->readAnimation(animationFile, m_skeleton->data); + + m_animTimer = 0.0f; + m_loop = loop; +} + +void CCSpineNode::update(float dt) +{ + if (m_animation && m_skeleton) + { + m_animTimer += dt; + + m_animation->apply(m_skeleton, m_animTimer, m_loop); + m_skeleton->updateWorldTransform(); + } +} + +void CCSpineNode::draw() +{ + CC_NODE_DRAW_SETUP(); + + if (m_skeleton) + m_skeleton->draw(); + + CCNode::draw(); +} diff --git a/spine-cpp/src/cocos2dx/CCSpineNode.h b/spine-cpp/src/cocos2dx/CCSpineNode.h new file mode 100644 index 000000000..50dd75d14 --- /dev/null +++ b/spine-cpp/src/cocos2dx/CCSpineNode.h @@ -0,0 +1,38 @@ +// +// CCSpineNode.h +// SpineExample +// +// Created by wu shengjin on 13-3-18. +// +// + +#ifndef __CCSpineNode__ +#define __CCSpineNode__ + +#include "cocos2d.h" +#include + +using namespace spine; + + +USING_NS_CC; + +class CCSpineNode : public CCNode { +public: + static CCSpineNode* createWithFileNames(const char* skeletonFileName, const char* atlasFileName); + bool initWithFiles(const char* skeletonFileName, const char* atlasFileName); + + void playAnimation(const char* fileName, bool loop = true); + + void update(float dt); + void draw(); +private: + SkeletonJson* m_skeletonJson; + Skeleton* m_skeleton; + Animation* m_animation; + + float m_animTimer; + bool m_loop; +}; + +#endif /* defined(__SpineExample__CCSpineNode__) */ diff --git a/spine-cpp/src/cocos2dx/HelloWorldScene.cpp b/spine-cpp/src/cocos2dx/HelloWorldScene.cpp new file mode 100755 index 000000000..2ce49d672 --- /dev/null +++ b/spine-cpp/src/cocos2dx/HelloWorldScene.cpp @@ -0,0 +1,45 @@ +#include "HelloWorldScene.h" +#include "SimpleAudioEngine.h" +#include "CCSpineNode.h" + +using namespace cocos2d; +using namespace CocosDenshion; + +CCScene* HelloWorld::scene() +{ + // 'scene' is an autorelease object + CCScene *scene = CCScene::create(); + + // 'layer' is an autorelease object + HelloWorld *layer = HelloWorld::create(); + + // add layer as a child to scene + scene->addChild(layer); + + // return the scene + return scene; +} + +// on "init" you need to initialize your instance +bool HelloWorld::init() +{ + ////////////////////////////// + // 1. super init first + if ( !CCLayer::init() ) + { + return false; + } + + CCSpineNode* spineNode = CCSpineNode::createWithFileNames("./data/spineboy-skeleton.json", "./data/spineboy.atlas"); + + spineNode->playAnimation("./data/spineboy-walk.json"); + + CCSize winSize = CCDirector::sharedDirector()->getWinSize(); + spineNode->setPosition(ccp(winSize.width/2, 0)); + + + addChild(spineNode); + + + return true; +} diff --git a/spine-cpp/src/cocos2dx/HelloWorldScene.h b/spine-cpp/src/cocos2dx/HelloWorldScene.h new file mode 100755 index 000000000..2f5934799 --- /dev/null +++ b/spine-cpp/src/cocos2dx/HelloWorldScene.h @@ -0,0 +1,20 @@ +#ifndef __HELLOWORLD_SCENE_H__ +#define __HELLOWORLD_SCENE_H__ + +#include "cocos2d.h" + +class HelloWorld : public cocos2d::CCLayer +{ +public: + // Method 'init' in cocos2d-x returns bool, instead of 'id' in cocos2d-iphone (an object pointer) + virtual bool init(); + + // there's no 'id' in cpp, so we recommend to return the class instance pointer + static cocos2d::CCScene* scene(); + + // preprocessor macro for "static create()" constructor ( node() deprecated ) + CREATE_FUNC(HelloWorld); + +}; + +#endif // __HELLOWORLD_SCENE_H__ diff --git a/spine-cpp/src/spine-cc/Atlas.cpp b/spine-cpp/src/spine-cc/Atlas.cpp new file mode 100644 index 000000000..ce390074b --- /dev/null +++ b/spine-cpp/src/spine-cc/Atlas.cpp @@ -0,0 +1,43 @@ +#include + +namespace spine { + +AtlasPage::~AtlasPage () { + CC_SAFE_RELEASE(texture); +} + +// + +Atlas::Atlas (std::ifstream &file) { + load(file); +} + +Atlas::Atlas (std::istream &input) { + load(input); +} + +Atlas::Atlas (const std::string &text) { + load(text); +} + +Atlas::Atlas (const char *begin, const char *end) { + load(begin, end); +} + +BaseAtlasPage* Atlas::newAtlasPage (const std::string &name) { + AtlasPage *page = new AtlasPage(); + page->texture = CCTextureCache::sharedTextureCache()->addImage(name.c_str()); + return page; +} + +BaseAtlasRegion* Atlas::newAtlasRegion (BaseAtlasPage* page) { + AtlasRegion *region = new AtlasRegion(); + region->page = reinterpret_cast(page); + return region; +} + +AtlasRegion* Atlas::findRegion (const std::string &name) { + return reinterpret_cast(BaseAtlas::findRegion(name)); +} + +} /* namespace spine */ diff --git a/spine-cpp/src/spine-cc/AtlasAttachmentLoader.cpp b/spine-cpp/src/spine-cc/AtlasAttachmentLoader.cpp new file mode 100644 index 000000000..b6bb98ef0 --- /dev/null +++ b/spine-cpp/src/spine-cc/AtlasAttachmentLoader.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +namespace spine { + +AtlasAttachmentLoader::AtlasAttachmentLoader (Atlas *atlas) : + atlas(atlas) { +} + +Attachment* AtlasAttachmentLoader::newAttachment (AttachmentType type, const std::string &name) { + switch (type) { + case region: { + AtlasRegion *region = atlas->findRegion(name); + if (!region) throw std::runtime_error("Atlas region not found: " + name); + return new RegionAttachment(region); + } + default: + throw std::runtime_error("Unknown attachment type: " + type); + } +} + +} /* namespace spine */ diff --git a/spine-cpp/src/spine-cc/RegionAttachment.cpp b/spine-cpp/src/spine-cc/RegionAttachment.cpp new file mode 100644 index 000000000..7d6977968 --- /dev/null +++ b/spine-cpp/src/spine-cc/RegionAttachment.cpp @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include + +namespace spine { + +RegionAttachment::RegionAttachment (AtlasRegion *region) { + texture = region->page->texture; + const CCSize& texSize = texture->getContentSizeInPixels(); + float u = region->x / texSize.width; + float u2 = (region->x + region->width) / texSize.width; + float v = region->y / texSize.height; + float v2 = (region->y + region->height) / texSize.height; + if (region->rotate) { + vertices.tl.texCoords.u = u; + vertices.tl.texCoords.v = v2; + vertices.tr.texCoords.u = u; + vertices.tr.texCoords.v = v; + vertices.br.texCoords.u = u2; + vertices.br.texCoords.v = v; + vertices.bl.texCoords.u = u2; + vertices.bl.texCoords.v = v2; + } else { + vertices.bl.texCoords.u = u; + vertices.bl.texCoords.v = v2; + vertices.tl.texCoords.u = u; + vertices.tl.texCoords.v = v; + vertices.tr.texCoords.u = u2; + vertices.tr.texCoords.v = v; + vertices.br.texCoords.u = u2; + vertices.br.texCoords.v = v2; + } +} + +void RegionAttachment::draw (Slot *slot) { + Skeleton* skeleton = (Skeleton*)slot->skeleton; + + GLubyte r = skeleton->r * slot->r * 255; + GLubyte g = skeleton->g * slot->g * 255; + GLubyte b = skeleton->b * slot->b * 255; + GLubyte a = skeleton->a * slot->a * 255; + vertices.bl.colors.r = r; + vertices.bl.colors.g = g; + vertices.bl.colors.b = b; + vertices.bl.colors.a = a; + vertices.tl.colors.r = r; + vertices.tl.colors.g = g; + vertices.tl.colors.b = b; + vertices.tl.colors.a = a; + vertices.tr.colors.r = r; + vertices.tr.colors.g = g; + vertices.tr.colors.b = b; + vertices.tr.colors.a = a; + vertices.br.colors.r = r; + vertices.br.colors.g = g; + vertices.br.colors.b = b; + vertices.br.colors.a = a; + + updateWorldVertices(slot->bone); + + // SMFL doesn't handle batching for us, so we'll just force a single texture per skeleton. + skeleton->texture = texture; + skeleton->vertexArray.push_back(vertices); +} + +void RegionAttachment::updateWorldVertices (spine::Bone *bone) { + vertices.bl.vertices.x = offset[0] * bone->m00 + offset[1] * bone->m01 + bone->worldX; + vertices.bl.vertices.y = offset[0] * bone->m10 + offset[1] * bone->m11 + bone->worldY; + vertices.bl.vertices.z = 0; + vertices.tl.vertices.x = offset[2] * bone->m00 + offset[3] * bone->m01 + bone->worldX; + vertices.tl.vertices.y = offset[2] * bone->m10 + offset[3] * bone->m11 + bone->worldY; + vertices.tl.vertices.z = 0; + vertices.tr.vertices.x = offset[4] * bone->m00 + offset[5] * bone->m01 + bone->worldX; + vertices.tr.vertices.y = offset[4] * bone->m10 + offset[5] * bone->m11 + bone->worldY; + vertices.tr.vertices.z = 0; + vertices.br.vertices.x = offset[6] * bone->m00 + offset[7] * bone->m01 + bone->worldX; + vertices.br.vertices.y = offset[6] * bone->m10 + offset[7] * bone->m11 + bone->worldY; + vertices.br.vertices.z = 0; +} + +} /* namespace spine */ diff --git a/spine-cpp/src/spine-cc/Skeleton.cpp b/spine-cpp/src/spine-cc/Skeleton.cpp new file mode 100644 index 000000000..d858047a8 --- /dev/null +++ b/spine-cpp/src/spine-cc/Skeleton.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + + +namespace spine { + +Skeleton::Skeleton (SkeletonData *skeletonData) : + BaseSkeleton(skeletonData), + texAtlas(0), + texture(0) { + + +} + +void Skeleton::draw () { + const_cast(this)->vertexArray.clear(); + for (int i = 0, n = slots.size(); i < n; i++) + if (slots[i]->attachment) slots[i]->attachment->draw(slots[i]); + + if (texture == 0) + return; + + if (texAtlas == 0) + { + texAtlas = CCTextureAtlas::createWithTexture(texture, vertexArray.size()); + texAtlas->retain(); + } + + for (int i=0; iupdateQuad(&vertexArray[i], i); + } + + texAtlas->drawQuads(); +} + +} /* namespace spine */ diff --git a/spine-cpp/src/spine-cc/SkeletonJson.cpp b/spine-cpp/src/spine-cc/SkeletonJson.cpp new file mode 100644 index 000000000..2585a4975 --- /dev/null +++ b/spine-cpp/src/spine-cc/SkeletonJson.cpp @@ -0,0 +1,16 @@ +#include +#include + +namespace spine { + +SkeletonJson::SkeletonJson (BaseAttachmentLoader *attachmentLoader) : + BaseSkeletonJson(attachmentLoader) { + yDown = false; +} + +SkeletonJson::SkeletonJson (Atlas *atlas) : + BaseSkeletonJson(new AtlasAttachmentLoader(atlas)) { + yDown = false; +} + +} /* namespace spine */