1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
#include "Canvas.h"
#include "../../nCine/Graphics/RenderQueue.h"
#include "../../nCine/Base/Random.h"
namespace Jazz2::UI
{
Canvas::Canvas()
: AnimTime(0.0f), _renderCommandsCount(0), _currentRenderQueue(nullptr)
{
setVisitOrderState(SceneNode::VisitOrderState::Disabled);
}
void Canvas::OnUpdate(float timeMult)
{
SceneNode::OnUpdate(timeMult);
AnimTime += timeMult * AnimTimeMultiplier;
}
bool Canvas::OnDraw(RenderQueue& renderQueue)
{
SceneNode::OnDraw(renderQueue);
_renderCommandsCount = 0;
_currentRenderQueue = &renderQueue;
return false;
}
void Canvas::DrawRenderCommand(RenderCommand* command)
{
_currentRenderQueue->AddCommand(command);
}
void Canvas::DrawTexture(const Texture& texture, Vector2f pos, std::uint16_t z, Vector2f size, const Vector4f& texCoords, const Colorf& color, bool additiveBlending, float angle)
{
auto command = RentRenderCommand();
if (command->GetMaterial().SetShaderProgramType(Material::ShaderProgramType::Sprite)) {
command->GetMaterial().ReserveUniformsDataMemory();
command->GetGeometry().SetDrawParameters(GL_TRIANGLE_STRIP, 0, 4);
// Required to reset render command properly
//command->SetTransformation(command->transformation());
auto* textureUniform = command->GetMaterial().Uniform(Material::TextureUniformName);
if (textureUniform && textureUniform->GetIntValue(0) != 0) {
textureUniform->SetIntValue(0); // GL_TEXTURE0
}
}
if (additiveBlending) {
command->GetMaterial().SetBlendingFactors(GL_SRC_ALPHA, GL_ONE);
} else {
command->GetMaterial().SetBlendingFactors(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
auto instanceBlock = command->GetMaterial().UniformBlock(Material::InstanceBlockName);
instanceBlock->GetUniform(Material::TexRectUniformName)->SetFloatVector(texCoords.Data());
instanceBlock->GetUniform(Material::SpriteSizeUniformName)->SetFloatVector(size.Data());
instanceBlock->GetUniform(Material::ColorUniformName)->SetFloatVector(color.Data());
Matrix4x4f worldMatrix = Matrix4x4f::Translation(pos.X, pos.Y, 0.0f);
if (std::abs(angle) > 0.01f) {
worldMatrix.Translate(size.X * 0.5f, size.Y * 0.5f, 0.0f);
worldMatrix.RotateZ(angle);
worldMatrix.Translate(size.X * -0.5f, size.Y * -0.5f, 0.0f);
}
command->SetTransformation(worldMatrix);
command->SetLayer(z);
command->GetMaterial().SetTexture(texture);
_currentRenderQueue->AddCommand(command);
}
void Canvas::DrawSolid(Vector2f pos, std::uint16_t z, Vector2f size, const Colorf& color, bool additiveBlending)
{
auto command = RentRenderCommand();
if (command->GetMaterial().SetShaderProgramType(Material::ShaderProgramType::SpriteNoTexture)) {
command->GetMaterial().ReserveUniformsDataMemory();
command->GetGeometry().SetDrawParameters(GL_TRIANGLE_STRIP, 0, 4);
// Required to reset render command properly
//command->SetTransformation(command->transformation());
}
if (additiveBlending) {
command->GetMaterial().SetBlendingFactors(GL_SRC_ALPHA, GL_ONE);
} else {
command->GetMaterial().SetBlendingFactors(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
auto instanceBlock = command->GetMaterial().UniformBlock(Material::InstanceBlockName);
instanceBlock->GetUniform(Material::SpriteSizeUniformName)->SetFloatVector(size.Data());
instanceBlock->GetUniform(Material::ColorUniformName)->SetFloatVector(color.Data());
command->SetTransformation(Matrix4x4f::Translation(pos.X, pos.Y, 0.0f));
command->SetLayer(z);
_currentRenderQueue->AddCommand(command);
}
Vector2f Canvas::ApplyAlignment(Alignment align, Vector2f vec, Vector2f size)
{
Vector2f result = vec;
// Sprites are aligned to center by default
switch (align & Alignment::HorizontalMask) {
case Alignment::Center: result.X -= size.X * 0.5f; break;
case Alignment::Right: result.X -= size.X; break;
}
switch (align & Alignment::VerticalMask) {
case Alignment::Center: result.Y -= size.Y * 0.5f; break;
case Alignment::Bottom: result.Y -= size.Y; break;
}
return result;
}
RenderCommand* Canvas::RentRenderCommand()
{
if (_renderCommandsCount < _renderCommands.size()) {
RenderCommand* command = _renderCommands[_renderCommandsCount].get();
command->SetType(RenderCommand::Type::Sprite);
_renderCommandsCount++;
return command;
} else {
std::unique_ptr<RenderCommand>& command = _renderCommands.emplace_back(std::make_unique<RenderCommand>(RenderCommand::Type::Sprite));
command->GetMaterial().SetBlendingEnabled(true);
_renderCommandsCount++;
return command.get();
}
}
}
|