Merge branch 'master' of https://github.com/supertuxkart/stk-code
@@ -3,7 +3,6 @@ environment:
|
||||
DEPS_BRANCH: master
|
||||
ASSETS_DIR: c:\\projects\stk-assets
|
||||
APPVEYOR_CACHE_ENTRY_ZIP_ARGS: -t7z -m0=lzma2 -mx=9
|
||||
IRC_NOTIFY_SCRIPT: c:\\projects\stk-code\tools\appveyor-irc-notify.py
|
||||
|
||||
os: Visual Studio 2015
|
||||
clone_depth: 1
|
||||
@@ -57,10 +56,3 @@ before_build:
|
||||
build:
|
||||
parallel: true
|
||||
project: build\ALL_BUILD.vcxproj
|
||||
|
||||
|
||||
on_success:
|
||||
- "python %IRC_NOTIFY_SCRIPT% supertuxkart [{author}:{branch}] {short_commit}: {message} {color_green}Succeeded,Details: {build_url},Commit: {commit_url}"
|
||||
|
||||
on_failure:
|
||||
- "python %IRC_NOTIFY_SCRIPT% supertuxkart [{author}:{branch}] {short_commit}: {message} {color_red}Failed,Details: {build_url},Commit: {commit_url}"
|
||||
|
||||
13
.travis.yml
@@ -54,16 +54,3 @@ script:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then /usr/local/opt/cmake/bin/cmake .. -DFREETYPE_INCLUDE_DIRS=/usr/local/opt/freetype/include/freetype2/ -DUSE_SYSTEM_GLEW=1 -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include/ -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DFREETYPE_LIBRARY=/usr/local/opt/freetype/lib/libfreetype.dylib -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSERVER_ONLY=$SERVER_ONLY -DCHECK_ASSETS=off -DBUILD_RECORDER=off; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSERVER_ONLY=$SERVER_ONLY -DCHECK_ASSETS=off -DBUILD_RECORDER=off; fi
|
||||
- make VERBOSE=1 -j3
|
||||
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "irc.freenode.org#supertuxkart"
|
||||
skip_join: false
|
||||
use_notice: true
|
||||
template:
|
||||
#- "[%{commit}: %{author}] %{message}"
|
||||
#- "%{build_url}"
|
||||
- "[%{repository}#%{branch} @%{commit}] %{author}): %{message}"
|
||||
- "Diff: %{compare_url}"
|
||||
- "Build: %{build_url}"
|
||||
|
||||
221
CHANGELOG.md
@@ -1,16 +1,35 @@
|
||||
## SuperTuxKart 0.9.4
|
||||
* Networking game for normal race, time trial, free for all, capture the flag and soccer
|
||||
* Better random item distribution for various numbers of karts
|
||||
* Improved powerup handling in AI
|
||||
* New tracks Las Dunas Soccer by samuncle
|
||||
# Changelog
|
||||
This file documents notable changes to SuperTuxKart across versions since its inception.
|
||||
|
||||
## SuperTuxKart 0.9.3
|
||||
It should be kept in mind that some versions have a less complete changelog than others, and that this changelog do not list the details of the many small bugfixes and improvements which together make a significant part of the progress between releases.
|
||||
|
||||
For similar reasons, and because some features are vastly more complex than others, attributions of main changes should not be taken as a shorcut for overall contribution.
|
||||
|
||||
## Unreleased
|
||||
* Networking game for normal race, time trial, free for all, capture the flag and soccer
|
||||
* Better random item distribution for various numbers of karts by Alayan and hiker
|
||||
* Numerous improvements to input on Android by deveee
|
||||
* Unlockable SuperTux challenges in Story Mode by Alayan
|
||||
* Race UI improvements (new speedometer, nitro gauge, bigger minimap) by Alayan
|
||||
* Improvements to ghost replays (more data saved, live time difference, replay comparison, UI improvements, egg hunt replays) by Alayan
|
||||
* Kart color customization by Benau
|
||||
* Improved powerup handling in AI by Alayan
|
||||
* Local multiplayer improvements by Fantasmos
|
||||
* New coal skin by Alayan
|
||||
* Visual improvements (new skidding particles, better rescue, bubblegum flashing before ending)
|
||||
* Audio improvements (crash sound depending on speed/direction, sound cue in nitro challenges)
|
||||
* Gameplay improvements (much better slipstreaming, GP points...)
|
||||
* Terrain slowdown works again as intended on several tracks where it was missing
|
||||
* Many bugfixes
|
||||
### Tracks and modeling
|
||||
#### Tracks
|
||||
* Many unwanted shortcuts and exploits fixed by Auria
|
||||
* Las Dunas Soccer by samuncle
|
||||
|
||||
## SuperTuxKart 0.9.3 (28. October 2017)
|
||||
* Reduced RAM and VRAM usage, reducing load times by Auria and Benau
|
||||
* New mesh format optimized for space and hardware skinning
|
||||
* Code refactoring of both render pipeline by Benau and Elderme
|
||||
* New kart Wilber and Hexley by Jymis
|
||||
* New kart Kiki and updated Konqi by Benau
|
||||
* New tracks Candela City, Cornfield Crossing and Las Dunas Arena by samuncle
|
||||
* Physics improvements and various physics bugfixes by hiker
|
||||
* Kart GFX improvements (exhaust and headlight)
|
||||
* In-game screen recording powered by libopenglrecorder
|
||||
@@ -19,92 +38,113 @@
|
||||
* New grand prix win scene
|
||||
* Gamepad configuration bugfixes
|
||||
* 3 Strikes Battles : added spare tire karts
|
||||
* Various improvements (wall driving fixes, parachutes, GP points, cannon fixes, colorization shader)
|
||||
* Visual representation of the start line in all tracks
|
||||
* Various improvements (starting boost effect, wall driving fixes, parachutes, GP points, help page for bananas, cannon fixes, colorization shader)
|
||||
### Tracks and modeling
|
||||
#### Karts
|
||||
* New kart Wilber and Hexley by Jymis
|
||||
* New kart Kiki and updated Konqi by Benau
|
||||
#### Tracks
|
||||
* All tracks drivable in reverse, with arrows pointing in the correct direction
|
||||
* Candela City by samuncle (replace Shiny Suburbs)
|
||||
* Cornfield Crossing by samuncle (replace Bovine Barnyard)
|
||||
* New battle track Las Dunas Arena by samuncle
|
||||
|
||||
## SuperTuxKart 0.9.2
|
||||
## SuperTuxKart 0.9.2 (1. July 2016)
|
||||
* Ghost replay races by Benau
|
||||
* Battle mode AI by Benau
|
||||
* Soccer mode AI by Benau
|
||||
* New icy soccer field by samuncle and Benau
|
||||
* New subsea track by samuncle
|
||||
* New volcano track by Ponzino
|
||||
* TTF font rendering by Benau
|
||||
* New ruby and forest skins by Benau
|
||||
* Kart properties refactor by Flakebi
|
||||
* Scripting work under the hood
|
||||
* Work on the track editor by mhp
|
||||
* Tweak to challenges
|
||||
* New farm track song by 0zone0ne and Krobonil
|
||||
* Bugfixes
|
||||
### Tracks and modeling
|
||||
#### Tracks
|
||||
* Antediluvian Abysses by samuncle (replace Subsea)
|
||||
* Volcano Island by Ponzino
|
||||
* New icy soccer field by samuncle and Benau
|
||||
|
||||
## SuperTuxKart 0.9.1
|
||||
## SuperTuxKart 0.9.1 (17. October 2015)
|
||||
* Many bug fixes
|
||||
* Started to use scripting in tracks
|
||||
* Significant audio performance improvements
|
||||
* Smaller tweaks and improvements to several tracks including
|
||||
** Math class
|
||||
** XR591
|
||||
** Fort Magma
|
||||
** Gran Paradiso
|
||||
** Subsea
|
||||
* Tweak to challenges
|
||||
### Tracks and modeling
|
||||
#### Tracks
|
||||
* Better support for driving tracks in reverse
|
||||
* Smaller tweaks and improvements to several tracks including
|
||||
* Math class
|
||||
* XR591
|
||||
* Fort Magma
|
||||
* Gran Paradiso Island
|
||||
* Subsea
|
||||
|
||||
## SupertTuxKart 0.9 (April 2015)
|
||||
## SupertTuxKart 0.9 (24. April 2015)
|
||||
* Fully shader-based rendering engine
|
||||
* New tracks Cocoa Temple and Gran Paradiso
|
||||
* Graphical improvements to many other tracks
|
||||
* New karts amanda and gavroche
|
||||
* New and improved tux, adiumy, sara the wizard and the racer, xue kart
|
||||
* Online login which allows to:
|
||||
** connect with friends and see when they are playing
|
||||
** vote for addons
|
||||
** collect online achievements
|
||||
* connect with friends and see when they are playing
|
||||
* vote for addons
|
||||
* collect online achievements
|
||||
* Grand Prix editor, including creation of random GPs
|
||||
* Different kart physics
|
||||
|
||||
### Tracks and modeling
|
||||
#### Karts
|
||||
* New karts Amanda and Gavroche by XGhost
|
||||
* New and improved Tux, Adiumy, Sara the Wizard and the Racer, Xue
|
||||
#### Tracks
|
||||
* Cocoa Temple by samuncle (replace Amazonian Journey)
|
||||
* Gran Paradiso Island by samuncle (replace The Island)
|
||||
* Graphical improvements to many other tracks
|
||||
|
||||
## SuperTuxKart 0.8.1 (26. November 2013)
|
||||
* New track STK Enterprise
|
||||
* Updated track The old mines
|
||||
* Updated Lighthouse track
|
||||
* Updated Zen Garden track
|
||||
* New Soccer mode
|
||||
* New Egg Hunt mode
|
||||
* New karts Xue and Sara
|
||||
* Updated Beastie kart
|
||||
* Added Tutorial
|
||||
* Added new Supertux difficulty
|
||||
* New bubblegum shield weapon
|
||||
* New Speedometer and nitro meter
|
||||
* Add ability to filter addons
|
||||
* Updated nitro models
|
||||
* Add ability to save and resume Grand Prix
|
||||
* Improve skid marks and nitro effects
|
||||
* Wiimote support
|
||||
|
||||
### Tracks and modeling
|
||||
#### Karts
|
||||
* New karts Xue and Sara
|
||||
* Updated Beastie kart
|
||||
#### Tracks
|
||||
* STK Enterprise by Rubberduck (replace Star Track)
|
||||
* Gameplay and graphical updates to several tracks :
|
||||
* The Old Mine
|
||||
* Lighthouse
|
||||
* Zen Garden
|
||||
#### Miscellaneous
|
||||
* Updated nitro models
|
||||
|
||||
## SuperTuxKart 0.8 (11. December 2012)
|
||||
* Story mode and new challenge set
|
||||
* Improved AI
|
||||
* Skidding and better collision physics
|
||||
* Reverse mode
|
||||
* New green valley track
|
||||
* New Blackhill Mansion track
|
||||
* Updated XR591 track
|
||||
* Updated Fort Magma track
|
||||
* Updated jungle track
|
||||
* Updates Sand track
|
||||
* Updated menus
|
||||
* New music
|
||||
|
||||
### Tracks and modeling
|
||||
#### Tracks
|
||||
* Green Valley by Wolfs (replace Tux Tollway)
|
||||
* Blackhill Mansion by samuncle (replace Crescent Crossing)
|
||||
* Gameplay and graphical updates to several tracks :
|
||||
* XR591
|
||||
* Fort Magma
|
||||
* Jungle
|
||||
* Sand
|
||||
|
||||
|
||||
## SuperTuxKart 0.7.3 (2. November 2011)
|
||||
* New Zen Garden and Subsea tracks
|
||||
* New Island battle arena
|
||||
* New Suzanne kart
|
||||
* New graphical effects
|
||||
* New weapons 'Swatter' and 'Rubber Ball'
|
||||
* Added Thunderbird as race referee
|
||||
* 3 Strikes Battles now displays lives as spare tires
|
||||
* Improved bubble gum
|
||||
* See progression during Grand Prix
|
||||
@@ -113,16 +153,28 @@
|
||||
* Improved kart control at high speeds
|
||||
* Better placement of rescued karts
|
||||
* Transition track-making to blender 2.5/2.6
|
||||
### Tracks and modeling
|
||||
#### Karts
|
||||
* New Suzanne kart
|
||||
#### Tracks
|
||||
* Zen Garden by samuncle (replace Secret Garden)
|
||||
* New Subsea
|
||||
* New Island battle arena
|
||||
#### Miscellaneous
|
||||
* Added Thunderbird as race referee
|
||||
|
||||
## SuperTuxKart 0.7.2 (15. July 2011)
|
||||
* Added in-game addon manager
|
||||
* Fixed major memory leaks
|
||||
* New Snow Peak track by Samuncle
|
||||
* Improved star track UFO by Rudy
|
||||
* New Beastie kart.
|
||||
* Show when you get a highscore
|
||||
* Improve gamepad configuration under Windows (add ability to tell gamepads apart)
|
||||
* Various other tweaks done and glitches fixed
|
||||
### Tracks and modeling
|
||||
#### Karts
|
||||
* New Beastie kart.
|
||||
#### Tracks
|
||||
* Improved Snow Peak by samuncle
|
||||
* Improved Star Track UFO by Rudy
|
||||
|
||||
## SuperTuxKart 0.7.1b (21. April 2011)
|
||||
* Fix circular dependency in challenges
|
||||
@@ -130,8 +182,6 @@
|
||||
|
||||
## SuperTuxKart 0.7.1 (15. April 2011)
|
||||
* Particle (smoke, splash, fire) and weather effects
|
||||
* New Fort Magma by Samuncle, new Shiny Suburbs track by Horace
|
||||
* New Beagle kart by wolterh
|
||||
* Added internet news
|
||||
* Support for live language switch
|
||||
* Added optional minimal race UI
|
||||
@@ -146,6 +196,12 @@
|
||||
* Fixed character names that contain non-ASCII characters
|
||||
* Full RTL (right to left) support
|
||||
* Various other tweaks done and glitches fixed
|
||||
### Tracks and modeling
|
||||
#### Karts
|
||||
* New Beagle kart by wolterh
|
||||
#### Tracks
|
||||
* New Fort Magma by samuncle
|
||||
* New Shiny Suburbs by Horace
|
||||
|
||||
## SuperTuxKart 0.7 (December 2010)
|
||||
Too many to list them all. Main points:
|
||||
@@ -158,8 +214,12 @@ Too many to list them all. Main points:
|
||||
* Other improvements
|
||||
- Allowed alternative ways/shortcuts in tracks
|
||||
- New item 'switch'
|
||||
* New art:
|
||||
- New tracks farm, hacienda, scotland, secret garden
|
||||
### Tracks and modeling
|
||||
#### Tracks
|
||||
- Farm
|
||||
- Hacienda by samuncle (replace Beach)
|
||||
- Scotland by Canis Lupus
|
||||
- Secret Garden
|
||||
|
||||
## SuperTuxKart 0.6.2a (October 2009)
|
||||
* Bugfix: STK would crash while trying to save the config file
|
||||
@@ -179,7 +239,7 @@ Too many to list them all. Main points:
|
||||
* Bugfix: battle mode would not display track groups.
|
||||
|
||||
## SuperTuxKart 0.6.1 (February 2009)
|
||||
* Added new kart ("Puffy"), new battle map ("Cave"), and new music for Snow Mountain.
|
||||
* New music for Snow Mountain.
|
||||
* Fixed bug in track selection screen that could cause a crash when track groups were used.
|
||||
* Fixed crash in character selection that could happen if an old user config file existed.
|
||||
* Fixed incorrect rescues in Fort Magma.
|
||||
@@ -187,15 +247,19 @@ Too many to list them all. Main points:
|
||||
* A plunger in the face is now removed when restarting.
|
||||
* Added slow-down for karts driving backwards.
|
||||
* Somewhat reduced 'shaking' of AI driven karts.
|
||||
### Tracks and modeling
|
||||
#### Karts
|
||||
- New Puffy kart
|
||||
#### Tracks
|
||||
- New Cave battle map
|
||||
|
||||
|
||||
## SuperTuxKart 0.6 (January 2009)
|
||||
* New improved physics and kart handling
|
||||
* Added sharp turns and nitro speed boost (replacing wheelies and jump)
|
||||
* Totally rewrote powerups (plunger, bowling ball, cake, bubblegum) and new look for bananas
|
||||
* New and improved tracks : skyline, snow mountain, race track, space track, old mine, XR591
|
||||
* New game mode : 3-Strikes Battle
|
||||
* Major improvements to AI
|
||||
* New/improved karts (and removed some old ones) : wilber, eviltux, hexley
|
||||
* Improved user interface
|
||||
* Karts now have a visible suspension effect
|
||||
* Fully positional audio with OpenAL
|
||||
@@ -210,9 +274,23 @@ Too many to list them all. Main points:
|
||||
* Bug fixes and code refactor/cleanup/documentation
|
||||
- Fixed 'joystick locks' (kart would turn even if the joystick is in neutral),
|
||||
thanks to Samjam for the patch.
|
||||
|
||||
### Tracks and modeling
|
||||
#### Karts
|
||||
* Improved Wilber
|
||||
* Eviltux
|
||||
* Hexley
|
||||
* Some old karts have been removed
|
||||
#### Tracks
|
||||
* Skyline
|
||||
* Snow Mountain
|
||||
* Race track
|
||||
* Old Mine
|
||||
* XR591
|
||||
* Improved track :
|
||||
* Star track
|
||||
|
||||
## SuperTuxKart 0.5 (May 2008)
|
||||
* Six new tracks and one improved track: Fort Magma, SnowTux Peak, Amazonian Journey, City, Canyon, Crescent Crossing and StarTrack
|
||||
* Complete Challenges to unlock game modes, new tracks and a skidding preview
|
||||
* New Follow the Leader game mode
|
||||
* New Grand Prix
|
||||
@@ -223,18 +301,29 @@ Too many to list them all. Main points:
|
||||
* Many Bugfixes including:
|
||||
- a memory leak fix (Charlie Head)
|
||||
- an AI crash fix (Chris Morris)
|
||||
|
||||
|
||||
### Tracks and modeling
|
||||
#### Tracks
|
||||
* SnowTux Peak
|
||||
* Amazonian Journey
|
||||
* City
|
||||
* Canyon
|
||||
* BSODs Battlements renamed to Fort Magma
|
||||
* Improved Crescent Crossing, Fort Magma, and Star Track
|
||||
|
||||
## SuperTuxKart 0.4 (February 2008)
|
||||
* New physics handling using the bullet physics engine
|
||||
* New kart: wilber
|
||||
* Improved 'Shifting Sands' and 'Lighthouse' tracks
|
||||
* Improved AI
|
||||
* New GUI handling, including resolution switching GUI
|
||||
* Improved input handling
|
||||
* Jump and look-back featue
|
||||
* Additional music and main theme
|
||||
### Tracks and modeling
|
||||
#### Karts
|
||||
* New kart: wilber
|
||||
|
||||
#### Tracks
|
||||
* Improved 'Shifting Sands' and 'Lighthouse'
|
||||
|
||||
## SuperTuxKart 0.3 (May 2007)
|
||||
* Highscore lists
|
||||
@@ -266,7 +355,7 @@ Too many to list them all. Main points:
|
||||
- Fixed keyboard keys unable to work on the first key press bug
|
||||
- And others
|
||||
|
||||
##SuperTuxKart 0.2 (22. Sep 2006)
|
||||
## SuperTuxKart 0.2 (22. Sep 2006)
|
||||
* Significant performance improvement by using display lists
|
||||
* Improved AI
|
||||
* Support for different grand prixs
|
||||
@@ -284,7 +373,7 @@ Too many to list them all. Main points:
|
||||
* Added help and about screens, added credits to track designer
|
||||
* Items were added to all tracks
|
||||
|
||||
##SuperTuxKart 0.1 (04. May 2006) (not officially released)
|
||||
## SuperTuxKart 0.1 (04. May 2006) (not officially released)
|
||||
* Significant speedup by using a new HOT and collision algorithm --> all tracks are now playable
|
||||
* Removed all SDL dependencies, only plib is needed
|
||||
* Single and multi-window menu can be used
|
||||
@@ -292,7 +381,7 @@ Too many to list them all. Main points:
|
||||
* Some bug fixes and small improvements
|
||||
* Added profile option to support automatic profiling
|
||||
|
||||
##SuperTuxKart 0.0.0 (22. Dec 2004)
|
||||
## SuperTuxKart 0.0.0 (22. Dec 2004)
|
||||
* new tracks
|
||||
* new characters and karts
|
||||
* new user-interface
|
||||
|
||||
@@ -24,6 +24,8 @@ option(USE_SYSTEM_ANGELSCRIPT "Use system angelscript instead of built-in angels
|
||||
option(USE_SYSTEM_ENET "Use system ENET instead of the built-in version, when available." ON)
|
||||
option(USE_SYSTEM_GLEW "Use system GLEW instead of the built-in version, when available." ON)
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(USE_CRYPTO_OPENSSL "Use OpenSSL instead of Nettle for cryptography in STK." OFF
|
||||
"NOT APPLE" ON)
|
||||
CMAKE_DEPENDENT_OPTION(BUILD_RECORDER "Build opengl recorder" ON
|
||||
"NOT SERVER_ONLY;NOT APPLE" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(USE_FRIBIDI "Support for right-to-left languages" ON
|
||||
@@ -453,26 +455,45 @@ else()
|
||||
target_link_libraries(supertuxkart ${PTHREAD_LIBRARY})
|
||||
endif()
|
||||
|
||||
# CURL and OpenSSL
|
||||
# CURL and OpenSSL or Nettle
|
||||
# 1.0.1d for compatible AES GCM handling
|
||||
SET(OPENSSL_MINIMUM_VERSION "1.0.1d")
|
||||
if(MSVC)
|
||||
set(USE_CRYPTO_OPENSSL ON)
|
||||
target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libcurl.lib)
|
||||
target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libeay32.lib)
|
||||
elseif(MINGW)
|
||||
set(USE_CRYPTO_OPENSSL ON)
|
||||
target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libcurldll.a)
|
||||
target_link_libraries(supertuxkart ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/lib/libeay32.dll)
|
||||
else()
|
||||
find_package(CURL REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
if(${OPENSSL_VERSION} VERSION_LESS ${OPENSSL_MINIMUM_VERSION} OR
|
||||
(${OPENSSL_VERSION} VERSION_EQUAL ${OPENSSL_MINIMUM_VERSION} AND ${OPENSSL_VERSION} STRLESS ${OPENSSL_MINIMUM_VERSION}))
|
||||
message(FATAL_ERROR "OpenSSL version found (${OPENSSL_VERSION}) is less then the minimum required (${OPENSSL_MINIMUM_VERSION}), aborting.")
|
||||
endif()
|
||||
|
||||
include_directories(${CURL_INCLUDE_DIRS})
|
||||
include_directories(${OpenSSL_INCLUDE_DIRS})
|
||||
|
||||
find_path(NETTLE_INCLUDE_DIRS nettle/gcm.h nettle/sha.h nettle/base64.h nettle/version.h nettle/yarrow.h)
|
||||
find_library(NETTLE_LIBRARY NAMES nettle libnettle)
|
||||
|
||||
if (NOT NETTLE_INCLUDE_DIRS OR NOT NETTLE_LIBRARY OR USE_CRYPTO_OPENSSL)
|
||||
set(USE_CRYPTO_OPENSSL ON)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
if(${OPENSSL_VERSION} VERSION_LESS ${OPENSSL_MINIMUM_VERSION} OR
|
||||
(${OPENSSL_VERSION} VERSION_EQUAL ${OPENSSL_MINIMUM_VERSION} AND ${OPENSSL_VERSION} STRLESS ${OPENSSL_MINIMUM_VERSION}))
|
||||
message(FATAL_ERROR "OpenSSL version found (${OPENSSL_VERSION}) is less then the minimum required (${OPENSSL_MINIMUM_VERSION}), aborting.")
|
||||
endif()
|
||||
include_directories(${OpenSSL_INCLUDE_DIRS})
|
||||
else()
|
||||
set(USE_CRYPTO_OPENSSL OFF)
|
||||
include_directories(${NETTLE_INCLUDE_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (USE_CRYPTO_OPENSSL)
|
||||
message(STATUS "OpenSSL will be used for cryptography in STK.")
|
||||
add_definitions(-DENABLE_CRYPTO_OPENSSL)
|
||||
else()
|
||||
message(STATUS "Nettle will be used for cryptography in STK.")
|
||||
add_definitions(-DENABLE_CRYPTO_NETTLE)
|
||||
endif()
|
||||
|
||||
# Common library dependencies
|
||||
@@ -484,9 +505,14 @@ target_link_libraries(supertuxkart
|
||||
stkirrlicht
|
||||
${Angelscript_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
${OPENSSL_CRYPTO_LIBRARY}
|
||||
)
|
||||
|
||||
if (USE_CRYPTO_OPENSSL)
|
||||
target_link_libraries(supertuxkart ${OPENSSL_CRYPTO_LIBRARY})
|
||||
else()
|
||||
target_link_libraries(supertuxkart ${NETTLE_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(NOT SERVER_ONLY)
|
||||
if(NOT USE_GLES2)
|
||||
target_link_libraries(supertuxkart ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARIES})
|
||||
|
||||
@@ -161,6 +161,7 @@ LOCAL_CFLAGS := -I../lib/angelscript/include \
|
||||
-Iobj/openssl/include \
|
||||
-DUSE_GLES2 \
|
||||
-DENABLE_SOUND \
|
||||
-DENABLE_CRYPTO_OPENSSL \
|
||||
-DNDEBUG \
|
||||
-DANDROID_PACKAGE_NAME=\"$(PACKAGE_NAME)\" \
|
||||
-DANDROID_APP_DIR_NAME=\"$(APP_DIR_NAME)\" \
|
||||
|
||||
@@ -64,7 +64,6 @@ Add-ons website
|
||||
= Additional Programming =
|
||||
|
||||
Main Contributors
|
||||
- Dawid Gan (deveee) : general improvements and many many bugfixes
|
||||
- Marc Coll : Grand Prix editor
|
||||
- Flakebi
|
||||
- Konstin
|
||||
@@ -91,7 +90,8 @@ Bug fixes & misc contributions
|
||||
- Stephen Dunn (Work on audio)
|
||||
- Patrick Ammann
|
||||
- Ward Muylaert
|
||||
|
||||
- Fantasmos
|
||||
- QwertyChouskie
|
||||
|
||||
= Visual art =
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ ghost_plus.png by Alayan, based on https://openclipart.org/detail/17847/cartoon-
|
||||
|
||||
options_language.png by Alayan, based on http://www.languageicon.org/, released under CC-BY-SA 3+
|
||||
|
||||
blue_flag.png, heart.png and red_flag.png by Benau, released under CC-BY-SA 4
|
||||
|
||||
====
|
||||
|
||||
Glass Skin by Auria, under CC-BY-SA 3+
|
||||
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
data/gui/blue_flag.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
@@ -2,25 +2,26 @@
|
||||
<stkgui>
|
||||
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row" padding="10">
|
||||
|
||||
<header id="selected_track" width="80%" height="30"
|
||||
<header id="selected_track" width="80%"
|
||||
I18N="No neeed to translate this, it will be overwritten by the track name"
|
||||
text="" align="center" text_align="center" />
|
||||
|
||||
<spacer height="20" />
|
||||
|
||||
<!-- Track selection -->
|
||||
<box width="100%" height="60%" layout="vertical-row">
|
||||
<ribbon_grid id="tracks" proportion="1" width="100%" height="100%" square_items="true"
|
||||
label_location="each" align="center" child_width="240" child_height="160" />
|
||||
<box proportion="3" width="100%" layout="vertical-row">
|
||||
<ribbon_grid id="tracks" proportion="1" width="100%" square_items="true"
|
||||
label_location="each" align="center" max_rows="2" child_width="160"
|
||||
child_height="120"/>
|
||||
</box>
|
||||
|
||||
<!-- Populated dynamically at runtime -->
|
||||
<tabs width="100%" height="5%" id="trackgroups"> </tabs>
|
||||
|
||||
<spacer height="50" />
|
||||
<spacer height="10%" />
|
||||
|
||||
<!-- Laps and reverse -->
|
||||
<div width="100%" height="100" layout="horizontal-row" align="center">
|
||||
<div width="100%" height="fit" layout="horizontal-row" align="center">
|
||||
|
||||
<spacer proportion="1" />
|
||||
|
||||
@@ -40,8 +41,10 @@
|
||||
<spacer proportion="1" />
|
||||
</div>
|
||||
|
||||
<spacer height="5%" />
|
||||
|
||||
<!-- Dialog buttons -->
|
||||
<div width="100%" height="60" layout="horizontal-row">
|
||||
<div width="100%" height="fit" layout="horizontal-row">
|
||||
<spacer proportion="2" />
|
||||
<button id="ok" text="OK" proportion="1" />
|
||||
<spacer proportion="1" />
|
||||
@@ -49,5 +52,7 @@
|
||||
<spacer proportion="2" />
|
||||
</div>
|
||||
|
||||
<spacer height="2%" />
|
||||
|
||||
</div>
|
||||
</stkgui>
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<div x="2%" y="10%" width="96%" height="80%" layout="vertical-row" >
|
||||
<label id="title" raw_text="Text" proportion="1"/>
|
||||
|
||||
<spacer height="25" width="10" />
|
||||
<spacer height="7%" width="10" />
|
||||
<textbox id="textfield" width="75%" align="center"/>
|
||||
|
||||
<spacer height="20" width="20" />
|
||||
<spacer height="7%" width="20" />
|
||||
<button id="ok" I18N="In the general textfield dialog" text="OK" align="center" proportion="1"/>
|
||||
|
||||
<spacer height="15" width="20" />
|
||||
<spacer height="5%" width="20" />
|
||||
<button id="cancel" I18N="In the general textfield dialog" text="Cancel" align="center" proportion="1"/>
|
||||
</div>
|
||||
</stkgui>
|
||||
|
||||
@@ -38,9 +38,14 @@
|
||||
<div width="99%" align="center" layout="horizontal-row" height="fit">
|
||||
<div proportion="2" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_difficulty_toggle" text_align="left"/>
|
||||
<spacer width="1%" height="fit"/>
|
||||
<spacer width="2%" height="fit"/>
|
||||
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show replays matching the current difficulty"/>
|
||||
</div>
|
||||
<div proportion="1" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_multiplayer_toggle" text_align="left"/>
|
||||
<spacer width="2%" height="fit"/>
|
||||
<label height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Hide multiplayer replays"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="99%" align="center" layout="horizontal-row" height="fit">
|
||||
|
||||
@@ -3,55 +3,56 @@
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
<div x="2%" y="2%" width="96%" height="96%" layout="vertical-row">
|
||||
<header id="name" height="7%" width="80%" align="center" text_align="center"/>
|
||||
|
||||
<header id="name" height="5%" width="80%" align="center" text_align="center"/>
|
||||
|
||||
<spacer width="1" height="5%"/>
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<box width="100%" height="40%" padding="10" layout="horizontal-row">
|
||||
<spacer width="10" height="100%"/>
|
||||
<!-- Left pane -->
|
||||
<div width="45%" height="100%" align="center" layout="vertical-row">
|
||||
<div proportion="1" height="100%" layout="vertical-row">
|
||||
<icon-button proportion="1" width="100%" height="100%" id="screenshot" custom_ratio="1.33333"/>
|
||||
</div>
|
||||
|
||||
<spacer width="5%" height="100%"/>
|
||||
|
||||
<!-- Right pane -->
|
||||
<div width="45%" height="95%" align="center" layout="vertical-row">
|
||||
<div proportion="1" height="100%" layout="vertical-row">
|
||||
<list id="tracks" width="100%" height="100%"/>
|
||||
</div>
|
||||
|
||||
</box>
|
||||
<spacer width="1" height="5%"/>
|
||||
<box width="100%" height="28%" padding="20" layout="vertical-row">
|
||||
<div width="100%" height="20%" layout="horizontal-row" >
|
||||
<label id="ai-text" width="50%" I18N="In the grand prix info screen" text="AI karts" text_align="right"/>
|
||||
<spacer width="30"/>
|
||||
<spinner id="ai-spinner" width="30%" min_value="1" max_value="20" align="center" wrap_around="true" />
|
||||
<spacer width="1" height="1%"/>
|
||||
<box width="100%" height="33%" layout="vertical-row">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="ai-text" proportion="1" I18N="In the grand prix info screen" text="AI karts" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<spinner id="ai-spinner" width="50%" min_value="1" max_value="20" align="center" wrap_around="true" />
|
||||
</div>
|
||||
</div>
|
||||
<spacer height="5%" />
|
||||
<div width="100%" height="20%" layout="horizontal-row" >
|
||||
<label id="reverse-text" width="50%" I18N="In the grand prix info screen" text="Reverse" text_align="right"/>
|
||||
<spacer width="30"/>
|
||||
<spinner id="reverse-spinner" width="30%" align="center" wrap_around="true" />
|
||||
<spacer width="1" height="1%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="reverse-text" proportion="1" I18N="In the grand prix info screen" text="Reverse" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<spinner id="reverse-spinner" width="50%" align="center" wrap_around="true" />
|
||||
</div>
|
||||
</div>
|
||||
<spacer height="5%" />
|
||||
<div width="100%" height="20%" layout="horizontal-row">
|
||||
<label id="track-text" width="50%" I18N="In the grand prix info screen" text="Tracks" text_align="right"/>
|
||||
<spacer width="30"/>
|
||||
<spinner id="track-spinner" width="30%" min_value="1" max_value="20" align="center" wrap_around="true" />
|
||||
<spacer width="1" height="1%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row">
|
||||
<label id="track-text" proportion="1" I18N="In the grand prix info screen" text="Tracks" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<spinner id="track-spinner" width="50%" min_value="1" max_value="20" align="center" wrap_around="true" />
|
||||
</div>
|
||||
</div>
|
||||
<spacer height="5%" />
|
||||
<div width="100%" height="20%" layout="horizontal-row" >
|
||||
<label id="group-text" width="50%" I18N="In the grand prix info screen" text="Track group" text_align="right"/>
|
||||
<spacer width="30"/>
|
||||
<spinner id="group-spinner" width="30%" align="center" wrap_around="true" />
|
||||
<spacer width="1" height="1%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="group-text" proportion="1" I18N="In the grand prix info screen" text="Track group" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<spinner id="group-spinner" width="50%" align="center" wrap_around="true" />
|
||||
</div>
|
||||
</div>
|
||||
</box>
|
||||
<spacer height="2%"/>
|
||||
<buttonbar id="buttons" height="15%" width="100%" align="center">
|
||||
|
||||
<spacer width="1" height="1%"/>
|
||||
<buttonbar id="buttons" height="17%" width="100%" align="center">
|
||||
<icon-button id="start" width="64" height="64" icon="gui/green_check.png"
|
||||
I18N="In the grand prix info screen" text="Start Race"/>
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<header width="80%" I18N="Title in grand prix editor screen" text="Grand Prix editor"
|
||||
align="center" text_align="center" />
|
||||
|
||||
<spacer height="20" />
|
||||
<spacer height="10" />
|
||||
|
||||
<box proportion="4" width="100%" layout="vertical-row">
|
||||
<box proportion="8" width="100%" layout="vertical-row">
|
||||
<ribbon_grid id="gplist" proportion="1" width="100%" square_items="true"
|
||||
label_location="each" align="left" max_rows="2" child_width="160"
|
||||
child_height="120" keep_selection="true" />
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
<spacer height="20" />
|
||||
|
||||
<box proportion="2" width="100%" layout="vertical-row">
|
||||
<box proportion="5" width="100%" layout="vertical-row">
|
||||
<label id="gpname" text_align="center" width="100%" text="" />
|
||||
<ribbon_grid id="tracks" proportion="1" width="100%" square_items="true"
|
||||
label_location="each" align="left" max_rows="1"
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<spacer height="20" />
|
||||
|
||||
<buttonbar proportion="1" id="menu" height="135" width="100%" align="center">
|
||||
<buttonbar proportion="3" id="menu" height="135" width="100%" align="center">
|
||||
<icon-button id="new" width="128" height="128" icon="gui/gp_new.png"
|
||||
I18N="Menu item" text="New" />
|
||||
<icon-button id="copy" width="128" height="128" icon="gui/gp_copy.png"
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<spacer width="25" height="25"/>
|
||||
<bubble proportion="2" height="100%" word_wrap="true"
|
||||
I18N="In the help menu"
|
||||
text="The 'skidding' key allows you to skid. Short skids help to take sharp turns. If you skid long enough, you will get a boost. You can't stop turning while skidding, so orient your kart carefully before !"/>
|
||||
text="The 'skidding' key allows you to skid. Short skids help to take sharp turns. If you skid long enough, you will get a boost. You can't stop turning while skidding, so orient your kart carefully before!"/>
|
||||
</div>
|
||||
|
||||
<spacer height="3%" width="10"/>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<div width="100%" proportion="1" layout="horizontal-row">
|
||||
<icon align="center" width="64" height="64" icon="models/zipper_collect.png"/>
|
||||
<spacer width="25" height="25"/>
|
||||
<bubble proportion="1" height="100%" text="Zipper - will give you a strong speed boost. But beware of not losing control of your kart !"/>
|
||||
<bubble proportion="1" height="100%" text="Zipper - will give you a strong speed boost. But beware of not losing control of your kart!"/>
|
||||
</div>
|
||||
|
||||
<div width="100%" proportion="1" layout="horizontal-row">
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<spacer width="25" height="25"/>
|
||||
<bubble proportion="1" height="100%"
|
||||
I18N="In the help menu"
|
||||
text="When input devices are configured, select the 'multiplayer race' icon in the main menu. Each player can press the 'fire' key of their gamepad or keyboard to join the game, and use their input device to select their kart. The game continues when everyone selected their kart. Note that the mouse may not be used for this operation."/>
|
||||
text="When input devices are configured, select the 'multiplayer' icon in the main menu. Each player can press the 'fire' key of their gamepad or keyboard to join the game, and use their input device to select their kart. The game continues when everyone selected their kart. Note that the mouse may not be used for this operation."/>
|
||||
</div>
|
||||
<spacer width="50" height="25" />
|
||||
</box>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 3.7 KiB |
@@ -25,9 +25,9 @@
|
||||
I18N="Main menu button" text="Addons"/>
|
||||
</buttonbar>
|
||||
|
||||
<spacer width="10" height="7%"/>
|
||||
<spacer width="10" height="6%"/>
|
||||
|
||||
<bottombar width="100%" height="10%" layout="horizontal-row">
|
||||
<bottombar width="100%" height="11%" layout="horizontal-row">
|
||||
|
||||
<spacer width="10" height="10" />
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
<spacer width="10" height="10" />
|
||||
|
||||
<buttonbar id="menu_bottomrow" x="0" y="0" width="38%" height="100%" align="center">
|
||||
<buttonbar id="menu_bottomrow" x="0" y="0" width="42%" height="100%" align="center">
|
||||
<icon-button id="test_gpwin" width="64" height="64" icon="gui/main_options.png"
|
||||
raw_text="TEST: GPWin" label_location="hover"/>
|
||||
<icon-button id="test_gplose" width="64" height="64" icon="gui/main_options.png"
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<spacer height="2%"/>
|
||||
<div proportion="2" x="2%" width="96%" layout="horizontal-row">
|
||||
<box proportion="4" height="100%" layout="vertical-row">
|
||||
<textbox id="chat" width="100%" height="30%"/>
|
||||
<div x="2%" width="96%" height="fit" layout="horizontal-row">
|
||||
<box proportion="4" height="fit" layout="vertical-row">
|
||||
<textbox id="chat" width="100%"/>
|
||||
<spacer height="10"/>
|
||||
<div width="100%" height="30%" proportion="1" layout="horizontal-row">
|
||||
<button id="send" width="10%" height="fit" I18N="In the network lobby" text="Send" />
|
||||
<spacer width="10"/>
|
||||
<label id="timeout-message" width="80%" height="fit"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row">
|
||||
<button id="send" width="20%" height="fit" I18N="In the network lobby" text="Send" />
|
||||
<spacer width="1%"/>
|
||||
<label id="timeout-message" width="79%" height="fit"/>
|
||||
</div>
|
||||
</box>
|
||||
<spacer width="3%"/>
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
<button id="user-id" width="20%" height="fit" align="center"/>
|
||||
<spacer height="20"/>
|
||||
|
||||
<box width="50%" height="10%" layout="horizontal-row" align="center" valign="center">
|
||||
<spacer proportion="1"/>
|
||||
<box width="fit" height="fit" layout="horizontal-row" align="center" valign="center">
|
||||
<spacer width="25"/>
|
||||
<label I18N="In the networking menu" align="center"
|
||||
text="Enable splitscreen or player handicaps" text_align="right"/>
|
||||
<spacer width="25"/>
|
||||
<checkbox id="enable-splitscreen" align="center" />
|
||||
<spacer proportion="1"/>
|
||||
<spacer width="25"/>
|
||||
</box>
|
||||
|
||||
<spacer height="15" width="10"/>
|
||||
|
||||
@@ -1,44 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="2%" y="5%" width="96%" height="85%" layout="vertical-row" >
|
||||
|
||||
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
|
||||
I18N="In the server info dialog" text="Server Info"/>
|
||||
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<div width="80%" align="center" layout="vertical-row" height="fit" >
|
||||
<!--
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the server info dialog" text="Name"/>
|
||||
<label id="name" proportion="2" text_align="left" text=""/>
|
||||
</div>
|
||||
-->
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Server name:"/>
|
||||
<label proportion="2" text_align="left" id="server_name" text=""/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Difficulty:"/>
|
||||
<label proportion="2" text_align="left" id="server_difficulty" text=""/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Game mode:"/>
|
||||
<label proportion="2" text_align="left" id="server_game_mode" text=""/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_password" text_align="left" proportion="1" text="Password"/>
|
||||
<textbox id="password" proportion="2" height="fit"/>
|
||||
</div>
|
||||
<div x="2%" y="0%" width="96%" height="100%" layout="vertical-row" >
|
||||
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"/>
|
||||
<spacer height="30"/>
|
||||
<label id="server-info" width="90%" height="fit" align="left" text_align="left" text=""/>
|
||||
<box x="0%" width="90%" height="50%" align="center" layout="vertical-row">
|
||||
<list id="player-list" x="0" y="0" width="100%" height="100%"/>
|
||||
</box>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_password" text_align="left" proportion="1" text="Password"/>
|
||||
<textbox id="password" proportion="2" height="fit"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true" text=""/>
|
||||
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<buttonbar id="options" width="90%" height="20%" align="center">
|
||||
<buttonbar id="options" width="90%" height="15%" align="center">
|
||||
<icon-button id="join" width="64" height="64" icon="gui/green_check.png"
|
||||
I18N="In the server info dialog" text="Join" label_location="bottom"/>
|
||||
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
</div>
|
||||
|
||||
<box proportion="1" width="98%" align="center" layout="vertical-row" padding="6">
|
||||
<list id="server_list" x="0" y="0" width="100%" height="100%"/>
|
||||
<list id="server_list" x="0" y="0" width="100%" height="93%"/>
|
||||
<textbox id="searcher" width="100%" height="7%"/>
|
||||
</box>
|
||||
<div width="99%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
@@ -17,6 +18,10 @@
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left"
|
||||
I18N="In the server selection screen" text="Show only private server(s)"/>
|
||||
<checkbox width="fit" id="game_started" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left"
|
||||
I18N="In the server selection screen" text="Hide servers with an ongoing game"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
|
||||
<header id="title" width="100%" text_align="center" text="Paused" proportion="3" />
|
||||
<header id="title" width="100%" text_align="center" text="Paused" proportion="2" />
|
||||
|
||||
<!-- FIXME: some play in proportions occur below because the text of an icon
|
||||
button is added UNDER it and not within its allocated height -->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
|
||||
<header id="title" width="100%" text_align="center" text="Paused" proportion="3" />
|
||||
<div x="2%" y="5%" width="90%" height="90%" layout="vertical-row" >
|
||||
<header id="title" width="100%" text_align="center" text="Paused" proportion="2" />
|
||||
|
||||
<!-- FIXME: some play in proportions occur below because the text of an icon
|
||||
button is added UNDER it and not within its allocated height -->
|
||||
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
data/gui/red_flag.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
@@ -2,27 +2,30 @@
|
||||
<stkgui>
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
|
||||
<icon id="red_team" I18N="In soccer setup screen" text="Red Team" icon="gui/soccer_ball_red.png" width="7%" height="7%"/>
|
||||
<icon id="blue_team" I18N="In soccer setup screen" text="Blue Team" icon="gui/soccer_ball_blue.png" width="7%" height="7%"/>
|
||||
|
||||
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row" >
|
||||
|
||||
<header width="80%" text="Race Setup" align="center" text_align="center" />
|
||||
|
||||
<spacer height="10" width="25"/>
|
||||
|
||||
<div layout="horizontal-row" width="fit" height="35" align="left">
|
||||
<div layout="horizontal-row" width="fit" height="fit" align="left">
|
||||
<bright proportion="1" height="100%"
|
||||
I18N="In soccer setup screen" text="Number of goals to win" text_align="left" />
|
||||
<spacer width="10" height="25"/>
|
||||
<spinner id="goalamount" width="200" height="90%" min_value="1" max_value="10"/>
|
||||
<spinner id="goalamount" width="200" min_value="1" max_value="10"/>
|
||||
</div>
|
||||
|
||||
<div layout="horizontal-row" width="fit" height="35" align="left">
|
||||
<div layout="horizontal-row" width="fit" height="fit" align="left">
|
||||
<bright proportion="1" height="100%"
|
||||
I18N="In soccer setup screen" text="Maximum time (min.)" text_align="left" />
|
||||
<spacer width="10" height ="25"/>
|
||||
<spinner id="timeamount" width="200" height="90%" min_value="1" max_value="15"/>
|
||||
<spinner id="timeamount" width="200" min_value="1" max_value="15"/>
|
||||
</div>
|
||||
|
||||
<div layout="horizontal-row" width="fit" height="35" align="left">
|
||||
<div layout="horizontal-row" width="fit" height="fit" align="left">
|
||||
<bright proportion="1" height="100%"
|
||||
I18N="In soccer setup screen" text="Game type (Goals limit / Time limit)" text_align="left" />
|
||||
<spacer width="10" height="25"/>
|
||||
@@ -33,14 +36,16 @@
|
||||
|
||||
<bubble height="fit" width="100%" id="lblLeftRight" I18N="In soccer setup screen" text="Use left/right to choose your team and press fire" word_wrap="true" text_align="center"/>
|
||||
|
||||
<spacer height="10" width="25"/>
|
||||
|
||||
<div id="central_div" layout="horizontal-row" width="100%" proportion="1" align="center">
|
||||
<roundedbox y="5%" width="100%" layout="horizontal-row" height="95%">
|
||||
<roundedbox width="100%" layout="horizontal-row" height="100%">
|
||||
<!-- Content is added programmatically -->
|
||||
</roundedbox>
|
||||
<icon id="red_team" I18N="In soccer setup screen" text="Red Team" icon="gui/soccer_ball_red.png" width="font" height="font"/> <!-- Layout is done programmatically -->
|
||||
<icon id="blue_team" I18N="In soccer setup screen" text="Blue Team" icon="gui/soccer_ball_blue.png" width="font" height="font"/>
|
||||
</div>
|
||||
|
||||
<spacer height="10" width="25"/>
|
||||
|
||||
<button id="continue" I18N="In soccer setup screen" text="Continue" align="center" width="60%"/>
|
||||
</div>
|
||||
</stkgui>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div x="2%" y="2%" width="96%" height="96%" layout="vertical-row">
|
||||
<header id="name" height="7%" width="80%" align="center" text_align="center"/>
|
||||
|
||||
<spacer width="1" height="1%"/>
|
||||
<spacer width="1" height="2%"/>
|
||||
|
||||
<box width="100%" height="40%" padding="10" layout="horizontal-row">
|
||||
<!-- Left pane -->
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
</box>
|
||||
<spacer width="1" height="1%"/>
|
||||
<box width="100%" height="33%" padding="15" layout="vertical-row">
|
||||
<box width="100%" height="33%" layout="vertical-row">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="lap-text" proportion="1" I18N="In the track info screen" text="Number of laps" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
@@ -59,7 +59,7 @@
|
||||
wrap_around="true" />
|
||||
</div>
|
||||
</div>
|
||||
<spacer height="10"/>
|
||||
<spacer width="1" height="1%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="ai-text" proportion="1" I18N="In the track info screen" text="Number of AI karts" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
@@ -68,7 +68,7 @@
|
||||
wrap_around="true" />
|
||||
</div>
|
||||
</div>
|
||||
<spacer height="10"/>
|
||||
<spacer width="1" height="1%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="option-text" proportion="1" I18N="In the track info screen" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
@@ -78,6 +78,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="1" height="1%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="record-race-text" proportion="1" I18N="In the track info screen" text="Record the race for ghost replay" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
@@ -87,10 +88,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="1" height="1%"/>
|
||||
</box>
|
||||
<spacer width="1" height="1%"/>
|
||||
<buttonbar id="buttons" height="15%" width="100%" align="center">
|
||||
<buttonbar id="buttons" height="17%" width="100%" align="center">
|
||||
<icon-button id="start" width="64" height="64" icon="gui/green_check.png"
|
||||
I18N="In the track info screen" text="Start Race"/>
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
<spacer width="20" height="2%"/>
|
||||
|
||||
<div width="90%" align="center" layout="vertical-row" height="18%">
|
||||
<div width="100%" align="center" layout="vertical-row" height="18%">
|
||||
<buttonbar id="options" width="100%" height="100%" align="center">
|
||||
<icon-button id="ok" width="fit" height="fit" icon="gui/green_check.png"
|
||||
I18N="In the user screen" text="OK" label_location="bottom"/>
|
||||
|
||||
@@ -6,7 +6,7 @@ CPP_FILE_LIST="`find ./src \
|
||||
-name '*.cpp' -or \
|
||||
-name '*.c' -or \
|
||||
-name '*.hpp' -or \
|
||||
-name "*.h" \
|
||||
-name "*.h" | sort -n \
|
||||
`"
|
||||
XML_FILE_LIST="`find ./data ../stk-assets/tracks ../stk-assets/karts \
|
||||
-name 'achievements.xml' -or \
|
||||
@@ -15,7 +15,7 @@ XML_FILE_LIST="`find ./data ../stk-assets/tracks ../stk-assets/karts \
|
||||
-name 'scene.xml' -or \
|
||||
-name '*.challenge' -or \
|
||||
-name '*.grandprix' -or \
|
||||
-name '*.stkgui' \
|
||||
-name '*.stkgui' | sort -n \
|
||||
`"
|
||||
ANGELSCRIPT_FILE_LIST="`find ./data ../stk-assets/tracks -name '*.as'`"
|
||||
|
||||
|
||||
@@ -346,9 +346,6 @@ endcopy:
|
||||
// and the epilogue below, the stack unwind works as it should.
|
||||
// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
|
||||
"pushl %%ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_startproc \n"
|
||||
#endif
|
||||
".cfi_adjust_cfa_offset 4 \n"
|
||||
".cfi_rel_offset ebp, 0 \n"
|
||||
"movl %%esp, %%ebp \n"
|
||||
@@ -395,9 +392,6 @@ endcopy:
|
||||
"popl %%ebp \n"
|
||||
".cfi_adjust_cfa_offset -4 \n"
|
||||
".cfi_restore ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_endproc \n"
|
||||
#endif
|
||||
#endif
|
||||
// Copy EAX:EDX to retQW. As the stack pointer has been
|
||||
// restored it is now safe to access the local variable
|
||||
@@ -474,9 +468,6 @@ endcopy:
|
||||
// and the epilogue below, the stack unwind works as it should.
|
||||
// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
|
||||
"pushl %%ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_startproc \n"
|
||||
#endif
|
||||
".cfi_adjust_cfa_offset 4 \n"
|
||||
".cfi_rel_offset ebp, 0 \n"
|
||||
"movl %%esp, %%ebp \n"
|
||||
@@ -524,9 +515,6 @@ endcopy:
|
||||
"popl %%ebp \n"
|
||||
".cfi_adjust_cfa_offset -4 \n"
|
||||
".cfi_restore ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_endproc \n"
|
||||
#endif
|
||||
#endif
|
||||
// Copy EAX:EDX to retQW. As the stack pointer has been
|
||||
// restored it is now safe to access the local variable
|
||||
@@ -603,9 +591,6 @@ endcopy:
|
||||
// and the epilogue below, the stack unwind works as it should.
|
||||
// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
|
||||
"pushl %%ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_startproc \n"
|
||||
#endif
|
||||
".cfi_adjust_cfa_offset 4 \n"
|
||||
".cfi_rel_offset ebp, 0 \n"
|
||||
"movl %%esp, %%ebp \n"
|
||||
@@ -653,9 +638,6 @@ endcopy:
|
||||
"popl %%ebp \n"
|
||||
".cfi_adjust_cfa_offset -4 \n"
|
||||
".cfi_restore ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_endproc \n"
|
||||
#endif
|
||||
#endif
|
||||
// Copy EAX:EDX to retQW. As the stack pointer has been
|
||||
// restored it is now safe to access the local variable
|
||||
@@ -741,9 +723,6 @@ endcopy:
|
||||
// and the epilogue below, the stack unwind works as it should.
|
||||
// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
|
||||
"pushl %%ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_startproc \n"
|
||||
#endif
|
||||
".cfi_adjust_cfa_offset 4 \n"
|
||||
".cfi_rel_offset ebp, 0 \n"
|
||||
"movl %%esp, %%ebp \n"
|
||||
@@ -795,9 +774,6 @@ endcopy:
|
||||
"popl %%ebp \n"
|
||||
".cfi_adjust_cfa_offset -4 \n"
|
||||
".cfi_restore ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_endproc \n"
|
||||
#endif
|
||||
#endif
|
||||
// Copy EAX:EDX to retQW. As the stack pointer has been
|
||||
// restored it is now safe to access the local variable
|
||||
@@ -879,9 +855,6 @@ endcopy:
|
||||
// and the epilogue below, the stack unwind works as it should.
|
||||
// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
|
||||
"pushl %%ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_startproc \n"
|
||||
#endif
|
||||
".cfi_adjust_cfa_offset 4 \n"
|
||||
".cfi_rel_offset ebp, 0 \n"
|
||||
"movl %%esp, %%ebp \n"
|
||||
@@ -930,9 +903,6 @@ endcopy:
|
||||
"popl %%ebp \n"
|
||||
".cfi_adjust_cfa_offset -4 \n"
|
||||
".cfi_restore ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_endproc \n"
|
||||
#endif
|
||||
#endif
|
||||
// Copy EAX:EDX to retQW. As the stack pointer has been
|
||||
// restored it is now safe to access the local variable
|
||||
@@ -1016,9 +986,6 @@ endcopy:
|
||||
// and the epilogue below, the stack unwind works as it should.
|
||||
// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
|
||||
"pushl %%ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_startproc \n"
|
||||
#endif
|
||||
".cfi_adjust_cfa_offset 4 \n"
|
||||
".cfi_rel_offset ebp, 0 \n"
|
||||
"movl %%esp, %%ebp \n"
|
||||
@@ -1070,9 +1037,6 @@ endcopy:
|
||||
"popl %%ebp \n"
|
||||
".cfi_adjust_cfa_offset -4 \n"
|
||||
".cfi_restore ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_endproc \n"
|
||||
#endif
|
||||
#endif
|
||||
// Copy EAX:EDX to retQW. As the stack pointer has been
|
||||
// restored it is now safe to access the local variable
|
||||
@@ -1144,9 +1108,6 @@ endcopy:
|
||||
// and the epilogue below, the stack unwind works as it should.
|
||||
// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
|
||||
"pushl %%ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_startproc \n"
|
||||
#endif
|
||||
".cfi_adjust_cfa_offset 4 \n"
|
||||
".cfi_rel_offset ebp, 0 \n"
|
||||
"movl %%esp, %%ebp \n"
|
||||
@@ -1191,9 +1152,6 @@ endcopy:
|
||||
"popl %%ebp \n"
|
||||
".cfi_adjust_cfa_offset -4 \n"
|
||||
".cfi_restore ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_endproc \n"
|
||||
#endif
|
||||
#endif
|
||||
// Copy EAX:EDX to retQW. As the stack pointer has been
|
||||
// restored it is now safe to access the local variable
|
||||
@@ -1281,9 +1239,6 @@ endcopy:
|
||||
// and the epilogue below, the stack unwind works as it should.
|
||||
// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
|
||||
"pushl %%ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_startproc \n"
|
||||
#endif
|
||||
".cfi_adjust_cfa_offset 4 \n"
|
||||
".cfi_rel_offset ebp, 0 \n"
|
||||
"movl %%esp, %%ebp \n"
|
||||
@@ -1337,9 +1292,6 @@ endcopy:
|
||||
"popl %%ebp \n"
|
||||
".cfi_adjust_cfa_offset -4 \n"
|
||||
".cfi_restore ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_endproc \n"
|
||||
#endif
|
||||
#endif
|
||||
// Copy EAX:EDX to retQW. As the stack pointer has been
|
||||
// restored it is now safe to access the local variable
|
||||
@@ -1434,9 +1386,6 @@ endcopy:
|
||||
// and the epilogue below, the stack unwind works as it should.
|
||||
// TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below
|
||||
"pushl %%ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_startproc \n"
|
||||
#endif
|
||||
".cfi_adjust_cfa_offset 4 \n"
|
||||
".cfi_rel_offset ebp, 0 \n"
|
||||
"movl %%esp, %%ebp \n"
|
||||
@@ -1503,9 +1452,6 @@ endcopy:
|
||||
"popl %%ebp \n"
|
||||
".cfi_adjust_cfa_offset -4 \n"
|
||||
".cfi_restore ebp \n"
|
||||
#ifndef __ANDROID__
|
||||
".cfi_endproc \n"
|
||||
#endif
|
||||
#endif
|
||||
// Copy EAX:EDX to retQW. As the stack pointer has been
|
||||
// restored it is now safe to access the local variable
|
||||
|
||||
@@ -33,6 +33,8 @@ bool CIrrDeviceAndroid::IsPaused = true;
|
||||
bool CIrrDeviceAndroid::IsFocused = false;
|
||||
bool CIrrDeviceAndroid::IsStarted = false;
|
||||
|
||||
AndroidApplicationInfo CIrrDeviceAndroid::ApplicationInfo;
|
||||
|
||||
// Execution of android_main() function is a kind of "onCreate" event, so this
|
||||
// function should be used there to make sure that global window state variables
|
||||
// have their default values on startup.
|
||||
@@ -50,6 +52,7 @@ CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
||||
Gyroscope(0),
|
||||
AccelerometerActive(false),
|
||||
GyroscopeActive(false),
|
||||
TextInputEnabled(false),
|
||||
IsMousePressed(false),
|
||||
GamepadAxisX(0),
|
||||
GamepadAxisY(0),
|
||||
@@ -58,68 +61,82 @@ CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CIrrDeviceAndroid");
|
||||
#endif
|
||||
|
||||
Android = (android_app *)(param.PrivateData);
|
||||
assert(Android != NULL);
|
||||
|
||||
Android->userData = this;
|
||||
Android->onAppCmd = handleAndroidCommand;
|
||||
Android->onAppCmdDirect = handleAndroidCommandDirect;
|
||||
Android->onInputEvent = handleInput;
|
||||
|
||||
printConfig();
|
||||
createKeyMap();
|
||||
|
||||
CursorControl = new CCursorControl();
|
||||
|
||||
Android = (android_app*)(param.PrivateData);
|
||||
|
||||
Close = Android->destroyRequested;
|
||||
|
||||
// It typically shouldn't happen, but just in case...
|
||||
if (Close)
|
||||
return;
|
||||
|
||||
SensorManager = ASensorManager_getInstance();
|
||||
SensorEventQueue = ASensorManager_createEventQueue(SensorManager,
|
||||
Android->looper, LOOPER_ID_USER, NULL, NULL);
|
||||
|
||||
ANativeActivity_setWindowFlags(Android->activity,
|
||||
AWINDOW_FLAG_KEEP_SCREEN_ON |
|
||||
AWINDOW_FLAG_FULLSCREEN, 0);
|
||||
|
||||
os::Printer::log("Waiting for Android activity window to be created.", ELL_DEBUG);
|
||||
|
||||
while (!IsStarted || !IsFocused || IsPaused)
|
||||
if (Android == NULL && CreationParams.DriverType != video::EDT_NULL)
|
||||
{
|
||||
s32 events = 0;
|
||||
android_poll_source* source = 0;
|
||||
|
||||
s32 id = ALooper_pollAll(-1, NULL, &events, (void**)&source);
|
||||
|
||||
if (id >=0 && source != NULL)
|
||||
{
|
||||
source->process(Android, source);
|
||||
}
|
||||
os::Printer::log("Irrlicht device can run only with NULL driver without android_app.", ELL_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(Android->window);
|
||||
os::Printer::log("Done", ELL_DEBUG);
|
||||
|
||||
ExposedVideoData.OGLESAndroid.Window = Android->window;
|
||||
|
||||
createVideoModeList();
|
||||
if (Android != NULL)
|
||||
{
|
||||
Android->userData = this;
|
||||
Android->onAppCmd = handleAndroidCommand;
|
||||
Android->onAppCmdDirect = handleAndroidCommandDirect;
|
||||
Android->onInputEvent = handleInput;
|
||||
|
||||
printConfig();
|
||||
|
||||
Close = Android->destroyRequested;
|
||||
|
||||
// It typically shouldn't happen, but just in case...
|
||||
if (Close)
|
||||
return;
|
||||
|
||||
SensorManager = ASensorManager_getInstance();
|
||||
SensorEventQueue = ASensorManager_createEventQueue(SensorManager,
|
||||
Android->looper, LOOPER_ID_USER, NULL, NULL);
|
||||
|
||||
ANativeActivity_setWindowFlags(Android->activity,
|
||||
AWINDOW_FLAG_KEEP_SCREEN_ON |
|
||||
AWINDOW_FLAG_FULLSCREEN, 0);
|
||||
|
||||
os::Printer::log("Waiting for Android activity window to be created.", ELL_DEBUG);
|
||||
|
||||
while (!IsStarted || !IsFocused || IsPaused)
|
||||
{
|
||||
s32 events = 0;
|
||||
android_poll_source* source = 0;
|
||||
|
||||
s32 id = ALooper_pollAll(-1, NULL, &events, (void**)&source);
|
||||
|
||||
if (id >=0 && source != NULL)
|
||||
{
|
||||
source->process(Android, source);
|
||||
}
|
||||
}
|
||||
|
||||
assert(Android->window);
|
||||
os::Printer::log("Done", ELL_DEBUG);
|
||||
|
||||
ExposedVideoData.OGLESAndroid.Window = Android->window;
|
||||
|
||||
createVideoModeList();
|
||||
}
|
||||
|
||||
createDriver();
|
||||
|
||||
if (VideoDriver)
|
||||
{
|
||||
createGUIAndScene();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CIrrDeviceAndroid::~CIrrDeviceAndroid()
|
||||
{
|
||||
Android->userData = NULL;
|
||||
Android->onAppCmd = NULL;
|
||||
Android->onInputEvent = NULL;
|
||||
if (Android)
|
||||
{
|
||||
Android->userData = NULL;
|
||||
Android->onAppCmd = NULL;
|
||||
Android->onInputEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::printConfig()
|
||||
@@ -211,6 +228,9 @@ bool CIrrDeviceAndroid::run()
|
||||
{
|
||||
os::Timer::tick();
|
||||
|
||||
if (Android == NULL)
|
||||
return !Close;
|
||||
|
||||
while (!Close)
|
||||
{
|
||||
s32 Events = 0;
|
||||
@@ -372,8 +392,8 @@ void CIrrDeviceAndroid::handleAndroidCommandDirect(ANativeActivity* activity,
|
||||
switch (cmd)
|
||||
{
|
||||
case APP_CMD_RESUME:
|
||||
os::Printer::log("Android command direct APP_CMD_RESUME", ELL_DEBUG);
|
||||
hideNavBar(activity);
|
||||
os::Printer::log("Android command direct APP_CMD_RESUME", ELL_DEBUG);
|
||||
hideNavBar(activity);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -684,14 +704,22 @@ s32 CIrrDeviceAndroid::handleKeyboard(AInputEvent* androidEvent)
|
||||
|
||||
if (event.KeyInput.Key > 0)
|
||||
{
|
||||
getKeyChar(event);
|
||||
if (TextInputEnabled == true)
|
||||
{
|
||||
event.KeyInput.Char = getUnicodeChar(androidEvent);
|
||||
}
|
||||
|
||||
if (event.KeyInput.Char == 0)
|
||||
{
|
||||
event.KeyInput.Char = getKeyChar(event);
|
||||
}
|
||||
}
|
||||
|
||||
// If button doesn't return key code, then at least use device-specific
|
||||
// scan code, because it's better than nothing
|
||||
if (event.KeyInput.Key == 0)
|
||||
{
|
||||
event.KeyInput.Key = (EKEY_CODE)scanCode;
|
||||
event.KeyInput.Key = (EKEY_CODE)((int)IRR_KEY_CODES_COUNT + scanCode);
|
||||
}
|
||||
|
||||
// Handle an event when back button in pressed just like an escape key
|
||||
@@ -842,7 +870,7 @@ s32 CIrrDeviceAndroid::handleGamepad(AInputEvent* androidEvent)
|
||||
|
||||
if (event.KeyInput.Key == 0)
|
||||
{
|
||||
event.KeyInput.Key = (EKEY_CODE)scanCode;
|
||||
event.KeyInput.Key = (EKEY_CODE)((int)IRR_KEY_CODES_COUNT + scanCode);
|
||||
}
|
||||
|
||||
postEventFromUser(event);
|
||||
@@ -935,14 +963,14 @@ void CIrrDeviceAndroid::createKeyMap()
|
||||
KeyMap[AKEYCODE_DEL] = IRR_KEY_BACK;
|
||||
KeyMap[AKEYCODE_GRAVE] = IRR_KEY_OEM_3;
|
||||
KeyMap[AKEYCODE_MINUS] = IRR_KEY_MINUS;
|
||||
KeyMap[AKEYCODE_EQUALS] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_LEFT_BRACKET] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_RIGHT_BRACKET] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_BACKSLASH] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_SEMICOLON] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_APOSTROPHE] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_SLASH] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_AT] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_EQUALS] = IRR_KEY_PLUS;
|
||||
KeyMap[AKEYCODE_LEFT_BRACKET] = IRR_KEY_OEM_4;
|
||||
KeyMap[AKEYCODE_RIGHT_BRACKET] = IRR_KEY_OEM_6;
|
||||
KeyMap[AKEYCODE_BACKSLASH] = IRR_KEY_OEM_5;
|
||||
KeyMap[AKEYCODE_SEMICOLON] = IRR_KEY_OEM_1;
|
||||
KeyMap[AKEYCODE_APOSTROPHE] = IRR_KEY_OEM_7;
|
||||
KeyMap[AKEYCODE_SLASH] = IRR_KEY_OEM_2;
|
||||
KeyMap[AKEYCODE_AT] = IRR_KEY_2;
|
||||
KeyMap[AKEYCODE_NUM] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_HEADSETHOOK] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_FOCUS] = IRR_KEY_UNKNOWN;
|
||||
@@ -985,8 +1013,8 @@ void CIrrDeviceAndroid::createKeyMap()
|
||||
KeyMap[AKEYCODE_CTRL_RIGHT] = IRR_KEY_CONTROL;
|
||||
KeyMap[AKEYCODE_CAPS_LOCK] = IRR_KEY_CAPITAL;
|
||||
KeyMap[AKEYCODE_SCROLL_LOCK] = IRR_KEY_SCROLL;
|
||||
KeyMap[AKEYCODE_META_LEFT] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_META_RIGHT] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_META_LEFT] = IRR_KEY_LWIN;
|
||||
KeyMap[AKEYCODE_META_RIGHT] = IRR_KEY_RWIN;
|
||||
KeyMap[AKEYCODE_FUNCTION] = IRR_KEY_UNKNOWN;
|
||||
KeyMap[AKEYCODE_SYSRQ] = IRR_KEY_SNAPSHOT;
|
||||
KeyMap[AKEYCODE_BREAK] = IRR_KEY_PAUSE;
|
||||
@@ -1093,59 +1121,118 @@ void CIrrDeviceAndroid::createKeyMap()
|
||||
KeyMap[AKEYCODE_MEDIA_AUDIO_TRACK] = IRR_KEY_UNKNOWN;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::getKeyChar(SEvent& event)
|
||||
wchar_t CIrrDeviceAndroid::getKeyChar(SEvent& event)
|
||||
{
|
||||
// Handle ASCII chars
|
||||
|
||||
event.KeyInput.Char = 0;
|
||||
wchar_t key_char = 0;
|
||||
|
||||
// A-Z
|
||||
if (event.KeyInput.SystemKeyCode > 28 && event.KeyInput.SystemKeyCode < 55)
|
||||
{
|
||||
if (event.KeyInput.Shift)
|
||||
{
|
||||
event.KeyInput.Char = event.KeyInput.SystemKeyCode + 36;
|
||||
key_char = event.KeyInput.SystemKeyCode + 36;
|
||||
}
|
||||
else
|
||||
{
|
||||
event.KeyInput.Char = event.KeyInput.SystemKeyCode + 68;
|
||||
key_char = event.KeyInput.SystemKeyCode + 68;
|
||||
}
|
||||
}
|
||||
|
||||
// 0-9
|
||||
else if (event.KeyInput.SystemKeyCode > 6 && event.KeyInput.SystemKeyCode < 17)
|
||||
{
|
||||
event.KeyInput.Char = event.KeyInput.SystemKeyCode + 41;
|
||||
key_char = event.KeyInput.SystemKeyCode + 41;
|
||||
}
|
||||
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_BACK)
|
||||
{
|
||||
event.KeyInput.Char = 8;
|
||||
key_char = 8;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_DEL)
|
||||
{
|
||||
event.KeyInput.Char = 8;
|
||||
key_char = 8;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_TAB)
|
||||
{
|
||||
event.KeyInput.Char = 9;
|
||||
key_char = 9;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_ENTER)
|
||||
{
|
||||
event.KeyInput.Char = 13;
|
||||
key_char = 13;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_SPACE)
|
||||
{
|
||||
event.KeyInput.Char = 32;
|
||||
key_char = 32;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_COMMA)
|
||||
{
|
||||
event.KeyInput.Char = 44;
|
||||
key_char = 44;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_PERIOD)
|
||||
{
|
||||
event.KeyInput.Char = 46;
|
||||
key_char = 46;
|
||||
}
|
||||
|
||||
return key_char;
|
||||
}
|
||||
|
||||
wchar_t CIrrDeviceAndroid::getUnicodeChar(AInputEvent* event)
|
||||
{
|
||||
bool was_detached = false;
|
||||
JNIEnv* env = NULL;
|
||||
|
||||
jint status = Android->activity->vm->GetEnv((void**)&env, JNI_VERSION_1_6);
|
||||
|
||||
if (status == JNI_EDETACHED)
|
||||
{
|
||||
JavaVMAttachArgs args;
|
||||
args.version = JNI_VERSION_1_6;
|
||||
args.name = "NativeThread";
|
||||
args.group = NULL;
|
||||
|
||||
status = Android->activity->vm->AttachCurrentThread(&env, &args);
|
||||
was_detached = true;
|
||||
}
|
||||
|
||||
if (status != JNI_OK)
|
||||
{
|
||||
os::Printer::log("Cannot get unicode character.", ELL_DEBUG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
jlong down_time = AKeyEvent_getDownTime(event);
|
||||
jlong event_time = AKeyEvent_getEventTime(event);
|
||||
jint action = AKeyEvent_getAction(event);
|
||||
jint code = AKeyEvent_getKeyCode(event);
|
||||
jint repeat = AKeyEvent_getRepeatCount(event);
|
||||
jint meta_state = AKeyEvent_getMetaState(event);
|
||||
jint device_id = AInputEvent_getDeviceId(event);
|
||||
jint scan_code = AKeyEvent_getScanCode(event);
|
||||
jint flags = AKeyEvent_getFlags(event);
|
||||
jint source = AInputEvent_getSource(event);
|
||||
|
||||
jclass key_event = env->FindClass("android/view/KeyEvent");
|
||||
jmethodID key_event_constructor = env->GetMethodID(key_event, "<init>",
|
||||
"(JJIIIIIIII)V");
|
||||
|
||||
jobject key_event_obj = env->NewObject(key_event, key_event_constructor,
|
||||
down_time, event_time, action, code,
|
||||
repeat, meta_state, device_id,
|
||||
scan_code, flags, source);
|
||||
|
||||
jmethodID get_unicode = env->GetMethodID(key_event, "getUnicodeChar", "(I)I");
|
||||
|
||||
wchar_t unicode_char = env->CallIntMethod(key_event_obj, get_unicode,
|
||||
meta_state);
|
||||
|
||||
if (was_detached)
|
||||
{
|
||||
Android->activity->vm->DetachCurrentThread();
|
||||
}
|
||||
|
||||
return unicode_char;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::hideNavBar(ANativeActivity* activity)
|
||||
@@ -1288,6 +1375,120 @@ int CIrrDeviceAndroid::getRotation()
|
||||
return rotation;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::readApplicationInfo(ANativeActivity* activity)
|
||||
{
|
||||
bool was_detached = false;
|
||||
JNIEnv* env = NULL;
|
||||
|
||||
jint status = activity->vm->GetEnv((void**)&env, JNI_VERSION_1_6);
|
||||
|
||||
if (status == JNI_EDETACHED)
|
||||
{
|
||||
JavaVMAttachArgs args;
|
||||
args.version = JNI_VERSION_1_6;
|
||||
args.name = "NativeThread";
|
||||
args.group = NULL;
|
||||
|
||||
status = activity->vm->AttachCurrentThread(&env, &args);
|
||||
was_detached = true;
|
||||
}
|
||||
|
||||
if (status != JNI_OK)
|
||||
{
|
||||
os::Printer::log("Cannot get application info.", ELL_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
jobject activity_obj = activity->clazz;
|
||||
jclass activity_class = env->GetObjectClass(activity_obj);
|
||||
|
||||
jmethodID get_package_manager = env->GetMethodID(activity_class,
|
||||
"getPackageManager",
|
||||
"()Landroid/content/pm/PackageManager;");
|
||||
jobject package_manager_obj = env->CallObjectMethod(activity_obj,
|
||||
get_package_manager);
|
||||
|
||||
jmethodID get_intent = env->GetMethodID(activity_class, "getIntent",
|
||||
"()Landroid/content/Intent;");
|
||||
|
||||
jobject intent_obj = env->CallObjectMethod(activity_obj, get_intent);
|
||||
jclass intent = env->FindClass("android/content/Intent");
|
||||
|
||||
jmethodID get_component = env->GetMethodID(intent, "getComponent",
|
||||
"()Landroid/content/ComponentName;");
|
||||
|
||||
jobject component_name = env->CallObjectMethod(intent_obj, get_component);
|
||||
|
||||
jclass package_manager = env->FindClass("android/content/pm/PackageManager");
|
||||
|
||||
jfieldID get_meta_data_field = env->GetStaticFieldID(package_manager,
|
||||
"GET_META_DATA", "I");
|
||||
jint get_meta_data = env->GetStaticIntField(package_manager,
|
||||
get_meta_data_field);
|
||||
|
||||
jmethodID get_activity_info = env->GetMethodID(package_manager,
|
||||
"getActivityInfo",
|
||||
"(Landroid/content/ComponentName;I)"
|
||||
"Landroid/content/pm/ActivityInfo;");
|
||||
|
||||
jobject activity_info_obj = env->CallObjectMethod(package_manager_obj,
|
||||
get_activity_info,
|
||||
component_name,
|
||||
get_meta_data);
|
||||
jclass activity_info = env->FindClass("android/content/pm/ActivityInfo");
|
||||
|
||||
jfieldID application_info_field = env->GetFieldID(activity_info,
|
||||
"applicationInfo",
|
||||
"Landroid/content/pm/ApplicationInfo;");
|
||||
jobject application_info_obj = env->GetObjectField(activity_info_obj,
|
||||
application_info_field);
|
||||
jclass application_info = env->FindClass("android/content/pm/ApplicationInfo");
|
||||
|
||||
jfieldID native_library_dir_field = env->GetFieldID(application_info,
|
||||
"nativeLibraryDir",
|
||||
"Ljava/lang/String;");
|
||||
jstring native_library_dir_str = (jstring)env->GetObjectField(
|
||||
application_info_obj,
|
||||
native_library_dir_field);
|
||||
const char* native_library_dir = env->GetStringUTFChars(
|
||||
native_library_dir_str,
|
||||
NULL);
|
||||
|
||||
jfieldID data_dir_field = env->GetFieldID(application_info, "dataDir",
|
||||
"Ljava/lang/String;");
|
||||
jstring data_dir_str = (jstring)env->GetObjectField(application_info_obj,
|
||||
data_dir_field);
|
||||
const char* data_dir = env->GetStringUTFChars(data_dir_str, NULL);
|
||||
|
||||
if (native_library_dir != NULL)
|
||||
{
|
||||
ApplicationInfo.native_lib_dir = native_library_dir;
|
||||
}
|
||||
|
||||
if (data_dir != NULL)
|
||||
{
|
||||
ApplicationInfo.data_dir = data_dir;
|
||||
}
|
||||
|
||||
ApplicationInfo.initialized = true;
|
||||
|
||||
if (was_detached)
|
||||
{
|
||||
activity->vm->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
const AndroidApplicationInfo& CIrrDeviceAndroid::getApplicationInfo(
|
||||
ANativeActivity* activity)
|
||||
{
|
||||
if (activity != NULL && ApplicationInfo.initialized == false)
|
||||
{
|
||||
readApplicationInfo(activity);
|
||||
}
|
||||
|
||||
return ApplicationInfo;
|
||||
}
|
||||
|
||||
DeviceOrientation CIrrDeviceAndroid::getDefaultOrientation()
|
||||
{
|
||||
int rotation = getRotation();
|
||||
|
||||
@@ -30,6 +30,15 @@ namespace irr
|
||||
ORIENTATION_LANDSCAPE
|
||||
};
|
||||
|
||||
struct AndroidApplicationInfo
|
||||
{
|
||||
std::string native_lib_dir;
|
||||
std::string data_dir;
|
||||
bool initialized;
|
||||
|
||||
AndroidApplicationInfo() : initialized(false) {};
|
||||
};
|
||||
|
||||
class CIrrDeviceAndroid : public CIrrDeviceStub, video::IImagePresenter
|
||||
{
|
||||
public:
|
||||
@@ -64,6 +73,7 @@ namespace irr
|
||||
virtual bool deactivateGyroscope();
|
||||
virtual bool isGyroscopeActive();
|
||||
virtual bool isGyroscopeAvailable();
|
||||
virtual void setTextInputEnabled(bool enabled) {TextInputEnabled = enabled;}
|
||||
|
||||
class CCursorControl : public gui::ICursorControl
|
||||
{
|
||||
@@ -104,6 +114,8 @@ namespace irr
|
||||
};
|
||||
|
||||
static void onCreate();
|
||||
static const AndroidApplicationInfo& getApplicationInfo(
|
||||
ANativeActivity* activity);
|
||||
|
||||
private:
|
||||
android_app* Android;
|
||||
@@ -113,6 +125,8 @@ namespace irr
|
||||
const ASensor* Gyroscope;
|
||||
bool AccelerometerActive;
|
||||
bool GyroscopeActive;
|
||||
bool TextInputEnabled;
|
||||
static AndroidApplicationInfo ApplicationInfo;
|
||||
|
||||
static bool IsPaused;
|
||||
static bool IsFocused;
|
||||
@@ -141,8 +155,10 @@ namespace irr
|
||||
void createDriver();
|
||||
void createKeyMap();
|
||||
void createVideoModeList();
|
||||
void getKeyChar(SEvent& event);
|
||||
wchar_t getKeyChar(SEvent& event);
|
||||
wchar_t getUnicodeChar(AInputEvent* event);
|
||||
static void hideNavBar(ANativeActivity* activity);
|
||||
static void readApplicationInfo(ANativeActivity* activity);
|
||||
int getRotation();
|
||||
DeviceOrientation getDefaultOrientation();
|
||||
video::SExposedVideoData& getExposedVideoData();
|
||||
|
||||
@@ -2179,6 +2179,8 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList()
|
||||
XRRScreenResources* res = XRRGetScreenResources(display, DefaultRootWindow(display));
|
||||
if (!res)
|
||||
break;
|
||||
|
||||
const char* output_name = getenv("IRR_VIDEO_OUTPUT");
|
||||
|
||||
RROutput primary_id = XRRGetOutputPrimary(display, DefaultRootWindow(display));
|
||||
|
||||
@@ -2198,8 +2200,18 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (res->outputs[i] == primary_id ||
|
||||
output_id == 0 || crtc_tmp->x < crtc->x ||
|
||||
bool is_primary = false;
|
||||
|
||||
if (output_name != NULL)
|
||||
{
|
||||
is_primary = (strcmp(output_name, output_tmp->name) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
is_primary = (res->outputs[i] == primary_id);
|
||||
}
|
||||
|
||||
if (is_primary || output_id == 0 || crtc_tmp->x < crtc->x ||
|
||||
(crtc_tmp->x == crtc->x && crtc_tmp->y < crtc->y))
|
||||
{
|
||||
XRRFreeCrtcInfo(crtc);
|
||||
@@ -2215,7 +2227,7 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList()
|
||||
XRRFreeOutputInfo(output_tmp);
|
||||
}
|
||||
|
||||
if (res->outputs[i] == primary_id)
|
||||
if (is_primary)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Modify this file to change the last-modified date when you add/remove a file.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
||||
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
||||
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "audio/music_dummy.hpp"
|
||||
#include "audio/music_ogg.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
@@ -170,10 +171,15 @@ void MusicInformation::startMusic()
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SOUND
|
||||
m_normal_music = new MusicOggStream(m_normal_loop_start);
|
||||
#else
|
||||
m_normal_music = new MusicDummy();
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
m_normal_music = new MusicOggStream(m_normal_loop_start);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_normal_music = new MusicDummy();
|
||||
}
|
||||
|
||||
if (m_normal_music->load(m_normal_filename) == false)
|
||||
{
|
||||
@@ -201,10 +207,15 @@ void MusicInformation::startMusic()
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SOUND
|
||||
m_fast_music = new MusicOggStream(m_fast_loop_start);
|
||||
#else
|
||||
m_fast_music = new MusicDummy();
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
m_fast_music = new MusicOggStream(m_fast_loop_start);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_fast_music = new MusicDummy();
|
||||
}
|
||||
|
||||
if (m_fast_music->load(m_fast_filename) == false)
|
||||
{
|
||||
|
||||
@@ -50,43 +50,44 @@ MusicManager::MusicManager()
|
||||
|
||||
//FIXME: I'm not sure that this code goes here
|
||||
#ifdef ENABLE_SOUND
|
||||
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
#if defined(__APPLE__) && !defined(NDEBUG)
|
||||
// HACK: On OSX, when OpenAL is initialized, breaking in a debugger causes
|
||||
// my iTunes music to stop too, which is highly annoying ;) so in debug
|
||||
// mode, require a restart to enable sound
|
||||
if (UserConfigParams::m_sfx || UserConfigParams::m_music)
|
||||
{
|
||||
// HACK: On OSX, when OpenAL is initialized, breaking in a debugger
|
||||
// causes my iTunes music to stop too, which is highly annoying ;) so in
|
||||
// debug mode, require a restart to enable sound
|
||||
if (UserConfigParams::m_sfx || UserConfigParams::m_music)
|
||||
{
|
||||
#endif
|
||||
|
||||
ALCdevice* device = alcOpenDevice ( NULL ); //The default sound device
|
||||
if( device == NULL )
|
||||
{
|
||||
Log::warn("MusicManager", "Could not open the default sound device.");
|
||||
m_initialized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
ALCcontext* context = alcCreateContext( device, NULL );
|
||||
|
||||
if( context == NULL )
|
||||
{
|
||||
Log::warn("MusicManager", "Could not create a sound context.");
|
||||
m_initialized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
alcMakeContextCurrent( context );
|
||||
m_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
ALCdevice* device = alcOpenDevice(NULL); //The default sound device
|
||||
|
||||
if (device == NULL)
|
||||
{
|
||||
Log::warn("MusicManager", "Could not open the default sound "
|
||||
"device.");
|
||||
m_initialized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ALCcontext* context = alcCreateContext(device, NULL);
|
||||
|
||||
if (context == NULL)
|
||||
{
|
||||
Log::warn("MusicManager", "Could not create a sound "
|
||||
"context.");
|
||||
m_initialized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
alcMakeContextCurrent(context);
|
||||
m_initialized = true;
|
||||
}
|
||||
}
|
||||
#if defined(__APPLE__) && !defined(NDEBUG)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
alGetError(); //Called here to clear any non-important errors found
|
||||
alGetError(); //Called here to clear any non-important errors found
|
||||
}
|
||||
#endif
|
||||
|
||||
loadMusicInformation();
|
||||
|
||||
@@ -97,24 +97,27 @@ bool SFXBuffer::load()
|
||||
if (UserConfigParams::m_sfx == false) return false;
|
||||
|
||||
#ifdef ENABLE_SOUND
|
||||
if (m_loaded) return false;
|
||||
|
||||
alGetError(); // clear errors from previously
|
||||
|
||||
alGenBuffers(1, &m_buffer);
|
||||
if (!SFXManager::checkError("generating a buffer"))
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
assert( alIsBuffer(m_buffer) );
|
||||
|
||||
if (!loadVorbisBuffer(m_file, m_buffer))
|
||||
{
|
||||
Log::error("SFXBuffer", "Could not load sound effect %s",
|
||||
m_file.c_str());
|
||||
// TODO: free al buffer here?
|
||||
return false;
|
||||
if (m_loaded) return false;
|
||||
|
||||
alGetError(); // clear errors from previously
|
||||
|
||||
alGenBuffers(1, &m_buffer);
|
||||
if (!SFXManager::checkError("generating a buffer"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(alIsBuffer(m_buffer));
|
||||
|
||||
if (!loadVorbisBuffer(m_file, m_buffer))
|
||||
{
|
||||
Log::error("SFXBuffer", "Could not load sound effect %s",
|
||||
m_file.c_str());
|
||||
// TODO: free al buffer here?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -131,10 +134,13 @@ bool SFXBuffer::load()
|
||||
void SFXBuffer::unload()
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (m_loaded)
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
alDeleteBuffers(1, &m_buffer);
|
||||
m_buffer = 0;
|
||||
if (m_loaded)
|
||||
{
|
||||
alDeleteBuffers(1, &m_buffer);
|
||||
m_buffer = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_loaded = false;
|
||||
@@ -148,6 +154,9 @@ void SFXBuffer::unload()
|
||||
bool SFXBuffer::loadVorbisBuffer(const std::string &name, ALuint buffer)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return false;
|
||||
|
||||
const int ogg_endianness = (IS_LITTLE_ENDIAN ? 0 : 1);
|
||||
|
||||
|
||||
|
||||
@@ -98,32 +98,35 @@ SFXManager::SFXManager()
|
||||
loadSfx();
|
||||
|
||||
#ifdef ENABLE_SOUND
|
||||
pthread_cond_init(&m_cond_request, NULL);
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
m_thread_id.setAtomic(new pthread_t());
|
||||
// The thread is created even if there atm sfx are disabled
|
||||
// (since the user might enable it later).
|
||||
int error = pthread_create(m_thread_id.getData(), &attr,
|
||||
&SFXManager::mainLoop, this);
|
||||
if (error)
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
m_thread_id.lock();
|
||||
delete m_thread_id.getData();
|
||||
m_thread_id.unlock();
|
||||
m_thread_id.setAtomic(0);
|
||||
Log::error("SFXManager", "Could not create thread, error=%d.",
|
||||
errno);
|
||||
pthread_cond_init(&m_cond_request, NULL);
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
m_thread_id.setAtomic(new pthread_t());
|
||||
// The thread is created even if there atm sfx are disabled
|
||||
// (since the user might enable it later).
|
||||
int error = pthread_create(m_thread_id.getData(), &attr,
|
||||
&SFXManager::mainLoop, this);
|
||||
if (error)
|
||||
{
|
||||
m_thread_id.lock();
|
||||
delete m_thread_id.getData();
|
||||
m_thread_id.unlock();
|
||||
m_thread_id.setAtomic(0);
|
||||
Log::error("SFXManager", "Could not create thread, error=%d.",
|
||||
errno);
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
setMasterSFXVolume( UserConfigParams::m_sfx_volume );
|
||||
m_sfx_commands.lock();
|
||||
m_sfx_commands.getData().clear();
|
||||
m_sfx_commands.unlock();
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
setMasterSFXVolume( UserConfigParams::m_sfx_volume );
|
||||
m_sfx_commands.lock();
|
||||
m_sfx_commands.getData().clear();
|
||||
m_sfx_commands.unlock();
|
||||
#endif
|
||||
} // SoundManager
|
||||
|
||||
@@ -133,11 +136,14 @@ SFXManager::SFXManager()
|
||||
SFXManager::~SFXManager()
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
m_thread_id.lock();
|
||||
pthread_join(*m_thread_id.getData(), NULL);
|
||||
delete m_thread_id.getData();
|
||||
m_thread_id.unlock();
|
||||
pthread_cond_destroy(&m_cond_request);
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
m_thread_id.lock();
|
||||
pthread_join(*m_thread_id.getData(), NULL);
|
||||
delete m_thread_id.getData();
|
||||
m_thread_id.unlock();
|
||||
pthread_cond_destroy(&m_cond_request);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---- clear m_all_sfx
|
||||
@@ -189,6 +195,9 @@ SFXManager::~SFXManager()
|
||||
void SFXManager::queue(SFXCommands command, SFXBase *sfx)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
SFXCommand *sfx_command = new SFXCommand(command, sfx);
|
||||
queueCommand(sfx_command);
|
||||
#endif
|
||||
@@ -205,6 +214,9 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx)
|
||||
void SFXManager::queue(SFXCommands command, SFXBase *sfx, float f)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
SFXCommand *sfx_command = new SFXCommand(command, sfx, f);
|
||||
queueCommand(sfx_command);
|
||||
#endif
|
||||
@@ -221,8 +233,11 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx, float f)
|
||||
void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
SFXCommand *sfx_command = new SFXCommand(command, sfx, p);
|
||||
queueCommand(sfx_command);
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
SFXCommand *sfx_command = new SFXCommand(command, sfx, p);
|
||||
queueCommand(sfx_command);
|
||||
#endif
|
||||
} // queue (Vec3)
|
||||
|
||||
@@ -231,6 +246,9 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p)
|
||||
void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p, SFXBuffer* buffer)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
SFXCommand *sfx_command = new SFXCommand(command, sfx, p);
|
||||
sfx_command->m_buffer = buffer;
|
||||
queueCommand(sfx_command);
|
||||
@@ -250,6 +268,9 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx, float f,
|
||||
const Vec3 &p)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
SFXCommand *sfx_command = new SFXCommand(command, sfx, f, p);
|
||||
queueCommand(sfx_command);
|
||||
#endif
|
||||
@@ -262,6 +283,9 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx, float f,
|
||||
void SFXManager::queue(SFXCommands command, MusicInformation *mi)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
SFXCommand *sfx_command = new SFXCommand(command, mi);
|
||||
queueCommand(sfx_command);
|
||||
#endif
|
||||
@@ -275,6 +299,9 @@ void SFXManager::queue(SFXCommands command, MusicInformation *mi)
|
||||
void SFXManager::queue(SFXCommands command, MusicInformation *mi, float f)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
SFXCommand *sfx_command = new SFXCommand(command, mi, f);
|
||||
queueCommand(sfx_command);
|
||||
#endif
|
||||
@@ -288,6 +315,9 @@ void SFXManager::queue(SFXCommands command, MusicInformation *mi, float f)
|
||||
void SFXManager::queueCommand(SFXCommand *command)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
m_sfx_commands.lock();
|
||||
if(World::getWorld() &&
|
||||
m_sfx_commands.getData().size() > 20*race_manager->getNumberOfKarts()+20 &&
|
||||
@@ -321,12 +351,17 @@ void SFXManager::queueCommand(SFXCommand *command)
|
||||
void SFXManager::stopThread()
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
queue(SFX_EXIT);
|
||||
// Make sure the thread wakes up.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
#else
|
||||
setCanBeDeleted();
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
queue(SFX_EXIT);
|
||||
// Make sure the thread wakes up.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
setCanBeDeleted();
|
||||
}
|
||||
} // stopThread
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -338,6 +373,9 @@ void SFXManager::stopThread()
|
||||
void* SFXManager::mainLoop(void *obj)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return NULL;
|
||||
|
||||
VS::setThreadName("SFXManager");
|
||||
SFXManager *me = (SFXManager*)obj;
|
||||
|
||||
@@ -674,14 +712,24 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
|
||||
positional = buffer->isPositional();
|
||||
}
|
||||
|
||||
SFXBase* sfx = NULL;
|
||||
|
||||
#ifdef ENABLE_SOUND
|
||||
//assert( alIsBuffer(buffer->getBufferID()) ); crashes on server
|
||||
SFXBase* sfx = new SFXOpenAL(buffer, positional, buffer->getGain(), owns_buffer);
|
||||
#else
|
||||
SFXBase* sfx = new DummySFX(buffer, positional, buffer->getGain());
|
||||
if (owns_buffer)
|
||||
delete buffer;
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
//assert( alIsBuffer(buffer->getBufferID()) ); crashes on server
|
||||
sfx = new SFXOpenAL(buffer, positional, buffer->getGain(), owns_buffer);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sfx = new DummySFX(buffer, positional, buffer->getGain());
|
||||
|
||||
if (owns_buffer)
|
||||
{
|
||||
delete buffer;
|
||||
}
|
||||
}
|
||||
|
||||
sfx->setMasterVolume(m_master_gain);
|
||||
|
||||
@@ -766,6 +814,9 @@ void SFXManager::deleteSFXMapping(const std::string &name)
|
||||
void SFXManager::update()
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
queue(SFX_UPDATE, (SFXBase*)NULL);
|
||||
// Wake up the sfx thread to handle all queued up audio commands.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
@@ -780,6 +831,9 @@ void SFXManager::update()
|
||||
void SFXManager::reallyUpdateNow(SFXCommand *current)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return;
|
||||
|
||||
if (m_last_update_time < 0.0)
|
||||
{
|
||||
// first time
|
||||
@@ -906,10 +960,13 @@ void SFXManager::reallyResumeAllNow()
|
||||
bool SFXManager::checkError(const std::string &context)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return true;
|
||||
|
||||
// Check (and clear) the error flag
|
||||
int error = alGetError();
|
||||
|
||||
if(error != AL_NO_ERROR)
|
||||
if (error != AL_NO_ERROR)
|
||||
{
|
||||
Log::error("SFXManager", "SFXOpenAL OpenAL error while %s: %s",
|
||||
context.c_str(), SFXManager::getErrorString(error).c_str());
|
||||
@@ -958,6 +1015,9 @@ void SFXManager::setMasterSFXVolume(float gain)
|
||||
const std::string SFXManager::getErrorString(int err)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return std::string("sound disabled");
|
||||
|
||||
switch(err)
|
||||
{
|
||||
case AL_NO_ERROR: return std::string("AL_NO_ERROR" );
|
||||
@@ -968,9 +1028,9 @@ const std::string SFXManager::getErrorString(int err)
|
||||
case AL_OUT_OF_MEMORY: return std::string("AL_OUT_OF_MEMORY" );
|
||||
default: return std::string("UNKNOWN");
|
||||
};
|
||||
#else
|
||||
return std::string("sound disabled");
|
||||
#endif
|
||||
|
||||
return std::string("sound disabled");
|
||||
} // getErrorString
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -152,6 +152,10 @@ public:
|
||||
{
|
||||
return m_elements[key];
|
||||
}
|
||||
U& at(const T key)
|
||||
{
|
||||
return m_elements.at(key);
|
||||
}
|
||||
}; // MapUserConfigParam
|
||||
typedef MapUserConfigParam<uint32_t, uint32_t> UIntToUIntUserConfigParam;
|
||||
typedef MapUserConfigParam<std::string, uint32_t> StringToUIntUserConfigParam;
|
||||
@@ -464,7 +468,7 @@ namespace UserConfigParams
|
||||
"A parameter that determines general accelerometer sensitivity."));
|
||||
|
||||
PARAM_PREFIX FloatUserConfigParam m_multitouch_scale
|
||||
PARAM_DEFAULT( FloatUserConfigParam(1.1f, "multitouch_scale",
|
||||
PARAM_DEFAULT( FloatUserConfigParam(1.2f, "multitouch_scale",
|
||||
&m_multitouch_group,
|
||||
"A parameter in range [0.5, 1.5] that determines the scale of the "
|
||||
"multitouch interface."));
|
||||
@@ -586,7 +590,7 @@ namespace UserConfigParams
|
||||
PARAM_DEFAULT(BoolUserConfigParam(false, "hq_mipmap",
|
||||
&m_video_group, "Generate mipmap for textures using "
|
||||
"high quality method with SSE"));
|
||||
|
||||
|
||||
// ---- Recording
|
||||
PARAM_PREFIX GroupUserConfigParam m_recording_group
|
||||
PARAM_DEFAULT(GroupUserConfigParam("Recording",
|
||||
@@ -672,6 +676,8 @@ namespace UserConfigParams
|
||||
PARAM_PREFIX bool m_race_now PARAM_DEFAULT( false );
|
||||
|
||||
PARAM_PREFIX bool m_enforce_current_player PARAM_DEFAULT( false );
|
||||
|
||||
PARAM_PREFIX bool m_enable_sound PARAM_DEFAULT( true );
|
||||
|
||||
/** True to test funky ambient/diffuse/specularity in RGB &
|
||||
* all anisotropic */
|
||||
@@ -681,21 +687,24 @@ namespace UserConfigParams
|
||||
PARAM_PREFIX bool m_profiler_enabled PARAM_DEFAULT( false );
|
||||
|
||||
// ---- Networking
|
||||
PARAM_PREFIX StringToUIntUserConfigParam m_stun_list
|
||||
PARAM_DEFAULT(StringToUIntUserConfigParam("stun_list",
|
||||
"The stun servers that will be used to know the public address,"
|
||||
" LHS: server address, RHS: ping time.",
|
||||
PARAM_PREFIX StringToUIntUserConfigParam m_stun_servers
|
||||
PARAM_DEFAULT(StringToUIntUserConfigParam("stun_servers",
|
||||
"The stun servers that will be used to know the public address with"
|
||||
" port, LHS: server address, RHS: ping time.",
|
||||
{
|
||||
{ "numb.viagenie.ca", 0u },
|
||||
{ "stun.12connect.com", 0u },
|
||||
{ "stun.callwithus.com", 0u },
|
||||
{ "stun.cope.es", 0u },
|
||||
{ "stun.counterpath.net", 0u },
|
||||
{ "stun.ekiga.net", 0u },
|
||||
{ "stun.ivao.aero", 0u },
|
||||
{ "stun.schlund.de", 0u },
|
||||
{ "stun.stunprotocol.org", 0u },
|
||||
{ "stun.voip.aebc.com", 0u }
|
||||
{ "stun.12connect.com:3478", 0u },
|
||||
{ "stun.callwithus.com:3478", 0u },
|
||||
{ "stun.cope.es:3478", 0u },
|
||||
{ "stun.counterpath.net:3478", 0u },
|
||||
{ "stun.ekiga.net:3478", 0u },
|
||||
{ "stun.ivao.aero:3478", 0u },
|
||||
{ "stun.schlund.de:3478", 0u },
|
||||
{ "stun.stunprotocol.org:3478", 0u },
|
||||
{ "stun.l.google.com:19302", 0u },
|
||||
{ "stun1.l.google.com:19302", 0u },
|
||||
{ "stun2.l.google.com:19302", 0u },
|
||||
{ "stun3.l.google.com:19302", 0u },
|
||||
{ "stun4.l.google.com:19302", 0u }
|
||||
}
|
||||
));
|
||||
|
||||
@@ -750,31 +759,42 @@ namespace UserConfigParams
|
||||
PARAM_PREFIX FloatUserConfigParam m_time_limit_threshold_ffa
|
||||
PARAM_DEFAULT(FloatUserConfigParam(0.7f, "time-limit-threshold-ffa",
|
||||
&m_network_group, "Value used to calculate time limit in free for all, which "
|
||||
"is max(number of players * time-limit-threshold-ffa, 2.0) * 60, negative value to disable time limit."));
|
||||
"is max(number of players * time-limit-threshold-ffa, 3.0) * 60, negative value to disable time limit."));
|
||||
PARAM_PREFIX FloatUserConfigParam m_capture_limit_threshold
|
||||
PARAM_DEFAULT(FloatUserConfigParam(0.5f, "capture-limit-threshold",
|
||||
PARAM_DEFAULT(FloatUserConfigParam(0.7f, "capture-limit-threshold",
|
||||
&m_network_group, "Value used to calculate capture limit in CTF, which "
|
||||
"is max(2.0, number of players * capture-limit-threshold), negative value to disable capture limit."));
|
||||
"is max(3.0, number of players * capture-limit-threshold), negative value to disable capture limit."));
|
||||
PARAM_PREFIX FloatUserConfigParam m_time_limit_threshold_ctf
|
||||
PARAM_DEFAULT(FloatUserConfigParam(0.9f, "time-limit-threshold-ctf",
|
||||
&m_network_group, "Value used to calculate time limit in CTF, which "
|
||||
"is max(2.0, number of players * (time-limit-threshold-ctf + flag-return-timemout / 60.0)) * 60.0,"
|
||||
"is max(3.0, number of players * (time-limit-threshold-ctf + flag-return-timemout / 60.0)) * 60.0,"
|
||||
" negative value to disable time limit."));
|
||||
PARAM_PREFIX StringToUIntUserConfigParam m_server_ban_list
|
||||
PARAM_DEFAULT(StringToUIntUserConfigParam("server_ban_list",
|
||||
"LHS: IP in x.x.x.x format, RHS: online id, if 0 than all players "
|
||||
"from this IP will be banned.",
|
||||
{ { "0.0.0.0", 0u } }
|
||||
));
|
||||
PARAM_PREFIX StringToUIntUserConfigParam m_server_ip_ban_list
|
||||
PARAM_DEFAULT(StringToUIntUserConfigParam("server_ip_ban_list",
|
||||
"LHS: IP in X.X.X.X/Y (CIDR) format, use Y of 32 for a specific ip, "
|
||||
"RHS: time epoch to expire, if -1 (uint32_t max) than a permanent ban.",
|
||||
{ { "0.0.0.0/0", 0u } }));
|
||||
PARAM_PREFIX UIntToUIntUserConfigParam m_server_online_id_ban_list
|
||||
PARAM_DEFAULT(UIntToUIntUserConfigParam("server_online_id_ban_list",
|
||||
"LHS: online id, RHS: time epoch to expire, if -1 (uint32_t max) than a permanent ban.",
|
||||
{ { 0u, 0u } }));
|
||||
PARAM_PREFIX IntUserConfigParam m_max_ping
|
||||
PARAM_DEFAULT(IntUserConfigParam(300, "max-ping",
|
||||
&m_network_group, "Maximum ping allowed for a player (in ms)."));
|
||||
PARAM_PREFIX IntUserConfigParam m_jitter_tolerance
|
||||
PARAM_DEFAULT(IntUserConfigParam(100, "jitter-tolerance",
|
||||
&m_network_group, "Tolerance of jitter in network allowed (in ms)."));
|
||||
PARAM_PREFIX IntUserConfigParam m_timer_sync_difference_tolerance
|
||||
PARAM_DEFAULT(IntUserConfigParam(5, "timer-sync-difference-tolerance",
|
||||
&m_network_group, "Max time difference tolerance (in ms) to synchronize timer with server."));
|
||||
PARAM_PREFIX BoolUserConfigParam m_kick_high_ping_players
|
||||
PARAM_DEFAULT(BoolUserConfigParam(false, "kick-high-ping-players",
|
||||
&m_network_group, "Kick players whose ping is above max-ping."));
|
||||
PARAM_PREFIX FloatUserConfigParam m_auto_lap_ratio
|
||||
PARAM_DEFAULT(FloatUserConfigParam(-1.0f, "auto-lap-ratio",
|
||||
&m_network_group, "Value used by server to automatically calculate lap of each race in network game, "
|
||||
"if more than 0.0f, the number of lap of each track vote in linear race will be determined "
|
||||
"by max(1.0f, auto-lap-ratio * default lap of that track)."));
|
||||
|
||||
// ---- Gamemode setup
|
||||
PARAM_PREFIX UIntToUIntUserConfigParam m_num_karts_per_gamemode
|
||||
|
||||
@@ -700,5 +700,14 @@ void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position,
|
||||
glGetError();
|
||||
} // GL32_draw2DRectangle
|
||||
|
||||
void preloadShaders()
|
||||
{
|
||||
Primitive2DList::getInstance();
|
||||
UniformColoredTextureRectShader::getInstance();
|
||||
TextureRectShader::getInstance();
|
||||
ColoredRectShader::getInstance();
|
||||
ColoredTextureRectShader::getInstance();
|
||||
} // preloadShaders
|
||||
|
||||
#endif // !SERVER_ONLY
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <SColor.h>
|
||||
#include <SVertexIndex.h>
|
||||
|
||||
void preloadShaders();
|
||||
|
||||
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
|
||||
const irr::core::rect<irr::s32>& destRect,
|
||||
const irr::core::rect<irr::s32>& sourceRect,
|
||||
|
||||
@@ -248,7 +248,9 @@ void CameraNormal::update(float dt)
|
||||
|
||||
// If an explosion is happening, stop moving the camera,
|
||||
// but keep it target on the kart.
|
||||
if (dynamic_cast<ExplosionAnimation*>(m_kart->getKartAnimation()))
|
||||
ExplosionAnimation* ea =
|
||||
dynamic_cast<ExplosionAnimation*>(m_kart->getKartAnimation());
|
||||
if (ea && !ea->hasResetAlready())
|
||||
{
|
||||
float above_kart, cam_angle, side_way, distance;
|
||||
bool smoothing;
|
||||
|
||||
@@ -134,6 +134,28 @@ CPUParticleManager::GLParticle::GLParticle(bool flips)
|
||||
glBindVertexArray(0);
|
||||
} // GLParticle
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
CPUParticleManager::CPUParticleManager()
|
||||
{
|
||||
assert(CVS->isGLSL());
|
||||
|
||||
const float vertices[] =
|
||||
{
|
||||
-0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 1.0f, 1.0f,
|
||||
};
|
||||
glGenBuffers(1, &m_particle_quad);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_particle_quad);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// For preloading shaders
|
||||
ParticleRenderer::getInstance();
|
||||
AlphaTestParticleRenderer::getInstance();
|
||||
} // CPUParticleManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void CPUParticleManager::addBillboardNode(scene::IBillboardSceneNode* node)
|
||||
{
|
||||
|
||||
@@ -116,21 +116,7 @@ private:
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
CPUParticleManager()
|
||||
{
|
||||
const float vertices[] =
|
||||
{
|
||||
-0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 1.0f, 1.0f,
|
||||
};
|
||||
glGenBuffers(1, &m_particle_quad);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_particle_quad);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
|
||||
GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
CPUParticleManager();
|
||||
// ------------------------------------------------------------------------
|
||||
~CPUParticleManager()
|
||||
{
|
||||
|
||||
@@ -638,8 +638,11 @@ void IrrDriver::initDevice()
|
||||
#endif
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if(CVS->isGLSL())
|
||||
if (CVS->isGLSL())
|
||||
{
|
||||
m_renderer = new ShaderBasedRenderer();
|
||||
preloadShaders();
|
||||
}
|
||||
else
|
||||
m_renderer = new FixedPipelineRenderer();
|
||||
#endif
|
||||
@@ -795,6 +798,9 @@ void IrrDriver::getOpenGLData(std::string *vendor, std::string *renderer,
|
||||
std::string *version)
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
if (ProfileWorld::isNoGraphics())
|
||||
return;
|
||||
|
||||
*vendor = (char*)glGetString(GL_VENDOR );
|
||||
*renderer = (char*)glGetString(GL_RENDERER);
|
||||
*version = (char*)glGetString(GL_VERSION );
|
||||
@@ -1847,22 +1853,6 @@ void IrrDriver::doScreenShot()
|
||||
*/
|
||||
void IrrDriver::update(float dt)
|
||||
{
|
||||
// User aborted (e.g. closed window)
|
||||
// =================================
|
||||
if (!m_device->run())
|
||||
{
|
||||
// Don't bother cleaning up GUI, has no use and may result in crashes
|
||||
//GUIEngine::cleanUp();
|
||||
//GUIEngine::deallocate();
|
||||
main_loop->abort();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we quit via the menu the m_device->run() does not return true.
|
||||
// To avoid any other calls, we return here.
|
||||
if(main_loop->isAborted())
|
||||
return;
|
||||
|
||||
// If the resolution should be switched, do it now. This will delete the
|
||||
// old device and create a new one.
|
||||
if (m_resolution_changing!=RES_CHANGE_NONE)
|
||||
|
||||
@@ -758,6 +758,9 @@ PostProcessing::PostProcessing()
|
||||
STKTexManager::getInstance()->addTexture(m_areamap);
|
||||
areamap->drop();
|
||||
|
||||
// For preloading shaders
|
||||
MotionBlurShader::getInstance();
|
||||
LightningShader::getInstance();
|
||||
} // PostProcessing
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -127,7 +127,7 @@ void SPMeshBuffer::uploadGLMesh()
|
||||
{
|
||||
m_textures[i][j] = SPTextureManager::get()->getTexture
|
||||
(m_shaders[0]->hasTextureLayer(j) ?
|
||||
std::get<2>(m_stk_material[i])->getSamplerPath(j) : "",
|
||||
std::get<2>(m_stk_material[i])->getSamplerPath(j) : "",
|
||||
j == 0 ? std::get<2>(m_stk_material[i]) : NULL,
|
||||
m_shaders[0]->isSrgbForTextureLayer(j),
|
||||
std::get<2>(m_stk_material[i])->getContainerId());
|
||||
@@ -469,10 +469,22 @@ void SPMeshBuffer::reloadTextureCompare()
|
||||
void SPMeshBuffer::setSTKMaterial(Material* m)
|
||||
{
|
||||
m_stk_material[0] = std::make_tuple(0u, getIndexCount(), m);
|
||||
m_shaders[0] = SPShaderManager::get()->getSPShader(
|
||||
std::get<2>(m_stk_material[0])->getShaderName());
|
||||
m_shaders[1] = SPShaderManager::get()->getSPShader(
|
||||
std::get<2>(m_stk_material[0])->getShaderName() + "_skinned");
|
||||
const std::string shader_name =
|
||||
std::get<2>(m_stk_material[0])->getShaderName();
|
||||
const std::string skinned_shader_name =
|
||||
std::get<2>(m_stk_material[0])->getShaderName() + "_skinned";
|
||||
|
||||
m_shaders[0] = SPShaderManager::get()->getSPShader(shader_name);
|
||||
if (!m_shaders[0])
|
||||
{
|
||||
Log::warn("SPMeshBuffer", "%s shader is missing, fallback to solid",
|
||||
shader_name.c_str());
|
||||
m_shaders[0] = SPShaderManager::get()->getSPShader("solid");
|
||||
}
|
||||
|
||||
m_shaders[1] = SPShaderManager::get()->getSPShader(skinned_shader_name);
|
||||
if (!m_shaders[1])
|
||||
m_shaders[1] = SPShaderManager::get()->getSPShader("solid_skinned");
|
||||
} // setSTKMaterial
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "config/user_config.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
#include "guiengine/screen_keyboard.hpp"
|
||||
#include "guiengine/screen.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
|
||||
@@ -49,6 +50,7 @@ void AbstractStateManager::enterGameState()
|
||||
{
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
assert(!ScreenKeyboard::isActive());
|
||||
|
||||
if (getCurrentScreen() != NULL) getCurrentScreen()->tearDown();
|
||||
m_menu_stack.clear();
|
||||
@@ -90,6 +92,7 @@ void AbstractStateManager::pushMenu(Screen* screen)
|
||||
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
assert(!ScreenKeyboard::isActive());
|
||||
|
||||
if (UserConfigParams::logGUI())
|
||||
{
|
||||
@@ -122,6 +125,7 @@ void AbstractStateManager::pushScreen(Screen* screen)
|
||||
{
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
assert(!ScreenKeyboard::isActive());
|
||||
|
||||
if (UserConfigParams::logGUI())
|
||||
{
|
||||
@@ -146,6 +150,7 @@ void AbstractStateManager::replaceTopMostScreen(Screen* screen, GUIEngine::GameS
|
||||
//assert(m_game_mode != GAME);
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
assert(!ScreenKeyboard::isActive());
|
||||
|
||||
if (!screen->isLoaded()) screen->loadFromFile();
|
||||
std::string name = screen->getName();
|
||||
@@ -179,6 +184,7 @@ void AbstractStateManager::reshowTopMostMenu()
|
||||
assert(m_game_mode != GAME);
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
assert(!ScreenKeyboard::isActive());
|
||||
|
||||
// Send tear-down event to previous menu
|
||||
if (m_menu_stack.size() > 0)
|
||||
@@ -243,6 +249,7 @@ void AbstractStateManager::resetAndGoToScreen(Screen* screen)
|
||||
{
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
assert(!ScreenKeyboard::isActive());
|
||||
|
||||
std::string name = screen->getName();
|
||||
|
||||
@@ -271,6 +278,7 @@ void AbstractStateManager::resetAndSetStack(Screen* screens[])
|
||||
assert(screens[0] != NULL);
|
||||
// you need to close any dialog before calling this
|
||||
assert(!ModalDialog::isADialogActive());
|
||||
assert(!ScreenKeyboard::isActive());
|
||||
|
||||
if (m_game_mode != GAME) getCurrentScreen()->tearDown();
|
||||
m_menu_stack.clear();
|
||||
|
||||
@@ -821,7 +821,10 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
|
||||
w->onClick();
|
||||
EventPropagation result = w->onClick();
|
||||
|
||||
if (result == EVENT_BLOCK)
|
||||
return result;
|
||||
|
||||
// These events are only triggered by mouse (or so I hope)
|
||||
// The player that owns the mouser receives "game master" priviledges
|
||||
|
||||
@@ -292,8 +292,10 @@ void updatePosition()
|
||||
*/
|
||||
void add(MessageType mt, const irr::core::stringw &message)
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
Message *m = new TextMessage(mt, message);
|
||||
privateAdd(m);
|
||||
#endif
|
||||
} // add
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -305,6 +307,7 @@ void add(MessageType mt, const irr::core::stringw &message)
|
||||
*/
|
||||
void update(float dt)
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
if (!g_container)
|
||||
g_container = new SkinWidgetContainer();
|
||||
|
||||
@@ -325,7 +328,7 @@ void update(float dt)
|
||||
current->remove();
|
||||
}
|
||||
g_all_messages.unlock();
|
||||
|
||||
#endif
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -337,7 +340,9 @@ void update(float dt)
|
||||
*/
|
||||
void showProgressBar(int progress, const wchar_t* msg)
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
g_progress_bar_msg.setProgress(progress, msg);
|
||||
#endif
|
||||
} // showProgressBar
|
||||
|
||||
} // namespace GUIEngine
|
||||
|
||||
@@ -674,7 +674,7 @@ namespace GUIEngine
|
||||
bool ok() const { return (m_magic_number == 0xCAFEC001); }
|
||||
|
||||
/** Gets called when the widget is active and got clicked. (Only works for button widgets for now.) */
|
||||
virtual void onClick() { }
|
||||
virtual EventPropagation onClick() { return EVENT_LET; }
|
||||
virtual irr::core::dimension2di getDimension() const { return irr::core::dimension2di(m_w, m_h); }
|
||||
};
|
||||
|
||||
|
||||
@@ -120,6 +120,14 @@ CGUIEditBox::~CGUIEditBox()
|
||||
dl->setIMEEnable(false);
|
||||
}
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
if (irr_driver->getDevice()->getType() == irr::EIDT_ANDROID)
|
||||
{
|
||||
CIrrDeviceAndroid* dl = dynamic_cast<CIrrDeviceAndroid*>(
|
||||
irr_driver->getDevice());
|
||||
dl->setTextInputEnabled(false);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -268,11 +276,19 @@ bool CGUIEditBox::OnEvent(const SEvent& event)
|
||||
irr_driver->getDevice());
|
||||
dl->setIMEEnable(false);
|
||||
}
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
if (irr_driver->getDevice()->getType() == irr::EIDT_ANDROID)
|
||||
{
|
||||
CIrrDeviceAndroid* dl = dynamic_cast<CIrrDeviceAndroid*>(
|
||||
irr_driver->getDevice());
|
||||
dl->setTextInputEnabled(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef _IRR_COMPILE_WITH_X11_DEVICE_
|
||||
else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_X11_DEVICE_
|
||||
if (irr_driver->getDevice()->getType() == irr::EIDT_X11)
|
||||
{
|
||||
CIrrDeviceLinux* dl = dynamic_cast<CIrrDeviceLinux*>(
|
||||
@@ -280,8 +296,16 @@ bool CGUIEditBox::OnEvent(const SEvent& event)
|
||||
dl->setIMEEnable(true);
|
||||
dl->setIMELocation(calculateICPos());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
if (irr_driver->getDevice()->getType() == irr::EIDT_ANDROID)
|
||||
{
|
||||
CIrrDeviceAndroid* dl = dynamic_cast<CIrrDeviceAndroid*>(
|
||||
irr_driver->getDevice());
|
||||
dl->setTextInputEnabled(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
|
||||
case EET_IMPUT_METHOD_EVENT:
|
||||
|
||||
@@ -572,7 +572,11 @@ void CGUISTKListBox::draw()
|
||||
Items[i].m_contents[x].m_center, true, &clientClip);
|
||||
}
|
||||
//Position back to inital pos
|
||||
textRect.UpperLeftCorner.X -= ItemsIconWidth+6;
|
||||
if (IconBank && (Items[i].m_contents[x].m_icon > -1))
|
||||
textRect.UpperLeftCorner.X -= ItemsIconWidth;
|
||||
|
||||
textRect.UpperLeftCorner.X -= 6;
|
||||
|
||||
//Calculate new beginning
|
||||
textRect.UpperLeftCorner.X += Items[i].m_contents[x].m_proportion * part_size;
|
||||
}
|
||||
@@ -780,4 +784,3 @@ void CGUISTKListBox::setDrawBackground(bool draw)
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
|
||||
@@ -54,11 +54,11 @@ void ListWidget::setIcons(STKModifiedSpriteBank* icons, int size)
|
||||
m_use_icons = (icons != NULL);
|
||||
m_icons = icons;
|
||||
|
||||
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
|
||||
assert(list != NULL);
|
||||
|
||||
if (m_use_icons)
|
||||
{
|
||||
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
|
||||
assert(list != NULL);
|
||||
|
||||
list->setSpriteBank(m_icons);
|
||||
|
||||
// determine needed height
|
||||
@@ -83,6 +83,10 @@ void ListWidget::setIcons(STKModifiedSpriteBank* icons, int size)
|
||||
list->setItemHeight( item_height );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
list->setSpriteBank(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -145,7 +149,8 @@ void ListWidget::createHeader()
|
||||
}
|
||||
|
||||
int x = m_x;
|
||||
for (unsigned int n=0; n<m_header.size(); n++)
|
||||
int scrollbar_width = GUIEngine::getSkin()->getSize(EGDS_SCROLLBAR_SIZE);
|
||||
for (unsigned int n=0; n<m_header.size()+1; n++)
|
||||
{
|
||||
std::ostringstream name;
|
||||
name << m_properties[PROP_ID];
|
||||
@@ -160,12 +165,22 @@ void ListWidget::createHeader()
|
||||
header->m_h = header_height;
|
||||
|
||||
header->m_x = x;
|
||||
header->m_w = (int)(m_w * float(m_header[n].m_proportion)
|
||||
/float(proportion_total));
|
||||
if (n == m_header.size())
|
||||
{
|
||||
header->m_w = scrollbar_width;
|
||||
header->setActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
int header_width = m_w - scrollbar_width;
|
||||
header->m_w = (int)(header_width * float(m_header[n].m_proportion)
|
||||
/float(proportion_total));
|
||||
}
|
||||
|
||||
x += header->m_w;
|
||||
|
||||
header->setText( m_header[n].m_text );
|
||||
if (n < m_header.size())
|
||||
header->setText( m_header[n].m_text );
|
||||
header->m_properties[PROP_ID] = name.str();
|
||||
|
||||
header->add();
|
||||
|
||||
@@ -112,10 +112,12 @@ void RatingBarWidget::setStepValuesByMouse(const core::position2di & mouse_posit
|
||||
}
|
||||
}
|
||||
|
||||
void RatingBarWidget::onClick()
|
||||
EventPropagation RatingBarWidget::onClick()
|
||||
{
|
||||
if(m_allow_voting)
|
||||
m_rating = m_hover_rating;
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace GUIEngine
|
||||
|
||||
void setStepValuesByMouse(const core::position2di & mouse_position, const core::recti & stars_rect);
|
||||
|
||||
virtual void onClick();
|
||||
virtual EventPropagation onClick();
|
||||
|
||||
void allowVoting() { m_allow_voting = true; }
|
||||
};
|
||||
|
||||
@@ -779,6 +779,14 @@ EventPropagation RibbonWidget::mouseHovered(Widget* child,
|
||||
return EVENT_BLOCK;
|
||||
} // mouseHovered
|
||||
|
||||
EventPropagation RibbonWidget::onClick()
|
||||
{
|
||||
if (m_ribbon_type == RIBBON_TOOLBAR)
|
||||
return EVENT_BLOCK;
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
const std::string& RibbonWidget::getSelectionIDString(const int playerID)
|
||||
{
|
||||
|
||||
@@ -92,6 +92,8 @@ namespace GUIEngine
|
||||
virtual EventPropagation focused(const int playerID) OVERRIDE;
|
||||
virtual void unfocused(const int playerID, Widget* new_focus) OVERRIDE;
|
||||
|
||||
virtual EventPropagation onClick() OVERRIDE;
|
||||
|
||||
PtrVector<irr::gui::IGUIStaticText, REF> m_labels;
|
||||
|
||||
IRibbonListener* m_listener;
|
||||
|
||||
@@ -242,7 +242,7 @@ EventPropagation SpinnerWidget::rightPressed(const int playerID)
|
||||
else
|
||||
setSelectedButton(/* right*/ true);
|
||||
|
||||
return EVENT_LET;
|
||||
return EVENT_BLOCK_BUT_HANDLED;
|
||||
} // rightPressed
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -262,7 +262,7 @@ EventPropagation SpinnerWidget::leftPressed(const int playerID)
|
||||
else
|
||||
return EVENT_BLOCK;
|
||||
|
||||
return EVENT_LET;
|
||||
return EVENT_BLOCK_BUT_HANDLED;
|
||||
} // leftPressed
|
||||
|
||||
void SpinnerWidget::activateSelectedButton()
|
||||
@@ -457,13 +457,13 @@ void SpinnerWidget::setCustomText(const core::stringw& text)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void SpinnerWidget::onClick()
|
||||
EventPropagation SpinnerWidget::onClick()
|
||||
{
|
||||
if (m_children[1].m_deactivated ||
|
||||
m_children[1].m_properties[PROP_ID] != "spinnerbody" ||
|
||||
!isGauge())
|
||||
{
|
||||
return;
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
const core::position2di mouse_position
|
||||
@@ -487,6 +487,8 @@ void SpinnerWidget::onClick()
|
||||
|
||||
setValue(new_value);
|
||||
}
|
||||
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace GUIEngine
|
||||
virtual EventPropagation leftPressed(const int playerID);
|
||||
|
||||
/** \brief implementing method from base class Widget */
|
||||
virtual void onClick();
|
||||
virtual EventPropagation onClick();
|
||||
|
||||
/** When inferring widget size from its label length, this method will be called to
|
||||
* if/how much space must be added to the raw label's size for the widget to be large enough */
|
||||
|
||||
@@ -100,20 +100,6 @@ irr::core::stringw Binding::getAsString() const
|
||||
|
||||
switch(m_id)
|
||||
{
|
||||
#if defined(WIN32) || (defined(__linux__) && !defined(ANDROID))
|
||||
// Windows codes certain special keys, which have atm no defined
|
||||
// value in irr::IRR_KEY_*. So for now hardcode the values.
|
||||
// FIXME: what happens with international keyboards? E.g. A [
|
||||
// might be an Umlaut on a German keyboard. How do we get
|
||||
// the character to display in this case??
|
||||
case 186: s=";"; break;
|
||||
case 191: s="/"; break;
|
||||
case 192: s="`"; break;
|
||||
case 219: s="["; break;
|
||||
case 220: s="\\"; break;
|
||||
case 221: s="]"; break;
|
||||
case 222: s="'"; break;
|
||||
#endif
|
||||
//I18N: input configuration screen: mouse button
|
||||
case irr::IRR_KEY_LBUTTON : s = _C("input_key", "Left Mouse Button"); break;
|
||||
//I18N: input configuration screen: mouse button
|
||||
@@ -327,6 +313,20 @@ irr::core::stringw Binding::getAsString() const
|
||||
case irr::IRR_KEY_PA1 : s = _C("input_key", "Pa1"); break;
|
||||
//I18N: input configuration screen: keyboard key
|
||||
case irr::IRR_KEY_OEM_CLEAR : s = _C("input_key", "Oem Clear"); break;
|
||||
//I18N: input configuration screen: keyboard key
|
||||
case irr::IRR_KEY_OEM_1 : s = ";"; break;
|
||||
//I18N: input configuration screen: keyboard key
|
||||
case irr::IRR_KEY_OEM_2 : s = "/"; break;
|
||||
//I18N: input configuration screen: keyboard key
|
||||
case irr::IRR_KEY_OEM_3 : s = "`"; break;
|
||||
//I18N: input configuration screen: keyboard key
|
||||
case irr::IRR_KEY_OEM_4 : s = "["; break;
|
||||
//I18N: input configuration screen: keyboard key
|
||||
case irr::IRR_KEY_OEM_5 : s = "\\"; break;
|
||||
//I18N: input configuration screen: keyboard key
|
||||
case irr::IRR_KEY_OEM_6 : s = "]"; break;
|
||||
//I18N: input configuration screen: keyboard key
|
||||
case irr::IRR_KEY_OEM_7 : s = "'"; break;
|
||||
|
||||
// for azerty layout
|
||||
case irr::IRR_KEY_AMPERSAND : s = "&"; break;
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#ifdef ANDROID
|
||||
#include <android/asset_manager.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#include "../../../lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -49,6 +51,9 @@ void AssetsAndroid::init()
|
||||
#ifdef ANDROID
|
||||
if (m_file_manager == NULL)
|
||||
return;
|
||||
|
||||
if (!global_android_app)
|
||||
return;
|
||||
|
||||
bool needs_extract_data = false;
|
||||
const std::string version = std::string("supertuxkart.") + STK_VERSION;
|
||||
@@ -339,6 +344,9 @@ void AssetsAndroid::extractData()
|
||||
bool AssetsAndroid::extractDir(std::string dir_name)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
if (!global_android_app)
|
||||
return false;
|
||||
|
||||
AAssetManager* amgr = global_android_app->activity->assetManager;
|
||||
|
||||
Log::info("AssetsAndroid", "Extracting %s directory",
|
||||
@@ -482,7 +490,7 @@ void AssetsAndroid::removeData()
|
||||
if (file == m_stk_dir + "/.nomedia")
|
||||
continue;
|
||||
|
||||
Log::info("AssetsAndroid", "Deleting file: %s\n", file.c_str());
|
||||
Log::info("AssetsAndroid", "Deleting file: %s", file.c_str());
|
||||
|
||||
if (m_file_manager->isDirectory(file))
|
||||
{
|
||||
@@ -493,6 +501,20 @@ void AssetsAndroid::removeData()
|
||||
m_file_manager->removeFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
std::string data_path = getDataPath();
|
||||
|
||||
if (!data_path.empty())
|
||||
{
|
||||
const std::string child_path = data_path + "/files/libchildprocess.so";
|
||||
|
||||
if (m_file_manager->fileExists(child_path))
|
||||
{
|
||||
Log::info("AssetsAndroid", "Deleting old libchildprocess: %s",
|
||||
child_path.c_str());
|
||||
m_file_manager->removeFile(child_path);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -581,3 +603,31 @@ std::string AssetsAndroid::getPreferredPath(const std::vector<std::string>&
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Get a path for internal data directory
|
||||
* \return Path for internal data directory or empty string when failed
|
||||
*/
|
||||
std::string AssetsAndroid::getDataPath()
|
||||
{
|
||||
#ifdef ANDROID
|
||||
std::string data_path = "/data/data/" ANDROID_PACKAGE_NAME;
|
||||
|
||||
if (access(data_path.c_str(), R_OK) != 0)
|
||||
{
|
||||
Log::warn("AssetsAndroid", "Cannot use standard data dir");
|
||||
|
||||
AndroidApplicationInfo application_info =
|
||||
CIrrDeviceAndroid::getApplicationInfo(global_android_app->activity);
|
||||
|
||||
data_path = application_info.data_dir;
|
||||
}
|
||||
|
||||
if (access(data_path.c_str(), R_OK) != 0)
|
||||
{
|
||||
data_path = "";
|
||||
}
|
||||
|
||||
return data_path;
|
||||
#endif
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ public:
|
||||
~AssetsAndroid() {};
|
||||
|
||||
void init();
|
||||
static std::string getDataPath();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -198,7 +198,8 @@ public:
|
||||
void redirectOutput();
|
||||
|
||||
bool fileIsNewer(const std::string& f1, const std::string& f2) const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
const std::string& getUserConfigDir() const { return m_user_config_dir; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the irrlicht file system. */
|
||||
irr::io::IFileSystem* getFileSystem() { return m_file_system; }
|
||||
|
||||
@@ -345,7 +345,8 @@ void Attachment::hitBanana(ItemState *item_state)
|
||||
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_BATTLE)
|
||||
{
|
||||
World::getWorld()->kartHit(m_kart->getWorldKartId());
|
||||
ExplosionAnimation::create(m_kart);
|
||||
if (m_kart->getKartAnimation() == NULL)
|
||||
ExplosionAnimation::create(m_kart);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -606,7 +607,8 @@ void Attachment::update(int ticks)
|
||||
m_bubble_explode_sound->play();
|
||||
}
|
||||
|
||||
ItemManager::get()->dropNewItem(Item::ITEM_BUBBLEGUM, m_kart);
|
||||
if (!m_kart->isGhostKart())
|
||||
ItemManager::get()->dropNewItem(Item::ITEM_BUBBLEGUM, m_kart);
|
||||
}
|
||||
break;
|
||||
} // switch
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/explosion_animation.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "modes/soccer_world.hpp"
|
||||
#include "network/compress_network_body.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
@@ -243,14 +242,11 @@ void Flyable::getClosestKart(const AbstractKart **minKart,
|
||||
kart->isInvulnerable() ||
|
||||
kart->getKartAnimation() ) continue;
|
||||
|
||||
const SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
if (sw)
|
||||
{
|
||||
// Don't hit teammates in soccer world
|
||||
if (sw->getKartTeam(kart->getWorldKartId()) == sw
|
||||
->getKartTeam(m_owner->getWorldKartId()))
|
||||
// Don't hit teammates in team world
|
||||
if (world->hasTeam() &&
|
||||
world->getKartTeam(kart->getWorldKartId()) ==
|
||||
world->getKartTeam(m_owner->getWorldKartId()))
|
||||
continue;
|
||||
}
|
||||
|
||||
btTransform t=kart->getTrans();
|
||||
|
||||
@@ -410,7 +406,7 @@ bool Flyable::updateAndDelete(int ticks)
|
||||
{
|
||||
if (!RewindManager::get()->isRewinding())
|
||||
{
|
||||
m_animation->update(stk_config->ticks2Time(ticks));
|
||||
m_animation->update(ticks);
|
||||
Moveable::update(ticks);
|
||||
}
|
||||
return false;
|
||||
@@ -548,15 +544,12 @@ void Flyable::explode(AbstractKart *kart_hit, PhysicalObject *object,
|
||||
for ( unsigned int i = 0 ; i < world->getNumKarts() ; i++ )
|
||||
{
|
||||
AbstractKart *kart = world->getKart(i);
|
||||
|
||||
const SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
if (sw)
|
||||
{
|
||||
// Don't explode teammates in soccer world
|
||||
if (sw->getKartTeam(kart->getWorldKartId()) == sw
|
||||
->getKartTeam(m_owner->getWorldKartId()))
|
||||
// Don't explode teammates in team world
|
||||
if (world->hasTeam() &&
|
||||
world->getKartTeam(kart->getWorldKartId()) ==
|
||||
world->getKartTeam(m_owner->getWorldKartId()))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kart->isGhostKart()) continue;
|
||||
|
||||
// If no secondary hits should be done, only hit the
|
||||
@@ -572,7 +565,7 @@ void Flyable::explode(AbstractKart *kart_hit, PhysicalObject *object,
|
||||
// The explosion animation will register itself with the kart
|
||||
// and will free it later.
|
||||
ExplosionAnimation::create(kart, getXYZ(), kart==kart_hit);
|
||||
if(kart==kart_hit && Track::getCurrentTrack()->isArena())
|
||||
if (kart == kart_hit)
|
||||
{
|
||||
world->kartHit(kart->getWorldKartId(),
|
||||
m_owner->getWorldKartId());
|
||||
|
||||
@@ -49,7 +49,7 @@ NetworkItemManager::NetworkItemManager()
|
||||
auto peers = STKHost::get()->getPeers();
|
||||
for (auto& p : peers)
|
||||
{
|
||||
if (!p->isValidated())
|
||||
if (!p->isValidated() || p->isWaitingForGame())
|
||||
continue;
|
||||
m_last_confirmed_item_ticks[p] = 0;
|
||||
}
|
||||
@@ -137,17 +137,17 @@ Item* NetworkItemManager::dropNewItem(ItemState::ItemType type,
|
||||
// Server: store the data for this event:
|
||||
m_item_events.lock();
|
||||
m_item_events.getData().emplace_back(World::getWorld()->getTicksSinceStart(),
|
||||
type, item->getItemId(),
|
||||
kart->getWorldKartId(),
|
||||
kart->getXYZ());
|
||||
type, item->getItemId(),
|
||||
kart->getWorldKartId(),
|
||||
kart->getXYZ() );
|
||||
m_item_events.unlock();
|
||||
return item;
|
||||
} // newItem
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called by the GameProtocol when a confirmation for an item event is
|
||||
* received by a host. Once all hosts have confirmed an event, it can be
|
||||
* deleted and won't be send to any clients again.
|
||||
* received by the server. Once all hosts have confirmed an event, it can be
|
||||
* deleted and won't be sent to any clients again.
|
||||
* \param peer Peer confirming the latest event time received.
|
||||
* \param ticks Time at which the last event was received.
|
||||
*/
|
||||
@@ -251,8 +251,8 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
// forward this confirmed state to the current time (i.e. world time).
|
||||
// This is done in several steps:
|
||||
// 1) First remove all client-side predicted items from the list of all
|
||||
// items, and store them for now in a predictem_item cache. Predicted
|
||||
// item only happen between m_confirmed_state_time and 'now'.
|
||||
// items. Predicted item only happen between m_confirmed_state_time
|
||||
// and 'now'.
|
||||
// 2) Apply all events included in this state to the confirmed state.
|
||||
// a) When a collection event is found, adjust the confirmed item state
|
||||
// only (this state will later be copied to the current item state).
|
||||
@@ -338,7 +338,7 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
gp->sendItemEventConfirmation(World::getWorld()->getTicksSinceStart());
|
||||
}
|
||||
|
||||
// Forward the confirmed item state till the world time:
|
||||
// Forward the confirmed item state to the world time:
|
||||
int dt = World::getWorld()->getTicksSinceStart() - current_time;
|
||||
if(dt>0) forwardTime(dt);
|
||||
|
||||
@@ -359,6 +359,7 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
item_new->setPredicted(false);
|
||||
item_new->setItemId(i);
|
||||
m_all_items[i] = item_new;
|
||||
*((ItemState*)m_all_items[i]) = *is;
|
||||
}
|
||||
else if (!is && item)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ class Plunger;
|
||||
class RubberBand : public NoCopy
|
||||
{
|
||||
public:
|
||||
enum RubberBandTo : uint8_t
|
||||
enum RubberBandTo
|
||||
{
|
||||
RB_TO_PLUNGER = 0, /**< Rubber band is attached to plunger. */
|
||||
RB_TO_KART, /**< Rubber band is attached to a kart hit. */
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "karts/explosion_animation.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "modes/soccer_world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
|
||||
@@ -207,7 +206,7 @@ bool Swatter::updateAndTestFinished(int ticks)
|
||||
float min_dist2
|
||||
= m_kart->getKartProperties()->getSwatterDistance();
|
||||
|
||||
if (dist2 < min_dist2)
|
||||
if (dist2 < min_dist2 && !m_kart->isGhostKart())
|
||||
{
|
||||
// Start squashing
|
||||
m_animation_phase = SWATTER_TO_TARGET;
|
||||
@@ -290,14 +289,11 @@ void Swatter::chooseTarget()
|
||||
if (kart->isInvulnerable() || kart->isSquashed())
|
||||
continue;
|
||||
|
||||
const SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
if (sw)
|
||||
{
|
||||
// Don't hit teammates in soccer world
|
||||
if (sw->getKartTeam(kart->getWorldKartId()) == sw
|
||||
->getKartTeam(m_kart->getWorldKartId()))
|
||||
// Don't hit teammates in team world
|
||||
if (world->hasTeam() &&
|
||||
world->getKartTeam(kart->getWorldKartId()) ==
|
||||
world->getKartTeam(m_kart->getWorldKartId()))
|
||||
continue;
|
||||
}
|
||||
|
||||
float dist2 = (kart->getXYZ()-m_kart->getXYZ()).length2();
|
||||
if(dist2<min_dist2)
|
||||
@@ -316,6 +312,8 @@ void Swatter::chooseTarget()
|
||||
void Swatter::pointToTarget()
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
if (m_kart->isGhostKart()) return;
|
||||
|
||||
if(!m_target)
|
||||
{
|
||||
m_scene_node->setRotation(core::vector3df());
|
||||
@@ -338,6 +336,8 @@ void Swatter::pointToTarget()
|
||||
*/
|
||||
void Swatter::squashThingsAround()
|
||||
{
|
||||
if (m_kart->isGhostKart()) return;
|
||||
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
|
||||
AbstractKart* closest_kart = m_closest_kart;
|
||||
|
||||
@@ -143,16 +143,6 @@ void AbstractKart::setKartAnimation(AbstractKartAnimation *ka)
|
||||
m_kart_animation = ka;
|
||||
} // setKartAnimation
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Moves the current physical transform into this kart's position.
|
||||
*/
|
||||
void AbstractKart::kartIsInRestNow()
|
||||
{
|
||||
// Update the kart transforms with the newly computed position
|
||||
// after all karts are reset
|
||||
setTrans(getBody()->getWorldTransform());
|
||||
} // kartIsInRest
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the time at which the kart was at a given distance.
|
||||
* Returns -1.0f if none */
|
||||
@@ -160,3 +150,27 @@ float AbstractKart::getTimeForDistance(float distance)
|
||||
{
|
||||
return -1.0f;
|
||||
} // getTimeForDistance
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Moves the current physical transform into this kart's position.
|
||||
*/
|
||||
void AbstractKart::kartIsInRestNow()
|
||||
{
|
||||
// Update the kart transforms with the newly computed position
|
||||
// after all karts are reset
|
||||
m_starting_transform = getBody()->getWorldTransform();
|
||||
setTrans(m_starting_transform);
|
||||
} // kartIsInRest
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Called before go phase to make sure all karts start at the same
|
||||
* position in case there is a slope. */
|
||||
void AbstractKart::makeKartRest()
|
||||
{
|
||||
btRigidBody *body = getBody();
|
||||
body->clearForces();
|
||||
body->setLinearVelocity(Vec3(0.0f));
|
||||
body->setAngularVelocity(Vec3(0.0f));
|
||||
body->proceedToTransform(m_starting_transform);
|
||||
setTrans(m_starting_transform);
|
||||
} // makeKartRest
|
||||
|
||||
@@ -74,7 +74,7 @@ private:
|
||||
/** Index of kart in world. */
|
||||
unsigned int m_world_kart_id;
|
||||
|
||||
|
||||
btTransform m_starting_transform;
|
||||
protected:
|
||||
/** The kart properties. */
|
||||
std::unique_ptr<KartProperties> m_kart_properties;
|
||||
@@ -509,6 +509,9 @@ public:
|
||||
virtual void playSound(SFXBuffer* buffer) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool isVisible() = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void makeKartRest();
|
||||
|
||||
}; // AbstractKart
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "karts/abstract_kart_animation.hpp"
|
||||
|
||||
#include "graphics/slip_stream.hpp"
|
||||
#include "items/powerup.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/kart_model.hpp"
|
||||
#include "karts/skidding.hpp"
|
||||
@@ -42,9 +43,11 @@ AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
|
||||
m_name = name;
|
||||
m_end_transform = btTransform(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
m_end_transform.setOrigin(Vec3(std::numeric_limits<float>::max()));
|
||||
m_end_ticks = -1;
|
||||
m_created_ticks = World::getWorld()->getTicksSinceStart();
|
||||
m_check_created_ticks = std::make_shared<int>(-1);
|
||||
m_confirmed_by_network = false;
|
||||
m_ignore_undo = false;
|
||||
// Remove previous animation if there is one
|
||||
#ifndef DEBUG
|
||||
// Use this code in non-debug mode to avoid a memory leak (and messed
|
||||
@@ -98,7 +101,7 @@ AbstractKartAnimation::~AbstractKartAnimation()
|
||||
m_kart->setTrans(transform);
|
||||
Physics::getInstance()->addKart(m_kart);
|
||||
|
||||
if (RewindManager::get()->useLocalEvent())
|
||||
if (RewindManager::get()->useLocalEvent() && !m_ignore_undo)
|
||||
{
|
||||
AbstractKart* kart = m_kart;
|
||||
Vec3 angular_velocity = kart->getBody()->getAngularVelocity();
|
||||
@@ -122,16 +125,31 @@ AbstractKartAnimation::~AbstractKartAnimation()
|
||||
} // ~AbstractKartAnimation
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AbstractKartAnimation::addNetworkAnimationChecker()
|
||||
void AbstractKartAnimation::addNetworkAnimationChecker(bool reset_powerup)
|
||||
{
|
||||
Powerup* p = NULL;
|
||||
if (reset_powerup)
|
||||
{
|
||||
if (m_kart)
|
||||
{
|
||||
p = m_kart->getPowerup();
|
||||
p->reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isClient())
|
||||
{
|
||||
// Prevent access to deleted kart animation object
|
||||
std::weak_ptr<int> cct = m_check_created_ticks;
|
||||
RewindManager::get()->addRewindInfoEventFunction(new
|
||||
RewindInfoEventFunction(m_created_ticks,
|
||||
[](){},
|
||||
[](){},
|
||||
/*replay_function*/[p]()
|
||||
{
|
||||
if (p)
|
||||
p->reset();
|
||||
},
|
||||
/*delete_function*/[cct]()
|
||||
{
|
||||
auto cct_sp = cct.lock();
|
||||
@@ -143,14 +161,17 @@ void AbstractKartAnimation::addNetworkAnimationChecker()
|
||||
} // addNetworkAnimationChecker
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AbstractKartAnimation::checkNetworkAnimationCreationSucceed()
|
||||
void AbstractKartAnimation::
|
||||
checkNetworkAnimationCreationSucceed(const btTransform& fallback_trans)
|
||||
{
|
||||
if (!m_confirmed_by_network && *m_check_created_ticks != -1 &&
|
||||
World::getWorld()->getTicksSinceStart() > *m_check_created_ticks)
|
||||
{
|
||||
Log::warn("AbstractKartAnimation",
|
||||
"No animation has been created on server, remove locally.");
|
||||
m_timer = -1.0f;
|
||||
m_timer = -1;
|
||||
m_end_transform = fallback_trans;
|
||||
m_ignore_undo = true;
|
||||
}
|
||||
} // checkNetworkAnimationCreationSucceed
|
||||
|
||||
@@ -160,13 +181,40 @@ void AbstractKartAnimation::checkNetworkAnimationCreationSucceed()
|
||||
* NOTE: calling this function must be the last thing done in any kart
|
||||
* animation class, since this object might be deleted, so accessing any
|
||||
* members might be invalid.
|
||||
* \param dt Time step size.
|
||||
* \param ticks Number of time steps - should be 1.
|
||||
*/
|
||||
void AbstractKartAnimation::update(float dt)
|
||||
void AbstractKartAnimation::update(int ticks)
|
||||
{
|
||||
// Scale the timer according to m_end_ticks told by server if
|
||||
// necessary
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isClient() &&
|
||||
World::getWorld()->getPhase() == World::RACE_PHASE &&
|
||||
usePredefinedEndTransform() && m_end_ticks != -1)
|
||||
{
|
||||
int cur_end_ticks = World::getWorld()->getTicksSinceStart() +
|
||||
m_timer;
|
||||
|
||||
const int difference = cur_end_ticks - m_end_ticks;
|
||||
if (World::getWorld()->getTicksSinceStart() > m_end_ticks)
|
||||
{
|
||||
// Stop right now
|
||||
m_timer = -1;
|
||||
}
|
||||
else if (difference > 0)
|
||||
{
|
||||
// Speed up
|
||||
m_timer -= ticks;
|
||||
}
|
||||
else if (difference < 0)
|
||||
{
|
||||
// Slow down
|
||||
return;
|
||||
}
|
||||
}
|
||||
// See if the timer expires, if so return the kart to normal game play
|
||||
m_timer -= dt;
|
||||
if(m_timer<0)
|
||||
m_timer -= ticks;
|
||||
if (m_timer < 0)
|
||||
{
|
||||
if(m_kart) m_kart->setKartAnimation(NULL);
|
||||
delete this;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
|
||||
#include "config/stk_config.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
@@ -50,44 +51,53 @@ private:
|
||||
|
||||
bool m_confirmed_by_network;
|
||||
|
||||
bool m_ignore_undo;
|
||||
|
||||
protected:
|
||||
/** A pointer to the kart which is animated by this class. */
|
||||
AbstractKart *m_kart;
|
||||
|
||||
/** Timer for the explosion. */
|
||||
float m_timer;
|
||||
/** Timer for the animation. */
|
||||
int m_timer;
|
||||
|
||||
btTransform m_end_transform;
|
||||
|
||||
int m_end_ticks;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void addNetworkAnimationChecker();
|
||||
void addNetworkAnimationChecker(bool reset_powerup);
|
||||
public:
|
||||
AbstractKartAnimation(AbstractKart *kart,
|
||||
const std::string &name);
|
||||
virtual ~AbstractKartAnimation();
|
||||
virtual void update(float dt);
|
||||
virtual void update(int ticks);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current animation timer. */
|
||||
virtual float getAnimationTimer() const { return m_timer; }
|
||||
virtual float getAnimationTimer() const
|
||||
{ return stk_config->ticks2Time(m_timer); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** To easily allow printing the name of the animation being used atm.
|
||||
* Used in AstractKart in case of an incorrect sequence of calls. */
|
||||
virtual const std::string &getName() const { return m_name; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool useEarlyEndTransform() const { return true; }
|
||||
/** If true, the end transform can be determined early, used in network for
|
||||
* for client to synchronize with server. */
|
||||
virtual bool usePredefinedEndTransform() const { return true; }
|
||||
// ------------------------------------------------------------------------
|
||||
const btTransform& getEndTransform() const { return m_end_transform; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setEndTransform(const btTransform& t)
|
||||
void setEndTransformTicks(const btTransform& t, int ticks)
|
||||
{
|
||||
if (!useEarlyEndTransform())
|
||||
if (!usePredefinedEndTransform() || m_confirmed_by_network)
|
||||
return;
|
||||
m_confirmed_by_network = true;
|
||||
m_end_transform = t;
|
||||
m_end_ticks = ticks;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
void checkNetworkAnimationCreationSucceed();
|
||||
|
||||
void checkNetworkAnimationCreationSucceed(const btTransform& fallback_trans);
|
||||
// ----------------------------------------------------------------------------
|
||||
int getEndTicks() const { return m_end_ticks; }
|
||||
}; // AbstractKartAnimation
|
||||
|
||||
#endif
|
||||
|
||||
@@ -81,7 +81,7 @@ void CannonAnimation::init(Ipo *ipo, const Vec3 &start_left,
|
||||
const Vec3 &end_right, float skid_rot)
|
||||
{
|
||||
m_curve = new AnimationBase(ipo);
|
||||
m_timer = ipo->getEndTime();
|
||||
m_timer = stk_config->time2Ticks(ipo->getEndTime());
|
||||
|
||||
// First make sure that left and right points are indeed correct
|
||||
// -------------------------------------------------------------
|
||||
@@ -214,25 +214,25 @@ CannonAnimation::~CannonAnimation()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updates the kart animation.
|
||||
* \param dt Time step size.
|
||||
* \return True if the explosion is still shown, false if it has finished.
|
||||
* \param ticks Number of time steps - should be 1.
|
||||
*/
|
||||
void CannonAnimation::update(float dt)
|
||||
void CannonAnimation::update(int ticks)
|
||||
{
|
||||
if(m_timer < dt)
|
||||
float dt = stk_config->ticks2Time(ticks);
|
||||
if (m_timer < ticks)
|
||||
{
|
||||
AbstractKartAnimation::update(dt);
|
||||
AbstractKartAnimation::update(ticks);
|
||||
return;
|
||||
}
|
||||
AbstractKartAnimation::update(dt);
|
||||
AbstractKartAnimation::update(ticks);
|
||||
|
||||
// First compute the current rotation
|
||||
// ==================================
|
||||
// Get the tangent = derivative at the current point to compute the
|
||||
// new orientation of the kart
|
||||
Vec3 tangent;
|
||||
m_curve->getDerivativeAt(m_curve->getAnimationDuration() - m_timer,
|
||||
&tangent);
|
||||
m_curve->getDerivativeAt(m_curve->getAnimationDuration() -
|
||||
getAnimationTimer(), &tangent);
|
||||
// Get the current kart orientation
|
||||
const btTransform &trans = m_kart ? m_kart->getTrans()
|
||||
: m_flyable->getBody()->getWorldTransform();
|
||||
@@ -275,7 +275,7 @@ void CannonAnimation::update(float dt)
|
||||
// forward direction.
|
||||
|
||||
// The timer counts backwards, so the fraction goes from 1 to 0
|
||||
float f = m_timer / m_curve->getAnimationDuration();
|
||||
float f = getAnimationTimer() / m_curve->getAnimationDuration();
|
||||
float f_current_width = m_start_line_length * f
|
||||
+ m_end_line_length * (1.0f - f);
|
||||
|
||||
|
||||
@@ -79,8 +79,8 @@ public:
|
||||
const Vec3 &start_left, const Vec3 &start_right,
|
||||
const Vec3 &end_left, const Vec3 &end_right);
|
||||
virtual ~CannonAnimation();
|
||||
virtual void update(float dt);
|
||||
virtual void update(int ticks);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool useEarlyEndTransform() const { return false; }
|
||||
virtual bool usePredefinedEndTransform() const { return false; }
|
||||
}; // CannonAnimation
|
||||
#endif
|
||||
|
||||
@@ -200,7 +200,7 @@ void AIBaseLapController::computePath()
|
||||
void AIBaseLapController::update(int ticks)
|
||||
{
|
||||
AIBaseController::update(ticks);
|
||||
if(DriveGraph::get())
|
||||
if(DriveGraph::get() && m_world)
|
||||
{
|
||||
// Update the current node:
|
||||
int old_node = m_track_node;
|
||||
|
||||
@@ -562,7 +562,7 @@ void SkiddingAI::handleSteering(float dt)
|
||||
|
||||
// Potentially adjust the point to aim for in order to either
|
||||
// aim to collect item, or steer to avoid a bad item.
|
||||
if(m_ai_properties->m_collect_avoid_items)
|
||||
if(m_ai_properties->m_collect_avoid_items && m_kart->getBlockedByPlungerTicks()<=0)
|
||||
handleItemCollectionAndAvoidance(&aim_point, last_node);
|
||||
|
||||
steer_angle = steerToPoint(aim_point);
|
||||
@@ -2054,9 +2054,24 @@ void SkiddingAI::handleAcceleration(int ticks)
|
||||
|
||||
if(m_kart->getBlockedByPlungerTicks()>0)
|
||||
{
|
||||
if(m_kart->getSpeed() < m_kart->getCurrentMaxSpeed() / 2)
|
||||
m_controls->setAccel(0.05f);
|
||||
else
|
||||
int item_skill = computeSkill(ITEM_SKILL);
|
||||
float accel_threshold = 0.5f;
|
||||
|
||||
if (item_skill == 0)
|
||||
accel_threshold = 0.3f;
|
||||
else if (item_skill == 1)
|
||||
accel_threshold = 0.5f;
|
||||
else if (item_skill == 2)
|
||||
accel_threshold = 0.6f;
|
||||
else if (item_skill == 3)
|
||||
accel_threshold = 0.7f;
|
||||
else if (item_skill == 4)
|
||||
accel_threshold = 0.8f;
|
||||
// The best players, knowing the track, don't slow down with a plunger
|
||||
else if (item_skill == 5)
|
||||
accel_threshold = 1.0f;
|
||||
|
||||
if(m_kart->getSpeed() > m_kart->getCurrentMaxSpeed() * accel_threshold)
|
||||
m_controls->setAccel(0.0f);
|
||||
return;
|
||||
}
|
||||
@@ -3071,10 +3086,28 @@ void SkiddingAI::setSteering(float angle, float dt)
|
||||
else if(steer_fraction < -1.0f) steer_fraction = -1.0f;
|
||||
|
||||
// Restrict steering when a plunger is in the face
|
||||
// The degree of restriction depends on item_skill
|
||||
|
||||
//FIXME : the AI speed estimate in curves don't account for this restriction
|
||||
if(m_kart->getBlockedByPlungerTicks()>0)
|
||||
{
|
||||
if (steer_fraction > 0.5f) steer_fraction = 0.5f;
|
||||
else if(steer_fraction < -0.5f) steer_fraction = -0.5f;
|
||||
int item_skill = computeSkill(ITEM_SKILL);
|
||||
float steering_limit = 0.5f;
|
||||
if (item_skill == 0)
|
||||
steering_limit = 0.35f;
|
||||
else if (item_skill == 1)
|
||||
steering_limit = 0.45f;
|
||||
else if (item_skill == 2)
|
||||
steering_limit = 0.55f;
|
||||
else if (item_skill == 3)
|
||||
steering_limit = 0.65f;
|
||||
else if (item_skill == 4)
|
||||
steering_limit = 0.75f;
|
||||
else if (item_skill == 5)
|
||||
steering_limit = 0.9f;
|
||||
|
||||
if (steer_fraction > steering_limit) steer_fraction = steering_limit;
|
||||
else if(steer_fraction < -steering_limit) steer_fraction = -steering_limit;
|
||||
}
|
||||
|
||||
const Skidding *skidding = m_kart->getSkidding();
|
||||
|
||||
@@ -62,8 +62,8 @@ SoccerAI::SoccerAI(AbstractKart *kart)
|
||||
m_world = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
m_track = Track::getCurrentTrack();
|
||||
m_cur_team = m_world->getKartTeam(m_kart->getWorldKartId());
|
||||
m_opp_team = (m_cur_team == SOCCER_TEAM_BLUE ?
|
||||
SOCCER_TEAM_RED : SOCCER_TEAM_BLUE);
|
||||
m_opp_team = (m_cur_team == KART_TEAM_BLUE ?
|
||||
KART_TEAM_RED : KART_TEAM_BLUE);
|
||||
|
||||
// Don't call our own setControllerName, since this will add a
|
||||
// billboard showing 'AIBaseController' to the kart.
|
||||
@@ -110,8 +110,8 @@ void SoccerAI::reset()
|
||||
void SoccerAI::update(int ticks)
|
||||
{
|
||||
#ifdef BALL_AIM_DEBUG
|
||||
Vec3 red = m_world->getBallAimPosition(SOCCER_TEAM_RED);
|
||||
Vec3 blue = m_world->getBallAimPosition(SOCCER_TEAM_BLUE);
|
||||
Vec3 red = m_world->getBallAimPosition(KART_TEAM_RED);
|
||||
Vec3 blue = m_world->getBallAimPosition(KART_TEAM_BLUE);
|
||||
m_red_sphere->setPosition(red.toIrrVector());
|
||||
m_blue_sphere->setPosition(blue.toIrrVector());
|
||||
#endif
|
||||
@@ -226,7 +226,7 @@ Vec3 SoccerAI::determineBallAimingPosition()
|
||||
{
|
||||
#ifdef BALL_AIM_DEBUG
|
||||
// Choose your favourite team to watch
|
||||
if (m_world->getKartTeam(m_kart->getWorldKartId()) == SOCCER_TEAM_BLUE)
|
||||
if (m_world->getKartTeam(m_kart->getWorldKartId()) == KART_TEAM_BLUE)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
cam->setMode(Camera::CM_NORMAL);
|
||||
|
||||
@@ -46,10 +46,10 @@ private:
|
||||
SoccerWorld *m_world;
|
||||
|
||||
/** Save the team this AI belongs to. */
|
||||
SoccerTeam m_cur_team;
|
||||
KartTeam m_cur_team;
|
||||
|
||||
/** Save the opposite team of this AI team. */
|
||||
SoccerTeam m_opp_team;
|
||||
KartTeam m_opp_team;
|
||||
|
||||
/** Define which way to handle to ball, either steer with it,
|
||||
* or overtake it (Defense). */
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "items/attachment.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
/** A static create function that does only create an explosion if
|
||||
@@ -73,16 +75,51 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
|
||||
bool direct_hit)
|
||||
: AbstractKartAnimation(kart, "ExplosionAnimation")
|
||||
{
|
||||
m_end_transform = m_kart->getTrans();
|
||||
m_xyz = m_kart->getXYZ();
|
||||
m_orig_xyz = m_xyz;
|
||||
m_direct_hit = direct_hit;
|
||||
m_reset_ticks = -1;
|
||||
float timer = m_kart->getKartProperties()->getExplosionDuration();
|
||||
m_timer = stk_config->time2Ticks(timer);
|
||||
m_normal = m_kart->getNormal();
|
||||
m_kart->playCustomSFX(SFXManager::CUSTOM_EXPLODE);
|
||||
m_timer = m_kart->getKartProperties()->getExplosionDuration();
|
||||
|
||||
// Non-direct hits will be only affected half as much.
|
||||
if(!direct_hit) m_timer*=0.5f;
|
||||
if (!m_direct_hit)
|
||||
{
|
||||
timer *= 0.5f;
|
||||
m_timer /= 2;
|
||||
}
|
||||
|
||||
// Put the kart back to its own flag base like rescue if direct hit in CTF
|
||||
if (race_manager->getMajorMode() ==
|
||||
RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG && m_direct_hit)
|
||||
{
|
||||
m_reset_ticks = stk_config->time2Ticks(timer * 0.2f);
|
||||
}
|
||||
|
||||
if (m_reset_ticks != -1)
|
||||
{
|
||||
m_xyz = m_kart->getXYZ();
|
||||
m_orig_xyz = m_xyz;
|
||||
btTransform prev_trans = kart->getTrans();
|
||||
World::getWorld()->moveKartAfterRescue(kart);
|
||||
m_end_transform = kart->getTrans();
|
||||
m_reset_xyz = m_end_transform.getOrigin();
|
||||
m_reset_normal = m_end_transform.getBasis().getColumn(1);
|
||||
kart->getBody()->setCenterOfMassTransform(prev_trans);
|
||||
kart->setTrans(prev_trans);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_end_transform = m_kart->getTrans();
|
||||
m_xyz = m_kart->getXYZ();
|
||||
m_orig_xyz = m_xyz;
|
||||
}
|
||||
m_kart->playCustomSFX(SFXManager::CUSTOM_EXPLODE);
|
||||
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isServer())
|
||||
{
|
||||
m_end_ticks = m_timer + World::getWorld()->getTicksSinceStart() + 1;
|
||||
}
|
||||
// Half of the overall time is spent in raising, so only use
|
||||
// half of the explosion time here.
|
||||
// Velocity after t seconds is:
|
||||
@@ -90,16 +127,16 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
|
||||
// Since v(explosion_time*0.5) = 0, the following forumla computes
|
||||
// the right initial velocity for a kart to land back after
|
||||
// the specified time.
|
||||
m_velocity = 0.5f * m_timer * Track::getCurrentTrack()->getGravity();
|
||||
m_velocity = 0.5f * timer * Track::getCurrentTrack()->getGravity();
|
||||
|
||||
m_curr_rotation.setHeading(m_kart->getHeading());
|
||||
m_curr_rotation.setPitch(m_kart->getPitch());
|
||||
m_curr_rotation.setRoll(m_kart->getRoll());
|
||||
|
||||
const int max_rotation = direct_hit ? 2 : 1;
|
||||
const int max_rotation = m_direct_hit ? 2 : 1;
|
||||
// To get rotations in both directions for each axis we determine a random
|
||||
// number between -(max_rotation-1) and +(max_rotation-1)
|
||||
float f=2.0f*M_PI/m_timer;
|
||||
float f = 2.0f * M_PI / timer;
|
||||
m_add_rotation.setHeading( (rand()%(2*max_rotation+1)-max_rotation)*f );
|
||||
m_add_rotation.setPitch( (rand()%(2*max_rotation+1)-max_rotation)*f );
|
||||
m_add_rotation.setRoll( (rand()%(2*max_rotation+1)-max_rotation)*f );
|
||||
@@ -108,9 +145,10 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
|
||||
float t = m_kart->getKartProperties()->getExplosionInvulnerabilityTime();
|
||||
m_kart->setInvulnerableTicks(stk_config->time2Ticks(t));
|
||||
m_kart->showStarEffect(t);
|
||||
|
||||
|
||||
m_kart->getAttachment()->clear();
|
||||
addNetworkAnimationChecker();
|
||||
// Clear powerups when direct hit in CTF
|
||||
addNetworkAnimationChecker(m_reset_ticks != -1);
|
||||
} // ExplosionAnimation
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -135,26 +173,44 @@ ExplosionAnimation::~ExplosionAnimation()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updates the kart animation.
|
||||
* \param dt Time step size.
|
||||
* \return True if the explosion is still shown, false if it has finished.
|
||||
* \param ticks Number of time steps - should be 1.
|
||||
*/
|
||||
void ExplosionAnimation::update(float dt)
|
||||
void ExplosionAnimation::update(int ticks)
|
||||
{
|
||||
m_velocity -= dt*Track::getCurrentTrack()->getGravity();
|
||||
m_xyz = m_xyz + dt*m_velocity*m_normal;
|
||||
float dt = stk_config->ticks2Time(ticks);
|
||||
m_velocity -= dt * Track::getCurrentTrack()->getGravity();
|
||||
m_xyz = m_xyz + dt * m_velocity * m_normal;
|
||||
|
||||
// Make sure the kart does not end up under the track
|
||||
if ((m_xyz - m_orig_xyz).dot(m_normal)<0)
|
||||
{
|
||||
m_xyz = m_orig_xyz;
|
||||
// This will trigger the end of the animations
|
||||
m_timer = -1;
|
||||
// Don't end the animation if networking for predefined end transform
|
||||
if (!NetworkConfig::get()->isNetworking())
|
||||
m_timer = -1;
|
||||
}
|
||||
m_kart->setXYZ(m_xyz);
|
||||
m_curr_rotation += dt*m_add_rotation;
|
||||
m_curr_rotation += dt * m_add_rotation;
|
||||
btQuaternion q(m_curr_rotation.getHeading(), m_curr_rotation.getPitch(),
|
||||
m_curr_rotation.getRoll());
|
||||
m_kart->setRotation(q);
|
||||
|
||||
AbstractKartAnimation::update(dt);
|
||||
if (m_reset_ticks != -1)
|
||||
{
|
||||
m_reset_xyz = m_reset_xyz + dt * m_velocity * m_reset_normal;
|
||||
if ((m_reset_xyz - m_end_transform.getOrigin()).dot(m_reset_normal) <
|
||||
0.0f)
|
||||
m_reset_xyz = m_end_transform.getOrigin();
|
||||
}
|
||||
if (m_reset_ticks != -1 && m_timer < m_reset_ticks)
|
||||
{
|
||||
m_kart->setXYZ(m_reset_xyz);
|
||||
m_kart->setRotation(m_end_transform.getRotation());
|
||||
m_kart->getBody()->setCenterOfMassTransform(m_kart->getTrans());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kart->setXYZ(m_xyz);
|
||||
m_kart->setRotation(q);
|
||||
}
|
||||
|
||||
AbstractKartAnimation::update(ticks);
|
||||
} // update
|
||||
|
||||
@@ -64,6 +64,15 @@ protected:
|
||||
* on difficulty (so that on easy you can drive again earlier. */
|
||||
float m_duration;
|
||||
|
||||
bool m_direct_hit;
|
||||
|
||||
/** If not -1, when > m_timer it will use m_reset_xyz below for
|
||||
* animation. */
|
||||
int m_reset_ticks;
|
||||
|
||||
/** Used for reset kart back to flag base in CTF. */
|
||||
Vec3 m_reset_xyz, m_reset_normal;
|
||||
|
||||
ExplosionAnimation(AbstractKart *kart);
|
||||
ExplosionAnimation(AbstractKart *kart, const Vec3 &pos,
|
||||
bool direct_hit);
|
||||
@@ -73,6 +82,8 @@ public:
|
||||
static ExplosionAnimation *create(AbstractKart *kart);
|
||||
|
||||
virtual ~ExplosionAnimation();
|
||||
virtual void update(float dt);
|
||||
virtual void update(int ticks);
|
||||
bool hasResetAlready() const
|
||||
{ return m_reset_ticks != -1 && m_timer < m_reset_ticks; }
|
||||
}; // ExplosionAnimation
|
||||
#endif
|
||||
|
||||
@@ -92,6 +92,8 @@ void GhostKart::updateGraphics(float dt)
|
||||
// immediately call Moveable's updateGraphics.
|
||||
Moveable::updateSmoothedGraphics(dt);
|
||||
Moveable::updateGraphics(center_shift, btQuaternion(0, 0, 0, 1));
|
||||
// Also update attachment's graphics
|
||||
m_attachment->updateGraphics(dt);
|
||||
} // updateGraphics
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -150,15 +152,15 @@ void GhostKart::update(int ticks)
|
||||
|
||||
Attachment::AttachmentType attach_type =
|
||||
ReplayRecorder::codeToEnumAttach(m_all_bonus_info[idx].m_attachment);
|
||||
int attach_ticks = 0;
|
||||
int16_t attach_ticks = 0;
|
||||
if (attach_type == Attachment::ATTACH_BUBBLEGUM_SHIELD)
|
||||
attach_ticks = stk_config->time2Ticks(10);
|
||||
attach_ticks = (int16_t)stk_config->time2Ticks(10);
|
||||
else if (attach_type == Attachment::ATTACH_BOMB)
|
||||
attach_ticks = stk_config->time2Ticks(30);
|
||||
attach_ticks = (int16_t)stk_config->time2Ticks(30);
|
||||
// The replay history will take care of clearing,
|
||||
// just make sure it won't expire by itself
|
||||
else
|
||||
attach_ticks = stk_config->time2Ticks(300);
|
||||
attach_ticks = 32767;
|
||||
|
||||
if ( attach_type == Attachment::ATTACH_NOTHING )
|
||||
m_attachment->clear();
|
||||
|
||||
@@ -98,9 +98,9 @@ public:
|
||||
float getTimeForEggs(int egg_number);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void kartIsInRestNow() OVERRIDE {};
|
||||
virtual void kartIsInRestNow() OVERRIDE {}
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
virtual void makeKartRest() OVERRIDE {}
|
||||
}; // GhostKart
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1034,6 +1034,11 @@ void Kart::setRaceResult()
|
||||
FreeForAll* ffa = dynamic_cast<FreeForAll*>(World::getWorld());
|
||||
m_race_result = ffa->getKartAtPosition(1) == this;
|
||||
}
|
||||
else if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG)
|
||||
{
|
||||
CaptureTheFlag* ctf = dynamic_cast<CaptureTheFlag*>(World::getWorld());
|
||||
m_race_result = ctf->getKartCTFResult(getWorldKartId());
|
||||
}
|
||||
else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
|
||||
{
|
||||
SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
@@ -1279,13 +1284,6 @@ void Kart::update(int ticks)
|
||||
{
|
||||
m_powerup->update(ticks);
|
||||
|
||||
// Make the restitution depend on speed: this avoids collision issues,
|
||||
// otherwise a collision with high speed can see a kart being push
|
||||
// high up in the air (and out of control). So for higher speed we
|
||||
// reduce the restitution, meaning the karts will get less of a push
|
||||
// based on the collision speed.
|
||||
m_body->setRestitution(m_kart_properties->getRestitution(fabsf(m_speed)));
|
||||
|
||||
// Reset any instand speed increase in the bullet kart
|
||||
m_vehicle->setMinSpeed(0);
|
||||
|
||||
@@ -1304,12 +1302,12 @@ void Kart::update(int ticks)
|
||||
// before updating the graphical position (which is done in
|
||||
// Moveable::update() ), otherwise 'stuttering' can happen (caused by
|
||||
// graphical and physical position not being the same).
|
||||
float dt = stk_config->ticks2Time(ticks);
|
||||
if (has_animation_before && !RewindManager::get()->isRewinding())
|
||||
{
|
||||
m_kart_animation->update(dt);
|
||||
m_kart_animation->update(ticks);
|
||||
}
|
||||
|
||||
float dt = stk_config->ticks2Time(ticks);
|
||||
if (!RewindManager::get()->isRewinding())
|
||||
{
|
||||
m_time_previous_counter += dt;
|
||||
@@ -1336,6 +1334,12 @@ void Kart::update(int ticks)
|
||||
// Update the locally maintained speed of the kart (m_speed), which
|
||||
// is used furthermore for engine power, camera distance etc
|
||||
updateSpeed();
|
||||
// Make the restitution depend on speed: this avoids collision issues,
|
||||
// otherwise a collision with high speed can see a kart being push
|
||||
// high up in the air (and out of control). So for higher speed we
|
||||
// reduce the restitution, meaning the karts will get less of a push
|
||||
// based on the collision speed.
|
||||
m_body->setRestitution(m_kart_properties->getRestitution(fabsf(m_speed)));
|
||||
|
||||
m_controller->update(ticks);
|
||||
|
||||
|
||||
@@ -355,13 +355,10 @@ void KartProperties::combineCharacteristics(PerPlayerDifficulty difficulty)
|
||||
|
||||
// Try to get the kart type
|
||||
const AbstractCharacteristic *characteristic = kart_properties_manager->
|
||||
getKartTypeCharacteristic(m_kart_type);
|
||||
if (!characteristic)
|
||||
Log::warn("KartProperties", "Can't find kart type '%s' for kart '%s'",
|
||||
m_kart_type.c_str(), m_name.c_str());
|
||||
else
|
||||
// Kart type found
|
||||
m_combined_characteristic->addCharacteristic(characteristic);
|
||||
getKartTypeCharacteristic(m_kart_type, m_name);
|
||||
|
||||
// Combine kart type
|
||||
m_combined_characteristic->addCharacteristic(characteristic);
|
||||
|
||||
m_combined_characteristic->addCharacteristic(kart_properties_manager->
|
||||
getPlayerCharacteristic(getPerPlayerDifficultyAsString(difficulty)));
|
||||
|
||||
@@ -215,6 +215,7 @@ void KartPropertiesManager::loadCharacteristics(const XMLNode *root)
|
||||
for (const XMLNode *type : nodes)
|
||||
{
|
||||
type->get("name", &name);
|
||||
m_kart_types.push_back(name);
|
||||
m_kart_type_characteristics.insert(std::pair<const std::string,
|
||||
std::unique_ptr<AbstractCharacteristic> >(name,
|
||||
std::unique_ptr<AbstractCharacteristic>(new XmlCharacteristic(type))));
|
||||
@@ -303,10 +304,24 @@ const AbstractCharacteristic* KartPropertiesManager::getDifficultyCharacteristic
|
||||
} // getDifficultyCharacteristic
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const AbstractCharacteristic* KartPropertiesManager::getKartTypeCharacteristic(const std::string &type) const
|
||||
const AbstractCharacteristic* KartPropertiesManager::getKartTypeCharacteristic(const std::string &type,
|
||||
const std::string &name) const
|
||||
{
|
||||
bool type_is_valid = false;
|
||||
for (unsigned i=0; i < m_kart_types.size(); i++)
|
||||
{
|
||||
if (type == m_kart_types[i])
|
||||
type_is_valid = true;
|
||||
}
|
||||
|
||||
if (!type_is_valid)
|
||||
Log::warn("KartProperties", "Can't find kart type '%s' for kart '%s', defaulting to '%s'.",
|
||||
type.c_str(), name.c_str(), m_kart_types[0].c_str());
|
||||
|
||||
std::string valid_type = (type_is_valid) ? type : m_kart_types[0];
|
||||
|
||||
std::map<std::string, std::unique_ptr<AbstractCharacteristic> >::const_iterator
|
||||
it = m_kart_type_characteristics.find(type);
|
||||
it = m_kart_type_characteristics.find(valid_type);
|
||||
if (it == m_kart_type_characteristics.cend())
|
||||
return nullptr;
|
||||
return it->second.get();
|
||||
|
||||
@@ -49,6 +49,9 @@ private:
|
||||
/** List of all kart groups. */
|
||||
std::vector<std::string> m_all_groups;
|
||||
|
||||
/** List of all kart types. */
|
||||
std::vector<std::string> m_kart_types;
|
||||
|
||||
/** Mapping of group names to list of kart indices in each group. */
|
||||
std::map<std::string, std::vector<int> > m_groups_2_indices;
|
||||
|
||||
@@ -105,7 +108,7 @@ public:
|
||||
const AbstractCharacteristic* getDifficultyCharacteristic(const std::string &type) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Get a characteristic that holds the values for a kart type. */
|
||||
const AbstractCharacteristic* getKartTypeCharacteristic(const std::string &type) const;
|
||||
const AbstractCharacteristic* getKartTypeCharacteristic(const std::string &type, const std::string &name) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Get a characteristic that holds the values for a player difficulty. */
|
||||
const AbstractCharacteristic* getPlayerCharacteristic(const std::string &type) const;
|
||||
|
||||
@@ -52,6 +52,8 @@ KartRewinder::KartRewinder(const std::string& ident,
|
||||
*/
|
||||
void KartRewinder::reset()
|
||||
{
|
||||
m_transfrom_from_network =
|
||||
btTransform(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
Kart::reset();
|
||||
Rewinder::reset();
|
||||
SmoothNetworkBody::setEnable(true);
|
||||
@@ -86,7 +88,7 @@ void KartRewinder::computeError()
|
||||
m_skidding->checkSmoothing();
|
||||
}
|
||||
else
|
||||
ka->checkNetworkAnimationCreationSucceed();
|
||||
ka->checkNetworkAnimationCreationSucceed(m_transfrom_from_network);
|
||||
|
||||
float diff = fabsf(m_prev_steering - AbstractKart::getSteerPercent());
|
||||
if (diff > 0.05f)
|
||||
@@ -121,7 +123,7 @@ BareNetworkString* KartRewinder::saveState(std::vector<std::string>* ru)
|
||||
buffer->addUInt16(m_view_blocked_by_plunger);
|
||||
// m_invulnerable_ticks will not be negative
|
||||
AbstractKartAnimation* ka = getKartAnimation();
|
||||
bool has_animation = ka != NULL && ka->useEarlyEndTransform();
|
||||
bool has_animation = ka != NULL && ka->usePredefinedEndTransform();
|
||||
uint16_t fire_and_invulnerable = (m_fire_clicked ? 1 << 15 : 0) |
|
||||
(has_animation ? 1 << 14 : 0) | m_invulnerable_ticks;
|
||||
buffer->addUInt16(fire_and_invulnerable);
|
||||
@@ -136,6 +138,7 @@ BareNetworkString* KartRewinder::saveState(std::vector<std::string>* ru)
|
||||
buffer->add(trans.getOrigin());
|
||||
btQuaternion quat = trans.getRotation();
|
||||
buffer->add(quat);
|
||||
buffer->addUInt32(ka->getEndTicks());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -199,19 +202,19 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count)
|
||||
|
||||
// 2) Kart animation status or transform and velocities
|
||||
// -----------
|
||||
btTransform t;
|
||||
t.setOrigin(buffer->getVec3());
|
||||
t.setRotation(buffer->getQuat());
|
||||
Vec3 lv = buffer->getVec3();
|
||||
Vec3 av = buffer->getVec3();
|
||||
m_transfrom_from_network.setOrigin(buffer->getVec3());
|
||||
m_transfrom_from_network.setRotation(buffer->getQuat());
|
||||
|
||||
if (has_animation)
|
||||
{
|
||||
int end_ticks = buffer->getUInt32();
|
||||
AbstractKartAnimation* ka = getKartAnimation();
|
||||
if (ka)
|
||||
ka->setEndTransform(t);
|
||||
ka->setEndTransformTicks(m_transfrom_from_network, end_ticks);
|
||||
}
|
||||
|
||||
Vec3 lv = buffer->getVec3();
|
||||
Vec3 av = buffer->getVec3();
|
||||
// Don't restore to phyics position if showing kart animation
|
||||
if (!getKartAnimation())
|
||||
{
|
||||
@@ -222,10 +225,10 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count)
|
||||
body->setAngularVelocity(av);
|
||||
// This function also reads the velocity, so it must be called
|
||||
// after the velocities are set
|
||||
body->proceedToTransform(t);
|
||||
body->proceedToTransform(m_transfrom_from_network);
|
||||
// Update kart transform in case that there are access to its value
|
||||
// before Moveable::update() is called (which updates the transform)
|
||||
setTrans(t);
|
||||
setTrans(m_transfrom_from_network);
|
||||
}
|
||||
|
||||
m_vehicle->setMinSpeed(buffer->getFloat());
|
||||
|
||||
@@ -30,10 +30,7 @@ class KartRewinder : public Rewinder, public Kart
|
||||
{
|
||||
private:
|
||||
|
||||
// Flags to indicate the different event types
|
||||
enum { EVENT_CONTROL = 0x01,
|
||||
EVENT_ATTACH = 0x02 };
|
||||
|
||||
btTransform m_transfrom_from_network;
|
||||
float m_prev_steering, m_steering_smoothing_dt, m_steering_smoothing_time;
|
||||
|
||||
public:
|
||||
|
||||
@@ -323,6 +323,14 @@ void MaxSpeed::update(int ticks)
|
||||
m_current_max_speed += speedup.getSpeedIncrease();
|
||||
m_add_engine_force += speedup.getEngineForce();
|
||||
}
|
||||
if (getSpeedIncreaseTicksLeft(MS_INCREASE_SKIDDING) > 0 &&
|
||||
getSpeedIncreaseTicksLeft(MS_INCREASE_RED_SKIDDING) > 0)
|
||||
{
|
||||
SpeedIncrease &speedup = m_speed_increase[MS_INCREASE_SKIDDING];
|
||||
m_current_max_speed -= speedup.getSpeedIncrease();
|
||||
m_add_engine_force -= speedup.getEngineForce();
|
||||
}
|
||||
|
||||
m_current_max_speed *= slowdown_factor;
|
||||
|
||||
// Then cap the current speed of the kart
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
MS_INCREASE_NITRO,
|
||||
MS_INCREASE_RUBBER,
|
||||
MS_INCREASE_SKIDDING,
|
||||
MS_INCREASE_RED_SKIDDING,
|
||||
MS_INCREASE_MAX};
|
||||
|
||||
/** The categories to use for decreasing the speed of a kart:
|
||||
|
||||
@@ -19,13 +19,12 @@
|
||||
#include "karts/rescue_animation.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/referee.hpp"
|
||||
#include "items/attachment.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "modes/three_strikes_battle.hpp"
|
||||
#include "modes/world_with_rank.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
#include "physics/triangle_mesh.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
@@ -37,7 +36,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "graphics/camera_normal.hpp"
|
||||
/** The constructor stores a pointer to the kart this object is animating,
|
||||
* and initialised the timer.
|
||||
* \param kart Pointer to the kart which is animated.
|
||||
@@ -56,51 +54,43 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
|
||||
|
||||
m_referee = new Referee(*m_kart);
|
||||
m_kart->getNode()->addChild(m_referee->getSceneNode());
|
||||
m_timer = m_kart->getKartProperties()->getRescueDuration();
|
||||
float timer = m_kart->getKartProperties()->getRescueDuration();
|
||||
m_rescue_moment = stk_config->time2Ticks(timer * 0.6f);
|
||||
m_timer = stk_config->time2Ticks(timer);
|
||||
m_up_vector = m_kart->getTrans().getBasis().getColumn(1);
|
||||
m_xyz = m_kart->getXYZ();
|
||||
m_orig_rotation = m_kart->getRotation();
|
||||
m_kart->getAttachment()->clear();
|
||||
|
||||
if (NetworkConfig::get()->isNetworking() &&
|
||||
NetworkConfig::get()->isServer())
|
||||
{
|
||||
m_end_ticks = m_timer + World::getWorld()->getTicksSinceStart() + 1;
|
||||
}
|
||||
|
||||
// Determine maximum rescue height with up-raycast
|
||||
float max_height = m_kart->getKartProperties()->getRescueHeight();
|
||||
float hit_dest = maximumHeight();
|
||||
|
||||
max_height = std::min(hit_dest, max_height);
|
||||
m_velocity = max_height / m_timer;
|
||||
|
||||
// Determine the rotation that will rotate the kart from the current
|
||||
// up direction to the right up direction it should have according to
|
||||
// the last vaild quad of the kart
|
||||
WorldWithRank* wwr = dynamic_cast<WorldWithRank*>(World::getWorld());
|
||||
if (DriveGraph::get() && wwr &&
|
||||
wwr->getTrackSector(m_kart->getWorldKartId())->getCurrentGraphNode() > -1)
|
||||
{
|
||||
const int sector = wwr->getTrackSector(m_kart->getWorldKartId())
|
||||
->getCurrentGraphNode();
|
||||
const Vec3& quad_normal = DriveGraph::get()->getQuad(sector)
|
||||
->getNormal();
|
||||
btQuaternion angle_rot(btVector3(0, 1, 0),
|
||||
Track::getCurrentTrack()->getAngle(sector));
|
||||
m_des_rotation = shortestArcQuat(Vec3(0, 1, 0), quad_normal) * angle_rot;
|
||||
m_des_rotation.normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_des_rotation = m_orig_rotation;
|
||||
}
|
||||
m_velocity = max_height / timer;
|
||||
|
||||
// Add a hit unless it was auto-rescue
|
||||
if (race_manager->getMinorMode()==RaceManager::MINOR_MODE_BATTLE &&
|
||||
!is_auto_rescue)
|
||||
{
|
||||
ThreeStrikesBattle *world=(ThreeStrikesBattle*)World::getWorld();
|
||||
world->kartHit(m_kart->getWorldKartId());
|
||||
World::getWorld()->kartHit(m_kart->getWorldKartId());
|
||||
if (UserConfigParams::m_arena_ai_stats)
|
||||
world->increaseRescueCount();
|
||||
{
|
||||
ThreeStrikesBattle* tsb = dynamic_cast<ThreeStrikesBattle*>
|
||||
(World::getWorld());
|
||||
if (tsb)
|
||||
tsb->increaseRescueCount();
|
||||
}
|
||||
}
|
||||
|
||||
addNetworkAnimationChecker();
|
||||
// Clear powerups when rescue in CTF
|
||||
addNetworkAnimationChecker(race_manager->getMajorMode() ==
|
||||
RaceManager::MAJOR_MODE_CAPTURE_THE_FLAG);
|
||||
} // RescueAnimation
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -140,34 +130,24 @@ float RescueAnimation::maximumHeight()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updates the kart animation.
|
||||
* \param dt Time step size.
|
||||
* \return True if the explosion is still shown, false if it has finished.
|
||||
* \param ticks Number of time steps - should be 1.
|
||||
*/
|
||||
void RescueAnimation::update(float dt)
|
||||
void RescueAnimation::update(int ticks)
|
||||
{
|
||||
if (m_timer <= (m_kart->getKartProperties()->getRescueDuration() * rescue_moment))
|
||||
float dt = stk_config->ticks2Time(ticks);
|
||||
if (m_timer <= m_rescue_moment)
|
||||
{
|
||||
if (m_kart_on_track == false)
|
||||
{
|
||||
m_kart_on_track = true;
|
||||
m_kart->getBody()->setCenterOfMassTransform(m_end_transform);
|
||||
m_kart->setTrans(m_end_transform);
|
||||
for (unsigned int i = 0; i < Camera::getNumCameras(); i++)
|
||||
{
|
||||
CameraNormal* camera = dynamic_cast<CameraNormal*>(Camera::getCamera(i));
|
||||
if (camera && camera->getKart() == m_kart &&
|
||||
dynamic_cast<CameraNormal*>(camera))
|
||||
{
|
||||
camera->setMode(Camera::CM_NORMAL);
|
||||
camera->snapToPosition();
|
||||
}
|
||||
}
|
||||
|
||||
m_up_vector = m_kart->getTrans().getBasis().getColumn(1);
|
||||
m_xyz = m_kart->getXYZ();
|
||||
|
||||
float hit_dest = maximumHeight();
|
||||
float max_height = std::min(hit_dest, m_kart->getKartProperties()->getRescueHeight()) * rescue_moment;
|
||||
float max_height = std::min(hit_dest,
|
||||
m_kart->getKartProperties()->getRescueHeight()) * 0.6f;
|
||||
m_xyz += max_height * m_up_vector;
|
||||
}
|
||||
|
||||
@@ -180,6 +160,6 @@ void RescueAnimation::update(float dt)
|
||||
m_kart->setXYZ(m_xyz);
|
||||
}
|
||||
|
||||
AbstractKartAnimation::update(dt);
|
||||
AbstractKartAnimation::update(ticks);
|
||||
|
||||
} // update
|
||||
|
||||
@@ -37,18 +37,11 @@ protected:
|
||||
/** Column 1 of btTransform of kart. */
|
||||
Vec3 m_up_vector;
|
||||
|
||||
/** The kart's original rotation. */
|
||||
btQuaternion m_orig_rotation;
|
||||
|
||||
/** Desired rotation for rescue determined by last valid quad. */
|
||||
btQuaternion m_des_rotation;
|
||||
|
||||
/** The velocity with which the kart is moved. */
|
||||
float m_velocity;
|
||||
|
||||
/* At what percent of the animation should the kart be on the track*/
|
||||
/*0.75 means that for 3 quaters of the animation it'll be on track*/
|
||||
const float rescue_moment = 0.6F;
|
||||
int m_rescue_moment;
|
||||
|
||||
/* Has the kart been moved onto the track */
|
||||
bool m_kart_on_track = false;
|
||||
|
||||
@@ -59,6 +52,6 @@ public:
|
||||
RescueAnimation(AbstractKart *kart, bool is_auto_rescue=false);
|
||||
float maximumHeight();
|
||||
virtual ~RescueAnimation();
|
||||
virtual void update(float dt);
|
||||
virtual void update(int ticks);
|
||||
}; // RescueAnimation
|
||||
#endif
|
||||
|
||||
@@ -503,8 +503,10 @@ void Skidding::update(int ticks, bool is_on_ground,
|
||||
->setCreationRateRelative(KartGFX::KGFX_SKIDL, 1.0f);
|
||||
m_kart->getKartGFX()
|
||||
->setCreationRateRelative(KartGFX::KGFX_SKIDR, 1.0f);
|
||||
unsigned int bonus_cat = (level == 1) ? MaxSpeed::MS_INCREASE_SKIDDING :
|
||||
MaxSpeed::MS_INCREASE_RED_SKIDDING;
|
||||
m_kart->m_max_speed->
|
||||
instantSpeedIncrease(MaxSpeed::MS_INCREASE_SKIDDING,
|
||||
instantSpeedIncrease(bonus_cat,
|
||||
bonus_speed, bonus_speed,
|
||||
bonus_force,
|
||||
stk_config->time2Ticks(bonus_time),
|
||||
|
||||
139
src/main.cpp
@@ -166,6 +166,7 @@
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include <IEventReceiver.h>
|
||||
|
||||
@@ -214,6 +215,7 @@
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "network/protocols/client_lobby.hpp"
|
||||
#include "network/protocols/server_lobby.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
@@ -559,7 +561,14 @@ void cmdLineHelp()
|
||||
" --aiNP=a,b,... Use the karts a, b, ... for the AI, no additional player kart.\n"
|
||||
" --laps=N Define number of laps to N.\n"
|
||||
" --mode=N N=1 Beginner, N=2 Intermediate, N=3 Expert, N=4 SuperTux.\n"
|
||||
" --type=N N=0 Normal, N=1 Time trial, N=2 Follow The Leader\n"
|
||||
" --type=N N=0 Normal, N=1 Time trial, N=2 Battle, N=3 Soccer,\n"
|
||||
" N=4 Follow The Leader. In configure server use --battle-mode=n\n"
|
||||
" for battle server and --soccer-timed / goals for soccer server\n"
|
||||
" to control verbosely, see below:\n"
|
||||
" --battle-mode=n Specify battle mode in netowrk, 0 is Free-For-All and\n"
|
||||
" 1 is Capture The Flag.\n"
|
||||
" --soccer-timed Use time limit mode in network soccer game.\n"
|
||||
" --soccer-goals Use goals limit mode in network soccer game.\n"
|
||||
" --reverse Play track in reverse (if allowed)\n"
|
||||
" -f, --fullscreen Use fullscreen display.\n"
|
||||
" -w, --windowed Use windowed display (default).\n"
|
||||
@@ -567,6 +576,7 @@ void cmdLineHelp()
|
||||
" -v, --version Print version of SuperTuxKart.\n"
|
||||
" --trackdir=DIR A directory from which additional tracks are "
|
||||
"loaded.\n"
|
||||
" --seed=n Seed for random number generation to provide reproducible behavior.\n"
|
||||
" --profile-laps=n Enable automatic driven profile mode for n "
|
||||
"laps.\n"
|
||||
" --profile-time=n Enable automatic driven profile mode for n "
|
||||
@@ -600,7 +610,6 @@ void cmdLineHelp()
|
||||
" --init-user Save the above login and password (if set) in config.\n"
|
||||
" --disable-polling Don't poll for logged in user.\n"
|
||||
" --port=n Port number to use.\n"
|
||||
" --disable-lan Disable LAN detection (connect using WAN).\n"
|
||||
" --auto-connect Automatically connect to fist server and start race\n"
|
||||
" --max-players=n Maximum number of clients (server only).\n"
|
||||
" --min-players=n Minimum number of clients (server only).\n"
|
||||
@@ -610,10 +619,6 @@ void cmdLineHelp()
|
||||
" --team-choosing Allow choosing team in lobby, implicitly allowed in lan or\n"
|
||||
" password protected server. This function cannot be used in\n"
|
||||
" owner-less server.\n"
|
||||
" --soccer-timed Use time limit mode in network soccer game.\n"
|
||||
" --soccer-goals Use goals limit mode in network soccer game.\n"
|
||||
" --battle-mode=n Specify battle mode in netowrk, 0 is Free For All and\n"
|
||||
" 1 is Capture The Flag.\n"
|
||||
" --network-gp=n Specify number of tracks used in network grand prix.\n"
|
||||
" --no-validation Allow non validated and unencrypted connection in wan.\n"
|
||||
" --ranked Server will submit ranking to stk addons server.\n"
|
||||
@@ -737,7 +742,7 @@ int handleCmdLinePreliminary()
|
||||
if(CommandLine::has("--debug=all") )
|
||||
UserConfigParams::m_verbosity |= UserConfigParams::LOG_ALL;
|
||||
if(CommandLine::has("--online"))
|
||||
MainMenuScreen::m_enable_online=true;
|
||||
History::m_online_history_replay = true;
|
||||
#if !(defined(SERVER_ONLY) || defined(ANDROID))
|
||||
if(CommandLine::has("--apitrace"))
|
||||
{
|
||||
@@ -756,11 +761,6 @@ int handleCmdLinePreliminary()
|
||||
if(CommandLine::has("--kartdir", &s))
|
||||
KartPropertiesManager::addKartSearchDir(s);
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if(CommandLine::has("--no-graphics") || CommandLine::has("-l"))
|
||||
#endif
|
||||
ProfileWorld::disableGraphics();
|
||||
|
||||
if (CommandLine::has("--sp-shader-debug"))
|
||||
SP::SPShader::m_sp_shader_debug = true;
|
||||
|
||||
@@ -906,7 +906,15 @@ int handleCmdLinePreliminary()
|
||||
if(CommandLine::has("--dont-load-navmesh"))
|
||||
Track::m_dont_load_navmesh = true;
|
||||
|
||||
if (CommandLine::has("--no-sound"))
|
||||
UserConfigParams::m_enable_sound = false;
|
||||
|
||||
if (CommandLine::has("--seed", &n))
|
||||
{
|
||||
srand(n);
|
||||
Log::info("main", "STK using random seed (%d)", n);
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // handleCmdLinePreliminary
|
||||
|
||||
@@ -1187,7 +1195,7 @@ int handleCmdLine()
|
||||
NetworkConfig::get()->setIsWAN();
|
||||
NetworkConfig::get()->setIsServer(false);
|
||||
auto server = std::make_shared<Server>(0, L"", 0, 0, 0, 0, server_addr,
|
||||
!server_password.empty());
|
||||
!server_password.empty(), false);
|
||||
NetworkConfig::get()->addNetworkPlayer(
|
||||
input_manager->getDeviceManager()->getLatestUsedDevice(),
|
||||
PlayerManager::getCurrentPlayer(), PLAYER_DIFFICULTY_NORMAL);
|
||||
@@ -1197,7 +1205,7 @@ int handleCmdLine()
|
||||
cts->setup();
|
||||
Log::info("main", "Trying to connect to server '%s'.",
|
||||
server_addr.toString().c_str());
|
||||
if (!cts->handleDirectConnect(10000))
|
||||
if (!cts->tryConnect(2000, 15))
|
||||
{
|
||||
Log::error("main", "Timeout trying to connect to server '%s'.",
|
||||
server_addr.toString().c_str());
|
||||
@@ -1349,11 +1357,6 @@ int handleCmdLine()
|
||||
if (server_lobby)
|
||||
server_lobby->requestStart();
|
||||
|
||||
/** Disable detection of LAN connection when connecting via WAN. This is
|
||||
* mostly a debugging feature to force using WAN connection. */
|
||||
if (CommandLine::has("--disable-lan"))
|
||||
NetworkConfig::m_disable_lan = true;
|
||||
|
||||
// Race parameters
|
||||
if(CommandLine::has("--kartsize-debug"))
|
||||
{
|
||||
@@ -1556,7 +1559,7 @@ int handleCmdLine()
|
||||
history->setReplayHistory(true);
|
||||
// Force the no-start screen flag, since this initialises
|
||||
// the player structures correctly.
|
||||
if(!MainMenuScreen::m_enable_online)
|
||||
if (!History::m_online_history_replay)
|
||||
UserConfigParams::m_no_start_screen = true;
|
||||
} // --history
|
||||
|
||||
@@ -1646,6 +1649,12 @@ void initRest()
|
||||
stk_config->load(file_manager->getAsset("stk_config.xml"));
|
||||
|
||||
irr_driver = new IrrDriver();
|
||||
|
||||
if (irr_driver->getDevice() == NULL)
|
||||
{
|
||||
Log::fatal("main", "Couldn't initialise irrlicht device. Quitting.\n");
|
||||
}
|
||||
|
||||
StkTime::init(); // grabs the timer object from the irrlicht device
|
||||
|
||||
// Now create the actual non-null device in the irrlicht driver
|
||||
@@ -1801,6 +1810,22 @@ void askForInternetPermission()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifdef ANDROID
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
void main_abort()
|
||||
{
|
||||
if (main_loop)
|
||||
{
|
||||
main_loop->abort();
|
||||
}
|
||||
}
|
||||
#ifdef ANDROID
|
||||
}
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
@@ -1810,8 +1835,7 @@ int main(int argc, char *argv[] )
|
||||
#ifndef WIN32
|
||||
signal(SIGTERM, [](int signum)
|
||||
{
|
||||
if (main_loop)
|
||||
main_loop->abort();
|
||||
main_abort();
|
||||
});
|
||||
#endif
|
||||
srand(( unsigned ) time( 0 ));
|
||||
@@ -1828,6 +1852,11 @@ int main(int argc, char *argv[] )
|
||||
FileManager::setStdoutName(s);
|
||||
if (CommandLine::has("--stdout-dir", &s))
|
||||
FileManager::setStdoutDir(s);
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if(CommandLine::has("--no-graphics") || CommandLine::has("-l"))
|
||||
#endif
|
||||
ProfileWorld::disableGraphics();
|
||||
|
||||
// Init the minimum managers so that user config exists, then
|
||||
// handle all command line options that do not need (or must
|
||||
@@ -2083,7 +2112,7 @@ int main(int argc, char *argv[] )
|
||||
{
|
||||
// This will setup the race manager etc.
|
||||
history->Load();
|
||||
if (!MainMenuScreen::m_enable_online)
|
||||
if (!History::m_online_history_replay)
|
||||
{
|
||||
race_manager->setupPlayerKartInfo();
|
||||
race_manager->startNew(false);
|
||||
@@ -2343,6 +2372,70 @@ void runUnitTests()
|
||||
Log::info("UnitTest", "RewindQueue");
|
||||
RewindQueue::unitTesting();
|
||||
|
||||
Log::info("UnitTest", "IP ban");
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
ServerLobby sl;
|
||||
|
||||
UserConfigParams::m_server_ip_ban_list =
|
||||
{
|
||||
{ "1.2.3.4/32", std::numeric_limits<uint32_t>::max() }
|
||||
};
|
||||
sl.updateBanList();
|
||||
assert(sl.isBannedForIP(TransportAddress("1.2.3.4")));
|
||||
assert(!sl.isBannedForIP(TransportAddress("1.2.3.5")));
|
||||
assert(!sl.isBannedForIP(TransportAddress("1.2.3.3")));
|
||||
|
||||
UserConfigParams::m_server_ip_ban_list =
|
||||
{
|
||||
{ "1.2.3.4/23", std::numeric_limits<uint32_t>::max() }
|
||||
};
|
||||
sl.updateBanList();
|
||||
assert(!sl.isBannedForIP(TransportAddress("1.2.1.255")));
|
||||
assert(sl.isBannedForIP(TransportAddress("1.2.2.0")));
|
||||
assert(sl.isBannedForIP(TransportAddress("1.2.2.3")));
|
||||
assert(sl.isBannedForIP(TransportAddress("1.2.2.4")));
|
||||
assert(sl.isBannedForIP(TransportAddress("1.2.2.5")));
|
||||
assert(sl.isBannedForIP(TransportAddress("1.2.3.3")));
|
||||
assert(sl.isBannedForIP(TransportAddress("1.2.3.4")));
|
||||
assert(sl.isBannedForIP(TransportAddress("1.2.3.5")));
|
||||
assert(sl.isBannedForIP(TransportAddress("1.2.3.255")));
|
||||
assert(!sl.isBannedForIP(TransportAddress("1.2.4.0")));
|
||||
|
||||
UserConfigParams::m_server_ip_ban_list =
|
||||
{
|
||||
{ "11.12.13.14/22", std::numeric_limits<uint32_t>::max() },
|
||||
{ "12.13.14.15/24", std::numeric_limits<uint32_t>::max() },
|
||||
{ "123.234.56.78/26", std::numeric_limits<uint32_t>::max() },
|
||||
{ "234.123.56.78/25", std::numeric_limits<uint32_t>::max() },
|
||||
// Test for overlap handling
|
||||
{ "12.13.14.23/32", std::numeric_limits<uint32_t>::max() },
|
||||
{ "12.13.14.255/32", std::numeric_limits<uint32_t>::max() }
|
||||
};
|
||||
sl.updateBanList();
|
||||
assert(!sl.isBannedForIP(TransportAddress("11.12.11.255")));
|
||||
assert(sl.isBannedForIP(TransportAddress("11.12.12.0")));
|
||||
assert(sl.isBannedForIP(TransportAddress("11.12.13.14")));
|
||||
assert(sl.isBannedForIP(TransportAddress("11.12.15.255")));
|
||||
assert(!sl.isBannedForIP(TransportAddress("11.12.16.0")));
|
||||
|
||||
assert(!sl.isBannedForIP(TransportAddress("12.13.13.255")));
|
||||
assert(sl.isBannedForIP(TransportAddress("12.13.14.0")));
|
||||
assert(sl.isBannedForIP(TransportAddress("12.13.14.15")));
|
||||
assert(sl.isBannedForIP(TransportAddress("12.13.14.255")));
|
||||
assert(!sl.isBannedForIP(TransportAddress("12.13.15.0")));
|
||||
|
||||
assert(!sl.isBannedForIP(TransportAddress("123.234.56.63")));
|
||||
assert(sl.isBannedForIP(TransportAddress("123.234.56.64")));
|
||||
assert(sl.isBannedForIP(TransportAddress("123.234.56.78")));
|
||||
assert(sl.isBannedForIP(TransportAddress("123.234.56.127")));
|
||||
assert(!sl.isBannedForIP(TransportAddress("123.234.56.128")));
|
||||
|
||||
assert(!sl.isBannedForIP(TransportAddress("234.123.55.255")));
|
||||
assert(sl.isBannedForIP(TransportAddress("234.123.56.0")));
|
||||
assert(sl.isBannedForIP(TransportAddress("234.123.56.78")));
|
||||
assert(sl.isBannedForIP(TransportAddress("234.123.56.127")));
|
||||
assert(!sl.isBannedForIP(TransportAddress("234.123.56.128")));
|
||||
|
||||
Log::info("UnitTest", "=====================");
|
||||
Log::info("UnitTest", "Testing successful ");
|
||||
Log::info("UnitTest", "=====================");
|
||||
|
||||
@@ -48,6 +48,25 @@ void override_default_params()
|
||||
UserConfigParams::m_multitouch_enabled = true;
|
||||
}
|
||||
|
||||
// Set multitouch device scale depending on actual screen size
|
||||
int32_t screen_size = AConfiguration_getScreenSize(global_android_app->config);
|
||||
|
||||
switch (screen_size)
|
||||
{
|
||||
case ACONFIGURATION_SCREENSIZE_SMALL:
|
||||
case ACONFIGURATION_SCREENSIZE_NORMAL:
|
||||
UserConfigParams::m_multitouch_scale = 1.3f;
|
||||
break;
|
||||
case ACONFIGURATION_SCREENSIZE_LARGE:
|
||||
UserConfigParams::m_multitouch_scale = 1.2f;
|
||||
break;
|
||||
case ACONFIGURATION_SCREENSIZE_XLARGE:
|
||||
UserConfigParams::m_multitouch_scale = 1.1f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Enable screen keyboard
|
||||
UserConfigParams::m_screen_keyboard = 1;
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "utils/profiler.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
@@ -111,11 +112,9 @@ float MainLoop::getLimitedDt()
|
||||
return 1.0f/60.0f;
|
||||
}
|
||||
|
||||
IrrlichtDevice* device = irr_driver->getDevice();
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
m_curr_time = device->getTimer()->getRealTime();
|
||||
m_curr_time = StkTime::getRealTimeMs();
|
||||
dt = (float)(m_curr_time - m_prev_time);
|
||||
// On a server (i.e. without graphics) the frame rate can be under
|
||||
// 1 ms, i.e. dt = 0. Additionally, the resolution of a sleep
|
||||
@@ -131,7 +130,7 @@ float MainLoop::getLimitedDt()
|
||||
while (dt <= 0 && !ProfileWorld::isProfileMode())
|
||||
{
|
||||
StkTime::sleep(1);
|
||||
m_curr_time = device->getTimer()->getRealTime();
|
||||
m_curr_time = StkTime::getRealTimeMs();
|
||||
dt = (float)(m_curr_time - m_prev_time);
|
||||
}
|
||||
|
||||
@@ -279,9 +278,7 @@ void MainLoop::updateRace(int ticks)
|
||||
*/
|
||||
void MainLoop::run()
|
||||
{
|
||||
IrrlichtDevice* device = irr_driver->getDevice();
|
||||
|
||||
m_curr_time = device->getTimer()->getRealTime();
|
||||
m_curr_time = StkTime::getRealTimeMs();
|
||||
// DT keeps track of the leftover time, since the race update
|
||||
// happens in fixed timesteps
|
||||
float left_over_time = 0;
|
||||
@@ -460,6 +457,20 @@ void MainLoop::run()
|
||||
World::getWorld()->updateTime(1);
|
||||
}
|
||||
} // for i < num_steps
|
||||
|
||||
// Handle controller the last to avoid slow PC sending actions too late
|
||||
if (!m_abort)
|
||||
{
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
// User aborted (e.g. closed window)
|
||||
bool abort = !irr_driver->getDevice()->run();
|
||||
if (abort)
|
||||
m_abort = true;
|
||||
}
|
||||
if (auto gp = GameProtocol::lock())
|
||||
gp->sendActions();
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER(); // MainLoop pop
|
||||
PROFILER_SYNC_FRAME();
|
||||
} // while !m_abort
|
||||
|
||||