Add in new and edit buttons. Add delete functionality.

master
sigonasr2 9 months ago
parent 4c5781d0c9
commit 121845a4af
  1. BIN
      TiledCollisionEditor/EditButton.png
  2. 234
      TiledCollisionEditor/main.cpp
  3. BIN
      TiledCollisionEditor/newCollisionButton.png
  4. 415
      TiledCollisionEditor/olcPGEX_QuickGUI.h

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

@ -6,6 +6,7 @@
using namespace olc;
using namespace olc::utils;
using namespace QuickGUI;
const std::string TILESET_DIR="./Tiles/";
@ -23,6 +24,8 @@ class TiledCollisionEditor : public olc::PixelGameEngine
vf2d upperLeftDragOffset{};
Renderable circle;
Renderable createNewButtonImg;
Renderable editButtonImg;
TransformedView view;
@ -34,6 +37,11 @@ public:
Renderable rollingCounter;
Manager gui;
ImageCheckBox*createNewButton;
ImageCheckBox*editButton;
public:
bool OnUserCreate() override
{
@ -46,6 +54,9 @@ public:
SetDrawTarget(nullptr);
circle.Decal()->Update();
createNewButtonImg.Load("newCollisionButton.png");
editButtonImg.Load("EditButton.png");
std::string tilesetFilename=TILESET_DIR+"Basic Tileset.tsx";
Tileset&tileset=tilesets[tilesetFilename]=TSXParser{tilesetFilename}.GetData();
@ -55,6 +66,11 @@ public:
tilesetImg.Load(TILESET_DIR+tileset.filename);
if(tilesets.size()==1)activeTileset=tilesetFilename;
createNewButton=new ImageCheckBox{gui,createNewButtonImg,false,vf2d{4.f,ScreenHeight()-36.f},{32.f,32.f},{4,1},{32,32}};
createNewButton->hotkey=Q;
editButton=new ImageCheckBox{gui,editButtonImg,true,vf2d{40.f,ScreenHeight()-36.f},{32.f,32.f},{4,4},{32,32}};
editButton->hotkey=E;
return true;
}
@ -65,42 +81,9 @@ public:
float currentHealth=0;
float targetHealth=60;
bool OnUserUpdate(float fElapsedTime) override
{
Clear(VERY_DARK_BLUE);
view.HandlePanAndZoom();
void Update(){
const Tileset&tileset=tilesets[activeTileset];
view.DrawDecal({0,0},images[activeTileset].Decal());
for(int y=0;y<tileset.tilecount/tileset.columns;y++){
for(int x=0;x<tileset.columns;x++){
view.DrawRectDecal(vf2d{float(x),float(y)}*tileset.tilewidth,vf2d{float(tileset.tilewidth),float(tileset.tileheight)},GREY);
}
}
if(editingQuad==nullptr){
std::string selectedObj="";
}
for(auto&[objName,obj]:tileset.objects){
view.DrawLineDecal(obj.bounds.pos,obj.bounds.pos+vf2d{0.f,float(obj.bounds.size.y)},YELLOW);
view.DrawLineDecal(obj.bounds.pos,obj.bounds.pos+vf2d{float(obj.bounds.size.x),0.f},YELLOW);
view.DrawLineDecal(obj.bounds.pos+obj.bounds.size,obj.bounds.pos+obj.bounds.size+vf2d{0.f,-float(obj.bounds.size.y)},YELLOW);
view.DrawLineDecal(obj.bounds.pos+obj.bounds.size,obj.bounds.pos+obj.bounds.size+vf2d{-float(obj.bounds.size.x),0.f},YELLOW);
vi2d nameTextSize=GetTextSizeProp(objName)*0.25f;
view.GradientFillRectDecal(obj.bounds.pos,nameTextSize+vf2d{2,2},RED,{255,0,0,64},{255,0,0,64},RED);
view.DrawStringPropDecal(obj.bounds.pos+vf2d{1.25f,1.25f},objName,BLACK,vf2d{0.25f,0.25f});
view.DrawStringPropDecal(obj.bounds.pos+vf2d{1,1},objName,WHITE,vf2d{0.25f,0.25f});
if(geom2d::contains(obj.bounds,view.ScreenToWorld(GetMousePos()))){
selectedObj=objName;
}
}
if(selectedObj.length()>0){
for(int y=0;y<tileset.tilecount/tileset.columns;y++){
for(int x=0;x<tileset.columns;x++){
@ -140,22 +123,66 @@ public:
pointInd++;
}
}
if(GetMouse(Mouse::LEFT).bPressed){
#pragma region Select a point on a collision quad.
for(const Quadrilateral&quad:obj.collisionTiles){
for(size_t pointInd=0;const vf2d&point:quad){
if(geom2d::line<float>(point,view.ScreenToWorld(GetMousePos())).length()<4){
if(GetMouse(Mouse::LEFT).bPressed){
editingPoint=pointInd;
if(editButton->bChecked){
if(GetMouse(Mouse::LEFT).bPressed){
#pragma region Select a point on a collision quad.
for(const Quadrilateral&quad:obj.collisionTiles){
for(size_t pointInd=0;const vf2d&point:quad){
if(geom2d::line<float>(point,view.ScreenToWorld(GetMousePos())).length()<4){
if(GetMouse(Mouse::LEFT).bPressed){
editingPoint=pointInd;
editingQuad=const_cast<Quadrilateral*>(&quad);
originalQuad=quad;
}
goto exitCollisionCheck;
}
pointInd++;
}
}
#pragma endregion
for(const Quadrilateral&quad:obj.collisionTiles){
std::array<geom2d::triangle<float>,2>collisionTris{
geom2d::triangle<float>{quad[0],quad[1],quad[2]},
geom2d::triangle<float>{quad[0],quad[2],quad[3]},
};
for(geom2d::triangle<float>&tri:collisionTris){
if(geom2d::contains(tri,view.ScreenToWorld(GetMousePos()))){
dragTranslate=true;
editingQuad=const_cast<Quadrilateral*>(&quad);
upperLeftDragOffset=GetSnapPoint()-quad[0];
originalQuad=*editingQuad;
goto exitCollisionCheck;
}
goto exitCollisionCheck;
}
pointInd++;
}
exitCollisionCheck:
if(EditingQuad&&!dragging){
(*editingQuad)[editingPoint]=GetSnapPoint();
editingPoint++;
}
}
if(GetMouse(Mouse::RIGHT).bPressed||GetKey(ESCAPE).bPressed){
if(EditingQuad||dragTranslate){
editingPoint=4;
dragging=false;
*editingQuad=originalQuad;
editingQuad=nullptr;
dragTranslate=false;
}
}
#pragma endregion
}else{
if(GetMouse(Mouse::LEFT).bPressed){
Quadrilateral newQuad{GetSnapPoint()};
tilesets[activeTileset].objects[selectedObj].collisionTiles.push_back(newQuad);
dragging=true;
editingQuad=const_cast<Quadrilateral*>(&obj.collisionTiles.back());
originalQuad=*editingQuad;
}
}
if(GetMouse(Mouse::RIGHT).bPressed&&!EditingQuad&&!dragTranslate){
std::vector<Quadrilateral*>quadsToBeRemoved;
for(const Quadrilateral&quad:obj.collisionTiles){
std::array<geom2d::triangle<float>,2>collisionTris{
geom2d::triangle<float>{quad[0],quad[1],quad[2]},
@ -163,26 +190,15 @@ public:
};
for(geom2d::triangle<float>&tri:collisionTris){
if(geom2d::contains(tri,view.ScreenToWorld(GetMousePos()))){
dragTranslate=true;
editingQuad=const_cast<Quadrilateral*>(&quad);
upperLeftDragOffset=GetSnapPoint()-quad[0];
originalQuad=*editingQuad;
goto exitCollisionCheck;
//Delete this quad, the mouse is overlapping it!
quadsToBeRemoved.push_back(const_cast<Quadrilateral*>(&quad));
break;
}
}
}
exitCollisionCheck:
if(EditingQuad&&!dragging){
(*editingQuad)[editingPoint]=GetSnapPoint();
editingPoint++;
}else{
if(obj.collisionTiles.size()==0){
Quadrilateral newQuad{GetSnapPoint()};
tilesets[activeTileset].objects[selectedObj].collisionTiles.push_back(newQuad);
dragging=true;
editingQuad=const_cast<Quadrilateral*>(&obj.collisionTiles.back());
originalQuad=*editingQuad;
}
for(Quadrilateral*quad:quadsToBeRemoved){
std::erase_if(tilesets[activeTileset].objects[selectedObj].collisionTiles,[&](Quadrilateral&q){return &q==quad;});
}
}
@ -201,23 +217,72 @@ public:
}
dragTranslate=false;
}
}
}
if(GetMouse(Mouse::RIGHT).bPressed||GetKey(ESCAPE).bPressed){
if(EditingQuad){
editingPoint=4;
dragging=false;
*editingQuad=originalQuad;
editingQuad=nullptr;
}
bool OnUserUpdate(float fElapsedTime) override
{
Clear(VERY_DARK_BLUE);
view.HandlePanAndZoom();
const float CAMERA_MOVESPD = 150.f;
if(GetKey(W).bHeld)view.MoveWorldOffset(vf2d{0.f,-CAMERA_MOVESPD}*fElapsedTime/view.GetWorldScale());
if(GetKey(S).bHeld)view.MoveWorldOffset(vf2d{0.f,CAMERA_MOVESPD}*fElapsedTime/view.GetWorldScale());
if(GetKey(A).bHeld)view.MoveWorldOffset(vf2d{-CAMERA_MOVESPD,0.f}*fElapsedTime/view.GetWorldScale());
if(GetKey(D).bHeld)view.MoveWorldOffset(vf2d{CAMERA_MOVESPD,0.f}*fElapsedTime/view.GetWorldScale());
const Tileset&tileset=tilesets[activeTileset];
view.DrawDecal({0,0},images[activeTileset].Decal());
for(int y=0;y<tileset.tilecount/tileset.columns;y++){
for(int x=0;x<tileset.columns;x++){
view.DrawRectDecal(vf2d{float(x),float(y)}*tileset.tilewidth,vf2d{float(tileset.tilewidth),float(tileset.tileheight)},GREY);
}
}
if(editingQuad==nullptr){
std::string selectedObj="";
}
if(createNewButton->bPressed)editButton->bChecked=false;
if(editButton->bPressed)createNewButton->bChecked=false;
if(GetMouseY()<ScreenHeight()-36||GetMouseX()>72){
Update();
}
//Font test.
/*DrawStringDecal({0,0},"the quick brown fox jumps over the lazy dog 1234567890 !@#$%^&*()-=_+[]{}\\;':\",./<>?~`",WHITE,{1.5f,1.5f});
DrawStringDecal({0,18},"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 1234567890 !@#$%^&*()-=_+[]{}\\;':\",./<>?~`",WHITE,{1.5f,1.5f});
DrawStringPropDecal({0,36},"the quick brown fox jumps over the lazy dog 1234567890 !@#$%^&*()-=_+[]{}\\;':\",./<>?~`",WHITE,{1.5f,1.5f});
DrawStringPropDecal({0,54},"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 1234567890 !@#$%^&*()-=_+[]{}\\;':\",./<>?~`",WHITE,{1.5f,1.5f});
*/
if(selectedObj.length()>0){
const TilesetObject&obj=tileset.objects.at(selectedObj);
Quadrilateral*highlightedQuad=nullptr;
for(const Quadrilateral&quad:obj.collisionTiles){
std::array<geom2d::triangle<float>,2>collisionTris{
geom2d::triangle<float>{quad[0],quad[1],quad[2]},
geom2d::triangle<float>{quad[0],quad[2],quad[3]},
};
for(geom2d::triangle<float>&tri:collisionTris){
if(geom2d::contains(tri,view.ScreenToWorld(GetMousePos()))){
highlightedQuad=const_cast<Quadrilateral*>(&quad);
goto renderQuads;
}
}
}
renderQuads:
for(const Quadrilateral&quad:obj.collisionTiles){
std::vector<vf2d>points;
std::vector<vf2d>uvs;
std::vector<Pixel>cols;
points.assign(quad.begin(),quad.end());
uvs.assign(4,{0.f,0.f});
cols.assign(4,{255,40,40,128});
cols.assign(4,(!GetMouse(Mouse::LEFT).bHeld&&highlightedQuad==&quad)?Pixel{255,20,20,150}:Pixel{255,40,40,128});
view.DrawPolygonDecal(nullptr,points,uvs,cols);
for(bool highlighted=false;const vf2d&point:quad){
@ -230,13 +295,28 @@ public:
}
}
}
//Font test.
/*DrawStringDecal({0,0},"the quick brown fox jumps over the lazy dog 1234567890 !@#$%^&*()-=_+[]{}\\;':\",./<>?~`",WHITE,{1.5f,1.5f});
DrawStringDecal({0,18},"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 1234567890 !@#$%^&*()-=_+[]{}\\;':\",./<>?~`",WHITE,{1.5f,1.5f});
DrawStringPropDecal({0,36},"the quick brown fox jumps over the lazy dog 1234567890 !@#$%^&*()-=_+[]{}\\;':\",./<>?~`",WHITE,{1.5f,1.5f});
DrawStringPropDecal({0,54},"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 1234567890 !@#$%^&*()-=_+[]{}\\;':\",./<>?~`",WHITE,{1.5f,1.5f});
*/
for(auto&[objName,obj]:tileset.objects){
view.DrawLineDecal(obj.bounds.pos,obj.bounds.pos+vf2d{0.f,float(obj.bounds.size.y)},YELLOW);
view.DrawLineDecal(obj.bounds.pos,obj.bounds.pos+vf2d{float(obj.bounds.size.x),0.f},YELLOW);
view.DrawLineDecal(obj.bounds.pos+obj.bounds.size,obj.bounds.pos+obj.bounds.size+vf2d{0.f,-float(obj.bounds.size.y)},YELLOW);
view.DrawLineDecal(obj.bounds.pos+obj.bounds.size,obj.bounds.pos+obj.bounds.size+vf2d{-float(obj.bounds.size.x),0.f},YELLOW);
vi2d nameTextSize=GetTextSizeProp(objName)*0.25f;
view.GradientFillRectDecal(obj.bounds.pos,nameTextSize+vf2d{2,2},RED,{255,0,0,64},{255,0,0,64},RED);
view.DrawStringPropDecal(obj.bounds.pos+vf2d{1.25f,1.25f},objName,BLACK,vf2d{0.25f,0.25f});
view.DrawStringPropDecal(obj.bounds.pos+vf2d{1,1},objName,WHITE,vf2d{0.25f,0.25f});
if(geom2d::contains(obj.bounds,view.ScreenToWorld(GetMousePos()))){
selectedObj=objName;
}
}
gui.Update(this);
gui.DrawDecal(this);
DrawStringDecal(createNewButton->vPos+vf2d{3,0},"Q");
DrawStringDecal(editButton->vPos+vf2d{3,0},"E");
return true;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

@ -1,74 +1,73 @@
/*
OneLoneCoder - QuickGUI v1.03
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A semi-immediate mode GUI for very simple GUI stuff.
Includes:
Label - Displays a single-line string
TextBox - Click to enter/edit single-line text
Button - A clickable labelled rectangle
CheckBox - A clickable labelled rectangle that retains state
ImageButton - A Button with an image instead of text
ImageCheckBox- A CheckBox with an image instead of text
Slider - An omnidirectional draggable handle between two values
ListBox - A list of strings, that can be scrolled and an item selected
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2024 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, 2020, 2021, 2022, 2023, 2024
Changes
~~~~~~~
v1.01 +Moved Slider::fGrabRad into "theme"
+Manager::CopyThemeFrom() - copies theme attributes from a different manager
+ListBox - Displays a vector of strings
v1.02 +ImageButton
+ImageCheckBox
+ListBox::bSelectionChanged flag, true when list selected item changes
=Fix - Text box mouse behaviours, mouse release is now meaningless
+CheckBox Fix for decal display
v1.03 =Fix ImageCheckBox
/*
OneLoneCoder - QuickGUI v1.02
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A semi-immediate mode GUI for very simple GUI stuff.
Includes:
Label - Displays a single-line string
TextBox - Click to enter/edit single-line text
Button - A clickable labelled rectangle
CheckBox - A clickable labelled rectangle that retains state
ImageButton - A Button with an image instead of text
ImageCheckBox- A CheckBox with an image instead of text
Slider - An omnidirectional draggable handle between two values
ListBox - A list of strings, that can be scrolled and an item selected
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2021 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, <EFBFBD>OneLoneCoder 2019, 2020, 2021, 2022
Changes
~~~~~~~
v1.01 +Moved Slider::fGrabRad into "theme"
+Manager::CopyThemeFrom() - copies theme attributes from a different manager
+ListBox - Displays a vector of strings
v1.02 +ImageButton
+ImageCheckBox
+ListBox::bSelectionChanged flag, true when list selected item changes
=Fix - Text box mouse behaviours, mouse release is now meaningless
+CheckBox Fix for decal display
*/
@ -101,6 +100,8 @@ namespace olc::QuickGUI
bool bHeld = false;
// True on single frame control ceases being manipulated
bool bReleased = false;
// true on all frames control is being hovered over
bool bHovered = false;
public:
// Updates the controls behvaiour
@ -121,7 +122,7 @@ namespace olc::QuickGUI
// Hover - currently under the users mouse focus
// Click - user is interacting with the control
enum class State { Disabled, Normal, Hover, Click } m_state = State::Normal;
// To add a "swish" to things, controls can fade between states
float m_fTransition = 0.0;
};
@ -135,7 +136,7 @@ namespace olc::QuickGUI
// given to this manager via AddControl() if true
Manager(const bool bCleanUpForMe = true);
virtual ~Manager();
public:
// Add a gui element derived form BaseControl to this manager
void AddControl(BaseControl* control);
@ -145,15 +146,17 @@ namespace olc::QuickGUI
void Draw(olc::PixelGameEngine* pge);
// Draws as "decal" all controls this manager operates
void DrawDecal(olc::PixelGameEngine* pge);
public: // This managers "Theme" can be set here
// Various element colours
olc::Pixel colNormal = olc::DARK_BLUE;
olc::Pixel colHover = olc::BLUE;
olc::Pixel colClick = olc::CYAN;
olc::Pixel colDisable = olc::DARK_GREY;
olc::Pixel colBorder = olc::WHITE;
olc::Pixel colText = olc::WHITE;
olc::Pixel colNormal = {45, 0, 105};
olc::Pixel colSelected = {183, 99, 201};
olc::Pixel colHover = {173, 127, 235};
olc::Pixel colClick = {129, 36, 255};
olc::Pixel colDisable = {93, 87, 102};
olc::Pixel colBorder = {209, 209, 209};
olc::Pixel colBorderSelected = {63, 35, 84};
olc::Pixel colText = {209, 209, 209};
// Speed to transiton from Normal -> Hover
float fHoverSpeedOn = 10.0f;
// Speed to transiton from Hover -> Normal
@ -207,16 +210,17 @@ namespace olc::QuickGUI
TextBox(olc::QuickGUI::Manager& manager, // Associate with a Manager
const std::string& text, // Text to display
const olc::vf2d& pos, // Location of text box top-left
const olc::vf2d& size); // Size of text box
const olc::vf2d& size,
const olc::vf2d& fontSize={1,1}); // Size of text box
public: // BaseControl overrides
void Update(olc::PixelGameEngine* pge) override;
void Draw(olc::PixelGameEngine* pge) override;
void DrawDecal(olc::PixelGameEngine* pge) override;
protected:
bool m_bTextEdit = false;
protected:
vf2d fontSize;
};
// Creates a Button Control - a clickable, labelled rectangle
@ -226,8 +230,9 @@ namespace olc::QuickGUI
Button(olc::QuickGUI::Manager& manager, // Associate with a Manager
const std::string& text, // Text to display
const olc::vf2d& pos, // Location of button top-left
const olc::vf2d& size); // Size of button
const olc::vf2d& size,
const olc::vf2d& fontScale={1,1}); // Size of button
public:
// Position of button
olc::vf2d vPos;
@ -235,6 +240,8 @@ namespace olc::QuickGUI
olc::vf2d vSize;
// Text displayed on button
std::string sText;
olc::vf2d fontScale;
Key hotkey{NONE};
public: // BaseControl overrides
void Update(olc::PixelGameEngine* pge) override;
@ -261,16 +268,41 @@ namespace olc::QuickGUI
void DrawDecal(olc::PixelGameEngine* pge) override;
};
class CustomButton : public Button
{
public:
CustomButton(olc::QuickGUI::Manager& manager, // Associate with a Manager
const olc::Renderable &icon, // Text to display
const olc::Renderable &back_icon, // The image that appears behind the button, to be blended.
const olc::vf2d& pos, // Location of button top-left
const olc::vf2d& size,
const olc::vi2d& sprOffset,
const olc::vi2d& sprSize); // Size of button
public:
const olc::Renderable& pIcon;
const olc::Renderable& pBackIcon;
olc::vi2d sprOffset;
olc::vi2d sprSize;
public:
void DrawDecal(olc::PixelGameEngine* pge) override;
};
class ImageButton : public Button
{
public:
ImageButton(olc::QuickGUI::Manager& manager, // Associate with a Manager
const olc::Renderable &icon, // Text to display
const olc::vf2d& pos, // Location of button top-left
const olc::vf2d& size); // Size of button
const olc::vf2d& size,
const olc::vi2d& sprOffset,
const olc::vi2d& sprSize); // Size of button
public:
const olc::Renderable& pIcon;
olc::vi2d sprOffset;
olc::vi2d sprSize;
public:
void Draw(olc::PixelGameEngine* pge) override;
@ -284,7 +316,9 @@ namespace olc::QuickGUI
const olc::Renderable& icon, // Text to display
const bool check, // Is checked or not?
const olc::vf2d& pos, // Location of button top-left
const olc::vf2d& size); // Size of button
const olc::vf2d& size,
const olc::vi2d& sprOffset,
const olc::vi2d& sprSize); // Size of button
public:
bool bChecked = false;
@ -333,7 +367,8 @@ namespace olc::QuickGUI
ListBox(olc::QuickGUI::Manager& manager, // Associate with a Manager
std::vector<std::string>& vList,
const olc::vf2d& pos, // Location of list top-left
const olc::vf2d& size); // Size of list
const olc::vf2d& size, // Location of list top-left
const float fontSize=10); // Size of list
// Position of list
olc::vf2d vPos;
@ -343,12 +378,13 @@ namespace olc::QuickGUI
bool bHasBorder = true;
// Show a background?
bool bHasBackground = true;
public:
Slider *m_pSlider = nullptr;
Manager m_group;
size_t m_nVisibleItems = 0;
std::vector<std::string>& m_vList;
float fontSize=10;
public:
// Item currently selected
@ -468,7 +504,7 @@ namespace olc::QuickGUI
{
vPos = pos; vSize = size; sText = text;
}
void Label::Update(olc::PixelGameEngine* pge)
{
@ -537,8 +573,8 @@ namespace olc::QuickGUI
#pragma region TextBox
TextBox::TextBox(olc::QuickGUI::Manager& manager, const std::string& text, const olc::vf2d& pos, const olc::vf2d& size)
: Label(manager, text, pos, size)
TextBox::TextBox(olc::QuickGUI::Manager& manager, const std::string& text, const olc::vf2d& pos, const olc::vf2d& size,const olc::vf2d& fontSize)
: Label(manager, text, pos, size),fontSize(fontSize)
{
nAlign = Alignment::Left;
bHasBorder = true;
@ -552,9 +588,15 @@ namespace olc::QuickGUI
bPressed = false;
bReleased = false;
olc::vf2d vMouse = pge->GetMousePos();
if (m_bTextEdit && !pge->IsTextEntryEnabled()){
//sText = pge->TextEntryGetString();
m_bTextEdit = false;
}
if (vMouse.x >= vPos.x && vMouse.x < vPos.x + vSize.x &&
vMouse.y >= vPos.y && vMouse.y < vPos.y + vSize.y)
{
@ -568,7 +610,7 @@ namespace olc::QuickGUI
pge->TextEntryEnable(false);
}
if (bPressed && !pge->IsTextEntryEnabled() && !m_bTextEdit)
{
pge->TextEntryEnable(true, sText);
@ -577,7 +619,6 @@ namespace olc::QuickGUI
bHeld = pge->GetMouse(olc::Mouse::LEFT).bHeld;
}
else
{
@ -585,14 +626,14 @@ namespace olc::QuickGUI
bPressed = pge->GetMouse(olc::Mouse::LEFT).bPressed;
bReleased = pge->GetMouse(olc::Mouse::LEFT).bReleased;
bHeld = pge->GetMouse(olc::Mouse::LEFT).bHeld;
if (bPressed && m_bTextEdit)
if (bPressed && m_bTextEdit && pge->IsTextEntryEnabled())
{
sText = pge->TextEntryGetString();
pge->TextEntryEnable(false);
m_bTextEdit = false;
}
}
}
if (m_bTextEdit && pge->IsTextEntryEnabled())
sText = pge->TextEntryGetString();
@ -618,11 +659,11 @@ namespace olc::QuickGUI
olc::vf2d vCursorPos = pge->GetTextSizeProp(sText.substr(0, i));
pge->FillRect(olc::vf2d(vPos.x + 2.0f + vCursorPos.x, (vPos.y + (vSize.y - 10.0f) * 0.5f)), { 2, 10 }, m_manager.colText);
}
// Draw Text
olc::vf2d vText = pge->GetTextSizeProp(sText);
pge->DrawStringProp(olc::vf2d(vPos.x + 2.0f, vPos.y + (vSize.y - vText.y) * 0.5f), sText, m_manager.colText);
}
void TextBox::DrawDecal(olc::PixelGameEngine* pge)
@ -646,19 +687,19 @@ namespace olc::QuickGUI
{
// Draw Cursor
int32_t i = pge->TextEntryGetCursor();
olc::vf2d vCursorPos = pge->GetTextSizeProp(sText.substr(0, i));
olc::vf2d vCursorPos = pge->GetTextSizeProp(sText.substr(0, i))*fontSize;
pge->FillRectDecal(olc::vf2d(vPos.x + 2.0f + vCursorPos.x, (vPos.y + (vSize.y - 10.0f) * 0.5f)), { 2, 10 }, m_manager.colText);
}
// Draw Text
olc::vf2d vText = pge->GetTextSizeProp(sText);
pge->DrawStringPropDecal(olc::vf2d(vPos.x + 2.0f, vPos.y + (vSize.y - vText.y) * 0.5f), sText, m_manager.colText);
pge->DrawStringPropDecal(olc::vf2d(vPos.x + 2.0f, vPos.y + (vSize.y - vText.y) * 0.5f)-vf2d{0,1*fontSize.y}, sText, m_manager.colText,fontSize);
}
#pragma endregion
#pragma region Button
Button::Button(olc::QuickGUI::Manager& manager, const std::string& text, const olc::vf2d& pos, const olc::vf2d& size)
: BaseControl(manager)
Button::Button(olc::QuickGUI::Manager& manager, const std::string& text, const olc::vf2d& pos, const olc::vf2d& size, const olc::vf2d& fontScale)
: BaseControl(manager),fontScale(fontScale)
{
vPos = pos; vSize = size; sText = text;
}
@ -676,29 +717,32 @@ namespace olc::QuickGUI
if (m_state != State::Click)
{
if (vMouse.x >= vPos.x && vMouse.x < vPos.x + vSize.x &&
vMouse.y >= vPos.y && vMouse.y < vPos.y + vSize.y)
vMouse.y >= vPos.y && vMouse.y < vPos.y + vSize.y
||pge->GetKey(hotkey).bPressed||pge->GetKey(hotkey).bHeld||pge->GetKey(hotkey).bReleased)
{
m_fTransition += fElapsedTime * m_manager.fHoverSpeedOn;
m_state = State::Hover;
bHovered = true;
bPressed = pge->GetMouse(olc::Mouse::LEFT).bPressed;
bPressed = pge->GetMouse(olc::Mouse::LEFT).bPressed||pge->GetKey(hotkey).bPressed;
if (bPressed)
{
m_state = State::Click;
}
bHeld = pge->GetMouse(olc::Mouse::LEFT).bHeld;
bHeld = pge->GetMouse(olc::Mouse::LEFT).bHeld||pge->GetKey(hotkey).bHeld;
}
else
{
m_fTransition -= fElapsedTime * m_manager.fHoverSpeedOff;
m_state = State::Normal;
bHovered = false;
}
}
else
{
bHeld = pge->GetMouse(olc::Mouse::LEFT).bHeld;
bReleased = pge->GetMouse(olc::Mouse::LEFT).bReleased;
bHeld = pge->GetMouse(olc::Mouse::LEFT).bHeld||pge->GetKey(hotkey).bHeld;
bReleased = pge->GetMouse(olc::Mouse::LEFT).bReleased||pge->GetKey(hotkey).bReleased;
if (bReleased) m_state = State::Normal;
}
@ -751,36 +795,62 @@ namespace olc::QuickGUI
pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colBorder);
pge->SetDecalMode(olc::DecalMode::NORMAL);
olc::vf2d vText = pge->GetTextSizeProp(sText);
pge->DrawStringPropDecal(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText);
olc::vf2d vText = pge->GetTextSizeProp(sText)*fontScale;
pge->DrawStringPropDecal(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText,fontScale);
}
#pragma endregion
#pragma region CustomButton
CustomButton::CustomButton(olc::QuickGUI::Manager& manager, const olc::Renderable& icon,const olc::Renderable& back_icon, const olc::vf2d& pos, const olc::vf2d& size,const olc::vi2d& sprOffset,const olc::vi2d& sprSize)
: Button(manager, "", pos, size), pIcon(icon), pBackIcon(back_icon), sprOffset(sprOffset), sprSize(sprSize)
{}
#pragma region ImageButton
ImageButton::ImageButton(olc::QuickGUI::Manager& manager, const olc::Renderable& icon, const olc::vf2d& pos, const olc::vf2d& size)
: Button(manager, "", pos, size), pIcon(icon)
void CustomButton::DrawDecal(olc::PixelGameEngine* pge)
{
if (!bVisible)
return;
switch (m_state)
{
case State::Disabled:
pge->DrawPartialDecal(vPos,pBackIcon.Decal(),sprOffset,sprSize,{1.0,1.0},m_manager.colDisable);
break;
case State::Normal:
case State::Hover:
pge->DrawPartialDecal(vPos,pBackIcon.Decal(),sprOffset,sprSize,{1.0,1.0},olc::PixelLerp(m_manager.colNormal, m_manager.colHover, m_fTransition));
break;
case State::Click:
pge->DrawPartialDecal(vPos,pBackIcon.Decal(),sprOffset,sprSize,{1.0,1.0},m_manager.colClick);
break;
}
pge->DrawPartialDecal(vPos,pIcon.Decal(),sprOffset,sprSize,{1.0,1.0},WHITE);
}
#pragma endregion
#pragma region ImageButton
ImageButton::ImageButton(olc::QuickGUI::Manager& manager, const olc::Renderable& icon, const olc::vf2d& pos, const olc::vf2d& size,const olc::vi2d& sprOffset,const olc::vi2d& sprSize)
: Button(manager, "", pos, size), pIcon(icon), sprOffset(sprOffset), sprSize(sprSize)
{
}
void ImageButton::Draw(olc::PixelGameEngine* pge)
{
Button::Draw(pge);
pge->DrawSprite(vPos + olc::vi2d(4, 4), pIcon.Sprite());
pge->DrawPartialSprite(vPos + olc::vi2d(4, 4), pIcon.Sprite(),sprOffset,sprSize);
}
void ImageButton::DrawDecal(olc::PixelGameEngine* pge)
{
Button::DrawDecal(pge);
pge->DrawDecal(vPos + olc::vi2d(4, 4), pIcon.Decal());
pge->DrawPartialDecal(vPos + olc::vi2d(4, 4), pIcon.Decal(),sprOffset,sprSize);
}
#pragma endregion
#pragma region ImageCheckBox
ImageCheckBox::ImageCheckBox(olc::QuickGUI::Manager& manager, const olc::Renderable& gfx, const bool check, const olc::vf2d& pos, const olc::vf2d& size)
: ImageButton(manager, gfx, pos, size)
ImageCheckBox::ImageCheckBox(olc::QuickGUI::Manager& manager, const olc::Renderable& gfx, const bool check, const olc::vf2d& pos, const olc::vf2d& size,const olc::vi2d& sprOffset,const olc::vi2d& sprSize)
: ImageButton(manager, gfx, pos, size,sprOffset,sprSize)
{
bChecked = check;
}
@ -807,18 +877,49 @@ namespace olc::QuickGUI
if (!bVisible)
return;
ImageButton::DrawDecal(pge);
if (bChecked)
{
pge->SetDecalMode(olc::DecalMode::WIREFRAME);
pge->FillRectDecal(vPos + olc::vf2d(2, 2), vSize - olc::vf2d(4, 4), m_manager.colBorder);
pge->SetDecalMode(olc::DecalMode::NORMAL);
ImageButton::DrawDecal(pge);
}
switch (m_state)
{
case State::Disabled:
pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colDisable);
break;
case State::Normal:
case State::Hover:
if(bChecked){
pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), olc::PixelLerp(m_manager.colSelected, m_manager.colHover, m_fTransition));
} else {
pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), olc::PixelLerp(m_manager.colNormal, m_manager.colHover, m_fTransition));
}
break;
case State::Click:
pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colClick);
pge->DrawDecal(vPos + olc::vi2d(4, 4), pIcon.Decal());
break;
}
pge->DrawPartialDecal(vPos + olc::vi2d(4, 4), pIcon.Decal(),sprOffset,sprSize);
pge->SetDecalMode(olc::DecalMode::WIREFRAME);
pge->FillRectDecal(vPos + olc::vf2d(2, 2), vSize - olc::vf2d(4, 4), m_manager.colBorder);
pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colBorder);
pge->SetDecalMode(olc::DecalMode::NORMAL);
if (bChecked)
{
pge->SetDecalMode(olc::DecalMode::WIREFRAME);
for(int i=0;i<4;i++){
pge->FillRectDecal(vPos + olc::vf2d(2, 2) + olc::vf2d(i,i)/2, vSize - olc::vf2d(4, 4) - olc::vf2d(i*2,i*2)/2, m_manager.colBorderSelected);
}
pge->SetDecalMode(olc::DecalMode::NORMAL);
}
olc::vf2d vText = pge->GetTextSizeProp(sText);
pge->DrawStringPropDecal(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText);
}
@ -883,7 +984,7 @@ namespace olc::QuickGUI
{
if (m_state == State::Disabled || !bVisible)
return;
float fElapsedTime = pge->GetElapsedTime();
olc::vf2d vMouse = pge->GetMousePos();
@ -902,14 +1003,17 @@ namespace olc::QuickGUI
{
m_fTransition += fElapsedTime * m_manager.fHoverSpeedOn;
m_state = State::Hover;
bHovered = true;
if (pge->GetMouse(olc::Mouse::LEFT).bPressed)
{
m_state = State::Click;
bPressed = true;
}
}
else
else {
m_state = State::Normal;
bHovered = false;
}
}
if (pge->GetMouse(olc::Mouse::LEFT).bReleased)
@ -986,8 +1090,8 @@ namespace olc::QuickGUI
#pragma endregion
#pragma region ListBox
ListBox::ListBox(olc::QuickGUI::Manager& manager, std::vector<std::string>& vList, const olc::vf2d& pos, const olc::vf2d& size)
: BaseControl(manager), m_vList(vList)
ListBox::ListBox(olc::QuickGUI::Manager& manager, std::vector<std::string>& vList, const olc::vf2d& pos, const olc::vf2d& size, const float fontSize)
: BaseControl(manager), m_vList(vList), fontSize(fontSize)
{
m_group.CopyThemeFrom(m_manager);
vPos = pos;
@ -1001,15 +1105,17 @@ namespace olc::QuickGUI
if (m_state == State::Disabled || !bVisible)
return;
nPreviouslySelectedItem = nSelectedItem;
olc::vf2d vMouse = pge->GetMousePos() - vPos + olc::vi2d(2,0);
if (pge->GetMouse(olc::Mouse::LEFT).bPressed)
bHovered=pge->GetMouseX() >= vPos.x && pge->GetMouseX() < vPos.x + vSize.x &&
pge->GetMouseY() >= vPos.y && pge->GetMouseY() < vPos.y + vSize.y;
if (pge->GetMouse(olc::Mouse::LEFT).bHeld)
{
if (vMouse.x >= 0 && vMouse.x < vSize.x - (m_group.fGrabRad * 2) && vMouse.y >= 0 && vMouse.y < vSize.y)
{
nSelectedItem = size_t(m_pSlider->fValue + vMouse.y / 10);
nSelectedItem = size_t(m_pSlider->fValue + vMouse.y / fontSize);
}
}
@ -1018,7 +1124,18 @@ namespace olc::QuickGUI
bSelectionChanged = nSelectedItem != nPreviouslySelectedItem;
m_pSlider->fMax = float(m_vList.size());
m_pSlider->fMax = float(m_vList.size()-vSize.y/fontSize+1);
if(bHovered&&pge->GetMouseWheel()!=0){
if(pge->GetMouseWheel()>0){
m_pSlider->fValue=std::clamp(m_pSlider->fValue-1, m_pSlider->fMin, m_pSlider->fMax);
} else {
m_pSlider->fValue=std::clamp(m_pSlider->fValue+1, m_pSlider->fMin, m_pSlider->fMax);
}
}
m_pSlider->fValue=int(m_pSlider->fValue);
m_group.Update(pge);
}
@ -1037,15 +1154,15 @@ namespace olc::QuickGUI
size_t idx0 = size_t(m_pSlider->fValue);
size_t idx1 = std::min(idx0 + size_t((vSize.y - 4) / 10), m_vList.size());
size_t idx1 = std::min(idx0 + size_t((vSize.y - 4) / fontSize), m_vList.size());
olc::vf2d vTextPos = vPos + olc::vf2d(2,2);
for (size_t idx = idx0; idx < idx1; idx++)
{
if (idx == nSelectedItem)
pge->FillRect(vTextPos - olc::vi2d(1,1), {int32_t(vSize.x - m_group.fGrabRad * 2), 10}, m_group.colHover);
pge->DrawStringProp(vTextPos, m_vList[idx]);
vTextPos.y += 10;
pge->FillRect(vTextPos - olc::vi2d(1,-1), {int32_t(vSize.x - m_group.fGrabRad * 2), int(fontSize)}, m_group.colHover);
pge->DrawStringProp(vTextPos + olc::vi2d(0,2), m_vList[idx],olc::WHITE,fontSize/10);
vTextPos.y += fontSize;
}
m_group.Draw(pge);
@ -1060,15 +1177,21 @@ namespace olc::QuickGUI
pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colNormal);
size_t idx0 = size_t(m_pSlider->fValue);
size_t idx1 = std::min(idx0 + size_t((vSize.y - 4) / 10), m_vList.size());
size_t idx1 = std::min(idx0 + size_t((vSize.y - 4) / fontSize), m_vList.size());
olc::vf2d vTextPos = vPos + olc::vf2d(2, 2);
for (size_t idx = idx0; idx < idx1; idx++)
{
if (idx == nSelectedItem)
pge->FillRectDecal(vTextPos - olc::vi2d(1, 1), { vSize.x - m_group.fGrabRad * 2.0f, 10.0f }, m_group.colHover);
pge->DrawStringPropDecal(vTextPos, m_vList[idx]);
vTextPos.y += 10;
pge->FillRectDecal(vTextPos - olc::vi2d(1, -1), { vSize.x - m_group.fGrabRad * 2.0f, fontSize }, m_group.colHover);
float width = pge->GetTextSizeProp(m_vList[idx]).x*fontSize/10;
if (width>vSize.x-m_manager.fGrabRad*2){
float scaleX = (vSize.x-m_manager.fGrabRad*2)/width;
pge->DrawStringPropDecal(vTextPos + olc::vi2d(0,2), m_vList[idx], olc::WHITE, olc::vf2d{scaleX,1}*fontSize/10);
} else {
pge->DrawStringPropDecal(vTextPos + olc::vi2d(0,2), m_vList[idx], olc::WHITE, olc::vf2d{1,1}*fontSize/10);
}
vTextPos.y += fontSize;
}
if (bHasBorder)
@ -1126,17 +1249,17 @@ namespace olc::QuickGUI
{
std::string sDirectory = m_vDirectory[m_listDirectory->nSelectedItem];
/*if (sDirectory == "..")
m_path = m_path.parent_path().string() + "/";
m_path = m_path.parent_path().string() + "/";
else
m_path += sDirectory+ "/";*/
m_path += sDirectory+ "/";*/
m_path += sDirectory + "/";
// Reconstruct Lists
m_vDirectory.clear();
m_vFiles.clear();
for (auto const& dir_entry : std::filesystem::directory_iterator{ m_path })
{
@ -1153,7 +1276,7 @@ namespace olc::QuickGUI
}
pge->DrawStringDecal({ 0,0 }, m_path.string());
pge->DrawStringDecal({ 0,0 }, m_path.string());

Loading…
Cancel
Save