Compare commits

...
This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.

1 Commits

Author SHA1 Message Date
mniip
e812406a15 Refactor zoom window 2023-04-14 10:46:10 +02:00
9 changed files with 178 additions and 148 deletions

View File

@ -128,7 +128,7 @@ struct Vec2
// Return a rectangle starting at origin, whose dimensions match this vector // Return a rectangle starting at origin, whose dimensions match this vector
template<typename S = T, typename = std::enable_if_t<std::is_integral_v<S>>> template<typename S = T, typename = std::enable_if_t<std::is_integral_v<S>>>
constexpr inline Rect<T> OriginRect() const constexpr Rect<T> OriginRect() const
{ {
return RectSized(Vec2<T>(0, 0), *this); return RectSized(Vec2<T>(0, 0), *this);
} }
@ -379,23 +379,29 @@ public:
); );
} }
inline Rect<T> &operator|=(Rect<T> other) Rect<T> &operator|=(Rect<T> other)
{ {
return *this = *this | other; return *this = *this | other;
} }
inline Rect<T> &operator&=(Rect<T> other) Rect<T> &operator&=(Rect<T> other)
{ {
return *this = *this & other; return *this = *this & other;
} }
inline bool Contains(Vec2<T> point) const bool Contains(Vec2<T> point) const
{ {
return point.X >= TopLeft.X && point.X <= BottomRight.X && point.Y >= TopLeft.Y && point.Y <= BottomRight.Y; return point.X >= TopLeft.X && point.X <= BottomRight.X && point.Y >= TopLeft.Y && point.Y <= BottomRight.Y;
} }
// Whether rect fits inside this, assuming **rect is not empty**
bool Contains(Rect<T> rect) const
{
return rect.TopLeft.X >= TopLeft.X && rect.BottomRight.X <= BottomRight.X && rect.TopLeft.Y >= TopLeft.Y && rect.BottomRight.Y <= BottomRight.Y;
}
template<typename S = T, typename = std::enable_if_t<std::is_integral_v<S>>> template<typename S = T, typename = std::enable_if_t<std::is_integral_v<S>>>
inline Vec2<T> Size() const Vec2<T> Size() const
{ {
return BottomRight - TopLeft + Vec2<T>(1, 1); return BottomRight - TopLeft + Vec2<T>(1, 1);
} }

View File

@ -22,6 +22,7 @@ struct RasterDrawMethods
void DrawRect(Rect<int>, RGB<uint8_t>); void DrawRect(Rect<int>, RGB<uint8_t>);
void BlendRect(Rect<int>, RGBA<uint8_t>); void BlendRect(Rect<int>, RGBA<uint8_t>);
void XorRect(Rect<int>);
void XorDottedRect(Rect<int>); void XorDottedRect(Rect<int>);

View File

