From 2cb1d745b28e2805d598f62f18ce83ee4aad050b Mon Sep 17 00:00:00 2001
From: Dominic Masters <dominic@domsplace.com>
Date: Fri, 27 Sep 2024 21:55:53 -0500
Subject: [PATCH] Add JSON parser

---
 assets/dawnrpg/CMakeLists.txt                 |  3 +-
 .../dawnrpg/{maps/testmap.json => test.json}  |  0
 src/dawn/asset/AssetManager.cpp               | 15 ++++++
 src/dawn/asset/AssetManager.hpp               |  1 +
 src/dawn/asset/loaders/CMakeLists.txt         |  1 +
 src/dawn/asset/loaders/JSONLoader.cpp         | 46 +++++++++++++++++++
 src/dawn/asset/loaders/JSONLoader.hpp         | 42 +++++++++++++++++
 src/dawn/dawnlibs.hpp                         |  5 +-
 src/dawnrpg/component/entity/Entity.cpp       |  2 +-
 src/dawnrpg/component/entity/Player.cpp       | 11 ++++-
 src/dawnrpg/scenes/WorldScene.cpp             |  5 ++
 11 files changed, 126 insertions(+), 5 deletions(-)
 rename assets/dawnrpg/{maps/testmap.json => test.json} (100%)
 create mode 100644 src/dawn/asset/loaders/JSONLoader.cpp
 create mode 100644 src/dawn/asset/loaders/JSONLoader.hpp

diff --git a/assets/dawnrpg/CMakeLists.txt b/assets/dawnrpg/CMakeLists.txt
index 0cc5becb..75919a7b 100644
--- a/assets/dawnrpg/CMakeLists.txt
+++ b/assets/dawnrpg/CMakeLists.txt
@@ -3,4 +3,5 @@
 # This software is released under the MIT License.
 # https://opensource.org/licenses/MIT
 
-tool_truetype(font_silver "${CMAKE_CURRENT_LIST_DIR}/Silver.ttf")
\ No newline at end of file
+tool_truetype(font_silver "${CMAKE_CURRENT_LIST_DIR}/Silver.ttf")
+tool_copy(json_test "${CMAKE_CURRENT_LIST_DIR}/test.json" "${DAWN_ASSETS_BUILD_DIR}/test.json")
\ No newline at end of file
diff --git a/assets/dawnrpg/maps/testmap.json b/assets/dawnrpg/test.json
similarity index 100%
rename from assets/dawnrpg/maps/testmap.json
rename to assets/dawnrpg/test.json
diff --git a/src/dawn/asset/AssetManager.cpp b/src/dawn/asset/AssetManager.cpp
index f8d55315..eca085b4 100644
--- a/src/dawn/asset/AssetManager.cpp
+++ b/src/dawn/asset/AssetManager.cpp
@@ -6,6 +6,7 @@
 #include "AssetManager.hpp"
 #include "loaders/TextureLoader.hpp"
 #include "loaders/TrueTypeLoader.hpp"
+#include "loaders/JSONLoader.hpp"
 
 using namespace Dawn;
 
@@ -80,6 +81,20 @@ std::shared_ptr<TrueTypeTexture> AssetManager::get<TrueTypeTexture>(
   return loader->getTexture(fontSize);
 }
 
