gamnit :: SpriteSet :: defaultinit
# Set of sprites sorting them into different `SpriteContext`
class SpriteSet
super HashSet[Sprite]
# Animation speed multiplier (0.0 to pause, 1.0 for normal speed, etc.)
var time_mod = 1.0 is writable
# Seconds elapsed since the launch of the program, in world time responding to `time_mod`
var time = 0.0
# Map texture then static vs dynamic to a `SpriteContext`
private var contexts_map = new HashMap4[RootTexture, nullable RootTexture, Bool, Int, Array[SpriteContext]]
# Contexts in `contexts_map`, sorted by draw order
private var contexts_items = new Array[SpriteContext]
# Sprites needing resorting in `contexts_map`
private var sprites_to_remap = new Array[Sprite]
# Add a sprite to the appropriate context
private fun map_sprite(sprite: Sprite)
do
assert sprite.context == null else print_error "Sprite {sprite} belongs to another SpriteSet"
# Sort by texture and animation texture
var texture = sprite.texture.root
var animation = sprite.animation
var animation_texture = if animation != null then
animation.frames.first.root else null
var draw_order = sprite.draw_order
var contexts = contexts_map[texture, animation_texture, sprite.static, draw_order]
var context = null
if contexts != null then
for c in contexts.reverse_iterator do
var size = c.sprites.length + 1
if size * 4 <= 0xffff then
context = c
break
end
end
end
if context == null then
var usage = if sprite.static then gl_STATIC_DRAW else gl_DYNAMIC_DRAW
context = new SpriteContext(texture, animation_texture, usage, draw_order)
if contexts == null then
contexts = new Array[SpriteContext]
contexts_map[texture, animation_texture, sprite.static, draw_order] = contexts
end
contexts.add context
contexts_items.add context
sprite_draw_order_sorter.sort(contexts_items)
end
context.sprites.add sprite
context.sprites_to_update.add sprite
context.last_sprite_to_update = sprite
sprite.context = context
sprite.sprite_set = self
if animation != null and sprite.animation_start == -1.0 then
# Start animation
sprite.animation_start = time
end
end
# Remove a sprite from its context
private fun unmap_sprite(sprite: Sprite)
do
var context = sprite.context
assert context != null
context.sprites.remove sprite
sprite.context = null
sprite.sprite_set = null
end
# Draw all sprites by all contexts
private fun draw
do
# Remap sprites that may need to change context
for sprite in sprites_to_remap do
# Skip if it was removed from this set after being modified
if sprite.sprite_set != self then continue
unmap_sprite sprite
map_sprite sprite
end
sprites_to_remap.clear
# Sort by draw order
for context in contexts_items do context.draw
end
redef fun add(e)
do
if contexts_items.has(e.context) then return
map_sprite e
super
end
redef fun remove(e)
do
super
if e isa Sprite then unmap_sprite e
end
redef fun remove_all(e)
do
if not has(e) then return
remove e
end
redef fun clear
do
for sprite in self do
sprite.context = null
sprite.sprite_set = null
end
super
for c in contexts_items do c.destroy
contexts_map.clear
contexts_items.clear
sprites_to_remap.clear
end
private fun reset
do
for sprite in self do
sprite.context = null
end
for c in contexts_items do c.destroy
contexts_map.clear
contexts_items.clear
sprites_to_remap.clear
for sprite in self do
map_sprite sprite
end
end
end
lib/gamnit/flat/flat_core.nit:891,1--1038,3