✨ draw sprites on the game window.
parent
85b5b4e820
commit
bb78d60407
Binary file not shown.
After Width: | Height: | Size: 421 B |
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<!-- SHADERS -->
|
||||||
|
<resource type="text" name="vertex-shader"
|
||||||
|
path="shaders/default_vertex.glsl"/>
|
||||||
|
|
||||||
|
<resource type="text" name="fragment-shader"
|
||||||
|
path="shaders/default_fragment.glsl"/>
|
||||||
|
|
||||||
|
<!-- IMAGES -->
|
||||||
|
<resource type="image" name="demo" path="images/demo.png"/>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,21 @@
|
||||||
|
#version 130
|
||||||
|
|
||||||
|
in vec4 f_color;
|
||||||
|
in vec2 f_tex;
|
||||||
|
|
||||||
|
out vec4 out_color;
|
||||||
|
uniform sampler2D tex_sampler;
|
||||||
|
uniform int has_texture;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
if (has_texture != 0)
|
||||||
|
{
|
||||||
|
vec4 texcolor = f_color * texture(tex_sampler, f_tex);
|
||||||
|
out_color = texcolor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_color = f_color;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#version 130
|
||||||
|
|
||||||
|
in vec3 pos;
|
||||||
|
in vec4 color;
|
||||||
|
in vec2 tex;
|
||||||
|
out vec2 f_tex;
|
||||||
|
out vec4 f_color;
|
||||||
|
|
||||||
|
uniform mat4 mvp;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = mvp * vec4(pos, 1.0);
|
||||||
|
f_color = color;
|
||||||
|
f_tex = tex;
|
||||||
|
}
|
26
meson.build
26
meson.build
|
@ -7,8 +7,11 @@ project('mornelune',
|
||||||
'cpp_stdd=c++17'
|
'cpp_stdd=c++17'
|
||||||
])
|
])
|
||||||
|
|
||||||
|
share_dir = get_option('prefix') / get_option('datadir') / 'mornelune'
|
||||||
|
|
||||||
conf = configuration_data()
|
conf = configuration_data()
|
||||||
conf.set('version', meson.project_version())
|
conf.set('version', meson.project_version())
|
||||||
|
conf.set('share_dir', share_dir)
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
input: 'src/conf.in.hpp',
|
input: 'src/conf.in.hpp',
|
||||||
|
@ -24,6 +27,7 @@ executable(
|
||||||
'src/Game.cpp',
|
'src/Game.cpp',
|
||||||
'src/Services.cpp',
|
'src/Services.cpp',
|
||||||
'src/Service.cpp',
|
'src/Service.cpp',
|
||||||
|
'src/Sprite.cpp',
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
'src/logs/Logs.cpp',
|
'src/logs/Logs.cpp',
|
||||||
|
@ -32,8 +36,30 @@ executable(
|
||||||
# Events
|
# Events
|
||||||
'src/events/Events.cpp',
|
'src/events/Events.cpp',
|
||||||
'src/events/Event.cpp',
|
'src/events/Event.cpp',
|
||||||
|
|
||||||
|
# Graphics
|
||||||
|
'src/gfx/Graphics.cpp',
|
||||||
|
'src/gfx/Shader.cpp',
|
||||||
|
'src/gfx/Mesh.cpp',
|
||||||
|
'src/gfx/Material.cpp',
|
||||||
|
'src/gfx/Texture.cpp',
|
||||||
|
'src/gfx/Shape.cpp',
|
||||||
|
|
||||||
|
# Resources
|
||||||
|
'src/res/Resources.cpp',
|
||||||
|
'src/res/BaseRes.cpp',
|
||||||
|
'src/res/TextRes.cpp',
|
||||||
|
'src/res/ImageRes.cpp',
|
||||||
|
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
dependency('sdl2'),
|
||||||
|
dependency('SDL2_image'),
|
||||||
|
dependency('glew'),
|
||||||
|
dependency('glm'),
|
||||||
|
dependency('tinyxml2')
|
||||||
],
|
],
|
||||||
install: true
|
install: true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
install_subdir('assets', install_dir: share_dir)
|
||||||
|
|
28
src/Game.cpp
28
src/Game.cpp
|
@ -1,7 +1,9 @@
|
||||||
#include "Game.hpp"
|
#include "Game.hpp"
|
||||||
#include "logs/FileLogs.hpp"
|
#include "logs/FileLogs.hpp"
|
||||||
#include "src/events/Events.hpp"
|
#include "events/Events.hpp"
|
||||||
#include "src/logs/Logs.hpp"
|
#include "logs/Logs.hpp"
|
||||||
|
#include "gfx/Graphics.hpp"
|
||||||
|
#include "Sprite.hpp"
|
||||||
|
|
||||||
namespace ml
|
namespace ml
|
||||||
{
|
{
|
||||||
|
@ -16,6 +18,28 @@ namespace ml
|
||||||
void Game::start()
|
void Game::start()
|
||||||
{
|
{
|
||||||
ML_SYS(FileLogs)->log(LEVEL_INFO, "game started");
|
ML_SYS(FileLogs)->log(LEVEL_INFO, "game started");
|
||||||
|
|
||||||
|
m_running = true;
|
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
Sprite sprite {256.0f, 256.0f, 128.0f, 128.0f};
|
||||||
|
sprite.set_texture("demo");
|
||||||
|
|
||||||
|
while (m_running)
|
||||||
|
{
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
if (event.type == SDL_QUIT)
|
||||||
|
{
|
||||||
|
m_running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ML_SYS(Graphics)->clear(4, 139, 154);
|
||||||
|
ML_SYS(Graphics)->draw(sprite);
|
||||||
|
ML_SYS(Graphics)->update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::stop()
|
void Game::stop()
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace ml
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool m_running = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,4 +21,20 @@ namespace ml
|
||||||
/*virtual*/ Services::~Services()
|
/*virtual*/ Services::~Services()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Services::init()
|
||||||
|
{
|
||||||
|
for (auto& entry: m_services)
|
||||||
|
{
|
||||||
|
entry.second->init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Services::free()
|
||||||
|
{
|
||||||
|
for (auto& entry: m_services)
|
||||||
|
{
|
||||||
|
entry.second->free();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@ namespace ml
|
||||||
|
|
||||||
virtual ~Services();
|
virtual ~Services();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void free();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
size_t id();
|
size_t id();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "Sprite.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Sprite::Sprite(float x, float y, float w, float h)
|
||||||
|
: Shape(std::make_unique<Mesh>(glm::vec3{x, y, 0.0f},
|
||||||
|
glm::vec3{w, h, 0.0f}),
|
||||||
|
std::make_unique<Shader>(),
|
||||||
|
std::make_unique<Material>())
|
||||||
|
, m_pos { glm::vec3 {x, y, 0.0f} }
|
||||||
|
, m_size { glm::vec3 {w, h, 0.0f} }
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Sprite::~Sprite()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sprite::set_texture(std::string const& name)
|
||||||
|
{
|
||||||
|
m_material = std::make_unique<Material>(name);
|
||||||
|
float const tw = m_material->texture().width();
|
||||||
|
float const th = m_material->texture().height();
|
||||||
|
|
||||||
|
set_sub_texture(name, 0, 0, tw, th);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sprite::set_sub_texture(std::string const& name,
|
||||||
|
float x, float y, float w, float h)
|
||||||
|
{
|
||||||
|
m_material = std::make_unique<Material>(name);
|
||||||
|
|
||||||
|
float const tw = m_material->texture().width();
|
||||||
|
float const th = m_material->texture().height();
|
||||||
|
|
||||||
|
m_mesh = std::make_unique<Mesh>(m_pos, m_size,
|
||||||
|
glm::vec2 {x / tw,
|
||||||
|
y / th},
|
||||||
|
glm::vec2 {w / tw,
|
||||||
|
h / th});
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef ml_SPRITE_HPP
|
||||||
|
#define ml_SPRITE_HPP
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include "commons.hpp"
|
||||||
|
#include "gfx/Mesh.hpp"
|
||||||
|
#include "gfx/Shader.hpp"
|
||||||
|
#include "gfx/Material.hpp"
|
||||||
|
#include "gfx/Shape.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Textured AABB.
|
||||||
|
* @see Shape
|
||||||
|
**/
|
||||||
|
class Sprite: public Shape
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Sprite(float x, float y, float w, float h);
|
||||||
|
virtual ~Sprite();
|
||||||
|
|
||||||
|
void set_texture(std::string const& name);
|
||||||
|
|
||||||
|
void set_sub_texture(std::string const& name,
|
||||||
|
float x, float y, float w, float h);
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::vec3 m_pos;
|
||||||
|
glm::vec3 m_size;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef ml_COMMONS_HPP
|
#ifndef ml_COMMONS_HPP
|
||||||
#define ml_COMMONS_HPP
|
#define ml_COMMONS_HPP
|
||||||
|
|
||||||
|
#include "conf.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -12,6 +14,9 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
#define ML_ASSET(NAME) \
|
||||||
|
(std::filesystem::path(ML_SHARE_DIR) / "assets" / NAME)
|
||||||
|
|
||||||
#define ML ml::Services::get()
|
#define ML ml::Services::get()
|
||||||
#define ML_SYS(SYSTEM) ML->get<SYSTEM>()
|
#define ML_SYS(SYSTEM) ML->get<SYSTEM>()
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,6 @@
|
||||||
#define ml_CONF_HPP
|
#define ml_CONF_HPP
|
||||||
|
|
||||||
#define ML_VERSION std::string("@version@")
|
#define ML_VERSION std::string("@version@")
|
||||||
|
#define ML_SHARE_DIR std::string("@share_dir@")
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include "Graphics.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Graphics::Graphics(std::string const& title,
|
||||||
|
unsigned width,
|
||||||
|
unsigned height)
|
||||||
|
: m_title { title }
|
||||||
|
, m_width { width }
|
||||||
|
, m_height { height }
|
||||||
|
{
|
||||||
|
m_projection = glm::ortho(0.0f,
|
||||||
|
static_cast<float>(m_width),
|
||||||
|
static_cast<float>(m_height),
|
||||||
|
-1.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Graphics::~Graphics()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::init() /*override*/
|
||||||
|
{
|
||||||
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
int init_flags = IMG_INIT_PNG;
|
||||||
|
|
||||||
|
if ((IMG_Init(init_flags) & init_flags) != init_flags)
|
||||||
|
{
|
||||||
|
throw gfx_error {"cannot initialize SDL2 image"};
|
||||||
|
}
|
||||||
|
|
||||||
|
m_window = SDL_CreateWindow(m_title.c_str(),
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
m_width, m_height,
|
||||||
|
SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
|
||||||
|
|
||||||
|
if (!m_window)
|
||||||
|
{
|
||||||
|
throw gfx_error {"cannot create window"};
|
||||||
|
}
|
||||||
|
|
||||||
|
m_context = SDL_GL_CreateContext(m_window);
|
||||||
|
|
||||||
|
if (!m_context)
|
||||||
|
{
|
||||||
|
throw gfx_error {"cannot create GL context"};
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = glewInit();
|
||||||
|
|
||||||
|
if (status != GLEW_OK)
|
||||||
|
{
|
||||||
|
throw gfx_error {"cannot create GLEW context"};
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::free() /*override*/
|
||||||
|
{
|
||||||
|
SDL_GL_DeleteContext(m_context);
|
||||||
|
SDL_DestroyWindow(m_window);
|
||||||
|
IMG_Quit();
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::clear(unsigned r, unsigned g, unsigned b)
|
||||||
|
{
|
||||||
|
glClearColor(r/255.0f, g/255.0f, b/255.0f, 255.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::draw(Shape const& shape)
|
||||||
|
{
|
||||||
|
shape.shader().set_matrix("mvp", m_projection);
|
||||||
|
shape.draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::update()
|
||||||
|
{
|
||||||
|
SDL_GL_SwapWindow(m_window);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef ml_GRAPHICS_HPP
|
||||||
|
#define ml_GRAPHICS_HPP
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "../Service.hpp"
|
||||||
|
#include "Shape.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
ML_ERROR(gfx_error);
|
||||||
|
|
||||||
|
class Graphics: public Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Graphics(std::string const& title,
|
||||||
|
unsigned width,
|
||||||
|
unsigned height);
|
||||||
|
virtual ~Graphics();
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
void free() override;
|
||||||
|
|
||||||
|
void clear(unsigned r, unsigned g, unsigned b);
|
||||||
|
void draw(Shape const& shape);
|
||||||
|
void update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_title;
|
||||||
|
unsigned m_width;
|
||||||
|
unsigned m_height;
|
||||||
|
glm::mat4 m_projection;
|
||||||
|
|
||||||
|
SDL_Window* m_window = nullptr;
|
||||||
|
SDL_GLContext m_context;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "Material.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Material::Material(glm::vec4 const& color)
|
||||||
|
: m_color { color }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*explicit*/ Material::Material(std::string const& texture_name)
|
||||||
|
: m_texture { std::make_unique<Texture>() }
|
||||||
|
{
|
||||||
|
m_texture->load(texture_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Material::~Material()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Material::use() const
|
||||||
|
{
|
||||||
|
if (m_texture)
|
||||||
|
{
|
||||||
|
m_texture->use();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef ml_MATERIAL_HPP
|
||||||
|
#define ml_MATERIAL_HPP
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "Texture.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
class Material
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Material(glm::vec4 const& color=glm::vec4{1.0f});
|
||||||
|
explicit Material(std::string const& texture_name);
|
||||||
|
|
||||||
|
virtual ~Material();
|
||||||
|
|
||||||
|
glm::vec4 color() const { return m_color; }
|
||||||
|
bool has_texture() const { return m_texture != nullptr; }
|
||||||
|
Texture const& texture() const { return *m_texture; }
|
||||||
|
|
||||||
|
void use() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::vec4 m_color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
std::unique_ptr<Texture> m_texture;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,78 @@
|
||||||
|
#include "Mesh.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Mesh::Mesh()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*explicit*/ Mesh::Mesh(glm::vec3 pos,
|
||||||
|
glm::vec3 size,
|
||||||
|
glm::vec2 tpos,
|
||||||
|
glm::vec2 tsize)
|
||||||
|
{
|
||||||
|
quad(pos, size, tpos, tsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Mesh::~Mesh()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 Mesh::get(size_t index) const
|
||||||
|
{
|
||||||
|
if (index >= count())
|
||||||
|
{
|
||||||
|
throw mesh_error {"cannot access to vertex '"
|
||||||
|
+ std::to_string(index)
|
||||||
|
+ "'"};
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_vertices[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh& Mesh::vertex(glm::vec3 v)
|
||||||
|
{
|
||||||
|
m_vertices.push_back(v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh& Mesh::texture(glm::vec2 v)
|
||||||
|
{
|
||||||
|
m_textures.push_back(v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh& Mesh::quad(glm::vec3 pos,
|
||||||
|
glm::vec3 size,
|
||||||
|
glm::vec2 tpos,
|
||||||
|
glm::vec2 tsize)
|
||||||
|
{
|
||||||
|
// a -- b
|
||||||
|
// | |
|
||||||
|
// d -- c
|
||||||
|
|
||||||
|
float hw = size.x / 2.0f;
|
||||||
|
float hh = size.y / 2.0f;
|
||||||
|
|
||||||
|
glm::vec3 a {pos.x - hw, pos.y - hh, pos.z};
|
||||||
|
glm::vec3 b {pos.x + hw, pos.y - hh, pos.z};
|
||||||
|
glm::vec3 c {pos.x + hw, pos.y + hh, pos.z};
|
||||||
|
glm::vec3 d {pos.x - hw, pos.y + hh, pos.z};
|
||||||
|
|
||||||
|
glm::vec2 ta {tpos.x, tpos.y};
|
||||||
|
glm::vec2 tb {tpos.x + tsize.x, tpos.y};
|
||||||
|
glm::vec2 tc {tpos.x + tsize.x, tpos.y + tsize.y};
|
||||||
|
glm::vec2 td {tpos.x, tpos.y + tsize.y};
|
||||||
|
|
||||||
|
vertex(a); texture(ta);
|
||||||
|
vertex(b); texture(tb);
|
||||||
|
vertex(c); texture(tc);
|
||||||
|
|
||||||
|
vertex(a); texture(ta);
|
||||||
|
vertex(c); texture(tc);
|
||||||
|
vertex(d); texture(td);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef ml_MESH_HPP
|
||||||
|
#define ml_MESH_HPP
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
ML_ERROR(mesh_error);
|
||||||
|
|
||||||
|
class Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Mesh();
|
||||||
|
explicit Mesh(glm::vec3 pos,
|
||||||
|
glm::vec3 size,
|
||||||
|
glm::vec2 tpos = glm::vec2 {0.0f, 0.0f},
|
||||||
|
glm::vec2 tsize = glm::vec2 {1.0f, 1.0f});
|
||||||
|
|
||||||
|
virtual ~Mesh();
|
||||||
|
|
||||||
|
Mesh& vertex(glm::vec3 v);
|
||||||
|
Mesh& texture(glm::vec2 v);
|
||||||
|
|
||||||
|
Mesh& quad(glm::vec3 pos,
|
||||||
|
glm::vec3 size,
|
||||||
|
glm::vec2 tpos = glm::vec2 {0.0f, 0.0f},
|
||||||
|
glm::vec2 tsize = glm::vec2 {1.0f, 1.0f});
|
||||||
|
|
||||||
|
std::vector<glm::vec3> data() const { return m_vertices; }
|
||||||
|
std::vector<glm::vec2> tex_data() const { return m_textures; }
|
||||||
|
|
||||||
|
size_t count() const { return m_vertices.size(); }
|
||||||
|
|
||||||
|
glm::vec3 get(size_t index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<glm::vec3> m_vertices;
|
||||||
|
std::vector<glm::vec2> m_textures;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,116 @@
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include "Shader.hpp"
|
||||||
|
#include "../Services.hpp"
|
||||||
|
#include "../res/Resources.hpp"
|
||||||
|
#include "../res/TextRes.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Shader::Shader()
|
||||||
|
: m_program { glCreateProgram() }
|
||||||
|
{
|
||||||
|
load_shader(GL_VERTEX_SHADER, "vertex-shader");
|
||||||
|
load_shader(GL_FRAGMENT_SHADER, "fragment-shader");
|
||||||
|
|
||||||
|
for (auto shader: m_shaders)
|
||||||
|
{
|
||||||
|
glAttachShader(m_program, shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
glLinkProgram(m_program);
|
||||||
|
GLint status = GL_FALSE;
|
||||||
|
|
||||||
|
glGetProgramiv(m_program, GL_LINK_STATUS, &status);
|
||||||
|
|
||||||
|
if (status == GL_FALSE)
|
||||||
|
{
|
||||||
|
size_t const SZ = 1024;
|
||||||
|
char msg [SZ];
|
||||||
|
|
||||||
|
glGetProgramInfoLog(m_program, SZ, NULL, msg);
|
||||||
|
throw shader_error {std::string() + "link error: " + msg};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Shader::~Shader()
|
||||||
|
{
|
||||||
|
for (auto shader: m_shaders)
|
||||||
|
{
|
||||||
|
glDeleteShader(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteProgram(m_program);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Shader::attrib(std::string const& name) const
|
||||||
|
{
|
||||||
|
int res = glGetAttribLocation(m_program, name.c_str());
|
||||||
|
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
throw shader_error {"cannot find attribute '" + name + "'"};
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Shader::uniform(std::string const& name) const
|
||||||
|
{
|
||||||
|
use();
|
||||||
|
int res = glGetUniformLocation(m_program, name.c_str());
|
||||||
|
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
throw shader_error {"cannot find uniform '" + name + "'"};
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::set_matrix(std::string const& name, glm::mat4 mat) const
|
||||||
|
{
|
||||||
|
use();
|
||||||
|
glUniformMatrix4fv(uniform(name), 1, GL_FALSE, glm::value_ptr(mat));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::set_int(std::string const& name, int value) const
|
||||||
|
{
|
||||||
|
use();
|
||||||
|
glUniform1i(uniform(name), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::use() const
|
||||||
|
{
|
||||||
|
glUseProgram(m_program);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint Shader::load_shader(GLenum shader_type, std::string const& name)
|
||||||
|
{
|
||||||
|
GLuint shader = glCreateShader(shader_type);
|
||||||
|
|
||||||
|
auto res = ML_SYS(Resources)->get<TextRes>(name);
|
||||||
|
std::string source = res->data();
|
||||||
|
char const* src [] = { source.c_str() };
|
||||||
|
|
||||||
|
glShaderSource(shader, 1, src, nullptr);
|
||||||
|
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
GLint status = GL_FALSE;
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||||
|
|
||||||
|
if (status == GL_FALSE)
|
||||||
|
{
|
||||||
|
size_t const SZ = 1024;
|
||||||
|
char msg [SZ];
|
||||||
|
|
||||||
|
glGetShaderInfoLog(shader, SZ, NULL, msg);
|
||||||
|
throw shader_error {std::string() + "shader '"
|
||||||
|
+ name
|
||||||
|
+ "' error: " + msg};
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shaders.push_back(shader);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef ml_SHADER_HPP
|
||||||
|
#define ml_SHADER_HPP
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include "../commons.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
ML_ERROR(shader_error);
|
||||||
|
|
||||||
|
class Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Shader();
|
||||||
|
virtual ~Shader();
|
||||||
|
|
||||||
|
int attrib(std::string const& name) const;
|
||||||
|
int uniform(std::string const& name) const;
|
||||||
|
|
||||||
|
void set_matrix(std::string const& name, glm::mat4 mat) const;
|
||||||
|
void set_int(std::string const& name, int value) const;
|
||||||
|
|
||||||
|
void use() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint m_program;
|
||||||
|
std::vector<GLuint> m_shaders;
|
||||||
|
|
||||||
|
GLuint load_shader(GLenum shader_type, std::string const& name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,97 @@
|
||||||
|
#include "Shape.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Shape::Shape(std::unique_ptr<Mesh> mesh,
|
||||||
|
std::unique_ptr<Shader> shader,
|
||||||
|
std::unique_ptr<Material> material)
|
||||||
|
: m_mesh { std::move(mesh) }
|
||||||
|
, m_shader { std::move(shader) }
|
||||||
|
, m_material { std::move(material) }
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Shape::~Shape()
|
||||||
|
{
|
||||||
|
glDeleteBuffers(ML_GL_BUFFER_COUNT, m_vbo);
|
||||||
|
glDeleteVertexArrays(1, &m_vao);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shape::draw() const
|
||||||
|
{
|
||||||
|
glBindVertexArray(m_vao);
|
||||||
|
m_shader->use();
|
||||||
|
m_material->use();
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, m_mesh->count());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shape::update()
|
||||||
|
{
|
||||||
|
m_shader->use();
|
||||||
|
m_shader->set_int("has_texture", m_material->has_texture() ? 1 : 0);
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &m_vao);
|
||||||
|
glBindVertexArray(m_vao);
|
||||||
|
|
||||||
|
glGenBuffers(ML_GL_BUFFER_COUNT, m_vbo);
|
||||||
|
|
||||||
|
auto vecs = m_mesh->data();
|
||||||
|
|
||||||
|
// POS
|
||||||
|
// ---
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo[ML_GL_POS_BUFFER]);
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER,
|
||||||
|
m_mesh->count() * sizeof(glm::vec3),
|
||||||
|
vecs.data(),
|
||||||
|
GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_shader->attrib("pos"));
|
||||||
|
glVertexAttribPointer(m_shader->attrib("pos"),
|
||||||
|
3,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
sizeof(glm::vec3),
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo[ML_GL_POS_BUFFER]);
|
||||||
|
|
||||||
|
// COLOR
|
||||||
|
// -----
|
||||||
|
std::vector<glm::vec4> colors(vecs.size(),
|
||||||
|
m_material->color());
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo[ML_GL_COLOR_BUFFER]);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER,
|
||||||
|
colors.size() * sizeof(glm::vec4),
|
||||||
|
colors.data(),
|
||||||
|
GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_shader->attrib("color"));
|
||||||
|
glVertexAttribPointer(m_shader->attrib("color"),
|
||||||
|
4,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
sizeof(glm::vec4),
|
||||||
|
nullptr);
|
||||||
|
// TEX
|
||||||
|
// ---
|
||||||
|
std::vector<glm::vec2> texpos = m_mesh->tex_data();
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo[ML_GL_TEX_BUFFER]);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER,
|
||||||
|
texpos.size() * sizeof(glm::vec2),
|
||||||
|
texpos.data(),
|
||||||
|
GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(m_shader->attrib("tex"));
|
||||||
|
glVertexAttribPointer(m_shader->attrib("tex"),
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
sizeof(glm::vec2),
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef ml_SHAPE_HPP
|
||||||
|
#define ml_SHAPE_HPP
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "Mesh.hpp"
|
||||||
|
#include "Shader.hpp"
|
||||||
|
#include "Material.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
enum ML_GL_BUFFER {
|
||||||
|
ML_GL_POS_BUFFER = 0,
|
||||||
|
ML_GL_COLOR_BUFFER,
|
||||||
|
ML_GL_TEX_BUFFER,
|
||||||
|
ML_GL_BUFFER_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Anything drawable should inherit from this class.
|
||||||
|
* @see Sprite
|
||||||
|
* @see Graphics
|
||||||
|
**/
|
||||||
|
class Shape
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Shape(std::unique_ptr<Mesh> mesh,
|
||||||
|
std::unique_ptr<Shader> shader,
|
||||||
|
std::unique_ptr<Material> material);
|
||||||
|
virtual ~Shape();
|
||||||
|
|
||||||
|
Shader const& shader() const { return *m_shader; }
|
||||||
|
void draw() const;
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<Mesh> m_mesh;
|
||||||
|
std::unique_ptr<Shader> m_shader;
|
||||||
|
std::unique_ptr<Material> m_material;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint m_vao;
|
||||||
|
GLuint m_vbo[ML_GL_BUFFER_COUNT];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "Texture.hpp"
|
||||||
|
#include "../Services.hpp"
|
||||||
|
#include "../res/Resources.hpp"
|
||||||
|
#include "../res/ImageRes.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Texture::Texture()
|
||||||
|
{
|
||||||
|
glGenTextures(1, &m_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Texture::~Texture()
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &m_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::use() const
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::load(std::string const& name)
|
||||||
|
{
|
||||||
|
auto res = ML_SYS(Resources)->get<ImageRes>(name);
|
||||||
|
auto surface = res->data();
|
||||||
|
m_width = surface->w;
|
||||||
|
m_height = surface->h;
|
||||||
|
|
||||||
|
use();
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
GL_RGBA,
|
||||||
|
m_width,
|
||||||
|
m_height,
|
||||||
|
0,
|
||||||
|
GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
surface->pixels);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef ml_TEXTURE_HPP
|
||||||
|
#define ml_TEXTURE_HPP
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include "../commons.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
class Texture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Texture();
|
||||||
|
virtual ~Texture();
|
||||||
|
|
||||||
|
unsigned width() const { return m_width; }
|
||||||
|
unsigned height() const { return m_height; }
|
||||||
|
|
||||||
|
void use() const;
|
||||||
|
void load(std::string const& name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint m_tex;
|
||||||
|
unsigned m_width = 0;
|
||||||
|
unsigned m_height = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
14
src/main.cpp
14
src/main.cpp
|
@ -3,9 +3,13 @@
|
||||||
#include "conf.hpp"
|
#include "conf.hpp"
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
|
|
||||||
|
// Services
|
||||||
|
#include "Services.hpp"
|
||||||
#include "logs/FileLogs.hpp"
|
#include "logs/FileLogs.hpp"
|
||||||
#include "events/Events.hpp"
|
#include "events/Events.hpp"
|
||||||
#include "Services.hpp"
|
#include "gfx/Graphics.hpp"
|
||||||
|
#include "res/Resources.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include "Game.hpp"
|
#include "Game.hpp"
|
||||||
|
|
||||||
|
@ -13,12 +17,18 @@ int main(int, char**)
|
||||||
{
|
{
|
||||||
ML->add<ml::FileLogs>
|
ML->add<ml::FileLogs>
|
||||||
(std::filesystem::temp_directory_path() / "mornelune.log");
|
(std::filesystem::temp_directory_path() / "mornelune.log");
|
||||||
|
|
||||||
|
ML->add<ml::Resources>();
|
||||||
|
|
||||||
ML->add<ml::Events>();
|
ML->add<ml::Events>();
|
||||||
|
ML->add<ml::Graphics>("Mornelune", 1024, 768);
|
||||||
|
ML->init();
|
||||||
|
|
||||||
ml::Game game;
|
ml::Game game;
|
||||||
|
|
||||||
game.start();
|
game.start();
|
||||||
game.stop();
|
game.stop();
|
||||||
|
|
||||||
|
ML->free();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "BaseRes.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ BaseRes::BaseRes()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ BaseRes::~BaseRes()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef ml_BASERES_HPP
|
||||||
|
#define ml_BASERES_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
ML_ERROR(resource_error);
|
||||||
|
|
||||||
|
class BaseRes
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit BaseRes();
|
||||||
|
virtual ~BaseRes();
|
||||||
|
|
||||||
|
virtual void load(std::filesystem::path const& path) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "ImageRes.hpp"
|
||||||
|
#include "src/res/BaseRes.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ ImageRes::ImageRes()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ ImageRes::~ImageRes()
|
||||||
|
{
|
||||||
|
if (m_surface)
|
||||||
|
{
|
||||||
|
SDL_FreeSurface(m_surface);
|
||||||
|
m_surface = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageRes::load(std::filesystem::path const& path) /*override*/
|
||||||
|
{
|
||||||
|
m_surface = IMG_Load(path.c_str());
|
||||||
|
|
||||||
|
if (!m_surface)
|
||||||
|
{
|
||||||
|
throw resource_error {"cannot load image '" + path.string() + "'"};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef ml_IMAGERES_HPP
|
||||||
|
#define ml_IMAGERES_HPP
|
||||||
|
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "BaseRes.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
class ImageRes: public BaseRes
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ImageRes();
|
||||||
|
virtual ~ImageRes();
|
||||||
|
|
||||||
|
SDL_Surface* data() const { return m_surface; }
|
||||||
|
|
||||||
|
void load(std::filesystem::path const& path) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_Surface* m_surface = nullptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <tinyxml2.h>
|
||||||
|
namespace xml = tinyxml2;
|
||||||
|
|
||||||
|
#include "../Services.hpp"
|
||||||
|
#include "Resources.hpp"
|
||||||
|
#include "TextRes.hpp"
|
||||||
|
#include "ImageRes.hpp"
|
||||||
|
#include "BaseRes.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Resources::Resources()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Resources::~Resources()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resources::init() /*override*/
|
||||||
|
{
|
||||||
|
xml::XMLDocument doc;
|
||||||
|
doc.LoadFile(ML_ASSET("manifest.xml").string().c_str());
|
||||||
|
|
||||||
|
auto* root = doc.RootElement();
|
||||||
|
|
||||||
|
xml::XMLElement* itr = root->FirstChildElement();
|
||||||
|
|
||||||
|
while (itr)
|
||||||
|
{
|
||||||
|
std::string type = itr->Attribute("type");
|
||||||
|
std::filesystem::path path = itr->Attribute("path");
|
||||||
|
std::string name = itr->Attribute("name");
|
||||||
|
|
||||||
|
if (type == "text")
|
||||||
|
{
|
||||||
|
ML_SYS(Resources)->load<TextRes>(name, path);
|
||||||
|
}
|
||||||
|
else if (type == "image")
|
||||||
|
{
|
||||||
|
ML_SYS(Resources)->load<ImageRes>(name, path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw resource_error {"unknown resource '"
|
||||||
|
+ name
|
||||||
|
+ "' of type '" + type + "'"};
|
||||||
|
}
|
||||||
|
|
||||||
|
itr = itr->NextSiblingElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
#ifndef ml_RESOURCES_HPP
|
||||||
|
#define ml_RESOURCES_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "../Service.hpp"
|
||||||
|
#include "BaseRes.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
class Resources: public Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Resources();
|
||||||
|
virtual ~Resources();
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void load(std::string const& name,
|
||||||
|
std::filesystem::path const& path);
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::shared_ptr<T> get(std::string const& name) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<BaseRes>>
|
||||||
|
m_resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Resources::load(std::string const& name,
|
||||||
|
std::filesystem::path const& path)
|
||||||
|
{
|
||||||
|
if (auto itr = m_resources.find(name);
|
||||||
|
itr == std::end(m_resources))
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<T>();
|
||||||
|
res->load(ML_ASSET(path));
|
||||||
|
|
||||||
|
m_resources.insert({name, res});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw resource_error {"resource '" + name + "' already exists"};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::shared_ptr<T> Resources::get(std::string const& name) const
|
||||||
|
{
|
||||||
|
if (auto itr = m_resources.find(name);
|
||||||
|
itr != std::end(m_resources))
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<T>(itr->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw resource_error {"cannot find resource '" + name + "'"};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include "TextRes.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ TextRes::TextRes()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ TextRes::~TextRes()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextRes::load(std::filesystem::path const& path) /*override*/
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
std::ifstream file { path };
|
||||||
|
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
throw resource_error
|
||||||
|
{"cannot find resource '" + path.string() + "'"};
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << file.rdbuf();
|
||||||
|
|
||||||
|
m_data = ss.str();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef ml_TEXTRES_HPP
|
||||||
|
#define ml_TEXTRES_HPP
|
||||||
|
|
||||||
|
#include "BaseRes.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
class TextRes: public BaseRes
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TextRes();
|
||||||
|
virtual ~TextRes();
|
||||||
|
|
||||||
|
std::string data() const { return m_data; }
|
||||||
|
|
||||||
|
void load(std::filesystem::path const& path) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue