#include "DrawCanvasManager.h"
#include "DrawCanvas.h"
#include "RKTransformObject.h"
#include "RKMaterial.h"
#include "CasualCore/Graphics/Level.h"
#include "CasualCore/RKEngine/Public/Include/RKVertexDeclaration.h"
static const char* s_guiVertexFormat = "DrawCanvasVertexFormat";
/// Helper class to re-direct draw calls to the canvas manager class (prevents exposing implementtation details)
class DrawCanvasObject : public RKTransformObject
{
public:
explicit DrawCanvasObject(DrawCanvasManager& a_manager) : m_manager(a_manager) {}
virtual void Draw(const class RKCamera* camera, class RKFrustumFitter* frustumFitter) override
{
m_manager.Draw();
}
DrawCanvasManager & m_manager;
};
void DrawCanvasManager::Init(CasualCore::Level* a_level)
{
// Store the canvas level object
m_level = a_level;
// Create canvas object
m_drawObject = RKNEW(DrawCanvasObject)(*this);
m_drawObject->Init();
m_drawObject->PostInit();
// Add object to the level
m_level->AddObject(m_drawObject);
// Create the shared vertex decleration
m_vertexDecl = RKVertexDeclaration_Create(s_guiVertexFormat);
RKVertexDeclaration_AddElement(m_vertexDecl, RKDECLTYPE_FLOAT3, RKDECLUSAGE_POSITION, 0, 0);
RKVertexDeclaration_AddElement(m_vertexDecl, RKDECLTYPE_FLOAT2, RKDECLUSAGE_TEXCOORD_0, 12, 0);
RKVertexDeclaration_AddElement(m_vertexDecl, RKDECLTYPE_FLOAT4, RKDECLUSAGE_COLOR, 20, 0);
RKVertexDeclaration_End(m_vertexDecl, 36);
// Create alpha material
m_pAlphaMaterial = RKMaterial_Create(DrawCanvas::GetAlphaMaterialName(), false, false, "bneUI", "white");
RKMaterialType *pType = m_pAlphaMaterial->GetMaterialType();
pType->SetSrcBlendMode(RK_SRC_ALPHA);
pType->SetDstBlendMode(RK_ONE_MINUS_SRC_ALPHA);
pType->SetEnableBlending(true);
pType->SetDepthTest(false);
pType->SetDepthWrite(false);
pType->SetEnableCulling(false);
// Create solid material
m_pSolidMaterial = RKMaterial_Create(DrawCanvas::GetSolidMaterialName(), false, false, "bneUI", "white");
pType = m_pSolidMaterial->GetMaterialType();
pType->SetEnableBlending(false);
pType->SetDepthTest(false);
pType->SetDepthWrite(false);
pType->SetEnableCulling(false);
}
void DrawCanvasManager::Done()
{
RKASSERT(m_canvasArray.Size() == 0, "Drawing canvas objects not deleted");
// Destroy solid and alpha material
RKMaterial_Destroy(&m_pSolidMaterial);
RKMaterial_Destroy(&m_pAlphaMaterial);
// Remove object from the level (we delete it ourselves)
if (m_drawObject)
{
m_drawObject->Deinit();
m_level->RemoveObject(m_drawObject, false);
SAFE_DELETE(m_drawObject);
}
m_level = nullptr;
// Destroy the vertex format
RKVertexDeclaration_Destroy(&m_vertexDecl);
}
DrawCanvas* DrawCanvasManager::CreateCanvas()
{
DrawCanvas* retCanvas = RKNEW(DrawCanvas)(m_vertexDecl);
m_canvasArray.Append(retCanvas);
return retCanvas;
}
void DrawCanvasManager::DestroyCanvas(DrawCanvas* a_canvas)
{
m_canvasArray.EraseFirst(a_canvas);
RKDELETE(a_canvas);
}
void DrawCanvasManager::Draw()
{
// NOTE: It is very important for thread safety that this is not called except from an object draw call
// Loop for all canvas objects and draw them
for (uint32_t i = 0; i < m_canvasArray.Size(); i++)
{
m_canvasArray[i]->Draw();
}
}