scummvm/engines/wintermute/ad/ad_scene.cpp

3002 lines
86 KiB
C++
Raw Normal View History

2012-03-06 03:34:46 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program 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.
2012-03-06 03:34:46 +00:00
* This program 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.
2012-03-06 03:34:46 +00:00
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#include "engines/wintermute/ad/ad_scene.h"
#include "engines/wintermute/ad/ad_actor.h"
#include "engines/wintermute/ad/ad_entity.h"
#include "engines/wintermute/ad/ad_game.h"
#include "engines/wintermute/ad/ad_layer.h"
#include "engines/wintermute/ad/ad_node_state.h"
#include "engines/wintermute/ad/ad_object.h"
#include "engines/wintermute/ad/ad_path.h"
#include "engines/wintermute/ad/ad_path_point.h"
#include "engines/wintermute/ad/ad_rot_level.h"
#include "engines/wintermute/ad/ad_scale_level.h"
#include "engines/wintermute/ad/ad_scene_node.h"
#include "engines/wintermute/ad/ad_scene_state.h"
#include "engines/wintermute/ad/ad_sentence.h"
#include "engines/wintermute/ad/ad_waypoint_group.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/font/base_font.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_object.h"
#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_point.h"
#include "engines/wintermute/base/base_region.h"
#include "engines/wintermute/base/base_scriptable.h"
#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/base/base_viewport.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/ui/ui_window.h"
#include "engines/wintermute/utils/utils.h"
2012-03-06 03:34:46 +00:00
#include <limits.h>
namespace WinterMute {
IMPLEMENT_PERSISTENT(AdScene, false)
2012-03-06 03:34:46 +00:00
//////////////////////////////////////////////////////////////////////////
AdScene::AdScene(BaseGame *inGame) : BaseObject(inGame) {
_pfTarget = new BasePoint;
setDefaults();
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
AdScene::~AdScene() {
cleanup();
_gameRef->unregisterObject(_fader);
delete _pfTarget;
_pfTarget = NULL;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::setDefaults() {
_initialized = false;
_pfReady = true;
_pfTargetPath = NULL;
_pfRequester = NULL;
_mainLayer = NULL;
2012-03-06 03:34:46 +00:00
_pfPointsNum = 0;
_persistentState = false;
_persistentStateSprites = true;
2012-03-06 03:34:46 +00:00
_autoScroll = true;
_offsetLeft = _offsetTop = 0;
_targetOffsetLeft = _targetOffsetTop = 0;
2012-03-06 03:34:46 +00:00
_lastTimeH = _lastTimeV = 0;
_scrollTimeH = _scrollTimeV = 10;
_scrollPixelsH = _scrollPixelsV = 1;
2012-03-06 03:34:46 +00:00
_pfMaxTime = 15;
2012-03-06 03:34:46 +00:00
_paralaxScrolling = true;
2012-03-06 03:34:46 +00:00
// editor settings
_editorMarginH = _editorMarginV = 100;
_editorColFrame = 0xE0888888;
_editorColEntity = 0xFF008000;
_editorColRegion = 0xFF0000FF;
_editorColBlocked = 0xFF800080;
_editorColWaypoints = 0xFF0000FF;
_editorColEntitySel = 0xFFFF0000;
_editorColRegionSel = 0xFFFF0000;
_editorColBlockedSel = 0xFFFF0000;
_editorColWaypointsSel = 0xFFFF0000;
_editorColScale = 0xFF00FF00;
_editorColDecor = 0xFF00FFFF;
_editorColDecorSel = 0xFFFF0000;
_editorShowRegions = true;
_editorShowBlocked = true;
_editorShowDecor = true;
_editorShowEntities = true;
_editorShowScale = true;
_shieldWindow = NULL;
_fader = new BaseFader(_gameRef);
_gameRef->registerObject(_fader);
_viewport = NULL;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::cleanup() {
BaseObject::cleanup();
2012-03-06 03:34:46 +00:00
_mainLayer = NULL; // reference only
2012-03-06 03:34:46 +00:00
int i;
delete _shieldWindow;
_shieldWindow = NULL;
2012-03-06 03:34:46 +00:00
_gameRef->unregisterObject(_fader);
_fader = NULL;
2012-03-06 03:34:46 +00:00
for (i = 0; i < _layers.getSize(); i++) {
_gameRef->unregisterObject(_layers[i]);
}
_layers.clear();
2012-03-06 03:34:46 +00:00
for (i = 0; i < _waypointGroups.getSize(); i++) {
_gameRef->unregisterObject(_waypointGroups[i]);
}
_waypointGroups.clear();
2012-03-06 03:34:46 +00:00
for (i = 0; i < _scaleLevels.getSize(); i++) {
_gameRef->unregisterObject(_scaleLevels[i]);
}
_scaleLevels.clear();
2012-03-06 03:34:46 +00:00
for (i = 0; i < _rotLevels.getSize(); i++) {
_gameRef->unregisterObject(_rotLevels[i]);
}
_rotLevels.clear();
2012-03-06 03:34:46 +00:00
for (i = 0; i < _pfPath.getSize(); i++) {
delete _pfPath[i];
}
_pfPath.clear();
_pfPointsNum = 0;
2012-03-06 03:34:46 +00:00
for (i = 0; i < _objects.getSize(); i++) {
_gameRef->unregisterObject(_objects[i]);
}
_objects.clear();
2012-03-06 03:34:46 +00:00
delete _viewport;
_viewport = NULL;
2012-03-06 03:34:46 +00:00
setDefaults();
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::getPath(BasePoint source, BasePoint target, AdPath *path, BaseObject *requester) {
if (!_pfReady) {
return false;
} else {
_pfReady = false;
*_pfTarget = target;
_pfTargetPath = path;
_pfRequester = requester;
2012-03-06 03:34:46 +00:00
_pfTargetPath->reset();
_pfTargetPath->setReady(false);
2012-03-06 03:34:46 +00:00
// prepare working path
int i;
pfPointsStart();
2012-03-06 03:34:46 +00:00
// first point
//_pfPath.add(new AdPathPoint(source.x, source.y, 0));
2012-03-06 03:34:46 +00:00
// if we're one pixel stuck, get unstuck
int startX = source.x;
int startY = source.y;
int bestDistance = 1000;
if (isBlockedAt(startX, startY, true, requester)) {
int tolerance = 2;
for (int xxx = startX - tolerance; xxx <= startX + tolerance; xxx++) {
for (int yyy = startY - tolerance; yyy <= startY + tolerance; yyy++) {
if (isWalkableAt(xxx, yyy, true, requester)) {
int distance = abs(xxx - source.x) + abs(yyy - source.y);
if (distance < bestDistance) {
startX = xxx;
startY = yyy;
2012-03-06 03:34:46 +00:00
bestDistance = distance;
2012-03-06 03:34:46 +00:00
}
}
}
}
}
pfPointsAdd(startX, startY, 0);
2012-03-06 03:34:46 +00:00
//CorrectTargetPoint(&target.x, &target.y);
// last point
//_pfPath.add(new AdPathPoint(target.x, target.y, INT_MAX));
pfPointsAdd(target.x, target.y, INT_MAX);
2012-03-06 03:34:46 +00:00
// active waypoints
for (i = 0; i < _waypointGroups.getSize(); i++) {
if (_waypointGroups[i]->_active) {
pfAddWaypointGroup(_waypointGroups[i], requester);
2012-03-06 03:34:46 +00:00
}
}
// free waypoints
for (i = 0; i < _objects.getSize(); i++) {
if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentWptGroup) {
pfAddWaypointGroup(_objects[i]->_currentWptGroup, requester);
2012-03-06 03:34:46 +00:00
}
}
AdGame *adGame = (AdGame *)_gameRef;
for (i = 0; i < adGame->_objects.getSize(); i++) {
if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentWptGroup) {
pfAddWaypointGroup(adGame->_objects[i]->_currentWptGroup, requester);
2012-03-06 03:34:46 +00:00
}
}
return true;
}
}
//////////////////////////////////////////////////////////////////////////
void AdScene::pfAddWaypointGroup(AdWaypointGroup *wpt, BaseObject *requester) {
if (!wpt->_active) {
return;
}
2012-03-06 03:34:46 +00:00
for (int i = 0; i < wpt->_points.getSize(); i++) {
if (isBlockedAt(wpt->_points[i]->x, wpt->_points[i]->y, true, requester)) {
continue;
}
2012-03-06 03:34:46 +00:00
//_pfPath.add(new AdPathPoint(Wpt->_points[i]->x, Wpt->_points[i]->y, INT_MAX));
pfPointsAdd(wpt->_points[i]->x, wpt->_points[i]->y, INT_MAX);
2012-03-06 03:34:46 +00:00
}
}
//////////////////////////////////////////////////////////////////////////
float AdScene::getZoomAt(int x, int y) {
2012-03-06 03:34:46 +00:00
float ret = 100;
bool found = false;
if (_mainLayer) {
for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) {
AdSceneNode *node = _mainLayer->_nodes[i];
if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_blocked && node->_region->pointInRegion(x, y)) {
if (node->_region->_zoom != 0) {
ret = node->_region->_zoom;
2012-03-06 03:34:46 +00:00
found = true;
break;
}
}
}
}
if (!found) {
ret = getScaleAt(y);
}
2012-03-06 03:34:46 +00:00
return ret;
}
//////////////////////////////////////////////////////////////////////////
uint32 AdScene::getAlphaAt(int x, int y, bool colorCheck) {
if (!_gameRef->_debugDebugMode) {
colorCheck = false;
}
2012-03-06 03:34:46 +00:00
uint32 ret;
if (colorCheck) {
ret = 0xFFFF0000;
} else {
ret = 0xFFFFFFFF;
}
2012-03-06 03:34:46 +00:00
if (_mainLayer) {
for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) {
AdSceneNode *node = _mainLayer->_nodes[i];
if (node->_type == OBJECT_REGION && node->_region->_active && (colorCheck || !node->_region->_blocked) && node->_region->pointInRegion(x, y)) {
if (!node->_region->_blocked) {
ret = node->_region->_alpha;
}
2012-03-06 03:34:46 +00:00
break;
}
}
}
return ret;
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::isBlockedAt(int x, int y, bool checkFreeObjects, BaseObject *requester) {
2012-03-06 03:34:46 +00:00
bool ret = true;
if (checkFreeObjects) {
for (int i = 0; i < _objects.getSize(); i++) {
if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) {
if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) {
return true;
}
2012-03-06 03:34:46 +00:00
}
}
AdGame *adGame = (AdGame *)_gameRef;
for (int i = 0; i < adGame->_objects.getSize(); i++) {
if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentBlockRegion) {
if (adGame->_objects[i]->_currentBlockRegion->pointInRegion(x, y)) {
return true;
}
2012-03-06 03:34:46 +00:00
}
}
}
if (_mainLayer) {
for (int i = 0; i < _mainLayer->_nodes.getSize(); i++) {
AdSceneNode *node = _mainLayer->_nodes[i];
2012-03-06 03:34:46 +00:00
/*
2012-06-12 12:41:29 +00:00
if (Node->_type == OBJECT_REGION && Node->_region->_active && Node->_region->_blocked && Node->_region->PointInRegion(X, Y))
2012-03-06 03:34:46 +00:00
{
ret = true;
break;
}
*/
if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_decoration && node->_region->pointInRegion(x, y)) {
if (node->_region->_blocked) {
2012-03-06 03:34:46 +00:00
ret = true;
break;
} else {
ret = false;
}
2012-03-06 03:34:46 +00:00
}
}
}
return ret;
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::isWalkableAt(int x, int y, bool checkFreeObjects, BaseObject *requester) {
2012-03-06 03:34:46 +00:00
bool ret = false;
if (checkFreeObjects) {
for (int i = 0; i < _objects.getSize(); i++) {
if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) {
if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) {
return false;
}
2012-03-06 03:34:46 +00:00
}
}
AdGame *adGame = (AdGame *)_gameRef;
for (int i = 0; i < adGame->_objects.getSize(); i++) {
if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentBlockRegion) {
if (adGame->_objects[i]->_currentBlockRegion->pointInRegion(x, y)) {
return false;
}
2012-03-06 03:34:46 +00:00
}
}
}
if (_mainLayer) {
for (int i = 0; i < _mainLayer->_nodes.getSize(); i++) {
AdSceneNode *node = _mainLayer->_nodes[i];
if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_decoration && node->_region->pointInRegion(x, y)) {
if (node->_region->_blocked) {
2012-03-06 03:34:46 +00:00
ret = false;
break;
} else {
ret = true;
}
2012-03-06 03:34:46 +00:00
}
}
}
return ret;
}
//////////////////////////////////////////////////////////////////////////
int AdScene::getPointsDist(BasePoint p1, BasePoint p2, BaseObject *requester) {
double xStep, yStep, x, y;
2012-03-06 03:34:46 +00:00
int xLength, yLength, xCount, yCount;
int x1, y1, x2, y2;
2012-03-06 03:34:46 +00:00
x1 = p1.x;
y1 = p1.y;
x2 = p2.x;
y2 = p2.y;
2012-03-06 03:34:46 +00:00
xLength = abs(x2 - x1);
yLength = abs(y2 - y1);
2012-03-06 03:34:46 +00:00
if (xLength > yLength) {
if (x1 > x2) {
BaseUtils::swap(&x1, &x2);
BaseUtils::swap(&y1, &y2);
2012-03-06 03:34:46 +00:00
}
yStep = (double)(y2 - y1) / (double)(x2 - x1);
y = y1;
2012-03-06 03:34:46 +00:00
for (xCount = x1; xCount < x2; xCount++) {
if (isBlockedAt(xCount, (int)y, true, requester)) {
return -1;
}
y += yStep;
2012-03-06 03:34:46 +00:00
}
} else {
if (y1 > y2) {
BaseUtils::swap(&x1, &x2);
BaseUtils::swap(&y1, &y2);
2012-03-06 03:34:46 +00:00
}
xStep = (double)(x2 - x1) / (double)(y2 - y1);
x = x1;
2012-03-06 03:34:46 +00:00
for (yCount = y1; yCount < y2; yCount++) {
if (isBlockedAt((int)x, yCount, true, requester)) {
return -1;
}
x += xStep;
2012-03-06 03:34:46 +00:00
}
}
return MAX(xLength, yLength);
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::pathFinderStep() {
2012-03-06 03:34:46 +00:00
int i;
// get lowest unmarked
int lowestDist = INT_MAX;
AdPathPoint *lowestPt = NULL;
2012-03-06 03:34:46 +00:00
for (i = 0; i < _pfPointsNum; i++)
if (!_pfPath[i]->_marked && _pfPath[i]->_distance < lowestDist) {
lowestDist = _pfPath[i]->_distance;
lowestPt = _pfPath[i];
2012-03-06 03:34:46 +00:00
}
if (lowestPt == NULL) { // no path -> terminate PathFinder
_pfReady = true;
_pfTargetPath->setReady(true);
2012-03-06 03:34:46 +00:00
return;
}
lowestPt->_marked = true;
2012-03-06 03:34:46 +00:00
// target point marked, generate path and terminate
if (lowestPt->x == _pfTarget->x && lowestPt->y == _pfTarget->y) {
while (lowestPt != NULL) {
_pfTargetPath->_points.insert_at(0, new BasePoint(lowestPt->x, lowestPt->y));
lowestPt = lowestPt->_origin;
2012-03-06 03:34:46 +00:00
}
_pfReady = true;
_pfTargetPath->setReady(true);
2012-03-06 03:34:46 +00:00
return;
}
// otherwise keep on searching
for (i = 0; i < _pfPointsNum; i++)
if (!_pfPath[i]->_marked) {
int j = getPointsDist(*lowestPt, *_pfPath[i], _pfRequester);
if (j != -1 && lowestPt->_distance + j < _pfPath[i]->_distance) {
_pfPath[i]->_distance = lowestPt->_distance + j;
_pfPath[i]->_origin = lowestPt;
2012-03-06 03:34:46 +00:00
}
}
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::initLoop() {
2012-03-06 03:34:46 +00:00
#ifdef _DEBUGxxxx
int nu_steps = 0;
uint32 start = _gameRef->_currentTime;
while (!_pfReady && g_system->getMillis() - start <= _pfMaxTime) {
2012-03-06 03:34:46 +00:00
PathFinderStep();
nu_steps++;
2012-03-06 03:34:46 +00:00
}
if (nu_steps > 0) {
_gameRef->LOG(0, "STAT: PathFinder iterations in one loop: %d (%s) _pfMaxTime=%d", nu_steps, _pfReady ? "finished" : "not yet done", _pfMaxTime);
}
2012-03-06 03:34:46 +00:00
#else
uint32 start = _gameRef->_currentTime;
while (!_pfReady && g_system->getMillis() - start <= _pfMaxTime) {
pathFinderStep();
}
2012-03-06 03:34:46 +00:00
#endif
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::loadFile(const char *filename) {
byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (buffer == NULL) {
_gameRef->LOG(0, "AdScene::LoadFile failed for file '%s'", filename);
return STATUS_FAILED;
2012-03-06 03:34:46 +00:00
}
bool ret;
2012-03-06 03:34:46 +00:00
setFilename(filename);
2012-03-06 03:34:46 +00:00
if (DID_FAIL(ret = loadBuffer(buffer, true))) {
_gameRef->LOG(0, "Error parsing SCENE file '%s'", filename);
}
2012-03-06 03:34:46 +00:00
setFilename(filename);
2012-03-06 03:34:46 +00:00
2012-07-25 19:05:03 +00:00
delete[] buffer;
2012-03-06 03:34:46 +00:00
return ret;
}
TOKEN_DEF_START
TOKEN_DEF(SCENE)
TOKEN_DEF(TEMPLATE)
TOKEN_DEF(NAME)
TOKEN_DEF(LAYER)
TOKEN_DEF(WAYPOINTS)
TOKEN_DEF(EVENTS)
TOKEN_DEF(CURSOR)
TOKEN_DEF(CAMERA)
TOKEN_DEF(ENTITY)
TOKEN_DEF(SCALE_LEVEL)
TOKEN_DEF(ROTATION_LEVEL)
TOKEN_DEF(EDITOR_MARGIN_H)
TOKEN_DEF(EDITOR_MARGIN_V)
TOKEN_DEF(EDITOR_COLOR_FRAME)
TOKEN_DEF(EDITOR_COLOR_ENTITY_SEL)
TOKEN_DEF(EDITOR_COLOR_REGION_SEL)
TOKEN_DEF(EDITOR_COLOR_DECORATION_SEL)
TOKEN_DEF(EDITOR_COLOR_BLOCKED_SEL)
TOKEN_DEF(EDITOR_COLOR_WAYPOINTS_SEL)
TOKEN_DEF(EDITOR_COLOR_REGION)
TOKEN_DEF(EDITOR_COLOR_DECORATION)
TOKEN_DEF(EDITOR_COLOR_BLOCKED)
TOKEN_DEF(EDITOR_COLOR_ENTITY)
TOKEN_DEF(EDITOR_COLOR_WAYPOINTS)
TOKEN_DEF(EDITOR_COLOR_SCALE)
TOKEN_DEF(EDITOR_SHOW_REGIONS)
TOKEN_DEF(EDITOR_SHOW_BLOCKED)
TOKEN_DEF(EDITOR_SHOW_DECORATION)
TOKEN_DEF(EDITOR_SHOW_ENTITIES)
TOKEN_DEF(EDITOR_SHOW_SCALE)
TOKEN_DEF(SCRIPT)
TOKEN_DEF(CAPTION)
TOKEN_DEF(PROPERTY)
TOKEN_DEF(VIEWPORT)
TOKEN_DEF(PERSISTENT_STATE_SPRITES)
TOKEN_DEF(PERSISTENT_STATE)
TOKEN_DEF(EDITOR_PROPERTY)
TOKEN_DEF_END
//////////////////////////////////////////////////////////////////////////
bool AdScene::loadBuffer(byte *buffer, bool complete) {
2012-03-06 03:34:46 +00:00
TOKEN_TABLE_START(commands)
TOKEN_TABLE(SCENE)
TOKEN_TABLE(TEMPLATE)
TOKEN_TABLE(NAME)
TOKEN_TABLE(LAYER)
TOKEN_TABLE(WAYPOINTS)
TOKEN_TABLE(EVENTS)
TOKEN_TABLE(CURSOR)
TOKEN_TABLE(CAMERA)
TOKEN_TABLE(ENTITY)
TOKEN_TABLE(SCALE_LEVEL)
TOKEN_TABLE(ROTATION_LEVEL)
TOKEN_TABLE(EDITOR_MARGIN_H)
TOKEN_TABLE(EDITOR_MARGIN_V)
TOKEN_TABLE(EDITOR_COLOR_FRAME)
TOKEN_TABLE(EDITOR_COLOR_ENTITY_SEL)
TOKEN_TABLE(EDITOR_COLOR_REGION_SEL)
TOKEN_TABLE(EDITOR_COLOR_DECORATION_SEL)
TOKEN_TABLE(EDITOR_COLOR_BLOCKED_SEL)
TOKEN_TABLE(EDITOR_COLOR_WAYPOINTS_SEL)
TOKEN_TABLE(EDITOR_COLOR_REGION)
TOKEN_TABLE(EDITOR_COLOR_DECORATION)
TOKEN_TABLE(EDITOR_COLOR_BLOCKED)
TOKEN_TABLE(EDITOR_COLOR_ENTITY)
TOKEN_TABLE(EDITOR_COLOR_WAYPOINTS)
TOKEN_TABLE(EDITOR_COLOR_SCALE)
TOKEN_TABLE(EDITOR_SHOW_REGIONS)
TOKEN_TABLE(EDITOR_SHOW_DECORATION)
TOKEN_TABLE(EDITOR_SHOW_BLOCKED)
TOKEN_TABLE(EDITOR_SHOW_ENTITIES)
TOKEN_TABLE(EDITOR_SHOW_SCALE)
TOKEN_TABLE(SCRIPT)
TOKEN_TABLE(CAPTION)
TOKEN_TABLE(PROPERTY)
TOKEN_TABLE(VIEWPORT)
TOKEN_TABLE(PERSISTENT_STATE_SPRITES)
TOKEN_TABLE(PERSISTENT_STATE)
TOKEN_TABLE(EDITOR_PROPERTY)
TOKEN_TABLE_END
cleanup();
2012-03-06 03:34:46 +00:00
byte *params;
int cmd;
BaseParser parser;
2012-03-06 03:34:46 +00:00
if (complete) {
if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_SCENE) {
_gameRef->LOG(0, "'SCENE' keyword expected.");
return STATUS_FAILED;
2012-03-06 03:34:46 +00:00
}
buffer = params;
2012-03-06 03:34:46 +00:00
}
int ar, ag, ab, aa;
char camera[MAX_PATH_LENGTH] = "";
/* float waypointHeight = -1.0f; */
2012-03-06 03:34:46 +00:00
while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
2012-03-06 03:34:46 +00:00
switch (cmd) {
case TOKEN_TEMPLATE:
if (DID_FAIL(loadFile((char *)params))) {
cmd = PARSERR_GENERIC;
}
2012-03-06 03:34:46 +00:00
break;
case TOKEN_NAME:
setName((char *)params);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_CAPTION:
setCaption((char *)params);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_LAYER: {
AdLayer *layer = new AdLayer(_gameRef);
if (!layer || DID_FAIL(layer->loadBuffer(params, false))) {
2012-03-06 03:34:46 +00:00
cmd = PARSERR_GENERIC;
delete layer;
layer = NULL;
} else {
_gameRef->registerObject(layer);
_layers.add(layer);
if (layer->_main) {
_mainLayer = layer;
_width = layer->_width;
_height = layer->_height;
2012-03-06 03:34:46 +00:00
}
}
}
break;
case TOKEN_WAYPOINTS: {
AdWaypointGroup *wpt = new AdWaypointGroup(_gameRef);
if (!wpt || DID_FAIL(wpt->loadBuffer(params, false))) {
2012-03-06 03:34:46 +00:00
cmd = PARSERR_GENERIC;
delete wpt;
wpt = NULL;
} else {
_gameRef->registerObject(wpt);
_waypointGroups.add(wpt);
2012-03-06 03:34:46 +00:00
}
}
break;
case TOKEN_SCALE_LEVEL: {
AdScaleLevel *sl = new AdScaleLevel(_gameRef);
if (!sl || DID_FAIL(sl->loadBuffer(params, false))) {
2012-03-06 03:34:46 +00:00
cmd = PARSERR_GENERIC;
delete sl;
sl = NULL;
} else {
_gameRef->registerObject(sl);
_scaleLevels.add(sl);
2012-03-06 03:34:46 +00:00
}
}
break;
case TOKEN_ROTATION_LEVEL: {
AdRotLevel *rl = new AdRotLevel(_gameRef);
if (!rl || DID_FAIL(rl->loadBuffer(params, false))) {
2012-03-06 03:34:46 +00:00
cmd = PARSERR_GENERIC;
delete rl;
rl = NULL;
} else {
_gameRef->registerObject(rl);
_rotLevels.add(rl);
2012-03-06 03:34:46 +00:00
}
}
break;
case TOKEN_ENTITY: {
AdEntity *entity = new AdEntity(_gameRef);
if (!entity || DID_FAIL(entity->loadBuffer(params, false))) {
2012-03-06 03:34:46 +00:00
cmd = PARSERR_GENERIC;
delete entity;
entity = NULL;
} else {
addObject(entity);
2012-03-06 03:34:46 +00:00
}
}
break;
case TOKEN_CURSOR:
delete _cursor;
_cursor = new BaseSprite(_gameRef);
if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
delete _cursor;
_cursor = NULL;
2012-03-06 03:34:46 +00:00
cmd = PARSERR_GENERIC;
}
break;
case TOKEN_CAMERA:
strcpy(camera, (char *)params);
break;
case TOKEN_EDITOR_MARGIN_H:
parser.scanStr((char *)params, "%d", &_editorMarginH);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_MARGIN_V:
parser.scanStr((char *)params, "%d", &_editorMarginV);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_FRAME:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColFrame = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_ENTITY:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColEntity = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_ENTITY_SEL:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColEntitySel = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_REGION_SEL:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColRegionSel = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_DECORATION_SEL:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColDecorSel = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_BLOCKED_SEL:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColBlockedSel = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_WAYPOINTS_SEL:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColWaypointsSel = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_REGION:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColRegion = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_DECORATION:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColDecor = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_BLOCKED:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColBlocked = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_WAYPOINTS:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColWaypoints = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_COLOR_SCALE:
parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa);
_editorColScale = BYTETORGBA(ar, ag, ab, aa);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_SHOW_REGIONS:
parser.scanStr((char *)params, "%b", &_editorShowRegions);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_SHOW_BLOCKED:
parser.scanStr((char *)params, "%b", &_editorShowBlocked);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_SHOW_DECORATION:
parser.scanStr((char *)params, "%b", &_editorShowDecor);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_SHOW_ENTITIES:
parser.scanStr((char *)params, "%b", &_editorShowEntities);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_SHOW_SCALE:
parser.scanStr((char *)params, "%b", &_editorShowScale);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_SCRIPT:
addScript((char *)params);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_PROPERTY:
parseProperty(params, false);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_VIEWPORT: {
Rect32 rc;
parser.scanStr((char *)params, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom);
if (!_viewport) {
_viewport = new BaseViewport(_gameRef);
}
if (_viewport) {
_viewport->setRect(rc.left, rc.top, rc.right, rc.bottom, true);
}
2012-03-06 03:34:46 +00:00
}
case TOKEN_PERSISTENT_STATE:
parser.scanStr((char *)params, "%b", &_persistentState);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_PERSISTENT_STATE_SPRITES:
parser.scanStr((char *)params, "%b", &_persistentStateSprites);
2012-03-06 03:34:46 +00:00
break;
case TOKEN_EDITOR_PROPERTY:
parseEditorProperty(params, false);
2012-03-06 03:34:46 +00:00
break;
}
}
if (cmd == PARSERR_TOKENNOTFOUND) {
_gameRef->LOG(0, "Syntax error in SCENE definition");
return STATUS_FAILED;
2012-03-06 03:34:46 +00:00
}
if (_mainLayer == NULL) {
_gameRef->LOG(0, "Warning: scene '%s' has no main layer.", getFilename());
}
2012-03-06 03:34:46 +00:00
sortScaleLevels();
sortRotLevels();
2012-03-06 03:34:46 +00:00
_initialized = true;
2012-03-06 03:34:46 +00:00
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::traverseNodes(bool doUpdate) {
if (!_initialized) {
return STATUS_OK;
}
2012-03-06 03:34:46 +00:00
int j, k;
AdGame *adGame = (AdGame *)_gameRef;
2012-03-06 03:34:46 +00:00
//////////////////////////////////////////////////////////////////////////
// prepare viewport
bool popViewport = false;
if (_viewport && !_gameRef->_editorMode) {
_gameRef->pushViewport(_viewport);
popViewport = true;
} else if (adGame->_sceneViewport && !_gameRef->_editorMode) {
_gameRef->pushViewport(adGame->_sceneViewport);
popViewport = true;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// *** adjust scroll offset
2012-07-09 00:50:15 +00:00
if (doUpdate) {
2012-03-06 03:34:46 +00:00
/*
if (_autoScroll && _gameRef->_mainObject != NULL)
2012-03-06 03:34:46 +00:00
{
ScrollToObject(_gameRef->_mainObject);
2012-03-06 03:34:46 +00:00
}
*/
if (_autoScroll) {
2012-03-06 03:34:46 +00:00
// adjust horizontal scroll
if (_gameRef->_timer - _lastTimeH >= _scrollTimeH) {
_lastTimeH = _gameRef->_timer;
if (_offsetLeft < _targetOffsetLeft) {
_offsetLeft += _scrollPixelsH;
_offsetLeft = MIN(_offsetLeft, _targetOffsetLeft);
} else if (_offsetLeft > _targetOffsetLeft) {
_offsetLeft -= _scrollPixelsH;
_offsetLeft = MAX(_offsetLeft, _targetOffsetLeft);
2012-03-06 03:34:46 +00:00
}
}
// adjust vertical scroll
if (_gameRef->_timer - _lastTimeV >= _scrollTimeV) {
_lastTimeV = _gameRef->_timer;
if (_offsetTop < _targetOffsetTop) {
_offsetTop += _scrollPixelsV;
_offsetTop = MIN(_offsetTop, _targetOffsetTop);
} else if (_offsetTop > _targetOffsetTop) {
_offsetTop -= _scrollPixelsV;
_offsetTop = MAX(_offsetTop, _targetOffsetTop);
2012-03-06 03:34:46 +00:00
}
}
if (_offsetTop == _targetOffsetTop && _offsetLeft == _targetOffsetLeft) {
_ready = true;
}
} else {
_ready = true; // not scrolling, i.e. always ready
}
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
int viewportWidth, viewportHeight;
getViewportSize(&viewportWidth, &viewportHeight);
2012-03-06 03:34:46 +00:00
int viewportX, viewportY;
getViewportOffset(&viewportX, &viewportY);
2012-03-06 03:34:46 +00:00
int scrollableX = _width - viewportWidth;
int scrollableY = _height - viewportHeight;
2012-03-06 03:34:46 +00:00
double widthRatio = scrollableX <= 0 ? 0 : ((double)(_offsetLeft) / (double)scrollableX);
double heightRatio = scrollableY <= 0 ? 0 : ((double)(_offsetTop) / (double)scrollableY);
2012-03-06 03:34:46 +00:00
int origX, origY;
_gameRef->getOffset(&origX, &origY);
2012-03-06 03:34:46 +00:00
//////////////////////////////////////////////////////////////////////////
// *** display/update everything
_gameRef->_renderer->setup2D();
2012-03-06 03:34:46 +00:00
// for each layer
/* int mainOffsetX = 0; */
/* int mainOffsetY = 0; */
2012-03-06 03:34:46 +00:00
for (j = 0; j < _layers.getSize(); j++) {
if (!_layers[j]->_active) {
continue;
}
2012-03-06 03:34:46 +00:00
// make layer exclusive
2012-07-09 00:50:15 +00:00
if (!doUpdate) {
if (_layers[j]->_closeUp && !_gameRef->_editorMode) {
if (!_shieldWindow) {
_shieldWindow = new UIWindow(_gameRef);
}
if (_shieldWindow) {
_shieldWindow->_posX = _shieldWindow->_posY = 0;
_shieldWindow->_width = _gameRef->_renderer->_width;
_shieldWindow->_height = _gameRef->_renderer->_height;
_shieldWindow->display();
2012-03-06 03:34:46 +00:00
}
}
}
if (_paralaxScrolling) {
int offsetX = (int)(widthRatio * (_layers[j]->_width - viewportWidth) - viewportX);
int offsetY = (int)(heightRatio * (_layers[j]->_height - viewportHeight) - viewportY);
_gameRef->setOffset(offsetX, offsetY);
2012-03-06 03:34:46 +00:00
_gameRef->_offsetPercentX = (float)offsetX / ((float)_layers[j]->_width - viewportWidth) * 100.0f;
_gameRef->_offsetPercentY = (float)offsetY / ((float)_layers[j]->_height - viewportHeight) * 100.0f;
2012-03-06 03:34:46 +00:00
//_gameRef->QuickMessageForm("%d %f", OffsetX+ViewportX, _gameRef->_offsetPercentX);
2012-03-06 03:34:46 +00:00
} else {
_gameRef->setOffset(_offsetLeft - viewportX, _offsetTop - viewportY);
2012-03-06 03:34:46 +00:00
_gameRef->_offsetPercentX = (float)(_offsetLeft - viewportX) / ((float)_layers[j]->_width - viewportWidth) * 100.0f;
_gameRef->_offsetPercentY = (float)(_offsetTop - viewportY) / ((float)_layers[j]->_height - viewportHeight) * 100.0f;
2012-03-06 03:34:46 +00:00
}
// for each node
for (k = 0; k < _layers[j]->_nodes.getSize(); k++) {
AdSceneNode *node = _layers[j]->_nodes[k];
switch (node->_type) {
2012-03-06 03:34:46 +00:00
case OBJECT_ENTITY:
if (node->_entity->_active && (_gameRef->_editorMode || !node->_entity->_editorOnly)) {
_gameRef->_renderer->setup2D();
2012-03-06 03:34:46 +00:00
if (doUpdate) {
node->_entity->update();
} else {
node->_entity->display();
}
2012-03-06 03:34:46 +00:00
}
break;
case OBJECT_REGION: {
if (node->_region->_blocked) {
break;
}
if (node->_region->_decoration) {
break;
}
2012-03-06 03:34:46 +00:00
if (!doUpdate) {
displayRegionContent(node->_region);
}
2012-03-06 03:34:46 +00:00
}
break;
default:
error("AdScene::TraverseNodes - Unhandled enum");
break;
2012-03-06 03:34:46 +00:00
} // switch
} // each node
// display/update all objects which are off-regions
if (_layers[j]->_main) {
2012-07-09 00:50:15 +00:00
if (doUpdate) {
updateFreeObjects();
2012-03-06 03:34:46 +00:00
} else {
displayRegionContent(NULL);
2012-03-06 03:34:46 +00:00
}
}
} // each layer
// restore state
_gameRef->setOffset(origX, origY);
_gameRef->_renderer->setup2D();
2012-03-06 03:34:46 +00:00
// display/update fader
if (_fader) {
if (doUpdate) {
_fader->update();
} else {
_fader->display();
}
2012-03-06 03:34:46 +00:00
}
if (popViewport) {
_gameRef->popViewport();
}
2012-03-06 03:34:46 +00:00
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::display() {
return traverseNodes(false);
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::updateFreeObjects() {
AdGame *adGame = (AdGame *)_gameRef;
// 3D-code removed
// bool is3DSet;
2012-03-06 03:34:46 +00:00
// *** update all active objects
// is3DSet = false;
for (int i = 0; i < adGame->_objects.getSize(); i++) {
if (!adGame->_objects[i]->_active) {
continue;
}
// 3D-code removed
adGame->_objects[i]->update();
adGame->_objects[i]->_drawn = false;
2012-03-06 03:34:46 +00:00
}
for (int i = 0; i < _objects.getSize(); i++) {
if (!_objects[i]->_active) {
continue;
}
2012-03-06 03:34:46 +00:00
_objects[i]->update();
_objects[i]->_drawn = false;
2012-03-06 03:34:46 +00:00
}
if (_autoScroll && _gameRef->_mainObject != NULL) {
scrollToObject(_gameRef->_mainObject);
2012-03-06 03:34:46 +00:00
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::displayRegionContent(AdRegion *region, bool display3DOnly) {
AdGame *adGame = (AdGame *)_gameRef;
BaseArray<AdObject *> objects;
AdObject *obj;
2012-03-06 03:34:46 +00:00
// global objects
for (int i = 0; i < adGame->_objects.getSize(); i++) {
obj = adGame->_objects[i];
if (obj->_active && !obj->_drawn && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) {
objects.add(obj);
2012-03-06 03:34:46 +00:00
}
}
// scene objects
for (int i = 0; i < _objects.getSize(); i++) {
obj = _objects[i];
if (obj->_active && !obj->_editorOnly && !obj->_drawn && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) {
objects.add(obj);
2012-03-06 03:34:46 +00:00
}
}
// sort by _posY
qsort(objects.getData(), objects.getSize(), sizeof(AdObject *), AdScene::compareObjs);
2012-03-06 03:34:46 +00:00
// display them
for (int i = 0; i < objects.getSize(); i++) {
obj = objects[i];
2012-03-06 03:34:46 +00:00
if (display3DOnly && !obj->_is3D) {
continue;
}
2012-03-06 03:34:46 +00:00
_gameRef->_renderer->setup2D();
2012-03-06 03:34:46 +00:00
if (_gameRef->_editorMode || !obj->_editorOnly) {
obj->display();
}
obj->_drawn = true;
2012-03-06 03:34:46 +00:00
}
// display design only objects
if (!display3DOnly) {
if (_gameRef->_editorMode && region == NULL) {
for (int i = 0; i < _objects.getSize(); i++) {
if (_objects[i]->_active && _objects[i]->_editorOnly) {
_objects[i]->display();
_objects[i]->_drawn = true;
2012-03-06 03:34:46 +00:00
}
}
}
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
int AdScene::compareObjs(const void *obj1, const void *obj2) {
AdObject *object1 = *(AdObject **)obj1;
AdObject *object2 = *(AdObject **)obj2;
2012-03-06 03:34:46 +00:00
if (object1->_posY < object2->_posY) {
return -1;
} else if (object1->_posY > object2->_posY) {
return 1;
} else {
return 0;
}
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::displayRegionContentOld(AdRegion *region) {
AdGame *adGame = (AdGame *)_gameRef;
AdObject *obj;
2012-03-06 03:34:46 +00:00
// display all objects in region sorted by _posY
2012-03-06 03:34:46 +00:00
do {
obj = NULL;
int minY = INT_MAX;
// global objects
for (int i = 0; i < adGame->_objects.getSize(); i++) {
if (adGame->_objects[i]->_active && !adGame->_objects[i]->_drawn && adGame->_objects[i]->_posY < minY && (adGame->_objects[i]->_stickRegion == region || region == NULL || (adGame->_objects[i]->_stickRegion == NULL && region->pointInRegion(adGame->_objects[i]->_posX, adGame->_objects[i]->_posY)))) {
obj = adGame->_objects[i];
minY = adGame->_objects[i]->_posY;
2012-03-06 03:34:46 +00:00
}
}
// scene objects
for (int i = 0; i < _objects.getSize(); i++) {
if (_objects[i]->_active && !_objects[i]->_editorOnly && !_objects[i]->_drawn && _objects[i]->_posY < minY && (_objects[i]->_stickRegion == region || region == NULL || (_objects[i]->_stickRegion == NULL && region->pointInRegion(_objects[i]->_posX, _objects[i]->_posY)))) {
obj = _objects[i];
minY = _objects[i]->_posY;
2012-03-06 03:34:46 +00:00
}
}
if (obj != NULL) {
_gameRef->_renderer->setup2D();
2012-03-06 03:34:46 +00:00
if (_gameRef->_editorMode || !obj->_editorOnly) {
obj->display();
}
obj->_drawn = true;
2012-03-06 03:34:46 +00:00
}
} while (obj != NULL);
// design only objects
if (_gameRef->_editorMode && region == NULL) {
for (int i = 0; i < _objects.getSize(); i++) {
if (_objects[i]->_active && _objects[i]->_editorOnly) {
_objects[i]->display();
_objects[i]->_drawn = true;
2012-03-06 03:34:46 +00:00
}
}
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::update() {
return traverseNodes(true);
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::scrollTo(int offsetX, int offsetY) {
int viewportWidth, viewportHeight;
getViewportSize(&viewportWidth, &viewportHeight);
2012-03-06 03:34:46 +00:00
int origOffsetLeft = _targetOffsetLeft;
int origOffsetTop = _targetOffsetTop;
2012-03-06 03:34:46 +00:00
_targetOffsetLeft = MAX(0, offsetX - viewportWidth / 2);
_targetOffsetLeft = MIN(_targetOffsetLeft, _width - viewportWidth);
2012-03-06 03:34:46 +00:00
_targetOffsetTop = MAX(0, offsetY - viewportHeight / 2);
_targetOffsetTop = MIN(_targetOffsetTop, _height - viewportHeight);
2012-03-06 03:34:46 +00:00
if (_gameRef->_mainObject && _gameRef->_mainObject->_is3D) {
if (abs(origOffsetLeft - _targetOffsetLeft) < 5) {
_targetOffsetLeft = origOffsetLeft;
}
if (abs(origOffsetTop - _targetOffsetTop) < 5) {
_targetOffsetTop = origOffsetTop;
}
//_targetOffsetTop = 0;
2012-03-06 03:34:46 +00:00
}
_ready = false;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::scrollToObject(BaseObject *object) {
if (object) {
scrollTo(object->_posX, object->_posY - object->getHeight() / 2);
}
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::skipToObject(BaseObject *object) {
if (object) {
skipTo(object->_posX, object->_posY - object->getHeight() / 2);
}
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::skipTo(int offsetX, int offsetY) {
int viewportWidth, viewportHeight;
getViewportSize(&viewportWidth, &viewportHeight);
2012-03-06 03:34:46 +00:00
_offsetLeft = MAX(0, offsetX - viewportWidth / 2);
_offsetLeft = MIN(_offsetLeft, _width - viewportWidth);
2012-03-06 03:34:46 +00:00
_offsetTop = MAX(0, offsetY - viewportHeight / 2);
_offsetTop = MIN(_offsetTop, _height - viewportHeight);
2012-03-06 03:34:46 +00:00
_targetOffsetLeft = _offsetLeft;
_targetOffsetTop = _offsetTop;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// high level scripting interface
//////////////////////////////////////////////////////////////////////////
bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
2012-03-06 03:34:46 +00:00
//////////////////////////////////////////////////////////////////////////
// LoadActor
//////////////////////////////////////////////////////////////////////////
if (strcmp(name, "LoadActor") == 0) {
stack->correctParams(1);
AdActor *act = new AdActor(_gameRef);
if (act && DID_SUCCEED(act->loadFile(stack->pop()->getString()))) {
addObject(act);
stack->pushNative(act, true);
2012-03-06 03:34:46 +00:00
} else {
delete act;
act = NULL;
stack->pushNULL();
2012-03-06 03:34:46 +00:00
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// LoadEntity
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "LoadEntity") == 0) {
stack->correctParams(1);
AdEntity *ent = new AdEntity(_gameRef);
if (ent && DID_SUCCEED(ent->loadFile(stack->pop()->getString()))) {
addObject(ent);
stack->pushNative(ent, true);
2012-03-06 03:34:46 +00:00
} else {
delete ent;
ent = NULL;
stack->pushNULL();
2012-03-06 03:34:46 +00:00
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// CreateEntity
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "CreateEntity") == 0) {
stack->correctParams(1);
ScValue *val = stack->pop();
2012-03-06 03:34:46 +00:00
AdEntity *ent = new AdEntity(_gameRef);
addObject(ent);
if (!val->isNULL()) {
ent->setName(val->getString());
}
stack->pushNative(ent, true);
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// UnloadObject / UnloadActor / UnloadEntity / UnloadActor3D / DeleteEntity
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "UnloadObject") == 0 || strcmp(name, "UnloadActor") == 0 || strcmp(name, "UnloadEntity") == 0 || strcmp(name, "UnloadActor3D") == 0 || strcmp(name, "DeleteEntity") == 0) {
stack->correctParams(1);
ScValue *val = stack->pop();
AdObject *obj = (AdObject *)val->getNative();
removeObject(obj);
if (val->getType() == VAL_VARIABLE_REF) {
val->setNULL();
}
2012-03-06 03:34:46 +00:00
stack->pushNULL();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// SkipTo
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "SkipTo") == 0) {
stack->correctParams(2);
ScValue *val1 = stack->pop();
ScValue *val2 = stack->pop();
if (val1->isNative()) {
skipToObject((BaseObject *)val1->getNative());
2012-03-06 03:34:46 +00:00
} else {
skipTo(val1->getInt(), val2->getInt());
2012-03-06 03:34:46 +00:00
}
stack->pushNULL();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// ScrollTo / ScrollToAsync
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollTo") == 0 || strcmp(name, "ScrollToAsync") == 0) {
stack->correctParams(2);
ScValue *val1 = stack->pop();
ScValue *val2 = stack->pop();
if (val1->isNative()) {
scrollToObject((BaseObject *)val1->getNative());
2012-03-06 03:34:46 +00:00
} else {
scrollTo(val1->getInt(), val2->getInt());
2012-03-06 03:34:46 +00:00
}
if (strcmp(name, "ScrollTo") == 0) {
script->waitForExclusive(this);
}
stack->pushNULL();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// GetLayer
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetLayer") == 0) {
stack->correctParams(1);
ScValue *val = stack->pop();
if (val->isInt()) {
int layer = val->getInt();
if (layer < 0 || layer >= _layers.getSize()) {
stack->pushNULL();
} else {
stack->pushNative(_layers[layer], true);
}
2012-03-06 03:34:46 +00:00
} else {
const char *layerName = val->getString();
bool layerFound = false;
for (int i = 0; i < _layers.getSize(); i++) {
if (scumm_stricmp(layerName, _layers[i]->getName()) == 0) {
stack->pushNative(_layers[i], true);
layerFound = true;
2012-03-06 03:34:46 +00:00
break;
}
}
if (!layerFound) {
stack->pushNULL();
}
2012-03-06 03:34:46 +00:00
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// GetWaypointGroup
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetWaypointGroup") == 0) {
stack->correctParams(1);
int group = stack->pop()->getInt();
if (group < 0 || group >= _waypointGroups.getSize()) {
stack->pushNULL();
} else {
stack->pushNative(_waypointGroups[group], true);
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// GetNode
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetNode") == 0) {
stack->correctParams(1);
const char *nodeName = stack->pop()->getString();
2012-03-06 03:34:46 +00:00
BaseObject *node = getNodeByName(nodeName);
if (node) {
stack->pushNative((BaseScriptable *)node, true);
} else {
stack->pushNULL();
}
2012-03-06 03:34:46 +00:00
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// GetFreeNode
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetFreeNode") == 0) {
stack->correctParams(1);
ScValue *val = stack->pop();
2012-03-06 03:34:46 +00:00
AdObject *ret = NULL;
if (val->isInt()) {
int index = val->getInt();
if (index >= 0 && index < _objects.getSize()) {
ret = _objects[index];
}
2012-03-06 03:34:46 +00:00
} else {
const char *nodeName = val->getString();
for (int i = 0; i < _objects.getSize(); i++) {
if (_objects[i] && _objects[i]->getName() && scumm_stricmp(_objects[i]->getName(), nodeName) == 0) {
ret = _objects[i];
2012-03-06 03:34:46 +00:00
break;
}
}
}
if (ret) {
stack->pushNative(ret, true);
} else {
stack->pushNULL();
}
2012-03-06 03:34:46 +00:00
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// GetRegionAt
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetRegionAt") == 0) {
stack->correctParams(3);
int x = stack->pop()->getInt();
int y = stack->pop()->getInt();
ScValue *val = stack->pop();
2012-03-06 03:34:46 +00:00
bool includeDecors = false;
if (!val->isNULL()) {
includeDecors = val->getBool();
}
2012-03-06 03:34:46 +00:00
if (_mainLayer) {
for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) {
AdSceneNode *node = _mainLayer->_nodes[i];
if (node->_type == OBJECT_REGION && node->_region->_active && node->_region->pointInRegion(x, y)) {
if (node->_region->_decoration && !includeDecors) {
continue;
}
2012-03-06 03:34:46 +00:00
stack->pushNative(node->_region, true);
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
}
}
stack->pushNULL();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// IsBlockedAt
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "IsBlockedAt") == 0) {
stack->correctParams(2);
int x = stack->pop()->getInt();
int y = stack->pop()->getInt();
2012-03-06 03:34:46 +00:00
stack->pushBool(isBlockedAt(x, y));
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// IsWalkableAt
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "IsWalkableAt") == 0) {
stack->correctParams(2);
int x = stack->pop()->getInt();
int y = stack->pop()->getInt();
2012-03-06 03:34:46 +00:00
stack->pushBool(isWalkableAt(x, y));
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// GetScaleAt
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetScaleAt") == 0) {
stack->correctParams(2);
int x = stack->pop()->getInt();
int y = stack->pop()->getInt();
2012-03-06 03:34:46 +00:00
stack->pushFloat(getZoomAt(x, y));
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// GetRotationAt
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetRotationAt") == 0) {
stack->correctParams(2);
int x = stack->pop()->getInt();
int y = stack->pop()->getInt();
2012-03-06 03:34:46 +00:00
stack->pushFloat(getRotationAt(x, y));
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// IsScrolling
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "IsScrolling") == 0) {
stack->correctParams(0);
bool ret = false;
if (_autoScroll) {
if (_targetOffsetLeft != _offsetLeft || _targetOffsetTop != _offsetTop) {
ret = true;
}
2012-03-06 03:34:46 +00:00
}
stack->pushBool(ret);
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// FadeOut / FadeOutAsync
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "FadeOut") == 0 || strcmp(name, "FadeOutAsync") == 0) {
stack->correctParams(5);
uint32 duration = stack->pop()->getInt(500);
byte red = stack->pop()->getInt(0);
byte green = stack->pop()->getInt(0);
byte blue = stack->pop()->getInt(0);
byte alpha = stack->pop()->getInt(0xFF);
2012-03-06 03:34:46 +00:00
_fader->fadeOut(BYTETORGBA(red, green, blue, alpha), duration);
if (strcmp(name, "FadeOutAsync") != 0) {
script->waitFor(_fader);
}
2012-03-06 03:34:46 +00:00
stack->pushNULL();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// FadeIn / FadeInAsync
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "FadeIn") == 0 || strcmp(name, "FadeInAsync") == 0) {
stack->correctParams(5);
uint32 duration = stack->pop()->getInt(500);
byte red = stack->pop()->getInt(0);
byte green = stack->pop()->getInt(0);
byte blue = stack->pop()->getInt(0);
byte alpha = stack->pop()->getInt(0xFF);
2012-03-06 03:34:46 +00:00
_fader->fadeIn(BYTETORGBA(red, green, blue, alpha), duration);
if (strcmp(name, "FadeInAsync") != 0) {
script->waitFor(_fader);
}
2012-03-06 03:34:46 +00:00
stack->pushNULL();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// GetFadeColor
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetFadeColor") == 0) {
stack->correctParams(0);
stack->pushInt(_fader->getCurrentColor());
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// IsPointInViewport
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "IsPointInViewport") == 0) {
stack->correctParams(2);
int x = stack->pop()->getInt();
int y = stack->pop()->getInt();
stack->pushBool(pointInViewport(x, y));
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// SetViewport
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "SetViewport") == 0) {
stack->correctParams(4);
int x = stack->pop()->getInt();
int y = stack->pop()->getInt();
int width = stack->pop()->getInt();
int height = stack->pop()->getInt();
2012-03-06 03:34:46 +00:00
if (width <= 0) {
width = _gameRef->_renderer->_width;
}
if (height <= 0) {
height = _gameRef->_renderer->_height;
}
2012-03-06 03:34:46 +00:00
if (!_viewport) {
_viewport = new BaseViewport(_gameRef);
}
if (_viewport) {
_viewport->setRect(x, y, x + width, y + height);
}
2012-03-06 03:34:46 +00:00
stack->pushBool(true);
2012-03-06 03:34:46 +00:00
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// AddLayer
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "AddLayer") == 0) {
stack->correctParams(1);
ScValue *val = stack->pop();
2012-03-06 03:34:46 +00:00
AdLayer *layer = new AdLayer(_gameRef);
if (!val->isNULL()) {
layer->setName(val->getString());
}
if (_mainLayer) {
layer->_width = _mainLayer->_width;
layer->_height = _mainLayer->_height;
2012-03-06 03:34:46 +00:00
}
_layers.add(layer);
_gameRef->registerObject(layer);
2012-03-06 03:34:46 +00:00
stack->pushNative(layer, true);
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// InsertLayer
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "InsertLayer") == 0) {
stack->correctParams(2);
int index = stack->pop()->getInt();
ScValue *val = stack->pop();
2012-03-06 03:34:46 +00:00
AdLayer *layer = new AdLayer(_gameRef);
if (!val->isNULL()) {
layer->setName(val->getString());
}
if (_mainLayer) {
layer->_width = _mainLayer->_width;
layer->_height = _mainLayer->_height;
2012-03-06 03:34:46 +00:00
}
if (index < 0) {
index = 0;
}
if (index <= _layers.getSize() - 1) {
_layers.insert_at(index, layer);
} else {
_layers.add(layer);
}
2012-03-06 03:34:46 +00:00
_gameRef->registerObject(layer);
2012-03-06 03:34:46 +00:00
stack->pushNative(layer, true);
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// DeleteLayer
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "DeleteLayer") == 0) {
stack->correctParams(1);
ScValue *val = stack->pop();
2012-03-06 03:34:46 +00:00
AdLayer *toDelete = NULL;
if (val->isNative()) {
BaseScriptable *temp = val->getNative();
for (int i = 0; i < _layers.getSize(); i++) {
if (_layers[i] == temp) {
toDelete = _layers[i];
2012-03-06 03:34:46 +00:00
break;
}
}
} else {
int index = val->getInt();
if (index >= 0 && index < _layers.getSize()) {
toDelete = _layers[index];
2012-03-06 03:34:46 +00:00
}
}
if (toDelete == NULL) {
stack->pushBool(false);
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
if (toDelete->_main) {
script->runtimeError("Scene.DeleteLayer - cannot delete main scene layer");
stack->pushBool(false);
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
for (int i = 0; i < _layers.getSize(); i++) {
if (_layers[i] == toDelete) {
_layers.remove_at(i);
_gameRef->unregisterObject(toDelete);
2012-03-06 03:34:46 +00:00
break;
}
}
stack->pushBool(true);
return STATUS_OK;
} else {
return BaseObject::scCallMethod(script, stack, thisStack, name);
2012-03-06 03:34:46 +00:00
}
}
//////////////////////////////////////////////////////////////////////////
ScValue *AdScene::scGetProperty(const char *name) {
_scValue->setNULL();
2012-03-06 03:34:46 +00:00
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
if (strcmp(name, "Type") == 0) {
_scValue->setString("scene");
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// NumLayers (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "NumLayers") == 0) {
_scValue->setInt(_layers.getSize());
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// NumWaypointGroups (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "NumWaypointGroups") == 0) {
_scValue->setInt(_waypointGroups.getSize());
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// MainLayer (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "MainLayer") == 0) {
if (_mainLayer) {
_scValue->setNative(_mainLayer, true);
} else {
_scValue->setNULL();
}
2012-03-06 03:34:46 +00:00
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// NumFreeNodes (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "NumFreeNodes") == 0) {
_scValue->setInt(_objects.getSize());
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// MouseX (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "MouseX") == 0) {
int viewportX;
getViewportOffset(&viewportX);
2012-03-06 03:34:46 +00:00
_scValue->setInt(_gameRef->_mousePos.x + _offsetLeft - viewportX);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// MouseY (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "MouseY") == 0) {
int viewportY;
getViewportOffset(NULL, &viewportY);
2012-03-06 03:34:46 +00:00
_scValue->setInt(_gameRef->_mousePos.y + _offsetTop - viewportY);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// AutoScroll
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "AutoScroll") == 0) {
_scValue->setBool(_autoScroll);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// PersistentState
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "PersistentState") == 0) {
_scValue->setBool(_persistentState);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// PersistentStateSprites
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "PersistentStateSprites") == 0) {
_scValue->setBool(_persistentStateSprites);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// ScrollPixelsX
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollPixelsX") == 0) {
_scValue->setInt(_scrollPixelsH);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// ScrollPixelsY
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollPixelsY") == 0) {
_scValue->setInt(_scrollPixelsV);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// ScrollSpeedX
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollSpeedX") == 0) {
_scValue->setInt(_scrollTimeH);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// ScrollSpeedY
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollSpeedY") == 0) {
_scValue->setInt(_scrollTimeV);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// OffsetX
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "OffsetX") == 0) {
_scValue->setInt(_offsetLeft);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// OffsetY
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "OffsetY") == 0) {
_scValue->setInt(_offsetTop);
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// Width (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Width") == 0) {
if (_mainLayer) {
_scValue->setInt(_mainLayer->_width);
} else {
_scValue->setInt(0);
}
return _scValue;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// Height (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Height") == 0) {
if (_mainLayer) {
_scValue->setInt(_mainLayer->_height);
} else {
_scValue->setInt(0);
}
return _scValue;
} else {
return BaseObject::scGetProperty(name);
2012-03-06 03:34:46 +00:00
}
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::scSetProperty(const char *name, ScValue *value) {
2012-03-06 03:34:46 +00:00
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
if (strcmp(name, "Name") == 0) {
setName(value->getString());
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// AutoScroll
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "AutoScroll") == 0) {
_autoScroll = value->getBool();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// PersistentState
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "PersistentState") == 0) {
_persistentState = value->getBool();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// PersistentStateSprites
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "PersistentStateSprites") == 0) {
_persistentStateSprites = value->getBool();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// ScrollPixelsX
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollPixelsX") == 0) {
_scrollPixelsH = value->getInt();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// ScrollPixelsY
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollPixelsY") == 0) {
_scrollPixelsV = value->getInt();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// ScrollSpeedX
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollSpeedX") == 0) {
_scrollTimeH = value->getInt();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// ScrollSpeedY
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollSpeedY") == 0) {
_scrollTimeV = value->getInt();
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// OffsetX
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "OffsetX") == 0) {
_offsetLeft = value->getInt();
2012-03-06 03:34:46 +00:00
int viewportWidth, viewportHeight;
getViewportSize(&viewportWidth, &viewportHeight);
2012-03-06 03:34:46 +00:00
_offsetLeft = MAX(0, _offsetLeft - viewportWidth / 2);
_offsetLeft = MIN(_offsetLeft, _width - viewportWidth);
_targetOffsetLeft = _offsetLeft;
2012-03-06 03:34:46 +00:00
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
// OffsetY
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "OffsetY") == 0) {
_offsetTop = value->getInt();
2012-03-06 03:34:46 +00:00
int viewportWidth, viewportHeight;
getViewportSize(&viewportWidth, &viewportHeight);
2012-03-06 03:34:46 +00:00
_offsetTop = MAX(0, _offsetTop - viewportHeight / 2);
_offsetTop = MIN(_offsetTop, _height - viewportHeight);
_targetOffsetTop = _offsetTop;
2012-03-06 03:34:46 +00:00
return STATUS_OK;
} else {
return BaseObject::scSetProperty(name, value);
2012-03-06 03:34:46 +00:00
}
}
//////////////////////////////////////////////////////////////////////////
const char *AdScene::scToString() {
2012-03-06 03:34:46 +00:00
return "[scene object]";
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::addObject(AdObject *object) {
_objects.add(object);
return _gameRef->registerObject(object);
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::removeObject(AdObject *object) {
for (int i = 0; i < _objects.getSize(); i++) {
if (_objects[i] == object) {
_objects.remove_at(i);
return _gameRef->unregisterObject(object);
2012-03-06 03:34:46 +00:00
}
}
return STATUS_FAILED;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::saveAsText(BaseDynamicBuffer *buffer, int indent) {
2012-03-06 03:34:46 +00:00
int i;
buffer->putTextIndent(indent, "SCENE {\n");
2012-03-06 03:34:46 +00:00
buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName());
buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption());
2012-03-06 03:34:46 +00:00
if (_persistentState) {
buffer->putTextIndent(indent + 2, "PERSISTENT_STATE=%s\n", _persistentState ? "TRUE" : "FALSE");
}
2012-03-06 03:34:46 +00:00
if (!_persistentStateSprites) {
buffer->putTextIndent(indent + 2, "PERSISTENT_STATE_SPRITES=%s\n", _persistentStateSprites ? "TRUE" : "FALSE");
}
2012-03-06 03:34:46 +00:00
// scripts
for (i = 0; i < _scripts.getSize(); i++) {
buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
2012-03-06 03:34:46 +00:00
}
buffer->putTextIndent(indent + 2, "\n");
2012-03-06 03:34:46 +00:00
// properties
if (_scProp) {
_scProp->saveAsText(buffer, indent + 2);
}
2012-03-06 03:34:46 +00:00
// viewport
if (_viewport) {
Rect32 *rc = _viewport->getRect();
buffer->putTextIndent(indent + 2, "VIEWPORT { %d, %d, %d, %d }\n", rc->left, rc->top, rc->right, rc->bottom);
2012-03-06 03:34:46 +00:00
}
// editor settings
buffer->putTextIndent(indent + 2, "; ----- editor settings\n");
buffer->putTextIndent(indent + 2, "EDITOR_MARGIN_H=%d\n", _editorMarginH);
buffer->putTextIndent(indent + 2, "EDITOR_MARGIN_V=%d\n", _editorMarginV);
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_FRAME { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColFrame), RGBCOLGetG(_editorColFrame), RGBCOLGetB(_editorColFrame), RGBCOLGetA(_editorColFrame));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_ENTITY_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColEntitySel), RGBCOLGetG(_editorColEntitySel), RGBCOLGetB(_editorColEntitySel), RGBCOLGetA(_editorColEntitySel));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_REGION_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColRegionSel), RGBCOLGetG(_editorColRegionSel), RGBCOLGetB(_editorColRegionSel), RGBCOLGetA(_editorColRegionSel));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_BLOCKED_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColBlockedSel), RGBCOLGetG(_editorColBlockedSel), RGBCOLGetB(_editorColBlockedSel), RGBCOLGetA(_editorColBlockedSel));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_DECORATION_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColDecorSel), RGBCOLGetG(_editorColDecorSel), RGBCOLGetB(_editorColDecorSel), RGBCOLGetA(_editorColDecorSel));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_WAYPOINTS_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColWaypointsSel), RGBCOLGetG(_editorColWaypointsSel), RGBCOLGetB(_editorColWaypointsSel), RGBCOLGetA(_editorColWaypointsSel));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_ENTITY { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColEntity), RGBCOLGetG(_editorColEntity), RGBCOLGetB(_editorColEntity), RGBCOLGetA(_editorColEntity));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_REGION { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColRegion), RGBCOLGetG(_editorColRegion), RGBCOLGetB(_editorColRegion), RGBCOLGetA(_editorColRegion));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_DECORATION { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColDecor), RGBCOLGetG(_editorColDecor), RGBCOLGetB(_editorColDecor), RGBCOLGetA(_editorColDecor));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_BLOCKED { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColBlocked), RGBCOLGetG(_editorColBlocked), RGBCOLGetB(_editorColBlocked), RGBCOLGetA(_editorColBlocked));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_WAYPOINTS { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColWaypoints), RGBCOLGetG(_editorColWaypoints), RGBCOLGetB(_editorColWaypoints), RGBCOLGetA(_editorColWaypoints));
buffer->putTextIndent(indent + 2, "EDITOR_COLOR_SCALE { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColScale), RGBCOLGetG(_editorColScale), RGBCOLGetB(_editorColScale), RGBCOLGetA(_editorColScale));
buffer->putTextIndent(indent + 2, "EDITOR_SHOW_REGIONS=%s\n", _editorShowRegions ? "TRUE" : "FALSE");
buffer->putTextIndent(indent + 2, "EDITOR_SHOW_BLOCKED=%s\n", _editorShowBlocked ? "TRUE" : "FALSE");
buffer->putTextIndent(indent + 2, "EDITOR_SHOW_DECORATION=%s\n", _editorShowDecor ? "TRUE" : "FALSE");
buffer->putTextIndent(indent + 2, "EDITOR_SHOW_ENTITIES=%s\n", _editorShowEntities ? "TRUE" : "FALSE");
buffer->putTextIndent(indent + 2, "EDITOR_SHOW_SCALE=%s\n", _editorShowScale ? "TRUE" : "FALSE");
buffer->putTextIndent(indent + 2, "\n");
BaseClass::saveAsText(buffer, indent + 2);
2012-03-06 03:34:46 +00:00
// waypoints
buffer->putTextIndent(indent + 2, "; ----- waypoints\n");
for (i = 0; i < _waypointGroups.getSize(); i++) {
_waypointGroups[i]->saveAsText(buffer, indent + 2);
}
2012-03-06 03:34:46 +00:00
buffer->putTextIndent(indent + 2, "\n");
2012-03-06 03:34:46 +00:00
// layers
buffer->putTextIndent(indent + 2, "; ----- layers\n");
for (i = 0; i < _layers.getSize(); i++) {
_layers[i]->saveAsText(buffer, indent + 2);
}
2012-03-06 03:34:46 +00:00
// scale levels
buffer->putTextIndent(indent + 2, "; ----- scale levels\n");
for (i = 0; i < _scaleLevels.getSize(); i++) {
_scaleLevels[i]->saveAsText(buffer, indent + 2);
}
2012-03-06 03:34:46 +00:00
// rotation levels
buffer->putTextIndent(indent + 2, "; ----- rotation levels\n");
for (i = 0; i < _rotLevels.getSize(); i++) {
_rotLevels[i]->saveAsText(buffer, indent + 2);
}
2012-03-06 03:34:46 +00:00
buffer->putTextIndent(indent + 2, "\n");
2012-03-06 03:34:46 +00:00
// free entities
buffer->putTextIndent(indent + 2, "; ----- free entities\n");
for (i = 0; i < _objects.getSize(); i++) {
if (_objects[i]->_type == OBJECT_ENTITY) {
_objects[i]->saveAsText(buffer, indent + 2);
2012-03-06 03:34:46 +00:00
}
}
buffer->putTextIndent(indent, "}\n");
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::sortScaleLevels() {
2012-03-06 03:34:46 +00:00
bool changed;
do {
changed = false;
for (int i = 0; i < _scaleLevels.getSize() - 1; i++) {
if (_scaleLevels[i]->_posY > _scaleLevels[i + 1]->_posY) {
AdScaleLevel *sl = _scaleLevels[i];
_scaleLevels[i] = _scaleLevels[i + 1];
_scaleLevels[i + 1] = sl;
2012-03-06 03:34:46 +00:00
changed = true;
}
}
} while (changed);
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::sortRotLevels() {
2012-03-06 03:34:46 +00:00
bool changed;
do {
changed = false;
for (int i = 0; i < _rotLevels.getSize() - 1; i++) {
if (_rotLevels[i]->_posX > _rotLevels[i + 1]->_posX) {
AdRotLevel *rl = _rotLevels[i];
_rotLevels[i] = _rotLevels[i + 1];
_rotLevels[i + 1] = rl;
2012-03-06 03:34:46 +00:00
changed = true;
}
}
} while (changed);
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
float AdScene::getScaleAt(int Y) {
AdScaleLevel *prev = NULL;
AdScaleLevel *next = NULL;
2012-03-06 03:34:46 +00:00
for (int i = 0; i < _scaleLevels.getSize(); i++) {
/* AdScaleLevel *xxx = _scaleLevels[i];*/
/* int j = _scaleLevels.getSize(); */
if (_scaleLevels[i]->_posY < Y) {
prev = _scaleLevels[i];
} else {
next = _scaleLevels[i];
2012-03-06 03:34:46 +00:00
break;
}
}
if (prev == NULL || next == NULL) {
return 100;
}
2012-03-06 03:34:46 +00:00
int delta_y = next->_posY - prev->_posY;
float delta_scale = next->_scale - prev->_scale;
Y -= prev->_posY;
2012-03-06 03:34:46 +00:00
float percent = (float)Y / ((float)delta_y / 100.0f);
return prev->_scale + delta_scale / 100 * percent;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::persist(BasePersistenceManager *persistMgr) {
BaseObject::persist(persistMgr);
persistMgr->transfer(TMEMBER(_autoScroll));
persistMgr->transfer(TMEMBER(_editorColBlocked));
persistMgr->transfer(TMEMBER(_editorColBlockedSel));
persistMgr->transfer(TMEMBER(_editorColDecor));
persistMgr->transfer(TMEMBER(_editorColDecorSel));
persistMgr->transfer(TMEMBER(_editorColEntity));
persistMgr->transfer(TMEMBER(_editorColEntitySel));
persistMgr->transfer(TMEMBER(_editorColFrame));
persistMgr->transfer(TMEMBER(_editorColRegion));
persistMgr->transfer(TMEMBER(_editorColRegionSel));
persistMgr->transfer(TMEMBER(_editorColScale));
persistMgr->transfer(TMEMBER(_editorColWaypoints));
persistMgr->transfer(TMEMBER(_editorColWaypointsSel));
persistMgr->transfer(TMEMBER(_editorMarginH));
persistMgr->transfer(TMEMBER(_editorMarginV));
persistMgr->transfer(TMEMBER(_editorShowBlocked));
persistMgr->transfer(TMEMBER(_editorShowDecor));
persistMgr->transfer(TMEMBER(_editorShowEntities));
persistMgr->transfer(TMEMBER(_editorShowRegions));
persistMgr->transfer(TMEMBER(_editorShowScale));
persistMgr->transfer(TMEMBER(_fader));
persistMgr->transfer(TMEMBER(_height));
persistMgr->transfer(TMEMBER(_initialized));
persistMgr->transfer(TMEMBER(_lastTimeH));
persistMgr->transfer(TMEMBER(_lastTimeV));
2012-06-22 18:06:12 +00:00
_layers.persist(persistMgr);
persistMgr->transfer(TMEMBER(_mainLayer));
2012-06-22 18:06:12 +00:00
_objects.persist(persistMgr);
persistMgr->transfer(TMEMBER(_offsetLeft));
persistMgr->transfer(TMEMBER(_offsetTop));
persistMgr->transfer(TMEMBER(_paralaxScrolling));
persistMgr->transfer(TMEMBER(_persistentState));
persistMgr->transfer(TMEMBER(_persistentStateSprites));
persistMgr->transfer(TMEMBER(_pfMaxTime));
_pfPath.persist(persistMgr);
persistMgr->transfer(TMEMBER(_pfPointsNum));
persistMgr->transfer(TMEMBER(_pfReady));
persistMgr->transfer(TMEMBER(_pfRequester));
persistMgr->transfer(TMEMBER(_pfTarget));
persistMgr->transfer(TMEMBER(_pfTargetPath));
2012-06-22 18:06:12 +00:00
_rotLevels.persist(persistMgr);
_scaleLevels.persist(persistMgr);
persistMgr->transfer(TMEMBER(_scrollPixelsH));
persistMgr->transfer(TMEMBER(_scrollPixelsV));
persistMgr->transfer(TMEMBER(_scrollTimeH));
persistMgr->transfer(TMEMBER(_scrollTimeV));
persistMgr->transfer(TMEMBER(_shieldWindow));
persistMgr->transfer(TMEMBER(_targetOffsetLeft));
persistMgr->transfer(TMEMBER(_targetOffsetTop));
2012-06-22 18:06:12 +00:00
_waypointGroups.persist(persistMgr);
persistMgr->transfer(TMEMBER(_viewport));
persistMgr->transfer(TMEMBER(_width));
2012-03-06 03:34:46 +00:00
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::afterLoad() {
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::correctTargetPoint2(int startX, int startY, int *targetX, int *targetY, bool checkFreeObjects, BaseObject *requester) {
double xStep, yStep, x, y;
2012-03-06 03:34:46 +00:00
int xLength, yLength, xCount, yCount;
int x1, y1, x2, y2;
2012-03-06 03:34:46 +00:00
x1 = *targetX;
y1 = *targetY;
x2 = startX;
y2 = startY;
2012-03-06 03:34:46 +00:00
xLength = abs(x2 - x1);
yLength = abs(y2 - y1);
2012-03-06 03:34:46 +00:00
if (xLength > yLength) {
/*
2012-06-12 12:41:29 +00:00
if (X1 > X2)
2012-03-06 03:34:46 +00:00
{
Swap(&X1, &X2);
Swap(&Y1, &Y2);
}
*/
yStep = fabs((double)(y2 - y1) / (double)(x2 - x1));
y = y1;
2012-03-06 03:34:46 +00:00
for (xCount = x1; xCount < x2; xCount++) {
if (isWalkableAt(xCount, (int)y, checkFreeObjects, requester)) {
*targetX = xCount;
*targetY = (int)y;
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
y += yStep;
2012-03-06 03:34:46 +00:00
}
} else {
/*
2012-06-12 12:41:29 +00:00
if (Y1 > Y2) {
2012-03-06 03:34:46 +00:00
Swap(&X1, &X2);
Swap(&Y1, &Y2);
}
*/
xStep = fabs((double)(x2 - x1) / (double)(y2 - y1));
x = x1;
2012-03-06 03:34:46 +00:00
for (yCount = y1; yCount < y2; yCount++) {
if (isWalkableAt((int)x, yCount, checkFreeObjects, requester)) {
*targetX = (int)x;
*targetY = yCount;
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
x += xStep;
2012-03-06 03:34:46 +00:00
}
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::correctTargetPoint(int startX, int startY, int *argX, int *argY, bool checkFreeObjects, BaseObject *requester) {
int x = *argX;
int y = *argY;
2012-03-06 03:34:46 +00:00
if (isWalkableAt(x, y, checkFreeObjects, requester) || !_mainLayer) {
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
// right
int lengthRight = 0;
bool foundRight = false;
for (x = *argX, y = *argY; x < _mainLayer->_width; x++, lengthRight++) {
if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x - 5, y, checkFreeObjects, requester)) {
foundRight = true;
2012-03-06 03:34:46 +00:00
break;
}
}
// left
int lengthLeft = 0;
bool foundLeft = false;
for (x = *argX, y = *argY; x >= 0; x--, lengthLeft--) {
if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x + 5, y, checkFreeObjects, requester)) {
foundLeft = true;
2012-03-06 03:34:46 +00:00
break;
}
}
// up
int lengthUp = 0;
bool foundUp = false;
for (x = *argX, y = *argY; y >= 0; y--, lengthUp--) {
if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y + 5, checkFreeObjects, requester)) {
foundUp = true;
2012-03-06 03:34:46 +00:00
break;
}
}
// down
int lengthDown = 0;
bool foundDown = false;
for (x = *argX, y = *argY; y < _mainLayer->_height; y++, lengthDown++) {
if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y - 5, checkFreeObjects, requester)) {
foundDown = true;
2012-03-06 03:34:46 +00:00
break;
}
}
if (!foundLeft && !foundRight && !foundUp && !foundDown) {
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
int offsetX = INT_MAX, offsetY = INT_MAX;
2012-03-06 03:34:46 +00:00
if (foundLeft && foundRight) {
if (abs(lengthLeft) < abs(lengthRight)) {
offsetX = lengthLeft;
} else {
offsetX = lengthRight;
}
} else if (foundLeft) {
offsetX = lengthLeft;
} else if (foundRight) {
offsetX = lengthRight;
}
2012-03-06 03:34:46 +00:00
if (foundUp && foundDown) {
if (abs(lengthUp) < abs(lengthDown)) {
offsetY = lengthUp;
} else {
offsetY = lengthDown;
}
} else if (foundUp) {
offsetY = lengthUp;
} else if (foundDown) {
offsetY = lengthDown;
}
2012-03-06 03:34:46 +00:00
if (abs(offsetX) < abs(offsetY)) {
*argX = *argX + offsetX;
} else {
*argY = *argY + offsetY;
}
2012-03-06 03:34:46 +00:00
if (!isWalkableAt(*argX, *argY)) {
return correctTargetPoint2(startX, startY, argX, argY, checkFreeObjects, requester);
} else {
return STATUS_OK;
}
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::pfPointsStart() {
_pfPointsNum = 0;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::pfPointsAdd(int x, int y, int distance) {
if (_pfPointsNum >= _pfPath.getSize()) {
_pfPath.add(new AdPathPoint(x, y, distance));
2012-03-06 03:34:46 +00:00
} else {
_pfPath[_pfPointsNum]->x = x;
_pfPath[_pfPointsNum]->y = y;
_pfPath[_pfPointsNum]->_distance = distance;
_pfPath[_pfPointsNum]->_marked = false;
_pfPath[_pfPointsNum]->_origin = NULL;
2012-03-06 03:34:46 +00:00
}
_pfPointsNum++;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::getViewportOffset(int *offsetX, int *offsetY) {
AdGame *adGame = (AdGame *)_gameRef;
if (_viewport && !_gameRef->_editorMode) {
if (offsetX) {
*offsetX = _viewport->_offsetX;
}
if (offsetY) {
*offsetY = _viewport->_offsetY;
}
} else if (adGame->_sceneViewport && !_gameRef->_editorMode) {
if (offsetX) {
*offsetX = adGame->_sceneViewport->_offsetX;
}
if (offsetY) {
*offsetY = adGame->_sceneViewport->_offsetY;
}
2012-03-06 03:34:46 +00:00
} else {
if (offsetX) {
*offsetX = 0;
}
if (offsetY) {
*offsetY = 0;
}
2012-03-06 03:34:46 +00:00
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::getViewportSize(int *width, int *height) {
AdGame *adGame = (AdGame *)_gameRef;
if (_viewport && !_gameRef->_editorMode) {
if (width) {
*width = _viewport->getWidth();
}
if (height) {
*height = _viewport->getHeight();
}
} else if (adGame->_sceneViewport && !_gameRef->_editorMode) {
if (width) {
*width = adGame->_sceneViewport->getWidth();
}
if (height) {
*height = adGame->_sceneViewport->getHeight();
}
2012-03-06 03:34:46 +00:00
} else {
if (width) {
*width = _gameRef->_renderer->_width;
}
if (height) {
*height = _gameRef->_renderer->_height;
}
2012-03-06 03:34:46 +00:00
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
int AdScene::getOffsetLeft() {
int viewportX;
getViewportOffset(&viewportX);
2012-03-06 03:34:46 +00:00
return _offsetLeft - viewportX;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
int AdScene::getOffsetTop() {
int viewportY;
getViewportOffset(NULL, &viewportY);
2012-03-06 03:34:46 +00:00
return _offsetTop - viewportY;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::pointInViewport(int x, int y) {
int left, top, width, height;
2012-03-06 03:34:46 +00:00
getViewportOffset(&left, &top);
getViewportSize(&width, &height);
2012-03-06 03:34:46 +00:00
return x >= left && x <= left + width && y >= top && y <= top + height;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
void AdScene::setOffset(int offsetLeft, int offsetTop) {
_offsetLeft = offsetLeft;
_offsetTop = offsetTop;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
BaseObject *AdScene::getNodeByName(const char *name) {
BaseObject *ret = NULL;
2012-03-06 03:34:46 +00:00
// dependent objects
for (int i = 0; i < _layers.getSize(); i++) {
AdLayer *layer = _layers[i];
for (int j = 0; j < layer->_nodes.getSize(); j++) {
AdSceneNode *node = layer->_nodes[j];
if ((node->_type == OBJECT_ENTITY && !scumm_stricmp(name, node->_entity->getName())) ||
(node->_type == OBJECT_REGION && !scumm_stricmp(name, node->_region->getName()))) {
switch (node->_type) {
2012-03-06 03:34:46 +00:00
case OBJECT_ENTITY:
ret = node->_entity;
2012-03-06 03:34:46 +00:00
break;
case OBJECT_REGION:
ret = node->_region;
2012-03-06 03:34:46 +00:00
break;
default:
ret = NULL;
}
return ret;
}
}
}
// free entities
for (int i = 0; i < _objects.getSize(); i++) {
if (_objects[i]->_type == OBJECT_ENTITY && !scumm_stricmp(name, _objects[i]->getName())) {
return _objects[i];
2012-03-06 03:34:46 +00:00
}
}
// waypoint groups
for (int i = 0; i < _waypointGroups.getSize(); i++) {
if (!scumm_stricmp(name, _waypointGroups[i]->getName())) {
return _waypointGroups[i];
2012-03-06 03:34:46 +00:00
}
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::saveState() {
return persistState(true);
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::loadState() {
return persistState(false);
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::persistState(bool saving) {
if (!_persistentState) {
return STATUS_OK;
}
2012-03-06 03:34:46 +00:00
AdGame *adGame = (AdGame *)_gameRef;
AdSceneState *state = adGame->getSceneState(getFilename(), saving);
if (!state) {
return STATUS_OK;
}
2012-03-06 03:34:46 +00:00
AdNodeState *nodeState;
2012-03-06 03:34:46 +00:00
// dependent objects
for (int i = 0; i < _layers.getSize(); i++) {
AdLayer *layer = _layers[i];
for (int j = 0; j < layer->_nodes.getSize(); j++) {
AdSceneNode *node = layer->_nodes[j];
switch (node->_type) {
2012-03-06 03:34:46 +00:00
case OBJECT_ENTITY:
if (!node->_entity->_saveState) {
continue;
}
nodeState = state->getNodeState(node->_entity->getName(), saving);
if (nodeState) {
nodeState->transferEntity(node->_entity, _persistentStateSprites, saving);
2012-07-25 19:21:55 +00:00
//if (Saving) NodeState->_active = node->_entity->_active;
//else node->_entity->_active = NodeState->_active;
2012-03-06 03:34:46 +00:00
}
break;
case OBJECT_REGION:
if (!node->_region->_saveState) {
continue;
}
nodeState = state->getNodeState(node->_region->getName(), saving);
if (nodeState) {
if (saving) {
nodeState->_active = node->_region->_active;
} else {
node->_region->_active = nodeState->_active;
}
2012-03-06 03:34:46 +00:00
}
break;
2012-06-25 13:48:00 +00:00
default:
warning("AdScene::PersistState - unhandled enum");
2012-06-25 13:48:00 +00:00
break;
2012-03-06 03:34:46 +00:00
}
}
}
// free entities
for (int i = 0; i < _objects.getSize(); i++) {
if (!_objects[i]->_saveState) {
continue;
}
if (_objects[i]->_type == OBJECT_ENTITY) {
nodeState = state->getNodeState(_objects[i]->getName(), saving);
if (nodeState) {
nodeState->transferEntity((AdEntity *)_objects[i], _persistentStateSprites, saving);
2012-07-25 19:21:55 +00:00
//if (Saving) NodeState->_active = _objects[i]->_active;
//else _objects[i]->_active = NodeState->_active;
2012-03-06 03:34:46 +00:00
}
}
}
// waypoint groups
for (int i = 0; i < _waypointGroups.getSize(); i++) {
nodeState = state->getNodeState(_waypointGroups[i]->getName(), saving);
if (nodeState) {
if (saving) {
nodeState->_active = _waypointGroups[i]->_active;
} else {
_waypointGroups[i]->_active = nodeState->_active;
}
2012-03-06 03:34:46 +00:00
}
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
float AdScene::getRotationAt(int x, int y) {
AdRotLevel *prev = NULL;
AdRotLevel *next = NULL;
2012-03-06 03:34:46 +00:00
for (int i = 0; i < _rotLevels.getSize(); i++) {
/* AdRotLevel *xxx = _rotLevels[i];
int j = _rotLevels.getSize();*/
if (_rotLevels[i]->_posX < x) {
prev = _rotLevels[i];
} else {
next = _rotLevels[i];
2012-03-06 03:34:46 +00:00
break;
}
}
if (prev == NULL || next == NULL) {
return 0;
}
2012-03-06 03:34:46 +00:00
int delta_x = next->_posX - prev->_posX;
float delta_rot = next->_rotation - prev->_rotation;
x -= prev->_posX;
2012-03-06 03:34:46 +00:00
float percent = (float)x / ((float)delta_x / 100.0f);
return prev->_rotation + delta_rot / 100 * percent;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::handleItemAssociations(const char *itemName, bool show) {
for (int i = 0; i < _layers.getSize(); i++) {
AdLayer *layer = _layers[i];
for (int j = 0; j < layer->_nodes.getSize(); j++) {
if (layer->_nodes[j]->_type == OBJECT_ENTITY) {
AdEntity *ent = layer->_nodes[j]->_entity;
2012-03-06 03:34:46 +00:00
if (ent->_item && strcmp(ent->_item, itemName) == 0) {
ent->_active = show;
}
2012-03-06 03:34:46 +00:00
}
}
}
for (int i = 0; i < _objects.getSize(); i++) {
if (_objects[i]->_type == OBJECT_ENTITY) {
AdEntity *ent = (AdEntity *)_objects[i];
if (ent->_item && strcmp(ent->_item, itemName) == 0) {
ent->_active = show;
}
2012-03-06 03:34:46 +00:00
}
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::getRegionsAt(int x, int y, AdRegion **regionList, int numRegions) {
int numUsed = 0;
if (_mainLayer) {
for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) {
AdSceneNode *node = _mainLayer->_nodes[i];
if (node->_type == OBJECT_REGION && node->_region->_active && node->_region->pointInRegion(x, y)) {
if (numUsed < numRegions - 1) {
regionList[numUsed] = node->_region;
numUsed++;
} else {
break;
}
2012-03-06 03:34:46 +00:00
}
}
}
for (int i = numUsed; i < numRegions; i++) {
regionList[i] = NULL;
2012-03-06 03:34:46 +00:00
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::restoreDeviceObjects() {
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
BaseObject *AdScene::getNextAccessObject(BaseObject *currObject) {
BaseArray<AdObject *> objects;
getSceneObjects(objects, true);
2012-03-06 03:34:46 +00:00
if (objects.getSize() == 0) {
return NULL;
} else {
if (currObject != NULL) {
for (int i = 0; i < objects.getSize(); i++) {
if (objects[i] == currObject) {
if (i < objects.getSize() - 1) {
return objects[i + 1];
} else {
break;
}
2012-03-06 03:34:46 +00:00
}
}
}
return objects[0];
2012-03-06 03:34:46 +00:00
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
BaseObject *AdScene::getPrevAccessObject(BaseObject *currObject) {
BaseArray<AdObject *> objects;
getSceneObjects(objects, true);
2012-03-06 03:34:46 +00:00
if (objects.getSize() == 0) {
return NULL;
} else {
if (currObject != NULL) {
for (int i = objects.getSize() - 1; i >= 0; i--) {
if (objects[i] == currObject) {
if (i > 0) {
return objects[i - 1];
} else {
break;
}
2012-03-06 03:34:46 +00:00
}
}
}
return objects[objects.getSize() - 1];
2012-03-06 03:34:46 +00:00
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::getSceneObjects(BaseArray<AdObject *> &objects, bool interactiveOnly) {
for (int i = 0; i < _layers.getSize(); i++) {
2012-03-06 03:34:46 +00:00
// close-up layer -> remove everything below it
if (interactiveOnly && _layers[i]->_closeUp) {
objects.clear();
}
2012-03-06 03:34:46 +00:00
for (int j = 0; j < _layers[i]->_nodes.getSize(); j++) {
AdSceneNode *node = _layers[i]->_nodes[j];
switch (node->_type) {
2012-03-06 03:34:46 +00:00
case OBJECT_ENTITY: {
AdEntity *ent = node->_entity;
if (ent->_active && (ent->_registrable || !interactiveOnly)) {
objects.add(ent);
}
2012-03-06 03:34:46 +00:00
}
break;
case OBJECT_REGION: {
BaseArray<AdObject *> regionObj;
getRegionObjects(node->_region, regionObj, interactiveOnly);
for (int newIndex = 0; newIndex < regionObj.getSize(); newIndex++) {
bool found = false;
for (int old = 0; old < objects.getSize(); old++) {
if (objects[old] == regionObj[newIndex]) {
found = true;
2012-03-06 03:34:46 +00:00
break;
}
}
if (!found) {
objects.add(regionObj[newIndex]);
}
2012-03-06 03:34:46 +00:00
}
2012-07-25 19:21:55 +00:00
//if (RegionObj.getSize() > 0) Objects.Append(RegionObj);
2012-03-06 03:34:46 +00:00
}
break;
2012-06-25 13:48:00 +00:00
default:
warning("AdScene::GetSceneObjects - Unhandled enum");
2012-06-25 13:48:00 +00:00
break;
2012-03-06 03:34:46 +00:00
}
}
}
// objects outside any region
BaseArray<AdObject *> regionObj;
getRegionObjects(NULL, regionObj, interactiveOnly);
for (int newIndex = 0; newIndex < regionObj.getSize(); newIndex++) {
bool found = false;
for (int old = 0; old < objects.getSize(); old++) {
if (objects[old] == regionObj[newIndex]) {
found = true;
2012-03-06 03:34:46 +00:00
break;
}
}
if (!found) {
objects.add(regionObj[newIndex]);
}
2012-03-06 03:34:46 +00:00
}
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
//////////////////////////////////////////////////////////////////////////
bool AdScene::getRegionObjects(AdRegion *region, BaseArray<AdObject *> &objects, bool interactiveOnly) {
AdGame *adGame = (AdGame *)_gameRef;
AdObject *obj;
2012-03-06 03:34:46 +00:00
// global objects
for (int i = 0; i < adGame->_objects.getSize(); i++) {
obj = adGame->_objects[i];
if (obj->_active && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) {
if (interactiveOnly && !obj->_registrable) {
continue;
}
2012-03-06 03:34:46 +00:00
objects.add(obj);
2012-03-06 03:34:46 +00:00
}
}
// scene objects
for (int i = 0; i < _objects.getSize(); i++) {
obj = _objects[i];
if (obj->_active && !obj->_editorOnly && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) {
if (interactiveOnly && !obj->_registrable) {
continue;
}
2012-03-06 03:34:46 +00:00
objects.add(obj);
2012-03-06 03:34:46 +00:00
}
}
// sort by _posY
qsort(objects.getData(), objects.getSize(), sizeof(AdObject *), AdScene::compareObjs);
2012-03-06 03:34:46 +00:00
return STATUS_OK;
2012-03-06 03:34:46 +00:00
}
} // end of namespace WinterMute