diff --git a/Crawler/Crawler.vcxproj b/Crawler/Crawler.vcxproj
index a9d906a2..896a2b93 100644
--- a/Crawler/Crawler.vcxproj
+++ b/Crawler/Crawler.vcxproj
@@ -344,6 +344,7 @@
+
diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters
index f2629c11..8005006a 100644
--- a/Crawler/Crawler.vcxproj.filters
+++ b/Crawler/Crawler.vcxproj.filters
@@ -297,6 +297,9 @@
Header Files\Interface
+
+ Header Files
+
diff --git a/Crawler/MenuComponent.cpp b/Crawler/MenuComponent.cpp
index f49758d3..be1e789f 100644
--- a/Crawler/MenuComponent.cpp
+++ b/Crawler/MenuComponent.cpp
@@ -197,6 +197,14 @@ bool MenuComponent::PointWithinParent(MenuComponent*child,vi2d drawPos){
}
}
+bool MenuComponent::PointWithinParent(MenuComponent*child,geom2d::rect drawRect){
+ if(parentComponent!=nullptr){
+ return parentComponent->PointWithinParent(child,drawRect);
+ }else{
+ return true;
+ }
+}
+
bool MenuComponent::HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton){
return false;
};
diff --git a/Crawler/MenuComponent.h b/Crawler/MenuComponent.h
index de209676..595c0302 100644
--- a/Crawler/MenuComponent.h
+++ b/Crawler/MenuComponent.h
@@ -103,7 +103,9 @@ protected:
virtual bool GetHoverState(Crawler*game,MenuComponent*child);
virtual void AfterCreate(); //Called after the creation of all menus finish.
//CALL THIS FOR A PARENT to check a child's DrawDecal validity!
- virtual bool PointWithinParent(MenuComponent*child,vi2d drawPos);
+ virtual bool PointWithinParent(MenuComponent*child,vi2d drawPos);
+ //CALL THIS FOR A PARENT to check a child's DrawDecal validity!
+ virtual bool PointWithinParent(MenuComponent*child,geom2d::rect drawRect);
public:
MenuType parentMenu=MenuType::ENUM_END;
MenuComponent*parentComponent=nullptr;
diff --git a/Crawler/MenuItemButton.h b/Crawler/MenuItemButton.h
index f292e7d8..192c793c 100644
--- a/Crawler/MenuItemButton.h
+++ b/Crawler/MenuItemButton.h
@@ -157,7 +157,8 @@ protected:
vf2d quantityTextScale=rect.size/48.f;
vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*quantityTextScale;
vf2d drawPos=parentPos+rect.pos+rect.size-textSize;
- if(PointWithinParent(this,drawPos)){
+ geom2d::rectboundingBox={drawPos,textSize};
+ if(PointWithinParent(this,boundingBox)){
game->DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x);
}
}
diff --git a/Crawler/MenuItemItemButton.h b/Crawler/MenuItemItemButton.h
index 1a70605d..5149d680 100644
--- a/Crawler/MenuItemItemButton.h
+++ b/Crawler/MenuItemItemButton.h
@@ -141,7 +141,8 @@ protected:
vf2d quantityTextScale=rect.size/48.f;
vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*quantityTextScale;
vf2d drawPos=Menu::menus[parentMenu]->pos+parentPos+rect.pos+rect.size-textSize;
- if(PointWithinParent(this,drawPos)){
+ geom2d::rectboundingBox={drawPos,textSize};
+ if(PointWithinParent(this,boundingBox)){
game->DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x);
}
}
diff --git a/Crawler/ScrollableWindowComponent.h b/Crawler/ScrollableWindowComponent.h
index 231c9e53..6cdb32d1 100644
--- a/Crawler/ScrollableWindowComponent.h
+++ b/Crawler/ScrollableWindowComponent.h
@@ -260,6 +260,9 @@ public:
virtual inline bool PointWithinParent(MenuComponent*child,vi2d drawPos)override{
return geom2d::overlaps(geom2d::rect{Menu::menus[parentMenu]->pos+rect.pos,rect.size},drawPos);
}
+ virtual inline bool PointWithinParent(MenuComponent*child,geom2d::rect drawRect)override{
+ return geom2d::overlaps(geom2d::rect{Menu::menus[parentMenu]->pos+rect.pos,rect.size},drawRect);
+ }
virtual inline bool HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton)override{
//Set the offset so the center is highlighted by this button.
V(A::SCROLL_OFFSET).y=-(disabledButton->rect.pos.y-disabledButton->rect.size.y/2);
diff --git a/Crawler/State_GameRun.cpp b/Crawler/State_GameRun.cpp
index c5d6171f..938a014e 100644
--- a/Crawler/State_GameRun.cpp
+++ b/Crawler/State_GameRun.cpp
@@ -50,6 +50,7 @@ void State_GameRun::OnStateChange(GameState*prevState){
Menu::CloseAllMenus();
}
game->GetPlayer()->SetState(State::NORMAL);
+ port=ViewPort::rectViewPort({0,0},{72,100},{75,100});
}
void State_GameRun::OnUserUpdate(Crawler*game){
game->bossDisplayTimer=std::max(0.f,game->bossDisplayTimer-game->GetElapsedTime());
@@ -79,16 +80,16 @@ void State_GameRun::Draw(Crawler*game){
}
void State_GameRun::FontTest(){
- game->DrawStringDecal({8,8},"#000000This is a #000066test of hex");
- game->DrawStringDecal({8,16},"#FF0000This is a #BFA6F9test of hex");
- game->DrawStringDecal({8,24},"#00FF00This is a #E9A6F9test of hex");
- game->DrawStringDecal({8,32},"#0000FFThis is a #F9E8A6test of hex");
- game->DrawShadowStringDecal({8,40},"#000000This is a #000066test of hex");
- game->DrawShadowStringDecal({8,48},"#FF0000This is a #BFA6F9test of hex");
- game->DrawShadowStringDecal({8,56},"#00FF00This is a #E9A6F9test of hex");
- game->DrawShadowStringDecal({8,64},"#0000FFThis is a #F9E8A6test of hex");
- game->DrawShadowStringDecal(VisualNovel::font,{8,72},U"#000000This is a #000066test of hex");
- game->DrawShadowStringDecal(VisualNovel::font,{8,80},U"#FF0000This is a #BFA6F9test of hex");
- game->DrawShadowStringDecal(VisualNovel::font,{8,88},U"#00FF00This is a #E9A6F9test of hex");
- game->DrawShadowStringDecal(VisualNovel::font,{8,96},U"#0000FFThis is a #F9E8A6test of hex");
+ port.DrawStringDecal({8,8},"#FFFFFFThis is a #000066test of hex");
+ port.DrawStringDecal({8,16},"#FF0000This is a #BFA6F9test of hex");
+ port.DrawStringDecal({8,24},"#00FF00This is a #E9A6F9test of hex");
+ port.DrawStringDecal({8,32},"#0000FFThis is a #F9E8A6test of hex");
+ port.DrawShadowStringDecal({8,40},"#FFFFFFThis is a #000066test of hex");
+ port.DrawShadowStringDecal({8,48},"#FF0000This is a #BFA6F9test of hex");
+ port.DrawShadowStringDecal({8,56},"#00FF00This is a #E9A6F9test of hex");
+ port.DrawShadowStringDecal({8,64},"#0000FFThis is a #F9E8A6test of hex");
+ port.DrawShadowStringDecal(VisualNovel::font,{8,72},U"#FFFFFFThis is a #000066test of hex");
+ port.DrawShadowStringDecal(VisualNovel::font,{8,80},U"#FF0000This is a #BFA6F9test of hex");
+ port.DrawShadowStringDecal(VisualNovel::font,{8,88},U"#00FF00This is a #E9A6F9test of hex");
+ port.DrawShadowStringDecal(VisualNovel::font,{8,96},U"#0000FFThis is a #F9E8A6test of hex");
}
\ No newline at end of file
diff --git a/Crawler/State_GameRun.h b/Crawler/State_GameRun.h
index a8931edb..90c9bf13 100644
--- a/Crawler/State_GameRun.h
+++ b/Crawler/State_GameRun.h
@@ -37,8 +37,10 @@ All rights reserved.
#pragma endregion
#pragma once
#include "GameState.h"
+#include "olcPGEX_ViewPort.h"
class State_GameRun:public GameState{
+ ViewPort port;
virtual void OnStateChange(GameState*prevState)override final;
virtual void OnUserUpdate(Crawler*game)override final;
virtual void Draw(Crawler*game)override final;
diff --git a/Crawler/State_OverworldMap.cpp b/Crawler/State_OverworldMap.cpp
index 1724a4ec..ec52dc26 100644
--- a/Crawler/State_OverworldMap.cpp
+++ b/Crawler/State_OverworldMap.cpp
@@ -35,7 +35,6 @@ Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
-#include "State_OverworldMap.h"
#include "Crawler.h"
#include "DEFINES.h"
#include "Menu.h"
@@ -46,6 +45,7 @@ All rights reserved.
#include "MenuLabel.h"
#include "EncountersSpawnListScrollableWindowComponent.h"
#include "VisualNovel.h"
+#include "State_OverworldMap.h"
INCLUDE_MONSTER_LIST
INCLUDE_game
diff --git a/Crawler/State_OverworldMap.h b/Crawler/State_OverworldMap.h
index b1a69756..4f65deb8 100644
--- a/Crawler/State_OverworldMap.h
+++ b/Crawler/State_OverworldMap.h
@@ -38,6 +38,7 @@ All rights reserved.
#pragma once
#include "GameState.h"
#include "ConnectionPoint.h"
+#include "olcPGEX_ViewPort.h"
class State_OverworldMap:public GameState{
friend class Crawler;
diff --git a/Crawler/Version.h b/Crawler/Version.h
index 8b582ff8..f208064c 100644
--- a/Crawler/Version.h
+++ b/Crawler/Version.h
@@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 1
-#define VERSION_BUILD 3827
+#define VERSION_BUILD 3862
#define stringify(a) stringify_(a)
#define stringify_(a) #a
diff --git a/Crawler/olcPGEX_ViewPort.h b/Crawler/olcPGEX_ViewPort.h
new file mode 100644
index 00000000..7a4893e2
--- /dev/null
+++ b/Crawler/olcPGEX_ViewPort.h
@@ -0,0 +1,775 @@
+#pragma once
+
+#include "olcPixelGameEngine.h"
+#include "olcPGEX_TTF.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Declarations
+namespace olc {
+ class ViewPort : public olc::PGEX {
+ public:
+ ViewPort();
+ ViewPort(std::vector vertices, vf2d offset = {0, 0});
+ virtual ~ViewPort();
+ void addPoint(vf2d point);
+ void clear();
+ void drawEdges();
+ void setOffset(vf2d offset);
+
+ static ViewPort rectViewPort(vf2d topLeft,
+ vf2d size,
+ olc::vf2d offset = {0, 0});
+
+ void DrawDecal(const olc::vf2d &pos,
+ olc::Decal *decal,
+ const olc::vf2d &scale = {1.0f, 1.0f},
+ const olc::Pixel &tint = olc::WHITE) const;
+ void DrawPartialDecal(const olc::vf2d &pos,
+ olc::Decal *decal,
+ const olc::vf2d &source_pos,
+ const olc::vf2d &source_size,
+ const olc::vf2d &scale = {1.0f, 1.0f},
+ const olc::Pixel &tint = olc::WHITE) const;
+ void DrawPartialDecal(const vf2d &pos,
+ const vf2d &size,
+ Decal *decal,
+ const vf2d source_pos,
+ const vf2d &source_size,
+ const Pixel &tint = olc::WHITE) const;
+ void DrawExplicitDecal(olc::Decal *decal,
+ const olc::vf2d *pos,
+ const olc::vf2d *uv,
+ const olc::Pixel *col,
+ uint32_t elements = 4) const;
+ void DrawWarpedDecal(Decal *decal,
+ const vf2d (&pos)[4],
+ const Pixel &tint = WHITE) const;
+ void DrawWarpedDecal(Decal *decal,
+ const vf2d *pos,
+ const Pixel &tint = WHITE) const;
+ void DrawWarpedDecal(Decal *decal,
+ const std::array &pos,
+ const Pixel &tint = WHITE) const;
+ void DrawPartialWarpedDecal(Decal *decal,
+ const vf2d (&pos)[4],
+ const vf2d &source_pos,
+ const vf2d &source_size,
+ const Pixel &tint = WHITE) const;
+ void DrawPartialWarpedDecal(Decal *decal,
+ const vf2d *pos,
+ const vf2d &source_pos,
+ const vf2d &source_size,
+ const Pixel &tint = WHITE) const;
+ void DrawPartialWarpedDecal(Decal *decal,
+ const std::array &pos,
+ const vf2d &source_pos,
+ const vf2d &source_size,
+ const Pixel &tint = WHITE) const;
+ void DrawRotatedDecal(const vf2d &pos,
+ Decal *decal,
+ const float fAngle,
+ const vf2d ¢er = {0.0f, 0.0f},
+ const vf2d &scale = {1.0f, 1.0f},
+ const Pixel &tint = WHITE) const;
+ void DrawPartialRotatedDecal(const vf2d &pos,
+ Decal *decal,
+ const float fAngle,
+ const vf2d ¢er,
+ const vf2d &source_pos,
+ const vf2d &source_size,
+ const vf2d &scale = {1.0f, 1.0f},
+ const Pixel &tint = WHITE) const;
+ void FillRectDecal(const vf2d &pos,
+ const vf2d &size,
+ const Pixel col = WHITE) const;
+ void GradientFillRectDecal(const vf2d &pos,
+ const vf2d &size,
+ const Pixel colTL,
+ const Pixel colBL,
+ const Pixel colBR,
+ const Pixel colTR) const;
+ void DrawPolygonDecal(Decal *decal,
+ const std::vector &pos,
+ const std::vector &uv,
+ const Pixel tint = WHITE) const;
+ void DrawPolygonDecal(Decal *decal,
+ const std::vector &pos,
+ const std::vector &depth,
+ const std::vector &uv,
+ const Pixel tint = WHITE) const;
+ void DrawPolygonDecal(Decal *decal,
+ const std::vector &pos,
+ const std::vector &uv,
+ const std::vector &tint) const;
+ void DrawLineDecal(const vf2d &pos1,
+ const vf2d &pos2,
+ Pixel p = WHITE) const;
+ // Draws a multiline string as a decal, with tinting and scaling
+ void DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
+ void DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
+ void DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
+ void DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
+ void DrawShadowStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
+ void DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
+ void DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f });
+
+ private:
+ void drawClippedDecal(Decal *decal,
+ const vf2d *points,
+ const vf2d *uvs,
+ const Pixel *col,
+ uint32_t elements = 0) const;
+
+ static float lineSegmentIntersect(vf2d lineA,
+ vf2d lineB,
+ vf2d segmentA,
+ vf2d segmentB);
+ static float directionFromLine(vf2d lineA, vf2d lineB, vf2d point);
+
+ std::vector clipVertices;
+ olc::vf2d offset;
+ };
+} // namespace olc
+
+// Definitions
+
+#ifdef OLC_PGEX_VIEWPORT
+#undef OLC_PGEX_VIEWPORT
+
+olc::ViewPort::ViewPort() {
+}
+olc::ViewPort::~ViewPort() {
+}
+
+olc::ViewPort::ViewPort(std::vector vertices, olc::vf2d offset)
+ : clipVertices{vertices},
+ offset{offset} {
+}
+
+void olc::ViewPort::addPoint(vf2d point) {
+ clipVertices.push_back(point);
+}
+
+void olc::ViewPort::clear() {
+ clipVertices.clear();
+}
+
+void olc::ViewPort::drawEdges() {
+ for (auto i = 0u; i < clipVertices.size(); i++) {
+ auto current = clipVertices[i] + offset;
+ auto next = clipVertices[(i + 1) % clipVertices.size()] + offset;
+
+ pge->DrawLineDecal(current, next, olc::RED);
+ }
+}
+
+void olc::ViewPort::setOffset(vf2d offset) {
+ this->offset = offset;
+}
+
+olc::ViewPort
+ olc::ViewPort::rectViewPort(vf2d topLeft, vf2d size, olc::vf2d offset) {
+ return {{
+ topLeft,
+ {topLeft.x, topLeft.y + size.y},
+ topLeft + size,
+ {topLeft.x + size.x, topLeft.y},
+ },
+ offset};
+}
+
+void olc::ViewPort::DrawDecal(const olc::vf2d &pos,
+ olc::Decal *decal,
+ const olc::vf2d &scale,
+ const olc::Pixel &tint) const {
+ std::vector points{
+ pos,
+ {pos.x, pos.y + decal->sprite->height * scale.y},
+ {pos.x + decal->sprite->width * scale.x,
+ pos.y + decal->sprite->height * scale.y},
+ {pos.x + decal->sprite->width * scale.x, pos.y},
+ };
+ DrawWarpedDecal(decal, points.data(), tint);
+}
+
+void olc::ViewPort::DrawPartialDecal(const olc::vf2d &pos,
+ olc::Decal *decal,
+ const olc::vf2d &source_pos,
+ const olc::vf2d &source_size,
+ const olc::vf2d &scale,
+ const olc::Pixel &tint) const {
+ DrawPartialDecal(pos, source_size * scale, decal, source_pos, source_size, tint);
+}
+
+void olc::ViewPort::DrawPartialDecal(const vf2d &pos,
+ const vf2d &size,
+ Decal *decal,
+ const vf2d source_pos,
+ const vf2d &source_size,
+ const Pixel &tint) const {
+ std::vector points{
+ pos,
+ {pos.x, pos.y + size.y},
+ pos + size,
+ {pos.x + size.x, pos.y},
+ };
+ DrawPartialWarpedDecal(decal, points.data(), source_pos, source_size, tint);
+}
+
+void olc::ViewPort::DrawExplicitDecal(olc::Decal *decal,
+ const olc::vf2d *pos,
+ const olc::vf2d *uv,
+ const olc::Pixel *col,
+ uint32_t elements) const {
+ drawClippedDecal(decal, pos, uv, col, elements);
+}
+
+void olc::ViewPort::DrawWarpedDecal(Decal *decal,
+ const vf2d (&pos)[4],
+ const Pixel &tint) const {
+ DrawWarpedDecal(decal, (const vf2d *)pos, tint);
+}
+void olc::ViewPort::DrawWarpedDecal(Decal *decal,
+ const vf2d *pos,
+ const Pixel &tint) const {
+ std::vector uvs{
+ {0, 0},
+ {0, 1},
+ {1, 1},
+ {1, 0},
+ };
+ std::vector cols{
+ tint,
+ tint,
+ tint,
+ tint,
+ };
+
+ drawClippedDecal(decal, pos, uvs.data(), cols.data(), 4);
+}
+void olc::ViewPort::DrawWarpedDecal(Decal *decal,
+ const std::array &pos,
+ const Pixel &tint) const {
+ DrawWarpedDecal(decal, pos.data(), tint);
+}
+
+void olc::ViewPort::DrawPartialWarpedDecal(Decal *decal,
+ const vf2d (&pos)[4],
+ const vf2d &source_pos,
+ const vf2d &source_size,
+ const Pixel &tint) const {
+ DrawPartialWarpedDecal(decal,
+ (const vf2d *)pos,
+ source_pos,
+ source_size,
+ tint);
+}
+
+void olc::ViewPort::DrawPartialWarpedDecal(Decal *decal,
+ const vf2d *pos,
+ const vf2d &source_pos,
+ const vf2d &source_size,
+ const Pixel &tint) const {
+ olc::vf2d sourceUvPos =
+ source_pos
+ / olc::vf2d{static_cast(decal->sprite->width),
+ static_cast(decal->sprite->height)};
+ olc::vf2d sourceUvSize =
+ source_size
+ / olc::vf2d{static_cast(decal->sprite->width),
+ static_cast(decal->sprite->height)};
+ std::vector uvs{
+ sourceUvPos,
+ {sourceUvPos.x, sourceUvPos.y + sourceUvSize.y},
+ sourceUvPos + sourceUvSize,
+ {sourceUvPos.x + sourceUvSize.x, sourceUvPos.y},
+ };
+ std::vector cols{
+ tint,
+ tint,
+ tint,
+ tint,
+ };
+
+ drawClippedDecal(decal, pos, uvs.data(), cols.data(), 4);
+}
+
+void olc::ViewPort::DrawPartialWarpedDecal(Decal *decal,
+ const std::array &pos,
+ const vf2d &source_pos,
+ const vf2d &source_size,
+ const Pixel &tint) const {
+ DrawPartialWarpedDecal(decal, pos.data(), source_pos, source_size, tint);
+}
+
+void olc::ViewPort::DrawRotatedDecal(const vf2d &pos,
+ Decal *decal,
+ const float fAngle,
+ const vf2d ¢er,
+ const vf2d &scale,
+ const Pixel &tint) const {
+ auto sin = std::sin(fAngle);
+ auto cos = std::cos(fAngle);
+
+ std::vector points{
+ -center * scale,
+ olc::vf2d{-center.x, decal->sprite->height - center.y} * scale,
+ olc::vf2d{decal->sprite->width - center.x,
+ decal->sprite->height - center.y}
+ * scale,
+ olc::vf2d{decal->sprite->width - center.x, -center.y} * scale,
+ };
+
+ for (auto i = 0u; i < points.size(); i++) {
+ points[i] = pos
+ + olc::vf2d{points[i].x * cos - points[i].y * sin,
+ points[i].x * sin + points[i].y * cos};
+ }
+
+ DrawWarpedDecal(decal, points.data(), tint);
+}
+
+void olc::ViewPort::DrawPartialRotatedDecal(const vf2d &pos,
+ Decal *decal,
+ const float fAngle,
+ const vf2d ¢er,
+ const vf2d &source_pos,
+ const vf2d &source_size,
+ const vf2d &scale,
+ const Pixel &tint) const {
+ auto sin = std::sin(fAngle);
+ auto cos = std::cos(fAngle);
+
+ std::vector points{
+ -center * scale,
+ olc::vf2d{-center.x, source_size.y - center.y} * scale,
+ (source_size - center) * scale,
+ olc::vf2d{source_size.x - center.x, -center.y} * scale,
+ };
+
+ for (auto i = 0u; i < points.size(); i++) {
+ points[i] = pos
+ + olc::vf2d{points[i].x * cos - points[i].y * sin,
+ points[i].x * sin + points[i].y * cos};
+ }
+
+ DrawPartialWarpedDecal(decal, points.data(), source_pos, source_size, tint);
+}
+
+void olc::ViewPort::FillRectDecal(const vf2d &pos,
+ const vf2d &size,
+ const Pixel col) const {
+ std::vector points{
+ pos,
+ {pos.x, pos.y + size.y},
+ pos + size,
+ {pos.x + size.y, pos.y},
+ };
+ std::vector uvs{
+ {0, 0},
+ {0, 1},
+ {1, 1},
+ {1, 0},
+ };
+
+ DrawPolygonDecal(nullptr, points, uvs, col);
+}
+
+void olc::ViewPort::GradientFillRectDecal(const vf2d &pos,
+ const vf2d &size,
+ const Pixel colTL,
+ const Pixel colBL,
+ const Pixel colBR,
+ const Pixel colTR) const {
+ std::vector points{
+ pos,
+ {pos.x, pos.y + size.y},
+ pos + size,
+ {pos.x + size.y, pos.y},
+ };
+
+ std::vector uvs{
+ {0, 0},
+ {0, 1},
+ {1, 1},
+ {1, 0},
+ };
+
+ std::vector colors{
+ colTL,
+ colBL,
+ colBR,
+ colTR,
+ };
+
+ drawClippedDecal(nullptr, points.data(), uvs.data(), colors.data(), points.size());
+}
+
+void olc::ViewPort::DrawPolygonDecal(Decal *decal,
+ const std::vector &pos,
+ const std::vector &uv,
+ const Pixel tint) const {
+ std::vector colors;
+ colors.resize(pos.size());
+ for (auto i = 0u; i < colors.size(); i++) {
+ colors[i] = tint;
+ }
+
+ drawClippedDecal(decal, pos.data(), uv.data(), colors.data(), pos.size());
+}
+
+void olc::ViewPort::DrawPolygonDecal(Decal *decal,
+ const std::vector &pos,
+ const std::vector &,
+ const std::vector &uv,
+ const Pixel tint) const {
+ DrawPolygonDecal(decal, pos, uv, tint);
+}
+
+void olc::ViewPort::DrawPolygonDecal(Decal *decal,
+ const std::vector &pos,
+ const std::vector &uv,
+ const std::vector &tint) const {
+ drawClippedDecal(decal, pos.data(), uv.data(), tint.data(), pos.size());
+}
+
+void olc::ViewPort::DrawLineDecal(const vf2d &pos1,
+ const vf2d &pos2,
+ Pixel p) const {
+ vf2d posA = pos1;
+ vf2d posB = pos2;
+
+ for (auto i = 0u; i < clipVertices.size(); i++) {
+ auto clipA = clipVertices[i];
+ auto clipB = clipVertices[(i + 1) % clipVertices.size()];
+
+ auto intersection = lineSegmentIntersect(clipA, clipB, posA, posB);
+ if (intersection < 0 || intersection > 1) {
+ continue;
+ }
+
+ auto clipDirection = directionFromLine(clipA, clipB, posA);
+ auto intersectionPoint = posA + (posB - posA) * intersection;
+
+ if (clipDirection >= 0) {
+ posA = intersectionPoint;
+ } else {
+ posB = intersectionPoint;
+ }
+ }
+
+ pge->DrawLineDecal(posA + offset, posB + offset, p);
+}
+
+void olc::ViewPort::drawClippedDecal(Decal *decal,
+ const vf2d *points,
+ const vf2d *uvs,
+ const Pixel *col,
+ uint32_t elements) const {
+ std::vector outputList{points, points + elements};
+ std::vector outputUvs{uvs, uvs + elements};
+ std::vector outputCols{col, col + elements};
+
+ for (auto i = 0u; i < clipVertices.size(); i++) {
+ auto clipA = clipVertices[i];
+ auto clipB = clipVertices[(i + 1) % 4];
+
+ auto inputList{outputList};
+ auto inputUvs{outputUvs};
+ auto inputCols{outputCols};
+ outputList.clear();
+ outputUvs.clear();
+ outputCols.clear();
+
+ for (auto i = 0u; i < inputList.size(); i++) {
+ auto polygonA = inputList[i];
+ auto polygonB = inputList[(i + 1) % inputList.size()];
+ auto uvA = inputUvs[i];
+ auto uvB = inputUvs[(i + 1) % inputList.size()];
+ auto colA = inputCols[i];
+ auto colB = inputCols[(i + 1) % inputList.size()];
+
+ auto intersection =
+ lineSegmentIntersect(clipA, clipB, polygonA, polygonB);
+ auto intersectionPoint =
+ polygonA + (polygonB - polygonA) * intersection;
+ auto intersectionUv = uvA + (uvB - uvA) * intersection;
+ auto intersectionCol = PixelLerp(colA, colB, intersection);
+
+ float aDirection = directionFromLine(clipA, clipB, polygonA);
+ float bDirection = directionFromLine(clipA, clipB, polygonB);
+
+ if (bDirection <= 0) {
+ if (aDirection > 0) {
+ outputList.push_back(intersectionPoint);
+ outputUvs.push_back(intersectionUv);
+ outputCols.push_back(intersectionCol);
+ }
+ outputList.push_back(polygonB);
+ outputUvs.push_back(uvB);
+ outputCols.push_back(colB);
+ } else if (aDirection <= 0) {
+ outputList.push_back(intersectionPoint);
+ outputUvs.push_back(intersectionUv);
+ outputCols.push_back(intersectionCol);
+ }
+ }
+ }
+
+ if (outputList.size() == 0) {
+ return;
+ }
+
+ for (auto &point : outputList) {
+ point += offset;
+ }
+
+ pge->DrawExplicitDecal(decal,
+ outputList.data(),
+ outputUvs.data(),
+ outputCols.data(),
+ outputList.size());
+}
+
+float olc::ViewPort::lineSegmentIntersect(vf2d lineA,
+ vf2d lineB,
+ vf2d segmentA,
+ vf2d segmentB) {
+ return ((lineA.x - segmentA.x) * (lineA.y - lineB.y)
+ - (lineA.y - segmentA.y) * (lineA.x - lineB.x))
+ / ((lineA.x - lineB.x) * (segmentA.y - segmentB.y)
+ - (lineA.y - lineB.y) * (segmentA.x - segmentB.x));
+}
+
+float olc::ViewPort::directionFromLine(vf2d lineA, vf2d lineB, vf2d point) {
+ return (lineB.x - lineA.x) * (point.y - lineA.y)
+ - (point.x - lineA.x) * (lineB.y - lineA.y);
+}
+
+void olc::ViewPort::DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale){
+ olc::vf2d spos = { 0.0f, 0.0f };
+ Pixel textCol=col;
+ const auto hexToNumber=[](char c){
+ if(c<='9')return c-'0';
+ return (c-'A')+10;
+ };
+ for (int skip=0,index=-1;auto c : sText)
+ {
+ index++;
+ if(skip){
+ skip--;
+ continue;
+ }
+ if(c=='\r')continue; //Ignore carriage returns. Stupid Linux.
+ if (c == '\n')
+ {
+ spos.x = 0; spos.y += 8.0f * scale.y;
+ }
+ else if (c == '\t')
+ {
+ spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
+ }
+ else if (c>=-128&&c<-105)
+ {
+ textCol={PixelGameEngine::charToColor[c].r,PixelGameEngine::charToColor[c].g,PixelGameEngine::charToColor[c].b,col.a};
+ }
+ else if (c=='#')
+ {
+ skip=6;
+ textCol=BLACK;
+ for(int i=1;i<7;i++){
+ if(i<3){
+ textCol.r*=16;
+ textCol.r+=hexToNumber(sText[index+i]);
+ }else
+ if(i<5){
+ textCol.g*=16;
+ textCol.g+=hexToNumber(sText[index+i]);
+ }else{
+ textCol.b*=16;
+ textCol.b+=hexToNumber(sText[index+i]);
+ }
+ }
+ }
+ else
+ {
+ int32_t ox = (c - 32) % 16;
+ int32_t oy = (c - 32) / 16;
+ DrawPartialDecal(pos + spos, pge->GetFontDecal(), {float(ox) * 8.0f, float(oy) * 8.0f}, {8.0f, 8.0f}, scale, textCol);
+ spos.x += 8.0f * scale.x;
+ }
+ }
+}
+
+void olc::ViewPort::DrawStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const olc::vf2d& scale){
+ struct DecalData{
+ Decal*decal;
+ float expireTime=0.0f;
+ };
+ if(sText.length()==0)return;
+ static std::mapgarbageCollector;
+ std::u32string key=font.GetFontName()+U"_"+sText;
+ if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
+ garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
+ }
+ garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
+ std::erase_if(garbageCollector,[&](auto&key){
+ if(key.second.expireTimeGetRuntime()){
+ delete key.second.decal;
+ return true;
+ }
+ return false;
+ });
+ DrawDecal(pos,garbageCollector[key].decal,scale/4,col);
+}
+
+void olc::ViewPort::DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale){
+ olc::vf2d spos = { 0.0f, 0.0f };
+ Pixel textCol=col;
+ const auto hexToNumber=[](char c){
+ if(c<='9')return c-'0';
+ return (c-'A')+10;
+ };
+ for (int skip=0,index=-1;auto c : sText)
+ {
+ index++;
+ if(skip){
+ skip--;
+ continue;
+ }
+ if(c=='\r')continue; //Ignore carriage returns. Stupid Linux.
+ if (c == '\n')
+ {
+ spos.x = 0; spos.y += 8.0f * scale.y;
+ }
+ else if (c == '\t')
+ {
+ spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x;
+ }
+ else if (c>=-128&&c<-105)
+ {
+ textCol={PixelGameEngine::charToColor[c].r,PixelGameEngine::charToColor[c].g,PixelGameEngine::charToColor[c].b,col.a};
+ }
+ else if (c==PixelGameEngine::Reset[0])
+ {
+ textCol=col;
+ }
+ else if (c=='#')
+ {
+ skip=6;
+ textCol=BLACK;
+ for(int i=1;i<7;i++){
+ if(i<3){
+ textCol.r*=16;
+ textCol.r+=hexToNumber(sText[index+i]);
+ }else
+ if(i<5){
+ textCol.g*=16;
+ textCol.g+=hexToNumber(sText[index+i]);
+ }else{
+ textCol.b*=16;
+ textCol.b+=hexToNumber(sText[index+i]);
+ }
+ }
+ }
+ else
+ {
+ int32_t ox = (c - 32) % 16;
+ int32_t oy = (c - 32) / 16;
+ DrawPartialDecal(pos + spos, pge->GetFontDecal(), { float(ox) * 8.0f + float(pge->vFontSpacing[c - 32].x), float(oy) * 8.0f }, { float(pge->vFontSpacing[c - 32].y), 8.0f }, scale, textCol);
+ spos.x += float(pge->vFontSpacing[c - 32].y) * scale.x;
+ }
+ }
+}
+
+void olc::ViewPort::DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){
+ std::string strippedText=sText;
+ std::erase_if(strippedText,[](char chr){return chr<0;});
+ int skip=0;
+ std::erase_if(strippedText,[&](char chr){if(skip>0){skip--;return true;}if(chr=='#'){skip=6;return true;}return false;});
+ for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){
+ for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){
+ if(x!=0||y!=0){
+ DrawStringDecal(pos+vf2d{x,y}, strippedText, shadowCol,scale);
+ }
+ }
+ }
+ DrawStringDecal(pos, sText, col,scale);
+}
+
+void olc::ViewPort::DrawShadowStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){
+ std::string strippedText=sText;
+ std::erase_if(strippedText,[](char chr){return chr<0;});
+ int skip=0;
+ std::erase_if(strippedText,[&](char chr){if(skip>0){skip--;return true;}if(chr=='#'){skip=6;return true;}return false;});
+ for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){
+ for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){
+ if(x!=0||y!=0){
+ DrawStringPropDecal(pos+vf2d{x,y}, strippedText, shadowCol,scale);
+ }
+ }
+ }
+ DrawStringPropDecal(pos, sText, col,scale);
+}
+
+void olc::ViewPort::DrawShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){
+ struct DecalData{
+ Decal*decal;
+ float expireTime=0.0f;
+ };
+ if(sText.length()==0)return;
+ static std::mapgarbageCollector;
+ std::u32string key=font.GetFontName()+U"_"+sText;
+ if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
+ garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
+ }
+ garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
+ std::erase_if(garbageCollector,[&](auto&key){
+ if(key.second.expireTimeGetRuntime()){
+ delete key.second.decal;
+ return true;
+ }
+ return false;
+ });
+ for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){
+ for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){
+ if(x!=0||y!=0){
+ DrawDecal(pos+vf2d{x,y},garbageCollector[key].decal,scale/4,shadowCol);
+ }
+ }
+ }
+ DrawDecal(pos,garbageCollector[key].decal,scale/4,col);
+}
+
+void olc::ViewPort::DrawDropShadowStringDecal(Font&font, const olc::vf2d& pos, const std::u32string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale){
+ struct DecalData{
+ Decal*decal;
+ float expireTime=0.0f;
+ };
+ if(sText.length()==0)return;
+ static std::mapgarbageCollector;
+ std::u32string key=font.GetFontName()+U"_"+sText;
+ if(!garbageCollector.count(key)){ //If the text key already exists, don't have to recreate the decal, just update the expire time.
+ garbageCollector[key].decal=font.RenderStringToDecal(sText,WHITE);
+ }
+ garbageCollector[key].expireTime=pge->GetRuntime()+120.0f;
+ std::erase_if(garbageCollector,[&](auto&key){
+ if(key.second.expireTimeGetRuntime()){
+ delete key.second.decal;
+ return true;
+ }
+ return false;
+ });
+ DrawDecal(pos+vf2d{0,0.5f},garbageCollector[key].decal,scale/4,shadowCol);
+ DrawDecal(pos+vf2d{0.5f,0},garbageCollector[key].decal,scale/4,shadowCol);
+ DrawDecal(pos+vf2d{0.5f,0.5f},garbageCollector[key].decal,scale/4,shadowCol);
+ DrawDecal(pos,garbageCollector[key].decal,scale/4,col);
+}
+
+#endif
\ No newline at end of file
diff --git a/Crawler/olcPixelGameEngine.h b/Crawler/olcPixelGameEngine.h
index da2d031d..d9b24053 100644
--- a/Crawler/olcPixelGameEngine.h
+++ b/Crawler/olcPixelGameEngine.h
@@ -1171,6 +1171,8 @@ namespace olc
void ClearBuffer(Pixel p, bool bDepth = true);
// Returns the font image
olc::Sprite* GetFontSprite();
+ // Returns the font image
+ olc::Decal* GetFontDecal();
// Clip a line segment to visible area
bool ClipLineToScreen(olc::vi2d& in_p1, olc::vi2d& in_p2);
@@ -1254,6 +1256,8 @@ namespace olc
public: // Branding
std::string sAppName;
+ friend class ViewPort;
+
private: // Inner mysterious workings
olc::Sprite* pDrawTarget = nullptr;
Pixel::Mode nPixelMode = Pixel::NORMAL;
@@ -2461,6 +2465,8 @@ namespace olc
olc::Sprite* PixelGameEngine::GetFontSprite()
{ return fontRenderable.Sprite(); }
+ olc::Decal* PixelGameEngine::GetFontDecal()
+ { return fontRenderable.Decal(); }
bool PixelGameEngine::ClipLineToScreen(olc::vi2d& in_p1, olc::vi2d& in_p2)
{
diff --git a/Crawler/pixelGameEngine.cpp b/Crawler/pixelGameEngine.cpp
index dc93023c..a6680bf1 100644
--- a/Crawler/pixelGameEngine.cpp
+++ b/Crawler/pixelGameEngine.cpp
@@ -39,6 +39,8 @@ All rights reserved.
//#define OLC_PGE_HEADLESS
#define OLC_PGEX_TTF
#include "olcPGEX_TTF.h"
+#define OLC_PGEX_VIEWPORT
+#include "olcPGEX_ViewPort.h"
#define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"
#define OLC_PGEX_TRANSFORMEDVIEW