Thread-safety
This commit is contained in:
parent
1abaf6c321
commit
916a41e064
@ -18,6 +18,7 @@
|
|||||||
<ClInclude Include="..\include\Animation\SalmonAnimation.h" />
|
<ClInclude Include="..\include\Animation\SalmonAnimation.h" />
|
||||||
<ClInclude Include="..\include\ApplicationInterface.h" />
|
<ClInclude Include="..\include\ApplicationInterface.h" />
|
||||||
<ClInclude Include="..\include\Engine.h" />
|
<ClInclude Include="..\include\Engine.h" />
|
||||||
|
<ClInclude Include="..\include\FontManager\FontManager.h" />
|
||||||
<ClInclude Include="..\include\FrameManager\FrameManager.h" />
|
<ClInclude Include="..\include\FrameManager\FrameManager.h" />
|
||||||
<ClInclude Include="..\include\GlobalConst.h" />
|
<ClInclude Include="..\include\GlobalConst.h" />
|
||||||
<ClInclude Include="..\include\GUIManager\ButtonWidget.h" />
|
<ClInclude Include="..\include\GUIManager\ButtonWidget.h" />
|
||||||
|
@ -113,7 +113,6 @@ protected:
|
|||||||
float DrawChar(vec2 pos, cardinal character);
|
float DrawChar(vec2 pos, cardinal character);
|
||||||
float DrawCharToVBO(vec2 pos, cardinal character, TTriangleList& triangleList);
|
float DrawCharToVBO(vec2 pos, cardinal character, TTriangleList& triangleList);
|
||||||
|
|
||||||
vec2 FitStringToBox(vec2 posFrom, vec2 posTo, TTextBasicAreaParams params, std::string& str);
|
|
||||||
vec2 FitStringToBoxWithWordWrap(vec2 posFrom, vec2 posTo, TTextBasicAreaParams params, std::string& str);
|
vec2 FitStringToBoxWithWordWrap(vec2 posFrom, vec2 posTo, TTextBasicAreaParams params, std::string& str);
|
||||||
public:
|
public:
|
||||||
TFontManager() { }
|
TFontManager() { }
|
||||||
|
@ -59,12 +59,19 @@ protected:
|
|||||||
bool CreateTexDataFromTga(const std::string& filename, TTextureData& texData);
|
bool CreateTexDataFromTga(const std::string& filename, TTextureData& texData);
|
||||||
bool CreateTexDataFromPng(const std::string& filename, TTextureData& texData);
|
bool CreateTexDataFromPng(const std::string& filename, TTextureData& texData);
|
||||||
|
|
||||||
cardinal AddTextureBmp24Data(const TTextureData& texData);
|
cardinal AddTextureBmp24Data(const TTextureData& texData); //MAIN THREAD ONLY
|
||||||
cardinal AddTextureBmp32Data(const TTextureData& texData);
|
cardinal AddTextureBmp32Data(const TTextureData& texData); //MAIN THREAD ONLY
|
||||||
cardinal AddCubemapTextureBmp24Data(TTextureData* texData);
|
cardinal AddCubemapTextureBmp24Data(TTextureData* texData); //MAIN THREAD ONLY
|
||||||
//cardinal AddCubemapTextureBmp32Data(TTextureData* texData); Not implemented yet
|
//cardinal AddCubemapTextureBmp32Data(TTextureData* texData); Not implemented yet
|
||||||
|
|
||||||
void InnerClear();
|
|
||||||
|
cardinal InnerAddEmptyTexture(const std::string& texName, cardinal width, cardinal height); //MAIN THREAD ONLY
|
||||||
|
cardinal InnerAddEmptyCubemapTexture(const std::string& texName, cardinal width, cardinal height); //MAIN THREAD ONLY
|
||||||
|
cardinal InnerAddDepthTexture(const std::string& texName, cardinal width, cardinal height); //MAIN THREAD ONLY
|
||||||
|
void InnerDeleteTexture(TTextureMap::iterator itr); //MAIN THREAD ONLY //MAIN THREAD ONLY
|
||||||
|
|
||||||
|
|
||||||
|
void InnerClear(); //MAIN THREAD ONLY
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TTextureListClass();
|
TTextureListClass();
|
||||||
|
@ -26,6 +26,9 @@ namespace SE
|
|||||||
};
|
};
|
||||||
|
|
||||||
void AssertIfInMainThread();
|
void AssertIfInMainThread();
|
||||||
|
|
||||||
|
void TryUpdateMainThreadId();
|
||||||
|
|
||||||
void PerformInMainThreadAsync(boost::function<void()> f);
|
void PerformInMainThreadAsync(boost::function<void()> f);
|
||||||
|
|
||||||
template<typename RETURNTYPE>
|
template<typename RETURNTYPE>
|
||||||
|
@ -184,85 +184,11 @@ float TFontManager::DrawCharToVBO(vec2 pos, cardinal character, TTriangleList& t
|
|||||||
vec2 t2 = vec2(fontParams.ShiftX + fontParams.BitmapWidth,
|
vec2 t2 = vec2(fontParams.ShiftX + fontParams.BitmapWidth,
|
||||||
1 - fontParams.ShiftY - fontParams.InternalShiftY);
|
1 - fontParams.ShiftY - fontParams.InternalShiftY);
|
||||||
|
|
||||||
/*
|
|
||||||
vec2 p12 = vec2(p1.v[0], p2.v[1]);
|
|
||||||
vec2 p21 = vec2(p2.v[0], p1.v[1]);
|
|
||||||
|
|
||||||
vec2 t12 = vec2(t1.v[0], t2.v[1]);
|
|
||||||
vec2 t21 = vec2(t2.v[0], t1.v[1]);
|
|
||||||
|
|
||||||
|
|
||||||
triangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(vec3(p1, 0));
|
|
||||||
triangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(vec3(p12, 0));
|
|
||||||
triangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(vec3(p2, 0));
|
|
||||||
|
|
||||||
triangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(vec3(p2, 0));
|
|
||||||
triangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(vec3(p21, 0));
|
|
||||||
triangleList.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(vec3(p1, 0));
|
|
||||||
|
|
||||||
triangleList.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t1);
|
|
||||||
triangleList.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t12);
|
|
||||||
triangleList.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t2);
|
|
||||||
|
|
||||||
triangleList.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t2);
|
|
||||||
triangleList.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t21);
|
|
||||||
triangleList.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(t1);
|
|
||||||
*/
|
|
||||||
triangleList.Data += MakeDataTriangleList(p1, p2, t1, t2);
|
triangleList.Data += MakeDataTriangleList(p1, p2, t1, t2);
|
||||||
|
|
||||||
return fontParams.Advance*scale_x;
|
return fontParams.Advance*scale_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 TFontManager::FitStringToBox(vec2 posFrom, vec2 posTo, TTextBasicAreaParams params, std::string& str)
|
|
||||||
{
|
|
||||||
//Need to make this deprecated!
|
|
||||||
|
|
||||||
throw ErrorToLog("Call to deprecated TFontManager::FitStringToBox");
|
|
||||||
|
|
||||||
std::string fontName = GetCurrentFontName();
|
|
||||||
|
|
||||||
float intervalY = CONST_HEIGHT_COEF * params.Height;
|
|
||||||
|
|
||||||
size_t rows = 1;
|
|
||||||
|
|
||||||
float maxWidth = posTo.v[0] - posFrom.v[0];
|
|
||||||
|
|
||||||
cardinal p = 0;
|
|
||||||
vec2 cursor;
|
|
||||||
|
|
||||||
while (p<str.size())
|
|
||||||
{
|
|
||||||
char c = str[p];
|
|
||||||
|
|
||||||
if (c == '\n')
|
|
||||||
{
|
|
||||||
cursor.v[0] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cursor.v[0] += GetCharAdvance(c);
|
|
||||||
}
|
|
||||||
if (cursor.v[0] > maxWidth)
|
|
||||||
{
|
|
||||||
str.insert(p, 1, '\n');
|
|
||||||
cursor.v[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t found = str.find_first_of('\n');
|
|
||||||
|
|
||||||
while (found != std::string::npos)
|
|
||||||
{
|
|
||||||
rows++;
|
|
||||||
found = str.find_first_of('\n', found + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec2(posFrom.v[0], posFrom.v[1] + intervalY*rows);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
vec2 TFontManager::FitStringToBoxWithWordWrap(vec2 posFrom, vec2 posTo, TTextBasicAreaParams params, std::string& str)
|
vec2 TFontManager::FitStringToBoxWithWordWrap(vec2 posFrom, vec2 posTo, TTextBasicAreaParams params, std::string& str)
|
||||||
{
|
{
|
||||||
@ -455,7 +381,8 @@ void TFontManager::DrawTextInBox(vec2 posFrom, vec2 posTo, TTextBasicAreaParams
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
realPosFrom = FitStringToBox(posFrom, posTo, params, str);
|
//realPosFrom = FitStringToBox(posFrom, posTo, params, str);
|
||||||
|
throw ErrorToLog("Word wrap not supported!");
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawString(realPosFrom, params, str);
|
DrawString(realPosFrom, params, str);
|
||||||
@ -471,7 +398,8 @@ TTriangleList TFontManager::DrawTextInBoxToVBO(vec2 posFrom, vec2 posTo, TTextBa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
realPosFrom = FitStringToBox(posFrom, posTo, params, str);
|
throw ErrorToLog("Word wrap not supported!");
|
||||||
|
//realPosFrom = FitStringToBox(posFrom, posTo, params, str);
|
||||||
}
|
}
|
||||||
return DrawStringToVBO(realPosFrom, params, str);
|
return DrawStringToVBO(realPosFrom, params, str);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ TFrameManager::~TFrameManager()
|
|||||||
|
|
||||||
void TFrameManager::FreeFrameManager()
|
void TFrameManager::FreeFrameManager()
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
BOOST_FOREACH(auto& i, FrameMap)
|
BOOST_FOREACH(auto& i, FrameMap)
|
||||||
{
|
{
|
||||||
ResourceManager->TexList.DeleteTexture(i.second.TexName);
|
ResourceManager->TexList.DeleteTexture(i.second.TexName);
|
||||||
@ -37,6 +38,8 @@ void TFrameManager::FreeFrameManager()
|
|||||||
|
|
||||||
cardinal TFrameManager::AddFrameRenderBuffer(const std::string& frameName,cardinal width,cardinal height)
|
cardinal TFrameManager::AddFrameRenderBuffer(const std::string& frameName,cardinal width,cardinal height)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
#ifdef TARGET_ANDROID
|
#ifdef TARGET_ANDROID
|
||||||
#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE
|
#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE
|
||||||
#endif
|
#endif
|
||||||
@ -122,6 +125,7 @@ cardinal TFrameManager::AddFrameRenderBuffer(const std::string& frameName,cardin
|
|||||||
|
|
||||||
cardinal TFrameManager::AddCubemapBuffer(const std::string& frameName,cardinal width,cardinal height)
|
cardinal TFrameManager::AddCubemapBuffer(const std::string& frameName,cardinal width,cardinal height)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
#ifdef TARGET_ANDROID
|
#ifdef TARGET_ANDROID
|
||||||
#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE
|
#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE
|
||||||
@ -218,6 +222,8 @@ cardinal TFrameManager::AddCubemapBuffer(const std::string& frameName,cardinal w
|
|||||||
|
|
||||||
void TFrameManager::DeleteFrameRenderBuffer(const std::string& frameName)
|
void TFrameManager::DeleteFrameRenderBuffer(const std::string& frameName)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
if (FrameMap.count(frameName) > 0)
|
if (FrameMap.count(frameName) > 0)
|
||||||
{
|
{
|
||||||
ResourceManager->TexList.DeleteTexture(FrameMap[frameName].TexName);
|
ResourceManager->TexList.DeleteTexture(FrameMap[frameName].TexName);
|
||||||
@ -231,6 +237,7 @@ void TFrameManager::DeleteFrameRenderBuffer(const std::string& frameName)
|
|||||||
|
|
||||||
cardinal TFrameManager::AddDepthBuffer(const std::string& frameName, cardinal width, cardinal height)
|
cardinal TFrameManager::AddDepthBuffer(const std::string& frameName, cardinal width, cardinal height)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
#ifdef TARGET_ANDROID
|
#ifdef TARGET_ANDROID
|
||||||
#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE
|
#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE
|
||||||
|
@ -12,6 +12,8 @@ TRendererInterface::TRendererInterface()
|
|||||||
|
|
||||||
void TRendererInterface::TryEnableVertexAttribArrays()
|
void TRendererInterface::TryEnableVertexAttribArrays()
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
EnableVertexAttribArray(CONST_STRING_POSITION_ATTRIB);
|
EnableVertexAttribArray(CONST_STRING_POSITION_ATTRIB);
|
||||||
EnableVertexAttribArray(CONST_STRING_NORMAL_ATTRIB);
|
EnableVertexAttribArray(CONST_STRING_NORMAL_ATTRIB);
|
||||||
EnableVertexAttribArray(CONST_STRING_TEXCOORD_ATTRIB);
|
EnableVertexAttribArray(CONST_STRING_TEXCOORD_ATTRIB);
|
||||||
@ -21,6 +23,8 @@ void TRendererInterface::TryEnableVertexAttribArrays()
|
|||||||
|
|
||||||
void TRendererInterface::TryDisableVertexAttribArrays()
|
void TRendererInterface::TryDisableVertexAttribArrays()
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
DisableVertexAttribArray(CONST_STRING_BINORMAL_ATTRIB);
|
DisableVertexAttribArray(CONST_STRING_BINORMAL_ATTRIB);
|
||||||
DisableVertexAttribArray(CONST_STRING_TANGENT_ATTRIB);
|
DisableVertexAttribArray(CONST_STRING_TANGENT_ATTRIB);
|
||||||
DisableVertexAttribArray(CONST_STRING_TEXCOORD_ATTRIB);
|
DisableVertexAttribArray(CONST_STRING_TEXCOORD_ATTRIB);
|
||||||
@ -232,12 +236,16 @@ void TRendererInterface::SetProjectionMatrix(float width, float height)
|
|||||||
|
|
||||||
void TRendererInterface::SetFrameViewport(const std::string& frameName)
|
void TRendererInterface::SetFrameViewport(const std::string& frameName)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
ivec2 frameWidthHeight = ResourceManager->FrameManager.GetFrameWidthHeight(frameName);
|
ivec2 frameWidthHeight = ResourceManager->FrameManager.GetFrameWidthHeight(frameName);
|
||||||
glViewport(0, 0, frameWidthHeight.v[0], frameWidthHeight.v[1]);
|
glViewport(0, 0, frameWidthHeight.v[0], frameWidthHeight.v[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TRendererInterface::SetFullScreenViewport()
|
void TRendererInterface::SetFullScreenViewport()
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
glViewport(0, 0, ScreenWidth, ScreenHeight);
|
glViewport(0, 0, ScreenWidth, ScreenHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,6 +269,7 @@ void TRendererInterface::PopShader()
|
|||||||
|
|
||||||
void TRendererInterface::DrawRect(const vec2& p1, const vec2& p2)
|
void TRendererInterface::DrawRect(const vec2& p1, const vec2& p2)
|
||||||
{
|
{
|
||||||
|
|
||||||
T2DQuad quad;
|
T2DQuad quad;
|
||||||
|
|
||||||
quad.VertexCoord[0] = vec3(p1.v[0], p1.v[1], 0.0f);
|
quad.VertexCoord[0] = vec3(p1.v[0], p1.v[1], 0.0f);
|
||||||
@ -278,6 +287,7 @@ void TRendererInterface::DrawRect(const vec2& p1, const vec2& p2)
|
|||||||
|
|
||||||
void TRendererInterface::DrawRect(const vec2& p1, const vec2& p2, const vec2& t1, const vec2& t2)
|
void TRendererInterface::DrawRect(const vec2& p1, const vec2& p2, const vec2& t1, const vec2& t2)
|
||||||
{
|
{
|
||||||
|
|
||||||
T2DQuad quad;
|
T2DQuad quad;
|
||||||
|
|
||||||
quad.VertexCoord[0] = vec3(p1.v[0], p1.v[1], 0.0f);
|
quad.VertexCoord[0] = vec3(p1.v[0], p1.v[1], 0.0f);
|
||||||
@ -302,6 +312,7 @@ void TRendererInterface::DrawFrameFullScreen(const std::string& frameName)
|
|||||||
|
|
||||||
void TRendererInterface::DrawFramePartScreen(const std::string& frameName, vec2 posFrom, vec2 posTo)
|
void TRendererInterface::DrawFramePartScreen(const std::string& frameName, vec2 posFrom, vec2 posTo)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
cardinal texID = ResourceManager->FrameManager.GetFrameTexture(frameName.c_str());
|
cardinal texID = ResourceManager->FrameManager.GetFrameTexture(frameName.c_str());
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ namespace SE
|
|||||||
|
|
||||||
VBOObject::VBOObject()
|
VBOObject::VBOObject()
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
glGenBuffers(1, &Buffer);
|
glGenBuffers(1, &Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,14 +17,16 @@ VBOObject::VBOObject(const VBOObject& c)
|
|||||||
throw ErrorToLog("Copy constructor for VBOObject called\n");
|
throw ErrorToLog("Copy constructor for VBOObject called\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
VBOObject& VBOObject::operator=(const VBOObject& c)
|
VBOObject& VBOObject::operator=(const VBOObject& c)
|
||||||
{
|
{
|
||||||
throw ErrorToLog("operator= for VBOObject called\n");
|
throw ErrorToLog("operator= for VBOObject called\n");
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
VBOObject::~VBOObject()
|
VBOObject::~VBOObject()
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
glDeleteBuffers(1, &Buffer);
|
glDeleteBuffers(1, &Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +115,7 @@ TTriangleList::~TTriangleList()
|
|||||||
|
|
||||||
void TTriangleList::RefreshBuffer()
|
void TTriangleList::RefreshBuffer()
|
||||||
{
|
{
|
||||||
//VertBuffer
|
AssertIfInMainThread();
|
||||||
|
|
||||||
|
|
||||||
if (NeedPrepareBufferObjects && Data.Vec2CoordArr.size() > 0 && Data.Vec3CoordArr.size() > 0)
|
if (NeedPrepareBufferObjects && Data.Vec2CoordArr.size() > 0 && Data.Vec3CoordArr.size() > 0)
|
||||||
@ -303,7 +307,6 @@ void ScaleDataTriangleList(TDataTriangleList& triangleList, vec3 scaleVec)
|
|||||||
|
|
||||||
TDataTriangleList& ClearDataTriangleList(TDataTriangleList& triangleList)
|
TDataTriangleList& ClearDataTriangleList(TDataTriangleList& triangleList)
|
||||||
{
|
{
|
||||||
//throw ErrorToLog("Seems that here are some problems with this func. Do not use it!");
|
|
||||||
|
|
||||||
BOOST_FOREACH(auto& i, triangleList.Vec2CoordArr)
|
BOOST_FOREACH(auto& i, triangleList.Vec2CoordArr)
|
||||||
{
|
{
|
||||||
@ -349,6 +352,8 @@ void Replace6PointsInTriangleList(TDataTriangleList& triangleList, int pos, vec2
|
|||||||
|
|
||||||
void CheckGlError(const std::string& msg)
|
void CheckGlError(const std::string& msg)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
cardinal error = glGetError();
|
cardinal error = glGetError();
|
||||||
|
|
||||||
if (error != GL_NO_ERROR)
|
if (error != GL_NO_ERROR)
|
||||||
|
@ -7,6 +7,8 @@ namespace SE
|
|||||||
TRenderParamsSetter::TRenderParamsSetter(const TRenderParams& renderParams)
|
TRenderParamsSetter::TRenderParamsSetter(const TRenderParams& renderParams)
|
||||||
: RenderParams(renderParams)
|
: RenderParams(renderParams)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
if (RenderParams.ShaderName != "")
|
if (RenderParams.ShaderName != "")
|
||||||
{
|
{
|
||||||
Renderer->PushShader(RenderParams.ShaderName);
|
Renderer->PushShader(RenderParams.ShaderName);
|
||||||
@ -59,13 +61,7 @@ TRenderParamsSetter::~TRenderParamsSetter()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
std::string ShaderName;
|
|
||||||
|
|
||||||
mutable std::map<std::string, std::string> SamplerMap;
|
|
||||||
mutable std::map<std::string, float> FloatMap;
|
|
||||||
mutable std::map<std::string, vec4> Vec4Map;
|
|
||||||
*/
|
|
||||||
void TRenderParams::Serialize(boost::property_tree::ptree& propertyTree)
|
void TRenderParams::Serialize(boost::property_tree::ptree& propertyTree)
|
||||||
{
|
{
|
||||||
if (propertyTree.count("Shader") != 0)
|
if (propertyTree.count("Shader") != 0)
|
||||||
|
@ -8,6 +8,8 @@ namespace SE
|
|||||||
|
|
||||||
void TSalmonRendererGLES20::DrawQuad(const T2DQuad& quad)
|
void TSalmonRendererGLES20::DrawQuad(const T2DQuad& quad)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
//EnableVertexAttribArray("vPosition");
|
//EnableVertexAttribArray("vPosition");
|
||||||
//EnableVertexAttribArray("vTexCoord");
|
//EnableVertexAttribArray("vTexCoord");
|
||||||
|
|
||||||
@ -24,6 +26,8 @@ void TSalmonRendererGLES20::DrawQuad(const T2DQuad& quad)
|
|||||||
|
|
||||||
void TSalmonRendererGLES20::DrawTriangleList(const TTriangleList& triangleList)
|
void TSalmonRendererGLES20::DrawTriangleList(const TTriangleList& triangleList)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
for (std::map<std::string, std::vector<vec2> >::iterator i = triangleList.Data.Vec2CoordArr.begin(); i != triangleList.Data.Vec2CoordArr.end(); ++i )
|
for (std::map<std::string, std::vector<vec2> >::iterator i = triangleList.Data.Vec2CoordArr.begin(); i != triangleList.Data.Vec2CoordArr.end(); ++i )
|
||||||
{
|
{
|
||||||
VertexAttribPointer2fv(i->first, 0, reinterpret_cast<const char*>(&triangleList.Data.Vec2CoordArr[i->first][0]));
|
VertexAttribPointer2fv(i->first, 0, reinterpret_cast<const char*>(&triangleList.Data.Vec2CoordArr[i->first][0]));
|
||||||
|
@ -22,7 +22,7 @@ TSalmonRendererInterface::TSalmonRendererInterface()
|
|||||||
|
|
||||||
void TSalmonRendererInterface::SetUniforms()
|
void TSalmonRendererInterface::SetUniforms()
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
//Refactoring!
|
//Refactoring!
|
||||||
|
|
||||||
|
|
||||||
@ -70,6 +70,7 @@ void TSalmonRendererInterface::SetUniforms()
|
|||||||
|
|
||||||
void TSalmonRendererInterface::InitOpenGL(int screenWidth, int screenHeight, float matrixWidth, float matrixHeight)
|
void TSalmonRendererInterface::InitOpenGL(int screenWidth, int screenHeight, float matrixWidth, float matrixHeight)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
ModelviewMatrixStack.push(IdentityMatrix4);
|
ModelviewMatrixStack.push(IdentityMatrix4);
|
||||||
ProjectionMatrixStack.push(IdentityMatrix4);
|
ProjectionMatrixStack.push(IdentityMatrix4);
|
||||||
@ -126,6 +127,7 @@ void TSalmonRendererInterface::CalcCamPos()
|
|||||||
|
|
||||||
void TSalmonRendererInterface::SetPerspectiveFullScreenViewport()
|
void TSalmonRendererInterface::SetPerspectiveFullScreenViewport()
|
||||||
{
|
{
|
||||||
|
throw ErrorToLog("SetPerspectiveFullScreenViewport is deprecated");
|
||||||
|
|
||||||
glViewport(0, 0, ScreenWidth, ScreenHeight);
|
glViewport(0, 0, ScreenWidth, ScreenHeight);
|
||||||
|
|
||||||
@ -140,6 +142,8 @@ void TSalmonRendererInterface::SetPerspectiveProjection(float angle, float zNear
|
|||||||
|
|
||||||
void TSalmonRendererInterface::SetOrthoFullScreenViewport()
|
void TSalmonRendererInterface::SetOrthoFullScreenViewport()
|
||||||
{
|
{
|
||||||
|
throw ErrorToLog("SetOrthoFullScreenViewport is deprecated");
|
||||||
|
|
||||||
glViewport(0, 0, ScreenWidth, ScreenHeight);
|
glViewport(0, 0, ScreenWidth, ScreenHeight);
|
||||||
|
|
||||||
SetProjectionMatrix(static_cast<float>(MatrixWidth), static_cast<float>(MatrixHeight));
|
SetProjectionMatrix(static_cast<float>(MatrixWidth), static_cast<float>(MatrixHeight));
|
||||||
@ -310,6 +314,7 @@ void TSalmonRendererInterface::SetGlNegZView()
|
|||||||
|
|
||||||
void TSalmonRendererInterface::SwitchToScreen()
|
void TSalmonRendererInterface::SwitchToScreen()
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, CONST_SCREEN_FRAMEBUFFER);
|
glBindFramebuffer(GL_FRAMEBUFFER, CONST_SCREEN_FRAMEBUFFER);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
@ -317,6 +322,7 @@ void TSalmonRendererInterface::SwitchToScreen()
|
|||||||
|
|
||||||
void TSalmonRendererInterface::SwitchToFrameBuffer(const std::string& frameName)
|
void TSalmonRendererInterface::SwitchToFrameBuffer(const std::string& frameName)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
if (ResourceManager->FrameManager.FrameMap.count(frameName) > 0)
|
if (ResourceManager->FrameManager.FrameMap.count(frameName) > 0)
|
||||||
{
|
{
|
||||||
@ -332,7 +338,7 @@ void TSalmonRendererInterface::SwitchToFrameBuffer(const std::string& frameName)
|
|||||||
|
|
||||||
void TSalmonRendererInterface::SwitchToCubemapBuffer(const std::string& frameName,cardinal cubeSide)
|
void TSalmonRendererInterface::SwitchToCubemapBuffer(const std::string& frameName,cardinal cubeSide)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
if (ResourceManager->FrameManager.FrameMap.count(frameName) > 0)
|
if (ResourceManager->FrameManager.FrameMap.count(frameName) > 0)
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,8 @@ namespace SE
|
|||||||
|
|
||||||
void TSalmonRendererIos::SwitchToScreen()
|
void TSalmonRendererIos::SwitchToScreen()
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
IosSwitchToScreen();
|
IosSwitchToScreen();
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
@ -30,6 +30,8 @@ TSalmonRenderer::~TSalmonRenderer()
|
|||||||
|
|
||||||
bool TSalmonRenderer::BindOpenGLFunctions()
|
bool TSalmonRenderer::BindOpenGLFunctions()
|
||||||
{
|
{
|
||||||
|
//AssertIfInMainThread();
|
||||||
|
|
||||||
char* extensionList = (char*)glGetString(GL_EXTENSIONS);
|
char* extensionList = (char*)glGetString(GL_EXTENSIONS);
|
||||||
char* glVersion = (char*)glGetString(GL_VERSION);
|
char* glVersion = (char*)glGetString(GL_VERSION);
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
@ -250,6 +252,8 @@ bool TSalmonRenderer::BindOpenGLFunctions()
|
|||||||
|
|
||||||
void TSalmonRenderer::DrawQuad(const T2DQuad& quad)
|
void TSalmonRenderer::DrawQuad(const T2DQuad& quad)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
const float CONST_DEFAULT_NORM_VEC[3] = { 0.0f, 0.0f, 1.0f};
|
const float CONST_DEFAULT_NORM_VEC[3] = { 0.0f, 0.0f, 1.0f};
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
@ -313,6 +317,8 @@ vec4 TSalmonRenderer::GetFogColor()
|
|||||||
|
|
||||||
void TSalmonRenderer::DrawTriangleList(const TTriangleList& triangleList)
|
void TSalmonRenderer::DrawTriangleList(const TTriangleList& triangleList)
|
||||||
{
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
BOOST_FOREACH(auto& i, triangleList.Data.Vec2CoordArr)
|
BOOST_FOREACH(auto& i, triangleList.Data.Vec2CoordArr)
|
||||||
{
|
{
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, triangleList.VertBufferArr[i.first]->Buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, triangleList.VertBufferArr[i.first]->Buffer);
|
||||||
|
@ -15,6 +15,8 @@ void TApplication::OuterInit(int screenWidth, int screenHeight, float matrixWidt
|
|||||||
|
|
||||||
ResourceManager = new TResourceManager;
|
ResourceManager = new TResourceManager;
|
||||||
|
|
||||||
|
ResourceManager->MainThreadId = boost::this_thread::get_id();
|
||||||
|
|
||||||
Renderer = new TSalmonRendererAndroid;
|
Renderer = new TSalmonRendererAndroid;
|
||||||
|
|
||||||
ResourceManager->ScriptManager.BindBasicFunctions();
|
ResourceManager->ScriptManager.BindBasicFunctions();
|
||||||
|
@ -74,6 +74,8 @@ void TApplicationAncestor::OuterDeinit()
|
|||||||
|
|
||||||
void TApplicationAncestor::OuterDraw()
|
void TApplicationAncestor::OuterDraw()
|
||||||
{
|
{
|
||||||
|
TryUpdateMainThreadId();
|
||||||
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
@ -103,6 +105,8 @@ void TApplicationAncestor::OuterDraw()
|
|||||||
|
|
||||||
void TApplicationAncestor::OuterUpdate(cardinal timer)
|
void TApplicationAncestor::OuterUpdate(cardinal timer)
|
||||||
{
|
{
|
||||||
|
TryUpdateMainThreadId();
|
||||||
|
|
||||||
ResourceManager->Update(timer);
|
ResourceManager->Update(timer);
|
||||||
|
|
||||||
InnerUpdate(timer);
|
InnerUpdate(timer);
|
||||||
|
@ -23,9 +23,27 @@ TTextureListClass::TTextureListClass()
|
|||||||
CreateFunctionMap[".png"] = boost::bind(&TTextureListClass::CreateTexDataFromPng, this, _1, _2);
|
CreateFunctionMap[".png"] = boost::bind(&TTextureListClass::CreateTexDataFromPng, this, _1, _2);
|
||||||
CreateFunctionMap[".tga"] = boost::bind(&TTextureListClass::CreateTexDataFromTga, this, _1, _2);
|
CreateFunctionMap[".tga"] = boost::bind(&TTextureListClass::CreateTexDataFromTga, this, _1, _2);
|
||||||
|
|
||||||
|
/*
|
||||||
AddFunctionMap["bmp24"] = boost::bind(&TTextureListClass::AddTextureBmp24Data, this, _1);
|
AddFunctionMap["bmp24"] = boost::bind(&TTextureListClass::AddTextureBmp24Data, this, _1);
|
||||||
AddFunctionMap["bmp32"] = boost::bind(&TTextureListClass::AddTextureBmp32Data, this, _1);
|
AddFunctionMap["bmp32"] = boost::bind(&TTextureListClass::AddTextureBmp32Data, this, _1);
|
||||||
|
|
||||||
|
Let's use inner functions!
|
||||||
|
*/
|
||||||
|
|
||||||
|
AddFunctionMap["bmp24"] = [this](TTextureData& texData) -> cardinal
|
||||||
|
{
|
||||||
|
boost::function<cardinal()> f = boost::bind(&TTextureListClass::AddTextureBmp24Data, this, texData);
|
||||||
|
return PerformInMainThread<cardinal>(f);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
AddFunctionMap["bmp32"] = [this](TTextureData& texData) -> cardinal
|
||||||
|
{
|
||||||
|
boost::function<cardinal()> f = boost::bind(&TTextureListClass::AddTextureBmp32Data, this, texData);
|
||||||
|
return PerformInMainThread<cardinal>(f);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TTextureListClass::~TTextureListClass()
|
TTextureListClass::~TTextureListClass()
|
||||||
@ -40,6 +58,171 @@ void TTextureListClass::Clear()
|
|||||||
PerformInMainThreadAsync(boost::bind(&TTextureListClass::InnerClear, this));
|
PerformInMainThreadAsync(boost::bind(&TTextureListClass::InnerClear, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cardinal TTextureListClass::InnerAddEmptyTexture(const std::string& texName, cardinal width, cardinal height)
|
||||||
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
|
cardinal texID;
|
||||||
|
|
||||||
|
if (TexMap.count(texName) == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
glGenTextures(1, &texID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texID);
|
||||||
|
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
#ifdef TARGET_WIN32
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TARGET_WIN32 //TARGET_ANDROID or TARGET_IOS
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TexMap[texName].RefCount++;
|
||||||
|
texID = TexMap[texName].TexID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return texID;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
cardinal TTextureListClass::InnerAddEmptyCubemapTexture(const std::string& texName, cardinal width, cardinal height)
|
||||||
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
|
cardinal texID;
|
||||||
|
|
||||||
|
if (TexMap.count(texName) == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
glGenTextures(1, &texID);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
|
||||||
|
|
||||||
|
#ifdef TARGET_WIN32
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+0, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+1, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+2, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+3, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+4, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+5, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TARGET_WIN32 //TARGET_IOS or TARGET_ANDROID
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+0, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+1, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+2, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+3, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+4, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+5, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TexMap[texName].RefCount++;
|
||||||
|
texID = TexMap[texName].TexID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return texID;
|
||||||
|
}
|
||||||
|
|
||||||
|
cardinal TTextureListClass::InnerAddDepthTexture(const std::string& texName, cardinal width, cardinal height)
|
||||||
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TARGET_WIN32
|
||||||
|
cardinal texID;
|
||||||
|
|
||||||
|
if (TexMap.count(texName) == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
glGenTextures(1, &texID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texID);
|
||||||
|
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TexMap[texName].RefCount++;
|
||||||
|
texID = TexMap[texName].TexID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return texID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TARGET_ANDROID
|
||||||
|
|
||||||
|
throw ErrorToLog("Trying to create depth texture on Android!!!");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_IOS
|
||||||
|
|
||||||
|
throw ErrorToLog("Trying to create depth texture on iOS!!!");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TTextureListClass::InnerDeleteTexture(TTextureMap::iterator itr)
|
||||||
|
{
|
||||||
|
AssertIfInMainThread();
|
||||||
|
|
||||||
|
(itr->second.RefCount)--;
|
||||||
|
|
||||||
|
if (itr->second.RefCount == 0)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &(itr->second.TexID));
|
||||||
|
|
||||||
|
*Console << "ResourceManager::TexList texture " + (itr->first) + " deleted";
|
||||||
|
|
||||||
|
TexMap.erase(itr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*Console<<"ResourceManager::TexList texture "+(itr->first)+" reference deleted";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TTextureListClass::InnerClear()
|
void TTextureListClass::InnerClear()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -64,12 +247,10 @@ void TTextureListClass::Serialize(boost::property_tree::ptree& propertyTree)
|
|||||||
|
|
||||||
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, propertyTree.get_child("Textures"))
|
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, propertyTree.get_child("Textures"))
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string fileName = v.second.get<std::string>("FileName");
|
std::string fileName = v.second.get<std::string>("FileName");
|
||||||
std::string texName = v.second.get<std::string>("TexName", "");
|
std::string texName = v.second.get<std::string>("TexName", "");
|
||||||
|
|
||||||
AddTexture(fileName, texName);
|
AddTexture(fileName, texName);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,8 +391,6 @@ bool TTextureListClass::CreateTexDataFromBmp32(const std::string& filename, TTex
|
|||||||
texData.Data[x + 3] = fileArr[pos++];
|
texData.Data[x + 3] = fileArr[pos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
//delete [] fileArr;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +594,6 @@ cardinal TTextureListClass::AddTextureBmp24Data(const TTextureData& texData)
|
|||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, TexID);
|
glBindTexture(GL_TEXTURE_2D, TexID);
|
||||||
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
@ -502,8 +680,6 @@ cardinal TTextureListClass::GetTextureWidth(const std::string& texName)
|
|||||||
|
|
||||||
cardinal TTextureListClass::AddTextureDirectly(const std::string& filename, std::string texName)
|
cardinal TTextureListClass::AddTextureDirectly(const std::string& filename, std::string texName)
|
||||||
{
|
{
|
||||||
AssertIfInMainThread();
|
|
||||||
|
|
||||||
cardinal TexID;
|
cardinal TexID;
|
||||||
|
|
||||||
if (texName == "")
|
if (texName == "")
|
||||||
@ -520,22 +696,18 @@ cardinal TTextureListClass::AddTextureDirectly(const std::string& filename, std:
|
|||||||
std::string texext = GetFileExt(filename);
|
std::string texext = GetFileExt(filename);
|
||||||
|
|
||||||
TTextureData texData;
|
TTextureData texData;
|
||||||
if (CreateFunctionMap[texext](filename,texData))
|
if (CreateFunctionMap[texext](filename, texData))
|
||||||
{
|
{
|
||||||
|
|
||||||
NormalizeTexData(texData);
|
NormalizeTexData(texData);
|
||||||
TexID = AddFunctionMap[std::string(texData.Format)](texData);
|
TexID = AddFunctionMap[std::string(texData.Format)](texData);
|
||||||
|
|
||||||
if (TexID != 0)
|
*Console<<"ResourceManager::TexList Texture added: "+texName+" with id = "+tostr(TexID);
|
||||||
{
|
TexMap[texName].RefCount = 1;
|
||||||
*Console<<"ResourceManager::TexList Texture added: "+texName+" with id = "+tostr(TexID);
|
TexMap[texName].TexID = TexID;
|
||||||
TexMap[texName].RefCount = 1;
|
TexMap[texName].Width = texData.Width;
|
||||||
TexMap[texName].TexID = TexID;
|
TexMap[texName].Height = texData.Height;
|
||||||
TexMap[texName].Width = texData.Width;
|
|
||||||
TexMap[texName].Height = texData.Height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*Console<<"ResourceManager::TexList ERROR - TEXTURE ADD TO OPENGL FAILED: "+texName;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -565,16 +737,13 @@ cardinal TTextureListClass::AddTexture(const std::string& fileName, std::string
|
|||||||
{
|
{
|
||||||
std::string fullFileName = ResourceManager->PathToResources + fileName;
|
std::string fullFileName = ResourceManager->PathToResources + fileName;
|
||||||
|
|
||||||
boost::function<cardinal()> f = boost::bind(&TTextureListClass::AddTextureDirectly, this, fullFileName, texName);
|
return AddTextureDirectly(fullFileName, texName);
|
||||||
|
|
||||||
return PerformInMainThread<cardinal>(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cardinal TTextureListClass::AddTextureFromUserdata(const std::string& fileName, std::string texName)
|
cardinal TTextureListClass::AddTextureFromUserdata(const std::string& fileName, std::string texName)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
if (!IsFileExistsInUserData(fileName))
|
if (!IsFileExistsInUserData(fileName))
|
||||||
{
|
{
|
||||||
throw ErrorToLog("File not found in userdata: "+fileName);
|
throw ErrorToLog("File not found in userdata: "+fileName);
|
||||||
@ -582,16 +751,12 @@ cardinal TTextureListClass::AddTextureFromUserdata(const std::string& fileName,
|
|||||||
|
|
||||||
std::string fullFileName = GetFilePathUserData(fileName);
|
std::string fullFileName = GetFilePathUserData(fileName);
|
||||||
|
|
||||||
|
return AddTextureDirectly(fullFileName, texName);
|
||||||
boost::function<cardinal()> f = boost::bind(&TTextureListClass::AddTextureDirectly, this, fullFileName, texName);
|
|
||||||
|
|
||||||
return PerformInMainThread<cardinal>(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cardinal TTextureListClass::AddCubemapTexture(std::string filename[6])
|
cardinal TTextureListClass::AddCubemapTexture(std::string filename[6])
|
||||||
{
|
{
|
||||||
AssertIfInMainThread();
|
|
||||||
|
|
||||||
filename[0] = ResourceManager->PathToResources + filename[0];
|
filename[0] = ResourceManager->PathToResources + filename[0];
|
||||||
filename[1] = ResourceManager->PathToResources + filename[1];
|
filename[1] = ResourceManager->PathToResources + filename[1];
|
||||||
@ -620,11 +785,9 @@ cardinal TTextureListClass::AddCubemapTexture(std::string filename[6])
|
|||||||
*Console<<"ResourceManager::TexList ERROR - TEXTURE LOAD FAILED: "+texname;
|
*Console<<"ResourceManager::TexList ERROR - TEXTURE LOAD FAILED: "+texname;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
*Console<<"ResourceManager::TexList ERROR - FORMAT NOT SUPPORTED: "+texext;
|
*Console<<"ResourceManager::TexList ERROR - FORMAT NOT SUPPORTED: "+texext;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -633,9 +796,9 @@ cardinal TTextureListClass::AddCubemapTexture(std::string filename[6])
|
|||||||
|
|
||||||
//All textures have been inserted into texData[6], lets add them
|
//All textures have been inserted into texData[6], lets add them
|
||||||
|
|
||||||
TexID = AddCubemapTextureBmp24Data(texData);
|
boost::function<cardinal()> f = boost::bind(&TTextureListClass::AddCubemapTextureBmp24Data, this, texData);
|
||||||
|
|
||||||
//for (int j = 0; j < 6; j++) delete [] texData[j].Data;
|
TexID = PerformInMainThread<cardinal>(f);
|
||||||
|
|
||||||
if (TexID != 0)
|
if (TexID != 0)
|
||||||
{
|
{
|
||||||
@ -661,197 +824,48 @@ cardinal TTextureListClass::AddCubemapTexture(std::string filename[6])
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cardinal TTextureListClass::AddEmptyTexture(const std::string& texName,cardinal width,cardinal height)
|
cardinal TTextureListClass::AddEmptyTexture(const std::string& texName, cardinal width, cardinal height)
|
||||||
{
|
{
|
||||||
AssertIfInMainThread();
|
boost::function<cardinal()> f = boost::bind(&TTextureListClass::InnerAddEmptyTexture, this, texName, width, height);
|
||||||
|
|
||||||
cardinal texID;
|
|
||||||
|
|
||||||
if (TexMap.count(texName) == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
glGenTextures(1, &texID);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texID);
|
|
||||||
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
|
|
||||||
#ifdef TARGET_WIN32
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TARGET_WIN32 //TARGET_ANDROID or TARGET_IOS
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TexMap[texName].RefCount++;
|
|
||||||
texID = TexMap[texName].TexID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return texID;
|
|
||||||
|
|
||||||
|
return PerformInMainThread<cardinal>(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cardinal TTextureListClass::AddEmptyCubemapTexture(const std::string& texName,cardinal width,cardinal height)
|
cardinal TTextureListClass::AddEmptyCubemapTexture(const std::string& texName, cardinal width, cardinal height)
|
||||||
{
|
{
|
||||||
AssertIfInMainThread();
|
boost::function<cardinal()> f = boost::bind(&TTextureListClass::InnerAddEmptyCubemapTexture, this, texName, width, height);
|
||||||
|
|
||||||
cardinal texID;
|
return PerformInMainThread<cardinal>(f);
|
||||||
|
|
||||||
if (TexMap.count(texName) == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
glGenTextures(1, &texID);
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
|
|
||||||
|
|
||||||
#ifdef TARGET_WIN32
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+0, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+1, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+2, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+3, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+4, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+5, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TARGET_WIN32 //TARGET_IOS or TARGET_ANDROID
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+0, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+1, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+2, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+3, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+4, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+5, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TexMap[texName].RefCount++;
|
|
||||||
texID = TexMap[texName].TexID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return texID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cardinal TTextureListClass::AddDepthTexture(const std::string& texName,cardinal width,cardinal height)
|
cardinal TTextureListClass::AddDepthTexture(const std::string& texName, cardinal width, cardinal height)
|
||||||
{
|
{
|
||||||
AssertIfInMainThread();
|
boost::function<cardinal()> f = boost::bind(&TTextureListClass::InnerAddEmptyCubemapTexture, this, texName, width, height);
|
||||||
|
|
||||||
#ifdef TARGET_WIN32
|
|
||||||
cardinal texID;
|
|
||||||
|
|
||||||
if (TexMap.count(texName) == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
glGenTextures(1, &texID);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texID);
|
|
||||||
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TexMap[texName].RefCount++;
|
|
||||||
texID = TexMap[texName].TexID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return texID;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TARGET_ANDROID
|
|
||||||
|
|
||||||
throw ErrorToLog("Trying to create depth texture on Android!!!");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#ifdef TARGET_IOS
|
|
||||||
|
|
||||||
throw ErrorToLog("Trying to create depth texture on iOS!!!");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
return PerformInMainThread<cardinal>(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTextureListClass::DeleteTexture(const std::string& texName)
|
void TTextureListClass::DeleteTexture(const std::string& texName)
|
||||||
{
|
{
|
||||||
AssertIfInMainThread();
|
|
||||||
|
|
||||||
if (TexMap.count(texName) != 0)
|
if (TexMap.count(texName) != 0)
|
||||||
{
|
{
|
||||||
--TexMap[texName].RefCount;
|
InnerDeleteTexture(TexMap.find(texName));
|
||||||
|
|
||||||
if (TexMap[texName].RefCount == 0)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1,&(TexMap[texName].TexID));
|
|
||||||
TexMap.erase(texName);
|
|
||||||
*Console<<"ResourceManager::TexList texture "+texName+" deleted";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*Console<<"ResourceManager::TexList texture "+texName+" reference deleted";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TTextureListClass::DeleteTexture(cardinal texID)
|
void TTextureListClass::DeleteTexture(cardinal texID)
|
||||||
{
|
{
|
||||||
AssertIfInMainThread();
|
|
||||||
|
|
||||||
TTextureMap::iterator i = TexMap.begin();
|
TTextureMap::iterator i = TexMap.begin();
|
||||||
|
|
||||||
while (i != TexMap.end())
|
while (i != TexMap.end())
|
||||||
{
|
{
|
||||||
if (i->second.TexID == texID)
|
if (i->second.TexID == texID)
|
||||||
{
|
{
|
||||||
(i->second.RefCount)--;
|
InnerDeleteTexture(i);
|
||||||
|
|
||||||
if (i->second.RefCount == 0)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1,&(i->second.TexID));
|
|
||||||
|
|
||||||
*Console << "ResourceManager::TexList texture " + (i->first) + " deleted";
|
|
||||||
|
|
||||||
TexMap.erase(i);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*Console<<"ResourceManager::TexList texture "+(i->first)+" reference deleted";
|
|
||||||
|
|
||||||
i = TexMap.end(); //to go out of loop
|
i = TexMap.end(); //to go out of loop
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,15 @@ namespace SE
|
|||||||
{
|
{
|
||||||
if (boost::this_thread::get_id() != ResourceManager->MainThreadId)
|
if (boost::this_thread::get_id() != ResourceManager->MainThreadId)
|
||||||
{
|
{
|
||||||
throw ErrorToLog("ERROR! AssertIfInMainThread failed!");
|
throw ErrorToLog("ERROR! AssertIfInMainThread - assert failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TryUpdateMainThreadId()
|
||||||
|
{
|
||||||
|
if (boost::this_thread::get_id() != ResourceManager->MainThreadId)
|
||||||
|
{
|
||||||
|
ResourceManager->MainThreadId = boost::this_thread::get_id();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user