From 91163cfcadd635a8ac804810063c32aa19d76d5a Mon Sep 17 00:00:00 2001
From: Dominic Masters <dominic@domsplace.com>
Date: Wed, 1 Mar 2023 14:16:50 -0800
Subject: [PATCH] Updating a few more things to state events, will probably
 stop here for now and revist the trailing things later.

---
 src/dawn/asset/Asset.hpp                      |   5 +-
 src/dawn/asset/AssetManager.cpp               |   7 +-
 src/dawn/asset/assets/AudioAsset.cpp          | 151 ++++---
 src/dawn/display/animation/Animation.hpp      |  79 ++--
 .../display/animation/SimpleAnimation.hpp     | 409 +++++++++---------
 src/dawn/input/_InputManager.hpp              |  16 +-
 src/dawn/locale/LocaleManager.hpp             |   8 +-
 src/dawn/ui/UIComponent.hpp                   |   3 +-
 src/dawn/ui/UILabel.cpp                       |  22 +-
 src/dawn/ui/UILabel.hpp                       |   8 +-
 src/dawnlinux64/host/CMakeLists.txt           |  18 +-
 .../{DawnHostWin32.cpp => DawnHostTux32.cpp}  |   2 +-
 .../{DawnHostWin32.hpp => DawnHostTux32.hpp}  |  34 +-
 .../scene/components/audio/AudioSource.hpp    |  12 +-
 .../tools/languagegen/LanguageGen.hpp         |  28 +-
 15 files changed, 397 insertions(+), 405 deletions(-)
 rename src/dawnlinux64/host/{DawnHostWin32.cpp => DawnHostTux32.cpp} (92%)
 rename src/dawnlinux64/host/{DawnHostWin32.hpp => DawnHostTux32.hpp} (96%)

diff --git a/src/dawn/asset/Asset.hpp b/src/dawn/asset/Asset.hpp
index 4975969f..7111d09d 100644
--- a/src/dawn/asset/Asset.hpp
+++ b/src/dawn/asset/Asset.hpp
@@ -4,9 +4,7 @@
 // https://opensource.org/licenses/MIT
 
 #pragma once
-#include "dawnlibs.hpp"
-#include "assert/assert.hpp"
-#include "event/Event.hpp"
+#include "state/State.hpp"
 
 namespace Dawn {
   class AssetManager;
@@ -18,6 +16,7 @@ namespace Dawn {
       uint8_t state = 0x00;
       bool loaded = false;
       Event<> eventLoaded;
+      StateEvent<> event2Loaded;
 
       /**
        * Create an abstract Asset object.
diff --git a/src/dawn/asset/AssetManager.cpp b/src/dawn/asset/AssetManager.cpp
index 38369a48..a2288948 100644
--- a/src/dawn/asset/AssetManager.cpp
+++ b/src/dawn/asset/AssetManager.cpp
@@ -28,10 +28,12 @@ void AssetManager::queueLoad(Asset *asset) {
 }
 
 void AssetManager::queueUnload(std::vector<Asset*> assets) {
+  std::cout << "Asset list was queued to unload, but is not yet implemented" << std::endl;
   vectorAppend(&this->assetsToUnload, &assets);
 }
 
 void AssetManager::queueUnload(Asset *asset) {
+  std::cout << "Asset was queued to unload, but is not yet implemented" << std::endl;
   this->assetsToUnload.push_back(asset);
 }
 
@@ -64,12 +66,12 @@ void AssetManager::queueSwap(
 
 void AssetManager::syncTick() {
   auto it = this->assetsToLoad.begin();
-  // auto it = this->assetsNotLoaded.begin();
   while(it != this->assetsToLoad.end()) {
     auto asset = *it;
     if(asset->loaded) {
       it = this->assetsToLoad.erase(it);
       asset->eventLoaded.invoke();
+      asset->event2Loaded.invoke();
       continue;
     }
 
@@ -79,12 +81,13 @@ void AssetManager::syncTick() {
     if(asset->loaded) {
       it = this->assetsToLoad.erase(it);
       asset->eventLoaded.invoke();
+      asset->event2Loaded.invoke();
       continue;
     }
 
     ++it;
   }
-
+  // auto it = this->assetsNotLoaded.begin();
   // auto it2 = this->assetsToUnload.begin();
   // while(it2 != this->assetsToUnload.end()) {
   //   ++it2;
diff --git a/src/dawn/asset/assets/AudioAsset.cpp b/src/dawn/asset/assets/AudioAsset.cpp
index 41219db3..350e485e 100644
--- a/src/dawn/asset/assets/AudioAsset.cpp
+++ b/src/dawn/asset/assets/AudioAsset.cpp
@@ -1,77 +1,76 @@
-// Copyright (c) 2023 Dominic Masters
-// 
-// This software is released under the MIT License.
-// https://opensource.org/licenses/MIT
-
-#include "AudioAsset.hpp"
-
-using namespace Dawn;
-
-AudioAsset::AudioAsset(AssetManager *man, std::string name) :
-  Asset(man, name),
-  loader(name + ".audio")
-{
-
-}
-
-void AudioAsset::updateSync() {
-  if(this->state != 0x07) return;
-
-  // THIS WILL DEFINITELY CHANGE
-  this->state = 0x08;
-  this->loaded = true;
-  this->eventLoaded.invoke();
-}
-
-void AudioAsset::updateAsync() {
-  if(this->state != 0x00) return;
-  char *start, *end;
-  char buffer[1024];
-
-  // Open asset for reading
-  this->state = 0x01;
-  this->loader.open();
-
-  // Parse header data.
-  this->state = 0x02;
-  this->loader.read((uint8_t *)buffer, 1024);
-
-  // Channel count
-  this->state = 0x03;
-  start = buffer;
-  end = strchr(start, '|');
-  *end = '\0';
-  this->channelCount = atoi(start);
-  assertTrue(this->channelCount > 0);
-
-  // Sample Rate
-  this->state = 0x04;
-  start = end + 1;
-  end = strchr(start, '|');
-  *end = '\0';
-  this->sampleRate = (uint32_t)strtoul(start, NULL, 10);
-  assertTrue(this->sampleRate > 0);
-
-  // Number of samples per channel
-  this->state = 0x05;
-  start = end + 1;
-  end = strchr(start, '|');
-  *end = '\0';
-  this->samplesPerChannel = atoi(start);
-  assertTrue(this->samplesPerChannel > 0);
-
-  // Total Data Length
-  this->state = 0x06;
-  start = end + 1;
-  end = strchr(start, '|');
-  *end = '\0';
-  this->bufferSize = (size_t)atoll(start);
-  assertTrue(this->bufferSize > 0);
-
-  // Determine frame size
-  this->frameSize = sizeof(int16_t) * this->channelCount;
-
-  // Indicated start of data
-  this->state = 0x07;
-  this->bufferStart = end - buffer;
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "AudioAsset.hpp"
+
+using namespace Dawn;
+
+AudioAsset::AudioAsset(AssetManager *man, std::string name) :
+  Asset(man, name),
+  loader(name + ".audio")
+{
+
+}
+
+void AudioAsset::updateSync() {
+  if(this->state != 0x07) return;
+
+  // THIS WILL DEFINITELY CHANGE
+  this->state = 0x08;
+  this->loaded = true;
+}
+
+void AudioAsset::updateAsync() {
+  if(this->state != 0x00) return;
+  char *start, *end;
+  char buffer[1024];
+
+  // Open asset for reading
+  this->state = 0x01;
+  this->loader.open();
+
+  // Parse header data.
+  this->state = 0x02;
+  this->loader.read((uint8_t *)buffer, 1024);
+
+  // Channel count
+  this->state = 0x03;
+  start = buffer;
+  end = strchr(start, '|');
+  *end = '\0';
+  this->channelCount = atoi(start);
+  assertTrue(this->channelCount > 0);
+
+  // Sample Rate
+  this->state = 0x04;
+  start = end + 1;
+  end = strchr(start, '|');
+  *end = '\0';
+  this->sampleRate = (uint32_t)strtoul(start, NULL, 10);
+  assertTrue(this->sampleRate > 0);
+
+  // Number of samples per channel
+  this->state = 0x05;
+  start = end + 1;
+  end = strchr(start, '|');
+  *end = '\0';
+  this->samplesPerChannel = atoi(start);
+  assertTrue(this->samplesPerChannel > 0);
+
+  // Total Data Length
+  this->state = 0x06;
+  start = end + 1;
+  end = strchr(start, '|');
+  *end = '\0';
+  this->bufferSize = (size_t)atoll(start);
+  assertTrue(this->bufferSize > 0);
+
+  // Determine frame size
+  this->frameSize = sizeof(int16_t) * this->channelCount;
+
+  // Indicated start of data
+  this->state = 0x07;
+  this->bufferStart = end - buffer;
 }
\ No newline at end of file
diff --git a/src/dawn/display/animation/Animation.hpp b/src/dawn/display/animation/Animation.hpp
index fb155b91..416dc48e 100644
--- a/src/dawn/display/animation/Animation.hpp
+++ b/src/dawn/display/animation/Animation.hpp
@@ -1,40 +1,41 @@
-// Copyright (c) 2022 Dominic Masters
-// 
-// This software is released under the MIT License.
-// https://opensource.org/licenses/MIT
-
-#pragma once
-#include "event/Event.hpp"
-#include "Easing.hpp"
-#include "util/mathutils.hpp"
-
-namespace Dawn {
-  struct Animation {
-    public:
-      bool_t loop = false;
-      bool_t finished = false;
-      float_t time = 0;
-      float_t duration = 0;
-      Event<> eventAnimationEnd;
-      
-      /**
-       * Ticks the animation along. Delta is whatever you want to update the
-       * animation by (in seconds). Animations can overshoot if necessary and
-       * will not be clamped (by default). Subclasses may interpret ticks in
-       * different ways.
-       * 
-       * @param delta Time delta (in seconds) to tick the animaiton by.
-       */
-      virtual void tick(float_t delta) = 0;
-      
-      /**
-       * Restart a running animation.
-       */
-      virtual void restart();
-
-      /**
-       * Clears an animaton of all its animation items and keyframes.
-       */
-      virtual void clear();
-  };
+// Copyright (c) 2022 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "state/State.hpp"
+#include "Easing.hpp"
+#include "util/mathutils.hpp"
+
+namespace Dawn {
+  struct Animation {
+    public:
+      bool_t loop = false;
+      bool_t finished = false;
+      float_t time = 0;
+      float_t duration = 0;
+      Event<> eventAnimationEnd;
+      StateEvent<> event2AnimationEnd;
+      
+      /**
+       * Ticks the animation along. Delta is whatever you want to update the
+       * animation by (in seconds). Animations can overshoot if necessary and
+       * will not be clamped (by default). Subclasses may interpret ticks in
+       * different ways.
+       * 
+       * @param delta Time delta (in seconds) to tick the animaiton by.
+       */
+      virtual void tick(float_t delta) = 0;
+      
+      /**
+       * Restart a running animation.
+       */
+      virtual void restart();
+
+      /**
+       * Clears an animaton of all its animation items and keyframes.
+       */
+      virtual void clear();
+  };
 }
\ No newline at end of file
diff --git a/src/dawn/display/animation/SimpleAnimation.hpp b/src/dawn/display/animation/SimpleAnimation.hpp
index a194451e..a3a52e73 100644
--- a/src/dawn/display/animation/SimpleAnimation.hpp
+++ b/src/dawn/display/animation/SimpleAnimation.hpp
@@ -1,205 +1,206 @@
-// Copyright (c) 2022 Dominic Masters
-// 
-// This software is released under the MIT License.
-// https://opensource.org/licenses/MIT
-
-#pragma once
-#include "Animation.hpp"
-
-namespace Dawn {
-  template<typename T>
-  struct SimpleKeyframe {
-    float_t time;
-    T value;
-  };
-
-  template<typename T>
-  struct SimpleAnimation : public Animation {
-    protected:
-      /**
-       * Function for subclasses to be "notified" when the value has been 
-       * modified.
-       */
-      virtual void onValueModified() {
-
-      }
-
-      /**
-       * Sorts internal keyframes by their time to make them conform correctly.
-       */
-      void sortKeyframes() {
-        std::sort(
-          this->keyframes.begin(),
-          this->keyframes.end(),
-          [](struct SimpleKeyframe<T> &a, struct SimpleKeyframe<T>  &b) {
-            return a.time < b.time;
-          }
-        );
-      }
-
-    public:
-      easefunction_t *easing = &easeLinear;
-      T *modifies;
-      std::vector<struct SimpleKeyframe<T>> keyframes;
-
-      /**
-       * Constructs a new Simple Animation instance.
-       * 
-       * @param modifies Pointer to the value that will be modified.
-       */
-      SimpleAnimation(T *modifies) {
-        assertNotNull(modifies);
-        this->modifies = modifies;
-      }
-
-      /**
-       * Adds a keyframe that will be slerped to at a given time.
-       * 
-       * @param time Time the keyframe occurs.
-       * @param value Value at this given time.
-       */
-      void addKeyframe(float_t time, T value) {
-        assertTrue(time >= 0);
-        
-        struct SimpleKeyframe<T> keyframe;
-        keyframe.time = time;
-        keyframe.value = value;
-        this->duration = mathMax<float_t>(this->duration, time);
-        this->finished = false;
-        this->keyframes.push_back(keyframe);
-
-        if(time < this->duration) this->sortKeyframes();
-      }
-
-      /**
-       * Quickly add a series of keyframes. For example, if you want to have a
-       * keyframe series of;
-       * [ 1, 3, 5, 7, 9 ]
-       * 
-       * And occur at times
-       * [ 0, 2, 4, 6, 8 ]
-       * 
-       * You would pass frameTime as 2, and step as 2.
-       * 
-       * @param startTime When the first keyframe occurs.
-       * @param frameTime At what rate do keyframes occur.
-       * @param start Initial value (the value at startTime).
-       * @param end The end value (for the last keyframe).
-       * @param step How to step the value.
-       */
-      void addSequentialKeyframes(
-        float_t startTime,
-        float_t frameTime,
-        T start,
-        T end,
-        T step
-      ) {
-        T v = start;
-        float_t n = startTime;
-        while(v != end) {
-          this->addKeyframe(n, v);
-          n += frameTime;
-          v += step;
-        }
-      }
-
-      /**
-       * Shorthand addSequentialKeyframes, assumes a step of 1 and a startTime
-       * of 0.
-       * 
-       * @param frameTime Time between frames.
-       * @param start Initial value.
-       * @param end End value.
-       */
-      void addSequentialKeyframes(float_t frameTime, T start, T end) {
-        this->addSequentialKeyframes(0, frameTime, start, end, 1);
-      }
-
-      /**
-       * Immediately sets the value, bypassing keyframes and ticks. Useful for
-       * setting an initial value.
-       * 
-       * @param value Value to set.
-       */
-      void setValue(T value) {
-        *modifies = value;
-        this->onValueModified();
-      }
-
-      void tick(float_t delta) override {
-        if(this->finished) return;
-
-        float_t newTime = this->time + delta;
-
-        struct SimpleKeyframe<T> *keyframeNext = nullptr;
-        struct SimpleKeyframe<T> *keyframeCurrent = nullptr;
-        
-        // Find current and next keyframe(s)
-        auto itKey = this->keyframes.begin();
-        while(itKey != this->keyframes.end()) {
-          if(itKey->time > newTime) {
-            keyframeNext = &(*itKey);
-            break;
-          }
-          keyframeCurrent = &(*itKey);
-          ++itKey;
-        }
-
-        // Update values
-        if(keyframeCurrent != nullptr && keyframeNext == nullptr) {
-          // "End of animation"
-          *this->modifies = keyframeCurrent->value;
-          this->onValueModified();
-        } else if(keyframeNext != nullptr) {
-          T oldValue;
-          float_t oldTime;
-
-          if(keyframeCurrent == nullptr) {
-            // "Start of animation"
-            oldValue = keyframeCurrent->value;
-            oldTime = keyframeCurrent->time;
-          } else {
-            // "Mid animation"
-            oldTime = this->time;
-            oldValue = *this->modifies;
-          }
-
-          // Slerp between keyframes
-          float_t keyframeDelta = this->easing(
-            (newTime - oldTime) / (keyframeNext->time - oldTime)
-          );
-          *this->modifies = oldValue + (
-            (keyframeNext->value - oldValue) * keyframeDelta
-          );
-          this->onValueModified();
-        }
-
-        // First possible frame? I think this can be done cleaner
-        if(this->time == 0 && keyframeCurrent->time == 0) {
-          *this->modifies = keyframeCurrent->value;
-          this->onValueModified();
-        }
-
-        // Update time.
-        this->time = newTime;
-
-        // Has the animation finished?
-        if(newTime < this->duration) return;
-        
-        // Do we need to loop?
-        if(this->loop) {
-          this->time = 0;
-          return;
-        }
-
-        // Animation end.
-        this->finished = true;
-        this->eventAnimationEnd.invoke();
-      }
-      
-      void clear() override {
-        Animation::clear();
-        this->keyframes.clear();
-      }
-  };
+// Copyright (c) 2022 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "Animation.hpp"
+
+namespace Dawn {
+  template<typename T>
+  struct SimpleKeyframe {
+    float_t time;
+    T value;
+  };
+
+  template<typename T>
+  struct SimpleAnimation : public Animation {
+    protected:
+      /**
+       * Function for subclasses to be "notified" when the value has been 
+       * modified.
+       */
+      virtual void onValueModified() {
+
+      }
+
+      /**
+       * Sorts internal keyframes by their time to make them conform correctly.
+       */
+      void sortKeyframes() {
+        std::sort(
+          this->keyframes.begin(),
+          this->keyframes.end(),
+          [](struct SimpleKeyframe<T> &a, struct SimpleKeyframe<T>  &b) {
+            return a.time < b.time;
+          }
+        );
+      }
+
+    public:
+      easefunction_t *easing = &easeLinear;
+      T *modifies;
+      std::vector<struct SimpleKeyframe<T>> keyframes;
+
+      /**
+       * Constructs a new Simple Animation instance.
+       * 
+       * @param modifies Pointer to the value that will be modified.
+       */
+      SimpleAnimation(T *modifies) {
+        assertNotNull(modifies);
+        this->modifies = modifies;
+      }
+
+      /**
+       * Adds a keyframe that will be slerped to at a given time.
+       * 
+       * @param time Time the keyframe occurs.
+       * @param value Value at this given time.
+       */
+      void addKeyframe(float_t time, T value) {
+        assertTrue(time >= 0);
+        
+        struct SimpleKeyframe<T> keyframe;
+        keyframe.time = time;
+        keyframe.value = value;
+        this->duration = mathMax<float_t>(this->duration, time);
+        this->finished = false;
+        this->keyframes.push_back(keyframe);
+
+        if(time < this->duration) this->sortKeyframes();
+      }
+
+      /**
+       * Quickly add a series of keyframes. For example, if you want to have a
+       * keyframe series of;
+       * [ 1, 3, 5, 7, 9 ]
+       * 
+       * And occur at times
+       * [ 0, 2, 4, 6, 8 ]
+       * 
+       * You would pass frameTime as 2, and step as 2.
+       * 
+       * @param startTime When the first keyframe occurs.
+       * @param frameTime At what rate do keyframes occur.
+       * @param start Initial value (the value at startTime).
+       * @param end The end value (for the last keyframe).
+       * @param step How to step the value.
+       */
+      void addSequentialKeyframes(
+        float_t startTime,
+        float_t frameTime,
+        T start,
+        T end,
+        T step
+      ) {
+        T v = start;
+        float_t n = startTime;
+        while(v != end) {
+          this->addKeyframe(n, v);
+          n += frameTime;
+          v += step;
+        }
+      }
+
+      /**
+       * Shorthand addSequentialKeyframes, assumes a step of 1 and a startTime
+       * of 0.
+       * 
+       * @param frameTime Time between frames.
+       * @param start Initial value.
+       * @param end End value.
+       */
+      void addSequentialKeyframes(float_t frameTime, T start, T end) {
+        this->addSequentialKeyframes(0, frameTime, start, end, 1);
+      }
+
+      /**
+       * Immediately sets the value, bypassing keyframes and ticks. Useful for
+       * setting an initial value.
+       * 
+       * @param value Value to set.
+       */
+      void setValue(T value) {
+        *modifies = value;
+        this->onValueModified();
+      }
+
+      void tick(float_t delta) override {
+        if(this->finished) return;
+
+        float_t newTime = this->time + delta;
+
+        struct SimpleKeyframe<T> *keyframeNext = nullptr;
+        struct SimpleKeyframe<T> *keyframeCurrent = nullptr;
+        
+        // Find current and next keyframe(s)
+        auto itKey = this->keyframes.begin();
+        while(itKey != this->keyframes.end()) {
+          if(itKey->time > newTime) {
+            keyframeNext = &(*itKey);
+            break;
+          }
+          keyframeCurrent = &(*itKey);
+          ++itKey;
+        }
+
+        // Update values
+        if(keyframeCurrent != nullptr && keyframeNext == nullptr) {
+          // "End of animation"
+          *this->modifies = keyframeCurrent->value;
+          this->onValueModified();
+        } else if(keyframeNext != nullptr) {
+          T oldValue;
+          float_t oldTime;
+
+          if(keyframeCurrent == nullptr) {
+            // "Start of animation"
+            oldValue = keyframeCurrent->value;
+            oldTime = keyframeCurrent->time;
+          } else {
+            // "Mid animation"
+            oldTime = this->time;
+            oldValue = *this->modifies;
+          }
+
+          // Slerp between keyframes
+          float_t keyframeDelta = this->easing(
+            (newTime - oldTime) / (keyframeNext->time - oldTime)
+          );
+          *this->modifies = oldValue + (
+            (keyframeNext->value - oldValue) * keyframeDelta
+          );
+          this->onValueModified();
+        }
+
+        // First possible frame? I think this can be done cleaner
+        if(this->time == 0 && keyframeCurrent->time == 0) {
+          *this->modifies = keyframeCurrent->value;
+          this->onValueModified();
+        }
+
+        // Update time.
+        this->time = newTime;
+
+        // Has the animation finished?
+        if(newTime < this->duration) return;
+        
+        // Do we need to loop?
+        if(this->loop) {
+          this->time = 0;
+          return;
+        }
+
+        // Animation end.
+        this->finished = true;
+        this->eventAnimationEnd.invoke();
+        this->event2AnimationEnd.invoke();
+      }
+      
+      void clear() override {
+        Animation::clear();
+        this->keyframes.clear();
+      }
+  };
 }
\ No newline at end of file
diff --git a/src/dawn/input/_InputManager.hpp b/src/dawn/input/_InputManager.hpp
index 94be351c..b93416f7 100644
--- a/src/dawn/input/_InputManager.hpp
+++ b/src/dawn/input/_InputManager.hpp
@@ -7,6 +7,7 @@
 #include "dawnlibs.hpp"
 #include "util/mathutils.hpp"
 #include "assert/assert.hpp"
+#include "state/StateEvent.hpp"
 
 namespace Dawn {
   class DawnGame;
@@ -32,6 +33,9 @@ namespace Dawn {
     public:
       DawnGame *game;
 
+      StateEvent<inputbind_t> eventBindPressed;
+      StateEvent<inputbind_t> eventBindReleased;
+
       IInputManager(DawnGame *game) {
         assertNotNull(game);
         this->game = game;
@@ -163,7 +167,7 @@ namespace Dawn {
 
         // For each bind...
         while(it != this->binds.end()) {
-          float_t value = 0.0f;
+          float_t value = 0.0f, valCurrent;
 
           // For each input axis...
           auto bindIt = it->second.begin();
@@ -176,10 +180,20 @@ namespace Dawn {
 
           // Set into current values
           if(this->currentIsLeft) {
+            valCurrent = this->valuesRight[it->first];
             this->valuesLeft[it->first] = value;
           } else {
+            valCurrent = this->valuesLeft[it->first];
             this->valuesRight[it->first] = value;
           }
+
+          // Fire events when necessary.
+          if(value == 0 && valCurrent == 1) {
+            eventBindReleased.invoke(it->first);
+          } else if(valCurrent == 0 && value == 1) {
+            eventBindPressed.invoke(it->first);
+          }
+
           ++it;
         }
 
diff --git a/src/dawn/locale/LocaleManager.hpp b/src/dawn/locale/LocaleManager.hpp
index 5dd2c6f1..e341fe16 100644
--- a/src/dawn/locale/LocaleManager.hpp
+++ b/src/dawn/locale/LocaleManager.hpp
@@ -4,7 +4,7 @@
 // https://opensource.org/licenses/MIT
 
 #pragma once
-#include "event/Event.hpp"
+#include "state/State.hpp"
 #include "asset/AssetManager.hpp"
 
 namespace Dawn {
@@ -14,7 +14,7 @@ namespace Dawn {
     std::string language;
   };
 
-  class LocaleManager {
+  class LocaleManager : public StateOwner {
     private:
       DawnGame *game;
       LanguageAsset *asset;
@@ -26,8 +26,8 @@ namespace Dawn {
       void onLanguageLoaded();
 
     public:
-      Event<> eventLocaleChanged;
-      Event<> eventLanguageUpdated;
+      StateEvent<> eventLocaleChanged;
+      StateEvent<> eventLanguageUpdated;
 
       /**
        * Initializes the Locale Manager Instance. Locale Manager is responsible
diff --git a/src/dawn/ui/UIComponent.hpp b/src/dawn/ui/UIComponent.hpp
index c582f7ff..67d61ede 100644
--- a/src/dawn/ui/UIComponent.hpp
+++ b/src/dawn/ui/UIComponent.hpp
@@ -9,6 +9,7 @@
 #include "util/array.hpp"
 #include "util/mathutils.hpp"
 #include "display/shader/Shader.hpp"
+#include "state/State.hpp"
 
 namespace Dawn {
   enum UIComponentAlign {
@@ -20,7 +21,7 @@ namespace Dawn {
 
   class UIGrid;
   
-  class UIComponent {
+  class UIComponent : public StateOwner {
     protected:
       // Calculated (and cached) values
       float_t width = 1;
diff --git a/src/dawn/ui/UILabel.cpp b/src/dawn/ui/UILabel.cpp
index d59a9260..8d5c641a 100644
--- a/src/dawn/ui/UILabel.cpp
+++ b/src/dawn/ui/UILabel.cpp
@@ -9,9 +9,12 @@
 using namespace Dawn;
 
 UILabel::UILabel(UICanvas *canvas) : UIComponent(canvas) {
-  getGame()->localeManager.eventLanguageUpdated.addListener(
-    this, &UILabel::onLanguageUpdated
-  );
+  evtLangUpdated = useEvent([&]{
+    this->needsRebuffering = true;
+    if(key.size() > 0 && this->getGame()->localeManager.getString(key).size() > 0) {
+      this->hasText = true;
+    }
+  }, getGame()->localeManager.eventLanguageUpdated);
 }
 
 void UILabel::updatePositions() {
@@ -104,17 +107,4 @@ void UILabel::setTransform(
 ) {
   this->needsRebuffering = true;
   UIComponent::setTransform(xAlign, yAlign, alignment, z);
-}
-
-void UILabel::onLanguageUpdated() {
-  this->needsRebuffering = true;
-  if(key.size() > 0 && this->getGame()->localeManager.getString(key).size()>0){
-    this->hasText = true;
-  }
-}
-
-UILabel::~UILabel() {
-  getGame()->localeManager.eventLanguageUpdated.removeListener(
-    this, &UILabel::onLanguageUpdated
-  );
 }
\ No newline at end of file
diff --git a/src/dawn/ui/UILabel.hpp b/src/dawn/ui/UILabel.hpp
index 5831326b..8bb25f14 100644
--- a/src/dawn/ui/UILabel.hpp
+++ b/src/dawn/ui/UILabel.hpp
@@ -17,12 +17,10 @@ namespace Dawn {
       std::string key = "";
       float_t fontSize = 10.0f;
       bool_t hasText = false;
+      std::function<void()> evtLangUpdated;
 
       void updatePositions() override;
-
-      /** Event for when the language strings are updated */
-      void onLanguageUpdated();
-
+  
       std::vector<struct ShaderPassItem> getSelfPassItems(
         glm::mat4 projection,
         glm::mat4 view,
@@ -79,7 +77,5 @@ namespace Dawn {
        * @return Font size of the label.
        */
       float_t getFontSize();
-
-      ~UILabel();
   };
 }
\ No newline at end of file
diff --git a/src/dawnlinux64/host/CMakeLists.txt b/src/dawnlinux64/host/CMakeLists.txt
index 4517044d..31c73dd6 100644
--- a/src/dawnlinux64/host/CMakeLists.txt
+++ b/src/dawnlinux64/host/CMakeLists.txt
@@ -1,10 +1,10 @@
-# Copyright (c) 2022 Dominic Masters
-# 
-# This software is released under the MIT License.
-# https://opensource.org/licenses/MIT
-
-# Sources
-target_sources(${DAWN_TARGET_NAME}
-  PRIVATE
-    DawnHostWin32.cpp
+# Copyright (c) 2022 Dominic Masters
+# 
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+# Sources
+target_sources(${DAWN_TARGET_NAME}
+  PRIVATE
+    DawnHostTux32.cpp
 )
\ No newline at end of file
diff --git a/src/dawnlinux64/host/DawnHostWin32.cpp b/src/dawnlinux64/host/DawnHostTux32.cpp
similarity index 92%
rename from src/dawnlinux64/host/DawnHostWin32.cpp
rename to src/dawnlinux64/host/DawnHostTux32.cpp
index 0698c69a..4cd3927f 100644
--- a/src/dawnlinux64/host/DawnHostWin32.cpp
+++ b/src/dawnlinux64/host/DawnHostTux32.cpp
@@ -3,7 +3,7 @@
 // This software is released under the MIT License.
 // https://opensource.org/licenses/MIT
 
-#include "DawnHostWin32.hpp"
+#include "DawnHostTux32.hpp"
 
 using namespace Dawn;
 
diff --git a/src/dawnlinux64/host/DawnHostWin32.hpp b/src/dawnlinux64/host/DawnHostTux32.hpp
similarity index 96%
rename from src/dawnlinux64/host/DawnHostWin32.hpp
rename to src/dawnlinux64/host/DawnHostTux32.hpp
index 9f203953..cdff0cec 100644
--- a/src/dawnlinux64/host/DawnHostWin32.hpp
+++ b/src/dawnlinux64/host/DawnHostTux32.hpp
@@ -1,18 +1,18 @@
-// Copyright (c) 2022 Dominic Masters
-// 
-// This software is released under the MIT License.
-// https://opensource.org/licenses/MIT
-
-#pragma once
-#include "dawnlibs.hpp"
-#include "host/DawnHost.hpp"
-#include "game/DawnGame.hpp"
-
-/**
- * Main entry function received by parent Win32 Operating System.
- * 
- * @param argc Count of arguments passed to the program.
- * @param args Array of strings provided to the program.
- * @return 0 for success, else for any issue/error.
- */
+// Copyright (c) 2022 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "dawnlibs.hpp"
+#include "host/DawnHost.hpp"
+#include "game/DawnGame.hpp"
+
+/**
+ * Main entry function received by parent Win32 Operating System.
+ * 
+ * @param argc Count of arguments passed to the program.
+ * @param args Array of strings provided to the program.
+ * @return 0 for success, else for any issue/error.
+ */
 int32_t main(int32_t argc, char **args);
\ No newline at end of file
diff --git a/src/dawnopenal/scene/components/audio/AudioSource.hpp b/src/dawnopenal/scene/components/audio/AudioSource.hpp
index 6fc97ce4..db2885c4 100644
--- a/src/dawnopenal/scene/components/audio/AudioSource.hpp
+++ b/src/dawnopenal/scene/components/audio/AudioSource.hpp
@@ -52,12 +52,12 @@ namespace Dawn {
       enum AudioSourceState state = AUDIO_SOURCE_STATE_STOPPED;
       AudioSourcePlayMode playMode;
 
-      Event<> eventPlaying;
-      Event<> eventResumed;
-      Event<> eventPaused;
-      Event<> eventStopped;
-      Event<> eventFinished;
-      Event<> eventLooped;
+      StateEvent<> eventPlaying;
+      StateEvent<> eventResumed;
+      StateEvent<> eventPaused;
+      StateEvent<> eventStopped;
+      StateEvent<> eventFinished;
+      StateEvent<> eventLooped;
 
       /**
        * Creates an Audio Source item component.
diff --git a/src/dawntools/tools/languagegen/LanguageGen.hpp b/src/dawntools/tools/languagegen/LanguageGen.hpp
index c643baff..165eeca9 100644
--- a/src/dawntools/tools/languagegen/LanguageGen.hpp
+++ b/src/dawntools/tools/languagegen/LanguageGen.hpp
@@ -23,32 +23,32 @@ namespace Dawn {
 
   class LanguageParser : public XmlParser<struct LanguageString> {
     protected:
-      std::vector<std::string> getRequiredAttributes();
-      std::map<std::string, std::string> getOptionalAttributes();
+      std::vector<std::string> getRequiredAttributes() override;
+      std::map<std::string, std::string> getOptionalAttributes() override;
       int32_t onParse(
         Xml *node,
         std::map<std::string, std::string> values,
         struct LanguageString *out,
         std::string *error
-      );
+      ) override;
   };
 
   class LanguageGroupParser : public XmlParser<struct LanguageGroup> {
     protected:
-      std::vector<std::string> getRequiredAttributes();
-      std::map<std::string, std::string> getOptionalAttributes();
+      std::vector<std::string> getRequiredAttributes() override;
+      std::map<std::string, std::string> getOptionalAttributes()  override;
       int32_t onParse(
         Xml *node,
         std::map<std::string, std::string> values,
         struct LanguageGroup *out,
         std::string *error
-      );
+      )  override;
   };
   
   class LanguageRootParser : public XmlParser<struct LanguageRoot> {
     protected:
-      std::vector<std::string> getRequiredAttributes();
-      std::map<std::string, std::string> getOptionalAttributes();
+      std::vector<std::string> getRequiredAttributes() override;
+      std::map<std::string, std::string> getOptionalAttributes() override;
       int32_t onParse(
         Xml *node,
         std::map<std::string, std::string> values,
@@ -60,18 +60,6 @@ namespace Dawn {
   class LanguageGen : public DawnTool {
     protected:
       std::vector<std::string> getRequiredFlags() override;
-      
-      int32_t parseGroup(
-        Xml *node,
-        std::string key,
-        std::map<std::string, std::vector<struct LanguageString>> *strings
-      );
-
-      int32_t parseString(
-        Xml *node,
-        std::string key,
-        std::map<std::string, std::vector<struct LanguageString>> *strings
-      );
 
     public:
       int32_t start() override;