/* 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 . * */ #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