2019-11-23 20:27:39 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (C) 2013 Henry van Merode. All rights reserved.
|
|
|
|
Copyright (c) 2015-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
|
|
|
|
2022-10-01 16:24:52 +08:00
|
|
|
https://axmolengine.github.io/
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
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.
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-06-11 13:08:08 +08:00
|
|
|
#include "PUMaterialManager.h"
|
|
|
|
#include "extensions/Particle3D/PU/PUScriptCompiler.h"
|
|
|
|
#include "extensions/Particle3D/PU/PUTranslateManager.h"
|
|
|
|
#include "platform/FileUtils.h"
|
|
|
|
#include "platform/PlatformMacros.h"
|
2019-11-23 20:27:39 +08:00
|
|
|
#include "renderer/backend/Types.h"
|
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
#if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32)
|
2021-12-25 10:04:45 +08:00
|
|
|
# include <io.h>
|
2022-07-16 10:43:05 +08:00
|
|
|
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID)
|
2023-06-11 13:08:08 +08:00
|
|
|
# include "platform/android/FileUtils-android.h"
|
2021-12-25 10:04:45 +08:00
|
|
|
# include <android/asset_manager.h>
|
2022-07-16 10:43:05 +08:00
|
|
|
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC)
|
2021-12-25 10:04:45 +08:00
|
|
|
# include <ftw.h>
|
2022-07-16 10:43:05 +08:00
|
|
|
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX)
|
2021-12-25 10:04:45 +08:00
|
|
|
# include <sys/types.h>
|
|
|
|
# include <sys/stat.h>
|
|
|
|
# include <dirent.h>
|
2023-09-02 20:36:55 +08:00
|
|
|
#else
|
|
|
|
# include "base/filesystem.h"
|
2019-11-23 20:27:39 +08:00
|
|
|
#endif
|
2023-09-02 20:36:55 +08:00
|
|
|
|
|
|
|
#include "yasio/string_view.hpp"
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_BEGIN
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
PUMaterial::PUMaterial()
|
2021-12-25 10:04:45 +08:00
|
|
|
: isEnabledLight(true)
|
|
|
|
, ambientColor(Vec4::ONE)
|
|
|
|
, diffuseColor(Vec4::ONE)
|
|
|
|
, specularColor(Vec4::ZERO)
|
|
|
|
, emissiveColor(Vec4::ZERO)
|
|
|
|
, shininess(0.0f)
|
|
|
|
, depthTest(true)
|
|
|
|
, depthWrite(true)
|
|
|
|
, wrapMode(backend::SamplerAddressMode::CLAMP_TO_EDGE)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
blendFunc.src = backend::BlendFactor::ONE;
|
|
|
|
blendFunc.dst = backend::BlendFactor::ZERO;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
PUMaterialCache::PUMaterialCache() {}
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
PUMaterialCache::~PUMaterialCache()
|
|
|
|
{
|
2022-07-21 19:19:08 +08:00
|
|
|
for (auto&& iter : _materialMap)
|
2021-12-25 10:04:45 +08:00
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
iter->release();
|
|
|
|
}
|
|
|
|
_materialMap.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
PUMaterialCache* PUMaterialCache::Instance()
|
|
|
|
{
|
|
|
|
static PUMaterialCache pmm;
|
|
|
|
return &pmm;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
PUMaterial* PUMaterialCache::getMaterial(std::string_view name)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-21 19:19:08 +08:00
|
|
|
for (auto&& iter : _materialMap)
|
2021-12-25 10:04:45 +08:00
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
if (iter->name == name)
|
|
|
|
return iter;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool PUMaterialCache::loadMaterials(std::string_view file)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
bool isFirstCompile = true;
|
2021-12-25 10:04:45 +08:00
|
|
|
auto list = PUScriptCompiler::Instance()->compile(file, isFirstCompile);
|
|
|
|
if (list == nullptr || list->empty())
|
|
|
|
return false;
|
|
|
|
if (isFirstCompile)
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
PUTranslateManager::Instance()->translateMaterialSystem(this, list);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
void PUMaterialCache::addMaterial(PUMaterial* material)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-21 19:19:08 +08:00
|
|
|
for (auto&& iter : _materialMap)
|
2021-12-25 10:04:45 +08:00
|
|
|
{
|
|
|
|
if (iter->name == material->name)
|
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AXLOG("warning: Material has existed (FilePath: %s, MaterialName: %s)", material->fileName.c_str(),
|
2021-12-25 10:04:45 +08:00
|
|
|
material->name.c_str());
|
|
|
|
return;
|
|
|
|
}
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
material->retain();
|
2022-08-09 09:54:53 +08:00
|
|
|
_materialMap.emplace_back(material);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
#if (AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC)
|
2021-12-25 10:04:45 +08:00
|
|
|
int iterPath(const char* fpath, const struct stat* /*sb*/, int typeflag)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (typeflag == FTW_F)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
if (FileUtils::getInstance()->getFileExtension(fpath) == ".material")
|
|
|
|
PUMaterialCache::Instance()->loadMaterials(fpath);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
bool PUMaterialCache::loadMaterialsFromSearchPaths(std::string_view fileFolder)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
bool state = false;
|
2023-03-11 22:10:18 +08:00
|
|
|
#if defined(_WIN32)
|
2023-09-02 20:36:55 +08:00
|
|
|
std::string_view seg("/");
|
2021-12-31 12:12:40 +08:00
|
|
|
std::string fullPath{fileFolder};
|
|
|
|
fullPath += seg;
|
2023-09-02 20:36:55 +08:00
|
|
|
fullPath += "*.material"sv;
|
2023-03-11 22:10:18 +08:00
|
|
|
WIN32_FIND_DATAA data;
|
2023-09-02 20:36:55 +08:00
|
|
|
HANDLE handle = FindFirstFileExA(fullPath.c_str(), FindExInfoStandard, &data, FindExSearchNameMatch, NULL, 0);
|
2023-03-11 22:10:18 +08:00
|
|
|
if (handle != INVALID_HANDLE_VALUE)
|
2021-12-25 10:04:45 +08:00
|
|
|
{
|
|
|
|
state = true;
|
2023-03-11 22:10:18 +08:00
|
|
|
do
|
|
|
|
{
|
|
|
|
fullPath = fileFolder;
|
|
|
|
fullPath += seg;
|
|
|
|
fullPath += data.cFileName;
|
|
|
|
loadMaterials(fullPath);
|
2023-09-02 20:36:55 +08:00
|
|
|
|
2023-03-11 22:10:18 +08:00
|
|
|
} while (FindNextFileA(handle, &data));
|
|
|
|
FindClose(handle);
|
2021-12-25 10:04:45 +08:00
|
|
|
}
|
2023-09-02 19:56:50 +08:00
|
|
|
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID)
|
2021-12-31 12:12:40 +08:00
|
|
|
std::string::size_type pos = fileFolder.find("assets/");
|
|
|
|
std::string_view relativePath = fileFolder;
|
2021-12-25 10:04:45 +08:00
|
|
|
if (pos != std::string::npos)
|
|
|
|
{
|
2019-11-23 20:27:39 +08:00
|
|
|
// "assets/" is at the beginning of the path and we don't want it
|
|
|
|
relativePath = fileFolder.substr(pos + strlen("assets/"));
|
|
|
|
}
|
2021-12-31 12:12:40 +08:00
|
|
|
AAssetDir* dir = AAssetManager_openDir(FileUtilsAndroid::getAssetManager(), relativePath.data());
|
2021-12-25 10:04:45 +08:00
|
|
|
const char* fileName = nullptr;
|
2021-12-31 12:12:40 +08:00
|
|
|
std::string_view seg("/", 1);
|
|
|
|
std::string fullpath;
|
2019-11-23 20:27:39 +08:00
|
|
|
while ((fileName = AAssetDir_getNextFileName(dir)) != nullptr)
|
|
|
|
{
|
|
|
|
if (FileUtils::getInstance()->getFileExtension(fileName) == ".material")
|
|
|
|
{
|
2021-12-31 12:12:40 +08:00
|
|
|
fullpath.assign(fileFolder).append(seg).append(fileName);
|
2019-11-23 20:27:39 +08:00
|
|
|
loadMaterials(fullpath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AAssetDir_close(dir);
|
|
|
|
|
2022-07-16 10:43:05 +08:00
|
|
|
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC)
|
2021-12-31 12:12:40 +08:00
|
|
|
ftw(fileFolder.data(), iterPath, 500);
|
2023-09-02 19:56:50 +08:00
|
|
|
#elif (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX)
|
2021-12-25 10:04:45 +08:00
|
|
|
DIR* d; // dir handle
|
|
|
|
struct dirent* file; // readdir
|
2019-11-23 20:27:39 +08:00
|
|
|
struct stat statbuf;
|
|
|
|
|
2021-12-31 12:12:40 +08:00
|
|
|
if (!(d = opendir(fileFolder.data())))
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AXLOG("error opendir %s!!!\n", fileFolder.data());
|
2019-11-23 20:27:39 +08:00
|
|
|
return false;
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
while ((file = readdir(d)) != NULL)
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (strncmp(file->d_name, ".", 1) == 0 || (stat(file->d_name, &statbuf) >= 0 && S_ISDIR(statbuf.st_mode)))
|
2019-11-23 20:27:39 +08:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FileUtils::getInstance()->getFileExtension(file->d_name) == ".material")
|
|
|
|
{
|
2021-12-31 12:12:40 +08:00
|
|
|
std::string fullpath{fileFolder};
|
|
|
|
fullpath.append("/"sv).append(file->d_name);
|
2022-07-16 10:43:05 +08:00
|
|
|
AXLOG("%s", fullpath.c_str());
|
2019-11-23 20:27:39 +08:00
|
|
|
loadMaterials(fullpath);
|
|
|
|
state = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
closedir(d);
|
|
|
|
#else
|
2023-09-02 20:36:55 +08:00
|
|
|
// use c++17 filesystem
|
|
|
|
for (const auto& entry : stdfs::recursive_directory_iterator(fileFolder))
|
|
|
|
{
|
|
|
|
# if !defined(_WIN32)
|
|
|
|
if (entry.is_regular_file() && cxx20::ends_with(entry.path().native(), ".material"sv))
|
|
|
|
# else
|
|
|
|
if (entry.is_regular_file() && cxx20::ends_with(entry.path().native(), L".material"sv))
|
|
|
|
# endif
|
|
|
|
{
|
|
|
|
auto pathU8Str = entry.path().generic_u8string();
|
|
|
|
auto& pathStr = *reinterpret_cast<std::string*>(&pathU8Str);
|
|
|
|
loadMaterials(pathStr);
|
|
|
|
}
|
|
|
|
}
|
2019-11-23 20:27:39 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_END
|