diff --git a/image-resource/CMakeLists.txt b/image-resource/CMakeLists.txt
new file mode 100644
index 0000000..8ef3cfd
--- /dev/null
+++ b/image-resource/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.14)
+project(image-resource VERSION 1.0.0 LANGUAGES CXX)
+find_package(atta 0.1.0.0 REQUIRED)
+
+atta_add_target(projectScript "src/projectScript.cpp")
diff --git a/image-resource/README.md b/image-resource/README.md
new file mode 100644
index 0000000..a48d4bf
--- /dev/null
+++ b/image-resource/README.md
@@ -0,0 +1,14 @@
+
+# Image Resource
+
+
+
+
+
+Images can be created and updated dynamically in atta.
+
+In this example we create two planes and update their textures dynamically.
diff --git a/image-resource/image-resource.atta b/image-resource/image-resource.atta
new file mode 100644
index 0000000..977faa7
Binary files /dev/null and b/image-resource/image-resource.atta differ
diff --git a/image-resource/src/projectScript.cpp b/image-resource/src/projectScript.cpp
new file mode 100644
index 0000000..2e1111e
--- /dev/null
+++ b/image-resource/src/projectScript.cpp
@@ -0,0 +1,136 @@
+//--------------------------------------------------
+// Image Resource
+// projectScript.cpp
+// Date: 2022-08-19
+// By Breno Cunha Queiroz
+//--------------------------------------------------
+#include "projectScript.h"
+#include
+#include
+#include
+#include
+
+namespace rsc = atta::resource;
+namespace cmp = atta::component;
+const cmp::Entity plane(0);
+
+void Project::onLoad() {
+ rsc::Image::CreateInfo info;
+ info.width = 100;
+ info.height = 100;
+ info.format = rsc::Image::Format::RGBA8;
+ rsc::Image* img = rsc::create("animation", info);
+ rsc::Image* gameOfLife = rsc::create("gameOfLife", info);
+
+ // Init gameOfLife as white
+ uint8_t* data = gameOfLife->getData();
+ for (int i = 0; i < info.width * info.height * 4; i++)
+ data[i] = 255;
+
+ std::vector blinkers = {{10, 10}, {20, 20}, {10, 20}, {20, 10}};
+ std::vector gliders = {{30, 30}, {20, 50}, {10, 5}, {5, 5}, {80, 30}, {40, 90}, {90, 10}, {90, 50}};
+ std::vector liveCells = {};
+
+ for (atta::vec2i blinker : blinkers) {
+ liveCells.push_back(blinker + atta::vec2i(0, 0));
+ liveCells.push_back(blinker + atta::vec2i(1, 0));
+ liveCells.push_back(blinker + atta::vec2i(0, 1));
+ }
+
+ for (atta::vec2i glider : gliders) {
+ liveCells.push_back(glider + atta::vec2i(0, -1));
+ liveCells.push_back(glider + atta::vec2i(1, 0));
+ liveCells.push_back(glider + atta::vec2i(-1, 1));
+ liveCells.push_back(glider + atta::vec2i(0, 1));
+ liveCells.push_back(glider + atta::vec2i(1, 1));
+ }
+
+ for (atta::vec2i cell : liveCells) {
+ unsigned idx = (cell.y * info.width + cell.x) * 4;
+ data[idx] = data[idx + 1] = data[idx + 2] = 0;
+ }
+
+ gameOfLife->update();
+}
+
+void Project::onAttaLoop() {
+ updateAnimation();
+ updateGameOfLife();
+}
+
+void Project::updateAnimation() {
+ static auto start = std::chrono::system_clock::now();
+ auto end = std::chrono::system_clock::now();
+ int time = std::chrono::duration_cast(end - start).count() / 50;
+
+ // Change random pattern with time
+ rsc::Image* img = rsc::get("animation");
+ uint32_t w = img->getWidth();
+ uint32_t h = img->getHeight();
+ uint8_t* data = img->getData();
+ for (int i = 0; i < w * h * 4; i++)
+ data[i] = 255;
+
+ for (int y = 0; y < h; y++)
+ for (int x = 0; x < w; x++) {
+ int X = x + time;
+ int Y = y + time * 2;
+ X %= w;
+ Y %= h;
+ uint32_t idx = (w * Y + X) * 4;
+ data[idx + 0] = 255 * sin(x / float(w) * M_PI * 5);
+ data[idx + 1] = 255 * sin(y / float(h) * M_PI * 5);
+ data[idx + 2] = 255;
+ }
+ img->update();
+}
+
+void Project::updateGameOfLife() {
+ static auto start = std::chrono::system_clock::now();
+ auto end = std::chrono::system_clock::now();
+ int time = std::chrono::duration_cast(end - start).count()/100;
+
+ // Update every second
+ if (time > 0) {
+ start = end;
+
+ rsc::Image* gameOfLife = rsc::get("gameOfLife");
+ uint32_t w = gameOfLife->getWidth();
+ uint32_t h = gameOfLife->getHeight();
+ uint8_t* data = gameOfLife->getData();
+
+ uint8_t* backup = new uint8_t[w * h * 4];
+ for (int i = 0; i < w * h * 4; i++)
+ backup[i] = data[i];
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ int idx = (y * w + x) * 4;
+ int numNeighbors = 0;
+ bool isAlive = backup[idx] == 0;
+ // Count neightbors
+ for (int yn = y - 1; yn <= y + 1; yn++)
+ for (int xn = x - 1; xn <= x + 1; xn++) {
+ // Ignore center
+ if (yn == y && xn == x)
+ continue;
+ // Wrap coord
+ int X = (xn + w) % w;
+ int Y = (yn + h) % h;
+ if (backup[(Y * w + X) * 4] == 0)
+ numNeighbors++;
+ }
+
+ // Update cell
+ if (isAlive && (numNeighbors == 2 || numNeighbors == 3))
+ continue;
+ else if (!isAlive && numNeighbors == 3)
+ data[idx] = data[idx + 1] = data[idx + 2] = 0;
+ else
+ data[idx] = data[idx + 1] = data[idx + 2] = 255;
+ }
+ }
+ delete[] backup;
+ gameOfLife->update();
+ }
+}
diff --git a/image-resource/src/projectScript.h b/image-resource/src/projectScript.h
new file mode 100644
index 0000000..72b6be7
--- /dev/null
+++ b/image-resource/src/projectScript.h
@@ -0,0 +1,25 @@
+//--------------------------------------------------
+// Image Resource
+// projectScript.h
+// Date: 2022-08-19
+// By Breno Cunha Queiroz
+//--------------------------------------------------
+#ifndef PROJECT_SCRIPT_H
+#define PROJECT_SCRIPT_H
+#include
+
+namespace scr = atta::script;
+
+class Project : public scr::ProjectScript {
+ public:
+ void onLoad() override;
+ void onAttaLoop() override;
+
+ private:
+ void updateAnimation();
+ void updateGameOfLife();
+};
+
+ATTA_REGISTER_PROJECT_SCRIPT(Project)
+
+#endif // PROJECT_SCRIPT_H
diff --git a/logging/src/projectScript.h b/logging/src/projectScript.h
index 15330d1..833edd4 100644
--- a/logging/src/projectScript.h
+++ b/logging/src/projectScript.h
@@ -10,12 +10,11 @@
namespace scr = atta::script;
-class Project : public scr::ProjectScript
-{
-public:
- void onLoad() override;
+class Project : public scr::ProjectScript {
+ public:
+ void onLoad() override;
};
ATTA_REGISTER_PROJECT_SCRIPT(Project)
-#endif// PROJECT_SCRIPT_H
+#endif // PROJECT_SCRIPT_H
diff --git a/materials/.gitignore b/material-resource/.gitignore
similarity index 100%
rename from materials/.gitignore
rename to material-resource/.gitignore
diff --git a/materials/CMakeLists.txt b/material-resource/CMakeLists.txt
similarity index 86%
rename from materials/CMakeLists.txt
rename to material-resource/CMakeLists.txt
index 6dc0249..3822a21 100644
--- a/materials/CMakeLists.txt
+++ b/material-resource/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.14)
-project(materials VERSION 1.0.0 LANGUAGES CXX)
+project(material-resource VERSION 1.0.0 LANGUAGES CXX)
find_package(atta 0.1.0.0 REQUIRED)
# Download resources
diff --git a/materials/README.md b/material-resource/README.md
similarity index 85%
rename from materials/README.md
rename to material-resource/README.md
index 0908e66..82d0607 100644
--- a/materials/README.md
+++ b/material-resource/README.md
@@ -1,12 +1,12 @@
-# Materials
+# Material Resource
-
+
Entities are only rendered with a material if they also have `cmp::Transform` and `cmp::Mesh` components.
diff --git a/materials/materials.atta b/material-resource/material-resource.atta
similarity index 100%
rename from materials/materials.atta
rename to material-resource/material-resource.atta