gba-sprite-engine/engine/src/sprites/sprite_manager.cpp

91 lines
2.4 KiB
C++
Raw Normal View History

2018-08-01 16:03:16 +02:00
//
// Created by Wouter Groeneveld on 26/07/18.
//
#include <libgba-sprite-engine/sprites/sprite_manager.h>
#include <libgba-sprite-engine/sprites/affine_sprite.h>
2018-08-01 16:03:16 +02:00
#include <libgba-sprite-engine/gba/tonc_core.h>
#include <libgba-sprite-engine/allocator.h>
#include <libgba-sprite-engine/background/text_stream.h>
2018-08-01 16:03:16 +02:00
#define MAX_SPRITE_SIZE 128
#define MAX_AFFINE_SIZE 31
void SpriteManager::set(std::vector<Sprite*> sprites) {
2018-08-01 16:03:16 +02:00
initialized = false;
this->sprites.clear();
this->sprites.insert(this->sprites.end(), sprites.begin(), sprites.end());
}
void SpriteManager::add(Sprite* sprite) {
2018-08-01 16:03:16 +02:00
if(sprites.size() == MAX_SPRITE_SIZE) {
failure_gba(MaxSpriteSizeReached);
2018-08-01 16:03:16 +02:00
}
sprites.push_back(sprite);
copyOverImageDataToVRAM(sprite);
2018-08-01 16:03:16 +02:00
}
void SpriteManager::render() {
if(!initialized) {
failure_gba(Cant_Render_Before_Init);
2018-08-01 16:03:16 +02:00
}
copyOverSpriteOAMToVRAM();
}
void SpriteManager::persist() {
copyOverImageDataToVRAM();
2018-08-01 16:03:16 +02:00
initialized = true;
}
void SpriteManager::copyOverSpriteOAMToVRAM() {
int i = 0;
int affineIndex = 0;
for(auto sprite : this->sprites) {
if(affineIndex > MAX_AFFINE_SIZE) {
failure_gba(MaxSpritesWithAffineReached);
2018-08-01 16:03:16 +02:00
}
sprite->update();
2018-08-01 16:03:16 +02:00
auto oam = sprite->oam.get();
oam_mem[i] = *oam;
auto affine = dynamic_cast<AffineSprite*>(sprite);
if(affine) {
// WHY warning: can't do this: obj_aff_mem[affineIndex] = *affineShadow;
// because that would override OAM also! only want to set non-overlapping affine attribs
2018-08-04 10:43:27 +02:00
affine->setTransformationMatrix(&obj_aff_mem[affineIndex]);
2018-08-01 16:03:16 +02:00
affine->setAffineIndex(affineIndex);
affineIndex++;
}
i++;
}
for(int j = i; j < MAX_SPRITE_SIZE; j++) {
oam_mem[j].attr0 = ATTR0_HIDE;
}
}
void SpriteManager::copyOverImageDataToVRAM(Sprite *sprite) {
2018-08-09 12:35:05 +02:00
if(!sprite->data && sprite->imageSize == 0) {
// assume it's copied over from another sprite
sprite->buildOam(sprite->tileIndex);
} else {
const auto allocated = Allocator::allocateObjectTiles(sprite->imageSize);
dma3_cpy(allocated.pointer(), sprite->data, allocated.size);
sprite->buildOam(allocated.getTileLocation());
}
}
void SpriteManager::copyOverImageDataToVRAM() {
for(auto sprite : sprites) {
copyOverImageDataToVRAM(sprite);
2018-08-01 16:03:16 +02:00
}
}