| @@ -82,6 +82,7 @@ liblolcore_sources = \ | |||||
| generated/easymesh-scanner.cpp \ | generated/easymesh-scanner.cpp \ | ||||
| \ | \ | ||||
| base/assert.cpp base/hash.cpp base/log.cpp base/string.cpp \ | base/assert.cpp base/hash.cpp base/log.cpp base/string.cpp \ | ||||
| base/enum.cpp \ | |||||
| \ | \ | ||||
| math/vector.cpp math/real.cpp math/half.cpp math/trig.cpp \ | math/vector.cpp math/real.cpp math/half.cpp math/trig.cpp \ | ||||
| math/constants.cpp math/geometry.cpp \ | math/constants.cpp math/geometry.cpp \ | ||||
| @@ -107,7 +108,7 @@ liblolcore_sources = \ | |||||
| mesh/primitive.cpp mesh/primitive.h \ | mesh/primitive.cpp mesh/primitive.h \ | ||||
| \ | \ | ||||
| sys/init.cpp sys/timer.cpp sys/file.cpp \ | sys/init.cpp sys/timer.cpp sys/file.cpp \ | ||||
| sys/threadbase.h \ | |||||
| sys/thread.cpp sys/threadbase.h \ | |||||
| \ | \ | ||||
| image/image.cpp image/image-private.h \ | image/image.cpp image/image-private.h \ | ||||
| image/codec/gdiplus-image.cpp \ | image/codec/gdiplus-image.cpp \ | ||||
| @@ -0,0 +1,65 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // This program is free software; you can redistribute it and/or | |||||
| // modify it under the terms of the Do What The Fuck You Want To | |||||
| // Public License, Version 2, as published by Sam Hocevar. See | |||||
| // http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #if defined HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include "core.h" | |||||
| namespace lol | |||||
| { | |||||
| /* | |||||
| * Safe enum helpers | |||||
| */ | |||||
| Map<int64_t, String> BuildEnumMap(char const *str) | |||||
| { | |||||
| Map<int64_t, String> ret; | |||||
| char const *parser = str; | |||||
| int64_t next_value = 0; | |||||
| for (;;) | |||||
| { | |||||
| /* Find name */ | |||||
| while (*parser == ' ' || *parser == ',') | |||||
| ++parser; | |||||
| if (!*parser) | |||||
| break; | |||||
| /* Parse name */ | |||||
| char const *name = parser; | |||||
| while (*parser && *parser != ' ' && *parser != ',' && *parser != '=') | |||||
| ++parser; | |||||
| char const *name_end = parser; | |||||
| /* Find the value (if any) */ | |||||
| uint64_t current_value = next_value; | |||||
| while (*parser == ' ' || *parser == '=') | |||||
| ++parser; | |||||
| if (*parser && *parser != ',') | |||||
| { | |||||
| current_value = strtoll(parser, nullptr, 0); | |||||
| while (*parser && *parser != ' ' && *parser != ',') | |||||
| ++parser; | |||||
| } | |||||
| /* Store in the map */ | |||||
| ret[current_value] = String(name, (int)(name_end - name)); | |||||
| next_value = current_value + 1; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| } /* namespace lol */ | |||||
| @@ -26,42 +26,27 @@ namespace lol | |||||
| { | { | ||||
| /* A safe enum for MeshCSG operations. */ | /* A safe enum for MeshCSG operations. */ | ||||
| struct CSGUsageDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| Union, | |||||
| Substract, | |||||
| SubstractLoss, //will remove B from A, but not add inverted B | |||||
| And, | |||||
| Xor, | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<CSGUsageDef> CSGUsage; | |||||
| LOL_SAFE_ENUM(CSGUsage, | |||||
| Union, | |||||
| Substract, | |||||
| SubstractLoss, // will remove B from A, but not add inverted B | |||||
| And, | |||||
| Xor | |||||
| ); | |||||
| struct AxisDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| X, | |||||
| Y, | |||||
| Z, | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<AxisDef> Axis; | |||||
| LOL_SAFE_ENUM(Axis, | |||||
| X, | |||||
| Y, | |||||
| Z | |||||
| ); | |||||
| struct MeshTransformDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| Taper, | |||||
| Twist, | |||||
| Bend, | |||||
| Stretch, | |||||
| Shear, | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<MeshTransformDef> MeshTransform; | |||||
| LOL_SAFE_ENUM(MeshTransform, | |||||
| Taper, | |||||
| Twist, | |||||
| Bend, | |||||
| Stretch, | |||||
| Shear | |||||
| ); | |||||
| class EasyMesh | class EasyMesh | ||||
| { | { | ||||
| @@ -86,25 +86,21 @@ struct EasyMeshCmdType | |||||
| LOL_DECLARE_ENUM_METHODS(EasyMeshCmdType) | LOL_DECLARE_ENUM_METHODS(EasyMeshCmdType) | ||||
| }; | }; | ||||
| struct MeshTypeDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| Triangle, | |||||
| Quad, | |||||
| Box, | |||||
| Sphere, | |||||
| Capsule, | |||||
| Torus, | |||||
| Cylinder, | |||||
| Disc, | |||||
| Star, | |||||
| ExpandedStar, | |||||
| Cog, | |||||
| MAX, | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<MeshTypeDef> MeshType; | |||||
| LOL_SAFE_ENUM(MeshType, | |||||
| Triangle, | |||||
| Quad, | |||||
| Box, | |||||
| Sphere, | |||||
| Capsule, | |||||
| Torus, | |||||
| Cylinder, | |||||
| Disc, | |||||
| Star, | |||||
| ExpandedStar, | |||||
| Cog, | |||||
| MAX | |||||
| ); | |||||
| struct TexCoordBuildType | struct TexCoordBuildType | ||||
| { | { | ||||
| @@ -128,33 +124,24 @@ struct TexCoordBuildType | |||||
| LOL_DECLARE_ENUM_METHODS(TexCoordBuildType) | LOL_DECLARE_ENUM_METHODS(TexCoordBuildType) | ||||
| }; | }; | ||||
| struct MeshFaceTypeDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| BoxFront = 0, | |||||
| QuadDefault = 0, | |||||
| BoxLeft = 1, | |||||
| BoxBack = 2, | |||||
| BoxRight = 3, | |||||
| BoxTop = 4, | |||||
| BoxBottom = 5, | |||||
| Max, | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<MeshFaceTypeDef> MeshFaceType; | |||||
| struct TexCoordPosDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| BL, //BottomLeft | |||||
| BR, //BottomRight | |||||
| TL, //TopLeft | |||||
| TR, //TopRight | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<TexCoordPosDef> TexCoordPos; | |||||
| LOL_SAFE_ENUM(MeshFaceType, | |||||
| BoxFront = 0, | |||||
| QuadDefault = 0, | |||||
| BoxLeft = 1, | |||||
| BoxBack = 2, | |||||
| BoxRight = 3, | |||||
| BoxTop = 4, | |||||
| BoxBottom = 5, | |||||
| Max | |||||
| ); | |||||
| LOL_SAFE_ENUM(TexCoordPos, | |||||
| BL, // Bottom Left | |||||
| BR, // Bottom Right | |||||
| TL, // Top Left | |||||
| TR // Top Right | |||||
| ); | |||||
| class EasyMeshBuildData | class EasyMeshBuildData | ||||
| { | { | ||||
| @@ -227,14 +214,14 @@ public: | |||||
| mt = mt; | mt = mt; | ||||
| else if (mt == MeshType::Quad) | else if (mt == MeshType::Quad) | ||||
| { | { | ||||
| //There's nothin' else than QuadDefault | |||||
| // There's nothin' else than QuadDefault | |||||
| BL = vec2(0.f); | BL = vec2(0.f); | ||||
| TR = vec2(1.f); | TR = vec2(1.f); | ||||
| } | } | ||||
| else if (mt == MeshType::Box) | else if (mt == MeshType::Box) | ||||
| { | { | ||||
| vec2 data[][2] = | vec2 data[][2] = | ||||
| { //TexCoordBuildType::BoxDefault | |||||
| { // TexCoordBuildType::BoxDefault | |||||
| { vec2(0.f), vec2(.5f) }, | { vec2(0.f), vec2(.5f) }, | ||||
| { vec2(.5f, 0.f), vec2(1.f, .5f) }, | { vec2(.5f, 0.f), vec2(1.f, .5f) }, | ||||
| { vec2(0.f), vec2(.5f) }, | { vec2(0.f), vec2(.5f) }, | ||||
| @@ -242,8 +229,8 @@ public: | |||||
| { vec2(0.f, .5f), vec2(.5f, 1.f) }, | { vec2(0.f, .5f), vec2(.5f, 1.f) }, | ||||
| { vec2(.5f, .5f), vec2(1.f, 1.f) } | { vec2(.5f, .5f), vec2(1.f, 1.f) } | ||||
| }; | }; | ||||
| BL = data[face.ToScalar()][0]; //[tcbt] | |||||
| TR = data[face.ToScalar()][1]; //[tcbt] | |||||
| BL = data[face.ToScalar()][0]; // [tcbt] | |||||
| TR = data[face.ToScalar()][1]; // [tcbt] | |||||
| } | } | ||||
| else if (mt == MeshType::Sphere) | else if (mt == MeshType::Sphere) | ||||
| mt = mt; | mt = mt; | ||||
| @@ -276,7 +263,7 @@ public: | |||||
| return res * m_texcoord_scale + m_texcoord_offset2; | return res * m_texcoord_scale + m_texcoord_offset2; | ||||
| } | } | ||||
| //UV2 | |||||
| // UV2 | |||||
| void SetTexCoordBuildType2(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type2[mt.ToScalar()] = (1 << (tcbt + 1)) | (m_texcoord_build_type2[mt.ToScalar()] & 1); } | void SetTexCoordBuildType2(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type2[mt.ToScalar()] = (1 << (tcbt + 1)) | (m_texcoord_build_type2[mt.ToScalar()] & 1); } | ||||
| TexCoordBuildType GetTexCoordBuildType2(MeshType mt) | TexCoordBuildType GetTexCoordBuildType2(MeshType mt) | ||||
| { | { | ||||
| @@ -313,14 +300,14 @@ public: | |||||
| mt = mt; | mt = mt; | ||||
| else if (mt == MeshType::Quad) | else if (mt == MeshType::Quad) | ||||
| { | { | ||||
| //There's nothin' else than QuadDefault | |||||
| // There's nothin' else than QuadDefault | |||||
| BL = vec2(0.f); | BL = vec2(0.f); | ||||
| TR = vec2(1.f); | TR = vec2(1.f); | ||||
| } | } | ||||
| else if (mt == MeshType::Box) | else if (mt == MeshType::Box) | ||||
| { | { | ||||
| vec2 data[][2] = | vec2 data[][2] = | ||||
| { //TexCoordBuildType::BoxDefault | |||||
| { // TexCoordBuildType::BoxDefault | |||||
| { vec2(0.f), vec2(.5f) }, | { vec2(0.f), vec2(.5f) }, | ||||
| { vec2(.5f, 0.f), vec2(1.f, .5f) }, | { vec2(.5f, 0.f), vec2(1.f, .5f) }, | ||||
| { vec2(0.f), vec2(.5f) }, | { vec2(0.f), vec2(.5f) }, | ||||
| @@ -328,8 +315,8 @@ public: | |||||
| { vec2(0.f, .5f), vec2(.5f, 1.f) }, | { vec2(0.f, .5f), vec2(.5f, 1.f) }, | ||||
| { vec2(.5f, .5f), vec2(1.f, 1.f) } | { vec2(.5f, .5f), vec2(1.f, 1.f) } | ||||
| }; | }; | ||||
| BL = data[face.ToScalar()][0]; //[tcbt] | |||||
| TR = data[face.ToScalar()][1]; //[tcbt] | |||||
| BL = data[face.ToScalar()][0]; // [tcbt] | |||||
| TR = data[face.ToScalar()][1]; // [tcbt] | |||||
| } | } | ||||
| else if (mt == MeshType::Sphere) | else if (mt == MeshType::Sphere) | ||||
| mt = mt; | mt = mt; | ||||
| @@ -211,8 +211,7 @@ void GpuEasyMeshData::AddGpuData(GpuShaderData* gpudata, EasyMesh* src_mesh) | |||||
| BUILD_VFLAG(has_color, VertexUsage::Color, vflags); | BUILD_VFLAG(has_color, VertexUsage::Color, vflags); | ||||
| BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, vflags); | BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, vflags); | ||||
| BUILD_VFLAG_OR(has_texcoord, VertexUsage::TexCoordExt, vflags); | BUILD_VFLAG_OR(has_texcoord, VertexUsage::TexCoordExt, vflags); | ||||
| ASSERT(!vflags, "Vertex Usage setup is not implemented for %s, feel free to do so.", | |||||
| VertexUsage::GetNameList(vflags).C()); | |||||
| ASSERT(!vflags, "no Vertex Usage setup for 0x%04x", vflags); | |||||
| if (has_position) gpudata->AddAttribute(VertexUsage::Position, 0); | if (has_position) gpudata->AddAttribute(VertexUsage::Position, 0); | ||||
| if (has_normal) gpudata->AddAttribute(VertexUsage::Normal, 0); | if (has_normal) gpudata->AddAttribute(VertexUsage::Normal, 0); | ||||
| @@ -280,8 +279,7 @@ void GpuEasyMeshData::SetupVertexData(uint16_t vflags, EasyMesh* src_mesh) | |||||
| BUILD_VFLAG_COUNT(has_color, VertexUsage::Color, saveflags, flagnb); | BUILD_VFLAG_COUNT(has_color, VertexUsage::Color, saveflags, flagnb); | ||||
| BUILD_VFLAG_COUNT(has_texcoord, VertexUsage::TexCoord, saveflags, flagnb); | BUILD_VFLAG_COUNT(has_texcoord, VertexUsage::TexCoord, saveflags, flagnb); | ||||
| BUILD_VFLAG_COUNT(has_texcoordExt,VertexUsage::TexCoordExt, saveflags, flagnb); | BUILD_VFLAG_COUNT(has_texcoordExt,VertexUsage::TexCoordExt, saveflags, flagnb); | ||||
| ASSERT(!saveflags, "Vertex Declaration setup is not implemented for %s, feel free to do so.", | |||||
| VertexUsage::GetNameList(vflags).C()); | |||||
| ASSERT(!saveflags, "no Vertex Declaration setup for 0x%04x", vflags); | |||||
| if (flagnb == 5 && has_position && has_normal && has_color && has_texcoord && has_texcoordExt) | if (flagnb == 5 && has_position && has_normal && has_color && has_texcoord && has_texcoordExt) | ||||
| { | { | ||||
| @@ -369,8 +367,7 @@ void GpuEasyMeshData::SetupVertexData(uint16_t vflags, EasyMesh* src_mesh) | |||||
| COPY_VBO; | COPY_VBO; | ||||
| } | } | ||||
| else | else | ||||
| ASSERT(0, "Vertex Declaration combination is not implemented for %s, feel free to do so.", | |||||
| VertexUsage::GetNameList(vflags).C()); | |||||
| ASSERT(0, "no Vertex Declaration combination for 0x%04x", vflags); | |||||
| m_vdatas.Push(vflags, new_vdecl, new_vbo); | m_vdatas.Push(vflags, new_vdecl, new_vbo); | ||||
| } | } | ||||
| @@ -404,8 +401,7 @@ void GpuEasyMeshData::RenderMeshData(mat4 const &model, int render_mode) | |||||
| BUILD_VFLAG(has_color, VertexUsage::Color, vflags); | BUILD_VFLAG(has_color, VertexUsage::Color, vflags); | ||||
| BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, vflags); | BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, vflags); | ||||
| BUILD_VFLAG_OR(has_texcoord,VertexUsage::TexCoordExt, vflags); | BUILD_VFLAG_OR(has_texcoord,VertexUsage::TexCoordExt, vflags); | ||||
| ASSERT(!vflags, "Vertex Stream setup is not implemented for %s, feel free to do so.", | |||||
| VertexUsage::GetNameList(vflags).C()); | |||||
| ASSERT(!vflags, "no Vertex Stream setup for 0x%04x", vflags); | |||||
| int idx = 0; | int idx = 0; | ||||
| ShaderAttrib Attribs[4] = { lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib() }; | ShaderAttrib Attribs[4] = { lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib() }; | ||||
| @@ -21,18 +21,13 @@ | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| //Utility enum for renderers | |||||
| struct MeshRenderDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| NeedData, | |||||
| NeedConvert, | |||||
| CanRender, | |||||
| IgnoreRender, | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<MeshRenderDef> MeshRender; | |||||
| // Utility enum for renderers | |||||
| LOL_SAFE_ENUM(MeshRender, | |||||
| NeedData, | |||||
| NeedConvert, | |||||
| CanRender, | |||||
| IgnoreRender, | |||||
| ); | |||||
| //Vertex datas for easymesh vertex list. | //Vertex datas for easymesh vertex list. | ||||
| //TODO : <COORD, NORM, COLOR, UV> | //TODO : <COORD, NORM, COLOR, UV> | ||||
| @@ -391,7 +391,7 @@ Shader::Shader(char const *vert, char const *frag) | |||||
| String name(name_buffer); | String name(name_buffer); | ||||
| int index = -1; | int index = -1; | ||||
| VertexUsage usage = VertexUsage::MAX; | VertexUsage usage = VertexUsage::MAX; | ||||
| for (int j = 0; j < VertexUsage::MAX; ++j) | |||||
| for (int j = 0; j < (int)VertexUsage::MAX; ++j) | |||||
| { | { | ||||
| if (name.StartsWith(attribute_names[j])) | if (name.StartsWith(attribute_names[j])) | ||||
| { | { | ||||
| @@ -402,7 +402,7 @@ Shader::Shader(char const *vert, char const *frag) | |||||
| } | } | ||||
| } | } | ||||
| if ((int)usage == VertexUsage::MAX || index == -1) | |||||
| if (usage == VertexUsage::MAX || index == -1) | |||||
| { | { | ||||
| Log::Error("unable to parse attribute semantic from name: %s", | Log::Error("unable to parse attribute semantic from name: %s", | ||||
| name_buffer); | name_buffer); | ||||
| @@ -410,7 +410,7 @@ Shader::Shader(char const *vert, char const *frag) | |||||
| else | else | ||||
| { | { | ||||
| GLint location = glGetAttribLocation(data->prog_id, name_buffer); | GLint location = glGetAttribLocation(data->prog_id, name_buffer); | ||||
| uint64_t flags = (uint64_t)(uint16_t)usage << 16; | |||||
| uint64_t flags = (uint64_t)(uint16_t)usage.ToScalar() << 16; | |||||
| flags |= (uint64_t)(uint16_t)index; | flags |= (uint64_t)(uint16_t)index; | ||||
| // TODO: this is here just in case. Remove this once everything has been correctly tested | // TODO: this is here just in case. Remove this once everything has been correctly tested | ||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||
| @@ -440,7 +440,7 @@ int Shader::GetAttribCount() const | |||||
| ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const | ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const | ||||
| { | { | ||||
| ShaderAttrib ret; | ShaderAttrib ret; | ||||
| ret.m_flags = (uint64_t)(uint16_t)usage << 16; | |||||
| ret.m_flags = (uint64_t)(uint16_t)usage.ToScalar() << 16; | |||||
| ret.m_flags |= (uint64_t)(uint16_t)index; | ret.m_flags |= (uint64_t)(uint16_t)index; | ||||
| #if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
| #elif !defined __CELLOS_LV2__ | #elif !defined __CELLOS_LV2__ | ||||
| @@ -139,7 +139,7 @@ void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count) | |||||
| return; | return; | ||||
| #if defined _XBOX || defined USE_D3D9 | #if defined _XBOX || defined USE_D3D9 | ||||
| switch (type) | |||||
| switch (type.ToScalar()) | |||||
| { | { | ||||
| case MeshPrimitive::Triangles: | case MeshPrimitive::Triangles: | ||||
| if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_TRIANGLELIST, | if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_TRIANGLELIST, | ||||
| @@ -169,7 +169,7 @@ void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count) | |||||
| } | } | ||||
| #else | #else | ||||
| /* FIXME: this has nothing to do here! */ | /* FIXME: this has nothing to do here! */ | ||||
| switch (type) | |||||
| switch (type.ToScalar()) | |||||
| { | { | ||||
| case MeshPrimitive::Triangles: | case MeshPrimitive::Triangles: | ||||
| glDrawArrays(GL_TRIANGLES, skip, count); | glDrawArrays(GL_TRIANGLES, skip, count); | ||||
| @@ -198,7 +198,7 @@ void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase, | |||||
| return; | return; | ||||
| #if defined _XBOX || defined USE_D3D9 | #if defined _XBOX || defined USE_D3D9 | ||||
| switch (type) | |||||
| switch (type.ToScalar()) | |||||
| { | { | ||||
| case MeshPrimitive::Triangles: | case MeshPrimitive::Triangles: | ||||
| count = count / 3; | count = count / 3; | ||||
| @@ -231,7 +231,7 @@ void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase, | |||||
| } | } | ||||
| #else | #else | ||||
| /* FIXME: this has nothing to do here! */ | /* FIXME: this has nothing to do here! */ | ||||
| switch (type) | |||||
| switch (type.ToScalar()) | |||||
| { | { | ||||
| case MeshPrimitive::Triangles: | case MeshPrimitive::Triangles: | ||||
| /* FIXME: ignores most of the arguments! */ | /* FIXME: ignores most of the arguments! */ | ||||
| @@ -330,7 +330,7 @@ void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attribs[]) | |||||
| /* Only the first item is required to know which stream this | /* Only the first item is required to know which stream this | ||||
| * is about; the rest of the information is stored in the | * is about; the rest of the information is stored in the | ||||
| * vertex declaration already. */ | * vertex declaration already. */ | ||||
| uint32_t usage = (attr1.m_flags >> 16) & 0xffff; | |||||
| VertexUsage usage = VertexUsage((attr1.m_flags >> 16) & 0xffff); | |||||
| uint32_t index = attr1.m_flags & 0xffff; | uint32_t index = attr1.m_flags & 0xffff; | ||||
| /* Find the stream number */ | /* Find the stream number */ | ||||
| @@ -362,15 +362,15 @@ void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attribs[]) | |||||
| glBindBuffer(GL_ARRAY_BUFFER, vb->m_data->m_vbo); | glBindBuffer(GL_ARRAY_BUFFER, vb->m_data->m_vbo); | ||||
| for (int n = 0; n < 12 && attribs[n].m_flags != (uint64_t)0 - 1; n++) | for (int n = 0; n < 12 && attribs[n].m_flags != (uint64_t)0 - 1; n++) | ||||
| { | { | ||||
| uint32_t reg = attribs[n].m_flags >> 32; | |||||
| uint32_t usage = (attribs[n].m_flags >> 16) & 0xffff; | |||||
| VertexUsage usage = VertexUsage((attribs[n].m_flags >> 16) & 0xffff); | |||||
| uint32_t index = attribs[n].m_flags & 0xffff; | uint32_t index = attribs[n].m_flags & 0xffff; | ||||
| uint32_t reg = attribs[n].m_flags >> 32; | |||||
| # if !defined __CELLOS_LV2__ | # if !defined __CELLOS_LV2__ | ||||
| if (reg != 0xffffffff) | if (reg != 0xffffffff) | ||||
| glEnableVertexAttribArray((GLint)reg); | glEnableVertexAttribArray((GLint)reg); | ||||
| # else | # else | ||||
| switch (usage) | |||||
| switch (usage.ToScalar()) | |||||
| { | { | ||||
| case VertexUsage::Position: | case VertexUsage::Position: | ||||
| glEnableClientState(GL_VERTEX_ARRAY); | glEnableClientState(GL_VERTEX_ARRAY); | ||||
| @@ -627,26 +627,26 @@ VertexStreamBase VertexDeclaration::GetStream(int index) const | |||||
| switch (m_streams[i].stream_type) | switch (m_streams[i].stream_type) | ||||
| { | { | ||||
| #define LOL_TYPE(T) \ | |||||
| #define __T(T) \ | |||||
| case VertexStreamBase::Type##T: stream.AddStream<T>(n++, m_streams[i].usage); break; | case VertexStreamBase::Type##T: stream.AddStream<T>(n++, m_streams[i].usage); break; | ||||
| LOL_TYPE(void) | |||||
| LOL_TYPE(half) LOL_TYPE(f16vec2) LOL_TYPE(f16vec3) LOL_TYPE(f16vec4) | |||||
| LOL_TYPE(float) LOL_TYPE(vec2) LOL_TYPE(vec3) LOL_TYPE(vec4) | |||||
| LOL_TYPE(double) LOL_TYPE(dvec2) LOL_TYPE(dvec3) LOL_TYPE(dvec4) | |||||
| LOL_TYPE(int8_t) LOL_TYPE(i8vec2) LOL_TYPE(i8vec3) LOL_TYPE(i8vec4) | |||||
| LOL_TYPE(uint8_t) LOL_TYPE(u8vec2) LOL_TYPE(u8vec3) LOL_TYPE(u8vec4) | |||||
| LOL_TYPE(int16_t) LOL_TYPE(i16vec2) LOL_TYPE(i16vec3) LOL_TYPE(i16vec4) | |||||
| LOL_TYPE(uint16_t) LOL_TYPE(u16vec2) LOL_TYPE(u16vec3) LOL_TYPE(u16vec4) | |||||
| LOL_TYPE(int32_t) LOL_TYPE(ivec2) LOL_TYPE(ivec3) LOL_TYPE(ivec4) | |||||
| LOL_TYPE(uint32_t) LOL_TYPE(uvec2) LOL_TYPE(uvec3) LOL_TYPE(uvec4) | |||||
| #undef LOL_TYPE | |||||
| __T(void) | |||||
| __T(half) __T(f16vec2) __T(f16vec3) __T(f16vec4) | |||||
| __T(float) __T(vec2) __T(vec3) __T(vec4) | |||||
| __T(double) __T(dvec2) __T(dvec3) __T(dvec4) | |||||
| __T(int8_t) __T(i8vec2) __T(i8vec3) __T(i8vec4) | |||||
| __T(uint8_t) __T(u8vec2) __T(u8vec3) __T(u8vec4) | |||||
| __T(int16_t) __T(i16vec2) __T(i16vec3) __T(i16vec4) | |||||
| __T(uint16_t) __T(u16vec2) __T(u16vec3) __T(u16vec4) | |||||
| __T(int32_t) __T(ivec2) __T(ivec3) __T(ivec4) | |||||
| __T(uint32_t) __T(uvec2) __T(uvec3) __T(uvec4) | |||||
| #undef __T | |||||
| } | } | ||||
| ++count; | ++count; | ||||
| } | } | ||||
| while (count < 12) | while (count < 12) | ||||
| stream.AddStream<void>(count++, VertexStreamBase::Typevoid); | |||||
| stream.AddStream<void>(count++, VertexUsage::Position); | |||||
| return stream; | return stream; | ||||
| } | } | ||||
| @@ -12,13 +12,13 @@ | |||||
| #define __LOL_BASE_ALL_H__ | #define __LOL_BASE_ALL_H__ | ||||
| #include <lol/base/types.h> | #include <lol/base/types.h> | ||||
| #include <lol/base/enum.h> | |||||
| #include <lol/base/log.h> | #include <lol/base/log.h> | ||||
| #include <lol/base/assert.h> | #include <lol/base/assert.h> | ||||
| #include <lol/base/array.h> | #include <lol/base/array.h> | ||||
| #include <lol/base/string.h> | #include <lol/base/string.h> | ||||
| #include <lol/base/hash.h> | #include <lol/base/hash.h> | ||||
| #include <lol/base/map.h> | #include <lol/base/map.h> | ||||
| #include <lol/base/enum.h> | |||||
| #endif // __LOL_BASE_ALL_H__ | #endif // __LOL_BASE_ALL_H__ | ||||
| @@ -14,8 +14,10 @@ | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| template<typename DEF, typename T = typename DEF::Type> | |||||
| class SafeEnum : public DEF | |||||
| extern Map<int64_t, String> BuildEnumMap(char const *str); | |||||
| template<typename BASE, typename T = typename BASE::Type> | |||||
| class SafeEnum : public BASE | |||||
| { | { | ||||
| typedef T Type; | typedef T Type; | ||||
| Type m_value; | Type m_value; | ||||
| @@ -24,9 +26,27 @@ public: | |||||
| inline SafeEnum() : m_value() {} | inline SafeEnum() : m_value() {} | ||||
| inline SafeEnum(Type v) : m_value(v) {} | inline SafeEnum(Type v) : m_value(v) {} | ||||
| /* Allow conversion from/to int */ | |||||
| /* Allow conversion from int and to the underlying type */ | |||||
| inline explicit SafeEnum(int i) : m_value(T(i)) {} | |||||
| inline Type ToScalar() const { return m_value; } | inline Type ToScalar() const { return m_value; } | ||||
| /* Convert to string description */ | |||||
| inline class String ToString() const | |||||
| { | |||||
| /* FIXME: we all know this isn’t thread safe. But is it really | |||||
| * a big deal? */ | |||||
| static Map<int64_t, String> map; | |||||
| static bool ready = false; | |||||
| if (!ready) | |||||
| map = BuildEnumMap(BASE::GetDescription()); | |||||
| ready = true; | |||||
| if (map.HasKey((int64_t)m_value)) | |||||
| return map[(int64_t)m_value]; | |||||
| return "<invalid enum>"; | |||||
| } | |||||
| /* Safe comparisons between enums of the same type */ | /* Safe comparisons between enums of the same type */ | ||||
| friend bool operator == (SafeEnum const &a, SafeEnum const &b) | friend bool operator == (SafeEnum const &a, SafeEnum const &b) | ||||
| { | { | ||||
| @@ -54,6 +74,15 @@ public: | |||||
| } | } | ||||
| }; | }; | ||||
| #define LOL_SAFE_ENUM(name, ...) \ | |||||
| struct name ## Base \ | |||||
| { \ | |||||
| enum Type {__VA_ARGS__}; \ | |||||
| protected: \ | |||||
| static inline char const *GetDescription() { return #__VA_ARGS__; } \ | |||||
| }; \ | |||||
| typedef SafeEnum<name ## Base> name; | |||||
| //-- STRUCT TEMPLATE: | //-- STRUCT TEMPLATE: | ||||
| // enum E { | // enum E { | ||||
| // DEF_VALUE | // DEF_VALUE | ||||
| @@ -25,79 +25,24 @@ namespace lol | |||||
| * now there is only TexCoord and not TexCoord0 TexCoord1 etc. because | * now there is only TexCoord and not TexCoord0 TexCoord1 etc. because | ||||
| * we can always reorganise the vertex declaration for the indices to | * we can always reorganise the vertex declaration for the indices to | ||||
| * match. If the need arises these enums will be added. */ | * match. If the need arises these enums will be added. */ | ||||
| struct VertexUsage | |||||
| { | |||||
| DEF_VALUE | |||||
| ADD_VALUE(Position) | |||||
| ADD_VALUE(BlendWeight) | |||||
| ADD_VALUE(BlendIndices) | |||||
| ADD_VALUE(Normal) | |||||
| ADD_VALUE(PointSize) | |||||
| ADD_VALUE(TexCoord) | |||||
| ADD_VALUE(TexCoordExt) | |||||
| ADD_VALUE(Tangent) | |||||
| ADD_VALUE(Binormal) | |||||
| ADD_VALUE(TessFactor) | |||||
| ADD_VALUE(PositionT) | |||||
| ADD_VALUE(Color) | |||||
| ADD_VALUE(Fog) | |||||
| ADD_VALUE(Depth) | |||||
| ADD_VALUE(Sample) | |||||
| END_E_VALUE | |||||
| DEF_TEXT | |||||
| ADD_TEXT(Position) | |||||
| ADD_TEXT(BlendWeight) | |||||
| ADD_TEXT(BlendIndices) | |||||
| ADD_TEXT(Normal) | |||||
| ADD_TEXT(PointSize) | |||||
| ADD_TEXT(TexCoord) | |||||
| ADD_TEXT(TexCoordExt) | |||||
| ADD_TEXT(Tangent) | |||||
| ADD_TEXT(Binormal) | |||||
| ADD_TEXT(TessFactor) | |||||
| ADD_TEXT(PositionT) | |||||
| ADD_TEXT(Color) | |||||
| ADD_TEXT(Fog) | |||||
| ADD_TEXT(Depth) | |||||
| ADD_TEXT(Sample) | |||||
| END_TEXT | |||||
| LOL_DECLARE_ENUM_METHODS(VertexUsage); | |||||
| private: | |||||
| static String GetName(Value v, bool use_simple) | |||||
| { | |||||
| String tmp = String(""); | |||||
| if (!use_simple) tmp += "<"; | |||||
| tmp += VertexUsage(v).C(); | |||||
| if (!use_simple) tmp += ">"; | |||||
| return tmp; | |||||
| } | |||||
| public: | |||||
| static String GetName(Value v) | |||||
| { | |||||
| return GetName(v, false); | |||||
| } | |||||
| static String GetNameList(uint32_t v) | |||||
| { | |||||
| String tmp = String("<"); | |||||
| int nb = 0; | |||||
| for (int i = 0; i < MAX; ++i) | |||||
| { | |||||
| if (v & (1<<i)) | |||||
| { | |||||
| if (nb != 0) | |||||
| tmp += ", "; | |||||
| tmp += GetName(Value(i), true); | |||||
| ++nb; | |||||
| } | |||||
| } | |||||
| return tmp + ">"; | |||||
| } | |||||
| }; | |||||
| LOL_SAFE_ENUM(VertexUsage, | |||||
| Position, | |||||
| BlendWeight, | |||||
| BlendIndices, | |||||
| Normal, | |||||
| PointSize, | |||||
| TexCoord, | |||||
| TexCoordExt, | |||||
| Tangent, | |||||
| Binormal, | |||||
| TessFactor, | |||||
| PositionT, | |||||
| Color, | |||||
| Fog, | |||||
| Depth, | |||||
| Sample, | |||||
| MAX, | |||||
| ); | |||||
| struct ShaderUniform | struct ShaderUniform | ||||
| { | { | ||||
| @@ -152,7 +97,7 @@ public: | |||||
| static void Destroy(Shader *shader); | static void Destroy(Shader *shader); | ||||
| int GetAttribCount() const; | int GetAttribCount() const; | ||||
| ShaderAttrib GetAttribLocation(struct VertexUsage usage, int index) const; | |||||
| ShaderAttrib GetAttribLocation(VertexUsage usage, int index) const; | |||||
| ShaderUniform GetUniformLocation(char const *uni) const; | ShaderUniform GetUniformLocation(char const *uni) const; | ||||
| void SetUniform(ShaderUniform const &uni, int i); | void SetUniform(ShaderUniform const &uni, int i); | ||||
| @@ -40,21 +40,13 @@ private: | |||||
| /* A safe enum to indicate what kind of primitive to draw. Used in | /* A safe enum to indicate what kind of primitive to draw. Used in | ||||
| * VertexDeclaration::DrawElements() for instance. */ | * VertexDeclaration::DrawElements() for instance. */ | ||||
| struct MeshPrimitive | |||||
| { | |||||
| enum Value | |||||
| { | |||||
| Triangles, | |||||
| TriangleStrips, | |||||
| TriangleFans, | |||||
| Points, | |||||
| Lines, | |||||
| } | |||||
| m_value; | |||||
| inline MeshPrimitive(Value v) : m_value(v) {} | |||||
| inline operator Value() { return m_value; } | |||||
| }; | |||||
| LOL_SAFE_ENUM(MeshPrimitive, | |||||
| Triangles, | |||||
| TriangleStrips, | |||||
| TriangleFans, | |||||
| Points, | |||||
| Lines, | |||||
| ); | |||||
| class VertexStreamBase | class VertexStreamBase | ||||
| { | { | ||||
| @@ -107,20 +99,20 @@ public: | |||||
| protected: | protected: | ||||
| #define LOL_TYPE(T) \ | |||||
| #define __T(T) \ | |||||
| static uint8_t GetType(T *x) { UNUSED(x); return Type##T; } | static uint8_t GetType(T *x) { UNUSED(x); return Type##T; } | ||||
| LOL_TYPE(void) | |||||
| LOL_TYPE(half) LOL_TYPE(f16vec2) LOL_TYPE(f16vec3) LOL_TYPE(f16vec4) | |||||
| LOL_TYPE(float) LOL_TYPE(vec2) LOL_TYPE(vec3) LOL_TYPE(vec4) | |||||
| LOL_TYPE(double) LOL_TYPE(dvec2) LOL_TYPE(dvec3) LOL_TYPE(dvec4) | |||||
| LOL_TYPE(int8_t) LOL_TYPE(i8vec2) LOL_TYPE(i8vec3) LOL_TYPE(i8vec4) | |||||
| LOL_TYPE(uint8_t) LOL_TYPE(u8vec2) LOL_TYPE(u8vec3) LOL_TYPE(u8vec4) | |||||
| LOL_TYPE(int16_t) LOL_TYPE(i16vec2) LOL_TYPE(i16vec3) LOL_TYPE(i16vec4) | |||||
| LOL_TYPE(uint16_t) LOL_TYPE(u16vec2) LOL_TYPE(u16vec3) LOL_TYPE(u16vec4) | |||||
| LOL_TYPE(int32_t) LOL_TYPE(ivec2) LOL_TYPE(ivec3) LOL_TYPE(ivec4) | |||||
| LOL_TYPE(uint32_t) LOL_TYPE(uvec2) LOL_TYPE(uvec3) LOL_TYPE(uvec4) | |||||
| #undef LOL_TYPE | |||||
| __T(void) | |||||
| __T(half) __T(f16vec2) __T(f16vec3) __T(f16vec4) | |||||
| __T(float) __T(vec2) __T(vec3) __T(vec4) | |||||
| __T(double) __T(dvec2) __T(dvec3) __T(dvec4) | |||||
| __T(int8_t) __T(i8vec2) __T(i8vec3) __T(i8vec4) | |||||
| __T(uint8_t) __T(u8vec2) __T(u8vec3) __T(u8vec4) | |||||
| __T(int16_t) __T(i16vec2) __T(i16vec3) __T(i16vec4) | |||||
| __T(uint16_t) __T(u16vec2) __T(u16vec3) __T(u16vec4) | |||||
| __T(int32_t) __T(ivec2) __T(ivec3) __T(ivec4) | |||||
| __T(uint32_t) __T(uvec2) __T(uvec3) __T(uvec4) | |||||
| #undef __T | |||||
| template<typename T> inline void AddStream(int n, VertexUsage usage) | template<typename T> inline void AddStream(int n, VertexUsage usage) | ||||
| { | { | ||||
| @@ -132,7 +124,7 @@ protected: | |||||
| VertexStreamBase() {} | VertexStreamBase() {} | ||||
| private: | private: | ||||
| struct { uint8_t stream_type, usage, size; } m_streams[12 + 1]; | |||||
| struct { uint8_t stream_type, size; VertexUsage usage; } m_streams[12 + 1]; | |||||
| static VertexStreamBase const Empty; | static VertexStreamBase const Empty; | ||||
| }; | }; | ||||
| @@ -226,7 +218,13 @@ private: | |||||
| void Initialize(); | void Initialize(); | ||||
| void AddStream(VertexStreamBase const &); | void AddStream(VertexStreamBase const &); | ||||
| struct { uint8_t stream_type, index, usage, size; int reg; } m_streams[12 + 1]; | |||||
| struct | |||||
| { | |||||
| uint8_t stream_type, index, size; | |||||
| VertexUsage usage; | |||||
| int reg; | |||||
| } m_streams[12 + 1]; | |||||
| int m_count; | int m_count; | ||||
| private: | private: | ||||
| @@ -21,28 +21,18 @@ | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| struct FileAccessDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| Read = 0, | |||||
| Write, | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<FileAccessDef> FileAccess; | |||||
| struct StreamTypeDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| StdIn, | |||||
| StdOut, | |||||
| StdErr, | |||||
| File, | |||||
| FileBinary, | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<StreamTypeDef> StreamType; | |||||
| LOL_SAFE_ENUM(FileAccess, | |||||
| Read = 0, | |||||
| Write | |||||
| ); | |||||
| LOL_SAFE_ENUM(StreamType, | |||||
| StdIn, | |||||
| StdOut, | |||||
| StdErr, | |||||
| File, | |||||
| FileBinary | |||||
| ); | |||||
| class File | class File | ||||
| { | { | ||||
| @@ -58,19 +58,14 @@ struct ThreadStatus | |||||
| LOL_DECLARE_ENUM_METHODS(ThreadStatus) | LOL_DECLARE_ENUM_METHODS(ThreadStatus) | ||||
| }; | }; | ||||
| struct ThreadJobTypeDef | |||||
| { | |||||
| enum Type | |||||
| { | |||||
| NONE, | |||||
| WORK_TODO, | |||||
| WORK_DONE, | |||||
| WORK_FAILED, | |||||
| WORK_FETCHED, | |||||
| THREAD_STOP, | |||||
| }; | |||||
| }; | |||||
| typedef SafeEnum<ThreadJobTypeDef> ThreadJobType; | |||||
| LOL_SAFE_ENUM(ThreadJobType, | |||||
| NONE, | |||||
| WORK_TODO, | |||||
| WORK_DONE, | |||||
| WORK_FAILED, | |||||
| WORK_FETCHED, | |||||
| THREAD_STOP | |||||
| ); | |||||
| class ThreadJob | class ThreadJob | ||||
| { | { | ||||
| @@ -106,6 +106,7 @@ | |||||
| <ClCompile Include="audio.cpp" /> | <ClCompile Include="audio.cpp" /> | ||||
| <ClCompile Include="camera.cpp" /> | <ClCompile Include="camera.cpp" /> | ||||
| <ClCompile Include="base\assert.cpp" /> | <ClCompile Include="base\assert.cpp" /> | ||||
| <ClCompile Include="base\enum.cpp" /> | |||||
| <ClCompile Include="base\hash.cpp" /> | <ClCompile Include="base\hash.cpp" /> | ||||
| <ClCompile Include="base\log.cpp" /> | <ClCompile Include="base\log.cpp" /> | ||||
| <ClCompile Include="base\string.cpp" /> | <ClCompile Include="base\string.cpp" /> | ||||
| @@ -285,6 +285,9 @@ | |||||
| <ClCompile Include="base\assert.cpp"> | <ClCompile Include="base\assert.cpp"> | ||||
| <Filter>base</Filter> | <Filter>base</Filter> | ||||
| </ClCompile> | </ClCompile> | ||||
| <ClCompile Include="base\enum.cpp"> | |||||
| <Filter>base</Filter> | |||||
| </ClCompile> | |||||
| <ClCompile Include="base\hash.cpp"> | <ClCompile Include="base\hash.cpp"> | ||||
| <Filter>base</Filter> | <Filter>base</Filter> | ||||
| </ClCompile> | </ClCompile> | ||||
| @@ -92,7 +92,8 @@ void SubMesh::Render(Shader* shader) | |||||
| for (int j = 0; j < stream.GetStreamCount(); ++j) | for (int j = 0; j < stream.GetStreamCount(); ++j) | ||||
| { | { | ||||
| VertexUsage usage = stream.GetUsage(j); | VertexUsage usage = stream.GetUsage(j); | ||||
| attribs[j] = shader->GetAttribLocation(usage, indices[usage]++); | |||||
| int usage_index = usage.ToScalar(); | |||||
| attribs[j] = shader->GetAttribLocation(usage, indices[usage_index]++); | |||||
| } | } | ||||
| vertex_count = m_vbos[i]->GetSize() / m_vdecl->GetStream(i).GetSize(); | vertex_count = m_vbos[i]->GetSize() / m_vdecl->GetStream(i).GetSize(); | ||||
| @@ -20,7 +20,7 @@ testsuite_SOURCES = testsuite.cpp \ | |||||
| unit/build.cpp unit/real.cpp unit/image.cpp unit/quat.cpp unit/cmplx.cpp \ | unit/build.cpp unit/real.cpp unit/image.cpp unit/quat.cpp unit/cmplx.cpp \ | ||||
| unit/array.cpp unit/rotation.cpp unit/string.cpp unit/map.cpp \ | unit/array.cpp unit/rotation.cpp unit/string.cpp unit/map.cpp \ | ||||
| unit/color.cpp unit/atomic.cpp unit/interp.cpp unit/box.cpp \ | unit/color.cpp unit/atomic.cpp unit/interp.cpp unit/box.cpp \ | ||||
| unit/rand.cpp unit/thread.cpp unit/camera.cpp | |||||
| unit/rand.cpp unit/thread.cpp unit/camera.cpp unit/enum.cpp | |||||
| testsuite_CPPFLAGS = $(AM_CPPFLAGS) | testsuite_CPPFLAGS = $(AM_CPPFLAGS) | ||||
| testsuite_DEPENDENCIES = @LOL_DEPS@ | testsuite_DEPENDENCIES = @LOL_DEPS@ | ||||
| noinst_DATA = data/gradient.png | noinst_DATA = data/gradient.png | ||||
| @@ -50,6 +50,7 @@ | |||||
| <ClCompile Include="unit\camera.cpp" /> | <ClCompile Include="unit\camera.cpp" /> | ||||
| <ClCompile Include="unit\cmplx.cpp" /> | <ClCompile Include="unit\cmplx.cpp" /> | ||||
| <ClCompile Include="unit\color.cpp" /> | <ClCompile Include="unit\color.cpp" /> | ||||
| <ClCompile Include="unit\enum.cpp" /> | |||||
| <ClCompile Include="unit\half.cpp" /> | <ClCompile Include="unit\half.cpp" /> | ||||
| <ClCompile Include="unit\image.cpp" /> | <ClCompile Include="unit\image.cpp" /> | ||||
| <ClCompile Include="unit\interp.cpp" /> | <ClCompile Include="unit\interp.cpp" /> | ||||
| @@ -0,0 +1,52 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // This program is free software; you can redistribute it and/or | |||||
| // modify it under the terms of the Do What The Fuck You Want To | |||||
| // Public License, Version 2, as published by Sam Hocevar. See | |||||
| // http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #if defined HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include "core.h" | |||||
| #include "lol/unit.h" | |||||
| namespace lol | |||||
| { | |||||
| LOLUNIT_FIXTURE(EnumTest) | |||||
| { | |||||
| void SetUp() {} | |||||
| void TearDown() {} | |||||
| LOLUNIT_TEST(EnumToString) | |||||
| { | |||||
| LOL_SAFE_ENUM(MyEnum, | |||||
| First = -10, | |||||
| Second, | |||||
| Third = 5, | |||||
| ); | |||||
| MyEnum e = MyEnum::First; | |||||
| LOLUNIT_ASSERT(e.ToString() == "First"); | |||||
| e = MyEnum::Second; | |||||
| LOLUNIT_ASSERT(e.ToString() == "Second"); | |||||
| e = MyEnum::Third; | |||||
| LOLUNIT_ASSERT(e.ToString() == "Third"); | |||||
| e = MyEnum(42); | |||||
| LOLUNIT_ASSERT(e.ToString() != "First"); | |||||
| LOLUNIT_ASSERT(e.ToString() != "Second"); | |||||
| LOLUNIT_ASSERT(e.ToString() != "Third"); | |||||
| } | |||||
| }; | |||||
| } /* namespace lol */ | |||||