@ -111,6 +111,14 @@ void RasterDrawMethods<Derived>::BlendRect(Rect<int> rect, RGBA<uint8_t> colour)
}); });
} }
template<typename Derived>
void RasterDrawMethods<Derived>::XorRect(Rect<int> rect)
{
RasterizeRect(rect, [this](Vec2<int> pos) {
XorPixel(pos);
});
}
template<typename Derived> template<typename Derived>
void RasterDrawMethods<Derived>::XorDottedRect(Rect<int> rect) void RasterDrawMethods<Derived>::XorDottedRect(Rect<int> rect)
{ {

View File

@ -2,6 +2,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <optional>
#include <vector> #include <vector>
#include "Graphics.h" #include "Graphics.h"
#include "gui/interface/Point.h" #include "gui/interface/Point.h"
@ -47,6 +48,8 @@ class Renderer: public RasterDrawMethods<Renderer>
friend struct RasterDrawMethods<Renderer>; friend struct RasterDrawMethods<Renderer>;
void renderZoom();
public: public:
Vec2<int> Size() const Vec2<int> Size() const
{ {
@ -86,17 +89,24 @@ public:
ui::Point mousePos; ui::Point mousePos;
//Zoom window //Zoom window
ui::Point zoomWindowPosition; struct ZoomSettings
ui::Point zoomScopePosition; {
int zoomScopeSize; Vec2<int> ScopePosition;
bool zoomEnabled; int ScopeSize;
int ZFACTOR; int Factor;
Vec2<int> WindowPosition;
static int WindowSize(int scopeSize, int factor)
{
return scopeSize * factor - 1;
}
};
std::optional<ZoomSettings> Zoom;
//Renderers //Renderers
void RenderBegin(); void RenderBegin();
void RenderEnd(); void RenderEnd();
void RenderZoom();
void DrawBlob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb); void DrawBlob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb);
void DrawWalls(); void DrawWalls();
void DrawSigns(); void DrawSigns();

View File

@ -44,7 +44,7 @@ void Renderer::RenderBegin()
void Renderer::RenderEnd() void Renderer::RenderEnd()
{ {
RenderZoom(); renderZoom();
} }
void Renderer::SetSample(int x, int y) void Renderer::SetSample(int x, int y)
@ -73,39 +73,24 @@ void Renderer::FinaliseParts()
} }
} }
void Renderer::RenderZoom() void Renderer::renderZoom()
{ {
if(!zoomEnabled) if (!Zoom)
return; return;
auto const factor = Zoom->Factor;
auto const size = Zoom->ScopeSize;
auto const scope = RectSized(Zoom->ScopePosition, Vec2(1, 1) * size);
auto const window = RectSized(Zoom->WindowPosition, Vec2(1, 1) * ZoomSettings::WindowSize(Zoom->ScopeSize, factor));
DrawFilledRect(window.Inset(-1), 0x000000_rgb);
DrawRect(window.Inset(-2), 0xC0C0C0_rgb);
for (auto offset : (Vec2(1, 1) * size).OriginRect())
{ {
int x, y, i, j; pixel px = video[Zoom->ScopePosition + offset];
pixel pix; for (auto pxOffset : Vec2(factor - 1, factor - 1).OriginRect())
pixel * img = vid; video[Zoom->WindowPosition + offset * factor + pxOffset] = px;
clearrect(zoomWindowPosition.X-1, zoomWindowPosition.Y-1, zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1);
drawrect(zoomWindowPosition.X-2, zoomWindowPosition.Y-2, zoomScopeSize*ZFACTOR+3, zoomScopeSize*ZFACTOR+3, 192, 192, 192, 255);
drawrect(zoomWindowPosition.X-1, zoomWindowPosition.Y-1, zoomScopeSize*ZFACTOR+1, zoomScopeSize*ZFACTOR+1, 0, 0, 0, 255);
for (j=0; j<zoomScopeSize; j++)
for (i=0; i<zoomScopeSize; i++)
{
pix = img[(j+zoomScopePosition.Y)*(VIDXRES)+(i+zoomScopePosition.X)];
for (y=0; y<ZFACTOR-1; y++)
for (x=0; x<ZFACTOR-1; x++)
img[(j*ZFACTOR+y+zoomWindowPosition.Y)*(VIDXRES)+(i*ZFACTOR+x+zoomWindowPosition.X)] = pix;
}
if (zoomEnabled)
{
for (j=-1; j<=zoomScopeSize; j++)
{
xor_pixel(zoomScopePosition.X+j, zoomScopePosition.Y-1);
xor_pixel(zoomScopePosition.X+j, zoomScopePosition.Y+zoomScopeSize);
}
for (j=0; j<zoomScopeSize; j++)
{
xor_pixel(zoomScopePosition.X-1, zoomScopePosition.Y+j);
xor_pixel(zoomScopePosition.X+zoomScopeSize, zoomScopePosition.Y+j);
}
}
} }
XorRect(scope.Inset(-1));
} }
void Renderer::DrawBlob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb) void Renderer::DrawBlob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb)
@ -275,11 +260,6 @@ Renderer::Renderer(Simulation * sim):
findingElement(0), findingElement(0),
foundElements(0), foundElements(0),
mousePos(0, 0), mousePos(0, 0),
zoomWindowPosition(0, 0),
zoomScopePosition(0, 0),
zoomScopeSize(32),
zoomEnabled(false),
ZFACTOR(8),
gridSize(0) gridSize(0)
{ {
PopulateTables(); PopulateTables();

View File

@ -299,14 +299,14 @@ void GameController::AdjustZoomSize(int delta, bool logarithmic)
{ {
int newSize; int newSize;
if(logarithmic) if(logarithmic)
newSize = gameModel->GetZoomSize() + std::max(gameModel->GetZoomSize() / 10, 1) * delta; newSize = gameModel->GetZoomScopeSize() + std::max(gameModel->GetZoomScopeSize() / 10, 1) * delta;
else else
newSize = gameModel->GetZoomSize() + delta; newSize = gameModel->GetZoomScopeSize() + delta;
if(newSize<5) if(newSize<5)
newSize = 5; newSize = 5;
if(newSize>64) if(newSize>64)
newSize = 64; newSize = 64;
gameModel->SetZoomSize(newSize); gameModel->SetZoomScopeSize(newSize);
int newZoomFactor = 256/newSize; int newZoomFactor = 256/newSize;
if(newZoomFactor<3) if(newZoomFactor<3)
@ -928,21 +928,21 @@ void GameController::SetToolStrength(float value)
void GameController::SetZoomPosition(ui::Point position) void GameController::SetZoomPosition(ui::Point position)
{ {
ui::Point zoomPosition = position-(gameModel->GetZoomSize()/2); ui::Point zoomPosition = position-(gameModel->GetZoomScopeSize()/2);
if(zoomPosition.X < 0) if(zoomPosition.X < 0)
zoomPosition.X = 0; zoomPosition.X = 0;
if(zoomPosition.Y < 0) if(zoomPosition.Y < 0)
zoomPosition.Y = 0; zoomPosition.Y = 0;
if(zoomPosition.X >= XRES-gameModel->GetZoomSize()) if(zoomPosition.X >= XRES-gameModel->GetZoomScopeSize())
zoomPosition.X = XRES-gameModel->GetZoomSize(); zoomPosition.X = XRES-gameModel->GetZoomScopeSize();
if(zoomPosition.Y >= YRES-gameModel->GetZoomSize()) if(zoomPosition.Y >= YRES-gameModel->GetZoomScopeSize())
zoomPosition.Y = YRES-gameModel->GetZoomSize(); zoomPosition.Y = YRES-gameModel->GetZoomScopeSize();
ui::Point zoomWindowPosition = ui::Point(0, 0); ui::Point zoomWindowPosition = ui::Point(0, 0);
if(position.X < XRES/2) if(position.X < XRES/2)
zoomWindowPosition.X = XRES-(gameModel->GetZoomSize()*gameModel->GetZoomFactor()); zoomWindowPosition.X = XRES-(gameModel->GetZoomScopeSize()*gameModel->GetZoomFactor());
gameModel->SetZoomPosition(zoomPosition); gameModel->SetZoomScopePosition(zoomPosition);
gameModel->SetZoomWindowPosition(zoomWindowPosition); gameModel->SetZoomWindowPosition(zoomWindowPosition);
} }

View File

@ -1075,85 +1075,96 @@ void GameModel::SetLastTool(Tool * newTool)
void GameModel::SetZoomEnabled(bool enabled) void GameModel::SetZoomEnabled(bool enabled)
{ {
ren->zoomEnabled = enabled; if (enabled)
ren->Zoom = zoomSettings;
else
ren->Zoom = std::nullopt;
notifyZoomChanged(); notifyZoomChanged();
} }
bool GameModel::GetZoomEnabled() bool GameModel::GetZoomEnabled() const
{ {
return ren->zoomEnabled; return bool(ren->Zoom);
} }
void GameModel::SetZoomPosition(ui::Point position) void GameModel::SetZoomScopePosition(Vec2<int> position)
{ {
ren->zoomScopePosition = position; zoomSettings.ScopePosition = position;
if (ren->Zoom)
ren->Zoom->ScopePosition = position;
notifyZoomChanged(); notifyZoomChanged();
} }
ui::Point GameModel::GetZoomPosition() Vec2<int> GameModel::GetZoomScopePosition() const
{ {
return ren->zoomScopePosition; return zoomSettings.ScopePosition;
} }
bool GameModel::MouseInZoom(ui::Point position) void GameModel::SetZoomWindowPosition(Vec2<int> position)
{ {
if (!GetZoomEnabled()) zoomSettings.WindowPosition = position;
return false; if (ren->Zoom)
ren->Zoom->WindowPosition = position;
int zoomFactor = GetZoomFactor();
ui::Point zoomWindowPosition = GetZoomWindowPosition();
ui::Point zoomWindowSize = ui::Point(GetZoomSize()*zoomFactor, GetZoomSize()*zoomFactor);
if (position.X >= zoomWindowPosition.X && position.Y >= zoomWindowPosition.Y && position.X < zoomWindowPosition.X+zoomWindowSize.X && position.Y < zoomWindowPosition.Y+zoomWindowSize.Y)
return true;
return false;
}
ui::Point GameModel::AdjustZoomCoords(ui::Point position)
{
if (!GetZoomEnabled())
return position;
int zoomFactor = GetZoomFactor();
ui::Point zoomWindowPosition = GetZoomWindowPosition();
ui::Point zoomWindowSize = ui::Point(GetZoomSize()*zoomFactor, GetZoomSize()*zoomFactor);
if (position.X >= zoomWindowPosition.X && position.Y >= zoomWindowPosition.Y && position.X < zoomWindowPosition.X+zoomWindowSize.X && position.Y < zoomWindowPosition.Y+zoomWindowSize.Y)
return ((position-zoomWindowPosition)/GetZoomFactor())+GetZoomPosition();
return position;
}
void GameModel::SetZoomWindowPosition(ui::Point position)
{
ren->zoomWindowPosition = position;
notifyZoomChanged(); notifyZoomChanged();
} }
ui::Point GameModel::GetZoomWindowPosition() Vec2<int> GameModel::GetZoomWindowPosition() const
{ {
return ren->zoomWindowPosition; return zoomSettings.WindowPosition;
} }
void GameModel::SetZoomSize(int size) void GameModel::SetZoomScopeSize(int size)
{ {
ren->zoomScopeSize = size; zoomSettings.ScopeSize = size;
if (ren->Zoom)
ren->Zoom->ScopeSize = size;
notifyZoomChanged(); notifyZoomChanged();
} }
int GameModel::GetZoomSize() int GameModel::GetZoomScopeSize() const
{ {
return ren->zoomScopeSize; return zoomSettings.ScopeSize;
} }
void GameModel::SetZoomFactor(int factor) void GameModel::SetZoomFactor(int factor)
{ {
ren->ZFACTOR = factor; zoomSettings.Factor = factor;
if (ren->Zoom)
ren->Zoom->Factor = factor;
notifyZoomChanged(); notifyZoomChanged();
} }
int GameModel::GetZoomFactor() int GameModel::GetZoomFactor() const
{ {
return ren->ZFACTOR; return zoomSettings.Factor;
}
bool GameModel::MouseInZoom(Vec2<int> position) const
{
if (!GetZoomEnabled())
return false;
auto const window = RectSized(
GetZoomWindowPosition(),
Vec2(1, 1) * Renderer::ZoomSettings::WindowSize(GetZoomScopeSize(), GetZoomFactor())
);
return window.Contains(position);
}
Vec2<int> GameModel::AdjustZoomCoords(Vec2<int> position) const
{
if (!GetZoomEnabled())
return position;
auto const factor = GetZoomFactor();
auto const window = RectSized(
GetZoomWindowPosition(),
Vec2(1, 1) * Renderer::ZoomSettings::WindowSize(GetZoomScopeSize(), factor)
);
if (window.Contains(position))
return (position - window.TopLeft) / factor + GetZoomScopePosition();
else
return position;
} }
void GameModel::SetActiveColourPreset(size_t preset) void GameModel::SetActiveColourPreset(size_t preset)

View File

@ -1,10 +1,11 @@
#pragma once #pragma once
#include "gui/interface/Colour.h"
#include "client/User.h"
#include "gui/interface/Point.h"
#include <vector>
#include <deque> #include <deque>
#include <memory> #include <memory>
#include <vector>
#include "client/User.h"
#include "graphics/Renderer.h"
#include "gui/interface/Colour.h"
#include "gui/interface/Point.h"
class Menu; class Menu;
class Tool; class Tool;
@ -16,7 +17,6 @@ class GameController;
class SaveInfo; class SaveInfo;
class SaveFile; class SaveFile;
class Simulation; class Simulation;
class Renderer;
class Snapshot; class Snapshot;
struct SnapshotDelta; struct SnapshotDelta;
class GameSave; class GameSave;
@ -90,7 +90,14 @@ private:
String infoTip; String infoTip;
String toolTip; String toolTip;
//bool zoomEnabled;
Renderer::ZoomSettings zoomSettings = {
Vec2<int>::Zero,
32,
8,
Vec2<int>::Zero,
};
void notifyRendererChanged(); void notifyRendererChanged();
void notifySimulationChanged(); void notifySimulationChanged();
void notifyPausedChanged(); void notifyPausedChanged();
@ -208,18 +215,18 @@ public:
void SetUser(User user); void SetUser(User user);
Simulation * GetSimulation(); Simulation * GetSimulation();
Renderer * GetRenderer(); Renderer * GetRenderer();
void SetZoomEnabled(bool enabled); void SetZoomEnabled(bool);
bool GetZoomEnabled(); bool GetZoomEnabled() const;
void SetZoomSize(int size); void SetZoomScopeSize(int);
int GetZoomSize(); int GetZoomScopeSize() const;
void SetZoomFactor(int factor); void SetZoomFactor(int);
int GetZoomFactor(); int GetZoomFactor() const;
void SetZoomPosition(ui::Point position); void SetZoomScopePosition(Vec2<int>);
ui::Point GetZoomPosition(); Vec2<int> GetZoomScopePosition() const;
bool MouseInZoom(ui::Point position); void SetZoomWindowPosition(Vec2<int>);
ui::Point AdjustZoomCoords(ui::Point position); Vec2<int> GetZoomWindowPosition() const;
void SetZoomWindowPosition(ui::Point position); bool MouseInZoom(Vec2<int>) const;
ui::Point GetZoomWindowPosition(); Vec2<int> AdjustZoomCoords(Vec2<int>) const;
void SetClipboard(GameSave * save); void SetClipboard(GameSave * save);
void SetPlaceSave(GameSave * save); void SetPlaceSave(GameSave * save);
void Log(String message, bool printToFile); void Log(String message, bool printToFile);

View File

@ -2724,13 +2724,13 @@ int LuaScriptInterface::renderer_zoomEnabled(lua_State * l)
{ {
if (lua_gettop(l) == 0) if (lua_gettop(l) == 0)
{ {
lua_pushboolean(l, luacon_ren->zoomEnabled); lua_pushboolean(l, luacon_model->GetZoomEnabled());
return 1; return 1;
} }
else else
{ {
luaL_checktype(l, -1, LUA_TBOOLEAN); luaL_checktype(l, -1, LUA_TBOOLEAN);
luacon_ren->zoomEnabled = lua_toboolean(l, -1); luacon_model->SetZoomEnabled(lua_toboolean(l, -1));
return 0; return 0;
} }
} }
@ -2738,53 +2738,60 @@ int LuaScriptInterface::renderer_zoomWindowInfo(lua_State * l)
{ {
if (lua_gettop(l) == 0) if (lua_gettop(l) == 0)
{ {
ui::Point location = luacon_ren->zoomWindowPosition; Vec2<int> const windowPos = luacon_model->GetZoomWindowPosition();
lua_pushnumber(l, location.X); lua_pushnumber(l, windowPos.X);
lua_pushnumber(l, location.Y); lua_pushnumber(l, windowPos.Y);
lua_pushnumber(l, luacon_ren->ZFACTOR); lua_pushnumber(l, luacon_model->GetZoomFactor());
lua_pushnumber(l, luacon_ren->zoomScopeSize * luacon_ren->ZFACTOR); lua_pushnumber(l, luacon_model->GetZoomScopeSize() * luacon_model->GetZoomFactor());
return 4; return 4;
} }
int x = luaL_optint(l, 1, 0); int const x = luaL_optint(l, 1, 0);
int y = luaL_optint(l, 2, 0); int const y = luaL_optint(l, 2, 0);
int f = luaL_optint(l, 3, 0); int const factor = luaL_optint(l, 3, 0);
if (f <= 0) if (factor <= 0)
return luaL_error(l, "Zoom factor must be greater than 0"); return luaL_error(l, "Zoom factor must be greater than 0");
auto const window = RectSized(
Vec2(x, y),
Vec2(1, 1) * Renderer::ZoomSettings::WindowSize(luacon_model->GetZoomScopeSize(), factor)
);
// To prevent crash when zoom window is outside screen // To prevent crash when zoom window is outside screen
if (x < 0 || y < 0 || luacon_ren->zoomScopeSize * f + x > XRES || luacon_ren->zoomScopeSize * f + y > YRES) if (!RES.OriginRect().Contains(window))
return luaL_error(l, "Zoom window outside of bounds"); return luaL_error(l, "Zoom window outside of bounds");
luacon_ren->zoomWindowPosition = ui::Point(x, y); luacon_model->SetZoomWindowPosition(Vec2(x, y));
luacon_ren->ZFACTOR = f; luacon_model->SetZoomFactor(factor);
return 0; return 0;
} }
int LuaScriptInterface::renderer_zoomScopeInfo(lua_State * l) int LuaScriptInterface::renderer_zoomScopeInfo(lua_State * l)
{ {
if (lua_gettop(l) == 0) if (lua_gettop(l) == 0)
{ {
ui::Point location = luacon_ren->zoomScopePosition; Vec2<int> const scopePos = luacon_model->GetZoomScopePosition();
lua_pushnumber(l, location.X); lua_pushnumber(l, scopePos.X);
lua_pushnumber(l, location.Y); lua_pushnumber(l, scopePos.Y);
lua_pushnumber(l, luacon_ren->zoomScopeSize); lua_pushnumber(l, luacon_model->GetZoomScopeSize());
return 3; return 3;
} }
int x = luaL_optint(l, 1, 0); int const x = luaL_optint(l, 1, 0);
int y = luaL_optint(l, 2, 0); int const y = luaL_optint(l, 2, 0);
int s = luaL_optint(l, 3, 0); int const size = luaL_optint(l, 3, 0);
if (s <= 0) if (size <= 0)
return luaL_error(l, "Zoom scope size must be greater than 0"); return luaL_error(l, "Zoom scope size must be greater than 0");
auto const scope = RectSized(Vec2(x, y), Vec2(1, 1) * size);
auto const window = RectSized(
luacon_model->GetZoomWindowPosition(),
Vec2(1, 1) * Renderer::ZoomSettings::WindowSize(size, luacon_model->GetZoomFactor())
);
// To prevent crash when zoom or scope window is outside screen // To prevent crash when zoom or scope window is outside screen
int windowEdgeRight = luacon_ren->ZFACTOR * s + luacon_ren->zoomWindowPosition.X; if (!RES.OriginRect().Contains(scope))
int windowEdgeBottom = luacon_ren->ZFACTOR * s + luacon_ren->zoomWindowPosition.Y;
if (x < 0 || y < 0 || x + s > XRES || y + s > YRES)
return luaL_error(l, "Zoom scope outside of bounds"); return luaL_error(l, "Zoom scope outside of bounds");
if (windowEdgeRight > XRES || windowEdgeBottom > YRES) if (!RES.OriginRect().Contains(window))
return luaL_error(l, "Zoom window outside of bounds"); return luaL_error(l, "Zoom window outside of bounds");
luacon_ren->zoomScopePosition = ui::Point(x, y); luacon_model->SetZoomScopePosition(Vec2(x, y));
luacon_ren->zoomScopeSize = s; luacon_model->SetZoomScopeSize(size);
return 0; return 0;
} }