BGE: Code clean up for world (mist, background, ambient)
Code clean up for BGE world mist, background and global ambient color. Move mist render update to BlenderWolrdInfo Reviewers: moguri, brecht Reviewed By: moguri, brecht Differential Revision: https://developer.blender.org/D152
This commit is contained in:
parent
c73693d4a5
commit
931c3e6544
@ -446,7 +446,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
|
||||
rasterizer->SetEyeSeparation(scene->gm.eyeseparation);
|
||||
}
|
||||
|
||||
rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f);
|
||||
rasterizer->SetBackColor(scene->gm.framing.col);
|
||||
}
|
||||
|
||||
if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include <stdio.h> // printf()
|
||||
|
||||
#include "BlenderWorldInfo.h"
|
||||
#include "KX_PythonInit.h"
|
||||
#include "GPU_material.h"
|
||||
|
||||
/* This little block needed for linking to Blender... */
|
||||
#ifdef WIN32
|
||||
@ -40,23 +42,7 @@
|
||||
#endif
|
||||
|
||||
/* This list includes only data type definitions */
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_image_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_property_types.h"
|
||||
#include "DNA_text_types.h"
|
||||
#include "DNA_sensor_types.h"
|
||||
#include "DNA_controller_types.h"
|
||||
#include "DNA_actuator_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
@ -65,7 +51,7 @@
|
||||
/* end of blender include block */
|
||||
|
||||
|
||||
BlenderWorldInfo::BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld)
|
||||
BlenderWorldInfo::BlenderWorldInfo(Scene *blenderscene, World *blenderworld)
|
||||
{
|
||||
if (blenderworld) {
|
||||
m_hasworld = true;
|
||||
@ -212,3 +198,38 @@ void BlenderWorldInfo::setAmbientColor(float r, float g, float b)
|
||||
m_ambientcolor[1] = g;
|
||||
m_ambientcolor[2] = b;
|
||||
}
|
||||
|
||||
void BlenderWorldInfo::UpdateBackGround()
|
||||
{
|
||||
if (m_hasworld) {
|
||||
RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer();
|
||||
|
||||
if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) {
|
||||
m_rasterizer->SetBackColor(m_backgroundcolor);
|
||||
GPU_horizon_update_color(m_backgroundcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlenderWorldInfo::UpdateWorldSettings()
|
||||
{
|
||||
if (m_hasworld) {
|
||||
RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer();
|
||||
|
||||
if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) {
|
||||
m_rasterizer->SetAmbientColor(m_ambientcolor);
|
||||
GPU_ambient_update_color(m_ambientcolor);
|
||||
|
||||
if (m_hasmist) {
|
||||
m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor);
|
||||
GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor);
|
||||
m_rasterizer->EnableFog(true);
|
||||
GPU_mist_update_enable(true);
|
||||
}
|
||||
else {
|
||||
m_rasterizer->EnableFog(false);
|
||||
GPU_mist_update_enable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,37 +31,33 @@
|
||||
|
||||
#ifndef __BLENDERWORLDINFO_H__
|
||||
#define __BLENDERWORLDINFO_H__
|
||||
#include "MT_CmMatrix4x4.h"
|
||||
#include "KX_WorldInfo.h"
|
||||
#include "KX_KetsjiEngine.h"
|
||||
#include "RAS_IRasterizer.h"
|
||||
|
||||
struct Scene;
|
||||
struct World;
|
||||
const class KX_KetsjiEngine;
|
||||
const class RAS_IRasterizer;
|
||||
|
||||
class BlenderWorldInfo : public KX_WorldInfo
|
||||
{
|
||||
bool m_hasworld;
|
||||
float m_backgroundcolor[3];
|
||||
|
||||
bool m_hasmist;
|
||||
short m_misttype;
|
||||
float m_miststart;
|
||||
float m_mistdistance;
|
||||
float m_mistintensity;
|
||||
float m_mistcolor[3];
|
||||
|
||||
float m_backgroundcolor[3];
|
||||
float m_ambientcolor[3];
|
||||
|
||||
public:
|
||||
BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld);
|
||||
BlenderWorldInfo(Scene *blenderscene, World *blenderworld);
|
||||
~BlenderWorldInfo();
|
||||
|
||||
bool hasWorld();
|
||||
bool hasMist();
|
||||
float getBackColorRed();
|
||||
float getBackColorGreen();
|
||||
float getBackColorBlue();
|
||||
|
||||
float getAmbientColorRed();
|
||||
float getAmbientColorGreen();
|
||||
float getAmbientColorBlue();
|
||||
|
||||
short getMistType();
|
||||
float getMistStart();
|
||||
float getMistDistance();
|
||||
@ -69,7 +65,12 @@ public:
|
||||
float getMistColorRed();
|
||||
float getMistColorGreen();
|
||||
float getMistColorBlue();
|
||||
|
||||
float getBackColorRed();
|
||||
float getBackColorGreen();
|
||||
float getBackColorBlue();
|
||||
float getAmbientColorRed();
|
||||
float getAmbientColorGreen();
|
||||
float getAmbientColorBlue();
|
||||
void setBackColor(float r, float g, float b);
|
||||
void setUseMist(bool enable);
|
||||
void setMistType(short type);
|
||||
@ -78,7 +79,8 @@ public:
|
||||
void setMistIntensity(float intensity);
|
||||
void setMistColor(float r, float g, float b);
|
||||
void setAmbientColor(float r, float g, float b);
|
||||
|
||||
void UpdateBackGround();
|
||||
void UpdateWorldSettings();
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("GE:BlenderWorldInfo")
|
||||
|
@ -80,8 +80,6 @@
|
||||
|
||||
#include "KX_NavMeshObject.h"
|
||||
|
||||
#include "GPU_material.h"
|
||||
|
||||
#define DEFAULT_LOGIC_TIC_RATE 60.0
|
||||
//#define DEFAULT_PHYSICS_TIC_RATE 60.0
|
||||
|
||||
@ -317,7 +315,7 @@ void KX_KetsjiEngine::RenderDome()
|
||||
KX_Camera* cam = scene->GetActiveCamera();
|
||||
|
||||
// pass the scene's worldsettings to the rasterizer
|
||||
SetWorldSettings(scene->GetWorldInfo());
|
||||
scene->GetWorldInfo()->UpdateWorldSettings();
|
||||
|
||||
// shadow buffers
|
||||
if (i == 0) {
|
||||
@ -477,7 +475,7 @@ void KX_KetsjiEngine::ClearFrame()
|
||||
|
||||
if (doclear) {
|
||||
KX_Scene* firstscene = *m_scenes.begin();
|
||||
SetBackGround(firstscene->GetWorldInfo());
|
||||
firstscene->GetWorldInfo()->UpdateBackGround();
|
||||
|
||||
m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(),
|
||||
clearvp.GetRight(), clearvp.GetTop());
|
||||
@ -827,7 +825,7 @@ void KX_KetsjiEngine::Render()
|
||||
KX_Scene* scene = *sceneit;
|
||||
KX_Camera* cam = scene->GetActiveCamera();
|
||||
// pass the scene's worldsettings to the rasterizer
|
||||
SetWorldSettings(scene->GetWorldInfo());
|
||||
scene->GetWorldInfo()->UpdateWorldSettings();
|
||||
|
||||
// this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes
|
||||
//scene->UpdateMeshTransformations();
|
||||
@ -884,7 +882,7 @@ void KX_KetsjiEngine::Render()
|
||||
KX_Camera* cam = scene->GetActiveCamera();
|
||||
|
||||
// pass the scene's worldsettings to the rasterizer
|
||||
SetWorldSettings(scene->GetWorldInfo());
|
||||
scene->GetWorldInfo()->UpdateWorldSettings();
|
||||
|
||||
if (scene->IsClearingZBuffer())
|
||||
m_rasterizer->ClearDepthBuffer();
|
||||
@ -964,77 +962,6 @@ const STR_String& KX_KetsjiEngine::GetExitString()
|
||||
return m_exitstring;
|
||||
}
|
||||
|
||||
|
||||
void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi)
|
||||
{
|
||||
if (wi->hasWorld())
|
||||
{
|
||||
if (m_rasterizer->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
|
||||
{
|
||||
m_rasterizer->SetBackColor(
|
||||
wi->getBackColorRed(),
|
||||
wi->getBackColorGreen(),
|
||||
wi->getBackColorBlue(),
|
||||
0.0
|
||||
);
|
||||
|
||||
float horicolor[] = {wi->getBackColorRed(), wi->getBackColorGreen(), wi->getBackColorBlue()};
|
||||
GPU_horizon_update_color(horicolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
|
||||
{
|
||||
if (wi->hasWorld())
|
||||
{
|
||||
if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID)
|
||||
{
|
||||
m_rasterizer->SetAmbientColor(
|
||||
wi->getAmbientColorRed(),
|
||||
wi->getAmbientColorGreen(),
|
||||
wi->getAmbientColorBlue()
|
||||
);
|
||||
|
||||
float ambcolor[] = {wi->getAmbientColorRed(), wi->getAmbientColorGreen(), wi->getAmbientColorBlue()};
|
||||
GPU_ambient_update_color(ambcolor);
|
||||
|
||||
if (wi->hasMist())
|
||||
{
|
||||
m_rasterizer->SetFog(
|
||||
wi->getMistType(),
|
||||
wi->getMistStart(),
|
||||
wi->getMistDistance(),
|
||||
wi->getMistIntensity(),
|
||||
wi->getMistColorRed(),
|
||||
wi->getMistColorGreen(),
|
||||
wi->getMistColorBlue()
|
||||
);
|
||||
|
||||
float mistcolor[] = {wi->getMistColorRed(), wi->getMistColorGreen(), wi->getMistColorBlue()};
|
||||
GPU_mist_update_values(
|
||||
wi->getMistType(),
|
||||
wi->getMistStart(),
|
||||
wi->getMistDistance(),
|
||||
wi->getMistIntensity(),
|
||||
mistcolor
|
||||
);
|
||||
|
||||
m_rasterizer->EnableFog(true);
|
||||
GPU_mist_update_enable(true);
|
||||
}
|
||||
else {
|
||||
m_rasterizer->EnableFog(false);
|
||||
GPU_mist_update_enable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
|
||||
{
|
||||
m_overrideCam = true;
|
||||
|
@ -205,14 +205,12 @@ private:
|
||||
void PostRenderScene(KX_Scene* scene);
|
||||
void RenderDebugProperties();
|
||||
void RenderShadowBuffers(KX_Scene *scene);
|
||||
void SetBackGround(KX_WorldInfo* worldinfo);
|
||||
|
||||
public:
|
||||
KX_KetsjiEngine(class KX_ISystem* system);
|
||||
virtual ~KX_KetsjiEngine();
|
||||
|
||||
// set the devices and stuff. the client must take care of creating these
|
||||
void SetWorldSettings(KX_WorldInfo* worldinfo);
|
||||
void SetKeyboardDevice(SCA_IInputDevice* keyboarddevice);
|
||||
void SetMouseDevice(SCA_IInputDevice* mousedevice);
|
||||
void SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice);
|
||||
|
@ -57,9 +57,6 @@ public:
|
||||
|
||||
virtual bool hasWorld() = 0;
|
||||
virtual bool hasMist() = 0;
|
||||
virtual float getBackColorRed() = 0;
|
||||
virtual float getBackColorGreen() = 0;
|
||||
virtual float getBackColorBlue() = 0;
|
||||
virtual short getMistType() = 0;
|
||||
virtual float getMistStart() = 0;
|
||||
virtual float getMistDistance() = 0;
|
||||
@ -67,11 +64,12 @@ public:
|
||||
virtual float getMistColorRed() = 0;
|
||||
virtual float getMistColorGreen() = 0;
|
||||
virtual float getMistColorBlue() = 0;
|
||||
|
||||
virtual float getBackColorRed() = 0;
|
||||
virtual float getBackColorGreen() = 0;
|
||||
virtual float getBackColorBlue() = 0;
|
||||
virtual float getAmbientColorRed() = 0;
|
||||
virtual float getAmbientColorGreen() = 0;
|
||||
virtual float getAmbientColorBlue() = 0;
|
||||
|
||||
virtual void setUseMist(bool enable) = 0;
|
||||
virtual void setMistType(short) = 0;
|
||||
virtual void setMistStart(float) = 0;
|
||||
@ -80,7 +78,8 @@ public:
|
||||
virtual void setMistColor(float, float, float) = 0;
|
||||
virtual void setBackColor(float, float, float) = 0;
|
||||
virtual void setAmbientColor(float,float,float) = 0;
|
||||
|
||||
virtual void UpdateBackGround() = 0;
|
||||
virtual void UpdateWorldSettings() = 0;
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_WorldInfo")
|
||||
|
@ -297,15 +297,11 @@ public:
|
||||
/**
|
||||
* Fog
|
||||
*/
|
||||
virtual void SetFog(short type, float start, float dist, float intensity, float r, float g, float b) = 0;
|
||||
virtual void SetFogColor(float r, float g,float b) = 0;
|
||||
virtual void SetFogStart(float start) = 0;
|
||||
virtual void SetFogEnd(float end) = 0;
|
||||
virtual void SetFog(short type, float start, float dist, float intensity, float color[3]) = 0;
|
||||
virtual void DisplayFog() = 0;
|
||||
virtual void EnableFog(bool enable) = 0;
|
||||
virtual bool IsFogEnabled() = 0;
|
||||
|
||||
virtual void SetBackColor(float red, float green, float blue, float alpha) = 0;
|
||||
virtual void SetBackColor(float color[3]) = 0;
|
||||
|
||||
/**
|
||||
* \param drawingmode = KX_BOUNDINGBOX, KX_WIREFRAME, KX_SOLID, KX_SHADED or KX_TEXTURED.
|
||||
@ -380,7 +376,7 @@ public:
|
||||
*/
|
||||
virtual void SetEmissive(float eX, float eY, float eZ, float e) = 0;
|
||||
|
||||
virtual void SetAmbientColor(float red, float green, float blue) = 0;
|
||||
virtual void SetAmbientColor(float color[3]) = 0;
|
||||
virtual void SetAmbient(float factor) = 0;
|
||||
|
||||
/**
|
||||
|
@ -194,109 +194,52 @@ bool RAS_OpenGLRasterizer::Init()
|
||||
}
|
||||
|
||||
|
||||
void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue)
|
||||
void RAS_OpenGLRasterizer::SetAmbientColor(float color[3])
|
||||
{
|
||||
m_ambr = red;
|
||||
m_ambg = green;
|
||||
m_ambb = blue;
|
||||
m_ambr = color[0];
|
||||
m_ambg = color[1];
|
||||
m_ambb = color[2];
|
||||
}
|
||||
|
||||
|
||||
void RAS_OpenGLRasterizer::SetAmbient(float factor)
|
||||
{
|
||||
float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f };
|
||||
float ambient[] = {m_ambr * factor, m_ambg * factor, m_ambb * factor, 1.0f};
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
|
||||
}
|
||||
|
||||
|
||||
void RAS_OpenGLRasterizer::SetBackColor(float red,
|
||||
float green,
|
||||
float blue,
|
||||
float alpha)
|
||||
void RAS_OpenGLRasterizer::SetBackColor(float color[3])
|
||||
{
|
||||
m_redback = red;
|
||||
m_greenback = green;
|
||||
m_blueback = blue;
|
||||
m_alphaback = alpha;
|
||||
m_redback = color[0];
|
||||
m_greenback = color[1];
|
||||
m_blueback = color[2];
|
||||
m_alphaback = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RAS_OpenGLRasterizer::SetFogColor(float r,
|
||||
float g,
|
||||
float b)
|
||||
void RAS_OpenGLRasterizer::SetFog(short type, float start, float dist, float intensity, float color[3])
|
||||
{
|
||||
m_fogr = r;
|
||||
m_fogg = g;
|
||||
m_fogb = b;
|
||||
float params[4] = {color[0], color[1], color[2], 1.0f};
|
||||
glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
glFogf(GL_FOG_DENSITY, intensity / 10.0f);
|
||||
glFogf(GL_FOG_START, start);
|
||||
glFogf(GL_FOG_END, start + dist);
|
||||
glFogfv(GL_FOG_COLOR, params);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RAS_OpenGLRasterizer::SetFogStart(float start)
|
||||
{
|
||||
m_fogstart = start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RAS_OpenGLRasterizer::SetFogEnd(float fogend)
|
||||
{
|
||||
m_fogdist = fogend;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RAS_OpenGLRasterizer::SetFog(short type,
|
||||
float start,
|
||||
float dist,
|
||||
float intensity,
|
||||
float r,
|
||||
float g,
|
||||
float b)
|
||||
{
|
||||
m_fogtype = type;
|
||||
m_fogstart = start;
|
||||
m_fogdist = dist;
|
||||
m_fogintensity = intensity;
|
||||
m_fogr = r;
|
||||
m_fogg = g;
|
||||
m_fogb = b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RAS_OpenGLRasterizer::EnableFog(bool enable)
|
||||
{
|
||||
m_fogenabled = enable;
|
||||
}
|
||||
|
||||
bool RAS_OpenGLRasterizer::IsFogEnabled()
|
||||
{
|
||||
return m_fogenabled;
|
||||
}
|
||||
|
||||
|
||||
void RAS_OpenGLRasterizer::DisplayFog()
|
||||
{
|
||||
if ((m_drawingmode >= KX_SOLID) && m_fogenabled)
|
||||
{
|
||||
float params[4] = {m_fogr, m_fogg, m_fogb, 1.0f};
|
||||
glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
glFogf(GL_FOG_DENSITY, m_fogintensity / 10.0f);
|
||||
glFogf(GL_FOG_START, m_fogstart);
|
||||
glFogf(GL_FOG_END, m_fogstart + m_fogdist);
|
||||
glFogfv(GL_FOG_COLOR, params);
|
||||
if ((m_drawingmode >= KX_SOLID) && m_fogenabled) {
|
||||
glEnable(GL_FOG);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else {
|
||||
glDisable(GL_FOG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
|
||||
{
|
||||
return mat.Activate(this, m_materialCachingInfo);
|
||||
|
@ -80,14 +80,7 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer
|
||||
|
||||
/* fogging vars */
|
||||
bool m_fogenabled;
|
||||
short m_fogtype;
|
||||
float m_fogstart;
|
||||
float m_fogdist;
|
||||
float m_fogintensity;
|
||||
float m_fogr;
|
||||
float m_fogg;
|
||||
float m_fogb;
|
||||
|
||||
|
||||
float m_redback;
|
||||
float m_greenback;
|
||||
float m_blueback;
|
||||
@ -200,16 +193,12 @@ public:
|
||||
virtual const MT_Point3& GetCameraPosition();
|
||||
virtual bool GetCameraOrtho();
|
||||
|
||||
virtual void SetFog(short type, float start, float dist, float intensity, float r, float g, float b);
|
||||
virtual void SetFogColor(float r, float g, float b);
|
||||
virtual void SetFogStart(float fogstart);
|
||||
virtual void SetFogEnd(float fogend);
|
||||
virtual void SetFog(short type, float start, float dist, float intensity, float color[3]);
|
||||
virtual void EnableFog(bool enable);
|
||||
virtual void DisplayFog();
|
||||
virtual bool IsFogEnabled();
|
||||
|
||||
virtual void SetBackColor(float red, float green, float blue, float alpha);
|
||||
|
||||
virtual void SetBackColor(float color[3]);
|
||||
|
||||
virtual void SetDrawingMode(int drawingmode);
|
||||
virtual int GetDrawingMode();
|
||||
|
||||
@ -229,7 +218,7 @@ public:
|
||||
virtual void SetDiffuse(float difX, float difY, float difZ, float diffuse);
|
||||
virtual void SetEmissive(float eX, float eY, float eZ, float e);
|
||||
|
||||
virtual void SetAmbientColor(float red, float green, float blue);
|
||||
virtual void SetAmbientColor(float color[3]);
|
||||
virtual void SetAmbient(float factor);
|
||||
|
||||
virtual void SetPolygonOffset(float mult, float add);
|
||||
|
@ -200,7 +200,7 @@ void ImageRender::Render()
|
||||
m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]);
|
||||
m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
|
||||
m_rasterizer->BeginFrame(m_engine->GetClockTime());
|
||||
m_engine->SetWorldSettings(m_scene->GetWorldInfo());
|
||||
m_scene->GetWorldInfo()->UpdateWorldSettings();
|
||||
m_rasterizer->SetAuxilaryClientInfo(m_scene);
|
||||
m_rasterizer->DisplayFog();
|
||||
// matrix calculation, don't apply any of the stereo mode
|
||||
|
Loading…
Reference in New Issue
Block a user