From 5e81a2ce8fbc882c03b7875445e61dffd0478198 Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Tue, 12 Mar 2024 18:54:36 -0500 Subject: [PATCH] TSXParser refactor and preparations for editor functionality. --- .gitignore | 438 ++++++ TiledCollisionEditor.sln | 31 + TiledCollisionEditor/Quadrilateral.h | 44 + TiledCollisionEditor/TSXParser.h | 171 +++ .../TiledCollisionEditor.vcxproj | 175 +++ .../TiledCollisionEditor.vcxproj.filters | 63 + TiledCollisionEditor/Tiles/Basic Tileset.tsx | 810 ++++++++++++ .../Tiles/tilemap-3-normal.png | Bin 0 -> 13501 bytes TiledCollisionEditor/Tileset.h | 53 + TiledCollisionEditor/TilesetObject.cpp | 78 ++ TiledCollisionEditor/TilesetObject.h | 55 + TiledCollisionEditor/XMLTag.cpp | 74 ++ TiledCollisionEditor/XMLTag.h | 53 + TiledCollisionEditor/main.cpp | 50 + TiledCollisionEditor/olcPGEX_QuickGUI.h | 1177 +++++++++++++++++ .../olcPGEX_TransformedView.h | 0 .../olcUTIL_Camera2D.h | 0 .../olcUTIL_Geometry2D.h | 0 .../pixelGameEngine.cpp | 4 +- .../pixelGameEngine.h | 0 main.cpp | 56 - 21 files changed, 3275 insertions(+), 57 deletions(-) create mode 100644 .gitignore create mode 100644 TiledCollisionEditor.sln create mode 100644 TiledCollisionEditor/Quadrilateral.h create mode 100644 TiledCollisionEditor/TSXParser.h create mode 100644 TiledCollisionEditor/TiledCollisionEditor.vcxproj create mode 100644 TiledCollisionEditor/TiledCollisionEditor.vcxproj.filters create mode 100644 TiledCollisionEditor/Tiles/Basic Tileset.tsx create mode 100644 TiledCollisionEditor/Tiles/tilemap-3-normal.png create mode 100644 TiledCollisionEditor/Tileset.h create mode 100644 TiledCollisionEditor/TilesetObject.cpp create mode 100644 TiledCollisionEditor/TilesetObject.h create mode 100644 TiledCollisionEditor/XMLTag.cpp create mode 100644 TiledCollisionEditor/XMLTag.h create mode 100644 TiledCollisionEditor/main.cpp create mode 100644 TiledCollisionEditor/olcPGEX_QuickGUI.h rename olcPGEX_TransformedView.h => TiledCollisionEditor/olcPGEX_TransformedView.h (100%) rename olcUTIL_Camera2D.h => TiledCollisionEditor/olcUTIL_Camera2D.h (100%) rename olcUTIL_Geometry2D.h => TiledCollisionEditor/olcUTIL_Geometry2D.h (100%) rename pixelGameEngine.cpp => TiledCollisionEditor/pixelGameEngine.cpp (61%) rename pixelGameEngine.h => TiledCollisionEditor/pixelGameEngine.h (100%) delete mode 100644 main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bef5ed9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,438 @@ +# Created by https://www.toptal.com/developers/gitignore/api/visualstudio,c++ +# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudio,c++ + +### C++ ### +# Prerequisites +*.d +*.ini + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.iobj +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +### VisualStudio Patch ### +# Additional files built by Visual Studio + +# End of https://www.toptal.com/developers/gitignore/api/visualstudio,c++ \ No newline at end of file diff --git a/TiledCollisionEditor.sln b/TiledCollisionEditor.sln new file mode 100644 index 0000000..beef300 --- /dev/null +++ b/TiledCollisionEditor.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34525.116 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TiledCollisionEditor", "TiledCollisionEditor\TiledCollisionEditor.vcxproj", "{1DCE7E68-F810-4183-83F3-233A8EE41027}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1DCE7E68-F810-4183-83F3-233A8EE41027}.Debug|x64.ActiveCfg = Debug|x64 + {1DCE7E68-F810-4183-83F3-233A8EE41027}.Debug|x64.Build.0 = Debug|x64 + {1DCE7E68-F810-4183-83F3-233A8EE41027}.Debug|x86.ActiveCfg = Debug|Win32 + {1DCE7E68-F810-4183-83F3-233A8EE41027}.Debug|x86.Build.0 = Debug|Win32 + {1DCE7E68-F810-4183-83F3-233A8EE41027}.Release|x64.ActiveCfg = Release|x64 + {1DCE7E68-F810-4183-83F3-233A8EE41027}.Release|x64.Build.0 = Release|x64 + {1DCE7E68-F810-4183-83F3-233A8EE41027}.Release|x86.ActiveCfg = Release|Win32 + {1DCE7E68-F810-4183-83F3-233A8EE41027}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DC9A1F91-BAD2-4A60-8406-CDB843D55AA0} + EndGlobalSection +EndGlobal diff --git a/TiledCollisionEditor/Quadrilateral.h b/TiledCollisionEditor/Quadrilateral.h new file mode 100644 index 0000000..50f9de5 --- /dev/null +++ b/TiledCollisionEditor/Quadrilateral.h @@ -0,0 +1,44 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +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. + +Portions of this software are copyright © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion +#pragma once +#include "olcUTIL_Geometry2D.h" + +using namespace olc; +#include + +using Quadrilateral=std::array; \ No newline at end of file diff --git a/TiledCollisionEditor/TSXParser.h b/TiledCollisionEditor/TSXParser.h new file mode 100644 index 0000000..f4003f7 --- /dev/null +++ b/TiledCollisionEditor/TSXParser.h @@ -0,0 +1,171 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +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. + +Portions of this software are copyright © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion +#pragma once +#include +#include +#include +#include + +#include "olcUTIL_Geometry2D.h" +#include "Tileset.h" + +using namespace olc; +using namespace olc::utils; + +class TSXParser{ + public: + inline Tileset&GetData(){ + return parsedTilesetInfo; + } + private: + Tileset parsedTilesetInfo; + int previousTagID; + inline void ParseTag(std::string tag){ + XMLTag newTag; + //First character is a '<' so we discard it. + tag.erase(0,1); tag.erase(tag.length()-1,1); //Erase the first and last characters in the tag. Now parse by spaces. + std::stringstream s(tag); //Turn it into a string stream to now parse into individual whitespaces. + std::string data; + while (s.good()) { + int quotationMarkCount=0; + bool pastEquals=false; + data=""; + bool valid=false; + while(s.good()){ + int character=s.get(); + if(character=='"'){ + quotationMarkCount++; + } + if(character==' '&"ationMarkCount%2==0){ + valid=true; + break; + } + data+=character; + if(pastEquals&"ationMarkCount%2==0){ + valid=true; + break; + } + if(character=='='&"ationMarkCount%2==0){ + pastEquals=true; + } + } + if(valid&&data.length()>0){ + if (newTag.tag.length()==0) { //Tag's empty, so first line is the tag. + newTag.tag=data; + } else { + std::string key = data.substr(0,data.find("=")); + std::string value = data.substr(data.find("=")+1,std::string::npos); + + //Strip Quotation marks. + value = value.substr(1,std::string::npos); + value = value.substr(0,value.length()-1); + + newTag.data[key]=value; + } + } + } + + if (newTag.tag=="tileset") { + parsedTilesetInfo.tilewidth=stoi(newTag.data["tilewidth"]); + parsedTilesetInfo.tileheight=stoi(newTag.data["tileheight"]); + parsedTilesetInfo.columns=stoi(newTag.data["columns"]); + } else + if (newTag.tag=="image") { + parsedTilesetInfo.ImageData=newTag; + parsedTilesetInfo.filename=newTag.GetString("source"); + parsedTilesetInfo.imagewidth=newTag.GetInteger("width"); + parsedTilesetInfo.imageheight=newTag.GetInteger("height"); + } else + if (newTag.tag=="property"){ + if(newTag.data["name"]=="Name"){ + std::string objectName=newTag.data["value"]; + parsedTilesetInfo.objects[objectName].AddTile(parsedTilesetInfo,previousTagID); + } + } else + if (newTag.tag=="tile"){ + previousTagID=newTag.GetInteger("id"); + } + }; + public: + inline TSXParser(std::string file) + :previousTagID(-1){ + std::ifstream f(file,std::ios::in); + + std::string accumulator=""; + + while (f.good()) { + std::string data; + f>>data; + if (data.empty()) continue; + + if (accumulator.length()>0) { + accumulator+=" "+data; + //Check if it ends with '>' + if (data[data.length()-1]=='>') { + ParseTag(accumulator); + accumulator=""; + } + } else + if (data[0]=='<') { + //Beginning of XML tag. + accumulator=data; + if(accumulator.length()>1&&accumulator.at(1)=='/'){ + accumulator=""; //Restart because this is an end tag. + } + if(accumulator.length()>1&&accumulator.find('>')!=std::string::npos){ + accumulator=""; //Restart because this tag has nothing in it! + } + } + } + } +}; + +//#define TSX_PARSER_SETUP + +std::ostream&operator<<(std::ostream& os, Tileset& rhs){ + os< + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {1dce7e68-f810-4183-83f3-233a8ee41027} + TiledCollisionEditor + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TiledCollisionEditor/TiledCollisionEditor.vcxproj.filters b/TiledCollisionEditor/TiledCollisionEditor.vcxproj.filters new file mode 100644 index 0000000..45af918 --- /dev/null +++ b/TiledCollisionEditor/TiledCollisionEditor.vcxproj.filters @@ -0,0 +1,63 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/TiledCollisionEditor/Tiles/Basic Tileset.tsx b/TiledCollisionEditor/Tiles/Basic Tileset.tsx new file mode 100644 index 0000000..b0d0850 --- /dev/null +++ b/TiledCollisionEditor/Tiles/Basic Tileset.tsx @@ -0,0 +1,810 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TiledCollisionEditor/Tiles/tilemap-3-normal.png b/TiledCollisionEditor/Tiles/tilemap-3-normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ddd413ed8436161fb119c770fe608f14cd774765 GIT binary patch literal 13501 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 BYS{n) literal 0 HcmV?d00001 diff --git a/TiledCollisionEditor/Tileset.h b/TiledCollisionEditor/Tileset.h new file mode 100644 index 0000000..f874624 --- /dev/null +++ b/TiledCollisionEditor/Tileset.h @@ -0,0 +1,53 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +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. + +Portions of this software are copyright © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion +#pragma once +#include +#include "XMLTag.h" +#include "TilesetObject.h" +#include "pixelGameEngine.h" + +struct Tileset{ + std::string filename; + std::unordered_mapobjects; + XMLTag ImageData; + int tilewidth=0,tileheight=0; + int imagewidth=0,imageheight=0; + int columns=0; + bool isTerrain=false; + friend std::ostream& operator << (std::ostream& os, Tileset& rhs); +}; \ No newline at end of file diff --git a/TiledCollisionEditor/TilesetObject.cpp b/TiledCollisionEditor/TilesetObject.cpp new file mode 100644 index 0000000..6672e68 --- /dev/null +++ b/TiledCollisionEditor/TilesetObject.cpp @@ -0,0 +1,78 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +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. + +Portions of this software are copyright © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion + +#include "TilesetObject.h" +#include "Tileset.h" + +void TilesetObject::AddTile(const Tileset&tileset,int tileID){ + if(bounds.size==vi2d{1,1}){ + int tileX=tileID%tileset.columns; + int tileY=tileID/tileset.columns; + bounds={vi2d{tileX,tileY}*tileset.tilewidth,{tileset.tilewidth,tileset.tileheight}}; + upperLeftTileId=tileID; + }else{ + int tileX=tileID%tileset.columns; + int tileY=tileID/tileset.columns; + int textureX=tileX*tileset.tilewidth; + int textureY=tileY*tileset.tileheight; + int minX=bounds.pos.x; + int minY=bounds.pos.y; + int maxX=bounds.pos.x+bounds.size.x; + int maxY=bounds.pos.y+bounds.size.y; + + if(textureXmaxX){ + maxX=textureX+tileset.tilewidth; + } + if(textureYmaxY){ + maxY=textureY+tileset.tileheight; + } + bounds={{minX,minY},{maxX-minX,maxY-minY}}; + + int minTileX=minX/tileset.tilewidth; + int minTileY=minY/tileset.tileheight; + + int upperLeftTileId=minTileY*tileset.columns+minTileX; + this->upperLeftTileId=upperLeftTileId; + } + } \ No newline at end of file diff --git a/TiledCollisionEditor/TilesetObject.h b/TiledCollisionEditor/TilesetObject.h new file mode 100644 index 0000000..d7f36bf --- /dev/null +++ b/TiledCollisionEditor/TilesetObject.h @@ -0,0 +1,55 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +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. + +Portions of this software are copyright © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion +#pragma once +#include +#include "Quadrilateral.h" + +using namespace olc::utils; + +class Tileset; + +class TilesetObject{ +public: + std::string name; + int upperLeftTileId; + bool perspectiveObj=false; + bool facingLeft=true; + geom2d::rectbounds; + std::vectorcollisionTiles; + void AddTile(const Tileset&tileset,int tileID); +}; \ No newline at end of file diff --git a/TiledCollisionEditor/XMLTag.cpp b/TiledCollisionEditor/XMLTag.cpp new file mode 100644 index 0000000..c653ff1 --- /dev/null +++ b/TiledCollisionEditor/XMLTag.cpp @@ -0,0 +1,74 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +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. + +Portions of this software are copyright © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion +#include "XMLTag.h" + +const std::string XMLTag::FormatTagData(std::maptiles){ + std::string displayStr=""; + for (std::map::iterator it=data.begin();it!=data.end();it++) { + displayStr+=" "+it->first+": "+it->second+"\n"; + } + return displayStr; +} + +std::string XMLTag::str(){ + return tag+"\n"; +} + +int XMLTag::GetInteger(std::string dataTag){ + return std::stoi(data[dataTag]); +} + +float XMLTag::GetFloat(std::string dataTag){ + return std::stof(data[dataTag]); +} + +double XMLTag::GetDouble(std::string dataTag){ + return std::stod(data[dataTag]); +} + +bool XMLTag::GetBool(std::string dataTag){ + if (data[dataTag]=="0"||data[dataTag]=="false") { + return false; + } else { + return true; + } +} + +std::string XMLTag::GetString(std::string dataTag){ + return data[dataTag]; +} \ No newline at end of file diff --git a/TiledCollisionEditor/XMLTag.h b/TiledCollisionEditor/XMLTag.h new file mode 100644 index 0000000..da96f22 --- /dev/null +++ b/TiledCollisionEditor/XMLTag.h @@ -0,0 +1,53 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +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. + +Portions of this software are copyright © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion +#pragma once +#include +#include + +struct XMLTag{ + std::string tag; + std::map data; + const std::string FormatTagData(std::maptiles); + friend std::ostream& operator << (std::ostream& os, XMLTag& rhs); + std::string str(); + int GetInteger(std::string dataTag); + float GetFloat(std::string dataTag); + double GetDouble(std::string dataTag); + bool GetBool(std::string dataTag); + std::string GetString(std::string dataTag); +}; \ No newline at end of file diff --git a/TiledCollisionEditor/main.cpp b/TiledCollisionEditor/main.cpp new file mode 100644 index 0000000..6f3d872 --- /dev/null +++ b/TiledCollisionEditor/main.cpp @@ -0,0 +1,50 @@ +#include "TSXParser.h" +#include "olcPGEX_TransformedView.h" +#include "olcUTIL_Camera2D.h" +#include "olcPGEX_QuickGUI.h" + +using namespace olc; +using namespace olc::utils; + +const std::string TILESET_DIR="./Tiles/"; + +class TiledCollisionEditor : public olc::PixelGameEngine +{ + std::unordered_maptilesets; + std::unordered_mapimages; + +public: + TiledCollisionEditor() + { + sAppName = "TiledCollisionEditor"; + } + +public: + bool OnUserCreate() override + { + std::string tilesetFilename=TILESET_DIR+"Basic Tileset.tsx"; + Tileset&tileset=tilesets[tilesetFilename]=TSXParser{tilesetFilename}.GetData(); + + Renderable&tilesetImg=images[tilesetFilename]; + tilesetImg.Load(TILESET_DIR+tileset.filename); + return true; + } + + bool OnUserUpdate(float fElapsedTime) override + { + Clear(VERY_DARK_BLUE); + for(auto&[tilesetName,tileset]:tilesets){ + DrawDecal({0,0},images[tilesetName].Decal()); + } + return true; + } +}; + +int main() +{ + TiledCollisionEditor demo; + if (demo.Construct(640, 180, 4, 4)) + demo.Start(); + + return 0; +} diff --git a/TiledCollisionEditor/olcPGEX_QuickGUI.h b/TiledCollisionEditor/olcPGEX_QuickGUI.h new file mode 100644 index 0000000..f045ba9 --- /dev/null +++ b/TiledCollisionEditor/olcPGEX_QuickGUI.h @@ -0,0 +1,1177 @@ +/* + 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 + +*/ + +#ifndef OLC_PGEX_QUICKGUI_H +#define OLC_PGEX_QUICKGUI_H + +#include "pixelGameEngine.h" + + +namespace olc::QuickGUI +{ + class Manager; + + // Virtual base class for all controls + class BaseControl + { + public: + BaseControl(olc::QuickGUI::Manager& manager); + virtual ~BaseControl(); + + public: + // Switches the control on/off + void Enable(const bool bEnable); + // Sets whether or not the control is interactive/displayed + bool bVisible = true; + + // True on single frame control begins being manipulated + bool bPressed = false; + // True on all frames control is under user manipulation + bool bHeld = false; + // True on single frame control ceases being manipulated + bool bReleased = false; + + public: + // Updates the controls behvaiour + virtual void Update(olc::PixelGameEngine* pge) = 0; + // Draws the control using "sprite" based CPU operations + virtual void Draw(olc::PixelGameEngine* pge) = 0; + // Draws the control using "decal" based GPU operations + virtual void DrawDecal(olc::PixelGameEngine* pge) = 0; + + protected: + // Controls are related to a manager, where the theme resides + // and control groups can be implemented + olc::QuickGUI::Manager& m_manager; + + // All controls exists in one of four states + // Disabled - Greyed out and not interactive + // Normal - interactive and operational + // 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; + }; + + + // A QuickGUI::Manager acts as a convenient grouping of controls + class Manager + { + public: + // Construct Manager, bCleanUpForMe will automatically DELETE any controls + // 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); + // Updates all controls this manager operates + void Update(olc::PixelGameEngine* pge); + // Draws as "sprite" all controls this manager operates + 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; + // Speed to transiton from Normal -> Hover + float fHoverSpeedOn = 10.0f; + // Speed to transiton from Hover -> Normal + float fHoverSpeedOff = 4.0f; + // Size of grab handle + float fGrabRad = 8.0f; + // Copy all theme attributes into a different manager object + void CopyThemeFrom(const Manager& manager); + + private: + // Should this manager call delete on the controls it opeerates? + bool m_bEraseControlsOnDestroy = true; + // Container of controls + std::vector m_vControls; + }; + + + // Creates a Label Control - it's just text! + class Label : public BaseControl + { + public: + Label(olc::QuickGUI::Manager& manager, // Associate with a Manager + const std::string& text, // Text to display + const olc::vf2d& pos, // Location of label top-left + const olc::vf2d& size); // Size of label + + public: + // Position of button + olc::vf2d vPos; + // Size of button + olc::vf2d vSize; + // Text displayed on button + std::string sText; + // Show a border? + bool bHasBorder = false; + // Show a background? + bool bHasBackground = false; + // Where should the text be positioned? + enum class Alignment + {Left, Centre, Right} nAlign = Alignment::Centre; + + public: // BaseControl overrides + void Update(olc::PixelGameEngine* pge) override; + void Draw(olc::PixelGameEngine* pge) override; + void DrawDecal(olc::PixelGameEngine* pge) override; + }; + + class TextBox : public Label + { + public: + 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 + + 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; + + }; + + // Creates a Button Control - a clickable, labelled rectangle + class Button : public BaseControl + { + public: + 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 + + public: + // Position of button + olc::vf2d vPos; + // Size of button + olc::vf2d vSize; + // Text displayed on button + std::string sText; + + public: // BaseControl overrides + void Update(olc::PixelGameEngine* pge) override; + void Draw(olc::PixelGameEngine* pge) override; + void DrawDecal(olc::PixelGameEngine* pge) override; + }; + + // Creates a Button Control - a clickable, labelled rectangle + class CheckBox : public Button + { + public: + CheckBox(olc::QuickGUI::Manager& manager, // Associate with a Manager + const std::string& text, // 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 + + public: + bool bChecked = false; + + public: // BaseControl overrides + void Update(olc::PixelGameEngine* pge) override; + void Draw(olc::PixelGameEngine* pge) override; + 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 + + public: + const olc::Renderable& pIcon; + + public: + void Draw(olc::PixelGameEngine* pge) override; + void DrawDecal(olc::PixelGameEngine* pge) override; + }; + + class ImageCheckBox : public ImageButton + { + public: + ImageCheckBox(olc::QuickGUI::Manager& manager, // Associate with a Manager + 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 + + public: + bool bChecked = false; + + public: + void Update(olc::PixelGameEngine* pge) override; + void Draw(olc::PixelGameEngine* pge) override; + void DrawDecal(olc::PixelGameEngine* pge) override; + }; + + + // Creates a Slider Control - a grabbable handle that slides between two locations + class Slider : public BaseControl + { + public: + Slider(olc::QuickGUI::Manager& manager, // Associate with a Manager + const olc::vf2d& posmin, // Screen location of "minimum" + const olc::vf2d& posmax, // Screen location of "maximum" + const float valmin, // Value of minimum + const float valmax, // Value of maximum + const float value); // Starting value + + public: + // Minium value + float fMin = -100.0f; + // Maximum value + float fMax = +100.0f; + // Current value + float fValue = 0.0f; + + // Location of minimum/start + olc::vf2d vPosMin; + // Location of maximum/end + olc::vf2d vPosMax; + + public: // BaseControl overrides + void Update(olc::PixelGameEngine* pge) override; + void Draw(olc::PixelGameEngine* pge) override; + void DrawDecal(olc::PixelGameEngine* pge) override; + }; + + + class ListBox : public BaseControl + { + public: + ListBox(olc::QuickGUI::Manager& manager, // Associate with a Manager + std::vector& vList, + const olc::vf2d& pos, // Location of list top-left + const olc::vf2d& size); // Size of list + + // Position of list + olc::vf2d vPos; + // Size of list + olc::vf2d vSize; + // Show a border? + bool bHasBorder = true; + // Show a background? + bool bHasBackground = true; + + public: + Slider *m_pSlider = nullptr; + Manager m_group; + size_t m_nVisibleItems = 0; + std::vector& m_vList; + + public: + // Item currently selected + size_t nSelectedItem = 0; + size_t nPreviouslySelectedItem = 0; + // Has selection changed? + bool bSelectionChanged = false; + + public: // BaseControl overrides + void Update(olc::PixelGameEngine* pge) override; + void Draw(olc::PixelGameEngine* pge) override; + void DrawDecal(olc::PixelGameEngine* pge) override; + }; + + + class ModalDialog : public olc::PGEX + { + public: + ModalDialog(); + + public: + void ShowFileOpen(const std::string& sPath); + + protected: + virtual bool OnBeforeUserUpdate(float& fElapsedTime) override; + + private: + bool m_bShowDialog = false; + + Manager m_manFileSelect; + ListBox* m_listVolumes = nullptr; + ListBox* m_listDirectory = nullptr; + ListBox* m_listFiles = nullptr; + + std::vector m_vVolumes; + std::vector m_vDirectory; + std::vector m_vFiles; + std::filesystem::path m_path; + }; +} + + +#ifdef OLC_PGEX_QUICKGUI +#undef OLC_PGEX_QUICKGUI +namespace olc::QuickGUI +{ + +#pragma region BaseControl + BaseControl::BaseControl(olc::QuickGUI::Manager& manager) : m_manager(manager) + { + m_manager.AddControl(this); + } + + BaseControl::~BaseControl() + { + + } + + void BaseControl::Enable(const bool bEnable) + { + m_state = bEnable ? State::Normal : State::Disabled; + } +#pragma endregion + +#pragma region Manager + Manager::Manager(const bool bCleanUpForMe) + { + m_bEraseControlsOnDestroy = bCleanUpForMe; + } + + Manager::~Manager() + { + if (m_bEraseControlsOnDestroy) + for (auto& p : m_vControls) + delete p; + + m_vControls.clear(); + } + + void Manager::AddControl(BaseControl* control) + { + m_vControls.push_back(control); + } + + void Manager::Update(olc::PixelGameEngine* pge) + { + for (auto& p : m_vControls) p->Update(pge); + } + + void Manager::Draw(olc::PixelGameEngine* pge) + { + for (auto& p : m_vControls) p->Draw(pge); + } + + void Manager::DrawDecal(olc::PixelGameEngine* pge) + { + for (auto& p : m_vControls) p->DrawDecal(pge); + } + + void Manager::CopyThemeFrom(const Manager& manager) + { + this->colBorder = manager.colBorder; + this->colClick = manager.colClick; + this->colDisable = manager.colDisable; + this->colHover = manager.colHover; + this->colNormal = manager.colNormal; + this->colText = manager.colText; + this->fGrabRad = manager.fGrabRad; + this->fHoverSpeedOff = manager.fHoverSpeedOff; + this->fHoverSpeedOn = manager.fHoverSpeedOn; + } +#pragma endregion + +#pragma region Label + Label::Label(olc::QuickGUI::Manager& manager, const std::string& text, const olc::vf2d& pos, const olc::vf2d& size) + : BaseControl(manager) + { + vPos = pos; vSize = size; sText = text; + } + + void Label::Update(olc::PixelGameEngine* pge) + { + + } + + void Label::Draw(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + if (bHasBackground) + { + pge->FillRect(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colNormal); + } + + if(bHasBorder) + pge->DrawRect(vPos, vSize - olc::vf2d(1, 1), m_manager.colBorder); + + olc::vf2d vText = pge->GetTextSizeProp(sText); + switch (nAlign) + { + case Alignment::Left: + pge->DrawStringProp(olc::vf2d( vPos.x + 2.0f, vPos.y + (vSize.y - vText.y) * 0.5f ), sText, m_manager.colText); + break; + case Alignment::Centre: + pge->DrawStringProp(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText); + break; + case Alignment::Right: + pge->DrawStringProp(olc::vf2d{ vPos.x + vSize.x - vText.x - 2.0f, vPos.y + (vSize.y - vText.y) * 0.5f }, sText, m_manager.colText); + break; + } + } + + void Label::DrawDecal(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + if (bHasBackground) + { + pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colNormal); + } + + if (bHasBorder) + { + pge->SetDecalMode(olc::DecalMode::WIREFRAME); + 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); + switch (nAlign) + { + case Alignment::Left: + pge->DrawStringPropDecal({ vPos.x + 2.0f, vPos.y + (vSize.y - vText.y) * 0.5f }, sText, m_manager.colText); + break; + case Alignment::Centre: + pge->DrawStringPropDecal(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText); + break; + case Alignment::Right: + pge->DrawStringPropDecal({ vPos.x + vSize.x - vText.x - 2.0f, vPos.y + (vSize.y - vText.y) * 0.5f }, sText, m_manager.colText); + break; + } + } +#pragma endregion + + +#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) + { + nAlign = Alignment::Left; + bHasBorder = true; + bHasBackground = false; + } + + void TextBox::Update(olc::PixelGameEngine* pge) + { + if (m_state == State::Disabled || !bVisible) + return; + + bPressed = false; + bReleased = false; + + olc::vf2d vMouse = pge->GetMousePos(); + + if (vMouse.x >= vPos.x && vMouse.x < vPos.x + vSize.x && + vMouse.y >= vPos.y && vMouse.y < vPos.y + vSize.y) + { + // Released inside box does nothing to me, but i may have + // to finish off the neighbours... oo err + bPressed = pge->GetMouse(olc::Mouse::LEFT).bPressed; + bReleased = pge->GetMouse(olc::Mouse::LEFT).bReleased; + + if (bPressed && pge->IsTextEntryEnabled() && !m_bTextEdit) + { + pge->TextEntryEnable(false); + } + + + if (bPressed && !pge->IsTextEntryEnabled() && !m_bTextEdit) + { + pge->TextEntryEnable(true, sText); + m_bTextEdit = true; + } + + bHeld = pge->GetMouse(olc::Mouse::LEFT).bHeld; + + + } + else + { + // Released outside box + 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) + { + sText = pge->TextEntryGetString(); + pge->TextEntryEnable(false); + m_bTextEdit = false; + } + } + + if (m_bTextEdit && pge->IsTextEntryEnabled()) + sText = pge->TextEntryGetString(); + } + + void TextBox::Draw(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + if (bHasBackground) + { + pge->FillRect(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colNormal); + } + + if (bHasBorder) + pge->DrawRect(vPos, vSize - olc::vf2d(1, 1), m_manager.colBorder); + + if (m_bTextEdit && pge->IsTextEntryEnabled()) + { + // Draw Cursor + int32_t i = pge->TextEntryGetCursor(); + 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) + { + if (!bVisible) + return; + + if (bHasBackground) + { + pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colNormal); + } + + if (bHasBorder) + { + pge->SetDecalMode(olc::DecalMode::WIREFRAME); + pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colBorder); + pge->SetDecalMode(olc::DecalMode::NORMAL); + } + + if (m_bTextEdit && pge->IsTextEntryEnabled()) + { + // Draw Cursor + int32_t i = pge->TextEntryGetCursor(); + olc::vf2d vCursorPos = pge->GetTextSizeProp(sText.substr(0, i)); + 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); + } +#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) + { + vPos = pos; vSize = size; sText = text; + } + + void Button::Update(olc::PixelGameEngine* pge) + { + if (m_state == State::Disabled || !bVisible) + return; + + bPressed = false; + bReleased = false; + float fElapsedTime = pge->GetElapsedTime(); + + olc::vf2d vMouse = pge->GetMousePos(); + 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) + { + m_fTransition += fElapsedTime * m_manager.fHoverSpeedOn; + m_state = State::Hover; + + bPressed = pge->GetMouse(olc::Mouse::LEFT).bPressed; + if (bPressed) + { + m_state = State::Click; + } + + bHeld = pge->GetMouse(olc::Mouse::LEFT).bHeld; + } + else + { + m_fTransition -= fElapsedTime * m_manager.fHoverSpeedOff; + m_state = State::Normal; + } + } + else + { + bHeld = pge->GetMouse(olc::Mouse::LEFT).bHeld; + bReleased = pge->GetMouse(olc::Mouse::LEFT).bReleased; + if (bReleased) m_state = State::Normal; + } + + m_fTransition = std::clamp(m_fTransition, 0.0f, 1.0f); + } + + void Button::Draw(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + switch (m_state) + { + case State::Disabled: + pge->FillRect(vPos, vSize, m_manager.colDisable); + break; + case State::Normal: + case State::Hover: + pge->FillRect(vPos, vSize, olc::PixelLerp(m_manager.colNormal, m_manager.colHover, m_fTransition)); + break; + case State::Click: + pge->FillRect(vPos, vSize, m_manager.colClick); + break; + } + + pge->DrawRect(vPos, vSize - olc::vf2d(1, 1), m_manager.colBorder); + olc::vf2d vText = pge->GetTextSizeProp(sText); + pge->DrawStringProp(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText); + } + + void Button::DrawDecal(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + 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: + 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); + break; + } + pge->SetDecalMode(olc::DecalMode::WIREFRAME); + 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); + } +#pragma endregion + + +#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 ImageButton::Draw(olc::PixelGameEngine* pge) + { + Button::Draw(pge); + pge->DrawSprite(vPos + olc::vi2d(4, 4), pIcon.Sprite()); + } + + void ImageButton::DrawDecal(olc::PixelGameEngine* pge) + { + Button::DrawDecal(pge); + pge->DrawDecal(vPos + olc::vi2d(4, 4), pIcon.Decal()); + } +#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) + { + bChecked = check; + } + + void ImageCheckBox::Update(olc::PixelGameEngine* pge) + { + if (m_state == State::Disabled || !bVisible) + return; + + ImageButton::Update(pge); + if (bPressed) bChecked = !bChecked; + } + + void ImageCheckBox::Draw(olc::PixelGameEngine* pge) + { + ImageButton::Draw(pge); + + if (bChecked) + pge->DrawRect(vPos + olc::vf2d(2, 2), vSize - olc::vi2d(5, 5), m_manager.colBorder); + } + + void ImageCheckBox::DrawDecal(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + ImageButton::DrawDecal(pge); + + if (bChecked) + { + pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colClick); + pge->DrawDecal(vPos + olc::vi2d(4, 4), pIcon.Decal()); + } + + 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); + + olc::vf2d vText = pge->GetTextSizeProp(sText); + pge->DrawStringPropDecal(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText); + } +#pragma endregion + + +#pragma region CheckBox + CheckBox::CheckBox(olc::QuickGUI::Manager& manager, const std::string& text, const bool check, const olc::vf2d& pos, const olc::vf2d& size) + : Button(manager, text, pos, size) + { + bChecked = check; + } + + void CheckBox::Update(olc::PixelGameEngine* pge) + { + if (m_state == State::Disabled || !bVisible) + return; + + Button::Update(pge); + if (bPressed) + bChecked = !bChecked; + } + + void CheckBox::Draw(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + Button::Draw(pge); + + if (bChecked) + pge->DrawRect(vPos + olc::vf2d(2, 2), vSize - olc::vi2d(5, 5), m_manager.colBorder); + } + + void CheckBox::DrawDecal(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + Button::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); + } + + olc::vf2d vText = pge->GetTextSizeProp(sText); + pge->DrawStringPropDecal(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText); + } +#pragma endregion + +#pragma region Slider + Slider::Slider(olc::QuickGUI::Manager& manager, const olc::vf2d& posmin, const olc::vf2d& posmax, const float valmin, const float valmax, const float value) + : BaseControl(manager) + { + vPosMin = posmin; vPosMax = posmax; fMin = valmin; fMax = valmax; fValue = value; + } + + void Slider::Update(olc::PixelGameEngine* pge) + { + if (m_state == State::Disabled || !bVisible) + return; + + float fElapsedTime = pge->GetElapsedTime(); + + olc::vf2d vMouse = pge->GetMousePos(); + bHeld = false; + if (m_state == State::Click) + { + olc::vf2d d = vPosMax - vPosMin; + float u = d.dot(vMouse - vPosMin) / d.mag2(); + fValue = u * (fMax - fMin) + fMin; + bHeld = true; + } + else + { + olc::vf2d vSliderPos = vPosMin + (vPosMax - vPosMin) * ((fValue - fMin) / (fMax - fMin)); + if ((vMouse - vSliderPos).mag2() <= int32_t(m_manager.fGrabRad) * int32_t(m_manager.fGrabRad)) + { + m_fTransition += fElapsedTime * m_manager.fHoverSpeedOn; + m_state = State::Hover; + if (pge->GetMouse(olc::Mouse::LEFT).bPressed) + { + m_state = State::Click; + bPressed = true; + } + } + else + m_state = State::Normal; + } + + if (pge->GetMouse(olc::Mouse::LEFT).bReleased) + { + m_state = State::Normal; + bReleased = true; + } + + if (m_state == State::Normal) + { + m_fTransition -= fElapsedTime * m_manager.fHoverSpeedOff; + m_state = State::Normal; + bHeld = false; + } + + fValue = std::clamp(fValue, fMin, fMax); + m_fTransition = std::clamp(m_fTransition, 0.0f, 1.0f); + } + + void Slider::Draw(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + pge->DrawLine(vPosMin, vPosMax, m_manager.colBorder); + olc::vf2d vSliderPos = vPosMin + (vPosMax - vPosMin) * ((fValue - fMin) / (fMax - fMin)); + + switch (m_state) + { + case State::Disabled: + pge->FillCircle(vSliderPos, int32_t(m_manager.fGrabRad), m_manager.colDisable); + break; + case State::Normal: + case State::Hover: + pge->FillCircle(vSliderPos, int32_t(m_manager.fGrabRad), olc::PixelLerp(m_manager.colNormal, m_manager.colHover, m_fTransition)); + break; + case State::Click: + pge->FillCircle(vSliderPos, int32_t(m_manager.fGrabRad), m_manager.colClick); + break; + } + + + pge->DrawCircle(vSliderPos, int32_t(m_manager.fGrabRad), m_manager.colBorder); + } + + void Slider::DrawDecal(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + pge->DrawLineDecal(vPosMin, vPosMax, m_manager.colBorder); + olc::vf2d vSliderPos = vPosMin + (vPosMax - vPosMin) * ((fValue - fMin) / (fMax - fMin)); + + switch (m_state) + { + case State::Disabled: + pge->FillRectDecal(vSliderPos - olc::vf2d(m_manager.fGrabRad, m_manager.fGrabRad), olc::vf2d(m_manager.fGrabRad, m_manager.fGrabRad) * 2.0f, m_manager.colDisable); + break; + case State::Normal: + case State::Hover: + pge->FillRectDecal(vSliderPos - olc::vf2d(m_manager.fGrabRad, m_manager.fGrabRad), olc::vf2d(m_manager.fGrabRad, m_manager.fGrabRad) * 2.0f, olc::PixelLerp(m_manager.colNormal, m_manager.colHover, m_fTransition)); + break; + case State::Click: + pge->FillRectDecal(vSliderPos - olc::vf2d(m_manager.fGrabRad, m_manager.fGrabRad), olc::vf2d(m_manager.fGrabRad, m_manager.fGrabRad) * 2.0f, m_manager.colClick); + break; + } + + pge->SetDecalMode(olc::DecalMode::WIREFRAME); + pge->FillRectDecal(vSliderPos - olc::vf2d(m_manager.fGrabRad, m_manager.fGrabRad), olc::vf2d(m_manager.fGrabRad, m_manager.fGrabRad) * 2.0f, m_manager.colBorder); + pge->SetDecalMode(olc::DecalMode::NORMAL); + } + + +#pragma endregion + +#pragma region ListBox + ListBox::ListBox(olc::QuickGUI::Manager& manager, std::vector& vList, const olc::vf2d& pos, const olc::vf2d& size) + : BaseControl(manager), m_vList(vList) + { + m_group.CopyThemeFrom(m_manager); + vPos = pos; + vSize = size; + m_pSlider = new Slider(m_group, { pos.x + size.x - m_manager.fGrabRad - 1, pos.y + m_manager.fGrabRad + 1 }, + { pos.x + size.x - m_manager.fGrabRad - 1, pos.y + size.y - m_manager.fGrabRad - 1 }, 0, float(m_vList.size()), 0); + } + + void ListBox::Update(olc::PixelGameEngine* pge) + { + 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) + { + 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 = std::clamp(nSelectedItem, size_t(0), m_vList.size()-1); + + bSelectionChanged = nSelectedItem != nPreviouslySelectedItem; + + + m_pSlider->fMax = float(m_vList.size()); + m_group.Update(pge); + } + + void ListBox::Draw(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + if (bHasBackground) + { + pge->FillRect(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colNormal); + } + + if (bHasBorder) + pge->DrawRect(vPos, vSize - olc::vf2d(1, 1), m_manager.colBorder); + + + size_t idx0 = size_t(m_pSlider->fValue); + size_t idx1 = std::min(idx0 + size_t((vSize.y - 4) / 10), 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; + } + + m_group.Draw(pge); + } + + void ListBox::DrawDecal(olc::PixelGameEngine* pge) + { + if (!bVisible) + return; + + if (bHasBackground) + 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()); + + 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; + } + + if (bHasBorder) + { + pge->SetDecalMode(olc::DecalMode::WIREFRAME); + pge->FillRectDecal(vPos + olc::vf2d(1, 1), vSize - olc::vf2d(2, 2), m_manager.colBorder); + pge->SetDecalMode(olc::DecalMode::NORMAL); + } + + m_group.DrawDecal(pge); + } +#pragma endregion + + + +#pragma region Modal + ModalDialog::ModalDialog() : olc::PGEX(true) + { + + // Create File Open Dialog + olc::vi2d vScreenSize = pge->GetScreenSize(); + + m_listDirectory = new ListBox(m_manFileSelect, m_vDirectory, olc::vf2d(20, 20), olc::vf2d(300, 500)); + m_listFiles = new ListBox(m_manFileSelect, m_vFiles, olc::vf2d(330, 20), olc::vf2d(300, 500)); + + m_path = "/"; + for (auto const& dir_entry : std::filesystem::directory_iterator{ m_path }) + { + if(dir_entry.is_directory()) + m_vDirectory.push_back(dir_entry.path().filename().string()); + else + m_vFiles.push_back(dir_entry.path().filename().string()); + } + } + + void ModalDialog::ShowFileOpen(const std::string& sPath) + { + m_bShowDialog = true; + } + + bool ModalDialog::OnBeforeUserUpdate(float& fElapsedTime) + { + if(!m_bShowDialog) return false; + + m_manFileSelect.Update(this->pge); + + if (pge->GetKey(olc::Key::BACK).bPressed) + { + m_path = m_path.parent_path().string() + "/"; + //m_listDirectory->bSelectionChanged = true; + //m_listDirectory->nSelectedItem = 0; + } + + if (m_listDirectory->bSelectionChanged) + { + std::string sDirectory = m_vDirectory[m_listDirectory->nSelectedItem]; + /*if (sDirectory == "..") + m_path = m_path.parent_path().string() + "/"; + else + 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 }) + { + if (dir_entry.is_directory() || dir_entry.is_other()) + m_vDirectory.push_back(dir_entry.path().filename().string()); + else + m_vFiles.push_back(dir_entry.path().filename().string()); + } + + //m_vDirectory.push_back(".."); + + //m_listFiles->nSelectedItem = 0; + //m_listDirectory->nSelectedItem = 0; + + } + + pge->DrawStringDecal({ 0,0 }, m_path.string()); + + + + + m_manFileSelect.DrawDecal(this->pge); + + + + if (pge->GetKey(olc::Key::ESCAPE).bPressed) + { + m_bShowDialog = false; + return false; + } + + return true; + } +#pragma endregion + +} +#endif // OLC_PGEX_QUICKGUI +#endif // OLC_PGEX_QUICKGUI_H \ No newline at end of file diff --git a/olcPGEX_TransformedView.h b/TiledCollisionEditor/olcPGEX_TransformedView.h similarity index 100% rename from olcPGEX_TransformedView.h rename to TiledCollisionEditor/olcPGEX_TransformedView.h diff --git a/olcUTIL_Camera2D.h b/TiledCollisionEditor/olcUTIL_Camera2D.h similarity index 100% rename from olcUTIL_Camera2D.h rename to TiledCollisionEditor/olcUTIL_Camera2D.h diff --git a/olcUTIL_Geometry2D.h b/TiledCollisionEditor/olcUTIL_Geometry2D.h similarity index 100% rename from olcUTIL_Geometry2D.h rename to TiledCollisionEditor/olcUTIL_Geometry2D.h diff --git a/pixelGameEngine.cpp b/TiledCollisionEditor/pixelGameEngine.cpp similarity index 61% rename from pixelGameEngine.cpp rename to TiledCollisionEditor/pixelGameEngine.cpp index 2f3c126..da79b0e 100644 --- a/pixelGameEngine.cpp +++ b/TiledCollisionEditor/pixelGameEngine.cpp @@ -3,4 +3,6 @@ #include "olcUTIL_Geometry2D.h" #include "pixelGameEngine.h" #define OLC_PGEX_TRANSFORMEDVIEW -#include "olcPGEX_TransformedView.h" \ No newline at end of file +#include "olcPGEX_TransformedView.h" +#define OLC_PGEX_QUICKGUI +#include "olcPGEX_QuickGUI.h" \ No newline at end of file diff --git a/pixelGameEngine.h b/TiledCollisionEditor/pixelGameEngine.h similarity index 100% rename from pixelGameEngine.h rename to TiledCollisionEditor/pixelGameEngine.h diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 2cde94e..0000000 --- a/main.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "olcUTIL_Geometry2D.h" -#include "pixelGameEngine.h" -#include "olcPGEX_TransformedView.h" -#include "olcUTIL_Camera2D.h" - -using namespace olc; - -#define WIDTH 640 -#define HEIGHT 480 - -class TiledCollisionEditor : public olc::PixelGameEngine -{ - - -public: - TiledCollisionEditor() - { - sAppName = "TiledCollisionEditor"; - } - -public: - bool OnUserCreate() override - { - return true; - } - - bool OnUserUpdate(float fElapsedTime) override - { - return true; - } - - bool OnUserDestroy()override{ - return true; - } -}; - -enum Direction{ - RIGHT, - DOWN, - LEFT, - UP -}; - -struct Data{ - int x,y; -}; - - -int main() -{ - TiledCollisionEditor demo; - if (demo.Construct(640, 480, 4, 4)) - demo.Start(); - - return 0; -}