/* ** scene.cpp ** ** This file is part of mkxp. ** ** Copyright (C) 2013 Jonas Kulla ** ** mkxp 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 2 of the License, or ** (at your option) any later version. ** ** mkxp 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 mkxp. If not, see . */ #include "scene.h" #include "sharedstate.h" Scene::Scene() { geometry.xOrigin = geometry.yOrigin = 0; geometry.rect = IntRect(); } Scene::~Scene() { /* Ensure elements don't unlink from a destructed Scene */ IntruListLink *iter; for (iter = elements.begin(); iter != elements.end(); iter = iter->next) { iter->data->scene = 0; } } void Scene::insert(SceneElement &element) { IntruListLink *iter; for (iter = elements.begin(); iter != elements.end(); iter = iter->next) { SceneElement *e = iter->data; if (element < *e) { elements.insertBefore(element.link, *iter); return; } } elements.append(element.link); } void Scene::insertAfter(SceneElement &element, SceneElement &after) { IntruListLink *iter; for (iter = &after.link; iter != elements.end(); iter = iter->next) { SceneElement *e = iter->data; if (element < *e) { elements.insertBefore(element.link, *iter); return; } } elements.append(element.link); } void Scene::reinsert(SceneElement &element) { elements.remove(element.link); insert(element); } void Scene::notifyGeometryChange() { IntruListLink *iter; for (iter = elements.begin(); iter != elements.end(); iter = iter->next) { iter->data->onGeometryChange(geometry); } } void Scene::composite() { IntruListLink *iter; for (iter = elements.begin(); iter != elements.end(); iter = iter->next) { SceneElement *e = iter->data; if (e->visible) e->draw(); } } SceneElement::SceneElement(Scene &scene, int z, bool isSprite) : link(this), creationStamp(shState->genTimeStamp()), z(z), visible(true), scene(&scene), spriteY(0), isSprite(isSprite) { scene.insert(*this); } SceneElement::SceneElement(Scene &scene, int z, unsigned int cStamp) : link(this), creationStamp(cStamp), z(z), visible(true), scene(&scene), spriteY(0), isSprite(false) { scene.insert(*this); } SceneElement::~SceneElement() { unlink(); } void SceneElement::setScene(Scene &scene) { unlink(); this->scene = &scene; scene.insert(*this); onGeometryChange(scene.getGeometry()); } int SceneElement::getZ() const { return z; } void SceneElement::setZ(int value) { if (z == value) return; z = value; scene->reinsert(*this); } bool SceneElement::getVisible() const { return visible; } void SceneElement::setVisible(bool value) { visible = value; } bool SceneElement::operator<(const SceneElement &o) const { /* Element draw order is decided by their Z value. * If two Z values are equal, the later created object * has priority */ if (z <= o.z) { if (z == o.z) { if (rgssVer >= 2) { /* RGSS2: If two sprites' Z values collide, * their Y coordinates decide draw order. Only * on equal Y does the creation time take effect */ if (isSprite && o.isSprite && spriteY != o.spriteY) return (spriteY < o.spriteY); } return (creationStamp <= o.creationStamp); } return true; } return false; } void SceneElement::setSpriteY(int value) { spriteY = value; scene->reinsert(*this); } void SceneElement::unlink() { if (scene) scene->elements.remove(link); }