+template<>
+std::shared_ptr<json> AssetManager::get<json>(
+  const std::string filename
+) {
+  auto existing = this->getExisting<JSONLoader>(filename);
+  if(existing) return existing->data;
+
+  std::shared_ptr<JSONLoader> loader = std::make_shared<JSONLoader>(
+    filename
+  );
+  pendingAssetLoaders.push_back(std::static_pointer_cast<AssetLoader>(loader));
+  return loader->data;
+}
+
 
 AssetManager::~AssetManager() {
   
diff --git a/src/dawn/asset/AssetManager.hpp b/src/dawn/asset/AssetManager.hpp
index d9ec5034..a2bea45f 100644
--- a/src/dawn/asset/AssetManager.hpp
+++ b/src/dawn/asset/AssetManager.hpp
@@ -80,6 +80,7 @@ namespace Dawn {
        * Returns the asset loader for the given asset.
        * 
        * @param filename The filename of the asset to get.
+       * @param fontSize The font size to get the truetype asset of.
        * @return The asset loader for the given asset.
        */
       template<class T>
diff --git a/src/dawn/asset/loaders/CMakeLists.txt b/src/dawn/asset/loaders/CMakeLists.txt
index e7c90da1..1f2bcac1 100644
--- a/src/dawn/asset/loaders/CMakeLists.txt
+++ b/src/dawn/asset/loaders/CMakeLists.txt
@@ -8,4 +8,5 @@ target_sources(${DAWN_TARGET_NAME}
   PRIVATE
     TextureLoader.cpp
     TrueTypeLoader.cpp
+    JSONLoader.cpp
 )
\ No newline at end of file
diff --git a/src/dawn/asset/loaders/JSONLoader.cpp b/src/dawn/asset/loaders/JSONLoader.cpp
new file mode 100644
index 00000000..350ea52b
--- /dev/null
+++ b/src/dawn/asset/loaders/JSONLoader.cpp
@@ -0,0 +1,46 @@
+// Copyright (c) 2024 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "JSONLoader.hpp"
+#include "assert/assert.hpp"
+
+using namespace Dawn;
+
+JSONLoader::JSONLoader(const std::string name) :
+  AssetLoader(name),
+  loader(name + ".json"),
+  state(JSONLoaderLoadState::INITIAL)
+{
+  data = std::make_shared<json>();
+}
+
+void JSONLoader::updateAsync() {
+  if(this->state != JSONLoaderLoadState::INITIAL) return;
+  this->state = JSONLoaderLoadState::LOADING_FILE;
+
+  this->loader.open();
+  auto size = this->loader.getSize();
+
+  auto buffer = new uint8_t[size + 1];
+  assertNotNull(buffer, "Failed to allocate buffer!");
+
+  this->state = JSONLoaderLoadState::PARSING_DATA;
+  auto read = this->loader.read(buffer, size);
+  assertTrue(read == size, "Failed to read entire file!");
+  buffer[size] = '\0';
+
+  *data = json::parse(buffer);
+  delete[] buffer;
+
+  this->state = JSONLoaderLoadState::DONE;
+  this->loaded = true;
+}
+
+void JSONLoader::updateSync() {
+}
+
+JSONLoader::~JSONLoader() {
+  this->data = nullptr;
+}
\ No newline at end of file
diff --git a/src/dawn/asset/loaders/JSONLoader.hpp b/src/dawn/asset/loaders/JSONLoader.hpp
new file mode 100644
index 00000000..3eb412c9
--- /dev/null
+++ b/src/dawn/asset/loaders/JSONLoader.hpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2024 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "asset/AssetLoader.hpp"
+#include "asset/AssetDataLoader.hpp"
+
+namespace Dawn {
+  enum class JSONLoaderLoadState {
+    INITIAL,
+    LOADING_FILE,
+    PARSING_DATA,
+    DONE
+  };
+
+  class JSONLoader : public AssetLoader {
+    protected:
+      AssetDataLoader loader;
+      enum JSONLoaderLoadState state;
+
+    public:
+      std::shared_ptr<json> data;
+
+      /**
+       * Constructs a JSON asset loader. You should instead use the parent
+       * asset managers' abstracted load method
+       * 
+       * @param name File name asset to load, omitting the extension.
+       */
+      JSONLoader(const std::string name);
+
+      void updateSync() override;
+      void updateAsync() override;
+
+      /**
+       * Dispose / Cleanup the JSON asset.
+       */
+      ~JSONLoader();
+  };
+}
\ No newline at end of file
diff --git a/src/dawn/dawnlibs.hpp b/src/dawn/dawnlibs.hpp
index 9d70aea2..fb85f91e 100644
--- a/src/dawn/dawnlibs.hpp
+++ b/src/dawn/dawnlibs.hpp
@@ -47,4 +47,7 @@ extern "C" {
 // #include <glm/gtx/intersect.hpp>
 #include <glm/gtc/type_ptr.hpp>
 #define GLM_ENABLE_EXPERIMENTAL 1
-#include <glm/gtx/matrix_decompose.hpp>
\ No newline at end of file
+#include <glm/gtx/matrix_decompose.hpp>
+
+#include <nlohmann/json.hpp>
+using json = nlohmann::json;
\ No newline at end of file
diff --git a/src/dawnrpg/component/entity/Entity.cpp b/src/dawnrpg/component/entity/Entity.cpp
index e7af6935..5175c06e 100644
--- a/src/dawnrpg/component/entity/Entity.cpp
+++ b/src/dawnrpg/component/entity/Entity.cpp
@@ -37,7 +37,7 @@ void Entity::onInit() {
       return;
     }
 
-    float_t t = Easing::easeInOutSine(1.0f - this->stepTime);
+    float_t t = 1.0f - this->stepTime;
     glm::vec3 lastPosition = this->lastTilePosition.toWorldSpace();
     glm::vec3 newLocal = glm::mix(lastPosition, nextPosition, t);
     this->getItem()->setLocalPosition(newLocal);
diff --git a/src/dawnrpg/component/entity/Player.cpp b/src/dawnrpg/component/entity/Player.cpp
index 085e3e56..71a3d347 100644
--- a/src/dawnrpg/component/entity/Player.cpp
+++ b/src/dawnrpg/component/entity/Player.cpp
@@ -14,11 +14,11 @@ void Player::updateCameraPosition() {
   if(!c) return;
   glm::vec3 pos = this->getItem()->getLocalPosition();
   c->getItem()->lookAtPixelPerfect(
-    pos + glm::vec3(0, 3, 1),
+    pos + glm::vec3(0, -10, 0),
     pos,
     c->getRenderTarget()->getHeight(),
     c->fov,
-    32.0f
+    48.0f
   );
 }
 
@@ -45,6 +45,13 @@ void Player::onInit() {
     }
   }));
 
+  auto c = camera.lock();
+  if(c) {
+    listeners.push_back(c->getRenderTarget()->onResize.listen([this](int width, int height){
+      this->updateCameraPosition();
+    }));
+  }
+
   listeners.push_back(eventMove.listen([this]() {
     this->updateCameraPosition();
   }));
diff --git a/src/dawnrpg/scenes/WorldScene.cpp b/src/dawnrpg/scenes/WorldScene.cpp
index bbbad327..adbed34a 100644
--- a/src/dawnrpg/scenes/WorldScene.cpp
+++ b/src/dawnrpg/scenes/WorldScene.cpp
@@ -25,6 +25,11 @@
 using namespace Dawn;
 
 void Dawn::worldScene(Scene &s) {
+  auto testj = s.getGame()->assetManager.get<json>("test");
+  while(!s.getGame()->assetManager.isEverythingLoaded()) {
+    s.getGame()->assetManager.update();
+  }
+
   auto cameraItem = s.createSceneItem();
   auto camera = cameraItem->addComponent<Camera>();
   cameraItem->lookAt({ 3, 3, 3 }, { 0, 0, 0 }, { 0, 1, 0 });