refactor: 移除自定义字符串模块并改用标准库
移除core/string.h和core/string.cpp,使用标准库<string>替代 删除renderer/shader.h及相关实现文件 在需要UTF-8转换的地方添加简化版实现 更新相关头文件的包含关系
This commit is contained in:
parent
60ef7ab63f
commit
4afd52cc82
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <core/string.h>
|
|
||||||
#include <core/types.h>
|
#include <core/types.h>
|
||||||
|
#include <string>
|
||||||
#include <renderer/renderer.h>
|
#include <renderer/renderer.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <platform/window.h>
|
#include <platform/window.h>
|
||||||
|
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace extra2d {
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 字符串编码转换工具函数
|
|
||||||
// 统一使用 std::string (UTF-8) 作为项目标准字符串类型
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
// UTF-8 ↔ UTF-16 转换
|
|
||||||
std::u16string utf8ToUtf16(const std::string& utf8);
|
|
||||||
std::string utf16ToUtf8(const std::u16string& utf16);
|
|
||||||
|
|
||||||
// UTF-8 ↔ UTF-32 转换
|
|
||||||
std::u32string utf8ToUtf32(const std::string& utf8);
|
|
||||||
std::string utf32ToUtf8(const std::u32string& utf32);
|
|
||||||
|
|
||||||
// UTF-8 ↔ Wide String 转换
|
|
||||||
std::wstring utf8ToWide(const std::string& utf8);
|
|
||||||
std::string wideToUtf8(const std::wstring& wide);
|
|
||||||
|
|
||||||
// UTF-8 ↔ GBK/GB2312 转换(Windows 中文系统常用)
|
|
||||||
std::string utf8ToGbk(const std::string& utf8);
|
|
||||||
std::string gbkToUtf8(const std::string& gbk);
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 内联实现
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
inline std::u16string utf8ToUtf16(const std::string& utf8) {
|
|
||||||
if (utf8.empty()) return std::u16string();
|
|
||||||
|
|
||||||
// UTF-8 → UTF-32 → UTF-16 (with surrogate pairs)
|
|
||||||
std::u32string u32 = utf8ToUtf32(utf8);
|
|
||||||
std::u16string result;
|
|
||||||
result.reserve(u32.size());
|
|
||||||
|
|
||||||
for (char32_t ch : u32) {
|
|
||||||
if (ch <= 0xFFFF) {
|
|
||||||
result.push_back(static_cast<char16_t>(ch));
|
|
||||||
} else if (ch <= 0x10FFFF) {
|
|
||||||
// Surrogate pair
|
|
||||||
ch -= 0x10000;
|
|
||||||
result.push_back(static_cast<char16_t>(0xD800 | (ch >> 10)));
|
|
||||||
result.push_back(static_cast<char16_t>(0xDC00 | (ch & 0x3FF)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string utf16ToUtf8(const std::u16string& utf16) {
|
|
||||||
if (utf16.empty()) return std::string();
|
|
||||||
|
|
||||||
// UTF-16 → UTF-32 → UTF-8
|
|
||||||
std::u32string u32;
|
|
||||||
u32.reserve(utf16.size());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < utf16.size(); ++i) {
|
|
||||||
char16_t cu = utf16[i];
|
|
||||||
char32_t ch;
|
|
||||||
if (cu >= 0xD800 && cu <= 0xDBFF && i + 1 < utf16.size()) {
|
|
||||||
// High surrogate
|
|
||||||
char16_t cl = utf16[i + 1];
|
|
||||||
if (cl >= 0xDC00 && cl <= 0xDFFF) {
|
|
||||||
ch = 0x10000 + ((static_cast<char32_t>(cu - 0xD800) << 10) |
|
|
||||||
(cl - 0xDC00));
|
|
||||||
++i;
|
|
||||||
} else {
|
|
||||||
ch = cu; // Invalid, pass through
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ch = cu;
|
|
||||||
}
|
|
||||||
u32.push_back(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return utf32ToUtf8(u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::u32string utf8ToUtf32(const std::string& utf8) {
|
|
||||||
std::u32string result;
|
|
||||||
result.reserve(utf8.size());
|
|
||||||
|
|
||||||
const char* ptr = utf8.c_str();
|
|
||||||
const char* end = ptr + utf8.size();
|
|
||||||
|
|
||||||
while (ptr < end) {
|
|
||||||
char32_t ch = 0;
|
|
||||||
unsigned char byte = static_cast<unsigned char>(*ptr);
|
|
||||||
|
|
||||||
if ((byte & 0x80) == 0) {
|
|
||||||
// 1-byte sequence
|
|
||||||
ch = byte;
|
|
||||||
ptr += 1;
|
|
||||||
} else if ((byte & 0xE0) == 0xC0) {
|
|
||||||
// 2-byte sequence
|
|
||||||
ch = (byte & 0x1F) << 6;
|
|
||||||
ch |= (static_cast<unsigned char>(ptr[1]) & 0x3F);
|
|
||||||
ptr += 2;
|
|
||||||
} else if ((byte & 0xF0) == 0xE0) {
|
|
||||||
// 3-byte sequence
|
|
||||||
ch = (byte & 0x0F) << 12;
|
|
||||||
ch |= (static_cast<unsigned char>(ptr[1]) & 0x3F) << 6;
|
|
||||||
ch |= (static_cast<unsigned char>(ptr[2]) & 0x3F);
|
|
||||||
ptr += 3;
|
|
||||||
} else if ((byte & 0xF8) == 0xF0) {
|
|
||||||
// 4-byte sequence
|
|
||||||
ch = (byte & 0x07) << 18;
|
|
||||||
ch |= (static_cast<unsigned char>(ptr[1]) & 0x3F) << 12;
|
|
||||||
ch |= (static_cast<unsigned char>(ptr[2]) & 0x3F) << 6;
|
|
||||||
ch |= (static_cast<unsigned char>(ptr[3]) & 0x3F);
|
|
||||||
ptr += 4;
|
|
||||||
} else {
|
|
||||||
// Invalid UTF-8, skip
|
|
||||||
ptr += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push_back(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string utf32ToUtf8(const std::u32string& utf32) {
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
for (char32_t ch : utf32) {
|
|
||||||
if (ch <= 0x7F) {
|
|
||||||
// 1-byte
|
|
||||||
result.push_back(static_cast<char>(ch));
|
|
||||||
} else if (ch <= 0x7FF) {
|
|
||||||
// 2-byte
|
|
||||||
result.push_back(static_cast<char>(0xC0 | ((ch >> 6) & 0x1F)));
|
|
||||||
result.push_back(static_cast<char>(0x80 | (ch & 0x3F)));
|
|
||||||
} else if (ch <= 0xFFFF) {
|
|
||||||
// 3-byte
|
|
||||||
result.push_back(static_cast<char>(0xE0 | ((ch >> 12) & 0x0F)));
|
|
||||||
result.push_back(static_cast<char>(0x80 | ((ch >> 6) & 0x3F)));
|
|
||||||
result.push_back(static_cast<char>(0x80 | (ch & 0x3F)));
|
|
||||||
} else if (ch <= 0x10FFFF) {
|
|
||||||
// 4-byte
|
|
||||||
result.push_back(static_cast<char>(0xF0 | ((ch >> 18) & 0x07)));
|
|
||||||
result.push_back(static_cast<char>(0x80 | ((ch >> 12) & 0x3F)));
|
|
||||||
result.push_back(static_cast<char>(0x80 | ((ch >> 6) & 0x3F)));
|
|
||||||
result.push_back(static_cast<char>(0x80 | (ch & 0x3F)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::wstring utf8ToWide(const std::string& utf8) {
|
|
||||||
if (utf8.empty()) return std::wstring();
|
|
||||||
|
|
||||||
if constexpr (sizeof(wchar_t) == 4) {
|
|
||||||
// wchar_t is 32-bit (Linux/Switch): same as UTF-32
|
|
||||||
std::u32string u32 = utf8ToUtf32(utf8);
|
|
||||||
return std::wstring(u32.begin(), u32.end());
|
|
||||||
} else {
|
|
||||||
// wchar_t is 16-bit (Windows): same as UTF-16
|
|
||||||
std::u16string u16 = utf8ToUtf16(utf8);
|
|
||||||
return std::wstring(u16.begin(), u16.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string wideToUtf8(const std::wstring& wide) {
|
|
||||||
if (wide.empty()) return std::string();
|
|
||||||
|
|
||||||
if constexpr (sizeof(wchar_t) == 4) {
|
|
||||||
std::u32string u32(wide.begin(), wide.end());
|
|
||||||
return utf32ToUtf8(u32);
|
|
||||||
} else {
|
|
||||||
std::u16string u16(wide.begin(), wide.end());
|
|
||||||
return utf16ToUtf8(u16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GBK/GB2312 转换(Windows 平台实现)
|
|
||||||
// 注意:Windows 实现在 .cpp 文件中,避免头文件包含 windows.h 导致冲突
|
|
||||||
#ifdef _WIN32
|
|
||||||
// 前向声明,实现在 .cpp 文件中
|
|
||||||
std::string utf8ToGbkImpl(const std::string& utf8);
|
|
||||||
std::string gbkToUtf8Impl(const std::string& gbk);
|
|
||||||
|
|
||||||
inline std::string utf8ToGbk(const std::string& utf8) {
|
|
||||||
return utf8ToGbkImpl(utf8);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string gbkToUtf8(const std::string& gbk) {
|
|
||||||
return gbkToUtf8Impl(gbk);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// 非 Windows 平台,GBK 转换使用 iconv 或返回原字符串
|
|
||||||
inline std::string utf8ToGbk(const std::string& utf8) {
|
|
||||||
// TODO: 使用 iconv 实现
|
|
||||||
return utf8;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string gbkToUtf8(const std::string& gbk) {
|
|
||||||
// TODO: 使用 iconv 实现
|
|
||||||
return gbk;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace extra2d
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
#include <core/color.h>
|
#include <core/color.h>
|
||||||
#include <core/rect.h>
|
#include <core/rect.h>
|
||||||
#include <core/size.h>
|
#include <core/size.h>
|
||||||
#include <core/string.h>
|
|
||||||
#include <core/transform.h>
|
#include <core/transform.h>
|
||||||
#include <core/types.h>
|
#include <core/types.h>
|
||||||
#include <core/vec2.h>
|
#include <core/vec2.h>
|
||||||
|
|
@ -26,7 +25,6 @@
|
||||||
#include <renderer/camera.h>
|
#include <renderer/camera.h>
|
||||||
#include <renderer/render_target.h>
|
#include <renderer/render_target.h>
|
||||||
#include <renderer/renderer.h>
|
#include <renderer/renderer.h>
|
||||||
#include <renderer/shader.h>
|
|
||||||
|
|
||||||
// Scene
|
// Scene
|
||||||
#include <scene/node.h>
|
#include <scene/node.h>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <core/size.h>
|
#include <core/size.h>
|
||||||
#include <core/string.h>
|
|
||||||
#include <core/types.h>
|
#include <core/types.h>
|
||||||
#include <core/vec2.h>
|
#include <core/vec2.h>
|
||||||
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <core/color.h>
|
|
||||||
#include <core/types.h>
|
|
||||||
#include <graphics/opengl/gl_shader.h>
|
|
||||||
#include <functional>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace extra2d {
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Shader参数绑定回调
|
|
||||||
// ============================================================================
|
|
||||||
using ShaderBindCallback = std::function<void(GLShader &)>;
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Shader系统 - 管理所有Shader的加载、缓存和热重载
|
|
||||||
// ============================================================================
|
|
||||||
class ShaderSystem {
|
|
||||||
public:
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 单例访问
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
static ShaderSystem &getInstance();
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 初始化和关闭
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
bool init();
|
|
||||||
void shutdown();
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// Shader加载
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从文件加载Shader
|
|
||||||
* @param name Shader名称(用于缓存)
|
|
||||||
* @param vertPath 顶点着色器文件路径
|
|
||||||
* @param fragPath 片段着色器文件路径
|
|
||||||
* @return 加载的Shader,失败返回nullptr
|
|
||||||
*/
|
|
||||||
Ptr<GLShader> loadFromFile(const std::string &name,
|
|
||||||
const std::string &vertPath,
|
|
||||||
const std::string &fragPath);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从源码字符串加载Shader
|
|
||||||
* @param name Shader名称(用于缓存)
|
|
||||||
* @param vertSource 顶点着色器源码
|
|
||||||
* @param fragSource 片段着色器源码
|
|
||||||
* @return 加载的Shader,失败返回nullptr
|
|
||||||
*/
|
|
||||||
Ptr<GLShader> loadFromSource(const std::string &name,
|
|
||||||
const std::string &vertSource,
|
|
||||||
const std::string &fragSource);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从已编译的程序获取Shader
|
|
||||||
* @param name Shader名称
|
|
||||||
* @return 缓存的Shader,不存在返回nullptr
|
|
||||||
*/
|
|
||||||
Ptr<GLShader> get(const std::string &name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 检查Shader是否存在
|
|
||||||
*/
|
|
||||||
bool has(const std::string &name) const;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// Shader移除
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
void remove(const std::string &name);
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 热重载支持
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 启用/禁用文件监视
|
|
||||||
*/
|
|
||||||
void setFileWatching(bool enable);
|
|
||||||
bool isFileWatching() const { return fileWatching_; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 更新文件监视(在主循环中调用)
|
|
||||||
*/
|
|
||||||
void updateFileWatching();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 重载指定Shader
|
|
||||||
*/
|
|
||||||
bool reload(const std::string &name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 重载所有Shader
|
|
||||||
*/
|
|
||||||
void reloadAll();
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 内置Shader获取
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Ptr<GLShader> getBuiltinSpriteShader();
|
|
||||||
Ptr<GLShader> getBuiltinParticleShader();
|
|
||||||
Ptr<GLShader> getBuiltinPostProcessShader();
|
|
||||||
Ptr<GLShader> getBuiltinShapeShader();
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 工具方法
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从文件读取文本内容
|
|
||||||
*/
|
|
||||||
static std::string readFile(const std::string &filepath);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取Shader文件的最后修改时间
|
|
||||||
*/
|
|
||||||
static uint64_t getFileModifiedTime(const std::string &filepath);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ShaderSystem() = default;
|
|
||||||
~ShaderSystem() = default;
|
|
||||||
ShaderSystem(const ShaderSystem &) = delete;
|
|
||||||
ShaderSystem &operator=(const ShaderSystem &) = delete;
|
|
||||||
|
|
||||||
struct ShaderInfo {
|
|
||||||
Ptr<GLShader> shader;
|
|
||||||
std::string vertPath;
|
|
||||||
std::string fragPath;
|
|
||||||
uint64_t vertModifiedTime;
|
|
||||||
uint64_t fragModifiedTime;
|
|
||||||
bool isBuiltin;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::unordered_map<std::string, ShaderInfo> shaders_;
|
|
||||||
bool fileWatching_ = false;
|
|
||||||
float watchTimer_ = 0.0f;
|
|
||||||
static constexpr float WATCH_INTERVAL = 1.0f; // 检查间隔(秒)
|
|
||||||
|
|
||||||
// 内置Shader缓存
|
|
||||||
Ptr<GLShader> builtinSpriteShader_;
|
|
||||||
Ptr<GLShader> builtinParticleShader_;
|
|
||||||
Ptr<GLShader> builtinPostProcessShader_;
|
|
||||||
Ptr<GLShader> builtinShapeShader_;
|
|
||||||
|
|
||||||
bool loadBuiltinShaders();
|
|
||||||
void checkAndReload();
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Shader参数包装器 - 简化Uniform设置
|
|
||||||
// ============================================================================
|
|
||||||
class ShaderParams {
|
|
||||||
public:
|
|
||||||
explicit ShaderParams(GLShader &shader);
|
|
||||||
|
|
||||||
ShaderParams &setBool(const std::string &name, bool value);
|
|
||||||
ShaderParams &setInt(const std::string &name, int value);
|
|
||||||
ShaderParams &setFloat(const std::string &name, float value);
|
|
||||||
ShaderParams &setVec2(const std::string &name, const glm::vec2 &value);
|
|
||||||
ShaderParams &setVec3(const std::string &name, const glm::vec3 &value);
|
|
||||||
ShaderParams &setVec4(const std::string &name, const glm::vec4 &value);
|
|
||||||
ShaderParams &setMat4(const std::string &name, const glm::mat4 &value);
|
|
||||||
ShaderParams &setColor(const std::string &name, const Color &color);
|
|
||||||
|
|
||||||
private:
|
|
||||||
GLShader &shader_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 便捷宏
|
|
||||||
// ============================================================================
|
|
||||||
#define E2D_SHADER_SYSTEM() ::extra2d::ShaderSystem::getInstance()
|
|
||||||
|
|
||||||
} // namespace extra2d
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
#include <core/string.h>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
namespace extra2d {
|
|
||||||
|
|
||||||
std::string utf8ToGbkImpl(const std::string& utf8) {
|
|
||||||
if (utf8.empty()) return std::string();
|
|
||||||
|
|
||||||
// UTF-8 → Wide → GBK
|
|
||||||
int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0);
|
|
||||||
if (wideLen <= 0) return std::string();
|
|
||||||
|
|
||||||
std::wstring wide(wideLen - 1, 0);
|
|
||||||
MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, &wide[0], wideLen);
|
|
||||||
|
|
||||||
int gbkLen = WideCharToMultiByte(CP_ACP, 0, wide.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
|
||||||
if (gbkLen <= 0) return std::string();
|
|
||||||
|
|
||||||
std::string gbk(gbkLen - 1, 0);
|
|
||||||
WideCharToMultiByte(CP_ACP, 0, wide.c_str(), -1, &gbk[0], gbkLen, nullptr, nullptr);
|
|
||||||
|
|
||||||
return gbk;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string gbkToUtf8Impl(const std::string& gbk) {
|
|
||||||
if (gbk.empty()) return std::string();
|
|
||||||
|
|
||||||
// GBK → Wide → UTF-8
|
|
||||||
int wideLen = MultiByteToWideChar(CP_ACP, 0, gbk.c_str(), -1, nullptr, 0);
|
|
||||||
if (wideLen <= 0) return std::string();
|
|
||||||
|
|
||||||
std::wstring wide(wideLen - 1, 0);
|
|
||||||
MultiByteToWideChar(CP_ACP, 0, gbk.c_str(), -1, &wide[0], wideLen);
|
|
||||||
|
|
||||||
int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
|
||||||
if (utf8Len <= 0) return std::string();
|
|
||||||
|
|
||||||
std::string utf8(utf8Len - 1, 0);
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, &utf8[0], utf8Len, nullptr, nullptr);
|
|
||||||
|
|
||||||
return utf8;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace extra2d
|
|
||||||
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <graphics/opengl/gl_font_atlas.h>
|
#include <graphics/opengl/gl_font_atlas.h>
|
||||||
#include <core/string.h>
|
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
|
#include <string>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
#include <stb/stb_truetype.h>
|
#include <stb/stb_truetype.h>
|
||||||
|
|
@ -10,6 +10,54 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// UTF-8 到 UTF-32 转换(简化版)
|
||||||
|
// ============================================================================
|
||||||
|
static std::u32string utf8ToUtf32(const std::string& utf8) {
|
||||||
|
std::u32string result;
|
||||||
|
result.reserve(utf8.size());
|
||||||
|
|
||||||
|
const char* ptr = utf8.c_str();
|
||||||
|
const char* end = ptr + utf8.size();
|
||||||
|
|
||||||
|
while (ptr < end) {
|
||||||
|
char32_t ch = 0;
|
||||||
|
unsigned char byte = static_cast<unsigned char>(*ptr);
|
||||||
|
|
||||||
|
if ((byte & 0x80) == 0) {
|
||||||
|
// 1-byte sequence
|
||||||
|
ch = byte;
|
||||||
|
ptr += 1;
|
||||||
|
} else if ((byte & 0xE0) == 0xC0) {
|
||||||
|
// 2-byte sequence
|
||||||
|
ch = (byte & 0x1F) << 6;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[1]) & 0x3F);
|
||||||
|
ptr += 2;
|
||||||
|
} else if ((byte & 0xF0) == 0xE0) {
|
||||||
|
// 3-byte sequence
|
||||||
|
ch = (byte & 0x0F) << 12;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[1]) & 0x3F) << 6;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[2]) & 0x3F);
|
||||||
|
ptr += 3;
|
||||||
|
} else if ((byte & 0xF8) == 0xF0) {
|
||||||
|
// 4-byte sequence
|
||||||
|
ch = (byte & 0x07) << 18;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[1]) & 0x3F) << 12;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[2]) & 0x3F) << 6;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[3]) & 0x3F);
|
||||||
|
ptr += 4;
|
||||||
|
} else {
|
||||||
|
// Invalid UTF-8, skip
|
||||||
|
ptr += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push_back(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 构造函数 - 初始化字体图集
|
// 构造函数 - 初始化字体图集
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <core/string.h>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
#include <graphics/gpu_context.h>
|
#include <graphics/gpu_context.h>
|
||||||
#include <graphics/opengl/gl_font_atlas.h>
|
#include <graphics/opengl/gl_font_atlas.h>
|
||||||
#include <graphics/opengl/gl_renderer.h>
|
#include <graphics/opengl/gl_renderer.h>
|
||||||
|
|
@ -14,6 +14,54 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// UTF-8 到 UTF-32 转换(简化版)
|
||||||
|
// ============================================================================
|
||||||
|
static std::u32string utf8ToUtf32(const std::string& utf8) {
|
||||||
|
std::u32string result;
|
||||||
|
result.reserve(utf8.size());
|
||||||
|
|
||||||
|
const char* ptr = utf8.c_str();
|
||||||
|
const char* end = ptr + utf8.size();
|
||||||
|
|
||||||
|
while (ptr < end) {
|
||||||
|
char32_t ch = 0;
|
||||||
|
unsigned char byte = static_cast<unsigned char>(*ptr);
|
||||||
|
|
||||||
|
if ((byte & 0x80) == 0) {
|
||||||
|
// 1-byte sequence
|
||||||
|
ch = byte;
|
||||||
|
ptr += 1;
|
||||||
|
} else if ((byte & 0xE0) == 0xC0) {
|
||||||
|
// 2-byte sequence
|
||||||
|
ch = (byte & 0x1F) << 6;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[1]) & 0x3F);
|
||||||
|
ptr += 2;
|
||||||
|
} else if ((byte & 0xF0) == 0xE0) {
|
||||||
|
// 3-byte sequence
|
||||||
|
ch = (byte & 0x0F) << 12;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[1]) & 0x3F) << 6;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[2]) & 0x3F);
|
||||||
|
ptr += 3;
|
||||||
|
} else if ((byte & 0xF8) == 0xF0) {
|
||||||
|
// 4-byte sequence
|
||||||
|
ch = (byte & 0x07) << 18;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[1]) & 0x3F) << 12;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[2]) & 0x3F) << 6;
|
||||||
|
ch |= (static_cast<unsigned char>(ptr[3]) & 0x3F);
|
||||||
|
ptr += 4;
|
||||||
|
} else {
|
||||||
|
// Invalid UTF-8, skip
|
||||||
|
ptr += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push_back(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// 形状渲染着色器 - 支持顶点颜色批处理 (GLES 3.2)
|
// 形状渲染着色器 - 支持顶点颜色批处理 (GLES 3.2)
|
||||||
static const char *SHAPE_VERTEX_SHADER = R"(
|
static const char *SHAPE_VERTEX_SHADER = R"(
|
||||||
#version 300 es
|
#version 300 es
|
||||||
|
|
|
||||||
|
|
@ -1,492 +0,0 @@
|
||||||
#include <core/color.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <renderer/shader.h>
|
|
||||||
#include <sstream>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <utils/logger.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace extra2d {
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 内置Shader源码
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
// 标准精灵着色器 (GLES 3.2)
|
|
||||||
static const char *BUILTIN_SPRITE_VERT = R"(
|
|
||||||
#version 300 es
|
|
||||||
precision highp float;
|
|
||||||
layout(location = 0) in vec2 a_position;
|
|
||||||
layout(location = 1) in vec2 a_texCoord;
|
|
||||||
layout(location = 2) in vec4 a_color;
|
|
||||||
|
|
||||||
uniform mat4 u_viewProjection;
|
|
||||||
uniform mat4 u_model;
|
|
||||||
|
|
||||||
out vec2 v_texCoord;
|
|
||||||
out vec4 v_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = u_viewProjection * u_model * vec4(a_position, 0.0, 1.0);
|
|
||||||
v_texCoord = a_texCoord;
|
|
||||||
v_color = a_color;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
static const char *BUILTIN_SPRITE_FRAG = R"(
|
|
||||||
#version 300 es
|
|
||||||
precision highp float;
|
|
||||||
in vec2 v_texCoord;
|
|
||||||
in vec4 v_color;
|
|
||||||
|
|
||||||
uniform sampler2D u_texture;
|
|
||||||
uniform float u_opacity;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 texColor = texture(u_texture, v_texCoord);
|
|
||||||
fragColor = texColor * v_color;
|
|
||||||
fragColor.a *= u_opacity;
|
|
||||||
|
|
||||||
if (fragColor.a < 0.01) {
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
// 粒子着色器 (GLES 3.2)
|
|
||||||
static const char *BUILTIN_PARTICLE_VERT = R"(
|
|
||||||
#version 300 es
|
|
||||||
precision highp float;
|
|
||||||
layout(location = 0) in vec2 a_position;
|
|
||||||
layout(location = 1) in vec2 a_texCoord;
|
|
||||||
layout(location = 2) in vec4 a_color;
|
|
||||||
layout(location = 3) in float a_size;
|
|
||||||
layout(location = 4) in float a_rotation;
|
|
||||||
|
|
||||||
uniform mat4 u_viewProjection;
|
|
||||||
|
|
||||||
out vec2 v_texCoord;
|
|
||||||
out vec4 v_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float c = cos(a_rotation);
|
|
||||||
float s = sin(a_rotation);
|
|
||||||
mat2 rot = mat2(c, -s, s, c);
|
|
||||||
|
|
||||||
vec2 pos = rot * a_position * a_size;
|
|
||||||
gl_Position = u_viewProjection * vec4(pos, 0.0, 1.0);
|
|
||||||
|
|
||||||
v_texCoord = a_texCoord;
|
|
||||||
v_color = a_color;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
static const char *BUILTIN_PARTICLE_FRAG = R"(
|
|
||||||
#version 300 es
|
|
||||||
precision highp float;
|
|
||||||
in vec2 v_texCoord;
|
|
||||||
in vec4 v_color;
|
|
||||||
|
|
||||||
uniform sampler2D u_texture;
|
|
||||||
uniform int u_textureEnabled;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 color = v_color;
|
|
||||||
|
|
||||||
if (u_textureEnabled > 0) {
|
|
||||||
color *= texture(u_texture, v_texCoord);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 圆形粒子
|
|
||||||
vec2 center = v_texCoord - vec2(0.5);
|
|
||||||
float dist = length(center);
|
|
||||||
float alpha = 1.0 - smoothstep(0.4, 0.5, dist);
|
|
||||||
color.a *= alpha;
|
|
||||||
|
|
||||||
if (color.a < 0.01) {
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragColor = color;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
// 后处理着色器 (GLES 3.2)
|
|
||||||
static const char *BUILTIN_POSTPROCESS_VERT = R"(
|
|
||||||
#version 300 es
|
|
||||||
precision highp float;
|
|
||||||
layout(location = 0) in vec2 a_position;
|
|
||||||
layout(location = 1) in vec2 a_texCoord;
|
|
||||||
|
|
||||||
out vec2 v_texCoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
||||||
v_texCoord = a_texCoord;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
static const char *BUILTIN_POSTPROCESS_FRAG = R"(
|
|
||||||
#version 300 es
|
|
||||||
precision highp float;
|
|
||||||
in vec2 v_texCoord;
|
|
||||||
|
|
||||||
uniform sampler2D u_texture;
|
|
||||||
uniform vec2 u_resolution;
|
|
||||||
uniform float u_time;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
fragColor = texture(u_texture, v_texCoord);
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
// 形状渲染着色器 (GLES 3.2)
|
|
||||||
static const char *BUILTIN_SHAPE_VERT = R"(
|
|
||||||
#version 300 es
|
|
||||||
precision highp float;
|
|
||||||
layout(location = 0) in vec2 a_position;
|
|
||||||
layout(location = 1) in vec4 a_color;
|
|
||||||
|
|
||||||
uniform mat4 u_viewProjection;
|
|
||||||
|
|
||||||
out vec4 v_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = u_viewProjection * vec4(a_position, 0.0, 1.0);
|
|
||||||
v_color = a_color;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
static const char *BUILTIN_SHAPE_FRAG = R"(
|
|
||||||
#version 300 es
|
|
||||||
precision highp float;
|
|
||||||
in vec4 v_color;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
fragColor = v_color;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// ShaderSystem实现
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
ShaderSystem &ShaderSystem::getInstance() {
|
|
||||||
static ShaderSystem instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShaderSystem::init() {
|
|
||||||
E2D_INFO("初始化Shader系统...");
|
|
||||||
|
|
||||||
if (!loadBuiltinShaders()) {
|
|
||||||
E2D_ERROR("加载内置Shader失败!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
E2D_INFO("Shader系统初始化完成");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShaderSystem::shutdown() {
|
|
||||||
E2D_INFO("关闭Shader系统...");
|
|
||||||
clear();
|
|
||||||
|
|
||||||
builtinSpriteShader_.reset();
|
|
||||||
builtinParticleShader_.reset();
|
|
||||||
builtinPostProcessShader_.reset();
|
|
||||||
builtinShapeShader_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShaderSystem::loadBuiltinShaders() {
|
|
||||||
// 加载精灵Shader
|
|
||||||
builtinSpriteShader_ = std::make_shared<GLShader>();
|
|
||||||
if (!builtinSpriteShader_->compileFromSource(BUILTIN_SPRITE_VERT,
|
|
||||||
BUILTIN_SPRITE_FRAG)) {
|
|
||||||
E2D_ERROR("编译内置精灵Shader失败!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载粒子Shader
|
|
||||||
builtinParticleShader_ = std::make_shared<GLShader>();
|
|
||||||
if (!builtinParticleShader_->compileFromSource(BUILTIN_PARTICLE_VERT,
|
|
||||||
BUILTIN_PARTICLE_FRAG)) {
|
|
||||||
E2D_ERROR("编译内置粒子Shader失败!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载后处理Shader
|
|
||||||
builtinPostProcessShader_ = std::make_shared<GLShader>();
|
|
||||||
if (!builtinPostProcessShader_->compileFromSource(BUILTIN_POSTPROCESS_VERT,
|
|
||||||
BUILTIN_POSTPROCESS_FRAG)) {
|
|
||||||
E2D_ERROR("编译内置后处理Shader失败!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载形状Shader
|
|
||||||
builtinShapeShader_ = std::make_shared<GLShader>();
|
|
||||||
if (!builtinShapeShader_->compileFromSource(BUILTIN_SHAPE_VERT,
|
|
||||||
BUILTIN_SHAPE_FRAG)) {
|
|
||||||
E2D_ERROR("编译内置形状Shader失败!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
E2D_INFO("内置Shader加载成功");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<GLShader> ShaderSystem::loadFromFile(const std::string &name,
|
|
||||||
const std::string &vertPath,
|
|
||||||
const std::string &fragPath) {
|
|
||||||
// 读取文件内容
|
|
||||||
std::string vertSource = readFile(vertPath);
|
|
||||||
std::string fragSource = readFile(fragPath);
|
|
||||||
|
|
||||||
if (vertSource.empty()) {
|
|
||||||
E2D_ERROR("无法读取顶点着色器文件: {}", vertPath);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragSource.empty()) {
|
|
||||||
E2D_ERROR("无法读取片段着色器文件: {}", fragPath);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 编译Shader
|
|
||||||
auto shader = std::make_shared<GLShader>();
|
|
||||||
if (!shader->compileFromSource(vertSource.c_str(), fragSource.c_str())) {
|
|
||||||
E2D_ERROR("编译Shader '{}' 失败", name);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 存储Shader信息
|
|
||||||
ShaderInfo info;
|
|
||||||
info.shader = shader;
|
|
||||||
info.vertPath = vertPath;
|
|
||||||
info.fragPath = fragPath;
|
|
||||||
info.vertModifiedTime = getFileModifiedTime(vertPath);
|
|
||||||
info.fragModifiedTime = getFileModifiedTime(fragPath);
|
|
||||||
info.isBuiltin = false;
|
|
||||||
|
|
||||||
shaders_[name] = std::move(info);
|
|
||||||
|
|
||||||
E2D_INFO("加载Shader '{}' 成功", name);
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<GLShader> ShaderSystem::loadFromSource(const std::string &name,
|
|
||||||
const std::string &vertSource,
|
|
||||||
const std::string &fragSource) {
|
|
||||||
auto shader = std::make_shared<GLShader>();
|
|
||||||
if (!shader->compileFromSource(vertSource.c_str(), fragSource.c_str())) {
|
|
||||||
E2D_ERROR("编译Shader '{}' 失败", name);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderInfo info;
|
|
||||||
info.shader = shader;
|
|
||||||
info.vertModifiedTime = 0;
|
|
||||||
info.fragModifiedTime = 0;
|
|
||||||
info.isBuiltin = false;
|
|
||||||
|
|
||||||
shaders_[name] = std::move(info);
|
|
||||||
|
|
||||||
E2D_INFO("加载Shader '{}' 成功", name);
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<GLShader> ShaderSystem::get(const std::string &name) {
|
|
||||||
auto it = shaders_.find(name);
|
|
||||||
if (it != shaders_.end()) {
|
|
||||||
return it->second.shader;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShaderSystem::has(const std::string &name) const {
|
|
||||||
return shaders_.find(name) != shaders_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShaderSystem::remove(const std::string &name) { shaders_.erase(name); }
|
|
||||||
|
|
||||||
void ShaderSystem::clear() { shaders_.clear(); }
|
|
||||||
|
|
||||||
void ShaderSystem::setFileWatching(bool enable) {
|
|
||||||
fileWatching_ = enable;
|
|
||||||
if (enable) {
|
|
||||||
E2D_INFO("启用Shader文件监视");
|
|
||||||
} else {
|
|
||||||
E2D_INFO("禁用Shader文件监视");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShaderSystem::updateFileWatching() {
|
|
||||||
if (!fileWatching_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
watchTimer_ += 0.016f; // 假设60fps
|
|
||||||
if (watchTimer_ >= WATCH_INTERVAL) {
|
|
||||||
watchTimer_ = 0.0f;
|
|
||||||
checkAndReload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShaderSystem::checkAndReload() {
|
|
||||||
for (auto &[name, info] : shaders_) {
|
|
||||||
if (info.isBuiltin)
|
|
||||||
continue;
|
|
||||||
if (info.vertPath.empty() || info.fragPath.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint64_t vertTime = getFileModifiedTime(info.vertPath);
|
|
||||||
uint64_t fragTime = getFileModifiedTime(info.fragPath);
|
|
||||||
|
|
||||||
if (vertTime > info.vertModifiedTime || fragTime > info.fragModifiedTime) {
|
|
||||||
E2D_INFO("检测到Shader '{}' 文件变化,正在重载...", name);
|
|
||||||
reload(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShaderSystem::reload(const std::string &name) {
|
|
||||||
auto it = shaders_.find(name);
|
|
||||||
if (it == shaders_.end()) {
|
|
||||||
E2D_ERROR("无法重载不存在的Shader '{}'", name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &info = it->second;
|
|
||||||
if (info.isBuiltin) {
|
|
||||||
E2D_WARN("无法重载内置Shader '{}'", name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.vertPath.empty() || info.fragPath.empty()) {
|
|
||||||
E2D_ERROR("Shader '{}' 没有关联的文件路径", name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新加载
|
|
||||||
auto newShader = loadFromFile(name, info.vertPath, info.fragPath);
|
|
||||||
if (newShader) {
|
|
||||||
E2D_INFO("重载Shader '{}' 成功", name);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShaderSystem::reloadAll() {
|
|
||||||
for (const auto &[name, info] : shaders_) {
|
|
||||||
if (!info.isBuiltin) {
|
|
||||||
reload(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<GLShader> ShaderSystem::getBuiltinSpriteShader() {
|
|
||||||
return builtinSpriteShader_;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<GLShader> ShaderSystem::getBuiltinParticleShader() {
|
|
||||||
return builtinParticleShader_;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<GLShader> ShaderSystem::getBuiltinPostProcessShader() {
|
|
||||||
return builtinPostProcessShader_;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<GLShader> ShaderSystem::getBuiltinShapeShader() {
|
|
||||||
return builtinShapeShader_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ShaderSystem::readFile(const std::string &filepath) {
|
|
||||||
std::ifstream file(filepath, std::ios::in | std::ios::binary);
|
|
||||||
if (!file.is_open()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream buffer;
|
|
||||||
buffer << file.rdbuf();
|
|
||||||
return buffer.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t ShaderSystem::getFileModifiedTime(const std::string &filepath) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
struct _stat64 statBuf;
|
|
||||||
if (_stat64(filepath.c_str(), &statBuf) == 0) {
|
|
||||||
return static_cast<uint64_t>(statBuf.st_mtime);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
struct stat statBuf;
|
|
||||||
if (stat(filepath.c_str(), &statBuf) == 0) {
|
|
||||||
return static_cast<uint64_t>(statBuf.st_mtime);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// ShaderParams实现
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
ShaderParams::ShaderParams(GLShader &shader) : shader_(shader) {}
|
|
||||||
|
|
||||||
ShaderParams &ShaderParams::setBool(const std::string &name, bool value) {
|
|
||||||
shader_.setBool(name, value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderParams &ShaderParams::setInt(const std::string &name, int value) {
|
|
||||||
shader_.setInt(name, value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderParams &ShaderParams::setFloat(const std::string &name, float value) {
|
|
||||||
shader_.setFloat(name, value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderParams &ShaderParams::setVec2(const std::string &name,
|
|
||||||
const glm::vec2 &value) {
|
|
||||||
shader_.setVec2(name, value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderParams &ShaderParams::setVec3(const std::string &name,
|
|
||||||
const glm::vec3 &value) {
|
|
||||||
shader_.setVec3(name, value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderParams &ShaderParams::setVec4(const std::string &name,
|
|
||||||
const glm::vec4 &value) {
|
|
||||||
shader_.setVec4(name, value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderParams &ShaderParams::setMat4(const std::string &name,
|
|
||||||
const glm::mat4 &value) {
|
|
||||||
shader_.setMat4(name, value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderParams &ShaderParams::setColor(const std::string &name,
|
|
||||||
const Color &color) {
|
|
||||||
shader_.setVec4(name, glm::vec4(color.r, color.g, color.b, color.a));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace extra2d
|
|
||||||
Loading…
Reference in New Issue