Initial commit
This commit is contained in:
475
engines/twine/debugger/console.cpp
Normal file
475
engines/twine/debugger/console.cpp
Normal file
@@ -0,0 +1,475 @@
|
||||
/* 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 "twine/debugger/console.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/util.h"
|
||||
#include "twine/debugger/debug_state.h"
|
||||
#include "twine/holomap.h"
|
||||
#include "twine/renderer/redraw.h"
|
||||
#include "twine/resources/hqr.h"
|
||||
#include "twine/scene/gamestate.h"
|
||||
#include "twine/scene/scene.h"
|
||||
#include "twine/renderer/screens.h"
|
||||
#include "twine/text.h"
|
||||
#include "twine/twine.h"
|
||||
#include "twine/audio/music.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
TwinEConsole::TwinEConsole(TwinEEngine *engine) : _engine(engine), GUI::Debugger() {
|
||||
registerCmd("give_item", WRAP_METHOD(TwinEConsole, doGiveItem));
|
||||
registerCmd("give_allitems", WRAP_METHOD(TwinEConsole, doGiveAllItems));
|
||||
registerCmd("give_key", WRAP_METHOD(TwinEConsole, doGiveKey));
|
||||
registerCmd("give_gas", WRAP_METHOD(TwinEConsole, doGiveGas));
|
||||
registerCmd("give_kashes", WRAP_METHOD(TwinEConsole, doGiveKashes));
|
||||
registerCmd("play_video", WRAP_METHOD(TwinEConsole, doPlayVideo));
|
||||
registerCmd("play_midi", WRAP_METHOD(TwinEConsole, doPlayMidi));
|
||||
registerCmd("play_music", WRAP_METHOD(TwinEConsole, doPlayMusic));
|
||||
registerCmd("change_scene", WRAP_METHOD(TwinEConsole, doChangeScene));
|
||||
registerCmd("change_chapter", WRAP_METHOD(TwinEConsole, doChangeChapter));
|
||||
registerCmd("toggle_scenery_view", WRAP_METHOD(TwinEConsole, doToggleSceneryView));
|
||||
registerCmd("magic_points", WRAP_METHOD(TwinEConsole, doAddMagicPoints));
|
||||
registerCmd("dumpfile", WRAP_METHOD(TwinEConsole, doDumpFile));
|
||||
registerCmd("toggle_zones", WRAP_METHOD(TwinEConsole, doToggleZoneRendering));
|
||||
registerCmd("toggle_tracks", WRAP_METHOD(TwinEConsole, doToggleTrackRendering));
|
||||
registerCmd("toggle_godmode", WRAP_METHOD(TwinEConsole, doToggleGodMode));
|
||||
registerCmd("toggle_autoagressive", WRAP_METHOD(TwinEConsole, doToggleAutoAggressive));
|
||||
registerCmd("toggle_actors", WRAP_METHOD(TwinEConsole, doToggleActorRendering));
|
||||
registerCmd("toggle_clips", WRAP_METHOD(TwinEConsole, doToggleClipRendering));
|
||||
registerCmd("toggle_freecamera", WRAP_METHOD(TwinEConsole, doToggleFreeCamera));
|
||||
registerCmd("toggle_scenerendering", WRAP_METHOD(TwinEConsole, doToggleSceneRendering));
|
||||
registerCmd("set_track_obj", WRAP_METHOD(TwinEConsole, doSetTrackObject));
|
||||
registerCmd("scene_actor", WRAP_METHOD(TwinEConsole, doSkipSceneActorsBut));
|
||||
registerCmd("hero_pos", WRAP_METHOD(TwinEConsole, doSetHeroPosition));
|
||||
registerCmd("set_life", WRAP_METHOD(TwinEConsole, doSetLife));
|
||||
registerCmd("set_game_flag", WRAP_METHOD(TwinEConsole, doSetGameFlag));
|
||||
registerCmd("show_game_flag", WRAP_METHOD(TwinEConsole, doPrintGameFlag));
|
||||
registerCmd("set_inventory_flag", WRAP_METHOD(TwinEConsole, doSetInventoryFlag));
|
||||
registerCmd("show_inventory_flag", WRAP_METHOD(TwinEConsole, doPrintInventoryFlag));
|
||||
registerCmd("set_holomap_flag", WRAP_METHOD(TwinEConsole, doSetHolomapFlag));
|
||||
registerCmd("set_holomap_trajectory", WRAP_METHOD(TwinEConsole, doSetHolomapTrajectory));
|
||||
registerCmd("show_holomap_flag", WRAP_METHOD(TwinEConsole, doPrintHolomapFlag));
|
||||
}
|
||||
|
||||
TwinEConsole::~TwinEConsole() {
|
||||
}
|
||||
|
||||
void TwinEConsole::preEnter() {
|
||||
_engine->_input->resetActionStates();
|
||||
Super::preEnter();
|
||||
}
|
||||
|
||||
void TwinEConsole::postEnter() {
|
||||
_engine->_input->resetActionStates();
|
||||
Super::postEnter();
|
||||
}
|
||||
|
||||
#define TOGGLE_DEBUG(var, description) \
|
||||
if ((var)) { \
|
||||
debugPrintf("Disabling " description); \
|
||||
(var) = false; \
|
||||
} else { \
|
||||
debugPrintf("Enabling " description); \
|
||||
(var) = true; \
|
||||
}
|
||||
|
||||
bool TwinEConsole::doToggleZoneRendering(int argc, const char **argv) {
|
||||
TOGGLE_DEBUG(_engine->_debugState->_showingZones, "zone rendering\n")
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doToggleActorRendering(int argc, const char **argv) {
|
||||
TOGGLE_DEBUG(_engine->_debugState->_showingActors, "actor rendering\n")
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doToggleTrackRendering(int argc, const char **argv) {
|
||||
TOGGLE_DEBUG(_engine->_debugState->_showingTracks, "tracks rendering\n")
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doToggleGodMode(int argc, const char **argv) {
|
||||
TOGGLE_DEBUG(_engine->_debugState->_godMode, "god mode\n")
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doToggleClipRendering(int argc, const char **argv) {
|
||||
TOGGLE_DEBUG(_engine->_debugState->_showingClips, "clip rendering\n")
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doToggleSceneryView(int argc, const char **argv) {
|
||||
TOGGLE_DEBUG(_engine->_redraw->_flagMCGA, "scenery view\n")
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doToggleAutoAggressive(int argc, const char **argv) {
|
||||
TOGGLE_DEBUG(_engine->_actor->_combatAuto, "auto aggressive\n")
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doAddMagicPoints(int argc, const char **argv) {
|
||||
if (argc < 2) {
|
||||
debugPrintf("Usage: specify the magic points\n");
|
||||
return true;
|
||||
}
|
||||
const int16 magicPoints = atoi(argv[1]);
|
||||
_engine->_gameState->_magicLevelIdx = CLIP<int16>(magicPoints, 0, 4);
|
||||
_engine->_gameState->setMaxMagicPoints();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doSkipSceneActorsBut(int argc, const char **argv) {
|
||||
if (argc < 2) {
|
||||
debugPrintf("Usage: give actor id of scene or -1 to disable\n");
|
||||
return true;
|
||||
}
|
||||
const int16 actorIdx = atoi(argv[1]);
|
||||
debugPrintf("Only load actor %d in the next scene\n", actorIdx);
|
||||
_engine->_debugState->_onlyLoadActor = actorIdx;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doToggleFreeCamera(int argc, const char **argv) {
|
||||
TOGGLE_DEBUG(_engine->_debugState->_useFreeCamera, "free camera movement\n")
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doSetTrackObject(int argc, const char **argv) {
|
||||
if (argc <= 2) {
|
||||
debugPrintf("Expected to get a the scene actor number and the track\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
const int32 otherActorIdx = atoi(argv[1]);
|
||||
const int32 offset = atoi(argv[2]);
|
||||
_engine->_scene->getActor(otherActorIdx)->_offsetTrack = offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doToggleSceneRendering(int argc, const char **argv) {
|
||||
TOGGLE_DEBUG(_engine->_debugState->_disableGridRendering, "scene rendering\n")
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doSetInventoryFlag(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get a inventory flag index as first parameter\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8 idx = atoi(argv[1]);
|
||||
if (idx >= NUM_INVENTORY_ITEMS) {
|
||||
debugPrintf("given index exceeds the max allowed value of %i\n", NUM_INVENTORY_ITEMS - 1);
|
||||
return true;
|
||||
}
|
||||
const uint8 val = argc == 3 ? atoi(argv[2]) : 0;
|
||||
_engine->_gameState->_inventoryFlags[idx] = val;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doSetHolomapTrajectory(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get a holomap trajectory index as parameter\n");
|
||||
return true;
|
||||
}
|
||||
_engine->_scene->_numHolomapTraj = atoi(argv[1]);
|
||||
_engine->_scene->reloadCurrentScene();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doSetHolomapFlag(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get a holomap flag index as first parameter. Use -1 to set all flags\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
GameState* state = _engine->_gameState;
|
||||
state->setGameFlag(InventoryItems::kiHolomap, 1);
|
||||
state->_inventoryFlags[InventoryItems::kiHolomap] = 1;
|
||||
state->setGameFlag(GAMEFLAG_INVENTORY_DISABLED, 0);
|
||||
|
||||
const int idx = atoi(argv[1]);
|
||||
if (idx == -1) {
|
||||
for (int i = 0; i < _engine->numHoloPos(); ++i) {
|
||||
_engine->_holomap->setHoloPos(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (idx < 0 || idx >= _engine->numHoloPos()) {
|
||||
debugPrintf("given index exceeds the max allowed value of %i\n", _engine->numHoloPos() - 1);
|
||||
return true;
|
||||
}
|
||||
_engine->_holomap->setHoloPos(idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doSetGameFlag(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get a game flag index as first parameter\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8 idx = atoi(argv[1]);
|
||||
const uint8 val = argc == 3 ? atoi(argv[2]) : 0;
|
||||
_engine->_gameState->setGameFlag(idx, val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doPrintGameFlag(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
for (int i = 0; i < NUM_GAME_FLAGS; ++i) {
|
||||
debugPrintf("[%03d] = %d\n", i, _engine->_gameState->hasGameFlag(i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8 idx = atoi(argv[1]);
|
||||
debugPrintf("[%03d] = %d\n", idx, _engine->_gameState->hasGameFlag(idx));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doPrintInventoryFlag(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
for (int i = 0; i < NUM_INVENTORY_ITEMS; ++i) {
|
||||
debugPrintf("[%03d] = %d\n", i, _engine->_gameState->_inventoryFlags[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8 idx = atoi(argv[1]);
|
||||
if (idx < NUM_INVENTORY_ITEMS) {
|
||||
debugPrintf("[%03d] = %d\n", idx, _engine->_gameState->_inventoryFlags[idx]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doPrintHolomapFlag(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
for (int i = 0; i < _engine->numHoloPos(); ++i) {
|
||||
debugPrintf("[%03d] = %d\n", i, _engine->_gameState->_holomapFlags[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint16 idx = atoi(argv[1]);
|
||||
if (idx < _engine->numHoloPos()) {
|
||||
debugPrintf("[%03d] = %d\n", idx, _engine->_gameState->_holomapFlags[idx]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doGiveKey(int argc, const char **argv) {
|
||||
int amount = 1;
|
||||
if (argc >= 2) {
|
||||
amount = atoi(argv[1]);
|
||||
}
|
||||
_engine->_gameState->addKeys(amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doGiveGas(int argc, const char **argv) {
|
||||
int amount = 1;
|
||||
if (argc >= 2) {
|
||||
amount = atoi(argv[1]);
|
||||
}
|
||||
_engine->_gameState->addGas(amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doGiveKashes(int argc, const char **argv) {
|
||||
int amount = 1;
|
||||
if (argc >= 2) {
|
||||
amount = atoi(argv[1]);
|
||||
}
|
||||
_engine->_gameState->addKashes(amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doSetHeroPosition(int argc, const char **argv) {
|
||||
IVec3 &pos = _engine->_scene->_sceneHero->_posObj;
|
||||
if (argc < 4) {
|
||||
debugPrintf("Current hero position: %i:%i:%i\n", pos.x, pos.y, pos.z);
|
||||
return true;
|
||||
}
|
||||
pos.x = atoi(argv[1]);
|
||||
pos.y = atoi(argv[2]);
|
||||
pos.z = atoi(argv[3]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doPlayVideo(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get a video filename as first parameter\n");
|
||||
return true;
|
||||
}
|
||||
_engine->queueMovie(argv[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doPlayMidi(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get a midi id as first parameter\n");
|
||||
return true;
|
||||
}
|
||||
int newMidiIndex = atoi(argv[1]);
|
||||
_engine->_music->playMidiFile(newMidiIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doPlayMusic(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get a music track id as first parameter\n");
|
||||
return true;
|
||||
}
|
||||
int newMusicTrackIndex = atoi(argv[1]);
|
||||
_engine->_music->playMusic(newMusicTrackIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doChangeScene(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get a scene index as first parameter\n");
|
||||
return true;
|
||||
}
|
||||
byte newSceneIndex = atoi(argv[1]);
|
||||
if (newSceneIndex >= LBA1SceneId::SceneIdMax) {
|
||||
debugPrintf("Scene index out of bounds\n");
|
||||
return true;
|
||||
}
|
||||
_engine->_scene->_newCube = atoi(argv[1]);
|
||||
_engine->_scene->_flagChgCube = ScenePositionType::kScene;
|
||||
_engine->_scene->changeCube();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doChangeChapter(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get a chapter index as first parameter\n");
|
||||
return true;
|
||||
}
|
||||
debugPrintf("Old chapter was: %i\n", _engine->_gameState->getChapter());
|
||||
_engine->_gameState->setChapter(atoi(argv[1]));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doDumpFile(int argc, const char **argv) {
|
||||
if (argc <= 2) {
|
||||
debugPrintf("Expected to get a a hqr file and an index\n");
|
||||
return true;
|
||||
}
|
||||
const char *hqr = argv[1];
|
||||
const int index = atoi(argv[2]);
|
||||
const Common::String &targetFileName = Common::String::format("dumps/%03i-%s.dump", index, hqr);
|
||||
HQR::dumpEntry(hqr, index, targetFileName.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *ItemNames[] = {
|
||||
"Holomap",
|
||||
"MagicBall",
|
||||
"UseSabre",
|
||||
"GawleysHorn",
|
||||
"Tunic",
|
||||
"BookOfBu",
|
||||
"SendellsMedallion",
|
||||
"FlaskOfClearWater",
|
||||
"RedCard",
|
||||
"BlueCard",
|
||||
"IDCard",
|
||||
"MrMiesPass",
|
||||
"ProtoPack",
|
||||
"Snowboard",
|
||||
"Penguin",
|
||||
"GasItem",
|
||||
"PirateFlag",
|
||||
"MagicFlute",
|
||||
"SpaceGuitar",
|
||||
"HairDryer",
|
||||
"AncesteralKey",
|
||||
"BottleOfSyrup",
|
||||
"EmptyBottle",
|
||||
"FerryTicket",
|
||||
"Keypad",
|
||||
"CoffeeCan",
|
||||
"BonusList",
|
||||
"CloverLeaf"
|
||||
};
|
||||
static_assert(ARRAYSIZE(ItemNames) == InventoryItems::MaxInventoryItems, "Array size doesn't match items");
|
||||
|
||||
bool TwinEConsole::doGiveItem(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get an item as first parameter\n");
|
||||
for (int i = 0; i < ARRAYSIZE(ItemNames); ++i) {
|
||||
debugPrintf(" - %2i: %s\n", i, ItemNames[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
byte itemIdx = atoi(argv[1]);
|
||||
if (itemIdx >= InventoryItems::MaxInventoryItems) {
|
||||
debugPrintf("Item index out of bounds\n");
|
||||
return true;
|
||||
}
|
||||
GameState* state = _engine->_gameState;
|
||||
state->setGameFlag(itemIdx, 1);
|
||||
state->_inventoryFlags[itemIdx] = 1;
|
||||
state->setGameFlag(GAMEFLAG_INVENTORY_DISABLED, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doGiveAllItems(int argc, const char **argv) {
|
||||
GameState* state = _engine->_gameState;
|
||||
for (int32 i = 0; i < NUM_INVENTORY_ITEMS; ++i) {
|
||||
state->setGameFlag(i, 1);
|
||||
state->_inventoryFlags[i] = 1;
|
||||
}
|
||||
state->setGameFlag(GAMEFLAG_INVENTORY_DISABLED, 0);
|
||||
int amount = 1;
|
||||
if (argc >= 2) {
|
||||
amount = atoi(argv[1]);
|
||||
}
|
||||
state->addKeys(amount);
|
||||
state->addLeafBoxes(amount);
|
||||
state->addKashes(amount);
|
||||
state->addLeafs(amount);
|
||||
state->addMagicPoints(amount);
|
||||
state->addGas(amount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwinEConsole::doSetLife(int argc, const char **argv) {
|
||||
if (argc <= 1) {
|
||||
debugPrintf("Expected to get the life points as parameter\n");
|
||||
return true;
|
||||
}
|
||||
_engine->_scene->_sceneHero->setLife(atoi(argv[1]));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace TwinE
|
||||
86
engines/twine/debugger/console.h
Normal file
86
engines/twine/debugger/console.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TWINE_CONSOLE_H
|
||||
#define TWINE_CONSOLE_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
#include "twine/scene/gamestate.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
class TwinEEngine;
|
||||
|
||||
class TwinEConsole : public GUI::Debugger {
|
||||
private:
|
||||
using Super = GUI::Debugger;
|
||||
TwinEEngine *_engine;
|
||||
|
||||
bool doToggleSceneryView(int argc, const char **argv);
|
||||
bool doPlayVideo(int argc, const char **argv);
|
||||
bool doPlayMidi(int argc, const char **argv);
|
||||
bool doPlayMusic(int argc, const char **argv);
|
||||
bool doPrintGameFlag(int argc, const char **argv);
|
||||
bool doPrintInventoryFlag(int argc, const char **argv);
|
||||
bool doPrintHolomapFlag(int argc, const char **argv);
|
||||
bool doSetHeroPosition(int argc, const char **argv);
|
||||
bool doGiveItem(int argc, const char **argv);
|
||||
bool doSetLife(int argc, const char **argv);
|
||||
bool doGiveAllItems(int argc, const char **argv);
|
||||
bool doChangeScene(int argc, const char **argv);
|
||||
bool doToggleAutoAggressive(int argc, const char **argv);
|
||||
bool doGiveKey(int argc, const char **argv);
|
||||
bool doGiveGas(int argc, const char **argv);
|
||||
bool doGiveKashes(int argc, const char **argv);
|
||||
bool doToggleZoneRendering(int argc, const char **argv);
|
||||
bool doToggleClipRendering(int argc, const char **argv);
|
||||
bool doToggleActorRendering(int argc, const char **argv);
|
||||
bool doToggleTrackRendering(int argc, const char **argv);
|
||||
bool doToggleGodMode(int argc, const char **argv);
|
||||
bool doToggleFreeCamera(int argc, const char **argv);
|
||||
bool doToggleSceneRendering(int argc, const char **argv);
|
||||
bool doSetTrackObject(int argc, const char **argv);
|
||||
bool doChangeChapter(int argc, const char **argv);
|
||||
bool doSkipSceneActorsBut(int argc, const char **argv);
|
||||
bool doSetGameFlag(int argc, const char **argv);
|
||||
bool doSetInventoryFlag(int argc, const char **argv);
|
||||
bool doSetHolomapFlag(int argc, const char **argv);
|
||||
bool doAddMagicPoints(int argc, const char **argv);
|
||||
bool doDumpFile(int argc, const char **argv);
|
||||
bool doSetHolomapTrajectory(int argc, const char **argv);
|
||||
|
||||
protected:
|
||||
void preEnter() override;
|
||||
void postEnter() override;
|
||||
|
||||
public:
|
||||
TwinEConsole(TwinEEngine *engine);
|
||||
~TwinEConsole() override;
|
||||
|
||||
bool exec(const char *file) {
|
||||
const char *argv[] = {"", file};
|
||||
return cmdExecFile(2, argv);
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace TwinE
|
||||
|
||||
#endif // TWINE_CONSOLE_H
|
||||
237
engines/twine/debugger/debug_state.cpp
Normal file
237
engines/twine/debugger/debug_state.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/* 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 "twine/debugger/debug_state.h"
|
||||
#include "common/util.h"
|
||||
#include "twine/menu/interface.h"
|
||||
#include "twine/menu/menu.h"
|
||||
#include "twine/renderer/redraw.h"
|
||||
#include "twine/renderer/renderer.h"
|
||||
#include "twine/scene/grid.h"
|
||||
#include "twine/scene/scene.h"
|
||||
#include "twine/text.h"
|
||||
#include "twine/twine.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
DebugState::DebugState(TwinEEngine *engine) : _engine(engine) {}
|
||||
|
||||
void DebugState::update() {
|
||||
changeGridCamera();
|
||||
}
|
||||
|
||||
void DebugState::drawClip(const Common::Rect &rect) {
|
||||
if (!_showingClips) {
|
||||
return;
|
||||
}
|
||||
_engine->_menu->drawRectBorders(rect);
|
||||
}
|
||||
|
||||
void DebugState::projectBoundingBoxPoints(IVec3 *pPoint3d, IVec3 *pPoint3dProjected) {
|
||||
*pPoint3dProjected = _engine->_renderer->projectPoint(*pPoint3d);
|
||||
}
|
||||
|
||||
bool DebugState::checkZoneType(ZoneType type) const {
|
||||
return (_typeZones & (1u << (uint32)type)) != 0u;
|
||||
}
|
||||
|
||||
DebugState::ScenePositionsProjected DebugState::calculateBoxPositions(const IVec3 &mins, const IVec3 &maxs) {
|
||||
ScenePositionsProjected positions;
|
||||
// compute the points in 3D
|
||||
positions.frontBottomLeftPoint.x = mins.x - _engine->_grid->_worldCube.x;
|
||||
positions.frontBottomLeftPoint.y = mins.y - _engine->_grid->_worldCube.y;
|
||||
positions.frontBottomLeftPoint.z = maxs.z - _engine->_grid->_worldCube.z;
|
||||
|
||||
positions.frontBottomRightPoint.x = maxs.x - _engine->_grid->_worldCube.x;
|
||||
positions.frontBottomRightPoint.y = mins.y - _engine->_grid->_worldCube.y;
|
||||
positions.frontBottomRightPoint.z = maxs.z - _engine->_grid->_worldCube.z;
|
||||
|
||||
positions.frontTopLeftPoint.x = mins.x - _engine->_grid->_worldCube.x;
|
||||
positions.frontTopLeftPoint.y = maxs.y - _engine->_grid->_worldCube.y;
|
||||
positions.frontTopLeftPoint.z = maxs.z - _engine->_grid->_worldCube.z;
|
||||
|
||||
positions.frontTopRightPoint = maxs - _engine->_grid->_worldCube;
|
||||
positions.backBottomLeftPoint = mins - _engine->_grid->_worldCube;
|
||||
|
||||
positions.backBottomRightPoint.x = maxs.x - _engine->_grid->_worldCube.x;
|
||||
positions.backBottomRightPoint.y = mins.y - _engine->_grid->_worldCube.y;
|
||||
positions.backBottomRightPoint.z = mins.z - _engine->_grid->_worldCube.z;
|
||||
|
||||
positions.backTopLeftPoint.x = mins.x - _engine->_grid->_worldCube.x;
|
||||
positions.backTopLeftPoint.y = maxs.y - _engine->_grid->_worldCube.y;
|
||||
positions.backTopLeftPoint.z = mins.z - _engine->_grid->_worldCube.z;
|
||||
|
||||
positions.backTopRightPoint.x = maxs.x - _engine->_grid->_worldCube.x;
|
||||
positions.backTopRightPoint.y = maxs.y - _engine->_grid->_worldCube.y;
|
||||
positions.backTopRightPoint.z = mins.z - _engine->_grid->_worldCube.z;
|
||||
|
||||
// project all points
|
||||
|
||||
projectBoundingBoxPoints(&positions.frontBottomLeftPoint, &positions.frontBottomLeftPoint2D);
|
||||
projectBoundingBoxPoints(&positions.frontBottomRightPoint, &positions.frontBottomRightPoint2D);
|
||||
projectBoundingBoxPoints(&positions.frontTopLeftPoint, &positions.frontTopLeftPoint2D);
|
||||
projectBoundingBoxPoints(&positions.frontTopRightPoint, &positions.frontTopRightPoint2D);
|
||||
projectBoundingBoxPoints(&positions.backBottomLeftPoint, &positions.backBottomLeftPoint2D);
|
||||
projectBoundingBoxPoints(&positions.backBottomRightPoint, &positions.backBottomRightPoint2D);
|
||||
projectBoundingBoxPoints(&positions.backTopLeftPoint, &positions.backTopLeftPoint2D);
|
||||
projectBoundingBoxPoints(&positions.backTopRightPoint, &positions.backTopRightPoint2D);
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
bool DebugState::drawBox(const ScenePositionsProjected &positions, uint8 color) {
|
||||
bool state = false;
|
||||
// draw front part
|
||||
state |= _engine->_interface->drawLine(positions.frontBottomLeftPoint2D.x, positions.frontBottomLeftPoint2D.y, positions.frontTopLeftPoint2D.x, positions.frontTopLeftPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.frontTopLeftPoint2D.x, positions.frontTopLeftPoint2D.y, positions.frontTopRightPoint2D.x, positions.frontTopRightPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.frontTopRightPoint2D.x, positions.frontTopRightPoint2D.y, positions.frontBottomRightPoint2D.x, positions.frontBottomRightPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.frontBottomRightPoint2D.x, positions.frontBottomRightPoint2D.y, positions.frontBottomLeftPoint2D.x, positions.frontBottomLeftPoint2D.y, color);
|
||||
|
||||
// draw top part
|
||||
state |= _engine->_interface->drawLine(positions.frontTopLeftPoint2D.x, positions.frontTopLeftPoint2D.y, positions.backTopLeftPoint2D.x, positions.backTopLeftPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.backTopLeftPoint2D.x, positions.backTopLeftPoint2D.y, positions.backTopRightPoint2D.x, positions.backTopRightPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.backTopRightPoint2D.x, positions.backTopRightPoint2D.y, positions.frontTopRightPoint2D.x, positions.frontTopRightPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.frontTopRightPoint2D.x, positions.frontTopRightPoint2D.y, positions.frontTopLeftPoint2D.x, positions.frontTopLeftPoint2D.y, color);
|
||||
|
||||
// draw back part
|
||||
state |= _engine->_interface->drawLine(positions.backBottomLeftPoint2D.x, positions.backBottomLeftPoint2D.y, positions.backTopLeftPoint2D.x, positions.backTopLeftPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.backTopLeftPoint2D.x, positions.backTopLeftPoint2D.y, positions.backTopRightPoint2D.x, positions.backTopRightPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.backTopRightPoint2D.x, positions.backTopRightPoint2D.y, positions.backBottomRightPoint2D.x, positions.backBottomRightPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.backBottomRightPoint2D.x, positions.backBottomRightPoint2D.y, positions.backBottomLeftPoint2D.x, positions.backBottomLeftPoint2D.y, color);
|
||||
|
||||
// draw bottom part
|
||||
state |= _engine->_interface->drawLine(positions.frontBottomLeftPoint2D.x, positions.frontBottomLeftPoint2D.y, positions.backBottomLeftPoint2D.x, positions.backBottomLeftPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.backBottomLeftPoint2D.x, positions.backBottomLeftPoint2D.y, positions.backBottomRightPoint2D.x, positions.backBottomRightPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.backBottomRightPoint2D.x, positions.backBottomRightPoint2D.y, positions.frontBottomRightPoint2D.x, positions.frontBottomRightPoint2D.y, color);
|
||||
state |= _engine->_interface->drawLine(positions.frontBottomRightPoint2D.x, positions.frontBottomRightPoint2D.y, positions.frontBottomLeftPoint2D.x, positions.frontBottomLeftPoint2D.y, color);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void DebugState::changeGridCamera() {
|
||||
if (!_useFreeCamera) {
|
||||
return;
|
||||
}
|
||||
|
||||
Grid *grid = _engine->_grid;
|
||||
Redraw *redraw = _engine->_redraw;
|
||||
Input *input = _engine->_input;
|
||||
if (input->isActionActive(TwinEActionType::DebugGridCameraPressUp)) {
|
||||
grid->_startCube.z--;
|
||||
redraw->_firstTime = true;
|
||||
} else if (input->isActionActive(TwinEActionType::DebugGridCameraPressDown)) {
|
||||
grid->_startCube.z++;
|
||||
redraw->_firstTime = true;
|
||||
}
|
||||
if (input->isActionActive(TwinEActionType::DebugGridCameraPressLeft)) {
|
||||
grid->_startCube.x--;
|
||||
redraw->_firstTime = true;
|
||||
} else if (input->isActionActive(TwinEActionType::DebugGridCameraPressRight)) {
|
||||
grid->_startCube.x++;
|
||||
redraw->_firstTime = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool DebugState::displayActors() {
|
||||
bool state = false;
|
||||
for (int32 a = 0; a < _engine->_scene->_nbObjets; a++) {
|
||||
const ActorStruct *actorPtr = _engine->_scene->getActor(a);
|
||||
const IVec3 &pos = actorPtr->posObj();
|
||||
const BoundingBox &bbox = actorPtr->_boundingBox;
|
||||
const ScenePositionsProjected &positions = calculateBoxPositions(pos + bbox.mins, pos + bbox.maxs);
|
||||
if (!drawBox(positions, COLOR_WHITE)) {
|
||||
continue;
|
||||
}
|
||||
const int boxwidth = 75;
|
||||
const int lineHeight = 14;
|
||||
const Common::Rect filledRect(positions.frontTopRightPoint2D.x, positions.frontTopRightPoint2D.y, positions.frontTopRightPoint2D.x + boxwidth, positions.frontTopRightPoint2D.y + lineHeight);
|
||||
_engine->_interface->box(filledRect, COLOR_WHITE);
|
||||
_engine->_menu->drawRectBorders(filledRect);
|
||||
_engine->drawText(positions.frontTopRightPoint2D.x, positions.frontTopRightPoint2D.y, Common::String::format("Actor: %i", a), true, false, boxwidth);
|
||||
const int16 rleft = positions.frontTopLeftPoint2D.x;
|
||||
const int16 rtop = positions.backTopLeftPoint2D.y;
|
||||
const int16 rright = positions.backTopRightPoint2D.x;
|
||||
const int16 rbottom = positions.frontBottomRightPoint2D.y;
|
||||
Common::Rect actorRect(rleft, rtop, rright, rbottom);
|
||||
actorRect.extend(filledRect);
|
||||
_engine->_redraw->addPhysBox(actorRect);
|
||||
state = true;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// TODO: implement the rendering points of all tracks as a dot with the id
|
||||
bool DebugState::displayTracks() {
|
||||
#if 0
|
||||
for (int i = 0; i < _engine->_scene->sceneNumTracks; i++) {
|
||||
const Vec3 *trackPoint = &_engine->_scene->sceneTracks[i];
|
||||
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DebugState::displayZones() {
|
||||
bool state = false;
|
||||
for (int i = 0; i < _engine->_scene->_sceneNumZones; i++) {
|
||||
const ZoneStruct *zonePtr = &_engine->_scene->_sceneZones[i];
|
||||
|
||||
if (!checkZoneType(zonePtr->type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ScenePositionsProjected &positions = calculateBoxPositions(zonePtr->mins, zonePtr->maxs);
|
||||
const uint8 color = 15 * 3 + (int)zonePtr->type * 16;
|
||||
if (!drawBox(positions, color)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int boxwidth = 50;
|
||||
const int lineHeight = 14;
|
||||
const Common::Rect filledRect(positions.frontTopRightPoint2D.x, positions.frontTopRightPoint2D.y, positions.frontTopRightPoint2D.x + boxwidth, positions.frontTopRightPoint2D.y + lineHeight);
|
||||
_engine->_interface->box(filledRect, COLOR_WHITE);
|
||||
_engine->_menu->drawRectBorders(filledRect);
|
||||
_engine->drawText(positions.frontTopRightPoint2D.x, positions.frontTopRightPoint2D.y, Common::String::format("ID: %i", i), true, false, boxwidth);
|
||||
state = true;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void DebugState::addFrameData(uint32 frameTime, int32 waitMillis, uint32 maxDelay) {
|
||||
if (!_frameDataRecording) {
|
||||
return;
|
||||
}
|
||||
_frameData.emplace_back(frameTime, waitMillis, maxDelay);
|
||||
}
|
||||
|
||||
void DebugState::renderDebugView() {
|
||||
if (_showingZones) {
|
||||
displayZones();
|
||||
}
|
||||
if (_showingActors) {
|
||||
displayActors();
|
||||
}
|
||||
if (_showingTracks) {
|
||||
displayTracks();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TwinE
|
||||
122
engines/twine/debugger/debug_state.h
Normal file
122
engines/twine/debugger/debug_state.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TWINE_DEBUG_SCENE_H
|
||||
#define TWINE_DEBUG_SCENE_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "twine/debugger/ringbuffer.h"
|
||||
#include "twine/shared.h"
|
||||
#include <cstdarg>
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
class TwinEEngine;
|
||||
|
||||
class DebugState {
|
||||
private:
|
||||
TwinEEngine *_engine;
|
||||
|
||||
void projectBoundingBoxPoints(IVec3 *point3d, IVec3 *point3dProjected);
|
||||
bool checkZoneType(ZoneType type) const;
|
||||
bool displayZones();
|
||||
bool displayActors();
|
||||
bool displayTracks();
|
||||
|
||||
struct ScenePositionsProjected {
|
||||
IVec3 frontBottomLeftPoint;
|
||||
IVec3 frontBottomRightPoint;
|
||||
|
||||
IVec3 frontTopLeftPoint;
|
||||
IVec3 frontTopRightPoint;
|
||||
|
||||
IVec3 backBottomLeftPoint;
|
||||
IVec3 backBottomRightPoint;
|
||||
|
||||
IVec3 backTopLeftPoint;
|
||||
IVec3 backTopRightPoint;
|
||||
|
||||
IVec3 frontBottomLeftPoint2D;
|
||||
IVec3 frontBottomRightPoint2D;
|
||||
|
||||
IVec3 frontTopLeftPoint2D;
|
||||
IVec3 frontTopRightPoint2D;
|
||||
|
||||
IVec3 backBottomLeftPoint2D;
|
||||
IVec3 backBottomRightPoint2D;
|
||||
|
||||
IVec3 backTopLeftPoint2D;
|
||||
IVec3 backTopRightPoint2D;
|
||||
};
|
||||
|
||||
ScenePositionsProjected calculateBoxPositions(const IVec3 &mins, const IVec3 &maxs);
|
||||
bool drawBox(const ScenePositionsProjected &positions, uint8 color);
|
||||
|
||||
/** Change scenario camera positions */
|
||||
void changeGridCamera();
|
||||
|
||||
public:
|
||||
DebugState(TwinEEngine *engine);
|
||||
bool _showingZones = false;
|
||||
bool _showingActors = false;
|
||||
bool _showingTracks = false;
|
||||
bool _showingClips = false;
|
||||
bool _godMode = false;
|
||||
unsigned int _typeZones = 127; // all zones on as default
|
||||
int16 _onlyLoadActor = -1;
|
||||
const char *_openPopup = nullptr;
|
||||
bool _holomapFlagsWindow = false;
|
||||
bool _gameFlagsWindow = false;
|
||||
bool _menuTextWindow = false;
|
||||
bool _sceneDetailsWindow = false;
|
||||
bool _actorDetailsWindow = true;
|
||||
bool _sceneFlagsWindow = false;
|
||||
bool _paletteWindow = false;
|
||||
bool _loggerWindow = false;
|
||||
bool _frameTimeWindow = false;
|
||||
bool _frameDataRecording = true;
|
||||
bool _playFoundItemAnimation = false;
|
||||
|
||||
bool _useFreeCamera = false;
|
||||
bool _disableGridRendering = false;
|
||||
TextBankId _textBankId = TextBankId::Inventory_Intro_and_Holomap;
|
||||
|
||||
void renderDebugView();
|
||||
void drawClip(const Common::Rect &rect);
|
||||
|
||||
struct FrameData {
|
||||
uint32 frameTime;
|
||||
int32 waitMillis;
|
||||
uint32 maxDelay;
|
||||
};
|
||||
using FrameDataBuffer = RingBuffer<FrameData, 256>;
|
||||
FrameDataBuffer _frameData;
|
||||
|
||||
void addFrameData(uint32 frameTime, int32 waitMillis, uint32 maxDelay);
|
||||
|
||||
void update();
|
||||
};
|
||||
|
||||
} // namespace TwinE
|
||||
|
||||
#endif
|
||||
953
engines/twine/debugger/debugtools.cpp
Normal file
953
engines/twine/debugger/debugtools.cpp
Normal file
@@ -0,0 +1,953 @@
|
||||
/* 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 "twine/debugger/debugtools.h"
|
||||
#include "backends/imgui/components/imgui_logger.h"
|
||||
#include "backends/imgui/imgui.h"
|
||||
#include "backends/imgui/imgui_fonts.h"
|
||||
#include "backends/imgui/imgui_utils.h"
|
||||
#include "common/log.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str-enc.h"
|
||||
#include "common/str.h"
|
||||
#include "common/util.h"
|
||||
#include "graphics/palette.h"
|
||||
#include "twine/debugger/debug_state.h"
|
||||
#include "twine/debugger/dt-internal.h"
|
||||
#include "twine/holomap.h"
|
||||
#include "twine/holomap_v1.h"
|
||||
#include "twine/parser/entity.h"
|
||||
#include "twine/renderer/redraw.h"
|
||||
#include "twine/renderer/screens.h"
|
||||
#include "twine/resources/resources.h"
|
||||
#include "twine/scene/actor.h"
|
||||
#include "twine/scene/gamestate.h"
|
||||
#include "twine/scene/grid.h"
|
||||
#include "twine/scene/scene.h"
|
||||
|
||||
#include "twine/shared.h"
|
||||
#include "twine/twine.h"
|
||||
|
||||
namespace ImGuiEx {
|
||||
|
||||
bool InputIVec3(const char *label, TwinE::IVec3 &v, ImGuiInputTextFlags flags = 0) {
|
||||
int tmp[3] = {v.x, v.y, v.z};
|
||||
ImGui::InputInt3(label, tmp, flags);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
v.x = tmp[0];
|
||||
v.y = tmp[1];
|
||||
v.z = tmp[2];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputAngle(const char *label, int32 *v, int step = 1, int step_fast = 100, const char *format = "%.2f", ImGuiInputTextFlags flags = 0) {
|
||||
double tmp = TwinE::AngleToDegree(*v);
|
||||
if (ImGui::InputDouble(label, &tmp, step, step_fast, format, flags)) {
|
||||
*v = TwinE::DegreeToAngle(tmp);
|
||||
return true;
|
||||
}
|
||||
ImGui::SetItemTooltip("Angle: %i", (int)*v);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputBoundingBox(ImGuiID id, const char *prefixLabel, TwinE::BoundingBox &bbox) {
|
||||
TwinE::BoundingBox copy = bbox;
|
||||
Common::String idStr = Common::String::format("%s mins##mins%u", prefixLabel, id);
|
||||
if (ImGuiEx::InputIVec3(idStr.c_str(), copy.mins)) {
|
||||
if (copy.isValid()) {
|
||||
bbox.mins = copy.mins;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
idStr = Common::String::format("%s maxs##maxs%u", prefixLabel, id);
|
||||
if (ImGuiEx::InputIVec3(idStr.c_str(), copy.maxs)) {
|
||||
if (copy.isValid()) {
|
||||
bbox.maxs = copy.maxs;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ImGuiEx
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
#define HOLOMAP_FLAGS_TITLE "Holomap flags"
|
||||
#define GAME_FLAGS_TITLE "Game flags"
|
||||
#define ACTOR_DETAILS_TITLE "Actor"
|
||||
#define MENU_TEXT_TITLE "Menu texts"
|
||||
|
||||
static const char *toString(ShapeType type) {
|
||||
switch (type) {
|
||||
case ShapeType::kNone:
|
||||
return "None";
|
||||
case ShapeType::kSolid:
|
||||
return "Solid";
|
||||
case ShapeType::kStairsTopLeft:
|
||||
return "StairsTopLeft";
|
||||
case ShapeType::kStairsTopRight:
|
||||
return "StairsTopRight";
|
||||
case ShapeType::kStairsBottomLeft:
|
||||
return "StairsBottomLeft";
|
||||
case ShapeType::kStairsBottomRight:
|
||||
return "StairsBottomRight";
|
||||
case ShapeType::kDoubleSideStairsTop1:
|
||||
return "DoubleSideStairsTop1";
|
||||
case ShapeType::kDoubleSideStairsBottom1:
|
||||
return "DoubleSideStairsBottom1";
|
||||
case ShapeType::kDoubleSideStairsLeft1:
|
||||
return "DoubleSideStairsLeft1";
|
||||
case ShapeType::kDoubleSideStairsRight1:
|
||||
return "DoubleSideStairsRight1";
|
||||
case ShapeType::kDoubleSideStairsTop2:
|
||||
return "DoubleSideStairsTop2";
|
||||
case ShapeType::kDoubleSideStairsBottom2:
|
||||
return "DoubleSideStairsBottom2";
|
||||
case ShapeType::kDoubleSideStairsLeft2:
|
||||
return "DoubleSideStairsLeft2";
|
||||
case ShapeType::kDoubleSideStairsRight2:
|
||||
return "DoubleSideStairsRight2";
|
||||
case ShapeType::kFlatBottom1:
|
||||
return "FlatBottom1";
|
||||
case ShapeType::kFlatBottom2:
|
||||
return "FlatBottom2";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void onLog(LogMessageType::Type type, int level, uint32 debugChannel, const char *message) {
|
||||
switch (type) {
|
||||
case LogMessageType::kError:
|
||||
_logger->addLog("[error]%s", message);
|
||||
break;
|
||||
case LogMessageType::kWarning:
|
||||
_logger->addLog("[warn]%s", message);
|
||||
break;
|
||||
case LogMessageType::kInfo:
|
||||
_logger->addLog("%s", message);
|
||||
break;
|
||||
case LogMessageType::kDebug:
|
||||
_logger->addLog("[debug]%s", message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void onImGuiInit() {
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
ImFontConfig icons_config;
|
||||
icons_config.MergeMode = true;
|
||||
icons_config.PixelSnapH = false;
|
||||
icons_config.OversampleH = 3;
|
||||
icons_config.OversampleV = 3;
|
||||
icons_config.GlyphOffset = {0, 4};
|
||||
|
||||
static const ImWchar icons_ranges[] = {ICON_MIN_MS, ICON_MAX_MS, 0};
|
||||
ImGui::addTTFFontFromArchive("MaterialSymbolsSharp.ttf", 16.f, &icons_config, icons_ranges);
|
||||
|
||||
_tinyFont = ImGui::addTTFFontFromArchive("LiberationSans-Regular.ttf", 10.0f, nullptr, nullptr);
|
||||
|
||||
_logger = new ImGuiEx::ImGuiLogger;
|
||||
|
||||
Common::setLogWatcher(onLog);
|
||||
}
|
||||
|
||||
static void holomapFlagsWindow(TwinEEngine *engine) {
|
||||
if (!engine->_debugState->_holomapFlagsWindow) {
|
||||
return;
|
||||
}
|
||||
if (ImGui::Begin(HOLOMAP_FLAGS_TITLE, &engine->_debugState->_holomapFlagsWindow)) {
|
||||
if (ImGui::BeginTable("###holomapflags", 8)) {
|
||||
for (int i = 0; i < engine->numHoloPos(); ++i) {
|
||||
ImGui::TableNextColumn();
|
||||
Common::String id = Common::String::format("[%03d]", i);
|
||||
ImGuiEx::InputInt(id.c_str(), &engine->_gameState->_holomapFlags[i]);
|
||||
ImGui::SetItemTooltip("%s", engine->_holomap->getLocationName(i));
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
if (engine->isLBA1()) {
|
||||
HolomapV1 *holomap = (HolomapV1*)engine->_holomap;
|
||||
|
||||
ImGuiEx::InputInt("current", &holomap->_current);
|
||||
ImGuiEx::InputInt("otimer", &holomap->_otimer);
|
||||
ImGuiEx::InputInt("dalpha", &holomap->_dalpha);
|
||||
ImGuiEx::InputInt("dbeta", &holomap->_dbeta);
|
||||
ImGuiEx::InputInt("calpha", &holomap->_calpha);
|
||||
ImGuiEx::InputInt("cbeta", &holomap->_cbeta);
|
||||
ImGuiEx::InputInt("cgamma", &holomap->_cgamma);
|
||||
ImGuiEx::InputInt("oalpha", &holomap->_oalpha);
|
||||
ImGuiEx::InputInt("obeta", &holomap->_obeta);
|
||||
|
||||
ImGui::Checkbox("automove", &holomap->_automove);
|
||||
ImGui::Checkbox("flagredraw", &holomap->_flagredraw);
|
||||
ImGui::Checkbox("dialstat", &holomap->_dialstat);
|
||||
ImGui::Checkbox("flagpal", &holomap->_flagpal);
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static void paletteWindow(TwinEEngine *engine) {
|
||||
if (!engine->_debugState->_paletteWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ImVec2 available = ImGui::GetContentRegionAvail();
|
||||
const float contentRegionHeight = available.y + ImGui::GetCursorPosY();
|
||||
const ImVec2 windowSize(10.0f * ImGui::GetFrameHeight(), contentRegionHeight);
|
||||
ImGui::SetNextWindowSize(windowSize, ImGuiCond_FirstUseEver);
|
||||
|
||||
if (ImGui::Begin("Palettes", &engine->_debugState->_paletteWindow)) {
|
||||
if (engine->_screens->_flagPalettePcx) {
|
||||
ImGui::Text("palettepcx is active");
|
||||
} else {
|
||||
ImGui::Text("ptrpal is active");
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Front buffer palette");
|
||||
const Graphics::Palette &frontBufferPalette = engine->_frontVideoBuffer.getPalette();
|
||||
ImGui::PushID("frontBufferPalette");
|
||||
ImGuiEx::Palette(frontBufferPalette);
|
||||
ImGui::PopID();
|
||||
|
||||
ImGui::SeparatorText("PalettePCX");
|
||||
ImGui::PushID("palettePcx");
|
||||
ImGuiEx::Palette(engine->_screens->_palettePcx);
|
||||
ImGui::PopID();
|
||||
|
||||
ImGui::SeparatorText("Palette");
|
||||
ImGui::PushID("ptrPal");
|
||||
ImGuiEx::Palette(engine->_screens->_ptrPal);
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static float WaitTime(void *data, int i) {
|
||||
TwinE::DebugState::FrameDataBuffer &buffer = *(TwinE::DebugState::FrameDataBuffer *)data;
|
||||
return (float)buffer[i].waitMillis;
|
||||
}
|
||||
|
||||
static float FrameTime(void *data, int i) {
|
||||
TwinE::DebugState::FrameDataBuffer &buffer = *(TwinE::DebugState::FrameDataBuffer *)data;
|
||||
return (float)buffer[i].frameTime;
|
||||
}
|
||||
|
||||
static void frameTimeWindow(TwinEEngine *engine) {
|
||||
if (!engine->_debugState->_frameTimeWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::Begin("Frame time", &engine->_debugState->_frameTimeWindow)) {
|
||||
ImGui::Checkbox("Record", &engine->_debugState->_frameDataRecording);
|
||||
ImGui::PlotHistogram("Wait time", WaitTime, &engine->_debugState->_frameData, (int)engine->_debugState->_frameData.size(), 0, "Wait time in millis", -100.0f, 100.0f, ImVec2(0, 80));
|
||||
ImGui::PlotHistogram("Frame time", FrameTime, &engine->_debugState->_frameData, (int)engine->_debugState->_frameData.size(), 0, "Frame time in millis", -100.0f, 100.0f, ImVec2(0, 80));
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static void sceneFlagsWindow(TwinEEngine *engine) {
|
||||
if (!engine->_debugState->_sceneFlagsWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::Begin("Scene flags", &engine->_debugState->_sceneFlagsWindow)) {
|
||||
if (ImGui::BeginTable("###sceneflags", 8)) {
|
||||
for (int i = 0; i < NUM_SCENES_FLAGS; ++i) {
|
||||
ImGui::TableNextColumn();
|
||||
Common::String id = Common::String::format("[%03d]", i);
|
||||
ImGuiEx::InputInt(id.c_str(), &engine->_scene->_listFlagCube[i]);
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static void gameFlagsWindow(TwinEEngine *engine) {
|
||||
if (!engine->_debugState->_gameFlagsWindow) {
|
||||
return;
|
||||
}
|
||||
if (ImGui::Begin(GAME_FLAGS_TITLE, &engine->_debugState->_gameFlagsWindow)) {
|
||||
ImGui::Text("Chapter %i", engine->_gameState->getChapter());
|
||||
if (ImGui::BeginTable("###gameflags", 8)) {
|
||||
for (int i = 0; i < NUM_GAME_FLAGS; ++i) {
|
||||
ImGui::TableNextColumn();
|
||||
Common::String id = Common::String::format("[%03d]", i);
|
||||
int16 val = engine->_gameState->hasGameFlag(i);
|
||||
if (ImGuiEx::InputInt(id.c_str(), &val)) {
|
||||
engine->_gameState->setGameFlag(i, val);
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static void menuTextsWindow(TwinEEngine *engine) {
|
||||
if (!engine->_debugState->_menuTextWindow) {
|
||||
return;
|
||||
}
|
||||
if (ImGui::Begin(MENU_TEXT_TITLE, &engine->_debugState->_menuTextWindow)) {
|
||||
int id = (int)engine->_debugState->_textBankId;
|
||||
if (ImGui::InputInt("Text bank", &id)) {
|
||||
engine->_debugState->_textBankId = (TextBankId)id;
|
||||
}
|
||||
const TextBankId oldTextBankId = engine->_text->textBank();
|
||||
engine->_text->initDial(engine->_debugState->_textBankId);
|
||||
for (int32 i = 0; i < 1000; ++i) {
|
||||
char buf[256];
|
||||
if (engine->_text->getMenuText((TextId)i, buf, sizeof(buf))) {
|
||||
ImGui::Text("%4i: %s\n", i, buf);
|
||||
}
|
||||
}
|
||||
engine->_text->initDial(oldTextBankId);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static void sceneSelectionCombo(TwinEEngine *engine) {
|
||||
Scene *scene = engine->_scene;
|
||||
GameState *gameState = engine->_gameState;
|
||||
Common::U32String originalSceneName(gameState->_sceneName, Common::kDos850);
|
||||
const Common::String sceneName = originalSceneName.encode(Common::kUtf8);
|
||||
if (ImGui::BeginCombo("Scene", sceneName.c_str())) {
|
||||
for (int i = 0; i < engine->numHoloPos(); ++i) {
|
||||
Common::U32String originalLocationName(engine->_holomap->getLocationName(i), Common::kDos850);
|
||||
const Common::String locationName = originalLocationName.encode(Common::kUtf8);
|
||||
Common::String name = Common::String::format("[%03d] %s", i, locationName.c_str());
|
||||
if (ImGui::Selectable(name.c_str(), i == engine->_scene->_numCube)) {
|
||||
scene->_numCube = i;
|
||||
scene->_newCube = scene->_numCube;
|
||||
engine->_redraw->_firstTime = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
static const struct ZonesDesc {
|
||||
const char *name;
|
||||
ZoneType type;
|
||||
const char *desc;
|
||||
} ZoneDescriptions[] = {
|
||||
{"Cube", ZoneType::kCube, "Change to another scene"},
|
||||
{"Camera", ZoneType::kCamera, "Binds camera view"},
|
||||
{"Sceneric", ZoneType::kSceneric, "For use in Life Script"},
|
||||
{"Grid", ZoneType::kGrid, "Set disappearing Grid fragment"},
|
||||
{"Object", ZoneType::kObject, "Give bonus"},
|
||||
{"Text", ZoneType::kText, "Displays text message"},
|
||||
{"Ladder", ZoneType::kLadder, "Hero can climb on it"},
|
||||
{"Escalator", ZoneType::kEscalator, nullptr},
|
||||
{"Hit", ZoneType::kHit, nullptr},
|
||||
{"Rail", ZoneType::kRail, nullptr}};
|
||||
|
||||
static void sceneDetailsWindows(TwinEEngine *engine) {
|
||||
if (!engine->_debugState->_sceneDetailsWindow) {
|
||||
return;
|
||||
}
|
||||
if (ImGui::Begin("Scene", &engine->_debugState->_sceneDetailsWindow)) {
|
||||
Scene *scene = engine->_scene;
|
||||
GameState *gameState = engine->_gameState;
|
||||
ImGui::Text("Scene: %i", scene->_numCube);
|
||||
ImGui::Text("Scene name: %s", gameState->_sceneName);
|
||||
sceneSelectionCombo(engine);
|
||||
|
||||
if (ImGui::Checkbox("Bounding boxes", &engine->_debugState->_showingActors)) {
|
||||
engine->_redraw->_firstTime = true;
|
||||
}
|
||||
if (ImGui::Checkbox("Clipping", &engine->_debugState->_showingClips)) {
|
||||
engine->_redraw->_firstTime = true;
|
||||
}
|
||||
if (ImGui::Checkbox("Zones", &engine->_debugState->_showingZones)) {
|
||||
engine->_redraw->_firstTime = true;
|
||||
}
|
||||
// if (ImGui::Checkbox("Tracks", &engine->_debugState->_showingTracks)) {
|
||||
// engine->_redraw->_firstTime = true;
|
||||
// }
|
||||
if (engine->_debugState->_showingZones) {
|
||||
if (ImGui::CollapsingHeader("Show zone types")) {
|
||||
for (int i = 0; i < ARRAYSIZE(ZoneDescriptions); ++i) {
|
||||
if (ImGui::CheckboxFlags(ZoneDescriptions[i].name, &engine->_debugState->_typeZones, (1u << (uint32)ZoneDescriptions[i].type))) {
|
||||
engine->_redraw->_firstTime = true;
|
||||
}
|
||||
if (ZoneDescriptions[i].desc) {
|
||||
ImGui::SetItemTooltip(ZoneDescriptions[i].desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Zones##zonesheader")) {
|
||||
for (int i = 0; i < scene->_sceneNumZones; ++i) {
|
||||
ZoneStruct *zone = &scene->_sceneZones[i];
|
||||
ImGui::Text("Zone idx: %i", i);
|
||||
ImGui::Indent();
|
||||
const ZonesDesc &zoneDesc = ZoneDescriptions[(int)zone->type];
|
||||
ImGui::Text("Type: %s", zoneDesc.name);
|
||||
if (zoneDesc.desc != nullptr) {
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", zoneDesc.desc);
|
||||
}
|
||||
ImGui::PushID(i);
|
||||
ImGuiEx::InputIVec3("Mins", zone->mins);
|
||||
ImGuiEx::InputIVec3("Maxs", zone->maxs);
|
||||
ImGui::PopID();
|
||||
|
||||
ImGui::Text("Num: %i", zone->num);
|
||||
ImGui::Text("Info0: %i", zone->infoData.generic.info0);
|
||||
ImGui::Text("Info1: %i", zone->infoData.generic.info1);
|
||||
ImGui::Text("Info2: %i", zone->infoData.generic.info2);
|
||||
ImGui::Text("Info3: %i", zone->infoData.generic.info3);
|
||||
ImGui::Text("Info4: %i", zone->infoData.generic.info4);
|
||||
ImGui::Text("Info5: %i", zone->infoData.generic.info5);
|
||||
ImGui::Text("Info6: %i", zone->infoData.generic.info6);
|
||||
ImGui::Text("Info7: %i", zone->infoData.generic.info7);
|
||||
ImGui::Unindent();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Tracks##tracksheader")) {
|
||||
for (int i = 0; i < scene->_sceneNumTracks; ++i) {
|
||||
ImGui::Text("Track %i: %i %i %i", i, scene->_sceneTracks[i].x, scene->_sceneTracks[i].y, scene->_sceneTracks[i].z);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Trajectories##trajectoriesheader")) {
|
||||
const TrajectoryData &trajectories = engine->_resources->getTrajectories();
|
||||
for (int i = 0; i < (int)trajectories.getTrajectories().size(); ++i) {
|
||||
const Trajectory *trajectory = trajectories.getTrajectory(i);
|
||||
ImGui::Text("Trajectory %i", i);
|
||||
ImGui::SameLine();
|
||||
Common::String buttonId = Common::String::format("Activate##activateTrajectory%i", i);
|
||||
if (ImGui::Button(buttonId.c_str())) {
|
||||
scene->_numHolomapTraj = i;
|
||||
scene->reloadCurrentScene();
|
||||
}
|
||||
ImGui::Indent();
|
||||
ImGui::Text("location: %i", trajectory->locationIdx);
|
||||
ImGui::Text("trajectory location: %i", trajectory->trajLocationIdx);
|
||||
ImGui::Text("vehicle: %i", trajectory->vehicleIdx);
|
||||
ImGui::Text("pos: %i %i %i", trajectory->angle.x, trajectory->angle.y, trajectory->angle.z);
|
||||
ImGui::Text("num anim frames: %i", trajectory->numAnimFrames);
|
||||
ImGui::Unindent();
|
||||
}
|
||||
}
|
||||
ImGuiEx::InputInt("Previous scene index", &scene->_oldcube);
|
||||
ImGuiEx::InputInt("Need change scene index", &scene->_newCube);
|
||||
|
||||
ImGui::Text("Climbing flag");
|
||||
ImGui::SameLine();
|
||||
ImGuiEx::Boolean(scene->_flagClimbing);
|
||||
|
||||
ImGuiEx::InputInt("Currently followed actor", &scene->_numObjFollow);
|
||||
|
||||
ImGui::Checkbox("Render grid tiles", &scene->_flagRenderGrid);
|
||||
ImGuiEx::InputInt("Current script value", &scene->_currentScriptValue);
|
||||
ImGuiEx::InputInt("Talking actor", &scene->_talkingActor);
|
||||
ImGuiEx::InputInt("Cube jingle", &scene->_cubeJingle);
|
||||
ImGuiEx::InputIVec3("New hero pos", scene->_sceneStart);
|
||||
ImGuiEx::InputInt("Alpha light", &scene->_alphaLight);
|
||||
ImGuiEx::InputInt("Beta light", &scene->_betaLight);
|
||||
ImGuiEx::InputInt("Fall Y position", &scene->_startYFalling);
|
||||
ImGui::Text("Hero position type: %i", (int)scene->_flagChgCube);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static void actorDetailsWindow(int &actorIdx, TwinEEngine *engine) {
|
||||
if (!engine->_debugState->_actorDetailsWindow) {
|
||||
return;
|
||||
}
|
||||
ActorStruct *actor = engine->_scene->getActor(actorIdx);
|
||||
if (actor == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::Begin(ACTOR_DETAILS_TITLE, &engine->_debugState->_actorDetailsWindow)) {
|
||||
if (actorIdx < 0 || actorIdx > engine->_scene->_nbObjets) {
|
||||
actorIdx = 0;
|
||||
}
|
||||
Common::String currentActorLabel = Common::String::format("Actor %i", actorIdx);
|
||||
if (ImGui::BeginCombo("Actor", currentActorLabel.c_str())) {
|
||||
for (int i = 0; i < engine->_scene->_nbObjets; ++i) {
|
||||
Common::String label = Common::String::format("Actor %i", i);
|
||||
if (engine->_scene->_mecaPenguinIdx == i) {
|
||||
label += " (Penguin)";
|
||||
}
|
||||
const bool selected = i == actorIdx;
|
||||
if (ImGui::Selectable(label.c_str(), selected)) {
|
||||
actorIdx = i;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGuiEx::InputIVec3("Pos", actor->_posObj);
|
||||
ImGuiEx::InputAngle("Rotation", &actor->_beta);
|
||||
ImGuiEx::InputInt("Rotation speed", &actor->_srot);
|
||||
ImGuiEx::InputInt("Life", &actor->_lifePoint);
|
||||
ImGuiEx::InputInt("Armor", &actor->_armor);
|
||||
ImGuiEx::InputBoundingBox(actorIdx, "Bounding box", actor->_boundingBox);
|
||||
|
||||
if (ImGui::CollapsingHeader("Properties")) {
|
||||
if (ImGui::BeginTable("Properties", 2)) {
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Followed");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_followedActor);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Control mode");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_move);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Delay");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_delayInMillis);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Strength");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_hitForce);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Hit by");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_hitBy);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Bonus");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_bonusParameter);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("ZoneSce");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_zoneSce);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Brick shape");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", toString(actor->brickShape()));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Brick causes damage");
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiEx::Boolean(actor->brickCausesDamage());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Collision");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_objCol);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Carried by");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_carryBy);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Talk color");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_talkColor);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Body");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_body); // TODO: link to resources
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Gen body");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_genBody);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Save gen body");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_saveGenBody);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Gen anim");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_genAnim);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Next gen anim");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_nextGenAnim);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Ptr anim action");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_ptrAnimAction);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Sprite");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i", actor->_sprite);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("A3DS");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%i %i %i", actor->A3DS.Num, actor->A3DS.Deb, actor->A3DS.Fin);
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Work Flags")) {
|
||||
static const char *Names[] = {
|
||||
"WAIT_HIT_FRAME",
|
||||
"OK_HIT",
|
||||
"ANIM_END",
|
||||
"NEW_FRAME",
|
||||
"WAS_DRAWN",
|
||||
"OBJ_DEAD",
|
||||
"AUTO_STOP_DOOR",
|
||||
"ANIM_MASTER_ROT",
|
||||
"FALLING",
|
||||
"IS_TARGETABLE",
|
||||
"IS_BLINKING",
|
||||
"DRAW_SHADOW",
|
||||
"ANIM_MASTER_GRAVITY",
|
||||
"SKATING",
|
||||
"OK_RENVOIE",
|
||||
"LEFT_JUMP",
|
||||
"RIGHT_JUMP",
|
||||
"WAIT_SUPER_HIT",
|
||||
"TRACK_MASTER_ROT",
|
||||
"FLY_JETPACK",
|
||||
"DONT_PICK_CODE_JEU",
|
||||
"MANUAL_INTER_FRAME",
|
||||
"WAIT_COORD",
|
||||
"CHECK_FALLING"};
|
||||
if (ImGui::BeginTable("##workflags", 6)) {
|
||||
for (int i = 0; i < ARRAYSIZE(Names); ++i) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::CheckboxFlags(Names[i], (uint32_t *)&actor->_workFlags, (1 << i));
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
if (ImGui::CollapsingHeader("Flags")) {
|
||||
static const char *Names[] = {
|
||||
"CHECK_OBJ_COL",
|
||||
"CHECK_BRICK_COL",
|
||||
"CHECK_ZONE",
|
||||
"SPRITE_CLIP",
|
||||
"PUSHABLE",
|
||||
"COL_BASSE",
|
||||
"CHECK_CODE_JEU",
|
||||
"CHECK_WATER_COL",
|
||||
"0x000100",
|
||||
"INVISIBLE",
|
||||
"SPRITE_3D",
|
||||
"OBJ_FALLABLE",
|
||||
"NO_SHADOW",
|
||||
"OBJ_BACKGROUND",
|
||||
"OBJ_CARRIER",
|
||||
"MINI_ZV",
|
||||
"POS_INVALIDE",
|
||||
"NO_CHOC",
|
||||
"ANIM_3DS",
|
||||
"NO_PRE_CLIP",
|
||||
"OBJ_ZBUFFER",
|
||||
"OBJ_IN_WATER",
|
||||
};
|
||||
if (ImGui::BeginTable("##staticflags", 6)) {
|
||||
for (int i = 0; i < ARRAYSIZE(Names); ++i) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::CheckboxFlags(Names[i], (uint32_t *)&actor->_flags, (1 << i));
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
if (actor->_body != -1) {
|
||||
ImGui::SeparatorText("Body");
|
||||
if (actor->_entityDataPtr != nullptr) {
|
||||
BodyData &bodyData = actor->_entityDataPtr->getBody(actor->_body);
|
||||
ImGuiEx::InputBoundingBox((int)(uintptr)&bodyData, "Bounding box", bodyData.bbox);
|
||||
} else {
|
||||
ImGui::Text("No entity data");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Entity");
|
||||
EntityData &entityData = actor->_entityData;
|
||||
Common::Array<EntityBody> &entityBodies = entityData.getBodies();
|
||||
ImGui::Text("Bodies: %i", (int)entityBodies.size());
|
||||
for (EntityBody &entityBody : entityBodies) {
|
||||
ImGui::Text("%s index: %i", Resources::HQR_FILE3D_FILE, entityBody.index);
|
||||
ImGui::Indent();
|
||||
ImGui::Text("%s index: %i", Resources::HQR_BODY_FILE, entityBody.hqrBodyIndex);
|
||||
Common::String id = Common::String::format("Has bounding box##%i", entityBody.index);
|
||||
ImGui::Checkbox(id.c_str(), &entityBody.actorBoundingBox.hasBoundingBox);
|
||||
ImGuiEx::InputBoundingBox((int)(uintptr)&entityBody, "Bounding box", entityBody.actorBoundingBox.bbox);
|
||||
ImGui::Unindent();
|
||||
}
|
||||
Common::Array<EntityAnim> &animations = entityData.getAnimations();
|
||||
ImGui::Text("Animations: %i", (int)animations.size());
|
||||
for (EntityAnim &animation : animations) {
|
||||
ImGui::Text("Animation type: %i", (int)animation.animation);
|
||||
ImGui::Indent();
|
||||
ImGui::Text("Body animation index: %i", (int)animation.animIndex);
|
||||
ImGui::Text("actions: %i", (int)animation._actions.size());
|
||||
for (EntityAnim::Action &action : animation._actions) {
|
||||
ImGui::BulletText("%i", (int)action.type);
|
||||
}
|
||||
ImGui::Unindent();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static void gameStateMenu(TwinEEngine *engine) {
|
||||
if (ImGui::BeginMenu("Game State")) {
|
||||
int keys = engine->_gameState->_nbLittleKeys;
|
||||
if (ImGui::InputInt("Keys", &keys)) {
|
||||
engine->_gameState->setKeys(keys);
|
||||
}
|
||||
int kashes = engine->_gameState->_goldPieces;
|
||||
if (ImGui::InputInt("Cash", &kashes)) {
|
||||
engine->_gameState->setKashes(kashes);
|
||||
}
|
||||
int zlitos = engine->_gameState->_zlitosPieces;
|
||||
if (ImGui::InputInt("Zlitos", &zlitos)) {
|
||||
engine->_gameState->setZlitos(zlitos);
|
||||
}
|
||||
int magicPoints = engine->_gameState->_magicPoint;
|
||||
if (ImGui::InputInt("Magic points", &magicPoints)) {
|
||||
engine->_gameState->setMagicPoints(magicPoints);
|
||||
}
|
||||
int magicLevel = engine->_gameState->_magicLevelIdx;
|
||||
if (ImGui::InputInt("Magic level", &magicLevel)) {
|
||||
engine->_gameState->_magicLevelIdx = CLIP<int16>(magicLevel, 0, 4);
|
||||
}
|
||||
int leafs = engine->_gameState->_inventoryNumLeafs;
|
||||
if (ImGui::InputInt("Leafs", &leafs)) {
|
||||
engine->_gameState->setLeafs(leafs);
|
||||
}
|
||||
int leafBoxes = engine->_gameState->_inventoryNumLeafsBox;
|
||||
if (ImGui::InputInt("Leaf boxes", &leafBoxes)) {
|
||||
engine->_gameState->setLeafBoxes(leafBoxes);
|
||||
}
|
||||
int gas = engine->_gameState->_inventoryNumGas;
|
||||
if (ImGui::InputInt("Gas", &gas)) {
|
||||
engine->_gameState->setGas(gas);
|
||||
}
|
||||
const TextBankId oldTextBankId = engine->_text->textBank();
|
||||
engine->_text->initDial(TextBankId::Inventory_Intro_and_Holomap);
|
||||
|
||||
for (int i = 0; i < NUM_INVENTORY_ITEMS; ++i) {
|
||||
Common::String label;
|
||||
if (engine->_text->getText((TextId)(100 + i))) {
|
||||
Common::U32String original(engine->_text->_currDialTextEntry->string, Common::kDos850);
|
||||
label = original.encode(Common::kUtf8).substr(0, 30);
|
||||
} else {
|
||||
label = Common::String::format("Item %i", i);
|
||||
}
|
||||
uint8 &value = engine->_gameState->_inventoryFlags[i];
|
||||
bool hasItem = value != 0;
|
||||
if (ImGui::Checkbox(label.c_str(), &hasItem)) {
|
||||
value = hasItem == 0 ? 0 : 1;
|
||||
}
|
||||
}
|
||||
engine->_text->initDial(oldTextBankId);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
static void gridMenu(TwinEEngine *engine) {
|
||||
if (ImGui::BeginMenu("Grid")) {
|
||||
ImGui::Text("World cube %i %i %i", engine->_grid->_worldCube.x, engine->_grid->_worldCube.y, engine->_grid->_worldCube.z);
|
||||
#if 0
|
||||
Grid *grid = engine->_grid;
|
||||
|
||||
if (ImGui::Button(ICON_MS_ADD)) {
|
||||
grid->_cellingGridIdx++;
|
||||
if (grid->_cellingGridIdx > 133) {
|
||||
grid->_cellingGridIdx = 133;
|
||||
}
|
||||
}
|
||||
if (ImGui::Button(ICON_MS_REMOVE)) {
|
||||
grid->_cellingGridIdx--;
|
||||
if (grid->_cellingGridIdx < 0) {
|
||||
grid->_cellingGridIdx = 0;
|
||||
}
|
||||
}
|
||||
// Enable/disable celling grid
|
||||
if (ImGui::Button("Apply ceiling grid")) {
|
||||
if (grid->_useCellingGrid == -1) {
|
||||
grid->_useCellingGrid = 1;
|
||||
// grid->createGridMap();
|
||||
grid->initCellingGrid(grid->_cellingGridIdx);
|
||||
debug("Enable Celling Grid index: %d", grid->_cellingGridIdx);
|
||||
engine->_scene->_needChangeScene = SCENE_CEILING_GRID_FADE_2; // tricky to make the fade
|
||||
} else if (grid->_useCellingGrid == 1) {
|
||||
grid->_useCellingGrid = -1;
|
||||
grid->copyMapToCube();
|
||||
engine->_redraw->_firstTime = true;
|
||||
debug("Disable Celling Grid index: %d", grid->_cellingGridIdx);
|
||||
engine->_scene->_needChangeScene = SCENE_CEILING_GRID_FADE_2; // tricky to make the fade
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
static void debuggerMenu(TwinEEngine *engine) {
|
||||
if (ImGui::BeginMenu("Debugger")) {
|
||||
ImGui::Text("Timer: %i", (int)engine->timerRef);
|
||||
if (ImGui::MenuItem("Logs")) {
|
||||
engine->_debugState->_loggerWindow = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Texts")) {
|
||||
engine->_debugState->_menuTextWindow = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Holomap flags")) {
|
||||
engine->_debugState->_holomapFlagsWindow = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Game flags")) {
|
||||
engine->_debugState->_gameFlagsWindow = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Scene details")) {
|
||||
engine->_debugState->_sceneDetailsWindow = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Scene flags")) {
|
||||
engine->_debugState->_sceneFlagsWindow = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Actor details")) {
|
||||
engine->_debugState->_actorDetailsWindow = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Frame time")) {
|
||||
engine->_debugState->_frameTimeWindow = true;
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Actions");
|
||||
|
||||
if (ImGui::MenuItem("Center actor")) {
|
||||
ActorStruct *actor = engine->_scene->getActor(OWN_ACTOR_SCENE_INDEX);
|
||||
actor->_posObj = engine->_grid->_worldCube;
|
||||
actor->_posObj.y += 16 * SIZE_BRICK_Y;
|
||||
int32 y = actor->_posObj.y - 1 - SIZE_BRICK_Y;
|
||||
while (y > 0 && ShapeType::kNone == engine->_grid->worldColBrick(actor->_posObj.x, y, actor->_posObj.z)) {
|
||||
y -= SIZE_BRICK_Y;
|
||||
}
|
||||
actor->_posObj.y = (y + SIZE_BRICK_Y) & ~(SIZE_BRICK_Y - 1);
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Animations")) {
|
||||
if (ImGui::MenuItem("Found item")) {
|
||||
engine->_debugState->_playFoundItemAnimation = true;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Palettes")) {
|
||||
LifeScriptContext fakeCtx(0, engine->_scene->_sceneHero);
|
||||
if (ImGui::MenuItem("Show palette")) {
|
||||
engine->_debugState->_paletteWindow = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Dark palette")) {
|
||||
engine->_scriptLife->lSET_DARK_PAL(engine, fakeCtx);
|
||||
}
|
||||
if (ImGui::MenuItem("Normal palette")) {
|
||||
engine->_scriptLife->lSET_NORMAL_PAL(engine, fakeCtx);
|
||||
}
|
||||
#if 0
|
||||
// TODO: the fade functions are blocking and break the imgui begin/end cycle
|
||||
if (ImGui::MenuItem("lFADE_PAL_RED")) {
|
||||
engine->_scriptLife->lFADE_PAL_RED(engine, fakeCtx);
|
||||
}
|
||||
if (ImGui::MenuItem("lFADE_ALARM_RED")) {
|
||||
engine->_scriptLife->lFADE_ALARM_RED(engine, fakeCtx);
|
||||
}
|
||||
if (ImGui::MenuItem("lFADE_ALARM_PAL")) {
|
||||
engine->_scriptLife->lFADE_ALARM_PAL(engine, fakeCtx);
|
||||
}
|
||||
if (ImGui::MenuItem("lFADE_RED_PAL")) {
|
||||
engine->_scriptLife->lFADE_RED_PAL(engine, fakeCtx);
|
||||
}
|
||||
if (ImGui::MenuItem("lFADE_RED_ALARM")) {
|
||||
engine->_scriptLife->lFADE_RED_ALARM(engine, fakeCtx);
|
||||
}
|
||||
if (ImGui::MenuItem("lFADE_PAL_ALARM")) {
|
||||
engine->_scriptLife->lFADE_PAL_ALARM(engine, fakeCtx);
|
||||
}
|
||||
#endif
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::MenuItem("Force Redraw")) {
|
||||
engine->_redraw->_firstTime = true;
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Options");
|
||||
|
||||
ImGui::Checkbox("Free camera", &engine->_debugState->_useFreeCamera);
|
||||
ImGui::Checkbox("God mode", &engine->_debugState->_godMode);
|
||||
|
||||
sceneSelectionCombo(engine);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void onImGuiRender() {
|
||||
if (!debugChannelSet(-1, kDebugImGui)) {
|
||||
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse;
|
||||
return;
|
||||
}
|
||||
static int currentActor = 0;
|
||||
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.ConfigFlags &= ~(ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse);
|
||||
|
||||
ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
|
||||
TwinEEngine *engine = (TwinEEngine *)g_engine;
|
||||
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
debuggerMenu(engine);
|
||||
gameStateMenu(engine);
|
||||
gridMenu(engine);
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
|
||||
actorDetailsWindow(currentActor, engine);
|
||||
sceneDetailsWindows(engine);
|
||||
menuTextsWindow(engine);
|
||||
holomapFlagsWindow(engine);
|
||||
gameFlagsWindow(engine);
|
||||
paletteWindow(engine);
|
||||
sceneFlagsWindow(engine);
|
||||
frameTimeWindow(engine);
|
||||
_logger->draw("Logger", &engine->_debugState->_loggerWindow);
|
||||
|
||||
if (engine->_debugState->_openPopup) {
|
||||
ImGui::OpenPopup(engine->_debugState->_openPopup);
|
||||
engine->_debugState->_openPopup = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void onImGuiCleanup() {
|
||||
Common::setLogWatcher(nullptr);
|
||||
delete _logger;
|
||||
_logger = nullptr;
|
||||
}
|
||||
|
||||
} // namespace TwinE
|
||||
31
engines/twine/debugger/debugtools.h
Normal file
31
engines/twine/debugger/debugtools.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TWINE_DEBUGGER_DEBUGTOOLS_H
|
||||
#define TWINE_DEBUGGER_DEBUGTOOLS_H
|
||||
|
||||
namespace TwinE {
|
||||
void onImGuiInit();
|
||||
void onImGuiRender();
|
||||
void onImGuiCleanup();
|
||||
} // namespace TwinE
|
||||
|
||||
#endif
|
||||
34
engines/twine/debugger/dt-internal.h
Normal file
34
engines/twine/debugger/dt-internal.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TWINE_DEBUGGER_DT_INTERNAL_H
|
||||
#define TWINE_DEBUGGER_DT_INTERNAL_H
|
||||
|
||||
#include "backends/imgui/components/imgui_logger.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
ImFont *_tinyFont = nullptr;
|
||||
ImGuiEx::ImGuiLogger *_logger = nullptr;
|
||||
|
||||
} // namespace TwinE
|
||||
|
||||
#endif
|
||||
215
engines/twine/debugger/ringbuffer.h
Normal file
215
engines/twine/debugger/ringbuffer.h
Normal file
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/util.h"
|
||||
#include <stddef.h>
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
/**
|
||||
* @brief Non allocating buffer class holds a maximum of given entries and allows an endless insert
|
||||
* by overrinding previous elements in the buffer
|
||||
*/
|
||||
template<typename TYPE, size_t SIZE = 64u>
|
||||
class RingBuffer {
|
||||
protected:
|
||||
size_t _size;
|
||||
size_t _front;
|
||||
size_t _back;
|
||||
TYPE _buffer[SIZE];
|
||||
|
||||
public:
|
||||
using value_type = TYPE;
|
||||
|
||||
RingBuffer() : _size(0u), _front(0u), _back(SIZE - 1u) {
|
||||
}
|
||||
|
||||
class iterator {
|
||||
private:
|
||||
RingBuffer *_ringBuffer;
|
||||
size_t _idx;
|
||||
|
||||
public:
|
||||
iterator(RingBuffer *ringBuffer, size_t idx) : _ringBuffer(ringBuffer), _idx(idx) {
|
||||
}
|
||||
|
||||
inline const TYPE &operator*() const {
|
||||
return _ringBuffer->_buffer[_idx % _ringBuffer->capacity()];
|
||||
}
|
||||
|
||||
inline TYPE &operator*() {
|
||||
return _ringBuffer->_buffer[_idx % _ringBuffer->capacity()];
|
||||
}
|
||||
|
||||
inline const TYPE &operator()() const {
|
||||
return _ringBuffer->_buffer[_idx % _ringBuffer->capacity()];
|
||||
}
|
||||
|
||||
inline TYPE &operator()() {
|
||||
return _ringBuffer->_buffer[_idx % _ringBuffer->capacity()];
|
||||
}
|
||||
|
||||
iterator &operator++() {
|
||||
++_idx;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator!=(const iterator &rhs) const {
|
||||
return _ringBuffer != rhs._ringBuffer || _idx != rhs._idx;
|
||||
}
|
||||
|
||||
inline bool operator==(const iterator &rhs) const {
|
||||
return _ringBuffer == rhs._ringBuffer && _idx == rhs._idx;
|
||||
}
|
||||
|
||||
inline const TYPE *operator->() const {
|
||||
return &_ringBuffer->_buffer[_idx % _ringBuffer->capacity()];
|
||||
}
|
||||
};
|
||||
|
||||
iterator begin() {
|
||||
return iterator(this, _front);
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return iterator(this, _front + _size);
|
||||
}
|
||||
|
||||
iterator begin() const {
|
||||
return iterator(const_cast<RingBuffer *>(this), _front);
|
||||
}
|
||||
|
||||
iterator end() const {
|
||||
return iterator(const_cast<RingBuffer *>(this), _front + _size);
|
||||
}
|
||||
|
||||
inline size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
constexpr size_t capacity() const {
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
inline bool empty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access to the first element in the buffer
|
||||
* @note This is not the same as accessing the index 0 element
|
||||
*/
|
||||
const TYPE &front() const {
|
||||
return _buffer[_front];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access to the first element in the buffer
|
||||
* @note This is not the same as accessing the index 0 element
|
||||
*/
|
||||
TYPE &front() {
|
||||
return _buffer[_front];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access to the last element in the buffer
|
||||
* @note This is not the same as accessing the index @c size-1 element
|
||||
*/
|
||||
const TYPE &back() const {
|
||||
return _buffer[_back];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access to the last element in the buffer
|
||||
* @note This is not the same as accessing the index @c size-1 element
|
||||
*/
|
||||
TYPE &back() {
|
||||
return _buffer[_back];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the whole ring buffer
|
||||
* @note Does not call any destructors - they are called when the buffer itself gets destroyed
|
||||
*/
|
||||
void clear() {
|
||||
_front = 0u;
|
||||
_back = SIZE - 1u;
|
||||
_size = 0u;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pushes an element to the end of the buffer
|
||||
*/
|
||||
void push_back(const TYPE &x) {
|
||||
_back = (_back + 1u) % SIZE;
|
||||
if (_size == SIZE) {
|
||||
_front = (_front + 1u) % SIZE;
|
||||
} else {
|
||||
++_size;
|
||||
}
|
||||
_buffer[_back] = x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pushes an elements to the end of the buffer
|
||||
* @note Performs a move operation
|
||||
*/
|
||||
template<typename... _Args>
|
||||
void emplace_back(_Args &&...args) {
|
||||
_back = (_back + 1u) % SIZE;
|
||||
if (_size == SIZE) {
|
||||
_front = (_front + 1u) % SIZE;
|
||||
} else {
|
||||
++_size;
|
||||
}
|
||||
_buffer[_back] = Common::move(TYPE{Common::forward<_Args>(args)...});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes element from the beginning of the buffer
|
||||
*/
|
||||
void pop() {
|
||||
if (_size == 0) {
|
||||
return;
|
||||
}
|
||||
--_size;
|
||||
_front = (_front + 1u) % SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase the given amount of elements from the end of the buffer
|
||||
*/
|
||||
void erase_back(const size_t n) {
|
||||
if (n >= _size) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
_size -= n;
|
||||
_back = (_front + _size - 1u) % SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase the given amount of elements from the beginning of the buffer
|
||||
*/
|
||||
void erase_front(const size_t n) {
|
||||
if (n >= _size) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
_front = (_front + n) % SIZE;
|
||||
_size -= n;
|
||||
}
|
||||
|
||||
inline TYPE &operator[](size_t i) {
|
||||
return _buffer[(_front + i) % SIZE];
|
||||
}
|
||||
|
||||
inline const TYPE &operator[](size_t i) const {
|
||||
return _buffer[(_front + i) % SIZE];
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace TwinE
|
||||
Reference in New Issue
Block a user