/*
This file is part of Retro Graphics Toolkit
Retro Graphics Toolkit is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or any later version.
Retro Graphics Toolkit is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Retro Graphics Toolkit. If not, see .
Copyright Sega16 (or whatever you wish to call me) (2012-2019)
*/
#include
#include
#include "classlevel.h"
#include "filemisc.h"
level::level(Project*prj) {
this->prj = prj;
layeramt = 1;
lvlI.resize(1, {1, 1, 1, 1, 0, 0, CHUNKS});
dat.resize(1);
odat.resize(1);
dat[0] = new std::vector;
dat[0]->resize(1);
odat[0] = new std::vector;
layernames.emplace_back("0");
}
level::level(const level&o, Project*prj) {
this->prj = prj;
layeramt = o.layeramt;
lvlI = o.lvlI;
layernames = o.layernames;
dat.resize(o.dat.size());
odat.resize(o.odat.size());
for (unsigned i = 0; i < o.dat.size(); ++i)
dat[i] = new std::vector(*o.dat[i]);
for (unsigned i = 0; i < o.odat.size(); ++i)
odat[i] = new std::vector(*o.odat[i]);
}
void level::addLayer(unsigned at, bool after) {
unsigned base = at;
if (after)
++at;
lvlI.insert(lvlI.begin() + at, lvlI[base]);
std::vector*vtmp = new std::vector;
dat.insert(dat.begin() + at, vtmp);
dat[at]->resize(lvlI[at].w * lvlI[at].h);
}
void level::removeLayer(unsigned which) {
lvlI.erase(lvlI.begin() + which);
delete dat[which];
dat.erase(dat.begin() + which);
delete odat[which];
odat.erase(odat.begin() + which);
layernames.erase(layernames.begin() + which);
}
bool level::inRangeLayer(unsigned tst) {
if (tst >= layeramt) {
fl_alert("Level layer out of range error");
return false;
} else
return true;
}
struct levelInfo*level::getInfo(unsigned layer) {
return& lvlI.at(layer);
}
void level::setInfo(unsigned layer, struct levelInfo i) {
lvlI[layer] = i;
}
struct levDat*level::getlevDat(unsigned layer, unsigned x, unsigned y) {
return&(dat.at(layer)->at(y * lvlI[layer].w + x));
}
void level::setlevDat(unsigned layer, unsigned x, unsigned y, struct levDat d) {
(*(dat[layer]))[y * lvlI[layer].w + x] = d;
}
struct levobjDat*level::getObjDat(unsigned layer, unsigned idx) {
return&(odat.at(layer)->at(idx));
}
void level::setlevObjDat(unsigned layer, unsigned idx, struct levobjDat d) {
(*(odat[layer]))[idx] = d;
}
void level::setlayeramt(unsigned amt, bool lastLayerDim) {
if (amt <= 0) {
fprintf(stderr, "level:setlayeramt called with invalid amount (%u). Forcing amount to one.\n", amt);
amt = 1;
}
if (amt > layeramt) {
if (lastLayerDim)
lvlI.reserve(amt);
else {
lvlI.resize(amt, {1, 1, 1, 1, 0, 0, CHUNKS});
}
dat.reserve(amt);
odat.reserve(amt);
layernames.reserve(amt);
for (unsigned i = layeramt; i < amt; ++i) {
if (lastLayerDim)
lvlI.push_back(lvlI[layeramt - 1]);
std::vector*vtmp = new std::vector;
vtmp->resize(lvlI[i].w * lvlI[i].h);
dat.push_back(vtmp);
std::vector*votmp = new std::vector;
odat.push_back(votmp);
layernames.emplace_back(std::to_string(i));
}
} else if (amt < layeramt) {
for (unsigned i = amt; i < layeramt; ++i) {
delete dat[i];
delete odat[i];
}
lvlI.resize(amt);
dat.resize(amt);
odat.resize(amt);
layernames.resize(amt);
}
layeramt = amt;
}
void level::resizeLayer(unsigned idx, unsigned nw, unsigned nh) {
std::vectortmp = std::vector(*(dat[idx]));
unsigned ow = lvlI[idx].w, oh = lvlI[idx].h;
dat[idx]->resize(nw * nh);
for (unsigned y = 0; y < std::min(oh, nh); ++y)
std::copy(tmp.begin() + y * ow, tmp.begin() + y * ow + std::min(ow, nw), dat[idx]->begin() + y * nw);
lvlI[idx].w = nw;
lvlI[idx].h = nh;
}
void level::save(FILE*fp) const {
/*Format
* uint32_t layers amount
* For each layer info struct
* Data see struct levDat
* uint32_t objects amount
* Data see struct levobjDat*/
fwrite(&layeramt, sizeof(uint32_t), 1, fp);
for (unsigned i = 0; i < layeramt; ++i) {
saveStrifNot(fp, layernames[i].c_str(), std::to_string(i).c_str());
fwrite(&lvlI[i], sizeof(struct levelInfo), 1, fp);
fwrite(dat[i]->data(), dat[i]->size(), sizeof(struct levDat), fp);
uint32_t objamt = odat[i]->size();
fwrite(&objamt, 1, sizeof(uint32_t), fp);
if (objamt)
fwrite(odat[i]->data(), odat[i]->size(), sizeof(struct levobjDat), fp);
}
}
void level::load(FILE*fp, uint32_t version) {
uint32_t amtnew;
fread(&amtnew, 1, sizeof(uint32_t), fp);
if (amtnew <= 0) {
fprintf(stderr, "Invalid number of level layers detected (%u). Skipping loading levels.\n", amtnew);
return;
}
setlayeramt(amtnew, false);
for (unsigned i = 0; i < layeramt; ++i) {
fileToStr(fp, layernames[i], std::to_string(i).c_str());
uint32_t objamt;
fread(&lvlI[i], sizeof(struct levelInfo), 1, fp);
dat[i]->resize(lvlI[i].w * lvlI[i].h);
fread(dat[i]->data(), sizeof(struct levDat), lvlI[i].w * lvlI[i].h, fp);
fread(&objamt, sizeof(uint32_t), 1, fp);
if (objamt) {
odat[i]->resize(objamt);
fread(odat[i]->data(), sizeof(struct levobjDat), odat[i]->size(), fp);
}
}
}
void level::subType(unsigned oid, unsigned nid, enum source s, int plane) {
uint_fast32_t x, y, i;
int_fast32_t temp;
for (i = 0; i < layeramt; ++i) {
struct levelInfo*in = getInfo(i);
if ((in->src & 3) == s) {
if (s == BLOCKS) {
if (plane >= 0) {
if (plane == in->src >> 2)
continue;
}
}
for (y = 0; y < in->h; ++y) {
for (x = 0; x < in->w; ++x) {
struct levDat*l = getlevDat(i, x, y);
if (l->id == oid)
l->id = nid;
else if (l->id > oid) {
if (l->id > 0)
l->id--;
}
}
}
}
}
}