From faa58ab0981db521b090b5aa6aaf990984f6bb94 Mon Sep 17 00:00:00 2001 From: Matthew Duggan Date: Sat, 22 Apr 2023 17:36:16 +0900 Subject: [PATCH] TETRAEDGE: Implement more Amerzone support features Game now plays intro movie and loads first scene, but scene is not yet drawn. --- engines/tetraedge/game/amerzone_game.cpp | 130 +++++++++- engines/tetraedge/game/amerzone_game.h | 31 ++- engines/tetraedge/game/application.cpp | 2 +- engines/tetraedge/game/application.h | 2 + engines/tetraedge/game/game.cpp | 2 +- engines/tetraedge/game/lua_binds.cpp | 251 ++++++++++++++++++- engines/tetraedge/te/te_core.cpp | 3 +- engines/tetraedge/te/te_mesh.cpp | 9 + engines/tetraedge/te/te_pick_mesh.cpp | 5 +- engines/tetraedge/te/te_pick_mesh.h | 4 +- engines/tetraedge/te/te_ray_intersection.cpp | 104 ++------ engines/tetraedge/te/te_ray_intersection.h | 8 +- engines/tetraedge/te/te_warp.cpp | 210 ++++++++++++++-- engines/tetraedge/te/te_warp.h | 16 +- engines/tetraedge/te/te_warp_bloc.cpp | 110 ++++---- engines/tetraedge/te/te_warp_bloc.h | 10 +- engines/tetraedge/te/te_warp_marker.h | 2 + 17 files changed, 691 insertions(+), 208 deletions(-) diff --git a/engines/tetraedge/game/amerzone_game.cpp b/engines/tetraedge/game/amerzone_game.cpp index 906a8eb2aaf..e8c80951d80 100644 --- a/engines/tetraedge/game/amerzone_game.cpp +++ b/engines/tetraedge/game/amerzone_game.cpp @@ -104,7 +104,7 @@ bool AmerzoneGame::changeWarp(const Common::String &zone, const Common::String & dotpos = sceneXml.rfind('.'); Common::String sceneLua = sceneXml.substr(0, dotpos); - sceneLua += ".xml"; + sceneLua += ".lua"; _luaScript.load(core->findFile(sceneLua)); _luaScript.execute(); _luaScript.execute("OnWarpEnter"); @@ -117,7 +117,12 @@ bool AmerzoneGame::changeWarp(const Common::String &zone, const Common::String & } void AmerzoneGame::draw() { - error("TODO: Implement AmerzoneGame::draw"); + if (!_running) + return; + if (_warpX) + _warpX->render(); + if (_warpY) + _warpY->render(); } void AmerzoneGame::enter() { @@ -164,12 +169,14 @@ void AmerzoneGame::enter() { _warpX = new TeWarp(); _warpX->setRotation(app->frontOrientationLayout().rotation()); _warpX->init(); + // TODO: Set FOV here? _warpX->setVisible(true, false); _luaContext.create(); _luaScript.attachToContext(&_luaContext); - warning("TODO: Finish AmerzoneGame::enter"); + // Game also sets up fade sprites, which is set up in Game. + _running = true; _playedTimer.start(); _edgeButtonRolloverCount = 0; @@ -196,8 +203,64 @@ void AmerzoneGame::initLoadedBackupData() { changeWarp(app->firstWarpPath(), app->firstScene(), true); } +void AmerzoneGame::isInDrag(bool inDrag) { + const Common::Point mousePt = g_engine->getInputMgr()->lastMousePos(); + if (inDrag != _isInDrag) { + _isInDrag = inDrag; + if (inDrag) { + // Start drag operation + _mouseDragStart = mousePt; + _mouseDragLast = mousePt; + _decelAnimX.stop(); + _decelAnimY.stop(); + _dragTimer.stop(); + _dragTimer.start(); + } else { + // Finish drag operation + _dragTimer.timeElapsed(); + Application *app = g_engine->getApplication(); + TeVector3f32 mouseDir(mousePt.x - _mouseDragLast.x, mousePt.y - _mouseDragLast.y, 0); + if (app->inverseLook()) + mouseDir = mouseDir * -1.0f; + const TeMatrix4x4 layoutRot = app->frontOrientationLayout().rotation().toTeMatrix(); + TeVector3f32 dest = layoutRot * mouseDir; + dest.x() /= 2; + dest.y() /= 2; + _speedX = CLIP(dest.x(), -10000.0f, 10000.0f); + _speedY = CLIP(dest.y(), -10000.0f, 10000.0f); + startDecelerationAnim(); + } + } +} + void AmerzoneGame::leave(bool flag) { - error("TODO: Implement AmerzoneGame::leave"); + _inGameGui.unload(); + _question2.unload(); + Application *app = g_engine->getApplication(); + app->frontOrientationLayout().removeChild(&_dialog2); + _dialog2.unload(); + if (_warpX) { + delete _warpX; + _warpX = nullptr; + } + if (_warpY) { + saveBackup("save.xml"); + } + app->frontOrientationLayout().removeChild(&_inventoryMenu); + _inventoryMenu.unload(); + + // TODO: game does this.. doesn't this leak? + _warpY = nullptr; + _prevWarpY = nullptr; + + // TODO: Game goes through a list of (cached?) warps here to clean up. + warning("TODO: Finish AmerzoneGame::leave"); + + _notifier.unload(); + _luaContext.destroy(); + _running = false; + _playedTimer.stop(); + _music.stop(); } bool AmerzoneGame::onChangeWarpAnimFinished() { @@ -231,19 +294,30 @@ bool AmerzoneGame::onAnimationFinished(const Common::String &anim) { } bool AmerzoneGame::onMouseLeftUp(const Common::Point &pt) { - error("TODO: Implement AmerzoneGame::onMouseLeftUp"); + _warpY->setMouseLeftUpForMakers(); + TeVector3f32 offset = TeVector3f32(pt - _mouseDragStart); + if (offset.length() > 20.0f) + _warpY->checkObjectEvents(); + isInDrag(false); + return false; } bool AmerzoneGame::onMouseLeftDown(const Common::Point &pt) { - error("TODO: Implement AmerzoneGame::onMouseLeftDown"); + isInDrag(true); + return false; } bool AmerzoneGame::onObjectClick(const Common::String &obj) { error("TODO: Implement AmerzoneGame::onObjectClick"); } +bool AmerzoneGame::onPuzzleEnterAnimLoadTime() { + error("TODO: Implement AmerzoneGame::onPuzzleEnterAnimLoadTime"); +} + void AmerzoneGame::optimizeWarpResources() { - error("TODO: Implement AmerzoneGame::optimizeWarpResources"); + // Note: original calls this OptimizeWarpRessources + warning("TODO: Implement AmerzoneGame::optimizeWarpResources"); } void AmerzoneGame::setAngleX(float angle) { @@ -284,11 +358,19 @@ void AmerzoneGame::setAngleY(float angle) { _orientationY = 45.0f; } -void AmerzoneGame::speedX(float speed) { +void AmerzoneGame::showPuzzle(int puzzleNo, int puzParam1, int puzParam2) { + _puzzleNo = puzzleNo; + _puzParam1 = puzParam1; + _puzParam2 = puzParam2; + onPuzzleEnterAnimLoadTime(); +} + + +void AmerzoneGame::speedX(const float &speed) { _speedX = CLIP(speed, -10000.0f, 10000.0f); } -void AmerzoneGame::speedY(float speed) { +void AmerzoneGame::speedY(const float &speed) { _speedY = CLIP(speed, -10000.0f, 10000.0f); } @@ -313,6 +395,36 @@ void AmerzoneGame::startChangeWarpAnim() { } } +void AmerzoneGame::startDecelerationAnim() { + _decelAnimX.stop(); + _decelAnimY.stop(); + + Common::Array curve; + curve.push_back(0); + curve.push_back(0.35f); + curve.push_back(0.68f); + curve.push_back(0.85f); + curve.push_back(0.93f); + curve.push_back(0.97f); + curve.push_back(1); + + _decelAnimX.setCurve(curve); + _decelAnimX._duration = 400; + _decelAnimX._startVal = _speedX; + _decelAnimX._endVal = 0; + _decelAnimX._callbackObj = this; + _decelAnimX._callbackMethod = &AmerzoneGame::speedX; + _decelAnimX.play(); + + _decelAnimY.setCurve(curve); + _decelAnimY._duration = 400; + _decelAnimY._startVal = _speedY; + _decelAnimY._endVal = 0; + _decelAnimY._callbackObj = this; + _decelAnimY._callbackMethod = &AmerzoneGame::speedY; + _decelAnimY.play(); +} + void AmerzoneGame::update() { TeInputMgr *inputMgr = g_engine->getInputMgr(); diff --git a/engines/tetraedge/game/amerzone_game.h b/engines/tetraedge/game/amerzone_game.h index 291e61ae40a..71bae1c9c13 100644 --- a/engines/tetraedge/game/amerzone_game.h +++ b/engines/tetraedge/game/amerzone_game.h @@ -33,7 +33,6 @@ namespace Tetraedge { class AmerzoneGame : public Tetraedge::Game { public: AmerzoneGame(); - ~AmerzoneGame() {} virtual void addToBag(const Common::String &objname) override; @@ -47,21 +46,29 @@ public: virtual bool onDialogFinished(const Common::String &val) override; virtual bool onVideoFinished() override; -private: - void changeSpeedToMouseDirection(); + TeWarp *warpY() { return _warpY; } + const Common::String lastObjectHitName() const { return _lastObjectHitName; } + void setAngleX(float angle); void setAngleY(float angle); - void speedX(float speed); - void speedY(float speed); + void showPuzzle(int puzzleNo, int puzParam1, int puzParam2); + +private: + void changeSpeedToMouseDirection(); + void isInDrag(bool val); + void speedX(const float &speed); + void speedY(const float &speed); bool onHelpButtonValidated(); bool onAnimationFinished(const Common::String &anim); bool onMouseLeftUp(const Common::Point &pt); bool onMouseLeftDown(const Common::Point &pt); bool onObjectClick(const Common::String &obj); + bool onPuzzleEnterAnimLoadTime(); void optimizeWarpResources(); void startChangeWarpAnim(); + void startDecelerationAnim(); bool onChangeWarpAnimFinished(); TeTimer _dragTimer; @@ -75,15 +82,17 @@ private: float _speedY; bool _isInDrag; int _edgeButtonRolloverCount; - TeVector2s32 _mouseDragStart; - TeVector2s32 _mouseDragLast; - /* - TeCurveAnim _decelAnimX; - TeCurveAnim _decelAnimY; - */ + Common::Point _mouseDragStart; + Common::Point _mouseDragLast; + int _puzzleNo; + int _puzParam1; + int _puzParam2; + TeCurveAnim2 _decelAnimX; + TeCurveAnim2 _decelAnimY; TeWarp *_warpX; TeWarp *_warpY; TeWarp *_prevWarpY; + Common::String _lastObjectHitName; }; } // end namespace Tetraedge diff --git a/engines/tetraedge/game/application.cpp b/engines/tetraedge/game/application.cpp index 0ba25825c9f..aa097cc4896 100644 --- a/engines/tetraedge/game/application.cpp +++ b/engines/tetraedge/game/application.cpp @@ -301,7 +301,7 @@ void Application::create() { onMainWindowSizeChanged(); _splashScreens.enter(); - _drawShadows = (!ConfMan.getBool("disable_shadows")); + _drawShadows = !(g_engine->gameIsAmerzone() || ConfMan.getBool("disable_shadows")); // Note: this is not in the original, but seems like a good place to do it.. g_engine->getGame()->loadUnlockedArtwork(); diff --git a/engines/tetraedge/game/application.h b/engines/tetraedge/game/application.h index f24ccd069d0..513def1c88b 100644 --- a/engines/tetraedge/game/application.h +++ b/engines/tetraedge/game/application.h @@ -88,6 +88,7 @@ public: MainMenu &mainMenu() { return _mainMenu; } OptionsMenu &optionsMenu() { return _optionsMenu; } TeMusic &music() { return _music; } + TeMusic &videoMusic() { return _videoMusic; } Credits &credits() { return _credits; } UpsellScreen &upsellScreen() { return _upsellScreen; } TeVisualFade &visualFade() { return _visFade; } @@ -131,6 +132,7 @@ private: TeVisualFade _visFade; TeMusic _music; + TeMusic _videoMusic; // Only used in Amerzone TeSpriteLayout _appSpriteLayout; TeSpriteLayout _mouseCursorLayout; TeSpriteLayout _autoSaveIcon1; diff --git a/engines/tetraedge/game/game.cpp b/engines/tetraedge/game/game.cpp index 576577bd23b..3b7870f4c0e 100644 --- a/engines/tetraedge/game/game.cpp +++ b/engines/tetraedge/game/game.cpp @@ -291,7 +291,7 @@ bool Game::playMovie(const Common::String &vidPath, const Common::String &musicP TeButtonLayout *skipVideoButton = _inGameGui.buttonLayoutChecked("skipVideoButton"); skipVideoButton->setVisible(false); - TeMusic &music = app->music(); + TeMusic &music = (g_engine->gameIsAmerzone() ? app->videoMusic() : app->music()); music.stop(); music.setChannelName("video"); music.repeat(false); diff --git a/engines/tetraedge/game/lua_binds.cpp b/engines/tetraedge/game/lua_binds.cpp index ad5f50507ad..ed01d3ab476 100644 --- a/engines/tetraedge/game/lua_binds.cpp +++ b/engines/tetraedge/game/lua_binds.cpp @@ -28,8 +28,10 @@ #include "tetraedge/game/lua_binds.h" #include "tetraedge/game/object3d.h" #include "tetraedge/game/syberia_game.h" +#include "tetraedge/game/amerzone_game.h" #include "tetraedge/to_lua.h" #include "tetraedge/te/te_core.h" +#include "tetraedge/te/te_sound_manager.h" #include "tetraedge/te/te_lua_thread.h" #include "tetraedge/te/te_particle.h" @@ -203,10 +205,19 @@ static int tolua_ExportedFunctions_Selected00(lua_State *L) { error("#ferror in function 'Selected': %d %d %s", err.index, err.array, err.type); } -static void TakeObject(const Common::String &obj) { +static void TakeObject_Amerzone(const Common::String &obj) { + AmerzoneGame *game = dynamic_cast(g_engine->getGame()); + assert(game); + game->luaContext().setGlobal(game->lastObjectHitName(), true); + game->warpY()->takeObject(game->lastObjectHitName()); + if (!obj.empty()) { + game->addToBag(obj); + g_engine->getSoundManager()->playFreeSound("Sounds/SFX/N_prendre.ogg", 1.0, "sfx"); + } +} + +static void TakeObject_Syberia(const Common::String &obj) { Game *game = g_engine->getGame(); - // TODO: Set global _lastHitObjectName?? How is it used? - //game->luaContext().setGlobal(_lastHitObjectName, true); if (!obj.empty()) game->addToBag(obj); } @@ -215,7 +226,10 @@ static int tolua_ExportedFunctions_TakeObject00(lua_State *L) { tolua_Error err; if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) { Common::String s1(tolua_tostring(L, 1, nullptr)); - TakeObject(s1); + if (g_engine->gameIsAmerzone()) + TakeObject_Amerzone(s1); + else + TakeObject_Syberia(s1); return 0; } error("#ferror in function 'TakeObject': %d %d %s", err.index, err.array, err.type); @@ -428,6 +442,11 @@ static int tolua_ExportedFunctions_ChangeWarp00(lua_State *L) { bool flag = tolua_toboolean(L, 3, false); ChangeWarp(s1, s2, flag); return 0; + } else if (g_engine->gameIsAmerzone() && tolua_isstring(L, 1, 0, &err) && tolua_isboolean(L, 2, 1, &err) && tolua_isnoobj(L, 3, &err)) { + Common::String s1(tolua_tostring(L, 1, nullptr)); + bool flag = tolua_toboolean(L, 2, false); + ChangeWarp(s1, "", flag); + return 0; } error("#ferror in function 'ChangeWarp': %d %d %s", err.index, err.array, err.type); } @@ -2651,7 +2670,7 @@ static int tolua_EnableParticle(lua_State *L) { -void LuaOpenBinds(lua_State *L) { +static void LuaOpenBinds_Syberia(lua_State *L) { tolua_open(L); tolua_module(L, 0, 0); tolua_beginmodule(L, 0); @@ -2827,6 +2846,228 @@ void LuaOpenBinds(lua_State *L) { tolua_endmodule(L); } +// ======== Amerzone-specific bind functions below ======== + +static int tolua_ExportedFunctions_PrintDebugMessage00(lua_State *L) { + tolua_Error err; + if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) { + Common::String s1(tolua_tostring(L, 1, nullptr)); + debug("%s", s1.c_str()); + return 0; + } + error("#ferror in function 'PrintDebugMessage': %d %d %s", err.index, err.array, err.type); +} + +static void PutObject(const Common::String &name, bool enable) { + AmerzoneGame *game = dynamic_cast(g_engine->getGame()); + assert(game); + game->warpY()->putObject(name, enable); +} + +static int tolua_ExportedFunctions_PutObject00(lua_State *L) { + tolua_Error err; + if (tolua_isstring(L, 1, 0, &err) && tolua_isboolean(L, 2, 1, &err) + && tolua_isnoobj(L, 3, &err)) { + Common::String s1(tolua_tostring(L, 1, nullptr)); + bool b1 = tolua_toboolean(L, 2, 1); + PutObject(s1, b1); + return 0; + } + error("#ferror in function 'PutObject': %d %d %s", err.index, err.array, err.type); +} + +static void SetAnimationPart(const Common::String &name, int x, int y, int z, bool flag) { + AmerzoneGame *game = dynamic_cast(g_engine->getGame()); + assert(game); + game->warpY()->setAnimationPart(name, x, y, z, flag); +} + +static int tolua_ExportedFunctions_StartAnimationPart00(lua_State *L) { + tolua_Error err; + if (tolua_isstring(L, 1, 0, &err) && tolua_isnumber(L, 2, 0, &err) + && tolua_isnumber(L, 3, 0, &err) && tolua_isnumber(L, 4, 1, &err) + && tolua_isboolean(L, 5, 1, &err) && tolua_isnoobj(L, 6, &err)) { + Common::String s1(tolua_tostring(L, 1, nullptr)); + double d1 = tolua_tonumber(L, 2, 0.0); + double d2 = tolua_tonumber(L, 3, 0.0); + double d3 = tolua_tonumber(L, 4, -1.0); + bool b1 = tolua_tonumber(L, 5, 0); + SetAnimationPart(s1, (int)d1, (int)d2, (int)d3, b1); + return 0; + } + error("#ferror in function 'SetAnimationPart': %d %d %s", err.index, err.array, err.type); +} + +static void RemoveObject_Amerzone(const Common::String &name) { + AmerzoneGame *game = dynamic_cast(g_engine->getGame()); + assert(game); + game->warpY()->takeObject(name); +} + +static int tolua_ExportedFunctions_RemoveObject00_Amerzone(lua_State *L) { + tolua_Error err; + if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) { + Common::String s1(tolua_tostring(L, 1, nullptr)); + RemoveObject_Amerzone(s1); + return 0; + } + error("#ferror in function 'RemoveObject': %d %d %s", err.index, err.array, err.type); +} + +static int tolua_ExportedFunctions_AddToBag00(lua_State *L) { + tolua_Error err; + if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) { + Common::String s1(tolua_tostring(L, 1, nullptr)); + debug("%s", s1.c_str()); + return 0; + } + error("#ferror in function 'PrintDebugMessage': %d %d %s", err.index, err.array, err.type); +} + +void SaveGame(const Common::String &name) { + g_engine->getGame()->saveBackup(name); +} + +static int tolua_ExportedFunctions_SaveGame00(lua_State *L) { + tolua_Error err; + if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) { + Common::String s1(tolua_tostring(L, 1, nullptr)); + SaveGame(s1); + return 0; + } + error("#ferror in function 'SaveGame': %d %d %s", err.index, err.array, err.type); +} + +static void SetMarker(const Common::String &name, int imgNo, long markerId) { + AmerzoneGame *game = dynamic_cast(g_engine->getGame()); + assert(game); + game->warpY()->configMarker(name, imgNo, markerId); +} + +static int tolua_ExportedFunctions_SetMarker00(lua_State *L) { + tolua_Error err; + if (tolua_isstring(L, 1, 0, &err) && tolua_isnumber(L, 2, 0, &err) + && tolua_isnumber(L, 3, 0, &err) && tolua_isnoobj(L, 4, &err)) { + Common::String s1(tolua_tostring(L, 1, nullptr)); + double d1 = tolua_tonumber(L, 2, 0.0); + double d2 = tolua_tonumber(L, 3, 0.0); + SetMarker(s1, (int)d1, (long)d2); + return 0; + } + error("#ferror in function 'SetMarker': %d %d %s", err.index, err.array, err.type); +} + +static void LookAt(int x, int y) { + AmerzoneGame *game = dynamic_cast(g_engine->getGame()); + assert(game); + game->setAngleX(-x); + int yval = y + -360; + if (y < 90) + yval = y; + game->setAngleY(-yval); +} + +static int tolua_ExportedFunctions_LookAt00(lua_State *L) { + tolua_Error err; + if (tolua_isnumber(L, 1, 0, &err) && tolua_isnumber(L, 2, 0, &err) + && tolua_isnoobj(L, 3, &err)) { + double d1 = tolua_tonumber(L, 1, 0.0); + double d2 = tolua_tonumber(L, 2, 0.0); + LookAt((int)d1, (int)d2); + return 0; + } + error("#ferror in function 'LookAt': %d %d %s", err.index, err.array, err.type); +} + +static void ShowPuzzle(int x, int y = 0, int z = 0) { + AmerzoneGame *game = dynamic_cast(g_engine->getGame()); + assert(game); + game->showPuzzle(x, y, z); +} + +static int tolua_ExportedFunctions_ShowPuzzle00(lua_State *L) { + tolua_Error err; + if (tolua_isnumber(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) { + double d1 = tolua_tonumber(L, 1, 0.0); + ShowPuzzle((int)d1); + return 0; + } + error("#ferror in function 'ShowPuzzle': %d %d %s", err.index, err.array, err.type); +} + +static int tolua_ExportedFunctions_ShowPuzzle01(lua_State *L) { + tolua_Error err; + if (tolua_isnumber(L, 1, 0, &err) && tolua_isnumber(L, 2, 0, &err) + && tolua_isnumber(L, 3, 0, &err) && tolua_isnoobj(L, 4, &err)) { + double d1 = tolua_tonumber(L, 1, 0.0); + double d2 = tolua_tonumber(L, 2, 0.0); + double d3 = tolua_tonumber(L, 3, 0.0); + ShowPuzzle((int)d1, (int)d2, (int)d3); + return 0; + } + return tolua_ExportedFunctions_ShowPuzzle00(L); +} + + +static void LuaOpenBinds_Amerzone(lua_State *L) { + tolua_open(L); + tolua_module(L, 0, 0); + tolua_beginmodule(L, 0); + + tolua_function(L, "Selected", tolua_ExportedFunctions_Selected00); + //tolua_function(L, "TestObjectLimit", tolua_ExportedFunctions_TestObjectLimit00); // unused + tolua_function(L, "PrintDebugMessage", tolua_ExportedFunctions_PrintDebugMessage00); + //tolua_function(L, "SetCondition", tolua_ExportedFunctions_SetCondition00); // unused + //tolua_function(L, "UnsetCondition", tolua_ExportedFunctions_UnsetCondition00); // unused + tolua_function(L, "TakeObject", tolua_ExportedFunctions_TakeObject00); + tolua_function(L, "PutObject", tolua_ExportedFunctions_PutObject00); + // This is not the same as RemoveObject from Syberia. + tolua_function(L, "RemoveObject", tolua_ExportedFunctions_RemoveObject00_Amerzone); + tolua_function(L, "StartAnimationPart", tolua_ExportedFunctions_StartAnimationPart00); + //tolua_function(L, "StartAnimation", tolua_ExportedFunctions_StartAnimation00); // unused + //tolua_function(L, "AnimationSetToEnd", tolua_ExportedFunctions_AnimationSetToEnd00); // unused + //tolua_function(L, "AnimationSetToStart", tolua_ExportedFunctions_AnimationSetToStart00); // unused + //tolua_function(L, "DrawText", tolua_ExportedFunctions_DrawText00); // unused + tolua_function(L, "ChangeWarp", tolua_ExportedFunctions_ChangeWarp00); + tolua_function(L, "AddToBag", tolua_ExportedFunctions_AddToBag00); + // Note: same as RemoveObject in Syberia + tolua_function(L, "RemoveFromBag", tolua_ExportedFunctions_RemoveObject00); + tolua_function(L, "RemoveFromBag", tolua_ExportedFunctions_RemoveObject01); + tolua_function(L, "SaveGame", tolua_ExportedFunctions_SaveGame00); + tolua_function(L, "SetMarker", tolua_ExportedFunctions_SetMarker00); + tolua_function(L, "LookAt", tolua_ExportedFunctions_LookAt00); + //tolua_function(L, "Wait", tolua_ExportedFunctions_Wait00); // unused + tolua_function(L, "PlaySound", tolua_ExportedFunctions_PlaySound00); + tolua_function(L, "StopSound", tolua_ExportedFunctions_StopSound00); + tolua_function(L, "PlayMusic", tolua_ExportedFunctions_PlayMusic00); + tolua_function(L, "ShowPuzzle", tolua_ExportedFunctions_ShowPuzzle00); + tolua_function(L, "ShowPuzzle", tolua_ExportedFunctions_ShowPuzzle01); + tolua_function(L, "PlayMovie", tolua_ExportedFunctions_PlayMovie00); + //tolua_function(L, "SetFOV", tolua_ExportedFunctions_SetFOV00); // unused + //tolua_function(L, "LoadSprite", tolua_ExportedFunctions_LoadSprite00); // unused + //tolua_function(L, "UnloadSprite", tolua_ExportedFunctions_UnloadSprite00); // unused + //tolua_function(L, "PushAnswer", tolua_ExportedFunctions_PushAnswer00); // unused + tolua_function(L, "FinishGame", tolua_ExportedFunctions_FinishGame00); + tolua_function(L, "ShowDocument", tolua_ExportedFunctions_ShowDocument00); + tolua_function(L, "HideDocument", tolua_ExportedFunctions_HideDocument00); + tolua_function(L, "AddDocument", tolua_ExportedFunctions_AddDocument00); + //tolua_function(L, "ClearImportantDocuments", tolua_ExportedFunctions_ClearImportantDocuments00); // unused + //tolua_function(L, "SetImportantDocument", tolua_ExportedFunctions_SetImportantDocument00); // unused + tolua_function(L, "TestFileFlagSystemFlag", tolua_ExportedFunctions_TestFileFlagSystemFlag00); + //tolua_function(L, "SetViewAngleXLimits", tolua_ExportedFunctions_SetViewAngleXLimits00); // unused + //tolua_function(L, "SetViewAngleYLimits", tolua_ExportedFunctions_SetViewAngleYLimits00); // unused + + tolua_endmodule(L); +} + +void LuaOpenBinds(lua_State *L) { + if (g_engine->gameIsAmerzone()) + LuaOpenBinds_Amerzone(L); + else + LuaOpenBinds_Syberia(L); +} + + } } // end namespace Tetraedge diff --git a/engines/tetraedge/te/te_core.cpp b/engines/tetraedge/te/te_core.cpp index 8e5f11a9d4e..430136e7b59 100644 --- a/engines/tetraedge/te/te_core.cpp +++ b/engines/tetraedge/te/te_core.cpp @@ -192,7 +192,8 @@ Common::FSNode TeCore::findFile(const Common::Path &path) const { "iPhone-iPad/DefaultDistributor", // iOS Syb 1 paid "Android-iPhone-iPad/iPhone-iPad", // iOS Syb 2 "PC-MacOSX-Android-iPhone-iPad", // iOS Syb 2 - "Full/HD" // Amerzone + "Full/HD", // Amerzone + "Part1-Full/PC-MacOSX/DefaultDistributor" // Amerzone }; const Common::Path langs[] = { diff --git a/engines/tetraedge/te/te_mesh.cpp b/engines/tetraedge/te/te_mesh.cpp index 0a23828d5b6..14e1c4fadee 100644 --- a/engines/tetraedge/te/te_mesh.cpp +++ b/engines/tetraedge/te/te_mesh.cpp @@ -42,6 +42,15 @@ void TeMesh::defaultMaterial(const TeIntrusivePtr &texture) { _materials[0] = TeMaterial(texture, mode); } +TeMaterial *TeMesh::material(uint index) { + assert(!_materials.empty()); + if (index < _materials.size()) { + return &_materials[index]; + } else { + return &_materials[0]; + } +} + const TeMaterial *TeMesh::material(uint index) const { assert(!_materials.empty()); if (index < _materials.size()) { diff --git a/engines/tetraedge/te/te_pick_mesh.cpp b/engines/tetraedge/te/te_pick_mesh.cpp index 696a85c8ac6..df7e31ed1ee 100644 --- a/engines/tetraedge/te/te_pick_mesh.cpp +++ b/engines/tetraedge/te/te_pick_mesh.cpp @@ -66,11 +66,10 @@ void TePickMesh::getTriangle(uint triNum, TeVector3f32 &v1, TeVector3f32 &v2, Te v3 = _verticies[triNum * 3 + 2]; } -bool TePickMesh::intersect(const TeVector3f32 &origin, const TeVector3f32 &dir, TeVector3f32 &ptOut, float &lenOut) { +bool TePickMesh::intersect(const Math::Ray &ray, TeVector3f32 &ptOut, float &lenOut) { if (!_flag || !_nTriangles) return false; float nearest = FLT_MAX; - const Math::Ray ray(origin, dir); for (uint i = 0; i < _nTriangles; i++) { float idist; Math::Vector3d iloc; @@ -80,7 +79,7 @@ bool TePickMesh::intersect(const TeVector3f32 &origin, const TeVector3f32 &dir, } } if (nearest != FLT_MAX) { - ptOut = origin + dir * nearest; + ptOut = ray.getOrigin() + ray.getDirection() * nearest; lenOut = nearest; return true; } diff --git a/engines/tetraedge/te/te_pick_mesh.h b/engines/tetraedge/te/te_pick_mesh.h index 02e99bfbc51..7e8f0c8aab9 100644 --- a/engines/tetraedge/te/te_pick_mesh.h +++ b/engines/tetraedge/te/te_pick_mesh.h @@ -35,7 +35,7 @@ public: // void create(); // unused void destroy(); void getTriangle(uint triNum, TeVector3f32 &v1, TeVector3f32 &v2, TeVector3f32 &v3) const; - bool intersect(const TeVector3f32 &origin, const TeVector3f32 &dir, TeVector3f32 &ptOut, float &lenOut); + bool intersect(const Math::Ray &ray, TeVector3f32 &ptOut, float &lenOut); void nbTriangles(uint nTriangles); TePickMesh &operator+=(const TePickMesh &other); TePickMesh &operator=(const TePickMesh &other); @@ -44,7 +44,9 @@ public: void setName(const Common::String &name) { _name = name; } void setFlag(bool val) { _flag = val; } + bool flag() const { return _flag; } const Common::String &name() const { return _name; } + uint nTriangles() const { return _nTriangles; } private: bool _flag; diff --git a/engines/tetraedge/te/te_ray_intersection.cpp b/engines/tetraedge/te/te_ray_intersection.cpp index fd645bf1c37..aaf3f55a724 100644 --- a/engines/tetraedge/te/te_ray_intersection.cpp +++ b/engines/tetraedge/te/te_ray_intersection.cpp @@ -19,96 +19,44 @@ * */ +#include "math/ray.h" + #include "tetraedge/te/te_ray_intersection.h" +#include "tetraedge/te/te_pick_mesh.h" namespace Tetraedge { namespace TeRayIntersection { -TePickMesh *getMesh(const TeVector3f32 ¶m_1, const TeVector3f32 ¶m_2, const Common::Array &pickMeshes, - float param_4, float param_5, TeVector3f32 *param_6) { - error("TODO: implement TeRayIntersection::getMesh"); -} +// Note: the TeRayIntersection::intersect function is +// replaced by Math::Ray::intersectTriangle -/* -// This is a version from https://www.lighthouse3d.com/tutorials/maths/ray-triangle-intersection/ -int intersect(const TeVector3f32 &p, const TeVector3f32 &d, const TeVector3f32 &v0, - const TeVector3f32 &v1, const TeVector3f32 &v2, TeVector3f32 &hitPt, float &hitDist) { - const TeVector3f32 e1 = v1 - v0; - const TeVector3f32 e2 = v2 - v0; - const TeVector3f32 h = TeVector3f32::crossProduct(d, e2); +TePickMesh *getMesh(const Math::Ray ray, const Common::Array &pickMeshes, + float maxDist, float minDist, TeVector3f32 *ptOut) { + TeVector3f32 bestPt; + TePickMesh *bestMesh = nullptr; - if (h == TeVector3f32()) - return -1; - - float a = e1.dotProduct(h); - if (fabs(a) < 1e-6f) - return 0; - - float f = 1.0f / a; - const TeVector3f32 s = p - v0; - float u = f * s.dotProduct(h); - if (u < 0.0f || u > 1.0f) - return 0; - - const TeVector3f32 q = TeVector3f32::crossProduct(s, e1); - float v = f * d.dotProduct(q); - - if (v < 0.0f || u + v > 1.0f) - return 0; - - float t = f * e2.dotProduct(q); - - if (t < 1e-6f) - return 0; - - hitDist = t; - hitPt = p + t * d; - - return 1; -}*/ - -/* -int intersect(const TeVector3f32 &rayPos, const TeVector3f32 &rayDir, const TeVector3f32 &v1, - const TeVector3f32 &v2, const TeVector3f32 &v3, TeVector3f32 &vout, float &fout) { - const TeVector3f32 v2_v1 = v2 - v1; - const TeVector3f32 v3_v1 = v3 - v1; - const TeVector3f32 v = v2_v1 ^ v3_v1; - - if (v == TeVector3f32(0.0f, 0.0f, 0.0f)) - return -1; - - int result = -1; - float f1 = v.dotProduct(rayPos - v1); - float f2 = v.dotProduct(rayDir); - if (fabs(f2) > 1e-9) { - f2 = -f1 / f2; - fout = f2; - result = 0; - if (f2 >= 0.0) { - vout = rayPos + (rayDir * f2); - float dot1 = v2_v1.dotProduct(v2_v1); - float dot2 = v2_v1.dotProduct(v3_v1); - float dot3 = v3_v1.dotProduct(v3_v1); - const TeVector3f32 vout_v1 = vout - v1; - float dots1 = dot2 * dot2 - dot1 * dot3; - float dot4 = vout_v1.dotProduct(v2_v1); - float dot5 = vout_v1.dotProduct(v3_v1); - float dots2 = (dot2 * dot5 - dot3 * dot4) / dots1; - if (dots2 >= 0.0 && dots2 <= 1.0) { - float dots3 = (dot2 * dot4 - dot1 * dot5) / dots1; - if (dots3 >= 0.0 && dots2 + dots3 <= 1.0) - result = 1; + for (auto *mesh : pickMeshes) { + if (!mesh->flag()) + continue; + for (uint i = 0; i < mesh->nTriangles(); i++) { + TeVector3f32 v1; + TeVector3f32 v2; + TeVector3f32 v3; + mesh->getTriangle(i, v1, v2, v3); + float intersectDist; + TeVector3f32 intersectPt; + if (ray.intersectTriangle(v1, v2, v3, intersectPt, intersectDist) && intersectDist < maxDist && intersectDist >= minDist) { + bestPt = intersectPt; + bestMesh = mesh; } } - } else { - // Sorry about the logic.. this is what the decompiler gave me - // and I'm not brave enough to figure it out. - result = (-(uint)(f1 == -0.0) & 1) * 2; } - return result; + + if (ptOut) + *ptOut = bestPt; + return bestMesh; } -*/ } // end namespace TeRayIntersection diff --git a/engines/tetraedge/te/te_ray_intersection.h b/engines/tetraedge/te/te_ray_intersection.h index fccb6f79a58..cae02d35003 100644 --- a/engines/tetraedge/te/te_ray_intersection.h +++ b/engines/tetraedge/te/te_ray_intersection.h @@ -31,12 +31,8 @@ class TePickMesh; namespace TeRayIntersection { -TePickMesh *getMesh(const TeVector3f32 ¶m_1, const TeVector3f32 ¶m_2, const Common::Array &pickMeshes, - float param_4, float param_5, TeVector3f32 *param_6); - -// Replaced with Math::Ray::intersectTriangle -//int intersect(const TeVector3f32 &rayPos, const TeVector3f32 &rayDir, const TeVector3f32 &v1, -// const TeVector3f32 &v2, const TeVector3f32 &v3, TeVector3f32 &vout, float &fout); +TePickMesh *getMesh(const Math::Ray ray, const Common::Array &pickMeshes, + float maxDist, float minDist, TeVector3f32 *ptOut); } // end namespace TeRayIntersection diff --git a/engines/tetraedge/te/te_warp.cpp b/engines/tetraedge/te/te_warp.cpp index 29f57d1ff65..5496c0946c0 100644 --- a/engines/tetraedge/te/te_warp.cpp +++ b/engines/tetraedge/te/te_warp.cpp @@ -19,12 +19,15 @@ * */ +#include "common/math.h" + #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_input_mgr.h" #include "tetraedge/te/te_renderer.h" +#include "tetraedge/te/te_ray_intersection.h" namespace Tetraedge { @@ -32,7 +35,9 @@ namespace Tetraedge { bool TeWarp::debug = false; TeWarp::TeWarp() : _visible1(false), _loaded(false), _preloaded(false), - _numAnims(0), _someXVal(0), _someYVal(0), _someMeshX(0), _someMeshY(0) { + _numAnims(0), _someXVal(0), _someYVal(0), _someMeshX(0), _someMeshY(0), + _renderWarpBlocs(true), _xCount(0), _yCount(0), _clickedPickMesh(nullptr), + _clickedAnimData(nullptr) { } TeWarp::~TeWarp() { @@ -115,31 +120,93 @@ TeMarker *TeWarp::allocMarker(unsigned long *nMarkers) { } void TeWarp::checkObjectEvents() { - //const Common::Point lastMouse = g_engine->getInputMgr()->lastMousePos(); - //Math::Ray mouseRay = _camera.getRay(lastMouse); - //for (uint i = 0; i < _numAnims; i++) { - // - //} - error("TODO: Implement 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._curFrameMaybe]._pickMesh; + TeVector3f32 intersectPt; + float intersectLen; + if (pickMesh.flag() && 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() { - _animDatas.clear(); + _putAnimData.clear(); error("TODO: Implement TeWarp::clear"); } -TeWarp::AnimData *TeWarp::findAnimation(const Common::String &name) { +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()) + return; + foundId = anim->_markerIds[0]; + } + assert(foundId >= 0 && foundId < _warpMarkers.size()); + + TeWarpMarker *warpMarker = _warpMarkers[foundId]; + if (markerImgNo == -1) { + warpMarker->marker()->visible(false); + } else { + Common::String markerPath = Common::String::format("2D/Menus/InGame/Marker_%d.png", markerImgNo); + Common::String markerPathOver = 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, markerPathOver, markerPathOver); + TeSpriteLayout *btnUp = dynamic_cast(warpMarker->marker()->button().upLayout()); + if (!btnUp) + error("Loading button image %s failed", markerPath.c_str()); + warning("TeWarp::configMarker: set anim values and something else here?"); + //btnUp->_tiledSurfacePtr->_frameAnim._repeatCount = -1; + //btnUp->_tiledSurfacePtr->_frameAnim.setFrameRate(8.0); + btnUp->play(); + warpMarker->marker()->visible(true); + } +} + +TeWarp::AnimData *TeWarp::findAnimation(const Common::String &objname) { for (uint i = 0; i < _numAnims; i++) { - if (_loadedAnimData[i]._name == name) + if (_loadedAnimData[i]._name == objname) return _loadedAnimData.data() + i; } return nullptr; } -bool TeWarp::hasObjectOrAnim(const Common::String &name) { +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._name == fullName) + return &e; + } + return nullptr; +} + +bool TeWarp::hasObjectOrAnim(const Common::String &objname) { for (uint i = 0; i < _numAnims; i++) { - if (_loadedAnimData[i]._name == name) + if (_loadedAnimData[i]._name == objname) return true; } return false; @@ -147,7 +214,7 @@ bool TeWarp::hasObjectOrAnim(const Common::String &name) { void TeWarp::init() { // This mostly sets up the camera.. maybe nothing to do? - warning("TODO: Implement TeWarp::init"); + warning("TODO: Implement TeWarp::init?"); } void TeWarp::load(const Common::String &path, bool flag) { @@ -156,7 +223,7 @@ void TeWarp::load(const Common::String &path, bool flag) { _warpPath = path; TeCore *core = g_engine->getCore(); Common::FSNode node = core->findFile(_warpPath); - if (node.isReadable()) + if (!node.isReadable()) error("Couldn't find TeWarp path '%s'", _warpPath.c_str()); if (_preloaded) @@ -169,15 +236,14 @@ void TeWarp::load(const Common::String &path, bool flag) { if (Common::String(header) != "TeWarp") error("Invalid header in warp data %s", _warpPath.c_str()); uint32 globalTexDataOffset = file.readUint32LE(); - Common::String encodingType = file.readPascalString(); + _texEncodingType = file.readPascalString(); _xCount = file.readUint32LE(); _yCount = file.readUint32LE(); _numAnims = file.readUint32LE(); _someXVal = file.readUint32LE(); _someYVal = file.readUint32LE(); - warning("TeWarp::load: TODO: Identify these ints.."); - /*int someInt3 = */file.readUint32LE(); - /*int someInt4 = */file.readUint32LE(); + _someMeshX = file.readUint32LE(); + _someMeshY = file.readUint32LE(); _warpBlocs.resize(_xCount * _yCount * 6); for (uint i = 0; i < _xCount * _yCount * 6; i++) { TeWarpBloc::CubeFace face = static_cast(file.readByte()); @@ -191,7 +257,7 @@ void TeWarp::load(const Common::String &path, bool flag) { } } _loadedAnimData.resize(_numAnims); - _animDatas.reserve(_numAnims); + _putAnimData.reserve(_numAnims); for (uint i = 0; i < _numAnims; i++) { char aname[5]; file.read(aname, 4); @@ -237,14 +303,14 @@ void TeWarp::load(const Common::String &path, bool flag) { } } frameData._warpBlocs.resize(frameData._numWarpBlocs); - - error("TODO: Finish line 323~343"); + for (int k = 0; k < frameData._numWarpBlocs; k++) { + frameData._warpBlocs[k] = warpBlocs[k]; + } } } _loaded = true; - error("TODO: Finish TeWarp::load"); } bool TeWarp::onMarkerValidated(const Common::String &name) { @@ -253,7 +319,59 @@ bool TeWarp::onMarkerValidated(const Common::String &name) { } bool TeWarp::onMouseLeftDown(const Common::Point &pt) { - error("TODO: Implement TeWarp::onMouseLeftDown"); + const Math::Ray mouseRay = _camera.getRay(pt); + _clickedPickMesh = nullptr; + _clickedAnimData = nullptr; + + bool hitAnimData = false; + FrameData *frameData; + for (auto &animData : _loadedAnimData) { + frameData = &(animData._frameDatas[animData._curFrameMaybe]); + TeVector3f32 interesctPt; + float intersectDist; + if (frameData->_pickMesh.flag() && frameData->_pickMesh.intersect(mouseRay, interesctPt, intersectDist)) { + _clickedAnimData = &animData; + hitAnimData = true; + break; + } + } + + if (!hitAnimData) { + _clickedPickMesh = TeRayIntersection::getMesh(mouseRay, _pickMeshes2, FLT_MAX, 0, nullptr); + if (_clickedPickMesh) { + Exit *exit = findExit(_clickedPickMesh->name(), true); + _warpMarkers[exit->_markerId]->marker()->button().setEnable(false); + } + return false; + } + + 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) { + for (auto &animData : _loadedAnimData) { + if (animData._name != name || animData._frameDatas.size() != 1 + || animData._curFrameMaybe != 0) + continue; + bool alreadyAdded = false; + for (auto putAnim : _putAnimData) { + if (putAnim == &animData) { + alreadyAdded = true; + break; + } + } + if (!alreadyAdded) + _putAnimData.push_back(&animData); + for (auto &frameData : animData._frameDatas) { + frameData._pickMesh.setFlag(enable); + } + return; + } + warning("Impossible de trouver l\'objet %s dans le Warp", name.c_str()); } void TeWarp::update() { @@ -261,7 +379,15 @@ void TeWarp::update() { return; Application *app = g_engine->getApplication(); _frustum.update(app->mainWindowCamera()); - error("TODO: Implement TeWarp::update"); + for (uint i = 0; i < _xCount * _yCount * 6; i++) { + _warpBlocs[i].loadTexture(_file, _texEncodingType); + } + + if (!_loadedAnimData.empty()) + error("TODO: Finish updating anims in TeWarp::update"); + // for (uint i = 0; i < _loadedAnimData.size(); i++) { + // + // } } void TeWarp::sendExit(TeWarp::Exit &exit) { @@ -289,6 +415,10 @@ void TeWarp::sendMarker(const Common::String &name, unsigned long markerId) { anim->_markerIds.push_back(markerId); } +void TeWarp::setAnimationPart(const Common::String &name, int x, int y, int z, bool flag) { + error("TODO: Implement TeWarp::setAnimationPart"); +} + void TeWarp::setColor(const TeColor &col) { Te3DObject2::setColor(col); for (auto &warpMarker : _warpMarkers) { @@ -332,7 +462,31 @@ void TeWarp::render() { renderer->disableZBuffer(); renderer->pushMatrix(); - // TODO: Render the WarpBlocs here. + if (_renderWarpBlocs) { + for (uint i = 0; i < _xCount * _yCount * 6; i++) { + _warpBlocs[i].render(); + } + } + + TeVector3f32 vertexes[6]; + for (uint i = 0; i < _putAnimData.size(); i++) { + AnimData *animData = _putAnimData[i]; + for (uint j = 0; j < animData->_frameDatas.size(); j++) { + FrameData &frameData = animData->_frameDatas[j]; + for (uint k = 0; k < frameData._warpBlocs.size(); k++) { + TeWarpBloc &bloc = frameData._warpBlocs[k]; + vertexes[0] = bloc.vertex(0); + vertexes[1] = bloc.vertex(1); + vertexes[2] = bloc.vertex(3); + vertexes[3] = bloc.vertex(1); + vertexes[4] = bloc.vertex(2); + vertexes[5] = bloc.vertex(3); + if (_frustum.triangleIsIn(vertexes) && _frustum.triangleIsIn(vertexes + 3)) { + bloc.render(); + } + } + } + } for (auto &warpMarker : _warpMarkers) { warpMarker->marker()->update(&_camera); @@ -346,8 +500,6 @@ void TeWarp::render() { renderer->popMatrix(); renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW); renderer->popMatrix(); - - error("TODO: Finish TeWarp::render"); } void TeWarp::rotateCamera(const TeQuaternion &rot) { @@ -360,6 +512,10 @@ void TeWarp::setFov(float fov) { _camera.setFov(fov); } +void TeWarp::takeObject(const Common::String &name) { + error("TODO: Implement TeWarp::takeObject"); +} + void TeWarp::unload() { error("TODO: Implement TeWarp::unload"); } diff --git a/engines/tetraedge/te/te_warp.h b/engines/tetraedge/te/te_warp.h index 94e6bc2ea05..4da38eb91f0 100644 --- a/engines/tetraedge/te/te_warp.h +++ b/engines/tetraedge/te/te_warp.h @@ -46,9 +46,10 @@ public: class AnimData { public: - AnimData() : _fps(15.0f), _flag(false) {} + AnimData() : _fps(15.0f), _flag(false), _curFrameMaybe(0) {} Common::Array _markerIds; float _fps; + int _curFrameMaybe; bool _flag; TeTimer _timer; Common::String _name; @@ -78,7 +79,7 @@ public: uint addQuadToPickMesh(TePickMesh &pickmesh, uint trinum, TeWarpBloc::CubeFace face, const TeVector2s32 ¶m_4, uint param_5, uint param_6); TeMarker *allocMarker(unsigned long *nMarkers); - void configMarker(const Common::String objname, int markerImgNo, long markerId); + void configMarker(const Common::String &objname, int markerImgNo, long markerId); void checkObjectEvents(); void clear(); //void entry(); // unused @@ -90,16 +91,19 @@ public: void load(const Common::String &path, bool flag); //void loadTextures(); // unused //void preload(const Common::String &path); // unused + void putObject(const Common::String &name, bool enable); void update(); void render(); void rotateCamera(const TeQuaternion &rot); void sendExit(Exit &exit); void sendMarker(const Common::String &name, unsigned long markerId); + void setAnimationPart(const Common::String &name, int x, int y, int z, bool flag); void setColor(const TeColor &col) override; void setMarkersOpacity(float opacity); void setMouseLeftUpForMakers(); void setFov(float fov); void setVisible(bool v1, bool v2); + void takeObject(const Common::String &name); void unload(); void unloadTextures(); void updateCamera(const TeVector3f32 &screen); @@ -121,12 +125,16 @@ private: bool _visible1; bool _loaded; bool _preloaded; + bool _renderWarpBlocs; + + TePickMesh *_clickedPickMesh; + AnimData *_clickedAnimData; TeFrustum _frustum; Common::Array _warpMarkers; Common::List _paths; - Common::Array _animDatas; + Common::Array _putAnimData; Common::List _exitList; uint _someXVal; uint _someYVal; @@ -136,9 +144,11 @@ private: uint _yCount; uint _numAnims; Common::Array _warpBlocs; + Common::Array _pickMeshes2; Common::Array _loadedAnimData; TeSignal1Param _markerValidatedSignal; TeSignal1Param _animFinishedSignal; + Common::String _texEncodingType; }; } // end namespace Tetraedge diff --git a/engines/tetraedge/te/te_warp_bloc.cpp b/engines/tetraedge/te/te_warp_bloc.cpp index 9a31d46bf71..815d2a12499 100644 --- a/engines/tetraedge/te/te_warp_bloc.cpp +++ b/engines/tetraedge/te/te_warp_bloc.cpp @@ -20,15 +20,16 @@ */ #include "tetraedge/te/te_warp_bloc.h" +#include "tetraedge/te/te_renderer.h" +#include "tetraedge/tetraedge.h" namespace Tetraedge { -TeWarpBloc::TeWarpBloc() : _colors(nullptr), _cubeFace(FaceInvalid) { +TeWarpBloc::TeWarpBloc() : _cubeFace(FaceInvalid) { + _mesh.reset(TeMesh::makeInstance()); } TeWarpBloc::~TeWarpBloc() { - if (_colors) - delete _colors; } void TeWarpBloc::color(const TeColor &col) { @@ -39,88 +40,85 @@ void TeWarpBloc::color(const TeColor &col) { } void TeWarpBloc::color(uint num, const TeColor &col) { - if (_colors == nullptr) { - _colors = new TeColor[4]; - } - assert(num < 4); - _colors[num] = col; + _mesh->setColor(num, col); } void TeWarpBloc::create(CubeFace face, uint x, uint y, const TeVector2s32 &offset) { _cubeFace = face; _offset = offset; + _mesh->setConf(4, 4, TeMesh::MeshMode_TriangleStrip, 0, 0); + float y1 = offset._y * (1000.0f / y) - 500.0f; float y2 = y1 + 1000.0f / y; float x1 = offset._x * (1000.0f / x) - 500.0f; float x2 = x1 + 1000.0f / x; switch (face) { case Face0: - _verticies[0] = TeVector3f32(-x1, 500, -y1); - _verticies[1] = TeVector3f32(-x2, 500, -y1); - _verticies[2] = TeVector3f32(-x2, 500, -y2); - _verticies[3] = TeVector3f32(-x1, 500, -y2); + _mesh->setVertex(0, TeVector3f32(-x1, 500, -y1)); + _mesh->setVertex(1, TeVector3f32(-x2, 500, -y1)); + _mesh->setVertex(2, TeVector3f32(-x2, 500, -y2)); + _mesh->setVertex(3, TeVector3f32(-x1, 500, -y2)); break; case Face1: - _verticies[0] = TeVector3f32(-x1, -500, y1); - _verticies[1] = TeVector3f32(-x2, -500, y1); - _verticies[2] = TeVector3f32(-x2, -500, y2); - _verticies[3] = TeVector3f32(-x1, -500, y2); + _mesh->setVertex(0, TeVector3f32(-x1, -500, y1)); + _mesh->setVertex(1, TeVector3f32(-x2, -500, y1)); + _mesh->setVertex(2, TeVector3f32(-x2, -500, y2)); + _mesh->setVertex(3, TeVector3f32(-x1, -500, y2)); break; case Face2: - _verticies[0] = TeVector3f32(-x1, y1, 500); - _verticies[1] = TeVector3f32(-x2, y1, 500); - _verticies[2] = TeVector3f32(-x2, y2, 500); - _verticies[3] = TeVector3f32(-x1, y2, 500); + _mesh->setVertex(0, TeVector3f32(-x1, y1, 500)); + _mesh->setVertex(1, TeVector3f32(-x2, y1, 500)); + _mesh->setVertex(2, TeVector3f32(-x2, y2, 500)); + _mesh->setVertex(3, TeVector3f32(-x1, y2, 500)); break; case Face3: - _verticies[0] = TeVector3f32(x1, y1, -500); - _verticies[1] = TeVector3f32(x2, y1, -500); - _verticies[2] = TeVector3f32(x2, y2, -500); - _verticies[3] = TeVector3f32(x1, y2, -500); + _mesh->setVertex(0, TeVector3f32(x1, y1, -500)); + _mesh->setVertex(1, TeVector3f32(x2, y1, -500)); + _mesh->setVertex(2, TeVector3f32(x2, y2, -500)); + _mesh->setVertex(3, TeVector3f32(x1, y2, -500)); break; case Face4: - _verticies[0] = TeVector3f32(500, y1, x1); - _verticies[1] = TeVector3f32(500, y1, x2); - _verticies[2] = TeVector3f32(500, y2, x2); - _verticies[3] = TeVector3f32(500, y2, x1); + _mesh->setVertex(0, TeVector3f32(500, y1, x1)); + _mesh->setVertex(1, TeVector3f32(500, y1, x2)); + _mesh->setVertex(2, TeVector3f32(500, y2, x2)); + _mesh->setVertex(3, TeVector3f32(500, y2, x1)); break; case Face5: - _verticies[0] = TeVector3f32(-500, y1, -x1); - _verticies[1] = TeVector3f32(-500, y1, -x2); - _verticies[2] = TeVector3f32(-500, y2, -x2); - _verticies[3] = TeVector3f32(-500, y2, -x1); + _mesh->setVertex(0, TeVector3f32(-500, y1, -x1)); + _mesh->setVertex(1, TeVector3f32(-500, y1, -x2)); + _mesh->setVertex(2, TeVector3f32(-500, y2, -x2)); + _mesh->setVertex(3, TeVector3f32(-500, y2, -x1)); break; default: break; } - _texCoords[0] = TeVector2f32(0, 0); - _texCoords[1] = TeVector2f32(1, 0); - _texCoords[2] = TeVector2f32(1, 1); - _texCoords[3] = TeVector2f32(0, 1); - _indexes[0] = 0; - _indexes[1] = 1; - _indexes[2] = 2; - _indexes[3] = 3; + _mesh->setTextureUV(0, TeVector2f32(0, 0)); + _mesh->setTextureUV(1, TeVector2f32(1, 0)); + _mesh->setTextureUV(2, TeVector2f32(1, 1)); + _mesh->setTextureUV(3, TeVector2f32(0, 1)); + _mesh->setIndex(0, 0); + _mesh->setIndex(1, 1); + _mesh->setIndex(2, 2); + _mesh->setIndex(3, 3); } void TeWarpBloc::create() { - _colors = nullptr; - _texture.release(); + _mesh->materials().clear(); } void TeWarpBloc::index(uint offset, uint val) { assert(offset < 4); - _indexes[offset] = val; + _mesh->setIndex(offset, val); } bool TeWarpBloc::isLoaded() const { - return _texture.get() != nullptr; + return _mesh->materials().size() > 0 && _mesh->material(0)->_texture; } void TeWarpBloc::loadTexture(Common::File &file, const Common::String &type) { - if (_texture) + if (isLoaded()) return; if (!file.seek(_textureDataFileOffset)) @@ -129,34 +127,34 @@ void TeWarpBloc::loadTexture(Common::File &file, const Common::String &type) { TeImage img; img.load(file, type); - _texture = Te3DTexture::makeInstance(); - _texture->load(img); + _mesh->materials().resize(1); + _mesh->material(0)->_texture = Te3DTexture::makeInstance(); + _mesh->material(0)->_texture->load(img); } void TeWarpBloc::render() { - error("Implement TeWarpBloc::render"); + _mesh->draw(); } void TeWarpBloc::texture(uint idx, float x, float y) { assert(idx < 4); - _texCoords[idx].setX(x); - _texCoords[idx].setY(y); + _mesh->setTextureUV(idx, TeVector2f32(x, y)); } void TeWarpBloc::unloadTexture() { - _texture.release(); + if (!isLoaded()) + return; + _mesh->material(0)->_texture.release(); } void TeWarpBloc::vertex(uint idx, float x, float y, float z) { assert(idx < 4); - _verticies[idx].x() = x; - _verticies[idx].y() = y; - _verticies[idx].z() = z; + _mesh->setVertex(idx, TeVector3f32(x, y, z)); } -const TeVector3f32 &TeWarpBloc::vertex(uint idx) const { +TeVector3f32 TeWarpBloc::vertex(uint idx) const { assert(idx < 4); - return _verticies[idx]; + return _mesh->vertex(idx); } } // end namespace Tetraedge diff --git a/engines/tetraedge/te/te_warp_bloc.h b/engines/tetraedge/te/te_warp_bloc.h index 0a6532f1df7..f16868b8c78 100644 --- a/engines/tetraedge/te/te_warp_bloc.h +++ b/engines/tetraedge/te/te_warp_bloc.h @@ -28,6 +28,7 @@ #include "tetraedge/te/te_vector3f32.h" #include "tetraedge/te/te_intrusive_ptr.h" #include "tetraedge/te/te_3d_texture.h" +#include "tetraedge/te/te_mesh.h" #include "common/file.h" @@ -61,7 +62,7 @@ public: void texture(uint idx, float x, float y); void unloadTexture(); void vertex(uint n, float x, float y, float z); - const TeVector3f32 &vertex(uint n) const; + TeVector3f32 vertex(uint n) const; const TeVector2s32 offset() const { return _offset; } CubeFace face() const { return _cubeFace; } @@ -69,13 +70,10 @@ public: void setTextureFileOffset(long offset) { _textureDataFileOffset = offset; } private: - TeColor *_colors; TeVector2s32 _offset; - TeIntrusivePtr _texture; CubeFace _cubeFace; - TeVector3f32 _verticies[4]; - TeVector2f32 _texCoords[4]; - short _indexes[4]; + // Tex UV / indexes / texture from orig now in here. + Common::SharedPtr _mesh; long _textureDataFileOffset; }; diff --git a/engines/tetraedge/te/te_warp_marker.h b/engines/tetraedge/te/te_warp_marker.h index 31d8f653972..68ced45bcac 100644 --- a/engines/tetraedge/te/te_warp_marker.h +++ b/engines/tetraedge/te/te_warp_marker.h @@ -38,6 +38,8 @@ public: void marker(TeMarker *marker); bool onMarkerButtonValidated(); TeSignal1Param &markerButtonSignal() { return _markerButtonSignal; }; + void setName(const Common::String newName) { _name = newName; } + private: TeMarker *_marker;