| @@ -82,6 +82,7 @@ liblolcore_sources = \ | |||
| generated/easymesh-scanner.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/constants.cpp math/geometry.cpp \ | |||
| @@ -107,7 +108,7 @@ liblolcore_sources = \ | |||
| mesh/primitive.cpp mesh/primitive.h \ | |||
| \ | |||
| 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/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. */ | |||
| 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 | |||
| { | |||
| @@ -86,25 +86,21 @@ struct 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 | |||
| { | |||
| @@ -128,33 +124,24 @@ struct 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 | |||
| { | |||
| @@ -227,14 +214,14 @@ public: | |||
| mt = mt; | |||
| else if (mt == MeshType::Quad) | |||
| { | |||
| //There's nothin' else than QuadDefault | |||
| // There's nothin' else than QuadDefault | |||
| BL = vec2(0.f); | |||
| TR = vec2(1.f); | |||
| } | |||
| else if (mt == MeshType::Box) | |||
| { | |||
| vec2 data[][2] = | |||
| { //TexCoordBuildType::BoxDefault | |||
| { // TexCoordBuildType::BoxDefault | |||
| { vec2(0.f), vec2(.5f) }, | |||
| { vec2(.5f, 0.f), vec2(1.f, .5f) }, | |||
| { vec2(0.f), vec2(.5f) }, | |||
| @@ -242,8 +229,8 @@ public: | |||
| { vec2(0.f, .5f), vec2(.5f, 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) | |||
| mt = mt; | |||
| @@ -276,7 +263,7 @@ public: | |||
| 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); } | |||
| TexCoordBuildType GetTexCoordBuildType2(MeshType mt) | |||
| { | |||
| @@ -313,14 +300,14 @@ public: | |||
| mt = mt; | |||
| else if (mt == MeshType::Quad) | |||
| { | |||
| //There's nothin' else than QuadDefault | |||
| // There's nothin' else than QuadDefault | |||
| BL = vec2(0.f); | |||
| TR = vec2(1.f); | |||
| } | |||
| else if (mt == MeshType::Box) | |||
| { | |||
| vec2 data[][2] = | |||
| { //TexCoordBuildType::BoxDefault | |||
| { // TexCoordBuildType::BoxDefault | |||
| { vec2(0.f), vec2(.5f) }, | |||
| { vec2(.5f, 0.f), vec2(1.f, .5f) }, | |||
| { vec2(0.f), vec2(.5f) }, | |||
| @@ -328,8 +315,8 @@ public: | |||
| { vec2(0.f, .5f), vec2(.5f, 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) | |||
| mt = mt; | |||
| @@ -211,8 +211,7 @@ void GpuEasyMeshData::AddGpuData(GpuShaderData* gpudata, EasyMesh* src_mesh) | |||
| BUILD_VFLAG(has_color, VertexUsage::Color, vflags); | |||
| BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, 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_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_texcoord, VertexUsage::TexCoord, 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) | |||
| { | |||
| @@ -369,8 +367,7 @@ void GpuEasyMeshData::SetupVertexData(uint16_t vflags, EasyMesh* src_mesh) | |||
| COPY_VBO; | |||
| } | |||
| 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); | |||
| } | |||
| @@ -404,8 +401,7 @@ void GpuEasyMeshData::RenderMeshData(mat4 const &model, int render_mode) | |||
| BUILD_VFLAG(has_color, VertexUsage::Color, vflags); | |||
| BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, 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; | |||
| ShaderAttrib Attribs[4] = { lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib() }; | |||
| @@ -21,18 +21,13 @@ | |||
| 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. | |||
| //TODO : <COORD, NORM, COLOR, UV> | |||
| @@ -391,7 +391,7 @@ Shader::Shader(char const *vert, char const *frag) | |||
| String name(name_buffer); | |||
| int index = -1; | |||
| 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])) | |||
| { | |||
| @@ -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", | |||
| name_buffer); | |||
| @@ -410,7 +410,7 @@ Shader::Shader(char const *vert, char const *frag) | |||
| else | |||
| { | |||
| 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; | |||
| // TODO: this is here just in case. Remove this once everything has been correctly tested | |||
| #ifdef _DEBUG | |||
| @@ -440,7 +440,7 @@ int Shader::GetAttribCount() const | |||
| ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const | |||
| { | |||
| 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; | |||
| #if defined USE_D3D9 || defined _XBOX | |||
| #elif !defined __CELLOS_LV2__ | |||
| @@ -139,7 +139,7 @@ void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count) | |||
| return; | |||
| #if defined _XBOX || defined USE_D3D9 | |||
| switch (type) | |||
| switch (type.ToScalar()) | |||
| { | |||
| case MeshPrimitive::Triangles: | |||
| if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_TRIANGLELIST, | |||
| @@ -169,7 +169,7 @@ void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count) | |||
| } | |||
| #else | |||
| /* FIXME: this has nothing to do here! */ | |||
| switch (type) | |||
| switch (type.ToScalar()) | |||
| { | |||
| case MeshPrimitive::Triangles: | |||
| glDrawArrays(GL_TRIANGLES, skip, count); | |||
| @@ -198,7 +198,7 @@ void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase, | |||
| return; | |||
| #if defined _XBOX || defined USE_D3D9 | |||
| switch (type) | |||
| switch (type.ToScalar()) | |||
| { | |||
| case MeshPrimitive::Triangles: | |||
| count = count / 3; | |||
| @@ -231,7 +231,7 @@ void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase, | |||
| } | |||
| #else | |||
| /* FIXME: this has nothing to do here! */ | |||
| switch (type) | |||
| switch (type.ToScalar()) | |||
| { | |||
| case MeshPrimitive::Triangles: | |||
| /* 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 | |||
| * is about; the rest of the information is stored in the | |||
| * 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; | |||
| /* Find the stream number */ | |||
| @@ -362,15 +362,15 @@ void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attribs[]) | |||
| glBindBuffer(GL_ARRAY_BUFFER, vb->m_data->m_vbo); | |||
| 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 reg = attribs[n].m_flags >> 32; | |||
| # if !defined __CELLOS_LV2__ | |||
| if (reg != 0xffffffff) | |||
| glEnableVertexAttribArray((GLint)reg); | |||
| # else | |||
| switch (usage) | |||
| switch (usage.ToScalar()) | |||
| { | |||
| case VertexUsage::Position: | |||
| glEnableClientState(GL_VERTEX_ARRAY); | |||
| @@ -627,26 +627,26 @@ VertexStreamBase VertexDeclaration::GetStream(int index) const | |||
| 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; | |||
| 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; | |||
| } | |||
| while (count < 12) | |||
| stream.AddStream<void>(count++, VertexStreamBase::Typevoid); | |||
| stream.AddStream<void>(count++, VertexUsage::Position); | |||
| return stream; | |||
| } | |||
| @@ -12,13 +12,13 @@ | |||
| #define __LOL_BASE_ALL_H__ | |||
| #include <lol/base/types.h> | |||
| #include <lol/base/enum.h> | |||
| #include <lol/base/log.h> | |||
| #include <lol/base/assert.h> | |||
| #include <lol/base/array.h> | |||
| #include <lol/base/string.h> | |||
| #include <lol/base/hash.h> | |||
| #include <lol/base/map.h> | |||
| #include <lol/base/enum.h> | |||
| #endif // __LOL_BASE_ALL_H__ | |||
| @@ -14,8 +14,10 @@ | |||
| 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; | |||
| Type m_value; | |||
| @@ -24,9 +26,27 @@ public: | |||
| inline SafeEnum() : m_value() {} | |||
| 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; } | |||
| /* 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 */ | |||
| 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: | |||
| // enum E { | |||
| // DEF_VALUE | |||
| @@ -25,79 +25,24 @@ namespace lol | |||
| * now there is only TexCoord and not TexCoord0 TexCoord1 etc. because | |||
| * we can always reorganise the vertex declaration for the indices to | |||
| * 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 | |||
| { | |||
| @@ -152,7 +97,7 @@ public: | |||
| static void Destroy(Shader *shader); | |||
| int GetAttribCount() const; | |||
| ShaderAttrib GetAttribLocation(struct VertexUsage usage, int index) const; | |||
| ShaderAttrib GetAttribLocation(VertexUsage usage, int index) const; | |||
| ShaderUniform GetUniformLocation(char const *uni) const; | |||
| 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 | |||
| * 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 | |||
| { | |||
| @@ -107,20 +99,20 @@ public: | |||
| protected: | |||
| #define LOL_TYPE(T) \ | |||
| #define __T(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) | |||
| { | |||
| @@ -132,7 +124,7 @@ protected: | |||
| VertexStreamBase() {} | |||
| 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; | |||
| }; | |||
| @@ -226,7 +218,13 @@ private: | |||
| void Initialize(); | |||
| 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; | |||
| private: | |||
| @@ -21,28 +21,18 @@ | |||
| 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 | |||
| { | |||
| @@ -58,19 +58,14 @@ struct 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 | |||
| { | |||
| @@ -106,6 +106,7 @@ | |||
| <ClCompile Include="audio.cpp" /> | |||
| <ClCompile Include="camera.cpp" /> | |||
| <ClCompile Include="base\assert.cpp" /> | |||
| <ClCompile Include="base\enum.cpp" /> | |||
| <ClCompile Include="base\hash.cpp" /> | |||
| <ClCompile Include="base\log.cpp" /> | |||
| <ClCompile Include="base\string.cpp" /> | |||
| @@ -285,6 +285,9 @@ | |||
| <ClCompile Include="base\assert.cpp"> | |||
| <Filter>base</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="base\enum.cpp"> | |||
| <Filter>base</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="base\hash.cpp"> | |||
| <Filter>base</Filter> | |||
| </ClCompile> | |||
| @@ -92,7 +92,8 @@ void SubMesh::Render(Shader* shader) | |||
| for (int j = 0; j < stream.GetStreamCount(); ++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(); | |||
| @@ -20,7 +20,7 @@ testsuite_SOURCES = testsuite.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/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_DEPENDENCIES = @LOL_DEPS@ | |||
| noinst_DATA = data/gradient.png | |||
| @@ -50,6 +50,7 @@ | |||
| <ClCompile Include="unit\camera.cpp" /> | |||
| <ClCompile Include="unit\cmplx.cpp" /> | |||
| <ClCompile Include="unit\color.cpp" /> | |||
| <ClCompile Include="unit\enum.cpp" /> | |||
| <ClCompile Include="unit\half.cpp" /> | |||
| <ClCompile Include="unit\image.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 */ | |||