Browse Source

base: rough implementation of safe enums with minimal ToString() support.

undefined
Sam Hocevar 10 years ago
parent
commit
47e71bda63
20 changed files with 323 additions and 279 deletions
  1. +2
    -1
      src/Makefile.am
  2. +65
    -0
      src/base/enum.cpp
  3. +19
    -34
      src/easymesh/easymesh.h
  4. +42
    -55
      src/easymesh/easymeshbuild.h
  5. +4
    -8
      src/easymesh/easymeshrender.cpp
  6. +7
    -12
      src/easymesh/easymeshrender.h
  7. +4
    -4
      src/gpu/shader.cpp
  8. +21
    -21
      src/gpu/vertexbuffer.cpp
  9. +1
    -1
      src/lol/base/all.h
  10. +32
    -3
      src/lol/base/enum.h
  11. +19
    -74
      src/lol/gpu/shader.h
  12. +27
    -29
      src/lol/gpu/vertexbuffer.h
  13. +12
    -22
      src/lol/sys/file.h
  14. +8
    -13
      src/lol/sys/thread.h
  15. +1
    -0
      src/lolcore.vcxproj
  16. +3
    -0
      src/lolcore.vcxproj.filters
  17. +2
    -1
      src/mesh/mesh.cpp
  18. +1
    -1
      test/Makefile.am
  19. +1
    -0
      test/testsuite.vcxproj
  20. +52
    -0
      test/unit/enum.cpp

+ 2
- 1
src/Makefile.am View File

@@ -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 \


+ 65
- 0
src/base/enum.cpp View File

@@ -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 */


+ 19
- 34
src/easymesh/easymesh.h View File

@@ -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
{ {


+ 42
- 55
src/easymesh/easymeshbuild.h View File

@@ -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;


+ 4
- 8
src/easymesh/easymeshrender.cpp View File

@@ -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() };


+ 7
- 12
src/easymesh/easymeshrender.h View File

@@ -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>


+ 4
- 4
src/gpu/shader.cpp View File

@@ -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__


+ 21
- 21
src/gpu/vertexbuffer.cpp View File

@@ -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;
} }


+ 1
- 1
src/lol/base/all.h View File

@@ -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__



+ 32
- 3
src/lol/base/enum.h View File

@@ -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


+ 19
- 74
src/lol/gpu/shader.h View File

@@ -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);


+ 27
- 29
src/lol/gpu/vertexbuffer.h View File

@@ -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:


+ 12
- 22
src/lol/sys/file.h View File

@@ -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
{ {


+ 8
- 13
src/lol/sys/thread.h View 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
{ {


+ 1
- 0
src/lolcore.vcxproj View File

@@ -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" />


+ 3
- 0
src/lolcore.vcxproj.filters View File

@@ -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>


+ 2
- 1
src/mesh/mesh.cpp View File

@@ -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();


+ 1
- 1
test/Makefile.am View File

@@ -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


+ 1
- 0
test/testsuite.vcxproj View File

@@ -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" />


+ 52
- 0
test/unit/enum.cpp View File

@@ -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 */


Loading…
Cancel
Save