Skip to content

Atlas track all textures #1958

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 112 additions & 112 deletions arcade/experimental/atlas_load_save.py
Original file line number Diff line number Diff line change
@@ -1,112 +1,112 @@
"""
Quick and dirty atlas load/save testing.
Loading and saving atlases are not officially supported.
This is simply an experiment.

Dump atlas:
python arcade/experimental/atlas_load_save.py save

Load atlas:
python arcade/experimental/atlas_load_save.py load
"""

from __future__ import annotations

import sys
import math
import pprint
from typing import Dict, Tuple, List
from time import perf_counter
from pathlib import Path
import arcade
from arcade.texture_atlas.helpers import save_atlas, load_atlas

MODE = 'save'
RESOURCE_ROOT = arcade.resources.ASSET_PATH
DESTINATION = Path.cwd()

texture_paths: List[Path] = []
texture_paths += RESOURCE_ROOT.glob("images/enemies/*.png")
texture_paths += RESOURCE_ROOT.glob("images/items/*.png")
texture_paths += RESOURCE_ROOT.glob("images/alien/*.png")
texture_paths += RESOURCE_ROOT.glob("images/tiles/*.png")


def populate_atlas(atlas: arcade.TextureAtlas) -> Tuple[int, Dict[str, float]]:
"""Populate the atlas with all the resources we can find"""
perf_data = {}
textures = []
t = perf_counter()
for path in texture_paths:
texture = arcade.load_texture(path, hit_box_algorithm=arcade.hitbox.algo_simple)
textures.append(texture)
perf_data['load_textures'] = perf_counter() - t

t = perf_counter()
for texture in textures:
atlas.add(texture)
perf_data['add_textures'] = perf_counter() - t

return len(textures), perf_data


class AtlasLoadSave(arcade.Window):
"""
This class demonstrates how to load and save texture atlases.
"""

def __init__(self):
super().__init__(1280, 720, "Atlas Load Save")
self.done = False

if MODE == "save":
t = perf_counter()
self.atlas = arcade.TextureAtlas((1024, 1024))
count, perf_data = populate_atlas(self.atlas)
print(f'Populated atlas with {count} texture in {perf_counter() - t:.2f} seconds')
save_atlas(
self.atlas,
directory=Path.cwd(),
name="test",
resource_root=RESOURCE_ROOT,
)
self.done = True
if MODE == "load":
t = perf_counter()
self.atlas, perf_data = load_atlas(Path.cwd() / 'test.json', RESOURCE_ROOT)
print(f'Loaded atlas in {perf_counter() - t:.2f} seconds')
pprint.pprint(perf_data, indent=2)
# self.done = True

# Make a sprite for each texture
self.sp = arcade.SpriteList(atlas=self.atlas)
for i, texture in enumerate(self.atlas.textures):
pos = i * 64
sprite = arcade.Sprite(
texture,
center_x=32 + math.fmod(pos, self.width),
center_y=32 + math.floor(pos / self.width) * 64,
scale=0.45,
)
self.sp.append(sprite)

print(f'Atlas has {len(self.atlas._textures)} textures')

# self.atlas.show(draw_borders=True)

def on_draw(self):
self.clear()
self.sp.draw(pixelated=True)

def on_update(self, delta_time: float):
if self.done:
self.close()


if len(sys.argv) < 2 or sys.argv[1] not in ('load', 'save'):
print('Usage: atlas_load_save.py [save|load]')
sys.exit(1)

MODE = sys.argv[1]

AtlasLoadSave().run()
# """
# Quick and dirty atlas load/save testing.
# Loading and saving atlases are not officially supported.
# This is simply an experiment.

# Dump atlas:
# python arcade/experimental/atlas_load_save.py save

# Load atlas:
# python arcade/experimental/atlas_load_save.py load
# """

# from __future__ import annotations

# import sys
# import math
# import pprint
# from typing import Dict, Tuple, List
# from time import perf_counter
# from pathlib import Path
# import arcade
# from arcade.texture_atlas.helpers import save_atlas, load_atlas

# MODE = 'save'
# RESOURCE_ROOT = arcade.resources.ASSET_PATH
# DESTINATION = Path.cwd()

