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