Przeglądaj źródła

Making flyweight bindings more intelligent.

Sam Jaffe 6 lat temu
rodzic
commit
17521ece2c

+ 3 - 0
graphics/include/game/graphics/material.hpp

@@ -9,6 +9,7 @@
 
 #include <vector>
 
+#include "game/math/math_fwd.hpp"
 #include "game/util/identity.hpp"
 #include "shader_program.hpp"
 
@@ -30,6 +31,8 @@ namespace graphics {
                                       std::string const & texture,
                                       std::string const & uniform);
 
+    math::vec2i size() const;
+
   private:
     material(unsigned int, shader_program const &);
   };

+ 9 - 2
graphics/src/material.cpp

@@ -14,9 +14,11 @@ using namespace graphics;
 
 namespace {
   using key_t = std::pair<shaders::type, std::string>;
-  std::unordered_map<std::string, material> g_materials;
+  std::unordered_map<std::string, flyweight<material>> g_materials;
 }
 
+static math::vec2i ZERO{{0, 0}};
+
 flyweight<texture> get_texture(std::string const & texture,
                                std::string const & uniform) {
   if (!texture.empty()) {
@@ -43,8 +45,13 @@ flyweight<material> material::create(shader_program const & sp,
   material mat{++id, sp};
   mat.uniforms.push_back({get_texture(texture, uniform),
                           shaders::uniform_location(sp.id, uniform)});
-  return g_materials.emplace("", std::move(mat)).first->second;
+  flyweight<material> fly{id, mat};
+  return g_materials.emplace("", fly).first->second;
 }
 
 material::material(unsigned int id, shader_program const & sp)
     : identity<material>(id), shaders(sp) {}
+
+math::vec2i material::size() const {
+  return uniforms.empty() ? ZERO : uniforms.front().texture.actual().size;
+}

+ 4 - 3
graphics/src/shader.cpp

@@ -15,7 +15,7 @@ using namespace graphics;
 
 namespace {
   using key_t = std::pair<shaders::type, std::string>;
-  std::unordered_map<key_t, shader> g_shaders;
+  std::unordered_map<key_t, flyweight<shader>> g_shaders;
 }
 
 flyweight<shader> shader::create(shaders::type tp, std::string const & path) {
@@ -23,8 +23,9 @@ flyweight<shader> shader::create(shaders::type tp, std::string const & path) {
   auto found = g_shaders.find(key);
   if (found != g_shaders.end()) { return found->second; }
 
-  shader shad{shaders::init(tp, path), tp, path};
-  return g_shaders.emplace(key, std::move(shad)).first->second;
+  auto id = shaders::init(tp, path);
+  flyweight<shader> fly{id, {id, tp, path}};
+  return g_shaders.emplace(key, fly).first->second;
 }
 
 shader::shader(unsigned int id, shaders::type type, std::string const & path)

+ 3 - 3
graphics/src/shader_program.cpp

@@ -29,9 +29,9 @@ flyweight<shader_program> shader_program::create(std::string const & frag,
   auto fragment_shader = shader::create(shaders::type::FRAGMENT, frag);
   auto vertex_shader = shader::create(shaders::type::VERTEX, vert);
 
-  shader_program prog{shaders::init(fragment_shader, vertex_shader),
-                      fragment_shader, vertex_shader};
-  return g_shader_programs.emplace(key, std::move(prog)).first->second;
+  auto id = shaders::init(fragment_shader, vertex_shader);
+  flyweight<shader_program> fly{id, {id, fragment_shader, vertex_shader}};
+  return g_shader_programs.emplace(key, fly).first->second;
 }
 
 shader_program::shader_program(unsigned int id, flyweight<shader> frag,

+ 3 - 2
graphics/src/texture.cpp

@@ -48,8 +48,9 @@ flyweight<texture> texture::create(std::string const & imagefile) {
   unsigned char * data =
       stbi_load(imagefile.c_str(), &size.x(), &size.y(), &components, 0);
   scope(exit) { stbi_image_free(data); };
-  texture tex{textures::init(format(components), size, data), size};
-  return g_textures.emplace(imagefile, std::move(tex)).first->second;
+  auto id = textures::init(format(components), size, data);
+  flyweight<texture> fly{id, {id, size}};
+  return g_textures.emplace(imagefile, fly).first->second;
 }
 
 texture texture::create(char const * data, math::vec2i size) {

+ 6 - 5
util/include/game/util/flyweight.hpp

@@ -11,17 +11,18 @@
 
 #include "identity.hpp"
 
-template <typename T> class flyweight : public identity<T> {
+template <typename T> class flyweight {
 private:
   static std::unordered_map<unsigned int, T> actual_;
 
 public:
-  flyweight(unsigned int id, T actual) : identity<T>(id) {
+  const unsigned int id;
+
+public:
+  flyweight(unsigned int id, T actual) : id(id) {
     actual_.emplace(id, std::move(actual));
   }
-  flyweight(T actual) : identity<T>(actual) {
-    actual_.emplace(this->id, std::move(actual));
-  }
+  flyweight(identity<T> actual) : id(actual.id) {}
   T const & actual() const { return actual_.find(this->id)->second; }
 };