# texture_paths: List[Path] = []
# texture_paths += RESOURCE_ROOT.glob("images/enemies/*.png")
# texture_paths += RESOURCE_ROOT.glob("images/items/*.png")
# texture_paths += RESOURCE_ROOT.glob("images/alien/*.png")
# texture_paths += RESOURCE_ROOT.glob("images/tiles/*.png")


# def populate_atlas(atlas: arcade.TextureAtlas) -> Tuple[int, Dict[str, float]]:
# """Populate the atlas with all the resources we can find"""
# perf_data = {}
# textures = []
# t = perf_counter()
# for path in texture_paths:
# texture = arcade.load_texture(path, hit_box_algorithm=arcade.hitbox.algo_simple)
# textures.append(texture)
# perf_data['load_textures'] = perf_counter() - t

# t = perf_counter()
# for texture in textures:
# atlas.add(texture)
# perf_data['add_textures'] = perf_counter() - t

# return len(textures), perf_data


# class AtlasLoadSave(arcade.Window):
# """
# This class demonstrates how to load and save texture atlases.
# """

# def __init__(self):
# super().__init__(1280, 720, "Atlas Load Save")
# self.done = False

# if MODE == "save":
# t = perf_counter()
# self.atlas = arcade.TextureAtlas((1024, 1024))
# count, perf_data = populate_atlas(self.atlas)
# print(f'Populated atlas with {count} texture in {perf_counter() - t:.2f} seconds')
# save_atlas(
# self.atlas,
# directory=Path.cwd(),
# name="test",
# resource_root=RESOURCE_ROOT,
# )
# self.done = True
# if MODE == "load":
# t = perf_counter()
# self.atlas, perf_data = load_atlas(Path.cwd() / 'test.json', RESOURCE_ROOT)
# print(f'Loaded atlas in {perf_counter() - t:.2f} seconds')
# pprint.pprint(perf_data, indent=2)
# # self.done = True

# # Make a sprite for each texture
# self.sp = arcade.SpriteList(atlas=self.atlas)
# for i, texture in enumerate(self.atlas.textures):
# pos = i * 64
# sprite = arcade.Sprite(
# texture,
# center_x=32 + math.fmod(pos, self.width),
# center_y=32 + math.floor(pos / self.width) * 64,
# scale=0.45,
# )
# self.sp.append(sprite)

# print(f'Atlas has {len(self.atlas._textures)} textures')

# # self.atlas.show(draw_borders=True)

# def on_draw(self):
# self.clear()
# self.sp.draw(pixelated=True)

# def on_update(self, delta_time: float):
# if self.done:
# self.close()


# if len(sys.argv) < 2 or sys.argv[1] not in ('load', 'save'):
# print('Usage: atlas_load_save.py [save|load]')
# sys.exit(1)

# MODE = sys.argv[1]

# AtlasLoadSave().run()
2 changes: 1 addition & 1 deletion arcade/gui/nine_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def draw_sized(
:param pixelated: Whether to draw with nearest neighbor interpolation
"""
self.program.set_uniform_safe(
"texture_id", self._atlas.get_texture_id(self._texture.atlas_name)
"texture_id", self._atlas.get_texture_id(self._texture)
)
if pixelated:
self._atlas.texture.filter = self._ctx.NEAREST, self._ctx.NEAREST
Expand Down
32 changes: 16 additions & 16 deletions arcade/texture/texture.py
Original file line number Diff line number Diff line change
Expand Up @@ -869,22 +869,22 @@ def draw_scaled(
# Comparison and hash functions so textures can work with sets
# A texture's uniqueness is simply based on the name
# ------------------------------------------------------------
def __hash__(self) -> int:
return hash(self.cache_name)

def __eq__(self, other) -> bool:
if other is None:
return False
if not isinstance(other, self.__class__):
return False
return self.cache_name == other.cache_name

def __ne__(self, other) -> bool:
if other is None:
return True
if not isinstance(other, self.__class__):
return True
return self.cache_name != other.cache_name
# def __hash__(self) -> int:
# return hash(self.cache_name)

# def __eq__(self, other) -> bool:
# if other is None:
# return False
# if not isinstance(other, self.__class__):
# return False
# return self.cache_name == other.cache_name

# def __ne__(self, other) -> bool:
# if other is None:
# return True
# if not isinstance(other, self.__class__):
# return True
# return self.cache_name != other.cache_name

def __repr__(self) -> str:
cache_name = getattr(self, "cache_name", None)
Expand Down
Loading