diff --git a/.changeset/tall-socks-agree.md b/.changeset/tall-socks-agree.md
new file mode 100644
index 0000000..190e4cd
--- /dev/null
+++ b/.changeset/tall-socks-agree.md
@@ -0,0 +1,5 @@
+---
+"@threejs-kit/instanced-sprite-mesh": minor
+---
+
+createSpritesheet utility function for combining multiple image files into one and generating metadata for instancing
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/All Characters.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/All Characters.png
new file mode 100644
index 0000000..2921d3e
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/All Characters.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Attack.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Attack.png
new file mode 100644
index 0000000..1865f48
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Attack.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Death.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Death.png
new file mode 100644
index 0000000..cd631da
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Death.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Flight.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Flight.png
new file mode 100644
index 0000000..cd6d5de
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Flight.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Hit.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Hit.png
new file mode 100644
index 0000000..ca18caa
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Hit.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Attack.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Attack.png
new file mode 100644
index 0000000..3d1457e
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Attack.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Death.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Death.png
new file mode 100644
index 0000000..2d91ef6
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Death.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Idle.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Idle.png
new file mode 100644
index 0000000..47e4264
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Idle.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Run.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Run.png
new file mode 100644
index 0000000..1edb74f
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Run.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Take Hit.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Take Hit.png
new file mode 100644
index 0000000..da5458d
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Goblin/Take Hit.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Attack.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Attack.png
new file mode 100644
index 0000000..df07e60
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Attack.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Death.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Death.png
new file mode 100644
index 0000000..5ef0acd
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Death.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Idle.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Idle.png
new file mode 100644
index 0000000..672efbf
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Idle.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Run.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Run.png
new file mode 100644
index 0000000..ec7d5a1
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Run.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Take Hit.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Take Hit.png
new file mode 100644
index 0000000..7846e5c
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Mushroom/Take Hit.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Attack.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Attack.png
new file mode 100644
index 0000000..c855a32
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Attack.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Death.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Death.png
new file mode 100644
index 0000000..4131c3d
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Death.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Idle.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Idle.png
new file mode 100644
index 0000000..f70c60c
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Idle.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Shield.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Shield.png
new file mode 100644
index 0000000..ecf9d6f
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Shield.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Take Hit.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Take Hit.png
new file mode 100644
index 0000000..707370f
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Take Hit.png differ
diff --git a/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Walk.png b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Walk.png
new file mode 100644
index 0000000..8ccc7b1
Binary files /dev/null and b/apps/docs/src/assets/sprite/Monsters_Creatures_Fantasy/Skeleton/Walk.png differ
diff --git a/apps/docs/src/content/docs/instancedSprite/04-instanced-sprite-building.mdx b/apps/docs/src/content/docs/instancedSprite/04-instanced-sprite-building.mdx
index f1936a7..b21df2a 100644
--- a/apps/docs/src/content/docs/instancedSprite/04-instanced-sprite-building.mdx
+++ b/apps/docs/src/content/docs/instancedSprite/04-instanced-sprite-building.mdx
@@ -3,16 +3,100 @@ title: Making spritesheet from images
description: InstancedSpriteMesh
---
+import { Image } from "astro:assets";
-### InstancedSpriteMesh
-tutorial on how to make spritesheet metadata with just images:
-Sprites from
-https://luizmelo.itch.io/monsters-creatures-fantasy
+### `createSpritesheet` utility
+The `createSpritesheet` is a helper function that facilitates the creation of spritesheet metadata and a `Texture` which are essential for configuring
+`InstancedSpriteMesh`. The process involves the following steps:
-1. load images
-2. 1 img file = 1 animation
-3. Name animations and Combine img files into one spritesheet via html canvas so there's only one texture
-4. Generate meta
\ No newline at end of file
+1. *Initialization:* Begin by invoking the `createSpritesheet` function. This function is the starting point for creating your spritesheet.
+2. *Adding Images*: For each image you wish to include in the spritesheet, call the `add` function on the created spritesheet. This function requires specific parameters:
+ - `name`: A string identifier for the image. By default, this is set to "default".
+ - `imageUrl`: The URL or path to the image file.
+ - `config` object consiting of:
+ - `type` - choose whether you're providing how many rows and columns are in an image `"rowColumn"` or giving the size of a single frame for the builder to interpolate from `"frameSize"`
+ - `w` and `h` refer to either `column` and `row` or `imageWidth` and `imageHeight` depending on what you chose in `type`
+ ```ts
+ /* The configuration object is structured as follows: */
+ config: {
+ type: "rowColumn" | "frameSize";
+ w: number;
+ h: number;
+ }
+ ```
+3. *Build*: After adding all of the animations, call `build()`. The `createSpritesheet` function returns a promise. This promise resolves to an object containing a `texture: THREE.Texture`, which can be applied as the map property of a material, and a `spritesheet` for use in the InstancedSpriteMesh.
+
+
+**Important Note:** The utility currently supports only the rowMajor layout. This means the frames in the spritesheet are ordered from left to right and top to bottom, progressing row by row. Adjustments to support different frame sequencing may be added in future updates.
+
+
+
+
+## Example
+
+This example shows how to create a spritesheet using the Flying Eye character
+from the collection available at https://luizmelo.itch.io/monsters-creatures-fantasy.
+The Flying Eye character includes four separate animation files. The goal is to merge these
+files into a single texture and establish the necessary metadata for it.
+
+import attack from "@assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Attack.png";
+import flight from "@assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Flight.png";
+import death from "@assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Death.png";
+import hit from "@assets/sprite/Monsters_Creatures_Fantasy/Flying_eye/Hit.png";
+
+
+**Attack.png**
+
+
+
+**Flight.png**
+
+
+
+**Death.png**
+
+
+
+**Hit.png**
+
+
+
+
+
+### example code
+
+We call `createSpritesheet` and start defining metadata for each of the sprite files.
+- first `add` a `Flight.png` file - we name the animation as `fly` and use `rowColumn` type. We then provide `w` of 8 - because there are 8 columns (frames left to right) and `h` of 1 - because there is only one row of animation
+- for the second animation - `attack` - I'm going to use a `frameSize` type. So now we provide `w` and `h` in pixels of how big each frame is, then the builder calculates columsn and rows internally.
+- Then I add `death` and `hit` animations, just like I did the first one. Notice that these animations have a different number of columns, but that's fine. Each of your animations can have different column and row numbers.
+
+```ts
+
+import { createSpritesheet } from '@threejs-kit/instanced-sprite-mesh';
+
+const {spritesheet, texture} = await createSpritesheet()
+ .add('fly', '/Monsters_Creatures_Fantasy/Flying_eye/Flight.png', {
+ type: 'rowColumn',
+ w: 8,
+ h: 1
+ })
+ .add('attack', '/Monsters_Creatures_Fantasy/Flying_eye/Attack.png', {
+ type: 'frameSize',
+ w: 150,
+ h: 150
+ })
+ .add('death', '/Monsters_Creatures_Fantasy/Flying_eye/Death.png', {
+ type: 'rowColumn',
+ w: 4,
+ h: 1
+ })
+ .add('hit', '/Monsters_Creatures_Fantasy/Flying_eye/Hit.png', {
+ type: 'rowColumn',
+ w: 4,
+ h: 1
+ })
+ .build();
+```
\ No newline at end of file
diff --git a/apps/playground/src/routes/instanced-sprite/Scene.svelte b/apps/playground/src/routes/instanced-sprite/Scene.svelte
index 50bf753..211a7eb 100644
--- a/apps/playground/src/routes/instanced-sprite/Scene.svelte
+++ b/apps/playground/src/routes/instanced-sprite/Scene.svelte
@@ -4,37 +4,31 @@
import PlayerUpdater from './PlayerUpdater.svelte';
import { DEG2RAD } from 'three/src/math/MathUtils.js';
import AnimatedInstancedSprite from './AnimatedInstancedSprite.svelte';
- import { SpriteBuilder } from './spriteBuilder';
import FlyerUpdater from './FlyerUpdater.svelte';
+ import { createSpritesheet } from '@threejs-kit/instanced-sprite-mesh';
const count = 50000;
- const monster = new SpriteBuilder();
-
- const g = monster
+ const spritesheet = createSpritesheet()
.add('fly', '/textures/sprites/Monsters_Creatures_Fantasy/Flying_eye/Flight.png', {
- type: 'rowColumn',
- w: 8,
- h: 1,
- rowMajor: true
+ type: 'frameSize',
+ w: 150,
+ h: 150
})
.add('attack', '/textures/sprites/Monsters_Creatures_Fantasy/Flying_eye/Attack.png', {
type: 'rowColumn',
w: 8,
- h: 1,
- rowMajor: true
+ h: 1
})
.add('death', '/textures/sprites/Monsters_Creatures_Fantasy/Flying_eye/Death.png', {
type: 'rowColumn',
w: 4,
- h: 1,
- rowMajor: true
+ h: 1
})
.add('hit', '/textures/sprites/Monsters_Creatures_Fantasy/Flying_eye/Hit.png', {
type: 'rowColumn',
w: 4,
- h: 1,
- rowMajor: true
+ h: 1
})
.build();
@@ -55,7 +49,7 @@
-->
-{#await g then { spritesheet, texture }}
+{#await spritesheet then { spritesheet, texture }}
diff --git a/apps/playground/src/routes/instanced-sprite/spriteBuilder.ts b/apps/playground/src/routes/instanced-sprite/spriteBuilder.ts
deleted file mode 100644
index 3a94aaa..0000000
--- a/apps/playground/src/routes/instanced-sprite/spriteBuilder.ts
+++ /dev/null
@@ -1,178 +0,0 @@
-import type { SpritesheetFormat } from '@threejs-kit/instanced-sprite-mesh';
-import {
- CanvasTexture,
- ImageLoader,
- NearestFilter,
- RepeatWrapping,
- SRGBColorSpace,
- Texture
-} from 'three';
-
-type AnimationDefitinion = {
- name: string;
- imageUrl: string;
- custom?: SpritesheetFormat['frames'];
- auto?: {
- type: 'rowColumn' | 'frame';
- w: number;
- h: number;
- rowMajor: boolean;
- };
-};
-
-export class SpriteBuilder {
- private imageLoader: ImageLoader;
- private animations: AnimationDefitinion[];
-
- constructor() {
- this.imageLoader = new ImageLoader();
- this.animations = [];
- //
- }
-
- add(
- name: string = 'default',
- imageUrl: string,
- config: {
- type: 'rowColumn' | ' frame';
- w: number;
- h: number;
- rowMajor: boolean;
- }
- ) {
- const animation: AnimationDefitinion = {
- name,
- imageUrl
- };
-
- if (config.type == 'rowColumn') {
- animation['auto'] = {
- type: 'rowColumn',
- w: config.w,
- h: config.h,
- rowMajor: config.rowMajor
- };
- }
-
- this.animations.push(animation);
- return this;
- }
-
- async build() {
- const imgLoader = new ImageLoader();
-
- console.log(this.animations);
-
- const generatedSpritesheet: SpritesheetFormat = {
- frames: [],
- animations: {},
- sheetSize: [0, 0],
- animationLengths: []
- };
-
- let texture = new Texture();
-
- const images: { img: HTMLImageElement; w: number; h: number }[] = [];
-
- let generatedWidth = 0;
- let generatedHeight = 0;
-
- for (const anim of this.animations) {
- const img = await imgLoader.loadAsync(anim.imageUrl);
- const w = img.width;
- const h = img.height;
- generatedWidth = Math.max(generatedWidth, w);
- generatedHeight += h;
- images.push({
- img,
- w,
- h
- });
- }
-
- if (this.animations.length === 0) {
- // texture.image = images[0].img;
- } else {
- //
- }
-
- const canvas = document.createElement('canvas');
- canvas.width = generatedWidth;
- canvas.height = generatedHeight;
-
- const debugDiv = document.createElement('div');
- debugDiv.style.backgroundColor = 'grey';
- debugDiv.style.position = 'fixed';
- debugDiv.style.top = '0px';
- debugDiv.style.left = '0px';
- debugDiv.style.zIndex = '50';
- debugDiv.style.transform = 'scale(0.5,0.5)';
- debugDiv.style.transformOrigin = 'left';
- // debugDiv.style.scale = '50%';
-
- debugDiv.appendChild(canvas);
- document.body.appendChild(debugDiv);
-
- const context = canvas.getContext('2d');
-
- let y = 0;
- for (const { img, h } of images) {
- context?.drawImage(img, 0, y, img.width, img.height);
- y += h;
- }
-
- texture = new CanvasTexture(canvas);
-
- // texture.image = img;
- texture.needsUpdate = true;
-
- let animIndex = 0;
- let frameCounter = 0;
- let accumulatedHeight = 0;
-
- for (const a of this.animations) {
- const img = images[animIndex];
-
- let framesCount = 0;
-
- const imgPartialW = img.w;
- const imgPartialH = img.h;
-
- if (a.auto) {
- if (a.auto.type == 'rowColumn') {
- accumulatedHeight += imgPartialH;
- framesCount = a.auto.w * a.auto.h;
- generatedSpritesheet.animations[a.name] = [];
- for (let x = 0; x < a.auto.w; x++) {
- for (let y = 0; y < a.auto.h; y++) {
- generatedSpritesheet.frames.push([
- ((img.w / framesCount) * x) / generatedWidth,
- 1 - accumulatedHeight / generatedHeight,
- imgPartialW / framesCount / generatedWidth,
- imgPartialH / generatedHeight
- ]);
- generatedSpritesheet.animations[a.name].push([frameCounter, 1]);
- frameCounter++;
- }
- }
- }
-
- generatedSpritesheet.animationLengths.push(framesCount);
- }
- animIndex++;
- }
-
- texture.matrixAutoUpdate = false;
- texture.generateMipmaps = false;
- texture.premultiplyAlpha = false;
- texture.wrapS = texture.wrapT = RepeatWrapping;
- texture.magFilter = texture.minFilter = NearestFilter;
- texture.colorSpace = SRGBColorSpace;
-
- generatedSpritesheet.sheetSize = [generatedWidth, generatedHeight];
-
- console.log({ generatedSpritesheet });
-
- return { spritesheet: generatedSpritesheet, texture };
- }
-}
diff --git a/packages/instanced-sprite-mesh/src/index.ts b/packages/instanced-sprite-mesh/src/index.ts
index 1c7b122..019b9a7 100644
--- a/packages/instanced-sprite-mesh/src/index.ts
+++ b/packages/instanced-sprite-mesh/src/index.ts
@@ -1,5 +1,6 @@
export { InstancedSpriteMesh } from "./InstancedSpriteMesh";
export { makeDataTexture, parseAseprite } from "./material";
+export { createSpritesheet } from "./spriteBuilder";
export type { SpritesheetFormat } from "./material";
diff --git a/packages/instanced-sprite-mesh/src/spriteBuilder.ts b/packages/instanced-sprite-mesh/src/spriteBuilder.ts
new file mode 100644
index 0000000..fb93f10
--- /dev/null
+++ b/packages/instanced-sprite-mesh/src/spriteBuilder.ts
@@ -0,0 +1,179 @@
+import {
+ CanvasTexture,
+ ImageLoader,
+ NearestFilter,
+ RepeatWrapping,
+ SRGBColorSpace,
+ Texture,
+} from "three";
+import { SpritesheetFormat } from "./material";
+
+type AnimationDefitinion = {
+ name: string;
+ imageUrl: string;
+ custom?: SpritesheetFormat["frames"];
+ auto?: {
+ type: "rowColumn" | "frameSize";
+ w: number;
+ h: number;
+ // rowMajor: boolean;
+ };
+};
+
+export const createSpritesheet = () => {
+ return new SpriteBuilder();
+};
+
+class SpriteBuilder {
+ private animations: AnimationDefitinion[];
+
+ constructor() {
+ this.animations = [];
+ //
+ }
+
+ add(
+ name: string = "default",
+ imageUrl: string,
+ config: {
+ type: "rowColumn" | "frameSize";
+ w: number;
+ h: number;
+ // rowMajor: boolean;
+ }
+ ) {
+ const animation: AnimationDefitinion = {
+ name,
+ imageUrl,
+ };
+
+ if (config.type == "rowColumn") {
+ animation["auto"] = {
+ type: "rowColumn",
+ w: config.w,
+ h: config.h,
+ };
+ }
+
+ this.animations.push(animation);
+ return this;
+ }
+
+ async build() {
+ const imgLoader = new ImageLoader();
+
+ console.log(this.animations);
+
+ const spritesheet: SpritesheetFormat = {
+ frames: [],
+ animations: {},
+ sheetSize: [0, 0],
+ animationLengths: [],
+ };
+
+ let texture = new Texture();
+
+ const images: { img: HTMLImageElement; w: number; h: number }[] = [];
+
+ let generatedWidth = 0;
+ let generatedHeight = 0;
+
+ for (const anim of this.animations) {
+ const img = await imgLoader.loadAsync(anim.imageUrl);
+ const w = img.width;
+ const h = img.height;
+ generatedWidth = Math.max(generatedWidth, w);
+ generatedHeight += h;
+ images.push({
+ img,
+ w,
+ h,
+ });
+ }
+
+ if (this.animations.length === 0) {
+ // texture.image = images[0].img;
+ } else {
+ //
+ }
+
+ const canvas = document.createElement("canvas");
+ canvas.width = generatedWidth;
+ canvas.height = generatedHeight;
+
+ const context = canvas.getContext("2d");
+
+ let y = 0;
+ for (const { img, h } of images) {
+ context?.drawImage(img, 0, y, img.width, img.height);
+ y += h;
+ }
+
+ texture = new CanvasTexture(canvas);
+
+ // texture.image = img;
+ texture.needsUpdate = true;
+
+ let animIndex = 0;
+ let frameCounter = 0;
+ let accumulatedHeight = 0;
+
+ for (const a of this.animations) {
+ const img = images[animIndex];
+
+ let framesCount = 0;
+
+ const imgPartialW = img.w;
+ const imgPartialH = img.h;
+
+ if (a.auto) {
+ let rows = 0;
+ let columns = 0;
+
+ if (a.auto.type == "frameSize") {
+ columns = img.w / a.auto.w;
+ rows = img.h / a.auto.h;
+ }
+ if (a.auto.type == "rowColumn") {
+ columns = a.auto.w;
+ rows = a.auto.h;
+ }
+
+ // TODO ROW MAJOR / COLUMN MAJOR STUFF
+
+ accumulatedHeight += imgPartialH;
+ framesCount = rows * columns;
+ spritesheet.animations[a.name] = [];
+
+ for (let x = 0; x < columns; x++) {
+ for (let y = 0; y < rows; y++) {
+ spritesheet.frames.push([
+ ((img.w / framesCount) * x) / generatedWidth,
+ 1 - accumulatedHeight / generatedHeight,
+ imgPartialW / framesCount / generatedWidth,
+ imgPartialH / generatedHeight,
+ ]);
+ spritesheet.animations[a.name].push([frameCounter, 1]);
+ frameCounter++;
+ }
+ }
+
+ spritesheet.animationLengths.push(framesCount);
+ }
+ animIndex++;
+ }
+
+ texture.matrixAutoUpdate = false;
+ texture.generateMipmaps = false;
+ texture.premultiplyAlpha = false;
+ texture.wrapS = texture.wrapT = RepeatWrapping;
+ texture.magFilter = texture.minFilter = NearestFilter;
+ texture.colorSpace = SRGBColorSpace;
+
+ spritesheet.sheetSize = [generatedWidth, generatedHeight];
+
+ console.log({ generatedSpritesheet: spritesheet });
+
+ return { spritesheet, texture };
+ }
+}