mirror of https://github.com/axmolengine/axmol.git
1573 lines
52 KiB
C++
1573 lines
52 KiB
C++
/****************************************************************************
|
|
Copyright (c) 2013 cocos2d-x.org
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
|
Copyright (c) 2019-2020 simdsoft, @HALX99
|
|
Copyright (c) 2021 Bytedance Inc.
|
|
|
|
https://axmolengine.github.io/
|
|
|
|
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 "ActionTimeline/CSLoader.h"
|
|
|
|
#include "base/ObjectFactory.h"
|
|
#include "base/CCDirector.h"
|
|
#include "base/ccUTF8.h"
|
|
#include "ui/CocosGUI.h"
|
|
#include "2d/CCSpriteFrameCache.h"
|
|
#include "2d/CCParticleSystemQuad.h"
|
|
#include "2d/CCFastTMXTiledMap.h"
|
|
#include "platform/CCFileUtils.h"
|
|
|
|
#include "ActionTimeline/CCActionTimelineCache.h"
|
|
#include "ActionTimeline/CCActionTimeline.h"
|
|
#include "ActionTimeline/CCActionTimelineNode.h"
|
|
#include "CCSGUIReader.h"
|
|
#include "CCComAudio.h"
|
|
#include "CSParseBinary_generated.h"
|
|
|
|
#include "WidgetReader/NodeReaderProtocol.h"
|
|
#include "WidgetReader/NodeReaderDefine.h"
|
|
|
|
#include "WidgetReader/NodeReader/NodeReader.h"
|
|
#include "WidgetReader/SingleNodeReader/SingleNodeReader.h"
|
|
#include "WidgetReader/SpriteReader/SpriteReader.h"
|
|
#include "WidgetReader/ParticleReader/ParticleReader.h"
|
|
#include "WidgetReader/GameMapReader/GameMapReader.h"
|
|
#include "WidgetReader/ProjectNodeReader/ProjectNodeReader.h"
|
|
#include "WidgetReader/ComAudioReader/ComAudioReader.h"
|
|
|
|
#include "WidgetReader/ButtonReader/ButtonReader.h"
|
|
#include "WidgetReader/CheckBoxReader/CheckBoxReader.h"
|
|
#include "WidgetReader/ImageViewReader/ImageViewReader.h"
|
|
#include "WidgetReader/TextBMFontReader/TextBMFontReader.h"
|
|
#include "WidgetReader/TextReader/TextReader.h"
|
|
#include "WidgetReader/TextFieldReader/TextFieldReader.h"
|
|
#include "WidgetReader/TextAtlasReader/TextAtlasReader.h"
|
|
#include "WidgetReader/LoadingBarReader/LoadingBarReader.h"
|
|
#include "WidgetReader/SliderReader/SliderReader.h"
|
|
#include "WidgetReader/LayoutReader/LayoutReader.h"
|
|
#include "WidgetReader/ScrollViewReader/ScrollViewReader.h"
|
|
#include "WidgetReader/PageViewReader/PageViewReader.h"
|
|
#include "WidgetReader/ListViewReader/ListViewReader.h"
|
|
#include "WidgetReader/ArmatureNodeReader/ArmatureNodeReader.h"
|
|
#include "WidgetReader/Node3DReader/Node3DReader.h"
|
|
#include "WidgetReader/MeshReader/MeshReader.h"
|
|
#include "WidgetReader/UserCameraReader/UserCameraReader.h"
|
|
#include "WidgetReader/Particle3DReader/Particle3DReader.h"
|
|
#include "WidgetReader/GameNode3DReader/GameNode3DReader.h"
|
|
#include "WidgetReader/Light3DReader/Light3DReader.h"
|
|
#include "WidgetReader/TabControlReader/TabControlReader.h"
|
|
|
|
#include "WidgetReader/SkeletonReader/BoneNodeReader.h"
|
|
#include "WidgetReader/SkeletonReader/SkeletonNodeReader.h"
|
|
|
|
#if defined(AX_BUILD_WITH_SPINE) && AX_BUILD_WITH_SPINE
|
|
# include "WidgetReader/SpineSkeletonReader/SpineSkeletonReader.h"
|
|
#endif
|
|
#include "WidgetReader/RichTextReader/RichTextReader.h"
|
|
#include "WidgetReader/RadioButtonReader/RadioButtonReader.h"
|
|
#include "WidgetReader/RadioButtonReader/RadioButtonGroupReader.h"
|
|
#include "WidgetReader/TextFieldReader/TextFieldExReader.h"
|
|
#include "CCComExtensionData.h"
|
|
|
|
#include "flatbuffers/flatbuffers.h"
|
|
|
|
#include "FlatBuffersSerialize.h"
|
|
|
|
#include "WidgetCallBackHandlerProtocol.h"
|
|
|
|
#include <fstream>
|
|
|
|
using namespace ax::ui;
|
|
using namespace cocostudio;
|
|
using namespace cocostudio::timeline;
|
|
/* peterson */
|
|
using namespace flatbuffers;
|
|
/**/
|
|
|
|
NS_AX_BEGIN
|
|
|
|
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_TMXTiledMap = "TMXTiledMap";
|
|
|
|
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_LabelAtlas = "LabelAtlas";
|
|
static const char* ClassName_LabelBMFont = "LabelBMFont";
|
|
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* ClassName_Label = "Label";
|
|
|
|
static const char* ClassName_ComAudio = "ComAudio";
|
|
|
|
static const char* NODE = "nodeTree";
|
|
static const char* CHILDREN = "children";
|
|
static const char* CLASSNAME = "classname";
|
|
static const char* FILE_PATH = "fileName";
|
|
static const char* PLIST_FILE = "plistFile";
|
|
static const char* TMX_FILE = "tmxFile";
|
|
static const char* TMX_STRING = "tmxString";
|
|
static const char* RESOURCE_PATH = "resourcePath";
|
|
|
|
static const char* COMPONENTS = "components";
|
|
static const char* COMPONENT_TYPE = "componentType";
|
|
static const char* COMPONENT_NAME = "componentName";
|
|
static const char* COMPONENT_ENABLED = "componentEnabled";
|
|
static const char* COMPONENT_AUDIO_FILE_PATH = "comAudioFilePath";
|
|
static const char* COMPONENT_LOOP = "comAudioloop";
|
|
|
|
static const char* TAG = "tag";
|
|
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* ZORDER = "ZOrder";
|
|
static const char* PARTICLE_NUM = "particleNum";
|
|
static const char* FLIPX = "flipX";
|
|
static const char* FLIPY = "flipY";
|
|
static const char* VISIBLE = "visible";
|
|
|
|
static const char* TEXTURES = "textures";
|
|
static const char* TEXTURES_PNG = "texturesPng";
|
|
|
|
static const char* MONO_COCOS2D_VERSION = "cocos2dVersion";
|
|
|
|
// CSLoader
|
|
static CSLoader* _sharedCSLoader = nullptr;
|
|
|
|
CSLoader* CSLoader::getInstance()
|
|
{
|
|
if (!_sharedCSLoader)
|
|
{
|
|
_sharedCSLoader = new CSLoader();
|
|
_sharedCSLoader->init();
|
|
}
|
|
|
|
return _sharedCSLoader;
|
|
}
|
|
|
|
void CSLoader::destroyInstance()
|
|
{
|
|
AX_SAFE_DELETE(_sharedCSLoader);
|
|
ActionTimelineCache::destroyInstance();
|
|
}
|
|
|
|
CSLoader::CSLoader()
|
|
: _recordJsonPath(true), _jsonPath(""), _monoCocos2dxVersion(""), _rootNode(nullptr), _csBuildID("10.0.3000.0")
|
|
{
|
|
CREATE_CLASS_NODE_READER_INFO(NodeReader);
|
|
CREATE_CLASS_NODE_READER_INFO(SingleNodeReader);
|
|
CREATE_CLASS_NODE_READER_INFO(SpriteReader);
|
|
CREATE_CLASS_NODE_READER_INFO(ParticleReader);
|
|
CREATE_CLASS_NODE_READER_INFO(GameMapReader);
|
|
|
|
CREATE_CLASS_NODE_READER_INFO(ButtonReader);
|
|
CREATE_CLASS_NODE_READER_INFO(CheckBoxReader);
|
|
CREATE_CLASS_NODE_READER_INFO(ImageViewReader);
|
|
CREATE_CLASS_NODE_READER_INFO(TextBMFontReader);
|
|
CREATE_CLASS_NODE_READER_INFO(TextReader);
|
|
CREATE_CLASS_NODE_READER_INFO(TextFieldReader);
|
|
CREATE_CLASS_NODE_READER_INFO(TextAtlasReader);
|
|
CREATE_CLASS_NODE_READER_INFO(LoadingBarReader);
|
|
CREATE_CLASS_NODE_READER_INFO(SliderReader);
|
|
CREATE_CLASS_NODE_READER_INFO(LayoutReader);
|
|
CREATE_CLASS_NODE_READER_INFO(ScrollViewReader);
|
|
CREATE_CLASS_NODE_READER_INFO(PageViewReader);
|
|
CREATE_CLASS_NODE_READER_INFO(ListViewReader);
|
|
|
|
CREATE_CLASS_NODE_READER_INFO(ArmatureNodeReader);
|
|
CREATE_CLASS_NODE_READER_INFO(Node3DReader);
|
|
CREATE_CLASS_NODE_READER_INFO(MeshReader);
|
|
CREATE_CLASS_NODE_READER_INFO(UserCameraReader);
|
|
CREATE_CLASS_NODE_READER_INFO(Particle3DReader);
|
|
CREATE_CLASS_NODE_READER_INFO(GameNode3DReader);
|
|
CREATE_CLASS_NODE_READER_INFO(Light3DReader);
|
|
CREATE_CLASS_NODE_READER_INFO(TabControlReader);
|
|
|
|
CREATE_CLASS_NODE_READER_INFO(BoneNodeReader);
|
|
CREATE_CLASS_NODE_READER_INFO(SkeletonNodeReader);
|
|
|
|
/// Added by x-studio
|
|
CREATE_CLASS_NODE_READER_INFO(RichTextReader);
|
|
#if defined(AX_BUILD_WITH_SPINE) && AX_BUILD_WITH_SPINE
|
|
CREATE_CLASS_NODE_READER_INFO(SpineSkeletonReader);
|
|
#endif
|
|
CREATE_CLASS_NODE_READER_INFO(RadioButtonReader);
|
|
CREATE_CLASS_NODE_READER_INFO(RadioButtonGroupReader);
|
|
|
|
CREATE_CLASS_NODE_READER_INFO(TextFieldExReader);
|
|
}
|
|
|
|
void CSLoader::purge() {}
|
|
|
|
void CSLoader::init()
|
|
{
|
|
using namespace std::placeholders;
|
|
|
|
_funcs.insert(Pair(ClassName_Node, std::bind(&CSLoader::loadSimpleNode, this, _1)));
|
|
_funcs.insert(Pair(ClassName_SubGraph, std::bind(&CSLoader::loadSubGraph, this, _1)));
|
|
_funcs.insert(Pair(ClassName_Sprite, std::bind(&CSLoader::loadSprite, this, _1)));
|
|
_funcs.insert(Pair(ClassName_Particle, std::bind(&CSLoader::loadParticle, this, _1)));
|
|
_funcs.insert(Pair(ClassName_TMXTiledMap, std::bind(&CSLoader::loadTMXTiledMap, this, _1)));
|
|
_funcs.insert(Pair(ClassName_LabelAtlas, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_LabelBMFont, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_Panel, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_Button, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_CheckBox, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_ImageView, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_TextAtlas, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_TextBMFont, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_Text, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_LoadingBar, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_TextField, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_Slider, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_Layout, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_ScrollView, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_ListView, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_PageView, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_Widget, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
_funcs.insert(Pair(ClassName_Label, std::bind(&CSLoader::loadWidget, this, _1)));
|
|
|
|
_componentFuncs.insert(ComponentPair(ClassName_ComAudio, std::bind(&CSLoader::loadComAudio, this, _1)));
|
|
}
|
|
|
|
Node* CSLoader::createNode(std::string_view filename)
|
|
{
|
|
auto path = filename;
|
|
size_t pos = path.find_last_of('.');
|
|
auto suffix = path.substr(pos + 1, path.length());
|
|
|
|
CSLoader* load = CSLoader::getInstance();
|
|
|
|
if (suffix == "csb")
|
|
{
|
|
return load->createNodeWithFlatBuffersFile(filename);
|
|
}
|
|
else if (suffix == "json" || suffix == "ExportJson")
|
|
{
|
|
return load->createNodeFromJson(filename);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
Node* CSLoader::createNode(std::string_view filename, const ccNodeLoadCallback& callback)
|
|
{
|
|
auto path = filename;
|
|
size_t pos = path.find_last_of('.');
|
|
auto suffix = path.substr(pos + 1, path.length());
|
|
|
|
CSLoader* load = CSLoader::getInstance();
|
|
|
|
if (suffix == "csb")
|
|
{
|
|
return load->createNodeWithFlatBuffersFile(filename, callback);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
Node* CSLoader::createNodeWithVisibleSize(std::string_view filename)
|
|
{
|
|
auto node = createNode(filename);
|
|
if (node != nullptr)
|
|
{
|
|
Size frameSize = Director::getInstance()->getVisibleSize();
|
|
node->setContentSize(frameSize);
|
|
ui::Helper::doLayout(node);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
Node* CSLoader::createNodeWithVisibleSize(std::string_view filename, const ccNodeLoadCallback& callback)
|
|
{
|
|
auto node = createNode(filename, callback);
|
|
if (node != nullptr)
|
|
{
|
|
Size frameSize = Director::getInstance()->getVisibleSize();
|
|
node->setContentSize(frameSize);
|
|
ui::Helper::doLayout(node);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
std::string_view CSLoader::getExtentionName(std::string_view name)
|
|
{
|
|
auto path = name;
|
|
size_t pos = path.find_last_of('.');
|
|
auto result = path.substr(pos + 1, path.length());
|
|
|
|
return result;
|
|
}
|
|
|
|
ActionTimeline* CSLoader::createTimeline(std::string_view filename)
|
|
{
|
|
auto suffix = getExtentionName(filename);
|
|
|
|
ActionTimelineCache* cache = ActionTimelineCache::getInstance();
|
|
|
|
if (suffix == "csb")
|
|
{
|
|
return cache->createActionWithFlatBuffersFile(filename);
|
|
}
|
|
else if (suffix == "json" || suffix == "ExportJson")
|
|
{
|
|
return cache->createActionFromJson(filename);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
ActionTimeline* CSLoader::createTimeline(const Data& data, std::string_view filename)
|
|
{
|
|
auto suffix = getExtentionName(filename);
|
|
|
|
ActionTimelineCache* cache = ActionTimelineCache::getInstance();
|
|
|
|
if (suffix == "csb")
|
|
{
|
|
return cache->createActionWithDataBuffer(data, filename);
|
|
}
|
|
else if (suffix == "json" || suffix == "ExportJson")
|
|
{
|
|
std::string_view content((char*)data.getBytes(), data.getSize());
|
|
return cache->createActionFromContent(filename, content);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/*
|
|
ActionTimelineNode* CSLoader::createActionTimelineNode(std::string_view filename)
|
|
{
|
|
Node* root = createNode(filename);
|
|
ActionTimeline* action = createTimeline(filename);
|
|
|
|
if(root && action)
|
|
{
|
|
root->runAction(action);
|
|
action->gotoFrameAndPlay(0);
|
|
}
|
|
|
|
ActionTimelineNode* node = ActionTimelineNode::create(root, action);
|
|
return node;
|
|
}
|
|
ActionTimelineNode* CSLoader::createActionTimelineNode(std::string_view filename, int startIndex, int endIndex, bool
|
|
loop)
|
|
{
|
|
ActionTimelineNode* node = createActionTimelineNode(filename);
|
|
ActionTimeline* action = node->getActionTimeline();
|
|
if(action)
|
|
action->gotoFrameAndPlay(startIndex, endIndex, loop);
|
|
|
|
return node;
|
|
}
|
|
*/
|
|
|
|
Node* CSLoader::createNodeFromJson(std::string_view filename)
|
|
{
|
|
if (_recordJsonPath)
|
|
{
|
|
auto jsonPath = filename.substr(0, filename.find_last_of('/') + 1);
|
|
GUIReader::getInstance()->setFilePath(jsonPath);
|
|
|
|
_jsonPath = jsonPath;
|
|
}
|
|
else
|
|
{
|
|
GUIReader::getInstance()->setFilePath("");
|
|
}
|
|
|
|
Node* node = loadNodeWithFile(filename);
|
|
|
|
return node;
|
|
}
|
|
|
|
Node* CSLoader::loadNodeWithFile(std::string_view fileName)
|
|
{
|
|
// Read content from file
|
|
std::string contentStr = FileUtils::getInstance()->getStringFromFile(fileName);
|
|
|
|
Node* node = loadNodeWithContent(contentStr);
|
|
|
|
// Load animation data from file
|
|
ActionTimelineCache::getInstance()->loadAnimationActionWithContent(fileName, contentStr);
|
|
|
|
return node;
|
|
}
|
|
|
|
Node* CSLoader::loadNodeWithContent(std::string_view content)
|
|
{
|
|
rapidjson::Document doc;
|
|
doc.Parse<0>(content.data(), content.length());
|
|
if (doc.HasParseError())
|
|
{
|
|
AXLOG("GetParseError %d\n", doc.GetParseError());
|
|
}
|
|
|
|
// cocos2dx version mono editor is based on
|
|
_monoCocos2dxVersion = DICTOOL->getStringValue_json(doc, MONO_COCOS2D_VERSION, "");
|
|
|
|
// decode plist
|
|
int length = DICTOOL->getArrayCount_json(doc, TEXTURES);
|
|
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
std::string plist = DICTOOL->getStringValueFromArray_json(doc, TEXTURES, i);
|
|
std::string png = DICTOOL->getStringValueFromArray_json(doc, TEXTURES_PNG, i);
|
|
plist = _jsonPath + plist;
|
|
png = _jsonPath + png;
|
|
SpriteFrameCache::getInstance()->addSpriteFramesWithFile(plist, png);
|
|
}
|
|
|
|
// decode node tree
|
|
const rapidjson::Value& subJson = DICTOOL->getSubDictionary_json(doc, NODE);
|
|
Node* root = loadNode(subJson);
|
|
root->release();
|
|
|
|
return root;
|
|
}
|
|
|
|
Node* CSLoader::loadNode(const rapidjson::Value& json)
|
|
{
|
|
Node* node = nullptr;
|
|
std::string nodeType = DICTOOL->getStringValue_json(json, CLASSNAME);
|
|
|
|
NodeCreateFunc func = _funcs[nodeType];
|
|
if (func != nullptr)
|
|
{
|
|
const rapidjson::Value& options = DICTOOL->getSubDictionary_json(json, OPTIONS);
|
|
node = func(options);
|
|
|
|
// component
|
|
if (node)
|
|
{
|
|
const rapidjson::Value& components = DICTOOL->getSubDictionary_json(options, COMPONENTS);
|
|
int componentSize = DICTOOL->getArrayCount_json(options, COMPONENTS, 0);
|
|
for (int i = 0; i < componentSize; ++i)
|
|
{
|
|
const rapidjson::Value& dic = DICTOOL->getSubDictionary_json(components, COMPONENTS, i);
|
|
Component* component = loadComponent(dic);
|
|
if (component)
|
|
{
|
|
node->addComponent(component);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (node)
|
|
{
|
|
int length = DICTOOL->getArrayCount_json(json, CHILDREN, 0);
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
const rapidjson::Value& dic = DICTOOL->getSubDictionary_json(json, CHILDREN, i);
|
|
Node* child = loadNode(dic);
|
|
if (child)
|
|
{
|
|
PageView* pageView = dynamic_cast<PageView*>(node);
|
|
ListView* listView = dynamic_cast<ListView*>(node);
|
|
if (pageView)
|
|
{
|
|
Layout* layout = dynamic_cast<Layout*>(child);
|
|
if (layout)
|
|
{
|
|
pageView->addPage(layout);
|
|
}
|
|
}
|
|
else if (listView)
|
|
{
|
|
Widget* widget = dynamic_cast<Widget*>(child);
|
|
if (widget)
|
|
{
|
|
listView->pushBackCustomItem(widget);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_monoCocos2dxVersion != "3.x")
|
|
{
|
|
Widget* widget = dynamic_cast<Widget*>(child);
|
|
Widget* parent = dynamic_cast<Widget*>(node);
|
|
if (widget && parent && !dynamic_cast<Layout*>(parent))
|
|
{
|
|
if (widget->getPositionType() == ui::Widget::PositionType::PERCENT)
|
|
{
|
|
widget->setPositionPercent(
|
|
Vec2(widget->getPositionPercent().x + parent->getAnchorPoint().x,
|
|
widget->getPositionPercent().y + parent->getAnchorPoint().y));
|
|
widget->setPosition(Vec2(widget->getPositionX() + parent->getAnchorPointInPoints().x,
|
|
widget->getPositionY() + parent->getAnchorPointInPoints().y));
|
|
}
|
|
else
|
|
{
|
|
Size parentSize = parent->getContentSize();
|
|
widget->setPosition(
|
|
Vec2(widget->getPositionX() + parentSize.width * parent->getAnchorPoint().x,
|
|
widget->getPositionY() + parentSize.height * parent->getAnchorPoint().y));
|
|
}
|
|
}
|
|
}
|
|
|
|
node->addChild(child);
|
|
}
|
|
child->release();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AXLOG("Not supported NodeType: %s", nodeType.c_str());
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
void CSLoader::initNode(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);
|
|
uint8_t alpha = (uint8_t)DICTOOL->getIntValue_json(json, ALPHA, 255);
|
|
uint8_t red = (uint8_t)DICTOOL->getIntValue_json(json, RED, 255);
|
|
uint8_t green = (uint8_t)DICTOOL->getIntValue_json(json, GREEN, 255);
|
|
uint8_t blue = (uint8_t)DICTOOL->getIntValue_json(json, BLUE, 255);
|
|
int zorder = DICTOOL->getIntValue_json(json, ZORDER);
|
|
int tag = DICTOOL->getIntValue_json(json, TAG);
|
|
int actionTag = DICTOOL->getIntValue_json(json, ACTION_TAG);
|
|
bool visible = DICTOOL->getBooleanValue_json(json, VISIBLE);
|
|
|
|
if (x != 0 || y != 0)
|
|
node->setPosition(Point(x, y));
|
|
if (scalex != 1)
|
|
node->setScaleX(scalex);
|
|
if (scaley != 1)
|
|
node->setScaleY(scaley);
|
|
if (rotation != 0)
|
|
node->setRotation(rotation);
|
|
if (rotationSkewX != 0)
|
|
node->setRotationSkewX(rotationSkewX);
|
|
if (rotationSkewY != 0)
|
|
node->setRotationSkewY(rotationSkewY);
|
|
if (skewx != 0)
|
|
node->setSkewX(skewx);
|
|
if (skewy != 0)
|
|
node->setSkewY(skewy);
|
|
if (anchorx != 0.5f || anchory != 0.5f)
|
|
node->setAnchorPoint(Point(anchorx, anchory));
|
|
if (width != 0 || height != 0)
|
|
node->setContentSize(Size(width, height));
|
|
if (zorder != 0)
|
|
node->setLocalZOrder(zorder);
|
|
if (visible != true)
|
|
node->setVisible(visible);
|
|
|
|
if (alpha != 255)
|
|
{
|
|
node->setOpacity(alpha);
|
|
}
|
|
if (red != 255 || green != 255 || blue != 255)
|
|
{
|
|
node->setColor(Color3B(red, green, blue));
|
|
}
|
|
|
|
node->setTag(tag);
|
|
node->setUserObject(ActionTimelineData::create(actionTag));
|
|
}
|
|
|
|
Node* CSLoader::loadSimpleNode(const rapidjson::Value& json)
|
|
{
|
|
Node* node = Node::create();
|
|
// fix memory leak for v3.3
|
|
// node->retain();
|
|
initNode(node, json);
|
|
|
|
return node;
|
|
}
|
|
|
|
Node* CSLoader::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();
|
|
}
|
|
// fix memory leak for v3.3
|
|
// node->retain();
|
|
|
|
initNode(node, json);
|
|
|
|
return node;
|
|
}
|
|
|
|
Node* CSLoader::loadSprite(const rapidjson::Value& json)
|
|
{
|
|
const char* filePath = DICTOOL->getStringValue_json(json, FILE_PATH);
|
|
Sprite* sprite = nullptr;
|
|
|
|
if (filePath != nullptr)
|
|
{
|
|
std::string path = filePath;
|
|
|
|
SpriteFrame* spriteFrame = SpriteFrameCache::getInstance()->findFrame(path);
|
|
if (!spriteFrame)
|
|
{
|
|
path = _jsonPath + path;
|
|
sprite = Sprite::create(path);
|
|
}
|
|
else
|
|
{
|
|
sprite = Sprite::createWithSpriteFrame(spriteFrame);
|
|
}
|
|
|
|
if (!sprite)
|
|
{
|
|
sprite = Sprite::create();
|
|
AXLOG("filePath is empty. Create a sprite with no texture");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprite = Sprite::create();
|
|
}
|
|
|
|
// fix memory leak for v3.3
|
|
// sprite->retain();
|
|
|
|
initNode(sprite, json);
|
|
|
|
bool flipX = DICTOOL->getBooleanValue_json(json, FLIPX);
|
|
bool flipY = DICTOOL->getBooleanValue_json(json, FLIPY);
|
|
|
|
if (flipX != false)
|
|
sprite->setFlippedX(flipX);
|
|
if (flipY != false)
|
|
sprite->setFlippedY(flipY);
|
|
|
|
return sprite;
|
|
}
|
|
|
|
Node* CSLoader::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);
|
|
// fix memory leak for v3.3
|
|
// particle->retain();
|
|
|
|
initNode(particle, json);
|
|
|
|
return particle;
|
|
}
|
|
|
|
Node* CSLoader::loadTMXTiledMap(const rapidjson::Value& json)
|
|
{
|
|
const char* tmxFile = DICTOOL->getStringValue_json(json, TMX_FILE);
|
|
const char* tmxString = DICTOOL->getStringValue_json(json, TMX_STRING);
|
|
const char* resourcePath = DICTOOL->getStringValue_json(json, RESOURCE_PATH);
|
|
|
|
TMXTiledMap* tmx = nullptr;
|
|
|
|
if (tmxFile && strcmp("", tmxFile) != 0)
|
|
{
|
|
tmx = TMXTiledMap::create(tmxFile);
|
|
}
|
|
else if ((tmxString && strcmp("", tmxString) != 0) && (resourcePath && strcmp("", resourcePath) != 0))
|
|
{
|
|
tmx = TMXTiledMap::createWithXML(tmxString, resourcePath);
|
|
}
|
|
|
|
return tmx;
|
|
}
|
|
|
|
Node* CSLoader::loadWidget(const rapidjson::Value& json)
|
|
{
|
|
const char* str = DICTOOL->getStringValue_json(json, CLASSNAME);
|
|
if (str == nullptr)
|
|
return nullptr;
|
|
|
|
std::string classname = str;
|
|
|
|
WidgetPropertiesReader0300 widgetPropertiesReader;
|
|
Widget* widget = nullptr;
|
|
|
|
if (isWidget(classname))
|
|
{
|
|
std::string readerName{getGUIClassName(classname)};
|
|
readerName.append("Reader");
|
|
|
|
std::string_view guiClassName = getGUIClassName(classname);
|
|
widget = dynamic_cast<Widget*>(ObjectFactory::getInstance()->createObject(guiClassName));
|
|
// fix memory leak for v3.3
|
|
// widget->retain();
|
|
|
|
WidgetReaderProtocol* reader =
|
|
dynamic_cast<WidgetReaderProtocol*>(ObjectFactory::getInstance()->createObject(readerName));
|
|
|
|
if (reader && widget)
|
|
{
|
|
widgetPropertiesReader.setPropsForAllWidgetFromJsonDictionary(reader, widget, json);
|
|
}
|
|
}
|
|
else if (isCustomWidget(classname))
|
|
{
|
|
widget = dynamic_cast<Widget*>(ObjectFactory::getInstance()->createObject(classname));
|
|
|
|
// fix memory leak for v3.3
|
|
// widget->retain();
|
|
|
|
//
|
|
// 1st., custom widget parse properties of parent widget with parent widget reader
|
|
std::string_view readerName = getWidgetReaderClassName(widget);
|
|
WidgetReaderProtocol* reader =
|
|
dynamic_cast<WidgetReaderProtocol*>(ObjectFactory::getInstance()->createObject(readerName));
|
|
if (reader && widget)
|
|
{
|
|
widgetPropertiesReader.setPropsForAllWidgetFromJsonDictionary(reader, widget, json);
|
|
|
|
// 2nd., custom widget parse with custom reader
|
|
const char* customProperty = DICTOOL->getStringValue_json(json, "customProperty");
|
|
rapidjson::Document customJsonDict;
|
|
customJsonDict.Parse<0>(customProperty);
|
|
if (customJsonDict.HasParseError())
|
|
{
|
|
AXLOG("GetParseError %d\n", customJsonDict.GetParseError());
|
|
}
|
|
|
|
widgetPropertiesReader.setPropsForAllCustomWidgetFromJsonDictionary(classname, widget, customJsonDict);
|
|
}
|
|
else
|
|
{
|
|
AXLOG("Widget or WidgetReader doesn't exists!!! Please check your protocol buffers file.");
|
|
}
|
|
}
|
|
|
|
if (widget)
|
|
{
|
|
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);
|
|
if (rotationSkewX != 0)
|
|
widget->setRotationSkewX(rotationSkewX);
|
|
if (rotationSkewY != 0)
|
|
widget->setRotationSkewY(rotationSkewY);
|
|
if (skewx != 0)
|
|
widget->setSkewX(skewx);
|
|
if (skewy != 0)
|
|
widget->setSkewY(skewy);
|
|
|
|
int actionTag = DICTOOL->getIntValue_json(json, ACTION_TAG);
|
|
widget->setUserObject(ActionTimelineData::create(actionTag));
|
|
}
|
|
|
|
return widget;
|
|
}
|
|
|
|
Component* CSLoader::loadComponent(const rapidjson::Value& json)
|
|
{
|
|
Component* component = nullptr;
|
|
|
|
std::string componentType = DICTOOL->getStringValue_json(json, COMPONENT_TYPE);
|
|
|
|
ComponentCreateFunc func = _componentFuncs[componentType];
|
|
|
|
if (func != nullptr)
|
|
{
|
|
component = func(json);
|
|
}
|
|
|
|
return component;
|
|
}
|
|
|
|
Component* CSLoader::loadComAudio(const rapidjson::Value& json)
|
|
{
|
|
ComAudio* audio = ComAudio::create();
|
|
|
|
const char* name = DICTOOL->getStringValue_json(json, COMPONENT_NAME);
|
|
bool enabled = DICTOOL->getBooleanValue_json(json, COMPONENT_ENABLED);
|
|
|
|
audio->setName(name);
|
|
audio->setEnabled(enabled);
|
|
|
|
const char* filePath = DICTOOL->getStringValue_json(json, COMPONENT_AUDIO_FILE_PATH);
|
|
bool loop = DICTOOL->getBooleanValue_json(json, COMPONENT_LOOP);
|
|
|
|
audio->setFile(filePath);
|
|
audio->setLoop(loop);
|
|
|
|
return audio;
|
|
}
|
|
|
|
ax::Node* CSLoader::createNode(const Data& data)
|
|
{
|
|
return createNode(data, nullptr);
|
|
}
|
|
|
|
template <typename _Elem, typename _Fty>
|
|
inline void fast_split(_Elem* s, typename std::remove_const<_Elem>::type delim, const _Fty& op)
|
|
{
|
|
auto _Start = s; // the start of every string
|
|
auto _Ptr = s; // source string iterator
|
|
while (*_Ptr != '\0')
|
|
{
|
|
if (delim == *_Ptr /* && _Ptr != _Start*/)
|
|
{
|
|
if (_Ptr != _Start)
|
|
op(_Start, _Ptr);
|
|
_Start = _Ptr + 1;
|
|
}
|
|
++_Ptr;
|
|
}
|
|
if (_Start != _Ptr)
|
|
{
|
|
op(_Start, _Ptr);
|
|
}
|
|
}
|
|
Node* CSLoader::createNode(const Data& data, const ccNodeLoadCallback& callback)
|
|
{
|
|
CSLoader* loader = CSLoader::getInstance();
|
|
Node* node = nullptr;
|
|
do
|
|
{
|
|
AX_BREAK_IF(data.isNull() || data.getSize() <= 0);
|
|
auto csparsebinary = GetCSParseBinary(data.getBytes());
|
|
AX_BREAK_IF(nullptr == csparsebinary);
|
|
auto csBuildId = csparsebinary->version();
|
|
if (csBuildId)
|
|
{
|
|
int readerVersion = 0, writterVersion = 0;
|
|
// parse writter version
|
|
int revisionIndex = 0;
|
|
fast_split(csBuildId->c_str(), '.', [&](const char* start, const char* end) {
|
|
auto endv = const_cast<char*>(end);
|
|
char charS = *endv;
|
|
switch (++revisionIndex)
|
|
{
|
|
case 3:
|
|
*endv = '\0';
|
|
writterVersion = atoi(start);
|
|
*endv = charS;
|
|
break;
|
|
}
|
|
});
|
|
|
|
// parse reader version
|
|
revisionIndex = 0;
|
|
fast_split(&loader->_csBuildID.front(), '.', [&](char* start, char* end) {
|
|
auto endv = const_cast<char*>(end);
|
|
char charS = *endv;
|
|
switch (++revisionIndex)
|
|
{
|
|
case 3:
|
|
*endv = '\0';
|
|
readerVersion = atoi(start);
|
|
*endv = charS;
|
|
break;
|
|
}
|
|
});
|
|
|
|
AXASSERT(readerVersion >= writterVersion,
|
|
StringUtils::format(
|
|
"%s%s%s%s%s%s%s%s%s%s", "The reader build id of your Cocos exported file(", csBuildId->c_str(),
|
|
") and the reader build id in your axis(", loader->_csBuildID.c_str(),
|
|
") are not match.\n", "Please get the correct reader(build id ", csBuildId->c_str(), ")from ",
|
|
"https://github.com/axmolengine/axmol", " and replace it in your axis")
|
|
.c_str());
|
|
}
|
|
|
|
// decode plist
|
|
auto textures = csparsebinary->textures();
|
|
int textureSize = csparsebinary->textures()->size();
|
|
AXLOG("textureSize = %d", textureSize);
|
|
for (int i = 0; i < textureSize; ++i)
|
|
{
|
|
std::string plist = textures->Get(i)->c_str();
|
|
SpriteFrameCache::getInstance()->addSpriteFramesWithFile(plist);
|
|
}
|
|
|
|
node = loader->nodeWithFlatBuffers(csparsebinary->nodeTree(), callback);
|
|
} while (0);
|
|
|
|
loader->reconstructNestNode(node);
|
|
|
|
return node;
|
|
}
|
|
|
|
Node* CSLoader::createNodeWithFlatBuffersFile(std::string_view filename)
|
|
{
|
|
return createNodeWithFlatBuffersFile(filename, nullptr);
|
|
}
|
|
|
|
Node* CSLoader::createNodeWithFlatBuffersFile(std::string_view filename, const ccNodeLoadCallback& callback)
|
|
{
|
|
Node* node = nodeWithFlatBuffersFile(filename, callback);
|
|
|
|
reconstructNestNode(node);
|
|
|
|
return node;
|
|
}
|
|
|
|
inline void CSLoader::reconstructNestNode(ax::Node* node)
|
|
{
|
|
/* To reconstruct nest node as WidgetCallBackHandlerProtocol. */
|
|
auto callbackHandler = dynamic_cast<WidgetCallBackHandlerProtocol*>(node);
|
|
if (callbackHandler)
|
|
{
|
|
_callbackHandlers.popBack();
|
|
if (_callbackHandlers.empty())
|
|
{
|
|
_rootNode = nullptr;
|
|
AXLOG("Call back handler container has been clear.");
|
|
}
|
|
else
|
|
{
|
|
_rootNode = _callbackHandlers.back();
|
|
AXLOG("after pop back _rootNode name = %s", _rootNode->getName().data());
|
|
}
|
|
}
|
|
}
|
|
|
|
Node* CSLoader::nodeWithFlatBuffersFile(std::string_view fileName)
|
|
{
|
|
return nodeWithFlatBuffersFile(fileName, nullptr);
|
|
}
|
|
|
|
Node* CSLoader::nodeWithFlatBuffersFile(std::string_view fileName, const ccNodeLoadCallback& callback)
|
|
{
|
|
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(fileName);
|
|
|
|
AX_ASSERT(FileUtils::getInstance()->isFileExist(fullPath));
|
|
|
|
Data buf = FileUtils::getInstance()->getDataFromFile(fullPath);
|
|
|
|
if (buf.isNull())
|
|
{
|
|
AXLOG("CSLoader::nodeWithFlatBuffersFile - failed read file: %s", fileName.data());
|
|
AX_ASSERT(false);
|
|
return nullptr;
|
|
}
|
|
|
|
auto csparsebinary = GetCSParseBinary(buf.getBytes());
|
|
|
|
auto csBuildId = csparsebinary->version();
|
|
if (csBuildId)
|
|
{
|
|
int readerVersion = 0, writterVersion = 0;
|
|
// parse writter version
|
|
int revisionIndex = 0;
|
|
fast_split(csBuildId->c_str(), '.', [&](const char* start, const char* end) {
|
|
auto endv = const_cast<char*>(end);
|
|
char charS = *endv;
|
|
switch (++revisionIndex)
|
|
{
|
|
case 3:
|
|
*endv = '\0';
|
|
writterVersion = atoi(start);
|
|
*endv = charS;
|
|
break;
|
|
}
|
|
});
|
|
|
|
// parse reader version
|
|
revisionIndex = 0;
|
|
fast_split(&_csBuildID.front(), '.', [&](char* start, char* end) {
|
|
auto endv = const_cast<char*>(end);
|
|
char charS = *endv;
|
|
switch (++revisionIndex)
|
|
{
|
|
case 3:
|
|
*endv = '\0';
|
|
readerVersion = atoi(start);
|
|
*endv = charS;
|
|
break;
|
|
}
|
|
});
|
|
|
|
AXASSERT(readerVersion >= writterVersion,
|
|
StringUtils::format(
|
|
"%s%s%s%s%s%s%s%s%s%s", "The reader build id of your Cocos exported file(", csBuildId->c_str(),
|
|
") and the reader build id in your axis(", _csBuildID.c_str(), ") are not match.\n",
|
|
"Please get the correct reader(build id ", csBuildId->c_str(), ")from ",
|
|
"https://github.com/axmolengine/axmol", " and replace it in your axis")
|
|
.c_str());
|
|
|
|
if (readerVersion < writterVersion)
|
|
{
|
|
auto exceptionMsg =
|
|
StringUtils::format("error: The csloader version not match, require version is:%s, but %s provided!",
|
|
csBuildId->c_str(), _csBuildID.c_str());
|
|
throw std::logic_error(exceptionMsg.c_str());
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
// decode plist
|
|
auto textures = csparsebinary->textures();
|
|
int textureSize = textures->size();
|
|
for (int i = 0; i < textureSize; ++i)
|
|
{
|
|
std::string plist = textures->Get(i)->c_str();
|
|
SpriteFrameCache::getInstance()->addSpriteFramesWithFile(plist);
|
|
}
|
|
|
|
Node* node = nodeWithFlatBuffers(csparsebinary->nodeTree(), callback);
|
|
|
|
return node;
|
|
}
|
|
|
|
Node* CSLoader::nodeWithFlatBuffers(const flatbuffers::NodeTree* nodetree)
|
|
{
|
|
return nodeWithFlatBuffers(nodetree, nullptr);
|
|
}
|
|
|
|
Node* CSLoader::nodeWithFlatBuffers(const flatbuffers::NodeTree* nodetree, const ccNodeLoadCallback& callback)
|
|
{
|
|
if (nodetree == nullptr)
|
|
return nullptr;
|
|
|
|
{
|
|
Node* node = nullptr;
|
|
|
|
std::string classname = nodetree->classname()->c_str();
|
|
|
|
auto options = nodetree->options();
|
|
|
|
if (classname == "ProjectNode")
|
|
{
|
|
auto reader = ProjectNodeReader::getInstance();
|
|
auto projectNodeOptions = (ProjectNodeOptions*)options->data();
|
|
std::string filePath = projectNodeOptions->fileName()->c_str();
|
|
|
|
cocostudio::timeline::ActionTimeline* action = nullptr;
|
|
if (!filePath.empty() && FileUtils::getInstance()->isFileExist(filePath))
|
|
{
|
|
Data buf = FileUtils::getInstance()->getDataFromFile(filePath);
|
|
node = createNode(buf, callback);
|
|
action = createTimeline(buf, filePath);
|
|
}
|
|
else
|
|
{
|
|
node = Node::create();
|
|
}
|
|
reader->setPropsWithFlatBuffers(node, (const flatbuffers::Table*)options->data());
|
|
if (action)
|
|
{
|
|
action->setTimeSpeed(projectNodeOptions->innerActionSpeed());
|
|
node->runAction(action);
|
|
action->gotoFrameAndPause(0);
|
|
}
|
|
}
|
|
else if (classname == "SimpleAudio")
|
|
{
|
|
node = Node::create();
|
|
auto reader = ComAudioReader::getInstance();
|
|
Component* component = reader->createComAudioWithFlatBuffers((const flatbuffers::Table*)options->data());
|
|
if (component)
|
|
{
|
|
component->setName(PlayableFrame::PLAYABLE_EXTENTION);
|
|
node->addComponent(component);
|
|
reader->setPropsWithFlatBuffers(node, (const flatbuffers::Table*)options->data());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::string customClassName = nodetree->customClassName()->c_str();
|
|
if (customClassName != "")
|
|
{
|
|
classname = customClassName;
|
|
}
|
|
std::string readername{getGUIClassName(classname)};
|
|
readername.append("Reader");
|
|
|
|
NodeReaderProtocol* reader =
|
|
dynamic_cast<NodeReaderProtocol*>(ObjectFactory::getInstance()->createObject(readername));
|
|
if (reader == nullptr)
|
|
reader = dynamic_cast<NodeReaderProtocol*>(
|
|
ObjectFactory::getInstance()->createObject("CustomRootNodeReader"));
|
|
if (reader != nullptr)
|
|
{
|
|
if (!customClassName.empty())
|
|
reader->setCurrentCustomClassName(customClassName.c_str());
|
|
|
|
node = reader->createNodeWithFlatBuffers((const flatbuffers::Table*)options->data());
|
|
}
|
|
else
|
|
{
|
|
auto exceptionMsg = StringUtils::format(
|
|
R"(error: Missing custom reader class name:%s, please config at your project fiile xxx.xsxproj like follow:
|
|
<Project>
|
|
<publish-opts>
|
|
<custom-readers>
|
|
<item>%s</item>
|
|
</custom-readers>
|
|
</publish-opts>
|
|
</Project>
|
|
)",
|
|
readername.c_str(), readername.c_str());
|
|
throw std::logic_error(exceptionMsg.c_str());
|
|
}
|
|
|
|
Widget* widget = dynamic_cast<Widget*>(node);
|
|
if (widget)
|
|
{
|
|
auto callbackName = widget->getCallbackName();
|
|
auto callbackType = widget->getCallbackType();
|
|
|
|
bindCallback(callbackName, callbackType, widget, _rootNode);
|
|
}
|
|
|
|
/* To reconstruct nest node as WidgetCallBackHandlerProtocol. */
|
|
auto callbackHandler = dynamic_cast<WidgetCallBackHandlerProtocol*>(node);
|
|
if (callbackHandler)
|
|
{
|
|
_callbackHandlers.pushBack(node);
|
|
_rootNode = _callbackHandlers.back();
|
|
}
|
|
/**/
|
|
// _loadingNodeParentHierarchy.emplace_back(node);
|
|
}
|
|
|
|
// If node is invalid, there is no necessity to process children of node.
|
|
if (!node)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
auto children = nodetree->children();
|
|
int size = children->size();
|
|
for (int i = 0; i < size; ++i)
|
|
{
|
|
auto subNodeTree = children->Get(i);
|
|
Node* child = nodeWithFlatBuffers(subNodeTree, callback);
|
|
if (child)
|
|
{
|
|
if (auto pageView = dynamic_cast<PageView*>(node))
|
|
{
|
|
Layout* layout = dynamic_cast<Layout*>(child);
|
|
if (layout)
|
|
{
|
|
pageView->addPage(layout);
|
|
}
|
|
}
|
|
else if (auto listView = dynamic_cast<ListView*>(node))
|
|
{
|
|
Widget* widget = dynamic_cast<Widget*>(child);
|
|
if (widget)
|
|
{
|
|
listView->pushBackCustomItem(widget);
|
|
}
|
|
}
|
|
else if (auto radioButtonGroup = dynamic_cast<RadioButtonGroup*>(node))
|
|
{
|
|
radioButtonGroup->addRadioButton(dynamic_cast<RadioButton*>(child));
|
|
radioButtonGroup->addChild(child);
|
|
}
|
|
else
|
|
{
|
|
node->addChild(child);
|
|
}
|
|
|
|
if (callback)
|
|
{
|
|
callback(child);
|
|
}
|
|
}
|
|
}
|
|
|
|
// _loadingNodeParentHierarchy.pop_back();
|
|
|
|
return node;
|
|
}
|
|
}
|
|
|
|
bool CSLoader::bindCallback(std::string_view callbackName,
|
|
std::string_view callbackType,
|
|
ax::ui::Widget* sender,
|
|
ax::Node* handler)
|
|
{
|
|
if (callbackName.empty())
|
|
return false;
|
|
|
|
auto callbackHandler = dynamic_cast<WidgetCallBackHandlerProtocol*>(handler);
|
|
if (callbackHandler) // The handler can handle callback
|
|
{
|
|
if (callbackType == "Click")
|
|
{
|
|
Widget::ccWidgetClickCallback callbackFunc = callbackHandler->onLocateClickCallback(callbackName);
|
|
if (callbackFunc)
|
|
{
|
|
sender->addClickEventListener(callbackFunc);
|
|
return true;
|
|
}
|
|
}
|
|
else if (callbackType == "Touch")
|
|
{
|
|
Widget::ccWidgetTouchCallback callbackFunc = callbackHandler->onLocateTouchCallback(callbackName);
|
|
if (callbackFunc)
|
|
{
|
|
sender->addTouchEventListener(callbackFunc);
|
|
return true;
|
|
}
|
|
}
|
|
else if (callbackType == "Event")
|
|
{
|
|
Widget::ccWidgetEventCallback callbackFunc = callbackHandler->onLocateEventCallback(callbackName);
|
|
if (callbackFunc)
|
|
{
|
|
sender->addCCSEventListener(callbackFunc);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
AXLOG("callBackName %s cannot be found", callbackName.data());
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CSLoader::isWidget(std::string_view type)
|
|
{
|
|
return (type == ClassName_Panel || type == ClassName_Button || type == ClassName_CheckBox ||
|
|
type == ClassName_ImageView || type == ClassName_TextAtlas || type == ClassName_LabelAtlas ||
|
|
type == ClassName_LabelBMFont || type == ClassName_TextBMFont || type == ClassName_Text ||
|
|
type == ClassName_LoadingBar || type == ClassName_TextField || type == ClassName_Slider ||
|
|
type == ClassName_Layout || type == ClassName_ScrollView || type == ClassName_ListView ||
|
|
type == ClassName_PageView || type == ClassName_Widget || type == ClassName_Label);
|
|
}
|
|
|
|
bool CSLoader::isCustomWidget(std::string_view type)
|
|
{
|
|
Widget* widget = dynamic_cast<Widget*>(ObjectFactory::getInstance()->createObject(type));
|
|
if (widget)
|
|
{
|
|
AX_SAFE_DELETE(widget);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
std::string_view CSLoader::getGUIClassName(std::string_view name)
|
|
{
|
|
std::string_view convertedClassName;
|
|
if (name == "Panel")
|
|
{
|
|
convertedClassName = "Layout"sv;
|
|
}
|
|
else if (name == "TextArea")
|
|
{
|
|
convertedClassName = "Text"sv;
|
|
}
|
|
else if (name == "TextButton")
|
|
{
|
|
convertedClassName = "Button"sv;
|
|
}
|
|
else if (name == "Label")
|
|
{
|
|
convertedClassName = "Text"sv;
|
|
}
|
|
else if (name == "LabelAtlas")
|
|
{
|
|
convertedClassName = "TextAtlas"sv;
|
|
}
|
|
else if (name == "LabelBMFont")
|
|
{
|
|
convertedClassName = "TextBMFont"sv;
|
|
}
|
|
else
|
|
convertedClassName = name;
|
|
|
|
return convertedClassName;
|
|
}
|
|
|
|
std::string_view CSLoader::getWidgetReaderClassName(Widget* widget)
|
|
{
|
|
std::string_view readerName;
|
|
|
|
// 1st., custom widget parse properties of parent widget with parent widget reader
|
|
if (dynamic_cast<Button*>(widget))
|
|
{
|
|
readerName = "ButtonReader";
|
|
}
|
|
else if (dynamic_cast<CheckBox*>(widget))
|
|
{
|
|
readerName = "CheckBoxReader";
|
|
}
|
|
else if (dynamic_cast<ImageView*>(widget))
|
|
{
|
|
readerName = "ImageViewReader";
|
|
}
|
|
else if (dynamic_cast<TextAtlas*>(widget))
|
|
{
|
|
readerName = "TextAtlasReader";
|
|
}
|
|
else if (dynamic_cast<TextBMFont*>(widget))
|
|
{
|
|
readerName = "TextBMFontReader";
|
|
}
|
|
else if (dynamic_cast<Text*>(widget))
|
|
{
|
|
readerName = "TextReader";
|
|
}
|
|
else if (dynamic_cast<LoadingBar*>(widget))
|
|
{
|
|
readerName = "LoadingBarReader";
|
|
}
|
|
else if (dynamic_cast<Slider*>(widget))
|
|
{
|
|
readerName = "SliderReader";
|
|
}
|
|
else if (dynamic_cast<TextField*>(widget))
|
|
{
|
|
readerName = "TextFieldReader";
|
|
}
|
|
else if (dynamic_cast<ListView*>(widget))
|
|
{
|
|
readerName = "ListViewReader";
|
|
}
|
|
else if (dynamic_cast<PageView*>(widget))
|
|
{
|
|
readerName = "PageViewReader";
|
|
}
|
|
else if (dynamic_cast<ScrollView*>(widget))
|
|
{
|
|
readerName = "ScrollViewReader";
|
|
}
|
|
|
|
else if (dynamic_cast<Layout*>(widget))
|
|
{
|
|
readerName = "LayoutReader";
|
|
}
|
|
else if (dynamic_cast<Widget*>(widget))
|
|
{
|
|
readerName = "WidgetReader";
|
|
}
|
|
else
|
|
readerName = hlookup::empty_sv;
|
|
|
|
return readerName;
|
|
}
|
|
|
|
void CSLoader::registReaderObject(std::string_view className, ObjectFactory::Instance ins)
|
|
{
|
|
ObjectFactory::TInfo t;
|
|
t._class = className;
|
|
t._fun = ins;
|
|
|
|
ObjectFactory::getInstance()->registerType(t);
|
|
}
|
|
|
|
Node* CSLoader::createNodeWithFlatBuffersForSimulator(std::string_view filename)
|
|
{
|
|
FlatBuffersSerialize* fbs = FlatBuffersSerialize::getInstance();
|
|
fbs->_isSimulator = true;
|
|
FlatBufferBuilder* builder = fbs->createFlatBuffersWithXMLFileForSimulator(filename);
|
|
|
|
auto csparsebinary = GetCSParseBinary(builder->GetBufferPointer());
|
|
|
|
// decode plist
|
|
auto textures = csparsebinary->textures();
|
|
int textureSize = csparsebinary->textures()->size();
|
|
// AXLOG("textureSize = %d", textureSize);
|
|
for (int i = 0; i < textureSize; ++i)
|
|
{
|
|
SpriteFrameCache::getInstance()->addSpriteFramesWithFile(textures->Get(i)->c_str());
|
|
}
|
|
|
|
auto nodeTree = csparsebinary->nodeTree();
|
|
|
|
Node* node = nodeWithFlatBuffersForSimulator(nodeTree);
|
|
|
|
_rootNode = nullptr;
|
|
|
|
fbs->deleteFlatBufferBuilder();
|
|
|
|
return node;
|
|
}
|
|
|
|
Node* CSLoader::nodeWithFlatBuffersForSimulator(const flatbuffers::NodeTree* nodetree)
|
|
{
|
|
Node* node = nullptr;
|
|
|
|
std::string classname = nodetree->classname()->c_str();
|
|
|
|
auto options = nodetree->options();
|
|
|
|
if (classname == "ProjectNode")
|
|
{
|
|
auto reader = ProjectNodeReader::getInstance();
|
|
auto projectNodeOptions = (ProjectNodeOptions*)options->data();
|
|
std::string filePath = projectNodeOptions->fileName()->c_str();
|
|
|
|
cocostudio::timeline::ActionTimeline* action = nullptr;
|
|
if (filePath != "" && FileUtils::getInstance()->isFileExist(filePath))
|
|
{
|
|
node = createNodeWithFlatBuffersForSimulator(filePath);
|
|
action = cocostudio::timeline::ActionTimelineCache::getInstance()->createActionWithFlatBuffersForSimulator(
|
|
filePath);
|
|
}
|
|
else
|
|
{
|
|
node = Node::create();
|
|
}
|
|
reader->setPropsWithFlatBuffers(node, (const flatbuffers::Table*)options->data());
|
|
if (action)
|
|
{
|
|
action->setTimeSpeed(projectNodeOptions->innerActionSpeed());
|
|
node->runAction(action);
|
|
action->gotoFrameAndPause(0);
|
|
}
|
|
}
|
|
else if (classname == "SimpleAudio")
|
|
{
|
|
node = Node::create();
|
|
auto reader = ComAudioReader::getInstance();
|
|
Component* component = reader->createComAudioWithFlatBuffers((const flatbuffers::Table*)options->data());
|
|
if (component)
|
|
{
|
|
node->addComponent(component);
|
|
reader->setPropsWithFlatBuffers(node, (const flatbuffers::Table*)options->data());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::string readername{getGUIClassName(classname)};
|
|
readername.append("Reader");
|
|
|
|
NodeReaderProtocol* reader =
|
|
dynamic_cast<NodeReaderProtocol*>(ObjectFactory::getInstance()->createObject(readername));
|
|
if (reader)
|
|
{
|
|
node = reader->createNodeWithFlatBuffers((const flatbuffers::Table*)options->data());
|
|
}
|
|
|
|
Widget* widget = dynamic_cast<Widget*>(node);
|
|
if (widget)
|
|
{
|
|
auto callbackName = widget->getCallbackName();
|
|
auto callbackType = widget->getCallbackType();
|
|
|
|
bindCallback(callbackName, callbackType, widget, _rootNode);
|
|
}
|
|
|
|
if (_rootNode == nullptr)
|
|
{
|
|
_rootNode = node;
|
|
}
|
|
// _loadingNodeParentHierarchy.emplace_back(node);
|
|
}
|
|
|
|
// If node is invalid, there is no necessity to process children of node.
|
|
if (!node)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
auto children = nodetree->children();
|
|
int size = children->size();
|
|
for (int i = 0; i < size; ++i)
|
|
{
|
|
auto subNodeTree = children->Get(i);
|
|
Node* child = nodeWithFlatBuffersForSimulator(subNodeTree);
|
|
if (child)
|
|
{
|
|
PageView* pageView = dynamic_cast<PageView*>(node);
|
|
ListView* listView = dynamic_cast<ListView*>(node);
|
|
if (pageView)
|
|
{
|
|
Layout* layout = dynamic_cast<Layout*>(child);
|
|
if (layout)
|
|
{
|
|
pageView->addPage(layout);
|
|
}
|
|
}
|
|
else if (listView)
|
|
{
|
|
Widget* widget = dynamic_cast<Widget*>(child);
|
|
if (widget)
|
|
{
|
|
listView->pushBackCustomItem(widget);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
node->addChild(child);
|
|
}
|
|
}
|
|
}
|
|
|
|
// _loadingNodeParentHierarchy.pop_back();
|
|
|
|
return node;
|
|
}
|
|
|
|
NS_AX_END
|