682 lines
21 KiB
C++
682 lines
21 KiB
C++
/* 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "tetraedge/tetraedge.h"
|
|
#include "tetraedge/game/application.h"
|
|
#include "tetraedge/te/te_warp.h"
|
|
#include "tetraedge/te/te_core.h"
|
|
#include "tetraedge/te/te_frustum.h"
|
|
#include "tetraedge/te/te_input_mgr.h"
|
|
#include "tetraedge/te/te_renderer.h"
|
|
#include "tetraedge/te/te_ray_intersection.h"
|
|
|
|
namespace Tetraedge {
|
|
|
|
/*static*/
|
|
bool TeWarp::debug = false;
|
|
|
|
TeWarp::TeWarp() : _visible1(false), _loaded(false), _preloaded(false),
|
|
_someXVal(0), _someYVal(0), _someMeshX(0), _someMeshY(0),
|
|
_renderWarpBlocs(true), _xCount(0), _yCount(0), _clickedPickMesh(nullptr),
|
|
_clickedAnimData(nullptr), _markersActive(true) {
|
|
}
|
|
|
|
TeWarp::~TeWarp() {
|
|
_markerValidatedSignal.clear();
|
|
unload();
|
|
_file.reset();
|
|
}
|
|
|
|
void TeWarp::activeMarkers(bool active) {
|
|
_markersActive = active;
|
|
for (auto &warpMarker : _warpMarkers)
|
|
warpMarker->marker()->active(active);
|
|
}
|
|
|
|
uint TeWarp::addQuadToPickMesh(TePickMesh &pickmesh, uint trinum,
|
|
TeWarpBloc::CubeFace face, const TeVector2s32 &size, uint xscale, uint yscale) {
|
|
TeVector3f32 pt1;
|
|
TeVector3f32 pt2;
|
|
TeVector3f32 pt3;
|
|
TeVector3f32 pt4;
|
|
|
|
float x1 = size._x * (1000.0f / xscale) - 500.0f;
|
|
float x2 = 1000.0f / xscale + x1;
|
|
float y1 = size._y * (1000.0f / yscale) - 500.0f;
|
|
float y2 = 1000.0f / yscale + y1;
|
|
|
|
switch (face) {
|
|
case TeWarpBloc::Face0:
|
|
pt1 = TeVector3f32(-x1, 500, -y1);
|
|
pt2 = TeVector3f32(-x2, 500, -y1);
|
|
pt3 = TeVector3f32(-x2, 500, -y2);
|
|
pt4 = TeVector3f32(-x1, 500, -y2);
|
|
break;
|
|
case TeWarpBloc::Face1:
|
|
pt1 = TeVector3f32(-x1, -500, y1);
|
|
pt2 = TeVector3f32(-x2, -500, y1);
|
|
pt3 = TeVector3f32(-x2, -500, y2);
|
|
pt4 = TeVector3f32(-x1, -500, y2);
|
|
break;
|
|
case TeWarpBloc::Face2:
|
|
pt1 = TeVector3f32(-x1, y1, 500);
|
|
pt2 = TeVector3f32(-x2, y1, 500);
|
|
pt3 = TeVector3f32(-x2, y2, 500);
|
|
pt4 = TeVector3f32(-x1, y2, 500);
|
|
break;
|
|
case TeWarpBloc::Face3:
|
|
pt1 = TeVector3f32(x1, y1, -500);
|
|
pt2 = TeVector3f32(x2, y1, -500);
|
|
pt3 = TeVector3f32(x2, y2, -500);
|
|
pt4 = TeVector3f32(x1, y2, -500);
|
|
break;
|
|
case TeWarpBloc::Face4:
|
|
pt1 = TeVector3f32(500, y1, x1);
|
|
pt2 = TeVector3f32(500, y1, x2);
|
|
pt3 = TeVector3f32(500, y2, x2);
|
|
pt4 = TeVector3f32(500, y2, x1);
|
|
break;
|
|
case TeWarpBloc::Face5:
|
|
pt1 = TeVector3f32(-500, y1, -x1);
|
|
pt2 = TeVector3f32(-500, y1, -x2);
|
|
pt3 = TeVector3f32(-500, y2, -x2);
|
|
pt4 = TeVector3f32(-500, y2, -x1);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
pickmesh.setTriangle(trinum, pt1, pt2, pt4);
|
|
pickmesh.setTriangle(trinum + 1, pt2, pt3, pt4);
|
|
return trinum + 1;
|
|
}
|
|
|
|
|
|
TeMarker *TeWarp::allocMarker(unsigned long *nMarkers) {
|
|
TeMarker *newMarker = new TeMarker();
|
|
TeWarpMarker *newWarpMarker = new TeWarpMarker();
|
|
newWarpMarker->marker(newMarker);
|
|
newWarpMarker->markerButtonSignal().add(this, &TeWarp::onMarkerValidated);
|
|
*nMarkers = _warpMarkers.size();
|
|
_warpMarkers.push_back(newWarpMarker);
|
|
return newMarker;
|
|
}
|
|
|
|
void TeWarp::checkObjectEvents() {
|
|
const Common::Point lastMouse = g_engine->getInputMgr()->lastMousePos();
|
|
Math::Ray mouseRay = _camera.getRay(lastMouse);
|
|
for (auto &animData : _loadedAnimData) {
|
|
if (_clickedAnimData == &animData) {
|
|
TePickMesh &pickMesh = animData._frameDatas[animData._curFrameNo]._pickMesh;
|
|
TeVector3f32 intersectPt;
|
|
float intersectLen;
|
|
if (pickMesh.enabled() && pickMesh.intersect(mouseRay, intersectPt, intersectLen)) {
|
|
_markerValidatedSignal.call(pickMesh.name());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
TePickMesh *mesh = TeRayIntersection::getMesh(mouseRay, _pickMeshes2, FLT_MAX, 0, nullptr);
|
|
if (mesh && mesh == _clickedPickMesh)
|
|
_markerValidatedSignal.call(mesh->name());
|
|
_clickedAnimData = nullptr;
|
|
_clickedPickMesh = nullptr;
|
|
}
|
|
|
|
void TeWarp::clear() {
|
|
_putAnimData.clear();
|
|
|
|
for (auto &data : _loadedAnimData)
|
|
data._enabled = false;
|
|
|
|
for (auto *marker : _warpMarkers)
|
|
marker->marker()->visible(false);
|
|
}
|
|
|
|
void TeWarp::configMarker(const Common::String &objname, int markerImgNo, long markerId) {
|
|
Exit *exit = findExit(objname, false);
|
|
long foundId = -1;
|
|
if (exit) {
|
|
foundId = exit->_markerId;
|
|
} else {
|
|
AnimData *anim = findAnimation(objname);
|
|
if (!anim || anim->_markerIds.empty()) {
|
|
warning("configMarker: Didn't find marker %s", objname.c_str());
|
|
return;
|
|
}
|
|
foundId = anim->_markerIds[0];
|
|
}
|
|
assert(foundId >= 0 && foundId < (long)_warpMarkers.size());
|
|
|
|
TeWarpMarker *warpMarker = _warpMarkers[foundId];
|
|
// The game uses TeSprite, but we use the layout system instead.
|
|
TeLayout &frontLayout = g_engine->getApplication()->frontLayout();
|
|
if (markerImgNo == -1) {
|
|
warpMarker->marker()->visible(false);
|
|
frontLayout.removeChild(&warpMarker->marker()->button());
|
|
} else {
|
|
Common::Path markerPath(Common::String::format("2D/Menus/InGame/Marker_%d.png#anim", markerImgNo));
|
|
Common::Path markerPathDown(Common::String::format("2D/Menus/InGame/Marker_%d_over.png", markerImgNo));
|
|
if (!exit)
|
|
warpMarker->setName(objname);
|
|
else
|
|
warpMarker->setName(Common::String("3D\\") + objname);
|
|
|
|
warpMarker->marker()->button().load(markerPath, markerPathDown, "");
|
|
TeSpriteLayout *btnUp = dynamic_cast<TeSpriteLayout*>(warpMarker->marker()->button().upLayout());
|
|
if (!btnUp)
|
|
error("Loading button image %s failed", markerPath.toString(Common::Path::kNativeSeparator).c_str());
|
|
//warning("TeWarp::configMarker: set anim values and something else here?");
|
|
btnUp->_tiledSurfacePtr->_frameAnim.setLoopCount(-1);
|
|
btnUp->play();
|
|
warpMarker->marker()->visible(true);
|
|
// Ensure markers appear below menus and videos.
|
|
frontLayout.removeChild(&warpMarker->marker()->button());
|
|
frontLayout.addChildBefore(&warpMarker->marker()->button(), frontLayout.child(0));
|
|
}
|
|
}
|
|
|
|
TeWarp::AnimData *TeWarp::findAnimation(const Common::String &objname) {
|
|
for (auto &anim : _loadedAnimData) {
|
|
if (anim._name == objname)
|
|
return &anim;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
TeWarp::Exit *TeWarp::findExit(const Common::String &objname, bool flag) {
|
|
Common::String fullName;
|
|
if (flag)
|
|
fullName = objname;
|
|
else
|
|
fullName = Common::String("3D\\") + objname;
|
|
|
|
for (auto &e : _exitList) {
|
|
if (e._linkedWarpPath.contains(fullName))
|
|
return &e;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool TeWarp::hasObjectOrAnim(const Common::String &objname) const {
|
|
for (const auto &anim : _loadedAnimData) {
|
|
if (anim._name == objname)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TeWarp::init() {
|
|
TeVector3f32 winSize = g_engine->getApplication()->getMainWindow().size();
|
|
_camera.setProjMatrixType(1);
|
|
_camera.viewport(0, 0, (int)winSize.x(), (int)winSize.y());
|
|
_camera.setOrthoPlanes(1, 4096);
|
|
_camera.setAspectRatio(winSize.x() / winSize.y());
|
|
// update proj matrix
|
|
_camera.projectionMatrix();
|
|
warning("TODO: Finish TeWarp::init?");
|
|
}
|
|
|
|
void TeWarp::load(const Common::Path &path, bool flag) {
|
|
if (_warpPath == path && _loaded)
|
|
return;
|
|
_warpPath = path;
|
|
|
|
if (path.empty())
|
|
error("Empty TeWarp path!");
|
|
|
|
TeCore *core = g_engine->getCore();
|
|
TetraedgeFSNode node = core->findFile(_warpPath);
|
|
if (!node.isReadable()) {
|
|
error("Couldn't find TeWarp path data '%s'", _warpPath.toString(Common::Path::kNativeSeparator).c_str());
|
|
}
|
|
|
|
if (_preloaded)
|
|
error("TODO: Support preloading in TeWarp::load");
|
|
_file.reset(node.createReadStream());
|
|
char header[7];
|
|
header[6] = '\0';
|
|
_file->read(header, 6);
|
|
if (Common::String(header) != "TeWarp")
|
|
error("Invalid header in warp data %s", _warpPath.toString().c_str());
|
|
uint32 globalTexDataOffset = _file->readUint32LE();
|
|
_texEncodingType = _file->readPascalString();
|
|
_xCount = _file->readUint32LE();
|
|
_yCount = _file->readUint32LE();
|
|
uint32 numAnims = _file->readUint32LE();
|
|
_someXVal = _file->readUint32LE();
|
|
_someYVal = _file->readUint32LE();
|
|
_someMeshX = _file->readUint32LE();
|
|
_someMeshY = _file->readUint32LE();
|
|
if (_xCount > 1000 || _yCount > 1000 || numAnims > 1000)
|
|
error("Improbable values in TeWarp data xCount %d yCount %d numAnims %d", _xCount, _yCount, numAnims);
|
|
_warpBlocs.resize(_xCount * _yCount * 6);
|
|
for (uint i = 0; i < _xCount * _yCount * 6; i++) {
|
|
TeWarpBloc::CubeFace face = static_cast<TeWarpBloc::CubeFace>(_file->readByte());
|
|
// TODO: This is strange, surely we only need to set the offset and create the bloc
|
|
// once but the code seems to do it xCount * yCount times..
|
|
for (uint j = 0; j < _xCount * _yCount; j++) {
|
|
uint xoff = _file->readUint16LE();
|
|
uint yoff = _file->readUint16LE();
|
|
if (xoff > 1000 || yoff > 1000)
|
|
error("TeWarp::load: Improbable offsets %d, %d", xoff, yoff);
|
|
uint32 blocTexOffset = _file->readUint32LE();
|
|
_warpBlocs[i].setTextureFileOffset(globalTexDataOffset + blocTexOffset);
|
|
_warpBlocs[i].create(face, _xCount, _yCount, TeVector2s32(xoff, yoff));
|
|
}
|
|
}
|
|
_loadedAnimData.resize(numAnims);
|
|
_putAnimData.reserve(numAnims);
|
|
for (uint i = 0; i < numAnims; i++) {
|
|
char aname[5];
|
|
_file->read(aname, 4);
|
|
aname[4] = '\0';
|
|
_loadedAnimData[i]._name = aname;
|
|
uint numFrames = _file->readUint32LE();
|
|
if (numFrames > 1000)
|
|
error("TeWarp::load: Improbable frame count %d", numFrames);
|
|
byte numSomething = _file->readByte();
|
|
_loadedAnimData[i]._frameDatas.resize(numFrames);
|
|
for (uint j = 0; j < numFrames; j++) {
|
|
FrameData &frameData = _loadedAnimData[i]._frameDatas[j];
|
|
frameData._loadedTexCount = 0;
|
|
Common::Array<TeWarpBloc> warpBlocs;
|
|
for (uint k = 0; k < numSomething; k++) {
|
|
uint blocCount = _file->readUint32LE();
|
|
if (blocCount > 1000)
|
|
error("TeWarp::load: Improbable bloc count %d", blocCount);
|
|
if (blocCount) {
|
|
TeWarpBloc::CubeFace face = static_cast<TeWarpBloc::CubeFace>(_file->readByte());
|
|
warpBlocs.resize(blocCount);
|
|
for (auto &warpBloc : warpBlocs) {
|
|
uint xoff = _file->readUint16LE();
|
|
uint yoff = _file->readUint16LE();
|
|
if (xoff > 10000 || yoff > 10000)
|
|
error("TeWarp::load: Improbable offsets %d, %d", xoff, yoff);
|
|
uint32 texDataOff = _file->readUint32LE();
|
|
warpBloc.setTextureFileOffset(globalTexDataOffset + texDataOff);
|
|
warpBloc.create(face, _someXVal, _someYVal, TeVector2s32(xoff, yoff));
|
|
if (flag)
|
|
warpBloc.color(TeColor(255, 0, 0, 255));
|
|
}
|
|
uint meshSize = _file->readUint32LE();
|
|
if (meshSize > 1000)
|
|
error("TeWarp::load: Improbable meshSize %d", meshSize);
|
|
TePickMesh tmpMesh;
|
|
tmpMesh.setName(aname);
|
|
tmpMesh.nbTriangles(meshSize * 2);
|
|
for (uint m = 0; m < meshSize; m++) {
|
|
uint xoff = _file->readUint16LE();
|
|
uint yoff = _file->readUint16LE();
|
|
if (xoff > 10000 || yoff > 10000)
|
|
error("TeWarp::load: Improbable offsets %d, %d", xoff, yoff);
|
|
addQuadToPickMesh(tmpMesh, m * 2, face, TeVector2s32(xoff, yoff), _someMeshX, _someMeshY);
|
|
}
|
|
tmpMesh.setEnabled(true);
|
|
if (frameData._pickMesh.name().empty()) {
|
|
frameData._pickMesh = tmpMesh;
|
|
} else {
|
|
frameData._pickMesh += tmpMesh;
|
|
}
|
|
}
|
|
}
|
|
frameData._warpBlocs.resize(warpBlocs.size());
|
|
for (uint k = 0; k < frameData._warpBlocs.size(); k++) {
|
|
frameData._warpBlocs[k] = warpBlocs[k];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
_loaded = true;
|
|
}
|
|
|
|
bool TeWarp::onMarkerValidated(const Common::String &name) {
|
|
_markerValidatedSignal.call(name);
|
|
return false;
|
|
}
|
|
|
|
bool TeWarp::onMouseLeftDown(const Common::Point &pt) {
|
|
const Math::Ray mouseRay = _camera.getRay(pt);
|
|
_clickedPickMesh = nullptr;
|
|
_clickedAnimData = nullptr;
|
|
|
|
bool hitAnimData = false;
|
|
const FrameData *frameData = nullptr;
|
|
for (const auto &animData : _loadedAnimData) {
|
|
frameData = &(animData._frameDatas[animData._curFrameNo]);
|
|
TeVector3f32 interesctPt;
|
|
float intersectDist;
|
|
if (frameData->_pickMesh.enabled() && frameData->_pickMesh.intersect(mouseRay, interesctPt, intersectDist)) {
|
|
_clickedAnimData = &animData;
|
|
hitAnimData = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!hitAnimData) {
|
|
_clickedPickMesh = TeRayIntersection::getMesh(mouseRay, _pickMeshes2, FLT_MAX, 0, nullptr);
|
|
if (_clickedPickMesh) {
|
|
const Exit *exit = findExit(_clickedPickMesh->name(), true);
|
|
_warpMarkers[exit->_markerId]->marker()->button().setEnable(false);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const AnimData *data = findAnimation(frameData->_pickMesh.name());
|
|
for (auto &markerId : data->_markerIds) {
|
|
_warpMarkers[markerId]->marker()->button().setEnable(false);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TeWarp::putObject(const Common::String &name, bool enable) {
|
|
bool found = false;
|
|
for (auto &animData : _loadedAnimData) {
|
|
if (animData._name != name || animData._frameDatas.size() != 1
|
|
|| animData._curFrameNo != 0)
|
|
continue;
|
|
bool alreadyAdded = false;
|
|
for (auto putAnim : _putAnimData) {
|
|
if (putAnim == &animData) {
|
|
alreadyAdded = true;
|
|
break;
|
|
}
|
|
}
|
|
animData._enabled = true;
|
|
if (!alreadyAdded)
|
|
_putAnimData.push_back(&animData);
|
|
for (auto &frameData : animData._frameDatas) {
|
|
frameData._pickMesh.setEnabled(enable);
|
|
}
|
|
found = true;
|
|
}
|
|
if (!found)
|
|
warning("putObject: Impossible de trouver l\'objet %s dans le Warp", name.c_str());
|
|
}
|
|
|
|
void TeWarp::update() {
|
|
if (!_visible1 || !_file)
|
|
return;
|
|
//Application *app = g_engine->getApplication();
|
|
_frustum.update(_camera);
|
|
for (auto &bloc : _warpBlocs) {
|
|
bloc.loadTexture(*_file, _texEncodingType);
|
|
}
|
|
|
|
for (auto &anim : _loadedAnimData) {
|
|
if (anim._repCount && anim._frameDatas.size() > 1) {
|
|
uint64 elapsed = anim._timer.getTimeFromStart();
|
|
int frameNow = elapsed * anim._fps / 1000000.0;
|
|
int lastFrame = anim._curFrameNo;
|
|
if (anim._repCount != -1) {
|
|
anim._repCount = anim._repCount - frameNow / (anim._endFrameNo - anim._firstFrameNo);
|
|
if (anim._repCount < 1) {
|
|
anim._repCount = 0;
|
|
frameNow = anim._endFrameNo - 1;
|
|
_animFinishedSignal.call(anim._name);
|
|
}
|
|
}
|
|
|
|
anim._curFrameNo = anim._firstFrameNo + ((frameNow - anim._firstFrameNo) % (anim._endFrameNo - anim._firstFrameNo));
|
|
if (anim._curFrameNo != lastFrame) {
|
|
anim._frameDatas[lastFrame].unloadTextures();
|
|
anim._frameDatas[lastFrame]._loadedTexCount = 0;
|
|
}
|
|
}
|
|
anim._frameDatas[anim._curFrameNo].loadTextures(_frustum, *_file, _texEncodingType);
|
|
}
|
|
}
|
|
|
|
void TeWarp::sendExit(TeWarp::Exit &exit) {
|
|
_paths.push_back(exit._linkedWarpPath);
|
|
TePickMesh *mesh = new TePickMesh();
|
|
mesh->setName(exit._linkedWarpPath);
|
|
mesh->nbTriangles(exit._warpBlockList.size() * 2);
|
|
uint trinum = 0;
|
|
for (const auto &block : exit._warpBlockList) {
|
|
addQuadToPickMesh(*mesh, trinum, block._face, block._offset, block._x, block._y);
|
|
trinum += 2;
|
|
}
|
|
exit._warpBlockList.clear();
|
|
TeMarker *marker = _warpMarkers[exit._markerId]->marker();
|
|
assert(marker);
|
|
marker->button().load("2D/Menus/InGame/Marker_0.png#anim", "2D/Menus/InGame/Marker_0_over.png", "");
|
|
marker->visible(false);
|
|
marker->setZLoc(200.0f);
|
|
_exitList.push_back(exit);
|
|
}
|
|
|
|
void TeWarp::sendMarker(const Common::String &name, unsigned long markerId) {
|
|
AnimData *anim = findAnimation(name);
|
|
if (anim)
|
|
anim->_markerIds.push_back(markerId);
|
|
}
|
|
|
|
void TeWarp::startAnimationPart(const Common::String &name, int x, int startFrame, int endFrame, bool flag) {
|
|
bool started = false;
|
|
for (auto &animData : _loadedAnimData) {
|
|
if (animData._name != name)
|
|
continue;
|
|
animData._enabled = true;
|
|
bool alreadyPut = false;
|
|
for (auto *putAnim : _putAnimData) {
|
|
if (putAnim == &animData)
|
|
alreadyPut = true;
|
|
}
|
|
if (!alreadyPut)
|
|
_putAnimData.push_back(&animData);
|
|
|
|
animData._repCount = x;
|
|
animData._timer.stop();
|
|
animData._firstFrameNo = startFrame;
|
|
if (endFrame < 0)
|
|
endFrame += animData._frameDatas.size();
|
|
animData._endFrameNo = endFrame;
|
|
for (auto &frameData : animData._frameDatas) {
|
|
// TODO: Is this setting the right thing?
|
|
frameData._pickMesh.setEnabled(flag);
|
|
}
|
|
|
|
animData._timer.start();
|
|
started = true;
|
|
}
|
|
if (!started)
|
|
warning("startAnimationPartImpossible de trouver l\'animation %s dans le Warp.", name.c_str());
|
|
}
|
|
|
|
void TeWarp::setColor(const TeColor &col) {
|
|
Te3DObject2::setColor(col);
|
|
for (auto &warpMarker : _warpMarkers) {
|
|
warpMarker->marker()->button().setColor(col);
|
|
}
|
|
}
|
|
|
|
void TeWarp::setMouseLeftUpForMakers() {
|
|
for (auto &warpMarker : _warpMarkers) {
|
|
warpMarker->marker()->button().setEnable(true);
|
|
}
|
|
}
|
|
|
|
void TeWarp::setVisible(bool v1, bool v2) {
|
|
if (_visible1 == v1)
|
|
return;
|
|
|
|
_visible1 = v1;
|
|
TeInputMgr *inputMgr = g_engine->getInputMgr();
|
|
if (v1) {
|
|
inputMgr->_mouseLDownSignal.add(this, &TeWarp::onMouseLeftDown);
|
|
} else {
|
|
if (v2) {
|
|
for (auto *marker : _warpMarkers) {
|
|
TeMarker *m = marker->marker();
|
|
delete marker;
|
|
// May be still handling the button click
|
|
if (m)
|
|
m->deleteLater();
|
|
}
|
|
_warpMarkers.clear();
|
|
}
|
|
inputMgr->_mouseLDownSignal.remove(this, &TeWarp::onMouseLeftDown);
|
|
}
|
|
}
|
|
|
|
void TeWarp::render() {
|
|
if (!_visible1 || _scale.x() == 0.0f || _scale.y() == 0.0f ||
|
|
_scale.z() == 0.0f || !worldVisible() || color().a() == 0)
|
|
return;
|
|
|
|
TeRenderer *renderer = g_engine->getRenderer();
|
|
renderer->setMatrixMode(TeRenderer::MM_GL_PROJECTION);
|
|
renderer->pushMatrix();
|
|
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
|
|
renderer->pushMatrix();
|
|
_camera.apply();
|
|
renderer->disableZBuffer();
|
|
renderer->pushMatrix();
|
|
|
|
if (_renderWarpBlocs) {
|
|
for (auto &bloc : _warpBlocs) {
|
|
bloc.render();
|
|
}
|
|
}
|
|
|
|
for (AnimData *animData : _putAnimData) {
|
|
if (!animData->_enabled)
|
|
continue;
|
|
for (FrameData &frameData : animData->_frameDatas) {
|
|
for (TeWarpBloc &b : frameData._warpBlocs) {
|
|
if (_frustum.isTriangleInside(b.vertex(0), b.vertex(1), b.vertex(3))
|
|
|| _frustum.isTriangleInside(b.vertex(1), b.vertex(2), b.vertex(3))) {
|
|
b.render();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto &warpMarker : _warpMarkers) {
|
|
warpMarker->marker()->update(_camera);
|
|
}
|
|
|
|
renderer->setCurrentColor(TeColor(255, 255, 255, 255));
|
|
renderer->popMatrix();
|
|
renderer->enableZBuffer();
|
|
TeCamera::restore();
|
|
renderer->setMatrixMode(TeRenderer::MM_GL_PROJECTION);
|
|
renderer->popMatrix();
|
|
renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
|
|
renderer->popMatrix();
|
|
}
|
|
|
|
void TeWarp::rotateCamera(const TeQuaternion &rot) {
|
|
TeQuaternion normRot = rot;
|
|
normRot.normalize();
|
|
_camera.setRotation(normRot);
|
|
}
|
|
|
|
void TeWarp::setFov(float fov) {
|
|
_camera.setFov(fov);
|
|
// update proj matrix
|
|
_camera.projectionMatrix();
|
|
}
|
|
|
|
void TeWarp::takeObject(const Common::String &name) {
|
|
bool found = false;
|
|
for (auto &animData : _loadedAnimData) {
|
|
if (animData._name != name)
|
|
continue;
|
|
animData._curFrameNo = 0;
|
|
animData._enabled = false;
|
|
for (uint i = 0; i < _putAnimData.size(); i++) {
|
|
if (_putAnimData[i] == &animData) {
|
|
_putAnimData.remove_at(i);
|
|
break;
|
|
}
|
|
}
|
|
for (auto &frame : animData._frameDatas) {
|
|
frame._pickMesh.setEnabled(false);
|
|
}
|
|
found = true;
|
|
}
|
|
if (!found)
|
|
warning("takeObject: Impossible de trouver l\'objet %s dans le Warp", name.c_str());
|
|
}
|
|
|
|
void TeWarp::unload() {
|
|
// Not done in original but can happen if user clicks really fast.
|
|
g_engine->getInputMgr()->_mouseLDownSignal.remove(this, &TeWarp::onMouseLeftDown);
|
|
unloadTextures();
|
|
_xCount = 0;
|
|
_yCount = 0;
|
|
_loadedAnimData.clear();
|
|
_putAnimData.clear();
|
|
_paths.clear();
|
|
_pickMeshes2.clear();
|
|
_exitList.clear();
|
|
for (auto *marker : _warpMarkers) {
|
|
TeMarker *m = marker->marker();
|
|
delete marker;
|
|
// May be still handling the button click
|
|
if (m)
|
|
m->deleteLater();
|
|
}
|
|
_warpMarkers.clear();
|
|
_preloaded = false;
|
|
_loaded = false;
|
|
}
|
|
|
|
void TeWarp::unloadTextures() {
|
|
for (auto &bloc : _warpBlocs) {
|
|
bloc.unloadTexture();
|
|
}
|
|
|
|
for (auto &animData : _loadedAnimData) {
|
|
for (auto &frameData : animData._frameDatas) {
|
|
for (auto &warpBloc : frameData._warpBlocs) {
|
|
warpBloc.unloadTexture();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TeWarp::updateCamera(const TeVector3f32 &screen) {
|
|
_camera.viewport(0, 0, screen.x(), screen.y());
|
|
_camera.setOrthoPlanes(1, 4096);
|
|
_camera.setAspectRatio(screen.x() / screen.y());
|
|
// update proj matrix
|
|
_camera.projectionMatrix();
|
|
}
|
|
|
|
void TeWarp::FrameData::loadTextures(const TeFrustum &frustum, Common::SeekableReadStream &file, const Common::String &fileType) {
|
|
for (auto &b : _warpBlocs) {
|
|
if (!b.isLoaded() && (frustum.isTriangleInside(b.vertex(0), b.vertex(1), b.vertex(3))
|
|
|| frustum.isTriangleInside(b.vertex(1), b.vertex(2), b.vertex(3)))) {
|
|
b.loadTexture(file, fileType);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TeWarp::FrameData::unloadTextures() {
|
|
for (auto &bloc : _warpBlocs)
|
|
bloc.unloadTexture();
|
|
}
|
|
|
|
} // end namespace Tetraedge
|