| @@ -1,6 +1,6 @@ | |||||
| [vert.glsl] | [vert.glsl] | ||||
| #version 130 | |||||
| #version 120 | |||||
| attribute vec3 in_Position; | attribute vec3 in_Position; | ||||
| attribute vec2 in_TexCoord; | attribute vec2 in_TexCoord; | ||||
| @@ -19,22 +19,22 @@ void main() | |||||
| [frag.glsl] | [frag.glsl] | ||||
| #version 130 | |||||
| #version 120 | |||||
| #if defined GL_ES | #if defined GL_ES | ||||
| precision mediump float; | precision mediump float; | ||||
| #endif | #endif | ||||
| uniform sampler1D u_palette; | |||||
| uniform sampler2D u_texture; | uniform sampler2D u_texture; | ||||
| uniform sampler2D u_palette; | |||||
| uniform vec2 u_texsize; | uniform vec2 u_texsize; | ||||
| varying vec2 pass_TexCoord; | varying vec2 pass_TexCoord; | ||||
| void main() | void main() | ||||
| { | { | ||||
| vec4 pal_pos = texture2D(u_texture, pass_TexCoord); | |||||
| vec4 col = texture2D(u_palette, pal_pos.x); | |||||
| if (col.a == 0.0) | |||||
| vec4 pal = texture2D(u_texture, pass_TexCoord); | |||||
| vec4 col = texture2D(u_palette, vec2(pal.x, 0.f)); | |||||
| if (pal.x == 0.0) | |||||
| discard; | discard; | ||||
| gl_FragColor = col; | gl_FragColor = col; | ||||
| } | } | ||||
| @@ -203,10 +203,10 @@ bool ZedImageData::Open(char const *path) | |||||
| //Store size type | //Store size type | ||||
| { | { | ||||
| ivec2 size_16 = size; | ivec2 size_16 = size; | ||||
| int32_t s_16 = 16; | |||||
| int32_t s_16 = 8; | |||||
| while (1) | while (1) | ||||
| { | { | ||||
| if (size_16.x <= s_16) | |||||
| if (size_16.x < s_16) | |||||
| { | { | ||||
| size_16.x = s_16; | size_16.x = s_16; | ||||
| break; | break; | ||||
| @@ -216,7 +216,7 @@ bool ZedImageData::Open(char const *path) | |||||
| s_16 = 8; | s_16 = 8; | ||||
| while (1) | while (1) | ||||
| { | { | ||||
| if (size_16.y <= s_16) | |||||
| if (size_16.y < s_16) | |||||
| { | { | ||||
| size_16.y = s_16; | size_16.y = s_16; | ||||
| break; | break; | ||||
| @@ -67,11 +67,11 @@ static inline void DebugAbort() | |||||
| 2, 1, TOO_FEW_ARGUMENTS)) | 2, 1, TOO_FEW_ARGUMENTS)) | ||||
| #define LOL_COUNT_TO_12(...) \ | #define LOL_COUNT_TO_12(...) \ | ||||
| LOL_EVAL(LOL_GET_63RD(__VA_ARGS__, 10,10,10,10,10,10,10,10,10,10,\ | |||||
| 10,10,10,10,10,10,10,10,10,10,\ | |||||
| 10,10,10,10,10,10,10,10,10,10,\ | |||||
| 10,10,10,10,10,10,10,10,10,10,\ | |||||
| 10,10,10,10,10,10,10,10,10,10,\ | |||||
| LOL_EVAL(LOL_GET_63RD(__VA_ARGS__, 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,12,12,12,12,12,12,12,12,12,\ | |||||
| 12,11,10,9, 8, 7, 6, 5, 4, 3, \ | 12,11,10,9, 8, 7, 6, 5, 4, 3, \ | ||||
| 2, 1, TOO_FEW_ARGUMENTS)) | 2, 1, TOO_FEW_ARGUMENTS)) | ||||
| @@ -28,6 +28,37 @@ typedef Real<16> real; | |||||
| /* The “half” type used for 16-bit floating point numbers. */ | /* The “half” type used for 16-bit floating point numbers. */ | ||||
| class half; | class half; | ||||
| #define DEFINE_ENUM(NEW_ENUM) struct NEW_ENUM { | |||||
| #define START_VALUE enum Value { | |||||
| #define ADD_VALUE(NEW_VALUE) E##NEW_VALUE, | |||||
| #define END_VALUE MAX } m_value; | |||||
| #define START_TEXT \ | |||||
| inline String C() \ | |||||
| { \ | |||||
| static String text[] = { | |||||
| #define ADD_TEXT(NEW_TEXT) #NEW_TEXT, | |||||
| #define END_TEXT \ | |||||
| }; \ | |||||
| if (m_value >= MAX) \ | |||||
| return "INVALID"; \ | |||||
| return text[m_value]; \ | |||||
| }; \ | |||||
| #define END_ENUM(NEW_ENUM) \ | |||||
| inline NEW_ENUM() : m_value(MAX) {} \ | |||||
| inline NEW_ENUM(Value v) : m_value(v) {} \ | |||||
| inline NEW_ENUM(int v) : m_value((Value)v) {} \ | |||||
| inline NEW_ENUM(float v) : m_value((Value)(int)v) {} \ | |||||
| bool operator==(const NEW_ENUM& v) { return m_value == v.m_value; } \ | |||||
| bool operator==(const int& v) { return m_value == NEW_ENUM(v); } \ | |||||
| bool operator==(const float& v) { return m_value == NEW_ENUM(v); } \ | |||||
| inline operator Value() { return m_value; } \ | |||||
| }; \ | |||||
| bool operator== (int e1, NEW_ENUM& e2) { return (e2 == e1); } \ | |||||
| bool operator== (float e1, NEW_ENUM& e2){ return (e2 == e1); } | |||||
| } /* namespace lol */ | } /* namespace lol */ | ||||
| #endif // __LOL_BASE_TYPES_H__ | #endif // __LOL_BASE_TYPES_H__ | ||||
| @@ -113,9 +113,10 @@ public: | |||||
| bool Start(); | bool Start(); | ||||
| //Stop the threads | //Stop the threads | ||||
| bool Stop(); | bool Stop(); | ||||
| protected: | |||||
| //Work stuff | //Work stuff | ||||
| bool AddWork(ThreadJob* job); | bool AddWork(ThreadJob* job); | ||||
| protected: | |||||
| //Fetch Results | |||||
| bool FetchResult(Array<ThreadJob*>& results); | bool FetchResult(Array<ThreadJob*>& results); | ||||
| //Base thread work function | //Base thread work function | ||||
| static void *BaseThreadWork(void* data); | static void *BaseThreadWork(void* data); | ||||
| @@ -141,6 +142,8 @@ public: | |||||
| char const *GetName() { return "<GenericThreadManager>"; } | char const *GetName() { return "<GenericThreadManager>"; } | ||||
| //Work stuff | |||||
| bool AddJob(ThreadJob* job) { return AddWork(job); } | |||||
| bool GetWorkResult(Array<ThreadJob*>& results) | bool GetWorkResult(Array<ThreadJob*>& results) | ||||
| { | { | ||||
| results += m_job_result; | results += m_job_result; | ||||
| @@ -404,6 +404,7 @@ | |||||
| <LolFxCompile Include="gpu\defaultmaterial.lolfx" /> | <LolFxCompile Include="gpu\defaultmaterial.lolfx" /> | ||||
| <LolFxCompile Include="gpu\emptymaterial.lolfx" /> | <LolFxCompile Include="gpu\emptymaterial.lolfx" /> | ||||
| <LolFxCompile Include="gpu\line.lolfx" /> | <LolFxCompile Include="gpu\line.lolfx" /> | ||||
| <LolFxCompile Include="gpu\palette.lolfx" /> | |||||
| <LolFxCompile Include="gpu\testmaterial.lolfx" /> | <LolFxCompile Include="gpu\testmaterial.lolfx" /> | ||||
| <LolFxCompile Include="gpu\tile.lolfx" /> | <LolFxCompile Include="gpu\tile.lolfx" /> | ||||
| <LolFxCompile Include="gradient.lolfx" /> | <LolFxCompile Include="gradient.lolfx" /> | ||||
| @@ -732,6 +732,9 @@ | |||||
| <LolFxCompile Include="easymesh\shinyflat.lolfx"> | <LolFxCompile Include="easymesh\shinyflat.lolfx"> | ||||
| <Filter>easymesh</Filter> | <Filter>easymesh</Filter> | ||||
| </LolFxCompile> | </LolFxCompile> | ||||
| <LolFxCompile Include="gpu\palette.lolfx"> | |||||
| <Filter>...</Filter> | |||||
| </LolFxCompile> | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <None Include="easymesh\easymesh-parser.y"> | <None Include="easymesh\easymesh-parser.y"> | ||||
| @@ -23,6 +23,7 @@ | |||||
| #include "lolgl.h" | #include "lolgl.h" | ||||
| LOLFX_RESOURCE_DECLARE(tile); | LOLFX_RESOURCE_DECLARE(tile); | ||||
| LOLFX_RESOURCE_DECLARE(palette); | |||||
| LOLFX_RESOURCE_DECLARE(line); | LOLFX_RESOURCE_DECLARE(line); | ||||
| namespace lol | namespace lol | ||||
| @@ -72,9 +73,11 @@ private: | |||||
| int m_tile_cam; | int m_tile_cam; | ||||
| Array<Tile> m_tiles; | Array<Tile> m_tiles; | ||||
| Array<Tile> m_palettes; | |||||
| Array<Light *> m_lights; | Array<Light *> m_lights; | ||||
| Shader *m_tile_shader; | Shader *m_tile_shader; | ||||
| Shader *m_palette_shader; | |||||
| VertexDeclaration *m_tile_vdecl; | VertexDeclaration *m_tile_vdecl; | ||||
| Array<VertexBuffer *> m_tile_bufs; | Array<VertexBuffer *> m_tile_bufs; | ||||
| @@ -97,6 +100,7 @@ Scene::Scene(ivec2 size) | |||||
| data->m_tile_cam = -1; | data->m_tile_cam = -1; | ||||
| data->m_tile_shader = 0; | data->m_tile_shader = 0; | ||||
| data->m_palette_shader = 0; | |||||
| data->m_tile_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position), | data->m_tile_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position), | ||||
| VertexStream<vec2>(VertexUsage::TexCoord)); | VertexStream<vec2>(VertexUsage::TexCoord)); | ||||
| @@ -194,7 +198,10 @@ void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale, float | |||||
| t.scale = scale; | t.scale = scale; | ||||
| t.angle = angle; | t.angle = angle; | ||||
| data->m_tiles.Push(t); | |||||
| if (tileset->GetPalette()) | |||||
| data->m_palettes.Push(t); | |||||
| else | |||||
| data->m_tiles.Push(t); | |||||
| } | } | ||||
| void Scene::SetLineTime(float new_time) { data->m_new_line_time = new_time; } | void Scene::SetLineTime(float new_time) { data->m_new_line_time = new_time; } | ||||
| @@ -270,7 +277,7 @@ void Scene::RenderTiles() // XXX: rename to Blit() | |||||
| RenderContext rc; | RenderContext rc; | ||||
| /* Early test if nothing needs to be rendered */ | /* Early test if nothing needs to be rendered */ | ||||
| if (!data->m_tiles.Count()) | |||||
| if (!data->m_tiles.Count() && !data->m_palettes.Count()) | |||||
| return; | return; | ||||
| rc.SetDepthFunc(DepthFunc::LessOrEqual); | rc.SetDepthFunc(DepthFunc::LessOrEqual); | ||||
| @@ -283,71 +290,96 @@ void Scene::RenderTiles() // XXX: rename to Blit() | |||||
| #endif | #endif | ||||
| if (!data->m_tile_shader) | if (!data->m_tile_shader) | ||||
| data->m_tile_shader = Shader::Create(LOLFX_RESOURCE_NAME(tile)); | data->m_tile_shader = Shader::Create(LOLFX_RESOURCE_NAME(tile)); | ||||
| if (!data->m_palette_shader) | |||||
| data->m_palette_shader = Shader::Create(LOLFX_RESOURCE_NAME(palette)); | |||||
| ShaderUniform uni_mat, uni_tex, uni_texsize; | |||||
| ShaderAttrib attr_pos, attr_tex; | |||||
| attr_pos = data->m_tile_shader->GetAttribLocation(VertexUsage::Position, 0); | |||||
| attr_tex = data->m_tile_shader->GetAttribLocation(VertexUsage::TexCoord, 0); | |||||
| data->m_tile_shader->Bind(); | |||||
| for (int p = 0; p < 2; p++) | |||||
| { | |||||
| Shader *shader = (p == 0) ? data->m_tile_shader : data->m_palette_shader; | |||||
| Array<Tile>& tiles = (p == 0) ? data->m_tiles : data->m_palettes; | |||||
| uni_mat = data->m_tile_shader->GetUniformLocation("u_projection"); | |||||
| data->m_tile_shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetProjection()); | |||||
| uni_mat = data->m_tile_shader->GetUniformLocation("u_view"); | |||||
| data->m_tile_shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetView()); | |||||
| uni_mat = data->m_tile_shader->GetUniformLocation("u_model"); | |||||
| data->m_tile_shader->SetUniform(uni_mat, mat4(1.f)); | |||||
| if (tiles.Count() == 0) | |||||
| continue; | |||||
| uni_tex = data->m_tile_shader->GetUniformLocation("u_texture"); | |||||
| data->m_tile_shader->SetUniform(uni_tex, 0); | |||||
| uni_texsize = data->m_tile_shader->GetUniformLocation("u_texsize"); | |||||
| ShaderUniform uni_mat, uni_tex, uni_pal, uni_texsize; | |||||
| ShaderAttrib attr_pos, attr_tex; | |||||
| attr_pos = shader->GetAttribLocation(VertexUsage::Position, 0); | |||||
| attr_tex = shader->GetAttribLocation(VertexUsage::TexCoord, 0); | |||||
| for (int buf = 0, i = 0, n; i < data->m_tiles.Count(); i = n, buf += 2) | |||||
| { | |||||
| /* Count how many quads will be needed */ | |||||
| for (n = i + 1; n < data->m_tiles.Count(); n++) | |||||
| if (data->m_tiles[i].tileset != data->m_tiles[n].tileset) | |||||
| break; | |||||
| shader->Bind(); | |||||
| /* Create a vertex array object */ | |||||
| VertexBuffer *vb1 = new VertexBuffer(6 * (n - i) * sizeof(vec3)); | |||||
| vec3 *vertex = (vec3 *)vb1->Lock(0, 0); | |||||
| VertexBuffer *vb2 = new VertexBuffer(6 * (n - i) * sizeof(vec2)); | |||||
| vec2 *texture = (vec2 *)vb2->Lock(0, 0); | |||||
| uni_mat = shader->GetUniformLocation("u_projection"); | |||||
| shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetProjection()); | |||||
| uni_mat = shader->GetUniformLocation("u_view"); | |||||
| shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetView()); | |||||
| uni_mat = shader->GetUniformLocation("u_model"); | |||||
| shader->SetUniform(uni_mat, mat4(1.f)); | |||||
| data->m_tile_bufs.Push(vb1); | |||||
| data->m_tile_bufs.Push(vb2); | |||||
| uni_tex = shader->GetUniformLocation("u_texture"); | |||||
| uni_pal = data->m_palette_shader->GetUniformLocation("u_palette"); | |||||
| uni_texsize = shader->GetUniformLocation("u_texsize"); | |||||
| for (int j = i; j < n; j++) | |||||
| for (int buf = 0, i = 0, n; i < tiles.Count(); i = n, buf += 2) | |||||
| { | { | ||||
| data->m_tiles[i].tileset->BlitTile(data->m_tiles[j].id, | |||||
| data->m_tiles[j].pos, data->m_tiles[j].o, | |||||
| data->m_tiles[j].scale, data->m_tiles[j].angle, | |||||
| vertex + 6 * (j - i), texture + 6 * (j - i)); | |||||
| /* Count how many quads will be needed */ | |||||
| for (n = i + 1; n < tiles.Count(); n++) | |||||
| if (tiles[i].tileset != tiles[n].tileset) | |||||
| break; | |||||
| /* Create a vertex array object */ | |||||
| VertexBuffer *vb1 = new VertexBuffer(6 * (n - i) * sizeof(vec3)); | |||||
| vec3 *vertex = (vec3 *)vb1->Lock(0, 0); | |||||
| VertexBuffer *vb2 = new VertexBuffer(6 * (n - i) * sizeof(vec2)); | |||||
| vec2 *texture = (vec2 *)vb2->Lock(0, 0); | |||||
| data->m_tile_bufs.Push(vb1); | |||||
| data->m_tile_bufs.Push(vb2); | |||||
| for (int j = i; j < n; j++) | |||||
| { | |||||
| tiles[i].tileset->BlitTile(tiles[j].id, | |||||
| tiles[j].pos, tiles[j].o, | |||||
| tiles[j].scale, tiles[j].angle, | |||||
| vertex + 6 * (j - i), texture + 6 * (j - i)); | |||||
| } | |||||
| vb1->Unlock(); | |||||
| vb2->Unlock(); | |||||
| /* Bind texture */ | |||||
| if (tiles[i].tileset->GetPalette()) | |||||
| { | |||||
| if (tiles[i].tileset->GetTexture()) | |||||
| shader->SetUniform(uni_tex, tiles[i].tileset->GetTexture()->GetTextureUniform(), 0); | |||||
| if (tiles[i].tileset->GetPalette()->GetTexture()) | |||||
| shader->SetUniform(uni_pal, tiles[i].tileset->GetPalette()->GetTexture()->GetTextureUniform(), 1); | |||||
| } | |||||
| else | |||||
| { | |||||
| shader->SetUniform(uni_tex, 0); | |||||
| if (tiles[i].tileset->GetTexture()) | |||||
| shader->SetUniform(uni_tex, tiles[i].tileset->GetTexture()->GetTextureUniform(), 0); | |||||
| tiles[i].tileset->Bind(); | |||||
| } | |||||
| shader->SetUniform(uni_texsize, | |||||
| (vec2)tiles[i].tileset->GetTextureSize()); | |||||
| /* Bind vertex and texture coordinate buffers */ | |||||
| data->m_tile_vdecl->Bind(); | |||||
| data->m_tile_vdecl->SetStream(vb1, attr_pos); | |||||
| data->m_tile_vdecl->SetStream(vb2, attr_tex); | |||||
| /* Draw arrays */ | |||||
| data->m_tile_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6); | |||||
| data->m_tile_vdecl->Unbind(); | |||||
| tiles[i].tileset->Unbind(); | |||||
| } | } | ||||
| vb1->Unlock(); | |||||
| vb2->Unlock(); | |||||
| tiles.Empty(); | |||||
| /* Bind texture */ | |||||
| data->m_tiles[i].tileset->Bind(); | |||||
| data->m_tile_shader->SetUniform(uni_texsize, | |||||
| (vec2)data->m_tiles[i].tileset->GetTextureSize()); | |||||
| /* Bind vertex and texture coordinate buffers */ | |||||
| data->m_tile_vdecl->Bind(); | |||||
| data->m_tile_vdecl->SetStream(vb1, attr_pos); | |||||
| data->m_tile_vdecl->SetStream(vb2, attr_tex); | |||||
| /* Draw arrays */ | |||||
| data->m_tile_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6); | |||||
| data->m_tile_vdecl->Unbind(); | |||||
| data->m_tiles[i].tileset->Unbind(); | |||||
| shader->Unbind(); | |||||
| } | } | ||||
| data->m_tiles.Empty(); | |||||
| data->m_tile_shader->Unbind(); | |||||
| #if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
| /* TODO */ | /* TODO */ | ||||
| @@ -80,7 +80,9 @@ class FileData | |||||
| #elif HAVE_STDIO_H | #elif HAVE_STDIO_H | ||||
| /* FIXME: no modes, no error checking, no nothing */ | /* FIXME: no modes, no error checking, no nothing */ | ||||
| stat(file.C(), &m_stat); | stat(file.C(), &m_stat); | ||||
| m_fd = fopen(file.C(), (!force_binary) ? ("r") : ("rb")); | |||||
| String access = (mode == FileAccess::Write) ? ("w") : ("r"); | |||||
| if (force_binary) access += "b"; | |||||
| m_fd = fopen(file.C(), access.C()); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -293,13 +295,13 @@ File::~File() | |||||
| //-- | //-- | ||||
| void File::Open(StreamType stream) | void File::Open(StreamType stream) | ||||
| { | { | ||||
| return m_data->Open(stream); | |||||
| m_data->Open(stream); | |||||
| } | } | ||||
| //-- | //-- | ||||
| void File::Open(String const &file, FileAccess mode, bool force_binary) | void File::Open(String const &file, FileAccess mode, bool force_binary) | ||||
| { | { | ||||
| return m_data->Open(file, mode, force_binary); | |||||
| m_data->Open(file, mode, force_binary); | |||||
| } | } | ||||
| //-- | //-- | ||||
| @@ -101,6 +101,8 @@ void *BaseThreadManager::BaseThreadWork(void* data) | |||||
| void BaseThreadManager::TickGame(float seconds) | void BaseThreadManager::TickGame(float seconds) | ||||
| { | { | ||||
| Entity::TickGame(seconds); | |||||
| //Start if needed | //Start if needed | ||||
| Start(); | Start(); | ||||
| @@ -147,6 +147,7 @@ void TileSet::Init(char const *path, Image* image) | |||||
| { | { | ||||
| m_data->m_name = String("<tileset> ") + path; | m_data->m_name = String("<tileset> ") + path; | ||||
| m_palette = nullptr; | |||||
| m_data->m_texture = 0; | m_data->m_texture = 0; | ||||
| m_data->m_image = image; | m_data->m_image = image; | ||||
| m_data->m_image_size = m_data->m_image->GetSize(); | m_data->m_image_size = m_data->m_image->GetSize(); | ||||
| @@ -258,6 +259,31 @@ Texture const * TileSet::GetTexture() const | |||||
| return m_data->m_texture; | return m_data->m_texture; | ||||
| } | } | ||||
| Image * TileSet::GetImage() | |||||
| { | |||||
| return m_data->m_image; | |||||
| } | |||||
| Image const * TileSet::GetImage() const | |||||
| { | |||||
| return m_data->m_image; | |||||
| } | |||||
| void TileSet::SetPalette(TileSet* palette) | |||||
| { | |||||
| m_palette = palette; | |||||
| } | |||||
| TileSet* TileSet::GetPalette() | |||||
| { | |||||
| return m_palette; | |||||
| } | |||||
| TileSet const* TileSet::GetPalette() const | |||||
| { | |||||
| return m_palette; | |||||
| } | |||||
| void TileSet::Bind() | void TileSet::Bind() | ||||
| { | { | ||||
| if (!m_data->m_image && m_data->m_texture) | if (!m_data->m_image && m_data->m_texture) | ||||
| @@ -53,6 +53,11 @@ public: | |||||
| Texture * GetTexture(); | Texture * GetTexture(); | ||||
| Texture const * GetTexture() const; | Texture const * GetTexture() const; | ||||
| Image * GetImage(); | |||||
| Image const * GetImage() const; | |||||
| void SetPalette(TileSet* palette); | |||||
| TileSet* GetPalette(); | |||||
| TileSet const * GetPalette() const; | |||||
| ivec2 GetTextureSize() const; | ivec2 GetTextureSize() const; | ||||
| void Bind(); | void Bind(); | ||||
| void Unbind(); | void Unbind(); | ||||
| @@ -64,6 +69,7 @@ private: | |||||
| void Init(char const *path, Image* image); | void Init(char const *path, Image* image); | ||||
| TileSetData* m_data; | TileSetData* m_data; | ||||
| TileSet* m_palette; | |||||
| }; | }; | ||||
| } /* namespace lol */ | } /* namespace lol */ | ||||