mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-15 20:03:15 +02:00
Merge branch 'develop' into settings-rework
This commit is contained in:
41
.github/workflows/github.yml
vendored
41
.github/workflows/github.yml
vendored
@@ -99,14 +99,6 @@ jobs:
|
||||
extension: ipa
|
||||
preset: ios-release-conan
|
||||
conan_profile: ios-arm64
|
||||
- platform: mxe
|
||||
os: ubuntu-20.04
|
||||
mxe: i686-w64-mingw32.shared
|
||||
test: 0
|
||||
pack: 1
|
||||
cpack_args: -D CPACK_NSIS_EXECUTABLE=`which makensis`
|
||||
extension: exe
|
||||
cmake_args: -G Ninja
|
||||
- platform: msvc
|
||||
os: windows-latest
|
||||
test: 0
|
||||
@@ -135,7 +127,6 @@ jobs:
|
||||
- name: Dependencies
|
||||
run: source '${{github.workspace}}/CI/${{matrix.platform}}/before_install.sh'
|
||||
env:
|
||||
MXE_TARGET: ${{ matrix.mxe }}
|
||||
VCMI_BUILD_PLATFORM: x64
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
@@ -173,40 +164,16 @@ jobs:
|
||||
env:
|
||||
PULL_REQUEST: ${{ github.event.pull_request.number }}
|
||||
|
||||
- name: Configure CMake
|
||||
if: "${{ matrix.preset == '' }}"
|
||||
run: |
|
||||
mkdir -p '${{github.workspace}}/out/build/${{matrix.preset}}'
|
||||
cd '${{github.workspace}}/out/build/${{matrix.preset}}'
|
||||
cmake \
|
||||
../.. -GNinja \
|
||||
${{matrix.cmake_args}} -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DENABLE_TEST=${{matrix.test}} \
|
||||
-DENABLE_STRICT_COMPILATION=ON \
|
||||
-DPACKAGE_NAME_SUFFIX:STRING="$VCMI_PACKAGE_NAME_SUFFIX" \
|
||||
-DPACKAGE_FILE_NAME:STRING="$VCMI_PACKAGE_FILE_NAME" \
|
||||
-DENABLE_GITVERSION="$VCMI_PACKAGE_GITVERSION"
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
CXX: ${{ matrix.cxx }}
|
||||
|
||||
- name: CMake Preset
|
||||
if: "${{ matrix.preset != '' }}"
|
||||
run: |
|
||||
cmake --preset ${{ matrix.preset }}
|
||||
|
||||
- name: Build
|
||||
if: "${{ matrix.preset == '' }}"
|
||||
run: |
|
||||
cmake --build '${{github.workspace}}/out/build/${{matrix.preset}}'
|
||||
|
||||
- name: Build Preset
|
||||
if: "${{ matrix.preset != '' }}"
|
||||
run: |
|
||||
cmake --build --preset ${{matrix.preset}}
|
||||
|
||||
- name: Test
|
||||
if: ${{ matrix.test == 1 && matrix.preset != ''}}
|
||||
if: ${{ matrix.test == 1 }}
|
||||
run: |
|
||||
ctest --preset ${{matrix.preset}}
|
||||
|
||||
@@ -222,7 +189,7 @@ jobs:
|
||||
rm -rf _CPack_Packages
|
||||
|
||||
- name: Additional logs
|
||||
if: ${{ failure() && steps.cpack.outcome == 'failure' && matrix.platform == 'mxe' }}
|
||||
if: ${{ failure() && steps.cpack.outcome == 'failure' && matrix.platform == 'msvc' }}
|
||||
run: |
|
||||
cat '${{github.workspace}}/out/build/${{matrix.preset}}/_CPack_Packages/win32/NSIS/project.nsi'
|
||||
cat '${{github.workspace}}/out/build/${{matrix.preset}}/_CPack_Packages/win32/NSIS/NSISOutput.log'
|
||||
@@ -236,7 +203,7 @@ jobs:
|
||||
${{github.workspace}}/**/${{ env.VCMI_PACKAGE_FILE_NAME }}.${{ matrix.extension }}
|
||||
|
||||
- name: Upload build
|
||||
if: ${{ matrix.pack == 1 && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/features/')) && matrix.platform != 'msvc' }}
|
||||
if: ${{ matrix.pack == 1 && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/features/')) && matrix.platform == 'msvc' }}
|
||||
run: |
|
||||
cd '${{github.workspace}}/out/build/${{matrix.preset}}'
|
||||
source '${{github.workspace}}/CI/upload_package.sh'
|
||||
@@ -254,7 +221,7 @@ jobs:
|
||||
|
||||
- name: Trigger Android
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
if: ${{ (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/master') && matrix.platform == 'mxe' }}
|
||||
if: ${{ (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/master') && matrix.platform == 'msvc' }}
|
||||
with:
|
||||
token: ${{ secrets.VCMI_ANDROID_ACCESS_TOKEN }}
|
||||
repository: vcmi/vcmi-android
|
||||
|
@@ -11,7 +11,6 @@
|
||||
#include "CCallback.h"
|
||||
|
||||
#include "lib/CCreatureHandler.h"
|
||||
#include "client/CGameInfo.h"
|
||||
#include "lib/CGameState.h"
|
||||
#include "client/CPlayerInterface.h"
|
||||
#include "client/Client.h"
|
||||
@@ -21,7 +20,6 @@
|
||||
#include "lib/CGeneralTextHandler.h"
|
||||
#include "lib/CHeroHandler.h"
|
||||
#include "lib/NetPacks.h"
|
||||
#include "client/mapHandler.h"
|
||||
#include "lib/CArtHandler.h"
|
||||
#include "lib/GameConstants.h"
|
||||
#include "lib/CPlayerState.h"
|
||||
|
@@ -1,53 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# steps to upgrade MXE dependencies:
|
||||
# 1) Use Debian/Ubuntu system or install one (virtual machines will work too)
|
||||
# 2) update following script to include any new dependencies
|
||||
# You can also run it to upgrade existing ones, but don't expect much
|
||||
# MXE repository only provides ancient versions for the sake of "stability"
|
||||
# https://github.com/vcmi/vcmi-deps-mxe/blob/master/mirror-mxe.sh
|
||||
# 3) make release in vcmi-deps-mxe repository using resulting tar archive
|
||||
# 4) update paths to tar archive in this script
|
||||
|
||||
# Install nsis for installer creation
|
||||
sudo add-apt-repository 'deb http://security.ubuntu.com/ubuntu bionic-security main'
|
||||
sudo apt-get install -qq nsis ninja-build libssl1.0.0
|
||||
|
||||
# MXE repository was too slow for Travis far too often
|
||||
wget -nv https://github.com/vcmi/vcmi-deps-mxe/releases/download/2021-02-20/mxe-i686-w64-mingw32.shared-2021-01-22.tar
|
||||
tar -xvf mxe-i686-w64-mingw32.shared-2021-01-22.tar
|
||||
sudo dpkg -i mxe-*.deb
|
||||
sudo apt-get install -f --yes
|
||||
|
||||
if false; then
|
||||
# Add MXE repository and key
|
||||
echo "deb http://pkg.mxe.cc/repos/apt/debian wheezy main" \
|
||||
| sudo tee /etc/apt/sources.list.d/mxeapt.list
|
||||
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D43A795B73B16ABE9643FE1AFD8FFF16DB45C6AB
|
||||
|
||||
# Install needed packages
|
||||
sudo apt-get update -qq
|
||||
|
||||
sudo apt-get install -q --yes \
|
||||
mxe-$MXE_TARGET-gcc \
|
||||
mxe-$MXE_TARGET-boost \
|
||||
mxe-$MXE_TARGET-zlib \
|
||||
mxe-$MXE_TARGET-sdl2 \
|
||||
mxe-$MXE_TARGET-sdl2-gfx \
|
||||
mxe-$MXE_TARGET-sdl2-image \
|
||||
mxe-$MXE_TARGET-sdl2-mixer \
|
||||
mxe-$MXE_TARGET-sdl2-ttf \
|
||||
mxe-$MXE_TARGET-ffmpeg \
|
||||
mxe-$MXE_TARGET-qt \
|
||||
mxe-$MXE_TARGET-qtbase \
|
||||
mxe-$MXE_TARGET-intel-tbb \
|
||||
mxe-i686-w64-mingw32.static-luajit
|
||||
|
||||
fi # Disable
|
||||
|
||||
# alias for CMake
|
||||
|
||||
CMAKE_LOCATION=$(which cmake)
|
||||
sudo mv $CMAKE_LOCATION $CMAKE_LOCATION.orig
|
||||
sudo ln -s /usr/lib/mxe/usr/bin/$MXE_TARGET-cmake $CMAKE_LOCATION
|
@@ -1,7 +1,7 @@
|
||||
# Minimum required version greatly affect CMake behavior
|
||||
# So cmake_minimum_required must be called before the project()
|
||||
# 3.10.0 is used since it's minimal in MXE dependencies for now
|
||||
cmake_minimum_required(VERSION 3.10.0)
|
||||
# 3.16.0 is used since it's used by our currently oldest suppored system: Ubuntu-20.04
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
|
||||
project(VCMI)
|
||||
# TODO
|
||||
@@ -10,9 +10,6 @@ project(VCMI)
|
||||
# Cmake put them after all install code of main CMakelists in cmake_install.cmake
|
||||
# Currently I just added extra add_subdirectory and CMakeLists.txt in osx directory to bypass that.
|
||||
#
|
||||
# MXE:
|
||||
# - Try to implement MXE support into BundleUtilities so we can deploy deps automatically
|
||||
#
|
||||
# Vckpg:
|
||||
# - Improve install code once there is better way to deploy DLLs and Qt plugins
|
||||
#
|
||||
@@ -57,9 +54,8 @@ if(APPLE_IOS)
|
||||
else()
|
||||
option(ENABLE_TEST "Enable compilation of unit tests" OFF)
|
||||
endif()
|
||||
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.16.0")
|
||||
option(ENABLE_PCH "Enable compilation using precompiled headers" ON)
|
||||
endif(NOT ${CMAKE_VERSION} VERSION_LESS "3.16.0")
|
||||
|
||||
option(ENABLE_PCH "Enable compilation using precompiled headers" ON)
|
||||
option(ENABLE_GITVERSION "Enable Version.cpp with Git commit hash" ON)
|
||||
option(ENABLE_DEBUG_CONSOLE "Enable debug console for Windows builds" ON)
|
||||
option(ENABLE_STRICT_COMPILATION "Treat all compiler warnings as errors" OFF)
|
||||
@@ -90,11 +86,6 @@ if(APPLE_IOS AND COPY_CONFIG_ON_BUILD)
|
||||
set(COPY_CONFIG_ON_BUILD OFF)
|
||||
endif()
|
||||
|
||||
# No QT Linguist on MXE
|
||||
if((MINGW) AND (${CMAKE_CROSSCOMPILING}) AND (NOT USING_CONAN))
|
||||
set(ENABLE_TRANSLATIONS OFF)
|
||||
endif()
|
||||
|
||||
############################################
|
||||
# Miscellaneous options #
|
||||
############################################
|
||||
@@ -138,10 +129,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_
|
||||
set(ENABLE_PCH OFF) # broken
|
||||
endif()
|
||||
|
||||
if( ${CMAKE_VERSION} VERSION_LESS "3.16.0")
|
||||
set(ENABLE_PCH OFF) #not supported
|
||||
endif()
|
||||
|
||||
if(ENABLE_PCH)
|
||||
macro(enable_pch name)
|
||||
target_precompile_headers(${name} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:<StdInc.h$<ANGLE-R>>)
|
||||
@@ -296,13 +283,6 @@ if(CMAKE_COMPILER_IS_GNUCXX OR NOT WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare") # low chance of any significant issues
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-varargs") # emitted in fuzzylite headers, disabled
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pragmas") # emitted only by ancient gcc 5.5 in MXE build, remove after upgrade
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas") # emitted only by ancient gcc 5.5 in MXE build, remove after upgrade
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable") # emitted only by ancient gcc 5.5 in MXE build, remove after upgrade
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-maybe-uninitialized") # emitted only by ancient gcc 5.5 in MXE build, remove after upgrade
|
||||
endif()
|
||||
|
||||
if(ENABLE_STRICT_COMPILATION)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=array-bounds") # false positives in boost::multiarray during release build, keep as warning-only
|
||||
@@ -407,14 +387,7 @@ endif()
|
||||
|
||||
if(ENABLE_LUA)
|
||||
find_package(luajit)
|
||||
# MXE paths hardcoded for current dependencies pack - tried and could not make it work another way
|
||||
if((MINGW) AND (${CMAKE_CROSSCOMPILING}) AND (DEFINED MSYS) AND (NOT TARGET luajit::luajit))
|
||||
add_library(luajit::luajit STATIC IMPORTED)
|
||||
set_target_properties(luajit::luajit PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "/usr/lib/mxe/usr/i686-w64-mingw32.static/include/luajit-2.0")
|
||||
set_target_properties(luajit::luajit PROPERTIES
|
||||
IMPORTED_LOCATION "/usr/lib/mxe/usr/i686-w64-mingw32.static/lib/libluajit-5.1.a")
|
||||
endif()
|
||||
|
||||
if(TARGET luajit::luajit)
|
||||
message(STATUS "Using LuaJIT provided by system")
|
||||
else()
|
||||
@@ -580,9 +553,7 @@ if(WIN32)
|
||||
"${CMAKE_FIND_ROOT_PATH}/bin/*.dll")
|
||||
endif()
|
||||
|
||||
if((${CMAKE_CROSSCOMPILING}) AND (DEFINED MSYS))
|
||||
message(STATUS "Detected MXE build")
|
||||
elseif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
# Copy debug versions of libraries if build type is debug
|
||||
set(debug_postfix d)
|
||||
endif()
|
||||
@@ -685,7 +656,7 @@ if(WIN32)
|
||||
set(CPACK_NSIS_URL_INFO_ABOUT "http://vcmi.eu/")
|
||||
set(CPACK_NSIS_CONTACT @CPACK_PACKAGE_CONTACT@)
|
||||
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||
# Use BundleUtilities to fix build when Vcpkg is used and disable it for MXE
|
||||
# Use BundleUtilities to fix build when Vcpkg is used and disable it for mingw
|
||||
if(NOT (${CMAKE_CROSSCOMPILING}))
|
||||
add_subdirectory(win)
|
||||
endif()
|
||||
|
@@ -30,7 +30,7 @@ Platform support is constantly tested by continuous integration and CMake config
|
||||
|
||||
* (optional) All platforms: [using Conan package manager to obtain prebuilt dependencies](docs/conan.md)
|
||||
* [On Linux](https://wiki.vcmi.eu/How_to_build_VCMI_(Linux))
|
||||
* [On Linux for Windows with MXE](https://wiki.vcmi.eu/How_to_build_VCMI_(Linux/Cmake/MXE))
|
||||
* [On Linux for Windows with Conan and mingw](https://wiki.vcmi.eu/How_to_build_VCMI_(Linux/Cmake/Conan))
|
||||
* [On macOS](https://wiki.vcmi.eu/How_to_build_VCMI_(macOS))
|
||||
* [On Windows using MSVC and Vcpkg](https://wiki.vcmi.eu/How_to_build_VCMI_(Windows/Vcpkg))
|
||||
* [iOS on macOS](https://wiki.vcmi.eu/How_to_build_VCMI_(iOS))
|
||||
|
@@ -11,48 +11,43 @@
|
||||
//
|
||||
#include "StdInc.h"
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "mapHandler.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/FileStream.h"
|
||||
#include "mainmenu/CMainMenu.h"
|
||||
#include "lobby/CSelectionBase.h"
|
||||
#include "windows/CCastleInterface.h"
|
||||
#include "../lib/CConsoleHandler.h"
|
||||
#include "gui/CursorHandler.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../CCallback.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "windows/CAdvmapInterface.h"
|
||||
#include "../lib/CBuildingHandler.h"
|
||||
#include "CVideoHandler.h"
|
||||
#include "CMusicHandler.h"
|
||||
#include "Client.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "CServerHandler.h"
|
||||
#include "gui/NotificationHandler.h"
|
||||
#include "ClientCommandManager.h"
|
||||
#include "windows/CMessage.h"
|
||||
#include "renderSDL/SDL_Extensions.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/FileStream.h"
|
||||
#include "../lib/CConsoleHandler.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CBuildingHandler.h"
|
||||
#include "../CCallback.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/spells/CSpellHandler.h"
|
||||
#include "CMusicHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "Graphics.h"
|
||||
#include "Client.h"
|
||||
#include "../lib/serializer/BinaryDeserializer.h"
|
||||
#include "../lib/serializer/BinarySerializer.h"
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "../lib/NetPacks.h"
|
||||
#include "CMessage.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "../lib/logging/CBasicLogConfigurator.h"
|
||||
#include "../lib/CPlayerState.h"
|
||||
#include "gui/CAnimation.h"
|
||||
#include "../lib/serializer/Connection.h"
|
||||
#include "CServerHandler.h"
|
||||
#include "gui/NotificationHandler.h"
|
||||
#include "ClientCommandManager.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "mainmenu/CPrologEpilogVideo.h"
|
||||
#include <vstd/StringUtils.h>
|
||||
@@ -713,7 +708,7 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
|
||||
if(nullptr == mainWindow)
|
||||
{
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
auto createWindow = [displayIndex](Uint32 extraFlags) -> bool {
|
||||
auto createWindow = [displayIndex](uint32_t extraFlags) -> bool {
|
||||
mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), 0, 0, SDL_WINDOW_FULLSCREEN | extraFlags);
|
||||
return mainWindow != nullptr;
|
||||
};
|
||||
@@ -723,7 +718,7 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
|
||||
SDL_SetHint(SDL_HINT_RETURN_KEY_HIDES_IME, "1");
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
|
||||
|
||||
Uint32 windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
uint32_t windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
if(!createWindow(windowFlags | SDL_WINDOW_METAL))
|
||||
{
|
||||
logGlobal->warn("Metal unavailable, using OpenGLES");
|
||||
|
@@ -1,180 +1,221 @@
|
||||
set(client_SRCS
|
||||
StdInc.cpp
|
||||
../CCallback.cpp
|
||||
StdInc.cpp
|
||||
../CCallback.cpp
|
||||
|
||||
battle/BattleActionsController.cpp
|
||||
battle/BattleAnimationClasses.cpp
|
||||
battle/BattleEffectsController.cpp
|
||||
battle/BattleFieldController.cpp
|
||||
battle/BattleInterfaceClasses.cpp
|
||||
battle/BattleInterface.cpp
|
||||
battle/BattleObstacleController.cpp
|
||||
battle/BattleProjectileController.cpp
|
||||
battle/BattleRenderer.cpp
|
||||
battle/BattleSiegeController.cpp
|
||||
battle/BattleStacksController.cpp
|
||||
battle/BattleWindow.cpp
|
||||
battle/CreatureAnimation.cpp
|
||||
adventureMap/CAdvMapPanel.cpp
|
||||
adventureMap/CAdvMapInt.cpp
|
||||
adventureMap/CAdventureOptions.cpp
|
||||
adventureMap/CInGameConsole.cpp
|
||||
adventureMap/CInfoBar.cpp
|
||||
adventureMap/CList.cpp
|
||||
adventureMap/CMinimap.cpp
|
||||
adventureMap/CResDataBar.cpp
|
||||
adventureMap/CTerrainRect.cpp
|
||||
adventureMap/mapHandler.cpp
|
||||
|
||||
gui/CAnimation.cpp
|
||||
gui/Canvas.cpp
|
||||
gui/CursorHandler.cpp
|
||||
gui/CGuiHandler.cpp
|
||||
gui/CIntObject.cpp
|
||||
gui/ColorFilter.cpp
|
||||
gui/Fonts.cpp
|
||||
gui/SDL_Extensions.cpp
|
||||
gui/NotificationHandler.cpp
|
||||
gui/InterfaceObjectConfigurable.cpp
|
||||
battle/BattleActionsController.cpp
|
||||
battle/BattleAnimationClasses.cpp
|
||||
battle/BattleEffectsController.cpp
|
||||
battle/BattleFieldController.cpp
|
||||
battle/BattleInterface.cpp
|
||||
battle/BattleInterfaceClasses.cpp
|
||||
battle/BattleObstacleController.cpp
|
||||
battle/BattleProjectileController.cpp
|
||||
battle/BattleRenderer.cpp
|
||||
battle/BattleSiegeController.cpp
|
||||
battle/BattleStacksController.cpp
|
||||
battle/BattleWindow.cpp
|
||||
battle/CreatureAnimation.cpp
|
||||
|
||||
widgets/AdventureMapClasses.cpp
|
||||
widgets/Buttons.cpp
|
||||
widgets/CArtifactHolder.cpp
|
||||
widgets/CComponent.cpp
|
||||
widgets/CGarrisonInt.cpp
|
||||
widgets/Images.cpp
|
||||
widgets/MiscWidgets.cpp
|
||||
widgets/ObjectLists.cpp
|
||||
widgets/TextControls.cpp
|
||||
gui/CGuiHandler.cpp
|
||||
gui/CIntObject.cpp
|
||||
gui/CursorHandler.cpp
|
||||
gui/InterfaceObjectConfigurable.cpp
|
||||
gui/NotificationHandler.cpp
|
||||
|
||||
windows/CAdvmapInterface.cpp
|
||||
windows/CCastleInterface.cpp
|
||||
windows/CCreatureWindow.cpp
|
||||
windows/CreaturePurchaseCard.cpp
|
||||
windows/CHeroWindow.cpp
|
||||
windows/CKingdomInterface.cpp
|
||||
windows/CQuestLog.cpp
|
||||
windows/CSpellWindow.cpp
|
||||
windows/CTradeWindow.cpp
|
||||
windows/CWindowObject.cpp
|
||||
windows/GUIClasses.cpp
|
||||
windows/InfoWindows.cpp
|
||||
windows/QuickRecruitmentWindow.cpp
|
||||
windows/SystemOptionsWindow.cpp
|
||||
windows/VcmiSettingsWindow.cpp
|
||||
windows/SettingsMainContainer.cpp
|
||||
lobby/CBonusSelection.cpp
|
||||
lobby/CCampaignInfoScreen.cpp
|
||||
lobby/CLobbyScreen.cpp
|
||||
lobby/CSavingScreen.cpp
|
||||
lobby/CScenarioInfoScreen.cpp
|
||||
lobby/CSelectionBase.cpp
|
||||
lobby/OptionsTab.cpp
|
||||
lobby/RandomMapTab.cpp
|
||||
lobby/SelectionTab.cpp
|
||||
|
||||
mainmenu/CMainMenu.cpp
|
||||
mainmenu/CCampaignScreen.cpp
|
||||
mainmenu/CreditsScreen.cpp
|
||||
mainmenu/CPrologEpilogVideo.cpp
|
||||
mainmenu/CCampaignScreen.cpp
|
||||
mainmenu/CMainMenu.cpp
|
||||
mainmenu/CPrologEpilogVideo.cpp
|
||||
mainmenu/CreditsScreen.cpp
|
||||
|
||||
lobby/CBonusSelection.cpp
|
||||
lobby/CSelectionBase.cpp
|
||||
lobby/CLobbyScreen.cpp
|
||||
lobby/CSavingScreen.cpp
|
||||
lobby/CScenarioInfoScreen.cpp
|
||||
lobby/CCampaignInfoScreen.cpp
|
||||
lobby/OptionsTab.cpp
|
||||
lobby/RandomMapTab.cpp
|
||||
lobby/SelectionTab.cpp
|
||||
render/CAnimation.cpp
|
||||
render/CBitmapHandler.cpp
|
||||
render/CDefFile.cpp
|
||||
render/CFadeAnimation.cpp
|
||||
render/Canvas.cpp
|
||||
render/ColorFilter.cpp
|
||||
render/Graphics.cpp
|
||||
render/IFont.cpp
|
||||
|
||||
CBitmapHandler.cpp
|
||||
CreatureCostBox.cpp
|
||||
CGameInfo.cpp
|
||||
Client.cpp
|
||||
CMessage.cpp
|
||||
CMT.cpp
|
||||
CMusicHandler.cpp
|
||||
CPlayerInterface.cpp
|
||||
CVideoHandler.cpp
|
||||
CServerHandler.cpp
|
||||
Graphics.cpp
|
||||
mapHandler.cpp
|
||||
NetPacksClient.cpp
|
||||
NetPacksLobbyClient.cpp
|
||||
SDLRWwrapper.cpp
|
||||
ClientCommandManager.cpp
|
||||
renderSDL/CBitmapFont.cpp
|
||||
renderSDL/CBitmapHanFont.cpp
|
||||
renderSDL/CTrueTypeFont.cpp
|
||||
renderSDL/CursorHardware.cpp
|
||||
renderSDL/CursorSoftware.cpp
|
||||
renderSDL/SDLImage.cpp
|
||||
renderSDL/SDLImageLoader.cpp
|
||||
renderSDL/SDLRWwrapper.cpp
|
||||
renderSDL/SDL_Extensions.cpp
|
||||
|
||||
widgets/Buttons.cpp
|
||||
widgets/CArtifactHolder.cpp
|
||||
widgets/CComponent.cpp
|
||||
widgets/CGarrisonInt.cpp
|
||||
widgets/CreatureCostBox.cpp
|
||||
widgets/Images.cpp
|
||||
widgets/MiscWidgets.cpp
|
||||
widgets/ObjectLists.cpp
|
||||
widgets/TextControls.cpp
|
||||
|
||||
windows/CCastleInterface.cpp
|
||||
windows/CCreatureWindow.cpp
|
||||
windows/CHeroWindow.cpp
|
||||
windows/CKingdomInterface.cpp
|
||||
windows/CMessage.cpp
|
||||
windows/CQuestLog.cpp
|
||||
windows/CSpellWindow.cpp
|
||||
windows/CTradeWindow.cpp
|
||||
windows/CWindowObject.cpp
|
||||
windows/CreaturePurchaseCard.cpp
|
||||
windows/GUIClasses.cpp
|
||||
windows/InfoWindows.cpp
|
||||
windows/QuickRecruitmentWindow.cpp
|
||||
windows/SystemOptionsWindow.cpp
|
||||
windows/VcmiSettingsWindow.cpp
|
||||
windows/SettingsMainContainer.cpp
|
||||
|
||||
CGameInfo.cpp
|
||||
CMT.cpp
|
||||
CMusicHandler.cpp
|
||||
CPlayerInterface.cpp
|
||||
CServerHandler.cpp
|
||||
CVideoHandler.cpp
|
||||
Client.cpp
|
||||
ClientCommandManager.cpp
|
||||
NetPacksClient.cpp
|
||||
NetPacksLobbyClient.cpp
|
||||
)
|
||||
|
||||
set(client_HEADERS
|
||||
StdInc.h
|
||||
StdInc.h
|
||||
|
||||
battle/BattleActionsController.h
|
||||
battle/BattleAnimationClasses.h
|
||||
battle/BattleEffectsController.h
|
||||
battle/BattleFieldController.h
|
||||
battle/BattleInterfaceClasses.h
|
||||
battle/BattleInterface.h
|
||||
battle/BattleObstacleController.h
|
||||
battle/BattleProjectileController.h
|
||||
battle/BattleRenderer.h
|
||||
battle/BattleSiegeController.h
|
||||
battle/BattleStacksController.h
|
||||
battle/BattleWindow.h
|
||||
battle/CreatureAnimation.h
|
||||
battle/BattleConstants.h
|
||||
adventureMap/CAdvMapPanel.h
|
||||
adventureMap/CAdvMapInt.h
|
||||
adventureMap/CAdventureOptions.h
|
||||
adventureMap/CInGameConsole.h
|
||||
adventureMap/CInfoBar.h
|
||||
adventureMap/CList.h
|
||||
adventureMap/CMinimap.h
|
||||
adventureMap/CResDataBar.h
|
||||
adventureMap/CTerrainRect.h
|
||||
adventureMap/mapHandler.h
|
||||
|
||||
gui/CAnimation.h
|
||||
gui/Canvas.h
|
||||
gui/CursorHandler.h
|
||||
gui/CGuiHandler.h
|
||||
gui/ColorFilter.h
|
||||
gui/CIntObject.h
|
||||
gui/Fonts.h
|
||||
gui/TextAlignment.h
|
||||
gui/SDL_Compat.h
|
||||
gui/SDL_Extensions.h
|
||||
gui/SDL_Pixels.h
|
||||
gui/NotificationHandler.h
|
||||
gui/InterfaceObjectConfigurable.h
|
||||
battle/BattleActionsController.h
|
||||
battle/BattleAnimationClasses.h
|
||||
battle/BattleConstants.h
|
||||
battle/BattleEffectsController.h
|
||||
battle/BattleFieldController.h
|
||||
battle/BattleInterface.h
|
||||
battle/BattleInterfaceClasses.h
|
||||
battle/BattleObstacleController.h
|
||||
battle/BattleProjectileController.h
|
||||
battle/BattleRenderer.h
|
||||
battle/BattleSiegeController.h
|
||||
battle/BattleStacksController.h
|
||||
battle/BattleWindow.h
|
||||
battle/CreatureAnimation.h
|
||||
|
||||
widgets/AdventureMapClasses.h
|
||||
widgets/Buttons.h
|
||||
widgets/CArtifactHolder.h
|
||||
widgets/CComponent.h
|
||||
widgets/CGarrisonInt.h
|
||||
widgets/Images.h
|
||||
widgets/MiscWidgets.h
|
||||
widgets/ObjectLists.h
|
||||
widgets/TextControls.h
|
||||
windows/CAdvmapInterface.h
|
||||
windows/CCastleInterface.h
|
||||
windows/CCreatureWindow.h
|
||||
windows/CreaturePurchaseCard.h
|
||||
windows/CHeroWindow.h
|
||||
windows/CKingdomInterface.h
|
||||
windows/CQuestLog.h
|
||||
windows/CSpellWindow.h
|
||||
windows/CTradeWindow.h
|
||||
windows/CWindowObject.h
|
||||
windows/GUIClasses.h
|
||||
windows/InfoWindows.h
|
||||
windows/QuickRecruitmentWindow.h
|
||||
windows/SystemOptionsWindow.h
|
||||
windows/VcmiSettingsWindow.h
|
||||
windows/SettingsMainContainer.h
|
||||
gui/CGuiHandler.h
|
||||
gui/CIntObject.h
|
||||
gui/CursorHandler.h
|
||||
gui/InterfaceObjectConfigurable.h
|
||||
gui/NotificationHandler.h
|
||||
gui/TextAlignment.h
|
||||
|
||||
mainmenu/CMainMenu.h
|
||||
mainmenu/CCampaignScreen.h
|
||||
mainmenu/CreditsScreen.h
|
||||
mainmenu/CPrologEpilogVideo.h
|
||||
lobby/CBonusSelection.h
|
||||
lobby/CCampaignInfoScreen.h
|
||||
lobby/CLobbyScreen.h
|
||||
lobby/CSavingScreen.h
|
||||
lobby/CScenarioInfoScreen.h
|
||||
lobby/CSelectionBase.h
|
||||
lobby/OptionsTab.h
|
||||
lobby/RandomMapTab.h
|
||||
lobby/SelectionTab.h
|
||||
|
||||
lobby/CBonusSelection.h
|
||||
lobby/CSelectionBase.h
|
||||
lobby/CLobbyScreen.h
|
||||
lobby/CSavingScreen.h
|
||||
lobby/CScenarioInfoScreen.h
|
||||
lobby/CCampaignInfoScreen.h
|
||||
lobby/OptionsTab.h
|
||||
lobby/RandomMapTab.h
|
||||
lobby/SelectionTab.h
|
||||
mainmenu/CCampaignScreen.h
|
||||
mainmenu/CMainMenu.h
|
||||
mainmenu/CPrologEpilogVideo.h
|
||||
mainmenu/CreditsScreen.h
|
||||
|
||||
CBitmapHandler.h
|
||||
CreatureCostBox.h
|
||||
CGameInfo.h
|
||||
Client.h
|
||||
CMessage.h
|
||||
CMT.h
|
||||
CMusicHandler.h
|
||||
CPlayerInterface.h
|
||||
CVideoHandler.h
|
||||
CServerHandler.h
|
||||
Graphics.h
|
||||
mapHandler.h
|
||||
resource.h
|
||||
SDLRWwrapper.h
|
||||
ClientCommandManager.h
|
||||
render/CAnimation.h
|
||||
render/CBitmapHandler.h
|
||||
render/CDefFile.h
|
||||
render/CFadeAnimation.h
|
||||
render/Canvas.h
|
||||
render/ColorFilter.h
|
||||
render/Graphics.h
|
||||
render/ICursor.h
|
||||
render/IFont.h
|
||||
render/IImage.h
|
||||
render/IImageLoader.h
|
||||
|
||||
renderSDL/CBitmapFont.h
|
||||
renderSDL/CBitmapHanFont.h
|
||||
renderSDL/CTrueTypeFont.h
|
||||
renderSDL/CursorHardware.h
|
||||
renderSDL/CursorSoftware.h
|
||||
renderSDL/SDLImage.h
|
||||
renderSDL/SDLImageLoader.h
|
||||
renderSDL/SDLRWwrapper.h
|
||||
renderSDL/SDL_Extensions.h
|
||||
renderSDL/SDL_PixelAccess.h
|
||||
|
||||
widgets/Buttons.h
|
||||
widgets/CArtifactHolder.h
|
||||
widgets/CComponent.h
|
||||
widgets/CGarrisonInt.h
|
||||
widgets/CreatureCostBox.h
|
||||
widgets/Images.h
|
||||
widgets/MiscWidgets.h
|
||||
widgets/ObjectLists.h
|
||||
widgets/TextControls.h
|
||||
|
||||
windows/CCastleInterface.h
|
||||
windows/CCreatureWindow.h
|
||||
windows/CHeroWindow.h
|
||||
windows/CKingdomInterface.h
|
||||
windows/CMessage.h
|
||||
windows/CQuestLog.h
|
||||
windows/CSpellWindow.h
|
||||
windows/CTradeWindow.h
|
||||
windows/CWindowObject.h
|
||||
windows/CreaturePurchaseCard.h
|
||||
windows/GUIClasses.h
|
||||
windows/InfoWindows.h
|
||||
windows/QuickRecruitmentWindow.h
|
||||
windows/SystemOptionsWindow.h
|
||||
windows/VcmiSettingsWindow.h
|
||||
windows/SettingsMainContainer.h
|
||||
|
||||
CGameInfo.h
|
||||
CMT.h
|
||||
CMusicHandler.h
|
||||
CPlayerInterface.h
|
||||
CServerHandler.h
|
||||
CVideoHandler.h
|
||||
Client.h
|
||||
ClientCommandManager.h
|
||||
resource.h
|
||||
)
|
||||
|
||||
if(APPLE_IOS)
|
||||
|
@@ -13,7 +13,8 @@
|
||||
|
||||
#include "CMusicHandler.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "SDLRWwrapper.h"
|
||||
#include "renderSDL/SDLRWwrapper.h"
|
||||
|
||||
#include "../lib/JsonNode.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
@@ -22,6 +23,7 @@
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "../lib/TerrainHandler.h"
|
||||
|
||||
|
||||
#define VCMI_SOUND_NAME(x)
|
||||
#define VCMI_SOUND_FILE(y) #y,
|
||||
|
||||
|
@@ -11,7 +11,8 @@
|
||||
|
||||
#include <vcmi/Artifact.h>
|
||||
|
||||
#include "windows/CAdvmapInterface.h"
|
||||
#include "adventureMap/CAdvMapInt.h"
|
||||
#include "adventureMap/mapHandler.h"
|
||||
#include "battle/BattleInterface.h"
|
||||
#include "battle/BattleEffectsController.h"
|
||||
#include "battle/BattleFieldController.h"
|
||||
@@ -25,15 +26,15 @@
|
||||
#include "windows/CHeroWindow.h"
|
||||
#include "windows/CCreatureWindow.h"
|
||||
#include "windows/CQuestLog.h"
|
||||
#include "CMessage.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "widgets/CComponent.h"
|
||||
#include "widgets/Buttons.h"
|
||||
#include "windows/CTradeWindow.h"
|
||||
#include "windows/CSpellWindow.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "Graphics.h"
|
||||
#include "windows/GUIClasses.h"
|
||||
#include "render/CAnimation.h"
|
||||
#include "render/IImage.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
@@ -51,24 +52,23 @@
|
||||
#include "../lib/NetPacks.h"//todo: remove
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "mapHandler.h"
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "../lib/StartInfo.h"
|
||||
#include "../lib/CPlayerState.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "gui/CAnimation.h"
|
||||
#include "windows/InfoWindows.h"
|
||||
#include "../lib/UnlockGuard.h"
|
||||
#include "../lib/CPathfinder.h"
|
||||
#include "../lib/RoadHandler.h"
|
||||
#include "../lib/TerrainHandler.h"
|
||||
#include <SDL_timer.h>
|
||||
#include "CServerHandler.h"
|
||||
// FIXME: only needed for CGameState::mutex
|
||||
#include "../lib/CGameState.h"
|
||||
#include "gui/NotificationHandler.h"
|
||||
#include "adventureMap/CInGameConsole.h"
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
// The macro below is used to mark functions that are called by client when game state changes.
|
||||
// They all assume that CPlayerInterface::pim mutex is locked.
|
||||
@@ -342,7 +342,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
|
||||
auto unlockPim = vstd::makeUnlockGuard(*pim);
|
||||
while(frameNumber == GH.mainFPSmng->getFrameNumber())
|
||||
SDL_Delay(5);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(5));
|
||||
};
|
||||
|
||||
//first initializing done
|
||||
@@ -1514,7 +1514,7 @@ void CPlayerInterface::centerView (int3 pos, int focusTime)
|
||||
{
|
||||
auto unlockPim = vstd::makeUnlockGuard(*pim);
|
||||
IgnoreEvents ignore(*this);
|
||||
SDL_Delay(focusTime);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(focusTime));
|
||||
}
|
||||
}
|
||||
CCS->curh->show();
|
||||
@@ -2276,7 +2276,7 @@ void CPlayerInterface::waitForAllDialogs(bool unlockPim)
|
||||
while(!dialogs.empty())
|
||||
{
|
||||
auto unlock = vstd::makeUnlockGuardIf(*pim, unlockPim);
|
||||
SDL_Delay(5);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(5));
|
||||
}
|
||||
waitWhileDialog(unlockPim);
|
||||
}
|
||||
|
@@ -60,6 +60,8 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
template<typename T> class CApplyOnLobby;
|
||||
|
||||
const std::string CServerHandler::localhostAddress{"127.0.0.1"};
|
||||
|
@@ -11,13 +11,24 @@
|
||||
#include "CVideoHandler.h"
|
||||
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "renderSDL/SDL_Extensions.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
|
||||
#include <SDL_render.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
extern CGuiHandler GH; //global gui handler
|
||||
|
||||
#ifndef DISABLE_VIDEO
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
//reads events and returns true on key down
|
||||
static bool keyDown()
|
||||
{
|
||||
@@ -56,22 +67,20 @@ static si64 lodSeek(void * opaque, si64 pos, int whence)
|
||||
}
|
||||
|
||||
CVideoPlayer::CVideoPlayer()
|
||||
{
|
||||
stream = -1;
|
||||
format = nullptr;
|
||||
codecContext = nullptr;
|
||||
codec = nullptr;
|
||||
frame = nullptr;
|
||||
sws = nullptr;
|
||||
context = nullptr;
|
||||
texture = nullptr;
|
||||
dest = nullptr;
|
||||
destRect = CSDL_Ext::genRect(0,0,0,0);
|
||||
pos = CSDL_Ext::genRect(0,0,0,0);
|
||||
refreshWait = 0;
|
||||
refreshCount = 0;
|
||||
doLoop = false;
|
||||
}
|
||||
: stream(-1)
|
||||
, format (nullptr)
|
||||
, codecContext(nullptr)
|
||||
, codec(nullptr)
|
||||
, frame(nullptr)
|
||||
, sws(nullptr)
|
||||
, context(nullptr)
|
||||
, texture(nullptr)
|
||||
, dest(nullptr)
|
||||
, destRect(0,0,0,0)
|
||||
, pos(0,0,0,0)
|
||||
, frameTime(0)
|
||||
, doLoop(false)
|
||||
{}
|
||||
|
||||
bool CVideoPlayer::open(std::string fname, bool scale)
|
||||
{
|
||||
@@ -85,9 +94,8 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
close();
|
||||
|
||||
this->fname = fname;
|
||||
refreshWait = 3;
|
||||
refreshCount = -1;
|
||||
doLoop = loop;
|
||||
frameTime = 0;
|
||||
|
||||
ResourceID resource(std::string("Video/") + fname, EResType::VIDEO);
|
||||
|
||||
@@ -254,6 +262,7 @@ bool CVideoPlayer::nextFrame()
|
||||
if (doLoop && !gotError)
|
||||
{
|
||||
// Rewind
|
||||
frameTime = 0;
|
||||
if (av_seek_frame(format, stream, 0, AVSEEK_FLAG_BYTE) < 0)
|
||||
break;
|
||||
gotError = true;
|
||||
@@ -354,9 +363,11 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo
|
||||
if (sws == nullptr)
|
||||
return;
|
||||
|
||||
if (refreshCount <= 0)
|
||||
double frameEndTime = (frame->pts + frame->pkt_duration) * av_q2d(format->streams[stream]->time_base);
|
||||
frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.0;
|
||||
|
||||
if (frameTime >= frameEndTime )
|
||||
{
|
||||
refreshCount = refreshWait;
|
||||
if (nextFrame())
|
||||
show(x,y,dst,update);
|
||||
else
|
||||
@@ -374,8 +385,6 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo
|
||||
{
|
||||
redraw(x, y, dst, update);
|
||||
}
|
||||
|
||||
refreshCount --;
|
||||
}
|
||||
|
||||
void CVideoPlayer::close()
|
||||
|
@@ -56,39 +56,11 @@ public:
|
||||
|
||||
#include "../lib/filesystem/CInputStream.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
//compatibility for libav 9.18 in ubuntu 14.04, 52.66.100 is ffmpeg 2.2.3
|
||||
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 66, 100))
|
||||
inline AVFrame * av_frame_alloc()
|
||||
{
|
||||
return avcodec_alloc_frame();
|
||||
}
|
||||
|
||||
inline void av_frame_free(AVFrame ** frame)
|
||||
{
|
||||
av_free(*frame);
|
||||
*frame = nullptr;
|
||||
}
|
||||
#endif // VCMI_USE_OLD_AVUTIL
|
||||
|
||||
//fix for travis-ci
|
||||
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 0, 0))
|
||||
#define AVPixelFormat PixelFormat
|
||||
#define AV_PIX_FMT_NONE PIX_FMT_NONE
|
||||
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
#define AV_PIX_FMT_BGR565 PIX_FMT_BGR565
|
||||
#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24
|
||||
#define AV_PIX_FMT_BGR32 PIX_FMT_BGR32
|
||||
#define AV_PIX_FMT_RGB565 PIX_FMT_RGB565
|
||||
#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
|
||||
#define AV_PIX_FMT_RGB32 PIX_FMT_RGB32
|
||||
#endif
|
||||
struct AVFormatContext;
|
||||
struct AVCodecContext;
|
||||
struct AVCodec;
|
||||
struct AVFrame;
|
||||
struct AVIOContext;
|
||||
|
||||
class CVideoPlayer : public IMainVideoPlayer
|
||||
{
|
||||
@@ -108,8 +80,8 @@ class CVideoPlayer : public IMainVideoPlayer
|
||||
Rect destRect; // valid when dest is used
|
||||
Rect pos; // destination on screen
|
||||
|
||||
int refreshWait; // Wait several refresh before updating the image
|
||||
int refreshCount;
|
||||
/// video playback currnet progress, in seconds
|
||||
double frameTime;
|
||||
bool doLoop; // loop through video
|
||||
|
||||
bool playVideo(int x, int y, bool stopOnKey);
|
||||
@@ -141,4 +113,3 @@ public:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -13,6 +13,8 @@
|
||||
#include "CMusicHandler.h"
|
||||
#include "../lib/mapping/CCampaignHandler.h"
|
||||
#include "../CCallback.h"
|
||||
#include "adventureMap/CAdvMapInt.h"
|
||||
#include "adventureMap/mapHandler.h"
|
||||
#include "../lib/CConsoleHandler.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "../lib/CGameState.h"
|
||||
@@ -35,7 +37,6 @@
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/mapping/CMapService.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
#include "mapHandler.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "mainmenu/CMainMenu.h"
|
||||
#include "mainmenu/CCampaignScreen.h"
|
||||
@@ -46,7 +47,6 @@
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "CServerHandler.h"
|
||||
#include "../lib/ScriptHandler.h"
|
||||
#include "windows/CAdvmapInterface.h"
|
||||
#include <vcmi/events/EventBus.h>
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
|
@@ -12,6 +12,8 @@
|
||||
#include "ClientCommandManager.h"
|
||||
|
||||
#include "Client.h"
|
||||
#include "adventureMap/CInGameConsole.h"
|
||||
#include "adventureMap/CAdvMapInt.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "CServerHandler.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
@@ -20,19 +22,21 @@
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CPlayerState.h"
|
||||
#include "../lib/StringConstants.h"
|
||||
#include "gui/CAnimation.h"
|
||||
#include "windows/CAdvmapInterface.h"
|
||||
#include "windows/CCastleInterface.h"
|
||||
#include "render/CAnimation.h"
|
||||
#include "../CCallback.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "CMT.h"
|
||||
|
||||
#ifdef SCRIPTING_ENABLED
|
||||
#include "../lib/ScriptHandler.h"
|
||||
#endif
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
void ClientCommandManager::handleGoSolo()
|
||||
{
|
||||
Settings session = settings.write["session"];
|
||||
|
@@ -10,12 +10,21 @@
|
||||
#include "StdInc.h"
|
||||
#include "../lib/NetPacks.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/FileInfo.h"
|
||||
#include "../CCallback.h"
|
||||
#include "Client.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "windows/GUIClasses.h"
|
||||
#include "adventureMap/mapHandler.h"
|
||||
#include "adventureMap/CInGameConsole.h"
|
||||
#include "battle/BattleInterface.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "widgets/MiscWidgets.h"
|
||||
#include "CMT.h"
|
||||
#include "CServerHandler.h"
|
||||
|
||||
#include "../CCallback.h"
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/FileInfo.h"
|
||||
#include "../lib/serializer/Connection.h"
|
||||
#include "../lib/serializer/BinarySerializer.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
@@ -26,22 +35,13 @@
|
||||
#include "../lib/spells/CSpellHandler.h"
|
||||
#include "../lib/CSoundBase.h"
|
||||
#include "../lib/StartInfo.h"
|
||||
#include "mapHandler.h"
|
||||
#include "windows/GUIClasses.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "battle/BattleInterface.h"
|
||||
#include "../lib/mapping/CCampaignHandler.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CStack.h"
|
||||
#include "../lib/battle/BattleInfo.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/CPlayerState.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "widgets/MiscWidgets.h"
|
||||
#include "widgets/AdventureMapClasses.h"
|
||||
#include "CMT.h"
|
||||
#include "CServerHandler.h"
|
||||
|
||||
// TODO: as Tow suggested these template should all be part of CClient
|
||||
// This will require rework spectator interface properly though
|
||||
|
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "../Global.h"
|
||||
|
||||
#include "gui/SDL_Compat.h"
|
||||
|
||||
// This header should be treated as a pre compiled header file(PCH) in the compiler building settings.
|
||||
|
||||
// Here you can add specific libraries and macros which are specific to this project.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* CAdvmapInterface.cpp, part of VCMI engine
|
||||
* CAdvMapInt.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
@@ -8,56 +8,45 @@
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CAdvmapInterface.h"
|
||||
#include "CAdvMapInt.h"
|
||||
|
||||
#include "CCastleInterface.h"
|
||||
#include "CHeroWindow.h"
|
||||
#include "CKingdomInterface.h"
|
||||
#include "CSpellWindow.h"
|
||||
#include "CTradeWindow.h"
|
||||
#include "GUIClasses.h"
|
||||
#include "InfoWindows.h"
|
||||
#include "CAdvMapPanel.h"
|
||||
#include "CAdventureOptions.h"
|
||||
#include "CInGameConsole.h"
|
||||
#include "mapHandler.h"
|
||||
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../windows/CKingdomInterface.h"
|
||||
#include "../windows/CSpellWindow.h"
|
||||
#include "../windows/CTradeWindow.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../mainmenu/CMainMenu.h"
|
||||
#include "../lobby/CSelectionBase.h"
|
||||
#include "../lobby/CCampaignInfoScreen.h"
|
||||
#include "../lobby/CSavingScreen.h"
|
||||
#include "../lobby/CScenarioInfoScreen.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../mapHandler.h"
|
||||
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../windows/SettingsMainContainer.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/CSoundBase.h"
|
||||
#include "../../lib/spells/CSpellHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/JsonNode.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/CPathfinder.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
#include "../../lib/StartInfo.h"
|
||||
#include "../../lib/mapping/CMapInfo.h"
|
||||
#include "../../lib/TerrainHandler.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
#define ADVOPT (conf.go()->ac)
|
||||
using namespace CSDL_Ext;
|
||||
|
||||
std::shared_ptr<CAdvMapInt> adventureInt;
|
||||
|
||||
@@ -87,467 +76,6 @@ static void setScrollingCursor(ui8 direction)
|
||||
CCS->curh->set(Cursor::Map::SCROLL_SOUTH);
|
||||
}
|
||||
|
||||
CTerrainRect::CTerrainRect()
|
||||
: fadeSurface(nullptr),
|
||||
lastRedrawStatus(EMapAnimRedrawStatus::OK),
|
||||
fadeAnim(std::make_shared<CFadeAnimation>()),
|
||||
curHoveredTile(-1,-1,-1),
|
||||
currentPath(nullptr)
|
||||
{
|
||||
tilesw=(ADVOPT.advmapW+31)/32;
|
||||
tilesh=(ADVOPT.advmapH+31)/32;
|
||||
pos.x=ADVOPT.advmapX;
|
||||
pos.y=ADVOPT.advmapY;
|
||||
pos.w=ADVOPT.advmapW;
|
||||
pos.h=ADVOPT.advmapH;
|
||||
moveX = moveY = 0;
|
||||
addUsedEvents(LCLICK | RCLICK | MCLICK | HOVER | MOVE);
|
||||
}
|
||||
|
||||
CTerrainRect::~CTerrainRect()
|
||||
{
|
||||
if(fadeSurface)
|
||||
SDL_FreeSurface(fadeSurface);
|
||||
}
|
||||
|
||||
void CTerrainRect::deactivate()
|
||||
{
|
||||
CIntObject::deactivate();
|
||||
curHoveredTile = int3(-1,-1,-1); //we lost info about hovered tile when disabling
|
||||
}
|
||||
|
||||
void CTerrainRect::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
return;
|
||||
if(indeterminate(down))
|
||||
return;
|
||||
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
if(adventureInt->swipeEnabled)
|
||||
{
|
||||
if(handleSwipeStateChange((bool)down == true))
|
||||
{
|
||||
return; // if swipe is enabled, we don't process "down" events and wait for "up" (to make sure this wasn't a swiping gesture)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
if(down == false)
|
||||
return;
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
}
|
||||
#endif
|
||||
int3 mp = whichTileIsIt();
|
||||
if(mp.x < 0 || mp.y < 0 || mp.x >= LOCPLINT->cb->getMapSize().x || mp.y >= LOCPLINT->cb->getMapSize().y)
|
||||
return;
|
||||
|
||||
adventureInt->tileLClicked(mp);
|
||||
}
|
||||
|
||||
void CTerrainRect::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
if(adventureInt->swipeEnabled && isSwiping)
|
||||
return;
|
||||
#endif
|
||||
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
return;
|
||||
int3 mp = whichTileIsIt();
|
||||
|
||||
if(CGI->mh->map->isInTheMap(mp) && down)
|
||||
adventureInt->tileRClicked(mp);
|
||||
}
|
||||
|
||||
void CTerrainRect::clickMiddle(tribool down, bool previousState)
|
||||
{
|
||||
handleSwipeStateChange((bool)down == true);
|
||||
}
|
||||
|
||||
void CTerrainRect::mouseMoved(const SDL_MouseMotionEvent & sEvent)
|
||||
{
|
||||
handleHover(sEvent);
|
||||
|
||||
if(!adventureInt->swipeEnabled)
|
||||
return;
|
||||
|
||||
handleSwipeMove(sEvent);
|
||||
}
|
||||
|
||||
void CTerrainRect::handleSwipeMove(const SDL_MouseMotionEvent & sEvent)
|
||||
{
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
if(sEvent.state == 0 || GH.multifinger) // any "button" is enough on mobile
|
||||
#else
|
||||
if((sEvent.state & SDL_BUTTON_MMASK) == 0) // swipe only works with middle mouse on other platforms
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isSwiping)
|
||||
{
|
||||
// try to distinguish if this touch was meant to be a swipe or just fat-fingering press
|
||||
if(abs(sEvent.x - swipeInitialRealPos.x) > SwipeTouchSlop ||
|
||||
abs(sEvent.y - swipeInitialRealPos.y) > SwipeTouchSlop)
|
||||
{
|
||||
isSwiping = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(isSwiping)
|
||||
{
|
||||
adventureInt->swipeTargetPosition.x =
|
||||
swipeInitialMapPos.x + static_cast<si32>(swipeInitialRealPos.x - sEvent.x) / 32;
|
||||
adventureInt->swipeTargetPosition.y =
|
||||
swipeInitialMapPos.y + static_cast<si32>(swipeInitialRealPos.y - sEvent.y) / 32;
|
||||
adventureInt->swipeMovementRequested = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CTerrainRect::handleSwipeStateChange(bool btnPressed)
|
||||
{
|
||||
if(btnPressed)
|
||||
{
|
||||
swipeInitialRealPos = int3(GH.getCursorPosition().x, GH.getCursorPosition().y, 0);
|
||||
swipeInitialMapPos = int3(adventureInt->position);
|
||||
return true;
|
||||
}
|
||||
else if(isSwiping) // only accept this touch if it wasn't a swipe
|
||||
{
|
||||
isSwiping = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTerrainRect::handleHover(const SDL_MouseMotionEvent &sEvent)
|
||||
{
|
||||
int3 tHovered = whichTileIsIt(sEvent.x, sEvent.y);
|
||||
int3 pom = adventureInt->verifyPos(tHovered);
|
||||
|
||||
if(tHovered != pom) //tile outside the map
|
||||
{
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pom != curHoveredTile)
|
||||
{
|
||||
curHoveredTile = pom;
|
||||
adventureInt->tileHovered(pom);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::hover(bool on)
|
||||
{
|
||||
if (!on)
|
||||
{
|
||||
adventureInt->statusbar->clear();
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
}
|
||||
//Hoverable::hover(on);
|
||||
}
|
||||
void CTerrainRect::showPath(const Rect & extRect, SDL_Surface * to)
|
||||
{
|
||||
const static int pns[9][9] = {
|
||||
{16, 17, 18, 7, -1, 19, 6, 5, -1},
|
||||
{ 8, 9, 18, 7, -1, 19, 6, -1, 20},
|
||||
{ 8, 1, 10, 7, -1, 19, -1, 21, 20},
|
||||
{24, 17, 18, 15, -1, -1, 6, 5, 4},
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{ 8, 1, 2, -1, -1, 11, 22, 21, 20},
|
||||
{24, 17, -1, 23, -1, 3, 14, 5, 4},
|
||||
{24, -1, 2, 23, -1, 3, 22, 13, 4},
|
||||
{-1, 1, 2, 23, -1, 3, 22, 21, 12}
|
||||
}; //table of magic values TODO meaning, change variable name
|
||||
|
||||
for (int i = 0; i < -1 + (int)currentPath->nodes.size(); ++i)
|
||||
{
|
||||
const int3 &curPos = currentPath->nodes[i].coord, &nextPos = currentPath->nodes[i+1].coord;
|
||||
if(curPos.z != adventureInt->position.z)
|
||||
continue;
|
||||
|
||||
int pn=-1;//number of picture
|
||||
if (i==0) //last tile
|
||||
{
|
||||
int x = 32*(curPos.x-adventureInt->position.x)+CGI->mh->offsetX + pos.x,
|
||||
y = 32*(curPos.y-adventureInt->position.y)+CGI->mh->offsetY + pos.y;
|
||||
if (x<0 || y<0 || x>pos.w || y>pos.h)
|
||||
continue;
|
||||
pn=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int3 &prevPos = currentPath->nodes[i-1].coord;
|
||||
std::vector<CGPathNode> & cv = currentPath->nodes;
|
||||
|
||||
/* Vector directions
|
||||
* 0 1 2
|
||||
* \ | /
|
||||
* 3 - 4 - 5
|
||||
* / | \
|
||||
* 6 7 8
|
||||
*For example:
|
||||
* |
|
||||
* |__\
|
||||
* /
|
||||
* is id1=7, id2=5 (pns[7][5])
|
||||
*/
|
||||
bool pathContinuous = curPos.areNeighbours(nextPos) && curPos.areNeighbours(prevPos);
|
||||
if(pathContinuous && cv[i].action != CGPathNode::EMBARK && cv[i].action != CGPathNode::DISEMBARK)
|
||||
{
|
||||
int id1=(curPos.x-nextPos.x+1)+3*(curPos.y-nextPos.y+1); //Direction of entering vector
|
||||
int id2=(cv[i-1].coord.x-curPos.x+1)+3*(cv[i-1].coord.y-curPos.y+1); //Direction of exiting vector
|
||||
pn=pns[id1][id2];
|
||||
}
|
||||
else //path discontinuity or sea/land transition (eg. when moving through Subterranean Gate or Boat)
|
||||
{
|
||||
pn = 0;
|
||||
}
|
||||
}
|
||||
if (currentPath->nodes[i].turns)
|
||||
pn+=25;
|
||||
if (pn>=0)
|
||||
{
|
||||
const auto arrow = graphics->heroMoveArrows->getImage(pn);
|
||||
|
||||
int x = 32*(curPos.x-adventureInt->position.x)+CGI->mh->offsetX + pos.x,
|
||||
y = 32*(curPos.y-adventureInt->position.y)+CGI->mh->offsetY + pos.y;
|
||||
if (x< -32 || y< -32 || x>pos.w || y>pos.h)
|
||||
continue;
|
||||
int hvx = (x + arrow->width()) - (pos.x + pos.w),
|
||||
hvy = (y + arrow->height()) - (pos.y + pos.h);
|
||||
|
||||
Rect prevClip;
|
||||
CSDL_Ext::getClipRect(to, prevClip);
|
||||
CSDL_Ext::setClipRect(to, extRect); //preventing blitting outside of that rect
|
||||
|
||||
if(ADVOPT.smoothMove) //version for smooth hero move, with pos shifts
|
||||
{
|
||||
if (hvx<0 && hvy<0)
|
||||
{
|
||||
arrow->draw(to, x + moveX, y + moveY);
|
||||
}
|
||||
else if(hvx<0)
|
||||
{
|
||||
Rect srcRect = genRect(arrow->height() - hvy, arrow->width(), 0, 0);
|
||||
arrow->draw(to, x + moveX, y + moveY, &srcRect);
|
||||
}
|
||||
else if (hvy<0)
|
||||
{
|
||||
Rect srcRect = genRect(arrow->height(), arrow->width() - hvx, 0, 0);
|
||||
arrow->draw(to, x + moveX, y + moveY, &srcRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rect srcRect = genRect(arrow->height() - hvy, arrow->width() - hvx, 0, 0);
|
||||
arrow->draw(to, x + moveX, y + moveY, &srcRect);
|
||||
}
|
||||
}
|
||||
else //standard version
|
||||
{
|
||||
if (hvx<0 && hvy<0)
|
||||
{
|
||||
arrow->draw(to, x, y);
|
||||
}
|
||||
else if(hvx<0)
|
||||
{
|
||||
Rect srcRect = genRect(arrow->height() - hvy, arrow->width(), 0, 0);
|
||||
arrow->draw(to, x, y, &srcRect);
|
||||
}
|
||||
else if (hvy<0)
|
||||
{
|
||||
Rect srcRect = genRect(arrow->height(), arrow->width() - hvx, 0, 0);
|
||||
arrow->draw(to, x, y, &srcRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rect srcRect = genRect(arrow->height() - hvy, arrow->width() - hvx, 0, 0);
|
||||
arrow->draw(to, x, y, &srcRect);
|
||||
}
|
||||
}
|
||||
CSDL_Ext::setClipRect(to, prevClip);
|
||||
|
||||
}
|
||||
} //for (int i=0;i<currentPath->nodes.size()-1;i++)
|
||||
}
|
||||
|
||||
void CTerrainRect::show(SDL_Surface * to)
|
||||
{
|
||||
if (adventureInt->mode == EAdvMapMode::NORMAL)
|
||||
{
|
||||
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos);
|
||||
info.otherheroAnim = true;
|
||||
info.anim = adventureInt->anim;
|
||||
info.heroAnim = adventureInt->heroAnim;
|
||||
if (ADVOPT.smoothMove)
|
||||
info.movement = int3(moveX, moveY, 0);
|
||||
|
||||
lastRedrawStatus = CGI->mh->drawTerrainRectNew(to, &info);
|
||||
if (fadeAnim->isFading())
|
||||
{
|
||||
Rect r(pos);
|
||||
fadeAnim->update();
|
||||
fadeAnim->draw(to, r.topLeft());
|
||||
}
|
||||
|
||||
if (currentPath/* && adventureInt->position.z==currentPath->startPos().z*/) //drawing path
|
||||
{
|
||||
showPath(pos, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::showAll(SDL_Surface * to)
|
||||
{
|
||||
// world view map is static and doesn't need redraw every frame
|
||||
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
{
|
||||
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos, adventureInt->worldViewIcons);
|
||||
info.scaled = true;
|
||||
info.scale = adventureInt->worldViewScale;
|
||||
adventureInt->worldViewOptions.adjustDrawingInfo(info);
|
||||
CGI->mh->drawTerrainRectNew(to, &info);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::showAnim(SDL_Surface * to)
|
||||
{
|
||||
if (fadeAnim->isFading())
|
||||
show(to);
|
||||
else if (lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
|
||||
show(to); // currently the same; maybe we should pass some flag to map handler so it redraws ONLY tiles that need redraw instead of full
|
||||
}
|
||||
|
||||
int3 CTerrainRect::whichTileIsIt(const int x, const int y)
|
||||
{
|
||||
int3 ret;
|
||||
ret.x = adventureInt->position.x + ((x-CGI->mh->offsetX-pos.x)/32);
|
||||
ret.y = adventureInt->position.y + ((y-CGI->mh->offsetY-pos.y)/32);
|
||||
ret.z = adventureInt->position.z;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int3 CTerrainRect::whichTileIsIt()
|
||||
{
|
||||
return whichTileIsIt(GH.getCursorPosition().x, GH.getCursorPosition().y);
|
||||
}
|
||||
|
||||
int3 CTerrainRect::tileCountOnScreen()
|
||||
{
|
||||
switch (adventureInt->mode)
|
||||
{
|
||||
default:
|
||||
logGlobal->error("Unknown map mode %d", (int)adventureInt->mode);
|
||||
return int3();
|
||||
case EAdvMapMode::NORMAL:
|
||||
return int3(tilesw, tilesh, 1);
|
||||
case EAdvMapMode::WORLD_VIEW:
|
||||
return int3((si32)(tilesw / adventureInt->worldViewScale), (si32)(tilesh / adventureInt->worldViewScale), 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::fadeFromCurrentView()
|
||||
{
|
||||
if (!ADVOPT.screenFading)
|
||||
return;
|
||||
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
return;
|
||||
|
||||
if (!fadeSurface)
|
||||
fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h);
|
||||
CSDL_Ext::blitSurface(screen, fadeSurface, Point(0,0));
|
||||
fadeAnim->init(CFadeAnimation::EMode::OUT, fadeSurface);
|
||||
}
|
||||
|
||||
bool CTerrainRect::needsAnimUpdate()
|
||||
{
|
||||
return fadeAnim->isFading() || lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED;
|
||||
}
|
||||
|
||||
void CResDataBar::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
}
|
||||
|
||||
CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist)
|
||||
{
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>(defname, 0, 0);
|
||||
background->colorize(LOCPLINT->playerID);
|
||||
|
||||
pos.w = background->bg->w;
|
||||
pos.h = background->bg->h;
|
||||
|
||||
txtpos.resize(8);
|
||||
for (int i = 0; i < 8 ; i++)
|
||||
{
|
||||
txtpos[i].first = pos.x + offx + resdist*i;
|
||||
txtpos[i].second = pos.y + offy;
|
||||
}
|
||||
txtpos[7].first = txtpos[6].first + datedist;
|
||||
datetext = CGI->generaltexth->allTexts[62]+": %s, " + CGI->generaltexth->allTexts[63]
|
||||
+ ": %s, " + CGI->generaltexth->allTexts[64] + ": %s";
|
||||
addUsedEvents(RCLICK);
|
||||
}
|
||||
|
||||
CResDataBar::CResDataBar()
|
||||
{
|
||||
pos.x += ADVOPT.resdatabarX;
|
||||
pos.y += ADVOPT.resdatabarY;
|
||||
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>(ADVOPT.resdatabarG, 0, 0);
|
||||
background->colorize(LOCPLINT->playerID);
|
||||
|
||||
pos.w = background->bg->w;
|
||||
pos.h = background->bg->h;
|
||||
|
||||
txtpos.resize(8);
|
||||
for (int i = 0; i < 8 ; i++)
|
||||
{
|
||||
txtpos[i].first = pos.x + ADVOPT.resOffsetX + ADVOPT.resDist*i;
|
||||
txtpos[i].second = pos.y + ADVOPT.resOffsetY;
|
||||
}
|
||||
txtpos[7].first = txtpos[6].first + ADVOPT.resDateDist;
|
||||
datetext = CGI->generaltexth->allTexts[62]+": %s, " + CGI->generaltexth->allTexts[63]
|
||||
+ ": %s, " + CGI->generaltexth->allTexts[64] + ": %s";
|
||||
}
|
||||
|
||||
CResDataBar::~CResDataBar() = default;
|
||||
|
||||
void CResDataBar::draw(SDL_Surface * to)
|
||||
{
|
||||
//TODO: all this should be labels, but they require proper text update on change
|
||||
for (auto i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1))
|
||||
{
|
||||
std::string text = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(i));
|
||||
|
||||
graphics->fonts[FONT_SMALL]->renderTextLeft(to, text, Colors::WHITE, Point(txtpos[i].first,txtpos[i].second));
|
||||
}
|
||||
std::vector<std::string> temp;
|
||||
|
||||
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::MONTH)));
|
||||
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::WEEK)));
|
||||
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK)));
|
||||
|
||||
graphics->fonts[FONT_SMALL]->renderTextLeft(to, processStr(datetext,temp), Colors::WHITE, Point(txtpos[7].first,txtpos[7].second));
|
||||
}
|
||||
|
||||
void CResDataBar::show(SDL_Surface * to)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CResDataBar::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
draw(to);
|
||||
}
|
||||
|
||||
CAdvMapInt::CAdvMapInt():
|
||||
mode(EAdvMapMode::NORMAL),
|
||||
worldViewScale(0.0f), //actual init later in changeMode
|
||||
@@ -567,10 +95,10 @@ CAdvMapInt::CAdvMapInt():
|
||||
pos.h = screen->h;
|
||||
strongInterest = true; // handle all mouse move events to prevent dead mouse move space in fullscreen mode
|
||||
townList.onSelect = std::bind(&CAdvMapInt::selectionChanged,this);
|
||||
bg = BitmapHandler::loadBitmap(ADVOPT.mainGraphic);
|
||||
bg = IImage::createFromFile(ADVOPT.mainGraphic);
|
||||
if(!ADVOPT.worldViewGraphic.empty())
|
||||
{
|
||||
bgWorldView = BitmapHandler::loadBitmap(ADVOPT.worldViewGraphic);
|
||||
bgWorldView = IImage::createFromFile(ADVOPT.worldViewGraphic);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -580,7 +108,7 @@ CAdvMapInt::CAdvMapInt():
|
||||
if (!bgWorldView)
|
||||
{
|
||||
logGlobal->warn("bgWorldView not defined in resolution config; fallback to VWorld.bmp");
|
||||
bgWorldView = BitmapHandler::loadBitmap("VWorld.bmp");
|
||||
bgWorldView = IImage::createFromFile("VWorld.bmp");
|
||||
}
|
||||
|
||||
worldViewIcons = std::make_shared<CAnimation>("VwSymbol");//todo: customize with ADVOPT
|
||||
@@ -606,7 +134,7 @@ CAdvMapInt::CAdvMapInt():
|
||||
moveHero = makeButton(297, std::bind(&CAdvMapInt::fmoveHero,this), ADVOPT.moveHero, SDLK_m);
|
||||
spellbook = makeButton(298, std::bind(&CAdvMapInt::fshowSpellbok,this), ADVOPT.spellbook, SDLK_c);
|
||||
advOptions = makeButton(299, std::bind(&CAdvMapInt::fadventureOPtions,this), ADVOPT.advOptions, SDLK_a);
|
||||
sysOptions = makeButton(300, std::bind(&CAdvMapInt::openSettings, this), ADVOPT.sysOptions, SDLK_o);
|
||||
sysOptions = makeButton(300, std::bind(&CAdvMapInt::fsystemOptions,this), ADVOPT.sysOptions, SDLK_o);
|
||||
nextHero = makeButton(301, std::bind(&CAdvMapInt::fnextHero,this), ADVOPT.nextHero, SDLK_h);
|
||||
endTurn = makeButton(302, std::bind(&CAdvMapInt::fendTurn,this), ADVOPT.endTurn, SDLK_e);
|
||||
|
||||
@@ -713,11 +241,6 @@ CAdvMapInt::CAdvMapInt():
|
||||
addUsedEvents(MOVE);
|
||||
}
|
||||
|
||||
CAdvMapInt::~CAdvMapInt()
|
||||
{
|
||||
SDL_FreeSurface(bg);
|
||||
}
|
||||
|
||||
void CAdvMapInt::fshowOverview()
|
||||
{
|
||||
GH.pushIntT<CKingdomInterface>();
|
||||
@@ -816,7 +339,7 @@ void CAdvMapInt::fadventureOPtions()
|
||||
GH.pushIntT<CAdventureOptions>();
|
||||
}
|
||||
|
||||
void CAdvMapInt::openSettings()
|
||||
void CAdvMapInt::fsystemOptions()
|
||||
{
|
||||
GH.pushIntT<SettingsMainContainer>();
|
||||
}
|
||||
@@ -977,7 +500,7 @@ void CAdvMapInt::deactivate()
|
||||
|
||||
void CAdvMapInt::showAll(SDL_Surface * to)
|
||||
{
|
||||
blitAt(bg,0,0,to);
|
||||
bg->draw(to, 0, 0);
|
||||
|
||||
if(state != INGAME)
|
||||
return;
|
||||
@@ -1094,7 +617,7 @@ void CAdvMapInt::handleMapScrollingUpdate()
|
||||
int scrollSpeed = static_cast<int>(settings["adventure"]["scrollSpeed"].Float());
|
||||
//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
|
||||
if((animValHitCount % (4 / scrollSpeed)) == 0
|
||||
&& ((GH.topInt().get() == this) || isCtrlKeyDown()))
|
||||
&& ((GH.topInt().get() == this) || CSDL_Ext::isCtrlKeyDown()))
|
||||
{
|
||||
if((scrollingDir & LEFT) && (position.x > -CGI->mh->frameW))
|
||||
position.x--;
|
||||
@@ -1458,7 +981,7 @@ void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent )
|
||||
// adventure map scrolling with mouse
|
||||
// currently disabled in world view mode (as it is in OH3), but should work correctly if mode check is removed
|
||||
// don't scroll if there is no window in focus - these events don't seem to correspond to the actual mouse movement
|
||||
if(!isCtrlKeyDown() && isActive() && sEvent.windowID != 0 && mode == EAdvMapMode::NORMAL)
|
||||
if(!CSDL_Ext::isCtrlKeyDown() && isActive() && sEvent.windowID != 0 && mode == EAdvMapMode::NORMAL)
|
||||
{
|
||||
if(sEvent.x<15)
|
||||
{
|
||||
@@ -1508,7 +1031,7 @@ void CAdvMapInt::startHotSeatWait(PlayerColor Player)
|
||||
void CAdvMapInt::setPlayer(PlayerColor Player)
|
||||
{
|
||||
player = Player;
|
||||
graphics->blueToPlayersAdv(bg,player);
|
||||
bg->playerColored(player);
|
||||
|
||||
panelMain->setPlayerColor(player);
|
||||
panelWorldView->setPlayerColor(player);
|
||||
@@ -1968,42 +1491,6 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale)
|
||||
}
|
||||
}
|
||||
|
||||
CAdventureOptions::CAdventureOptions()
|
||||
: CWindowObject(PLAYER_COLORED, "ADVOPTS")
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v);
|
||||
viewWorld->addCallback(std::bind(&CPlayerInterface::viewWorldMap, LOCPLINT));
|
||||
|
||||
exit = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN);
|
||||
exit->assignedKeys.insert(SDLK_ESCAPE);
|
||||
|
||||
scenInfo = std::make_shared<CButton>(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_i);
|
||||
scenInfo->addCallback(CAdventureOptions::showScenarioInfo);
|
||||
|
||||
puzzle = std::make_shared<CButton>(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_p);
|
||||
puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT));
|
||||
|
||||
dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d);
|
||||
if(const CGHeroInstance *h = adventureInt->curHero())
|
||||
dig->addCallback(std::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h));
|
||||
else
|
||||
dig->block(true);
|
||||
}
|
||||
|
||||
void CAdventureOptions::showScenarioInfo()
|
||||
{
|
||||
if(LOCPLINT->cb->getStartInfo()->campState)
|
||||
{
|
||||
GH.pushIntT<CCampaignInfoScreen>();
|
||||
}
|
||||
else
|
||||
{
|
||||
GH.pushIntT<CScenarioInfoScreen>();
|
||||
}
|
||||
}
|
||||
|
||||
CAdvMapInt::WorldViewOptions::WorldViewOptions()
|
||||
{
|
||||
clear();
|
||||
@@ -2022,3 +1509,4 @@ void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
|
||||
|
||||
info.additionalIcons = &iconPositions;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* CAdvmapInterface.h, part of VCMI engine
|
||||
* CAdvMapInt.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
@@ -9,119 +9,45 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../widgets/AdventureMapClasses.h"
|
||||
#include "CWindowObject.h"
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../../lib/int3.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
#include "../../lib/spells/ViewSpellInt.h"
|
||||
#include "CTerrainRect.h"
|
||||
#include "CResDataBar.h"
|
||||
#include "CList.h"
|
||||
#include "CInfoBar.h"
|
||||
#include "CMinimap.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct CGPath;
|
||||
struct CGPathNode;
|
||||
class CGObjectInstance;
|
||||
class CGHeroInstance;
|
||||
class CGTownInstance;
|
||||
class CSpell;
|
||||
class CArmedInstance;
|
||||
class IShipyard;
|
||||
struct CGPathNode;
|
||||
struct ObjectPosInfo;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CCallback;
|
||||
class CAdvMapInt;
|
||||
class CHeroWindow;
|
||||
enum class EMapAnimRedrawStatus;
|
||||
class CFadeAnimation;
|
||||
class CButton;
|
||||
class IImage;
|
||||
class CAnimImage;
|
||||
class CGStatusBar;
|
||||
class CAdvMapPanel;
|
||||
class CAdvMapWorldViewPanel;
|
||||
class CAnimation;
|
||||
|
||||
struct MapDrawingInfo;
|
||||
|
||||
/*****************************/
|
||||
|
||||
enum class EAdvMapMode
|
||||
{
|
||||
NORMAL,
|
||||
WORLD_VIEW
|
||||
};
|
||||
|
||||
/// Adventure options dialog where you can view the world, dig, play the replay of the last turn,...
|
||||
class CAdventureOptions : public CWindowObject
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<CButton> exit;
|
||||
std::shared_ptr<CButton> viewWorld;
|
||||
std::shared_ptr<CButton> puzzle;
|
||||
std::shared_ptr<CButton> dig;
|
||||
std::shared_ptr<CButton> scenInfo;
|
||||
/*std::shared_ptr<CButton> replay*/
|
||||
|
||||
CAdventureOptions();
|
||||
static void showScenarioInfo();
|
||||
};
|
||||
|
||||
/// Holds information about which tiles of the terrain are shown/not shown at the screen
|
||||
class CTerrainRect : public CIntObject
|
||||
{
|
||||
SDL_Surface * fadeSurface;
|
||||
EMapAnimRedrawStatus lastRedrawStatus;
|
||||
std::shared_ptr<CFadeAnimation> fadeAnim;
|
||||
|
||||
int3 swipeInitialMapPos;
|
||||
int3 swipeInitialRealPos;
|
||||
bool isSwiping;
|
||||
static constexpr float SwipeTouchSlop = 16.0f;
|
||||
|
||||
void handleHover(const SDL_MouseMotionEvent & sEvent);
|
||||
void handleSwipeMove(const SDL_MouseMotionEvent & sEvent);
|
||||
/// handles start/finish of swipe (press/release of corresponding button); returns true if state change was handled
|
||||
bool handleSwipeStateChange(bool btnPressed);
|
||||
public:
|
||||
int tilesw, tilesh; //width and height of terrain to blit in tiles
|
||||
int3 curHoveredTile;
|
||||
int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels)
|
||||
CGPath * currentPath;
|
||||
|
||||
CTerrainRect();
|
||||
virtual ~CTerrainRect();
|
||||
void deactivate() override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void clickMiddle(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void showAnim(SDL_Surface * to);
|
||||
void showPath(const Rect &extRect, SDL_Surface * to);
|
||||
int3 whichTileIsIt(const int x, const int y); //x,y are cursor position
|
||||
int3 whichTileIsIt(); //uses current cursor pos
|
||||
/// @returns number of visible tiles on screen respecting current map scaling
|
||||
int3 tileCountOnScreen();
|
||||
/// animates view by caching current surface and crossfading it with normal screen
|
||||
void fadeFromCurrentView();
|
||||
bool needsAnimUpdate();
|
||||
};
|
||||
|
||||
/// Resources bar which shows information about how many gold, crystals,... you have
|
||||
/// Current date is displayed too
|
||||
class CResDataBar : public CIntObject
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<CPicture> background;
|
||||
|
||||
std::vector<std::pair<int,int> > txtpos;
|
||||
std::string datetext;
|
||||
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
CResDataBar();
|
||||
CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist);
|
||||
~CResDataBar();
|
||||
|
||||
void draw(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// That's a huge class which handles general adventure map actions and
|
||||
/// shows the right menu(questlog, spellbook, end turn,..) from where you
|
||||
/// can get to the towns and heroes.
|
||||
@@ -132,7 +58,6 @@ class CAdvMapInt : public CIntObject
|
||||
|
||||
public:
|
||||
CAdvMapInt();
|
||||
~CAdvMapInt();
|
||||
|
||||
int3 position; //top left corner of visible map part
|
||||
PlayerColor player;
|
||||
@@ -170,8 +95,8 @@ public:
|
||||
|
||||
WorldViewOptions worldViewOptions;
|
||||
|
||||
SDL_Surface * bg;
|
||||
SDL_Surface * bgWorldView;
|
||||
std::shared_ptr<IImage> bg;
|
||||
std::shared_ptr<IImage> bgWorldView;
|
||||
std::vector<std::shared_ptr<CAnimImage>> gems;
|
||||
CMinimap minimap;
|
||||
std::shared_ptr<CGStatusBar> statusbar;
|
||||
@@ -217,7 +142,7 @@ public:
|
||||
void fmoveHero();
|
||||
void fshowSpellbok();
|
||||
void fadventureOPtions();
|
||||
void openSettings();
|
||||
void fsystemOptions();
|
||||
void fnextHero();
|
||||
void fendTurn();
|
||||
|
96
client/adventureMap/CAdvMapPanel.cpp
Normal file
96
client/adventureMap/CAdvMapPanel.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* CAdvMapPanel.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CAdvMapPanel.h"
|
||||
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
CAdvMapPanel::CAdvMapPanel(std::shared_ptr<IImage> bg, Point position)
|
||||
: CIntObject()
|
||||
, background(bg)
|
||||
{
|
||||
defActions = 255;
|
||||
recActions = 255;
|
||||
pos.x += position.x;
|
||||
pos.y += position.y;
|
||||
if (bg)
|
||||
{
|
||||
pos.w = bg->width();
|
||||
pos.h = bg->height();
|
||||
}
|
||||
}
|
||||
|
||||
void CAdvMapPanel::addChildColorableButton(std::shared_ptr<CButton> button)
|
||||
{
|
||||
colorableButtons.push_back(button);
|
||||
addChildToPanel(button, ACTIVATE | DEACTIVATE);
|
||||
}
|
||||
|
||||
void CAdvMapPanel::setPlayerColor(const PlayerColor & clr)
|
||||
{
|
||||
for(auto & button : colorableButtons)
|
||||
{
|
||||
button->setPlayerColor(clr);
|
||||
}
|
||||
}
|
||||
|
||||
void CAdvMapPanel::showAll(SDL_Surface * to)
|
||||
{
|
||||
if(background)
|
||||
background->draw(to, pos.x, pos.y);
|
||||
|
||||
CIntObject::showAll(to);
|
||||
}
|
||||
|
||||
void CAdvMapPanel::addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions)
|
||||
{
|
||||
otherObjects.push_back(obj);
|
||||
obj->recActions |= actions | SHOWALL;
|
||||
obj->recActions &= ~DISPOSE;
|
||||
addChild(obj.get(), false);
|
||||
}
|
||||
|
||||
CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color)
|
||||
: CAdvMapPanel(bg, position), icons(_icons)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
int fillerHeight = bg ? spaceBottom - pos.y - pos.h : 0;
|
||||
|
||||
if(fillerHeight > 0)
|
||||
{
|
||||
backgroundFiller = std::make_shared<CFilledTexture>("DIBOXBCK", Rect(0, pos.h, pos.w, fillerHeight));
|
||||
}
|
||||
}
|
||||
|
||||
CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel() = default;
|
||||
|
||||
void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor & color, int indexOffset)
|
||||
{
|
||||
assert(iconsData.size() == currentIcons.size());
|
||||
|
||||
for(size_t idx = 0; idx < iconsData.size(); idx++)
|
||||
{
|
||||
const auto & data = iconsData.at(idx);
|
||||
currentIcons[idx]->setFrame(data.first + indexOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, int indexOffset)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
iconsData.push_back(data);
|
||||
currentIcons.push_back(std::make_shared<CAnimImage>(icons, data.first + indexOffset, 0, data.second.x, data.second.y));
|
||||
}
|
||||
|
60
client/adventureMap/CAdvMapPanel.h
Normal file
60
client/adventureMap/CAdvMapPanel.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* CAdvMapPanel.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class PlayerColor;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CAnimation;
|
||||
class CAnimImage;
|
||||
class CFilledTexture;
|
||||
class CButton;
|
||||
class IImage;
|
||||
|
||||
/// simple panel that contains other displayable elements; used to separate groups of controls
|
||||
class CAdvMapPanel : public CIntObject
|
||||
{
|
||||
std::vector<std::shared_ptr<CButton>> colorableButtons;
|
||||
std::vector<std::shared_ptr<CIntObject>> otherObjects;
|
||||
/// the surface passed to this obj will be freed in dtor
|
||||
std::shared_ptr<IImage> background;
|
||||
public:
|
||||
CAdvMapPanel(std::shared_ptr<IImage> bg, Point position);
|
||||
|
||||
void addChildToPanel(std::shared_ptr<CIntObject> obj, ui8 actions = 0);
|
||||
void addChildColorableButton(std::shared_ptr<CButton> button);
|
||||
/// recolors all buttons to given player color
|
||||
void setPlayerColor(const PlayerColor & clr);
|
||||
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// specialized version of CAdvMapPanel that handles recolorable def-based pictures for world view info panel
|
||||
class CAdvMapWorldViewPanel : public CAdvMapPanel
|
||||
{
|
||||
/// data that allows reconstruction of panel info icons
|
||||
std::vector<std::pair<int, Point>> iconsData;
|
||||
/// ptrs to child-pictures constructed from iconsData
|
||||
std::vector<std::shared_ptr<CAnimImage>> currentIcons;
|
||||
/// surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod)
|
||||
std::shared_ptr<CFilledTexture> backgroundFiller;
|
||||
std::shared_ptr<CAnimation> icons;
|
||||
public:
|
||||
CAdvMapWorldViewPanel(std::shared_ptr<CAnimation> _icons, std::shared_ptr<IImage> bg, Point position, int spaceBottom, const PlayerColor &color);
|
||||
virtual ~CAdvMapWorldViewPanel();
|
||||
|
||||
void addChildIcon(std::pair<int, Point> data, int indexOffset);
|
||||
/// recreates all pictures from given def to recolor them according to current player color
|
||||
void recolorIcons(const PlayerColor & color, int indexOffset);
|
||||
};
|
||||
|
61
client/adventureMap/CAdventureOptions.cpp
Normal file
61
client/adventureMap/CAdventureOptions.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* CAdventureOptions.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CAdventureOptions.h"
|
||||
|
||||
#include "CAdvMapInt.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../lobby/CCampaignInfoScreen.h"
|
||||
#include "../lobby/CScenarioInfoScreen.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/StartInfo.h"
|
||||
|
||||
CAdventureOptions::CAdventureOptions()
|
||||
: CWindowObject(PLAYER_COLORED, "ADVOPTS")
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
viewWorld = std::make_shared<CButton>(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_v);
|
||||
viewWorld->addCallback(std::bind(&CPlayerInterface::viewWorldMap, LOCPLINT));
|
||||
|
||||
exit = std::make_shared<CButton>(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN);
|
||||
exit->assignedKeys.insert(SDLK_ESCAPE);
|
||||
|
||||
scenInfo = std::make_shared<CButton>(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_i);
|
||||
scenInfo->addCallback(CAdventureOptions::showScenarioInfo);
|
||||
|
||||
puzzle = std::make_shared<CButton>(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_p);
|
||||
puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT));
|
||||
|
||||
dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d);
|
||||
if(const CGHeroInstance *h = adventureInt->curHero())
|
||||
dig->addCallback(std::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h));
|
||||
else
|
||||
dig->block(true);
|
||||
}
|
||||
|
||||
void CAdventureOptions::showScenarioInfo()
|
||||
{
|
||||
if(LOCPLINT->cb->getStartInfo()->campState)
|
||||
{
|
||||
GH.pushIntT<CCampaignInfoScreen>();
|
||||
}
|
||||
else
|
||||
{
|
||||
GH.pushIntT<CScenarioInfoScreen>();
|
||||
}
|
||||
}
|
||||
|
30
client/adventureMap/CAdventureOptions.h
Normal file
30
client/adventureMap/CAdventureOptions.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* CAdventureOptions.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../windows/CWindowObject.h"
|
||||
|
||||
class CButton;
|
||||
|
||||
/// Adventure options dialog where you can view the world, dig, play the replay of the last turn,...
|
||||
class CAdventureOptions : public CWindowObject
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<CButton> exit;
|
||||
std::shared_ptr<CButton> viewWorld;
|
||||
std::shared_ptr<CButton> puzzle;
|
||||
std::shared_ptr<CButton> dig;
|
||||
std::shared_ptr<CButton> scenInfo;
|
||||
/*std::shared_ptr<CButton> replay*/
|
||||
|
||||
CAdventureOptions();
|
||||
static void showScenarioInfo();
|
||||
};
|
||||
|
261
client/adventureMap/CInGameConsole.cpp
Normal file
261
client/adventureMap/CInGameConsole.cpp
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* CInGameConsole.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CInGameConsole.h"
|
||||
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../ClientCommandManager.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/mapObjects/CArmedInstance.h"
|
||||
|
||||
#include <SDL_timer.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
CInGameConsole::CInGameConsole()
|
||||
: CIntObject(KEYBOARD | TEXTINPUT),
|
||||
prevEntDisp(-1),
|
||||
defaultTimeout(10000),
|
||||
maxDisplayedTexts(10)
|
||||
{
|
||||
}
|
||||
|
||||
void CInGameConsole::show(SDL_Surface * to)
|
||||
{
|
||||
int number = 0;
|
||||
|
||||
std::vector<std::list< std::pair< std::string, uint32_t > >::iterator> toDel;
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(texts_mx);
|
||||
for(auto it = texts.begin(); it != texts.end(); ++it, ++number)
|
||||
{
|
||||
Point leftBottomCorner(0, pos.h);
|
||||
|
||||
graphics->fonts[FONT_MEDIUM]->renderTextLeft(to, it->first, Colors::GREEN,
|
||||
Point(leftBottomCorner.x + 50, leftBottomCorner.y - (int)texts.size() * 20 - 80 + number*20));
|
||||
|
||||
if((int)(SDL_GetTicks() - it->second) > defaultTimeout)
|
||||
{
|
||||
toDel.push_back(it);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto & elem : toDel)
|
||||
{
|
||||
texts.erase(elem);
|
||||
}
|
||||
}
|
||||
|
||||
void CInGameConsole::print(const std::string &txt)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(texts_mx);
|
||||
int lineLen = conf.go()->ac.outputLineLength;
|
||||
|
||||
if(txt.size() < lineLen)
|
||||
{
|
||||
texts.push_back(std::make_pair(txt, SDL_GetTicks()));
|
||||
if(texts.size() > maxDisplayedTexts)
|
||||
{
|
||||
texts.pop_front();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(lineLen);
|
||||
for(int g=0; g<txt.size() / lineLen + 1; ++g)
|
||||
{
|
||||
std::string part = txt.substr(g * lineLen, lineLen);
|
||||
if(part.size() == 0)
|
||||
break;
|
||||
|
||||
texts.push_back(std::make_pair(part, SDL_GetTicks()));
|
||||
if(texts.size() > maxDisplayedTexts)
|
||||
{
|
||||
texts.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInGameConsole::keyPressed (const SDL_KeyboardEvent & key)
|
||||
{
|
||||
if(key.type != SDL_KEYDOWN) return;
|
||||
|
||||
if(!captureAllKeys && key.keysym.sym != SDLK_TAB) return; //because user is not entering any text
|
||||
|
||||
switch(key.keysym.sym)
|
||||
{
|
||||
case SDLK_TAB:
|
||||
case SDLK_ESCAPE:
|
||||
{
|
||||
if(captureAllKeys)
|
||||
{
|
||||
endEnteringText(false);
|
||||
}
|
||||
else if(SDLK_TAB == key.keysym.sym)
|
||||
{
|
||||
startEnteringText();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDLK_RETURN: //enter key
|
||||
{
|
||||
if(!enteredText.empty() && captureAllKeys)
|
||||
{
|
||||
bool anyTextExceptCaret = enteredText.size() > 1;
|
||||
endEnteringText(anyTextExceptCaret);
|
||||
|
||||
if(anyTextExceptCaret)
|
||||
{
|
||||
CCS->soundh->playSound("CHAT");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDLK_BACKSPACE:
|
||||
{
|
||||
if(enteredText.size() > 1)
|
||||
{
|
||||
Unicode::trimRight(enteredText,2);
|
||||
enteredText += '_';
|
||||
refreshEnteredText();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDLK_UP: //up arrow
|
||||
{
|
||||
if(previouslyEntered.size() == 0)
|
||||
break;
|
||||
|
||||
if(prevEntDisp == -1)
|
||||
{
|
||||
prevEntDisp = static_cast<int>(previouslyEntered.size() - 1);
|
||||
enteredText = previouslyEntered[prevEntDisp] + "_";
|
||||
refreshEnteredText();
|
||||
}
|
||||
else if( prevEntDisp > 0)
|
||||
{
|
||||
--prevEntDisp;
|
||||
enteredText = previouslyEntered[prevEntDisp] + "_";
|
||||
refreshEnteredText();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDLK_DOWN: //down arrow
|
||||
{
|
||||
if(prevEntDisp != -1 && prevEntDisp+1 < previouslyEntered.size())
|
||||
{
|
||||
++prevEntDisp;
|
||||
enteredText = previouslyEntered[prevEntDisp] + "_";
|
||||
refreshEnteredText();
|
||||
}
|
||||
else if(prevEntDisp+1 == previouslyEntered.size()) //useful feature
|
||||
{
|
||||
prevEntDisp = -1;
|
||||
enteredText = "_";
|
||||
refreshEnteredText();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInGameConsole::textInputed(const SDL_TextInputEvent & event)
|
||||
{
|
||||
if(!captureAllKeys || enteredText.size() == 0)
|
||||
return;
|
||||
enteredText.resize(enteredText.size()-1);
|
||||
|
||||
enteredText += event.text;
|
||||
enteredText += "_";
|
||||
|
||||
refreshEnteredText();
|
||||
}
|
||||
|
||||
void CInGameConsole::textEdited(const SDL_TextEditingEvent & event)
|
||||
{
|
||||
//do nothing here
|
||||
}
|
||||
|
||||
void CInGameConsole::startEnteringText()
|
||||
{
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
if (captureAllKeys)
|
||||
return;
|
||||
|
||||
assert(GH.statusbar);
|
||||
assert(currentStatusBar.expired());//effectively, nullptr check
|
||||
|
||||
currentStatusBar = GH.statusbar;
|
||||
|
||||
captureAllKeys = true;
|
||||
enteredText = "_";
|
||||
|
||||
GH.statusbar->setEnteringMode(true);
|
||||
GH.statusbar->setEnteredText(enteredText);
|
||||
}
|
||||
|
||||
void CInGameConsole::endEnteringText(bool processEnteredText)
|
||||
{
|
||||
captureAllKeys = false;
|
||||
prevEntDisp = -1;
|
||||
if(processEnteredText)
|
||||
{
|
||||
std::string txt = enteredText.substr(0, enteredText.size()-1);
|
||||
previouslyEntered.push_back(txt);
|
||||
|
||||
if(txt.at(0) == '/')
|
||||
{
|
||||
//some commands like gosolo don't work when executed from GUI thread
|
||||
auto threadFunction = [=]()
|
||||
{
|
||||
ClientCommandManager commandController;
|
||||
commandController.processCommand(txt.substr(1), true);
|
||||
};
|
||||
|
||||
boost::thread clientCommandThread(threadFunction);
|
||||
clientCommandThread.detach();
|
||||
}
|
||||
else
|
||||
LOCPLINT->cb->sendMessage(txt, LOCPLINT->getSelection());
|
||||
}
|
||||
enteredText.clear();
|
||||
|
||||
auto statusbar = currentStatusBar.lock();
|
||||
assert(statusbar);
|
||||
|
||||
if (statusbar)
|
||||
statusbar->setEnteringMode(false);
|
||||
|
||||
currentStatusBar.reset();
|
||||
}
|
||||
|
||||
void CInGameConsole::refreshEnteredText()
|
||||
{
|
||||
auto statusbar = currentStatusBar.lock();
|
||||
assert(statusbar);
|
||||
|
||||
if (statusbar)
|
||||
statusbar->setEnteredText(enteredText);
|
||||
}
|
||||
|
39
client/adventureMap/CInGameConsole.h
Normal file
39
client/adventureMap/CInGameConsole.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* CInGameConsole.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
class CInGameConsole : public CIntObject
|
||||
{
|
||||
private:
|
||||
std::list< std::pair< std::string, uint32_t > > texts; //list<text to show, time of add>
|
||||
boost::mutex texts_mx; // protects texts
|
||||
std::vector< std::string > previouslyEntered; //previously entered texts, for up/down arrows to work
|
||||
int prevEntDisp; //displayed entry from previouslyEntered - if none it's -1
|
||||
int defaultTimeout; //timeout for new texts (in ms)
|
||||
int maxDisplayedTexts; //hiw many texts can be displayed simultaneously
|
||||
|
||||
std::weak_ptr<IStatusBar> currentStatusBar;
|
||||
public:
|
||||
std::string enteredText;
|
||||
void show(SDL_Surface * to) override;
|
||||
void print(const std::string &txt);
|
||||
void keyPressed (const SDL_KeyboardEvent & key) override; //call-in
|
||||
|
||||
void textInputed(const SDL_TextInputEvent & event) override;
|
||||
void textEdited(const SDL_TextEditingEvent & event) override;
|
||||
|
||||
void startEnteringText();
|
||||
void endEnteringText(bool processEnteredText);
|
||||
void refreshEnteredText();
|
||||
|
||||
CInGameConsole();
|
||||
};
|
323
client/adventureMap/CInfoBar.cpp
Normal file
323
client/adventureMap/CInfoBar.cpp
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* CInfoBar.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CInfoBar.h"
|
||||
|
||||
#include "CAdvMapInt.h"
|
||||
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
CInfoBar::CVisibleInfo::CVisibleInfo()
|
||||
: CIntObject(0, Point(8, 12))
|
||||
{
|
||||
}
|
||||
|
||||
void CInfoBar::CVisibleInfo::show(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::show(to);
|
||||
for(auto object : forceRefresh)
|
||||
object->showAll(to);
|
||||
}
|
||||
|
||||
CInfoBar::EmptyVisibleInfo::EmptyVisibleInfo()
|
||||
{
|
||||
}
|
||||
|
||||
CInfoBar::VisibleHeroInfo::VisibleHeroInfo(const CGHeroInstance * hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>("ADSTATHR");
|
||||
heroTooltip = std::make_shared<CHeroTooltip>(Point(0,0), hero);
|
||||
}
|
||||
|
||||
CInfoBar::VisibleTownInfo::VisibleTownInfo(const CGTownInstance * town)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>("ADSTATCS");
|
||||
townTooltip = std::make_shared<CTownTooltip>(Point(0,0), town);
|
||||
}
|
||||
|
||||
CInfoBar::VisibleDateInfo::VisibleDateInfo()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
animation = std::make_shared<CShowableAnim>(1, 0, getNewDayName(), CShowableAnim::PLAY_ONCE, 180);// H3 uses around 175-180 ms per frame
|
||||
|
||||
std::string labelText;
|
||||
if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) == 1 && LOCPLINT->cb->getDate(Date::DAY) != 1) // monday of any week but first - show new week info
|
||||
labelText = CGI->generaltexth->allTexts[63] + " " + boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::WEEK));
|
||||
else
|
||||
labelText = CGI->generaltexth->allTexts[64] + " " + boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK));
|
||||
|
||||
label = std::make_shared<CLabel>(95, 31, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, labelText);
|
||||
|
||||
forceRefresh.push_back(label);
|
||||
}
|
||||
|
||||
std::string CInfoBar::VisibleDateInfo::getNewDayName()
|
||||
{
|
||||
if(LOCPLINT->cb->getDate(Date::DAY) == 1)
|
||||
return "NEWDAY";
|
||||
|
||||
if(LOCPLINT->cb->getDate(Date::DAY) != 1)
|
||||
return "NEWDAY";
|
||||
|
||||
switch(LOCPLINT->cb->getDate(Date::WEEK))
|
||||
{
|
||||
case 1:
|
||||
return "NEWWEEK1";
|
||||
case 2:
|
||||
return "NEWWEEK2";
|
||||
case 3:
|
||||
return "NEWWEEK3";
|
||||
case 4:
|
||||
return "NEWWEEK4";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
CInfoBar::VisibleEnemyTurnInfo::VisibleEnemyTurnInfo(PlayerColor player)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>("ADSTATNX");
|
||||
banner = std::make_shared<CAnimImage>("CREST58", player.getNum(), 0, 20, 51);
|
||||
sand = std::make_shared<CShowableAnim>(99, 51, "HOURSAND", 0, 100); // H3 uses around 100 ms per frame
|
||||
glass = std::make_shared<CShowableAnim>(99, 51, "HOURGLAS", CShowableAnim::PLAY_ONCE, 1000); // H3 scales this nicely for AI turn duration, don't have anything like that in vcmi
|
||||
}
|
||||
|
||||
CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
//get amount of halls of each level
|
||||
std::vector<int> halls(4, 0);
|
||||
for(auto town : LOCPLINT->towns)
|
||||
{
|
||||
int hallLevel = town->hallLevel();
|
||||
//negative value means no village hall, unlikely but possible
|
||||
if(hallLevel >= 0)
|
||||
halls.at(hallLevel)++;
|
||||
}
|
||||
|
||||
std::vector<PlayerColor> allies, enemies;
|
||||
|
||||
//generate list of allies and enemies
|
||||
for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
|
||||
{
|
||||
if(LOCPLINT->cb->getPlayerStatus(PlayerColor(i), false) == EPlayerStatus::INGAME)
|
||||
{
|
||||
if(LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, PlayerColor(i)) != PlayerRelations::ENEMIES)
|
||||
allies.push_back(PlayerColor(i));
|
||||
else
|
||||
enemies.push_back(PlayerColor(i));
|
||||
}
|
||||
}
|
||||
|
||||
//generate widgets
|
||||
background = std::make_shared<CPicture>("ADSTATIN");
|
||||
allyLabel = std::make_shared<CLabel>(10, 106, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[390] + ":");
|
||||
enemyLabel = std::make_shared<CLabel>(10, 136, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[391] + ":");
|
||||
|
||||
int posx = allyLabel->pos.w + allyLabel->pos.x - pos.x + 4;
|
||||
for(PlayerColor & player : allies)
|
||||
{
|
||||
auto image = std::make_shared<CAnimImage>("ITGFLAGS", player.getNum(), 0, posx, 102);
|
||||
posx += image->pos.w;
|
||||
flags.push_back(image);
|
||||
}
|
||||
|
||||
posx = enemyLabel->pos.w + enemyLabel->pos.x - pos.x + 4;
|
||||
for(PlayerColor & player : enemies)
|
||||
{
|
||||
auto image = std::make_shared<CAnimImage>("ITGFLAGS", player.getNum(), 0, posx, 132);
|
||||
posx += image->pos.w;
|
||||
flags.push_back(image);
|
||||
}
|
||||
|
||||
for(size_t i=0; i<halls.size(); i++)
|
||||
{
|
||||
hallIcons.push_back(std::make_shared<CAnimImage>("itmtl", i, 0, 6 + 42 * (int)i , 11));
|
||||
if(halls[i])
|
||||
hallLabels.push_back(std::make_shared<CLabel>( 26 + 42 * (int)i, 64, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, boost::lexical_cast<std::string>(halls[i])));
|
||||
}
|
||||
}
|
||||
|
||||
CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const Component & compToDisplay, std::string message)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
background = std::make_shared<CPicture>("ADSTATOT", 1, 0);
|
||||
|
||||
comp = std::make_shared<CComponent>(compToDisplay);
|
||||
comp->moveTo(Point(pos.x+47, pos.y+50));
|
||||
|
||||
text = std::make_shared<CTextBox>(message, Rect(10, 4, 160, 50), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||
}
|
||||
|
||||
void CInfoBar::playNewDaySound()
|
||||
{
|
||||
if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) != 1) // not first day of the week
|
||||
CCS->soundh->playSound(soundBase::newDay);
|
||||
else if(LOCPLINT->cb->getDate(Date::WEEK) != 1) // not first week in month
|
||||
CCS->soundh->playSound(soundBase::newWeek);
|
||||
else if(LOCPLINT->cb->getDate(Date::MONTH) != 1) // not first month
|
||||
CCS->soundh->playSound(soundBase::newMonth);
|
||||
else
|
||||
CCS->soundh->playSound(soundBase::newDay);
|
||||
}
|
||||
|
||||
void CInfoBar::reset()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
state = EMPTY;
|
||||
visibleInfo = std::make_shared<EmptyVisibleInfo>();
|
||||
}
|
||||
|
||||
void CInfoBar::showSelection()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
if(adventureInt->selection)
|
||||
{
|
||||
if(auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection))
|
||||
{
|
||||
showHeroSelection(hero);
|
||||
return;
|
||||
}
|
||||
else if(auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection))
|
||||
{
|
||||
showTownSelection(town);
|
||||
return;
|
||||
}
|
||||
}
|
||||
showGameStatus();//FIXME: may be incorrect but shouldn't happen in general
|
||||
}
|
||||
|
||||
void CInfoBar::tick()
|
||||
{
|
||||
removeUsedEvents(TIME);
|
||||
if(GH.topInt() == adventureInt)
|
||||
showSelection();
|
||||
}
|
||||
|
||||
void CInfoBar::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(down)
|
||||
{
|
||||
if(state == HERO || state == TOWN)
|
||||
showGameStatus();
|
||||
else if(state == GAME)
|
||||
showDate();
|
||||
else
|
||||
showSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void CInfoBar::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
adventureInt->handleRightClick(CGI->generaltexth->allTexts[109], down);
|
||||
}
|
||||
|
||||
void CInfoBar::hover(bool on)
|
||||
{
|
||||
if(on)
|
||||
GH.statusbar->write(CGI->generaltexth->zelp[292].first);
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
|
||||
CInfoBar::CInfoBar(const Rect & position)
|
||||
: CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()),
|
||||
state(EMPTY)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
pos.w = position.w;
|
||||
pos.h = position.h;
|
||||
reset();
|
||||
}
|
||||
|
||||
void CInfoBar::showDate()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
playNewDaySound();
|
||||
state = DATE;
|
||||
visibleInfo = std::make_shared<VisibleDateInfo>();
|
||||
setTimer(3000); // confirmed to match H3
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CInfoBar::showComponent(const Component & comp, std::string message)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
state = COMPONENT;
|
||||
visibleInfo = std::make_shared<VisibleComponentInfo>(comp, message);
|
||||
setTimer(3000);
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CInfoBar::startEnemyTurn(PlayerColor color)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
state = AITURN;
|
||||
visibleInfo = std::make_shared<VisibleEnemyTurnInfo>(color);
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CInfoBar::showHeroSelection(const CGHeroInstance * hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
if(!hero)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
state = HERO;
|
||||
visibleInfo = std::make_shared<VisibleHeroInfo>(hero);
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CInfoBar::showTownSelection(const CGTownInstance * town)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
if(!town)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
state = TOWN;
|
||||
visibleInfo = std::make_shared<VisibleTownInfo>(town);
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CInfoBar::showGameStatus()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
state = GAME;
|
||||
visibleInfo = std::make_shared<VisibleGameStatusInfo>();
|
||||
setTimer(3000);
|
||||
redraw();
|
||||
}
|
||||
|
146
client/adventureMap/CInfoBar.h
Normal file
146
client/adventureMap/CInfoBar.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* CInfoBar.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CGHeroInstance;
|
||||
class CGTownInstance;
|
||||
struct Component;
|
||||
class PlayerColor;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CAnimImage;
|
||||
class CShowableAnim;
|
||||
class CComponent;
|
||||
class CHeroTooltip;
|
||||
class CTownTooltip;
|
||||
class CLabel;
|
||||
class CTextBox;
|
||||
|
||||
/// Info box which shows next week/day information, hold the current date
|
||||
class CInfoBar : public CIntObject
|
||||
{
|
||||
//all visible information located in one object - for ease of replacing
|
||||
class CVisibleInfo : public CIntObject
|
||||
{
|
||||
public:
|
||||
void show(SDL_Surface * to) override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<CPicture> background;
|
||||
std::list<std::shared_ptr<CIntObject>> forceRefresh;
|
||||
|
||||
CVisibleInfo();
|
||||
};
|
||||
|
||||
class EmptyVisibleInfo : public CVisibleInfo
|
||||
{
|
||||
public:
|
||||
EmptyVisibleInfo();
|
||||
};
|
||||
|
||||
class VisibleHeroInfo : public CVisibleInfo
|
||||
{
|
||||
std::shared_ptr<CHeroTooltip> heroTooltip;
|
||||
public:
|
||||
VisibleHeroInfo(const CGHeroInstance * hero);
|
||||
};
|
||||
|
||||
class VisibleTownInfo : public CVisibleInfo
|
||||
{
|
||||
std::shared_ptr<CTownTooltip> townTooltip;
|
||||
public:
|
||||
VisibleTownInfo(const CGTownInstance * town);
|
||||
};
|
||||
|
||||
class VisibleDateInfo : public CVisibleInfo
|
||||
{
|
||||
std::shared_ptr<CShowableAnim> animation;
|
||||
std::shared_ptr<CLabel> label;
|
||||
|
||||
std::string getNewDayName();
|
||||
public:
|
||||
VisibleDateInfo();
|
||||
};
|
||||
|
||||
class VisibleEnemyTurnInfo : public CVisibleInfo
|
||||
{
|
||||
std::shared_ptr<CAnimImage> banner;
|
||||
std::shared_ptr<CShowableAnim> glass;
|
||||
std::shared_ptr<CShowableAnim> sand;
|
||||
public:
|
||||
VisibleEnemyTurnInfo(PlayerColor player);
|
||||
};
|
||||
|
||||
class VisibleGameStatusInfo : public CVisibleInfo
|
||||
{
|
||||
std::shared_ptr<CLabel> allyLabel;
|
||||
std::shared_ptr<CLabel> enemyLabel;
|
||||
|
||||
std::vector<std::shared_ptr<CAnimImage>> flags;
|
||||
std::vector<std::shared_ptr<CAnimImage>> hallIcons;
|
||||
std::vector<std::shared_ptr<CLabel>> hallLabels;
|
||||
public:
|
||||
VisibleGameStatusInfo();
|
||||
};
|
||||
|
||||
class VisibleComponentInfo : public CVisibleInfo
|
||||
{
|
||||
std::shared_ptr<CComponent> comp;
|
||||
std::shared_ptr<CTextBox> text;
|
||||
public:
|
||||
VisibleComponentInfo(const Component & compToDisplay, std::string message);
|
||||
};
|
||||
|
||||
enum EState
|
||||
{
|
||||
EMPTY, HERO, TOWN, DATE, GAME, AITURN, COMPONENT
|
||||
};
|
||||
|
||||
std::shared_ptr<CVisibleInfo> visibleInfo;
|
||||
EState state;
|
||||
|
||||
//removes all information about current state, deactivates timer (if any)
|
||||
void reset();
|
||||
|
||||
void tick() override;
|
||||
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
|
||||
void playNewDaySound();
|
||||
public:
|
||||
CInfoBar(const Rect & pos);
|
||||
|
||||
/// show new day/week animation
|
||||
void showDate();
|
||||
|
||||
/// show component for 3 seconds. Used to display picked up resources
|
||||
void showComponent(const Component & comp, std::string message);
|
||||
|
||||
/// print enemy turn progress
|
||||
void startEnemyTurn(PlayerColor color);
|
||||
|
||||
/// reset to default view - selected object
|
||||
void showSelection();
|
||||
|
||||
/// show hero\town information
|
||||
void showHeroSelection(const CGHeroInstance * hero);
|
||||
void showTownSelection(const CGTownInstance * town);
|
||||
|
||||
/// for 3 seconds shows amount of town halls and players status
|
||||
void showGameStatus();
|
||||
};
|
||||
|
339
client/adventureMap/CList.cpp
Normal file
339
client/adventureMap/CList.cpp
Normal file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* CList.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CList.h"
|
||||
|
||||
#include "CAdvMapInt.h"
|
||||
|
||||
#include "../widgets/Images.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/CModHandler.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
CList::CListItem::CListItem(CList * Parent)
|
||||
: CIntObject(LCLICK | RCLICK | HOVER),
|
||||
parent(Parent),
|
||||
selection()
|
||||
{
|
||||
defActions = 255-DISPOSE;
|
||||
}
|
||||
|
||||
CList::CListItem::~CListItem()
|
||||
{
|
||||
}
|
||||
|
||||
void CList::CListItem::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if (down == true)
|
||||
showTooltip();
|
||||
}
|
||||
|
||||
void CList::CListItem::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(down == true)
|
||||
{
|
||||
//second click on already selected item
|
||||
if(parent->selected == this->shared_from_this())
|
||||
{
|
||||
open();
|
||||
}
|
||||
else
|
||||
{
|
||||
//first click - switch selection
|
||||
parent->select(this->shared_from_this());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CList::CListItem::hover(bool on)
|
||||
{
|
||||
if (on)
|
||||
GH.statusbar->write(getHoverText());
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
|
||||
void CList::CListItem::onSelect(bool on)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
selection.reset();
|
||||
if(on)
|
||||
selection = genSelection();
|
||||
select(on);
|
||||
GH.totalRedraw();
|
||||
}
|
||||
|
||||
CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create)
|
||||
: CIntObject(0, position),
|
||||
size(Size),
|
||||
selected(nullptr)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
scrollUp = std::make_shared<CButton>(Point(0, 0), btnUp, CGI->generaltexth->zelp[helpUp]);
|
||||
scrollDown = std::make_shared<CButton>(Point(0, scrollUp->pos.h + 32*(int)size), btnDown, CGI->generaltexth->zelp[helpDown]);
|
||||
|
||||
listBox = std::make_shared<CListBox>(create, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount);
|
||||
|
||||
//assign callback only after list was created
|
||||
scrollUp->addCallback(std::bind(&CListBox::moveToPrev, listBox));
|
||||
scrollDown->addCallback(std::bind(&CListBox::moveToNext, listBox));
|
||||
|
||||
scrollUp->addCallback(std::bind(&CList::update, this));
|
||||
scrollDown->addCallback(std::bind(&CList::update, this));
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void CList::update()
|
||||
{
|
||||
bool onTop = listBox->getPos() == 0;
|
||||
bool onBottom = listBox->getPos() + size >= listBox->size();
|
||||
|
||||
scrollUp->block(onTop);
|
||||
scrollDown->block(onBottom);
|
||||
}
|
||||
|
||||
void CList::select(std::shared_ptr<CListItem> which)
|
||||
{
|
||||
if(selected == which)
|
||||
return;
|
||||
|
||||
if(selected)
|
||||
selected->onSelect(false);
|
||||
|
||||
selected = which;
|
||||
if(which)
|
||||
{
|
||||
which->onSelect(true);
|
||||
onSelect();
|
||||
}
|
||||
}
|
||||
|
||||
int CList::getSelectedIndex()
|
||||
{
|
||||
return static_cast<int>(listBox->getIndexOf(selected));
|
||||
}
|
||||
|
||||
void CList::selectIndex(int which)
|
||||
{
|
||||
if(which < 0)
|
||||
{
|
||||
if(selected)
|
||||
select(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
listBox->scrollTo(which);
|
||||
update();
|
||||
select(std::dynamic_pointer_cast<CListItem>(listBox->getItem(which)));
|
||||
}
|
||||
}
|
||||
|
||||
void CList::selectNext()
|
||||
{
|
||||
int index = getSelectedIndex() + 1;
|
||||
if(index >= listBox->size())
|
||||
index = 0;
|
||||
selectIndex(index);
|
||||
}
|
||||
|
||||
void CList::selectPrev()
|
||||
{
|
||||
int index = getSelectedIndex();
|
||||
if(index <= 0)
|
||||
selectIndex(0);
|
||||
else
|
||||
selectIndex(index-1);
|
||||
}
|
||||
|
||||
CHeroList::CEmptyHeroItem::CEmptyHeroItem()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
movement = std::make_shared<CAnimImage>("IMOBIL", 0, 0, 0, 1);
|
||||
portrait = std::make_shared<CPicture>("HPSXXX", movement->pos.w + 1, 0);
|
||||
mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
|
||||
|
||||
pos.w = mana->pos.w + mana->pos.x - pos.x;
|
||||
pos.h = std::max(std::max<int>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
|
||||
}
|
||||
|
||||
CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero)
|
||||
: CListItem(parent),
|
||||
hero(Hero)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
movement = std::make_shared<CAnimImage>("IMOBIL", 0, 0, 0, 1);
|
||||
portrait = std::make_shared<CAnimImage>("PortraitsSmall", hero->portrait, 0, movement->pos.w + 1);
|
||||
mana = std::make_shared<CAnimImage>("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1);
|
||||
|
||||
pos.w = mana->pos.w + mana->pos.x - pos.x;
|
||||
pos.h = std::max(std::max<int>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void CHeroList::CHeroItem::update()
|
||||
{
|
||||
movement->setFrame(std::min<size_t>(movement->size()-1, hero->movement / 100));
|
||||
mana->setFrame(std::min<size_t>(mana->size()-1, hero->mana / 5));
|
||||
redraw();
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> CHeroList::CHeroItem::genSelection()
|
||||
{
|
||||
return std::make_shared<CPicture>("HPSYYY", movement->pos.w + 1, 0);
|
||||
}
|
||||
|
||||
void CHeroList::CHeroItem::select(bool on)
|
||||
{
|
||||
if(on && adventureInt->selection != hero)
|
||||
adventureInt->select(hero);
|
||||
}
|
||||
|
||||
void CHeroList::CHeroItem::open()
|
||||
{
|
||||
LOCPLINT->openHeroWindow(hero);
|
||||
}
|
||||
|
||||
void CHeroList::CHeroItem::showTooltip()
|
||||
{
|
||||
CRClickPopup::createAndPush(hero, GH.getCursorPosition());
|
||||
}
|
||||
|
||||
std::string CHeroList::CHeroItem::getHoverText()
|
||||
{
|
||||
return boost::str(boost::format(CGI->generaltexth->allTexts[15]) % hero->getNameTranslated() % hero->type->heroClass->getNameTranslated());
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> CHeroList::createHeroItem(size_t index)
|
||||
{
|
||||
if (LOCPLINT->wanderingHeroes.size() > index)
|
||||
return std::make_shared<CHeroItem>(this, LOCPLINT->wanderingHeroes[index]);
|
||||
return std::make_shared<CEmptyHeroItem>();
|
||||
}
|
||||
|
||||
CHeroList::CHeroList(int size, Point position, std::string btnUp, std::string btnDown):
|
||||
CList(size, position, btnUp, btnDown, LOCPLINT->wanderingHeroes.size(), 303, 304, std::bind(&CHeroList::createHeroItem, this, _1))
|
||||
{
|
||||
}
|
||||
|
||||
void CHeroList::select(const CGHeroInstance * hero)
|
||||
{
|
||||
selectIndex(vstd::find_pos(LOCPLINT->wanderingHeroes, hero));
|
||||
}
|
||||
|
||||
void CHeroList::update(const CGHeroInstance * hero)
|
||||
{
|
||||
//this hero is already present, update its status
|
||||
for(auto & elem : listBox->getItems())
|
||||
{
|
||||
auto item = std::dynamic_pointer_cast<CHeroItem>(elem);
|
||||
if(item && item->hero == hero && vstd::contains(LOCPLINT->wanderingHeroes, hero))
|
||||
{
|
||||
item->update();
|
||||
return;
|
||||
}
|
||||
}
|
||||
//simplest solution for now: reset list and restore selection
|
||||
|
||||
listBox->resize(LOCPLINT->wanderingHeroes.size());
|
||||
if (adventureInt->selection)
|
||||
{
|
||||
auto selectedHero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
|
||||
if (selectedHero)
|
||||
select(selectedHero);
|
||||
}
|
||||
CList::update();
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> CTownList::createTownItem(size_t index)
|
||||
{
|
||||
if (LOCPLINT->towns.size() > index)
|
||||
return std::make_shared<CTownItem>(this, LOCPLINT->towns[index]);
|
||||
return std::make_shared<CAnimImage>("ITPA", 0);
|
||||
}
|
||||
|
||||
CTownList::CTownItem::CTownItem(CTownList *parent, const CGTownInstance *Town):
|
||||
CListItem(parent),
|
||||
town(Town)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
picture = std::make_shared<CAnimImage>("ITPA", 0);
|
||||
pos = picture->pos;
|
||||
update();
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> CTownList::CTownItem::genSelection()
|
||||
{
|
||||
return std::make_shared<CAnimImage>("ITPA", 1);
|
||||
}
|
||||
|
||||
void CTownList::CTownItem::update()
|
||||
{
|
||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN];
|
||||
|
||||
picture->setFrame(iconIndex + 2);
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CTownList::CTownItem::select(bool on)
|
||||
{
|
||||
if (on && adventureInt->selection != town)
|
||||
adventureInt->select(town);
|
||||
}
|
||||
|
||||
void CTownList::CTownItem::open()
|
||||
{
|
||||
LOCPLINT->openTownWindow(town);
|
||||
}
|
||||
|
||||
void CTownList::CTownItem::showTooltip()
|
||||
{
|
||||
CRClickPopup::createAndPush(town, GH.getCursorPosition());
|
||||
}
|
||||
|
||||
std::string CTownList::CTownItem::getHoverText()
|
||||
{
|
||||
return town->getObjectName();
|
||||
}
|
||||
|
||||
CTownList::CTownList(int size, Point position, std::string btnUp, std::string btnDown):
|
||||
CList(size, position, btnUp, btnDown, LOCPLINT->towns.size(), 306, 307, std::bind(&CTownList::createTownItem, this, _1))
|
||||
{
|
||||
}
|
||||
|
||||
void CTownList::select(const CGTownInstance * town)
|
||||
{
|
||||
selectIndex(vstd::find_pos(LOCPLINT->towns, town));
|
||||
}
|
||||
|
||||
void CTownList::update(const CGTownInstance *)
|
||||
{
|
||||
//simplest solution for now: reset list and restore selection
|
||||
|
||||
listBox->resize(LOCPLINT->towns.size());
|
||||
if (adventureInt->selection)
|
||||
{
|
||||
auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection);
|
||||
if (town)
|
||||
select(town);
|
||||
}
|
||||
CList::update();
|
||||
}
|
||||
|
176
client/adventureMap/CList.h
Normal file
176
client/adventureMap/CList.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* CList.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
#include "../widgets/ObjectLists.h"
|
||||
#include "../../lib/FunctionList.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CGHeroInstance;
|
||||
class CGTownInstance;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CButton;
|
||||
|
||||
/// Base UI Element for hero\town lists
|
||||
class CList : public CIntObject
|
||||
{
|
||||
protected:
|
||||
class CListItem : public CIntObject, public std::enable_shared_from_this<CListItem>
|
||||
{
|
||||
CList * parent;
|
||||
std::shared_ptr<CIntObject> selection;
|
||||
public:
|
||||
CListItem(CList * parent);
|
||||
~CListItem();
|
||||
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
void onSelect(bool on);
|
||||
|
||||
/// create object with selection rectangle
|
||||
virtual std::shared_ptr<CIntObject> genSelection()=0;
|
||||
/// reaction on item selection (e.g. enable selection border)
|
||||
/// NOTE: item may be deleted in selected state
|
||||
virtual void select(bool on)=0;
|
||||
/// open item (town or hero screen)
|
||||
virtual void open()=0;
|
||||
/// show right-click tooltip
|
||||
virtual void showTooltip()=0;
|
||||
/// get hover text for status bar
|
||||
virtual std::string getHoverText()=0;
|
||||
};
|
||||
|
||||
std::shared_ptr<CListBox> listBox;
|
||||
const size_t size;
|
||||
|
||||
/**
|
||||
* @brief CList - protected constructor
|
||||
* @param size - maximal amount of visible at once items
|
||||
* @param position - cordinates
|
||||
* @param btnUp - path to image to use as top button
|
||||
* @param btnDown - path to image to use as bottom button
|
||||
* @param listAmount - amount of items in the list
|
||||
* @param helpUp - index in zelp.txt for button help tooltip
|
||||
* @param helpDown - index in zelp.txt for button help tooltip
|
||||
* @param create - function for creating items in listbox
|
||||
* @param destroy - function for deleting items in listbox
|
||||
*/
|
||||
CList(int size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown, CListBox::CreateFunc create);
|
||||
|
||||
//for selection\deselection
|
||||
std::shared_ptr<CListItem> selected;
|
||||
void select(std::shared_ptr<CListItem> which);
|
||||
friend class CListItem;
|
||||
|
||||
std::shared_ptr<CButton> scrollUp;
|
||||
std::shared_ptr<CButton> scrollDown;
|
||||
|
||||
/// should be called when list is invalidated
|
||||
void update();
|
||||
|
||||
public:
|
||||
/// functions that will be called when selection changes
|
||||
CFunctionList<void()> onSelect;
|
||||
|
||||
/// return index of currently selected element
|
||||
int getSelectedIndex();
|
||||
|
||||
/// set of methods to switch selection
|
||||
void selectIndex(int which);
|
||||
void selectNext();
|
||||
void selectPrev();
|
||||
};
|
||||
|
||||
/// List of heroes which is shown at the right of the adventure map screen
|
||||
class CHeroList : public CList
|
||||
{
|
||||
/// Empty hero item used as placeholder for unused entries in list
|
||||
class CEmptyHeroItem : public CIntObject
|
||||
{
|
||||
std::shared_ptr<CAnimImage> movement;
|
||||
std::shared_ptr<CAnimImage> mana;
|
||||
std::shared_ptr<CPicture> portrait;
|
||||
public:
|
||||
CEmptyHeroItem();
|
||||
};
|
||||
|
||||
class CHeroItem : public CListItem
|
||||
{
|
||||
std::shared_ptr<CAnimImage> movement;
|
||||
std::shared_ptr<CAnimImage> mana;
|
||||
std::shared_ptr<CAnimImage> portrait;
|
||||
public:
|
||||
const CGHeroInstance * const hero;
|
||||
|
||||
CHeroItem(CHeroList * parent, const CGHeroInstance * hero);
|
||||
|
||||
std::shared_ptr<CIntObject> genSelection() override;
|
||||
void update();
|
||||
void select(bool on) override;
|
||||
void open() override;
|
||||
void showTooltip() override;
|
||||
std::string getHoverText() override;
|
||||
};
|
||||
|
||||
std::shared_ptr<CIntObject> createHeroItem(size_t index);
|
||||
public:
|
||||
/**
|
||||
* @brief CHeroList
|
||||
* @param size, position, btnUp, btnDown @see CList::CList
|
||||
*/
|
||||
CHeroList(int size, Point position, std::string btnUp, std::string btnDown);
|
||||
|
||||
/// Select specific hero and scroll if needed
|
||||
void select(const CGHeroInstance * hero = nullptr);
|
||||
|
||||
/// Update hero. Will add or remove it from the list if needed
|
||||
void update(const CGHeroInstance * hero = nullptr);
|
||||
};
|
||||
|
||||
/// List of towns which is shown at the right of the adventure map screen or in the town screen
|
||||
class CTownList : public CList
|
||||
{
|
||||
class CTownItem : public CListItem
|
||||
{
|
||||
std::shared_ptr<CAnimImage> picture;
|
||||
public:
|
||||
const CGTownInstance * const town;
|
||||
|
||||
CTownItem(CTownList *parent, const CGTownInstance * town);
|
||||
|
||||
std::shared_ptr<CIntObject> genSelection() override;
|
||||
void update();
|
||||
void select(bool on) override;
|
||||
void open() override;
|
||||
void showTooltip() override;
|
||||
std::string getHoverText() override;
|
||||
};
|
||||
|
||||
std::shared_ptr<CIntObject> createTownItem(size_t index);
|
||||
public:
|
||||
/**
|
||||
* @brief CTownList
|
||||
* @param size, position, btnUp, btnDown @see CList::CList
|
||||
*/
|
||||
CTownList(int size, Point position, std::string btnUp, std::string btnDown);
|
||||
|
||||
/// Select specific town and scroll if needed
|
||||
void select(const CGTownInstance * town = nullptr);
|
||||
|
||||
/// Update town. Will add or remove it from the list if needed
|
||||
void update(const CGTownInstance * town = nullptr);
|
||||
};
|
||||
|
317
client/adventureMap/CMinimap.cpp
Normal file
317
client/adventureMap/CMinimap.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* CMinimap.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CMinimap.h"
|
||||
|
||||
#include "CAdvMapInt.h"
|
||||
|
||||
#include "../widgets/Images.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../renderSDL/SDL_PixelAccess.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/TerrainHandler.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapping/CMapDefines.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos)
|
||||
{
|
||||
const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
|
||||
|
||||
// if tile is not visible it will be black on minimap
|
||||
if(!tile)
|
||||
return Colors::BLACK;
|
||||
|
||||
// if object at tile is owned - it will be colored as its owner
|
||||
for (const CGObjectInstance *obj : tile->blockingObjects)
|
||||
{
|
||||
//heroes will be blitted later
|
||||
switch (obj->ID)
|
||||
{
|
||||
case Obj::HERO:
|
||||
case Obj::PRISON:
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerColor player = obj->getOwner();
|
||||
if(player == PlayerColor::NEUTRAL)
|
||||
return *graphics->neutralColor;
|
||||
else
|
||||
if (player < PlayerColor::PLAYER_LIMIT)
|
||||
return graphics->playerColors[player.getNum()];
|
||||
}
|
||||
|
||||
// else - use terrain color (blocked version or normal)
|
||||
const auto & colorPair = parent->colors.find(tile->terType->getId())->second;
|
||||
if (tile->blocked && (!tile->visitable))
|
||||
return colorPair.second;
|
||||
else
|
||||
return colorPair.first;
|
||||
}
|
||||
void CMinimapInstance::tileToPixels (const int3 &tile, int &x, int &y, int toX, int toY)
|
||||
{
|
||||
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
||||
|
||||
double stepX = double(pos.w) / mapSizes.x;
|
||||
double stepY = double(pos.h) / mapSizes.y;
|
||||
|
||||
x = static_cast<int>(toX + stepX * tile.x);
|
||||
y = static_cast<int>(toY + stepY * tile.y);
|
||||
}
|
||||
|
||||
void CMinimapInstance::blitTileWithColor(const SDL_Color &color, const int3 &tile, SDL_Surface *to, int toX, int toY)
|
||||
{
|
||||
//coordinates of rectangle on minimap representing this tile
|
||||
// begin - first to blit, end - first NOT to blit
|
||||
int xBegin, yBegin, xEnd, yEnd;
|
||||
tileToPixels (tile, xBegin, yBegin, toX, toY);
|
||||
tileToPixels (int3 (tile.x + 1, tile.y + 1, tile.z), xEnd, yEnd, toX, toY);
|
||||
|
||||
for (int y=yBegin; y<yEnd; y++)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t*)to->pixels + y * to->pitch + xBegin * minimap->format->BytesPerPixel;
|
||||
|
||||
for (int x=xBegin; x<xEnd; x++)
|
||||
ColorPutter<4, 1>::PutColor(ptr, color);
|
||||
}
|
||||
}
|
||||
|
||||
void CMinimapInstance::refreshTile(const int3 &tile)
|
||||
{
|
||||
blitTileWithColor(getTileColor(int3(tile.x, tile.y, level)), tile, minimap, 0, 0);
|
||||
}
|
||||
|
||||
void CMinimapInstance::drawScaled(int level)
|
||||
{
|
||||
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
||||
|
||||
//size of one map tile on our minimap
|
||||
double stepX = double(pos.w) / mapSizes.x;
|
||||
double stepY = double(pos.h) / mapSizes.y;
|
||||
|
||||
double currY = 0;
|
||||
for (int y=0; y<mapSizes.y; y++, currY += stepY)
|
||||
{
|
||||
double currX = 0;
|
||||
for (int x=0; x<mapSizes.x; x++, currX += stepX)
|
||||
{
|
||||
const SDL_Color &color = getTileColor(int3(x,y,level));
|
||||
|
||||
//coordinates of rectangle on minimap representing this tile
|
||||
// begin - first to blit, end - first NOT to blit
|
||||
int xBegin = static_cast<int>(currX);
|
||||
int yBegin = static_cast<int>(currY);
|
||||
int xEnd = static_cast<int>(currX + stepX);
|
||||
int yEnd = static_cast<int>(currY + stepY);
|
||||
|
||||
for (int y=yBegin; y<yEnd; y++)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t*)minimap->pixels + y * minimap->pitch + xBegin * minimap->format->BytesPerPixel;
|
||||
|
||||
for (int x=xBegin; x<xEnd; x++)
|
||||
ColorPutter<4, 1>::PutColor(ptr, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CMinimapInstance::CMinimapInstance(CMinimap *Parent, int Level):
|
||||
parent(Parent),
|
||||
minimap(CSDL_Ext::createSurfaceWithBpp<4>(parent->pos.w, parent->pos.h)),
|
||||
level(Level)
|
||||
{
|
||||
pos.w = parent->pos.w;
|
||||
pos.h = parent->pos.h;
|
||||
drawScaled(level);
|
||||
}
|
||||
|
||||
CMinimapInstance::~CMinimapInstance()
|
||||
{
|
||||
SDL_FreeSurface(minimap);
|
||||
}
|
||||
|
||||
void CMinimapInstance::showAll(SDL_Surface * to)
|
||||
{
|
||||
blitAtLoc(minimap, 0, 0, to);
|
||||
|
||||
//draw heroes
|
||||
std::vector <const CGHeroInstance *> heroes = LOCPLINT->cb->getHeroesInfo(false); //TODO: do we really need separate function for drawing heroes?
|
||||
for(auto & hero : heroes)
|
||||
{
|
||||
int3 position = hero->visitablePos();
|
||||
if(position.z == level)
|
||||
{
|
||||
const SDL_Color & color = graphics->playerColors[hero->getOwner().getNum()];
|
||||
blitTileWithColor(color, position, to, pos.x, pos.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors()
|
||||
{
|
||||
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > ret;
|
||||
|
||||
for(const auto & terrain : CGI->terrainTypeHandler->objects)
|
||||
{
|
||||
SDL_Color normal = CSDL_Ext::toSDL(terrain->minimapUnblocked);
|
||||
SDL_Color blocked = CSDL_Ext::toSDL(terrain->minimapBlocked);
|
||||
|
||||
ret[terrain->getId()] = std::make_pair(normal, blocked);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CMinimap::CMinimap(const Rect & position)
|
||||
: CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()),
|
||||
level(0),
|
||||
colors(loadColors())
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
pos.w = position.w;
|
||||
pos.h = position.h;
|
||||
|
||||
aiShield = std::make_shared<CPicture>("AIShield");
|
||||
aiShield->disable();
|
||||
}
|
||||
|
||||
int3 CMinimap::translateMousePosition()
|
||||
{
|
||||
// 0 = top-left corner, 1 = bottom-right corner
|
||||
double dx = double(GH.getCursorPosition().x - pos.x) / pos.w;
|
||||
double dy = double(GH.getCursorPosition().y - pos.y) / pos.h;
|
||||
|
||||
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
||||
|
||||
int3 tile ((si32)(mapSizes.x * dx), (si32)(mapSizes.y * dy), level);
|
||||
return tile;
|
||||
}
|
||||
|
||||
void CMinimap::moveAdvMapSelection()
|
||||
{
|
||||
int3 newLocation = translateMousePosition();
|
||||
adventureInt->centerOn(newLocation);
|
||||
|
||||
if (!(adventureInt->active & GENERAL))
|
||||
GH.totalRedraw(); //redraw this as well as inactive adventure map
|
||||
else
|
||||
redraw();//redraw only this
|
||||
}
|
||||
|
||||
void CMinimap::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(down)
|
||||
moveAdvMapSelection();
|
||||
}
|
||||
|
||||
void CMinimap::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
adventureInt->handleRightClick(CGI->generaltexth->zelp[291].second, down);
|
||||
}
|
||||
|
||||
void CMinimap::hover(bool on)
|
||||
{
|
||||
if(on)
|
||||
GH.statusbar->write(CGI->generaltexth->zelp[291].first);
|
||||
else
|
||||
GH.statusbar->clear();
|
||||
}
|
||||
|
||||
void CMinimap::mouseMoved(const SDL_MouseMotionEvent & sEvent)
|
||||
{
|
||||
if(mouseState(EIntObjMouseBtnType::LEFT))
|
||||
moveAdvMapSelection();
|
||||
}
|
||||
|
||||
void CMinimap::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
if(minimap)
|
||||
{
|
||||
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
||||
int3 tileCountOnScreen = adventureInt->terrain.tileCountOnScreen();
|
||||
|
||||
//draw radar
|
||||
Rect oldClip;
|
||||
Rect radar =
|
||||
{
|
||||
si16(adventureInt->position.x * pos.w / mapSizes.x + pos.x),
|
||||
si16(adventureInt->position.y * pos.h / mapSizes.y + pos.y),
|
||||
ui16(tileCountOnScreen.x * pos.w / mapSizes.x),
|
||||
ui16(tileCountOnScreen.y * pos.h / mapSizes.y)
|
||||
};
|
||||
|
||||
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
{
|
||||
// adjusts radar so that it doesn't go out of map in world view mode (since there's no frame)
|
||||
radar.x = std::min<int>(std::max(pos.x, radar.x), pos.x + pos.w - radar.w);
|
||||
radar.y = std::min<int>(std::max(pos.y, radar.y), pos.y + pos.h - radar.h);
|
||||
|
||||
if(radar.x < pos.x && radar.y < pos.y)
|
||||
return; // whole map is visible at once, no point in redrawing border
|
||||
}
|
||||
|
||||
CSDL_Ext::getClipRect(to, oldClip);
|
||||
CSDL_Ext::setClipRect(to, pos);
|
||||
CSDL_Ext::drawDashedBorder(to, radar, Colors::PURPLE);
|
||||
CSDL_Ext::setClipRect(to, oldClip);
|
||||
}
|
||||
}
|
||||
|
||||
void CMinimap::update()
|
||||
{
|
||||
if(aiShield->recActions & UPDATE) //AI turn is going on. There is no need to update minimap
|
||||
return;
|
||||
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
minimap = std::make_shared<CMinimapInstance>(this, level);
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CMinimap::setLevel(int newLevel)
|
||||
{
|
||||
level = newLevel;
|
||||
update();
|
||||
}
|
||||
|
||||
void CMinimap::setAIRadar(bool on)
|
||||
{
|
||||
if(on)
|
||||
{
|
||||
aiShield->enable();
|
||||
minimap.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
aiShield->disable();
|
||||
update();
|
||||
}
|
||||
// this my happen during AI turn when this interface is inactive
|
||||
// force redraw in order to properly update interface
|
||||
GH.totalRedraw();
|
||||
}
|
||||
|
||||
void CMinimap::hideTile(const int3 &pos)
|
||||
{
|
||||
if(minimap)
|
||||
minimap->refreshTile(pos);
|
||||
}
|
||||
|
||||
void CMinimap::showTile(const int3 &pos)
|
||||
{
|
||||
if(minimap)
|
||||
minimap->refreshTile(pos);
|
||||
}
|
||||
|
77
client/adventureMap/CMinimap.h
Normal file
77
client/adventureMap/CMinimap.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* CMinimap.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
|
||||
struct SDL_Color;
|
||||
class CMinimap;
|
||||
|
||||
class CMinimapInstance : public CIntObject
|
||||
{
|
||||
CMinimap * parent;
|
||||
SDL_Surface * minimap;
|
||||
int level;
|
||||
|
||||
//get color of selected tile on minimap
|
||||
const SDL_Color & getTileColor(const int3 & pos);
|
||||
|
||||
void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface * to, int x, int y);
|
||||
|
||||
//draw minimap already scaled.
|
||||
//result is not antialiased. Will result in "missing" pixels on huge maps (>144)
|
||||
void drawScaled(int level);
|
||||
public:
|
||||
CMinimapInstance(CMinimap * parent, int level);
|
||||
~CMinimapInstance();
|
||||
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void tileToPixels (const int3 & tile, int & x, int & y, int toX = 0, int toY = 0);
|
||||
void refreshTile(const int3 & pos);
|
||||
};
|
||||
|
||||
/// Minimap which is displayed at the right upper corner of adventure map
|
||||
class CMinimap : public CIntObject
|
||||
{
|
||||
protected:
|
||||
std::shared_ptr<CPicture> aiShield; //the graphic displayed during AI turn
|
||||
std::shared_ptr<CMinimapInstance> minimap;
|
||||
int level;
|
||||
|
||||
//to initialize colors
|
||||
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > loadColors();
|
||||
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover (bool on) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
|
||||
void moveAdvMapSelection();
|
||||
|
||||
public:
|
||||
// terrainID -> (normal color, blocked color)
|
||||
const std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > colors;
|
||||
|
||||
CMinimap(const Rect & position);
|
||||
|
||||
//should be called to invalidate whole map - different player or level
|
||||
int3 translateMousePosition();
|
||||
void update();
|
||||
void setLevel(int level);
|
||||
void setAIRadar(bool on);
|
||||
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void hideTile(const int3 &pos); //puts FoW
|
||||
void showTile(const int3 &pos); //removes FoW
|
||||
};
|
||||
|
105
client/adventureMap/CResDataBar.cpp
Normal file
105
client/adventureMap/CResDataBar.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* CResDataBar.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CResDataBar.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/Images.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
|
||||
#define ADVOPT (conf.go()->ac)
|
||||
|
||||
void CResDataBar::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
}
|
||||
|
||||
CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist)
|
||||
{
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>(defname, 0, 0);
|
||||
background->colorize(LOCPLINT->playerID);
|
||||
|
||||
pos.w = background->pos.w;
|
||||
pos.h = background->pos.h;
|
||||
|
||||
txtpos.resize(8);
|
||||
for (int i = 0; i < 8 ; i++)
|
||||
{
|
||||
txtpos[i].first = pos.x + offx + resdist*i;
|
||||
txtpos[i].second = pos.y + offy;
|
||||
}
|
||||
txtpos[7].first = txtpos[6].first + datedist;
|
||||
datetext = CGI->generaltexth->allTexts[62]+": %s, " + CGI->generaltexth->allTexts[63]
|
||||
+ ": %s, " + CGI->generaltexth->allTexts[64] + ": %s";
|
||||
addUsedEvents(RCLICK);
|
||||
}
|
||||
|
||||
CResDataBar::CResDataBar()
|
||||
{
|
||||
pos.x += ADVOPT.resdatabarX;
|
||||
pos.y += ADVOPT.resdatabarY;
|
||||
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
background = std::make_shared<CPicture>(ADVOPT.resdatabarG, 0, 0);
|
||||
background->colorize(LOCPLINT->playerID);
|
||||
|
||||
pos.w = background->pos.w;
|
||||
pos.h = background->pos.h;
|
||||
|
||||
txtpos.resize(8);
|
||||
for (int i = 0; i < 8 ; i++)
|
||||
{
|
||||
txtpos[i].first = pos.x + ADVOPT.resOffsetX + ADVOPT.resDist*i;
|
||||
txtpos[i].second = pos.y + ADVOPT.resOffsetY;
|
||||
}
|
||||
txtpos[7].first = txtpos[6].first + ADVOPT.resDateDist;
|
||||
datetext = CGI->generaltexth->allTexts[62]+": %s, " + CGI->generaltexth->allTexts[63]
|
||||
+ ": %s, " + CGI->generaltexth->allTexts[64] + ": %s";
|
||||
}
|
||||
|
||||
CResDataBar::~CResDataBar() = default;
|
||||
|
||||
void CResDataBar::draw(SDL_Surface * to)
|
||||
{
|
||||
//TODO: all this should be labels, but they require proper text update on change
|
||||
for (auto i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1))
|
||||
{
|
||||
std::string text = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(i));
|
||||
|
||||
graphics->fonts[FONT_SMALL]->renderTextLeft(to, text, Colors::WHITE, Point(txtpos[i].first,txtpos[i].second));
|
||||
}
|
||||
std::vector<std::string> temp;
|
||||
|
||||
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::MONTH)));
|
||||
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::WEEK)));
|
||||
temp.push_back(boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK)));
|
||||
|
||||
graphics->fonts[FONT_SMALL]->renderTextLeft(to, CSDL_Ext::processStr(datetext,temp), Colors::WHITE, Point(txtpos[7].first,txtpos[7].second));
|
||||
}
|
||||
|
||||
void CResDataBar::show(SDL_Surface * to)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CResDataBar::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
draw(to);
|
||||
}
|
||||
|
33
client/adventureMap/CResDataBar.h
Normal file
33
client/adventureMap/CResDataBar.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* CResDataBar.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
/// Resources bar which shows information about how many gold, crystals,... you have
|
||||
/// Current date is displayed too
|
||||
class CResDataBar : public CIntObject
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<CPicture> background;
|
||||
|
||||
std::vector<std::pair<int,int> > txtpos;
|
||||
std::string datetext;
|
||||
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
CResDataBar();
|
||||
CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist);
|
||||
~CResDataBar();
|
||||
|
||||
void draw(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
414
client/adventureMap/CTerrainRect.cpp
Normal file
414
client/adventureMap/CTerrainRect.cpp
Normal file
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* CTerrainRect.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CTerrainRect.h"
|
||||
|
||||
#include "mapHandler.h"
|
||||
#include "CAdvMapInt.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/CFadeAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/CPathfinder.h"
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
#define ADVOPT (conf.go()->ac)
|
||||
|
||||
CTerrainRect::CTerrainRect()
|
||||
: fadeSurface(nullptr),
|
||||
lastRedrawStatus(EMapAnimRedrawStatus::OK),
|
||||
fadeAnim(std::make_shared<CFadeAnimation>()),
|
||||
curHoveredTile(-1,-1,-1),
|
||||
currentPath(nullptr)
|
||||
{
|
||||
tilesw=(ADVOPT.advmapW+31)/32;
|
||||
tilesh=(ADVOPT.advmapH+31)/32;
|
||||
pos.x=ADVOPT.advmapX;
|
||||
pos.y=ADVOPT.advmapY;
|
||||
pos.w=ADVOPT.advmapW;
|
||||
pos.h=ADVOPT.advmapH;
|
||||
moveX = moveY = 0;
|
||||
addUsedEvents(LCLICK | RCLICK | MCLICK | HOVER | MOVE);
|
||||
}
|
||||
|
||||
CTerrainRect::~CTerrainRect()
|
||||
{
|
||||
if(fadeSurface)
|
||||
SDL_FreeSurface(fadeSurface);
|
||||
}
|
||||
|
||||
void CTerrainRect::deactivate()
|
||||
{
|
||||
CIntObject::deactivate();
|
||||
curHoveredTile = int3(-1,-1,-1); //we lost info about hovered tile when disabling
|
||||
}
|
||||
|
||||
void CTerrainRect::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
return;
|
||||
if(indeterminate(down))
|
||||
return;
|
||||
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
if(adventureInt->swipeEnabled)
|
||||
{
|
||||
if(handleSwipeStateChange((bool)down == true))
|
||||
{
|
||||
return; // if swipe is enabled, we don't process "down" events and wait for "up" (to make sure this wasn't a swiping gesture)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
if(down == false)
|
||||
return;
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
}
|
||||
#endif
|
||||
int3 mp = whichTileIsIt();
|
||||
if(mp.x < 0 || mp.y < 0 || mp.x >= LOCPLINT->cb->getMapSize().x || mp.y >= LOCPLINT->cb->getMapSize().y)
|
||||
return;
|
||||
|
||||
adventureInt->tileLClicked(mp);
|
||||
}
|
||||
|
||||
void CTerrainRect::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
if(adventureInt->swipeEnabled && isSwiping)
|
||||
return;
|
||||
#endif
|
||||
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
return;
|
||||
int3 mp = whichTileIsIt();
|
||||
|
||||
if(CGI->mh->map->isInTheMap(mp) && down)
|
||||
adventureInt->tileRClicked(mp);
|
||||
}
|
||||
|
||||
void CTerrainRect::clickMiddle(tribool down, bool previousState)
|
||||
{
|
||||
handleSwipeStateChange((bool)down == true);
|
||||
}
|
||||
|
||||
void CTerrainRect::mouseMoved(const SDL_MouseMotionEvent & sEvent)
|
||||
{
|
||||
handleHover(sEvent);
|
||||
|
||||
if(!adventureInt->swipeEnabled)
|
||||
return;
|
||||
|
||||
handleSwipeMove(sEvent);
|
||||
}
|
||||
|
||||
void CTerrainRect::handleSwipeMove(const SDL_MouseMotionEvent & sEvent)
|
||||
{
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
if(sEvent.state == 0 || GH.multifinger) // any "button" is enough on mobile
|
||||
#else
|
||||
if((sEvent.state & SDL_BUTTON_MMASK) == 0) // swipe only works with middle mouse on other platforms
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isSwiping)
|
||||
{
|
||||
// try to distinguish if this touch was meant to be a swipe or just fat-fingering press
|
||||
if(abs(sEvent.x - swipeInitialRealPos.x) > SwipeTouchSlop ||
|
||||
abs(sEvent.y - swipeInitialRealPos.y) > SwipeTouchSlop)
|
||||
{
|
||||
isSwiping = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(isSwiping)
|
||||
{
|
||||
adventureInt->swipeTargetPosition.x =
|
||||
swipeInitialMapPos.x + static_cast<si32>(swipeInitialRealPos.x - sEvent.x) / 32;
|
||||
adventureInt->swipeTargetPosition.y =
|
||||
swipeInitialMapPos.y + static_cast<si32>(swipeInitialRealPos.y - sEvent.y) / 32;
|
||||
adventureInt->swipeMovementRequested = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CTerrainRect::handleSwipeStateChange(bool btnPressed)
|
||||
{
|
||||
if(btnPressed)
|
||||
{
|
||||
swipeInitialRealPos = int3(GH.getCursorPosition().x, GH.getCursorPosition().y, 0);
|
||||
swipeInitialMapPos = int3(adventureInt->position);
|
||||
return true;
|
||||
}
|
||||
else if(isSwiping) // only accept this touch if it wasn't a swipe
|
||||
{
|
||||
isSwiping = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTerrainRect::handleHover(const SDL_MouseMotionEvent &sEvent)
|
||||
{
|
||||
int3 tHovered = whichTileIsIt(sEvent.x, sEvent.y);
|
||||
int3 pom = adventureInt->verifyPos(tHovered);
|
||||
|
||||
if(tHovered != pom) //tile outside the map
|
||||
{
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pom != curHoveredTile)
|
||||
{
|
||||
curHoveredTile = pom;
|
||||
adventureInt->tileHovered(pom);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::hover(bool on)
|
||||
{
|
||||
if (!on)
|
||||
{
|
||||
adventureInt->statusbar->clear();
|
||||
CCS->curh->set(Cursor::Map::POINTER);
|
||||
}
|
||||
//Hoverable::hover(on);
|
||||
}
|
||||
void CTerrainRect::showPath(const Rect & extRect, SDL_Surface * to)
|
||||
{
|
||||
const static int pns[9][9] = {
|
||||
{16, 17, 18, 7, -1, 19, 6, 5, -1},
|
||||
{ 8, 9, 18, 7, -1, 19, 6, -1, 20},
|
||||
{ 8, 1, 10, 7, -1, 19, -1, 21, 20},
|
||||
{24, 17, 18, 15, -1, -1, 6, 5, 4},
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{ 8, 1, 2, -1, -1, 11, 22, 21, 20},
|
||||
{24, 17, -1, 23, -1, 3, 14, 5, 4},
|
||||
{24, -1, 2, 23, -1, 3, 22, 13, 4},
|
||||
{-1, 1, 2, 23, -1, 3, 22, 21, 12}
|
||||
}; //table of magic values TODO meaning, change variable name
|
||||
|
||||
for (int i = 0; i < -1 + (int)currentPath->nodes.size(); ++i)
|
||||
{
|
||||
const int3 &curPos = currentPath->nodes[i].coord, &nextPos = currentPath->nodes[i+1].coord;
|
||||
if(curPos.z != adventureInt->position.z)
|
||||
continue;
|
||||
|
||||
int pn=-1;//number of picture
|
||||
if (i==0) //last tile
|
||||
{
|
||||
int x = 32*(curPos.x-adventureInt->position.x)+CGI->mh->offsetX + pos.x,
|
||||
y = 32*(curPos.y-adventureInt->position.y)+CGI->mh->offsetY + pos.y;
|
||||
if (x<0 || y<0 || x>pos.w || y>pos.h)
|
||||
continue;
|
||||
pn=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int3 &prevPos = currentPath->nodes[i-1].coord;
|
||||
std::vector<CGPathNode> & cv = currentPath->nodes;
|
||||
|
||||
/* Vector directions
|
||||
* 0 1 2
|
||||
* \ | /
|
||||
* 3 - 4 - 5
|
||||
* / | \
|
||||
* 6 7 8
|
||||
*For example:
|
||||
* |
|
||||
* |__\
|
||||
* /
|
||||
* is id1=7, id2=5 (pns[7][5])
|
||||
*/
|
||||
bool pathContinuous = curPos.areNeighbours(nextPos) && curPos.areNeighbours(prevPos);
|
||||
if(pathContinuous && cv[i].action != CGPathNode::EMBARK && cv[i].action != CGPathNode::DISEMBARK)
|
||||
{
|
||||
int id1=(curPos.x-nextPos.x+1)+3*(curPos.y-nextPos.y+1); //Direction of entering vector
|
||||
int id2=(cv[i-1].coord.x-curPos.x+1)+3*(cv[i-1].coord.y-curPos.y+1); //Direction of exiting vector
|
||||
pn=pns[id1][id2];
|
||||
}
|
||||
else //path discontinuity or sea/land transition (eg. when moving through Subterranean Gate or Boat)
|
||||
{
|
||||
pn = 0;
|
||||
}
|
||||
}
|
||||
if (currentPath->nodes[i].turns)
|
||||
pn+=25;
|
||||
if (pn>=0)
|
||||
{
|
||||
const auto arrow = graphics->heroMoveArrows->getImage(pn);
|
||||
|
||||
int x = 32*(curPos.x-adventureInt->position.x)+CGI->mh->offsetX + pos.x,
|
||||
y = 32*(curPos.y-adventureInt->position.y)+CGI->mh->offsetY + pos.y;
|
||||
if (x< -32 || y< -32 || x>pos.w || y>pos.h)
|
||||
continue;
|
||||
int hvx = (x + arrow->width()) - (pos.x + pos.w),
|
||||
hvy = (y + arrow->height()) - (pos.y + pos.h);
|
||||
|
||||
Rect prevClip;
|
||||
CSDL_Ext::getClipRect(to, prevClip);
|
||||
CSDL_Ext::setClipRect(to, extRect); //preventing blitting outside of that rect
|
||||
|
||||
if(ADVOPT.smoothMove) //version for smooth hero move, with pos shifts
|
||||
{
|
||||
if (hvx<0 && hvy<0)
|
||||
{
|
||||
arrow->draw(to, x + moveX, y + moveY);
|
||||
}
|
||||
else if(hvx<0)
|
||||
{
|
||||
Rect srcRect = CSDL_Ext::genRect(arrow->height() - hvy, arrow->width(), 0, 0);
|
||||
arrow->draw(to, x + moveX, y + moveY, &srcRect);
|
||||
}
|
||||
else if (hvy<0)
|
||||
{
|
||||
Rect srcRect = CSDL_Ext::genRect(arrow->height(), arrow->width() - hvx, 0, 0);
|
||||
arrow->draw(to, x + moveX, y + moveY, &srcRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rect srcRect = CSDL_Ext::genRect(arrow->height() - hvy, arrow->width() - hvx, 0, 0);
|
||||
arrow->draw(to, x + moveX, y + moveY, &srcRect);
|
||||
}
|
||||
}
|
||||
else //standard version
|
||||
{
|
||||
if (hvx<0 && hvy<0)
|
||||
{
|
||||
arrow->draw(to, x, y);
|
||||
}
|
||||
else if(hvx<0)
|
||||
{
|
||||
Rect srcRect = CSDL_Ext::genRect(arrow->height() - hvy, arrow->width(), 0, 0);
|
||||
arrow->draw(to, x, y, &srcRect);
|
||||
}
|
||||
else if (hvy<0)
|
||||
{
|
||||
Rect srcRect = CSDL_Ext::genRect(arrow->height(), arrow->width() - hvx, 0, 0);
|
||||
arrow->draw(to, x, y, &srcRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rect srcRect = CSDL_Ext::genRect(arrow->height() - hvy, arrow->width() - hvx, 0, 0);
|
||||
arrow->draw(to, x, y, &srcRect);
|
||||
}
|
||||
}
|
||||
CSDL_Ext::setClipRect(to, prevClip);
|
||||
|
||||
}
|
||||
} //for (int i=0;i<currentPath->nodes.size()-1;i++)
|
||||
}
|
||||
|
||||
void CTerrainRect::show(SDL_Surface * to)
|
||||
{
|
||||
if (adventureInt->mode == EAdvMapMode::NORMAL)
|
||||
{
|
||||
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos);
|
||||
info.otherheroAnim = true;
|
||||
info.anim = adventureInt->anim;
|
||||
info.heroAnim = adventureInt->heroAnim;
|
||||
if (ADVOPT.smoothMove)
|
||||
info.movement = int3(moveX, moveY, 0);
|
||||
|
||||
lastRedrawStatus = CGI->mh->drawTerrainRectNew(to, &info);
|
||||
if (fadeAnim->isFading())
|
||||
{
|
||||
Rect r(pos);
|
||||
fadeAnim->update();
|
||||
fadeAnim->draw(to, r.topLeft());
|
||||
}
|
||||
|
||||
if (currentPath/* && adventureInt->position.z==currentPath->startPos().z*/) //drawing path
|
||||
{
|
||||
showPath(pos, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::showAll(SDL_Surface * to)
|
||||
{
|
||||
// world view map is static and doesn't need redraw every frame
|
||||
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
{
|
||||
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), pos, adventureInt->worldViewIcons);
|
||||
info.scaled = true;
|
||||
info.scale = adventureInt->worldViewScale;
|
||||
adventureInt->worldViewOptions.adjustDrawingInfo(info);
|
||||
CGI->mh->drawTerrainRectNew(to, &info);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::showAnim(SDL_Surface * to)
|
||||
{
|
||||
if (fadeAnim->isFading())
|
||||
show(to);
|
||||
else if (lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
|
||||
show(to); // currently the same; maybe we should pass some flag to map handler so it redraws ONLY tiles that need redraw instead of full
|
||||
}
|
||||
|
||||
int3 CTerrainRect::whichTileIsIt(const int x, const int y)
|
||||
{
|
||||
int3 ret;
|
||||
ret.x = adventureInt->position.x + ((x-CGI->mh->offsetX-pos.x)/32);
|
||||
ret.y = adventureInt->position.y + ((y-CGI->mh->offsetY-pos.y)/32);
|
||||
ret.z = adventureInt->position.z;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int3 CTerrainRect::whichTileIsIt()
|
||||
{
|
||||
return whichTileIsIt(GH.getCursorPosition().x, GH.getCursorPosition().y);
|
||||
}
|
||||
|
||||
int3 CTerrainRect::tileCountOnScreen()
|
||||
{
|
||||
switch (adventureInt->mode)
|
||||
{
|
||||
default:
|
||||
logGlobal->error("Unknown map mode %d", (int)adventureInt->mode);
|
||||
return int3();
|
||||
case EAdvMapMode::NORMAL:
|
||||
return int3(tilesw, tilesh, 1);
|
||||
case EAdvMapMode::WORLD_VIEW:
|
||||
return int3((si32)(tilesw / adventureInt->worldViewScale), (si32)(tilesh / adventureInt->worldViewScale), 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrainRect::fadeFromCurrentView()
|
||||
{
|
||||
if (!ADVOPT.screenFading)
|
||||
return;
|
||||
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
return;
|
||||
|
||||
if (!fadeSurface)
|
||||
fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h);
|
||||
CSDL_Ext::blitSurface(screen, fadeSurface, Point(0,0));
|
||||
fadeAnim->init(CFadeAnimation::EMode::OUT, fadeSurface);
|
||||
}
|
||||
|
||||
bool CTerrainRect::needsAnimUpdate()
|
||||
{
|
||||
return fadeAnim->isFading() || lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED;
|
||||
}
|
||||
|
64
client/adventureMap/CTerrainRect.h
Normal file
64
client/adventureMap/CTerrainRect.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* CTerrainRect.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../../lib/int3.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
struct CGPath;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
enum class EMapAnimRedrawStatus;
|
||||
class CFadeAnimation;
|
||||
|
||||
/// Holds information about which tiles of the terrain are shown/not shown at the screen
|
||||
class CTerrainRect : public CIntObject
|
||||
{
|
||||
SDL_Surface * fadeSurface;
|
||||
EMapAnimRedrawStatus lastRedrawStatus;
|
||||
std::shared_ptr<CFadeAnimation> fadeAnim;
|
||||
|
||||
int3 swipeInitialMapPos;
|
||||
int3 swipeInitialRealPos;
|
||||
bool isSwiping;
|
||||
static constexpr float SwipeTouchSlop = 16.0f;
|
||||
|
||||
void handleHover(const SDL_MouseMotionEvent & sEvent);
|
||||
void handleSwipeMove(const SDL_MouseMotionEvent & sEvent);
|
||||
/// handles start/finish of swipe (press/release of corresponding button); returns true if state change was handled
|
||||
bool handleSwipeStateChange(bool btnPressed);
|
||||
public:
|
||||
int tilesw, tilesh; //width and height of terrain to blit in tiles
|
||||
int3 curHoveredTile;
|
||||
int moveX, moveY; //shift between actual position of screen and the one we wil blit; ranges from -31 to 31 (in pixels)
|
||||
CGPath * currentPath;
|
||||
|
||||
CTerrainRect();
|
||||
virtual ~CTerrainRect();
|
||||
void deactivate() override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void clickMiddle(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void showAnim(SDL_Surface * to);
|
||||
void showPath(const Rect &extRect, SDL_Surface * to);
|
||||
int3 whichTileIsIt(const int x, const int y); //x,y are cursor position
|
||||
int3 whichTileIsIt(); //uses current cursor pos
|
||||
/// @returns number of visible tiles on screen respecting current map scaling
|
||||
int3 tileCountOnScreen();
|
||||
/// animates view by caching current surface and crossfading it with normal screen
|
||||
void fadeFromCurrentView();
|
||||
bool needsAnimUpdate();
|
||||
};
|
||||
|
@@ -11,30 +11,24 @@
|
||||
#include "StdInc.h"
|
||||
#include "mapHandler.h"
|
||||
|
||||
#include "CBitmapHandler.h"
|
||||
#include "gui/CAnimation.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "Graphics.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "CMT.h"
|
||||
#include "CMusicHandler.h"
|
||||
#include "../lib/CRandomGenerator.h"
|
||||
#include "../lib/RoadHandler.h"
|
||||
#include "../lib/RiverHandler.h"
|
||||
#include "../lib/TerrainHandler.h"
|
||||
#include "../lib/filesystem/ResourceID.h"
|
||||
#include "../lib/JsonDetail.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/CFadeAnimation.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../render/Graphics.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/CStopWatch.h"
|
||||
#include "../../lib/CRandomGenerator.h"
|
||||
#include "../../lib/RoadHandler.h"
|
||||
#include "../../lib/RiverHandler.h"
|
||||
#include "../../lib/TerrainHandler.h"
|
||||
|
||||
#define ADVOPT (conf.go()->ac)
|
||||
|
||||
@@ -899,22 +893,22 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
|
||||
{
|
||||
if(parent->map->getTile(int3(pos.x, pos.y, pos.z)).blocked) //temporary hiding blocked positions
|
||||
{
|
||||
static SDL_Surface * block = nullptr;
|
||||
static std::shared_ptr<IImage> block;
|
||||
if (!block)
|
||||
block = BitmapHandler::loadBitmap("blocked");
|
||||
block = IImage::createFromFile("blocked");
|
||||
|
||||
CSDL_Ext::blitSurface(block, targetSurf, realTileRect.topLeft());
|
||||
block->draw(targetSurf, realTileRect.x, realTileRect.y);
|
||||
}
|
||||
}
|
||||
if (settings["session"]["showVisit"].Bool())
|
||||
{
|
||||
if(parent->map->getTile(int3(pos.x, pos.y, pos.z)).visitable) //temporary hiding visitable positions
|
||||
{
|
||||
static SDL_Surface * visit = nullptr;
|
||||
static std::shared_ptr<IImage> visit;
|
||||
if (!visit)
|
||||
visit = BitmapHandler::loadBitmap("visitable");
|
||||
visit = IImage::createFromFile("visitable");
|
||||
|
||||
CSDL_Ext::blitSurface(visit, targetSurf, realTileRect.topLeft());
|
||||
visit->draw(targetSurf, realTileRect.x, realTileRect.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1434,7 +1428,7 @@ std::shared_ptr<IImage> CMapHandler::CMapCache::requestWorldViewCacheOrCreate(CM
|
||||
auto iter = cache.find(key);
|
||||
if(iter == cache.end())
|
||||
{
|
||||
auto scaled = fullSurface->scaleFast(worldViewCachedScale);
|
||||
auto scaled = fullSurface->scaleFast(fullSurface->dimensions() * worldViewCachedScale);
|
||||
cache[key] = scaled;
|
||||
return scaled;
|
||||
}
|
@@ -10,9 +10,9 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../lib/int3.h"
|
||||
#include "../lib/spells/ViewSpellInt.h"
|
||||
#include "../lib/Rect.h"
|
||||
#include "../../lib/int3.h"
|
||||
#include "../../lib/spells/ViewSpellInt.h"
|
||||
#include "../../lib/Rect.h"
|
||||
|
||||
#ifdef IN
|
||||
#undef IN
|
@@ -364,7 +364,7 @@ bool MovementAnimation::init()
|
||||
Point begPosition = owner.stacksController->getStackPositionAtHex(prevHex, stack);
|
||||
Point endPosition = owner.stacksController->getStackPositionAtHex(nextHex, stack);
|
||||
|
||||
timeToMove = AnimationControls::getMovementDuration(stack->getCreature());
|
||||
progressPerSecond = AnimationControls::getMovementDistance(stack->getCreature());
|
||||
|
||||
begX = begPosition.x;
|
||||
begY = begPosition.y;
|
||||
@@ -375,8 +375,7 @@ bool MovementAnimation::init()
|
||||
if (stack->hasBonus(Selector::type()(Bonus::FLYING)))
|
||||
{
|
||||
float distance = static_cast<float>(sqrt(distanceX * distanceX + distanceY * distanceY));
|
||||
|
||||
timeToMove *= AnimationControls::getFlightDistance(stack->getCreature()) / distance;
|
||||
progressPerSecond = AnimationControls::getFlightDistance(stack->getCreature()) / distance;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -384,7 +383,7 @@ bool MovementAnimation::init()
|
||||
|
||||
void MovementAnimation::nextFrame()
|
||||
{
|
||||
progress += float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000 * timeToMove;
|
||||
progress += float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000 * progressPerSecond;
|
||||
|
||||
//moving instructions
|
||||
myAnim->pos.x = static_cast<Sint16>(begX + distanceX * progress );
|
||||
@@ -432,7 +431,7 @@ MovementAnimation::MovementAnimation(BattleInterface & owner, const CStack *stac
|
||||
curentMoveIndex(0),
|
||||
begX(0), begY(0),
|
||||
distanceX(0), distanceY(0),
|
||||
timeToMove(0.0),
|
||||
progressPerSecond(0.0),
|
||||
progress(0.0)
|
||||
{
|
||||
logAnim->debug("Created MovementAnimation for %s", stack->getName());
|
||||
|
@@ -147,8 +147,11 @@ private:
|
||||
double begX, begY; // starting position
|
||||
double distanceX, distanceY; // full movement distance, may be negative if creture moves topleft
|
||||
|
||||
double timeToMove; // full length of movement animation
|
||||
double progress; // range 0 -> 1, indicates move progrees. 0 = movement starts, 1 = move ends
|
||||
/// progress gain per second
|
||||
double progressPerSecond;
|
||||
|
||||
/// range 0 -> 1, indicates move progrees. 0 = movement starts, 1 = move ends
|
||||
double progress;
|
||||
|
||||
public:
|
||||
bool init() override;
|
||||
|
@@ -79,7 +79,7 @@ enum class ECreatureAnimType
|
||||
|
||||
DEAD = 22, // new group, used to show dead stacks. If empty - last frame from "DEATH" will be copied here
|
||||
DEAD_RANGED = 23, // new group, used to show dead stacks (if DEATH_RANGED was used). If empty - last frame from "DEATH_RANGED" will be copied here
|
||||
RESURRECTION = 24, // new group, used for animating resurrection, if empty - reversed "DEATH" animation will be copiend here
|
||||
RESURRECTION = 24, // new group, used for animating resurrection, if empty - reversed "DEATH" animation will be copied here
|
||||
FROZEN = 25, // new group, used when stack animation is paused (e.g. petrified). If empty - consist of first frame from HOLDING animation
|
||||
|
||||
CAST_UP = 30,
|
||||
|
@@ -21,8 +21,8 @@
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/CAnimation.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/battle/BattleAction.h"
|
||||
|
@@ -22,11 +22,11 @@
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../widgets/AdventureMapClasses.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../adventureMap/CInGameConsole.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/BattleFieldHandler.h"
|
||||
|
@@ -24,13 +24,12 @@
|
||||
#include "BattleRenderer.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../windows/CAdvmapInterface.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CStack.h"
|
||||
|
@@ -19,21 +19,21 @@
|
||||
#include "BattleWindow.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/AdventureMapClasses.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../windows/CMessage.h"
|
||||
#include "../windows/CCreatureWindow.h"
|
||||
#include "../windows/CSpellWindow.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../adventureMap/CInGameConsole.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CStack.h"
|
||||
@@ -48,6 +48,9 @@
|
||||
#include "../../lib/CondSh.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
void BattleConsole::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
@@ -218,8 +221,10 @@ void BattleHero::render(Canvas & canvas)
|
||||
canvas.draw(flagFrame, flagPosition);
|
||||
canvas.draw(heroFrame, heroPosition);
|
||||
|
||||
flagCurrentFrame += currentSpeed;
|
||||
currentFrame += currentSpeed;
|
||||
float timePassed = float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000.f;
|
||||
|
||||
flagCurrentFrame += currentSpeed * timePassed;
|
||||
currentFrame += currentSpeed * timePassed;
|
||||
|
||||
if(flagCurrentFrame >= flagAnimation->size(0))
|
||||
flagCurrentFrame -= flagAnimation->size(0);
|
||||
@@ -238,8 +243,8 @@ void BattleHero::pause()
|
||||
|
||||
void BattleHero::play()
|
||||
{
|
||||
//FIXME: un-hardcode speed
|
||||
currentSpeed = 0.25f;
|
||||
//H3 speed: 10 fps ( 100 ms per frame)
|
||||
currentSpeed = 10.f;
|
||||
}
|
||||
|
||||
float BattleHero::getFrame() const
|
||||
@@ -452,19 +457,19 @@ BattleOptionsWindow::BattleOptionsWindow(BattleInterface * owner):
|
||||
|
||||
animSpeeds = std::make_shared<CToggleGroup>([&](int value)
|
||||
{
|
||||
Settings speed = settings.write["battle"]["animationSpeed"];
|
||||
speed->Float() = float(value) / 100;
|
||||
Settings speed = settings.write["battle"]["speedFactor"];
|
||||
speed->Float() = float(value);
|
||||
});
|
||||
|
||||
std::shared_ptr<CToggleButton> toggle;
|
||||
toggle = std::make_shared<CToggleButton>(Point( 28, 225), "sysopb9.def", CGI->generaltexth->zelp[422]);
|
||||
animSpeeds->addToggle(40, toggle);
|
||||
animSpeeds->addToggle(1, toggle);
|
||||
|
||||
toggle = std::make_shared<CToggleButton>(Point( 92, 225), "sysob10.def", CGI->generaltexth->zelp[423]);
|
||||
animSpeeds->addToggle(63, toggle);
|
||||
animSpeeds->addToggle(2, toggle);
|
||||
|
||||
toggle = std::make_shared<CToggleButton>(Point(156, 225), "sysob11.def", CGI->generaltexth->zelp[424]);
|
||||
animSpeeds->addToggle(100, toggle);
|
||||
animSpeeds->addToggle(3, toggle);
|
||||
|
||||
animSpeeds->setSelected(getAnimSpeed());
|
||||
|
||||
@@ -502,9 +507,9 @@ BattleOptionsWindow::BattleOptionsWindow(BattleInterface * owner):
|
||||
int BattleOptionsWindow::getAnimSpeed() const
|
||||
{
|
||||
if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-battle-speed"].isNull())
|
||||
return static_cast<int>(vstd::round(settings["session"]["spectate-battle-speed"].Float() *100));
|
||||
return static_cast<int>(vstd::round(settings["session"]["spectate-battle-speed"].Float()));
|
||||
|
||||
return static_cast<int>(vstd::round(settings["battle"]["animationSpeed"].Float() *100));
|
||||
return static_cast<int>(vstd::round(settings["battle"]["speedFactor"].Float()));
|
||||
}
|
||||
|
||||
void BattleOptionsWindow::bDefaultf()
|
||||
|
@@ -20,9 +20,8 @@
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/Canvas.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/battle/CObstacleInstance.h"
|
||||
|
@@ -15,8 +15,7 @@
|
||||
#include "BattleStacksController.h"
|
||||
#include "CreatureAnimation.h"
|
||||
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
|
||||
@@ -77,7 +76,11 @@ void ProjectileAnimatedMissile::show(Canvas & canvas)
|
||||
|
||||
void ProjectileCatapult::show(Canvas & canvas)
|
||||
{
|
||||
auto image = animation->getImage(frameNum, 0, true);
|
||||
frameProgress += AnimationControls::getSpellEffectSpeed() * GH.mainFPSmng->getElapsedMilliseconds() / 1000;
|
||||
int frameCounter = std::floor(frameProgress);
|
||||
int frameIndex = (frameCounter + 1) % animation->size(0);
|
||||
|
||||
auto image = animation->getImage(frameIndex, 0, true);
|
||||
|
||||
if(image)
|
||||
{
|
||||
@@ -86,8 +89,6 @@ void ProjectileCatapult::show(Canvas & canvas)
|
||||
Point pos(posX, posY);
|
||||
|
||||
canvas.draw(image, pos);
|
||||
|
||||
frameNum = (frameNum + 1) % animation->size(0);
|
||||
}
|
||||
|
||||
float timePassed = GH.mainFPSmng->getElapsedMilliseconds() / 1000.f;
|
||||
@@ -116,10 +117,7 @@ void ProjectileRay::show(Canvas & canvas)
|
||||
for (size_t i = 0; i < rayConfig.size(); ++i)
|
||||
{
|
||||
auto ray = rayConfig[i];
|
||||
SDL_Color beginColor{ ray.r1, ray.g1, ray.b1, ray.a1};
|
||||
SDL_Color endColor { ray.r2, ray.g2, ray.b2, ray.a2};
|
||||
|
||||
canvas.drawLine(Point(x1, y1 + i), Point(x2, y2+i), beginColor, endColor);
|
||||
canvas.drawLine(Point(x1, y1 + i), Point(x2, y2+i), ray.start, ray.end);
|
||||
}
|
||||
}
|
||||
else // draw in vertical axis
|
||||
@@ -133,10 +131,8 @@ void ProjectileRay::show(Canvas & canvas)
|
||||
for (size_t i = 0; i < rayConfig.size(); ++i)
|
||||
{
|
||||
auto ray = rayConfig[i];
|
||||
SDL_Color beginColor{ ray.r1, ray.g1, ray.b1, ray.a1};
|
||||
SDL_Color endColor { ray.r2, ray.g2, ray.b2, ray.a2};
|
||||
|
||||
canvas.drawLine(Point(x1 + i, y1), Point(x2 + i, y2), beginColor, endColor);
|
||||
canvas.drawLine(Point(x1 + i, y1), Point(x2 + i, y2), ray.start, ray.end);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,13 +290,13 @@ void BattleProjectileController::createCatapultProjectile(const CStack * shooter
|
||||
auto catapultProjectile = new ProjectileCatapult();
|
||||
|
||||
catapultProjectile->animation = getProjectileImage(shooter);
|
||||
catapultProjectile->frameNum = 0;
|
||||
catapultProjectile->progress = 0;
|
||||
catapultProjectile->speed = computeProjectileFlightTime(from, dest, AnimationControls::getCatapultSpeed());
|
||||
catapultProjectile->from = from;
|
||||
catapultProjectile->dest = dest;
|
||||
catapultProjectile->shooterID = shooter->ID;
|
||||
catapultProjectile->playing = false;
|
||||
catapultProjectile->frameProgress = 0.f;
|
||||
|
||||
projectiles.push_back(std::shared_ptr<ProjectileBase>(catapultProjectile));
|
||||
}
|
||||
@@ -321,6 +317,7 @@ void BattleProjectileController::createProjectile(const CStack * shooter, Point
|
||||
projectile.reset(rayProjectile);
|
||||
|
||||
rayProjectile->rayConfig = shooterInfo.animation.projectileRay;
|
||||
rayProjectile->speed = computeProjectileFlightTime(from, dest, AnimationControls::getRayProjectileSpeed());
|
||||
}
|
||||
else if (stackUsesMissileProjectile(shooter))
|
||||
{
|
||||
@@ -328,11 +325,12 @@ void BattleProjectileController::createProjectile(const CStack * shooter, Point
|
||||
projectile.reset(missileProjectile);
|
||||
|
||||
missileProjectile->animation = getProjectileImage(shooter);
|
||||
missileProjectile->reverse = !owner.stacksController->facingRight(shooter);
|
||||
missileProjectile->frameNum = computeProjectileFrameID(from, dest, shooter);
|
||||
missileProjectile->reverse = !owner.stacksController->facingRight(shooter);
|
||||
missileProjectile->frameNum = computeProjectileFrameID(from, dest, shooter);
|
||||
missileProjectile->speed = computeProjectileFlightTime(from, dest, AnimationControls::getProjectileSpeed());
|
||||
}
|
||||
|
||||
projectile->speed = computeProjectileFlightTime(from, dest, AnimationControls::getProjectileSpeed());
|
||||
|
||||
projectile->from = from;
|
||||
projectile->dest = dest;
|
||||
projectile->shooterID = shooter->ID;
|
||||
|
@@ -61,7 +61,7 @@ struct ProjectileCatapult : ProjectileBase
|
||||
void show(Canvas & canvas) override;
|
||||
|
||||
std::shared_ptr<CAnimation> animation;
|
||||
int frameNum; // frame to display from projectile animation
|
||||
float frameProgress;
|
||||
};
|
||||
|
||||
/// Projectile for mages/evil eye - render ray expanding from origin position to destination
|
||||
|
@@ -20,8 +20,8 @@
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/IImage.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
|
@@ -25,13 +25,12 @@
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../../lib/spells/ISpellMechanics.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../render/Canvas.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/spells/ISpellMechanics.h"
|
||||
#include "../../lib/battle/BattleHex.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/CStack.h"
|
||||
@@ -89,10 +88,10 @@ BattleStacksController::BattleStacksController(BattleInterface & owner):
|
||||
static const auto shifterNegative = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 1.0f, 0.2f, 0.2f );
|
||||
static const auto shifterNeutral = ColorFilter::genRangeShifter( 0.f, 0.f, 0.f, 1.0f, 1.0f, 0.2f );
|
||||
|
||||
amountNormal->adjustPalette(shifterNormal);
|
||||
amountPositive->adjustPalette(shifterPositive);
|
||||
amountNegative->adjustPalette(shifterNegative);
|
||||
amountEffNeutral->adjustPalette(shifterNeutral);
|
||||
amountNormal->adjustPalette(shifterNormal, 0);
|
||||
amountPositive->adjustPalette(shifterPositive, 0);
|
||||
amountNegative->adjustPalette(shifterNegative, 0);
|
||||
amountEffNeutral->adjustPalette(shifterNeutral, 0);
|
||||
|
||||
//Restore border color {255, 231, 132, 255} to its original state
|
||||
amountNormal->resetPalette(26);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/ColorFilter.h"
|
||||
#include "../render/ColorFilter.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
|
@@ -17,17 +17,17 @@
|
||||
#include "BattleActionsController.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../windows/CSpellWindow.h"
|
||||
#include "../widgets/AdventureMapClasses.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../windows/CMessage.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../adventureMap/CInGameConsole.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
@@ -36,6 +36,9 @@
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/filesystem/ResourceID.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
BattleWindow::BattleWindow(BattleInterface & owner):
|
||||
owner(owner)
|
||||
{
|
||||
|
@@ -13,9 +13,9 @@
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
|
||||
#include "../gui/Canvas.h"
|
||||
#include "../gui/ColorFilter.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/ColorFilter.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
|
||||
static const SDL_Color creatureBlueBorder = { 0, 255, 255, 255 };
|
||||
static const SDL_Color creatureGoldBorder = { 255, 255, 0, 255 };
|
||||
@@ -47,6 +47,15 @@ std::shared_ptr<CreatureAnimation> AnimationControls::getAnimation(const CCreatu
|
||||
return std::make_shared<CreatureAnimation>(creature->animDefName, func);
|
||||
}
|
||||
|
||||
float AnimationControls::getAnimationSpeedFactor()
|
||||
{
|
||||
// according to testing, H3 ratios between slow/medium/fast might actually be 36/60/100 (x1.666)
|
||||
// exact value is hard to tell due to large rounding errors
|
||||
// however we will assume them to be 33/66/100 since these values are better for standard 60 fps displays:
|
||||
// with these numbers, base frame display duration will be 100/66/33 ms - exactly 6/4/2 frames
|
||||
return settings["battle"]["speedFactor"].Float();
|
||||
}
|
||||
|
||||
float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, const CreatureAnimation * anim, ECreatureAnimType type)
|
||||
{
|
||||
assert(creature->animation.walkAnimationTime != 0);
|
||||
@@ -56,20 +65,23 @@ float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, c
|
||||
// possible new fields for creature format:
|
||||
//split "Attack time" into "Shoot Time" and "Cast Time"
|
||||
|
||||
// a lot of arbitrary multipliers, mostly to make animation speed closer to H3
|
||||
const float baseSpeed = 0.1f;
|
||||
const float speedMult = static_cast<float>(settings["battle"]["animationSpeed"].Float());
|
||||
const float speed = baseSpeed / speedMult;
|
||||
// base speed for all H3 animations on slow speed is 10 frames per second (or 100ms per frame)
|
||||
const float baseSpeed = 10.f;
|
||||
const float speed = baseSpeed * getAnimationSpeedFactor();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ECreatureAnimType::MOVING:
|
||||
return static_cast<float>(speed * 2 * creature->animation.walkAnimationTime / anim->framesInGroup(type));
|
||||
return speed / creature->animation.walkAnimationTime;
|
||||
|
||||
case ECreatureAnimType::MOUSEON:
|
||||
return baseSpeed;
|
||||
|
||||
case ECreatureAnimType::HOLDING:
|
||||
return static_cast<float>(baseSpeed * creature->animation.idleAnimationTime / anim->framesInGroup(type));
|
||||
if ( creature->animation.idleAnimationTime > 0.01)
|
||||
return speed / creature->animation.idleAnimationTime;
|
||||
else
|
||||
return 0.f; // this animation is disabled for current creature
|
||||
|
||||
case ECreatureAnimType::SHOOT_UP:
|
||||
case ECreatureAnimType::SHOOT_FRONT:
|
||||
@@ -80,7 +92,7 @@ float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, c
|
||||
case ECreatureAnimType::CAST_DOWN:
|
||||
case ECreatureAnimType::CAST_FRONT:
|
||||
case ECreatureAnimType::CAST_UP:
|
||||
return static_cast<float>(speed * 4 * creature->animation.attackAnimationTime / anim->framesInGroup(type));
|
||||
return speed / creature->animation.attackAnimationTime;
|
||||
|
||||
// as strange as it looks like "attackAnimationTime" does not affects melee attacks
|
||||
// necessary because length of these animations must be same for all creatures for synchronization
|
||||
@@ -95,15 +107,15 @@ float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, c
|
||||
case ECreatureAnimType::GROUP_ATTACK_DOWN:
|
||||
case ECreatureAnimType::GROUP_ATTACK_FRONT:
|
||||
case ECreatureAnimType::GROUP_ATTACK_UP:
|
||||
return speed * 3 / anim->framesInGroup(type);
|
||||
return speed;
|
||||
|
||||
case ECreatureAnimType::TURN_L:
|
||||
case ECreatureAnimType::TURN_R:
|
||||
return speed / 3;
|
||||
return speed;
|
||||
|
||||
case ECreatureAnimType::MOVE_START:
|
||||
case ECreatureAnimType::MOVE_END:
|
||||
return speed / 3;
|
||||
return speed;
|
||||
|
||||
case ECreatureAnimType::DEAD:
|
||||
case ECreatureAnimType::DEAD_RANGED:
|
||||
@@ -116,37 +128,51 @@ float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, c
|
||||
|
||||
float AnimationControls::getProjectileSpeed()
|
||||
{
|
||||
return static_cast<float>(settings["battle"]["animationSpeed"].Float() * 4000);
|
||||
// H3 speed: 1250/2500/3750 pixels per second
|
||||
return static_cast<float>(getAnimationSpeedFactor() * 1250);
|
||||
}
|
||||
|
||||
float AnimationControls::getRayProjectileSpeed()
|
||||
{
|
||||
// H3 speed: 4000/8000/12000 pixels per second
|
||||
return static_cast<float>(getAnimationSpeedFactor() * 4000);
|
||||
}
|
||||
|
||||
float AnimationControls::getCatapultSpeed()
|
||||
{
|
||||
return static_cast<float>(settings["battle"]["animationSpeed"].Float() * 1000);
|
||||
// H3 speed: 200/400/600 pixels per second
|
||||
return static_cast<float>(getAnimationSpeedFactor() * 200);
|
||||
}
|
||||
|
||||
float AnimationControls::getSpellEffectSpeed()
|
||||
{
|
||||
return static_cast<float>(settings["battle"]["animationSpeed"].Float() * 30);
|
||||
// H3 speed: 10/20/30 frames per second
|
||||
return static_cast<float>(getAnimationSpeedFactor() * 10);
|
||||
}
|
||||
|
||||
float AnimationControls::getMovementDuration(const CCreature * creature)
|
||||
float AnimationControls::getMovementDistance(const CCreature * creature)
|
||||
{
|
||||
return static_cast<float>(settings["battle"]["animationSpeed"].Float() * 4 / creature->animation.walkAnimationTime);
|
||||
// H3 speed: 2/4/6 tiles per second
|
||||
return static_cast<float>( 2.0 * getAnimationSpeedFactor() / creature->animation.walkAnimationTime);
|
||||
}
|
||||
|
||||
float AnimationControls::getFlightDistance(const CCreature * creature)
|
||||
{
|
||||
return static_cast<float>(creature->animation.flightAnimationDistance * 200);
|
||||
// Note: for whatever reason, H3 uses "Walk Animation Time" here, even though "Flight Animation Distance" also exists
|
||||
// H3 speed: 250/500/750 pixels per second
|
||||
return static_cast<float>( 250.0 * getAnimationSpeedFactor() / creature->animation.walkAnimationTime);
|
||||
}
|
||||
|
||||
float AnimationControls::getFadeInDuration()
|
||||
{
|
||||
return 1.0f / settings["battle"]["animationSpeed"].Float();
|
||||
// H3 speed: 500/250/166 ms
|
||||
return 0.5f / getAnimationSpeedFactor();
|
||||
}
|
||||
|
||||
float AnimationControls::getObstaclesSpeed()
|
||||
{
|
||||
return 10.0;// does not seems to be affected by animaiton speed settings
|
||||
// H3 speed: 20 frames per second, irregardless of speed setting.
|
||||
return 20.f;
|
||||
}
|
||||
|
||||
ECreatureAnimType CreatureAnimation::getType() const
|
||||
@@ -345,7 +371,7 @@ void CreatureAnimation::nextFrame(Canvas & canvas, const ColorFilter & shifter,
|
||||
genSpecialPalette(SpecialPalette);
|
||||
|
||||
image->setSpecialPallete(SpecialPalette);
|
||||
image->adjustPalette(shifter);
|
||||
image->adjustPalette(shifter, 8);
|
||||
|
||||
canvas.draw(image, pos.topLeft(), Rect(0, 0, pos.w, pos.h));
|
||||
|
||||
@@ -407,7 +433,5 @@ void CreatureAnimation::pause()
|
||||
void CreatureAnimation::play()
|
||||
{
|
||||
//logAnim->trace("Play %s group %d at %d:%d", name, static_cast<int>(getType()), pos.x, pos.y);
|
||||
speed = 0;
|
||||
if(speedController(this, type) != 0)
|
||||
speed = 1 / speedController(this, type);
|
||||
speed = speedController(this, type);
|
||||
}
|
||||
|
@@ -11,7 +11,10 @@
|
||||
|
||||
#include "../../lib/FunctionList.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
|
||||
#include <SDL_pixels.h>
|
||||
|
||||
class CIntObject;
|
||||
class CreatureAnimation;
|
||||
@@ -25,25 +28,32 @@ namespace AnimationControls
|
||||
SDL_Color getGoldBorder();
|
||||
SDL_Color getNoBorder();
|
||||
|
||||
/// returns animation speed factor according to game settings,
|
||||
/// slow speed is considered to be "base speed" and will return 1.0
|
||||
float getAnimationSpeedFactor();
|
||||
|
||||
/// creates animation object with preset speed control
|
||||
std::shared_ptr<CreatureAnimation> getAnimation(const CCreature * creature);
|
||||
|
||||
/// returns animation speed of specific group, taking in mind game setting (in frames per second)
|
||||
float getCreatureAnimationSpeed(const CCreature * creature, const CreatureAnimation * anim, ECreatureAnimType groupID);
|
||||
|
||||
/// returns how far projectile should move per second
|
||||
/// returns how far projectile should move per second, in pixels per second
|
||||
float getProjectileSpeed();
|
||||
|
||||
/// returns speed of catapult projectile, in pixels per second (horizontal axis only)
|
||||
/// returns how far projectile should move per second, in pixels per second
|
||||
float getRayProjectileSpeed();
|
||||
|
||||
/// returns speed of catapult projectile, in pixels per second, on a straight line, without parabola correction
|
||||
float getCatapultSpeed();
|
||||
|
||||
/// returns speed of any spell effects, including any special effects like morale (in frames per second)
|
||||
float getSpellEffectSpeed();
|
||||
|
||||
/// returns duration of full movement animation, in seconds. Needed to move animation on screen
|
||||
float getMovementDuration(const CCreature * creature);
|
||||
/// returns speed of movement animation across the screen, in tiles per second
|
||||
float getMovementDistance(const CCreature * creature);
|
||||
|
||||
/// Returns distance on which flying creatures should during one animation loop
|
||||
/// returns speed of movement animation across the screen, in pixels per seconds
|
||||
float getFlightDistance(const CCreature * creature);
|
||||
|
||||
/// Returns total time for full fade-in effect on newly summoned creatures, in seconds
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -11,19 +11,22 @@
|
||||
#include "CGuiHandler.h"
|
||||
#include "../lib/CondSh.h"
|
||||
|
||||
#include <SDL_timer.h>
|
||||
|
||||
#include "CIntObject.h"
|
||||
#include "CursorHandler.h"
|
||||
#include "SDL_Extensions.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../../lib/CThreadHelper.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../CMT.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../battle/BattleInterface.h"
|
||||
|
||||
#include "../../lib/CThreadHelper.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
#include <SDL_render.h>
|
||||
#include <SDL_timer.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
extern std::queue<SDL_Event> SDLEventsQueue;
|
||||
extern boost::mutex eventsM;
|
||||
|
||||
@@ -474,7 +477,9 @@ void CGuiHandler::handleCurrentEvent( SDL_Event & current )
|
||||
}
|
||||
else if(current.type == SDL_FINGERUP)
|
||||
{
|
||||
#ifndef VCMI_IOS
|
||||
auto fingerCount = SDL_GetNumTouchFingers(current.tfinger.touchId);
|
||||
#endif //VCMI_IOS
|
||||
|
||||
if(isPointerRelativeMode)
|
||||
{
|
||||
@@ -639,12 +644,11 @@ const Point & CGuiHandler::getCursorPosition() const
|
||||
|
||||
void CGuiHandler::drawFPSCounter()
|
||||
{
|
||||
const static SDL_Color yellow = {255, 255, 0, 0};
|
||||
static SDL_Rect overlay = { 0, 0, 64, 32};
|
||||
Uint32 black = SDL_MapRGB(screen->format, 10, 10, 10);
|
||||
uint32_t black = SDL_MapRGB(screen->format, 10, 10, 10);
|
||||
SDL_FillRect(screen, &overlay, black);
|
||||
std::string fps = boost::lexical_cast<std::string>(mainFPSmng->fps);
|
||||
graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, yellow, Point(10, 10));
|
||||
graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, Colors::YELLOW, Point(10, 10));
|
||||
}
|
||||
|
||||
SDL_Keycode CGuiHandler::arrowToNum(SDL_Keycode key)
|
||||
@@ -749,7 +753,8 @@ void CFramerateManager::framerateDelay()
|
||||
// FPS is higher than it should be, then wait some time
|
||||
if(timeElapsed < rateticks)
|
||||
{
|
||||
SDL_Delay((Uint32)ceil(this->rateticks) - timeElapsed);
|
||||
int timeToSleep = (uint32_t)ceil(this->rateticks) - timeElapsed;
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(timeToSleep));
|
||||
}
|
||||
|
||||
currentTicks = SDL_GetTicks();
|
||||
|
@@ -10,8 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/Point.h"
|
||||
|
||||
#include <SDL_events.h>
|
||||
#include "SDL_keycode.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@@ -20,6 +19,7 @@ template <typename T> struct CondSh;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
union SDL_Event;
|
||||
struct SDL_MouseMotionEvent;
|
||||
|
||||
class CFramerateManager;
|
||||
class IStatusBar;
|
||||
|
@@ -11,10 +11,12 @@
|
||||
#include "CIntObject.h"
|
||||
|
||||
#include "CGuiHandler.h"
|
||||
#include "SDL_Extensions.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../windows/CMessage.h"
|
||||
|
||||
#include <SDL_pixels.h>
|
||||
#include <SDL_surface.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
IShowActivatable::IShowActivatable()
|
||||
{
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/Rect.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../render/Graphics.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
class CGuiHandler;
|
||||
|
@@ -11,11 +11,19 @@
|
||||
#include "StdInc.h"
|
||||
#include "CursorHandler.h"
|
||||
|
||||
#include "SDL_Extensions.h"
|
||||
#include "CGuiHandler.h"
|
||||
#include "CAnimation.h"
|
||||
#include "../renderSDL/CursorSoftware.h"
|
||||
#include "../renderSDL/CursorHardware.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../CMT.h"
|
||||
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
#include <SDL_render.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
#ifdef VCMI_APPLE
|
||||
#include <dispatch/dispatch.h>
|
||||
#endif
|
||||
@@ -260,7 +268,7 @@ void CursorHandler::centerCursor()
|
||||
|
||||
void CursorHandler::updateSpellcastCursor()
|
||||
{
|
||||
static const float frameDisplayDuration = 0.1f;
|
||||
static const float frameDisplayDuration = 0.1f; // H3 uses 100 ms per frame
|
||||
|
||||
frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.f;
|
||||
size_t newFrame = frame;
|
||||
@@ -308,148 +316,3 @@ void CursorHandler::show()
|
||||
cursor->setVisible(true);
|
||||
}
|
||||
|
||||
void CursorSoftware::render()
|
||||
{
|
||||
//texture must be updated in the main (renderer) thread, but changes to cursor type may come from other threads
|
||||
if (needUpdate)
|
||||
updateTexture();
|
||||
|
||||
Point renderPos = pos - pivot;
|
||||
|
||||
SDL_Rect destRect;
|
||||
destRect.x = renderPos.x;
|
||||
destRect.y = renderPos.y;
|
||||
destRect.w = 40;
|
||||
destRect.h = 40;
|
||||
|
||||
SDL_RenderCopy(mainRenderer, cursorTexture, nullptr, &destRect);
|
||||
}
|
||||
|
||||
void CursorSoftware::createTexture(const Point & dimensions)
|
||||
{
|
||||
if(cursorTexture)
|
||||
SDL_DestroyTexture(cursorTexture);
|
||||
|
||||
if (cursorSurface)
|
||||
SDL_FreeSurface(cursorSurface);
|
||||
|
||||
cursorSurface = CSDL_Ext::newSurface(dimensions.x, dimensions.y);
|
||||
cursorTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, dimensions.x, dimensions.y);
|
||||
|
||||
SDL_SetSurfaceBlendMode(cursorSurface, SDL_BLENDMODE_NONE);
|
||||
SDL_SetTextureBlendMode(cursorTexture, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
void CursorSoftware::updateTexture()
|
||||
{
|
||||
Point dimensions(-1, -1);
|
||||
|
||||
if (!cursorSurface || Point(cursorSurface->w, cursorSurface->h) != cursorImage->dimensions())
|
||||
createTexture(cursorImage->dimensions());
|
||||
|
||||
CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY);
|
||||
|
||||
cursorImage->draw(cursorSurface);
|
||||
SDL_UpdateTexture(cursorTexture, NULL, cursorSurface->pixels, cursorSurface->pitch);
|
||||
needUpdate = false;
|
||||
}
|
||||
|
||||
void CursorSoftware::setImage(std::shared_ptr<IImage> image, const Point & pivotOffset)
|
||||
{
|
||||
assert(image != nullptr);
|
||||
cursorImage = image;
|
||||
pivot = pivotOffset;
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
void CursorSoftware::setCursorPosition( const Point & newPos )
|
||||
{
|
||||
pos = newPos;
|
||||
}
|
||||
|
||||
void CursorSoftware::setVisible(bool on)
|
||||
{
|
||||
visible = on;
|
||||
}
|
||||
|
||||
CursorSoftware::CursorSoftware():
|
||||
cursorTexture(nullptr),
|
||||
cursorSurface(nullptr),
|
||||
needUpdate(false),
|
||||
visible(false),
|
||||
pivot(0,0)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
|
||||
CursorSoftware::~CursorSoftware()
|
||||
{
|
||||
if(cursorTexture)
|
||||
SDL_DestroyTexture(cursorTexture);
|
||||
|
||||
if (cursorSurface)
|
||||
SDL_FreeSurface(cursorSurface);
|
||||
}
|
||||
|
||||
CursorHardware::CursorHardware():
|
||||
cursor(nullptr)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
|
||||
CursorHardware::~CursorHardware()
|
||||
{
|
||||
if(cursor)
|
||||
SDL_FreeCursor(cursor);
|
||||
}
|
||||
|
||||
void CursorHardware::setVisible(bool on)
|
||||
{
|
||||
#ifdef VCMI_APPLE
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#endif
|
||||
if (on)
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
else
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
#ifdef VCMI_APPLE
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void CursorHardware::setImage(std::shared_ptr<IImage> image, const Point & pivotOffset)
|
||||
{
|
||||
auto cursorSurface = CSDL_Ext::newSurface(image->dimensions().x, image->dimensions().y);
|
||||
|
||||
CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY);
|
||||
|
||||
image->draw(cursorSurface);
|
||||
|
||||
auto oldCursor = cursor;
|
||||
cursor = SDL_CreateColorCursor(cursorSurface, pivotOffset.x, pivotOffset.y);
|
||||
|
||||
if (!cursor)
|
||||
logGlobal->error("Failed to set cursor! SDL says %s", SDL_GetError());
|
||||
|
||||
SDL_FreeSurface(cursorSurface);
|
||||
#ifdef VCMI_APPLE
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#endif
|
||||
SDL_SetCursor(cursor);
|
||||
|
||||
if (oldCursor)
|
||||
SDL_FreeCursor(oldCursor);
|
||||
#ifdef VCMI_APPLE
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void CursorHardware::setCursorPosition( const Point & newPos )
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
||||
void CursorHardware::render()
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
@@ -9,14 +9,12 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class CAnimation;
|
||||
class IImage;
|
||||
struct SDL_Surface;
|
||||
struct SDL_Texture;
|
||||
struct SDL_Cursor;
|
||||
|
||||
#include "../../lib/Point.h"
|
||||
|
||||
class ICursor;
|
||||
class IImage;
|
||||
class CAnimation;
|
||||
|
||||
namespace Cursor
|
||||
{
|
||||
enum class Type {
|
||||
@@ -112,57 +110,6 @@ namespace Cursor
|
||||
};
|
||||
}
|
||||
|
||||
class ICursor
|
||||
{
|
||||
public:
|
||||
virtual ~ICursor() = default;
|
||||
|
||||
virtual void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) = 0;
|
||||
virtual void setCursorPosition( const Point & newPos ) = 0;
|
||||
virtual void render() = 0;
|
||||
virtual void setVisible( bool on) = 0;
|
||||
};
|
||||
|
||||
class CursorHardware : public ICursor
|
||||
{
|
||||
std::shared_ptr<IImage> cursorImage;
|
||||
|
||||
SDL_Cursor * cursor;
|
||||
|
||||
public:
|
||||
CursorHardware();
|
||||
~CursorHardware();
|
||||
|
||||
void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) override;
|
||||
void setCursorPosition( const Point & newPos ) override;
|
||||
void render() override;
|
||||
void setVisible( bool on) override;
|
||||
};
|
||||
|
||||
class CursorSoftware : public ICursor
|
||||
{
|
||||
std::shared_ptr<IImage> cursorImage;
|
||||
|
||||
SDL_Texture * cursorTexture;
|
||||
SDL_Surface * cursorSurface;
|
||||
|
||||
Point pos;
|
||||
Point pivot;
|
||||
bool needUpdate;
|
||||
bool visible;
|
||||
|
||||
void createTexture(const Point & dimensions);
|
||||
void updateTexture();
|
||||
public:
|
||||
CursorSoftware();
|
||||
~CursorSoftware();
|
||||
|
||||
void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) override;
|
||||
void setCursorPosition( const Point & newPos ) override;
|
||||
void render() override;
|
||||
void setVisible( bool on) override;
|
||||
};
|
||||
|
||||
/// handles mouse cursor
|
||||
class CursorHandler final
|
||||
{
|
||||
|
@@ -1,395 +0,0 @@
|
||||
/*
|
||||
* Fonts.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "Fonts.h"
|
||||
|
||||
#include <SDL_ttf.h>
|
||||
|
||||
#include "SDL_Pixels.h"
|
||||
#include "../../lib/JsonNode.h"
|
||||
#include "../../lib/vcmi_endian.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
|
||||
size_t IFont::getStringWidth(const std::string & data) const
|
||||
{
|
||||
size_t width = 0;
|
||||
|
||||
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
|
||||
{
|
||||
width += getGlyphWidth(data.data() + i);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
void IFont::renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
renderText(surface, data, color, pos);
|
||||
}
|
||||
|
||||
void IFont::renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point size((int)getStringWidth(data), (int)getLineHeight());
|
||||
renderText(surface, data, color, pos - size);
|
||||
}
|
||||
|
||||
void IFont::renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point size((int)getStringWidth(data), (int)getLineHeight());
|
||||
renderText(surface, data, color, pos - size / 2);
|
||||
}
|
||||
|
||||
void IFont::renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point currPos = pos;
|
||||
|
||||
for(const std::string & line : data)
|
||||
{
|
||||
renderTextLeft(surface, line, color, currPos);
|
||||
currPos.y += (int)getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point currPos = pos;
|
||||
currPos.y -= (int)data.size() * (int)getLineHeight();
|
||||
|
||||
for(const std::string & line : data)
|
||||
{
|
||||
renderTextRight(surface, line, color, currPos);
|
||||
currPos.y += (int)getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point currPos = pos;
|
||||
currPos.y -= (int)data.size() * (int)getLineHeight() / 2;
|
||||
|
||||
for(const std::string & line : data)
|
||||
{
|
||||
renderTextCenter(surface, line, color, currPos);
|
||||
currPos.y += (int)getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
std::array<CBitmapFont::BitmapChar, CBitmapFont::totalChars> CBitmapFont::loadChars() const
|
||||
{
|
||||
std::array<BitmapChar, totalChars> ret;
|
||||
|
||||
size_t offset = 32;
|
||||
|
||||
for (auto & elem : ret)
|
||||
{
|
||||
elem.leftOffset = read_le_u32(data.first.get() + offset); offset+=4;
|
||||
elem.width = read_le_u32(data.first.get() + offset); offset+=4;
|
||||
elem.rightOffset = read_le_u32(data.first.get() + offset); offset+=4;
|
||||
}
|
||||
|
||||
for (auto & elem : ret)
|
||||
{
|
||||
int pixelOffset = read_le_u32(data.first.get() + offset); offset+=4;
|
||||
elem.pixels = data.first.get() + 4128 + pixelOffset;
|
||||
|
||||
assert(pixelOffset + 4128 < data.second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CBitmapFont::CBitmapFont(const std::string & filename):
|
||||
data(CResourceHandler::get()->load(ResourceID("data/" + filename, EResType::BMP_FONT))->readAll()),
|
||||
chars(loadChars()),
|
||||
height(data.first.get()[5])
|
||||
{}
|
||||
|
||||
size_t CBitmapFont::getLineHeight() const
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
size_t CBitmapFont::getGlyphWidth(const char * data) const
|
||||
{
|
||||
std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0])));
|
||||
|
||||
if (localChar.size() == 1)
|
||||
{
|
||||
const BitmapChar & ch = chars[ui8(localChar[0])];
|
||||
return ch.leftOffset + ch.width + ch.rightOffset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const
|
||||
{
|
||||
Rect clipRect;
|
||||
CSDL_Ext::getClipRect(surface, clipRect);
|
||||
|
||||
posX += character.leftOffset;
|
||||
|
||||
CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
|
||||
|
||||
Uint8 bpp = surface->format->BytesPerPixel;
|
||||
|
||||
// start of line, may differ from 0 due to end of surface or clipped surface
|
||||
int lineBegin = std::max<int>(0, clipRect.y - posY);
|
||||
int lineEnd = std::min<int>(height, clipRect.y + clipRect.h - posY - 1);
|
||||
|
||||
// start end end of each row, may differ from 0
|
||||
int rowBegin = std::max<int>(0, clipRect.x - posX);
|
||||
int rowEnd = std::min<int>(character.width, clipRect.x + clipRect.w - posX - 1);
|
||||
|
||||
//for each line in symbol
|
||||
for(int dy = lineBegin; dy <lineEnd; dy++)
|
||||
{
|
||||
Uint8 *dstLine = (Uint8*)surface->pixels;
|
||||
Uint8 *srcLine = character.pixels;
|
||||
|
||||
// shift source\destination pixels to current position
|
||||
dstLine += (posY+dy) * surface->pitch + posX * bpp;
|
||||
srcLine += dy * character.width;
|
||||
|
||||
//for each column in line
|
||||
for(int dx = rowBegin; dx < rowEnd; dx++)
|
||||
{
|
||||
Uint8* dstPixel = dstLine + dx*bpp;
|
||||
switch(srcLine[dx])
|
||||
{
|
||||
case 1: //black "shadow"
|
||||
colorPutter(dstPixel, 0, 0, 0);
|
||||
break;
|
||||
case 255: //text colour
|
||||
colorPutter(dstPixel, color.r, color.g, color.b);
|
||||
break;
|
||||
default :
|
||||
break; //transparency
|
||||
}
|
||||
}
|
||||
}
|
||||
posX += character.width;
|
||||
posX += character.rightOffset;
|
||||
}
|
||||
|
||||
void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
assert(surface);
|
||||
|
||||
int posX = pos.x;
|
||||
int posY = pos.y;
|
||||
|
||||
// Should be used to detect incorrect text parsing. Disabled right now due to some old UI code (mostly pregame and battles)
|
||||
//assert(data[0] != '{');
|
||||
//assert(data[data.size()-1] != '}');
|
||||
|
||||
SDL_LockSurface(surface);
|
||||
|
||||
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
|
||||
{
|
||||
std::string localChar = Unicode::fromUnicode(data.substr(i, Unicode::getCharacterSize(data[i])));
|
||||
|
||||
if (localChar.size() == 1)
|
||||
renderCharacter(surface, chars[ui8(localChar[0])], color, posX, posY);
|
||||
}
|
||||
SDL_UnlockSurface(surface);
|
||||
}
|
||||
|
||||
std::pair<std::unique_ptr<ui8[]>, ui64> CTrueTypeFont::loadData(const JsonNode & config)
|
||||
{
|
||||
std::string filename = "Data/" + config["file"].String();
|
||||
return CResourceHandler::get()->load(ResourceID(filename, EResType::TTF_FONT))->readAll();
|
||||
}
|
||||
|
||||
TTF_Font * CTrueTypeFont::loadFont(const JsonNode &config)
|
||||
{
|
||||
int pointSize = static_cast<int>(config["size"].Float());
|
||||
|
||||
if(!TTF_WasInit() && TTF_Init()==-1)
|
||||
throw std::runtime_error(std::string("Failed to initialize true type support: ") + TTF_GetError() + "\n");
|
||||
|
||||
return TTF_OpenFontRW(SDL_RWFromConstMem(data.first.get(), (int)data.second), 1, pointSize);
|
||||
}
|
||||
|
||||
int CTrueTypeFont::getFontStyle(const JsonNode &config)
|
||||
{
|
||||
const JsonVector & names = config["style"].Vector();
|
||||
int ret = 0;
|
||||
for(const JsonNode & node : names)
|
||||
{
|
||||
if (node.String() == "bold")
|
||||
ret |= TTF_STYLE_BOLD;
|
||||
else if (node.String() == "italic")
|
||||
ret |= TTF_STYLE_ITALIC;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig):
|
||||
data(loadData(fontConfig)),
|
||||
font(loadFont(fontConfig), TTF_CloseFont),
|
||||
blended(fontConfig["blend"].Bool())
|
||||
{
|
||||
assert(font);
|
||||
|
||||
TTF_SetFontStyle(font.get(), getFontStyle(fontConfig));
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getLineHeight() const
|
||||
{
|
||||
return TTF_FontHeight(font.get());
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getGlyphWidth(const char *data) const
|
||||
{
|
||||
return getStringWidth(std::string(data, Unicode::getCharacterSize(*data)));
|
||||
/*
|
||||
int advance;
|
||||
TTF_GlyphMetrics(font.get(), *data, nullptr, nullptr, nullptr, nullptr, &advance);
|
||||
return advance;
|
||||
*/
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getStringWidth(const std::string & data) const
|
||||
{
|
||||
int width;
|
||||
TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr);
|
||||
return width;
|
||||
}
|
||||
|
||||
void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
|
||||
{
|
||||
SDL_Color black = { 0, 0, 0, SDL_ALPHA_OPAQUE};
|
||||
renderText(surface, data, black, pos + Point(1,1));
|
||||
}
|
||||
|
||||
if (!data.empty())
|
||||
{
|
||||
SDL_Surface * rendered;
|
||||
if (blended)
|
||||
rendered = TTF_RenderUTF8_Blended(font.get(), data.c_str(), color);
|
||||
else
|
||||
rendered = TTF_RenderUTF8_Solid(font.get(), data.c_str(), color);
|
||||
|
||||
assert(rendered);
|
||||
|
||||
CSDL_Ext::blitSurface(rendered, surface, pos);
|
||||
SDL_FreeSurface(rendered);
|
||||
}
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getCharacterDataOffset(size_t index) const
|
||||
{
|
||||
size_t rowSize = (size + 7) / 8; // 1 bit per pixel, rounded up
|
||||
size_t charSize = rowSize * size; // glyph contains "size" rows
|
||||
return index * charSize;
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getCharacterIndex(ui8 first, ui8 second) const
|
||||
{
|
||||
if (second > 0x7f )
|
||||
second--;
|
||||
|
||||
return (first - 0x81) * (12*16 - 2) + (second - 0x40);
|
||||
}
|
||||
|
||||
void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const
|
||||
{
|
||||
//TODO: somewhat duplicated with CBitmapFont::renderCharacter();
|
||||
Rect clipRect;
|
||||
CSDL_Ext::getClipRect(surface, clipRect);
|
||||
|
||||
CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
|
||||
Uint8 bpp = surface->format->BytesPerPixel;
|
||||
|
||||
// start of line, may differ from 0 due to end of surface or clipped surface
|
||||
int lineBegin = std::max<int>(0, clipRect.y - posY);
|
||||
int lineEnd = std::min((int)size, clipRect.y + clipRect.h - posY);
|
||||
|
||||
// start end end of each row, may differ from 0
|
||||
int rowBegin = std::max<int>(0, clipRect.x - posX);
|
||||
int rowEnd = std::min<int>((int)size, clipRect.x + clipRect.w - posX);
|
||||
|
||||
//for each line in symbol
|
||||
for(int dy = lineBegin; dy <lineEnd; dy++)
|
||||
{
|
||||
Uint8 *dstLine = (Uint8*)surface->pixels;
|
||||
Uint8 *source = data.first.get() + getCharacterDataOffset(characterIndex);
|
||||
|
||||
// shift source\destination pixels to current position
|
||||
dstLine += (posY+dy) * surface->pitch + posX * bpp;
|
||||
source += ((size + 7) / 8) * dy;
|
||||
|
||||
//for each column in line
|
||||
for(int dx = rowBegin; dx < rowEnd; dx++)
|
||||
{
|
||||
// select current bit in bitmap
|
||||
int bit = (source[dx / 8] << (dx % 8)) & 0x80;
|
||||
|
||||
Uint8* dstPixel = dstLine + dx*bpp;
|
||||
if (bit != 0)
|
||||
colorPutter(dstPixel, color.r, color.g, color.b);
|
||||
}
|
||||
}
|
||||
posX += (int)size + 1;
|
||||
}
|
||||
|
||||
void CBitmapHanFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
int posX = pos.x;
|
||||
int posY = pos.y;
|
||||
|
||||
SDL_LockSurface(surface);
|
||||
|
||||
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
|
||||
{
|
||||
std::string localChar = Unicode::fromUnicode(data.substr(i, Unicode::getCharacterSize(data[i])));
|
||||
|
||||
if (localChar.size() == 1)
|
||||
fallback->renderCharacter(surface, fallback->chars[ui8(localChar[0])], color, posX, posY);
|
||||
|
||||
if (localChar.size() == 2)
|
||||
renderCharacter(surface, (int)getCharacterIndex(localChar[0], localChar[1]), color, posX, posY);
|
||||
}
|
||||
SDL_UnlockSurface(surface);
|
||||
}
|
||||
|
||||
CBitmapHanFont::CBitmapHanFont(const JsonNode &config):
|
||||
fallback(new CBitmapFont(config["fallback"].String())),
|
||||
data(CResourceHandler::get()->load(ResourceID("data/" + config["name"].String(), EResType::OTHER))->readAll()),
|
||||
size((size_t)config["size"].Float())
|
||||
{
|
||||
// basic tests to make sure that fonts are OK
|
||||
// 1) fonts must contain 190 "sections", 126 symbols each.
|
||||
assert(getCharacterIndex(0xfe, 0xff) == 190*126);
|
||||
// 2) ensure that font size is correct - enough to fit all possible symbols
|
||||
assert(getCharacterDataOffset(getCharacterIndex(0xfe, 0xff)) == data.second);
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getLineHeight() const
|
||||
{
|
||||
return std::max(size + 1, fallback->getLineHeight());
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getGlyphWidth(const char * data) const
|
||||
{
|
||||
std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0])));
|
||||
|
||||
if (localChar.size() == 1)
|
||||
return fallback->getGlyphWidth(data);
|
||||
|
||||
if (localChar.size() == 2)
|
||||
return size + 1;
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Fonts.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class JsonNode;
|
||||
class Point;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
struct SDL_Surface;
|
||||
struct SDL_Color;
|
||||
|
||||
typedef struct _TTF_Font TTF_Font;
|
||||
|
||||
class CBitmapFont;
|
||||
class CBitmapHanFont;
|
||||
|
||||
class IFont
|
||||
{
|
||||
protected:
|
||||
/// Internal function to render font, see renderTextLeft
|
||||
virtual void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const = 0;
|
||||
|
||||
public:
|
||||
virtual ~IFont()
|
||||
{}
|
||||
|
||||
/// Returns height of font
|
||||
virtual size_t getLineHeight() const = 0;
|
||||
/// Returns width, in pixels of a character glyph. Pointer must contain at least characterSize valid bytes
|
||||
virtual size_t getGlyphWidth(const char * data) const = 0;
|
||||
/// Return width of the string
|
||||
virtual size_t getStringWidth(const std::string & data) const;
|
||||
|
||||
/**
|
||||
* @param surface - destination to print text on
|
||||
* @param data - string to print
|
||||
* @param color - font color
|
||||
* @param pos - position of rendered font
|
||||
*/
|
||||
/// pos = topleft corner of the text
|
||||
void renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
|
||||
/// pos = center of the text
|
||||
void renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
|
||||
/// pos = bottomright corner of the text
|
||||
void renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
|
||||
|
||||
/// pos = topleft corner of the text
|
||||
void renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
|
||||
/// pos = center of the text
|
||||
void renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
|
||||
/// pos = bottomright corner of the text
|
||||
void renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
|
||||
};
|
||||
|
||||
class CBitmapFont : public IFont
|
||||
{
|
||||
static const size_t totalChars = 256;
|
||||
|
||||
struct BitmapChar
|
||||
{
|
||||
si32 leftOffset;
|
||||
ui32 width;
|
||||
si32 rightOffset;
|
||||
ui8 *pixels; // pixels of this character, part of BitmapFont::data
|
||||
};
|
||||
|
||||
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
|
||||
|
||||
const std::array<BitmapChar, totalChars> chars;
|
||||
const ui8 height;
|
||||
|
||||
std::array<BitmapChar, totalChars> loadChars() const;
|
||||
|
||||
void renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const;
|
||||
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
|
||||
public:
|
||||
CBitmapFont(const std::string & filename);
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
|
||||
friend class CBitmapHanFont;
|
||||
};
|
||||
|
||||
/// supports multi-byte characters for such languages like Chinese
|
||||
class CBitmapHanFont : public IFont
|
||||
{
|
||||
std::unique_ptr<CBitmapFont> fallback;
|
||||
// data, directly copied from file
|
||||
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
|
||||
|
||||
// size of the font. Not available in file but needed for proper rendering
|
||||
const size_t size;
|
||||
|
||||
size_t getCharacterDataOffset(size_t index) const;
|
||||
size_t getCharacterIndex(ui8 first, ui8 second) const;
|
||||
|
||||
void renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const;
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
|
||||
public:
|
||||
CBitmapHanFont(const JsonNode & config);
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
};
|
||||
|
||||
class CTrueTypeFont : public IFont
|
||||
{
|
||||
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
|
||||
|
||||
const std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> font;
|
||||
const bool blended;
|
||||
|
||||
std::pair<std::unique_ptr<ui8[]>, ui64> loadData(const JsonNode & config);
|
||||
TTF_Font * loadFont(const JsonNode & config);
|
||||
int getFontStyle(const JsonNode & config);
|
||||
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
|
||||
public:
|
||||
CTrueTypeFont(const JsonNode & fontConfig);
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
size_t getStringWidth(const std::string & data) const override;
|
||||
};
|
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
|
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* SDL_Compat.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <SDL_version.h>
|
||||
|
||||
#if (SDL_MAJOR_VERSION == 2)
|
||||
|
||||
#include <SDL_keycode.h>
|
||||
typedef int SDLX_Coord;
|
||||
typedef int SDLX_Size;
|
||||
|
||||
|
||||
#else
|
||||
#error "unknown or unsupported SDL version"
|
||||
#endif
|
||||
|
||||
|
@@ -17,13 +17,10 @@
|
||||
#include "CSelectionBase.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CServerHandler.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../mainmenu/CMainMenu.h"
|
||||
#include "../mainmenu/CPrologEpilogVideo.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
@@ -33,6 +30,9 @@
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
@@ -492,8 +492,8 @@ CBonusSelection::CRegion::CRegion(int id, bool accessible, bool selectable, cons
|
||||
graphicsSelected->disable();
|
||||
graphicsStriped = std::make_shared<CPicture>(prefix + "Co" + suffix + ".BMP");
|
||||
graphicsStriped->disable();
|
||||
pos.w = graphicsNotSelected->bg->w;
|
||||
pos.h = graphicsNotSelected->bg->h;
|
||||
pos.w = graphicsNotSelected->pos.w;
|
||||
pos.h = graphicsNotSelected->pos.h;
|
||||
|
||||
}
|
||||
|
||||
@@ -525,7 +525,7 @@ void CBonusSelection::CRegion::clickLeft(tribool down, bool previousState)
|
||||
if(indeterminate(down))
|
||||
return;
|
||||
|
||||
if(!down && selectable && !CSDL_Ext::isTransparent(graphicsNotSelected->getSurface(), GH.getCursorPosition() - pos.topLeft()))
|
||||
if(!down && selectable && !graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()))
|
||||
{
|
||||
CSH->setCampaignMap(idOfMapAndRegion);
|
||||
}
|
||||
@@ -535,7 +535,7 @@ void CBonusSelection::CRegion::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
// FIXME: For some reason "down" is only ever contain indeterminate_value
|
||||
auto text = CSH->si->campState->camp->scenarios[idOfMapAndRegion].regionText;
|
||||
if(!CSDL_Ext::isTransparent(graphicsNotSelected->getSurface(), GH.getCursorPosition() - pos.topLeft()) && text.size())
|
||||
if(!graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()) && text.size())
|
||||
{
|
||||
CRClickPopup::createAndPush(text);
|
||||
}
|
||||
|
@@ -15,10 +15,8 @@
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/StartInfo.h"
|
||||
#include "../../lib/mapping/CMapInfo.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
|
||||
CCampaignInfoScreen::CCampaignInfoScreen()
|
||||
|
@@ -20,12 +20,10 @@
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CServerHandler.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../mainmenu/CMainMenu.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
@@ -35,6 +33,7 @@
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../render/CAnimation.h"
|
||||
|
||||
#include "../../lib/NetPacksLobby.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
@@ -44,6 +43,8 @@
|
||||
#include "../../lib/mapping/CMapInfo.h"
|
||||
#include "../../lib/serializer/Connection.h"
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
ISelectionScreenInfo::ISelectionScreenInfo(ESelectionScreen ScreenType)
|
||||
: screenType(ScreenType)
|
||||
{
|
||||
@@ -312,7 +313,7 @@ CChatBox::CChatBox(const Rect & rect)
|
||||
type |= REDRAW_PARENT;
|
||||
|
||||
const int height = static_cast<int>(graphics->fonts[FONT_SMALL]->getLineHeight());
|
||||
inputBox = std::make_shared<CTextInput>(Rect(0, rect.h - height, rect.w, height));
|
||||
inputBox = std::make_shared<CTextInput>(Rect(0, rect.h - height, rect.w, height), EFonts::FONT_SMALL, 0);
|
||||
inputBox->removeUsedEvents(KEYBOARD);
|
||||
chatHistory = std::make_shared<CTextBox>("", Rect(0, 0, rect.w, rect.h - height), 1);
|
||||
|
||||
|
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CServerHandler.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
|
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CServerHandler.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
|
@@ -14,10 +14,8 @@
|
||||
#include "CLobbyScreen.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CServerHandler.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
@@ -26,6 +24,7 @@
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../windows/GUIClasses.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../render/CAnimation.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
@@ -36,6 +35,7 @@
|
||||
#include "../../lib/mapping/CMapInfo.h"
|
||||
#include "../../lib/serializer/Connection.h"
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
bool mapSorter::operator()(const std::shared_ptr<CMapInfo> aaa, const std::shared_ptr<CMapInfo> bbb)
|
||||
{
|
||||
|
@@ -14,12 +14,10 @@
|
||||
#include "CMainMenu.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CServerHandler.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
|
@@ -20,7 +20,6 @@
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/filesystem/CCompressedStream.h"
|
||||
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
@@ -28,7 +27,6 @@
|
||||
#include "../../lib/JsonNode.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../../lib/serializer/Connection.h"
|
||||
#include "../../lib/serializer/CTypeList.h"
|
||||
#include "../../lib/VCMIDirs.h"
|
||||
@@ -36,10 +34,8 @@
|
||||
#include "../windows/GUIClasses.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../Client.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
@@ -56,6 +52,7 @@
|
||||
#include "../../lib/CondSh.h"
|
||||
#include "../../lib/mapping/CCampaignHandler.h"
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
@@ -76,11 +73,7 @@ CMenuScreen::CMenuScreen(const JsonNode & configNode)
|
||||
|
||||
background = std::make_shared<CPicture>(config["background"].String());
|
||||
if(config["scalable"].Bool())
|
||||
{
|
||||
if(background->bg->format->palette)
|
||||
background->convertToScreenBPP();
|
||||
background->scaleTo(Point(screen->w, screen->h));
|
||||
}
|
||||
|
||||
pos = background->center();
|
||||
|
||||
|
377
client/render/CAnimation.cpp
Normal file
377
client/render/CAnimation.cpp
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* CAnimation.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CAnimation.h"
|
||||
|
||||
#include "CDefFile.h"
|
||||
|
||||
#include "Graphics.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/JsonNode.h"
|
||||
#include "../renderSDL/SDLImage.h"
|
||||
|
||||
std::shared_ptr<IImage> CAnimation::getFromExtraDef(std::string filename)
|
||||
{
|
||||
size_t pos = filename.find(':');
|
||||
if (pos == -1)
|
||||
return nullptr;
|
||||
CAnimation anim(filename.substr(0, pos));
|
||||
pos++;
|
||||
size_t frame = atoi(filename.c_str()+pos);
|
||||
size_t group = 0;
|
||||
pos = filename.find(':', pos);
|
||||
if (pos != -1)
|
||||
{
|
||||
pos++;
|
||||
group = frame;
|
||||
frame = atoi(filename.c_str()+pos);
|
||||
}
|
||||
anim.load(frame ,group);
|
||||
auto ret = anim.images[group][frame];
|
||||
anim.images.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CAnimation::loadFrame(size_t frame, size_t group)
|
||||
{
|
||||
if(size(group) <= frame)
|
||||
{
|
||||
printError(frame, group, "LoadFrame");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto image = getImage(frame, group, false);
|
||||
if(image)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//try to get image from def
|
||||
if(source[group][frame].getType() == JsonNode::JsonType::DATA_NULL)
|
||||
{
|
||||
if(defFile)
|
||||
{
|
||||
auto frameList = defFile->getEntries();
|
||||
|
||||
if(vstd::contains(frameList, group) && frameList.at(group) > frame) // frame is present
|
||||
{
|
||||
images[group][frame] = std::make_shared<SDLImage>(defFile.get(), frame, group);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// still here? image is missing
|
||||
|
||||
printError(frame, group, "LoadFrame");
|
||||
images[group][frame] = std::make_shared<SDLImage>("DEFAULT");
|
||||
}
|
||||
else //load from separate file
|
||||
{
|
||||
auto img = getFromExtraDef(source[group][frame]["file"].String());
|
||||
if(!img)
|
||||
img = std::make_shared<SDLImage>(source[group][frame]);
|
||||
|
||||
images[group][frame] = img;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAnimation::unloadFrame(size_t frame, size_t group)
|
||||
{
|
||||
auto image = getImage(frame, group, false);
|
||||
if(image)
|
||||
{
|
||||
images[group].erase(frame);
|
||||
|
||||
if(images[group].empty())
|
||||
images.erase(group);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CAnimation::initFromJson(const JsonNode & config)
|
||||
{
|
||||
std::string basepath;
|
||||
basepath = config["basepath"].String();
|
||||
|
||||
JsonNode base(JsonNode::JsonType::DATA_STRUCT);
|
||||
base["margins"] = config["margins"];
|
||||
base["width"] = config["width"];
|
||||
base["height"] = config["height"];
|
||||
|
||||
for(const JsonNode & group : config["sequences"].Vector())
|
||||
{
|
||||
size_t groupID = group["group"].Integer();//TODO: string-to-value conversion("moving" -> MOVING)
|
||||
source[groupID].clear();
|
||||
|
||||
for(const JsonNode & frame : group["frames"].Vector())
|
||||
{
|
||||
JsonNode toAdd(JsonNode::JsonType::DATA_STRUCT);
|
||||
JsonUtils::inherit(toAdd, base);
|
||||
toAdd["file"].String() = basepath + frame.String();
|
||||
source[groupID].push_back(toAdd);
|
||||
}
|
||||
}
|
||||
|
||||
for(const JsonNode & node : config["images"].Vector())
|
||||
{
|
||||
size_t group = node["group"].Integer();
|
||||
size_t frame = node["frame"].Integer();
|
||||
|
||||
if (source[group].size() <= frame)
|
||||
source[group].resize(frame+1);
|
||||
|
||||
JsonNode toAdd(JsonNode::JsonType::DATA_STRUCT);
|
||||
JsonUtils::inherit(toAdd, base);
|
||||
toAdd["file"].String() = basepath + node["file"].String();
|
||||
source[group][frame] = toAdd;
|
||||
}
|
||||
}
|
||||
|
||||
void CAnimation::exportBitmaps(const boost::filesystem::path& path) const
|
||||
{
|
||||
if(images.empty())
|
||||
{
|
||||
logGlobal->error("Nothing to export, animation is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
boost::filesystem::path actualPath = path / "SPRITES" / name;
|
||||
boost::filesystem::create_directories(actualPath);
|
||||
|
||||
size_t counter = 0;
|
||||
|
||||
for(const auto & groupPair : images)
|
||||
{
|
||||
size_t group = groupPair.first;
|
||||
|
||||
for(const auto & imagePair : groupPair.second)
|
||||
{
|
||||
size_t frame = imagePair.first;
|
||||
const auto img = imagePair.second;
|
||||
|
||||
boost::format fmt("%d_%d.bmp");
|
||||
fmt % group % frame;
|
||||
|
||||
img->exportBitmap(actualPath / fmt.str());
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
logGlobal->info("Exported %d frames to %s", counter, actualPath.string());
|
||||
}
|
||||
|
||||
void CAnimation::init()
|
||||
{
|
||||
if(defFile)
|
||||
{
|
||||
const std::map<size_t, size_t> defEntries = defFile->getEntries();
|
||||
|
||||
for (auto & defEntry : defEntries)
|
||||
source[defEntry.first].resize(defEntry.second);
|
||||
}
|
||||
|
||||
ResourceID resID(std::string("SPRITES/") + name, EResType::TEXT);
|
||||
|
||||
if (vstd::contains(graphics->imageLists, resID.getName()))
|
||||
initFromJson(graphics->imageLists[resID.getName()]);
|
||||
|
||||
auto configList = CResourceHandler::get()->getResourcesWithName(resID);
|
||||
|
||||
for(auto & loader : configList)
|
||||
{
|
||||
auto stream = loader->load(resID);
|
||||
std::unique_ptr<ui8[]> textData(new ui8[stream->getSize()]);
|
||||
stream->read(textData.get(), stream->getSize());
|
||||
|
||||
const JsonNode config((char*)textData.get(), stream->getSize());
|
||||
|
||||
initFromJson(config);
|
||||
}
|
||||
}
|
||||
|
||||
void CAnimation::printError(size_t frame, size_t group, std::string type) const
|
||||
{
|
||||
logGlobal->error("%s error: Request for frame not present in CAnimation! File name: %s, Group: %d, Frame: %d", type, name, group, frame);
|
||||
}
|
||||
|
||||
CAnimation::CAnimation(std::string Name):
|
||||
name(Name),
|
||||
preloaded(false),
|
||||
defFile()
|
||||
{
|
||||
size_t dotPos = name.find_last_of('.');
|
||||
if ( dotPos!=-1 )
|
||||
name.erase(dotPos);
|
||||
std::transform(name.begin(), name.end(), name.begin(), toupper);
|
||||
|
||||
ResourceID resource(std::string("SPRITES/") + name, EResType::ANIMATION);
|
||||
|
||||
if(CResourceHandler::get()->existsResource(resource))
|
||||
defFile = std::make_shared<CDefFile>(name);
|
||||
|
||||
init();
|
||||
|
||||
if(source.empty())
|
||||
logAnim->error("Animation %s failed to load", Name);
|
||||
}
|
||||
|
||||
CAnimation::CAnimation():
|
||||
name(""),
|
||||
preloaded(false),
|
||||
defFile()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
CAnimation::~CAnimation() = default;
|
||||
|
||||
void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup)
|
||||
{
|
||||
if(!source.count(sourceGroup))
|
||||
{
|
||||
logAnim->error("Group %d missing in %s", sourceGroup, name);
|
||||
return;
|
||||
}
|
||||
|
||||
if(source[sourceGroup].size() <= sourceFrame)
|
||||
{
|
||||
logAnim->error("Frame [%d %d] missing in %s", sourceGroup, sourceFrame, name);
|
||||
return;
|
||||
}
|
||||
|
||||
//todo: clone actual loaded Image object
|
||||
JsonNode clone(source[sourceGroup][sourceFrame]);
|
||||
|
||||
if(clone.getType() == JsonNode::JsonType::DATA_NULL)
|
||||
{
|
||||
std::string temp = name+":"+boost::lexical_cast<std::string>(sourceGroup)+":"+boost::lexical_cast<std::string>(sourceFrame);
|
||||
clone["file"].String() = temp;
|
||||
}
|
||||
|
||||
source[targetGroup].push_back(clone);
|
||||
|
||||
size_t index = source[targetGroup].size() - 1;
|
||||
|
||||
if(preloaded)
|
||||
load(index, targetGroup);
|
||||
}
|
||||
|
||||
void CAnimation::setCustom(std::string filename, size_t frame, size_t group)
|
||||
{
|
||||
if (source[group].size() <= frame)
|
||||
source[group].resize(frame+1);
|
||||
source[group][frame]["file"].String() = filename;
|
||||
//FIXME: update image if already loaded
|
||||
}
|
||||
|
||||
std::shared_ptr<IImage> CAnimation::getImage(size_t frame, size_t group, bool verbose) const
|
||||
{
|
||||
auto groupIter = images.find(group);
|
||||
if (groupIter != images.end())
|
||||
{
|
||||
auto imageIter = groupIter->second.find(frame);
|
||||
if (imageIter != groupIter->second.end())
|
||||
return imageIter->second;
|
||||
}
|
||||
if (verbose)
|
||||
printError(frame, group, "GetImage");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CAnimation::load()
|
||||
{
|
||||
for (auto & elem : source)
|
||||
for (size_t image=0; image < elem.second.size(); image++)
|
||||
loadFrame(image, elem.first);
|
||||
}
|
||||
|
||||
void CAnimation::unload()
|
||||
{
|
||||
for (auto & elem : source)
|
||||
for (size_t image=0; image < elem.second.size(); image++)
|
||||
unloadFrame(image, elem.first);
|
||||
|
||||
}
|
||||
|
||||
void CAnimation::preload()
|
||||
{
|
||||
if(!preloaded)
|
||||
{
|
||||
preloaded = true;
|
||||
load();
|
||||
}
|
||||
}
|
||||
|
||||
void CAnimation::loadGroup(size_t group)
|
||||
{
|
||||
if (vstd::contains(source, group))
|
||||
for (size_t image=0; image < source[group].size(); image++)
|
||||
loadFrame(image, group);
|
||||
}
|
||||
|
||||
void CAnimation::unloadGroup(size_t group)
|
||||
{
|
||||
if (vstd::contains(source, group))
|
||||
for (size_t image=0; image < source[group].size(); image++)
|
||||
unloadFrame(image, group);
|
||||
}
|
||||
|
||||
void CAnimation::load(size_t frame, size_t group)
|
||||
{
|
||||
loadFrame(frame, group);
|
||||
}
|
||||
|
||||
void CAnimation::unload(size_t frame, size_t group)
|
||||
{
|
||||
unloadFrame(frame, group);
|
||||
}
|
||||
|
||||
size_t CAnimation::size(size_t group) const
|
||||
{
|
||||
auto iter = source.find(group);
|
||||
if (iter != source.end())
|
||||
return iter->second.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CAnimation::horizontalFlip()
|
||||
{
|
||||
for(auto & group : images)
|
||||
for(auto & image : group.second)
|
||||
image.second->horizontalFlip();
|
||||
}
|
||||
|
||||
void CAnimation::verticalFlip()
|
||||
{
|
||||
for(auto & group : images)
|
||||
for(auto & image : group.second)
|
||||
image.second->verticalFlip();
|
||||
}
|
||||
|
||||
void CAnimation::playerColored(PlayerColor player)
|
||||
{
|
||||
for(auto & group : images)
|
||||
for(auto & image : group.second)
|
||||
image.second->playerColored(player);
|
||||
}
|
||||
|
||||
void CAnimation::createFlippedGroup(const size_t sourceGroup, const size_t targetGroup)
|
||||
{
|
||||
for(size_t frame = 0; frame < size(sourceGroup); ++frame)
|
||||
{
|
||||
duplicateImage(sourceGroup, frame, targetGroup);
|
||||
|
||||
auto image = getImage(frame, targetGroup);
|
||||
image->verticalFlip();
|
||||
}
|
||||
}
|
||||
|
@@ -9,77 +9,14 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/vcmi_endian.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
#ifdef IN
|
||||
#undef IN
|
||||
#endif
|
||||
|
||||
#ifdef OUT
|
||||
#undef OUT
|
||||
#endif
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class JsonNode;
|
||||
class Rect;
|
||||
class Point;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
struct SDL_Surface;
|
||||
struct SDL_Color;
|
||||
class CDefFile;
|
||||
class ColorFilter;
|
||||
|
||||
/*
|
||||
* Base class for images, can be used for non-animation pictures as well
|
||||
*/
|
||||
class IImage
|
||||
{
|
||||
public:
|
||||
using SpecialPalette = std::array<SDL_Color, 7>;
|
||||
|
||||
//draws image on surface "where" at position
|
||||
virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, const Rect * src = nullptr) const = 0;
|
||||
virtual void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const = 0;
|
||||
|
||||
virtual std::shared_ptr<IImage> scaleFast(float scale) const = 0;
|
||||
|
||||
virtual void exportBitmap(const boost::filesystem::path & path) const = 0;
|
||||
|
||||
//Change palette to specific player
|
||||
virtual void playerColored(PlayerColor player)=0;
|
||||
|
||||
//set special color for flag
|
||||
virtual void setFlagColor(PlayerColor player)=0;
|
||||
|
||||
//test transparency of specific pixel
|
||||
virtual bool isTransparent(const Point & coords) const = 0;
|
||||
|
||||
virtual Point dimensions() const = 0;
|
||||
int width() const;
|
||||
int height() const;
|
||||
|
||||
//only indexed bitmaps, 16 colors maximum
|
||||
virtual void shiftPalette(int from, int howMany) = 0;
|
||||
virtual void adjustPalette(const ColorFilter & shifter) = 0;
|
||||
virtual void resetPalette(int colorID) = 0;
|
||||
virtual void resetPalette() = 0;
|
||||
|
||||
//only indexed bitmaps with 7 special colors
|
||||
virtual void setSpecialPallete(const SpecialPalette & SpecialPalette) = 0;
|
||||
|
||||
virtual void horizontalFlip() = 0;
|
||||
virtual void verticalFlip() = 0;
|
||||
|
||||
IImage();
|
||||
virtual ~IImage();
|
||||
|
||||
/// loads image from specified file. Returns 0-sized images on failure
|
||||
static std::shared_ptr<IImage> createFromFile( const std::string & path );
|
||||
};
|
||||
class IImage;
|
||||
|
||||
/// Class for handling animation
|
||||
class CAnimation
|
||||
@@ -154,31 +91,3 @@ public:
|
||||
void createFlippedGroup(const size_t sourceGroup, const size_t targetGroup);
|
||||
};
|
||||
|
||||
const float DEFAULT_DELTA = 0.05f;
|
||||
|
||||
class CFadeAnimation
|
||||
{
|
||||
public:
|
||||
enum class EMode
|
||||
{
|
||||
NONE, IN, OUT
|
||||
};
|
||||
private:
|
||||
float delta;
|
||||
SDL_Surface * fadingSurface;
|
||||
bool fading;
|
||||
float fadingCounter;
|
||||
bool shouldFreeSurface;
|
||||
|
||||
float initialCounter() const;
|
||||
bool isFinished() const;
|
||||
public:
|
||||
EMode fadingMode;
|
||||
|
||||
CFadeAnimation();
|
||||
~CFadeAnimation();
|
||||
void init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd = false, float animDelta = DEFAULT_DELTA);
|
||||
void update();
|
||||
void draw(SDL_Surface * targetSurface, const Point & targetPoint);
|
||||
bool isFading() const { return fading; }
|
||||
};
|
@@ -8,13 +8,15 @@
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CBitmapHandler.h"
|
||||
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include <SDL_image.h>
|
||||
#include "CBitmapHandler.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "../lib/vcmi_endian.h"
|
||||
|
||||
#include <SDL_image.h>
|
||||
|
||||
namespace BitmapHandler
|
||||
{
|
||||
SDL_Surface * loadH3PCX(ui8 * data, size_t size);
|
358
client/render/CDefFile.cpp
Normal file
358
client/render/CDefFile.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* CDefFile.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CDefFile.h"
|
||||
|
||||
#include "IImageLoader.h"
|
||||
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/Point.h"
|
||||
|
||||
#include <SDL_pixels.h>
|
||||
|
||||
// Extremely simple file cache. TODO: smarter, more general solution
|
||||
class CFileCache
|
||||
{
|
||||
static const int cacheSize = 50; //Max number of cached files
|
||||
struct FileData
|
||||
{
|
||||
ResourceID name;
|
||||
size_t size;
|
||||
std::unique_ptr<ui8[]> data;
|
||||
|
||||
std::unique_ptr<ui8[]> getCopy()
|
||||
{
|
||||
auto ret = std::unique_ptr<ui8[]>(new ui8[size]);
|
||||
std::copy(data.get(), data.get() + size, ret.get());
|
||||
return ret;
|
||||
}
|
||||
FileData(ResourceID name_, size_t size_, std::unique_ptr<ui8[]> data_):
|
||||
name{std::move(name_)},
|
||||
size{size_},
|
||||
data{std::move(data_)}
|
||||
{}
|
||||
};
|
||||
|
||||
std::deque<FileData> cache;
|
||||
public:
|
||||
std::unique_ptr<ui8[]> getCachedFile(ResourceID rid)
|
||||
{
|
||||
for(auto & file : cache)
|
||||
{
|
||||
if (file.name == rid)
|
||||
return file.getCopy();
|
||||
}
|
||||
// Still here? Cache miss
|
||||
if (cache.size() > cacheSize)
|
||||
cache.pop_front();
|
||||
|
||||
auto data = CResourceHandler::get()->load(rid)->readAll();
|
||||
|
||||
cache.emplace_back(std::move(rid), data.second, std::move(data.first));
|
||||
|
||||
return cache.back().getCopy();
|
||||
}
|
||||
};
|
||||
|
||||
enum class DefType : uint32_t
|
||||
{
|
||||
SPELL = 0x40,
|
||||
SPRITE = 0x41,
|
||||
CREATURE = 0x42,
|
||||
MAP = 0x43,
|
||||
MAP_HERO = 0x44,
|
||||
TERRAIN = 0x45,
|
||||
CURSOR = 0x46,
|
||||
INTERFACE = 0x47,
|
||||
SPRITE_FRAME = 0x48,
|
||||
BATTLE_HERO = 0x49
|
||||
};
|
||||
|
||||
static CFileCache animationCache;
|
||||
|
||||
/*************************************************************************
|
||||
* DefFile, class used for def loading *
|
||||
*************************************************************************/
|
||||
|
||||
bool operator== (const SDL_Color & lhs, const SDL_Color & rhs)
|
||||
{
|
||||
return (lhs.a == rhs.a) && (lhs.b == rhs.b) &&(lhs.g == rhs.g) &&(lhs.r == rhs.r);
|
||||
}
|
||||
|
||||
CDefFile::CDefFile(std::string Name):
|
||||
data(nullptr),
|
||||
palette(nullptr)
|
||||
{
|
||||
//First 8 colors in def palette used for transparency
|
||||
static SDL_Color H3Palette[8] =
|
||||
{
|
||||
{ 0, 0, 0, 0},// transparency ( used in most images )
|
||||
{ 0, 0, 0, 64},// shadow border ( used in battle, adventure map def's )
|
||||
{ 0, 0, 0, 64},// shadow border ( used in fog-of-war def's )
|
||||
{ 0, 0, 0, 128},// shadow body ( used in fog-of-war def's )
|
||||
{ 0, 0, 0, 128},// shadow body ( used in battle, adventure map def's )
|
||||
{ 0, 0, 0, 0},// selection ( used in battle def's )
|
||||
{ 0, 0, 0, 128},// shadow body below selection ( used in battle def's )
|
||||
{ 0, 0, 0, 64} // shadow border below selection ( used in battle def's )
|
||||
};
|
||||
data = animationCache.getCachedFile(ResourceID(std::string("SPRITES/") + Name, EResType::ANIMATION));
|
||||
|
||||
palette = std::unique_ptr<SDL_Color[]>(new SDL_Color[256]);
|
||||
int it = 0;
|
||||
|
||||
ui32 type = read_le_u32(data.get() + it);
|
||||
it+=4;
|
||||
//int width = read_le_u32(data + it); it+=4;//not used
|
||||
//int height = read_le_u32(data + it); it+=4;
|
||||
it+=8;
|
||||
ui32 totalBlocks = read_le_u32(data.get() + it);
|
||||
it+=4;
|
||||
|
||||
for (ui32 i= 0; i<256; i++)
|
||||
{
|
||||
palette[i].r = data[it++];
|
||||
palette[i].g = data[it++];
|
||||
palette[i].b = data[it++];
|
||||
palette[i].a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
|
||||
switch(static_cast<DefType>(type))
|
||||
{
|
||||
case DefType::SPELL:
|
||||
palette[0] = H3Palette[0];
|
||||
break;
|
||||
case DefType::SPRITE:
|
||||
case DefType::SPRITE_FRAME:
|
||||
for(ui32 i= 0; i<8; i++)
|
||||
palette[i] = H3Palette[i];
|
||||
break;
|
||||
case DefType::CREATURE:
|
||||
palette[0] = H3Palette[0];
|
||||
palette[1] = H3Palette[1];
|
||||
palette[4] = H3Palette[4];
|
||||
palette[5] = H3Palette[5];
|
||||
palette[6] = H3Palette[6];
|
||||
palette[7] = H3Palette[7];
|
||||
break;
|
||||
case DefType::MAP:
|
||||
case DefType::MAP_HERO:
|
||||
palette[0] = H3Palette[0];
|
||||
palette[1] = H3Palette[1];
|
||||
palette[4] = H3Palette[4];
|
||||
//5 = owner flag, handled separately
|
||||
break;
|
||||
case DefType::TERRAIN:
|
||||
palette[0] = H3Palette[0];
|
||||
palette[1] = H3Palette[1];
|
||||
palette[2] = H3Palette[2];
|
||||
palette[3] = H3Palette[3];
|
||||
palette[4] = H3Palette[4];
|
||||
break;
|
||||
case DefType::CURSOR:
|
||||
palette[0] = H3Palette[0];
|
||||
break;
|
||||
case DefType::INTERFACE:
|
||||
palette[0] = H3Palette[0];
|
||||
palette[1] = H3Palette[1];
|
||||
palette[4] = H3Palette[4];
|
||||
//player colors handled separately
|
||||
//TODO: disallow colorizing other def types
|
||||
break;
|
||||
case DefType::BATTLE_HERO:
|
||||
palette[0] = H3Palette[0];
|
||||
palette[1] = H3Palette[1];
|
||||
palette[4] = H3Palette[4];
|
||||
break;
|
||||
default:
|
||||
logAnim->error("Unknown def type %d in %s", type, Name);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
for (ui32 i=0; i<totalBlocks; i++)
|
||||
{
|
||||
size_t blockID = read_le_u32(data.get() + it);
|
||||
it+=4;
|
||||
size_t totalEntries = read_le_u32(data.get() + it);
|
||||
it+=12;
|
||||
//8 unknown bytes - skipping
|
||||
|
||||
//13 bytes for name of every frame in this block - not used, skipping
|
||||
it+= 13 * (int)totalEntries;
|
||||
|
||||
for (ui32 j=0; j<totalEntries; j++)
|
||||
{
|
||||
size_t currOffset = read_le_u32(data.get() + it);
|
||||
offset[blockID].push_back(currOffset);
|
||||
it += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDefFile::loadFrame(size_t frame, size_t group, IImageLoader &loader) const
|
||||
{
|
||||
std::map<size_t, std::vector <size_t> >::const_iterator it;
|
||||
it = offset.find(group);
|
||||
assert (it != offset.end());
|
||||
|
||||
const ui8 * FDef = data.get()+it->second[frame];
|
||||
|
||||
const SSpriteDef sd = * reinterpret_cast<const SSpriteDef *>(FDef);
|
||||
SSpriteDef sprite;
|
||||
|
||||
sprite.format = read_le_u32(&sd.format);
|
||||
sprite.fullWidth = read_le_u32(&sd.fullWidth);
|
||||
sprite.fullHeight = read_le_u32(&sd.fullHeight);
|
||||
sprite.width = read_le_u32(&sd.width);
|
||||
sprite.height = read_le_u32(&sd.height);
|
||||
sprite.leftMargin = read_le_u32(&sd.leftMargin);
|
||||
sprite.topMargin = read_le_u32(&sd.topMargin);
|
||||
|
||||
ui32 currentOffset = sizeof(SSpriteDef);
|
||||
|
||||
//special case for some "old" format defs (SGTWMTA.DEF and SGTWMTB.DEF)
|
||||
|
||||
if(sprite.format == 1 && sprite.width > sprite.fullWidth && sprite.height > sprite.fullHeight)
|
||||
{
|
||||
sprite.leftMargin = 0;
|
||||
sprite.topMargin = 0;
|
||||
sprite.width = sprite.fullWidth;
|
||||
sprite.height = sprite.fullHeight;
|
||||
|
||||
currentOffset -= 16;
|
||||
}
|
||||
|
||||
const ui32 BaseOffset = currentOffset;
|
||||
|
||||
loader.init(Point(sprite.width, sprite.height),
|
||||
Point(sprite.leftMargin, sprite.topMargin),
|
||||
Point(sprite.fullWidth, sprite.fullHeight), palette.get());
|
||||
|
||||
switch(sprite.format)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
//pixel data is not compressed, copy data to surface
|
||||
for(ui32 i=0; i<sprite.height; i++)
|
||||
{
|
||||
loader.load(sprite.width, FDef + currentOffset);
|
||||
currentOffset += sprite.width;
|
||||
loader.endLine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
//for each line we have offset of pixel data
|
||||
const ui32 * RWEntriesLoc = reinterpret_cast<const ui32 *>(FDef+currentOffset);
|
||||
currentOffset += sizeof(ui32) * sprite.height;
|
||||
|
||||
for(ui32 i=0; i<sprite.height; i++)
|
||||
{
|
||||
//get position of the line
|
||||
currentOffset=BaseOffset + read_le_u32(RWEntriesLoc + i);
|
||||
ui32 TotalRowLength = 0;
|
||||
|
||||
while(TotalRowLength<sprite.width)
|
||||
{
|
||||
ui8 segmentType = FDef[currentOffset++];
|
||||
ui32 length = FDef[currentOffset++] + 1;
|
||||
|
||||
if(segmentType==0xFF)//Raw data
|
||||
{
|
||||
loader.load(length, FDef + currentOffset);
|
||||
currentOffset+=length;
|
||||
}
|
||||
else// RLE
|
||||
{
|
||||
loader.load(length, segmentType);
|
||||
}
|
||||
TotalRowLength += length;
|
||||
}
|
||||
|
||||
loader.endLine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
currentOffset = BaseOffset + read_le_u16(FDef + BaseOffset);
|
||||
|
||||
for(ui32 i=0; i<sprite.height; i++)
|
||||
{
|
||||
ui32 TotalRowLength=0;
|
||||
|
||||
while(TotalRowLength<sprite.width)
|
||||
{
|
||||
ui8 segment=FDef[currentOffset++];
|
||||
ui8 code = segment / 32;
|
||||
ui8 length = (segment & 31) + 1;
|
||||
|
||||
if(code==7)//Raw data
|
||||
{
|
||||
loader.load(length, FDef + currentOffset);
|
||||
currentOffset += length;
|
||||
}
|
||||
else//RLE
|
||||
{
|
||||
loader.load(length, code);
|
||||
}
|
||||
TotalRowLength+=length;
|
||||
}
|
||||
loader.endLine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
for(ui32 i=0; i<sprite.height; i++)
|
||||
{
|
||||
currentOffset = BaseOffset + read_le_u16(FDef + BaseOffset+i*2*(sprite.width/32));
|
||||
ui32 TotalRowLength=0;
|
||||
|
||||
while(TotalRowLength<sprite.width)
|
||||
{
|
||||
ui8 segment = FDef[currentOffset++];
|
||||
ui8 code = segment / 32;
|
||||
ui8 length = (segment & 31) + 1;
|
||||
|
||||
if(code==7)//Raw data
|
||||
{
|
||||
loader.load(length, FDef + currentOffset);
|
||||
currentOffset += length;
|
||||
}
|
||||
else//RLE
|
||||
{
|
||||
loader.load(length, code);
|
||||
}
|
||||
TotalRowLength += length;
|
||||
}
|
||||
loader.endLine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
logGlobal->error("Error: unsupported format of def file: %d", sprite.format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CDefFile::~CDefFile() = default;
|
||||
|
||||
const std::map<size_t, size_t > CDefFile::getEntries() const
|
||||
{
|
||||
std::map<size_t, size_t > ret;
|
||||
|
||||
for (auto & elem : offset)
|
||||
ret[elem.first] = elem.second.size();
|
||||
return ret;
|
||||
}
|
||||
|
51
client/render/CDefFile.h
Normal file
51
client/render/CDefFile.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* CDefFile.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/vcmi_endian.h"
|
||||
|
||||
class IImageLoader;
|
||||
struct SDL_Color;
|
||||
|
||||
/// Class for def loading
|
||||
/// After loading will store general info (palette and frame offsets) and pointer to file itself
|
||||
class CDefFile
|
||||
{
|
||||
private:
|
||||
|
||||
PACKED_STRUCT_BEGIN
|
||||
struct SSpriteDef
|
||||
{
|
||||
ui32 size;
|
||||
ui32 format; /// format in which pixel data is stored
|
||||
ui32 fullWidth; /// full width and height of frame, including borders
|
||||
ui32 fullHeight;
|
||||
ui32 width; /// width and height of pixel data, borders excluded
|
||||
ui32 height;
|
||||
si32 leftMargin;
|
||||
si32 topMargin;
|
||||
} PACKED_STRUCT_END;
|
||||
//offset[group][frame] - offset of frame data in file
|
||||
std::map<size_t, std::vector <size_t> > offset;
|
||||
|
||||
std::unique_ptr<ui8[]> data;
|
||||
std::unique_ptr<SDL_Color[]> palette;
|
||||
|
||||
public:
|
||||
CDefFile(std::string Name);
|
||||
~CDefFile();
|
||||
|
||||
//load frame as SDL_Surface
|
||||
void loadFrame(size_t frame, size_t group, IImageLoader &loader) const;
|
||||
|
||||
const std::map<size_t, size_t> getEntries() const;
|
||||
};
|
||||
|
||||
|
101
client/render/CFadeAnimation.cpp
Normal file
101
client/render/CFadeAnimation.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* CFadeAnimation.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CFadeAnimation.h"
|
||||
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
float CFadeAnimation::initialCounter() const
|
||||
{
|
||||
if (fadingMode == EMode::OUT)
|
||||
return 1.0f;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void CFadeAnimation::update()
|
||||
{
|
||||
if (!fading)
|
||||
return;
|
||||
|
||||
if (fadingMode == EMode::OUT)
|
||||
fadingCounter -= delta;
|
||||
else
|
||||
fadingCounter += delta;
|
||||
|
||||
if (isFinished())
|
||||
{
|
||||
fading = false;
|
||||
if (shouldFreeSurface)
|
||||
{
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
fadingSurface = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CFadeAnimation::isFinished() const
|
||||
{
|
||||
if (fadingMode == EMode::OUT)
|
||||
return fadingCounter <= 0.0f;
|
||||
return fadingCounter >= 1.0f;
|
||||
}
|
||||
|
||||
CFadeAnimation::CFadeAnimation()
|
||||
: delta(0), fadingSurface(nullptr), fading(false), fadingCounter(0), shouldFreeSurface(false),
|
||||
fadingMode(EMode::NONE)
|
||||
{
|
||||
}
|
||||
|
||||
CFadeAnimation::~CFadeAnimation()
|
||||
{
|
||||
if (fadingSurface && shouldFreeSurface)
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
}
|
||||
|
||||
void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd, float animDelta)
|
||||
{
|
||||
if (fading)
|
||||
{
|
||||
// in that case, immediately finish the previous fade
|
||||
// (alternatively, we could just return here to ignore the new fade request until this one finished (but we'd need to free the passed bitmap to avoid leaks))
|
||||
logGlobal->warn("Tried to init fading animation that is already running.");
|
||||
if (fadingSurface && shouldFreeSurface)
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
}
|
||||
if (animDelta <= 0.0f)
|
||||
{
|
||||
logGlobal->warn("Fade anim: delta should be positive; %f given.", animDelta);
|
||||
animDelta = DEFAULT_DELTA;
|
||||
}
|
||||
|
||||
if (sourceSurface)
|
||||
fadingSurface = sourceSurface;
|
||||
|
||||
delta = animDelta;
|
||||
fadingMode = mode;
|
||||
fadingCounter = initialCounter();
|
||||
fading = true;
|
||||
shouldFreeSurface = freeSurfaceAtEnd;
|
||||
}
|
||||
|
||||
void CFadeAnimation::draw(SDL_Surface * targetSurface, const Point &targetPoint)
|
||||
{
|
||||
if (!fading || !fadingSurface || fadingMode == EMode::NONE)
|
||||
{
|
||||
fading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
CSDL_Ext::setAlpha(fadingSurface, (int)(fadingCounter * 255));
|
||||
CSDL_Ext::blitSurface(fadingSurface, targetSurface, targetPoint); //FIXME
|
||||
CSDL_Ext::setAlpha(fadingSurface, 255);
|
||||
}
|
53
client/render/CFadeAnimation.h
Normal file
53
client/render/CFadeAnimation.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* CFadeAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef IN
|
||||
#undef IN
|
||||
#endif
|
||||
|
||||
#ifdef OUT
|
||||
#undef OUT
|
||||
#endif
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class Point;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
struct SDL_Surface;
|
||||
|
||||
const float DEFAULT_DELTA = 0.05f;
|
||||
|
||||
class CFadeAnimation
|
||||
{
|
||||
public:
|
||||
enum class EMode
|
||||
{
|
||||
NONE, IN, OUT
|
||||
};
|
||||
private:
|
||||
float delta;
|
||||
SDL_Surface * fadingSurface;
|
||||
bool fading;
|
||||
float fadingCounter;
|
||||
bool shouldFreeSurface;
|
||||
|
||||
float initialCounter() const;
|
||||
bool isFinished() const;
|
||||
public:
|
||||
EMode fadingMode;
|
||||
|
||||
CFadeAnimation();
|
||||
~CFadeAnimation();
|
||||
void init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd = false, float animDelta = DEFAULT_DELTA);
|
||||
void update();
|
||||
void draw(SDL_Surface * targetSurface, const Point & targetPoint);
|
||||
bool isFading() const { return fading; }
|
||||
};
|
@@ -10,10 +10,9 @@
|
||||
#include "StdInc.h"
|
||||
#include "Canvas.h"
|
||||
|
||||
#include "SDL_Extensions.h"
|
||||
#include "CAnimation.h"
|
||||
|
||||
#include "../Graphics.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "IImage.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
@@ -76,9 +75,9 @@ void Canvas::draw(Canvas & image, const Point & pos)
|
||||
CSDL_Ext::blitAt(image.surface, renderOffset.x + pos.x, renderOffset.y + pos.y, surface);
|
||||
}
|
||||
|
||||
void Canvas::drawLine(const Point & from, const Point & dest, const SDL_Color & colorFrom, const SDL_Color & colorDest)
|
||||
void Canvas::drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest)
|
||||
{
|
||||
CSDL_Ext::drawLine(surface, renderOffset.x + from.x, renderOffset.y + from.y, renderOffset.x + dest.x, renderOffset.y + dest.y, colorFrom, colorDest);
|
||||
CSDL_Ext::drawLine(surface, renderOffset.x + from.x, renderOffset.y + from.y, renderOffset.x + dest.x, renderOffset.y + dest.y, CSDL_Ext::toSDL(colorFrom), CSDL_Ext::toSDL(colorDest));
|
||||
}
|
||||
|
||||
void Canvas::drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text )
|
@@ -9,8 +9,9 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "TextAlignment.h"
|
||||
#include "../gui/TextAlignment.h"
|
||||
#include "../../lib/Rect.h"
|
||||
#include "../../lib/Color.h"
|
||||
|
||||
struct SDL_Color;
|
||||
struct SDL_Surface;
|
||||
@@ -56,7 +57,7 @@ public:
|
||||
void draw(Canvas & image, const Point & pos);
|
||||
|
||||
/// renders continuous, 1-pixel wide line with color gradient
|
||||
void drawLine(const Point & from, const Point & dest, const SDL_Color & colorFrom, const SDL_Color & colorDest);
|
||||
void drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest);
|
||||
|
||||
/// renders single line of text with specified parameters
|
||||
void drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text );
|
@@ -18,12 +18,15 @@
|
||||
#include <vcmi/SkillService.h>
|
||||
#include <vcmi/spells/Service.h>
|
||||
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../renderSDL/CBitmapFont.h"
|
||||
#include "../renderSDL/CBitmapHanFont.h"
|
||||
#include "../renderSDL/CTrueTypeFont.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/filesystem/CBinaryReader.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "gui/CAnimation.h"
|
||||
#include <SDL_ttf.h>
|
||||
#include "../lib/CThreadHelper.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
@@ -37,6 +40,8 @@
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
using namespace CSDL_Ext;
|
||||
|
||||
Graphics * graphics = nullptr;
|
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "gui/Fonts.h"
|
||||
#include "IFont.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@@ -22,6 +22,7 @@ struct InfoAboutTown;
|
||||
class CGObjectInstance;
|
||||
class ObjectTemplate;
|
||||
class EntityService;
|
||||
class JsonNode;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
28
client/render/ICursor.h
Normal file
28
client/render/ICursor.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* ICursor.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class Point;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class IImage;
|
||||
|
||||
class ICursor
|
||||
{
|
||||
public:
|
||||
virtual ~ICursor() = default;
|
||||
|
||||
virtual void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) = 0;
|
||||
virtual void setCursorPosition( const Point & newPos ) = 0;
|
||||
virtual void render() = 0;
|
||||
virtual void setVisible( bool on) = 0;
|
||||
};
|
||||
|
80
client/render/IFont.cpp
Normal file
80
client/render/IFont.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* IFont.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "IFont.h"
|
||||
|
||||
#include "../../lib/Point.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
//
|
||||
|
||||
size_t IFont::getStringWidth(const std::string & data) const
|
||||
{
|
||||
size_t width = 0;
|
||||
|
||||
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
|
||||
{
|
||||
width += getGlyphWidth(data.data() + i);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
void IFont::renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
renderText(surface, data, color, pos);
|
||||
}
|
||||
|
||||
void IFont::renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point size((int)getStringWidth(data), (int)getLineHeight());
|
||||
renderText(surface, data, color, pos - size);
|
||||
}
|
||||
|
||||
void IFont::renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point size((int)getStringWidth(data), (int)getLineHeight());
|
||||
renderText(surface, data, color, pos - size / 2);
|
||||
}
|
||||
|
||||
void IFont::renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point currPos = pos;
|
||||
|
||||
for(const std::string & line : data)
|
||||
{
|
||||
renderTextLeft(surface, line, color, currPos);
|
||||
currPos.y += (int)getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point currPos = pos;
|
||||
currPos.y -= (int)data.size() * (int)getLineHeight();
|
||||
|
||||
for(const std::string & line : data)
|
||||
{
|
||||
renderTextRight(surface, line, color, currPos);
|
||||
currPos.y += (int)getLineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
Point currPos = pos;
|
||||
currPos.y -= (int)data.size() * (int)getLineHeight() / 2;
|
||||
|
||||
for(const std::string & line : data)
|
||||
{
|
||||
renderTextCenter(surface, line, color, currPos);
|
||||
currPos.y += (int)getLineHeight();
|
||||
}
|
||||
}
|
||||
|
56
client/render/IFont.h
Normal file
56
client/render/IFont.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* IFont.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class Point;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
struct SDL_Surface;
|
||||
struct SDL_Color;
|
||||
|
||||
class IFont
|
||||
{
|
||||
protected:
|
||||
/// Internal function to render font, see renderTextLeft
|
||||
virtual void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const = 0;
|
||||
|
||||
public:
|
||||
virtual ~IFont()
|
||||
{}
|
||||
|
||||
/// Returns height of font
|
||||
virtual size_t getLineHeight() const = 0;
|
||||
/// Returns width, in pixels of a character glyph. Pointer must contain at least characterSize valid bytes
|
||||
virtual size_t getGlyphWidth(const char * data) const = 0;
|
||||
/// Return width of the string
|
||||
virtual size_t getStringWidth(const std::string & data) const;
|
||||
|
||||
/**
|
||||
* @param surface - destination to print text on
|
||||
* @param data - string to print
|
||||
* @param color - font color
|
||||
* @param pos - position of rendered font
|
||||
*/
|
||||
/// pos = topleft corner of the text
|
||||
void renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
|
||||
/// pos = center of the text
|
||||
void renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
|
||||
/// pos = bottomright corner of the text
|
||||
void renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
|
||||
|
||||
/// pos = topleft corner of the text
|
||||
void renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
|
||||
/// pos = center of the text
|
||||
void renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
|
||||
/// pos = bottomright corner of the text
|
||||
void renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
|
||||
};
|
||||
|
77
client/render/IImage.h
Normal file
77
client/render/IImage.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* IImage.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class PlayerColor;
|
||||
class Rect;
|
||||
class Point;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
struct SDL_Surface;
|
||||
struct SDL_Color;
|
||||
class ColorFilter;
|
||||
|
||||
/*
|
||||
* Base class for images, can be used for non-animation pictures as well
|
||||
*/
|
||||
class IImage
|
||||
{
|
||||
public:
|
||||
using SpecialPalette = std::array<SDL_Color, 7>;
|
||||
|
||||
//draws image on surface "where" at position
|
||||
virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, const Rect * src = nullptr) const = 0;
|
||||
virtual void draw(SDL_Surface * where, const Rect * dest, const Rect * src) const = 0;
|
||||
|
||||
virtual std::shared_ptr<IImage> scaleFast(const Point & size) const = 0;
|
||||
|
||||
virtual void exportBitmap(const boost::filesystem::path & path) const = 0;
|
||||
|
||||
//Change palette to specific player
|
||||
virtual void playerColored(PlayerColor player)=0;
|
||||
|
||||
//set special color for flag
|
||||
virtual void setFlagColor(PlayerColor player)=0;
|
||||
|
||||
//test transparency of specific pixel
|
||||
virtual bool isTransparent(const Point & coords) const = 0;
|
||||
|
||||
virtual Point dimensions() const = 0;
|
||||
int width() const;
|
||||
int height() const;
|
||||
|
||||
//only indexed bitmaps, 16 colors maximum
|
||||
virtual void shiftPalette(int from, int howMany) = 0;
|
||||
virtual void adjustPalette(const ColorFilter & shifter, size_t colorsToSkip) = 0;
|
||||
virtual void resetPalette(int colorID) = 0;
|
||||
virtual void resetPalette() = 0;
|
||||
|
||||
virtual void setAlpha(uint8_t value) = 0;
|
||||
|
||||
//only indexed bitmaps with 7 special colors
|
||||
virtual void setSpecialPallete(const SpecialPalette & SpecialPalette) = 0;
|
||||
|
||||
virtual void horizontalFlip() = 0;
|
||||
virtual void verticalFlip() = 0;
|
||||
|
||||
IImage();
|
||||
virtual ~IImage();
|
||||
|
||||
/// loads image from specified file. Returns 0-sized images on failure
|
||||
static std::shared_ptr<IImage> createFromFile( const std::string & path );
|
||||
|
||||
/// temporary compatibility method. Creates IImage from existing SDL_Surface
|
||||
/// Surface will be shared, called must still free it with SDL_FreeSurface
|
||||
static std::shared_ptr<IImage> createFromSurface( SDL_Surface * source );
|
||||
};
|
||||
|
34
client/render/IImageLoader.h
Normal file
34
client/render/IImageLoader.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* IImageLoader.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class Point;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class SDLImage;
|
||||
|
||||
struct SDL_Color;
|
||||
|
||||
class IImageLoader
|
||||
{
|
||||
public:
|
||||
//load size raw pixels from data
|
||||
virtual void load(size_t size, const ui8 * data) = 0;
|
||||
//set size pixels to color
|
||||
virtual void load(size_t size, ui8 color=0) = 0;
|
||||
|
||||
virtual void endLine() = 0;
|
||||
//init image with these sizes and palette
|
||||
virtual void init(Point SpriteSize, Point Margins, Point FullSize, SDL_Color *pal) = 0;
|
||||
|
||||
virtual ~IImageLoader() = default;
|
||||
};
|
143
client/renderSDL/CBitmapFont.cpp
Normal file
143
client/renderSDL/CBitmapFont.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* CBitmapFont.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CBitmapFont.h"
|
||||
|
||||
#include "SDL_Extensions.h"
|
||||
|
||||
#include "../../lib/vcmi_endian.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/Rect.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
std::array<CBitmapFont::BitmapChar, CBitmapFont::totalChars> CBitmapFont::loadChars() const
|
||||
{
|
||||
std::array<BitmapChar, totalChars> ret;
|
||||
|
||||
size_t offset = 32;
|
||||
|
||||
for (auto & elem : ret)
|
||||
{
|
||||
elem.leftOffset = read_le_u32(data.first.get() + offset); offset+=4;
|
||||
elem.width = read_le_u32(data.first.get() + offset); offset+=4;
|
||||
elem.rightOffset = read_le_u32(data.first.get() + offset); offset+=4;
|
||||
}
|
||||
|
||||
for (auto & elem : ret)
|
||||
{
|
||||
int pixelOffset = read_le_u32(data.first.get() + offset); offset+=4;
|
||||
elem.pixels = data.first.get() + 4128 + pixelOffset;
|
||||
|
||||
assert(pixelOffset + 4128 < data.second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CBitmapFont::CBitmapFont(const std::string & filename):
|
||||
data(CResourceHandler::get()->load(ResourceID("data/" + filename, EResType::BMP_FONT))->readAll()),
|
||||
chars(loadChars()),
|
||||
height(data.first.get()[5])
|
||||
{}
|
||||
|
||||
size_t CBitmapFont::getLineHeight() const
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
size_t CBitmapFont::getGlyphWidth(const char * data) const
|
||||
{
|
||||
std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0])));
|
||||
|
||||
if (localChar.size() == 1)
|
||||
{
|
||||
const BitmapChar & ch = chars[ui8(localChar[0])];
|
||||
return ch.leftOffset + ch.width + ch.rightOffset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const
|
||||
{
|
||||
Rect clipRect;
|
||||
CSDL_Ext::getClipRect(surface, clipRect);
|
||||
|
||||
posX += character.leftOffset;
|
||||
|
||||
CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
|
||||
|
||||
uint8_t bpp = surface->format->BytesPerPixel;
|
||||
|
||||
// start of line, may differ from 0 due to end of surface or clipped surface
|
||||
int lineBegin = std::max<int>(0, clipRect.y - posY);
|
||||
int lineEnd = std::min<int>(height, clipRect.y + clipRect.h - posY - 1);
|
||||
|
||||
// start end end of each row, may differ from 0
|
||||
int rowBegin = std::max<int>(0, clipRect.x - posX);
|
||||
int rowEnd = std::min<int>(character.width, clipRect.x + clipRect.w - posX - 1);
|
||||
|
||||
//for each line in symbol
|
||||
for(int dy = lineBegin; dy <lineEnd; dy++)
|
||||
{
|
||||
uint8_t *dstLine = (uint8_t*)surface->pixels;
|
||||
uint8_t *srcLine = character.pixels;
|
||||
|
||||
// shift source\destination pixels to current position
|
||||
dstLine += (posY+dy) * surface->pitch + posX * bpp;
|
||||
srcLine += dy * character.width;
|
||||
|
||||
//for each column in line
|
||||
for(int dx = rowBegin; dx < rowEnd; dx++)
|
||||
{
|
||||
uint8_t* dstPixel = dstLine + dx*bpp;
|
||||
switch(srcLine[dx])
|
||||
{
|
||||
case 1: //black "shadow"
|
||||
colorPutter(dstPixel, 0, 0, 0);
|
||||
break;
|
||||
case 255: //text colour
|
||||
colorPutter(dstPixel, color.r, color.g, color.b);
|
||||
break;
|
||||
default :
|
||||
break; //transparency
|
||||
}
|
||||
}
|
||||
}
|
||||
posX += character.width;
|
||||
posX += character.rightOffset;
|
||||
}
|
||||
|
||||
void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
assert(surface);
|
||||
|
||||
int posX = pos.x;
|
||||
int posY = pos.y;
|
||||
|
||||
// Should be used to detect incorrect text parsing. Disabled right now due to some old UI code (mostly pregame and battles)
|
||||
//assert(data[0] != '{');
|
||||
//assert(data[data.size()-1] != '}');
|
||||
|
||||
SDL_LockSurface(surface);
|
||||
|
||||
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
|
||||
{
|
||||
std::string localChar = Unicode::fromUnicode(data.substr(i, Unicode::getCharacterSize(data[i])));
|
||||
|
||||
if (localChar.size() == 1)
|
||||
renderCharacter(surface, chars[ui8(localChar[0])], color, posX, posY);
|
||||
}
|
||||
SDL_UnlockSurface(surface);
|
||||
}
|
||||
|
44
client/renderSDL/CBitmapFont.h
Normal file
44
client/renderSDL/CBitmapFont.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* CBitmapFont.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../render/IFont.h"
|
||||
|
||||
class CBitmapFont : public IFont
|
||||
{
|
||||
static const size_t totalChars = 256;
|
||||
|
||||
struct BitmapChar
|
||||
{
|
||||
si32 leftOffset;
|
||||
ui32 width;
|
||||
si32 rightOffset;
|
||||
ui8 *pixels; // pixels of this character, part of BitmapFont::data
|
||||
};
|
||||
|
||||
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
|
||||
|
||||
const std::array<BitmapChar, totalChars> chars;
|
||||
const ui8 height;
|
||||
|
||||
std::array<BitmapChar, totalChars> loadChars() const;
|
||||
|
||||
void renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const;
|
||||
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
|
||||
public:
|
||||
CBitmapFont(const std::string & filename);
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
|
||||
friend class CBitmapHanFont;
|
||||
};
|
||||
|
127
client/renderSDL/CBitmapHanFont.cpp
Normal file
127
client/renderSDL/CBitmapHanFont.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* CBitmapHanFont.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CBitmapHanFont.h"
|
||||
|
||||
#include "CBitmapFont.h"
|
||||
#include "SDL_Extensions.h"
|
||||
|
||||
#include "../../lib/JsonNode.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/Rect.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
size_t CBitmapHanFont::getCharacterDataOffset(size_t index) const
|
||||
{
|
||||
size_t rowSize = (size + 7) / 8; // 1 bit per pixel, rounded up
|
||||
size_t charSize = rowSize * size; // glyph contains "size" rows
|
||||
return index * charSize;
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getCharacterIndex(ui8 first, ui8 second) const
|
||||
{
|
||||
if (second > 0x7f )
|
||||
second--;
|
||||
|
||||
return (first - 0x81) * (12*16 - 2) + (second - 0x40);
|
||||
}
|
||||
|
||||
void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const
|
||||
{
|
||||
//TODO: somewhat duplicated with CBitmapFont::renderCharacter();
|
||||
Rect clipRect;
|
||||
CSDL_Ext::getClipRect(surface, clipRect);
|
||||
|
||||
CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0);
|
||||
uint8_t bpp = surface->format->BytesPerPixel;
|
||||
|
||||
// start of line, may differ from 0 due to end of surface or clipped surface
|
||||
int lineBegin = std::max<int>(0, clipRect.y - posY);
|
||||
int lineEnd = std::min((int)size, clipRect.y + clipRect.h - posY);
|
||||
|
||||
// start end end of each row, may differ from 0
|
||||
int rowBegin = std::max<int>(0, clipRect.x - posX);
|
||||
int rowEnd = std::min<int>((int)size, clipRect.x + clipRect.w - posX);
|
||||
|
||||
//for each line in symbol
|
||||
for(int dy = lineBegin; dy <lineEnd; dy++)
|
||||
{
|
||||
uint8_t *dstLine = (uint8_t*)surface->pixels;
|
||||
uint8_t *source = data.first.get() + getCharacterDataOffset(characterIndex);
|
||||
|
||||
// shift source\destination pixels to current position
|
||||
dstLine += (posY+dy) * surface->pitch + posX * bpp;
|
||||
source += ((size + 7) / 8) * dy;
|
||||
|
||||
//for each column in line
|
||||
for(int dx = rowBegin; dx < rowEnd; dx++)
|
||||
{
|
||||
// select current bit in bitmap
|
||||
int bit = (source[dx / 8] << (dx % 8)) & 0x80;
|
||||
|
||||
uint8_t* dstPixel = dstLine + dx*bpp;
|
||||
if (bit != 0)
|
||||
colorPutter(dstPixel, color.r, color.g, color.b);
|
||||
}
|
||||
}
|
||||
posX += (int)size + 1;
|
||||
}
|
||||
|
||||
void CBitmapHanFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
int posX = pos.x;
|
||||
int posY = pos.y;
|
||||
|
||||
SDL_LockSurface(surface);
|
||||
|
||||
for(size_t i=0; i<data.size(); i += Unicode::getCharacterSize(data[i]))
|
||||
{
|
||||
std::string localChar = Unicode::fromUnicode(data.substr(i, Unicode::getCharacterSize(data[i])));
|
||||
|
||||
if (localChar.size() == 1)
|
||||
fallback->renderCharacter(surface, fallback->chars[ui8(localChar[0])], color, posX, posY);
|
||||
|
||||
if (localChar.size() == 2)
|
||||
renderCharacter(surface, (int)getCharacterIndex(localChar[0], localChar[1]), color, posX, posY);
|
||||
}
|
||||
SDL_UnlockSurface(surface);
|
||||
}
|
||||
|
||||
CBitmapHanFont::CBitmapHanFont(const JsonNode &config):
|
||||
fallback(new CBitmapFont(config["fallback"].String())),
|
||||
data(CResourceHandler::get()->load(ResourceID("data/" + config["name"].String(), EResType::OTHER))->readAll()),
|
||||
size((size_t)config["size"].Float())
|
||||
{
|
||||
// basic tests to make sure that fonts are OK
|
||||
// 1) fonts must contain 190 "sections", 126 symbols each.
|
||||
assert(getCharacterIndex(0xfe, 0xff) == 190*126);
|
||||
// 2) ensure that font size is correct - enough to fit all possible symbols
|
||||
assert(getCharacterDataOffset(getCharacterIndex(0xfe, 0xff)) == data.second);
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getLineHeight() const
|
||||
{
|
||||
return std::max(size + 1, fallback->getLineHeight());
|
||||
}
|
||||
|
||||
size_t CBitmapHanFont::getGlyphWidth(const char * data) const
|
||||
{
|
||||
std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0])));
|
||||
|
||||
if (localChar.size() == 1)
|
||||
return fallback->getGlyphWidth(data);
|
||||
|
||||
if (localChar.size() == 2)
|
||||
return size + 1;
|
||||
|
||||
return 0;
|
||||
}
|
40
client/renderSDL/CBitmapHanFont.h
Normal file
40
client/renderSDL/CBitmapHanFont.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* CBitmapHanFont.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../render/IFont.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class JsonNode;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CBitmapFont;
|
||||
|
||||
/// supports multi-byte characters for such languages like Chinese
|
||||
class CBitmapHanFont : public IFont
|
||||
{
|
||||
std::unique_ptr<CBitmapFont> fallback;
|
||||
// data, directly copied from file
|
||||
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
|
||||
|
||||
// size of the font. Not available in file but needed for proper rendering
|
||||
const size_t size;
|
||||
|
||||
size_t getCharacterDataOffset(size_t index) const;
|
||||
size_t getCharacterIndex(ui8 first, ui8 second) const;
|
||||
|
||||
void renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const;
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
|
||||
public:
|
||||
CBitmapHanFont(const JsonNode & config);
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
};
|
102
client/renderSDL/CTrueTypeFont.cpp
Normal file
102
client/renderSDL/CTrueTypeFont.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* CTrueTypeFont.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CTrueTypeFont.h"
|
||||
|
||||
#include "SDL_Extensions.h"
|
||||
|
||||
#include "../../lib/JsonNode.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
|
||||
#include <SDL_ttf.h>
|
||||
|
||||
std::pair<std::unique_ptr<ui8[]>, ui64> CTrueTypeFont::loadData(const JsonNode & config)
|
||||
{
|
||||
std::string filename = "Data/" + config["file"].String();
|
||||
return CResourceHandler::get()->load(ResourceID(filename, EResType::TTF_FONT))->readAll();
|
||||
}
|
||||
|
||||
TTF_Font * CTrueTypeFont::loadFont(const JsonNode &config)
|
||||
{
|
||||
int pointSize = static_cast<int>(config["size"].Float());
|
||||
|
||||
if(!TTF_WasInit() && TTF_Init()==-1)
|
||||
throw std::runtime_error(std::string("Failed to initialize true type support: ") + TTF_GetError() + "\n");
|
||||
|
||||
return TTF_OpenFontRW(SDL_RWFromConstMem(data.first.get(), (int)data.second), 1, pointSize);
|
||||
}
|
||||
|
||||
int CTrueTypeFont::getFontStyle(const JsonNode &config)
|
||||
{
|
||||
const JsonVector & names = config["style"].Vector();
|
||||
int ret = 0;
|
||||
for(const JsonNode & node : names)
|
||||
{
|
||||
if (node.String() == "bold")
|
||||
ret |= TTF_STYLE_BOLD;
|
||||
else if (node.String() == "italic")
|
||||
ret |= TTF_STYLE_ITALIC;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig):
|
||||
data(loadData(fontConfig)),
|
||||
font(loadFont(fontConfig), TTF_CloseFont),
|
||||
blended(fontConfig["blend"].Bool())
|
||||
{
|
||||
assert(font);
|
||||
|
||||
TTF_SetFontStyle(font.get(), getFontStyle(fontConfig));
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getLineHeight() const
|
||||
{
|
||||
return TTF_FontHeight(font.get());
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getGlyphWidth(const char *data) const
|
||||
{
|
||||
return getStringWidth(std::string(data, Unicode::getCharacterSize(*data)));
|
||||
/*
|
||||
int advance;
|
||||
TTF_GlyphMetrics(font.get(), *data, nullptr, nullptr, nullptr, nullptr, &advance);
|
||||
return advance;
|
||||
*/
|
||||
}
|
||||
|
||||
size_t CTrueTypeFont::getStringWidth(const std::string & data) const
|
||||
{
|
||||
int width;
|
||||
TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr);
|
||||
return width;
|
||||
}
|
||||
|
||||
void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
|
||||
{
|
||||
if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
|
||||
renderText(surface, data, Colors::BLACK, pos + Point(1,1));
|
||||
|
||||
if (!data.empty())
|
||||
{
|
||||
SDL_Surface * rendered;
|
||||
if (blended)
|
||||
rendered = TTF_RenderUTF8_Blended(font.get(), data.c_str(), color);
|
||||
else
|
||||
rendered = TTF_RenderUTF8_Solid(font.get(), data.c_str(), color);
|
||||
|
||||
assert(rendered);
|
||||
|
||||
CSDL_Ext::blitSurface(rendered, surface, pos);
|
||||
SDL_FreeSurface(rendered);
|
||||
}
|
||||
}
|
||||
|
38
client/renderSDL/CTrueTypeFont.h
Normal file
38
client/renderSDL/CTrueTypeFont.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* CTrueTypeFont.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../render/IFont.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class JsonNode;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
typedef struct _TTF_Font TTF_Font;
|
||||
|
||||
class CTrueTypeFont : public IFont
|
||||
{
|
||||
const std::pair<std::unique_ptr<ui8[]>, ui64> data;
|
||||
|
||||
const std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> font;
|
||||
const bool blended;
|
||||
|
||||
std::pair<std::unique_ptr<ui8[]>, ui64> loadData(const JsonNode & config);
|
||||
TTF_Font * loadFont(const JsonNode & config);
|
||||
int getFontStyle(const JsonNode & config);
|
||||
|
||||
void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
|
||||
public:
|
||||
CTrueTypeFont(const JsonNode & fontConfig);
|
||||
|
||||
size_t getLineHeight() const override;
|
||||
size_t getGlyphWidth(const char * data) const override;
|
||||
size_t getStringWidth(const std::string & data) const override;
|
||||
};
|
85
client/renderSDL/CursorHardware.cpp
Normal file
85
client/renderSDL/CursorHardware.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* CursorHardware.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CursorHardware.h"
|
||||
|
||||
#include "SDL_Extensions.h"
|
||||
#include "../render/IImage.h"
|
||||
|
||||
#include <SDL_render.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
#ifdef VCMI_APPLE
|
||||
#include <dispatch/dispatch.h>
|
||||
#endif
|
||||
|
||||
CursorHardware::CursorHardware():
|
||||
cursor(nullptr)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
|
||||
CursorHardware::~CursorHardware()
|
||||
{
|
||||
if(cursor)
|
||||
SDL_FreeCursor(cursor);
|
||||
}
|
||||
|
||||
void CursorHardware::setVisible(bool on)
|
||||
{
|
||||
#ifdef VCMI_APPLE
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#endif
|
||||
if (on)
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
else
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
#ifdef VCMI_APPLE
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void CursorHardware::setImage(std::shared_ptr<IImage> image, const Point & pivotOffset)
|
||||
{
|
||||
auto cursorSurface = CSDL_Ext::newSurface(image->dimensions().x, image->dimensions().y);
|
||||
|
||||
CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY);
|
||||
|
||||
image->draw(cursorSurface);
|
||||
|
||||
auto oldCursor = cursor;
|
||||
cursor = SDL_CreateColorCursor(cursorSurface, pivotOffset.x, pivotOffset.y);
|
||||
|
||||
if (!cursor)
|
||||
logGlobal->error("Failed to set cursor! SDL says %s", SDL_GetError());
|
||||
|
||||
SDL_FreeSurface(cursorSurface);
|
||||
#ifdef VCMI_APPLE
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#endif
|
||||
SDL_SetCursor(cursor);
|
||||
|
||||
if (oldCursor)
|
||||
SDL_FreeCursor(oldCursor);
|
||||
#ifdef VCMI_APPLE
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void CursorHardware::setCursorPosition( const Point & newPos )
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
|
||||
void CursorHardware::render()
|
||||
{
|
||||
//no-op
|
||||
}
|
36
client/renderSDL/CursorHardware.h
Normal file
36
client/renderSDL/CursorHardware.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* CursorHardware.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class CAnimation;
|
||||
class IImage;
|
||||
struct SDL_Surface;
|
||||
struct SDL_Texture;
|
||||
struct SDL_Cursor;
|
||||
|
||||
#include "../../lib/Point.h"
|
||||
#include "../render/ICursor.h"
|
||||
|
||||
class CursorHardware : public ICursor
|
||||
{
|
||||
std::shared_ptr<IImage> cursorImage;
|
||||
|
||||
SDL_Cursor * cursor;
|
||||
|
||||
public:
|
||||
CursorHardware();
|
||||
~CursorHardware();
|
||||
|
||||
void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) override;
|
||||
void setCursorPosition( const Point & newPos ) override;
|
||||
void render() override;
|
||||
void setVisible( bool on) override;
|
||||
};
|
||||
|
103
client/renderSDL/CursorSoftware.cpp
Normal file
103
client/renderSDL/CursorSoftware.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* CursorSoftware.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CursorSoftware.h"
|
||||
|
||||
#include "SDL_Extensions.h"
|
||||
|
||||
#include "../render/IImage.h"
|
||||
|
||||
#include <SDL_render.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
void CursorSoftware::render()
|
||||
{
|
||||
//texture must be updated in the main (renderer) thread, but changes to cursor type may come from other threads
|
||||
if (needUpdate)
|
||||
updateTexture();
|
||||
|
||||
Point renderPos = pos - pivot;
|
||||
|
||||
SDL_Rect destRect;
|
||||
destRect.x = renderPos.x;
|
||||
destRect.y = renderPos.y;
|
||||
destRect.w = 40;
|
||||
destRect.h = 40;
|
||||
|
||||
SDL_RenderCopy(mainRenderer, cursorTexture, nullptr, &destRect);
|
||||
}
|
||||
|
||||
void CursorSoftware::createTexture(const Point & dimensions)
|
||||
{
|
||||
if(cursorTexture)
|
||||
SDL_DestroyTexture(cursorTexture);
|
||||
|
||||
if (cursorSurface)
|
||||
SDL_FreeSurface(cursorSurface);
|
||||
|
||||
cursorSurface = CSDL_Ext::newSurface(dimensions.x, dimensions.y);
|
||||
cursorTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, dimensions.x, dimensions.y);
|
||||
|
||||
SDL_SetSurfaceBlendMode(cursorSurface, SDL_BLENDMODE_NONE);
|
||||
SDL_SetTextureBlendMode(cursorTexture, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
void CursorSoftware::updateTexture()
|
||||
{
|
||||
Point dimensions(-1, -1);
|
||||
|
||||
if (!cursorSurface || Point(cursorSurface->w, cursorSurface->h) != cursorImage->dimensions())
|
||||
createTexture(cursorImage->dimensions());
|
||||
|
||||
CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY);
|
||||
|
||||
cursorImage->draw(cursorSurface);
|
||||
SDL_UpdateTexture(cursorTexture, NULL, cursorSurface->pixels, cursorSurface->pitch);
|
||||
needUpdate = false;
|
||||
}
|
||||
|
||||
void CursorSoftware::setImage(std::shared_ptr<IImage> image, const Point & pivotOffset)
|
||||
{
|
||||
assert(image != nullptr);
|
||||
cursorImage = image;
|
||||
pivot = pivotOffset;
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
void CursorSoftware::setCursorPosition( const Point & newPos )
|
||||
{
|
||||
pos = newPos;
|
||||
}
|
||||
|
||||
void CursorSoftware::setVisible(bool on)
|
||||
{
|
||||
visible = on;
|
||||
}
|
||||
|
||||
CursorSoftware::CursorSoftware():
|
||||
cursorTexture(nullptr),
|
||||
cursorSurface(nullptr),
|
||||
needUpdate(false),
|
||||
visible(false),
|
||||
pivot(0,0)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
|
||||
CursorSoftware::~CursorSoftware()
|
||||
{
|
||||
if(cursorTexture)
|
||||
SDL_DestroyTexture(cursorTexture);
|
||||
|
||||
if (cursorSurface)
|
||||
SDL_FreeSurface(cursorSurface);
|
||||
}
|
||||
|
44
client/renderSDL/CursorSoftware.h
Normal file
44
client/renderSDL/CursorSoftware.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* CursorSoftware.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class CAnimation;
|
||||
class IImage;
|
||||
struct SDL_Surface;
|
||||
struct SDL_Texture;
|
||||
struct SDL_Cursor;
|
||||
|
||||
#include "../../lib/Point.h"
|
||||
#include "../render/ICursor.h"
|
||||
|
||||
class CursorSoftware : public ICursor
|
||||
{
|
||||
std::shared_ptr<IImage> cursorImage;
|
||||
|
||||
SDL_Texture * cursorTexture;
|
||||
SDL_Surface * cursorSurface;
|
||||
|
||||
Point pos;
|
||||
Point pivot;
|
||||
bool needUpdate;
|
||||
bool visible;
|
||||
|
||||
void createTexture(const Point & dimensions);
|
||||
void updateTexture();
|
||||
public:
|
||||
CursorSoftware();
|
||||
~CursorSoftware();
|
||||
|
||||
void setImage(std::shared_ptr<IImage> image, const Point & pivotOffset) override;
|
||||
void setCursorPosition( const Point & newPos ) override;
|
||||
void render() override;
|
||||
void setVisible( bool on) override;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user