mirror of https://github.com/axmolengine/axmol.git
968 lines
22 KiB
C++
968 lines
22 KiB
C++
|
|
#include "EffekseerForCocos2d-x.h"
|
|
|
|
#ifdef AX_USE_METAL
|
|
#include "renderer/backend/Device.h"
|
|
#endif
|
|
|
|
namespace efk
|
|
{
|
|
|
|
void CalculateCameraDirectionAndPosition(const Effekseer::Matrix44& matrix, Effekseer::Vector3D& direction, Effekseer::Vector3D& position)
|
|
{
|
|
const auto& mat = matrix;
|
|
|
|
direction = -::Effekseer::Vector3D(matrix.Values[0][2], matrix.Values[1][2], matrix.Values[2][2]);
|
|
|
|
{
|
|
auto localPos = ::Effekseer::Vector3D(-mat.Values[3][0], -mat.Values[3][1], -mat.Values[3][2]);
|
|
auto f = ::Effekseer::Vector3D(mat.Values[0][2], mat.Values[1][2], mat.Values[2][2]);
|
|
auto r = ::Effekseer::Vector3D(mat.Values[0][0], mat.Values[1][0], mat.Values[2][0]);
|
|
auto u = ::Effekseer::Vector3D(mat.Values[0][1], mat.Values[1][1], mat.Values[2][1]);
|
|
|
|
position = r * localPos.X + u * localPos.Y + f * localPos.Z;
|
|
}
|
|
}
|
|
|
|
class ImageAccessor : public cocos2d::Image
|
|
{
|
|
public:
|
|
static bool getPngPremultipledAlphaEnabled() { return PNG_PREMULTIPLIED_ALPHA_ENABLED; }
|
|
};
|
|
|
|
Effekseer::ModelLoaderRef CreateModelLoader(Effekseer::FileInterfaceRef);
|
|
|
|
::Effekseer::MaterialLoaderRef CreateMaterialLoader(Effekseer::FileInterfaceRef);
|
|
|
|
void UpdateTextureData(::Effekseer::TextureRef textureData, cocos2d::Texture2D* texture);
|
|
|
|
void CleanupTextureData(::Effekseer::TextureRef textureData);
|
|
|
|
::EffekseerRenderer::DistortingCallback* CreateDistortingCallback(::EffekseerRenderer::RendererRef, Effekseer::RefPtr<::EffekseerRenderer::CommandList>);
|
|
|
|
void ResetBackground(::EffekseerRenderer::RendererRef renderer);
|
|
|
|
int ccNextPOT(int x)
|
|
{
|
|
x = x - 1;
|
|
x = x | (x >> 1);
|
|
x = x | (x >> 2);
|
|
x = x | (x >> 4);
|
|
x = x | (x >> 8);
|
|
x = x | (x >> 16);
|
|
return x + 1;
|
|
}
|
|
|
|
static std::u16string getFilenameWithoutExt(const char16_t* path)
|
|
{
|
|
int start = 0;
|
|
int end = 0;
|
|
|
|
for (int i = 0; path[i] != 0; i++)
|
|
{
|
|
if (path[i] == u'/' || path[i] == u'\\')
|
|
{
|
|
start = i + 1;
|
|
}
|
|
}
|
|
|
|
for (int i = start; path[i] != 0; i++)
|
|
{
|
|
if (path[i] == u'.')
|
|
{
|
|
end = i;
|
|
}
|
|
}
|
|
|
|
std::vector<char16_t> ret;
|
|
|
|
for (int i = start; i < end; i++)
|
|
{
|
|
ret.push_back(path[i]);
|
|
}
|
|
ret.push_back(0);
|
|
|
|
return std::u16string(ret.data());
|
|
}
|
|
|
|
class EffekseerFileReader : public Effekseer::FileReader
|
|
{
|
|
std::vector<uint8_t> data;
|
|
int32_t position;
|
|
|
|
public:
|
|
EffekseerFileReader(std::vector<uint8_t>& data)
|
|
{
|
|
this->data = data;
|
|
position = 0;
|
|
}
|
|
|
|
virtual ~EffekseerFileReader() {}
|
|
|
|
size_t Read(void* buffer, size_t size) override
|
|
{
|
|
int32_t readable = size;
|
|
if (data.size() - position < size)
|
|
readable = data.size() - position;
|
|
|
|
memcpy(buffer, &(data[position]), readable);
|
|
position += readable;
|
|
return readable;
|
|
}
|
|
|
|
void Seek(int position) override
|
|
{
|
|
this->position = position;
|
|
if (this->position < 0)
|
|
this->position = 0;
|
|
if (this->position > static_cast<int32_t>(data.size()))
|
|
this->position = static_cast<int32_t>(data.size());
|
|
}
|
|
|
|
int GetPosition() const override { return position; }
|
|
|
|
size_t GetLength() const override { return data.size(); }
|
|
};
|
|
|
|
class EffekseerFile : public Effekseer::FileInterface
|
|
{
|
|
public:
|
|
EffekseerFile();
|
|
virtual ~EffekseerFile();
|
|
Effekseer::FileReaderRef OpenRead(const EFK_CHAR* path);
|
|
Effekseer::FileWriterRef OpenWrite(const EFK_CHAR* path);
|
|
};
|
|
|
|
EffekseerFile::EffekseerFile() {}
|
|
EffekseerFile::~EffekseerFile() {}
|
|
|
|
Effekseer::FileReaderRef EffekseerFile::OpenRead(const EFK_CHAR* path)
|
|
{
|
|
char path_[300];
|
|
::Effekseer::ConvertUtf16ToUtf8(path_, 300, path);
|
|
|
|
cocos2d::Data data_ = cocos2d::FileUtils::getInstance()->getDataFromFile(path_);
|
|
|
|
if (data_.isNull())
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<uint8_t> data;
|
|
data.resize(data_.getSize());
|
|
memcpy(data.data(), data_.getBytes(), data.size());
|
|
return Effekseer::MakeRefPtr<EffekseerFileReader>(data);
|
|
}
|
|
|
|
Effekseer::FileWriterRef EffekseerFile::OpenWrite(const EFK_CHAR* path) { return nullptr; }
|
|
|
|
static std::map<Effekseer::TextureRef, std::basic_string<EFK_CHAR>> g_glTex2FilePath;
|
|
static std::map<std::basic_string<EFK_CHAR>, cocos2d::Texture2D*> g_filePath2CTex;
|
|
static std::map<std::basic_string<EFK_CHAR>, Effekseer::TextureRef> g_filePath2EffectData;
|
|
|
|
class TextureLoader : public ::Effekseer::TextureLoader
|
|
{
|
|
private:
|
|
::Effekseer::FileInterfaceRef m_fileInterface;
|
|
::Effekseer::DefaultFileInterface m_defaultFileInterface;
|
|
|
|
public:
|
|
TextureLoader(::Effekseer::FileInterfaceRef fileInterface = NULL);
|
|
virtual ~TextureLoader();
|
|
|
|
public:
|
|
Effekseer::TextureRef Load(const EFK_CHAR* path, ::Effekseer::TextureType textureType) override;
|
|
|
|
void Unload(Effekseer::TextureRef data) override;
|
|
};
|
|
|
|
TextureLoader::TextureLoader(::Effekseer::FileInterfaceRef fileInterface) : m_fileInterface(fileInterface)
|
|
{
|
|
}
|
|
|
|
TextureLoader::~TextureLoader() {}
|
|
|
|
Effekseer::TextureRef TextureLoader::Load(const EFK_CHAR* path, ::Effekseer::TextureType textureType)
|
|
{
|
|
auto key = std::basic_string<EFK_CHAR>(path);
|
|
if (g_filePath2CTex.find(key) != g_filePath2CTex.end())
|
|
{
|
|
auto texture = g_filePath2CTex[key];
|
|
texture->retain();
|
|
return g_filePath2EffectData[key];
|
|
}
|
|
|
|
auto reader = m_fileInterface->OpenRead(path);
|
|
|
|
if (reader != nullptr)
|
|
{
|
|
size_t size_texture = reader->GetLength();
|
|
char* data_texture = new char[size_texture];
|
|
reader->Read(data_texture, size_texture);
|
|
|
|
cocos2d::Image* image = new cocos2d::Image();
|
|
cocos2d::Texture2D* texture = new cocos2d::Texture2D();
|
|
|
|
auto backup = ImageAccessor::getPngPremultipledAlphaEnabled();
|
|
cocos2d::Image::setPNGPremultipliedAlphaEnabled(false);
|
|
|
|
if (image != nullptr && texture != nullptr && image->initWithImageData((const uint8_t*)data_texture, size_texture))
|
|
{
|
|
if (texture->initWithImage(image))
|
|
{
|
|
|
|
if(texture->getPixelsWide() > 1 || texture->getPixelsHigh() > 1)
|
|
{
|
|
#ifdef AX_USE_METAL
|
|
texture->generateMipmap();
|
|
#else
|
|
if (texture->getPixelsWide() == ccNextPOT(texture->getPixelsWide()) &&
|
|
texture->getPixelsHigh() == ccNextPOT(texture->getPixelsHigh()))
|
|
{
|
|
texture->generateMipmap();
|
|
}
|
|
else
|
|
{
|
|
char path8[300];
|
|
::Effekseer::ConvertUtf16ToUtf8(path8, 300, path);
|
|
CCLOG("%s : The texture is not shown on a mobile. The size is not power of two.", path8);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
AX_SAFE_DELETE(texture);
|
|
AX_SAFE_DELETE(image);
|
|
}
|
|
}
|
|
AX_SAFE_DELETE(image);
|
|
|
|
delete[] data_texture;
|
|
|
|
Effekseer::TextureRef textureData = Effekseer::MakeRefPtr<Effekseer::Texture>();;
|
|
UpdateTextureData(textureData, texture);
|
|
g_filePath2CTex[key] = texture;
|
|
g_filePath2EffectData[key] = textureData;
|
|
g_glTex2FilePath[textureData] = key;
|
|
|
|
cocos2d::Image::setPNGPremultipliedAlphaEnabled(backup);
|
|
|
|
return textureData;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void TextureLoader::Unload(Effekseer::TextureRef data)
|
|
{
|
|
if (data != NULL)
|
|
{
|
|
auto path = g_glTex2FilePath[data];
|
|
auto tex = g_filePath2CTex[path];
|
|
|
|
if (tex->getReferenceCount() == 1)
|
|
{
|
|
CleanupTextureData(data);
|
|
g_glTex2FilePath.erase(data);
|
|
g_filePath2EffectData.erase(path);
|
|
g_filePath2CTex.erase(path);
|
|
}
|
|
tex->release();
|
|
}
|
|
}
|
|
|
|
class EffekseerSetting;
|
|
|
|
static Effekseer::RefPtr<EffekseerSetting> g_effekseerSetting = nullptr;
|
|
|
|
class EffekseerSetting : public ::Effekseer::Setting
|
|
{
|
|
protected:
|
|
Effekseer::FileInterfaceRef effectFile = nullptr;
|
|
|
|
public:
|
|
|
|
EffekseerSetting()
|
|
{
|
|
effectFile = Effekseer::MakeRefPtr<EffekseerFile>();
|
|
SetEffectLoader(Effekseer::Effect::CreateEffectLoader(effectFile));
|
|
SetTextureLoader(Effekseer::MakeRefPtr<TextureLoader>(effectFile));
|
|
SetModelLoader(CreateModelLoader(effectFile));
|
|
SetMaterialLoader(CreateMaterialLoader(effectFile));
|
|
SetCurveLoader(Effekseer::MakeRefPtr<Effekseer::CurveLoader>(effectFile));
|
|
// TODO sound
|
|
}
|
|
|
|
virtual ~EffekseerSetting()
|
|
{
|
|
}
|
|
|
|
static Effekseer::RefPtr<EffekseerSetting> create()
|
|
{
|
|
if (g_effekseerSetting == nullptr)
|
|
{
|
|
g_effekseerSetting = Effekseer::MakeRefPtr<EffekseerSetting>();
|
|
}
|
|
|
|
return g_effekseerSetting;
|
|
}
|
|
|
|
int Release() override
|
|
{
|
|
auto ret = ::Effekseer::Setting::Release();
|
|
if (ret == 1)
|
|
{
|
|
g_effekseerSetting = nullptr;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
struct EffectResource
|
|
{
|
|
Effekseer::EffectRef effect = nullptr;
|
|
int counter = 0;
|
|
};
|
|
|
|
static InternalManager* g_internalManager = nullptr;
|
|
|
|
class InternalManager : public Effekseer::ReferenceObject
|
|
{
|
|
std::map<std::u16string, EffectResource> path2effect;
|
|
std::map<Effekseer::EffectRef, std::u16string> effect2path;
|
|
|
|
std::set<Effekseer::ManagerRef> managers;
|
|
std::vector<Effekseer::ManagerRef> managersVector;
|
|
|
|
Effekseer::ServerRef server = nullptr;
|
|
|
|
public:
|
|
InternalManager() {}
|
|
|
|
virtual ~InternalManager() override
|
|
{
|
|
if (server != nullptr)
|
|
{
|
|
server->Stop();
|
|
}
|
|
|
|
g_internalManager = nullptr;
|
|
}
|
|
|
|
Effekseer::EffectRef loadEffect(const EFK_CHAR* path, float maginification)
|
|
{
|
|
auto it_effect = path2effect.find(path);
|
|
|
|
if (it_effect == path2effect.end())
|
|
{
|
|
EffectResource resource;
|
|
auto setting = EffekseerSetting::create();
|
|
resource.effect = Effekseer::Effect::Create(setting.DownCast<Effekseer::Setting>(), path, maginification);
|
|
resource.counter = 1;
|
|
|
|
if (resource.effect != nullptr)
|
|
{
|
|
path2effect[path] = resource;
|
|
effect2path[resource.effect] = path;
|
|
|
|
if (server != nullptr)
|
|
{
|
|
auto key = getFilenameWithoutExt(path);
|
|
server->Register(key.c_str(), resource.effect);
|
|
}
|
|
|
|
return resource.effect;
|
|
}
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
it_effect->second.counter++;
|
|
return it_effect->second.effect;
|
|
}
|
|
}
|
|
|
|
void unloadEffect(Effekseer::EffectRef effect)
|
|
{
|
|
auto it_path = effect2path.find(effect);
|
|
if (it_path == effect2path.end())
|
|
return;
|
|
|
|
auto it_effect = path2effect.find(it_path->second);
|
|
if (it_effect == path2effect.end())
|
|
return;
|
|
|
|
it_effect->second.counter--;
|
|
if (it_effect->second.counter == 0)
|
|
{
|
|
if (server != nullptr)
|
|
{
|
|
server->Unregister(it_effect->second.effect);
|
|
}
|
|
|
|
it_effect->second.effect = nullptr;
|
|
effect2path.erase(it_path);
|
|
path2effect.erase(it_effect);
|
|
}
|
|
}
|
|
|
|
void registerManager(Effekseer::ManagerRef manager)
|
|
{
|
|
managers.insert(manager);
|
|
|
|
managersVector.clear();
|
|
for (auto m : managers)
|
|
{
|
|
managersVector.push_back(m);
|
|
}
|
|
}
|
|
|
|
void unregisterManager(Effekseer::ManagerRef manager)
|
|
{
|
|
managers.erase(manager);
|
|
managersVector.clear();
|
|
for (auto m : managers)
|
|
{
|
|
managersVector.push_back(m);
|
|
}
|
|
}
|
|
|
|
bool makeNetworkServerEnabled(uint16_t port)
|
|
{
|
|
if (server != nullptr)
|
|
return false;
|
|
server = Effekseer::Server::Create();
|
|
if (!server->Start(port))
|
|
{
|
|
server = nullptr;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void update()
|
|
{
|
|
if (server != nullptr)
|
|
{
|
|
if (managersVector.size() > 0)
|
|
{
|
|
server->Update(managersVector.data(), managersVector.size());
|
|
}
|
|
else
|
|
{
|
|
server->Update();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
InternalManager* getGlobalInternalManager()
|
|
{
|
|
if (g_internalManager == nullptr)
|
|
{
|
|
g_internalManager = new InternalManager();
|
|
}
|
|
else
|
|
{
|
|
g_internalManager->AddRef();
|
|
}
|
|
|
|
return g_internalManager;
|
|
}
|
|
|
|
Effect* Effect::create(const std::string& filename, float maginification)
|
|
{
|
|
EFK_CHAR path_[300];
|
|
::Effekseer::ConvertUtf8ToUtf16(path_, 300, filename.c_str());
|
|
|
|
auto internalManager = getGlobalInternalManager();
|
|
|
|
auto effect = internalManager->loadEffect(path_, maginification);
|
|
|
|
if (effect != nullptr)
|
|
{
|
|
auto e = new Effect(internalManager);
|
|
e->effect = effect;
|
|
e->autorelease();
|
|
ES_SAFE_RELEASE(internalManager);
|
|
return e;
|
|
}
|
|
|
|
ES_SAFE_RELEASE(internalManager);
|
|
return nullptr;
|
|
}
|
|
|
|
Effect::Effect(InternalManager* internalManager)
|
|
{
|
|
internalManager_ = internalManager;
|
|
ES_SAFE_ADDREF(internalManager_);
|
|
}
|
|
|
|
Effect::~Effect()
|
|
{
|
|
if (internalManager_ != nullptr)
|
|
{
|
|
internalManager_->unloadEffect(effect);
|
|
}
|
|
|
|
ES_SAFE_RELEASE(internalManager_);
|
|
}
|
|
|
|
EffectEmitter* EffectEmitter::create(EffectManager* manager) { return new EffectEmitter(manager); }
|
|
|
|
EffectEmitter* EffectEmitter::create(EffectManager* manager, const std::string& filename, float maginification)
|
|
{
|
|
auto effectEmitter = new EffectEmitter(manager);
|
|
auto effect = Effect::create(filename, maginification);
|
|
effectEmitter->setEffect(effect);
|
|
effectEmitter->playOnEnter = true;
|
|
return effectEmitter;
|
|
}
|
|
|
|
EffectEmitter::EffectEmitter(EffectManager* manager)
|
|
{
|
|
this->manager = manager;
|
|
|
|
if (manager != nullptr)
|
|
{
|
|
manager->retain();
|
|
}
|
|
|
|
autorelease();
|
|
|
|
dynamicInputs_.fill(0.0f);
|
|
}
|
|
|
|
EffectEmitter::~EffectEmitter()
|
|
{
|
|
if (effect_ != nullptr)
|
|
{
|
|
effect_->release();
|
|
}
|
|
|
|
if (manager != nullptr)
|
|
{
|
|
manager->release();
|
|
}
|
|
}
|
|
|
|
Effect* EffectEmitter::getEffect() { return effect_; }
|
|
|
|
void EffectEmitter::setEffect(Effect* effect)
|
|
{
|
|
if (effect_ != nullptr)
|
|
effect_->release();
|
|
|
|
effect_ = effect;
|
|
|
|
if (effect_ != nullptr)
|
|
effect_->retain();
|
|
}
|
|
|
|
::Effekseer::Handle EffectEmitter::getInternalHandle() const { return handle; }
|
|
|
|
void EffectEmitter::play() { play(0); }
|
|
|
|
void EffectEmitter::play(int32_t startTime)
|
|
{
|
|
if (effect_ == nullptr)
|
|
return;
|
|
if (manager == nullptr)
|
|
return;
|
|
|
|
if (startTime == 0)
|
|
{
|
|
handle = manager->play(effect_, 0, 0, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
handle = manager->play(effect_, 0, 0, 0, startTime);
|
|
}
|
|
|
|
auto transform = this->getNodeToWorldTransform();
|
|
manager->setMatrix(handle, transform);
|
|
isPlayedAtLeastOnce = true;
|
|
|
|
setTargetPosition(targetPosition_);
|
|
setColor(color_);
|
|
setSpeed(speed_);
|
|
|
|
for(size_t i = 0; i < 4; i++)
|
|
{
|
|
setDynamicInput(i, dynamicInputs_[i]);
|
|
}
|
|
}
|
|
|
|
bool EffectEmitter::getPlayOnEnter() { return playOnEnter; }
|
|
|
|
void EffectEmitter::setPlayOnEnter(bool value) { playOnEnter = value; }
|
|
|
|
bool EffectEmitter::getIsLooping() { return isLooping; }
|
|
|
|
void EffectEmitter::setIsLooping(bool value) { isLooping = value; }
|
|
|
|
bool EffectEmitter::getRemoveOnStop() { return removeOnStop; }
|
|
|
|
void EffectEmitter::setRemoveOnStop(bool value) { removeOnStop = value; }
|
|
|
|
void EffectEmitter::setColor(cocos2d::Color4B color)
|
|
{
|
|
color_ = color;
|
|
Effekseer::Color col;
|
|
col.R = color.r;
|
|
col.G = color.g;
|
|
col.B = color.b;
|
|
col.A = color.a;
|
|
manager->getInternalManager()->SetAllColor(handle, col);
|
|
}
|
|
|
|
float EffectEmitter::getSpeed()
|
|
{
|
|
return speed_;
|
|
// return manager->getInternalManager()->GetSpeed(handle);
|
|
}
|
|
|
|
void EffectEmitter::setSpeed(float speed)
|
|
{
|
|
speed_ = speed;
|
|
manager->getInternalManager()->SetSpeed(handle, speed);
|
|
}
|
|
|
|
void EffectEmitter::setTargetPosition(cocos2d::Vec3 position)
|
|
{
|
|
targetPosition_ = position;
|
|
manager->getInternalManager()->SetTargetLocation(handle, position.x, position.y, position.z);
|
|
}
|
|
|
|
float EffectEmitter::getDynamicInput(int32_t index)
|
|
{
|
|
return dynamicInputs_.at(index);
|
|
}
|
|
|
|
void EffectEmitter::setDynamicInput(int32_t index, float value)
|
|
{
|
|
dynamicInputs_.at(index) = value;
|
|
manager->getInternalManager()->SetDynamicInput(handle, index, value);
|
|
}
|
|
|
|
bool EffectEmitter::isPlaying() { return manager->getInternalManager()->Exists(handle); }
|
|
|
|
void EffectEmitter::stop() { manager->getInternalManager()->StopEffect(handle); }
|
|
|
|
void EffectEmitter::stopRoot() { manager->getInternalManager()->StopRoot(handle); }
|
|
|
|
void EffectEmitter::onEnter()
|
|
{
|
|
cocos2d::Node::onEnter();
|
|
|
|
if (playOnEnter)
|
|
{
|
|
play();
|
|
}
|
|
|
|
scheduleUpdate();
|
|
}
|
|
|
|
void EffectEmitter::onExit()
|
|
{
|
|
auto m = manager->getInternalManager();
|
|
if (m->Exists(handle))
|
|
{
|
|
manager->getInternalManager()->StopEffect(handle);
|
|
}
|
|
|
|
cocos2d::Node::onExit();
|
|
}
|
|
|
|
void EffectEmitter::update(float delta)
|
|
{
|
|
auto m = manager->getInternalManager();
|
|
if (!m->Exists(handle))
|
|
{
|
|
if (isLooping)
|
|
{
|
|
play();
|
|
}
|
|
else if (removeOnStop && isPlayedAtLeastOnce)
|
|
{
|
|
auto transform = this->getNodeToWorldTransform();
|
|
manager->setMatrix(handle, transform);
|
|
cocos2d::Node::update(delta);
|
|
|
|
this->removeFromParent();
|
|
return;
|
|
}
|
|
}
|
|
|
|
{
|
|
auto transform = this->getNodeToWorldTransform();
|
|
manager->setMatrix(handle, transform);
|
|
|
|
cocos2d::Node::update(delta);
|
|
}
|
|
}
|
|
|
|
void EffectEmitter::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& parentTransform, uint32_t parentFlags)
|
|
{
|
|
if (!manager->getInternalManager()->GetShown(handle) ||
|
|
manager->getInternalManager()->GetTotalInstanceCount() < 1)
|
|
return; // nothing to draw
|
|
|
|
#ifdef AX_USE_METAL
|
|
if (!manager->isDistorted)
|
|
{
|
|
// allow frame buffer texture to be copied for distortion
|
|
cocos2d::backend::Device::getInstance()->setFrameBufferOnly(false);
|
|
}
|
|
#endif
|
|
|
|
auto renderCommand = renderer->nextCallbackCommand();
|
|
|
|
renderCommand->init(_globalZOrder);
|
|
|
|
auto renderer2d = manager->getInternalRenderer();
|
|
Effekseer::Matrix44 mCamera = renderer2d->GetCameraMatrix();
|
|
Effekseer::Matrix44 mProj = renderer2d->GetProjectionMatrix();
|
|
renderCommand->func = [=]() -> void {
|
|
renderer2d->SetCameraMatrix(mCamera);
|
|
renderer2d->SetProjectionMatrix(mProj);
|
|
|
|
#ifdef AX_USE_METAL
|
|
auto commandList = manager->getInternalCommandList();
|
|
beforeRender(renderer2d, commandList);
|
|
#endif
|
|
renderer2d->SetRestorationOfStatesFlag(true);
|
|
renderer2d->BeginRendering();
|
|
manager->getInternalManager()->DrawHandle(handle);
|
|
renderer2d->EndRendering();
|
|
|
|
// Count drawcall and vertex
|
|
renderer->addDrawnBatches(renderer2d->GetDrawCallCount());
|
|
renderer->addDrawnVertices(renderer2d->GetDrawVertexCount());
|
|
renderer2d->ResetDrawCallCount();
|
|
renderer2d->ResetDrawVertexCount();
|
|
|
|
#ifdef AX_USE_METAL
|
|
afterRender(renderer2d, commandList);
|
|
#endif
|
|
|
|
};
|
|
|
|
renderer->addCommand(renderCommand);
|
|
|
|
cocos2d::Node::draw(renderer, parentTransform, parentFlags);
|
|
}
|
|
|
|
::Effekseer::Handle EffectManager::play(Effect* effect, float x, float y, float z)
|
|
{
|
|
return manager2d->Play(effect->getInternalPtr(), x, y, z);
|
|
}
|
|
|
|
::Effekseer::Handle EffectManager::play(Effect* effect, float x, float y, float z, int startTime)
|
|
{
|
|
return manager2d->Play(effect->getInternalPtr(), Effekseer::Vector3D(x, y, z), startTime);
|
|
}
|
|
|
|
void EffectManager::setMatrix(::Effekseer::Handle handle, const cocos2d::Mat4& mat)
|
|
{
|
|
Effekseer::Matrix43 mat_;
|
|
const float* p = mat.m;
|
|
int size = sizeof(float) * 3;
|
|
memcpy(mat_.Value[0], p, size);
|
|
p += 4;
|
|
memcpy(mat_.Value[1], p, size);
|
|
p += 4;
|
|
memcpy(mat_.Value[2], p, size);
|
|
p += 4;
|
|
memcpy(mat_.Value[3], p, size);
|
|
manager2d->SetMatrix(handle, mat_);
|
|
}
|
|
|
|
void EffectManager::setPotation(::Effekseer::Handle handle, float x, float y, float z) { manager2d->SetLocation(handle, x, y, z); }
|
|
|
|
void EffectManager::setRotation(::Effekseer::Handle handle, float x, float y, float z) { manager2d->SetRotation(handle, x, y, z); }
|
|
|
|
void EffectManager::setScale(::Effekseer::Handle handle, float x, float y, float z) { manager2d->SetScale(handle, x, y, z); }
|
|
|
|
bool EffectManager::Initialize(cocos2d::Size visibleSize)
|
|
{
|
|
int32_t spriteSize = 4000;
|
|
|
|
#if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID)
|
|
// large buffer make application slow on Android
|
|
spriteSize = 600;
|
|
#endif
|
|
|
|
CreateRenderer(spriteSize);
|
|
|
|
manager2d = ::Effekseer::Manager::Create(8000);
|
|
|
|
// set camera and projection matrix for 2d
|
|
// If you special camera or 3d, please set yourself with setCameraMatrix and setProjectionMatrix
|
|
renderer2d->SetProjectionMatrix(::Effekseer::Matrix44().OrthographicRH(visibleSize.width, visibleSize.height, 1.0f, 400.0f));
|
|
|
|
renderer2d->SetCameraMatrix(
|
|
::Effekseer::Matrix44().LookAtRH(::Effekseer::Vector3D(visibleSize.width / 2.0f, visibleSize.height / 2.0f, 200.0f),
|
|
::Effekseer::Vector3D(visibleSize.width / 2.0f, visibleSize.height / 2.0f, -200.0f),
|
|
::Effekseer::Vector3D(0.0f, 1.0f, 0.0f)));
|
|
|
|
distortingCallback = CreateDistortingCallback(renderer2d, commandList_);
|
|
|
|
manager2d->SetSpriteRenderer(renderer2d->CreateSpriteRenderer());
|
|
manager2d->SetRibbonRenderer(renderer2d->CreateRibbonRenderer());
|
|
manager2d->SetRingRenderer(renderer2d->CreateRingRenderer());
|
|
manager2d->SetModelRenderer(renderer2d->CreateModelRenderer());
|
|
manager2d->SetTrackRenderer(renderer2d->CreateTrackRenderer());
|
|
|
|
internalManager_ = getGlobalInternalManager();
|
|
internalManager_->registerManager(manager2d);
|
|
|
|
return true;
|
|
}
|
|
|
|
EffectManager* EffectManager::create(cocos2d::Size visibleSize)
|
|
{
|
|
auto ret = new EffectManager();
|
|
if (ret->Initialize(visibleSize))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
ret->release();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
EffectManager::EffectManager() {}
|
|
|
|
EffectManager::~EffectManager()
|
|
{
|
|
if (distortingCallback != nullptr &&
|
|
renderer2d->GetDistortingCallback() != distortingCallback)
|
|
{
|
|
delete distortingCallback;
|
|
distortingCallback = nullptr;
|
|
}
|
|
|
|
onDestructor();
|
|
|
|
if (manager2d != nullptr)
|
|
{
|
|
internalManager_->unregisterManager(manager2d);
|
|
manager2d = nullptr;
|
|
}
|
|
|
|
if (renderer2d != nullptr)
|
|
{
|
|
renderer2d = nullptr;
|
|
}
|
|
|
|
memoryPool_.Reset();
|
|
commandList_.Reset();
|
|
ES_SAFE_RELEASE(internalManager_);
|
|
}
|
|
|
|
void EffectManager::setIsDistortionEnabled(bool value)
|
|
{
|
|
isDistortionEnabled = value;
|
|
if (isDistortionEnabled)
|
|
{
|
|
renderer2d->SetDistortingCallback(distortingCallback);
|
|
}
|
|
else
|
|
{
|
|
renderer2d->SetDistortingCallback(nullptr);
|
|
}
|
|
}
|
|
|
|
void EffectManager::begin(cocos2d::Renderer* renderer, float globalZOrder)
|
|
{
|
|
if (isDistortionEnabled)
|
|
{
|
|
isDistorted = false;
|
|
}
|
|
else
|
|
{
|
|
isDistorted = true;
|
|
ResetBackground(renderer2d);
|
|
}
|
|
|
|
newFrame();
|
|
|
|
// TODO Batch render
|
|
/*
|
|
beginCommand.init(globalZOrder);
|
|
beginCommand.func = [this]() -> void
|
|
{
|
|
renderer2d->SetRestorationOfStatesFlag(true);
|
|
renderer2d->BeginRendering();
|
|
manager2d->Draw();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
renderer->addCommand(&beginCommand);
|
|
*/
|
|
}
|
|
|
|
void EffectManager::end(cocos2d::Renderer* renderer, float globalZOrder)
|
|
{
|
|
// TODO Batch render
|
|
/*
|
|
endCommand.init(globalZOrder);
|
|
endCommand.func = [this]() -> void
|
|
{
|
|
renderer2d->ResetRenderState();
|
|
renderer2d->EndRendering();
|
|
};
|
|
|
|
renderer->addCommand(&endCommand);
|
|
*/
|
|
}
|
|
|
|
void EffectManager::setCameraMatrix(const cocos2d::Mat4& mat)
|
|
{
|
|
Effekseer::Matrix44 mat_;
|
|
memcpy(mat_.Values, mat.m, sizeof(float) * 16);
|
|
|
|
::Effekseer::Vector3D cameraPosition;
|
|
::Effekseer::Vector3D cameraFrontDirection;
|
|
CalculateCameraDirectionAndPosition(mat_, cameraFrontDirection, cameraPosition);
|
|
|
|
Effekseer::Manager::LayerParameter layerParam;
|
|
layerParam.ViewerPosition = cameraPosition;
|
|
manager2d->SetLayerParameter(0, layerParam);
|
|
|
|
getInternalRenderer()->SetCameraMatrix(mat_);
|
|
}
|
|
|
|
void EffectManager::setProjectionMatrix(const cocos2d::Mat4& mat)
|
|
{
|
|
Effekseer::Matrix44 mat_;
|
|
memcpy(mat_.Values, mat.m, sizeof(float) * 16);
|
|
getInternalRenderer()->SetProjectionMatrix(mat_);
|
|
}
|
|
|
|
void EffectManager::update(float delta)
|
|
{
|
|
manager2d->Update();
|
|
time_ += delta;
|
|
renderer2d->SetTime(time_);
|
|
}
|
|
|
|
NetworkServer* NetworkServer::create() { return new NetworkServer(); }
|
|
|
|
NetworkServer::NetworkServer() { internalManager_ = getGlobalInternalManager(); }
|
|
|
|
NetworkServer::~NetworkServer() { ES_SAFE_RELEASE(internalManager_); }
|
|
|
|
bool NetworkServer::makeNetworkServerEnabled(uint16_t port) { return internalManager_->makeNetworkServerEnabled(port); }
|
|
|
|
void NetworkServer::update() { internalManager_->update(); }
|
|
} // namespace efk
|