#include #include "RUQCoreSpine.h" #include #include "RUUtils.h" #include "AudioEngine.h" #include "RedWise.hpp" using namespace spine; NS_RU_BEGIN std::unordered_map _mAtlasMap; std::unordered_map _mSkeletonDataMap; Cocos2dTextureLoader textureLoader; Atlas* QCoreSpine::getAtlasByName(std::string name){ auto iter = _mAtlasMap.find(name); if(iter!=_mAtlasMap.end()){ return iter->second; }else{ Atlas* atlas = new (__FILE__, __LINE__) Atlas(name.c_str(), &textureLoader, true); CCASSERT(atlas, "Error reading atlas file."); _mAtlasMap.insert(std::pair(name,atlas)); return atlas; } return nullptr; } SkeletonData* QCoreSpine::getSkeletonDataByName(std::string name,Atlas* atlas){ auto iter = _mSkeletonDataMap.find(name); if(iter!=_mSkeletonDataMap.end()){ return iter->second; }else{ auto attachmentLoader = new (__FILE__, __LINE__) Cocos2dAtlasAttachmentLoader(atlas); // auto attachmentLoader = SUPER(Cocos2dAttachmentLoader_create(atlas)); SkeletonBinary binary(attachmentLoader); binary.setScale(1.0f); SkeletonData* skeletonData = binary.readSkeletonDataFile(name.c_str()); CCASSERT(skeletonData, !binary.getError().isEmpty() ? binary.getError().buffer() : "Error reading skeleton data."); _mSkeletonDataMap.insert(std::pair(name,skeletonData)); return skeletonData; } return nullptr; } QCoreSpine* QCoreSpine::createWithData (SkeletonData* skeletonData, bool ownsSkeletonData) { QCoreSpine* node = new QCoreSpine(); node->initWithData(skeletonData, ownsSkeletonData); // FIXME how to set data name? node->autorelease(); node->setContent(); return node; } QCoreSpine* QCoreSpine::createWithJsonFile (const std::string& skeletonJsonFile, Atlas* atlas, float scale) { QCoreSpine* node = new QCoreSpine(); node->initWithJsonFile(skeletonJsonFile, atlas, scale); node->setDataName(skeletonJsonFile); node->autorelease(); node->setContent(); return node; } QCoreSpine* QCoreSpine::createWithJsonFile (const std::string& skeletonJsonFile, const std::string& atlasFile, float scale) { QCoreSpine* node = new QCoreSpine(); node->initWithJsonFile(skeletonJsonFile, atlasFile.c_str(), scale); node->setDataName(skeletonJsonFile); node->autorelease(); node->setContent(); return node; } QCoreSpine* QCoreSpine::createWithBinaryFile (const std::string& skeletonBinaryFile, Atlas* atlas, float scale) { QCoreSpine* node = new QCoreSpine(); node->initWithBinaryFile(skeletonBinaryFile, atlas, scale); node->setDataName(skeletonBinaryFile); node->autorelease(); node->setContent(); return node; } QCoreSpine* QCoreSpine::createWithBinaryFile (const std::string& skeletonBinaryFile, const std::string& atlasFile, float scale) { QCoreSpine* node = new QCoreSpine(); node->initWithBinaryFile(skeletonBinaryFile, atlasFile.c_str(), scale); node->setDataName(skeletonBinaryFile); node->autorelease(); node->setContent(); return node; } QCoreSpine* QCoreSpine::createWithBinaryFileAndCache (const std::string& skeletonBinaryFile, const std::string& atlasFile, float scale) { Atlas* atlas = getAtlasByName(atlasFile); // Atlas_createFromFile(atlasFile.c_str(), 0); auto skeletonData = getSkeletonDataByName(skeletonBinaryFile, atlas); reScaleSkeletonData(skeletonData,scale); QCoreSpine* node = createWithData(skeletonData,false); node->setScale(scale); node->setContent(); return node; } QCoreSpine::QCoreSpine () { _cbOnExit = nullptr; _dataName = ""; } QCoreSpine::~QCoreSpine() { } void QCoreSpine::onExit() { if (_cbOnExit != nullptr) { _cbOnExit(_dataName, this); } Node::onExit(); } SkeletonData* QCoreSpine::getSkeletonData(){ SkeletonData*skData =getSkeleton()->getData(); return skData; } float QCoreSpine::getAnimTime(std::string name){ float durTime = 0.0f; spine::Animation* tAnimation= findAnimation(name); if (tAnimation) { durTime = tAnimation->getDuration(); } return durTime; } void QCoreSpine::playBackAnim(const char* name,const std::function &func, bool isDeleteSelf,bool isLoop){ _mCallFunc = func; auto track = setAnimation(0, name, isLoop); if(track){ setTrackCompleteListener(track, [=] (TrackEntry* entry) { if(_mCallFunc){ this->_mCallFunc(); } if(isDeleteSelf){ this->runAction(RemoveSelf::create()); } }); float dur = getAnimTime(name); track->setTrackTime(dur); setTimeScale(-1); } } void QCoreSpine::playAnim(string name,const std::function &func, bool isDeleteSelf ,bool isLoop,float delay,bool delFunc){ if(delay>0){ auto node = Node::create(); this->addChild(node); node->runAction(Sequence::create(DelayTime::create(delay),CallFunc::create([=](){ resetVar(); _mCallFunc = func; auto track = setAnimation(0, name, isLoop); this->setTrackCompleteListener(track, [=](TrackEntry* entry){ if(_mCallFunc){ this->_mCallFunc(); if(delFunc){ _mCallFunc = nullptr; } } if(isDeleteSelf){ this->runAction(RemoveSelf::create()); } }); }),RemoveSelf::create(),NULL)); }else{ resetVar(); _mCallFunc = func; auto track = setAnimation(0, name, isLoop); this->setTrackCompleteListener(track, [=](TrackEntry* entry){ if(_mCallFunc){ if(delFunc){ this->_mCallFunc = nullptr; } func();//回调可能会把自己删掉的,所以最后调 } if(isDeleteSelf){ this->runAction(RemoveSelf::create()); } }); } } void QCoreSpine::playAnimN(string name,const std::function &funcN, bool isDeleteSelf ,bool isLoop ){ resetVar(); _mCallFuncN = funcN; auto track = setAnimation(0, name, isLoop); this->setTrackCompleteListener(track, [=](TrackEntry* entry){ if(_mCallFuncN){ this->_mCallFuncN(this); } if(isDeleteSelf){ this->runAction(RemoveSelf::create()); } }); } void QCoreSpine::playAnimInRange(const char* name){ resetVar(); int count = getSkeleton()->getData()->getAnimations().size(); spine::Vector sparr = getSkeleton()->getData()->getAnimations(); for(int i = 0;igetName().buffer(),name,len); if(p == 0){ _randomNames.push_back(sp->getName().buffer()); } } playRandomAnim(); } void QCoreSpine::playAnimInRangeWithArray(std::vector randomNames ,std::vector randomRates){ resetVar(); _randomNames = randomNames; _randomRates = randomRates; playRandomAnim(); } void QCoreSpine::playRandomAnim(){ bool v = false; if (_randomNames.size() > 0) { if (_randomRates.size() > 0) { CCASSERT(_randomNames.size() == _randomRates.size() , "有问题"); string animName = randomObjByRatio(_randomNames,_randomRates); v = true; setAnimation(0, animName, false); } } if(v){ _mComplete = [=](){ playRandomAnim(); }; } } void QCoreSpine::setContent(){ this->setEventListener([=](spine::TrackEntry* entry, spine::Event* event){ EventData eData = event->getData(); if (eData.getAudioPath().buffer()) { ///spine的声音事件,强制截取后缀改为redwise事件 // if (RedWise::getInstance()->isSFXEnable()) { // const std::string& mp3FileName = eData.getName().buffer(); // const std::string& eventName = mp3FileName.substr(0, mp3FileName.rfind(".")); // RedWise::getInstance()->postEvent(eventName); // } } else { ///其他spine事件 const char* evenName = eData.getName().buffer(); if (_mCallEvent) { _mCallEvent(entry,evenName); } } }); setCompleteListener([=] (TrackEntry* entry) { if(_mComplete){ _mComplete(); } }); } void QCoreSpine::setEventCallBack(const std::function &func){ _mCallEvent = func; } void QCoreSpine::reScaleSkeletonData(SkeletonData* skeletonData,float scale){ return; int i; for (i = 0; i < skeletonData->getBones().size(); ++i) { BoneData* data = skeletonData->getBones()[i]; data->setScaleX(data->getScaleX()* scale);// *= scale; data->setScaleY(data->getScaleY()* scale); data->setLength(data->getLength()* scale); } // for (i = 0; i < skeletonData->getTransformConstraints().size(); ++i) { // TransformConstraintData* data = skeletonData->getTransformConstraints()[i]; // data->offsetX *= scale; // data->offsetY *= scale; // } for (i = 0; i < skeletonData->getPathConstraints().size(); ++i) { PathConstraintData* data = skeletonData->getPathConstraints()[i]; if (data->getPositionMode() == PositionMode_Fixed) data->setPosition(data->getPosition()*scale);// *= scale; if (data->getSpacingMode() == SpacingMode_Length || data->getSpacingMode() == SpacingMode_Fixed) data->setSpacing(data->getSpacing() * scale);// *= scale; } } void QCoreSpine::changeToOtherParent(Node* newParent) { this->retain(); std::function cbBack = _cbOnExit; _cbOnExit = nullptr; this->removeFromParentAndCleanup(false); _cbOnExit = cbBack; newParent->addChild(this); this->release(); } std::function QCoreSpine::setCbOnExit(std::function cb) { auto t = _cbOnExit; _cbOnExit = cb; return t; } void QCoreSpine::setDataName(const string& name) { int pos = name.find("."); if (pos != -1) { _dataName = name.substr(0, pos); } else { _dataName = name; } } void QCoreSpine::changeSkeleton(const std::string& skeletonJsonFile, const std::string& atlasFile, float scale) { if (_ownsAnimationStateData) { if (_state) { delete _state->getData(); delete _state; } } if (_ownsSkeletonData && _skeleton) { delete _skeleton->getData(); } if (_ownsSkeleton && _skeleton) { delete _skeleton; } if (_ownsAtlas && _atlas) { delete _atlas; } if (_attachmentLoader) delete _attachmentLoader; if (_clipper) { delete _clipper; } this->initWithBinaryFile(skeletonJsonFile, atlasFile,scale); this->setDataName(skeletonJsonFile); } void QCoreSpine::resetVar(){ clearTracks(); _mCallFunc = nullptr; _mCallFuncN = nullptr; _mCallEvent = nullptr; _mComplete = nullptr; _randomNames.clear(); _randomRates.clear(); } string QCoreSpine::getRunningSequenceName(){ if(_state){ auto trackEntry = this->getCurrent(); if(trackEntry){ auto anim = trackEntry->getAnimation(); if(anim){ return string(anim->getName().buffer()); } } } return ""; } #define PROPERTY_SPINE_JSON_NAME "jsonName" #define PROPERTY_SPINE_ATLAS_NAME "atlasName" #define PROPERTY_SPINE_ANIM_NAME "curAnimName" #define PROPERTY_SPINE_SCALE "spineScale" #define PROPERTY_SPINE_LOOP "loop" void QCoreSpineLoader::onHandlePropTypeString(cocos2d::Node * pNode, cocos2d::Node * pParent, const char* pPropertyName, const char * pString, redream::REDReader * ccbReader) { if(strcmp(pPropertyName, PROPERTY_SPINE_JSON_NAME) == 0) { _skelName = pString; checkRefreshSpine(pNode); } else if(strcmp(pPropertyName, PROPERTY_SPINE_ATLAS_NAME) == 0) { _atlasName = pString; checkRefreshSpine(pNode); } else if(strcmp(pPropertyName, PROPERTY_SPINE_ANIM_NAME) == 0) { _curAnimName = pString; checkRefreshSpine(pNode); } else { QCoreSpineLoader::onHandlePropTypeString(pNode, pParent, pPropertyName, pString, ccbReader); } } void QCoreSpineLoader::onHandlePropTypeFloat(cocos2d::Node * pNode, cocos2d::Node * pParent, const char* pPropertyName, float pFloat, redream::REDReader * ccbReader) { if(strcmp(pPropertyName, PROPERTY_SPINE_SCALE) == 0) { _spineScale = pFloat; checkRefreshSpine(pNode); }else { QCoreSpineLoader::onHandlePropTypeFloatScale(pNode, pParent, pPropertyName, pFloat, ccbReader); } } void QCoreSpineLoader::onHandlePropTypeCheck(cocos2d::Node * pNode, cocos2d::Node * pParent, const char* pPropertyName, bool pCheck, redream::REDReader * ccbReader) { if(strcmp(pPropertyName, PROPERTY_SPINE_LOOP) == 0) { _loop = pCheck; checkRefreshSpine(pNode); }else { QCoreSpineLoader::onHandlePropTypeCheck(pNode, pParent, pPropertyName, pCheck, ccbReader); } } void QCoreSpineLoader::checkRefreshSpine(cocos2d::Node * pNode) { if (_skelName.length() > 0 && _atlasName.length() > 0 && _spineScale > 0.0f) { QCoreSpine* spine = (QCoreSpine*)pNode; if (spine) { spine->changeSkeleton(_skelName,_atlasName,_spineScale); if (_curAnimName.length() > 0) { spine->setAnimation(0, _curAnimName, _loop); } } } } float QCoreSpine::getAnimDuration(std::string name){ float durTime = 0.0f; spine::Animation* tAnimation= findAnimation(name); if (tAnimation) { durTime = tAnimation->getDuration(); } return durTime; } NS_RU_END