Moved to strategy design patter for 2D drawables
This commit is contained in:
parent
a367fa9cd6
commit
4d1f8bb3c7
14
src/drawables/draw_strategy_base.hpp
Normal file
14
src/drawables/draw_strategy_base.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace gz {
|
||||
/**
|
||||
* @brief Base class for draw strategies for type T
|
||||
*/
|
||||
template<typename T>
|
||||
class DrawStrategy {
|
||||
public:
|
||||
virtual void draw() = 0;
|
||||
virtual void update(const T&) = 0;
|
||||
virtual ~DrawStrategy() {};
|
||||
};
|
||||
}
|
34
src/drawables/print_draw_strategy.hpp
Normal file
34
src/drawables/print_draw_strategy.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "draw_strategy_base.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <gz-util/string/to_string.hpp>
|
||||
|
||||
namespace gz {
|
||||
/**
|
||||
* @brief Print the object to stdout when draw() is called
|
||||
* @details
|
||||
* When update() is called, to object is converted to string and stored in tAsString.
|
||||
* When draw() is called, tAsString is passed to `std::cout`.
|
||||
*/
|
||||
template<gz::ConvertibleToString T>
|
||||
class PrintDrawStrategy : public DrawStrategy<T> {
|
||||
public:
|
||||
void draw() override;
|
||||
void update(const T& t) override;
|
||||
private:
|
||||
std::string tAsString;
|
||||
};
|
||||
|
||||
|
||||
template<gz::ConvertibleToString T>
|
||||
void PrintDrawStrategy<T>::draw() {
|
||||
std::cout << tAsString << '\n';
|
||||
}
|
||||
|
||||
template<gz::ConvertibleToString T>
|
||||
void PrintDrawStrategy<T>::update(const T& t) {
|
||||
tAsString = gz::toString(t);
|
||||
}
|
||||
} // namespace gz
|
23
src/drawables/rectangle.cpp
Normal file
23
src/drawables/rectangle.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "rectangle.hpp"
|
||||
|
||||
#include "texture_manager.hpp"
|
||||
#include <gz-util/string/to_string.hpp>
|
||||
|
||||
namespace gz {
|
||||
Rectangle::Rectangle(float left, float top, float width, float height, std::unique_ptr<DrawStrategy<Rectangle>>&& drawStrategy)
|
||||
: position(left, top), size(width, height), drawStrategy(std::move(drawStrategy))
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
std::string Rectangle::toString() const {
|
||||
return "<Rectangle pos: " + gz::toString(position) + ", size: " + gz::toString(size) + ">";
|
||||
}
|
||||
|
||||
|
||||
void Rectangle::update() {
|
||||
drawStrategy->update(*this);
|
||||
}
|
||||
|
||||
|
||||
} // namespace gz::vlk
|
27
src/drawables/rectangle.hpp
Normal file
27
src/drawables/rectangle.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "vertex.hpp"
|
||||
#include "draw_strategy_base.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace gz {
|
||||
class Rectangle {
|
||||
public:
|
||||
Rectangle(float top, float left, float width, float height, std::unique_ptr<DrawStrategy<Rectangle>>&& drawStrategy);
|
||||
inline const glm::vec2& getPosition() const { return position; }
|
||||
inline void setPosition(const glm::vec2& v) { position = v; }
|
||||
inline void setPosition(glm::vec2&& v) { position = std::move(v); }
|
||||
inline const glm::vec2& getSize() const { return size; }
|
||||
inline void setSize(const glm::vec2& v) { size = v; }
|
||||
inline void setSize(glm::vec2&& v) { size = std::move(v); }
|
||||
void draw() { drawStrategy->draw(); };
|
||||
std::string toString() const;
|
||||
private:
|
||||
void update();
|
||||
glm::vec2 position;
|
||||
glm::vec2 size;
|
||||
std::unique_ptr<DrawStrategy<Rectangle>> drawStrategy;
|
||||
};
|
||||
|
||||
|
||||
} // namespace gz
|
25
src/drawables/text.cpp
Normal file
25
src/drawables/text.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "text.hpp"
|
||||
|
||||
#include "font.hpp"
|
||||
|
||||
namespace gz::vlk {
|
||||
Text::Text(Font font, std::string&& text)
|
||||
: text(std::move(text)), font(font)
|
||||
{
|
||||
|
||||
}
|
||||
std::string Text::toString() const {
|
||||
return "<Text: '" + text + "'>";
|
||||
}
|
||||
|
||||
void Text::setTextureCoordinates(FontManager& fontManager) {
|
||||
for (char c : text) {
|
||||
fontManager.getTexCoords(font, c, vertices[0].texCoord);
|
||||
fontManager.getTexCoords(font, c, vertices[1].texCoord);
|
||||
fontManager.getTexCoords(font, c, vertices[2].texCoord);
|
||||
fontManager.getTexCoords(font, c, vertices[3].texCoord);
|
||||
}
|
||||
// must be after getTexCoords, since that might load the texture
|
||||
}
|
||||
|
||||
} // namespace gz::vlk
|
25
src/drawables/text.hpp
Normal file
25
src/drawables/text.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "buffer_manager.hpp"
|
||||
#include <string>
|
||||
#include "font.hpp"
|
||||
|
||||
namespace gz::vlk {
|
||||
class Text {
|
||||
public:
|
||||
Text(Font font, std::string&& text);
|
||||
private:
|
||||
std::string text;
|
||||
void setTextureCoordinates(FontManager& fontManager);
|
||||
|
||||
uint32_t textureAtlasIndex;
|
||||
Font font;
|
||||
std::vector<Vertex2D> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
BufferInfo vertexBufferInfo;
|
||||
BufferInfo indexBufferInfo;
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
} // namespace gz::vlk
|
@ -1,72 +0,0 @@
|
||||
#include "shape.hpp"
|
||||
|
||||
#include "buffer_manager.hpp"
|
||||
#include "texture_manager.hpp"
|
||||
|
||||
namespace gz::vlk {
|
||||
Rectangle::Rectangle(float top, float left, uint32_t width, uint32_t height, glm::vec3 color, std::string&& texture)
|
||||
: top(top), left(left), width(width), height(height), color(color)
|
||||
{
|
||||
this->texture = std::move(texture);
|
||||
generateVertices();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Rectangle::generateVertices() {
|
||||
vertices.clear();
|
||||
vertices.emplace_back(Vertex2D{glm::vec2(top, left), color, glm::vec2(0, 0)});
|
||||
vertices.emplace_back(Vertex2D{glm::vec2(top, left + width), color, glm::vec2(0, 1)});
|
||||
vertices.emplace_back(Vertex2D{glm::vec2(top + height, left + width), color, glm::vec2(1, 1)});
|
||||
vertices.emplace_back(Vertex2D{glm::vec2(top + height, left), color, glm::vec2(1, 0)});
|
||||
indices = { 0, 1, 2, 2, 3, 0 };
|
||||
/* indices = { 2, 1, 0, 2, 3, 0 }; */
|
||||
}
|
||||
|
||||
void Shape::setIndexOffset(uint32_t offset) {
|
||||
for (size_t i = 0; i < indices.size(); i++) {
|
||||
indices[i] += offset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Shape::normalizeVertices(float width, float height) {
|
||||
for (size_t i = 0; i < vertices.size(); i++) {
|
||||
vertices[i].pos.x /= width;
|
||||
vertices[i].pos.y /= height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Shape::initalizeBufferInfos(BufferManager<Vertex2D, uint32_t>& bufferManager) {
|
||||
assert(vertexBufferInfo.index == BUFFER_NOT_INITIALIZED);
|
||||
std::tie(vertexBufferInfo, indexBufferInfo) = bufferManager.addVertices(vertices, indices);
|
||||
}
|
||||
|
||||
|
||||
void Rectangle::setTextureCoordinates(glm::vec2 topLeft, glm::vec2 bottomRight) {
|
||||
vertices[0].texCoord = topLeft;
|
||||
vertices[1].texCoord.x = bottomRight.x;
|
||||
vertices[1].texCoord.y = topLeft.y;
|
||||
vertices[2].texCoord = bottomRight;
|
||||
vertices[3].texCoord.x = topLeft.x;
|
||||
vertices[3].texCoord.y = bottomRight.y;
|
||||
}
|
||||
|
||||
void Rectangle::setTextureCoordinates(TextureManager& textureManager) {
|
||||
if (texture != "atlas") {
|
||||
textureManager.getTexCoords(texture, vertices[0].texCoord);
|
||||
textureManager.getTexCoords(texture, vertices[1].texCoord);
|
||||
textureManager.getTexCoords(texture, vertices[2].texCoord);
|
||||
textureManager.getTexCoords(texture, vertices[3].texCoord);
|
||||
textureAtlasIndex = textureManager.getTextureAtlasIndex(texture);
|
||||
}
|
||||
else {
|
||||
textureAtlasIndex = 0;
|
||||
|
||||
}
|
||||
// must be after getTexCoords, since that might load the texture
|
||||
}
|
||||
|
||||
|
||||
} // namespace gz::vlk
|
@ -1,67 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "buffer_manager.hpp"
|
||||
#include "vertex.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace gz::vlk {
|
||||
// defined in texture_manager.hpp
|
||||
class TextureManager;
|
||||
/**
|
||||
* @brief Base class for shapes
|
||||
* @details
|
||||
* In this implementaiton, a shape is a 2D object made of several vertices.
|
||||
* Each shape has its own vertex and index buffers, which are managed by a BufferManager.
|
||||
* Their texture is managed by a TextureManager.
|
||||
* @todo free resources and rule of 5
|
||||
*/
|
||||
class Shape {
|
||||
public:
|
||||
const std::vector<Vertex2D>& getVertices() const { return vertices; }
|
||||
const std::vector<uint32_t>& getIndices() const { return indices; }
|
||||
const std::string& getTexture() const { return texture; }
|
||||
uint32_t getTexureAtlasIndex() const { return textureAtlasIndex; }
|
||||
const BufferInfo& getVertexBufferInfo() const { return vertexBufferInfo; }
|
||||
const BufferInfo& getIndexBufferInfo() const { return indexBufferInfo; }
|
||||
|
||||
/**
|
||||
* @brief Add an offset to all indices (useful when putting multiple shapes in the same vertex buffer)
|
||||
*/
|
||||
void setIndexOffset(uint32_t offset);
|
||||
/**
|
||||
* @brief Normalize the vertices, so that (1, 1) is (width, height)
|
||||
*/
|
||||
void normalizeVertices(float width, float height);
|
||||
virtual void setTextureCoordinates(glm::vec2 topLeft, glm::vec2 bottomRight) {};
|
||||
virtual void setTextureCoordinates(TextureManager& textureManager) {};
|
||||
bool buffersInitalized() const { return vertexBufferInfo.index != BUFFER_NOT_INITIALIZED; }
|
||||
void initalizeBufferInfos(BufferManager<Vertex2D, uint32_t>& bufferManager);
|
||||
virtual ~Shape() {};
|
||||
protected:
|
||||
std::string texture = "texture.png";
|
||||
uint32_t textureAtlasIndex;
|
||||
std::vector<Vertex2D> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
BufferInfo vertexBufferInfo;
|
||||
BufferInfo indexBufferInfo;
|
||||
};
|
||||
|
||||
class Rectangle : public Shape {
|
||||
public:
|
||||
Rectangle(float top, float left, uint32_t width, uint32_t height, glm::vec3 color, std::string&& texture);
|
||||
void setTextureCoordinates(glm::vec2 topLeft, glm::vec2 bottomRight) override;
|
||||
/**
|
||||
* @brief Get the correct texture coordinates from a TextureManager
|
||||
* @details
|
||||
* If the texture is "atlas", the texture coordinates will remain at (0,0), (0,1), (1, 1), (1, 0) and
|
||||
* thus show the entire atlas.
|
||||
*/
|
||||
void setTextureCoordinates(TextureManager& textureManager) override;
|
||||
private:
|
||||
float top, left;
|
||||
uint32_t width, height;
|
||||
glm::vec3 color;
|
||||
void generateVertices();
|
||||
};
|
||||
} // namespace gz::vlk
|
34
src/vulkan_draw_strategies/ds_vk_base.cpp
Normal file
34
src/vulkan_draw_strategies/ds_vk_base.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "ds_vk_base.hpp"
|
||||
|
||||
#include "renderer2D.hpp"
|
||||
|
||||
namespace gz::vlk {
|
||||
void VulkanDS::setIndexOffset(uint32_t offset) {
|
||||
for (size_t i = 0; i < indices.size(); i++) {
|
||||
indices[i] += offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VulkanDS::normalizeVertices(float width, float height) {
|
||||
for (size_t i = 0; i < vertices.size(); i++) {
|
||||
vertices[i].pos.x /= width;
|
||||
vertices[i].pos.y /= height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VulkanDS::updateBufferInfos() {
|
||||
assert(vertexBufferInfo.index == BUFFER_NOT_INITIALIZED);
|
||||
std::tie(vertexBufferInfo, indexBufferInfo) = bufferManager.get().addVertices(vertices, indices);
|
||||
}
|
||||
|
||||
|
||||
VulkanTexturedDS::VulkanTexturedDS(TextureManager& textureManager, Texture texture)
|
||||
: texture(texture), textureAtlasIndex(textureManager.getTextureAtlasIndex(texture)), textureManager(textureManager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace gz::vlk
|
62
src/vulkan_draw_strategies/ds_vk_base.hpp
Normal file
62
src/vulkan_draw_strategies/ds_vk_base.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "draw_strategy_base.hpp"
|
||||
|
||||
#include "buffer_manager.hpp"
|
||||
#include "texture_manager.hpp"
|
||||
|
||||
namespace gz::vlk {
|
||||
class Renderer2D;
|
||||
class TextureManager;
|
||||
/**
|
||||
* @brief Draw rectangles using the vlk::Renderer2D
|
||||
*
|
||||
* @todo free resources and rule of 5
|
||||
*/
|
||||
class VulkanDS {
|
||||
public:
|
||||
VulkanDS(Renderer2D& renderer, BufferManager<Vertex2D, uint32_t>& bufferManager)
|
||||
: renderer(renderer), bufferManager(bufferManager) {};
|
||||
|
||||
const std::vector<Vertex2D>& getVertices() const { return vertices; }
|
||||
const std::vector<uint32_t>& getIndices() const { return indices; }
|
||||
const BufferInfo& getVertexBufferInfo() const { return vertexBufferInfo; }
|
||||
const BufferInfo& getIndexBufferInfo() const { return indexBufferInfo; }
|
||||
|
||||
/**
|
||||
* @brief Add an offset to all indices (useful when putting multiple shapes in the same vertex buffer)
|
||||
*/
|
||||
void setIndexOffset(uint32_t offset);
|
||||
/**
|
||||
* @brief Normalize the vertices, so that (1, 1) is (width, height)
|
||||
*/
|
||||
void normalizeVertices(float width, float height);
|
||||
inline bool buffersInitalized() const { return vertexBufferInfo.index != BUFFER_NOT_INITIALIZED; }
|
||||
virtual ~VulkanDS() {};
|
||||
protected:
|
||||
/**
|
||||
* @todo free resources
|
||||
*/
|
||||
void updateBufferInfos();
|
||||
std::vector<Vertex2D> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
BufferInfo vertexBufferInfo;
|
||||
BufferInfo indexBufferInfo;
|
||||
std::reference_wrapper<Renderer2D> renderer;
|
||||
std::reference_wrapper<BufferManager<Vertex2D, uint32_t>> bufferManager;
|
||||
};
|
||||
|
||||
|
||||
class VulkanTexturedDS {
|
||||
public:
|
||||
VulkanTexturedDS(TextureManager& textureManager, Texture texture);
|
||||
inline const Texture& getTexture() const { return texture; }
|
||||
inline uint32_t getTexureAtlasIndex() const { return textureAtlasIndex; }
|
||||
virtual ~VulkanTexturedDS() {};
|
||||
protected:
|
||||
Texture texture;
|
||||
TextureAtlasIndex textureAtlasIndex;
|
||||
std::reference_wrapper<TextureManager> textureManager;
|
||||
};
|
||||
|
||||
} // namespace gz::vlk
|
45
src/vulkan_draw_strategies/ds_vk_rectangle.cpp
Normal file
45
src/vulkan_draw_strategies/ds_vk_rectangle.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include "ds_vk_rectangle.hpp"
|
||||
|
||||
#include "texture_manager.hpp"
|
||||
#include "renderer2D.hpp"
|
||||
|
||||
namespace gz::vlk {
|
||||
|
||||
RectangleTexturedVkDS::RectangleTexturedVkDS(Renderer2D& renderer, BufferManager<Vertex2D, uint32_t>& bufferManager, const std::string& textureName)
|
||||
: VulkanDS(renderer, bufferManager),
|
||||
VulkanTexturedDS(this->renderer.get().getTextureManager(), this->renderer.get().getTextureManager().getTexture(textureName))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void RectangleTexturedVkDS::update(const Rectangle& rect) {
|
||||
// update buffers
|
||||
vertices.clear();
|
||||
const auto& pos = rect.getPosition();
|
||||
const auto& size = rect.getSize();
|
||||
glm::vec3 color(0, 0, 0);
|
||||
// topleft, topright, botright, botleft -> clockwise
|
||||
vertices.emplace_back(Vertex2D{pos, color, glm::vec2(0, 0)});
|
||||
vertices.emplace_back(Vertex2D{glm::vec2(pos.x + size.x, pos.y), color, glm::vec2(1, 0)});
|
||||
vertices.emplace_back(Vertex2D{glm::vec2(pos.x + size.x, pos.y + size.y), color, glm::vec2(1, 1)});
|
||||
vertices.emplace_back(Vertex2D{glm::vec2(pos.x, pos.y + size.y), color, glm::vec2(0, 1)});
|
||||
/* indices = { 0, 1, 2, 2, 3, 0 }; */
|
||||
/* indices = { 2, 1, 0, 2, 3, 0 }; */
|
||||
indices = { 0, 2, 1, 0, 3, 2 };
|
||||
normalizeVertices(renderer.get().getScExtent().width, renderer.get().getScExtent().height);
|
||||
|
||||
// update texture
|
||||
TextureManager& tm = textureManager.get();
|
||||
tm.setTexCoords(texture, vertices[0].texCoord);
|
||||
tm.setTexCoords(texture, vertices[1].texCoord);
|
||||
tm.setTexCoords(texture, vertices[2].texCoord);
|
||||
tm.setTexCoords(texture, vertices[3].texCoord);
|
||||
|
||||
updateBufferInfos();
|
||||
}
|
||||
|
||||
void RectangleTexturedVkDS::draw() {
|
||||
renderer.get().drawShape(bufferManager.get(), vertexBufferInfo, indexBufferInfo, textureAtlasIndex);
|
||||
}
|
||||
} // namespace gz::vlk
|
27
src/vulkan_draw_strategies/ds_vk_rectangle.hpp
Normal file
27
src/vulkan_draw_strategies/ds_vk_rectangle.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "rectangle.hpp"
|
||||
#include "ds_vk_base.hpp"
|
||||
namespace gz::vlk {
|
||||
/**
|
||||
* @details
|
||||
* Rectangle has vertex and index buffers from vlk::BufferManager
|
||||
* and a texture from vlk::TextureManager
|
||||
*/
|
||||
class RectangleTexturedVkDS : public DrawStrategy<Rectangle>, public VulkanDS, public VulkanTexturedDS {
|
||||
public:
|
||||
RectangleTexturedVkDS(Renderer2D& renderer, BufferManager<Vertex2D, uint32_t>& bufferManager, const std::string& textureName);
|
||||
/**
|
||||
* @todo
|
||||
*/
|
||||
void draw() override;
|
||||
|
||||
/**
|
||||
* @brief Set the new vertices and indices
|
||||
*/
|
||||
void update(const Rectangle& rect) override;
|
||||
private:
|
||||
void setTextureCoordinates();
|
||||
};
|
||||
|
||||
} // namespace gz::vlk
|
19
src/vulkan_draw_strategies/ds_vk_text.cpp
Normal file
19
src/vulkan_draw_strategies/ds_vk_text.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "ds_vk_text.hpp"
|
||||
|
||||
namespace gz::vlk {
|
||||
|
||||
void TextVkDS::draw() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TextVkDS::update(const Text& text) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TextVkDS::setTextureCoordinates() {
|
||||
|
||||
}
|
||||
}
|
24
src/vulkan_draw_strategies/ds_vk_text.hpp
Normal file
24
src/vulkan_draw_strategies/ds_vk_text.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "text.hpp"
|
||||
#include "ds_vk_base.hpp"
|
||||
|
||||
namespace gz::vlk {
|
||||
|
||||
class TextVkDS : public DrawStrategy<Text>, public VulkanDS, public VulkanTexturedDS {
|
||||
public:
|
||||
TextVkDS(Renderer2D& renderer, BufferManager<Vertex2D, uint32_t>& bufferManager, const std::string& textureName);
|
||||
/**
|
||||
* @todo
|
||||
*/
|
||||
void draw() override;
|
||||
|
||||
/**
|
||||
* @brief Set the new vertices and indices
|
||||
*/
|
||||
void update(const Text& text) override;
|
||||
private:
|
||||
void setTextureCoordinates();
|
||||
};
|
||||
|
||||
} // namespace gz::vlk
|
Loading…
Reference in New Issue
Block a user