From 47e71bda63e357b45329c09b51a2c8296c00236e Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sun, 8 Jun 2014 13:12:13 +0000 Subject: [PATCH] base: rough implementation of safe enums with minimal ToString() support. --- src/Makefile.am | 3 +- src/base/enum.cpp | 65 ++++++++++++++++++++++ src/easymesh/easymesh.h | 53 +++++++----------- src/easymesh/easymeshbuild.h | 97 ++++++++++++++------------------- src/easymesh/easymeshrender.cpp | 12 ++-- src/easymesh/easymeshrender.h | 19 +++---- src/gpu/shader.cpp | 8 +-- src/gpu/vertexbuffer.cpp | 42 +++++++------- src/lol/base/all.h | 2 +- src/lol/base/enum.h | 35 +++++++++++- src/lol/gpu/shader.h | 93 +++++++------------------------ src/lol/gpu/vertexbuffer.h | 56 +++++++++---------- src/lol/sys/file.h | 34 ++++-------- src/lol/sys/thread.h | 21 +++---- src/lolcore.vcxproj | 1 + src/lolcore.vcxproj.filters | 3 + src/mesh/mesh.cpp | 3 +- test/Makefile.am | 2 +- test/testsuite.vcxproj | 1 + test/unit/enum.cpp | 52 ++++++++++++++++++ 20 files changed, 323 insertions(+), 279 deletions(-) create mode 100644 src/base/enum.cpp create mode 100644 test/unit/enum.cpp diff --git a/src/Makefile.am b/src/Makefile.am index e6f7752c..bf865c48 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/base/enum.cpp b/src/base/enum.cpp new file mode 100644 index 00000000..5605e455 --- /dev/null +++ b/src/base/enum.cpp @@ -0,0 +1,65 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 Sam Hocevar +// 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 BuildEnumMap(char const *str) +{ + Map 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 */ + diff --git a/src/easymesh/easymesh.h b/src/easymesh/easymesh.h index fbe63f50..9a5fbb32 100644 --- a/src/easymesh/easymesh.h +++ b/src/easymesh/easymesh.h @@ -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 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 Axis; +LOL_SAFE_ENUM(Axis, + X, + Y, + Z +); -struct MeshTransformDef -{ - enum Type - { - Taper, - Twist, - Bend, - Stretch, - Shear, - }; -}; -typedef SafeEnum MeshTransform; +LOL_SAFE_ENUM(MeshTransform, + Taper, + Twist, + Bend, + Stretch, + Shear +); class EasyMesh { diff --git a/src/easymesh/easymeshbuild.h b/src/easymesh/easymeshbuild.h index b8526ae3..cae1b304 100644 --- a/src/easymesh/easymeshbuild.h +++ b/src/easymesh/easymeshbuild.h @@ -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 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 MeshFaceType; - -struct TexCoordPosDef -{ - enum Type - { - BL, //BottomLeft - BR, //BottomRight - TL, //TopLeft - TR, //TopRight - }; -}; -typedef SafeEnum 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; diff --git a/src/easymesh/easymeshrender.cpp b/src/easymesh/easymeshrender.cpp index fe225c09..ea489309 100644 --- a/src/easymesh/easymeshrender.cpp +++ b/src/easymesh/easymeshrender.cpp @@ -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() }; diff --git a/src/easymesh/easymeshrender.h b/src/easymesh/easymeshrender.h index 2afe9b1c..50e83cfb 100644 --- a/src/easymesh/easymeshrender.h +++ b/src/easymesh/easymeshrender.h @@ -21,18 +21,13 @@ namespace lol { -//Utility enum for renderers -struct MeshRenderDef -{ - enum Type - { - NeedData, - NeedConvert, - CanRender, - IgnoreRender, - }; -}; -typedef SafeEnum MeshRender; +// Utility enum for renderers +LOL_SAFE_ENUM(MeshRender, + NeedData, + NeedConvert, + CanRender, + IgnoreRender, +); //Vertex datas for easymesh vertex list. //TODO : diff --git a/src/gpu/shader.cpp b/src/gpu/shader.cpp index fe328d0a..8ee2022f 100644 --- a/src/gpu/shader.cpp +++ b/src/gpu/shader.cpp @@ -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__ diff --git a/src/gpu/vertexbuffer.cpp b/src/gpu/vertexbuffer.cpp index 424160bb..0225a1cd 100644 --- a/src/gpu/vertexbuffer.cpp +++ b/src/gpu/vertexbuffer.cpp @@ -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(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(count++, VertexStreamBase::Typevoid); + stream.AddStream(count++, VertexUsage::Position); return stream; } diff --git a/src/lol/base/all.h b/src/lol/base/all.h index de049a49..dd851359 100644 --- a/src/lol/base/all.h +++ b/src/lol/base/all.h @@ -12,13 +12,13 @@ #define __LOL_BASE_ALL_H__ #include -#include #include #include #include #include #include #include +#include #endif // __LOL_BASE_ALL_H__ diff --git a/src/lol/base/enum.h b/src/lol/base/enum.h index f62f88f3..45da4655 100644 --- a/src/lol/base/enum.h +++ b/src/lol/base/enum.h @@ -14,8 +14,10 @@ namespace lol { -template -class SafeEnum : public DEF +extern Map BuildEnumMap(char const *str); + +template +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 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 ""; + } + /* 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; + //-- STRUCT TEMPLATE: // enum E { // DEF_VALUE diff --git a/src/lol/gpu/shader.h b/src/lol/gpu/shader.h index 3e7cb19b..b7d179dc 100644 --- a/src/lol/gpu/shader.h +++ b/src/lol/gpu/shader.h @@ -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<"; - } -}; +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); diff --git a/src/lol/gpu/vertexbuffer.h b/src/lol/gpu/vertexbuffer.h index 34c5582f..8ab2c7e6 100644 --- a/src/lol/gpu/vertexbuffer.h +++ b/src/lol/gpu/vertexbuffer.h @@ -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 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: diff --git a/src/lol/sys/file.h b/src/lol/sys/file.h index 8e4997b6..f80b6ed6 100644 --- a/src/lol/sys/file.h +++ b/src/lol/sys/file.h @@ -21,28 +21,18 @@ namespace lol { -struct FileAccessDef -{ - enum Type - { - Read = 0, - Write, - }; -}; -typedef SafeEnum FileAccess; - -struct StreamTypeDef -{ - enum Type - { - StdIn, - StdOut, - StdErr, - File, - FileBinary, - }; -}; -typedef SafeEnum StreamType; +LOL_SAFE_ENUM(FileAccess, + Read = 0, + Write +); + +LOL_SAFE_ENUM(StreamType, + StdIn, + StdOut, + StdErr, + File, + FileBinary +); class File { diff --git a/src/lol/sys/thread.h b/src/lol/sys/thread.h index edd85917..0195e029 100644 --- a/src/lol/sys/thread.h +++ b/src/lol/sys/thread.h @@ -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 ThreadJobType; +LOL_SAFE_ENUM(ThreadJobType, + NONE, + WORK_TODO, + WORK_DONE, + WORK_FAILED, + WORK_FETCHED, + THREAD_STOP +); class ThreadJob { diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index dc6d445b..f8db905c 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -106,6 +106,7 @@ + diff --git a/src/lolcore.vcxproj.filters b/src/lolcore.vcxproj.filters index cabf55b3..89379d38 100644 --- a/src/lolcore.vcxproj.filters +++ b/src/lolcore.vcxproj.filters @@ -285,6 +285,9 @@ base + + base + base diff --git a/src/mesh/mesh.cpp b/src/mesh/mesh.cpp index b0a47386..8e133e6b 100644 --- a/src/mesh/mesh.cpp +++ b/src/mesh/mesh.cpp @@ -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(); diff --git a/test/Makefile.am b/test/Makefile.am index c55b05e1..e9b9878e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -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 diff --git a/test/testsuite.vcxproj b/test/testsuite.vcxproj index b450c2d8..9b5e6c06 100644 --- a/test/testsuite.vcxproj +++ b/test/testsuite.vcxproj @@ -50,6 +50,7 @@ + diff --git a/test/unit/enum.cpp b/test/unit/enum.cpp new file mode 100644 index 00000000..3602b6ac --- /dev/null +++ b/test/unit/enum.cpp @@ -0,0 +1,52 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 Sam Hocevar +// 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 */ +