Files
dota_factory/src/ui/GameWorldView.h

194 lines
6.4 KiB
C++

#pragma once
#include <optional>
#include <random>
#include <set>
#include <vector>
#include <QElapsedTimer>
#include <QOpenGLWidget>
#include <QPoint>
#include <QRectF>
#include <QTimer>
#include <QVector2D>
#include "Blueprint.h"
#include "BlueprintModeExitedEvent.h"
#include "BlueprintPlacementRequestedEvent.h"
#include "BuilderModeExitedEvent.h"
#include "BuildingType.h"
#include "BuildingTypeSelectedEvent.h"
#include "BuildingId.h"
#include "DemolishModeChangedEvent.h"
#include "DemolishModeToggleRequestedEvent.h"
#include "EventHandler.h"
#include "ExitBlueprintModeRequestedEvent.h"
#include "ExitBuilderModeRequestedEvent.h"
#include "WeaponFiredEvent.h"
#include "SchematicChoiceOption.h"
#include "SpeedChangeRequestedEvent.h"
#include "entt/entity/entity.hpp"
#include "EntitySelectedEvent.h"
#include "GameConfig.h"
#include "Rotation.h"
#include "Tick.h"
#include "TickDriver.h"
#include "VisualsConfig.h"
class Simulation;
class QPainter;
struct QPointCompare
{
bool operator()(const QPoint& a, const QPoint& b) const
{
if (a.x() != b.x()) { return a.x() < b.x(); }
return a.y() < b.y();
}
};
class GameWorldView : public QOpenGLWidget,
public CombinedEventHandler<WeaponFiredEvent,
BuildingTypeSelectedEvent,
ExitBuilderModeRequestedEvent,
DemolishModeToggleRequestedEvent,
BlueprintPlacementRequestedEvent,
ExitBlueprintModeRequestedEvent,
SpeedChangeRequestedEvent>
{
Q_OBJECT
public:
GameWorldView(Simulation* sim, const GameConfig* config,
const VisualsConfig* visuals, QWidget* parent = nullptr);
~GameWorldView() override;
double gameSpeed() const;
void resetFrameTimer();
void setGameSpeed(double multiplier);
void resetForNewGame();
protected:
void initializeGL() override;
void paintGL() override;
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
private slots:
void onFrame();
private:
void handleEvent(std::shared_ptr<const WeaponFiredEvent> event) override;
void handleEvent(std::shared_ptr<const BuildingTypeSelectedEvent> event) override;
void handleEvent(std::shared_ptr<const ExitBuilderModeRequestedEvent> event) override;
void handleEvent(std::shared_ptr<const DemolishModeToggleRequestedEvent> event) override;
void handleEvent(std::shared_ptr<const BlueprintPlacementRequestedEvent> event) override;
void handleEvent(std::shared_ptr<const ExitBlueprintModeRequestedEvent> event) override;
void handleEvent(std::shared_ptr<const SpeedChangeRequestedEvent> event) override;
void drawTiles(QPainter& painter);
void drawBuildings(QPainter& painter);
void drawStations(QPainter& painter);
void drawBeltItems(QPainter& painter);
void drawScrap(QPainter& painter);
void drawShips(QPainter& painter);
void drawDebugSensorRanges(QPainter& painter);
void drawDebugOverlay(QPainter& painter);
void drawBeams(QPainter& painter);
void drawOverlays(QPainter& painter);
void drawScreenSpace(QPainter& painter);
float tilePx() const;
float viewportWidthTiles() const;
QPointF worldToWidget(QVector2D worldPos) const;
QPointF tileToWidget(QPoint tile) const;
QPoint widgetToTile(QPoint widgetPt) const;
QRectF tileRect(QPoint tile) const;
QRect viewportRect() const;
float asteroidLeftEdge() const;
float enemyStationRightEdge() const;
void clampScroll();
bool isValidPlacement(BuildingType type, QPoint anchor, Rotation rot) const;
const BuildingDef* findBuildingDef(BuildingType type) const;
BuildingId buildingAtTile(QPoint tile) const;
BuildingId siteAtTile(QPoint tile) const;
QVector2D widgetToWorld(QPoint widgetPt) const;
void drawPortGlyph(QPainter& painter, QPoint bodyTile,
Rotation direction, const QColor& color);
void placeBlueprintAtTile(QPoint center);
std::optional<QVector2D> entityPosition(entt::entity entity) const;
void stepSpeed(int delta);
void placeAtTile(QPoint tile);
void enterBuilderMode(BuildingType type);
void exitBuilderMode();
void enterBlueprintMode(Blueprint blueprint);
void exitBlueprintMode();
void toggleDemolishMode();
struct ActiveBeam
{
WeaponFiredEvent event;
qint64 emittedWallMs;
QVector2D targetOffset;
};
static constexpr qint64 kBeamLifetimeMs = 300;
static constexpr float kScrollSpeedTilesPerSec = 10.0f;
Simulation* m_sim;
const GameConfig* m_config;
const VisualsConfig* m_visuals;
TickDriver m_tickDriver;
QElapsedTimer m_frameTimer;
qint64 m_wallMs;
std::mt19937 m_rng;
double m_gameSpeedMultiplier;
double m_prevNonZeroSpeed;
float m_scrollXTiles;
QTimer* m_renderTimer;
std::vector<ActiveBeam> m_activeBeams;
std::optional<BuildingType> m_builderType;
Rotation m_ghostRotation;
QPoint m_ghostTile;
bool m_ghostValid;
std::set<QPoint, QPointCompare> m_beltDragTiles;
bool m_dragging;
std::optional<Blueprint> m_blueprintMode;
QPoint m_blueprintGhostTile;
bool m_demolishMode;
BuildingId m_demolishHoverBuildingId;
bool m_debugDraw;
std::vector<BuildingId> m_selectedBuildingIds;
std::optional<entt::entity> m_selectedEntity;
bool m_boxSelecting;
QPoint m_boxStartTile;
QPoint m_boxCurrentTile;
bool m_scrollLeft;
bool m_scrollRight;
bool m_gameOverShown;
bool m_schematicChoiceShown;
Tick m_lastTick = Tick(-1);
int m_lastBlocks = -1;
int m_lastBossCounter = -1;
Tick m_lastBossCountdown = Tick(-1);
};