データベース:コードテーブルは一致に
守矢諏訪子 <suwako@076.moe>、2026-06-25 22:10
コミット dff300cc96b86babf7044752bcf26a24e11293c9
・親 91f9bb8
・ファイルを見る
6個のファイル、+88 -126
変更
.gitignore
| @@ -1,3 +1,3 @@ | ||
| 1 | -build | |
| 1 | +*build | |
| 2 | 2 | .vs |
| 3 | 3 | shaderplayground.db |
| @@ -39,6 +39,13 @@ | ||
| 39 | 39 | } // namespace sqlite |
| 40 | 40 | |
| 41 | 41 | namespace db { |
| 42 | + enum class ShaderCodeType { | |
| 43 | + Default = 0, | |
| 44 | + Lua = 1, | |
| 45 | + GlslVertex = 2, | |
| 46 | + GlslFragment = 3, | |
| 47 | + }; | |
| 48 | + | |
| 42 | 49 | // 初期設定。 |
| 43 | 50 | // 既に存在したら、見逃す。 |
| 44 | 51 | void Initialize(sqlite::Instance &db); |
| @@ -35,6 +35,7 @@ | ||
| 35 | 35 | #pragma once |
| 36 | 36 | |
| 37 | 37 | #include <util/types.hh> |
| 38 | +#include <database/setup.hh> | |
| 38 | 39 | |
| 39 | 40 | namespace sqlite { |
| 40 | 41 | class Instance; |
| @@ -43,7 +44,9 @@ | ||
| 43 | 44 | namespace db { |
| 44 | 45 | struct CodeData { |
| 45 | 46 | u32 id = 0; |
| 47 | + ShaderCodeType type = ShaderCodeType::Default; | |
| 46 | 48 | string code = ""; |
| 49 | + string filename = ""; | |
| 47 | 50 | }; |
| 48 | 51 | |
| 49 | 52 | struct ShaderData { |
| @@ -56,5 +59,5 @@ | ||
| 56 | 59 | }; |
| 57 | 60 | |
| 58 | 61 | vector<ShaderData> GetAllShaders(sqlite::Instance &db); |
| 59 | - void SaveCode(sqlite::Instance &db, u32 id, const string &code, const string &table); | |
| 62 | + void SaveCode(sqlite::Instance &db, const CodeData &data); | |
| 60 | 63 | } // namespace db |
変更
main.cc
| @@ -82,7 +82,7 @@ | ||
| 82 | 82 | |
| 83 | 83 | // GLADを初期化 |
| 84 | 84 | if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { |
| 85 | - std::cout << "GLADの初期化に失敗しました" << std::endl; | |
| 85 | + std::cerr << "GLADの初期化に失敗しました" << std::endl; | |
| 86 | 86 | return -1; |
| 87 | 87 | } |
| 88 | 88 | |
| @@ -103,36 +103,36 @@ | ||
| 103 | 103 | vector<db::ShaderData> codeMap = db::GetAllShaders(db); |
| 104 | 104 | u32 shaderId; |
| 105 | 105 | string shaderName; |
| 106 | - string VERT = ""; | |
| 107 | - string FRAG = ""; | |
| 108 | - string LUA = ""; | |
| 106 | + db::CodeData VERT = {}; | |
| 107 | + db::CodeData FRAG = {}; | |
| 108 | + db::CodeData LUA = {}; | |
| 109 | 109 | |
| 110 | 110 | for (const auto &c : codeMap) { |
| 111 | 111 | shaderId = c.id; |
| 112 | 112 | shaderName = c.name; |
| 113 | - VERT = c.vertexShader.code; | |
| 114 | - FRAG = c.fragmentShader.code; | |
| 115 | - LUA = c.luaCode.code; | |
| 113 | + VERT = c.vertexShader; | |
| 114 | + FRAG = c.fragmentShader; | |
| 115 | + LUA = c.luaCode; | |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 | string title = shaderName + "(頂点シェーダー)"; |
| 119 | - gui::Editor vertEditor(title, "VertexEditor", VERT, gui::Glsl, ge.GetCjkFont(), ge.GetMonoFont()); | |
| 119 | + gui::Editor vertEditor(title, "VertexEditor", VERT.code, gui::Glsl, ge.GetCjkFont(), ge.GetMonoFont()); | |
| 120 | 120 | |
| 121 | 121 | title = shaderName + "(フラグメントシェーダー)"; |
| 122 | - gui::Editor fragEditor(title, "FragmentEditor", FRAG, gui::Glsl, ge.GetCjkFont(), ge.GetMonoFont()); | |
| 122 | + gui::Editor fragEditor(title, "FragmentEditor", FRAG.code, gui::Glsl, ge.GetCjkFont(), ge.GetMonoFont()); | |
| 123 | 123 | |
| 124 | 124 | title = shaderName + "(Luaエディター)"; |
| 125 | - gui::Editor luaEditor(title, "LuaEditor", LUA, gui::Lua, ge.GetCjkFont(), ge.GetMonoFont()); | |
| 125 | + gui::Editor luaEditor(title, "LuaEditor", LUA.code, gui::Lua, ge.GetCjkFont(), ge.GetMonoFont()); | |
| 126 | 126 | |
| 127 | 127 | // シェーダーをコンパイル |
| 128 | - Shader vertexShader(VERT, GL_VERTEX_SHADER); | |
| 129 | - Shader fragmentShader(FRAG, GL_FRAGMENT_SHADER); | |
| 128 | + Shader vertexShader(VERT.code, GL_VERTEX_SHADER); | |
| 129 | + Shader fragmentShader(FRAG.code, GL_FRAGMENT_SHADER); | |
| 130 | 130 | |
| 131 | 131 | // シェーダープログラムをリンク |
| 132 | 132 | Program shaderProgram(vertexShader, fragmentShader); |
| 133 | 133 | |
| 134 | 134 | // 頂点データはLuaから受け取る |
| 135 | - lua::LuaEngine luaEngine(LUA, &shaderProgram, &cmd); | |
| 135 | + lua::LuaEngine luaEngine(LUA.code, &shaderProgram, &cmd); | |
| 136 | 136 | auto &mesh = luaEngine.GetMesh(); |
| 137 | 137 | |
| 138 | 138 | VertexArrays VAO(1); |
| @@ -156,14 +156,14 @@ | ||
| 156 | 156 | // メインレンダリングループ |
| 157 | 157 | while (!window.ShouldClose()) { |
| 158 | 158 | auto compileCommand = [&]() { |
| 159 | - VERT = vertEditor.Get().GetText(); | |
| 160 | - FRAG = fragEditor.Get().GetText(); | |
| 161 | - LUA = luaEditor.Get().GetText(); | |
| 159 | + VERT.code = vertEditor.Get().GetText(); | |
| 160 | + FRAG.code = fragEditor.Get().GetText(); | |
| 161 | + LUA.code = luaEditor.Get().GetText(); | |
| 162 | 162 | |
| 163 | 163 | try { |
| 164 | - shaderProgram.Reload(VERT, FRAG); | |
| 164 | + shaderProgram.Reload(VERT.code, FRAG.code); | |
| 165 | 165 | luaEngine.SetProgram(&shaderProgram); |
| 166 | - luaEngine.Reload(LUA); | |
| 166 | + luaEngine.Reload(LUA.code); | |
| 167 | 167 | { |
| 168 | 168 | lua::LuaMesh newMesh = luaEngine.GetMesh(); |
| 169 | 169 | |
| @@ -205,13 +205,13 @@ | ||
| 205 | 205 | }; |
| 206 | 206 | |
| 207 | 207 | auto saveCommand = [&]() { |
| 208 | - VERT = vertEditor.Get().GetText(); | |
| 209 | - FRAG = fragEditor.Get().GetText(); | |
| 210 | - LUA = luaEditor.Get().GetText(); | |
| 208 | + VERT.code = vertEditor.Get().GetText(); | |
| 209 | + FRAG.code = fragEditor.Get().GetText(); | |
| 210 | + LUA.code = luaEditor.Get().GetText(); | |
| 211 | 211 | |
| 212 | - db::SaveCode(db, shaderId, VERT, "vertex_shader"); | |
| 213 | - db::SaveCode(db, shaderId, FRAG, "fragment_shader"); | |
| 214 | - db::SaveCode(db, shaderId, LUA, "lua_code"); | |
| 212 | + db::SaveCode(db, VERT); | |
| 213 | + db::SaveCode(db, FRAG); | |
| 214 | + db::SaveCode(db, LUA); | |
| 215 | 215 | |
| 216 | 216 | gui::LogEntry entry; |
| 217 | 217 | entry.type = gui::LogType::Info; |
| @@ -42,8 +42,7 @@ | ||
| 42 | 42 | |
| 43 | 43 | namespace db { |
| 44 | 44 | void Initialize(sqlite::Instance &db) { |
| 45 | - cstr sql = R"( | |
| 46 | -CREATE TABLE IF NOT EXISTS version ( | |
| 45 | + cstr sql = R"(CREATE TABLE IF NOT EXISTS version ( | |
| 47 | 46 | id INTEGER PRIMARY KEY, |
| 48 | 47 | major INTEGER NOT NULL, |
| 49 | 48 | minor INTEGER NOT NULL, |
| @@ -78,60 +77,25 @@ | ||
| 78 | 77 | WHERE id = NEW.id; |
| 79 | 78 | END; |
| 80 | 79 | |
| 81 | -CREATE TABLE IF NOT EXISTS vertex_shader ( | |
| 80 | +CREATE TABLE IF NOT EXISTS shader_code ( | |
| 82 | 81 | id INTEGER PRIMARY KEY, |
| 83 | 82 | shader_id INTEGER NOT NULL, |
| 83 | + code_type INTEGER NOT NULL, | |
| 84 | 84 | code TEXT NOT NULL, |
| 85 | + filename TEXT, | |
| 85 | 86 | created_at DATETIME DEFAULT CURRENT_TIMESTAMP, |
| 86 | 87 | updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, |
| 87 | 88 | |
| 88 | 89 | FOREIGN KEY (shader_id) REFERENCES shaders(id) ON DELETE CASCADE |
| 89 | 90 | ); |
| 90 | 91 | |
| 91 | -CREATE TRIGGER IF NOT EXISTS vertex_shader_updated_at | |
| 92 | -AFTER UPDATE ON vertex_shader | |
| 92 | +CREATE TRIGGER IF NOT EXISTS shader_code_updated_at | |
| 93 | +AFTER UPDATE ON shader_code | |
| 93 | 94 | BEGIN |
| 94 | - UPDATE vertex_shader | |
| 95 | + UPDATE shader_code | |
| 95 | 96 | SET updated_at = CURRENT_TIMESTAMP |
| 96 | 97 | WHERE id = NEW.id; |
| 97 | -END; | |
| 98 | - | |
| 99 | -CREATE TABLE IF NOT EXISTS fragment_shader ( | |
| 100 | - id INTEGER PRIMARY KEY, | |
| 101 | - shader_id INTEGER NOT NULL, | |
| 102 | - code TEXT NOT NULL, | |
| 103 | - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| 104 | - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| 105 | - | |
| 106 | - FOREIGN KEY (shader_id) REFERENCES shaders(id) ON DELETE CASCADE | |
| 107 | -); | |
| 108 | - | |
| 109 | -CREATE TRIGGER IF NOT EXISTS fragment_shader_updated_at | |
| 110 | -AFTER UPDATE ON fragment_shader | |
| 111 | -BEGIN | |
| 112 | - UPDATE fragment_shader | |
| 113 | - SET updated_at = CURRENT_TIMESTAMP | |
| 114 | - WHERE id = NEW.id; | |
| 115 | -END; | |
| 116 | - | |
| 117 | -CREATE TABLE IF NOT EXISTS lua_code ( | |
| 118 | - id INTEGER PRIMARY KEY, | |
| 119 | - shader_id INTEGER NOT NULL, | |
| 120 | - code TEXT NOT NULL, | |
| 121 | - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| 122 | - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| 123 | - | |
| 124 | - FOREIGN KEY (shader_id) REFERENCES shaders(id) ON DELETE CASCADE | |
| 125 | -); | |
| 126 | - | |
| 127 | -CREATE TRIGGER IF NOT EXISTS lua_code_updated_at | |
| 128 | -AFTER UPDATE ON lua_code | |
| 129 | -BEGIN | |
| 130 | - UPDATE lua_code | |
| 131 | - SET updated_at = CURRENT_TIMESTAMP | |
| 132 | - WHERE id = NEW.id; | |
| 133 | -END; | |
| 134 | -)"; | |
| 98 | +END;)"; | |
| 135 | 99 | |
| 136 | 100 | db.Exec(sql); |
| 137 | 101 | |
| @@ -146,10 +110,7 @@ | ||
| 146 | 110 | |
| 147 | 111 | { |
| 148 | 112 | sqlite::Stmt stmt(db.GetDB()); |
| 149 | - string s = R"( | |
| 150 | - INSERT INTO version (major, minor, revision) VALUES (?, ?, ?); | |
| 151 | -)"; | |
| 152 | - stmt.Prepare(s); | |
| 113 | + stmt.Prepare("INSERT INTO version (major, minor, revision) VALUES (?, ?, ?);"); | |
| 153 | 114 | stmt.BindInt(1, version::major); |
| 154 | 115 | stmt.BindInt(2, version::minor); |
| 155 | 116 | stmt.BindInt(3, version::revision); |
| @@ -161,10 +122,7 @@ | ||
| 161 | 122 | |
| 162 | 123 | { |
| 163 | 124 | sqlite::Stmt stmt(db.GetDB()); |
| 164 | - string s = R"( | |
| 165 | - INSERT INTO shaders (name, description) VALUES (?, ?); | |
| 166 | -)"; | |
| 167 | - stmt.Prepare(s); | |
| 125 | + stmt.Prepare("INSERT INTO shaders (name, description) VALUES (?, ?);"); | |
| 168 | 126 | stmt.BindText(1, "default"); |
| 169 | 127 | stmt.BindText(2, ""); |
| 170 | 128 | assert(stmt.Step() == SQLITE_DONE && "最初のシェーダーを入れ込みに失敗。\n"); |
| @@ -173,36 +131,33 @@ | ||
| 173 | 131 | |
| 174 | 132 | { |
| 175 | 133 | sqlite::Stmt stmt(db.GetDB()); |
| 176 | - string s = R"( | |
| 177 | - INSERT INTO vertex_shader (shader_id, code) VALUES (?, ?); | |
| 178 | -)"; | |
| 179 | - stmt.Prepare(s); | |
| 134 | + stmt.Prepare("INSERT INTO shader_code (shader_id, code_type, code, filename) VALUES (?, ?, ?, ?);"); | |
| 180 | 135 | stmt.BindInt(1, shaderId); |
| 181 | - stmt.BindText(2, GetDefaultVertexShader()); | |
| 136 | + stmt.BindInt(2, static_cast<int>(db::ShaderCodeType::GlslVertex)); | |
| 137 | + stmt.BindText(3, GetDefaultVertexShader()); | |
| 138 | + stmt.BindText(4, "default.vert"); | |
| 182 | 139 | |
| 183 | 140 | assert(stmt.Step() == SQLITE_DONE && "最初のシェーダーを入れ込みに失敗。\n"); |
| 184 | 141 | } |
| 185 | 142 | |
| 186 | 143 | { |
| 187 | 144 | sqlite::Stmt stmt(db.GetDB()); |
| 188 | - string s = R"( | |
| 189 | - INSERT INTO fragment_shader (shader_id, code) VALUES (?, ?); | |
| 190 | -)"; | |
| 191 | - stmt.Prepare(s); | |
| 145 | + stmt.Prepare("INSERT INTO shader_code (shader_id, code_type, code, filename) VALUES (?, ?, ?, ?);"); | |
| 192 | 146 | stmt.BindInt(1, shaderId); |
| 193 | - stmt.BindText(2, GetDefaultFragmentShader()); | |
| 147 | + stmt.BindInt(2, static_cast<int>(db::ShaderCodeType::GlslFragment)); | |
| 148 | + stmt.BindText(3, GetDefaultFragmentShader()); | |
| 149 | + stmt.BindText(4, "default.frag"); | |
| 194 | 150 | |
| 195 | 151 | assert(stmt.Step() == SQLITE_DONE && "最初のシェーダーを入れ込みに失敗。\n"); |
| 196 | 152 | } |
| 197 | 153 | |
| 198 | 154 | { |
| 199 | 155 | sqlite::Stmt stmt(db.GetDB()); |
| 200 | - string s = R"( | |
| 201 | - INSERT INTO lua_code (shader_id, code) VALUES (?, ?); | |
| 202 | -)"; | |
| 203 | - stmt.Prepare(s); | |
| 156 | + stmt.Prepare("INSERT INTO shader_code (shader_id, code_type, code, filename) VALUES (?, ?, ?, ?);"); | |
| 204 | 157 | stmt.BindInt(1, shaderId); |
| 205 | - stmt.BindText(2, GetDefaultLuaCode()); | |
| 158 | + stmt.BindInt(2, static_cast<int>(db::ShaderCodeType::Lua)); | |
| 159 | + stmt.BindText(3, GetDefaultLuaCode()); | |
| 160 | + stmt.BindText(4, "default.lua"); | |
| 206 | 161 | |
| 207 | 162 | assert(stmt.Step() == SQLITE_DONE && "最初のシェーダーを入れ込みに失敗。\n"); |
| 208 | 163 | } |
| @@ -43,8 +43,7 @@ | ||
| 43 | 43 | vector<ShaderData> out; |
| 44 | 44 | |
| 45 | 45 | sqlite::Stmt stmt(db.GetDB()); |
| 46 | - string sql = "SELECT id, name, description FROM shaders ORDER BY updated_at DESC;"; | |
| 47 | - stmt.Prepare(sql); | |
| 46 | + stmt.Prepare("SELECT id, name, description FROM shaders ORDER BY updated_at DESC;"); | |
| 48 | 47 | |
| 49 | 48 | while (stmt.Step() == SQLITE_ROW) { |
| 50 | 49 | ShaderData data; |
| @@ -54,51 +53,49 @@ | ||
| 54 | 53 | |
| 55 | 54 | { |
| 56 | 55 | sqlite::Stmt codeStmt(db.GetDB()); |
| 57 | - string codeSql = "SELECT id, code FROM vertex_shader WHERE shader_id = ? LIMIT 1;"; | |
| 58 | - codeStmt.Prepare(codeSql); | |
| 56 | + codeStmt.Prepare("SELECT id, code_type, code, filename FROM shader_code WHERE shader_id = ?;"); | |
| 59 | 57 | codeStmt.BindInt(1, data.id); |
| 60 | - if (codeStmt.Step() == SQLITE_ROW) { | |
| 61 | - data.vertexShader.id = codeStmt.ColumnInt(0); | |
| 62 | - data.vertexShader.code = codeStmt.ColumnText(1); | |
| 63 | - } | |
| 64 | - } | |
| 65 | 58 | |
| 66 | - { | |
| 59 | + while (codeStmt.Step() == SQLITE_ROW) { | |
| 60 | + u32 id = codeStmt.ColumnInt(0); | |
| 61 | + ShaderCodeType type = static_cast<ShaderCodeType>(codeStmt.ColumnInt(1)); | |
| 62 | + string code = codeStmt.ColumnText(2); | |
| 63 | + string filename = codeStmt.ColumnText(3); | |
| 67 | 64 | |
| 68 | - sqlite::Stmt codeStmt(db.GetDB()); | |
| 69 | - string codeSql = "SELECT id, code FROM fragment_shader WHERE shader_id = ? LIMIT 1;"; | |
| 70 | - codeStmt.Prepare(codeSql); | |
| 71 | - codeStmt.BindInt(1, data.id); | |
| 72 | - if (codeStmt.Step() == SQLITE_ROW) { | |
| 73 | - data.fragmentShader.id = codeStmt.ColumnInt(0); | |
| 74 | - data.fragmentShader.code = codeStmt.ColumnText(1); | |
| 65 | + if (type == ShaderCodeType::GlslVertex) { | |
| 66 | + data.vertexShader.id = id; | |
| 67 | + data.vertexShader.type = type; | |
| 68 | + data.vertexShader.code = code; | |
| 69 | + data.vertexShader.filename = filename; | |
| 70 | + } else if (type == ShaderCodeType::GlslFragment) { | |
| 71 | + data.fragmentShader.id = id; | |
| 72 | + data.fragmentShader.type = type; | |
| 73 | + data.fragmentShader.code = code; | |
| 74 | + data.fragmentShader.filename = filename; | |
| 75 | + } else if (type == ShaderCodeType::Lua) { | |
| 76 | + data.luaCode.id = id; | |
| 77 | + data.luaCode.type = type; | |
| 78 | + data.luaCode.code = code; | |
| 79 | + data.luaCode.filename = filename; | |
| 80 | + } else { | |
| 81 | + throw std::exception("未対応コード類。"); | |
| 82 | + } | |
| 75 | 83 | } |
| 76 | 84 | } |
| 77 | 85 | |
| 78 | - { | |
| 79 | - sqlite::Stmt codeStmt(db.GetDB()); | |
| 80 | - string codeSql = "SELECT id, code FROM lua_code WHERE shader_id = ? LIMIT 1;"; | |
| 81 | - codeStmt.Prepare(codeSql); | |
| 82 | - codeStmt.BindInt(1, data.id); | |
| 83 | - if (codeStmt.Step() == SQLITE_ROW) { | |
| 84 | - data.luaCode.id = codeStmt.ColumnInt(0); | |
| 85 | - data.luaCode.code = codeStmt.ColumnText(1); | |
| 86 | - } | |
| 87 | - } | |
| 88 | - | |
| 89 | 86 | out.push_back(std::move(data)); |
| 90 | 87 | } |
| 91 | 88 | |
| 92 | 89 | return out; |
| 93 | 90 | } |
| 94 | 91 | |
| 95 | - void SaveCode(sqlite::Instance &db, u32 id, const string &code, const string &table) { | |
| 92 | + void SaveCode(sqlite::Instance &db, const CodeData &data) { | |
| 96 | 93 | sqlite::Stmt stmt(db.GetDB()); |
| 97 | - string sql = "UPDATE " + table + " SET code = ? WHERE id = ?;"; | |
| 98 | - stmt.Prepare(sql); | |
| 94 | + stmt.Prepare("UPDATE shader_code SET code = ?, filename = ? WHERE id = ?;"); | |
| 99 | 95 | |
| 100 | - stmt.BindText(1, code); | |
| 101 | - stmt.BindInt(2, id); | |
| 96 | + stmt.BindText(1, data.code); | |
| 97 | + stmt.BindText(2, data.filename); | |
| 98 | + stmt.BindInt(3, data.id); | |
| 102 | 99 | |
| 103 | 100 | assert(stmt.Step() == SQLITE_DONE && "コードの保存に失敗。\n"); |
| 104 | 101 | } |