diff --git a/.circleci/config.yml b/.circleci/config.yml index 4050a93f1..03540b8bf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,7 +9,7 @@ jobs: - run: echo deb http://deb.debian.org/debian stretch-backports-sloppy main >> /etc/apt/sources.list.d/debian-backports.list - run: apt update -y - run: apt install -y g++ libsdl2-dev libsdl2-ttf-dev git rpm wget - - run: apt install -y -t 'stretch-backports*' cmake libsodium-dev + - run: apt install -y -t 'stretch-backports*' cmake libsodium-dev libpng-dev - run: cmake -S. -Bbuild .. -DNIGHTLY_BUILD=ON -DCMAKE_INSTALL_PREFIX=/usr - run: cmake --build build -j 2 --target package - store_artifacts: {path: ./build/devilutionx, destination: devilutionx_linux_x86_64} @@ -24,7 +24,7 @@ jobs: steps: - checkout - run: apt-get update -y - - run: apt-get install -y cmake curl g++ git lcov libgtest-dev libgmock-dev libfmt-dev libsdl2-dev libsdl2-ttf-dev libsodium-dev + - run: apt-get install -y cmake curl g++ git lcov libgtest-dev libgmock-dev libfmt-dev libsdl2-dev libsdl2-ttf-dev libsodium-dev libpng-dev - run: cmake -S. -Bbuild -DRUN_TESTS=ON -DENABLE_CODECOVERAGE=ON - run: cmake --build build -j 2 - run: cmake --build build -j 2 --target test diff --git a/.github/workflows/Linux_x86.yml b/.github/workflows/Linux_x86.yml index f59532386..86349f6e7 100644 --- a/.github/workflows/Linux_x86.yml +++ b/.github/workflows/Linux_x86.yml @@ -20,7 +20,7 @@ jobs: run: > sudo dpkg --add-architecture i386 && sudo apt update -y && - sudo apt install -y cmake file g++-multilib git libfmt-dev:i386 libsdl2-dev:i386 libsdl2-ttf-dev:i386 libsodium-dev:i386 rpm wget + sudo apt install -y cmake file g++-multilib git libfmt-dev:i386 libsdl2-dev:i386 libsdl2-ttf-dev:i386 libsodium-dev:i386 libpng-dev:i386 rpm wget - name: Cache CMake build folder uses: actions/cache@v2 diff --git a/.github/workflows/Linux_x86_64_SDL1.yml b/.github/workflows/Linux_x86_64_SDL1.yml index 0719e1d2f..6f1cc5d48 100644 --- a/.github/workflows/Linux_x86_64_SDL1.yml +++ b/.github/workflows/Linux_x86_64_SDL1.yml @@ -19,7 +19,7 @@ jobs: - name: Create Build Environment run: > sudo apt update && - sudo apt install -y cmake file g++ git libfmt-dev libsdl-dev libsdl-ttf2.0-dev libsodium-dev rpm + sudo apt install -y cmake file g++ git libfmt-dev libsdl-dev libsdl-ttf2.0-dev libsodium-dev libpng-dev rpm - name: Cache CMake build folder uses: actions/cache@v2 diff --git a/3rdParty/SDL_image/CMakeLists.txt b/3rdParty/SDL_image/CMakeLists.txt new file mode 100644 index 000000000..65bacf65a --- /dev/null +++ b/3rdParty/SDL_image/CMakeLists.txt @@ -0,0 +1,26 @@ +include(FetchContent_MakeAvailableExcludeFromAll) + +include(FetchContent) +if(USE_SDL1) + FetchContent_Declare(SDL_image + URL https://www.libsdl.org/projects/SDL_image/release/SDL_image-1.2.12.tar.gz + URL_HASH MD5=a0f9098ebe5400f0bdc9b62e60797ecb + ) +else() + FetchContent_Declare(SDL_image + URL https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.5.tar.gz + URL_HASH MD5=f26f3a153360a8f09ed5220ef7b07aea + ) +endif() +FetchContent_MakeAvailableExcludeFromAll(SDL_image) + +add_library(SDL_image STATIC ${CMAKE_CURRENT_LIST_DIR}/IMG.c ${sdl_image_SOURCE_DIR}/IMG_png.c) +target_include_directories(SDL_image PRIVATE ${sdl_image_SOURCE_DIR}) +target_compile_definitions(SDL_image PRIVATE LOAD_PNG SDL_IMAGE_USE_COMMON_BACKEND) +target_link_libraries(SDL_image PNG::PNG) + +if(USE_SDL1) + target_link_libraries(SDL_image ${SDL_LIBRARY}) +else() + target_link_libraries(SDL_image SDL2::SDL2) +endif() diff --git a/3rdParty/SDL_image/IMG.c b/3rdParty/SDL_image/IMG.c new file mode 100644 index 000000000..8d38df571 --- /dev/null +++ b/3rdParty/SDL_image/IMG.c @@ -0,0 +1,51 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2021 Sam Lantinga + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* This is a heavily reduced version of IMG.c including only PNG support */ + +#include "SDL_image.h" + +extern int IMG_InitPNG(void); +extern void IMG_QuitPNG(void); + +static int initialized = 0; + +int IMG_Init(int flags) { + int result = 0; + + /* Passing 0 returns the currently initialized loaders */ + if (!flags) { + return initialized; + } + + if (flags & IMG_INIT_PNG) { + if ((initialized & IMG_INIT_PNG) || IMG_InitPNG() == 0) { + result |= IMG_INIT_PNG; + } + } + initialized |= result; + + return result; +} + +void IMG_Quit() { + if (initialized & IMG_INIT_PNG) { + IMG_QuitPNG(); + } + initialized = 0; +} diff --git a/3rdParty/libpng/CMakeLists.txt b/3rdParty/libpng/CMakeLists.txt new file mode 100644 index 000000000..8c19e2baa --- /dev/null +++ b/3rdParty/libpng/CMakeLists.txt @@ -0,0 +1,31 @@ +include(FetchContent_MakeAvailableExcludeFromAll) + +if(NOT DISABLE_LTO) + # Force CMake to raise an error if INTERPROCEDURAL_OPTIMIZATION + # is enabled and compiler does not support IPO + set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) +endif() + +if(DEVILUTIONX_STATIC_LIBPNG) + set(PNG_LIBRARY png_static) + set(PNG_STATIC ON CACHE BOOL "Build static lib" FORCE) + set(PNG_SHARED OFF CACHE BOOL "Build shared lib" FORCE) +else() + set(PNG_LIBRARY png) + set(PNG_STATIC OFF CACHE BOOL "Build static lib" FORCE) + set(PNG_SHARED ON CACHE BOOL "Build shared lib" FORCE) +endif() +set(PNG_TESTS OFF CACHE BOOL "Build libpng tests") + +include(FetchContent) +FetchContent_Declare(png + URL https://github.com/StephenCWills/libpng/archive/5cfc16530ae7f2c1f1c88ecd08b0fde2e2a4cd93.tar.gz + URL_HASH MD5=e98756c6316f51ca9c045bb2f1bdf307 +) +FetchContent_MakeAvailableExcludeFromAll(png) + +target_include_directories(${PNG_LIBRARY} INTERFACE + $ + $) + +add_library(PNG::PNG ALIAS ${PNG_LIBRARY}) diff --git a/CMake/ctr/n3ds_defs.cmake b/CMake/ctr/n3ds_defs.cmake index 337550bd7..973b0df62 100644 --- a/CMake/ctr/n3ds_defs.cmake +++ b/CMake/ctr/n3ds_defs.cmake @@ -2,6 +2,9 @@ set(ASAN OFF) set(UBSAN OFF) set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) +set(DEVILUTIONX_SYSTEM_LIBFMT OFF) +set(DEVILUTIONX_STATIC_LIBSODIUM ON) +set(DEVILUTIONX_STATIC_LIBFMT ON) set(DISABLE_ZERO_TIER ON) set(USE_SDL1 ON) set(PREFILL_PLAYER_NAME ON) @@ -11,7 +14,6 @@ list(APPEND CMAKE_MODULE_PATH "${DevilutionX_SOURCE_DIR}/CMake/ctr/modules") find_package(CITRO3D REQUIRED) find_package(FREETYPE REQUIRED) find_package(BZIP2 REQUIRED) -find_package(PNG REQUIRED) #additional compilation definitions add_definitions(-D__3DS__) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e3c5a860..60e40912a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,9 @@ option(DEVILUTIONX_SYSTEM_LIBFMT "Use system-provided libfmt" ON) cmake_dependent_option(DEVILUTIONX_STATIC_LIBFMT "Link static libfmt" OFF "DEVILUTIONX_SYSTEM_LIBFMT AND NOT DIST" ON) +option(DEVILUTIONX_SYSTEM_LIBPNG "Use system-provided libpng" ON) +cmake_dependent_option(DEVILUTIONX_STATIC_LIBPNG "Link static libpng" OFF + "DEVILUTIONX_SYSTEM_LIBPNG AND NOT DIST" ON) if(NOT VERSION_NUM) include(CMake/git.cmake) @@ -231,6 +234,21 @@ if(NOT fmt_FOUND) add_subdirectory(3rdParty/libfmt) endif() +if(DEVILUTIONX_SYSTEM_LIBPNG) + find_package(PNG QUIET) + if(PNG_FOUND) + message("-- Found png ${PNG_VERSION_STRING}") + else() + message("-- Suitable system png package not found, will use png from source") + endif() + if(NOT TARGET PNG::PNG AND TARGET 3ds::png) + add_library(PNG::PNG ALIAS 3ds::png) + endif() +endif() +if(NOT PNG_FOUND) + add_subdirectory(3rdParty/libpng) +endif() + if(ANDROID) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/android-project/3rdParty/SDL2) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/android-project/3rdParty/SDL2_ttf) @@ -276,6 +294,8 @@ if(NOT NONET AND NOT DISABLE_TCP) endif() endif() +add_subdirectory(3rdParty/SDL_image) + if(NOT NOSOUND) if(DEVILUTIONX_SYSTEM_SDL_AUDIOLIB) find_package(SDL_audiolib REQUIRED) @@ -666,6 +686,7 @@ if(NOT NONET) endif() target_link_libraries(libdevilutionx PUBLIC fmt::fmt) +target_link_libraries(libdevilutionx PUBLIC PNG::PNG) genex_for_option(DEBUG) target_compile_definitions(libdevilutionx PUBLIC "$<${DEBUG_GENEX}:_DEBUG>") @@ -788,6 +809,7 @@ else() ${SDL2_MAIN} SDL2::SDL2_ttf) endif() +target_link_libraries(libdevilutionx PUBLIC SDL_image) if(NOT NOSOUND) target_link_libraries(libdevilutionx PUBLIC SDL_audiolib) @@ -807,14 +829,13 @@ if (VITA) ScePower_stub SceAppUtil_stub freetype - png z ) target_compile_definitions(libdevilutionx PUBLIC VITA) endif() if(NINTENDO_3DS) - target_link_libraries(libdevilutionx PUBLIC 3ds::freetype 3ds::bzip2 3ds::png) + target_link_libraries(libdevilutionx PUBLIC 3ds::freetype 3ds::bzip2) target_link_libraries(libdevilutionx PUBLIC 3ds::citro3d 3ds::ctrulib) endif() @@ -905,7 +926,6 @@ if(NINTENDO_SWITCH) target_link_libraries(libdevilutionx PUBLIC freetype - png bz2 z ) diff --git a/Packaging/resources/ui_art/attack.png b/Packaging/resources/ui_art/attack.png new file mode 100644 index 000000000..0b07b8b41 Binary files /dev/null and b/Packaging/resources/ui_art/attack.png differ diff --git a/Packaging/resources/ui_art/attackp.png b/Packaging/resources/ui_art/attackp.png new file mode 100644 index 000000000..c48d108c6 Binary files /dev/null and b/Packaging/resources/ui_art/attackp.png differ diff --git a/Packaging/resources/ui_art/back.png b/Packaging/resources/ui_art/back.png new file mode 100644 index 000000000..0fbcea880 Binary files /dev/null and b/Packaging/resources/ui_art/back.png differ diff --git a/Packaging/resources/ui_art/backp.png b/Packaging/resources/ui_art/backp.png new file mode 100644 index 000000000..a3b670335 Binary files /dev/null and b/Packaging/resources/ui_art/backp.png differ diff --git a/Packaging/resources/ui_art/castspell.png b/Packaging/resources/ui_art/castspell.png new file mode 100644 index 000000000..91159b52c Binary files /dev/null and b/Packaging/resources/ui_art/castspell.png differ diff --git a/Packaging/resources/ui_art/castspellp.png b/Packaging/resources/ui_art/castspellp.png new file mode 100644 index 000000000..da6c71410 Binary files /dev/null and b/Packaging/resources/ui_art/castspellp.png differ diff --git a/Packaging/resources/ui_art/directions.png b/Packaging/resources/ui_art/directions.png new file mode 100644 index 000000000..8e125e6aa Binary files /dev/null and b/Packaging/resources/ui_art/directions.png differ diff --git a/Packaging/resources/ui_art/directions2.png b/Packaging/resources/ui_art/directions2.png new file mode 100644 index 000000000..024c5b47e Binary files /dev/null and b/Packaging/resources/ui_art/directions2.png differ diff --git a/Packaging/resources/ui_art/noaction.png b/Packaging/resources/ui_art/noaction.png new file mode 100644 index 000000000..6787d5825 Binary files /dev/null and b/Packaging/resources/ui_art/noaction.png differ diff --git a/Packaging/resources/ui_art/noactionp.png b/Packaging/resources/ui_art/noactionp.png new file mode 100644 index 000000000..f72f065d3 Binary files /dev/null and b/Packaging/resources/ui_art/noactionp.png differ diff --git a/Packaging/resources/ui_art/object.png b/Packaging/resources/ui_art/object.png new file mode 100644 index 000000000..2284373a6 Binary files /dev/null and b/Packaging/resources/ui_art/object.png differ diff --git a/Packaging/resources/ui_art/objectp.png b/Packaging/resources/ui_art/objectp.png new file mode 100644 index 000000000..eabad35e7 Binary files /dev/null and b/Packaging/resources/ui_art/objectp.png differ diff --git a/Packaging/resources/ui_art/pickitem.png b/Packaging/resources/ui_art/pickitem.png new file mode 100644 index 000000000..5c66019a1 Binary files /dev/null and b/Packaging/resources/ui_art/pickitem.png differ diff --git a/Packaging/resources/ui_art/pickitemp.png b/Packaging/resources/ui_art/pickitemp.png new file mode 100644 index 000000000..aadcf4f51 Binary files /dev/null and b/Packaging/resources/ui_art/pickitemp.png differ diff --git a/Packaging/resources/ui_art/talk.png b/Packaging/resources/ui_art/talk.png new file mode 100644 index 000000000..c7de225db Binary files /dev/null and b/Packaging/resources/ui_art/talk.png differ diff --git a/Packaging/resources/ui_art/talkp.png b/Packaging/resources/ui_art/talkp.png new file mode 100644 index 000000000..20fc1624d Binary files /dev/null and b/Packaging/resources/ui_art/talkp.png differ diff --git a/Packaging/switch/build.sh b/Packaging/switch/build.sh index 54a2740b4..19ad919d4 100755 --- a/Packaging/switch/build.sh +++ b/Packaging/switch/build.sh @@ -26,9 +26,10 @@ build() { install_deps() { "$DEVKITPRO/pacman/bin/pacman" -S --needed --noconfirm --quiet \ - switch-freetype switch-mesa switch-glad switch-glm switch-sdl2 \ - switch-sdl2_ttf switch-libvorbis switch-libmikmod switch-libsodium \ - libnx devkitA64 devkitA64 general-tools switch-tools devkitpro-pkgbuild-helpers + switch-freetype switch-mesa switch-glad switch-glm switch-libpng \ + switch-sdl2 switch-sdl2_ttf switch-libvorbis switch-libmikmod \ + switch-libsodium libnx devkitA64 devkitA64 general-tools \ + switch-tools devkitpro-pkgbuild-helpers } prepare_devkitpro() { diff --git a/Packaging/windows/mingw-prep.sh b/Packaging/windows/mingw-prep.sh index dd668eefa..3a7d65d07 100755 --- a/Packaging/windows/mingw-prep.sh +++ b/Packaging/windows/mingw-prep.sh @@ -3,6 +3,7 @@ SDLDEV_VERS=2.0.14 SDLTTF_VERS=2.0.15 SODIUM_VERS=1.0.18 +ZLIB_VERS=1.2.11 # exit when any command fails set -euo pipefail @@ -42,6 +43,12 @@ wget -q https://github.com/jedisct1/libsodium/releases/download/${SODIUM_VERS}-R tar -xzf libsodium-${SODIUM_VERS}-mingw.tar.gz --no-same-owner $SUDO cp -r libsodium-${SODIUM_ARCH}/* ${MINGW_PREFIX} +wget -q https://zlib.net/zlib-${ZLIB_VERS}.tar.gz -Ozlib-${ZLIB_VERS}.tar.gz +tar -xzf zlib-${ZLIB_VERS}.tar.gz +$SUDO cp zlib-${ZLIB_VERS}/zconf.h ${MINGW_PREFIX}/include +$SUDO cp zlib-${ZLIB_VERS}/zlib.h ${MINGW_PREFIX}/include +$SUDO ln -sf ../bin/zlib1.dll ${MINGW_PREFIX}/lib/libzlib1.dll.a + # Fixup pkgconfig prefix: find "${MINGW_PREFIX}/lib/pkgconfig/" -name '*.pc' -exec \ $SUDO sed -i "s|^prefix=.*|prefix=${MINGW_PREFIX}|" '{}' \; diff --git a/Source/controls/touch/renderers.cpp b/Source/controls/touch/renderers.cpp index 511243029..959f7277b 100644 --- a/Source/controls/touch/renderers.cpp +++ b/Source/controls/touch/renderers.cpp @@ -1,5 +1,14 @@ +#include "control.h" +#include "controls/plrctrls.h" #include "controls/touch/renderers.h" +#include "cursor.h" +#include "doom.h" #include "engine.h" +#include "gendung.h" +#include "inv.h" +#include "minitext.h" +#include "stores.h" +#include "towners.h" namespace devilution { @@ -25,6 +34,15 @@ void VirtualGamepadRenderer::Render(const Surface &out) void VirtualDirectionPadRenderer::Render(const Surface &out) { + RenderPad(out); + RenderKnob(out); +} + +void VirtualDirectionPadRenderer::RenderPad(const Surface &out) +{ + if (padSurface == nullptr) + padSurface.reset(LoadPNG("ui_art\\directions.png")); + auto center = virtualDirectionPad->area.position; auto radius = virtualDirectionPad->area.radius; int diameter = 2 * radius; @@ -34,10 +52,24 @@ void VirtualDirectionPadRenderer::Render(const Surface &out) int width = diameter; int height = diameter; SDL_Rect rect { x, y, width, height }; + SDL_BlitScaled(padSurface.get(), nullptr, out.surface, &rect); +} + +void VirtualDirectionPadRenderer::RenderKnob(const Surface &out) +{ + if (knobSurface == nullptr) + knobSurface.reset(LoadPNG("ui_art\\directions2.png")); - auto pixelFormat = out.surface->format; - auto color = SDL_MapRGBA(pixelFormat, 0, 255, 0, 255); - SDL_FillRect(out.surface, &rect, color); + auto center = virtualDirectionPad->position; + auto radius = virtualDirectionPad->area.radius / 3; + int diameter = 2 * radius; + + int x = center.x - radius; + int y = center.y - radius; + int width = diameter; + int height = diameter; + SDL_Rect rect { x, y, width, height }; + SDL_BlitScaled(knobSurface.get(), nullptr, out.surface, &rect); } void VirtualPadButtonRenderer::Render(const Surface &out) @@ -50,11 +82,137 @@ void VirtualPadButtonRenderer::Render(const Surface &out) int y = center.y - radius; int width = diameter; int height = diameter; + + SDL_Surface *surface = GetButtonSurface(); SDL_Rect rect { x, y, width, height }; + SDL_BlitScaled(surface, nullptr, out.surface, &rect); +} + +SDL_Surface *VirtualPadButtonRenderer::GetAttackSurface() +{ + if (attackSurface == nullptr) + attackSurface.reset(LoadPNG("ui_art\\attack.png")); + if (pressedAttackSurface == nullptr) + pressedAttackSurface.reset(LoadPNG("ui_art\\attackp.png")); + return virtualPadButton->isHeld ? pressedAttackSurface.get() : attackSurface.get(); +} + +SDL_Surface *VirtualPadButtonRenderer::GetTalkSurface() +{ + if (talkSurface == nullptr) + talkSurface.reset(LoadPNG("ui_art\\talk.png")); + if (pressedTalkSurface == nullptr) + pressedTalkSurface.reset(LoadPNG("ui_art\\talkp.png")); + return virtualPadButton->isHeld ? pressedTalkSurface.get() : talkSurface.get(); +} + +SDL_Surface *VirtualPadButtonRenderer::GetItemSurface() +{ + if (itemSurface == nullptr) + itemSurface.reset(LoadPNG("ui_art\\pickitem.png")); + if (pressedItemSurface == nullptr) + pressedItemSurface.reset(LoadPNG("ui_art\\pickitemp.png")); + return virtualPadButton->isHeld ? pressedItemSurface.get() : itemSurface.get(); +} + +SDL_Surface *VirtualPadButtonRenderer::GetObjectSurface() +{ + if (objectSurface == nullptr) + objectSurface.reset(LoadPNG("ui_art\\object.png")); + if (pressedObjectSurface == nullptr) + pressedObjectSurface.reset(LoadPNG("ui_art\\objectp.png")); + return virtualPadButton->isHeld ? pressedObjectSurface.get() : objectSurface.get(); +} - auto pixelFormat = out.surface->format; - auto color = SDL_MapRGBA(pixelFormat, 0, 255, 0, 255); - SDL_FillRect(out.surface, &rect, color); +SDL_Surface *VirtualPadButtonRenderer::GetCastSurface() +{ + if (castSurface == nullptr) + castSurface.reset(LoadPNG("ui_art\\castspell.png")); + if (pressedCastSurface == nullptr) + pressedCastSurface.reset(LoadPNG("ui_art\\castspellp.png")); + return virtualPadButton->isHeld ? pressedCastSurface.get() : castSurface.get(); +} + +SDL_Surface *VirtualPadButtonRenderer::GetCancelSurface() +{ + if (cancelSurface == nullptr) + cancelSurface.reset(LoadPNG("ui_art\\back.png")); + if (pressedCancelSurface == nullptr) + pressedCancelSurface.reset(LoadPNG("ui_art\\backp.png")); + return virtualPadButton->isHeld ? pressedCancelSurface.get() : cancelSurface.get(); +} + +SDL_Surface *VirtualPadButtonRenderer::GetBlankSurface() +{ + if (blankSurface == nullptr) + blankSurface.reset(LoadPNG("ui_art\\noaction.png")); + if (pressedBlankSurface == nullptr) + pressedBlankSurface.reset(LoadPNG("ui_art\\noactionp.png")); + return virtualPadButton->isHeld ? pressedBlankSurface.get() : blankSurface.get(); +} + +SDL_Surface *PrimaryActionButtonRenderer::GetButtonSurface() +{ + // NEED: Confirm surface + if (qtextflag) + return GetTalkSurface(); + if (invflag) + return GetInventoryButtonSurface(); + if (leveltype == DTYPE_TOWN) + return GetTownButtonSurface(); + return GetDungeonButtonSurface(); +} + +SDL_Surface *PrimaryActionButtonRenderer::GetTownButtonSurface() +{ + if (stextflag != STORE_NONE || pcursmonst != -1) + return GetTalkSurface(); + return GetBlankSurface(); +} + +SDL_Surface *PrimaryActionButtonRenderer::GetDungeonButtonSurface() +{ + if (pcursmonst != -1) { + const auto &monster = Monsters[pcursmonst]; + if (M_Talker(monster) || monster.mtalkmsg != TEXT_NONE) + return GetTalkSurface(); + } + return GetAttackSurface(); +} + +SDL_Surface *PrimaryActionButtonRenderer::GetInventoryButtonSurface() +{ + if (pcursinvitem != -1 || pcurs > CURSOR_HAND) + return GetItemSurface(); + return GetBlankSurface(); +} + +SDL_Surface *SecondaryActionButtonRenderer::GetButtonSurface() +{ + // NEED: Stairs surface + if (InGameMenu() || QuestLogIsOpen || sbookflag) + return GetBlankSurface(); + if (pcursobj != -1) + return GetObjectSurface(); + if (pcursitem != -1) + return GetItemSurface(); + return GetBlankSurface(); +} + +SDL_Surface *SpellActionButtonRenderer::GetButtonSurface() +{ + if (!InGameMenu() && !QuestLogIsOpen && !sbookflag) + return GetCastSurface(); + return GetBlankSurface(); +} + +SDL_Surface *CancelButtonRenderer::GetButtonSurface() +{ + if (InGameMenu()) + return GetCancelSurface(); + if (DoomFlag || invflag || sbookflag || QuestLogIsOpen || chrflag) + return GetCancelSurface(); + return GetBlankSurface(); } } // namespace devilution diff --git a/Source/controls/touch/renderers.h b/Source/controls/touch/renderers.h index 3b80b1f58..c1295efee 100644 --- a/Source/controls/touch/renderers.h +++ b/Source/controls/touch/renderers.h @@ -4,6 +4,8 @@ #include "controls/touch/gamepad.h" #include "engine/surface.hpp" +#include "utils/png.h" +#include "utils/sdl_ptrs.h" namespace devilution { @@ -11,6 +13,8 @@ class VirtualDirectionPadRenderer { public: VirtualDirectionPadRenderer(VirtualDirectionPad *virtualDirectionPad) : virtualDirectionPad(virtualDirectionPad) + , padSurface(nullptr) + , knobSurface(nullptr) { } @@ -18,19 +22,110 @@ public: private: VirtualDirectionPad *virtualDirectionPad; + SDLSurfaceUniquePtr padSurface; + SDLSurfaceUniquePtr knobSurface; + + void RenderPad(const Surface &out); + void RenderKnob(const Surface &out); }; class VirtualPadButtonRenderer { public: VirtualPadButtonRenderer(VirtualPadButton *virtualPadButton) : virtualPadButton(virtualPadButton) + , attackSurface(nullptr) + , pressedAttackSurface(nullptr) + , talkSurface(nullptr) + , pressedTalkSurface(nullptr) + , itemSurface(nullptr) + , pressedItemSurface(nullptr) + , objectSurface(nullptr) + , pressedObjectSurface(nullptr) + , castSurface(nullptr) + , pressedCastSurface(nullptr) + , cancelSurface(nullptr) + , pressedCancelSurface(nullptr) + , blankSurface(nullptr) + , pressedBlankSurface(nullptr) { } void Render(const Surface &out); -private: +protected: VirtualPadButton *virtualPadButton; + + virtual SDL_Surface *GetButtonSurface() = 0; + SDL_Surface *GetAttackSurface(); + SDL_Surface *GetTalkSurface(); + SDL_Surface *GetItemSurface(); + SDL_Surface *GetObjectSurface(); + SDL_Surface *GetCastSurface(); + SDL_Surface *GetCancelSurface(); + SDL_Surface *GetBlankSurface(); + +private: + SDLSurfaceUniquePtr attackSurface; + SDLSurfaceUniquePtr pressedAttackSurface; + SDLSurfaceUniquePtr talkSurface; + SDLSurfaceUniquePtr pressedTalkSurface; + SDLSurfaceUniquePtr itemSurface; + SDLSurfaceUniquePtr pressedItemSurface; + SDLSurfaceUniquePtr objectSurface; + SDLSurfaceUniquePtr pressedObjectSurface; + SDLSurfaceUniquePtr castSurface; + SDLSurfaceUniquePtr pressedCastSurface; + SDLSurfaceUniquePtr cancelSurface; + SDLSurfaceUniquePtr pressedCancelSurface; + SDLSurfaceUniquePtr blankSurface; + SDLSurfaceUniquePtr pressedBlankSurface; +}; + +class PrimaryActionButtonRenderer : public VirtualPadButtonRenderer { +public: + PrimaryActionButtonRenderer(VirtualPadButton *primaryActionButton) + : VirtualPadButtonRenderer(primaryActionButton) + { + } + +private: + SDL_Surface *GetButtonSurface(); + SDL_Surface *GetTownButtonSurface(); + SDL_Surface *GetDungeonButtonSurface(); + SDL_Surface *GetInventoryButtonSurface(); +}; + +class SecondaryActionButtonRenderer : public VirtualPadButtonRenderer { +public: + SecondaryActionButtonRenderer(VirtualPadButton *secondaryActionButton) + : VirtualPadButtonRenderer(secondaryActionButton) + { + } + +private: + SDL_Surface *GetButtonSurface(); +}; + +class SpellActionButtonRenderer : public VirtualPadButtonRenderer { +public: + SpellActionButtonRenderer(VirtualPadButton *spellActionButton) + : VirtualPadButtonRenderer(spellActionButton) + { + } + +private: + SDL_Surface *GetButtonSurface(); +}; + +class CancelButtonRenderer : public VirtualPadButtonRenderer { +public: + CancelButtonRenderer(VirtualPadButton *cancelButton) + : VirtualPadButtonRenderer(cancelButton) + { + } + +private: + SDL_Surface *GetButtonSurface(); }; class VirtualGamepadRenderer { @@ -48,10 +143,10 @@ public: private: VirtualDirectionPadRenderer directionPadRenderer; - VirtualPadButtonRenderer primaryActionButtonRenderer; - VirtualPadButtonRenderer secondaryActionButtonRenderer; - VirtualPadButtonRenderer spellActionButtonRenderer; - VirtualPadButtonRenderer cancelButtonRenderer; + PrimaryActionButtonRenderer primaryActionButtonRenderer; + SecondaryActionButtonRenderer secondaryActionButtonRenderer; + SpellActionButtonRenderer spellActionButtonRenderer; + CancelButtonRenderer cancelButtonRenderer; }; void DrawVirtualGamepad(const Surface &out); diff --git a/Source/monster.cpp b/Source/monster.cpp index 317bc1f78..33f57ce34 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3920,7 +3920,7 @@ void AddDoppelganger(Monster &monster) } } -bool M_Talker(Monster &monster) +bool M_Talker(const Monster &monster) { return IsAnyOf(monster._mAi, AI_LAZARUS, AI_WARLORD, AI_GARBUD, AI_ZHAR, AI_SNOTSPIL, AI_LACHDAN, AI_LAZHELP); } diff --git a/Source/monster.h b/Source/monster.h index 0b864c248..c5c1492dd 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -275,7 +275,7 @@ void InitMonsters(); void SetMapMonsters(const uint16_t *dunData, Point startPosition); int AddMonster(Point position, Direction dir, int mtype, bool inMap); void AddDoppelganger(Monster &monster); -bool M_Talker(Monster &monster); +bool M_Talker(const Monster &monster); void M_StartStand(Monster &monster, Direction md); void M_ClearSquares(int i); void M_GetKnockback(int i); diff --git a/Source/storm/storm_sdl_rw.cpp b/Source/storm/storm_sdl_rw.cpp index 678624ce7..198c56e49 100644 --- a/Source/storm/storm_sdl_rw.cpp +++ b/Source/storm/storm_sdl_rw.cpp @@ -96,4 +96,24 @@ SDL_RWops *SFileRw_FromStormHandle(HANDLE handle) return result; } +SDL_RWops *SFileOpenRw(const char *filename) +{ +#ifdef __ANDROID__ + std::string relativePath = filename; + for (std::size_t i = 0; i < relativePath.size(); ++i) { + if (relativePath[i] == '\\') + relativePath[i] = '/'; + } + SDL_RWops *rwops = SDL_RWFromFile(relativePath.c_str(), "rb"); + if (rwops != nullptr) + return rwops; +#endif + + HANDLE handle; + if (SFileOpenFile(filename, &handle)) + return SFileRw_FromStormHandle(handle); + + return nullptr; +} + } // namespace devilution diff --git a/Source/storm/storm_sdl_rw.h b/Source/storm/storm_sdl_rw.h index 8727c6106..16b800fa8 100644 --- a/Source/storm/storm_sdl_rw.h +++ b/Source/storm/storm_sdl_rw.h @@ -13,4 +13,11 @@ namespace devilution { */ SDL_RWops *SFileRw_FromStormHandle(HANDLE handle); +/** + * @brief Opens a Storm file and creates a read-only SDL_RWops from its handle. + * + * Closes the handle when it gets closed. + */ +SDL_RWops *SFileOpenRw(const char *filename); + } // namespace devilution diff --git a/Source/utils/png.h b/Source/utils/png.h new file mode 100644 index 000000000..d5b69de3c --- /dev/null +++ b/Source/utils/png.h @@ -0,0 +1,50 @@ +#pragma once + +#include + +#include "miniwin/miniwin.h" +#include "storm/storm.h" +#include "storm/storm_sdl_rw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +const int IMG_INIT_PNG = 0x00000002; + +int IMG_Init(int flags); +void IMG_Quit(void); +int IMG_isPNG(SDL_RWops *src); +SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src); +int IMG_SavePNG(SDL_Surface *surface, const char *file); +int IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst); + +inline SDL_Surface *IMG_LoadPNG(const char *file) +{ + SDL_RWops *src = SDL_RWFromFile(file, "rb"); + return IMG_LoadPNG_RW(src); +} + +#ifdef __cplusplus +} +#endif + +namespace devilution { + +inline int InitPNG() +{ + return IMG_Init(IMG_INIT_PNG); +} + +inline void QuitPNG() +{ + IMG_Quit(); +} + +inline SDL_Surface *LoadPNG(const char *file) +{ + SDL_RWops *rwops = SFileOpenRw(file); + return IMG_LoadPNG_RW(rwops); +} + +} // namespace devilution diff --git a/android-project/CMake/android_defs.cmake b/android-project/CMake/android_defs.cmake index ee7c52c90..013b2204b 100644 --- a/android-project/CMake/android_defs.cmake +++ b/android-project/CMake/android_defs.cmake @@ -2,6 +2,7 @@ set(ASAN OFF) set(UBSAN OFF) set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) +set(DEVILUTIONX_SYSTEM_LIBPNG OFF) set(DISABLE_ZERO_TIER ON) if(BINARY_RELEASE OR CMAKE_BUILD_TYPE STREQUAL "Release") diff --git a/appveyor.yml b/appveyor.yml index 3daf85929..b35f8b1b5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,7 +10,7 @@ install: - git pull - .\bootstrap-vcpkg.bat - cd %APPVEYOR_BUILD_FOLDER% - - vcpkg install --recurse fmt:x64-windows sdl2:x64-windows sdl2-ttf:x64-windows libsodium:x64-windows + - vcpkg install --recurse fmt:x64-windows sdl2:x64-windows sdl2-ttf:x64-windows libsodium:x64-windows libpng:x64-windows before_build: - cmake -G "Visual Studio 16 2019" -A x64 -DNIGHTLY_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake . diff --git a/docs/building.md b/docs/building.md index fbe51bb53..2db951dd4 100644 --- a/docs/building.md +++ b/docs/building.md @@ -12,11 +12,11 @@ although we have a fallback if necessary. ### Installing dependencies on Debian and Ubuntu ``` -sudo apt-get install cmake g++ libsdl2-ttf-dev libsodium-dev +sudo apt-get install cmake g++ libsdl2-ttf-dev libsodium-dev libpng-dev ``` ### Installing dependencies on Fedora ``` -sudo dnf install cmake glibc-devel SDL2-devel SDL2_ttf-devel libsodium-devel libasan libubsan +sudo dnf install cmake glibc-devel SDL2-devel SDL2_ttf-devel libsodium-devel libpng-devel libasan libubsan ``` ### Compiling ``` @@ -41,7 +41,7 @@ cmake --build . -j $(sysctl -n hw.physicalcpu) ### Installing dependencies ``` -pkg install cmake sdl2_ttf libsodium +pkg install cmake sdl2_ttf libsodium libpng ``` ### Compiling ``` @@ -54,7 +54,7 @@ cmake --build . -j $(sysctl -n hw.ncpu) ### Installing dependencies ``` -pkgin install cmake SDL2_ttf libsodium +pkgin install cmake SDL2_ttf libsodium libpng ``` ### Compiling ``` @@ -68,7 +68,7 @@ cmake --build . -j $(sysctl -n hw.ncpu) ### Installing dependencies ``` -pkg_add cmake sdl2-ttf libsodium gmake +pkg_add cmake sdl2-ttf libsodium libpng gmake ``` ### Compiling ``` @@ -84,7 +84,7 @@ cmake --build . -j $(sysctl -n hw.ncpuonline) ### 32-bit -Download and place the 32bit MinGW Development Libraries of [SDL2](https://www.libsdl.org/download-2.0.php), [SDL2_ttf](https://www.libsdl.org/projects/SDL_ttf/) and [Libsodium](https://github.com/jedisct1/libsodium/releases) in `/usr/i686-w64-mingw32`. This can be done automatically by running `Packaging/windows/mingw-prep.sh`. +Download the 32bit MinGW Development Libraries of [SDL2](https://www.libsdl.org/download-2.0.php), [SDL2_ttf](https://www.libsdl.org/projects/SDL_ttf/) and [Libsodium](https://github.com/jedisct1/libsodium/releases) as well as headers for [zlib](https://zlib.net/zlib-1.2.11.tar.gz) and place them in `/usr/i686-w64-mingw32`. This can be done automatically by running `Packaging/windows/mingw-prep.sh`. ``` sudo apt-get install cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 pkg-config-mingw-w64-i686 @@ -92,7 +92,7 @@ sudo apt-get install cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 pkg-config-ming ### 64-bit -Download and place the 64bit MinGW Development Libraries of [SDL2](https://www.libsdl.org/download-2.0.php), [SDL2_ttf](https://www.libsdl.org/projects/SDL_ttf/) and [Libsodium](https://github.com/jedisct1/libsodium/releases) in `/usr/x86_64-w64-mingw32`. This can be done automatically by running `Packaging/windows/mingw-prep64.sh`. +Download the 64bit MinGW Development Libraries of [SDL2](https://www.libsdl.org/download-2.0.php), [SDL2_ttf](https://www.libsdl.org/projects/SDL_ttf/) and [Libsodium](https://github.com/jedisct1/libsodium/releases) as well as headers for [zlib](https://zlib.net/zlib-1.2.11.tar.gz) and place them in `/usr/x86_64-w64-mingw32`. This can be done automatically by running `Packaging/windows/mingw-prep64.sh`. ``` sudo apt-get install cmake gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 pkg-config-mingw-w64-x86-64 @@ -124,7 +124,6 @@ of the `(i686|x86_64)-w64-mingw32` directory. ### Installing dependencies Make sure to install the `C++ CMake tools for Windows` component for Visual Studio. -* **Using vcpkg (recommended)** 1. Install vcpkg following the instructions from https://github.com/microsoft/vcpkg#quick-start. Don't forget to perform _user-wide integration_ step for additional convenience. @@ -133,19 +132,15 @@ Make sure to install the `C++ CMake tools for Windows` component for Visual Stud For the 64-bit version of the dependencies please run this command: ``` - vcpkg install fmt:x64-windows sdl2:x64-windows sdl2-ttf:x64-windows libsodium:x64-windows gtest:x64-windows + vcpkg install fmt:x64-windows sdl2:x64-windows sdl2-ttf:x64-windows libsodium:x64-windows libpng:x64-windows gtest:x64-windows ``` For the 32-bit version of the dependencies please run this command: ``` - vcpkg install fmt:x86-windows sdl2:x86-windows sdl2-ttf:x86-windows libsodium:x86-windows gtest:x86-windows + vcpkg install fmt:x86-windows sdl2:x86-windows sdl2-ttf:x86-windows libsodium:x86-windows libpng:x86-windows gtest:x86-windows ``` -* **Manually** -1. Download and place the MSVC Development Libraries of [SDL2](https://www.libsdl.org/download-2.0.php), [SDL2_ttf](https://www.libsdl.org/projects/SDL_ttf/) and [Libsodium](https://github.com/jedisct1/libsodium/releases) in `%USERPROFILE%\AppData\Local\Microsoft\WindowsApps\`. -2. If dependencies are not found or you wish to place them in other location - configure required path variables in _"Manage Configurations..."_ dialog inside Visual Studio or in _cmake-gui_. - ### Compiling * **Through Open->CMake in Visual Studio** @@ -208,8 +203,8 @@ https://devkitpro.org/wiki/Getting_Started ``` sudo (dkp-)pacman -S \ devkitARM general-tools 3dstools devkitpro-pkgbuild-helpers \ - libctru citro3d 3ds-sdl 3ds-sdl_ttf 3ds-freetype 3ds-cmake \ - 3ds-pkg-config picasso 3dslink + libctru citro3d 3ds-sdl 3ds-sdl_ttf 3ds-freetype 3ds-libpng \ + 3ds-cmake 3ds-pkg-config picasso 3dslink ``` - Download or compile [bannertool](https://github.com/Steveice10/bannertool/releases) and [makerom](https://github.com/jakcron/Project_CTR/releases) - Copy binaries to: `/opt/devkitpro/tools/bin/` @@ -236,7 +231,7 @@ cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release make ``` -[PlayStation Vita manual](docs/manual/platforms/vita.md) +[PlayStation Vita manual](/docs/manual/platforms/vita.md) @@ -244,11 +239,11 @@ make ### Installing dependencies on 32 bit Haiku ``` -pkgman install cmake_x86 devel:libsdl2_x86 devel:libsdl2_ttf_x86 devel:libsodium_x86 +pkgman install cmake_x86 devel:libsdl2_x86 devel:libsdl2_ttf_x86 devel:libsodium_x86 devel:libpng_x86 ``` ### Installing dependencies on 64 bit Haiku ``` -pkgman install cmake devel:libsdl2 devel:libsdl2_ttf devel:libsodium +pkgman install cmake devel:libsdl2 devel:libsdl2_ttf devel:libsodium devel:libpng ``` ### Compiling on 32 bit Haiku ```