Initial commit
This commit is contained in:
230
engines/alcachofa/debug.h
Normal file
230
engines/alcachofa/debug.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/* 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 ALCACHOFA_DEBUG_H
|
||||
#define ALCACHOFA_DEBUG_H
|
||||
|
||||
#include "alcachofa/alcachofa.h"
|
||||
|
||||
using namespace Common;
|
||||
|
||||
namespace Alcachofa {
|
||||
|
||||
class IDebugHandler {
|
||||
public:
|
||||
virtual ~IDebugHandler() {}
|
||||
|
||||
virtual void update() = 0;
|
||||
};
|
||||
|
||||
class ClosestFloorPointDebugHandler final : public IDebugHandler {
|
||||
int32 _polygonI;
|
||||
public:
|
||||
ClosestFloorPointDebugHandler(int32 polygonI) : _polygonI(polygonI) {}
|
||||
|
||||
void update() override {
|
||||
auto mousePos2D = g_engine->input().debugInput().mousePos2D();
|
||||
auto mousePos3D = g_engine->input().debugInput().mousePos3D();
|
||||
auto floor = g_engine->player().currentRoom()->activeFloor();
|
||||
auto renderer = dynamic_cast<IDebugRenderer *>(&g_engine->renderer());
|
||||
if (floor == nullptr || renderer == nullptr)
|
||||
return;
|
||||
|
||||
Point target3D;
|
||||
if (_polygonI < 0 || (uint)_polygonI >= floor->polygonCount())
|
||||
target3D = floor->closestPointTo(mousePos3D);
|
||||
else
|
||||
target3D = floor->at((uint)_polygonI).closestPointTo(mousePos3D);
|
||||
renderer->debugPolyline(mousePos2D, g_engine->camera().transform3Dto2D(target3D));
|
||||
}
|
||||
};
|
||||
|
||||
class FloorIntersectionsDebugHandler final : public IDebugHandler {
|
||||
int32 _polygonI;
|
||||
Point _fromPos3D;
|
||||
public:
|
||||
FloorIntersectionsDebugHandler(int32 polygonI) : _polygonI(polygonI) {}
|
||||
|
||||
void update() override {
|
||||
auto floor = g_engine->player().currentRoom()->activeFloor();
|
||||
auto renderer = dynamic_cast<IDebugRenderer *>(&g_engine->renderer());
|
||||
if (floor == nullptr || renderer == nullptr) {
|
||||
g_engine->console().attach("Either the room has no floor or the renderer is not a debug renderer");
|
||||
g_engine->setDebugMode(DebugMode::None, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_engine->input().debugInput().wasMouseLeftPressed())
|
||||
_fromPos3D = g_engine->input().debugInput().mousePos3D();
|
||||
renderer->debugPolyline(
|
||||
g_engine->camera().transform3Dto2D(_fromPos3D),
|
||||
g_engine->input().debugInput().mousePos2D(),
|
||||
kDebugRed);
|
||||
|
||||
if (_polygonI >= 0 && (uint)_polygonI < floor->polygonCount())
|
||||
drawIntersectionsFor(floor->at((uint)_polygonI), renderer);
|
||||
else {
|
||||
for (uint i = 0; i < floor->polygonCount(); i++)
|
||||
drawIntersectionsFor(floor->at(i), renderer);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr float kMarkerLength = 16;
|
||||
|
||||
void drawIntersectionsFor(const Polygon &polygon, IDebugRenderer *renderer) {
|
||||
auto &camera = g_engine->camera();
|
||||
auto mousePos3D = g_engine->input().debugInput().mousePos3D();
|
||||
for (uint i = 0; i < polygon._points.size(); i++) {
|
||||
if (!polygon.intersectsEdge(i, _fromPos3D, mousePos3D))
|
||||
continue;
|
||||
auto a = camera.transform3Dto2D(polygon._points[i]);
|
||||
auto b = camera.transform3Dto2D(polygon._points[(i + 1) % polygon._points.size()]);
|
||||
auto mid = (a + b) / 2;
|
||||
auto length = sqrtf(a.sqrDist(b));
|
||||
auto normal = a - b;
|
||||
normal = { normal.y, (int16)-normal.x };
|
||||
auto inner = mid + normal * (kMarkerLength / length);
|
||||
|
||||
renderer->debugPolyline(a, b, kDebugGreen);
|
||||
renderer->debugPolyline(mid, inner, kDebugGreen);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TeleportCharacterDebugHandler final : public IDebugHandler {
|
||||
MainCharacterKind _kind;
|
||||
public:
|
||||
TeleportCharacterDebugHandler(int32 kindI) : _kind((MainCharacterKind)kindI) {}
|
||||
|
||||
void update() override {
|
||||
g_engine->drawQueue().clear();
|
||||
g_engine->player().drawCursor(true);
|
||||
g_engine->drawQueue().draw();
|
||||
|
||||
auto &input = g_engine->input().debugInput();
|
||||
if (input.wasMouseRightPressed()) {
|
||||
g_engine->setDebugMode(DebugMode::None, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!input.wasMouseLeftPressed())
|
||||
return;
|
||||
auto floor = g_engine->player().currentRoom()->activeFloor();
|
||||
if (floor == nullptr || !floor->contains(input.mousePos3D()))
|
||||
return;
|
||||
|
||||
if (_kind == MainCharacterKind::Filemon)
|
||||
teleport(g_engine->world().filemon(), input.mousePos3D());
|
||||
else if (_kind == MainCharacterKind::Mortadelo)
|
||||
teleport(g_engine->world().mortadelo(), input.mousePos3D());
|
||||
else {
|
||||
teleport(g_engine->world().filemon(), input.mousePos3D());
|
||||
teleport(g_engine->world().mortadelo(), input.mousePos3D());
|
||||
}
|
||||
g_engine->setDebugMode(DebugMode::None, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
void teleport(MainCharacter &character, Point position) {
|
||||
auto currentRoom = g_engine->player().currentRoom();
|
||||
if (character.room() != currentRoom) {
|
||||
character.resetTalking();
|
||||
character.room() = currentRoom;
|
||||
}
|
||||
character.setPosition(position);
|
||||
}
|
||||
};
|
||||
|
||||
class FloorColorDebugHandler final : public IDebugHandler {
|
||||
const FloorColorShape &_shape;
|
||||
const bool _useColor;
|
||||
Color _curColor = kDebugGreen;
|
||||
bool _isOnFloor = false;
|
||||
static constexpr size_t kBufferSize = 64;
|
||||
char _buffer[kBufferSize] = { 0 };
|
||||
|
||||
FloorColorDebugHandler(const FloorColorShape &shape, bool useColor)
|
||||
: _shape(shape)
|
||||
, _useColor(useColor) {}
|
||||
public:
|
||||
static FloorColorDebugHandler *create(int32 objectI, bool useColor) {
|
||||
const Room *room = g_engine->player().currentRoom();
|
||||
uint floorCount = 0;
|
||||
for (auto itObject = room->beginObjects(); itObject != room->endObjects(); ++itObject) {
|
||||
FloorColor *floor = dynamic_cast<FloorColor *>(*itObject);
|
||||
if (floor == nullptr)
|
||||
continue;
|
||||
if (objectI <= 0)
|
||||
// dynamic_cast is not possible due to Shape not having virtual methods
|
||||
return new FloorColorDebugHandler(*(FloorColorShape *)(floor->shape()), useColor);
|
||||
floorCount++;
|
||||
objectI--;
|
||||
}
|
||||
|
||||
g_engine->console().debugPrintf("Invalid floor color index, there are %u floors in this room\n", floorCount);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void update() override {
|
||||
auto &input = g_engine->input().debugInput();
|
||||
if (input.wasMouseRightPressed()) {
|
||||
g_engine->setDebugMode(DebugMode::None, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (input.isMouseLeftDown()) {
|
||||
auto optColor = _shape.colorAt(input.mousePos3D());
|
||||
_isOnFloor = optColor.first;
|
||||
if (!_isOnFloor) {
|
||||
uint8 roomAlpha = (uint)(g_engine->player().currentRoom()->characterAlphaTint() * 255 / 100);
|
||||
optColor.second = Color { 255, 255, 255, roomAlpha };
|
||||
}
|
||||
|
||||
_curColor = _useColor
|
||||
? Color { optColor.second.r, optColor.second.g, optColor.second.b, 255 }
|
||||
: Color { optColor.second.a, optColor.second.a, optColor.second.a, 255 };
|
||||
g_engine->world().mortadelo().color() =
|
||||
g_engine->world().filemon().color() =
|
||||
_useColor ? optColor.second : Color { 255, 255, 255, optColor.second.a };
|
||||
}
|
||||
|
||||
snprintf(_buffer, kBufferSize, "r:%3d g:%3d b:%3d a:%3d",
|
||||
(int)_curColor.r, (int)_curColor.g, (int)_curColor.b, (int)_curColor.a);
|
||||
|
||||
auto *debugRenderer = dynamic_cast<IDebugRenderer *>(&g_engine->renderer());
|
||||
g_engine->drawQueue().clear();
|
||||
g_engine->player().drawCursor(true);
|
||||
g_engine->renderer().setTexture(nullptr);
|
||||
g_engine->renderer().quad({ 0, 0 }, { 50, 50 }, _isOnFloor ? _curColor : kDebugGreen);
|
||||
g_engine->drawQueue().add<TextDrawRequest>(
|
||||
g_engine->globalUI().dialogFont(), _buffer, Point { 70, 20 }, 500, false, kWhite, -kForegroundOrderCount + 1);
|
||||
if (!_isOnFloor)
|
||||
g_engine->renderer().quad({ 5, 5 }, { 40, 40 }, _curColor);
|
||||
if (debugRenderer != nullptr)
|
||||
debugRenderer->debugShape(_shape, kDebugBlue);
|
||||
g_engine->drawQueue().draw();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ALCACHOFA_DEBUG_H
|
||||
Reference in New Issue
Block a user