commit 41a75f74226936f002811bd1568a1c1a5e9707f2 Author: Jasper <j.blanckenburg@fasttube.de> Date: Thu May 19 20:07:15 2022 +0200 Initial commit diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..eb1167f --- /dev/null +++ b/.clang-format @@ -0,0 +1,137 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: "^ IWYU pragma:" +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^[<"](fmt|SDL2)/' + Priority: 3 + SortPriority: 0 + - Regex: "^<" + Priority: 4 + SortPriority: 0 + - Regex: ".*" + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: "(Test)?$" +IncludeIsMainSourceRegex: "" +IndentCaseLabels: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: "" +MacroBlockEnd: "" +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +--- + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..01f9cb9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +.vscode/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f7dc952 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 3.10) + +project("FT22 Steering Wheel Display") + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") + +set(CMAKE_CXX_STANDARD 17) + +# DEPENDENCIES {{{ + +find_package(SDL2 REQUIRED) +find_package(SDL2TTF REQUIRED) +find_package(SDL2IMAGE REQUIRED) + +include(FetchContent) + +# fmtlib +set(stw_display_orig_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) +set(BUILD_SHARED_LIBS ON) +FetchContent_Declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG 8.1.1 +) +if (NOT fmt_POPULATED) + FetchContent_MakeAvailable(fmt) +endif() +if (NOT DEFINED fmt_INCLUDE_DIR) + set(fmt_INCLUDE_DIR ${fmt_SOURCE_DIR}/${FMT_INC_DIR}) +endif() +set(BUILD_SHARED_LIBS ${lhotse_orig_BUILD_SHARED_LIBS}) + +# }}} + +add_compile_options(-Wall -Wextra -Wimplicit-fallthrough) + +add_executable( + stw-display + src/main.cpp + src/App.cpp + src/AMI.cpp + src/widgets.cpp + src/util.cpp +) +target_include_directories( + stw-display PUBLIC + "include" +) +target_include_directories( + stw-display PRIVATE + ${SDL2_INCLUDE_DIRS} + ${fmt_INCLUDE_DIR} +) +target_link_libraries( + stw-display + ${SDL2_LIBRARIES} + ${SDL2TTF_LIBRARY} + ${SDL2IMAGE_LIBRARY} + fmt) +add_dependencies(stw-display fmt) \ No newline at end of file diff --git a/cmake/FindSDL2IMAGE.cmake b/cmake/FindSDL2IMAGE.cmake new file mode 100644 index 0000000..1656c01 --- /dev/null +++ b/cmake/FindSDL2IMAGE.cmake @@ -0,0 +1,163 @@ +# Locate SDL2 library +# This module defines +# SDL2_LIBRARY, the name of the library to link against +# SDL2_FOUND, if false, do not try to link to SDL2 +# SDL2_INCLUDE_DIR, where to find SDL.h +# +# This module responds to the the flag: +# SDL2_BUILDING_LIBRARY +# If this is defined, then no SDL2main will be linked in because +# only applications need main(). +# Otherwise, it is assumed you are building an application and this +# module will attempt to locate and set the the proper link flags +# as part of the returned SDL2_LIBRARY variable. +# +# Don't forget to include SDLmain.h and SDLmain.m your project for the +# OS X framework based version. (Other versions link to -lSDL2main which +# this module will try to find on your behalf.) Also for OS X, this +# module will automatically add the -framework Cocoa on your behalf. +# +# +# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration +# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library +# (SDL2.dll, libsdl2.so, SDL2.framework, etc). +# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. +# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value +# as appropriate. These values are used to generate the final SDL2_LIBRARY +# variable, but when these values are unset, SDL2_LIBRARY does not get created. +# +# +# $SDL2DIR is an environment variable that would +# correspond to the ./configure --prefix=$SDL2DIR +# used in building SDL2. +# l.e.galup 9-20-02 +# +# Modified by Eric Wing. +# Added code to assist with automated building by using environmental variables +# and providing a more controlled/consistent search behavior. +# Added new modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). +# Also corrected the header search path to follow "proper" SDL guidelines. +# Added a search for SDL2main which is needed by some platforms. +# Added a search for threads which is needed by some platforms. +# Added needed compile switches for MinGW. +# +# On OSX, this will prefer the Framework version (if found) over others. +# People will have to manually change the cache values of +# SDL2_LIBRARY to override this selection or set the CMake environment +# CMAKE_INCLUDE_PATH to modify the search paths. +# +# Note that the header path has changed from SDL2/SDL.h to just SDL.h +# This needed to change because "proper" SDL convention +# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability +# reasons because not all systems place things in SDL2/ (see FreeBSD). + +#============================================================================= +# Copyright 2003-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +SET(SDL2IMAGE_SEARCH_PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +FIND_PATH(SDL2IMAGE_INCLUDE_DIR SDL_image.h + HINTS + $ENV{SDL2IMAGEDIR} + PATH_SUFFIXES include/SDL2 include + PATHS ${SDL2IMAGE_SEARCH_PATHS} +) + +FIND_LIBRARY(SDL2IMAGE_LIBRARY_TEMP + NAMES SDL2_image + HINTS + $ENV{SDL2IMAGEDIR} + PATH_SUFFIXES lib64 lib + PATHS ${SDL2IMAGE_SEARCH_PATHS} +) + +IF(NOT SDL2IMAGE_BUILDING_LIBRARY) + IF(NOT ${SDL2IMAGE_INCLUDE_DIR} MATCHES ".framework") + # Non-OS X framework versions expect you to also dynamically link to + # SDL2IMAGEmain. This is mainly for Windows and OS X. Other (Unix) platforms + # seem to provide SDL2IMAGEmain for compatibility even though they don't + # necessarily need it. + FIND_LIBRARY(SDL2IMAGEMAIN_LIBRARY + NAMES SDL2_image + HINTS + $ENV{SDL2IMAGEDIR} + PATH_SUFFIXES lib64 lib + PATHS ${SDL2IMAGE_SEARCH_PATHS} + ) + ENDIF(NOT ${SDL2IMAGE_INCLUDE_DIR} MATCHES ".framework") +ENDIF(NOT SDL2IMAGE_BUILDING_LIBRARY) + +# SDL2IMAGE may require threads on your system. +# The Apple build may not need an explicit flag because one of the +# frameworks may already provide it. +# But for non-OSX systems, I will use the CMake Threads package. +IF(NOT APPLE) + FIND_PACKAGE(Threads) +ENDIF(NOT APPLE) + +# MinGW needs an additional library, mwindows +# It's total link flags should look like -lmingw32 -lSDL2IMAGEmain -lSDL2IMAGE -lmwindows +# (Actually on second look, I think it only needs one of the m* libraries.) +IF(MINGW) + SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") +ENDIF(MINGW) + +IF(SDL2IMAGE_LIBRARY_TEMP) + # For SDL2IMAGEmain + IF(NOT SDL2IMAGE_BUILDING_LIBRARY) + IF(SDL2IMAGEMAIN_LIBRARY) + SET(SDL2IMAGE_LIBRARY_TEMP ${SDL2IMAGEMAIN_LIBRARY} ${SDL2IMAGE_LIBRARY_TEMP}) + ENDIF(SDL2IMAGEMAIN_LIBRARY) + ENDIF(NOT SDL2IMAGE_BUILDING_LIBRARY) + + # For OS X, SDL2IMAGE uses Cocoa as a backend so it must link to Cocoa. + # CMake doesn't display the -framework Cocoa string in the UI even + # though it actually is there if I modify a pre-used variable. + # I think it has something to do with the CACHE STRING. + # So I use a temporary variable until the end so I can set the + # "real" variable in one-shot. + IF(APPLE) + SET(SDL2IMAGE_LIBRARY_TEMP ${SDL2IMAGE_LIBRARY_TEMP} "-framework Cocoa") + ENDIF(APPLE) + + # For threads, as mentioned Apple doesn't need this. + # In fact, there seems to be a problem if I used the Threads package + # and try using this line, so I'm just skipping it entirely for OS X. + IF(NOT APPLE) + SET(SDL2IMAGE_LIBRARY_TEMP ${SDL2IMAGE_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) + ENDIF(NOT APPLE) + + # For MinGW library + IF(MINGW) + SET(SDL2IMAGE_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2IMAGE_LIBRARY_TEMP}) + ENDIF(MINGW) + + # Set the final string here so the GUI reflects the final state. + SET(SDL2IMAGE_LIBRARY ${SDL2IMAGE_LIBRARY_TEMP} CACHE STRING "Where the SDL2IMAGE Library can be found") + # Set the temp variable to INTERNAL so it is not seen in the CMake GUI + SET(SDL2IMAGE_LIBRARY_TEMP "${SDL2IMAGE_LIBRARY_TEMP}" CACHE INTERNAL "") +ENDIF(SDL2IMAGE_LIBRARY_TEMP) + +INCLUDE(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2IMAGE REQUIRED_VARS SDL2IMAGE_LIBRARY SDL2IMAGE_INCLUDE_DIR) \ No newline at end of file diff --git a/cmake/FindSDL2TTF.cmake b/cmake/FindSDL2TTF.cmake new file mode 100644 index 0000000..be8e7bc --- /dev/null +++ b/cmake/FindSDL2TTF.cmake @@ -0,0 +1,163 @@ +# Locate SDL2 library +# This module defines +# SDL2_LIBRARY, the name of the library to link against +# SDL2_FOUND, if false, do not try to link to SDL2 +# SDL2_INCLUDE_DIR, where to find SDL.h +# +# This module responds to the the flag: +# SDL2_BUILDING_LIBRARY +# If this is defined, then no SDL2main will be linked in because +# only applications need main(). +# Otherwise, it is assumed you are building an application and this +# module will attempt to locate and set the the proper link flags +# as part of the returned SDL2_LIBRARY variable. +# +# Don't forget to include SDLmain.h and SDLmain.m your project for the +# OS X framework based version. (Other versions link to -lSDL2main which +# this module will try to find on your behalf.) Also for OS X, this +# module will automatically add the -framework Cocoa on your behalf. +# +# +# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration +# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library +# (SDL2.dll, libsdl2.so, SDL2.framework, etc). +# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. +# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value +# as appropriate. These values are used to generate the final SDL2_LIBRARY +# variable, but when these values are unset, SDL2_LIBRARY does not get created. +# +# +# $SDL2DIR is an environment variable that would +# correspond to the ./configure --prefix=$SDL2DIR +# used in building SDL2. +# l.e.galup 9-20-02 +# +# Modified by Eric Wing. +# Added code to assist with automated building by using environmental variables +# and providing a more controlled/consistent search behavior. +# Added new modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). +# Also corrected the header search path to follow "proper" SDL guidelines. +# Added a search for SDL2main which is needed by some platforms. +# Added a search for threads which is needed by some platforms. +# Added needed compile switches for MinGW. +# +# On OSX, this will prefer the Framework version (if found) over others. +# People will have to manually change the cache values of +# SDL2_LIBRARY to override this selection or set the CMake environment +# CMAKE_INCLUDE_PATH to modify the search paths. +# +# Note that the header path has changed from SDL2/SDL.h to just SDL.h +# This needed to change because "proper" SDL convention +# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability +# reasons because not all systems place things in SDL2/ (see FreeBSD). + +#============================================================================= +# Copyright 2003-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +SET(SDL2TTF_SEARCH_PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +FIND_PATH(SDL2TTF_INCLUDE_DIR SDL_ttf.h + HINTS + $ENV{SDL2TTFDIR} + PATH_SUFFIXES include/SDL2 include + PATHS ${SDL2TTF_SEARCH_PATHS} +) + +FIND_LIBRARY(SDL2TTF_LIBRARY_TEMP + NAMES SDL2_ttf + HINTS + $ENV{SDL2TTFDIR} + PATH_SUFFIXES lib64 lib + PATHS ${SDL2TTF_SEARCH_PATHS} +) + +IF(NOT SDL2TTF_BUILDING_LIBRARY) + IF(NOT ${SDL2TTF_INCLUDE_DIR} MATCHES ".framework") + # Non-OS X framework versions expect you to also dynamically link to + # SDL2TTFmain. This is mainly for Windows and OS X. Other (Unix) platforms + # seem to provide SDL2TTFmain for compatibility even though they don't + # necessarily need it. + FIND_LIBRARY(SDL2TTFMAIN_LIBRARY + NAMES SDL2_ttf + HINTS + $ENV{SDL2TTFDIR} + PATH_SUFFIXES lib64 lib + PATHS ${SDL2TTF_SEARCH_PATHS} + ) + ENDIF(NOT ${SDL2TTF_INCLUDE_DIR} MATCHES ".framework") +ENDIF(NOT SDL2TTF_BUILDING_LIBRARY) + +# SDL2TTF may require threads on your system. +# The Apple build may not need an explicit flag because one of the +# frameworks may already provide it. +# But for non-OSX systems, I will use the CMake Threads package. +IF(NOT APPLE) + FIND_PACKAGE(Threads) +ENDIF(NOT APPLE) + +# MinGW needs an additional library, mwindows +# It's total link flags should look like -lmingw32 -lSDL2TTFmain -lSDL2TTF -lmwindows +# (Actually on second look, I think it only needs one of the m* libraries.) +IF(MINGW) + SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") +ENDIF(MINGW) + +IF(SDL2TTF_LIBRARY_TEMP) + # For SDL2TTFmain + IF(NOT SDL2TTF_BUILDING_LIBRARY) + IF(SDL2TTFMAIN_LIBRARY) + SET(SDL2TTF_LIBRARY_TEMP ${SDL2TTFMAIN_LIBRARY} ${SDL2TTF_LIBRARY_TEMP}) + ENDIF(SDL2TTFMAIN_LIBRARY) + ENDIF(NOT SDL2TTF_BUILDING_LIBRARY) + + # For OS X, SDL2TTF uses Cocoa as a backend so it must link to Cocoa. + # CMake doesn't display the -framework Cocoa string in the UI even + # though it actually is there if I modify a pre-used variable. + # I think it has something to do with the CACHE STRING. + # So I use a temporary variable until the end so I can set the + # "real" variable in one-shot. + IF(APPLE) + SET(SDL2TTF_LIBRARY_TEMP ${SDL2TTF_LIBRARY_TEMP} "-framework Cocoa") + ENDIF(APPLE) + + # For threads, as mentioned Apple doesn't need this. + # In fact, there seems to be a problem if I used the Threads package + # and try using this line, so I'm just skipping it entirely for OS X. + IF(NOT APPLE) + SET(SDL2TTF_LIBRARY_TEMP ${SDL2TTF_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) + ENDIF(NOT APPLE) + + # For MinGW library + IF(MINGW) + SET(SDL2TTF_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2TTF_LIBRARY_TEMP}) + ENDIF(MINGW) + + # Set the final string here so the GUI reflects the final state. + SET(SDL2TTF_LIBRARY ${SDL2TTF_LIBRARY_TEMP} CACHE STRING "Where the SDL2TTF Library can be found") + # Set the temp variable to INTERNAL so it is not seen in the CMake GUI + SET(SDL2TTF_LIBRARY_TEMP "${SDL2TTF_LIBRARY_TEMP}" CACHE INTERNAL "") +ENDIF(SDL2TTF_LIBRARY_TEMP) + +INCLUDE(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2TTF REQUIRED_VARS SDL2TTF_LIBRARY SDL2TTF_INCLUDE_DIR) \ No newline at end of file diff --git a/include/AMI.h b/include/AMI.h new file mode 100644 index 0000000..02bab54 --- /dev/null +++ b/include/AMI.h @@ -0,0 +1,20 @@ +#pragma once + +#include "widgets.h" + +#include <SDL2/SDL.h> + +constexpr const char* FT_LOGO_PATH = "resources/Fasttube_Logo-white.bmp"; + +class AMI { +public: + AMI(SDL_Renderer* renderer); + + void draw(); + +private: + SDL_Renderer* renderer; + + ImageWidget ft_logo; + TextWidget choose; +}; \ No newline at end of file diff --git a/include/App.h b/include/App.h new file mode 100644 index 0000000..6980a3d --- /dev/null +++ b/include/App.h @@ -0,0 +1,45 @@ +#pragma once + +#include "AMI.h" + +#include <SDL2/SDL.h> + +#include <memory> + +constexpr int SCREEN_WIDTH = 480; +constexpr int SCREEN_HEIGHT = 320; + +enum class AppView { AMI, DRIVER, TESTING }; + +class SDLManager { +public: + SDLManager(); + ~SDLManager(); +}; + +class App { +public: + App(); + ~App(); + + int run(); + +private: + void init_sdl(); + + void handle_events(); + void render(); + + // The SDLManager initializes & quits SDL and its subsystems. Thus, it must be + // the first member of the class, so that its constructor is called before the + // others and its destructor is called after the others. + SDLManager sdl_manager; + + std::unique_ptr<AMI> ami; + + bool running; + AppView view; + + SDL_Window* window; + SDL_Renderer* renderer; +}; \ No newline at end of file diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..c104e41 --- /dev/null +++ b/include/util.h @@ -0,0 +1,13 @@ +#pragma once + +#include <SDL2/SDL.h> +#include <SDL2/SDL_ttf.h> + +#include <string> + +namespace util { + +SDL_Texture* load_img(SDL_Renderer* renderer, const std::string& path); +TTF_Font* load_font(const std::string& path, int pt); + +} \ No newline at end of file diff --git a/include/widgets.h b/include/widgets.h new file mode 100644 index 0000000..aa00708 --- /dev/null +++ b/include/widgets.h @@ -0,0 +1,57 @@ +#pragma once + +#include <SDL2/SDL.h> +#include <SDL2/SDL_ttf.h> + +#include <optional> +#include <string> + +class Widget { +public: + Widget(SDL_Renderer* renderer, SDL_Rect dest_rect); + + virtual void update_rect(SDL_Rect new_rect); + + virtual void draw() = 0; + +protected: + SDL_Renderer* renderer; + SDL_Rect dest_rect; +}; + +class TextureWidget : public Widget { +public: + TextureWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, + std::optional<SDL_Texture*> texture); + ~TextureWidget(); + + virtual void draw() override; + + void update_texture(SDL_Texture* new_texture); + +private: + std::optional<SDL_Texture*> texture; +}; + +class ImageWidget : public TextureWidget { +public: + ImageWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, + const std::string& path); +}; + +class TextWidget : public TextureWidget { +public: + TextWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, + const std::string& font_path, + const std::string& initial_text = ""); + ~TextWidget(); + + void update_text(const std::string& new_text); + +protected: + TTF_Font* font; + + std::string text; + + SDL_Texture* generate_text(const std::string& text); +}; \ No newline at end of file diff --git a/resources/Avenir-Book.ttf b/resources/Avenir-Book.ttf new file mode 100644 index 0000000..96da4d7 Binary files /dev/null and b/resources/Avenir-Book.ttf differ diff --git a/resources/Fasttube_Logo-white.bmp b/resources/Fasttube_Logo-white.bmp new file mode 100644 index 0000000..c18bb18 Binary files /dev/null and b/resources/Fasttube_Logo-white.bmp differ diff --git a/resources/Fasttube_Logo-white.png b/resources/Fasttube_Logo-white.png new file mode 100644 index 0000000..00dd85c Binary files /dev/null and b/resources/Fasttube_Logo-white.png differ diff --git a/src/AMI.cpp b/src/AMI.cpp new file mode 100644 index 0000000..656e508 --- /dev/null +++ b/src/AMI.cpp @@ -0,0 +1,17 @@ +#include "AMI.h" + +AMI::AMI(SDL_Renderer* renderer) + : renderer{renderer}, ft_logo{renderer, + {.x = 182, .y = 0, .w = 116, .h = 40}, + FT_LOGO_PATH}, + choose{renderer, + {.x = 0, .y = 45, .w = 480, .h = 40}, + "resources/Avenir-Book.ttf", + "Choose a Mission:"} {} + +void AMI::draw() { + SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); + SDL_RenderClear(renderer); + ft_logo.draw(); + choose.draw(); +} \ No newline at end of file diff --git a/src/App.cpp b/src/App.cpp new file mode 100644 index 0000000..fe34268 --- /dev/null +++ b/src/App.cpp @@ -0,0 +1,89 @@ +#include "App.h" + +#include "AMI.h" + +#include <SDL2/SDL_image.h> +#include <fmt/format.h> + +#include <stdexcept> + +App::App() : view{AppView::AMI} { init_sdl(); } + +App::~App() { + // Destroy window + SDL_DestroyRenderer(renderer); + renderer = nullptr; + SDL_DestroyWindow(window); + window = nullptr; +} + +void App::init_sdl() { + window = SDL_CreateWindow("FT22 STW Display", SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, + SCREEN_HEIGHT, SDL_WINDOW_SHOWN); + if (window == nullptr) { + throw std::runtime_error( + fmt::format("Couldn't create window: {}", SDL_GetError())); + } + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + if (renderer == nullptr) { + throw std::runtime_error( + fmt::format("Couldn't create renderer: {}", SDL_GetError())); + } +} + +int App::run() { + ami = std::make_unique<AMI>(renderer); + + running = true; + + while (running) { + handle_events(); + render(); + SDL_Delay(1); + } + + return 0; +} + +void App::handle_events() { + SDL_Event e; + while (SDL_PollEvent(&e) != 0) { + if (e.type == SDL_QUIT) { + running = false; + } + } +} + +void App::render() { + switch (view) { + case AppView::AMI: + ami->draw(); + break; + default: + throw std::runtime_error(fmt::format("Unknown view: {}", (int)view)); + } + SDL_RenderPresent(renderer); +} + +SDLManager::SDLManager() { + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + throw std::runtime_error( + fmt::format("Couldn't initialize SDL: {}", SDL_GetError())); + } + if (TTF_Init() == -1) { + throw std::runtime_error( + fmt::format("Couldn't initialize SDL_ttf: {}", TTF_GetError())); + } + int img_flags = IMG_INIT_PNG; + if (!(IMG_Init(img_flags) & img_flags)) { + throw std::runtime_error( + fmt::format("Couldn't initialitze SDL_image: {}", IMG_GetError())); + } +} + +SDLManager::~SDLManager() { + IMG_Quit(); + TTF_Quit(); + SDL_Quit(); +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..2b60725 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,6 @@ +#include "App.h" + +int main() { + App app; + return app.run(); +} \ No newline at end of file diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..ed95a6c --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,34 @@ +#include "util.h" + +#include <SDL2/SDL_image.h> +#include <fmt/format.h> + +#include <stdexcept> + +namespace util { + +SDL_Texture* load_img(SDL_Renderer* renderer, const std::string& path) { + SDL_Surface* loaded = IMG_Load(path.c_str()); + if (loaded == nullptr) { + throw std::runtime_error( + fmt::format("Unable to load image {}: {}", path, IMG_GetError())); + } + SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, loaded); + if (texture == nullptr) { + throw std::runtime_error(fmt::format( + "Unable to convert image {} to texture: {}", path, IMG_GetError())); + } + SDL_FreeSurface(loaded); + return texture; +} + +TTF_Font* load_font(const std::string& path, int pt) { + TTF_Font* font = TTF_OpenFont(path.c_str(), pt); + if (font == nullptr) { + throw std::runtime_error( + fmt::format("Unable to load font {}: {}", path, TTF_GetError())); + } + return font; +} + +} // namespace util diff --git a/src/widgets.cpp b/src/widgets.cpp new file mode 100644 index 0000000..27f61af --- /dev/null +++ b/src/widgets.cpp @@ -0,0 +1,75 @@ +#include "widgets.h" + +#include "util.h" + +#include <SDL2/SDL_image.h> +#include <fmt/format.h> + +#include <stdexcept> + +Widget::Widget(SDL_Renderer* renderer, SDL_Rect rect) + : renderer{renderer}, dest_rect{rect} {} + +void Widget::update_rect(SDL_Rect new_rect) { dest_rect = new_rect; } + +TextureWidget::TextureWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, + std::optional<SDL_Texture*> texture) + : Widget{renderer, dest_rect}, texture{texture} {} + +TextureWidget::~TextureWidget() { + if (texture) { + SDL_DestroyTexture(*texture); + texture = nullptr; + } +} + +void TextureWidget::draw() { + if (texture) { + SDL_RenderCopy(renderer, *texture, NULL, &dest_rect); + } +} + +void TextureWidget::update_texture(SDL_Texture* new_texture) { + if (texture) { + SDL_DestroyTexture(*texture); + } + texture = new_texture; +} + +ImageWidget::ImageWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, + const std::string& path) + : TextureWidget{renderer, dest_rect, util::load_img(renderer, path)} {} + +TextWidget::TextWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, + const std::string& font_path, + const std::string& initial_text) + : TextureWidget{renderer, dest_rect, std::nullopt}, + font{util::load_font(font_path, 28)}, text{initial_text} { + if (text != "") { + update_texture(generate_text(text)); + } +} + +TextWidget::~TextWidget() { TTF_CloseFont(font); } + +void TextWidget::update_text(const std::string& new_text) { + if (text != new_text) { + update_texture(generate_text(new_text)); + text = new_text; + } +} + +SDL_Texture* TextWidget::generate_text(const std::string& text) { + SDL_Surface* surf = + TTF_RenderText_Solid(font, text.c_str(), {0xFF, 0xFF, 0XFF, 0xFF}); + if (surf == nullptr) { + throw std::runtime_error( + fmt::format("Unable to render text surface: {}", TTF_GetError())); + } + SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surf); + if (texture == nullptr) { + throw std::runtime_error(fmt::format( + "Unable to create texture from text surface: {}", SDL_GetError())); + } + return texture; +} \ No newline at end of file