Browse Source

Merge branch 'text_renderer'

* text_renderer:
  Remove unneeded parameter to FPS counter ctor.
  Fix bugs in text display caused by indices not being normalized. Fix FPS '.' position Fix FPS display width. Fix text spacing in texture frame.
  Add text engine to the game_dispatch engine.
  Add code to fill out text cells with data.
  Add a text engine that mirrors current code in FPS Counter class but is disconnected from the rest of the system currently.
Sam Jaffe 6 năm trước cách đây
mục cha
commit
3798ecebe8

+ 4 - 0
engine/engine.xcodeproj/project.pbxproj

@@ -8,6 +8,7 @@
 
 /* Begin PBXBuildFile section */
 		CD1C83562298B55F00825C4E /* fps_counter.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD1C83542298B55F00825C4E /* fps_counter.cxx */; };
+		CD1C8419229A095600825C4E /* text_engine.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD1C8417229A095600825C4E /* text_engine.cxx */; };
 		CD62D8462251A94C0023219A /* libgraphics.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD62D8452251A94C0023219A /* libgraphics.dylib */; };
 		CD62D8482251A9500023219A /* libmath.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD62D8472251A9500023219A /* libmath.dylib */; };
 		CD62FCCE22904A8900376440 /* libengine.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CDB1F8AE1D7A30CD00700C6B /* libengine.dylib */; };
@@ -68,6 +69,7 @@
 
 /* Begin PBXFileReference section */
 		CD1C83542298B55F00825C4E /* fps_counter.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = fps_counter.cxx; sourceTree = "<group>"; };
+		CD1C8417229A095600825C4E /* text_engine.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = text_engine.cxx; sourceTree = "<group>"; };
 		CD62D8452251A94C0023219A /* libgraphics.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libgraphics.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		CD62D8472251A9500023219A /* libmath.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libmath.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		CD62FCB622904A7B00376440 /* GoogleMock.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GoogleMock.xcodeproj; path = "../../gmock-xcode-master/GoogleMock.xcodeproj"; sourceTree = "<group>"; };
@@ -174,6 +176,7 @@
 				CDB1F8D01D7A32A300700C6B /* events.cpp */,
 				CDB1F8C61D7A312B00700C6B /* game_dispatch.cpp */,
 				CD1C83542298B55F00825C4E /* fps_counter.cxx */,
+				CD1C8417229A095600825C4E /* text_engine.cxx */,
 				CDB1F8CA1D7A319A00700C6B /* scene.cpp */,
 				CD62FD3E2293746900376440 /* serial.cxx */,
 			);
@@ -352,6 +355,7 @@
 				CDB1F8CC1D7A319A00700C6B /* scene.cpp in Sources */,
 				CDB1F8C81D7A312B00700C6B /* game_dispatch.cpp in Sources */,
 				CD62FD402293746900376440 /* serial.cxx in Sources */,
