#include "WidgetReader/ArmatureNodeReader/ArmatureNodeReader.h" #include "platform/CCFileUtils.h" #include "flatbuffers/flatbuffers.h" #include "WidgetReader/NodeReader/NodeReader.h" #include "CSParseBinary_generated.h" #include "WidgetReader/ArmatureNodeReader/CSArmatureNode_generated.h" #include "CCArmature.h" #if defined(AX_BUILD_WITH_DRANGBONES) && AX_BUILD_WITH_DRANGBONES # include "DragonBones/CCDragonBonesHeaders.h" #endif USING_NS_AX; using namespace cocostudio; using namespace flatbuffers; IMPLEMENT_CLASS_NODE_READER_INFO(ArmatureNodeReader) ArmatureNodeReader::ArmatureNodeReader() {} ArmatureNodeReader::~ArmatureNodeReader() {} static ArmatureNodeReader* _instanceArmatureNodeReader = nullptr; ArmatureNodeReader* ArmatureNodeReader::getInstance() { if (_instanceArmatureNodeReader == nullptr) { _instanceArmatureNodeReader = new ArmatureNodeReader(); } return _instanceArmatureNodeReader; } void ArmatureNodeReader::destroyInstance() { AX_SAFE_DELETE(_instanceArmatureNodeReader); } Offset<Table> ArmatureNodeReader::createOptionsWithFlatBuffers(pugi::xml_node objectData, flatbuffers::FlatBufferBuilder* builder) { auto temp = NodeReader::getInstance()->createOptionsWithFlatBuffers(objectData, builder); auto nodeOptions = *(Offset<WidgetOptions>*)(&temp); bool isloop = false; bool isAutoPlay = false; std::string currentAnimationName; std::string currentArmatureName; int type = 0; std::string path; float armatureScale = 1.0f; float timeScale = 1.0f; /*int textureInfoFileType = 0; std::string textureInfoFilePath;*/ auto attribute = objectData.first_attribute(); while (attribute) { std::string_view attriname = attribute.name(); std::string_view value = attribute.value(); if (attriname == "IsLoop") { isloop = (value == "True") ? true : false; } else if (attriname == "IsAutoPlay") { isAutoPlay = (value == "True") ? true : false; } else if (attriname == "CurrentAnimationName") { currentAnimationName = value; } else if (attriname == "CurrentArmatureName") { currentArmatureName = value; } else if (attriname == "ArmatureScale") { armatureScale = atof(value.data()); } else if (attriname == "TimeScale") { timeScale = atof(value.data()); } attribute = attribute.next_attribute(); } auto child = objectData.first_child(); while (child) { std::string_view attriname = child.name(); if (attriname == "FileData") { attribute = child.first_attribute(); while (attribute) { attriname = attribute.name(); std::string_view value = attribute.value(); if (attriname == "Type") { type = 0; } else if (attriname == "Path") { path = value; } attribute = attribute.next_attribute(); } } child = child.next_sibling(); } auto options = CreateCSArmatureNodeOption(*builder, nodeOptions, CreateResourceItemData(*builder, type, builder->CreateString(path)), isloop, isAutoPlay, builder->CreateString(currentAnimationName), builder->CreateString(currentArmatureName), timeScale, armatureScale); return *(Offset<Table>*)(&options); } void ArmatureNodeReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Table* nodeOptions) { Node** ppResult = (Node**)(node); auto options = (flatbuffers::CSArmatureNodeOption*)nodeOptions; bool fileExist = false; std::string errorFilePath; std::string filepath(options->fileData()->path()->c_str()); if (FileUtils::getInstance()->isFileExist(filepath)) { fileExist = true; #if defined(AX_BUILD_WITH_DRANGBONES) && AX_BUILD_WITH_DRANGBONES auto filep = filepath.rfind('.'); if (filep != std::string::npos && strcmp(&filepath[filep], ".json") == 0) { // Currently, adjust by file ext, regard as DragonBones 4.5/5.0 // 4.5 texture info is fixed as texture.png, texture.json // 5.o texture info is _tex.json _tex.png auto sharedFactory = dragonBones::CCFactory::getFactory(); const auto dragonBonesData = sharedFactory->loadDragonBonesData(filepath, filepath); if (dragonBonesData != nullptr) { auto slash = filepath.rfind('/'); if (slash == std::string::npos) slash = filepath.rfind("\\"); if (slash != std::string::npos) { auto folder = filepath.substr(0, slash + 1); // try dragonBones 5.0 firstly; std::string commonName; auto _skePos = filepath.find("_ske"); if (_skePos != std::string::npos) { commonName = filepath.substr(slash + 1, _skePos - slash - 1); } auto succeed = sharedFactory->loadTextureAtlasData(folder + commonName + "_tex.json", filepath) != nullptr; if (succeed || sharedFactory->loadTextureAtlasData(folder + "texture.json", filepath) != nullptr) { std::string designArmatureName(options->currentArmatureName()->c_str()); auto armatureNode = sharedFactory->buildArmatureDisplay(designArmatureName); armatureNode->setScale(options->armatureScale()); armatureNode->getAnimation()->timeScale = options->timeScale(); std::string currentname = options->currentAnimationName()->c_str(); armatureNode->getAnimation()->play(currentname, options->isLoop() ? -1 : 1); *ppResult = armatureNode; } } } } else #endif { std::string fullpath = FileUtils::getInstance()->fullPathForFilename(filepath); std::string dirpath = fullpath.substr(0, fullpath.find_last_of('/')); FileUtils::getInstance()->addSearchPath(dirpath); ArmatureDataManager::getInstance()->addArmatureFileInfo(filepath); auto armatureNode = Armature::create(getArmatureName(filepath)); std::string currentname = options->currentAnimationName()->c_str(); if (options->isAutoPlay()) armatureNode->getAnimation()->play(currentname, -1, options->isLoop()); else { armatureNode->getAnimation()->play(currentname); armatureNode->getAnimation()->gotoAndPause(0); } *ppResult = armatureNode; } } else { *ppResult = Node::create(); errorFilePath = filepath; fileExist = false; } } ax::Node* ArmatureNodeReader::createNodeWithFlatBuffers(const flatbuffers::Table* nodeOptions) { Node* node = nullptr; // auto node = Armature::create(); // self auto options = (flatbuffers::CSArmatureNodeOption*)nodeOptions; setPropsWithFlatBuffers((Node*)(&node), (Table*)options); // super node auto NodeReader = NodeReader::getInstance(); NodeReader->setPropsWithFlatBuffers(node, (Table*)options->nodeOptions()); return node; } std::string ArmatureNodeReader::getArmatureName(std::string_view exporJsonPath) { // FileUtils.getFileData(exporJsonPath, "r", size) // need read armature name in exportJsonPath size_t end = exporJsonPath.find_last_of("."); size_t start = exporJsonPath.find_last_of('\\') + 1; size_t start1 = exporJsonPath.find_last_of('/') + 1; if (start < start1) start = start1; if (start == -1) start = 0; return std::string{exporJsonPath.substr(start, end - start)}; }