diff --git a/Crawler/Crawler.vcxproj b/Crawler/Crawler.vcxproj
index 42db6863..4edb87fc 100644
--- a/Crawler/Crawler.vcxproj
+++ b/Crawler/Crawler.vcxproj
@@ -283,6 +283,7 @@
+
diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters
index 70b8f184..7f5bcf5f 100644
--- a/Crawler/Crawler.vcxproj.filters
+++ b/Crawler/Crawler.vcxproj.filters
@@ -183,6 +183,9 @@
Header Files\Interface
+
+ Header Files
+
diff --git a/Crawler/InventoryWindow.cpp b/Crawler/InventoryWindow.cpp
index 7572bbc1..3637f5c7 100644
--- a/Crawler/InventoryWindow.cpp
+++ b/Crawler/InventoryWindow.cpp
@@ -19,7 +19,9 @@ Menu*Menu::InitializeInventoryWindow(){
constexpr int buttonSize=24;
constexpr int totalSpacing=buttonSize+itemSpacing;
- Menu*inventoryWindow=new Menu(CENTERED,{totalSpacing*invWidth-itemSpacing,totalSpacing*(invHeight+1)-itemSpacing});
+ vf2d windowSize={totalSpacing*invWidth-itemSpacing+1,totalSpacing*(invHeight+1)-itemSpacing+24};
+
+ Menu*inventoryWindow=new Menu(CENTERED,windowSize);
MenuFunc useItemFunc=[](MenuFuncData data){
MenuItemButton*button=(MenuItemButton*)data.component;
@@ -34,9 +36,9 @@ Menu*Menu::InitializeInventoryWindow(){
}
}
- MenuLabel*itemNameLabel=new MenuLabel{INVENTORY,vf2d{0,invHeight*totalSpacing-4},"",false,true};
+ MenuLabel*itemNameLabel=new MenuLabel{INVENTORY,geom2d::rect(vf2d{2,invHeight*totalSpacing-4},windowSize),"",false,true};
inventoryWindow->AddComponent("itemName",itemNameLabel);
- MenuLabel*itemDescriptionLabel=new MenuLabel{INVENTORY,vf2d{2+inventoryWindow->size.x/2,invHeight*totalSpacing+4+itemSpacing},"",true,true};
+ MenuLabel*itemDescriptionLabel=new MenuLabel{INVENTORY,geom2d::rect(vf2d{2,invHeight*totalSpacing+itemSpacing},{windowSize.x-4,windowSize.y-108}),"",true,true};
inventoryWindow->AddComponent("itemDescription",itemDescriptionLabel);
return inventoryWindow;
diff --git a/Crawler/Menu.cpp b/Crawler/Menu.cpp
index 5bc0aa46..1399bcaf 100644
--- a/Crawler/Menu.cpp
+++ b/Crawler/Menu.cpp
@@ -17,7 +17,8 @@ Menu::Menu(){}
Menu::Menu(vf2d pos,vf2d size)
:pos(pos==CENTERED?WINDOW_SIZE/2-size/2:vi2d{pos}),size(size){
-
+ r.Create(size.x,size.y);
+ overlay.Create(WINDOW_SIZE.x,WINDOW_SIZE.y);
}
void Menu::InitializeMenus(){
@@ -139,30 +140,65 @@ void Menu::Update(Crawler*game){
};
void Menu::Draw(Crawler*game){
-
if(GetCurrentTheme().IsScaled()){
- DrawScaledWindow(game,pos);
+ DrawScaledWindowBackground(game,pos);
}else{
- DrawTiledWindow(game,pos);
+ DrawTiledWindowBackground(game,pos);
}
+ game->SetDrawTarget(r.Sprite());
+ Pixel::Mode prevMode=game->GetPixelMode();
+ game->SetPixelMode(Pixel::MASK);
+ game->Clear(BLANK);
+ for(auto&key:buttons){
+ for(auto&button:key.second){
+ button->Draw(game,{0,0},this==Menu::stack.back());
+ }
+ }
+ for(auto&component:displayComponents){
+ component->Draw(game,{0,0},this==Menu::stack.back());
+ }
+ game->SetPixelMode(prevMode);
+ game->SetDrawTarget(nullptr);
+ r.Decal()->Update();
+ game->DrawDecal(pos,r.Decal());
for(auto&key:buttons){
for(auto&button:key.second){
- button->Draw(game,pos,this==Menu::stack.back());
+ button->DrawDecal(game,{0,0},this==Menu::stack.back());
}
}
for(auto&component:displayComponents){
- component->Draw(game,pos,this==Menu::stack.back());
+ component->DrawDecal(game,{0,0},this==Menu::stack.back());
+ }
+
+ if(GetCurrentTheme().IsScaled()){
+ DrawScaledWindowBorder(game,pos);
+ }else{
+ DrawTiledWindowBorder(game,pos);
}
if(draggingComponent!=nullptr){
+ game->SetDrawTarget(overlay.Sprite());
+ Pixel::Mode prevMode=game->GetPixelMode();
+ game->SetPixelMode(Pixel::MASK);
+ game->Clear(BLANK);
vf2d offsetPos=draggingComponent->rect.pos;
if(!MOUSE_NAVIGATION){
MenuComponent*selectedComponent=buttons[selection.y][selection.x];
- draggingComponent->Draw(game,pos+-offsetPos+selectedComponent->rect.pos+vi2d{1,-4},this==Menu::stack.back());
+ draggingComponent->Draw(game,pos-offsetPos+selectedComponent->rect.pos+vi2d{1,-4},this==Menu::stack.back());
}else{
draggingComponent->Draw(game,-offsetPos+game->GetMousePos(),this==Menu::stack.back());
}
+ game->SetPixelMode(prevMode);
+ game->SetDrawTarget(nullptr);
+ overlay.Decal()->Update();
+ game->DrawDecal({0,0},overlay.Decal());
+ if(!MOUSE_NAVIGATION){
+ MenuComponent*selectedComponent=buttons[selection.y][selection.x];
+ draggingComponent->DrawDecal(game,-offsetPos+selectedComponent->rect.pos+vi2d{1,-4},this==Menu::stack.back());
+ }else{
+ draggingComponent->DrawDecal(game,-pos-offsetPos+game->GetMousePos(),this==Menu::stack.back());
+ }
}
};
@@ -299,7 +335,7 @@ void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){
}
}
-void Menu::DrawScaledWindow(Crawler*game,vf2d menuPos){
+void Menu::DrawScaledWindowBorder(Crawler*game,vf2d menuPos){
vf2d patchSize={"Interface.9PatchSize"_f[0],"Interface.9PatchSize"_f[1]};
//Upper-Left
@@ -318,16 +354,9 @@ void Menu::DrawScaledWindow(Crawler*game,vf2d menuPos){
game->DrawPartialDecal(menuPos+vf2d{size.x,0},vf2d{patchSize.x,size.y},GetPatchPart(2,1).Decal(),{patchSize.x*2,patchSize.y*1},patchSize,GetRenderColor());
//Bottom
game->DrawPartialDecal(menuPos+vf2d{0,size.y},vf2d{size.x,patchSize.y},GetPatchPart(1,2).Decal(),{patchSize.x*1,patchSize.y*2},patchSize,GetRenderColor());
- //Center
- if(GetCurrentTheme().HasBackground()){
- Decal*back=GetCurrentTheme().GetBackground();
- game->DrawPartialDecal(menuPos,size,back,{0,0},back->sprite->Size(),GetRenderColor());
- }else{
- game->DrawPartialDecal(menuPos,size,GetPatchPart(1,1).Decal(),{patchSize.x*1,patchSize.y*1},patchSize,GetRenderColor());
- }
}
-void Menu::DrawTiledWindow(Crawler*game,vf2d menuPos){
+void Menu::DrawTiledWindowBorder(Crawler*game,vf2d menuPos){
vf2d patchSize={"Interface.9PatchSize"_f[0],"Interface.9PatchSize"_f[1]};
//Upper-Left
@@ -346,6 +375,23 @@ void Menu::DrawTiledWindow(Crawler*game,vf2d menuPos){
game->DrawPartialDecal(menuPos+vf2d{size.x,0},vf2d{patchSize.x,size.y},GetPatchPart(2,1).Decal(),{0,0},vf2d{patchSize.x,size.y},GetRenderColor());
//Bottom
game->DrawPartialDecal(menuPos+vf2d{0,size.y},vf2d{size.x,patchSize.y},GetPatchPart(1,2).Decal(),{0,0},vf2d{size.x,patchSize.y},GetRenderColor());
+}
+
+void Menu::DrawScaledWindowBackground(Crawler*game,vf2d menuPos){
+ vf2d patchSize={"Interface.9PatchSize"_f[0],"Interface.9PatchSize"_f[1]};
+
+ //Center
+ if(GetCurrentTheme().HasBackground()){
+ Decal*back=GetCurrentTheme().GetBackground();
+ game->DrawPartialDecal(menuPos,size,back,{0,0},back->sprite->Size(),GetRenderColor());
+ }else{
+ game->DrawPartialDecal(menuPos,size,GetPatchPart(1,1).Decal(),{patchSize.x*1,patchSize.y*1},patchSize,GetRenderColor());
+ }
+}
+
+void Menu::DrawTiledWindowBackground(Crawler*game,vf2d menuPos){
+ vf2d patchSize={"Interface.9PatchSize"_f[0],"Interface.9PatchSize"_f[1]};
+
//Center
if(GetCurrentTheme().HasBackground()){
Decal*back=GetCurrentTheme().GetBackground();
diff --git a/Crawler/Menu.h b/Crawler/Menu.h
index 9b73782e..60480180 100644
--- a/Crawler/Menu.h
+++ b/Crawler/Menu.h
@@ -24,18 +24,15 @@ class Menu:IAttributable{
friend class Crawler;
friend class Player;
static bool MOUSE_NAVIGATION;
- static std::mapmenus;
float buttonHoldTime=0;
std::map>buttons; //Buttons are stored in rows followed by their column order.
std::map>newButtonArrangement; //The new setup that the buttons will be at if a drag operation completes.
std::vectordisplayComponents; //Components that are only for displaying purposes.
vi2d selection={-1,-1};
- vf2d pos; //Specify the upper-left corner of the window. Using CENTERED will always put this where the upper-left corner would center the window.
- vf2d size; //Size in tiles (24x24), every menu will be tile-based
MenuComponent*draggingComponent=nullptr;
- Renderable r;
+ Renderable r,overlay;
public:
Menu();
Menu(vf2d pos,vf2d size);
@@ -49,6 +46,9 @@ public:
static safeunorderedmapthemes;
static const vf2d CENTERED;
safemapcomponents; //A friendly way to interrogate any component we are interested in.
+ static std::mapmenus;
+ vf2d pos; //Specify the upper-left corner of the window. Using CENTERED will always put this where the upper-left corner would center the window.
+ vf2d size; //Size in tiles (24x24), every menu will be tile-based
private:
void HoverMenuSelect(Crawler*game);
@@ -63,8 +63,10 @@ private:
static Theme&GetCurrentTheme();
void KeyboardButtonNavigation(Crawler*game,vf2d menuPos);
- void DrawScaledWindow(Crawler*game,vf2d menuPos);
- void DrawTiledWindow(Crawler*game,vf2d menuPos);
+ void DrawScaledWindowBackground(Crawler*game,vf2d menuPos);
+ void DrawTiledWindowBackground(Crawler*game,vf2d menuPos);
+ void DrawScaledWindowBorder(Crawler*game,vf2d menuPos);
+ void DrawTiledWindowBorder(Crawler*game,vf2d menuPos);
Pixel GetRenderColor();
};
diff --git a/Crawler/MenuComponent.cpp b/Crawler/MenuComponent.cpp
index af5f5925..aafd12a9 100644
--- a/Crawler/MenuComponent.cpp
+++ b/Crawler/MenuComponent.cpp
@@ -16,13 +16,15 @@ void MenuComponent::Update(Crawler*game){
}
void MenuComponent::Draw(Crawler*game,vf2d parentPos,bool focused){
- game->FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F)*(focused?1:"ThemeGlobal.MenuUnfocusedColorMult"_F));
+ game->FillRect(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F)*(focused?1:"ThemeGlobal.MenuUnfocusedColorMult"_F));
if(border){
- game->DrawRectDecal(rect.pos+parentPos,rect.size,focused?GREY:GREY*"ThemeGlobal.MenuUnfocusedColorMult"_F);
+ game->DrawRect(rect.pos+parentPos,rect.size,focused?GREY:GREY*"ThemeGlobal.MenuUnfocusedColorMult"_F);
}
- game->DrawStringPropDecal(rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
+ game->DrawStringProp(rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
}
+void MenuComponent::DrawDecal(Crawler*game,vf2d parentPos,bool focused){}
+
MenuComponent*MenuComponent::PickUpDraggableItem(){
return nullptr;
}
diff --git a/Crawler/MenuComponent.h b/Crawler/MenuComponent.h
index f2677c84..418caed6 100644
--- a/Crawler/MenuComponent.h
+++ b/Crawler/MenuComponent.h
@@ -21,6 +21,7 @@ public:
MenuComponent(MenuType parent,geom2d::rectrect,std::string label,MenuType menuDest,MenuFunc onClick,bool selectable=true);
virtual void Update(Crawler*game);
virtual void Draw(Crawler*game,vf2d parentPos,bool focused);
+ virtual void DrawDecal(Crawler*game,vf2d parentPos,bool focused);
//We picked up a draggable component, we should make a copy and return it here. If a nullptr is returned here, the pickup is not allowed.
//WARNING!!! This allocates a brand new component when successful!!! Be prepared to clear it!
virtual MenuComponent*PickUpDraggableItem();
diff --git a/Crawler/MenuIconButton.h b/Crawler/MenuIconButton.h
index 9b9f639f..d6ab4082 100644
--- a/Crawler/MenuIconButton.h
+++ b/Crawler/MenuIconButton.h
@@ -18,7 +18,7 @@ protected:
virtual inline void Draw(Crawler*game,vf2d parentPos,bool focused)override{
MenuComponent::Draw(game,parentPos,focused);
if(icon!=nullptr){
- game->DrawRotatedDecal(parentPos+rect.middle(),icon,0,icon->sprite->Size()/2,{1,1},focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
+ game->DrawSprite(parentPos+rect.middle()-icon->sprite->Size()/2,icon->sprite,1,Sprite::Flip::NONE,[&](Pixel&in){return focused?in:in*"ThemeGlobal.MenuUnfocusedColorMult"_F;});
}
}
};
\ No newline at end of file
diff --git a/Crawler/MenuItemButton.h b/Crawler/MenuItemButton.h
index ff6e934d..2c64e5a4 100644
--- a/Crawler/MenuItemButton.h
+++ b/Crawler/MenuItemButton.h
@@ -4,6 +4,7 @@
#include "Crawler.h"
#include "Item.h"
#include "safemap.h"
+#include "olcPGEX_Graphics2D.h"
INCLUDE_game
INCLUDE_ITEM_DATA
@@ -57,12 +58,12 @@ protected:
}
}
}
- virtual inline void Draw(Crawler*game,vf2d parentPos,bool focused)override{
- MenuIconButton::Draw(game,parentPos,focused);
+ virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
+ MenuIconButton::DrawDecal(game,parentPos,focused);
if(valid){
std::string quantityText="x"+std::to_string(Inventory::GetItemCount(invRef.at(inventoryIndex)));
vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*0.5;
- game->DrawShadowStringDecal(parentPos+rect.pos+rect.size-textSize,quantityText,WHITE,BLACK,{0.5,0.5},0.5);
+ game->DrawShadowStringDecal(Menu::menus[parentMenu]->pos+parentPos+rect.pos+rect.size-textSize,quantityText,WHITE,BLACK,{0.5,0.5},0.5);
}
}
virtual inline MenuComponent*PickUpDraggableItem()override{
diff --git a/Crawler/MenuLabel.h b/Crawler/MenuLabel.h
index 64b1bc18..d2251b00 100644
--- a/Crawler/MenuLabel.h
+++ b/Crawler/MenuLabel.h
@@ -2,6 +2,7 @@
#include "MenuComponent.h"
#include "DEFINES.h"
#include "Crawler.h"
+#include "utils.h"
INCLUDE_game
@@ -21,14 +22,15 @@ protected:
MenuComponent::Update(game);
}
virtual void inline Draw(Crawler*game,vf2d parentPos,bool focused)override{
- vf2d drawPos=rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2; //Assume centered.
+ std::string wrappedText=util::WrapText(game,label,rect.size.x,true,{1,1});
+ vf2d drawPos=parentPos+rect.middle()-game->GetTextSizeProp(wrappedText)/2; //Assume centered.
if(!centered){
drawPos=rect.pos+parentPos;
}
if(shadow){
- game->DrawShadowStringPropDecal(drawPos,label,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
+ game->DrawShadowStringProp(drawPos,wrappedText,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
}else{
- game->DrawStringPropDecal(drawPos,label,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
+ game->DrawStringProp(drawPos,wrappedText,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
}
}
};
\ No newline at end of file
diff --git a/Crawler/Version.h b/Crawler/Version.h
index 6a1a75ba..2498cb57 100644
--- a/Crawler/Version.h
+++ b/Crawler/Version.h
@@ -2,7 +2,7 @@
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 0
-#define VERSION_BUILD 1899
+#define VERSION_BUILD 1954
#define stringify(a) stringify_(a)
#define stringify_(a) #a
diff --git a/Crawler/olcPGEX_Graphics2D.h b/Crawler/olcPGEX_Graphics2D.h
new file mode 100644
index 00000000..45d473ef
--- /dev/null
+++ b/Crawler/olcPGEX_Graphics2D.h
@@ -0,0 +1,313 @@
+/*
+ olcPGEX_Graphics2D.h
+
+ +-------------------------------------------------------------+
+ | OneLoneCoder Pixel Game Engine Extension |
+ | Advanced 2D Rendering - v0.5 |
+ +-------------------------------------------------------------+
+
+ What is this?
+ ~~~~~~~~~~~~~
+ This is an extension to the olcPixelGameEngine, which provides
+ advanced olc::Sprite manipulation and drawing routines. To use
+ it, simply include this header file.
+
+ License (OLC-3)
+ ~~~~~~~~~~~~~~~
+
+ Copyright 2018 - 2019 OneLoneCoder.com
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions or derivations of source code must retain the above
+ copyright notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions or derivative works in binary form must reproduce
+ the above copyright notice. This list of conditions and the following
+ disclaimer must be reproduced in the documentation and/or other
+ materials provided with the distribution.
+
+ 3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Links
+ ~~~~~
+ YouTube: https://www.youtube.com/javidx9
+ Discord: https://discord.gg/WhwHUMV
+ Twitter: https://www.twitter.com/javidx9
+ Twitch: https://www.twitch.tv/javidx9
+ GitHub: https://www.github.com/onelonecoder
+ Homepage: https://www.onelonecoder.com
+
+ Author
+ ~~~~~~
+ David Barr, aka javidx9, ŠOneLoneCoder 2019
+*/
+
+/*
+ Matrices stored as [Column][Row] (i.e. x, y)
+
+ |C0R0 C1R0 C2R0| | x | | x'|
+ |C0R1 C1R1 C2R1| * | y | = | y'|
+ |C0R2 C1R2 C2R2| |1.0| | - |
+*/
+
+
+
+#ifndef OLC_PGEX_GFX2D
+#define OLC_PGEX_GFX2D
+
+#include
+#undef min
+#undef max
+
+namespace olc
+{
+ // Container class for Advanced 2D Drawing functions
+ class GFX2D : public olc::PGEX
+ {
+ // A representation of an affine transform, used to rotate, scale, offset & shear space
+ public:
+ class Transform2D
+ {
+ public:
+ Transform2D();
+
+ public:
+ // Set this transformation to unity
+ void Reset();
+ // Append a rotation of fTheta radians to this transform
+ void Rotate(float fTheta);
+ // Append a translation (ox, oy) to this transform
+ void Translate(float ox, float oy);
+ // Append a scaling operation (sx, sy) to this transform
+ void Scale(float sx, float sy);
+ // Append a shear operation (sx, sy) to this transform
+ void Shear(float sx, float sy);
+
+ void Perspective(float ox, float oy);
+ // Calculate the Forward Transformation of the coordinate (in_x, in_y) -> (out_x, out_y)
+ void Forward(float in_x, float in_y, float &out_x, float &out_y);
+ // Calculate the Inverse Transformation of the coordinate (in_x, in_y) -> (out_x, out_y)
+ void Backward(float in_x, float in_y, float &out_x, float &out_y);
+ // Regenerate the Inverse Transformation
+ void Invert();
+
+ private:
+ void Multiply();
+ float matrix[4][3][3];
+ int nTargetMatrix;
+ int nSourceMatrix;
+ bool bDirty;
+ };
+
+ public:
+ // Draws a sprite with the transform applied
+ static void DrawSprite(olc::Sprite *sprite, olc::GFX2D::Transform2D &transform);
+ };
+}
+
+
+#ifdef OLC_PGEX_GRAPHICS2D
+#undef OLC_PGEX_GRAPHICS2D
+
+namespace olc
+{
+ void GFX2D::DrawSprite(olc::Sprite *sprite, olc::GFX2D::Transform2D &transform)
+ {
+ if (sprite == nullptr)
+ return;
+
+ // Work out bounding rectangle of sprite
+ float ex, ey;
+ float sx, sy;
+ float px, py;
+
+ transform.Forward(0.0f, 0.0f, sx, sy);
+ px = sx; py = sy;
+ sx = std::min(sx, px); sy = std::min(sy, py);
+ ex = std::max(ex, px); ey = std::max(ey, py);
+
+ transform.Forward((float)sprite->width, (float)sprite->height, px, py);
+ sx = std::min(sx, px); sy = std::min(sy, py);
+ ex = std::max(ex, px); ey = std::max(ey, py);
+
+ transform.Forward(0.0f, (float)sprite->height, px, py);
+ sx = std::min(sx, px); sy = std::min(sy, py);
+ ex = std::max(ex, px); ey = std::max(ey, py);
+
+ transform.Forward((float)sprite->width, 0.0f, px, py);
+ sx = std::min(sx, px); sy = std::min(sy, py);
+ ex = std::max(ex, px); ey = std::max(ey, py);
+
+ // Perform inversion of transform if required
+ transform.Invert();
+
+ if (ex < sx)
+ std::swap(ex, sx);
+ if (ey < sy)
+ std::swap(ey, sy);
+
+ // Iterate through render space, and sample Sprite from suitable texel location
+ for (float i = sx; i < ex; i++)
+ {
+ for (float j = sy; j < ey; j++)
+ {
+ float ox, oy;
+ transform.Backward(i, j, ox, oy);
+ pge->Draw((int32_t)i, (int32_t)j, sprite->GetPixel((int32_t)(ox+0.5f), (int32_t)(oy+0.5f)));
+ }
+ }
+ }
+
+ olc::GFX2D::Transform2D::Transform2D()
+ {
+ Reset();
+ }
+
+ void olc::GFX2D::Transform2D::Reset()
+ {
+ nTargetMatrix = 0;
+ nSourceMatrix = 1;
+ bDirty = true;
+
+ // Columns Then Rows
+
+ // Matrices 0 & 1 are used as swaps in Transform accumulation
+ matrix[0][0][0] = 1.0f; matrix[0][1][0] = 0.0f; matrix[0][2][0] = 0.0f;
+ matrix[0][0][1] = 0.0f; matrix[0][1][1] = 1.0f; matrix[0][2][1] = 0.0f;
+ matrix[0][0][2] = 0.0f; matrix[0][1][2] = 0.0f; matrix[0][2][2] = 1.0f;
+
+ matrix[1][0][0] = 1.0f; matrix[1][1][0] = 0.0f; matrix[1][2][0] = 0.0f;
+ matrix[1][0][1] = 0.0f; matrix[1][1][1] = 1.0f; matrix[1][2][1] = 0.0f;
+ matrix[1][0][2] = 0.0f; matrix[1][1][2] = 0.0f; matrix[1][2][2] = 1.0f;
+
+ // Matrix 2 is a cache matrix to hold the immediate transform operation
+ // Matrix 3 is a cache matrix to hold the inverted transform
+ }
+
+ void olc::GFX2D::Transform2D::Multiply()
+ {
+ for (int c = 0; c < 3; c++)
+ {
+ for (int r = 0; r < 3; r++)
+ {
+ matrix[nTargetMatrix][c][r] = matrix[2][0][r] * matrix[nSourceMatrix][c][0] +
+ matrix[2][1][r] * matrix[nSourceMatrix][c][1] +
+ matrix[2][2][r] * matrix[nSourceMatrix][c][2];
+ }
+ }
+
+ std::swap(nTargetMatrix, nSourceMatrix);
+ bDirty = true; // Any transform multiply dirties the inversion
+ }
+
+ void olc::GFX2D::Transform2D::Rotate(float fTheta)
+ {
+ // Construct Rotation Matrix
+ matrix[2][0][0] = cosf(fTheta); matrix[2][1][0] = sinf(fTheta); matrix[2][2][0] = 0.0f;
+ matrix[2][0][1] = -sinf(fTheta); matrix[2][1][1] = cosf(fTheta); matrix[2][2][1] = 0.0f;
+ matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
+ Multiply();
+ }
+
+ void olc::GFX2D::Transform2D::Scale(float sx, float sy)
+ {
+ // Construct Scale Matrix
+ matrix[2][0][0] = sx; matrix[2][1][0] = 0.0f; matrix[2][2][0] = 0.0f;
+ matrix[2][0][1] = 0.0f; matrix[2][1][1] = sy; matrix[2][2][1] = 0.0f;
+ matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
+ Multiply();
+ }
+
+ void olc::GFX2D::Transform2D::Shear(float sx, float sy)
+ {
+ // Construct Shear Matrix
+ matrix[2][0][0] = 1.0f; matrix[2][1][0] = sx; matrix[2][2][0] = 0.0f;
+ matrix[2][0][1] = sy; matrix[2][1][1] = 1.0f; matrix[2][2][1] = 0.0f;
+ matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
+ Multiply();
+ }
+
+ void olc::GFX2D::Transform2D::Translate(float ox, float oy)
+ {
+ // Construct Translate Matrix
+ matrix[2][0][0] = 1.0f; matrix[2][1][0] = 0.0f; matrix[2][2][0] = ox;
+ matrix[2][0][1] = 0.0f; matrix[2][1][1] = 1.0f; matrix[2][2][1] = oy;
+ matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
+ Multiply();
+ }
+
+ void olc::GFX2D::Transform2D::Perspective(float ox, float oy)
+ {
+ // Construct Translate Matrix
+ matrix[2][0][0] = 1.0f; matrix[2][1][0] = 0.0f; matrix[2][2][0] = 0.0f;
+ matrix[2][0][1] = 0.0f; matrix[2][1][1] = 1.0f; matrix[2][2][1] = 0.0f;
+ matrix[2][0][2] = ox; matrix[2][1][2] = oy; matrix[2][2][2] = 1.0f;
+ Multiply();
+ }
+
+ void olc::GFX2D::Transform2D::Forward(float in_x, float in_y, float &out_x, float &out_y)
+ {
+ out_x = in_x * matrix[nSourceMatrix][0][0] + in_y * matrix[nSourceMatrix][1][0] + matrix[nSourceMatrix][2][0];
+ out_y = in_x * matrix[nSourceMatrix][0][1] + in_y * matrix[nSourceMatrix][1][1] + matrix[nSourceMatrix][2][1];
+ float out_z = in_x * matrix[nSourceMatrix][0][2] + in_y * matrix[nSourceMatrix][1][2] + matrix[nSourceMatrix][2][2];
+ if (out_z != 0)
+ {
+ out_x /= out_z;
+ out_y /= out_z;
+ }
+ }
+
+ void olc::GFX2D::Transform2D::Backward(float in_x, float in_y, float &out_x, float &out_y)
+ {
+ out_x = in_x * matrix[3][0][0] + in_y * matrix[3][1][0] + matrix[3][2][0];
+ out_y = in_x * matrix[3][0][1] + in_y * matrix[3][1][1] + matrix[3][2][1];
+ float out_z = in_x * matrix[3][0][2] + in_y * matrix[3][1][2] + matrix[3][2][2];
+ if (out_z != 0)
+ {
+ out_x /= out_z;
+ out_y /= out_z;
+ }
+ }
+
+ void olc::GFX2D::Transform2D::Invert()
+ {
+ if (bDirty) // Obviously costly so only do if needed
+ {
+ float det = matrix[nSourceMatrix][0][0] * (matrix[nSourceMatrix][1][1] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][1][2] * matrix[nSourceMatrix][2][1]) -
+ matrix[nSourceMatrix][1][0] * (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][2][1] * matrix[nSourceMatrix][0][2]) +
+ matrix[nSourceMatrix][2][0] * (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][1][2] - matrix[nSourceMatrix][1][1] * matrix[nSourceMatrix][0][2]);
+
+ float idet = 1.0f / det;
+ matrix[3][0][0] = (matrix[nSourceMatrix][1][1] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][1][2] * matrix[nSourceMatrix][2][1]) * idet;
+ matrix[3][1][0] = (matrix[nSourceMatrix][2][0] * matrix[nSourceMatrix][1][2] - matrix[nSourceMatrix][1][0] * matrix[nSourceMatrix][2][2]) * idet;
+ matrix[3][2][0] = (matrix[nSourceMatrix][1][0] * matrix[nSourceMatrix][2][1] - matrix[nSourceMatrix][2][0] * matrix[nSourceMatrix][1][1]) * idet;
+ matrix[3][0][1] = (matrix[nSourceMatrix][2][1] * matrix[nSourceMatrix][0][2] - matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][2][2]) * idet;
+ matrix[3][1][1] = (matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][2][0] * matrix[nSourceMatrix][0][2]) * idet;
+ matrix[3][2][1] = (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][2][0] - matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][2][1]) * idet;
+ matrix[3][0][2] = (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][1][2] - matrix[nSourceMatrix][0][2] * matrix[nSourceMatrix][1][1]) * idet;
+ matrix[3][1][2] = (matrix[nSourceMatrix][0][2] * matrix[nSourceMatrix][1][0] - matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][1][2]) * idet;
+ matrix[3][2][2] = (matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][1][1] - matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][1][0]) * idet;
+ bDirty = false;
+ }
+ }
+}
+
+#endif
+#endif
\ No newline at end of file
diff --git a/Crawler/olcPixelGameEngine.h b/Crawler/olcPixelGameEngine.h
index b472774e..5825f88d 100644
--- a/Crawler/olcPixelGameEngine.h
+++ b/Crawler/olcPixelGameEngine.h
@@ -805,6 +805,7 @@ namespace olc
public:
void SetSampleMode(olc::Sprite::Mode mode = olc::Sprite::Mode::NORMAL);
+ void Resize(int32_t w, int32_t h);
Pixel GetPixel(int32_t x, int32_t y) const;
bool SetPixel(int32_t x, int32_t y, Pixel p);
Pixel GetPixel(const olc::vi2d& a) const;
@@ -1093,20 +1094,21 @@ namespace olc
void FillTexturedTriangle(const std::vector& vPoints, std::vector vTex, std::vector vColour, olc::Sprite* sprTex);
void FillTexturedPolygon(const std::vector& vPoints, const std::vector& vTex, const std::vector& vColour, olc::Sprite* sprTex, olc::DecalStructure structure = olc::DecalStructure::LIST);
// Draws an entire sprite at location (x,y)
- void DrawSprite(int32_t x, int32_t y, Sprite* sprite, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE);
- void DrawSprite(const olc::vi2d& pos, Sprite* sprite, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE);
+ void DrawSprite(int32_t x, int32_t y, Sprite* sprite, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE, std::functioncolorFunc=[](Pixel&in){return in;});
+ void DrawSprite(const olc::vi2d& pos, Sprite* sprite, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE, std::functioncolorFunc=[](Pixel&in){return in;});
// Draws an area of a sprite at location (x,y), where the
// selected area is (ox,oy) to (ox+w,oy+h)
void DrawPartialSprite(int32_t x, int32_t y, Sprite* sprite, int32_t ox, int32_t oy, int32_t w, int32_t h, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE);
void DrawPartialSprite(const olc::vi2d& pos, Sprite* sprite, const olc::vi2d& sourcepos, const olc::vi2d& size, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE);
// Draws a single line of text - traditional monospaced
- void DrawString(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
- void DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
- olc::vi2d GetTextSize(const std::string& s);
- // Draws a single line of text - non-monospaced
- void DrawStringProp(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
void DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
+ void DrawShadowString(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
+ void DrawStringProp(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
+ void DrawShadowStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
+ olc::vi2d GetTextSize(const std::string& s);
olc::vi2d GetTextSizeProp(const std::string& s);
+ void DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
+ void DrawString(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
// Decal Quad functions
void SetDecalMode(const olc::DecalMode& mode);
@@ -1597,6 +1599,13 @@ namespace olc
Sprite::~Sprite()
{ pColData.clear(); }
+ void Sprite::Resize(int32_t w, int32_t h)
+ {
+ width = w; height = h;
+ pColData.resize(width * height);
+ pColData.resize(width * height, nDefaultPixel);
+ }
+
void Sprite::SetSampleMode(olc::Sprite::Mode mode)
{ modeSample = mode; }
@@ -2759,10 +2768,10 @@ namespace olc
}
- void PixelGameEngine::DrawSprite(const olc::vi2d& pos, Sprite* sprite, uint32_t scale, uint8_t flip)
+ void PixelGameEngine::DrawSprite(const olc::vi2d& pos, Sprite* sprite, uint32_t scale, uint8_t flip, std::functioncolorFunc)
{ DrawSprite(pos.x, pos.y, sprite, scale, flip); }
- void PixelGameEngine::DrawSprite(int32_t x, int32_t y, Sprite* sprite, uint32_t scale, uint8_t flip)
+ void PixelGameEngine::DrawSprite(int32_t x, int32_t y, Sprite* sprite, uint32_t scale, uint8_t flip, std::functioncolorFunc)
{
if (sprite == nullptr)
return;
@@ -3327,6 +3336,29 @@ namespace olc
}
DrawStringPropDecal(pos, sText, col,scale);
}
+
+ void PixelGameEngine::DrawShadowString(const olc::vi2d& pos, const std::string& sText, Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){
+ 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){
+ DrawString(pos.x+x,pos.y+y, sText, shadowCol,int(scale.x));
+ }
+ }
+ }
+ DrawString(pos.x,pos.y, sText, col,int(scale.x));
+ }
+
+ void PixelGameEngine::DrawShadowStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){
+ 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){
+ DrawStringProp(pos.x+x,pos.y+y, sText, shadowCol,int(scale.x));
+ }
+ }
+ }
+ DrawStringProp(pos.x,pos.y, sText, col,int(scale.x));
+ }
+
// Thanks Oso-Grande/Sopadeoso For these awesom and stupidly clever Text Rotation routines... duh XD
void PixelGameEngine::DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const Pixel col, const olc::vf2d& scale)
{
diff --git a/Crawler/pixelGameEngine.cpp b/Crawler/pixelGameEngine.cpp
index 0ff56113..26a00e8f 100644
--- a/Crawler/pixelGameEngine.cpp
+++ b/Crawler/pixelGameEngine.cpp
@@ -6,4 +6,6 @@
#define TMX_PARSER_SETUP
#include "TMXParser.h"
#define TSX_PARSER_SETUP
-#include "TSXParser.h"
\ No newline at end of file
+#include "TSXParser.h"
+#define OLC_PGEX_GRAPHICS2D
+#include "olcPGEX_Graphics2D.h"
\ No newline at end of file
diff --git a/Crawler/utils.cpp b/Crawler/utils.cpp
index 31887da6..89c58877 100644
--- a/Crawler/utils.cpp
+++ b/Crawler/utils.cpp
@@ -1,4 +1,5 @@
#include "utils.h"
+#include "olcPixelGameEngine.h"
float util::random(float range){
return float(rand())/RAND_MAX*range;
@@ -42,4 +43,28 @@ std::string util::timerStr(float time){
timeStr+=std::to_string(seconds%60);
return timeStr;
+}
+
+std::string util::WrapText(PixelGameEngine*pge,std::string str,int width,bool proportional,vd2d scale){
+ std::string newStr;
+ while (true) {
+ std::string word;
+ if (str.find(" ")==std::string::npos) {
+ word=str;
+ } else {
+ word = str.substr(0,str.find(" "));
+ }
+ vi2d newSize = vd2d(proportional?pge->GetTextSizeProp(newStr+(newStr.size()>0?" ":"")+word):pge->GetTextSize(newStr+(newStr.size()>0?" ":"")+word))*scale;
+ if (newSize.x>width) {
+ newStr+="\n"+word;
+ } else {
+ newStr+=(newStr.size()>0?" ":"")+word;
+ }
+ if (str.find(" ")==std::string::npos) {
+ break;
+ } else {
+ str.erase(0,str.find(" ")+1);
+ }
+ }
+ return newStr;
}
\ No newline at end of file
diff --git a/Crawler/utils.h b/Crawler/utils.h
index 24e583db..bd1399ac 100644
--- a/Crawler/utils.h
+++ b/Crawler/utils.h
@@ -12,4 +12,5 @@ namespace util{
float radToDeg(float rad);
float lerp(float n1,float n2,double t);
std::string timerStr(float time);
+ std::string WrapText(PixelGameEngine*pge,std::string str,int width,bool proportional,vd2d scale);
}
\ No newline at end of file