+				CD1C8419229A095600825C4E /* text_engine.cxx in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 1 - 0
engine/include/game/engine/engine_fwd.hpp

@@ -23,6 +23,7 @@ namespace engine {
   class fps_counter;
   class game_dispatch;
   class scene;
+  class text_engine;
 
   namespace event {
     struct key_event;

+ 6 - 2
engine/include/game/engine/fps_counter.hpp

@@ -14,10 +14,11 @@
 #include "game/util/time.hpp"
 
 namespace engine {
+  class text_engine;
   class fps_counter {
   public:
-    fps_counter(env::clock::duration const & fpscap,
-                graphics::manager const & mgr, std::size_t precision = 3);
+    fps_counter(std::shared_ptr<text_engine> text_engine,
+                std::size_t precision = 3);
     ~fps_counter();
 
     void set_frame_step(env::clock::duration const & since);
@@ -25,9 +26,12 @@ namespace engine {
     std::vector<graphics::object> const & glyphs() const { return glyphs_; }
 
   private:
+    std::string fps(env::clock::duration const & since) const;
+
     int counter_{0}, change_after_{10};
     std::size_t digits_;
     std::size_t magnitude_;
+    std::shared_ptr<text_engine> text_engine_;
     std::vector<graphics::object> glyphs_;
   };
 }

+ 1 - 0
engine/include/game/engine/game_dispatch.hpp

@@ -42,6 +42,7 @@ namespace engine {
     std::shared_ptr<graphics::renderer> renderer;
     math::vec2 screen_size;
     env::clock::duration minimum_frame_duration;
+    std::shared_ptr<text_engine> text_engine_;
     std::unique_ptr<fps_counter> counter;
 
     using scene_t = std::shared_ptr<scene>;

+ 41 - 0
engine/include/game/engine/text_engine.hpp

@@ -0,0 +1,41 @@
+//
+//  text_engine.hpp
+//  engine
+//
+//  Created by Sam Jaffe on 5/25/19.
+//  Copyright © 2019 Sam Jaffe. All rights reserved.
+//
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "game/graphics/object.hpp"
+#include "game/math/math_fwd.hpp"
+#include "vector/vector.hpp"
+
+namespace engine {
+  class text_engine {
+  public:
+    struct cell {
+      math::vec2 origin;
+      math::vec2 size;
+      std::string content;
+    };
+
+  public:
+    text_engine(std::string const & font,
+                std::shared_ptr<graphics::manager const> manager);
+
+    void create_text_cells(std::vector<graphics::object> & out,
+                           cell const & in);
+
+  private:
+    //    std::shared_ptr<graphics::manager const> manager_;
+    std::string font_;
+    graphics::object prototype_;
+    std::unordered_map<char, math::vec2> glyphs_;
+  };
+}

+ 13 - 50
engine/src/fps_counter.cxx

@@ -12,65 +12,28 @@
 #include <unordered_map>
 
 #include "game/engine/serial.hpp"
+#include "game/engine/text_engine.hpp"
 #include "game/graphics/object.hpp"
 
 using namespace engine;
 
-static graphics::object create(graphics::manager const & mgr) {
-  Json::Value value;
-  value["material"]["texture"]["file"] = "data/images/font.bmp";
-  value["material"]["texture"]["uniform"] = "u_normalMap";
-  return engine::to_object(value, mgr);
-}
-
-static std::size_t digits(env::clock::duration const & fpscap) {
-  auto fps = env::clock::duration::period::den / fpscap.count();
-  std::size_t digits = 1;
-  while (fps /= 10)
-    ++digits;
-  return digits;
-}
-
-std::unordered_map<char, math::vec2> const indices{
-    {'.', make_vector(6.f, 6.f)}, {'0', make_vector(0.f, 5.f)},
-    {'1', make_vector(1.f, 5.f)}, {'2', make_vector(2.f, 5.f)},
-    {'3', make_vector(3.f, 5.f)}, {'4', make_vector(4.f, 5.f)},
-    {'5', make_vector(5.f, 5.f)}, {'6', make_vector(6.f, 5.f)},
-    {'7', make_vector(7.f, 5.f)}, {'8', make_vector(0.f, 4.f)},
-    {'9', make_vector(1.f, 4.f)}};
-
-math::vec2 index(char value) {
-  auto it = indices.find(value);
-  return it != indices.end() ? it->second : make_vector(0.f, 0.f);
-}
-
-math::vec2 number_index(int num) { return index(char(num + '0')); }
-
-fps_counter::fps_counter(env::clock::duration const & fpscap,
-                         graphics::manager const & mgr, std::size_t precision)
+fps_counter::fps_counter(std::shared_ptr<text_engine> text_engine,
+                         std::size_t precision)
     : digits_(precision), magnitude_(std::pow(10, digits_)),
-      glyphs_(digits(fpscap) + digits_ + 1, create(mgr)) {
-  auto pixels = make_vector(0.125f, 0.125f);
-  for (std::size_t i = 0; i < glyphs_.size(); ++i) {
-    glyphs_[i].location.origin =
-        make_vector((glyphs_.size() - i) * 10.f - 5.f, 680.f);
-    glyphs_[i].location.size = make_vector(20.f, 20.f);
-    glyphs_[i].points = glyphs_[i].location;
-    glyphs_[i].frame.size = pixels;
-  }
-  glyphs_[digits_].frame.origin = index('.') * pixels;
-}
+      text_engine_(text_engine), glyphs_() {}
 
 fps_counter::~fps_counter() {}
 
+std::string fps_counter::fps(env::clock::duration const & since) const {
+  auto fps = magnitude_ * env::clock::duration::period::den / since.count();
+  std::string fps_str = std::to_string(fps);
+  fps_str.insert(fps_str.size() - digits_, ".");
+  return fps_str;
+}
+
 void fps_counter::set_frame_step(env::clock::duration const & since) {
   if (++counter_ != change_after_) { return; }
   counter_ = 0;
-  auto pixels = make_vector(0.125f, 0.125f);
-  auto fps = magnitude_ * env::clock::duration::period::den / since.count();
-  for (std::size_t i = 0; i < glyphs_.size(); ++i) {
-    if (i == digits_) continue;
-    glyphs_[i].frame.origin = number_index(fps % 10) * pixels;
-    fps /= 10;
-  }
+  text_engine_->create_text_cells(
+      glyphs_, {make_vector(5.f, 680.f), make_vector(10.f, 20.f), fps(since)});
 }

+ 4 - 2
engine/src/game_dispatch.cpp

@@ -12,6 +12,7 @@
 #include "game/engine/events.hpp"
 #include "game/engine/fps_counter.hpp"
 #include "game/engine/scene.hpp"
+#include "game/engine/text_engine.hpp"
 #include "game/graphics/object.hpp"
 #include "game/graphics/renderer.hpp"
 #include "game/util/env.hpp"
@@ -27,8 +28,9 @@ namespace engine {
   game_dispatch::game_dispatch(std::shared_ptr<graphics::renderer> renderer)
       : renderer(renderer), screen_size(env::screen_size()),
         minimum_frame_duration(env::fps::v60),
-        counter(new fps_counter(minimum_frame_duration, *renderer->manager())),
-        scenes(), current_timestamp(env::clock::now()), curr_scene() {}
+        text_engine_(new text_engine("font", renderer->manager())),
+        counter(new fps_counter(text_engine_)), scenes(),
+        current_timestamp(env::clock::now()), curr_scene() {}
 
   game_dispatch::~game_dispatch() {}
 

+ 61 - 0
engine/src/text_engine.cxx

@@ -0,0 +1,61 @@
+//
+//  text_engine.cxx
+//  engine
+//
+//  Created by Sam Jaffe on 5/25/19.
+//  Copyright © 2019 Sam Jaffe. All rights reserved.
+//
+
+#include "game/engine/text_engine.hpp"
+
+#include <json/value.h>
+
+#include "game/engine/serial.hpp"
+#include "game/graphics/manager.hpp"
+
+using namespace engine;
+
+Json::Value font_material(std::string const & font) {
+  Json::Value value;
+  value["material"]["texture"]["file"] = "data/images/fonts/" + font + ".bmp";
+  value["material"]["texture"]["uniform"] = "u_normalMap";
+  return value;
+}
+
+std::unordered_map<char, math::vec2> glyph_locations(std::string const & font) {
+  // TODO (sjaffe): Fill out glyphs programmatically (resource file)...
+  return {{'.', make_vector(6.f, 6.f)}, {'0', make_vector(0.f, 5.f)},
+          {'1', make_vector(1.f, 5.f)}, {'2', make_vector(2.f, 5.f)},
+          {'3', make_vector(3.f, 5.f)}, {'4', make_vector(4.f, 5.f)},
+          {'5', make_vector(5.f, 5.f)}, {'6', make_vector(6.f, 5.f)},
+          {'7', make_vector(7.f, 5.f)}, {'8', make_vector(0.f, 4.f)},
+          {'9', make_vector(1.f, 4.f)}};
+}
+
+text_engine::text_engine(std::string const & font,
+                         std::shared_ptr<graphics::manager const> manager)
+    : font_(font), prototype_(to_object(font_material(font_), *manager)),
+      glyphs_(glyph_locations(font_)) {
+  // TODO (sjaffe): Also needs to be programmatic
+  auto glyph_size = make_vector(0.125f, 0.125f);
+  // The font I chose is a monospace font where height = 2 * width
+  prototype_.frame.size = glyph_size / make_vector(2, 1);
+  for (auto & pair : glyphs_) {
+    pair.second *= glyph_size;
+  }
+}
+
+void text_engine::create_text_cells(std::vector<graphics::object> & out,
+                                    cell const & in) {
+  std::size_t const old_size = out.size();
+  std::size_t const new_size = in.content.size();
+  if (old_size != new_size) { out.resize(new_size, prototype_); }
+  for (std::size_t i = old_size; i < new_size; ++i) {
+    auto & obj = out[i];
+    obj.location = {in.origin + make_vector(in.size[0] * i, 0.f), in.size};
+    obj.points = obj.location;
+  }
+  for (std::size_t i = 0; i < new_size; ++i) {
+    out[i].frame.origin = glyphs_.find(in.content[i])->second;
+  }
+}