GAFObject* GAFObject::_instantiateObject(uint32_t id, GAFCharacterType type, uint32_t reference, bool isMask) { GAFObject* result = nullptr; if (type == GAFCharacterType::Timeline) { result = encloseNewTimeline(reference); } else if (type == GAFCharacterType::TextField) { TextsData_t::const_iterator it = m_timeline->getTextsData().find(reference); if (it != m_timeline->getTextsData().end()) { GAFTextField *tf = new GAFTextField(); tf->initWithTextData(it->second); result = tf; } } else if (type == GAFCharacterType::Texture) { GAFTextureAtlas* atlas = m_timeline->getTextureAtlas(); const GAFTextureAtlas::Elements_t& elementsMap = atlas->getElements(); cocos2d::SpriteFrame * spriteFrame = nullptr; GAFTextureAtlas::Elements_t::const_iterator elIt = elementsMap.find(reference); // Search for atlas element by its xref assert(elIt != elementsMap.end()); const GAFTextureAtlasElement* txElemet = nullptr; if (elIt != elementsMap.end()) { txElemet = elIt->second; GAFAssetTextureManager* txMgr = m_asset->getTextureManager(); cocos2d::Texture2D * texture = txMgr->getTextureById(txElemet->atlasIdx + 1); if (texture) { spriteFrame = cocos2d::SpriteFrame::createWithTexture(texture, txElemet->bounds); } else { CCLOGERROR("Cannot add sub object with Id: %d, atlas with idx: %d not found.", id, txElemet->atlasIdx); } } if (spriteFrame) { if (!isMask) result = new GAFMovieClip(); else result = new GAFMask(); result->initWithSpriteFrame(spriteFrame); result->objectIdRef = id; cocos2d::Vect pt = cocos2d::Vect(0 - (0 - (txElemet->pivotPoint.x / result->getContentSize().width)), 0 + (1 - (txElemet->pivotPoint.y / result->getContentSize().height))); result->setAnchorPoint(pt); if (txElemet->scale != 1.0f) { result->setAtlasScale(1.0f / txElemet->scale); } result->setBlendFunc(cocos2d::BlendFunc::ALPHA_PREMULTIPLIED); } } if (result) result->setTimelineParentObject(this); return result; }
void GAFObject::realizeFrame(cocos2d::Node* out, uint32_t frameIndex) { const AnimationFrames_t& animationFrames = m_timeline->getAnimationFrames(); if (animationFrames.size() <= frameIndex) { return; } GAFAnimationFrame *currentFrame = animationFrames[frameIndex]; const GAFAnimationFrame::SubobjectStates_t& states = currentFrame->getObjectStates(); for (const GAFSubobjectState* state : states) { GAFObject* subObject = m_displayList[state->objectIdRef]; CCASSERT(subObject, "Error. SubObject with current ID not found"); if (!subObject) continue; if (state->colorMults()[GAFColorTransformIndex::GAFCTI_A] >= 0.f && subObject->m_isInResetState) { subObject->m_currentFrame = subObject->m_currentSequenceStart; } subObject->m_isInResetState = state->colorMults()[GAFColorTransformIndex::GAFCTI_A] < 0.f; if (!state->isVisible()) continue; if (subObject->m_charType == GAFCharacterType::Timeline) { if (!subObject->m_isInResetState) { cocos2d::AffineTransform stateTransform = state->affineTransform; float csf = m_timeline->usedAtlasScale(); stateTransform.tx *= csf; stateTransform.ty *= csf; cocos2d::AffineTransform t = GAF_CGAffineTransformCocosFormatFromFlashFormat(state->affineTransform); subObject->setAdditionalTransform(t); subObject->m_parentFilters.clear(); const Filters_t& filters = state->getFilters(); subObject->m_parentFilters.insert(subObject->m_parentFilters.end(), filters.begin(), filters.end()); const float* cm = state->colorMults(); subObject->m_parentColorTransforms[0] = cocos2d::Vec4( m_parentColorTransforms[0].x * cm[0], m_parentColorTransforms[0].y * cm[1], m_parentColorTransforms[0].z * cm[2], m_parentColorTransforms[0].w * cm[3]); subObject->m_parentColorTransforms[1] = cocos2d::Vec4(state->colorOffsets()) + m_parentColorTransforms[1]; if (m_masks[state->objectIdRef]) { rearrangeSubobject(out, m_masks[state->objectIdRef], state->zIndex); } else { //subObject->removeFromParentAndCleanup(false); if (state->maskObjectIdRef == IDNONE) { rearrangeSubobject(out, subObject, state->zIndex); } else { // If the state has a mask, then attach it // to the clipping node. Clipping node will be attached on its state auto mask = m_masks[state->maskObjectIdRef]; CCASSERT(mask, "Error. No mask found for this ID"); if (mask) rearrangeSubobject(mask, subObject, state->zIndex); } } subObject->step(); } } else if (subObject->m_charType == GAFCharacterType::Texture) { cocos2d::Vect prevAP = subObject->getAnchorPoint(); cocos2d::Size prevCS = subObject->getContentSize(); #if ENABLE_RUNTIME_FILTERS if (subObject->m_objectType == GAFObjectType::MovieClip) { // Validate sprite type (w/ or w/o filter) const Filters_t& filters = state->getFilters(); GAFFilterData* filter = NULL; GAFMovieClip* mc = static_cast<GAFMovieClip*>(subObject); if (m_parentFilters.size() > 0) { filter = *m_parentFilters.begin(); } else if (filters.size() > 0) { filter = *filters.begin(); } if (filter) { filter->apply(mc); } if (!filter || filter->getType() != GAFFilterType::GFT_Blur) { mc->setBlurFilterData(nullptr); } if (!filter || filter->getType() != GAFFilterType::GFT_ColorMatrix) { mc->setColorMarixFilterData(nullptr); } if (!filter || filter->getType() != GAFFilterType::GFT_Glow) { mc->setGlowFilterData(nullptr); } if (!filter || filter->getType() != GAFFilterType::GFT_DropShadow) { GAFDropShadowFilterData::reset(mc); } } #endif cocos2d::Size newCS = subObject->getContentSize(); cocos2d::Vect newAP = cocos2d::Vect(((prevAP.x - 0.5f) * prevCS.width) / newCS.width + 0.5f, ((prevAP.y - 0.5f) * prevCS.height) / newCS.height + 0.5f); subObject->setAnchorPoint(newAP); if (m_masks[state->objectIdRef]) { rearrangeSubobject(out, m_masks[state->objectIdRef], state->zIndex); } else { //subObject->removeFromParentAndCleanup(false); if (state->maskObjectIdRef == IDNONE) { rearrangeSubobject(out, subObject, state->zIndex); } else { // If the state has a mask, then attach it // to the clipping node. Clipping node will be attached on its state auto mask = m_masks[state->maskObjectIdRef]; CCASSERT(mask, "Error. No mask found for this ID"); if (mask) rearrangeSubobject(mask, subObject, state->zIndex); } } cocos2d::AffineTransform stateTransform = state->affineTransform; float csf = m_timeline->usedAtlasScale(); stateTransform.tx *= csf; stateTransform.ty *= csf; cocos2d::AffineTransform t = GAF_CGAffineTransformCocosFormatFromFlashFormat(state->affineTransform); if (isFlippedX() || isFlippedY()) { float flipMulX = isFlippedX() ? -1 : 1; float flipOffsetX = isFlippedX() ? getContentSize().width - m_asset->getHeader().frameSize.getMinX() : 0; float flipMulY = isFlippedY() ? -1 : 1; float flipOffsetY = isFlippedY() ? -getContentSize().height + m_asset->getHeader().frameSize.getMinY() : 0; cocos2d::AffineTransform flipCenterTransform = cocos2d::AffineTransformMake(flipMulX, 0, 0, flipMulY, flipOffsetX, flipOffsetY); t = AffineTransformConcat(t, flipCenterTransform); } subObject->setExternalTransform(t); if (subObject->m_objectType == GAFObjectType::MovieClip) { GAFMovieClip* mc = static_cast<GAFMovieClip*>(subObject); float colorMults[4] = { state->colorMults()[0] * m_parentColorTransforms[0].x, state->colorMults()[1] * m_parentColorTransforms[0].y, state->colorMults()[2] * m_parentColorTransforms[0].z, state->colorMults()[3] * m_parentColorTransforms[0].w }; float colorOffsets[4] = { state->colorOffsets()[0] + m_parentColorTransforms[1].x, state->colorOffsets()[1] + m_parentColorTransforms[1].y, state->colorOffsets()[2] + m_parentColorTransforms[1].z, state->colorOffsets()[3] + m_parentColorTransforms[1].w }; mc->setColorTransform(colorMults, colorOffsets); } } else if (subObject->m_charType == GAFCharacterType::TextField) { GAFTextField *tf = static_cast<GAFTextField*>(subObject); rearrangeSubobject(out, subObject, state->zIndex); cocos2d::AffineTransform stateTransform = state->affineTransform; float csf = m_timeline->usedAtlasScale(); stateTransform.tx *= csf; stateTransform.ty *= csf; cocos2d::AffineTransform t = GAF_CGAffineTransformCocosFormatFromFlashFormat(state->affineTransform); if (isFlippedX() || isFlippedY()) { float flipMulX = isFlippedX() ? -1 : 1; float flipOffsetX = isFlippedX() ? getContentSize().width - m_asset->getHeader().frameSize.getMinX() : 0; float flipMulY = isFlippedY() ? -1 : 1; float flipOffsetY = isFlippedY() ? -getContentSize().height + m_asset->getHeader().frameSize.getMinY() : 0; cocos2d::AffineTransform flipCenterTransform = cocos2d::AffineTransformMake(flipMulX, 0, 0, flipMulY, flipOffsetX, flipOffsetY); t = AffineTransformConcat(t, flipCenterTransform); } subObject->setExternalTransform(t); } if (state->isVisible()) { subObject->m_lastVisibleInFrame = frameIndex + 1; } } GAFAnimationFrame::TimelineActions_t timelineActions = currentFrame->getTimelineActions(); for (GAFTimelineAction action : timelineActions) { switch (action.getType()) { case GAFActionType::Stop: pauseAnimation(); break; case GAFActionType::Play: resumeAnimation(); break; case GAFActionType::GotoAndStop: gotoAndStop(action.getParam(GAFTimelineAction::PI_FRAME)); break; case GAFActionType::GotoAndPlay: gotoAndPlay(action.getParam(GAFTimelineAction::PI_FRAME)); break; case GAFActionType::DispatchEvent: _eventDispatcher->dispatchCustomEvent(action.getParam(GAFTimelineAction::PI_EVENT_TYPE), &action); break; case GAFActionType::None: default: break; } } }
void GafFeatures::addObjectsToScene() { using namespace std::placeholders; if (!m_asset) { StartCounter(); m_asset = GAFAsset::create(m_files[m_anim_index], nullptr); double loadingTime = GetCounter(); cocos2d::log("Loading time [%f]\n", loadingTime); std::ostringstream ss; ss << m_files[m_anim_index] << " "; ss << loadingTime; //m_loadingTimeLabel->setString(ss.str().c_str()); ss.str(""); ss << "VRAM: "; ss << m_asset->getTextureManager()->getMemoryConsumptionStat(); ss << " bytes"; m_vramStat->setString(ss.str()); CC_SAFE_RETAIN(m_asset); } if (!m_objects) { m_objects = cocos2d::__Array::create(); m_objects->retain(); } const cocos2d::Size size = cocos2d::Director::getInstance()->getWinSizeInPixels(); if (m_asset) { GAFObject *object = m_asset->createObject(); object->setLocalZOrder(0); addChild(object); float scaleFactor = cocos2d::Director::getInstance()->getContentScaleFactor(); object->setAnchorPoint(cocos2d::Vec2(0.5, 0.5)); object->setPosition(centerScreenPosition(size / scaleFactor)); object->setLocator(true); m_objects->addObject(object); m_objectSequencesNames.clear(); #if CC_TARGET_PLATFORM == CC_PLATFORM_IOS CocosDenshion::SimpleAudioEngine::getInstance()->stopAllEffects(); for(auto& effect : m_musicEffects) { CocosDenshion::SimpleAudioEngine::getInstance()->unloadEffect(effect.second.c_str()); } #endif m_musicEffects.clear(); const AnimationSequences_t& secDictionary = m_asset->getRootTimeline()->getAnimationSequences(); // TODO: only root timeline (temporary workaround) if (!secDictionary.empty()) { for (AnimationSequences_t::const_iterator i = secDictionary.begin(), e = secDictionary.end(); i != e; ++i) { const std::string& seqName = i->first; std::string::size_type pos = seqName.find("__audio:"); if (pos != std::string::npos) { std::string effectName = seqName.substr(pos + 8) + ".wav"; #if CC_TARGET_PLATFORM == CC_PLATFORM_IOS CocosDenshion::SimpleAudioEngine::getInstance()->preloadEffect(effectName.c_str()); #endif m_musicEffects[i->second.startFrameNo] = std::move(effectName); } else { m_objectSequencesNames.push_back(i->first); } } } enableSequenceControllers(!m_objectSequencesNames.empty()); // will work only if animation has a sequence object->playSequence("walk", true); object->setLooped(true, true); object->start(); object->setSequenceDelegate(std::bind(&GafFeatures::onFinishSequence, this, _1, _2)); object->setFramePlayedDelegate(std::bind(&GafFeatures::onFramePlayed, this, _1, _2)); } }