Files
dl_old/dl/render/dl_factory.cpp
T

1768 lines
45 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "dl_factory.h"
#ifndef DL_DISABLE_RENDER
#include "dl_factory_imp.h"
#include "io/dl_file.h"
#include "system/dl_time.h"
#include "vk/dl_vk.h"
#include "dl_free_type.h"
#include "io/dl_json.h"
#include "system/dl_audio.h"
#include "render/dl_render_def.h"
#include "io/dl_input.h"
#include "system/dl_engine.h"
#include "system/dl_system.h"
namespace dl
{
Factory* g_factory;
void Factory::LoadModel(std::string_view path_name, std::string_view name)
{
//-------------------------资源名字防止重复-----------------------
std::string path_name_real;
std::string res_name;
if (!String::GetPathAndRes(_strPathModel, path_name, path_name_real, res_name, name))
return;
auto iter = _imp->_mapName2Model.find(res_name);
if (iter != _imp->_mapName2Model.end())
{
log_warn("资源名字已经存在:{},id:{}", res_name, iter->second);
return;
}
//-------------------------判断从文件还是从缓存读取-----------------------
bool b_read_cache;// 是否从缓存读取
bool b_exist = File::IsExist(path_name_real);// 文件是否存在
ModelCache::Node* cache_node = _imp->_modelCache.Get(path_name_real);// 缓存是否存在
if(!b_exist && !cache_node)
{// 不存在
log_err("加载模型失败(文件不存在,并且没有缓存文件):{}", path_name_real);
return;
}
if (!b_exist && cache_node)
{// 不存在,缓冲文件存在
b_read_cache = true;
}
else if (b_exist && cache_node)
{// 都存在
// 检查是否需要更新
time_t t = File::GetLastWriteTime(path_name_real);
if (cache_node->_t == t)
b_read_cache = true;
else
{
uint32_t crc32 = File::GetCrc32(path_name_real);
if (crc32 == cache_node->_crc32)
{
b_read_cache = true;
cache_node->_t = t;
}
else
{
cache_node->_crc32 = crc32;
cache_node->_t = t;
b_read_cache = false;
}
}
}
else
{// 只文件存在
b_read_cache = false;
cache_node = _imp->_modelCache.Add(path_name_real);
if (!cache_node)
{
log_err("添加缓存文件失败:{}", path_name_real);
return;
}
cache_node->_crc32 = File::GetCrc32(path_name_real);
cache_node->_t = File::GetLastWriteTime(path_name_real);
}
FloatTime t0 = g_time->GetCurrent();
std::vector<Model*> mul_model;
if (b_read_cache)
{
// 加载所有子模型
for (std::string& str : cache_node->_allSub)
{
// 加载model_object
ModelObject* model_object = new ModelObject;
model_object->Load(str);
// model_object -> model
Model* model = g_vk->CreateModel(model_object);
delete model_object;
// 记录model
mul_model.push_back(model);
}
if (mul_model.empty())
{
log_err("模型加载失败(从缓存,没有sub):{}", res_name);
return;
}
size_t id = g_vk->GetMulModelSize();
_imp->_mapName2Model[res_name] = id;
g_vk->AddMulModel(mul_model);
}
else
{// 从文件加载
std::vector<ModelObject*> mul_model_object = ModelObject::Create(path_name_real, res_name);
if (mul_model_object.empty())
return;
// 转换所有子模型
for (ModelObject* model_object : mul_model_object)
{
// model_object -> model
Model* model = g_vk->CreateModel(model_object);
// 记录model
mul_model.push_back(model);
}
if (mul_model.empty())
{
log_err("模型加载失败(从文件,没有sub):{}", path_name_real);
return;
}
size_t id = g_vk->GetMulModelSize();
_imp->_mapName2Model[res_name] = id;
g_vk->AddMulModel(mul_model);
// 更新子模型
size_t i = 0;
for (ModelObject* model_object : mul_model_object)
{// 资源名+id
// 文件名
std::string file_name = fmt::format("{}#{}", res_name, i);
// model文件
const std::string PATH_CACHE = GetPathBinary3D();
std::string path_child = PATH_CACHE + file_name + ".model";
if (model_object->IsHaveTexture())
{// 存在贴图则转存
// tex文件路径
std::string path_tex = PATH_CACHE + "texture/" + file_name + "/";
File::CreateFolder(path_tex);
// 复制贴图文件,并转换路径
model_object->ConvertTexturePath(path_tex);
}
model_object->SaveToFile(path_child);
cache_node->_allSub.push_back(path_child);
delete model_object;
++i;
}
}
FloatTime t1 = g_time->GetCurrent();
log_msg("成功加载一个模型文件:{},子模型数量:{},从缓存:{},耗时:{}",
res_name, mul_model.size(), b_read_cache, t1 - t0);
}
std::vector<std::string> Factory::GetAllModel()
{
std::vector<std::string> ret;
for (auto& iter : _imp->_mapName2Model)
ret.push_back(iter.first);
return ret;
}
gcActor Factory::CreateActor(std::string_view name)
{
gcActor act = get_gc<Actor>();
act->_idModel = _imp->_get_model_id(name);
act->_trans = Transform::Create();
act->_color = nullptr;
act->_modelAnimationInstance = _imp->_create_model_bone_animation(name);
act->_rigidBody = nullptr;
return act;
}
Camera* Factory::GetCamera()
{
return g_vk->GetCamera();
}
size_t Factory::LoadSkybox(std::string_view path)
{
return g_vk->LoadSkybox(path);
}
void Factory::SetSkybox(size_t id)
{
g_vk->SetSkybox(id);
}
void Factory::SetDebugView3D(DebugView3D type)
{
g_vk->SetDebugView(type);
}
dl::DebugView3D Factory::GetDebugView3D()
{
return g_vk->GetDebugView();
}
void Factory::UpdateDebugView()
{
//
bool ctrl = g_input->KeyState(KeyCode::LEFT_CONTROL);
bool alt = g_input->KeyState(KeyCode::LEFT_ALT);
if (!ctrl && !alt)
{
if (g_input->KeyDown(KeyCode::KP_0))
SetDebugView3D((DebugView3D)0);
else if (g_input->KeyDown(KeyCode::KP_1))
SetDebugView3D((DebugView3D)1);
else if (g_input->KeyDown(KeyCode::KP_2))
SetDebugView3D((DebugView3D)2);
else if (g_input->KeyDown(KeyCode::KP_3))
SetDebugView3D((DebugView3D)3);
else if (g_input->KeyDown(KeyCode::KP_4))
SetDebugView3D((DebugView3D)4);
else if (g_input->KeyDown(KeyCode::KP_5))
SetDebugView3D((DebugView3D)5);
else if (g_input->KeyDown(KeyCode::KP_6))
SetDebugView3D((DebugView3D)6);
else if (g_input->KeyDown(KeyCode::KP_7))
SetDebugView3D((DebugView3D)7);
else if (g_input->KeyDown(KeyCode::KP_8))
SetDebugView3D((DebugView3D)8);
else if (g_input->KeyDown(KeyCode::KP_9))
SetDebugView3D((DebugView3D)9);
}
else if (ctrl)
{
if (g_input->KeyDown(KeyCode::KP_0))
SetDebugView3D((DebugView3D)10);
else if (g_input->KeyDown(KeyCode::KP_1))
SetDebugView3D((DebugView3D)11);
else if (g_input->KeyDown(KeyCode::KP_2))
SetDebugView3D((DebugView3D)12);
else if (g_input->KeyDown(KeyCode::KP_3))
SetDebugView3D((DebugView3D)13);
else if (g_input->KeyDown(KeyCode::KP_4))
SetDebugView3D((DebugView3D)14);
else if (g_input->KeyDown(KeyCode::KP_5))
SetDebugView3D((DebugView3D)15);
else if (g_input->KeyDown(KeyCode::KP_6))
SetDebugView3D((DebugView3D)16);
else if (g_input->KeyDown(KeyCode::KP_7))
SetDebugView3D((DebugView3D)17);
else if (g_input->KeyDown(KeyCode::KP_8))
SetDebugView3D((DebugView3D)18);
else if (g_input->KeyDown(KeyCode::KP_9))
SetDebugView3D((DebugView3D)19);
}
else if (alt)
{
if (g_input->KeyDown(KeyCode::KP_0))
SetDebugView3D((DebugView3D)20);
else if (g_input->KeyDown(KeyCode::KP_1))
SetDebugView3D((DebugView3D)21);
else if (g_input->KeyDown(KeyCode::KP_2))
SetDebugView3D((DebugView3D)22);
else if (g_input->KeyDown(KeyCode::KP_3))
SetDebugView3D((DebugView3D)23);
else if (g_input->KeyDown(KeyCode::KP_4))
SetDebugView3D((DebugView3D)24);
else if (g_input->KeyDown(KeyCode::KP_5))
SetDebugView3D((DebugView3D)25);
else if (g_input->KeyDown(KeyCode::KP_6))
SetDebugView3D((DebugView3D)26);
else if (g_input->KeyDown(KeyCode::KP_7))
SetDebugView3D((DebugView3D)27);
else if (g_input->KeyDown(KeyCode::KP_8))
SetDebugView3D((DebugView3D)28);
else if (g_input->KeyDown(KeyCode::KP_9))
SetDebugView3D((DebugView3D)29);
}
}
gcSprite Factory::CreateSpriteDefault(const Color& col /*= ColorDef::WHITE*/)
{
auto spr = get_gc<Sprite>();
bool b_solid = col[3] == 0.0f || col[3] == 1.0f;
//等于0时,用户很有可能随后修改透明度
spr->_id = b_solid ? _imp->_idSolid : _imp->_idSolidTrans;
spr->_quad = QUAD_DEFAULT_SPRITE;
spr->_order = Z_DEFAULT;
FactoryImp::SpriteInfo* spr_info = _imp->_get_sprite_info(spr->_id);
assert(spr_info && "可能是忘了关闭发布模式");
for (int i = 0; i != 4; ++i)
{
spr->_col[i] = col;
spr->_uv[i] = spr_info->_uv[i];
}
#ifndef NDEBUG
spr->_name = ":";
#endif
return spr;
}
gcSprite Factory::CreateSprite(const SpriteID& spr_id)
{
FactoryImp::SpriteInfo* spr_info = _imp->_get_sprite_info(spr_id);
if (!spr_info)
{
log_err("获取SpriteInfo失败:{}", to_string(spr_id));
return g_factory->CreateSpriteDefault();
}
auto spr = get_gc<Sprite>();
spr->SetColor(spr_info->_color);
spr->_id = spr_id;
// 如果旋转过
Size size = Align::GetSize(spr_info->_rect);
if (spr_info->_bRightAngle)
std::swap(size[0], size[1]);
spr->_quad = createQuad(size, false)
- spr_info->_anchor;//偏移锚点
spr->_order = Z_DEFAULT;
for (int i = 0; i != 4; ++i)
spr->_uv[i] = spr_info->_uv[i];
#ifndef NDEBUG
spr->_name = GetSpriteName(spr_id);
#endif
return spr;
}
gcSprite Factory::CreateSprite(std::string_view name, size_t index /*= 0*/)
{
return CreateSprite(GetSpriteId(name, index));
}
dl::gcSprite Factory::CreateSprite(size_t rt_id)
{
auto spr = get_gc<Sprite>();
spr->_id._tex = rt_id;
spr->_id._rect = (size_t)-1;
spr->_bRenderTarget = true;
spr->_quad = createQuad(g_system->GetWindowSize(), false);
spr->_order = Z_DEFAULT_RENDER_TARGET;
for (int i = 0; i != 4; ++i)
{
spr->_col[i] = ColorDef::WHITE;
}
spr->_uv[0] = { 0.0f, 0.0f };
spr->_uv[1] = { 1.0f, 0.0f };
spr->_uv[2] = { 1.0f, 1.0f };
spr->_uv[3] = { 0.0f, 1.0f };
#ifndef NDEBUG
spr->_name = fmt::format("RenderTarget: {}", rt_id);
#endif
return spr;
}
bool Factory::RegisterSprite(std::string_view name, size_t index, Image* img, const Position& anchor)
{
if (!img)
{
log_err("传入图像为空:{}", name);
return false;
}
//--------------------记录Rect到Factory的_vecRectInfo----------------
auto iter = _imp->_sprGroup._mapName2SpriteID.find(std::string{ name });
if (iter != _imp->_sprGroup._mapName2SpriteID.end())
{
log_warn("精灵名字已存在:{}", name);
return false;
}
//
size_t id_tex;
size_t id_rect;
// 旋转精灵使w更大
bool right_angle = false;
{
Image img_r;
if (img->GetHeight() > img->GetWidth())
{
img_r = Image::RotateRightAngle1(*img);
img = &img_r;
right_angle = true;
}
if (!_imp->_reg_image(img, SIZE_SPRITE_BORDER, id_tex, id_rect))
{
log_err0("注册图像失败!");
return false;
}
}
// 创建 sprite_id
std::vector<SpriteID>& vec_spr_id = _imp->_sprGroup._mapName2SpriteID[std::string{ name }];
SpriteID& spr_id = Select::CreateIfEmpty(vec_spr_id, index);
spr_id._tex = id_tex;
spr_id._rect = id_rect;
//{纹理id,区域id} -> { SpriteInfo }
FactoryImp::SpriteInfo& info = Select::CreateIfEmpty(
_imp->_sprGroup._allSpriteInfo, id_tex, id_rect);
RectU rect = _imp->_get_rect(id_tex, id_rect);
info._rect = createRectU({}, Align::GetSize(rect));
_imp->_rect_to_uv(rect, info._uv, right_angle);
info._anchor = anchor;
info._color = ColorDef::WHITE;
info._bRightAngle = right_angle;
return true;
}
bool Factory::HasSprite(std::string_view name)
{
auto iter = _imp->_sprGroup._mapName2SpriteID.find(std::string{ name });
return iter != _imp->_sprGroup._mapName2SpriteID.end();
}
std::vector<gcSprite> Factory::CreateSpriteMulti(std::string_view name, size_t num /*= 0*/, size_t index /*= 0*/)
{
auto iter = _imp->_sprGroup._mapName2SpriteID.find(std::string{ name });
if (iter == _imp->_sprGroup._mapName2SpriteID.end())
{
log_warn("SpriteSheet不存在:{}", name);
return {};
}
std::vector<SpriteID>& all_id = iter->second;
if (num == 0)
num = all_id.size();
std::vector<gcSprite> ret;
ret.resize(num);
for (size_t i = 0; i < num; ++i)
{
ret[i] = CreateSprite(all_id[i]);
}
return ret;
}
gcSprite Factory::CloneSprite(gcSprite& spr)
{
auto ret = get_gc<Sprite>(*(spr.operator->()));
// 如果是拥有Coor,则需要深拷贝
if (ret->_bOwnCoor)
ret->_coor = spr->_coor->Clone();
ret->_reset_not_copy();
return ret;
}
std::vector<std::string> Factory::GetFolderAllSpriteName(std::string_view folder_name)
{
std::vector<std::string> ret;
for (auto& iter : _imp->_sprGroup._mapName2SpriteID)
{
std::string_view name = iter.first;
if (Sub::IsBegin(name, folder_name))
ret.push_back(std::string{ name });
}
return ret;
}
size_t Factory::GetSpriteSheetNum(std::string_view name)
{
auto iter = _imp->_sprGroup._mapName2SpriteID.find(std::string{ name });
if (iter == _imp->_sprGroup._mapName2SpriteID.end())
{
log_warn("SpriteSheet不存在:{}", name);
return 0;
}
return iter->second.size();
}
dl::SpriteID Factory::GetSpriteId(std::string_view name, size_t index)
{
auto iter = _imp->_sprGroup._mapName2SpriteID.find(std::string{ name });
if (iter == _imp->_sprGroup._mapName2SpriteID.end())
{
log_warn("SpriteSheet不存在:{}", name);
return _imp->_idSolid;
}
std::vector<SpriteID>& all_id = iter->second;
if (index >= all_id.size())
{
log_warn("下标越界:{},{}/{},", name, index, all_id.size());
return _imp->_idSolid;
}
return all_id[index];
}
Size Factory::GetSpriteTexSize(const SpriteID &spr_id)
{
FactoryImp::SpriteInfo* spr_info = _imp->_get_sprite_info(spr_id);
if (!spr_info)
{
log_err0("返回精灵信息失败!");
return toSizeNeg2Zero(SIZE_DEFAULT_SPRITE);
}
return Align::GetSize(spr_info->_rect);
}
std::string Factory::GetSpriteName(const SpriteID& spr_id)
{
for (auto& iter : _imp->_sprGroup._mapName2SpriteID)
{
for (SpriteID& iter1 : iter.second)
{
if (iter1._tex == spr_id._tex
&& iter1._rect == spr_id._rect)
{
return iter.first;
}
}
}
return "error";
}
Position Factory::GetSpriteAnchor(const SpriteID& spr_id)
{
FactoryImp::SpriteInfo* spr_info = _imp->_get_sprite_info(spr_id);
if (!spr_info)
{
log_err0("返回精灵信息失败!");
return {};
}
return spr_info->_anchor;
}
dl::Color Factory::GetSpriteColor(const SpriteID& spr_id)
{
FactoryImp::SpriteInfo* spr_info = _imp->_get_sprite_info(spr_id);
if (!spr_info)
{
log_err0("返回精灵信息失败!");
return {};
}
return spr_info->_color;
}
dl::gcAnimation Factory::CreateAnimation(std::string_view name, std::string_view state, unsigned dir)
{
auto iter = _mapAnimationInfo.find(name);
if (iter == _mapAnimationInfo.end())
{
log_err("创建精灵动画失败:{}:{}", name, state);
return {};
}
AnimationInfo& info = iter->second;
auto iter1 = info._allAni.find(state);
if (iter1 == info._allAni.end())
{
log_err("创建精灵动画失败:{},没有:{}", name, state);
return {};
}
AnimationInfo::Node& node = iter1->second;
gcAnimation ret = get_gc<Animation>(name, dir);
if (info._type == "sheet")
{
std::string name_spr = name + "." + fmt::vformat(info._format,
fmt::make_format_args(state));
unsigned count = node._count ? node._count : (unsigned)g_factory->GetSpriteSheetNum(name_spr);
unsigned beg = node._beg + (count + node._skip) * dir;
for (unsigned i = beg; i < beg + count; ++i)
{
gcSprite spr = g_factory->CreateSprite(name_spr, i);
spr->DtQuadOffset(info._offset);
ret->PushBack(spr);
}
ret->SetFrameTime(node._ftime);
log_msg("创建动画:{}({}),{}", name, dir, ret->GetFrameCount());
}
else if (info._type == "multi")
{
unsigned count = node._count;
unsigned beg = node._beg + (count + node._skip) * dir;
for (unsigned i = beg; i < beg + count; ++i)
{
std::string name_spr = name + "." + fmt::vformat(info._format,
fmt::make_format_args(state, i));
gcSprite spr = g_factory->CreateSprite(name_spr, 0);
spr->DtQuadOffset(info._offset);
ret->PushBack(spr);
}
ret->SetFrameTime(node._ftime);
log_msg("创建动画:{}({}),{}", name, dir, ret->GetFrameCount());
}
else
assert(0);
return ret;
}
dl::gcAnimation Factory::CloneAnimation(gcAnimation ani)
{
auto ret = get_gc<Animation>(*(ani.operator->()));
if (ani->_coor)
ret->_coor = ani->_coor->Clone();
ret->_vecSpr.clear();
for (auto& iter : ani->_vecSpr)
{
gcSprite spr = g_factory->CloneSprite(iter);
spr->SetCoor(ret->_coor);
ret->_vecSpr.push_back(spr);
}
return ret;
}
dl::gcSprite Factory::RenderSprite(std::string_view name, size_t index)
{
gcSprite ret = CreateSprite(name, index);
_vecSprite.push_back(ret);
return ret;
}
dl::gcSprite Factory::RenderSpriteDefault()
{
gcSprite ret = CreateSpriteDefault();
_vecSprite.push_back(ret);
return ret;
}
dl::gcText Factory::RenderText()
{
gcText ret = CreateTextDefault();
_vecText.push_back(ret);
return ret;
}
dl::gcAnimation Factory::RenderAnimation(std::string_view name, std::string_view state, unsigned dir)
{
// todo animation不是一帧
gcAnimation ret = CreateAnimation(name, state, dir);
ret->Render();
_vecAnimation.push_back(ret);
return ret;
}
size_t Factory::LoadFont(std::string_view path_name)
{
return g_freetype->LoadFace(path_name);
}
size_t Factory::GetFontSize()
{
return g_freetype->GetFontSize();
}
gcText Factory::CreateText(size_t font_id /*= 0*/,
unsigned font_size, const Color& col,
unsigned font_outline, const Color& col_outline,
unsigned font_shadow, const Color& col_shadow)
{
auto txt = get_gc<Text>();
if (font_id >= g_freetype->GetFontSize())
{
log_err0("字体id越界,将使用0号!");
assert(font_id);
font_id = 0;
}
txt->_fontId = font_id;
txt->_fontSize[TextParam::NORMAL] = font_size;
txt->_fontSize[TextParam::OUTLINE] = font_outline;
txt->_fontSize[TextParam::SHADOW] = font_shadow;
txt->_fontSizeReal = txt->_fontSize;
txt->_col[TextParam::NORMAL] = col;
txt->_col[TextParam::OUTLINE] = col_outline;
txt->_col[TextParam::SHADOW] = col_shadow;
txt->_coor = Coor::Create();
return txt;
}
CharImage* Factory::GetChar(const CharInfo& info)
{
// 缓存工作由CreateSpriteChar完成
return g_freetype->GetChar(info);
}
float Factory::CreateSpriteChar(const CharInfo& info, gcSprite& spr, gcSprite& spr_outline)
{
auto fn_failed = [&]()
{
spr = CreateSpriteDefault();
spr->SetQuad(createQuad(info._size, false));
spr_outline = CreateSpriteDefault();
spr_outline->SetQuad(createQuad(info._size, false));
};
if (info._font >= g_freetype->GetFontSize())
{
log_err("字体id不存在:{}", info._font);
fn_failed();
return 0;
}
if (info._size == 0)
{
log_err0("字体大小不能为0!");
fn_failed();
return 0;
}
// 排除控制字符
if ((info._ch >= 0 && info._ch <= 31)
|| info._ch == 127)
{
fn_failed();
return 0;
}
FactoryImp::CharSprite& char_spr = _imp->_hashCharImage[info];
FactoryImp::CharSprite::Data& d0 = char_spr._data[0];
FactoryImp::CharSprite::Data& d1 = char_spr._data[1];
RectU rect0;
RectU rect1;
// 注册图像(普通和描边一起注册)
if (d0._idTex == 0)
{
CharImage* char_img = g_freetype->GetChar(info);
if (char_img == nullptr)
{
log_err0("GetChar失败!");
fn_failed();
return 0;
}
char_spr._advance = char_img->_advance;
char_spr._anchor = { -char_img->_bearingX, char_img->_bearingY };
//0
if (!_imp->_reg_image(char_img->_image, 1, d0._idTex, d0._idRect))
{
delete char_img;
log_err0("注册图像失败!");
fn_failed();
return 0;
}
rect0 = _imp->_get_rect(d0._idTex, d0._idRect);
_imp->_rect_to_uv(rect0, d0._uv);
//1
if (info._outline > 0)
{
if (!_imp->_reg_image(char_img->_imageOutline, 1, d1._idTex, d1._idRect))
{
delete char_img;
log_err0("注册图像(描边)失败!");
fn_failed();
return 0;
}
rect1 = _imp->_get_rect(d1._idTex, d1._idRect);
_imp->_rect_to_uv(rect1, d1._uv);
}
delete char_img;
}
else
{
rect0 = _imp->_get_rect(d0._idTex, d0._idRect);
if (info._outline > 0)
{
rect1 = _imp->_get_rect(d1._idTex, d1._idRect);
}
}
//0
spr = MemoryPool::GetGC<Sprite>();
spr->SetColor(ColorDef::WHITE);
spr->_id = { d0._idTex, d0._idRect};
spr->_quad = createQuad(Align::GetSize(rect0), false)
- char_spr._anchor;//偏移锚点
spr->_order = Z_DEFAULT;
for (int i = 0; i != 4; ++i)
spr->_uv[i] = d0._uv[i];
//1
if (info._outline > 0)
{
spr_outline = MemoryPool::GetGC<Sprite>();
spr_outline->SetColor(ColorDef::WHITE);
spr_outline->_id = { d1._idTex, d1._idRect };
spr_outline->_quad = createQuad(Align::GetSize(rect1), false)
- char_spr._anchor;//偏移锚点
spr_outline->_order = Z_DEFAULT;
for (int i = 0; i != 4; ++i)
spr_outline->_uv[i] = d1._uv[i];
}
return char_spr._advance;
}
dl::Coor* Factory::GetRootCoor(size_t i)
{
return g_vk->GetRootCoor(i);
}
void Factory::AddColor(std::string_view name, const Color& col)
{
_hashTagColor[std::string{ name }] = col;
}
Color Factory::GetColor(std::string_view name)
{
if (name.size() == 10
&& name[0] == '0'
&& name[1] == 'x')
{//尝试十六进制
return createColor(name);
}
auto iter = _hashTagColor.find(std::string{ name });
if (iter == _hashTagColor.end())
{
log_err("Tag颜色查找失败:{}", name);
return ColorDef::WHITE;
}
else
return iter->second;
}
std::optional<Color> Factory::GetColorCheck(std::string_view name)
{
auto iter = _hashTagColor.find(std::string{ name });
if (iter == _hashTagColor.end())
{
return std::nullopt;
}
else
return iter->second;
}
void Factory::ExportTexture2D()
{
g_vk->ExportTextureCanvas(_strPathTemp);
}
void Factory::_render_sprite(Sprite* spr)
{
const SpriteID& id = g_factory->GetImp()->_idTrans;
VK::Canvas* canvas = nullptr;
if (!spr->_bRenderTarget)
canvas = g_vk->GetCanvasByTexture(spr->_id._tex);
else
canvas = g_vk->GetCanvasByRenderTarget(spr->_id._tex);
assert(canvas);
if (spr->_id._rect == -1
|| !spr->IsColorOne()
|| (spr->_id._tex >= id._tex))
{ //可能是半透明
canvas->_allSpriteTrans.push_back(spr);
}
else
canvas->_allSprite.push_back(spr);
}
void Factory::_render_pickup()
{
if (g_input->KeyDown(KeyCode::DELETE))
log_pause0("拾取检测");
if (_bOrderPickupShow)
{
if (!_vecPickupSprite.empty())
{
_vecPickupSprite.back()->RenderDebug();
}
if (!_vecPickupText.empty())
{
_vecPickupText.back()->RenderDebug();
}
}
}
struct ColorTag
{
char _name[32];
uint32_t _color;
};
void Factory::LoadColorCsv(std::string_view name)
{
assert(0);
/*std::vector<ColorTag> all;
CsvFile::Deserialize(name, all);
for (auto& iter : all)
{
AddColor(iter._name, ABGR::CreateColor(iter._color));
}*/
}
void Factory::SetOrderPickup(float order)
{
if (g_input->KeyState(KeyCode::RIGHT_CONTROL)
&& g_input->KeyDown(KeyCode::DELETE))
log_pause("当前拾取设置!");
_orderPickup = order;
}
void Factory::DeleteBinary(bool b_all, bool b_2d, bool b_3d)
{
if (!_bSetPath)
{
log_err0("尚未指定输出目录!");
return;
}
if (b_all)
File::DeleteContent(GetPathBinary());
else
{
if (b_2d)
File::DeleteContent(GetPathBinary2D());
if (b_3d)
File::DeleteContent(GetPathBinary3D());
}
}
constexpr std::string_view NAME_CACHE_MODEL = "model.cache";
void Factory::_auto_render()
{
for (auto& iter : _vecSprite)
iter->Render();
for (auto& iter : _vecText)
iter->Render();
}
void Factory::_clear_render()
{
_vecSprite.clear();
_vecText.clear();
_vecAnimation.clear();
}
void Factory::_render_rt()
{
if(Engine::GetParamRef()._show3D)
_sprRenderTarget0->Render();
}
void Factory::_resize()
{
_sprRenderTarget0->SetQuad(createQuad(g_system->GetWindowSize(), false));
}
void Factory::_init_path()
{
if (!_bSetPath)
{
SetPath(
File::PathCurrent(),
File::PathCurrent(),
File::PathStorage(),
File::PathTemp());
}
// File::CreateFolder(File::PathCurrent());
// File::CreateFolder(File::PathStorage());
// File::CreateFolder(File::PathTemp());
// File::CreateFolder(File::PathPrivate());
File::CreateFolder(_mapPathImage[""]);
File::CreateFolder(_strPathModel);
File::CreateFolder(_strPathVoice);
File::CreateFolder(_strPathBinary);
File::CreateFolder(_strPathTemp);
File::CreateFolder(GetPathBinary2D());
File::CreateFolder(GetPathBinary3D());
// 因为每个模型单独存放,不会合并,所以算法不一样
// 针对每一个模型文件,缓存 效验值、中间文件路径
// 如果效验值不同,则生成中间文件,并更新效验值
_imp->_modelCache.Load(GetPathBinary3D() + NAME_CACHE_MODEL);
// 合并大图纹理,生成Canvas
_load_sprite();
}
void Factory::_init_defualt_res()
{
// 先使用一下,保证gcSprite后于gcText析构
//gcSprite spr = CreateSpriteDefault();
//spr->SetColor(ColorDef::RED);
_sprRenderTarget0 = CreateSprite(0);
// 默认颜色
AddColor("red", ColorDef::RED);
AddColor("green", ColorDef::GREEN);
AddColor("blue", ColorDef::BLUE);
AddColor("white", ColorDef::WHITE);
AddColor("black", ColorDef::BLACK);
AddColor("yellow", ColorDef::YELLOW);
AddColor("purple", ColorDef::PURPLE);
AddColor("cyan", ColorDef::CYAN);
// 默认字体
LoadFont("dl/default.ttf");
//-------------默认模型-------------------
if (true)
{
//加载model_object
ModelObject* model_object = new ModelObject;
model_object->Load("dl/default.model");
//model_object -> model
Model* model = g_vk->CreateModel(model_object);
delete model_object;
assert(model);
size_t id = g_vk->GetMulModelSize();
_imp->_mapName2Model[":box"] = id;
std::vector<Model*> vec_model{ model };
g_vk->AddMulModel(vec_model);
}
}
void FactoryImp::_rect_to_uv(const RectU& rect, UV* uv, bool right_angle)
{
using namespace Align;
Position4 ltrb;
for (int i = 0; i != 4; ++i)
ltrb[i] = rect[i] / (Float)SIZE_TEXTURE_2D;
if (!right_angle)
{
uv[(size_t)Corner::LT] = GetLT(ltrb);
uv[(size_t)Corner::RT] = GetRT(ltrb);
uv[(size_t)Corner::RB] = GetRB(ltrb);
uv[(size_t)Corner::LB] = GetLB(ltrb);
}
else
{
uv[(size_t)Corner::LT] = GetRT(ltrb);
uv[(size_t)Corner::RT] = GetRB(ltrb);
uv[(size_t)Corner::RB] = GetLB(ltrb);
uv[(size_t)Corner::LB] = GetLT(ltrb);
}
/*for (int i = 0; i != 4; ++i)
uv[i][1] = 1.0f - uv[i][1];*/
}
void to_json(json& j, const FactoryImp::SpriteInfo& info)
{
j = json{
{"rect", info._rect},
{"uv", info._uv},
{"color", info._color},
{"anchor", info._anchor},
{"right_angle", info._bRightAngle}
};
}
void from_json(const json& j, FactoryImp::SpriteInfo& info)
{
j.at("rect").get_to(info._rect);
j.at("uv").get_to(info._uv);
j.at("color").get_to(info._color);
j.at("anchor").get_to(info._anchor);
j.at("right_angle").get_to(info._bRightAngle);
}
void to_json(json& j, const SpriteID& id)
{
j = json{
{"tex", id._tex},
{"rect", id._rect}
};
}
void from_json(const json& j, SpriteID& id)
{
j.at("tex").get_to(id._tex);
j.at("rect").get_to(id._rect);
}
void to_json(json& j, const FactoryImp::SpriteGroup& group)
{
j = json{
{"id_trans", group._idTrans},
{"sprite_info", group._allSpriteInfo},
{"sprite_id", group._mapName2SpriteID},
};
}
void from_json(const json& j, FactoryImp::SpriteGroup& group)
{
j.at("id_trans").get_to(group._idTrans);
j.at("sprite_info").get_to(group._allSpriteInfo);
j.at("sprite_id").get_to(group._mapName2SpriteID);
}
ModelAnimationInstance* FactoryImp::_create_model_bone_animation(std::string_view name)
{
auto iter = _mapName2Model.find(std::string{ name });
if (iter == _mapName2Model.end())
{
log_err("未知模型名称: {}", name);
return nullptr;
}
// 现在只有一个model
std::vector<Model*>& mul_model = g_vk->GetMulModel(iter->second);
// assert(mul_model.size() == 1);
Model* model = mul_model[0];
// 存在骨骼动画,则生成实例
if (model->_allAnimation.empty())
{
if(!model->_allSkin.empty())
log_warn("模型没有任何动画,但存在骨骼绑定:{}", name);
return nullptr;
}
ModelAnimationInstance* ret = new ModelAnimationInstance;
ret->_model = model;
ret->_treeNode = model->_treeNode;
ret->_treeNodeParent = model->_treeNodeParent;
ret->UpdateNode();
//for (size_t i = 0; i < ret->_treeNode.size(); ++i)
//{
// ret->_finalTrans[i] = Mat::CreateIdentity();
//}
ret->_id = g_vk->GetUboBoneFree();
if (ret->_id == -1)
{
return nullptr;
}
g_vk->SetUboBoneUse(ret->_id);
return ret;
}
constexpr PointU SPRITE_EXTEND_XY = { SIZE_SPRITE_BORDER, SIZE_SPRITE_BORDER };
constexpr Size SPRITE_EXTEND_SIZE = { SIZE_SPRITE_BORDER * 2, SIZE_SPRITE_BORDER * 2 };
bool FactoryImp::_reg_image(Image* image_src, unsigned border, size_t& id_tex, size_t& id_rect)
{
RectU rect;
// 扩展图像
Size size = image_src->GetSize() + toLonger(border * 2);
Image* image = Img::Create(size, ColorDef::NONE);
Img::AddRect(image, image_src, createRectU(image_src->GetSize()), toLonger(border));
Img::BuildBorder(image, border);
bool b_add = false;
for (size_t i = 0; i < _allTexPack.size(); ++i)
{
if (_allTexPack[i].Add(size, rect))
{
b_add = true;
id_tex = _numTexStatic + i;
id_rect = _allTexRect[i].size();
_allTexRect[i].push_back(Align::Shrink(std::as_const(rect), border));
break;
}
}
if (!b_add)
{//分配一个新的
TexPack tex_pack;
tex_pack.Reset({ SIZE_TEXTURE_2D, SIZE_TEXTURE_2D });
if (!tex_pack.Add(size, rect))
{
log_err0("注册图像失败!可能是图像太大。需要小于SIZE_TEXTURE_2D。");
return false;
}
id_tex = _numTexStatic + _allTexPack.size();
id_rect = 0;
_allTexPack.push_back(tex_pack);
_allTexRect.push_back({ Align::Shrink(std::as_const(rect), border) });
std::array<Image*, NUM_MIPMAP_2D> vec_image;
unsigned size_big = SIZE_TEXTURE_2D;
for (size_t i = 0; i < vec_image.size(); ++i)
{
vec_image[i] = Img::Create(toLonger(size_big), ColorDef::NONE);
size_big >>= 1;
assert(size_big);
}
g_vk->CreateCanvasImage(id_tex, vec_image);
for (size_t i = 0; i < vec_image.size(); ++i)
{
delete vec_image[i];
}
}
Texture tex = g_vk->GetCanvasByTexture(id_tex)->_texture;
g_vk->UpdateTexture2D(tex, Align::GetLT(rect),
image, createRectU(image->GetSize()));
delete image;
return true;
}
void Factory::_save_cache()
{
if(!_imp->_modelCache.Empty())
_imp->_modelCache.Save(GetPathBinary3D() + NAME_CACHE_MODEL);
}
void Factory::_load_sprite()
{
assert(_bSetPath);
// cache目录创建
const std::string PATH_CACHE = GetPathBinary2D();
File::CreateFolder(PATH_CACHE);
#if DL_PLATFORM == DL_PLATFORM_ANDROID
//_bUseBinary = true; // 提高加载速度
#endif
// 如果文件没有修改(或发布模式),则尝试从out目录加载纹理
if (!_bUseBinary)
{
for (auto& iter : _mapPathImage)
{
std::string name = iter.first;
std::string path = iter.second;
std::string path_out = PATH_CACHE + name;
if (!name.empty())
path_out += '/';
File::CreateFolder(path_out);
File::SearchRule rule;
rule._vecFmt.push_back("jpg");
rule._vecFmt.push_back("jpeg");
rule._vecFmt.push_back("png");
rule._vecFmt.push_back("tag");
rule._vecFmt.push_back("bmp");
rule._vecFmt.push_back("gif");
rule._vecFmt.push_back("hdr");
rule._vecFmt.push_back("pic");
rule._vecFmt.push_back("json");
rule._vecFmt.push_back("txt");
rule._vecFilter.push_back("__animation.json");
if (File::CheckPathFileModified(path, rule, path_out + "files.json", true))
{
log_msg("开始读取2d资源从:{},并生成到:{} -> {}", path, path_out, name);
_load_sprite_sub(path, name, path_out);
}
else
{
log_msg("跳过读取2d资源从:{},{} -> {}", path, path_out, name);
}
}
}
_load_sprite_binary();
_load_animation();
}
void Factory::_load_sprite_binary()
{
const std::string PATH_CACHE = GetPathBinary2D();
_imp->_numTexStatic = 0;
// 纹理id映射
std::unordered_map<std::string, std::unordered_map<size_t, size_t>> map_tex_id;
auto fn_load = [&](bool trans){
for (auto& iter : _mapPathImage)
{
std::string name = iter.first;
std::string path = iter.second;
std::string path_out = PATH_CACHE + name;
if (!name.empty())
path_out += '/';
Json::DisableLog l;
json j = Json::ParseFile(path_out + "sprite.json");
if (j.is_null())
{
log_err("从缓存目录读取2d资源失败:{}", path_out);
continue;
}
FactoryImp::SpriteGroup spr_group;
if (!Json::Get(j, spr_group))
{
log_err("从缓存目录解析2d资源失败:{}", path_out);
continue;
}
size_t i, tex_size;
if (!trans)
{
i = 0;
tex_size = spr_group._idTrans._tex;
}
else
{
i = spr_group._idTrans._tex;
tex_size = spr_group._allSpriteInfo.size();
}
for (; i < tex_size; ++i)
{
bool fail = false;
std::array<Image*, NUM_MIPMAP_2D> vec_image;
for (size_t j = 0; j < vec_image.size(); ++j)
{
std::string tex_path = fmt::format("{}{}_{}.png", path_out, i, j);
vec_image[j] = Img::Create(tex_path);
if (vec_image[j] == nullptr)
{
log_err("纹理加载失败:{}", tex_path);
fail = true;
break;
}
}
if (!fail)
{
map_tex_id[name][i] = _imp->_numTexStatic;
log_msg("创建显存2d纹理:{},{}", _imp->_numTexStatic, path_out);
//创建纹理资源(创建Canvas,并创建纹理)
g_vk->CreateCanvasImage(_imp->_numTexStatic++, vec_image);
}
for (size_t j = 0; j < vec_image.size(); ++j)
{
delete vec_image[j];
}
}
if (trans)
{// 第二步再统一生成
assert(map_tex_id.contains(name));
std::unordered_map<size_t, size_t> map_id = map_tex_id[name];
// 生成全局名字,全局精灵id
for (auto& iter : spr_group._mapName2SpriteID)
{
std::string spr_name = iter.first;
std::vector<SpriteID>& vec_spr_id = iter.second;
if (!name.empty())
spr_name = name + '.' + spr_name;
for (auto& iter1 : vec_spr_id)
{
SpriteID id;
assert(map_id.contains(iter1._tex));
id._tex = map_id[iter1._tex];
id._rect = iter1._rect;
_imp->_sprGroup._mapName2SpriteID[spr_name].push_back(id);
// 特殊精灵处理
if (name.empty())
{
if (spr_name == ":white")
_imp->_idSolid = id;
else if (spr_name == ":white_trans")
_imp->_idSolidTrans = id;
}
}
}
// 生成全局精灵信息
for (size_t j = 0; j < spr_group._allSpriteInfo.size(); ++j)
{
std::vector<FactoryImp::SpriteInfo>& vec_info = spr_group._allSpriteInfo[j];
assert(map_id.contains(j));
size_t g_tex_id = map_id[j];
if (g_tex_id >= _imp->_sprGroup._allSpriteInfo.size())
_imp->_sprGroup._allSpriteInfo.resize(g_tex_id + 1);
std::vector<FactoryImp::SpriteInfo>& vec_info_g = _imp->_sprGroup._allSpriteInfo[g_tex_id];
vec_info_g = vec_info;
}
}
}
};
fn_load(false);
_imp->_idTrans._tex = _imp->_numTexStatic;
fn_load(true);
log_msg("从缓存目录读取所有2d资源完成:\n"
"资源目录:{}\n"
"图像路径数:{}\n"
"纹理数:{}", PATH_CACHE, _mapPathImage.size(), _imp->_numTexStatic);
}
void Factory::_load_sprite_sub(std::string_view path, std::string_view name, std::string_view path_out)
{
// 遍历所有图像
std::vector<std::string> mul_file;
File::GetPathFileAll(path, mul_file, Img::REGEX_FORMAT);
std::list<FactoryImp::SheetNode> list_sheet_node_normal;
std::list<FactoryImp::SheetNode> list_sheet_node_trans;
for (std::string& path_name : mul_file)
{
log_info("开始加载图片:{}", path_name);
// 0.image
Image* image = Img::Create(path_name);
if (!image)
continue;
// 1.meta
struct ParamSheet
{
struct Node
{
std::string _anchor;
std::string _color;
};
Size _split;
std::string _anchor;// 公共锚点
std::unordered_map<std::size_t, Node> _allSprite;// 精灵单独配置
ParamSheet() :
_split{ 1, 1 },
_anchor{}
{
}
};
ParamSheet _paramSheet;
bool read_meta = false;
if(!read_meta)
{
// json meta
std::string meta_name = path_name;
String::ReplaceExtension(meta_name, "json");
std::ifstream ifs = File::Get(meta_name);
if (ifs.is_open())
{
read_meta = true;
json j = json::parse(ifs);
Json::DisableLog l;
Json::Get(j, "split", _paramSheet._split);// 分割
Json::Get(j, "anchor", _paramSheet._anchor);// 锚点
//子元素信息
for (unsigned y = 0; y < _paramSheet._split[1]; ++y)
for (unsigned x = 0; x < _paramSheet._split[0]; ++x)
{
size_t index = (size_t)(y * _paramSheet._split[0] + x);
ParamSheet::Node node;
json j_spr;
Json::Get(j, "sprite_" + to_string(index), j_spr);//独立信息
if (j_spr.empty())
continue;
Json::Get(j_spr, "anchor", _paramSheet._allSprite[index]._anchor);// 锚点
Json::Get(j_spr, "color", _paramSheet._allSprite[index]._color);// 颜色
}
}
}
if (!read_meta)
{
// Placements meta
std::string meta_name = String::EraseFilename(std::string_view{ path_name });
meta_name = fmt::format("{}Placements/{}.txt", meta_name, String::GetFileStem(path_name));
std::string str = File::GetString(meta_name);
if (!str.empty())
{
read_meta = true;
Position pos = String::toPosition2(str, '\n');
_paramSheet._anchor = dl::to_string(-pos);
}
}
Size wh = image->GetSize() / _paramSheet._split;//单图大小
Position anchor_pub = Align::Anchor2Position(toPosition(wh), _paramSheet._anchor);//公用锚点
// 2.record
unsigned index = 0;
for (unsigned y = 0; y < _paramSheet._split[1]; ++y)
{
for (unsigned x = 0; x < _paramSheet._split[0]; ++x)
{
FactoryImp::SheetNode img_rect;
img_rect._pathName = path_name;
img_rect._rect = createRectU(PointU{ x * wh[0], y * wh[1] }, wh);
img_rect._index = index;
img_rect._anchor = anchor_pub;
img_rect._color = ColorDef::WHITE;
// 如果自己有专门配置的锚点,则优先使用
auto iter = _paramSheet._allSprite.find(index);
if (iter != _paramSheet._allSprite.end())
{
ParamSheet::Node& node = iter->second;
if (!node._anchor.empty())
img_rect._anchor = Align::Anchor2Position(toPosition(wh), node._anchor);
if (!node._color.empty())
img_rect._color = createColor(node._color);
}
PointU lt = Align::GetLT(img_rect._rect);
// 去透明空白部分
Img::CalcLeastRect(image, img_rect._rect);
// 更新锚点
img_rect._anchor -= toPosition(Align::GetLT(img_rect._rect) - lt);
// 是否含有半透明颜色
bool is_have_translucent = Img::IsHaveTranslucent(image, img_rect._rect);
if (is_have_translucent)
list_sheet_node_trans.push_back(img_rect);
else
list_sheet_node_normal.push_back(img_rect);
// 即使空白,还是要自增下标
++index;
}
}
delete image;
}
log_msg("开始加载图片路径资源:{}\n"
"非半透精灵:{}\n"
"半透精灵:{}\n"
"即将开始合并图集……", name, list_sheet_node_normal.size(), list_sheet_node_trans.size());
// 特殊精灵 添加到默认图集
if (name.empty())
{
list_sheet_node_normal.push_back({ ":white", 0,
createRectU(SIZE_SPRITE_DEFAULT), {}, ColorDef::WHITE });
list_sheet_node_trans.push_back({ ":white_trans", 0,
createRectU(SIZE_SPRITE_DEFAULT), {}, ColorDef::WHITE });
}
// 3.合并图集
TexturePack::Static pack;
pack.SetSize(SIZE_TEXTURE_2D_SIZE);
size_t pack_id = 0;//当前操作图集id
// tex id -> nrit
std::vector<std::list<FactoryImp::SheetNodeTarget>> all_snt;
// 获得大小(扩展像素)
auto fn_get_size = [](const FactoryImp::SheetNode& nri) {
return Align::GetSize(nri._rect) + SPRITE_EXTEND_SIZE;
};
// 成功加入操作
auto fn_call_back = [&](const FactoryImp::SheetNode& nri, const PointU& lt) {
// rect未变,lt为扩展后位置
all_snt[pack_id].push_back({ nri, lt });
};
// 直到全部添加
while (!list_sheet_node_normal.empty())
{
all_snt.push_back({});
pack.Calc(list_sheet_node_normal, fn_get_size, fn_call_back);
++pack_id;
}
// 记录id
size_t tex_id_trans = pack_id;
size_t rect_id_trans = 0;
//直到全部添加
while (!list_sheet_node_trans.empty())
{
all_snt.push_back({});
pack.Calc(list_sheet_node_trans, fn_get_size, fn_call_back);
++pack_id;
}
// 4.创建纹理、保存信息
FactoryImp::SpriteGroup group;
size_t id_tex = 0;
for (auto& iter : all_snt)
{
// 整个大图 包含mipmap
std::array<Image*, NUM_MIPMAP_2D> vec_image_big;
unsigned size_big = SIZE_TEXTURE_2D;
for (size_t i = 0; i < vec_image_big.size(); ++i)
{
vec_image_big[i] = Img::Create(toLonger(size_big), ColorDef::NONE);
size_big >>= 1;
assert(size_big);
}
size_t id_rect = 0;
for (FactoryImp::SheetNodeTarget& snt : iter)
{
Image* image = nullptr;
bool b_reg_special = false;//是否以特殊精灵创建
if (snt._sheetNode._pathName == ":white")
{//纯色精灵
image = Img::Create(SIZE_SPRITE_DEFAULT + SPRITE_EXTEND_SIZE,
ColorDef::WHITE);
b_reg_special = true;
_imp->_idSolid = { id_tex, id_rect };
}
else if (snt._sheetNode._pathName == ":white_trans")
{
image = Img::Create(SIZE_SPRITE_DEFAULT + SPRITE_EXTEND_SIZE,
ColorDef::WHITE);
b_reg_special = true;
_imp->_idSolidTrans = { id_tex, id_rect };
}
else
{
Image* image_src = Img::Create(snt._sheetNode._pathName);
Size size = Align::GetSize(snt._sheetNode._rect) + SPRITE_EXTEND_SIZE;
image = Img::Create(size, ColorDef::NONE);
Img::AddRect(image, image_src, snt._sheetNode._rect, SPRITE_EXTEND_XY);
Img::BuildBorder(image, SIZE_SPRITE_BORDER);
delete image_src;
}
assert(image);// image现在为处理后的小图
// 加入到大图
constexpr unsigned EDGE = 1;
for (size_t i = 0; i < vec_image_big.size(); ++i)
{
if (i == 0)
Img::AddRect(vec_image_big[i], image, createRectU(image->GetSize()), snt._lt);
else
{
Float scale = 1.0f / Math::Pow(2u, (unsigned)i);
Size size = image->GetSize() / Math::Pow(2u, (unsigned)i);
Every::ClampFloor(size, 1u);
RectU rect = toSize(toPosition(createRectU(image->GetSize())) * scale);
PointU lt = toSize(toPosition(snt._lt) * scale);
Image* img_scale = Img::Resize(image, size);
assert(img_scale);
Img::AddRect(vec_image_big[i], img_scale, rect, lt);
delete img_scale;
}
}
//--------------------记录Rect到Factory的_vecRectInfo----------------
//名字转换
std::string name;
if (!b_reg_special)
{// 不是特殊精灵才生成资源名
name = String::GetResName(path, snt._sheetNode._pathName);
}
else
name = snt._sheetNode._pathName;
// 构建 name,index -> SpriteID
std::vector<SpriteID>& vec_spr_id = group._mapName2SpriteID[std::string{ name }];
if (snt._sheetNode._index >= vec_spr_id.size())
vec_spr_id.resize(snt._sheetNode._index + 1);
SpriteID& spr_id = vec_spr_id[snt._sheetNode._index];
spr_id._tex = id_tex;
spr_id._rect = id_rect;
// 构建 SpriteID -> SpriteInfo
if (id_tex >= group._allSpriteInfo.size())
group._allSpriteInfo.resize(id_tex + 1);
std::vector<FactoryImp::SpriteInfo>& vec_info = group._allSpriteInfo[id_tex];
if (id_rect >= vec_info.size())
vec_info.resize(id_rect + 1);
FactoryImp::SpriteInfo& info = vec_info[id_rect];
snt._lt += SPRITE_EXTEND_XY;// 还原到图像扩展之前位置
info._rect = createRectU(snt._lt, Align::GetSize(snt._sheetNode._rect));
_imp->_rect_to_uv(info._rect, info._uv);
info._anchor = snt._sheetNode._anchor;
info._color = snt._sheetNode._color;
delete image;
++id_rect;
}
for (size_t i = 0; i < vec_image_big.size(); ++i)
{
Img::Save(vec_image_big[i], fmt::format("{}{}_{}.png", path_out, id_tex, i));
}
//创建vk资源
//g_vk->CreateCanvas(id_tex, vec_image_big);
for (size_t i = 0; i < vec_image_big.size(); ++i)
{
delete vec_image_big[i];
}
++id_tex;
}
json j;
j = group;
File::SaveString(j.dump(4), path_out + "sprite.json");
log_msg("合并图集并导出信息完成:{} -> {}", name, path_out);
}
void Factory::_load_animation()
{
// 动画加载
for (auto& iter : _mapPathImage)
{
std::string name = iter.first;
std::string path = iter.second;
// 遍历所有文件夹下的 __animation.json
std::vector<std::string> mul_file;
File::GetPathFileAll(path, mul_file, "__animation.json");
for (std::string& path_name : mul_file)
{
log_info("开始加载动画:{}", path_name);
json j = Json::ParseFile(path_name);
if(j.is_null())
continue;
std::string res_name;
if (!name.empty())
{
res_name = fmt::format("{}.{}", name,
String::GetResName(path, path_name));
}
else
res_name = String::GetResName(path, path_name);
String::EraseExtension(res_name);
auto iter = _mapAnimationInfo.find(res_name);
if (iter != _mapAnimationInfo.end())
{
log_err("重复添加动画:{}", path_name);
continue;
}
AnimationInfo info = j;
_mapAnimationInfo[res_name] = info;
log_info("加载动画成功:{}\n"
"资源名:{}\n"
"数量:{}", path_name, res_name, info._allAni.size());
}
}
}
Factory::Factory() :
_bSetPath{ false },
_bUseBinary{ false },
_bOrderPickupShow{ false },
_idTemp{ 0 },
_orderPickup{ 1.0f }
{
_imp = new FactoryImp;
}
Factory::~Factory()
{
_save_cache();
delete _imp;
}
}
#endif