Merge branch 'master' of https://github.com/supertuxkart/stk-code into ScriptCache
1
.gitignore
vendored
@@ -39,6 +39,7 @@ src/html
|
||||
*.vcxproj.filters
|
||||
*.vcxproj.user
|
||||
*~
|
||||
*.swp
|
||||
|
||||
packets_log.txt
|
||||
history.dat
|
||||
|
||||
@@ -78,10 +78,6 @@ if(USE_WIIUSE)
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/wiiuse")
|
||||
endif()
|
||||
|
||||
# Build the angelscript library
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/angelscript/projects/cmake")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/angelscript/include")
|
||||
|
||||
# Set include paths
|
||||
include_directories(${STK_SOURCE_DIR})
|
||||
|
||||
@@ -101,6 +97,11 @@ elseif(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") # Enable multi-processor compilation (faster)
|
||||
endif()
|
||||
|
||||
|
||||
# Build the angelscript library
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/angelscript/projects/cmake")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/angelscript/include")
|
||||
|
||||
# OpenAL
|
||||
if(APPLE)
|
||||
# In theory it would be cleaner to let CMake detect the right dependencies. In practice, this means that if a OSX user has
|
||||
@@ -400,4 +401,4 @@ install(FILES ${STK_DATA_DIR}/supertuxkart.desktop DESTINATION share/application
|
||||
install(FILES data/supertuxkart_32.png DESTINATION share/icons/hicolor/32x32 RENAME supertuxkart.png)
|
||||
install(FILES data/supertuxkart_128.png DESTINATION share/icons/hicolor/128x128 RENAME supertuxkart.png)
|
||||
install(FILES data/supertuxkart_32.png data/supertuxkart_128.png DESTINATION share/pixmaps)
|
||||
install(FILES data/supertuxkart.appdata DESTINATION share/appdata)
|
||||
install(FILES data/supertuxkart.appdata.xml DESTINATION share/appdata)
|
||||
|
||||
@@ -26,11 +26,11 @@ Hope you enjoy the game.
|
||||
##Compiling SuperTuxKart
|
||||
|
||||
###Windows
|
||||
1. Install VS 2012 or later. The free express versions work fine.
|
||||
1. Install VS 2013 (or later). The free express versions work fine.
|
||||
2. Download and install a source package - either a released package or from our [git/svn repositories](http://supertuxkart.sourceforge.net/Source_control)
|
||||
3. Download the latest dependency package depdendencies_for_0.8.2.zip from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/). Unzip it in the root directory, so that the dependencies directory is next to the src and data directory (if you are updating from a previous dependency package, you can delete the .dll files in the root directory, they are not needed anymore).
|
||||
4. Download cmake and install it. Then start cmake-gui and select the STK root directory as 'Where is the source code', and a new directory in the root directory (next to src, data etc) as build directory (for now I assume that this directory is called bld).
|
||||
5. Click on configure. You will be asked to create the directory (yes), then for your VS version. Make sure to select the right version (be aware of the easy to confuse version numbers: VS 2012 = version 11; VS 2013 = version 12). Click on configure, then generate. This will create the directory 'bld', and a VS solution in that directory.
|
||||
5. Click on configure. You will be asked to create the directory (yes), then for your VS version. Make sure to select the right version (be aware of the easy to confuse version numbers: VS 2013 = version 12). Click on configure, then generate. This will create the directory 'bld', and a VS solution in that directory.
|
||||
6. In Visual Studio open the project file generated in the 'bld' folder
|
||||
7. Right click on the supertuxkart project in the solution explorer, and select "Set as StartUp Project".
|
||||
8. Select Build->Build Solution (or press F7) to compile.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<track id="fortmagma" laps="3" reverse="false" />
|
||||
<track id="minigolf" laps="3" reverse="false" />
|
||||
<track id="xr591" laps="3" reverse="false" />
|
||||
<track id="mines" laps="3" reverse="false" />
|
||||
<track id="minel" laps="3" reverse="false" />
|
||||
<track id="lighthouse" laps="4" reverse="false" />
|
||||
|
||||
</supertuxkart_grand_prix>
|
||||
|
||||
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
@@ -20,13 +20,13 @@
|
||||
I18N="Menu item" text="Move up" />
|
||||
<icon-button id="down" width="128" height="128" icon="gui/down.png"
|
||||
I18N="Menu item" text="Move down" />
|
||||
<icon-button id="add" width="128" height="128" icon="gui/gp_add_track.png"
|
||||
<icon-button id="add" width="128" height="128" icon="gui/blue_plus.png"
|
||||
I18N="Menu item" text="Add" />
|
||||
<icon-button id="edit" width="128" height="128" icon="gui/gp_edit_track.png"
|
||||
<icon-button id="edit" width="128" height="128" icon="gui/edit.png"
|
||||
I18N="Menu item" text="Edit" />
|
||||
<icon-button id="remove" width="128" height="128" icon="gui/gp_remove_track.png"
|
||||
<icon-button id="remove" width="128" height="128" icon="gui/remove.png"
|
||||
I18N="Menu item" text="Remove" />
|
||||
<icon-button id="save" width="128" height="128" icon="gui/gp_save.png"
|
||||
<icon-button id="save" width="128" height="128" icon="gui/save.png"
|
||||
I18N="Menu item" text="Save" />
|
||||
</buttonbar>
|
||||
</div>
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
I18N="Menu item" text="New" />
|
||||
<icon-button id="copy" width="128" height="128" icon="gui/gp_copy.png"
|
||||
I18N="Menu item" text="Copy" />
|
||||
<icon-button id="edit" width="128" height="128" icon="gui/gp_edit.png"
|
||||
<icon-button id="edit" width="128" height="128" icon="gui/edit.png"
|
||||
I18N="Menu item" text="Edit" />
|
||||
<icon-button id="remove" width="128" height="128" icon="gui/gp_remove.png"
|
||||
I18N="Menu item" text="Remove" />
|
||||
<icon-button id="rename" width="128" height="128" icon="gui/gp_rename.png"
|
||||
<icon-button id="rename" width="128" height="128" icon="gui/rename.png"
|
||||
I18N="Menu item" text="Rename" />
|
||||
</buttonbar>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
|
||||
I18N="In the change password dialog" text="Password Change"/>
|
||||
|
||||
<spacer height="40" width="50">
|
||||
<spacer height="40" width="50"/>
|
||||
|
||||
<div width="80%" align="center" layout="vertical-row" height="fit" >
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
@@ -13,14 +13,14 @@
|
||||
<textbox proportion="2" height="fit" id="current_password" I18N="In the change password dialog"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="20">
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" height="100%" text_align="left" I18N="In the change password dialog" text="New Password"/>
|
||||
<textbox proportion="2" height="fit" id="new_password1" I18N="In the change password dialog"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="20">
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" height="100%" text_align="left" I18N="In the change password dialog" text="Confirm"/>
|
||||
@@ -28,11 +28,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<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">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<buttonbar id="options" width="90%" height="16%" align="center">
|
||||
<icon-button id="submit" width="64" height="64" icon="gui/green_check.png"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<textbox proportion="1" id="name" I18N="In the create server screen"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="20">
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the create server screen" text="Max. number of players"/>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<textbox proportion="2" id="name" I18N="In the login dialog"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="20">
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the lobby settings screen" text="Max. number of players"/>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true" text=""/>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<buttonbar id="options" width="90%" height="30%" align="center">
|
||||
<icon-button id="view" width="64" height="64" icon="gui/difficulty_medium.png"
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
|
||||
I18N="In the registration dialog' dialog" text="Account Recovery"/>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true" I18N="In the registration dialog"
|
||||
text="You will receive an email with further instructions on how to reset your password. Please be patient and be sure to check your spam folder."/>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<buttonbar id="options" width="25%" height="15%" align="center">
|
||||
<icon-button id="cancel" width="64" height="64" icon="gui/green_check.png"
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
|
||||
I18N="In the recovery dialog' dialog" text="Account Recovery"/>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<label id="message" proportion="2" width="90%" align="center" text_align="left" word_wrap="true"
|
||||
text="Fill in the username and email address you supplied at registration to be able to reset your password."/>
|
||||
|
||||
<spacer height="40" width="50">
|
||||
<spacer height="40" width="50"/>
|
||||
|
||||
<div width="80%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
@@ -18,7 +18,7 @@
|
||||
<textbox proportion="2" id="username" I18N="In the recovery dialog"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="20">
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the recovery dialog" text="Email"/>
|
||||
@@ -27,12 +27,12 @@
|
||||
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true"
|
||||
I18N="In the recovery" text=""/>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<buttonbar id="options" width="25%" proportion="1" align="center">
|
||||
<icon-button id="submit" width="64" height="64" icon="gui/green_check.png"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
|
||||
I18N="In the registration dialog' dialog" text="Terms and Agreement"/>
|
||||
|
||||
<spacer height="25" width="50">
|
||||
<spacer height="25" width="50"/>
|
||||
|
||||
<box proportion="5" width="90%" align="center" layout="vertical-row" padding="8">
|
||||
<list id="terms" x="0" y="0" width="100%" height="100%"/>
|
||||
@@ -16,12 +16,12 @@
|
||||
text="I agree to the above terms and am 13 years or older. "/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true"
|
||||
I18N="In the registration dialog" text=""/>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<buttonbar id="options" width="45%" height="14%" align="center">
|
||||
<icon-button id="accept" width="64" height="64" icon="gui/green_check.png"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
|
||||
I18N="In the server info dialog' dialog" text="Server Info"/>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<div width="80%" align="center" layout="vertical-row" height="fit" >
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
@@ -14,11 +14,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<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">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<buttonbar id="options" width="90%" height="20%" align="center">
|
||||
<icon-button id="join" width="64" height="64" icon="gui/green_check.png"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
|
||||
I18N="User info dialog' dialog" text="User Info"/>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<div width="80%" align="center" layout="vertical-row" height="fit" >
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
@@ -13,11 +13,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<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">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<buttonbar id="options" width="90%" height="20%" align="center">
|
||||
<icon-button id="remove" width="64" height="64" icon="gui/package-uninstall.png"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<spacer width="10" height="10"/>
|
||||
|
||||
<div height="fit" width="100%" layout="horizontal-row" align="center">
|
||||
<textbox id="search_box" height="fit" proportion="1" height="100%"/>
|
||||
<textbox id="search_box" height="fit" proportion="1"/>
|
||||
<spacer width="10" height="10"/>
|
||||
<button id="search_button" height="100%" width="fit" text="Search" />
|
||||
</div>
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
|
||||
I18N="In the vote dialog' dialog" text="Vote"/>
|
||||
|
||||
<spacer height="20" width="50">
|
||||
<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">
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<div width="90%" height="64" align="center" layout="vertical-row" >
|
||||
<ratingbar id="rating" align="center" height="64" width="192"/>
|
||||
</div>
|
||||
|
||||
<spacer height="40" width="50">
|
||||
<spacer height="40" width="50"/>
|
||||
|
||||
<buttonbar id="options" width="25%" height="20%" align="center">
|
||||
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
|
||||
|
||||
@@ -16,40 +16,68 @@
|
||||
|
||||
<box proportion="1" width="100%" layout="vertical-row">
|
||||
|
||||
<spacer height="5" width="10"/>
|
||||
<spacer height="5" width="10" />
|
||||
|
||||
<!-- ************ SKIN CHOICE ************ -->
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<label I18N="In the graphics settings" text="Skin" align="center"/>
|
||||
<label I18N="In the ui settings" text="Skin" align="center"/>
|
||||
<spacer width="20" height="20"/>
|
||||
<spinner id="skinchoice" width="30%"/>
|
||||
</div>
|
||||
|
||||
<spacer width="20" height="18" />
|
||||
|
||||
<div width="75%" height="fit" layout="horizontal-row" >
|
||||
<checkbox id="showfps"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Display FPS"/>
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<checkbox id="showfps"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Display FPS"/>
|
||||
</div>
|
||||
|
||||
<spacer height="4" width="10" />
|
||||
|
||||
<div layout="horizontal-row" proportion="1" height="fit">
|
||||
<checkbox id="perPlayerDifficulty"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Enable handicaped users"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="75%" height="fit" layout="horizontal-row" >
|
||||
<checkbox id="show-login"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Always show login screen"/>
|
||||
<spacer height="4" width="10" />
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<div layout="horizontal-row" proportion="1" height="fit">
|
||||
<checkbox id="show-login"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Always show login screen"/>
|
||||
</div>
|
||||
|
||||
<spacer height="4" width="10" />
|
||||
|
||||
<div layout="horizontal-row" proportion="1" height="fit">
|
||||
<checkbox id="aiHandicap"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Handicap AI karts"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="75%" height="fit" layout="horizontal-row" >
|
||||
<checkbox id="enable-internet"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Allow STK to connect to the Internet"/>
|
||||
</div>
|
||||
<spacer height="4" width="10" />
|
||||
|
||||
<div width="75%" height="fit" layout="horizontal-row" >
|
||||
<checkbox id="enable-hw-report"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label id="label-hw-report" height="100%" I18N="In the ui settings"
|
||||
text="Allow STK to send anonymous HW statistics"/>
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<div proportion="1" height="fit" layout="horizontal-row" >
|
||||
<checkbox id="enable-internet"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Connect to the Internet"/>
|
||||
</div>
|
||||
|
||||
<spacer height="4" width="10" />
|
||||
|
||||
<div layout="horizontal-row" proportion="1" height="fit">
|
||||
<checkbox id="enable-hw-report"/>
|
||||
<spacer width="20" height="100%" />
|
||||
<label height="100%" id="label-hw-report" I18N="In the ui settings"
|
||||
text="Send anonymous HW statistics"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<spacer height="18" width="4"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
@@ -18,7 +18,7 @@
|
||||
<div layout="horizontal-row" width="fit" height="35" align="left">
|
||||
<bright proportion="1" height="100%"
|
||||
I18N="In soccer setup menu" text="Maximum time (min.)" text_align="left" />
|
||||
<spacer width="50" height ="25">
|
||||
<spacer width="50" height ="25"/>
|
||||
<spinner id="timeamount" width="200" height="90%" min_value="1" max_value="15"/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<spacer height="15" width="10"/>
|
||||
<div width="90%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="online" I18N="In the login screen" text_align="left"/>
|
||||
<checkbox width="fit" id="online" I18N="In the user screen" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
|
||||
</div>
|
||||
@@ -28,13 +28,13 @@
|
||||
<!-- Disable guest accounts for now
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label width="40%" id="label_guest" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Guest login"/>
|
||||
<checkbox id="guest" I18N="In the login screen" text_align="left"/>
|
||||
I18N="In the user screen" text="Guest login"/>
|
||||
<checkbox id="guest" I18N="In the user screen" text_align="left"/>
|
||||
</div>
|
||||
-->
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label width="40%" id="label_username" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Username"/>
|
||||
I18N="In the user screen" text="Username"/>
|
||||
<textbox id="username" proportion="2" height="fit" I18N="In the registration dialog"/>
|
||||
</div>
|
||||
<spacer height="20" width="20"/>
|
||||
@@ -52,9 +52,9 @@
|
||||
<buttonbar id="options" width="90%" height="13%" align="bottom">
|
||||
<icon-button id="ok" width="64" height="64" icon="gui/green_check.png"
|
||||
I18N="Login dialog" text="OK" label_location="bottom"/>
|
||||
<icon-button id="new_user" width="64" height="64" icon="gui/gp_add_track.png"
|
||||
<icon-button id="new_user" width="64" height="64" icon="gui/blue_plus.png"
|
||||
I18N="Login dialog" text="Add user" label_location="bottom"/>
|
||||
<icon-button id="delete" width="64" height="64" icon="gui/gp_remove_track.png"
|
||||
<icon-button id="delete" width="64" height="64" icon="gui/remove.png"
|
||||
I18N="Login dialog" text="Delete" label_location="bottom"/>
|
||||
<icon-button id="rename" width="64" height="64" icon="gui/gp_rename.png"
|
||||
I18N="Login dialog" text="Rename" label_location="bottom"/>
|
||||
|
||||
@@ -32,18 +32,18 @@
|
||||
<checkbox width="fit" id="remember-user" I18N="In the login screen" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label id="label_remember" proportion="1" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Remember password"/>
|
||||
I18N="In the user screen" text="Remember password"/>
|
||||
</div>
|
||||
<!-- Disable guest accounts for now
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_guest" proportion="1" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Guest login"/>
|
||||
<checkbox id="guest" I18N="In the login screen" text_align="left"/>
|
||||
I18N="In the user screen" text="Guest login"/>
|
||||
<checkbox id="guest" I18N="In the user screen" text_align="left"/>
|
||||
</div>
|
||||
-->
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_username" width="40%" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Username"/>
|
||||
I18N="In the user screen" text="Username"/>
|
||||
<textbox id="username" proportion="2" height="fit" I18N="In the registration dialog"/>
|
||||
</div>
|
||||
<spacer height="20" width="20"/>
|
||||
@@ -61,11 +61,11 @@
|
||||
<buttonbar id="options" width="90%" height="13%" align="center">
|
||||
<icon-button id="ok" width="64" height="64" icon="gui/green_check.png"
|
||||
I18N="Login dialog" text="OK" label_location="bottom"/>
|
||||
<icon-button id="new_user" width="64" height="64" icon="gui/gp_add_track.png"
|
||||
<icon-button id="new_user" width="64" height="64" icon="gui/blue_plus.png"
|
||||
I18N="Login dialog" text="Add user" label_location="bottom"/>
|
||||
<icon-button id="delete" width="64" height="64" icon="gui/gp_remove_track.png"
|
||||
<icon-button id="delete" width="64" height="64" icon="gui/remove.png"
|
||||
I18N="Login dialog" text="Delete" label_location="bottom"/>
|
||||
<icon-button id="rename" width="64" height="64" icon="gui/gp_rename.png"
|
||||
<icon-button id="rename" width="64" height="64" icon="gui/rename.png"
|
||||
I18N="Login dialog" text="Rename" label_location="bottom"/>
|
||||
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
|
||||
I18N="Login dialog" text="Cancel" label_location="bottom"/>
|
||||
|
||||
142
data/shaders/Lightspaceboundingbox.comp
Normal file
@@ -0,0 +1,142 @@
|
||||
uniform sampler2D depth;
|
||||
uniform float split0;
|
||||
uniform float split1;
|
||||
uniform float split2;
|
||||
uniform float splitmax;
|
||||
uniform mat4 SunCamMatrix;
|
||||
|
||||
layout (local_size_x = 8, local_size_y = 8) in;
|
||||
|
||||
struct CascadeBoundingBox
|
||||
{
|
||||
int xmin;
|
||||
int xmax;
|
||||
int ymin;
|
||||
int ymax;
|
||||
int zmin;
|
||||
int zmax;
|
||||
};
|
||||
|
||||
layout (std430) buffer BoundingBoxes
|
||||
{
|
||||
CascadeBoundingBox BB[4];
|
||||
};
|
||||
|
||||
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||
|
||||
shared int xmin[4];
|
||||
shared int xmax[4];
|
||||
shared int ymin[4];
|
||||
shared int ymax[4];
|
||||
shared int zmin[4];
|
||||
shared int zmax[4];
|
||||
|
||||
void main()
|
||||
{
|
||||
if (gl_LocalInvocationIndex < 4) {
|
||||
xmin[gl_LocalInvocationIndex] = ymin[gl_LocalInvocationIndex] = zmin[gl_LocalInvocationIndex] = 1000;
|
||||
xmax[gl_LocalInvocationIndex] = ymax[gl_LocalInvocationIndex] = zmax[gl_LocalInvocationIndex] = -1000;
|
||||
}
|
||||
|
||||
barrier();
|
||||
|
||||
ivec3 lmax0 = ivec3(-1000);
|
||||
ivec3 lmin0 = ivec3(1000);
|
||||
ivec3 lmax1 = ivec3(-1000);
|
||||
ivec3 lmin1 = ivec3(1000);
|
||||
ivec3 lmax2 = ivec3(-1000);
|
||||
ivec3 lmin2 = ivec3(1000);
|
||||
ivec3 lmax3 = ivec3(-1000);
|
||||
ivec3 lmin3 = ivec3(1000);
|
||||
|
||||
vec2 start_xy = gl_LocalInvocationID.xy + gl_WorkGroupID.xy * gl_WorkGroupSize.xy * 8;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
|
||||
|
||||
vec2 uv = (start_xy + vec2(i, j) * gl_WorkGroupID.xy) / screen;
|
||||
float z = texture(depth, uv).x;
|
||||
vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix);
|
||||
vec4 lightcoord = InverseViewMatrix * xpos;
|
||||
lightcoord /= lightcoord.w;
|
||||
lightcoord = SunCamMatrix * lightcoord;
|
||||
lightcoord /= lightcoord.w;
|
||||
ivec3 lc = ivec3(lightcoord.xyz) * 4;
|
||||
|
||||
if (xpos.z < split0) {
|
||||
lmax0 = max(lmax0, lc);
|
||||
lmin0 = min(lmin0, lc);
|
||||
} else if (xpos.z < split1) {
|
||||
lmax1 = max(lmax1, lc);
|
||||
lmin1 = min(lmin1, lc);
|
||||
} else if (xpos.z < split2) {
|
||||
lmax2 = max(lmax2, lc);
|
||||
lmin2 = min(lmin2, lc);
|
||||
} else if (xpos.z < splitmax) {
|
||||
lmax3 = max(lmax3, lc);
|
||||
lmin3 = min(lmin3, lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
atomicMax(xmax[0], lmax0.x);
|
||||
atomicMax(ymax[0], lmax0.y);
|
||||
atomicMax(zmax[0], lmax0.z);
|
||||
atomicMin(xmin[0], lmin0.x);
|
||||
atomicMin(ymin[0], lmin0.y);
|
||||
atomicMin(zmin[0], lmin0.z);
|
||||
|
||||
atomicMax(xmax[1], lmax1.x);
|
||||
atomicMax(ymax[1], lmax1.y);
|
||||
atomicMax(zmax[1], lmax1.z);
|
||||
atomicMin(xmin[1], lmin1.x);
|
||||
atomicMin(ymin[1], lmin1.y);
|
||||
atomicMin(zmin[1], lmin1.z);
|
||||
|
||||
atomicMax(xmax[2], lmax2.x);
|
||||
atomicMax(ymax[2], lmax2.y);
|
||||
atomicMax(zmax[2], lmax2.z);
|
||||
atomicMin(xmin[2], lmin2.x);
|
||||
atomicMin(ymin[2], lmin2.y);
|
||||
atomicMin(zmin[2], lmin2.z);
|
||||
|
||||
atomicMax(xmax[3], lmax3.x);
|
||||
atomicMax(ymax[3], lmax3.y);
|
||||
atomicMax(zmax[3], lmax3.z);
|
||||
atomicMin(xmin[3], lmin3.x);
|
||||
atomicMin(ymin[3], lmin3.y);
|
||||
atomicMin(zmin[3], lmin3.z);
|
||||
|
||||
barrier();
|
||||
|
||||
if (gl_LocalInvocationIndex == 0) {
|
||||
atomicMax(BB[0].xmax, xmax[0]);
|
||||
atomicMax(BB[0].ymax, ymax[0]);
|
||||
atomicMax(BB[0].zmax, zmax[0]);
|
||||
atomicMin(BB[0].xmin, xmin[0]);
|
||||
atomicMin(BB[0].ymin, ymin[0]);
|
||||
atomicMin(BB[0].zmin, zmin[0]);
|
||||
|
||||
atomicMax(BB[1].xmax, xmax[1]);
|
||||
atomicMax(BB[1].ymax, ymax[1]);
|
||||
atomicMax(BB[1].zmax, zmax[1]);
|
||||
atomicMin(BB[1].xmin, xmin[1]);
|
||||
atomicMin(BB[1].ymin, ymin[1]);
|
||||
atomicMin(BB[1].zmin, zmin[1]);
|
||||
|
||||
atomicMax(BB[2].xmax, xmax[2]);
|
||||
atomicMax(BB[2].ymax, ymax[2]);
|
||||
atomicMax(BB[2].zmax, zmax[2]);
|
||||
atomicMin(BB[2].xmin, xmin[2]);
|
||||
atomicMin(BB[2].ymin, ymin[2]);
|
||||
atomicMin(BB[2].zmin, zmin[2]);
|
||||
|
||||
atomicMax(BB[3].xmax, xmax[3]);
|
||||
atomicMax(BB[3].ymax, ymax[3]);
|
||||
atomicMax(BB[3].zmax, zmax[3]);
|
||||
atomicMin(BB[3].xmin, xmin[3]);
|
||||
atomicMin(BB[3].ymin, ymin[3]);
|
||||
atomicMin(BB[3].zmin, zmin[3]);
|
||||
}
|
||||
}
|
||||
|
||||
55
data/shaders/depthhistogram.comp
Normal file
@@ -0,0 +1,55 @@
|
||||
uniform sampler2D depth;
|
||||
|
||||
layout (local_size_x = 32, local_size_y = 32) in;
|
||||
|
||||
layout (std430) buffer Histogram
|
||||
{
|
||||
int bin[1024];
|
||||
int mindepth;
|
||||
int maxdepth;
|
||||
int count;
|
||||
};
|
||||
|
||||
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||
|
||||
shared int sbin[1024];
|
||||
shared int smindepth;
|
||||
shared int smaxdepth;
|
||||
shared int scount;
|
||||
|
||||
void main()
|
||||
{
|
||||
int x = int(gl_GlobalInvocationID.x), y = int(gl_GlobalInvocationID.y);
|
||||
vec2 uv = vec2(x, y) / screen;
|
||||
float z = texture(depth, uv).x;
|
||||
vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix);
|
||||
|
||||
int lineardepth = int(xpos.z * 4);
|
||||
|
||||
|
||||
sbin[gl_LocalInvocationIndex] = 0;
|
||||
if (gl_LocalInvocationIndex == 0) {
|
||||
smindepth = 1000;
|
||||
smaxdepth = 0;
|
||||
scount = 0;
|
||||
}
|
||||
|
||||
barrier();
|
||||
|
||||
if (lineardepth < 1000) {
|
||||
atomicAdd(sbin[lineardepth], 1);
|
||||
atomicAdd(scount, 1);
|
||||
atomicMin(smindepth, lineardepth);
|
||||
atomicMax(smaxdepth, lineardepth);
|
||||
}
|
||||
|
||||
barrier();
|
||||
|
||||
atomicAdd(bin[gl_LocalInvocationIndex], sbin[gl_LocalInvocationIndex]);
|
||||
if (gl_LocalInvocationIndex == 0) {
|
||||
atomicAdd(count, scount);
|
||||
atomicMin(mindepth, smindepth);
|
||||
atomicMax(maxdepth, smaxdepth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,10 +49,10 @@ void main(void)
|
||||
vec3 sampleDirection = reflect(-eyedir, normal);
|
||||
sampleDirection = (InverseViewMatrix * vec4(sampleDirection, 0.)).xyz;
|
||||
|
||||
float specval = texture(ntex, uv).z;
|
||||
float specval = pow(texture(ntex, uv).z, 2.);
|
||||
// From http://graphics.cs.williams.edu/papers/EnvMipReport2013/
|
||||
int texSize = textureSize(tex, 0).x;
|
||||
float lodval = clamp(log2(texSize * sqrt(3)) - .5 * log2(specval + 1), 0., 10.);
|
||||
float lodval = clamp(log2(texSize * sqrt(3.)) - .5 * log2(specval + 1.), 0., 10.);
|
||||
vec4 specular = textureLod(tex, sampleDirection, lodval);
|
||||
Spec = max(specular, vec4(0.));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
uniform sampler2D tex;
|
||||
uniform vec2 pixel;
|
||||
|
||||
float sigma = 1.;
|
||||
|
||||
// Gaussian separated blur with radius 6.
|
||||
|
||||
out vec4 FragColor;
|
||||
@@ -8,17 +10,22 @@ out vec4 FragColor;
|
||||
void main()
|
||||
{
|
||||
vec2 uv = gl_FragCoord.xy * pixel;
|
||||
vec4 sum = vec4(0.0);
|
||||
float X = uv.x;
|
||||
float Y = uv.y;
|
||||
|
||||
sum += texture(tex, vec2(X - 5.13333 * pixel.x, Y)) * 0.00640869;
|
||||
sum += texture(tex, vec2(X - 3.26667 * pixel.x, Y)) * 0.083313;
|
||||
sum += texture(tex, vec2(X - 1.4 * pixel.x, Y)) * 0.305481;
|
||||
sum += texture(tex, vec2(X, Y)) * 0.209473;
|
||||
sum += texture(tex, vec2(X + 1.4 * pixel.x, Y)) * 0.305481;
|
||||
sum += texture(tex, vec2(X + 3.26667 * pixel.x, Y)) * 0.083313;
|
||||
sum += texture(tex, vec2(X + 5.13333 * pixel.x, Y)) * 0.00640869;
|
||||
float g0, g1, g2;
|
||||
g0 = 1.0 / (sqrt(2.0 * 3.14) * sigma);
|
||||
g1 = exp(-0.5 / (sigma * sigma));
|
||||
g2 = g1 * g1;
|
||||
vec4 sum = texture(tex, vec2(X, Y)) * g0;
|
||||
g0 *= g1;
|
||||
g1 *= g2;
|
||||
for (int i = 1; i < 6; i++) {
|
||||
sum += texture(tex, vec2(X - i * pixel.x, Y)) * g0;
|
||||
sum += texture(tex, vec2(X + i * pixel.x, Y)) * g0;
|
||||
g0 *= g1;
|
||||
g1 *= g2;
|
||||
}
|
||||
|
||||
FragColor = sum;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
uniform sampler2D tex;
|
||||
uniform vec2 pixel;
|
||||
|
||||
float sigma = 1.;
|
||||
|
||||
// Gaussian separated blur with radius 6.
|
||||
|
||||
out vec4 FragColor;
|
||||
@@ -8,17 +10,22 @@ out vec4 FragColor;
|
||||
void main()
|
||||
{
|
||||
vec2 uv = gl_FragCoord.xy * pixel;
|
||||
vec4 sum = vec4(0.0);
|
||||
float X = uv.x;
|
||||
float Y = uv.y;
|
||||
|
||||
sum += texture(tex, vec2(X, Y - 5.13333 * pixel.y)) * 0.00640869;
|
||||
sum += texture(tex, vec2(X, Y - 3.26667 * pixel.y)) * 0.083313;
|
||||
sum += texture(tex, vec2(X, Y - 1.4 * pixel.y)) * 0.305481;
|
||||
sum += texture(tex, vec2(X, Y)) * 0.209473;
|
||||
sum += texture(tex, vec2(X, Y + 1.4 * pixel.y)) * 0.305481;
|
||||
sum += texture(tex, vec2(X, Y + 3.26667 * pixel.y)) * 0.083313;
|
||||
sum += texture(tex, vec2(X, Y + 5.13333 * pixel.y)) * 0.00640869;
|
||||
float g0, g1, g2;
|
||||
g0 = 1.0 / (sqrt(2.0 * 3.14) * sigma);
|
||||
g1 = exp(-0.5 / (sigma * sigma));
|
||||
g2 = g1 * g1;
|
||||
vec4 sum = texture(tex, vec2(X, Y)) * g0;
|
||||
g0 *= g1;
|
||||
g1 *= g2;
|
||||
for (int i = 1; i < 6; i++) {
|
||||
sum += texture(tex, vec2(X, Y - i * pixel.y)) * g0;
|
||||
sum += texture(tex, vec2(X, Y + i * pixel.y)) * g0;
|
||||
g0 *= g1;
|
||||
g1 *= g2;
|
||||
}
|
||||
|
||||
FragColor = sum;
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@ void main(void)
|
||||
vec4 col = texture(tex, uv);
|
||||
#endif
|
||||
if (col.a < 0.5) discard;
|
||||
FragColor = vec4(1.);
|
||||
FragColor = vec4(exp(8. * (2. * gl_FragCoord.z - 1.) / gl_FragCoord.w));
|
||||
}
|
||||
|
||||
6
data/shaders/shadow.frag
Normal file
@@ -0,0 +1,6 @@
|
||||
out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = vec4(exp(8. * (2. * gl_FragCoord.z - 1.) / gl_FragCoord.w));
|
||||
}
|
||||
16
data/shaders/shadowref.frag
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifdef GL_ARB_bindless_texture
|
||||
layout(bindless_sampler) uniform sampler2D tex;
|
||||
#else
|
||||
uniform sampler2D tex;
|
||||
#endif
|
||||
|
||||
in vec2 uv;
|
||||
in vec4 color;
|
||||
out vec4 FragColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 col = texture(tex, uv);
|
||||
if (col.a < 0.5) discard;
|
||||
FragColor = vec4(exp(8. * (2. * gl_FragCoord.z - 1.) / gl_FragCoord.w));
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
uniform sampler2D ntex;
|
||||
uniform sampler2D dtex;
|
||||
uniform sampler2DArrayShadow shadowtex;
|
||||
//uniform sampler2D warpx;
|
||||
///uniform sampler2D warpy;
|
||||
uniform sampler2DArray shadowtex;
|
||||
|
||||
uniform float split0;
|
||||
uniform float split1;
|
||||
uniform float split2;
|
||||
uniform float splitmax;
|
||||
|
||||
uniform vec3 direction;
|
||||
uniform vec3 col;
|
||||
//uniform int hasclouds;
|
||||
//uniform vec2 wind;
|
||||
//uniform float shadowoffset;
|
||||
|
||||
in vec2 uv;
|
||||
out vec4 Diff;
|
||||
@@ -20,8 +20,7 @@ vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||
|
||||
float getShadowFactor(vec3 pos, float bias, int index)
|
||||
{
|
||||
//float a[5] = float[](3.4, 4.2, 5.0, 5.2, 1.1);
|
||||
|
||||
|
||||
vec2 shadowoffset[4] = vec2[](
|
||||
vec2(-1., -1.),
|
||||
vec2(-1., 1.),
|
||||
@@ -30,25 +29,12 @@ float getShadowFactor(vec3 pos, float bias, int index)
|
||||
);
|
||||
|
||||
vec4 shadowcoord = (ShadowViewProjMatrixes[index] * InverseViewMatrix * vec4(pos, 1.0));
|
||||
shadowcoord /= shadowcoord.w;
|
||||
shadowcoord.xy /= shadowcoord.w;
|
||||
vec2 shadowtexcoord = shadowcoord.xy * 0.5 + 0.5;
|
||||
// shadowcoord = (shadowcoord * 0.5) + vec3(0.5);
|
||||
|
||||
// float movex = decdepth(texture(warpx, shadowcoord.xy));
|
||||
// float movey = decdepth(texture(warpy, shadowcoord.xy));
|
||||
// float dx = movex * 2.0 - 1.0;
|
||||
// float dy = movey * 2.0 - 1.0;
|
||||
// shadowcoord.xy += vec2(dx, dy);*/
|
||||
|
||||
//float shadowmapz = 2. * texture(shadowtex, vec3(shadowtexcoord, shadowcoord.z).x - 1.;
|
||||
// bias += smoothstep(0.001, 0.1, moved) * 0.014; // According to the warping
|
||||
float sum = 0.;
|
||||
for (float i = -1.5; i <= 1.5; i+= 1.)
|
||||
{
|
||||
for (float j = -1.5; j <= 1.5; j+= 1.)
|
||||
sum += texture(shadowtex, vec4(shadowtexcoord +vec2(i, j) / 1024., float(index), 0.5 * shadowcoord.z + 0.5));
|
||||
}
|
||||
return sum / 16.;
|
||||
float z = texture(shadowtex, vec3(shadowtexcoord, float(index))).x;
|
||||
float d = shadowcoord.z;
|
||||
return min(pow(exp(-8. * d) * z, 256.), 1.);
|
||||
}
|
||||
|
||||
void main() {
|
||||
@@ -70,86 +56,41 @@ void main() {
|
||||
|
||||
vec3 outcol = NdotL * col;
|
||||
|
||||
// if (hasclouds == 1)
|
||||
// {
|
||||
// vec2 cloudcoord = (xpos.xz * 0.00833333) + wind;
|
||||
// float cloud = texture(cloudtex, cloudcoord).x;
|
||||
// //float cloud = step(0.5, cloudcoord.x) * step(0.5, cloudcoord.y);
|
||||
|
||||
// outcol *= cloud;
|
||||
// }
|
||||
|
||||
// Shadows
|
||||
float bias = 0.005 * tan(acos(NdotL)); // According to the slope
|
||||
bias = clamp(bias, 0., 0.01);
|
||||
float factor;
|
||||
if (xpos.z < 5.)
|
||||
if (xpos.z < split0)
|
||||
factor = getShadowFactor(xpos.xyz, bias, 0);
|
||||
else if (xpos.z < 6.)
|
||||
/* else if (xpos.z < 6.)
|
||||
{
|
||||
float a = getShadowFactor(xpos.xyz, bias, 0), b = getShadowFactor(xpos.xyz, bias, 1);
|
||||
factor = mix(a, b, (xpos.z - 5.));
|
||||
}
|
||||
else if (xpos.z < 20.)
|
||||
}*/
|
||||
else if (xpos.z < split1)
|
||||
factor = getShadowFactor(xpos.xyz, bias, 1);
|
||||
else if (xpos.z < 21.)
|
||||
/* else if (xpos.z < 21.)
|
||||
{
|
||||
float a = getShadowFactor(xpos.xyz, bias, 1), b = getShadowFactor(xpos.xyz, bias, 2);
|
||||
factor = mix(a, b, (xpos.z - 20.));
|
||||
}
|
||||
else if (xpos.z < 50.)
|
||||
}*/
|
||||
else if (xpos.z < split2)
|
||||
factor = getShadowFactor(xpos.xyz, bias, 2);
|
||||
else if (xpos.z < 55.)
|
||||
/* else if (xpos.z < 55.)
|
||||
{
|
||||
float a = getShadowFactor(xpos.xyz, bias, 2), b = getShadowFactor(xpos.xyz, bias, 3);
|
||||
factor = mix(a, b, (xpos.z - 50.) / 5.);
|
||||
}
|
||||
else if (xpos.z < 145.)
|
||||
}*/
|
||||
else if (xpos.z < splitmax)
|
||||
factor = getShadowFactor(xpos.xyz, bias, 3);
|
||||
else if (xpos.z < 150.)
|
||||
/* else if (xpos.z < 150.)
|
||||
{
|
||||
factor = mix(getShadowFactor(xpos.xyz, bias, 3), 1., (xpos.z - 145.) / 5.);
|
||||
}
|
||||
}*/
|
||||
else
|
||||
factor = 1.;
|
||||
Diff = vec4(factor * NdotL * col, 1.);
|
||||
Spec = vec4(factor * Specular, 1.);
|
||||
return;
|
||||
|
||||
// float moved = (abs(dx) + abs(dy)) * 0.5;
|
||||
|
||||
// float avi = 0.002;
|
||||
// float abi = 0.0025;
|
||||
|
||||
/* float avi = 0.0018;
|
||||
float abi = 0.002;
|
||||
|
||||
float bias = avi * tan(acos(NdotL)); // According to the slope
|
||||
bias += smoothstep(0.001, 0.1, moved) * abi; // According to the warping
|
||||
bias = clamp(bias, 0.001, abi);
|
||||
|
||||
// This ID, and four IDs around this must match for a shadow pixel
|
||||
float right = texture(shadowtex, shadowcoord.xy + vec2(shadowoffset, 0.0)).a;
|
||||
float left = texture(shadowtex, shadowcoord.xy + vec2(-shadowoffset, 0.0)).a;
|
||||
float up = texture(shadowtex, shadowcoord.xy + vec2(0.0, shadowoffset)).a;
|
||||
float down = texture(shadowtex, shadowcoord.xy + vec2(0.0, -shadowoffset)).a;
|
||||
|
||||
float matching = ((right + left + up + down) * 0.25) - shadowread.a;
|
||||
matching = abs(matching) * 400.0;
|
||||
|
||||
// If the ID is different, we're likely in shadow - cut the bias to cut peter panning
|
||||
float off = 7.0 - step(abs(shadowread.a - depthread.a) - matching, 0.004) * 6.0;
|
||||
bias /= off;
|
||||
|
||||
const float softness = 8.0; // How soft is the light?
|
||||
float shadowed = step(shadowmapz + bias, shadowcoord.z);
|
||||
float dist = (shadowcoord.z / shadowmapz) - 1.0;
|
||||
float penumbra = dist * softness / gl_FragCoord.z;
|
||||
penumbra *= shadowed;*/
|
||||
|
||||
/* outcol.r = (shadowcoord.z - shadowmapz) * 50.0;
|
||||
outcol.g = moved;*/
|
||||
|
||||
// FragColor = vec4(outcol, 0.05);
|
||||
// OtherOutput = vec4(shadowed, penumbra, shadowed, shadowed);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ uniform sampler2D tex;
|
||||
uniform sampler2D logluminancetex;
|
||||
uniform float exposure = .09;
|
||||
uniform float Lwhite = 1.;
|
||||
uniform float vignette_weight = 0.;
|
||||
uniform float vignette_weight;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
</grand-prix>
|
||||
|
||||
<!-- Time in follow-the-leader after which karts are removed.
|
||||
The last values applies for all remaining karts.
|
||||
The last values applies for all remaining karts.
|
||||
time-per-kart Additional time added to the interval
|
||||
for each kart in the race. -->
|
||||
<follow-the-leader intervals="30 20 10"
|
||||
time-per-kart="1.5" />
|
||||
|
||||
<!-- Startup information.
|
||||
<!-- Startup information.
|
||||
Penalty: Penalty time if a kart accelerates before GO. -->
|
||||
<startup penalty="1" />
|
||||
|
||||
@@ -74,11 +74,11 @@
|
||||
|
||||
<!-- Skidmark data: maximum number of skid marks, and
|
||||
time for skidmarks to fade out. -->
|
||||
<skid-marks max-number="100" fadeout-time="60"/>
|
||||
|
||||
<!-- Defines when the upright constraint should be acctive, it's
|
||||
<skid-marks max-number="100" fadeout-time="60"/>
|
||||
|
||||
<!-- Defines when the upright constraint should be active, it's
|
||||
disabled when the kart is more than this value from the track. -->
|
||||
<near-ground distance="2"/>
|
||||
<near-ground distance="2"/>
|
||||
|
||||
<!-- How long the end animation will be shown. -->
|
||||
<delay-finish time="0.5"/>
|
||||
@@ -99,16 +99,16 @@
|
||||
need to be lost.
|
||||
ubound-fraction is the upper bound fraction of speed when lost will
|
||||
detach parachute. E.g. at max-speed 30% of speed must be lost.
|
||||
max-speed is a factor that decides the impact of rate of speed
|
||||
max-speed is a factor that decides the impact of rate of speed
|
||||
(distance between bounds) -->
|
||||
<parachute friction="2.0" time="4.0" time-other="8.0"
|
||||
<parachute friction="2.0" time="4.0" time-other="8.0"
|
||||
lbound-fraction="0.95" ubound-fraction="0.7" max-speed="23"/>
|
||||
|
||||
<!-- time is the time till a bomb explodes. time-increase is the time added
|
||||
<!-- time is the time till a bomb explodes. time-increase is the time added
|
||||
to timer when bomb is passed on. -->
|
||||
<bomb time="30.0" time-increase="-5.0"/>
|
||||
|
||||
<!-- Powerup collect-mode decides what is collected if a kart has already an
|
||||
<!-- Powerup collect-mode decides what is collected if a kart has already an
|
||||
powerup: same: get one more item of the same type.
|
||||
new: always get a new item.
|
||||
only-if-same: if the random item is the same one as the
|
||||
@@ -121,9 +121,9 @@
|
||||
nolok-bubble-gum, easter egg -->
|
||||
<switch time="5" items="1 0 4 4 2 5 2 7"/>
|
||||
|
||||
<!-- disappear-counter: How often bubblegum gets driven over before it disappears.
|
||||
shield-time: How long the bubblegum shield lasts
|
||||
restrict-weapons: If true, using weapons will destroy the user's shield -->
|
||||
<!-- disappear-counter: How often bubblegum gets driven over before it disappears.
|
||||
shield-time: How long the bubblegum shield lasts
|
||||
restrict-weapons: If true, using weapons will destroy the user's shield -->
|
||||
<bubblegum disappear-counter="1" shield-time="10.0" restrict-weapons="false"/>
|
||||
|
||||
<!-- explosion-impulse-objects is the impulse that pushes physical objects
|
||||
@@ -134,10 +134,10 @@
|
||||
work anymore - so for now don't enable this. -->
|
||||
<networking enable="false"/>
|
||||
|
||||
<!-- disable-while-unskid: Disable steering when stop skidding during
|
||||
<!-- disable-while-unskid: Disable steering when stop skidding during
|
||||
the time it takes to adjust the physical body with the graphics.
|
||||
camera-follow-skid: If true the camera will stay behind the kart,
|
||||
potentially making it easier to see where the kart is going to
|
||||
potentially making it easier to see where the kart is going to
|
||||
after a skid. -->
|
||||
<steer disable-while-unskid="false"
|
||||
camera-follow-skid="true" />
|
||||
@@ -145,23 +145,31 @@
|
||||
<!-- Default values for all karts
|
||||
============================ -->
|
||||
<general-kart-defaults>
|
||||
|
||||
<!-- Camera: Distance between kart and camera.
|
||||
forward-up-angle: Angle between camera and plane of kart (pitch)
|
||||
|
||||
<!-- Camera: Distance between kart and camera.
|
||||
forward-up-angle: Angle between camera and plane of kart (pitch)
|
||||
when the camera is pointing forward
|
||||
backward-up-angke: Angle between camera and plane of kart (pitch)
|
||||
when the camera is pointing backwards. This is usually
|
||||
backward-up-angle: Angle between camera and plane of kart (pitch)
|
||||
when the camera is pointing backwards. This is usually
|
||||
larger than the forward-up-angle, since the kart itself
|
||||
otherwise obstricts too much of the view. -->
|
||||
<camera distance="1.0" forward-up-angle="15"
|
||||
backward-up-angle="5"/>
|
||||
<!-- Additional offset to move graphical chassis with regards to the physics. -->
|
||||
<graphics y-offset="0.0"/>
|
||||
<!-- Options to affect the graphical chassis:
|
||||
y-offset: Additional offset to move graphical chassis with regards
|
||||
to the physics, used to reduce frequencey of graphical
|
||||
chassis in terrain.
|
||||
prevent-chassis-in-terrain: a hard flag to prevent nearly all instances
|
||||
of chassis in terrain. Can (atm) cause some stuttering. -->
|
||||
<graphics y-offset="0.0"
|
||||
prevent-chassis-in-terrain="true"
|
||||
/>
|
||||
|
||||
<!-- Jump animation related values:
|
||||
animation-time: only if the estimated time for a jump is larger
|
||||
than this value will the jump animation being shown. -->
|
||||
<jump animation-time="0.5" />
|
||||
<!-- Jump animation related values:
|
||||
animation-time: only if the estimated time for a jump is larger
|
||||
than this value will the jump animation being
|
||||
shown. -->
|
||||
<jump animation-time="0.5" />
|
||||
|
||||
<!-- Skidding: increase: multiplicative increase of skidding factor in each frame.
|
||||
decrease: multiplicative decrease of skidding factor in each frame.
|
||||
@@ -182,16 +190,16 @@
|
||||
bonus-force: Additional engine force (this is used to offset the fact
|
||||
that turning after skidding (e.g. to correct direction) often uses
|
||||
up the skid bonus).
|
||||
post-skid-rotate-factor: a factor to be used to determine how much
|
||||
the chassis of a kart should rotate to match the graphical view.
|
||||
post-skid-rotate-factor: a factor to be used to determine how much
|
||||
the chassis of a kart should rotate to match the graphical view.
|
||||
A factor of 1 is identical, a smaller factor will rotate the kart
|
||||
less (which might feel better).
|
||||
less (which might feel better).
|
||||
physical-jump-time: Time for a physical jump at the beginning of a skid.
|
||||
graphical-jump-time: Time for a graphics-only jump at the beginning
|
||||
of a skid.
|
||||
reduce-turn-min/max: The steering done by the controller (which is in
|
||||
[-1,1]) is mapped to [reduce-turn-min, reduce-turn-max] when skidding
|
||||
is active (for left turn, right turn will use [-max, -min]). The
|
||||
is active (for left turn, right turn will use [-max, -min]). The
|
||||
effect is that while you skid (say left) you can adjust the direction
|
||||
of the turn the kart is doing somewhat by steering to the left and right,
|
||||
but you will always keep on doing a left turn, just more or less. -->
|
||||
@@ -222,12 +230,12 @@
|
||||
max-item-angle: Items that would need more than this change in
|
||||
direction are not considered for collection.
|
||||
time-full-steer is the time for the AI to go from neutral steering to
|
||||
extreme left (or right). This can be used to reduce
|
||||
extreme left (or right). This can be used to reduce
|
||||
'shaking' of AI karts caused by changing steering direction
|
||||
too often. It also helps with making it easier to push the
|
||||
AI karts (otherwise micro-corrections make this nearly
|
||||
impossible). A value of 1/maxFPS / 2 will guarantee that
|
||||
the wheel can go from -1 to +1 steering in one frame,
|
||||
the wheel can go from -1 to +1 steering in one frame,
|
||||
basically disabling this mechanism.
|
||||
bad-item-closeness is the maximum distance between a good and a
|
||||
bad item which can force the AI to abandon a good item in order
|
||||
@@ -238,7 +246,7 @@
|
||||
section of the track should have in order to activate a zipper.
|
||||
|
||||
competitive when ahead of the player, or more competitive
|
||||
when behind the player.
|
||||
when behind the player.
|
||||
|
||||
skid-probability: Since the AI is usually very good at using
|
||||
skidding, this is used to implement some rubber-banding for
|
||||
@@ -259,7 +267,7 @@
|
||||
the speed the kart can drive at!
|
||||
collect-item-probability: Probability of the AI actually
|
||||
trying to collect an item (if an item is selected for
|
||||
collection in the first place).
|
||||
collection in the first place).
|
||||
-->
|
||||
<ai>
|
||||
<easy time-full-steer="0.1"
|
||||
@@ -335,11 +343,52 @@
|
||||
skidding-threshold="2.0"
|
||||
/>
|
||||
</ai>
|
||||
|
||||
|
||||
<!-- The per-player difficulties in multiplayer games.
|
||||
These values are multiplied with the current values of a car
|
||||
so 1 means that nothing changes.
|
||||
The meaning of the different values is explained below this tag. -->
|
||||
<difficulties>
|
||||
<normal>
|
||||
<mass value="1.0"/>
|
||||
<engine brake-factor="1.0" brake-time-increase="1.0" max-speed-reverse-ratio="1.0" power="1.0" max-speed="1.0"/>
|
||||
<nitro consumption="1.0" max-speed-increase="1.0" duration="1.0" fade-out-time="1.0"/>
|
||||
<bubblegum time="1.0" speed-fraction="1.0" torque="1.0" fade-in-time="1.0"/>
|
||||
<rescue time="1.0"/>
|
||||
<explosion time="1.0" radius="1.0" invulnerability-time="1.0"/>
|
||||
<slipstream length="1.0" width="1.0" collect-time="1.0" use-time="1.0"
|
||||
add-power="1.0" min-speed="1.0" max-speed-increase="1.0" duration="1.0"
|
||||
fade-out-time="1.0"/>
|
||||
<plunger band-max-length="1.0" band-force="1.0" band-duration="1.0"
|
||||
band-speed-increase="1.0" band-fade-out-time="1.0" in-face-time="1.0"/>
|
||||
<zipper time="1.0" force="1.0" speed-gain="1.0" max-speed-increase="1.0"
|
||||
fade-out-time="1.0"/>
|
||||
<swatter duration="1.0" squash-duration="1.0" squash-slowdown="1.0"/>
|
||||
<startup time="1.0 1.0" boost="1.0 1.0"/>
|
||||
</normal>
|
||||
<handicap>
|
||||
<mass value="1.0"/>
|
||||
<engine brake-factor="0.8" brake-time-increase="0.85" max-speed-reverse-ratio="0.8" power="0.8" max-speed="0.8"/>
|
||||
<nitro consumption="1.1" max-speed-increase="0.9" duration="1.0" fade-out-time="1.0"/>
|
||||
<bubblegum time="1.5" speed-fraction="1.5" torque="1.5" fade-in-time="1.0"/>
|
||||
<rescue time="1.5"/>
|
||||
<explosion time="1.3" invulnerability-time="0.7"/>
|
||||
<slipstream length="0.8" width="0.8" collect-time="1.5" use-time="0.8"
|
||||
add-power="0.8" min-speed="0.8" max-speed-increase="0.9" duration="0.8"
|
||||
fade-out-time="1.0"/>
|
||||
<plunger band-max-length="0.8" band-force="1.0" band-duration="1.0"
|
||||
band-speed-increase="0.8" band-fade-out-time="1.0" in-face-time="1.3"/>
|
||||
<zipper time="0.8" force="0.8" speed-gain="0.8" max-speed-increase="0.8"
|
||||
fade-out-time="1.0"/>
|
||||
<swatter duration="0.8" squash-duration="1.5" squash-slowdown="1.8"/>
|
||||
<startup time="0.8 0.8" boost="0.8 0.8"/>
|
||||
</handicap>
|
||||
</difficulties>
|
||||
|
||||
<!-- Suspension related values. stiffness: kart's suspension stiffness.
|
||||
rest: Length of suspension when at rest.
|
||||
travel-cm: maximum movement of suspension - in cm!!
|
||||
exp-string-response: dampen the suspension spring reaction
|
||||
rest: Length of suspension when at rest.
|
||||
travel-cm: maximum movement of suspension - in cm!!
|
||||
exp-string-response: dampen the suspension spring reaction
|
||||
exponentially.
|
||||
max-force: Maximum suspension force -->
|
||||
<suspension stiffness="140" rest="0.3" travel-cm="29"
|
||||
@@ -347,9 +396,9 @@
|
||||
|
||||
<!-- Wheel related parameters: damping-relaxation/compression: for
|
||||
bullet, damping parameters. Radius and width of wheel.
|
||||
front-right, front-left, rear-right and rear-left give the
|
||||
front-right, front-left, rear-right and rear-left give the
|
||||
position of the physics raycast wheels relative to the center of
|
||||
gravity. Default is to use the corners of the chassis to attach
|
||||
gravity. Default is to use the corners of the chassis to attach
|
||||
the wheels to. -->
|
||||
<wheels damping-relaxation="35" damping-compression="5" radius="0.25">
|
||||
<front-right position="0.38 0 0.6" />
|
||||
@@ -357,20 +406,20 @@
|
||||
<rear-right position="0.38 0 -0.6" />
|
||||
<rear-left position="-0.38 0 -0.6"/>
|
||||
</wheels>
|
||||
|
||||
|
||||
<!-- Parameters for the speed-weighted objects:
|
||||
a bigger value for strength-factor leads to the speed of the kart more quickly affecting
|
||||
the strength of the animation (up to a maximum value that corresponds to the original animation) -->
|
||||
<speed-weighted-objects strength-factor="0.05" speed-factor="1.0" texture-speed-x="0.0" texture-speed-y="0.0"/>
|
||||
|
||||
<!-- friction: slip used for bullet skidding. A high value
|
||||
<!-- friction: slip used for bullet skidding. A high value
|
||||
(like 10000000) disables bullet skidding. -->
|
||||
<friction slip="10000000"/>
|
||||
|
||||
<!-- Values related to stability of the chassis: damping, and reduced
|
||||
impact of roll.
|
||||
impact of roll.
|
||||
downward-impulse-factor: A speed proportional impulse applied each
|
||||
frame that pushes the vehicle onto the ground.
|
||||
frame that pushes the vehicle onto the ground.
|
||||
track-connection-accel: An artificial force that pulls a wheel to
|
||||
the ground if its off ground. Reduces the affect if a kart loses
|
||||
contact with the ground (i.e. it then can't steer or accelerate
|
||||
@@ -391,7 +440,7 @@
|
||||
'normal': impulse along the normal
|
||||
'driveline': impulse towards the nearest driveline.
|
||||
An impulse towards the driveline works nice when the kart is
|
||||
driving more or less correctly on the track - it pushes the
|
||||
driving more or less correctly on the track - it pushes the
|
||||
kart in the right direction. But if the kart is significanlty
|
||||
off track, it has severe problems (since an incorrect
|
||||
driveline point can be selected, pusing the kart in the
|
||||
@@ -403,15 +452,15 @@
|
||||
period, which results in less abrupt changes. If set to 0,
|
||||
the impulse is only applied once.
|
||||
resitution: restitution value to be used for the kart rigid bodies.
|
||||
bevel-factor: for each point of the chassis collision box one
|
||||
bevel-factor: for each point of the chassis collision box one
|
||||
additional point is added, resulting in a bevelled box shape.
|
||||
The original Z coordinate of the chassis is multiplied by
|
||||
The original Z coordinate of the chassis is multiplied by
|
||||
1-bevelZ (i.e. the main box part of the shape is shortened).
|
||||
The bevel point has the original Z coordinate, and the X and
|
||||
Y coordinates of the box are multiplied with (1-bevelX) and
|
||||
The bevel point has the original Z coordinate, and the X and
|
||||
Y coordinates of the box are multiplied with (1-bevelX) and
|
||||
(1-bevelY). A value of 0 for all bevel coordinates disables
|
||||
bevelling, and uses a simple box shape.
|
||||
As an example, a value of 1 for x and z will result in a
|
||||
As an example, a value of 1 for x and z will result in a
|
||||
sharp 'arrow' like shape.
|
||||
physical-wheel-position: Defines where the 'physical' (raycast)
|
||||
wheel will be located. It's a weight factor with 0 = being
|
||||
@@ -420,7 +469,7 @@
|
||||
physics settings are used which places the raycast wheels
|
||||
outside of the chassis and results in more stable physical
|
||||
behaviour of the karts. -->
|
||||
<collision impulse-type="normal"
|
||||
<collision impulse-type="normal"
|
||||
impulse="3000" impulse-time="0.1" terrain-impulse="1600"
|
||||
restitution="1.0" bevel-factor="0.5 0.0 0.7"
|
||||
physical-wheel-position="-1" />
|
||||
@@ -428,131 +477,131 @@
|
||||
<!-- If a kart starts within the specified time after 'go',
|
||||
it receives the corresponding bonus from 'boost'. Those
|
||||
fields must have the same size, and must be sorted by
|
||||
increasing times. -->
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "6 3" />
|
||||
|
||||
increasing times. -->
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "6 3" />
|
||||
|
||||
<!-- Rescue: time: How long it takes the kart to be raised.
|
||||
height: how height the kart will be raised before it is
|
||||
dropped back onto the track.
|
||||
dropped back onto the track.
|
||||
vert rescue offset: used to raise karts a bit higher before
|
||||
releasing them on the ground after a rescue. Used to avoid
|
||||
resetting karts into the track. Not sure if this is still
|
||||
necessary. -->
|
||||
<rescue vert-offset="0.0" time="1.2" height="2"/>
|
||||
|
||||
<rescue vert-offset="0.0" time="1.2" height="2"/>
|
||||
|
||||
<!-- Nitro: engine-force: additional engine power
|
||||
consumption: nitro consumption - heavier characters can be set
|
||||
to need more nitro than lighter character.
|
||||
small-container: how much energy a small container gives.
|
||||
big-container: how much energy a big container gives.
|
||||
big-container: how much energy a big container gives.
|
||||
max-speed-increase: How much the speed of a kart might exceed
|
||||
its maximum speed (in m/s).
|
||||
its maximum speed (in m/s).
|
||||
duration: How long the increased speed will be valid after
|
||||
the kart stops using nitro (and the fade-out-time starts).
|
||||
fade-out-time: Duration during which the increased maximum
|
||||
speed due to nitro fades out.
|
||||
speed due to nitro fades out.
|
||||
max: How much nitro a kart can store.
|
||||
-->
|
||||
<nitro engine-force="500" consumption="1" small-container="1" big-container="3"
|
||||
max-speed-increase="5" duration="1" fade-out-time="2" max="20"/>
|
||||
|
||||
<nitro engine-force="500" consumption="1" small-container="1" big-container="3"
|
||||
max-speed-increase="5" duration="1" fade-out-time="2" max="20"/>
|
||||
|
||||
<!-- Bubble gum data:
|
||||
time: How long the bubblegum lasts.
|
||||
speed-fraction: To what fraction of top-speed the speed is reduced.
|
||||
torque: To rotate the kart somewhat.
|
||||
fade-in-time: How quick the slowdown takes effect.
|
||||
-->
|
||||
<bubblegum time="1" speed-fraction="0.3" torque="500" fade-in-time="0.01"/>
|
||||
|
||||
|
||||
<!-- time: Time a zipper is active.
|
||||
force: Additional zipper force.
|
||||
<bubblegum time="1" speed-fraction="0.3" torque="500" fade-in-time="0.01"/>
|
||||
|
||||
|
||||
<!-- time: Time a zipper is active.
|
||||
force: Additional zipper force.
|
||||
speed-gain: One time additional speed.
|
||||
max-speed-increase: Additional speed allowed on top of the
|
||||
kart-specific maximum kart speed.
|
||||
fade-out-time: determines how long it takes for a zipper
|
||||
max-speed-increase: Additional speed allowed on top of the
|
||||
kart-specific maximum kart speed.
|
||||
fade-out-time: determines how long it takes for a zipper
|
||||
to fade out (after 'time').
|
||||
-->
|
||||
<zipper time="3.5" force="250.0" speed-gain="4.5" max-speed-increase="15"
|
||||
fade-out-time="1.0" />
|
||||
<zipper time="3.5" force="250.0" speed-gain="4.5" max-speed-increase="15"
|
||||
fade-out-time="1.0" />
|
||||
|
||||
<!-- Skidding: increase: multiplicative increase of skidding factor in each frame.
|
||||
decrease: multiplicative decrease of skidding factor in each frame.
|
||||
max: maximum skidding factor = maximum increase of steering angle.
|
||||
time-till-max: Time till maximum skidding is reached.
|
||||
visual: Additional graphical rotation of kart. The graphical rotation
|
||||
of the kart also determines the direction the kart is driving to
|
||||
when skidding is stopped.
|
||||
visual-time: How long it takes for the visual skid to reach maximum.
|
||||
revert-visual-time: how long it takes when stopping a skid to revert
|
||||
the visual skid and bring visuals and physics in sync again.
|
||||
angular-velocity: Angular velocity to be used for the kart when skidding.
|
||||
min-speed: Minimum speed a kart must have before it can skid. Must be
|
||||
>0, otherwise the kart can skid at the start of the race.
|
||||
time-till-bonus: How long a kart needs to skid in order to get a bonus.
|
||||
bonus-force: A speedup applied to the kart whick skidded for a while.
|
||||
bonus-time: How long the bonus-force is applied.
|
||||
bonus-force: Additional engine force (this is used to offset the fact
|
||||
that turning after skidding (e.g. to correct direction) often uses
|
||||
up the skid bonus).
|
||||
post-skid-rotate-factor: a factor to be used to determine how much
|
||||
the chassis of a kart should rotate to match the graphical view.
|
||||
A factor of 1 is identical, a smaller factor will rotate the kart
|
||||
less (which might feel better).
|
||||
physical-jump-time: Time for a physical jump at the beginning of a skid.
|
||||
graphical-jump-time: Time for a graphics-only jump at the beginning
|
||||
of a skid.
|
||||
reduce-turn-min/max: The steering done by the controller (which is in
|
||||
[-1,1]) is mapped to [reduce-turn-min, reduce-turn-max] when skidding
|
||||
is active (for left turn, right turn will use [-max, -min]). The
|
||||
effect is that while you skid (say left) you can adjust the direction
|
||||
of the turn the kart is doing somewhat by steering to the left and right,
|
||||
but you will always keep on doing a left turn, just more or less. -->
|
||||
<!-- Skidding: increase: multiplicative increase of skidding factor in each frame.
|
||||
decrease: multiplicative decrease of skidding factor in each frame.
|
||||
max: maximum skidding factor = maximum increase of steering angle.
|
||||
time-till-max: Time till maximum skidding is reached.
|
||||
visual: Additional graphical rotation of kart. The graphical rotation
|
||||
of the kart also determines the direction the kart is driving to
|
||||
when skidding is stopped.
|
||||
visual-time: How long it takes for the visual skid to reach maximum.
|
||||
revert-visual-time: how long it takes when stopping a skid to revert
|
||||
the visual skid and bring visuals and physics in sync again.
|
||||
angular-velocity: Angular velocity to be used for the kart when skidding.
|
||||
min-speed: Minimum speed a kart must have before it can skid. Must be
|
||||
>0, otherwise the kart can skid at the start of the race.
|
||||
time-till-bonus: How long a kart needs to skid in order to get a bonus.
|
||||
bonus-force: A speedup applied to the kart whick skidded for a while.
|
||||
bonus-time: How long the bonus-force is applied.
|
||||
bonus-force: Additional engine force (this is used to offset the fact
|
||||
that turning after skidding (e.g. to correct direction) often uses
|
||||
up the skid bonus).
|
||||
post-skid-rotate-factor: a factor to be used to determine how much
|
||||
the chassis of a kart should rotate to match the graphical view.
|
||||
A factor of 1 is identical, a smaller factor will rotate the kart
|
||||
less (which might feel better).
|
||||
physical-jump-time: Time for a physical jump at the beginning of a skid.
|
||||
graphical-jump-time: Time for a graphics-only jump at the beginning
|
||||
of a skid.
|
||||
reduce-turn-min/max: The steering done by the controller (which is in
|
||||
[-1,1]) is mapped to [reduce-turn-min, reduce-turn-max] when skidding
|
||||
is active (for left turn, right turn will use [-max, -min]). The
|
||||
effect is that while you skid (say left) you can adjust the direction
|
||||
of the turn the kart is doing somewhat by steering to the left and right,
|
||||
but you will always keep on doing a left turn, just more or less. -->
|
||||
<skid increase="1.05" decrease="0.95" max="2.5" time-till-max="0.5"
|
||||
visual="1.25" visual-time="0.7" revert-visual-time="0.7"
|
||||
min-speed="10" time-till-bonus="1.0 3.0"
|
||||
bonus-speed="4.5 6.5" bonus-time="3.0 4.0"
|
||||
bonus-force="250 350"
|
||||
physical-jump-time="0" graphical-jump-time="0.4"
|
||||
post-skid-rotate-factor="1"
|
||||
reduce-turn-min="0.2" reduce-turn-max="0.8"/>
|
||||
|
||||
|
||||
visual="1.25" visual-time="0.7" revert-visual-time="0.7"
|
||||
min-speed="10" time-till-bonus="1.0 3.0"
|
||||
bonus-speed="4.5 6.5" bonus-time="3.0 4.0"
|
||||
bonus-force="250 350"
|
||||
physical-jump-time="0" graphical-jump-time="0.4"
|
||||
post-skid-rotate-factor="1"
|
||||
reduce-turn-min="0.2" reduce-turn-max="0.8"/>
|
||||
|
||||
|
||||
<!-- Slipstream: length: How far behind a kart slipstream works
|
||||
width: how wide slipstream works furthest away from the kart.
|
||||
collect-time: How many seconds of sstream give maximum benefit
|
||||
use-time: How long the benefit will last.
|
||||
add-power: Additional power due to sstreaming. 1 = +100%
|
||||
min-speed: Minimum speed necessary for slipstream to take effect.
|
||||
min-speed: Minimum speed necessary for slipstream to take effect.
|
||||
max-speed-increase: How much the speed of the kart might exceed
|
||||
its normal maximum speed.
|
||||
duration: How long the higher speed lasts after slipstream stopped
|
||||
working.
|
||||
fade-out-time: How long the slip stream speed increase will
|
||||
fade-out-time: How long the slip stream speed increase will
|
||||
gradually be reduced. -->
|
||||
|
||||
<slipstream length="10" width="2" collect-time="2" use-time="5"
|
||||
add-power="3" min-speed="10"
|
||||
max-speed-increase="5" duration="1" fade-out-time="2"/>
|
||||
|
||||
|
||||
<slipstream length="10" width="2" collect-time="2" use-time="5"
|
||||
add-power="3" min-speed="10"
|
||||
max-speed-increase="5" duration="1" fade-out-time="2"/>
|
||||
|
||||
|
||||
<!-- Kart-specific settings for the swatter:
|
||||
duration: how long can the swatter be active.
|
||||
distance: How close a kart or an item must be before it can be hit.
|
||||
squash-duration: How long a kart will remain squashed.
|
||||
squash-slowdown: percentage of max speed that a kart is
|
||||
restricted to. -->
|
||||
<swatter duration="10" distance="3" squash-duration="5"
|
||||
squash-slowdown="0.5"/>
|
||||
|
||||
<swatter duration="10" distance="3" squash-duration="5"
|
||||
squash-slowdown="0.5"/>
|
||||
|
||||
<!-- Leaning related parameters, i.e. slightly leaning the karts when
|
||||
driving a fast curve.
|
||||
max: maximum leaning (i.e. when steering as much as possible at highest
|
||||
speed), in degrees.
|
||||
sped: Speed with which the leaning changes (in degree/second). -->
|
||||
<lean max="8.6" speed="5.0" />
|
||||
|
||||
|
||||
<!-- turn-radius defines the turn radius of the kart at
|
||||
a given speed. The actual steering angle is dependent on the
|
||||
wheel base of the kart: radius = wheel_base/sin(steering_angle).
|
||||
@@ -574,14 +623,14 @@
|
||||
0.5 * 0.25 + 0.5 * 0.15 = 0.2 ... which is overall the same
|
||||
time we had previously.
|
||||
-->
|
||||
<turn turn-radius="0:2.0 10:7.5 25:15 45:30"
|
||||
time-full-steer ="0:0.15 0.5:0.15 0.5:0.25 1.0:0.25"
|
||||
time-reset-steer="0.1" />
|
||||
|
||||
<!-- Speed and acceleration related values: power and max-speed (in m/s)
|
||||
<turn turn-radius="0:2.0 10:7.5 25:15 45:30"
|
||||
time-full-steer ="0:0.15 0.5:0.15 0.5:0.25 1.0:0.25"
|
||||
time-reset-steer="0.1" />
|
||||
|
||||
<!-- Speed and acceleration related values: power and max-speed (in m/s)
|
||||
have 3 values, one for low, medium, and hard.
|
||||
brake-factor: Value used when braking.
|
||||
brake-time-increase: The brake force is multiplied by
|
||||
brake-time-increase: The brake force is multiplied by
|
||||
(1+brake_time*brake_time_increase - i.e. the longer the brake was
|
||||
pressed, the harder the kart will brake.
|
||||
max-speed-reverse-ratio is the percentage of max speed for reverse gear.
|
||||
@@ -592,117 +641,117 @@
|
||||
|
||||
<!-- Simulated gears: switch-ratio defines at what ratio of the maximum
|
||||
speed what gear is selected, e.g. 0.25 means that if the speed is
|
||||
bigger or equal to 0.25 x maxSpeed then use gear 1, 0.5 means if
|
||||
bigger or equal to 0.25 x maxSpeed then use gear 1, 0.5 means if
|
||||
the speed is bigger or equal to 0.5 x maxSpeed then gear 2.
|
||||
gear-power-increase contains the increase in max power (to simulate
|
||||
different gears), e.g. 2.5 as first entry means: 2.5*maxPower in gear 1
|
||||
| first | second | third | . -->
|
||||
<gear switch-ratio="0.25 0.7 1.0" power-increase="2.2 1.7 1.3"/>
|
||||
|
||||
<gear switch-ratio="0.25 0.7 1.0" power-increase="2.2 1.7 1.3"/>
|
||||
|
||||
<!-- mass -->
|
||||
<mass value="225"/>
|
||||
|
||||
<mass value="225"/>
|
||||
|
||||
<!-- Kart-specific plunger and rubber band handling: max-length is
|
||||
the maximum length of rubber band before it snaps. force is
|
||||
the force a plunger/rubber band applies to the kart(s).
|
||||
duration is the duration a rubber band acts.
|
||||
in-face-time determines how long it takes before a plunger
|
||||
duration is the duration a rubber band acts.
|
||||
in-face-time determines how long it takes before a plunger
|
||||
in your face is removed. -->
|
||||
<plunger band-max-length="50" band-force="1500" band-duration="1"
|
||||
<plunger band-max-length="50" band-force="1500" band-duration="1"
|
||||
band-speed-increase="7" band-fade-out-time="3"
|
||||
in-face-time="3 4 4.5 4.5"/>
|
||||
|
||||
<!-- Kart-specific explosion parameters.
|
||||
<!-- Kart-specific explosion parameters.
|
||||
Time: how long it takes before the kart can drive again (this
|
||||
determines how height the kart is being thrown).
|
||||
Invulnerability-time: how long a kart will be invulnerable
|
||||
after being hit by an explosion.
|
||||
radius: Kart closer to this value will be affected by
|
||||
an explosion as well. -->
|
||||
<explosion time="2" radius="5"
|
||||
invulnerability-time="6" />
|
||||
|
||||
<kart-type>
|
||||
<light>
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "8.5 4.5" />
|
||||
|
||||
<nitro engine-force="350" consumption="1" small-container="1" big-container="3"
|
||||
max-speed-increase="4.5" duration="1.5" fade-out-time="2.5" max="20"/>
|
||||
|
||||
<slipstream length="11" width="2" collect-time="1.5" use-time="2.5"
|
||||
add-power="3.2" min-speed="9"
|
||||
max-speed-increase="4" duration="1.2" fade-out-time="2.3"/>
|
||||
|
||||
<turn turn-radius="0:3.0 10:10.0 25:20.0 45:40.0"
|
||||
time-full-steer ="0:0.15 0.5:0.15 0.5:0.25 1.0:0.25"
|
||||
time-reset-steer="0.1"/>
|
||||
|
||||
<engine power="250 300 350 400" max-speed="15.8 18.8 23.85 30.0" brake-factor="15.0"
|
||||
max-speed-reverse-ratio="0.3"/>
|
||||
<explosion time="2" radius="5"
|
||||
invulnerability-time="6" />
|
||||
|
||||
<gear switch-ratio="0.20 0.55 1" power-increase="5 4 3"/>
|
||||
<kart-type>
|
||||
<light>
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "8.5 4.5" />
|
||||
|
||||
<mass value="195"/>
|
||||
<nitro engine-force="350" consumption="1" small-container="1" big-container="3"
|
||||
max-speed-increase="4.5" duration="1.5" fade-out-time="2.5" max="20"/>
|
||||
|
||||
<explosion time="2.1" radius="5.5"
|
||||
invulnerability-time="7" />
|
||||
</light>
|
||||
|
||||
<medium>
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "4.2 2.6" />
|
||||
|
||||
<nitro engine-force="425" consumption="1.4" small-container="1" big-container="3"
|
||||
max-speed-increase="5" duration="1.2" fade-out-time="2" max="20"/>
|
||||
|
||||
<slipstream length="10" width="2" collect-time="2" use-time="3.3"
|
||||
<slipstream length="11" width="2" collect-time="1.5" use-time="2.5"
|
||||
add-power="3.2" min-speed="9"
|
||||
max-speed-increase="4" duration="1.2" fade-out-time="2.3"/>
|
||||
|
||||
<turn turn-radius="0:3.0 10:10.0 25:20.0 45:40.0"
|
||||
time-full-steer ="0:0.15 0.5:0.15 0.5:0.25 1.0:0.25"
|
||||
time-reset-steer="0.1"/>
|
||||
|
||||
<engine power="250 300 350 400" max-speed="15.8 18.8 23.85 30.0" brake-factor="15.0"
|
||||
max-speed-reverse-ratio="0.3"/>
|
||||
|
||||
<gear switch-ratio="0.20 0.55 1" power-increase="5 4 3"/>
|
||||
|
||||
<mass value="195"/>
|
||||
|
||||
<explosion time="2.1" radius="5.5"
|
||||
invulnerability-time="7" />
|
||||
</light>
|
||||
|
||||
<medium>
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "4.2 2.6" />
|
||||
|
||||
<nitro engine-force="425" consumption="1.4" small-container="1" big-container="3"
|
||||
max-speed-increase="5" duration="1.2" fade-out-time="2" max="20"/>
|
||||
|
||||
<slipstream length="10" width="2" collect-time="2" use-time="3.3"
|
||||
add-power="2.8" min-speed="10"
|
||||
max-speed-increase="5" duration="0.9" fade-out-time="1.6"/>
|
||||
|
||||
<turn turn-radius="0:4.5 10:16.0 25:30.0 45:60.0"
|
||||
time-full-steer ="0:0.17 0.5:0.17 0.5:0.28 1.0:0.28"
|
||||
time-reset-steer="0.1"/>
|
||||
max-speed-increase="5" duration="0.9" fade-out-time="1.6"/>
|
||||
|
||||
<engine power="425 500 575 600" max-speed="15 20 23.2 27" brake-factor="11.0"
|
||||
max-speed-reverse-ratio="0.4"/>
|
||||
<turn turn-radius="0:4.5 10:16.0 25:30.0 45:60.0"
|
||||
time-full-steer ="0:0.17 0.5:0.17 0.5:0.28 1.0:0.28"
|
||||
time-reset-steer="0.1"/>
|
||||
|
||||
<gear switch-ratio="0.30 0.7 1.0" power-increase="2.2 2.2 2.5"/>
|
||||
<engine power="425 500 575 600" max-speed="15 20 23.2 27" brake-factor="11.0"
|
||||
max-speed-reverse-ratio="0.4"/>
|
||||
|
||||
<mass value="250"/>
|
||||
<gear switch-ratio="0.30 0.7 1.0" power-increase="2.2 2.2 2.5"/>
|
||||
|
||||
<explosion time="1.8" radius="5"
|
||||
invulnerability-time="6" />
|
||||
</medium>
|
||||
|
||||
<heavy>
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "3.8 2" />
|
||||
|
||||
<nitro engine-force="600" consumption="2" small-container="1" big-container="3"
|
||||
max-speed-increase="8" duration="0.7" fade-out-time="1.3" max="20"/>
|
||||
|
||||
<slipstream length="8.5" width="2" collect-time="2" use-time="4"
|
||||
add-power="2.7" min-speed="10.5"
|
||||
max-speed-increase="8" duration="0.7" fade-out-time="1"/>
|
||||
<mass value="250"/>
|
||||
|
||||
<swatter duration="10" distance="3" squash-duration="5"
|
||||
squash-slowdown="0.5"/>
|
||||
|
||||
<turn turn-radius="0:4.0 10:18.5 25:43.0 45:72.5"
|
||||
time-full-steer ="0:0.23 0.5:0.23 0.5:0.41 1.0:0.41"
|
||||
time-reset-steer="0.1"/>
|
||||
<explosion time="1.8" radius="5"
|
||||
invulnerability-time="6" />
|
||||
</medium>
|
||||
|
||||
<engine power="600 700 800 900" max-speed="15 20 23 25" brake-factor="10"
|
||||
max-speed-reverse-ratio="0.65"/>
|
||||
<heavy>
|
||||
<startup time = "0.3 0.5"
|
||||
boost = "3.8 2" />
|
||||
|
||||
<gear switch-ratio="0.45 0.70 1" power-increase="1.5 1.7 2.5"/>
|
||||
<nitro engine-force="600" consumption="2" small-container="1" big-container="3"
|
||||
max-speed-increase="8" duration="0.7" fade-out-time="1.3" max="20"/>
|
||||
|
||||
<mass value="350"/>
|
||||
<slipstream length="8.5" width="2" collect-time="2" use-time="4"
|
||||
add-power="2.7" min-speed="10.5"
|
||||
max-speed-increase="8" duration="0.7" fade-out-time="1"/>
|
||||
|
||||
<explosion time="1.5" radius="4"
|
||||
invulnerability-time="6" />
|
||||
</heavy>
|
||||
</kart-type>
|
||||
<swatter duration="10" distance="3" squash-duration="5"
|
||||
squash-slowdown="0.5"/>
|
||||
|
||||
<turn turn-radius="0:4.0 10:18.5 25:43.0 45:72.5"
|
||||
time-full-steer ="0:0.23 0.5:0.23 0.5:0.41 1.0:0.41"
|
||||
time-reset-steer="0.1"/>
|
||||
|
||||
<engine power="600 700 800 900" max-speed="15 20 23 25" brake-factor="10"
|
||||
max-speed-reverse-ratio="0.65"/>
|
||||
|
||||
<gear switch-ratio="0.45 0.70 1" power-increase="1.5 1.7 2.5"/>
|
||||
|
||||
<mass value="350"/>
|
||||
|
||||
<explosion time="1.5" radius="4"
|
||||
invulnerability-time="6" />
|
||||
</heavy>
|
||||
</kart-type>
|
||||
</general-kart-defaults>
|
||||
</config>
|
||||
|
||||
@@ -481,6 +481,14 @@ struct SJoystickInfo
|
||||
//! The presence or absence of a hat cannot be determined.
|
||||
POV_HAT_UNKNOWN
|
||||
} PovHat;
|
||||
|
||||
//! Set if the name of the joystick is useful:
|
||||
/** On windows the generic name is useless, since it's always the same
|
||||
* indepentent of what joystick is connected ("Microsoft PC-joystick driver").
|
||||
* We will try to get a better name from the registry, but if this should
|
||||
* fail this flag is set and used by STK. */
|
||||
bool HasGenericName;
|
||||
|
||||
}; // struct SJoystickInfo
|
||||
|
||||
|
||||
|
||||
@@ -2038,6 +2038,7 @@ bool CIrrDeviceLinux::activateJoysticks(core::array<SJoystickInfo> & joystickInf
|
||||
|
||||
ActiveJoysticks.push_back(info);
|
||||
|
||||
returnInfo.HasGenericName = false;
|
||||
returnInfo.Joystick = joystick;
|
||||
returnInfo.PovHat = SJoystickInfo::POV_HAT_UNKNOWN;
|
||||
returnInfo.Axes = info.axes;
|
||||
|
||||
@@ -557,6 +557,7 @@ bool CIrrDeviceSDL::activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
|
||||
SJoystickInfo info;
|
||||
|
||||
info.Joystick = joystick;
|
||||
info.HasGenericName = false;
|
||||
info.Axes = SDL_JoystickNumAxes(Joysticks[joystick]);
|
||||
info.Buttons = SDL_JoystickNumButtons(Joysticks[joystick]);
|
||||
info.Name = SDL_JoystickName(joystick);
|
||||
|
||||
@@ -368,7 +368,8 @@ void setJoystickName(int index, const JOYCAPS &caps, SJoystickInfo *joystick)
|
||||
{
|
||||
// As a default use the name given in the joystick structure
|
||||
// - though that is always the same name, independent of joystick :(
|
||||
joystick->Name = caps.szPname;
|
||||
joystick->Name = caps.szPname;
|
||||
joystick->HasGenericName = true;
|
||||
|
||||
core::stringc key = core::stringc(REGSTR_PATH_JOYCONFIG)+"\\"+caps.szRegKey
|
||||
+ "\\"+REGSTR_KEY_JOYCURR;
|
||||
@@ -412,6 +413,7 @@ void setJoystickName(int index, const JOYCAPS &caps, SJoystickInfo *joystick)
|
||||
regresult = RegQueryValueExA(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0,
|
||||
(LPBYTE)name, ®size );
|
||||
joystick->Name = name;
|
||||
joystick->HasGenericName = false;
|
||||
} // if name
|
||||
} // if SUCCESS
|
||||
RegCloseKey(hKey);
|
||||
|
||||
@@ -719,7 +719,7 @@ bool CIrrDeviceMacOSX::createWindow()
|
||||
if (!CreationParams.WindowId)
|
||||
{
|
||||
[Window center];
|
||||
[Window setDelegate:[NSApp delegate]];
|
||||
[(NSFileManager *)Window setDelegate:[NSApp delegate]];
|
||||
|
||||
if(CreationParams.DriverType == video::EDT_OPENGL)
|
||||
[OGLContext setView:[Window contentView]];
|
||||
@@ -1709,6 +1709,7 @@ bool CIrrDeviceMacOSX::activateJoysticks(core::array<SJoystickInfo> & joystickIn
|
||||
|
||||
SJoystickInfo returnInfo;
|
||||
returnInfo.Joystick = jindex;
|
||||
returnInfo.HasGenericName = false;
|
||||
returnInfo.Axes = info.axes;
|
||||
//returnInfo.Hats = info.hats;
|
||||
returnInfo.Buttons = info.buttons;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 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/*")
|
||||
file(GLOB_RECURSE STK_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${PROJECT_BINARY_DIR}/tmp/*.rc")
|
||||
file(GLOB_RECURSE STK_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${PROJECT_BINARY_DIR}/tmp/*.rc")
|
||||
|
||||
@@ -198,7 +198,7 @@ void PlayerProfile::save(UTFWriter &out)
|
||||
<< L"\" guest=\"" << m_is_guest_account
|
||||
<< L"\" use-frequency=\"" << m_use_frequency << L"\"\n";
|
||||
|
||||
out << L" icon-filename=\"" << m_icon_filename <<L"\"\n";
|
||||
out << L" icon-filename=\"" << m_icon_filename << L"\"\n";
|
||||
|
||||
out << L" unique-id=\"" << m_unique_id
|
||||
<< L"\" saved-session=\"" << m_saved_session << L"\"\n";
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define HEADER_PLAYER_PROFILE_HPP
|
||||
|
||||
#include "challenges/story_mode_status.hpp"
|
||||
#include "network/remote_kart_info.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/types.hpp"
|
||||
@@ -66,6 +67,10 @@ public:
|
||||
private:
|
||||
LEAK_CHECK()
|
||||
|
||||
#ifdef DEBUG
|
||||
unsigned int m_magic_number;
|
||||
#endif
|
||||
|
||||
/** The name of the player (wide string, so it can be in native
|
||||
* language). */
|
||||
core::stringw m_local_name;
|
||||
@@ -73,10 +78,6 @@ private:
|
||||
/** True if this account is a guest account. */
|
||||
bool m_is_guest_account;
|
||||
|
||||
#ifdef DEBUG
|
||||
unsigned int m_magic_number;
|
||||
#endif
|
||||
|
||||
/** Counts how often this player was used (always -1 for guests). */
|
||||
int m_use_frequency;
|
||||
|
||||
@@ -111,8 +112,8 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
PlayerProfile(const core::stringw &name, bool is_guest = false);
|
||||
PlayerProfile(const XMLNode *node);
|
||||
PlayerProfile(const core::stringw &name, bool is_guest = false);
|
||||
PlayerProfile(const XMLNode *node);
|
||||
virtual ~PlayerProfile();
|
||||
void save(UTFWriter &out);
|
||||
void loadRemainingData(const XMLNode *node);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "io/xml_node.hpp"
|
||||
#include "items/item.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/player_difficulty.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
STKConfig* stk_config=0;
|
||||
@@ -387,16 +388,23 @@ void STKConfig::getAllData(const XMLNode * root)
|
||||
throw std::runtime_error(msg.str());
|
||||
}
|
||||
m_default_kart_properties->getAllData(node);
|
||||
const XMLNode *types = node->getNode("kart-type");
|
||||
const XMLNode *child_node = node->getNode("kart-type");
|
||||
|
||||
for (unsigned int i = 0; i < types->getNumNodes(); ++i)
|
||||
for (unsigned int i = 0; i < child_node->getNumNodes(); ++i)
|
||||
{
|
||||
const XMLNode* type = types->getNode(i);
|
||||
const XMLNode* type = child_node->getNode(i);
|
||||
m_kart_properties[type->getName()] = new KartProperties();
|
||||
m_kart_properties[type->getName()]->copyFrom(m_default_kart_properties);
|
||||
m_kart_properties[type->getName()]->getAllData(type);
|
||||
}
|
||||
|
||||
child_node = node->getNode("difficulties");
|
||||
for (unsigned int i = 0; i < child_node->getNumNodes(); ++i)
|
||||
{
|
||||
const XMLNode* type = child_node->getNode(i);
|
||||
m_player_difficulties[i] = new PlayerDifficulty();
|
||||
m_player_difficulties[i]->getAllData(type);
|
||||
}
|
||||
} // getAllData
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
* configuration file.
|
||||
*/
|
||||
|
||||
#include "network/remote_kart_info.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
#include <vector>
|
||||
@@ -33,6 +34,7 @@
|
||||
#include <map>
|
||||
|
||||
class KartProperties;
|
||||
class PlayerDifficulty;
|
||||
class MusicInformation;
|
||||
class XMLNode;
|
||||
|
||||
@@ -47,8 +49,10 @@ class STKConfig : public NoCopy
|
||||
{
|
||||
protected:
|
||||
/** Default kart properties. */
|
||||
KartProperties *m_default_kart_properties;
|
||||
KartProperties *m_default_kart_properties;
|
||||
std::map<std::string, KartProperties*> m_kart_properties;
|
||||
/** Per-player difficulties. */
|
||||
PlayerDifficulty* m_player_difficulties[PLAYER_DIFFICULTY_COUNT];
|
||||
|
||||
public:
|
||||
/** What to do if a kart already has a powerup when it hits a bonus box:
|
||||
@@ -175,6 +179,9 @@ public:
|
||||
|
||||
const KartProperties &
|
||||
getKartProperties(std::string type) { return *m_kart_properties[type]; }
|
||||
|
||||
const PlayerDifficulty * getPlayerDifficulty(PerPlayerDifficulty difficulty)
|
||||
{ return m_player_difficulties[difficulty]; }
|
||||
}
|
||||
; // STKConfig
|
||||
|
||||
|
||||
@@ -672,6 +672,20 @@ namespace UserConfigParams
|
||||
PARAM_DEFAULT( StringUserConfigParam("Peach.stkskin", "skin_file",
|
||||
"Name of the skin to use") );
|
||||
|
||||
PARAM_PREFIX GroupUserConfigParam m_handicap
|
||||
PARAM_DEFAULT( GroupUserConfigParam("Handicap",
|
||||
"Everything related to handicaps.") );
|
||||
|
||||
PARAM_PREFIX BoolUserConfigParam m_per_player_difficulty
|
||||
PARAM_DEFAULT( BoolUserConfigParam(false, "per_player_difficulty",
|
||||
&m_handicap,
|
||||
"If handicapped users can be selected") );
|
||||
|
||||
PARAM_PREFIX BoolUserConfigParam m_ai_handicap
|
||||
PARAM_DEFAULT( BoolUserConfigParam(false, "ai_handicap",
|
||||
&m_handicap,
|
||||
"If AIs are handicapped") );
|
||||
|
||||
// ---- Internet related
|
||||
|
||||
PARAM_PREFIX IntUserConfigParam m_internet_status
|
||||
|
||||
@@ -64,7 +64,10 @@ Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
|
||||
setupCamera();
|
||||
if (kart != NULL)
|
||||
{
|
||||
m_distance = kart->getKartProperties()->getCameraDistance();
|
||||
if(UserConfigParams::m_camera_debug==2)
|
||||
m_distance = kart->getKartModel()->getLength();
|
||||
else
|
||||
m_distance = kart->getKartProperties()->getCameraDistance();
|
||||
setKart(kart);
|
||||
}
|
||||
else
|
||||
@@ -378,37 +381,6 @@ void Camera::smoothMoveCamera(float dt)
|
||||
}
|
||||
} // smoothMoveCamera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Computes the wanted camera position and target for normal camera mode.
|
||||
* Besides being used in update(dt), it is also used when switching the
|
||||
* camera from reverse mode to normal mode - in which case we don't want
|
||||
* to have a smooth camera.
|
||||
* \param wanted_position The position the camera should be.
|
||||
* \param wanted_target The target position the camera should target.
|
||||
*/
|
||||
void Camera::computeNormalCameraPosition(Vec3 *wanted_position,
|
||||
Vec3 *wanted_target)
|
||||
{
|
||||
*wanted_target = m_kart->getXYZ();
|
||||
wanted_target->setY(wanted_target->getY()+ 0.75f);
|
||||
|
||||
// This first line moves the camera around behind the kart, pointing it
|
||||
// towards where the kart is turning (and turning even more while skidding).
|
||||
// The skidding effect is dampened.
|
||||
float steering = m_kart->getSteerPercent()
|
||||
* (1.0f + (m_kart->getSkidding()->getSkidFactor() - 1.0f)
|
||||
/2.3f );
|
||||
// quadratically to dampen small variations (but keep sign)
|
||||
float dampened_steer = fabsf(steering) * steering;
|
||||
|
||||
float tan_up = tan(m_kart->getKartProperties()->getCameraForwardUpAngle());
|
||||
Vec3 relative_position(-m_distance*m_rotation_range*dampened_steer*0.5f,
|
||||
m_distance*tan_up+0.75f,
|
||||
-m_distance);
|
||||
*wanted_position = m_kart->getTrans()(relative_position);
|
||||
|
||||
} // computeNormalCameraPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Determine the camera settings for the current frame.
|
||||
* \param above_kart How far above the camera should aim at.
|
||||
@@ -549,7 +521,10 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
Vec3 wanted_position;
|
||||
Vec3 wanted_target = m_kart->getXYZ();
|
||||
if(UserConfigParams::m_camera_debug==2)
|
||||
wanted_target.setY(m_kart->getVehicle()->getWheelInfo(2).m_raycastInfo.m_contactPointWS.getY());
|
||||
{
|
||||
const btWheelInfo &w = m_kart->getVehicle()->getWheelInfo(2);
|
||||
wanted_target.setY(w.m_raycastInfo.m_contactPointWS.getY());
|
||||
}
|
||||
else
|
||||
wanted_target.setY(wanted_target.getY()+above_kart);
|
||||
float tan_up = tan(cam_angle);
|
||||
@@ -567,7 +542,7 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
}
|
||||
wanted_position = t(relative_position);
|
||||
|
||||
if (smoothing)
|
||||
if (smoothing && UserConfigParams::m_camera_debug==0)
|
||||
{
|
||||
smoothMoveCamera(dt);
|
||||
}
|
||||
@@ -591,8 +566,8 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
// Rotate the up vector (0,1,0) by the rotation ... which is just column 1
|
||||
Vec3 up = m_kart->getTrans().getBasis().getColumn(1);
|
||||
float f = 0.04f; // weight for new up vector to reduce shaking
|
||||
m_camera->setUpVector(f * up.toIrrVector() +
|
||||
(1.0f - f) * m_camera->getUpVector());
|
||||
m_camera->setUpVector( f * up.toIrrVector() +
|
||||
(1.0f - f) * m_camera->getUpVector());
|
||||
} // kart && !flying
|
||||
else
|
||||
m_camera->setUpVector(core::vector3df(0, 1, 0));
|
||||
|
||||
@@ -186,8 +186,6 @@ private:
|
||||
|
||||
void setupCamera();
|
||||
void smoothMoveCamera(float dt);
|
||||
void computeNormalCameraPosition(Vec3 *wanted_position,
|
||||
Vec3 *wanted_target);
|
||||
void handleEndCamera(float dt);
|
||||
void getCameraSettings(float *above_kart, float *cam_angle,
|
||||
float *side_way, float *distance,
|
||||
|
||||
@@ -165,7 +165,7 @@ unsigned GPUTimer::elapsedTimeus()
|
||||
FrameBuffer::FrameBuffer() {}
|
||||
|
||||
FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, size_t w, size_t h, bool layered) :
|
||||
RenderTargets(RTTs), DepthTexture(0), width(w), height(h)
|
||||
RenderTargets(RTTs), DepthTexture(0), width(w), height(h), fbolayer(0)
|
||||
{
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
@@ -184,7 +184,7 @@ FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, size_t w, size_t h, bo
|
||||
}
|
||||
|
||||
FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, GLuint DS, size_t w, size_t h, bool layered) :
|
||||
RenderTargets(RTTs), DepthTexture(DS), width(w), height(h)
|
||||
RenderTargets(RTTs), DepthTexture(DS), width(w), height(h), fbolayer(0)
|
||||
{
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
@@ -202,11 +202,15 @@ FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, GLuint DS, size_t w, s
|
||||
}
|
||||
GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
assert(result == GL_FRAMEBUFFER_COMPLETE_EXT);
|
||||
if (layered)
|
||||
glGenFramebuffers(1, &fbolayer);
|
||||
}
|
||||
|
||||
FrameBuffer::~FrameBuffer()
|
||||
{
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
if (fbolayer)
|
||||
glDeleteFramebuffers(1, &fbolayer);
|
||||
}
|
||||
|
||||
void FrameBuffer::Bind()
|
||||
@@ -217,6 +221,16 @@ void FrameBuffer::Bind()
|
||||
glDrawBuffers((int)RenderTargets.size(), bufs);
|
||||
}
|
||||
|
||||
void FrameBuffer::BindLayer(unsigned i)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbolayer);
|
||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, RenderTargets[0], 0, i);
|
||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, DepthTexture, 0, i);
|
||||
glViewport(0, 0, (int)width, (int)height);
|
||||
GLenum bufs[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
|
||||
glDrawBuffers((int)RenderTargets.size(), bufs);
|
||||
}
|
||||
|
||||
void FrameBuffer::Blit(const FrameBuffer &Src, FrameBuffer &Dst, GLbitfield mask, GLenum filter)
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, Src.fbo);
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
class FrameBuffer
|
||||
{
|
||||
private:
|
||||
GLuint fbo;
|
||||
GLuint fbo, fbolayer;
|
||||
std::vector<GLuint> RenderTargets;
|
||||
GLuint DepthTexture;
|
||||
size_t width, height;
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
FrameBuffer(const std::vector <GLuint> &RTTs, GLuint DS, size_t w, size_t h, bool layered = false);
|
||||
~FrameBuffer();
|
||||
void Bind();
|
||||
void BindLayer(unsigned);
|
||||
const std::vector<GLuint> &getRTT() const { return RenderTargets; }
|
||||
GLuint &getDepthTexture() { assert(DepthTexture); return DepthTexture; }
|
||||
size_t getWidth() const { return width; }
|
||||
|
||||
@@ -351,7 +351,7 @@ void IrrDriver::initDevice()
|
||||
UserConfigParams::m_height = (int)ssize.Height;
|
||||
}
|
||||
|
||||
core::dimension2d<u32> res = core::dimension2du(UserConfigParams::m_width,
|
||||
core::dimension2d<u32> res = core::dimension2du(UserConfigParams::m_width,
|
||||
UserConfigParams::m_height);
|
||||
|
||||
if (UserConfigParams::m_fullscreen)
|
||||
@@ -485,6 +485,7 @@ void IrrDriver::initDevice()
|
||||
m_need_ubo_workaround = false;
|
||||
m_need_rh_workaround = false;
|
||||
m_need_srgb_workaround = false;
|
||||
m_support_sdsm = true;
|
||||
#ifdef WIN32
|
||||
// Fix for Intel Sandy Bridge on Windows which supports GL up to 3.1 only
|
||||
if (strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL && (m_gl_major_version == 3 && m_gl_minor_version == 1))
|
||||
@@ -492,7 +493,10 @@ void IrrDriver::initDevice()
|
||||
#endif
|
||||
// Fix for Nvidia and instanced RH
|
||||
if (strstr((const char *)glGetString(GL_VENDOR), "NVIDIA") != NULL)
|
||||
{
|
||||
m_need_rh_workaround = true;
|
||||
m_support_sdsm = false;
|
||||
}
|
||||
|
||||
// Fix for AMD and bindless sRGB textures
|
||||
if (strstr((const char *)glGetString(GL_VENDOR), "ATI") != NULL)
|
||||
@@ -513,6 +517,7 @@ void IrrDriver::initDevice()
|
||||
hasDrawIndirect = false;
|
||||
hasComputeShaders = false;
|
||||
hasTextureStorage = false;
|
||||
hasTextureView = false;
|
||||
// Default false value for hasVSLayer if --no-graphics argument is used
|
||||
#if !defined(__APPLE__)
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
@@ -541,6 +546,11 @@ void IrrDriver::initDevice()
|
||||
hasTextureStorage = true;
|
||||
Log::info("GLDriver", "ARB Texture Storage enabled");
|
||||
}
|
||||
if (hasGLExtension("GL_ARB_texture_view")) {
|
||||
hasTextureView = true;
|
||||
Log::info("GLDriver", "ARB Texture View enabled");
|
||||
}
|
||||
m_support_sdsm = m_support_sdsm && hasComputeShaders && hasBuffserStorage;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -180,6 +180,8 @@ private:
|
||||
bool hasBuffserStorage;
|
||||
bool hasComputeShaders;
|
||||
bool hasTextureStorage;
|
||||
bool hasTextureView;
|
||||
bool m_support_sdsm;
|
||||
bool m_need_ubo_workaround;
|
||||
bool m_need_rh_workaround;
|
||||
bool m_need_srgb_workaround;
|
||||
@@ -266,6 +268,11 @@ public:
|
||||
return 120;
|
||||
}
|
||||
|
||||
bool supportsSDSM() const
|
||||
{
|
||||
return m_support_sdsm;
|
||||
}
|
||||
|
||||
bool needUBOWorkaround() const
|
||||
{
|
||||
return m_need_ubo_workaround;
|
||||
@@ -311,6 +318,11 @@ public:
|
||||
return hasTextureStorage;
|
||||
}
|
||||
|
||||
bool hasARBTextureView() const
|
||||
{
|
||||
return hasTextureView;
|
||||
}
|
||||
|
||||
video::SColorf getAmbientLight() const;
|
||||
|
||||
struct GlowData {
|
||||
@@ -767,6 +779,7 @@ public:
|
||||
|
||||
void renderScene(scene::ICameraSceneNode * const camnode, unsigned pointlightcount, std::vector<GlowData>& glows, float dt, bool hasShadows, bool forceRTT);
|
||||
unsigned UpdateLightsInfo(scene::ICameraSceneNode * const camnode, float dt);
|
||||
void UpdateSplitAndLightcoordRangeFromComputeShaders(size_t width, size_t height);
|
||||
void computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height);
|
||||
|
||||
// --------------------- OLD RTT --------------------
|
||||
|
||||
@@ -282,6 +282,8 @@ void PostProcessing::renderSunlight()
|
||||
DrawFullScreenEffect<FullScreenShader::SunLightShader>(cb->getPosition(), video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue()));
|
||||
}
|
||||
|
||||
extern float shadowSplit[5];
|
||||
|
||||
void PostProcessing::renderShadowedSunlight(const std::vector<core::matrix4> &sun_ortho_matrix, GLuint depthtex)
|
||||
{
|
||||
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
|
||||
@@ -292,7 +294,7 @@ void PostProcessing::renderShadowedSunlight(const std::vector<core::matrix4> &su
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
|
||||
FullScreenShader::ShadowedSunLightShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), depthtex);
|
||||
DrawFullScreenEffect<FullScreenShader::ShadowedSunLightShader>(cb->getPosition(), video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue()));
|
||||
DrawFullScreenEffect<FullScreenShader::ShadowedSunLightShader>(shadowSplit[1], shadowSplit[2], shadowSplit[3], shadowSplit[4], cb->getPosition(), video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue()));
|
||||
}
|
||||
|
||||
|
||||
@@ -314,6 +316,25 @@ void PostProcessing::renderGaussian3Blur(FrameBuffer &in_fbo, FrameBuffer &auxil
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessing::renderGaussian6BlurLayer(FrameBuffer &in_fbo)
|
||||
{
|
||||
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
// Used as temp
|
||||
irr_driver->getFBO(FBO_BLOOM_1024).Bind();
|
||||
GLuint LayerTex;
|
||||
glGenTextures(1, &LayerTex);
|
||||
glTextureView(LayerTex, GL_TEXTURE_2D, in_fbo.getRTT()[0], GL_R32F, 0, 1, i, 1);
|
||||
FullScreenShader::Gaussian6VBlurShader::getInstance()->SetTextureUnits(LayerTex);
|
||||
DrawFullScreenEffect<FullScreenShader::Gaussian6VBlurShader>(core::vector2df(1. / 1024., 1. / 1024.));
|
||||
in_fbo.BindLayer(i);
|
||||
FullScreenShader::Gaussian6HBlurShader::getInstance()->SetTextureUnits(irr_driver->getFBO(FBO_BLOOM_1024).getRTT()[0]);
|
||||
DrawFullScreenEffect<FullScreenShader::Gaussian6HBlurShader>(core::vector2df(1. / 1024., 1. / 1024.));
|
||||
glDeleteTextures(1, &LayerTex);
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessing::renderGaussian6Blur(FrameBuffer &in_fbo, FrameBuffer &auxiliary)
|
||||
{
|
||||
assert(in_fbo.getWidth() == auxiliary.getWidth() && in_fbo.getHeight() == auxiliary.getHeight());
|
||||
@@ -432,6 +453,7 @@ void PostProcessing::renderSSAO()
|
||||
DrawFullScreenEffect<FullScreenShader::SSAOShader>(irr_driver->getSSAORadius(), irr_driver->getSSAOK(), irr_driver->getSSAOSigma());
|
||||
}
|
||||
|
||||
|
||||
void PostProcessing::renderFog()
|
||||
{
|
||||
const Track * const track = World::getWorld()->getTrack();
|
||||
@@ -516,11 +538,11 @@ static void renderGodRay(GLuint tex, const core::vector2df &sunpos)
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
static void toneMap(FrameBuffer &fbo, GLuint rtt)
|
||||
static void toneMap(FrameBuffer &fbo, GLuint rtt, float vignette_weight)
|
||||
{
|
||||
fbo.Bind();
|
||||
FullScreenShader::ToneMapShader::getInstance()->SetTextureUnits(rtt);
|
||||
DrawFullScreenEffect<FullScreenShader::ToneMapShader>();
|
||||
DrawFullScreenEffect<FullScreenShader::ToneMapShader>(vignette_weight);
|
||||
}
|
||||
|
||||
static void renderDoF(FrameBuffer &fbo, GLuint rtt)
|
||||
@@ -718,7 +740,15 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, boo
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Tonemap", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TONEMAP));
|
||||
toneMap(*out_fbo, in_fbo->getRTT()[0]);
|
||||
// only enable vignette during race
|
||||
if(isRace)
|
||||
{
|
||||
toneMap(*out_fbo, in_fbo->getRTT()[0], 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
toneMap(*out_fbo, in_fbo->getRTT()[0], 0.0);
|
||||
}
|
||||
std::swap(in_fbo, out_fbo);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ public:
|
||||
/** Blur the in texture */
|
||||
void renderGaussian3Blur(FrameBuffer &in_fbo, FrameBuffer &auxiliary);
|
||||
void renderGaussian6Blur(FrameBuffer &in_fbo, FrameBuffer &auxiliary);
|
||||
void renderGaussian6BlurLayer(FrameBuffer &in_fbo);
|
||||
void renderGaussian17TapBlur(FrameBuffer &in_fbo, FrameBuffer &auxiliary);
|
||||
|
||||
/** Render tex. Used for blit/texture resize */
|
||||
|
||||
@@ -638,12 +638,155 @@ core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, const std::
|
||||
return tmp_matrix;
|
||||
tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
|
||||
down, up,
|
||||
30, zmax);
|
||||
zmin - 100, zmax);
|
||||
return tmp_matrix;
|
||||
}
|
||||
|
||||
float shadowSplit[5] = {1., 5., 20., 50., 150 };
|
||||
|
||||
struct CascadeBoundingBox
|
||||
{
|
||||
int xmin;
|
||||
int xmax;
|
||||
int ymin;
|
||||
int ymax;
|
||||
int zmin;
|
||||
int zmax;
|
||||
};
|
||||
|
||||
static size_t currentCBB = 0;
|
||||
static CascadeBoundingBox *CBB[2];
|
||||
|
||||
struct Histogram
|
||||
{
|
||||
int bin[1024];
|
||||
int mindepth;
|
||||
int maxdepth;
|
||||
int count;
|
||||
};
|
||||
|
||||
|
||||
/** Update shadowSplit values and make Cascade Bounding Box pointer valid.
|
||||
* The function aunches two compute kernel that generates an histogram of the depth buffer value (between 0 and 250 with increment of 0.25)
|
||||
* and get an axis aligned bounding box (from SunCamMatrix view) containing all depth buffer value.
|
||||
* It also retrieves the result from the previous computations (in a Round Robin fashion) and update CBB pointer.
|
||||
* \param width of the depth buffer
|
||||
* \param height of the depth buffer
|
||||
* TODO : The depth histogram part is commented out, needs to tweak it when I have some motivation
|
||||
*/
|
||||
void IrrDriver::UpdateSplitAndLightcoordRangeFromComputeShaders(size_t width, size_t height)
|
||||
{
|
||||
// Value that should be kept between multiple calls
|
||||
static GLuint ssbo[2];
|
||||
static Histogram *Hist[2];
|
||||
static GLsync LightcoordBBFence = 0;
|
||||
static size_t currentHist = 0;
|
||||
static GLuint ssboSplit[2];
|
||||
static float tmpshadowSplit[5] = { 1., 5., 20., 50., 150. };
|
||||
|
||||
if (!LightcoordBBFence)
|
||||
{
|
||||
glGenBuffers(2, ssbo);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[0]);
|
||||
glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
|
||||
CBB[0] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[1]);
|
||||
glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
|
||||
CBB[1] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
|
||||
|
||||
/* glGenBuffers(2, ssboSplit);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[0]);
|
||||
glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
|
||||
Hist[0] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[1]);
|
||||
glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
|
||||
Hist[1] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);*/
|
||||
}
|
||||
|
||||
// Use bounding boxes from last frame
|
||||
if (LightcoordBBFence)
|
||||
{
|
||||
while (glClientWaitSync(LightcoordBBFence, GL_SYNC_FLUSH_COMMANDS_BIT, 0) != GL_ALREADY_SIGNALED);
|
||||
glDeleteSync(LightcoordBBFence);
|
||||
}
|
||||
|
||||
/* {
|
||||
memcpy(shadowSplit, tmpshadowSplit, 5 * sizeof(float));
|
||||
unsigned numpix = Hist[currentHist]->count;
|
||||
unsigned split = 0;
|
||||
unsigned i;
|
||||
for (i = 0; i < 1022; i++)
|
||||
{
|
||||
split += Hist[currentHist]->bin[i];
|
||||
if (split > numpix / 2)
|
||||
break;
|
||||
}
|
||||
tmpshadowSplit[1] = (float)++i / 4.;
|
||||
|
||||
for (; i < 1023; i++)
|
||||
{
|
||||
split += Hist[currentHist]->bin[i];
|
||||
if (split > 3 * numpix / 4)
|
||||
break;
|
||||
}
|
||||
tmpshadowSplit[2] = (float)++i / 4.;
|
||||
|
||||
for (; i < 1024; i++)
|
||||
{
|
||||
split += Hist[currentHist]->bin[i];
|
||||
if (split > 7 * numpix / 8)
|
||||
break;
|
||||
}
|
||||
tmpshadowSplit[3] = (float)++i / 4.;
|
||||
|
||||
for (; i < 1024; i++)
|
||||
{
|
||||
split += Hist[currentHist]->bin[i];
|
||||
}
|
||||
|
||||
tmpshadowSplit[0] = (float)(Hist[currentHist]->bin[1024] - 1) / 4.;
|
||||
tmpshadowSplit[4] = (float)(Hist[currentHist]->bin[1025] + 1) / 4.;
|
||||
printf("numpix is %d\n", numpix);
|
||||
printf("total : %d\n", split);
|
||||
printf("split 0 : %f\n", tmpshadowSplit[1]);
|
||||
printf("split 1 : %f\n", tmpshadowSplit[2]);
|
||||
printf("split 2 : %f\n", tmpshadowSplit[3]);
|
||||
printf("min %f max %f\n", tmpshadowSplit[0], tmpshadowSplit[4]);
|
||||
currentHist = (currentHist + 1) % 2;
|
||||
}*/
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo[currentCBB]);
|
||||
// glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboSplit[currentHist]);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
CBB[currentCBB][i].xmin = CBB[currentCBB][i].ymin = CBB[currentCBB][i].zmin = 1000;
|
||||
CBB[currentCBB][i].xmax = CBB[currentCBB][i].ymax = CBB[currentCBB][i].zmax = -1000;
|
||||
}
|
||||
// memset(Hist[currentHist], 0, sizeof(Histogram));
|
||||
// Hist[currentHist]->mindepth = 3000;
|
||||
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
|
||||
glUseProgram(FullScreenShader::LightspaceBoundingBoxShader::getInstance()->Program);
|
||||
FullScreenShader::LightspaceBoundingBoxShader::getInstance()->SetTextureUnits(getDepthStencilTexture());
|
||||
FullScreenShader::LightspaceBoundingBoxShader::getInstance()->setUniforms(m_suncam->getViewMatrix(), tmpshadowSplit[1], tmpshadowSplit[2], tmpshadowSplit[3], tmpshadowSplit[4]);
|
||||
glDispatchCompute((int)width / 64, (int)height / 64, 1);
|
||||
|
||||
/* glUseProgram(FullScreenShader::DepthHistogramShader::getInstance()->Program);
|
||||
FullScreenShader::DepthHistogramShader::getInstance()->SetTextureUnits(getDepthStencilTexture());
|
||||
FullScreenShader::DepthHistogramShader::getInstance()->setUniforms();
|
||||
glDispatchCompute((int)width / 32, (int)height / 32, 1);*/
|
||||
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
LightcoordBBFence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
currentCBB = (currentCBB + 1) % 2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height)
|
||||
{
|
||||
if (irr_driver->supportsSDSM())
|
||||
UpdateSplitAndLightcoordRangeFromComputeShaders(width, height);
|
||||
static_cast<scene::CSceneManager *>(m_scene_manager)->OnAnimate(os::Timer::getTime());
|
||||
camnode->render();
|
||||
irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
|
||||
@@ -656,17 +799,17 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
|
||||
const float oldnear = camnode->getNearValue();
|
||||
float FarValues[] =
|
||||
{
|
||||
6.,
|
||||
21.,
|
||||
55.,
|
||||
150.,
|
||||
shadowSplit[1],
|
||||
shadowSplit[2],
|
||||
shadowSplit[3],
|
||||
shadowSplit[4],
|
||||
};
|
||||
float NearValues[] =
|
||||
{
|
||||
oldnear,
|
||||
5.,
|
||||
20.,
|
||||
50.,
|
||||
shadowSplit[0],
|
||||
shadowSplit[1],
|
||||
shadowSplit[2],
|
||||
shadowSplit[3]
|
||||
};
|
||||
|
||||
|
||||
@@ -697,9 +840,12 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
|
||||
// Build the 3 ortho projection (for the 3 shadow resolution levels)
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
camnode->setFarValue(FarValues[i]);
|
||||
camnode->setNearValue(NearValues[i]);
|
||||
camnode->render();
|
||||
if (!irr_driver->supportsSDSM())
|
||||
{
|
||||
camnode->setFarValue(FarValues[i]);
|
||||
camnode->setNearValue(NearValues[i]);
|
||||
camnode->render();
|
||||
}
|
||||
const scene::SViewFrustum *frustrum = camnode->getViewFrustum();
|
||||
float tmp[24] = {
|
||||
frustrum->getFarLeftDown().X,
|
||||
@@ -737,7 +883,6 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
|
||||
core::aabbox3df box = smallcambox;
|
||||
box = box.intersect(trackbox);
|
||||
|
||||
|
||||
std::vector<vector3df> vectors;
|
||||
vectors.push_back(frustrum->getFarLeftDown());
|
||||
vectors.push_back(frustrum->getFarLeftUp());
|
||||
@@ -748,19 +893,24 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
|
||||
vectors.push_back(frustrum->getNearRightDown());
|
||||
vectors.push_back(frustrum->getNearRightUp());
|
||||
|
||||
/* SunCamViewMatrix.transformBoxEx(trackbox);
|
||||
SunCamViewMatrix.transformBoxEx(box);
|
||||
core::matrix4 tmp_matrix;
|
||||
|
||||
core::vector3df extent = box.getExtent();
|
||||
const float w = fabsf(extent.X);
|
||||
const float h = fabsf(extent.Y);
|
||||
float z = box.MaxEdge.Z;
|
||||
if (irr_driver->supportsSDSM()){
|
||||
float left = CBB[currentCBB][i].xmin / 4 - 2;
|
||||
float right = CBB[currentCBB][i].xmax / 4 + 2;
|
||||
float up = CBB[currentCBB][i].ymin / 4 - 2;
|
||||
float down = CBB[currentCBB][i].ymax / 4 + 2;
|
||||
|
||||
// Snap to texels
|
||||
const float units_per_w = w / 1024;
|
||||
const float units_per_h = h / 1024;*/
|
||||
// Prevent Matrix without extend
|
||||
if (left != right && up != down)
|
||||
tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
|
||||
down, up,
|
||||
CBB[currentCBB][i].zmin / 4 - 100, CBB[currentCBB][i].zmax / 4 + 2);
|
||||
}
|
||||
else
|
||||
tmp_matrix = getTighestFitOrthoProj(SunCamViewMatrix, vectors);
|
||||
|
||||
m_shadow_camnodes[i]->setProjectionMatrix(getTighestFitOrthoProj(SunCamViewMatrix, vectors) , true);
|
||||
m_shadow_camnodes[i]->setProjectionMatrix(tmp_matrix , true);
|
||||
m_shadow_camnodes[i]->render();
|
||||
|
||||
sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW));
|
||||
@@ -824,16 +974,16 @@ void IrrDriver::renderShadowsDebug()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(0, UserConfigParams::m_height / 2, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2);
|
||||
m_post_processing->renderTextureLayer(m_rtts->getShadowDepthTex(), 0);
|
||||
m_post_processing->renderTextureLayer(m_rtts->getShadowFBO().getRTT()[0], 0);
|
||||
renderWireFrameFrustrum(m_shadows_cam[0], 0);
|
||||
glViewport(UserConfigParams::m_width / 2, UserConfigParams::m_height / 2, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2);
|
||||
m_post_processing->renderTextureLayer(m_rtts->getShadowDepthTex(), 1);
|
||||
m_post_processing->renderTextureLayer(m_rtts->getShadowFBO().getRTT()[0], 1);
|
||||
renderWireFrameFrustrum(m_shadows_cam[1], 1);
|
||||
glViewport(0, 0, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2);
|
||||
m_post_processing->renderTextureLayer(m_rtts->getShadowDepthTex(), 2);
|
||||
m_post_processing->renderTextureLayer(m_rtts->getShadowFBO().getRTT()[0], 2);
|
||||
renderWireFrameFrustrum(m_shadows_cam[2], 2);
|
||||
glViewport(UserConfigParams::m_width / 2, 0, UserConfigParams::m_width / 2, UserConfigParams::m_height / 2);
|
||||
m_post_processing->renderTextureLayer(m_rtts->getShadowDepthTex(), 3);
|
||||
m_post_processing->renderTextureLayer(m_rtts->getShadowFBO().getRTT()[0], 3);
|
||||
renderWireFrameFrustrum(m_shadows_cam[3], 3);
|
||||
glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height);
|
||||
}
|
||||
|
||||
@@ -978,14 +978,15 @@ void IrrDriver::renderShadows()
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_FRONT);
|
||||
m_rtts->getShadowFBO().Bind();
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(1.5, 0.);
|
||||
m_rtts->getShadowFBO().Bind();
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glCullFace(GL_BACK);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glClearColor(1., 1., 1., 1.);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(0., 0., 0., 0.);
|
||||
|
||||
for (unsigned cascade = 0; cascade < 4; cascade++)
|
||||
{
|
||||
@@ -1024,7 +1025,11 @@ void IrrDriver::renderShadows()
|
||||
}
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
if (irr_driver->hasARBTextureView())
|
||||
m_post_processing->renderGaussian6BlurLayer(m_rtts->getShadowFBO());
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_rtts->getShadowFBO().getRTT()[0]);
|
||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
|
||||
{
|
||||
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN));
|
||||
if (World::getWorld() && UserConfigParams::m_shadows && !irr_driver->needUBOWorkaround())
|
||||
m_post_processing->renderShadowedSunlight(sun_ortho_matrix, m_rtts->getShadowDepthTex());
|
||||
m_post_processing->renderShadowedSunlight(sun_ortho_matrix, m_rtts->getShadowFBO().getRTT()[0]);
|
||||
else
|
||||
m_post_processing->renderSunlight();
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
#include "utils/log.hpp"
|
||||
#include <ISceneManager.h>
|
||||
|
||||
static GLuint generateRTT3D(GLenum target, size_t w, size_t h, size_t d, GLint internalFormat, GLint format, GLint type)
|
||||
static GLuint generateRTT3D(GLenum target, size_t w, size_t h, size_t d, GLint internalFormat, GLint format, GLint type, unsigned mipmaplevel = 1)
|
||||
{
|
||||
GLuint result;
|
||||
glGenTextures(1, &result);
|
||||
glBindTexture(target, result);
|
||||
if (irr_driver->hasARBTextureStorage())
|
||||
glTexStorage3D(target, 1, internalFormat, w, h, d);
|
||||
glTexStorage3D(target, mipmaplevel, internalFormat, w, h, d);
|
||||
else
|
||||
glTexImage3D(target, 0, internalFormat, w, h, d, 0, format, type, 0);
|
||||
return result;
|
||||
@@ -223,8 +223,8 @@ RTT::RTT(size_t width, size_t height)
|
||||
|
||||
if (UserConfigParams::m_shadows && !irr_driver->needUBOWorkaround())
|
||||
{
|
||||
shadowColorTex = generateRTT3D(GL_TEXTURE_2D_ARRAY, 1024, 1024, 4, GL_R8, GL_RED, GL_UNSIGNED_BYTE);
|
||||
shadowDepthTex = generateRTT3D(GL_TEXTURE_2D_ARRAY, 1024, 1024, 4, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
|
||||
shadowColorTex = generateRTT3D(GL_TEXTURE_2D_ARRAY, 1024, 1024, 4, GL_R32F, GL_RED, GL_FLOAT, 1);
|
||||
shadowDepthTex = generateRTT3D(GL_TEXTURE_2D_ARRAY, 1024, 1024, 4, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 1);
|
||||
|
||||
somevector.clear();
|
||||
somevector.push_back(shadowColorTex);
|
||||
|
||||
@@ -44,7 +44,6 @@ public:
|
||||
FrameBuffer &getShadowFBO() { return *m_shadow_FBO; }
|
||||
FrameBuffer &getRH() { return *m_RH_FBO; }
|
||||
FrameBuffer &getRSM() { return *m_RSM; }
|
||||
unsigned getShadowDepthTex() const { return shadowDepthTex; }
|
||||
|
||||
unsigned getDepthStencilTexture() const { return DepthStencilTexture; }
|
||||
unsigned getRenderTarget(enum TypeRTT target) const { return RenderTargetTextures[target]; }
|
||||
|
||||
@@ -859,11 +859,13 @@ GLuint createShadowSampler()
|
||||
unsigned id;
|
||||
glGenSamplers(1, &id);
|
||||
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glSamplerParameterf(id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
glSamplerParameterf(id, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
||||
return id;
|
||||
#endif
|
||||
}
|
||||
@@ -1185,14 +1187,14 @@ namespace MeshShader
|
||||
{
|
||||
Program = LoadProgram(OBJECT,
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadow.frag").c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Program = LoadProgram(OBJECT,
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
|
||||
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadow.frag").c_str());
|
||||
}
|
||||
AssignUniforms("layer", "ModelMatrix");
|
||||
}
|
||||
@@ -1238,7 +1240,7 @@ namespace MeshShader
|
||||
Program = LoadProgram(OBJECT,
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadow.frag").c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1246,7 +1248,7 @@ namespace MeshShader
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedshadow.vert").c_str(),
|
||||
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/instanced_shadow.geom").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadow.frag").c_str());
|
||||
}
|
||||
AssignUniforms("layer");
|
||||
}
|
||||
@@ -1260,14 +1262,14 @@ namespace MeshShader
|
||||
{
|
||||
Program = LoadProgram(OBJECT,
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadowref.frag").c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Program = LoadProgram(OBJECT,
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
|
||||
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadowref.frag").c_str());
|
||||
}
|
||||
AssignUniforms("layer", "ModelMatrix");
|
||||
AssignSamplerNames(Program, 0, "tex");
|
||||
@@ -1567,7 +1569,7 @@ namespace FullScreenShader
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getRGBfromCIEXxy.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getCIEXYZ.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/tonemap.frag").c_str());
|
||||
AssignUniforms();
|
||||
AssignUniforms("vignette_weight");
|
||||
|
||||
AssignSamplerNames(Program, 0, "text");
|
||||
}
|
||||
@@ -1617,7 +1619,7 @@ namespace FullScreenShader
|
||||
|
||||
// Use 8 to circumvent a catalyst bug when binding sampler
|
||||
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 8, "shadowtex");
|
||||
AssignUniforms("direction", "col");
|
||||
AssignUniforms("split0", "split1", "split2", "splitmax", "direction", "col");
|
||||
}
|
||||
|
||||
RadianceHintsConstructionShader::RadianceHintsConstructionShader()
|
||||
@@ -1787,6 +1789,29 @@ namespace FullScreenShader
|
||||
AssignSamplerNames(Program, 0, "texture");
|
||||
}
|
||||
|
||||
|
||||
LightspaceBoundingBoxShader::LightspaceBoundingBoxShader()
|
||||
{
|
||||
Program = LoadProgram(OBJECT,
|
||||
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/Lightspaceboundingbox.comp").c_str(),
|
||||
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str());
|
||||
AssignSamplerNames(Program, 0, "depth");
|
||||
AssignUniforms("SunCamMatrix", "split0", "split1", "split2", "splitmax");
|
||||
GLuint block_idx = glGetProgramResourceIndex(Program, GL_SHADER_STORAGE_BLOCK, "BoundingBoxes");
|
||||
glShaderStorageBlockBinding(Program, block_idx, 2);
|
||||
}
|
||||
|
||||
DepthHistogramShader::DepthHistogramShader()
|
||||
{
|
||||
Program = LoadProgram(OBJECT,
|
||||
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/depthhistogram.comp").c_str(),
|
||||
GL_COMPUTE_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str());
|
||||
AssignSamplerNames(Program, 0, "depth");
|
||||
|
||||
GLuint block_idx = glGetProgramResourceIndex(Program, GL_SHADER_STORAGE_BLOCK, "Histogram");
|
||||
glShaderStorageBlockBinding(Program, block_idx, 1);
|
||||
}
|
||||
|
||||
GlowShader::GlowShader()
|
||||
{
|
||||
Program = LoadProgram(OBJECT,
|
||||
|
||||
@@ -377,9 +377,10 @@ public:
|
||||
BloomBlendShader();
|
||||
};
|
||||
|
||||
class ToneMapShader : public ShaderHelperSingleton<ToneMapShader>, public TextureRead<Nearest_Filtered>
|
||||
class ToneMapShader : public ShaderHelperSingleton<ToneMapShader, float>, public TextureRead<Nearest_Filtered>
|
||||
{
|
||||
public:
|
||||
|
||||
ToneMapShader();
|
||||
};
|
||||
|
||||
@@ -401,7 +402,7 @@ public:
|
||||
EnvMapShader();
|
||||
};
|
||||
|
||||
class ShadowedSunLightShader : public ShaderHelperSingleton<ShadowedSunLightShader, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Shadow_Sampler>
|
||||
class ShadowedSunLightShader : public ShaderHelperSingleton<ShadowedSunLightShader, float, float, float, float, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Shadow_Sampler>
|
||||
{
|
||||
public:
|
||||
ShadowedSunLightShader();
|
||||
@@ -510,6 +511,18 @@ public:
|
||||
LinearizeDepthShader();
|
||||
};
|
||||
|
||||
class LightspaceBoundingBoxShader : public ShaderHelperSingleton<LightspaceBoundingBoxShader, core::matrix4, float, float, float, float>, public TextureRead < Nearest_Filtered >
|
||||
{
|
||||
public:
|
||||
LightspaceBoundingBoxShader();
|
||||
};
|
||||
|
||||
class DepthHistogramShader : public ShaderHelperSingleton<DepthHistogramShader>, public TextureRead <Nearest_Filtered>
|
||||
{
|
||||
public:
|
||||
DepthHistogramShader();
|
||||
};
|
||||
|
||||
class GlowShader : public ShaderHelperSingleton<GlowShader>, public TextureRead<Bilinear_Filtered>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <IMeshSceneNode.h>
|
||||
#include <ISceneNode.h>
|
||||
|
||||
Shadow::Shadow(video::ITexture *texture, scene::ISceneNode *node,
|
||||
Shadow::Shadow(video::ITexture *texture, scene::ISceneNode *node,
|
||||
float scale = 1.0, float x_offset = 0.0, float y_offset = 0.0,
|
||||
float z_offset = 0.0)
|
||||
{
|
||||
|
||||
@@ -69,9 +69,11 @@ SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
|
||||
setTextureMatrix(&(m_node->getMaterial(0).getTextureMatrix(0)));
|
||||
m_slipstream_time = 0.0f;
|
||||
|
||||
float length = m_kart->getKartProperties()->getSlipstreamLength();
|
||||
float length = m_kart->getKartProperties()->getSlipstreamLength() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamLength();
|
||||
float kw = m_kart->getKartWidth();
|
||||
float ew = m_kart->getKartProperties()->getSlipstreamWidth();
|
||||
float ew = m_kart->getKartProperties()->getSlipstreamWidth() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamWidth();
|
||||
float kl = m_kart->getKartLength();
|
||||
|
||||
Vec3 p[4];
|
||||
@@ -299,7 +301,8 @@ void SlipStream::setIntensity(float f, const AbstractKart *kart)
|
||||
bool SlipStream::isSlipstreamReady() const
|
||||
{
|
||||
return m_slipstream_time>
|
||||
m_kart->getKartProperties()->getSlipstreamCollectTime();
|
||||
m_kart->getKartProperties()->getSlipstreamCollectTime() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamCollectTime();
|
||||
} // isSlipstreamReady
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -315,10 +318,14 @@ void SlipStream::updateSlipstreamPower()
|
||||
setIntensity(2.0f, NULL);
|
||||
const KartProperties *kp=m_kart->getKartProperties();
|
||||
m_kart->increaseMaxSpeed(MaxSpeed::MS_INCREASE_SLIPSTREAM,
|
||||
kp->getSlipstreamMaxSpeedIncrease(),
|
||||
kp->getSlipstreamAddPower(),
|
||||
kp->getSlipstreamDuration(),
|
||||
kp->getSlipstreamFadeOutTime() );
|
||||
kp->getSlipstreamMaxSpeedIncrease() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamMaxSpeedIncrease(),
|
||||
kp->getSlipstreamAddPower() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamAddPower(),
|
||||
kp->getSlipstreamDuration() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamDuration(),
|
||||
kp->getSlipstreamFadeOutTime() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamFadeOutTime());
|
||||
}
|
||||
} // upateSlipstreamPower
|
||||
|
||||
@@ -372,7 +379,8 @@ void SlipStream::update(float dt)
|
||||
// not moving. This is useful for debugging the graphics of SS-ing.
|
||||
#undef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
|
||||
#ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
|
||||
if(m_kart->getSpeed()<m_kart->getKartProperties()->getSlipstreamMinSpeed())
|
||||
if(m_kart->getSpeed()<m_kart->getKartProperties()->getSlipstreamMinSpeed() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamMinSpeed())
|
||||
{
|
||||
setIntensity(0, NULL);
|
||||
m_slipstream_mode = SS_NONE;
|
||||
@@ -414,7 +422,8 @@ void SlipStream::update(float dt)
|
||||
// give karts different slipstream properties.
|
||||
#ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
|
||||
if(m_target_kart->getSpeed() <
|
||||
m_kart->getKartProperties()->getSlipstreamMinSpeed())
|
||||
m_kart->getKartProperties()->getSlipstreamMinSpeed() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamMinSpeed())
|
||||
{
|
||||
if(UserConfigParams::m_slipstream_debug &&
|
||||
m_kart->getController()->isPlayerController())
|
||||
@@ -428,7 +437,8 @@ void SlipStream::update(float dt)
|
||||
// slipstream length+0.5*kart_length()+0.5*target_kart_length
|
||||
// away from the other kart
|
||||
Vec3 delta = m_kart->getXYZ() - m_target_kart->getXYZ();
|
||||
float l = m_target_kart->getKartProperties()->getSlipstreamLength()
|
||||
float l = m_kart->getKartProperties()->getSlipstreamLength() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamLength()
|
||||
+ 0.5f*( m_target_kart->getKartLength()
|
||||
+m_kart->getKartLength() );
|
||||
if(delta.length2_2d() > l*l)
|
||||
@@ -469,7 +479,8 @@ void SlipStream::update(float dt)
|
||||
m_slipstream_mode = SS_USE;
|
||||
m_kart->handleZipper();
|
||||
m_slipstream_time =
|
||||
m_kart->getKartProperties()->getSlipstreamCollectTime();
|
||||
m_kart->getKartProperties()->getSlipstreamCollectTime() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamCollectTime();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -490,7 +501,8 @@ void SlipStream::update(float dt)
|
||||
setIntensity(m_slipstream_time, m_target_kart);
|
||||
|
||||
m_slipstream_mode = SS_COLLECT;
|
||||
if(m_slipstream_time>m_kart->getKartProperties()->getSlipstreamCollectTime())
|
||||
if(m_slipstream_time>m_kart->getKartProperties()->getSlipstreamCollectTime() *
|
||||
m_kart->getPlayerDifficulty()->getSlipstreamCollectTime())
|
||||
{
|
||||
setIntensity(1.0f, m_target_kart);
|
||||
}
|
||||
|
||||
@@ -171,4 +171,4 @@ void STKTextBillboard::collectChar(video::ITexture* texture,
|
||||
const video::SColor* const colors)
|
||||
{
|
||||
m_chars.push_back(STKTextBillboardChar(texture, destRect, sourceRect, colors));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,10 +286,7 @@ SetTexture(GLMesh &mesh, unsigned i, bool isSrgb, const std::string &matname)
|
||||
{
|
||||
if (!mesh.textures[i])
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::fatal("STKMesh", "Missing texture %d for material %s, mesh <%s>",
|
||||
i, matname.c_str(), mesh.debug_name.c_str());
|
||||
#endif
|
||||
Log::fatal("STKMesh", "Missing texture %d for material %s", i, matname.c_str());
|
||||
return;
|
||||
}
|
||||
compressTexture(mesh.textures[i], isSrgb);
|
||||
|
||||
@@ -54,9 +54,6 @@ core::vector3df getWindDir();
|
||||
class STKMeshCommon
|
||||
{
|
||||
protected:
|
||||
bool m_culledForPlayerCam;
|
||||
bool m_culledForShadowCam[4];
|
||||
bool m_culledForRSMCam;
|
||||
std::string m_debug_name;
|
||||
|
||||
public:
|
||||
@@ -66,12 +63,6 @@ public:
|
||||
virtual void updateGL() = 0;
|
||||
virtual bool glow() const = 0;
|
||||
virtual bool isImmediateDraw() const { return false; }
|
||||
bool isCulledForPlayerCam() const { return m_culledForPlayerCam; }
|
||||
void setCulledForPlayerCam(bool v) { m_culledForPlayerCam = v; }
|
||||
bool isCulledForShadowCam(unsigned cascade) const { return m_culledForShadowCam[cascade]; }
|
||||
void setCulledForShadowCam(unsigned cascade, bool v) { m_culledForShadowCam[cascade] = v; }
|
||||
bool isCulledForRSMCam() const { return m_culledForRSMCam; }
|
||||
void setCulledForRSMCam(bool v) { m_culledForRSMCam = v; }
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
|
||||
@@ -110,7 +110,7 @@ void InstanceFiller<GlowInstanceData>::add(GLMesh *mesh, scene::ISceneNode *node
|
||||
template<typename T>
|
||||
static void
|
||||
FillInstances_impl(std::vector<std::pair<GLMesh *, scene::ISceneNode *> > InstanceList, T * InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer,
|
||||
size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &PolyCount, std::function<bool (const scene::ISceneNode *)> cull_func)
|
||||
size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &PolyCount)
|
||||
{
|
||||
// Should never be empty
|
||||
GLMesh *mesh = InstanceList.front().first;
|
||||
@@ -120,9 +120,8 @@ FillInstances_impl(std::vector<std::pair<GLMesh *, scene::ISceneNode *> > Instan
|
||||
{
|
||||
auto &Tp = InstanceList[i];
|
||||
scene::ISceneNode *node = Tp.second;
|
||||
if (cull_func(node))
|
||||
continue;
|
||||
InstanceFiller<T>::add(mesh, node, InstanceBuffer[InstanceBufferOffset++]);
|
||||
assert(InstanceBufferOffset * sizeof(T) < 10000 * sizeof(InstanceDataDualTex));
|
||||
}
|
||||
|
||||
DrawElementsIndirectCommand &CurrentCommand = CommandBuffer[CommandBufferOffset++];
|
||||
@@ -138,19 +137,18 @@ FillInstances_impl(std::vector<std::pair<GLMesh *, scene::ISceneNode *> > Instan
|
||||
template<typename T>
|
||||
static
|
||||
void FillInstances(const std::unordered_map<scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > &GatheredGLMesh, std::vector<GLMesh *> &InstancedList,
|
||||
T *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &Polycount,
|
||||
std::function<bool (const scene::ISceneNode *)> cull_func)
|
||||
T *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &Polycount)
|
||||
{
|
||||
auto It = GatheredGLMesh.begin(), E = GatheredGLMesh.end();
|
||||
for (; It != E; ++It)
|
||||
{
|
||||
FillInstances_impl<T>(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, Polycount, cull_func);
|
||||
FillInstances_impl<T>(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, Polycount);
|
||||
if (!UserConfigParams::m_azdo)
|
||||
InstancedList.push_back(It->second.front().first);
|
||||
}
|
||||
}
|
||||
|
||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForSolidPass[Material::SHADERTYPE_COUNT];
|
||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForSolidPass[Material::SHADERTYPE_COUNT], MeshForShadowPass[Material::SHADERTYPE_COUNT][4], MeshForRSM[Material::SHADERTYPE_COUNT];
|
||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForGlowPass;
|
||||
static std::vector <STKMeshCommon *> DeferredUpdate;
|
||||
|
||||
@@ -200,7 +198,8 @@ bool isCulledPrecise(const scene::ICameraSceneNode *cam, const scene::ISceneNode
|
||||
|
||||
static void
|
||||
handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *ImmediateDraw,
|
||||
const scene::ICameraSceneNode *cam, scene::ICameraSceneNode *shadowcam[4], const scene::ICameraSceneNode *rsmcam)
|
||||
const scene::ICameraSceneNode *cam, scene::ICameraSceneNode *shadowcam[4], const scene::ICameraSceneNode *rsmcam,
|
||||
bool &culledforcam, bool culledforshadowcam[4], bool &culledforrsm)
|
||||
{
|
||||
STKMeshCommon *node = dynamic_cast<STKMeshCommon*>(Node);
|
||||
if (!node)
|
||||
@@ -249,6 +248,11 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
return;
|
||||
}
|
||||
|
||||
culledforcam = culledforcam || isCulledPrecise(cam, Node);
|
||||
culledforrsm = culledforrsm || isCulledPrecise(rsmcam, Node);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
culledforshadowcam[i] = culledforshadowcam[i] || isCulledPrecise(shadowcam[i], Node);
|
||||
|
||||
// Transparent
|
||||
GLMesh *mesh;
|
||||
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
||||
@@ -284,21 +288,48 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
for_in(mesh, node->TransparentMesh[TM_DISPLACEMENT])
|
||||
pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation());
|
||||
|
||||
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
|
||||
if (!culledforcam)
|
||||
{
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
|
||||
{
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
if (node->glow())
|
||||
MeshForGlowPass[mesh->mb].emplace_back(mesh, Node);
|
||||
|
||||
if (Mat != Material::SHADERTYPE_SPLATTING && mesh->TextureMatrix.isIdentity())
|
||||
MeshForSolidPass[Mat][mesh->mb].emplace_back(mesh, Node);
|
||||
else
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
if (node->glow())
|
||||
MeshForGlowPass[mesh->mb].emplace_back(mesh, Node);
|
||||
|
||||
if (Mat != Material::SHADERTYPE_SPLATTING && mesh->TextureMatrix.isIdentity())
|
||||
MeshForSolidPass[Mat][mesh->mb].emplace_back(mesh, Node);
|
||||
else
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
switch (Mat)
|
||||
{
|
||||
case Material::SHADERTYPE_SOLID:
|
||||
ListMatDefault::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_ALPHA_TEST:
|
||||
ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SOLID_UNLIT:
|
||||
ListMatUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SPLATTING:
|
||||
ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
switch (Mat)
|
||||
{
|
||||
case Material::SHADERTYPE_SOLID:
|
||||
@@ -307,65 +338,44 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
case Material::SHADERTYPE_ALPHA_TEST:
|
||||
ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_NORMAL_MAP:
|
||||
ListMatNormalMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_DETAIL_MAP:
|
||||
ListMatDetails::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SOLID_UNLIT:
|
||||
ListMatUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SPHERE_MAP:
|
||||
ListMatSphereMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SPLATTING:
|
||||
ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_VEGETATION:
|
||||
ListMatGrass::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isCulledPrecise(cam, Node))
|
||||
continue;
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
switch (Mat)
|
||||
{
|
||||
case Material::SHADERTYPE_SOLID:
|
||||
ListMatDefault::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_ALPHA_TEST:
|
||||
ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_NORMAL_MAP:
|
||||
ListMatNormalMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_DETAIL_MAP:
|
||||
ListMatDetails::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SOLID_UNLIT:
|
||||
ListMatUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SPHERE_MAP:
|
||||
ListMatSphereMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SPLATTING:
|
||||
ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_VEGETATION:
|
||||
ListMatGrass::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!UserConfigParams::m_shadows)
|
||||
return;
|
||||
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
|
||||
for (unsigned cascade = 0; cascade < 4; ++cascade)
|
||||
{
|
||||
for (unsigned cascade = 0; cascade < 4; ++cascade)
|
||||
if (culledforshadowcam[cascade])
|
||||
continue;
|
||||
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
|
||||
{
|
||||
if (!irr_driver->hasARB_draw_indirect())
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
MeshForShadowPass[Mat][cascade][mesh->mb].emplace_back(mesh, Node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isCulledPrecise(shadowcam[cascade], Node))
|
||||
continue;
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
|
||||
@@ -403,53 +413,60 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
}
|
||||
if (!UserConfigParams::m_gi)
|
||||
return;
|
||||
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
|
||||
if (!culledforrsm)
|
||||
{
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
|
||||
{
|
||||
if (Mat == Material::SHADERTYPE_SPLATTING)
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
{
|
||||
if (Mat == Material::SHADERTYPE_SPLATTING)
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
MeshForRSM[Mat][mesh->mb].emplace_back(mesh, Node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isCulledPrecise(rsmcam, Node))
|
||||
continue;
|
||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||
ModelMatrix.getInverse(InvModelMatrix);
|
||||
|
||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||
{
|
||||
switch (Mat)
|
||||
{
|
||||
case Material::SHADERTYPE_SOLID:
|
||||
ListMatDefault::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_ALPHA_TEST:
|
||||
ListMatAlphaRef::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_NORMAL_MAP:
|
||||
ListMatNormalMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_DETAIL_MAP:
|
||||
ListMatDetails::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SOLID_UNLIT:
|
||||
ListMatUnlit::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SPHERE_MAP:
|
||||
ListMatSphereMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SPLATTING:
|
||||
ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_VEGETATION:
|
||||
ListMatGrass::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
break;
|
||||
switch (Mat)
|
||||
{
|
||||
case Material::SHADERTYPE_SOLID:
|
||||
ListMatDefault::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_ALPHA_TEST:
|
||||
ListMatAlphaRef::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_NORMAL_MAP:
|
||||
ListMatNormalMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_DETAIL_MAP:
|
||||
ListMatDetails::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SOLID_UNLIT:
|
||||
ListMatUnlit::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SPHERE_MAP:
|
||||
ListMatSphereMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->TextureMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_SPLATTING:
|
||||
ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix);
|
||||
break;
|
||||
case Material::SHADERTYPE_VEGETATION:
|
||||
ListMatGrass::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, windDir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,7 +475,8 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
||||
|
||||
static void
|
||||
parseSceneManager(core::list<scene::ISceneNode*> List, std::vector<scene::ISceneNode *> *ImmediateDraw,
|
||||
const scene::ICameraSceneNode* cam, scene::ICameraSceneNode *shadow_cam[4], const scene::ICameraSceneNode *rsmcam)
|
||||
const scene::ICameraSceneNode* cam, scene::ICameraSceneNode *shadow_cam[4], const scene::ICameraSceneNode *rsmcam,
|
||||
bool culledforcam, bool culledforshadowcam[4], bool culledforrsm)
|
||||
{
|
||||
core::list<scene::ISceneNode*>::Iterator I = List.begin(), E = List.end();
|
||||
for (; I != E; ++I)
|
||||
@@ -483,9 +501,13 @@ parseSceneManager(core::list<scene::ISceneNode*> List, std::vector<scene::IScene
|
||||
continue;
|
||||
}
|
||||
|
||||
handleSTKCommon(*I, ImmediateDraw, cam, shadow_cam, rsmcam);
|
||||
bool newculledforcam = culledforcam;
|
||||
bool newculledforrsm = culledforrsm;
|
||||
bool newculledforshadowcam[4] = { culledforshadowcam[0], culledforshadowcam[1], culledforshadowcam[2], culledforshadowcam[3] };
|
||||
|
||||
parseSceneManager((*I)->getChildren(), ImmediateDraw, cam, shadow_cam, rsmcam);
|
||||
handleSTKCommon(*I, ImmediateDraw, cam, shadow_cam, rsmcam, newculledforcam, newculledforshadowcam, newculledforrsm);
|
||||
|
||||
parseSceneManager((*I)->getChildren(), ImmediateDraw, cam, shadow_cam, rsmcam, newculledforcam, newculledforshadowcam, newculledforrsm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,16 +515,24 @@ template<Material::ShaderType Mat, typename T> static void
|
||||
GenDrawCalls(unsigned cascade, std::vector<GLMesh *> &InstancedList,
|
||||
T *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &PolyCount)
|
||||
{
|
||||
std::function<bool(const scene::ISceneNode *)> shadowculling = [&](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForShadowCam(cascade); };
|
||||
if (irr_driver->hasARB_draw_indirect())
|
||||
ShadowPassCmd::getInstance()->Offset[cascade][Mat] = CommandBufferOffset; // Store command buffer offset
|
||||
FillInstances<T>(MeshForSolidPass[Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, PolyCount, shadowculling);
|
||||
FillInstances<T>(MeshForShadowPass[Mat][cascade], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, PolyCount);
|
||||
if (UserConfigParams::m_azdo)
|
||||
ShadowPassCmd::getInstance()->Size[cascade][Mat] = CommandBufferOffset - ShadowPassCmd::getInstance()->Offset[cascade][Mat];
|
||||
}
|
||||
|
||||
int enableOpenMP;
|
||||
|
||||
static void FixBoundingBoxes(scene::ISceneNode* node)
|
||||
{
|
||||
for (scene::ISceneNode *child : node->getChildren())
|
||||
{
|
||||
FixBoundingBoxes(child);
|
||||
const_cast<core::aabbox3df&>(node->getBoundingBox()).addInternalBox(child->getBoundingBox());
|
||||
}
|
||||
}
|
||||
|
||||
void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
{
|
||||
windDir = getWindDir();
|
||||
@@ -527,24 +557,24 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
ListInstancedGlow::getInstance()->clear();
|
||||
|
||||
for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat)
|
||||
{
|
||||
MeshForSolidPass[Mat].clear();
|
||||
MeshForRSM[Mat].clear();
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
MeshForShadowPass[Mat][i].clear();
|
||||
}
|
||||
MeshForGlowPass.clear();
|
||||
DeferredUpdate.clear();
|
||||
core::list<scene::ISceneNode*> List = m_scene_manager->getRootSceneNode()->getChildren();
|
||||
|
||||
parseSceneManager(List, ImmediateDrawList::getInstance(), camnode, m_shadow_camnodes, m_suncam);
|
||||
PROFILER_PUSH_CPU_MARKER("- culling", 0xFF, 0xFF, 0x0);
|
||||
for (scene::ISceneNode *child : List)
|
||||
FixBoundingBoxes(child);
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < (int)DeferredUpdate.size(); i++)
|
||||
{
|
||||
scene::ISceneNode *node = dynamic_cast<scene::ISceneNode *>(DeferredUpdate[i]);
|
||||
DeferredUpdate[i]->setCulledForPlayerCam(isCulledPrecise(camnode, node));
|
||||
DeferredUpdate[i]->setCulledForRSMCam(isCulledPrecise(m_suncam, node));
|
||||
DeferredUpdate[i]->setCulledForShadowCam(0, isCulledPrecise(m_shadow_camnodes[0], node));
|
||||
DeferredUpdate[i]->setCulledForShadowCam(1, isCulledPrecise(m_shadow_camnodes[1], node));
|
||||
DeferredUpdate[i]->setCulledForShadowCam(2, isCulledPrecise(m_shadow_camnodes[2], node));
|
||||
DeferredUpdate[i]->setCulledForShadowCam(3, isCulledPrecise(m_shadow_camnodes[3], node));
|
||||
}
|
||||
bool cam = false, rsmcam = false;
|
||||
bool shadowcam[4] = { false, false, false, false };
|
||||
parseSceneManager(List, ImmediateDrawList::getInstance(), camnode, m_shadow_camnodes, m_suncam, cam, shadowcam, rsmcam);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
// Add a 1 s timeout
|
||||
if (!m_sync)
|
||||
@@ -615,7 +645,6 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Draw Command upload", 0xFF, 0x0, 0xFF);
|
||||
|
||||
auto playercamculling = [](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForPlayerCam(); };
|
||||
#pragma omp parallel sections if(enableOpenMP)
|
||||
{
|
||||
#pragma omp section
|
||||
@@ -632,23 +661,23 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
|
||||
// Default Material
|
||||
SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_SOLID] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_SOLID], ListInstancedMatDefault::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_SOLID], ListInstancedMatDefault::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
SolidPassCmd::getInstance()->Size[Material::SHADERTYPE_SOLID] = current_cmd - SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_SOLID];
|
||||
// Alpha Ref
|
||||
SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_ALPHA_TEST] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_ALPHA_TEST], ListInstancedMatAlphaRef::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_ALPHA_TEST], ListInstancedMatAlphaRef::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
SolidPassCmd::getInstance()->Size[Material::SHADERTYPE_ALPHA_TEST] = current_cmd - SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_ALPHA_TEST];
|
||||
// Unlit
|
||||
SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_SOLID_UNLIT] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_SOLID_UNLIT], ListInstancedMatUnlit::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_SOLID_UNLIT], ListInstancedMatUnlit::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
SolidPassCmd::getInstance()->Size[Material::SHADERTYPE_SOLID_UNLIT] = current_cmd - SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_SOLID_UNLIT];
|
||||
// Spheremap
|
||||
SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_SPHERE_MAP] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_SPHERE_MAP], ListInstancedMatSphereMap::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_SPHERE_MAP], ListInstancedMatSphereMap::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
SolidPassCmd::getInstance()->Size[Material::SHADERTYPE_SPHERE_MAP] = current_cmd - SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_SPHERE_MAP];
|
||||
// Grass
|
||||
SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_VEGETATION] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_VEGETATION], ListInstancedMatGrass::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_VEGETATION], ListInstancedMatGrass::getInstance()->SolidPass, InstanceBufferDualTex, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
SolidPassCmd::getInstance()->Size[Material::SHADERTYPE_VEGETATION] = current_cmd - SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_VEGETATION];
|
||||
|
||||
if (!irr_driver->hasBufferStorageExtension())
|
||||
@@ -661,11 +690,11 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
|
||||
// Detail
|
||||
SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_DETAIL_MAP] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_DETAIL_MAP], ListInstancedMatDetails::getInstance()->SolidPass, InstanceBufferThreeTex, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_DETAIL_MAP], ListInstancedMatDetails::getInstance()->SolidPass, InstanceBufferThreeTex, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
SolidPassCmd::getInstance()->Size[Material::SHADERTYPE_DETAIL_MAP] = current_cmd - SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_DETAIL_MAP];
|
||||
// Normal Map
|
||||
SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_NORMAL_MAP] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->SolidPass, InstanceBufferThreeTex, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->SolidPass, InstanceBufferThreeTex, CmdBuffer, offset, current_cmd, SolidPoly);
|
||||
SolidPassCmd::getInstance()->Size[Material::SHADERTYPE_NORMAL_MAP] = current_cmd - SolidPassCmd::getInstance()->Offset[Material::SHADERTYPE_NORMAL_MAP];
|
||||
|
||||
|
||||
@@ -695,7 +724,7 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
for (; It != E; ++It)
|
||||
{
|
||||
size_t Polycnt = 0;
|
||||
FillInstances_impl<GlowInstanceData>(It->second, GlowInstanceBuffer, GlowCmdBuffer, offset, current_cmd, Polycnt, playercamculling);
|
||||
FillInstances_impl<GlowInstanceData>(It->second, GlowInstanceBuffer, GlowCmdBuffer, offset, current_cmd, Polycnt);
|
||||
if (!UserConfigParams::m_azdo)
|
||||
ListInstancedGlow::getInstance()->push_back(It->second.front().first);
|
||||
}
|
||||
@@ -747,7 +776,6 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
}
|
||||
#pragma omp section
|
||||
{
|
||||
auto rsmcamculling = [](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForRSMCam(); };
|
||||
size_t offset = 0, current_cmd = 0;
|
||||
if (!irr_driver->hasBufferStorageExtension())
|
||||
{
|
||||
@@ -759,23 +787,23 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||
|
||||
// Default Material
|
||||
RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_SOLID] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_SOLID], ListInstancedMatDefault::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
FillInstances(MeshForRSM[Material::SHADERTYPE_SOLID], ListInstancedMatDefault::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
RSMPassCmd::getInstance()->Size[Material::SHADERTYPE_SOLID] = current_cmd - RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_SOLID];
|
||||
// Alpha Ref
|
||||
RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_ALPHA_TEST] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_ALPHA_TEST], ListInstancedMatAlphaRef::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
FillInstances(MeshForRSM[Material::SHADERTYPE_ALPHA_TEST], ListInstancedMatAlphaRef::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
RSMPassCmd::getInstance()->Size[Material::SHADERTYPE_ALPHA_TEST] = current_cmd - RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_ALPHA_TEST];
|
||||
// Unlit
|
||||
RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_SOLID_UNLIT] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_SOLID_UNLIT], ListInstancedMatUnlit::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
FillInstances(MeshForRSM[Material::SHADERTYPE_SOLID_UNLIT], ListInstancedMatUnlit::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
RSMPassCmd::getInstance()->Size[Material::SHADERTYPE_SOLID_UNLIT] = current_cmd - RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_SOLID_UNLIT];
|
||||
// Detail
|
||||
RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_DETAIL_MAP] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_DETAIL_MAP], ListInstancedMatDetails::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
FillInstances(MeshForRSM[Material::SHADERTYPE_DETAIL_MAP], ListInstancedMatDetails::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
RSMPassCmd::getInstance()->Size[Material::SHADERTYPE_DETAIL_MAP] = current_cmd - RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_DETAIL_MAP];
|
||||
// Normal Map
|
||||
RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_NORMAL_MAP] = current_cmd;
|
||||
FillInstances(MeshForSolidPass[Material::SHADERTYPE_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||
FillInstances(MeshForRSM[Material::SHADERTYPE_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly);
|
||||
RSMPassCmd::getInstance()->Size[Material::SHADERTYPE_NORMAL_MAP] = current_cmd - RSMPassCmd::getInstance()->Offset[Material::SHADERTYPE_NORMAL_MAP];
|
||||
|
||||
if (!irr_driver->hasBufferStorageExtension())
|
||||
|
||||
@@ -67,4 +67,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,7 @@ Weather::Weather(bool lightning, std::string sound)
|
||||
|
||||
if (m_lightning)
|
||||
{
|
||||
m_thunder_sound = SFXManager::get()->createSoundSource("thunder");
|
||||
m_thunder_sound = SFXManager::get()->createSoundSource("thunder");
|
||||
}
|
||||
|
||||
if (sound != "")
|
||||
@@ -50,10 +50,10 @@ Weather::Weather(bool lightning, std::string sound)
|
||||
|
||||
Weather::~Weather()
|
||||
{
|
||||
if (m_thunder_sound != NULL)
|
||||
if (m_thunder_sound != NULL)
|
||||
m_thunder_sound->deleteSFX();
|
||||
|
||||
if (m_weather_sound != NULL)
|
||||
if (m_weather_sound != NULL)
|
||||
m_weather_sound->deleteSFX();
|
||||
} // ~Weather
|
||||
|
||||
@@ -73,7 +73,7 @@ void Weather::update(float dt)
|
||||
{
|
||||
gui_base->doLightning();
|
||||
|
||||
if (m_thunder_sound)
|
||||
if (m_thunder_sound)
|
||||
{
|
||||
m_thunder_sound->play();
|
||||
}
|
||||
@@ -89,9 +89,9 @@ void Weather::update(float dt)
|
||||
|
||||
void Weather::playSound()
|
||||
{
|
||||
if (m_weather_sound)
|
||||
if (m_weather_sound)
|
||||
{
|
||||
m_weather_sound->setLoop(true);
|
||||
m_weather_sound->play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2082,6 +2082,20 @@ void Skin::drawBadgeOn(const Widget* widget, const core::recti& rect)
|
||||
"hourglass.png");
|
||||
doDrawBadge(texture, rect, max_icon_size, true);
|
||||
}
|
||||
if (widget->m_badges & ZIPPER_BADGE)
|
||||
{
|
||||
float max_icon_size = 0.43f;
|
||||
video::ITexture* texture = irr_driver->getTexture(FileManager::MODEL,
|
||||
"zipper_collect.png");
|
||||
doDrawBadge(texture, rect, max_icon_size, false);
|
||||
}
|
||||
if (widget->m_badges & ANCHOR_BADGE)
|
||||
{
|
||||
float max_icon_size = 0.43f;
|
||||
video::ITexture* texture = irr_driver->getTexture(FileManager::MODEL,
|
||||
"anchor-icon.png");
|
||||
doDrawBadge(texture, rect, max_icon_size, false);
|
||||
}
|
||||
} // drawBadgeOn
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -60,19 +60,23 @@ namespace GUIEngine
|
||||
enum BadgeType
|
||||
{
|
||||
/** display a lock on the widget, to mean a certain game feature is locked */
|
||||
LOCKED_BADGE = 1,
|
||||
LOCKED_BADGE = 1,
|
||||
/** display a green check on a widget, useful e.g. to display confirmation */
|
||||
OK_BADGE = 2,
|
||||
OK_BADGE = 2,
|
||||
/** display a red mark badge on the widget, useful e.g. to warn of an invalid choice */
|
||||
BAD_BADGE = 4,
|
||||
BAD_BADGE = 4,
|
||||
/** display a trophy badge on the widget, useful e.g. for challenges */
|
||||
TROPHY_BADGE = 8,
|
||||
TROPHY_BADGE = 8,
|
||||
/** A gamepad icon */
|
||||
GAMEPAD_BADGE = 16,
|
||||
GAMEPAD_BADGE = 16,
|
||||
/** A keyboard icon */
|
||||
KEYBOARD_BADGE = 32,
|
||||
/** An hourglass badge to indicate loading */
|
||||
LOADING_BADGE = 64
|
||||
LOADING_BADGE = 64,
|
||||
/** A zipper badge to indicate that this player receives a boost */
|
||||
ZIPPER_BADGE = 128,
|
||||
/** A anchor badge to indicate that this player receives a handicap */
|
||||
ANCHOR_BADGE = 256
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -38,14 +38,11 @@ using namespace irr;
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
KartStatsWidget::KartStatsWidget(core::recti area, const int player_id,
|
||||
std::string kart_group,
|
||||
bool multiplayer) : Widget(WTYPE_DIV)
|
||||
std::string kart_group, bool multiplayer,
|
||||
bool display_text) : Widget(WTYPE_DIV)
|
||||
{
|
||||
m_player_id = player_id;
|
||||
|
||||
setSize(area.UpperLeftCorner.X, area.UpperLeftCorner.Y,
|
||||
area.getWidth(), area.getHeight() );
|
||||
|
||||
const std::string default_kart = UserConfigParams::m_default_kart;
|
||||
const KartProperties* props =
|
||||
kart_properties_manager->getKart(default_kart);
|
||||
@@ -72,19 +69,16 @@ KartStatsWidget::KartStatsWidget(core::recti area, const int player_id,
|
||||
}
|
||||
|
||||
|
||||
const int offset = (m_h - (SKILL_COUNT*m_skill_bar_h)) / 2;
|
||||
for (int i = 0; i < SKILL_COUNT; ++i)
|
||||
{
|
||||
irr::core::recti skillArea(m_skill_bar_x, m_skill_bar_y + offset*i,
|
||||
m_skill_bar_x + m_skill_bar_w,
|
||||
m_skill_bar_y + m_skill_bar_h + offset*i);
|
||||
irr::core::recti skillArea(0, 0, 1, 1);
|
||||
|
||||
SkillLevelWidget* skill_bar = NULL;
|
||||
|
||||
skill_bar = new SkillLevelWidget(skillArea, m_player_id, multiplayer);
|
||||
skill_bar = new SkillLevelWidget(skillArea, m_player_id, multiplayer, display_text);
|
||||
|
||||
m_skills.push_back(skill_bar);
|
||||
m_children.push_back(skill_bar);
|
||||
m_skills.push_back(skill_bar);
|
||||
m_children.push_back(skill_bar);
|
||||
}
|
||||
|
||||
m_skills[SKILL_MASS]->setValue((int)(props->getMass()/5));
|
||||
@@ -99,6 +93,8 @@ KartStatsWidget::KartStatsWidget(core::recti area, const int player_id,
|
||||
m_skills[SKILL_POWER]->setLabel("POWER");
|
||||
m_skills[SKILL_POWER]->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_power", m_player_id);
|
||||
|
||||
move(area.UpperLeftCorner.X, area.UpperLeftCorner.Y,
|
||||
area.getWidth(), area.getHeight());
|
||||
} // KartStatsWidget
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -114,11 +110,14 @@ void KartStatsWidget::move(int x, int y, int w, int h)
|
||||
{
|
||||
Widget::move(x,y,w,h);
|
||||
setSize(m_x, m_y, m_w, m_h);
|
||||
int offset = (m_h - (SKILL_COUNT*m_skill_bar_h)) / 2;
|
||||
int margin = m_h / SKILL_COUNT - m_skill_bar_h / 2;
|
||||
if (margin > m_skill_bar_h)
|
||||
margin = m_skill_bar_h;
|
||||
int offset = (m_h - (SKILL_COUNT * margin)) / 2;
|
||||
for (int i = 0; i < SKILL_COUNT; ++i)
|
||||
{
|
||||
m_skills[i]->move(m_skill_bar_x,
|
||||
m_y + offset + m_skill_bar_h*i,
|
||||
m_y + offset + margin * i,
|
||||
m_skill_bar_w,
|
||||
m_skill_bar_h);
|
||||
}
|
||||
@@ -163,4 +162,13 @@ void KartStatsWidget::setSize(const int x, const int y, const int w, const int h
|
||||
m_skill_bar_y = y + h/2 - m_skill_bar_h/2;
|
||||
} // setSize
|
||||
|
||||
void KartStatsWidget::setDisplayText(bool display_text)
|
||||
{
|
||||
for (int i = 0; i < SKILL_COUNT; ++i)
|
||||
{
|
||||
m_skills[i]->setDisplayText(display_text);
|
||||
}
|
||||
} // setDisplayText
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -37,28 +37,26 @@ namespace GUIEngine
|
||||
* \brief A progress bar widget.
|
||||
* \ingroup widgetsgroup
|
||||
*/
|
||||
|
||||
|
||||
class KartStatsWidget : public Widget
|
||||
class KartStatsWidget : public Widget
|
||||
{
|
||||
/** 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 */
|
||||
virtual int getWidthNeededAroundLabel() const { return 35; }
|
||||
|
||||
|
||||
/** 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 */
|
||||
virtual int getHeightNeededAroundLabel() const { return 4; }
|
||||
|
||||
|
||||
/** widget coordinates */
|
||||
int m_skill_bar_x, m_skill_bar_y, m_skill_bar_h, m_skill_bar_w;
|
||||
|
||||
|
||||
int m_player_id;
|
||||
|
||||
std::vector<SkillLevelWidget*> m_skills;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
enum Stats
|
||||
{
|
||||
SKILL_MASS,
|
||||
@@ -68,10 +66,10 @@ class KartStatsWidget : public Widget
|
||||
};
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
|
||||
KartStatsWidget(core::recti area, const int player_id,
|
||||
std::string kart_group,
|
||||
bool multiplayer);
|
||||
std::string kart_group, bool multiplayer,
|
||||
bool display_text);
|
||||
virtual ~KartStatsWidget() {};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@@ -95,9 +93,12 @@ class KartStatsWidget : public Widget
|
||||
|
||||
/** Change the value of the widget, it must be a percent. */
|
||||
void setValue(Stats type, int value);
|
||||
|
||||
|
||||
/** Get the current values of the widget. */
|
||||
int getValue(Stats type);
|
||||
|
||||
/** If the labels should be displayed. */
|
||||
void setDisplayText(bool display_text);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
711
src/guiengine/widgets/player_kart_widget.cpp
Normal file
@@ -0,0 +1,711 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
//
|
||||
// Copyright (C) 2006-2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "config/player_manager.hpp"
|
||||
#include "guiengine/widgets/kart_stats_widget.hpp"
|
||||
#include "guiengine/widgets/model_view_widget.hpp"
|
||||
#include "guiengine/widgets/player_kart_widget.hpp"
|
||||
#include "guiengine/widgets/player_name_spinner.hpp"
|
||||
#include "input/input_device.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "online/online_profile.hpp"
|
||||
#include "states_screens/kart_selection.hpp"
|
||||
#include <IGUIEnvironment.h>
|
||||
|
||||
static const char RANDOM_KART_ID[] = "randomkart";
|
||||
|
||||
using namespace GUIEngine;
|
||||
|
||||
PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
|
||||
StateManager::ActivePlayer* associated_player,
|
||||
Online::OnlineProfile* associated_user,
|
||||
core::recti area, const int player_id,
|
||||
std::string kart_group,
|
||||
const int irrlicht_widget_id) : Widget(WTYPE_DIV)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (associated_player)
|
||||
assert(associated_player->ok());
|
||||
m_magic_number = 0x33445566;
|
||||
#endif
|
||||
m_ready_text = NULL;
|
||||
m_parent_screen = parent;
|
||||
|
||||
m_associated_user = associated_user;
|
||||
m_associated_player = associated_player;
|
||||
x_speed = 1.0f;
|
||||
y_speed = 1.0f;
|
||||
w_speed = 1.0f;
|
||||
h_speed = 1.0f;
|
||||
m_ready = false;
|
||||
m_handicapped = false;
|
||||
m_not_updated_yet = true;
|
||||
|
||||
m_irrlicht_widget_id = irrlicht_widget_id;
|
||||
|
||||
m_player_id = player_id;
|
||||
m_properties[PROP_ID] = StringUtils::insertValues("@p%i", m_player_id);
|
||||
|
||||
setSize(area.UpperLeftCorner.X, area.UpperLeftCorner.Y,
|
||||
area.getWidth(), area.getHeight() );
|
||||
target_x = m_x;
|
||||
target_y = m_y;
|
||||
target_w = m_w;
|
||||
target_h = m_h;
|
||||
|
||||
// ---- Player identity spinner
|
||||
m_player_ident_spinner = NULL;
|
||||
|
||||
m_player_ident_spinner = new PlayerNameSpinner(parent, m_player_id);
|
||||
m_player_ident_spinner->m_x = player_name_x;
|
||||
m_player_ident_spinner->m_y = player_name_y;
|
||||
m_player_ident_spinner->m_w = player_name_w;
|
||||
m_player_ident_spinner->m_h = player_name_h;
|
||||
|
||||
// ---- KartStatsWidget
|
||||
m_kart_stats = NULL;
|
||||
|
||||
// area for the stats widget
|
||||
core::recti statsArea;
|
||||
if (!parent->m_multiplayer)
|
||||
{
|
||||
statsArea = core::recti(m_kart_stats_x,
|
||||
m_kart_stats_y,
|
||||
m_kart_stats_x + m_kart_stats_w,
|
||||
m_kart_stats_y + m_kart_stats_h);
|
||||
}
|
||||
else
|
||||
{
|
||||
statsArea = core::recti(m_x , m_y + m_h/2,
|
||||
m_x + m_w, m_y + m_h);
|
||||
}
|
||||
|
||||
|
||||
m_kart_stats = new GUIEngine::KartStatsWidget(statsArea, player_id, kart_group,
|
||||
m_parent_screen->m_multiplayer,
|
||||
!m_parent_screen->m_multiplayer || parent->m_kart_widgets.size() == 0);
|
||||
m_kart_stats->m_properties[PROP_ID] = StringUtils::insertValues("@p%i_stats", m_player_id);
|
||||
m_children.push_back(m_kart_stats);
|
||||
|
||||
if (parent->m_multiplayer && associated_player)
|
||||
{
|
||||
if (associated_player->getDevice()->getType() == DT_KEYBOARD)
|
||||
{
|
||||
m_player_ident_spinner->setBadge(KEYBOARD_BADGE);
|
||||
}
|
||||
else if (associated_player->getDevice()->getType() == DT_GAMEPAD)
|
||||
{
|
||||
m_player_ident_spinner->setBadge(GAMEPAD_BADGE);
|
||||
}
|
||||
}
|
||||
else if (m_associated_user) // online user, FIXME is that useful ?
|
||||
{
|
||||
m_player_ident_spinner->setBadge(OK_BADGE);
|
||||
}
|
||||
|
||||
if (irrlicht_widget_id == -1)
|
||||
{
|
||||
m_player_ident_spinner->m_tab_down_root = g_root_id;
|
||||
}
|
||||
|
||||
spinnerID = StringUtils::insertValues("@p%i_spinner", m_player_id);
|
||||
|
||||
m_player_ident_spinner->m_properties[PROP_ID] = spinnerID;
|
||||
if (parent->m_multiplayer)
|
||||
{
|
||||
const int player_amount = PlayerManager::get()->getNumPlayers();
|
||||
m_player_ident_spinner->m_properties[PROP_MIN_VALUE] = "0";
|
||||
m_player_ident_spinner->m_properties[PROP_MAX_VALUE] =
|
||||
StringUtils::toString(player_amount-1);
|
||||
m_player_ident_spinner->m_properties[PROP_WRAP_AROUND] = "true";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_player_ident_spinner->m_properties[PROP_MIN_VALUE] = "0";
|
||||
m_player_ident_spinner->m_properties[PROP_MAX_VALUE] = "0";
|
||||
}
|
||||
|
||||
//m_player_ident_spinner->m_event_handler = this;
|
||||
m_children.push_back(m_player_ident_spinner);
|
||||
|
||||
// ----- Kart model view
|
||||
m_model_view = new ModelViewWidget();
|
||||
|
||||
m_model_view->m_x = model_x;
|
||||
m_model_view->m_y = model_y;
|
||||
m_model_view->m_w = model_w;
|
||||
m_model_view->m_h = model_h;
|
||||
m_model_view->m_properties[PROP_ID] =
|
||||
StringUtils::insertValues("@p%i_model", m_player_id);
|
||||
//m_model_view->setParent(this);
|
||||
m_children.push_back(m_model_view);
|
||||
|
||||
// Init kart model
|
||||
const std::string default_kart = UserConfigParams::m_default_kart;
|
||||
const KartProperties* props =
|
||||
kart_properties_manager->getKart(default_kart);
|
||||
|
||||
if(!props)
|
||||
{
|
||||
// If the default kart can't be found (e.g. previously a addon
|
||||
// kart was used, but the addon package was removed), use the
|
||||
// first kart as a default. This way we don't have to hardcode
|
||||
// any kart names.
|
||||
int id = kart_properties_manager->getKartByGroup(kart_group, 0);
|
||||
if (id == -1)
|
||||
{
|
||||
props = kart_properties_manager->getKartById(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
props = kart_properties_manager->getKartById(id);
|
||||
}
|
||||
|
||||
if(!props)
|
||||
Log::fatal("KartSelectionScreen", "Can't find default "
|
||||
"kart '%s' nor any other kart.",
|
||||
default_kart.c_str());
|
||||
}
|
||||
m_kartInternalName = props->getIdent();
|
||||
|
||||
const KartModel &kart_model = props->getMasterKartModel();
|
||||
|
||||
float scale = 35.0f;
|
||||
if (kart_model.getLength() > 1.45f)
|
||||
{
|
||||
// if kart is too long, size it down a bit so that it fits
|
||||
scale = 30.0f;
|
||||
}
|
||||
|
||||
m_model_view->addModel( kart_model.getModel(), Vec3(0,0,0),
|
||||
Vec3(scale, scale, scale),
|
||||
kart_model.getBaseFrame() );
|
||||
m_model_view->addModel( kart_model.getWheelModel(0),
|
||||
kart_model.getWheelGraphicsPosition(0) );
|
||||
m_model_view->addModel( kart_model.getWheelModel(1),
|
||||
kart_model.getWheelGraphicsPosition(1) );
|
||||
m_model_view->addModel( kart_model.getWheelModel(2),
|
||||
kart_model.getWheelGraphicsPosition(2) );
|
||||
m_model_view->addModel( kart_model.getWheelModel(3),
|
||||
kart_model.getWheelGraphicsPosition(3) );
|
||||
for(size_t i=0 ; i < kart_model.getSpeedWeightedObjectsCount() ; i++)
|
||||
{
|
||||
const SpeedWeightedObject& obj = kart_model.getSpeedWeightedObject((int)i);
|
||||
m_model_view->addModel(obj.m_model, obj.m_position);
|
||||
}
|
||||
m_model_view->setRotateContinuously( 35.0f );
|
||||
|
||||
// ---- Kart name label
|
||||
m_kart_name = new LabelWidget(true, true);
|
||||
m_kart_name->setText(props->getName(), false);
|
||||
m_kart_name->m_properties[PROP_TEXT_ALIGN] = "center";
|
||||
m_kart_name->m_properties[PROP_ID] =
|
||||
StringUtils::insertValues("@p%i_kartname", m_player_id);
|
||||
m_kart_name->m_x = kart_name_x;
|
||||
m_kart_name->m_y = kart_name_y;
|
||||
m_kart_name->m_w = kart_name_w;
|
||||
m_kart_name->m_h = kart_name_h;
|
||||
m_children.push_back(m_kart_name);
|
||||
} // PlayerKartWidget
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
PlayerKartWidget::~PlayerKartWidget()
|
||||
{
|
||||
if (GUIEngine::getFocusForPlayer(m_player_id) == this)
|
||||
{
|
||||
GUIEngine::focusNothingForPlayer(m_player_id);
|
||||
}
|
||||
|
||||
if (m_player_ident_spinner != NULL)
|
||||
{
|
||||
m_player_ident_spinner->setListener(NULL);
|
||||
|
||||
if (m_player_ident_spinner->getIrrlichtElement() != NULL)
|
||||
{
|
||||
m_player_ident_spinner->getIrrlichtElement()->remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_model_view->getIrrlichtElement() != NULL)
|
||||
m_model_view->getIrrlichtElement()->remove();
|
||||
|
||||
if (m_kart_name->getIrrlichtElement() != NULL)
|
||||
m_kart_name->getIrrlichtElement()->remove();
|
||||
getCurrentScreen()->manualRemoveWidget(this);
|
||||
|
||||
#ifdef DEBUG
|
||||
m_magic_number = 0xDEADBEEF;
|
||||
#endif
|
||||
} // ~PlayerKartWidget
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Called when players are renumbered (changes the player ID) */
|
||||
void PlayerKartWidget::setPlayerID(const int newPlayerID)
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
|
||||
if (StateManager::get()->getActivePlayer(newPlayerID)
|
||||
!= m_associated_player)
|
||||
{
|
||||
Log::error("KartSelectionScreen", "Internal "
|
||||
"inconsistency, PlayerKartWidget has IDs and "
|
||||
"pointers that do not correspond to one player");
|
||||
Log::fatal("KartSelectionScreen", " Player: %p - Index: %d - m_associated_player: %p",
|
||||
StateManager::get()->getActivePlayer(newPlayerID),
|
||||
newPlayerID, m_associated_player);
|
||||
}
|
||||
|
||||
// Remove current focus, but remember it
|
||||
Widget* focus = GUIEngine::getFocusForPlayer(m_player_id);
|
||||
GUIEngine::focusNothingForPlayer(m_player_id);
|
||||
|
||||
// Change the player ID
|
||||
m_player_id = newPlayerID;
|
||||
if (!m_ready)
|
||||
m_player_ident_spinner->setID(m_player_id);
|
||||
m_kart_stats->setDisplayText(m_player_id == 0);
|
||||
// restore previous focus, but with new player ID
|
||||
if (focus != NULL) focus->setFocusForPlayer(m_player_id);
|
||||
|
||||
if (m_player_ident_spinner != NULL)
|
||||
{
|
||||
m_player_ident_spinner->setID(m_player_id);
|
||||
}
|
||||
} // setPlayerID
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the ID of this player */
|
||||
int PlayerKartWidget::getPlayerID() const
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
return m_player_id;
|
||||
} // getPlayerID
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Add the widgets to the current screen */
|
||||
void PlayerKartWidget::add()
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
|
||||
assert(KartSelectionScreen::getRunningInstance()
|
||||
->m_kart_widgets.contains(this));
|
||||
if (m_associated_player) // if player is local
|
||||
{
|
||||
bool mineInList = false;
|
||||
for (unsigned int p=0; p<StateManager::get()->activePlayerCount(); p++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
assert(StateManager::get()->getActivePlayer(p)->ok());
|
||||
#endif
|
||||
if (StateManager::get()->getActivePlayer(p) == m_associated_player)
|
||||
{
|
||||
mineInList = true;
|
||||
}
|
||||
}
|
||||
assert(mineInList);
|
||||
}
|
||||
|
||||
// the first player will have an ID of its own to allow for keyboard
|
||||
// navigation despite this widget being added last
|
||||
if (m_irrlicht_widget_id != -1)
|
||||
m_player_ident_spinner->m_reserved_id = m_irrlicht_widget_id;
|
||||
else
|
||||
m_player_ident_spinner->m_reserved_id = Widget::getNewNoFocusID();
|
||||
|
||||
m_player_ident_spinner->add();
|
||||
m_player_ident_spinner->getIrrlichtElement()->setTabStop(false);
|
||||
m_player_ident_spinner->setListener(this);
|
||||
m_kart_stats->add();
|
||||
m_model_view->add();
|
||||
m_kart_name->add();
|
||||
|
||||
m_model_view->update(0);
|
||||
|
||||
m_player_ident_spinner->clearLabels();
|
||||
|
||||
irr::core::stringw name; // name of the player
|
||||
if (m_associated_player)
|
||||
name = m_associated_player->getProfile()->getName();
|
||||
if (m_associated_user)
|
||||
name = m_associated_user->getUserName();
|
||||
|
||||
if (m_parent_screen->m_multiplayer)
|
||||
{
|
||||
const int player_amount = PlayerManager::get()->getNumPlayers();
|
||||
for (int n=0; n<player_amount; n++)
|
||||
{
|
||||
core::stringw name = PlayerManager::get()->getPlayer(n)->getName();
|
||||
m_player_ident_spinner->addLabel(translations->fribidize(name));
|
||||
if (UserConfigParams::m_per_player_difficulty)
|
||||
// The second player is the same, but with handicap
|
||||
m_player_ident_spinner->addLabel(translations->fribidize(name));
|
||||
}
|
||||
|
||||
// select the right player profile in the spinner
|
||||
m_player_ident_spinner->setValue(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_player_ident_spinner->addLabel(name);
|
||||
m_player_ident_spinner->setVisible(false);
|
||||
}
|
||||
|
||||
// Add anchor badge if the player is handicapped
|
||||
int spinner_value = m_player_ident_spinner->getValue();
|
||||
|
||||
assert(m_player_ident_spinner->getStringValue() == name);
|
||||
} // add
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Get the associated ActivePlayer object*/
|
||||
StateManager::ActivePlayer* PlayerKartWidget::getAssociatedPlayer()
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
return m_associated_player;
|
||||
} // getAssociatedPlayer
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Starts a 'move/resize' animation, by simply passing destination coords.
|
||||
* The animation will then occur on each call to 'onUpdate'. */
|
||||
void PlayerKartWidget::move(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
target_x = x;
|
||||
target_y = y;
|
||||
target_w = w;
|
||||
target_h = h;
|
||||
|
||||
x_speed = abs( m_x - x ) / 300.0f;
|
||||
y_speed = abs( m_y - y ) / 300.0f;
|
||||
w_speed = abs( m_w - w ) / 300.0f;
|
||||
h_speed = abs( m_h - h ) / 300.0f;
|
||||
} // move
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Call when player confirmed his identity and kart */
|
||||
void PlayerKartWidget::markAsReady()
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
if (m_ready) return; // already ready
|
||||
|
||||
m_ready = true;
|
||||
|
||||
stringw playerNameString = m_player_ident_spinner->getStringValue();
|
||||
core::rect<s32> rect(core::position2di(m_player_ident_spinner->m_x,
|
||||
m_player_ident_spinner->m_y),
|
||||
core::dimension2di(m_player_ident_spinner->m_w,
|
||||
m_player_ident_spinner->m_h));
|
||||
// 'playerNameString' is already fribidize, so we need to use
|
||||
// 'insertValues' and not _("...", a) so it's not flipped again
|
||||
m_ready_text =
|
||||
GUIEngine::getGUIEnv()->addStaticText(
|
||||
StringUtils::insertValues(_("%s is ready"),
|
||||
playerNameString).c_str(),
|
||||
rect );
|
||||
m_ready_text->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER );
|
||||
|
||||
m_children.remove(m_player_ident_spinner);
|
||||
m_player_ident_spinner->setListener(NULL);
|
||||
m_player_ident_spinner->getIrrlichtElement()->remove();
|
||||
m_player_ident_spinner->elementRemoved();
|
||||
delete m_player_ident_spinner;
|
||||
m_player_ident_spinner = NULL;
|
||||
|
||||
SFXManager::get()->quickSound( "wee" );
|
||||
|
||||
m_model_view->setRotateTo(30.0f, 1.0f);
|
||||
|
||||
player_name_w = 0;
|
||||
|
||||
m_model_view->setBadge(OK_BADGE);
|
||||
} // markAsReady
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** \return Whether this player confirmed his kart and indent selection */
|
||||
bool PlayerKartWidget::isReady()
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
return m_ready;
|
||||
} // isReady
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** \return Whether this player is handicapped or not */
|
||||
bool PlayerKartWidget::isHandicapped()
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
return m_handicapped;
|
||||
} // isHandicapped
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** Updates the animation (moving/shrinking/etc.) */
|
||||
void PlayerKartWidget::onUpdate(float delta)
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
if (target_x == m_x && target_y == m_y &&
|
||||
target_w == m_w && target_h == m_h) return;
|
||||
|
||||
int move_step = (int)(delta*1000.0f);
|
||||
|
||||
// move x towards target
|
||||
if (m_x < target_x)
|
||||
{
|
||||
m_x += (int)(move_step*x_speed);
|
||||
// don't move to the other side of the target
|
||||
if (m_x > target_x) m_x = target_x;
|
||||
}
|
||||
else if (m_x > target_x)
|
||||
{
|
||||
m_x -= (int)(move_step*x_speed);
|
||||
// don't move to the other side of the target
|
||||
if (m_x < target_x) m_x = target_x;
|
||||
}
|
||||
|
||||
// move y towards target
|
||||
if (m_y < target_y)
|
||||
{
|
||||
m_y += (int)(move_step*y_speed);
|
||||
// don't move to the other side of the target
|
||||
if (m_y > target_y) m_y = target_y;
|
||||
}
|
||||
else if (m_y > target_y)
|
||||
{
|
||||
m_y -= (int)(move_step*y_speed);
|
||||
// don't move to the other side of the target
|
||||
if (m_y < target_y) m_y = target_y;
|
||||
}
|
||||
|
||||
// move w towards target
|
||||
if (m_w < target_w)
|
||||
{
|
||||
m_w += (int)(move_step*w_speed);
|
||||
// don't move to the other side of the target
|
||||
if (m_w > target_w) m_w = target_w;
|
||||
}
|
||||
else if (m_w > target_w)
|
||||
{
|
||||
m_w -= (int)(move_step*w_speed);
|
||||
// don't move to the other side of the target
|
||||
if (m_w < target_w) m_w = target_w;
|
||||
}
|
||||
// move h towards target
|
||||
if (m_h < target_h)
|
||||
{
|
||||
m_h += (int)(move_step*h_speed);
|
||||
// don't move to the other side of the target
|
||||
if (m_h > target_h) m_h = target_h;
|
||||
}
|
||||
else if (m_h > target_h)
|
||||
{
|
||||
m_h -= (int)(move_step*h_speed);
|
||||
// don't move to the other side of the target
|
||||
if (m_h < target_h) m_h = target_h;
|
||||
}
|
||||
|
||||
setSize(m_x, m_y, m_w, m_h);
|
||||
|
||||
if (m_player_ident_spinner != NULL)
|
||||
{
|
||||
m_player_ident_spinner->move(player_name_x,
|
||||
player_name_y,
|
||||
player_name_w,
|
||||
player_name_h );
|
||||
}
|
||||
if (m_ready_text != NULL)
|
||||
{
|
||||
m_ready_text->setRelativePosition(
|
||||
core::recti(core::position2di(player_name_x, player_name_y),
|
||||
core::dimension2di(player_name_w, player_name_h)) );
|
||||
}
|
||||
if (!m_parent_screen->m_multiplayer)
|
||||
{
|
||||
m_kart_stats->move(m_kart_stats_x,
|
||||
m_kart_stats_y,
|
||||
m_kart_stats_w,
|
||||
m_kart_stats_h);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kart_stats->move(m_x, m_y + m_h/2,
|
||||
m_w, m_h/2);
|
||||
}
|
||||
|
||||
|
||||
m_model_view->move(model_x,
|
||||
model_y,
|
||||
model_w,
|
||||
model_h);
|
||||
|
||||
m_kart_name->move(kart_name_x,
|
||||
kart_name_y,
|
||||
kart_name_w,
|
||||
kart_name_h);
|
||||
|
||||
// When coming from the overworld, we must rebuild the preview scene at
|
||||
// least once, since the scene is being cleared by leaving the overworld
|
||||
if (m_not_updated_yet)
|
||||
{
|
||||
m_model_view->clearRttProvider();
|
||||
m_not_updated_yet = false;
|
||||
}
|
||||
} // onUpdate
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** Event callback */
|
||||
GUIEngine::EventPropagation PlayerKartWidget::transmitEvent(Widget* w,
|
||||
const std::string& originator,
|
||||
const int m_player_id )
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
// if it's declared ready, there is really nothing to process
|
||||
if (m_ready) return EVENT_LET;
|
||||
|
||||
//std::cout << "= kart selection :: transmitEvent "
|
||||
// << originator << " =\n";
|
||||
|
||||
std::string name = w->m_properties[PROP_ID];
|
||||
|
||||
//std::cout << " (checking if that's me: I am "
|
||||
// << spinnerID << ")\n";
|
||||
|
||||
// update player profile when spinner changed
|
||||
if (originator == spinnerID)
|
||||
{
|
||||
if(UserConfigParams::logGUI())
|
||||
{
|
||||
Log::info("[KartSelectionScreen]", "Identity changed "
|
||||
"for player %s : %s",m_player_id,
|
||||
irr::core::stringc(
|
||||
m_player_ident_spinner->getStringValue()
|
||||
.c_str()).c_str());
|
||||
}
|
||||
|
||||
if (m_parent_screen->m_multiplayer)
|
||||
{
|
||||
int spinner_value = m_player_ident_spinner->getValue();
|
||||
PlayerProfile* profile = PlayerManager::get()->getPlayer(
|
||||
UserConfigParams::m_per_player_difficulty ? spinner_value / 2 : spinner_value);
|
||||
m_associated_player->setPlayerProfile(profile);
|
||||
if(UserConfigParams::m_per_player_difficulty && spinner_value % 2 != 0)
|
||||
{
|
||||
m_handicapped = true;
|
||||
m_model_view->setBadge(ANCHOR_BADGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_handicapped = false;
|
||||
m_model_view->unsetBadge(ANCHOR_BADGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EVENT_LET; // continue propagating the event
|
||||
} // transmitEvent
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** Sets the size of the widget as a whole, and placed children widgets
|
||||
* inside itself */
|
||||
void PlayerKartWidget::setSize(const int x, const int y, const int w, const int h)
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
|
||||
// -- sizes
|
||||
player_name_h = 40;
|
||||
player_name_w = std::min(400, w);
|
||||
|
||||
kart_name_w = w;
|
||||
kart_name_h = 25;
|
||||
|
||||
// for shrinking effect
|
||||
if (h < 175)
|
||||
{
|
||||
const float factor = h / 175.0f;
|
||||
kart_name_h = (int)(kart_name_h*factor);
|
||||
player_name_h = (int)(player_name_h*factor);
|
||||
}
|
||||
|
||||
// --- layout
|
||||
player_name_x = x + w/2 - player_name_w/2;
|
||||
player_name_y = y;
|
||||
|
||||
if (m_parent_screen->m_multiplayer)
|
||||
{
|
||||
const int modelMaxHeight = (h - kart_name_h - player_name_h)/2;
|
||||
const int modelMaxWidth = w;
|
||||
const int bestSize = std::min(modelMaxWidth, modelMaxHeight);
|
||||
model_x = x + w/2 - (int)(bestSize/2);
|
||||
model_y = y + player_name_h;
|
||||
model_w = bestSize;
|
||||
model_h = bestSize;
|
||||
|
||||
m_kart_stats_w = model_w;
|
||||
m_kart_stats_h = model_h;
|
||||
m_kart_stats_x = x + w/2 - (int)(bestSize/2);
|
||||
m_kart_stats_y = model_y + model_h;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int modelMaxHeight = h - kart_name_h - player_name_h;
|
||||
const int modelMaxWidth = w;
|
||||
const int bestSize = std::min(modelMaxWidth, modelMaxHeight);
|
||||
const int modelY = y + player_name_h;
|
||||
model_x = x + w/4 - (int)(bestSize/2);
|
||||
model_y = modelY + modelMaxHeight/2 - bestSize/2;
|
||||
model_w = bestSize;
|
||||
model_h = bestSize;
|
||||
|
||||
m_kart_stats_w = w/2;
|
||||
m_kart_stats_h = h;
|
||||
m_kart_stats_x = x + w/2;
|
||||
m_kart_stats_y = y;
|
||||
}
|
||||
|
||||
kart_name_x = x;
|
||||
kart_name_y = y + h - kart_name_h;
|
||||
} // setSize
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Sets which kart was selected for this player */
|
||||
void PlayerKartWidget::setKartInternalName(const std::string& whichKart)
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
m_kartInternalName = whichKart;
|
||||
} // setKartInternalName
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
const std::string& PlayerKartWidget::getKartInternalName() const
|
||||
{
|
||||
assert(m_magic_number == 0x33445566);
|
||||
return m_kartInternalName;
|
||||
} // getKartInternalName
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** \brief Event callback from ISpinnerConfirmListener */
|
||||
EventPropagation PlayerKartWidget::onSpinnerConfirmed()
|
||||
{
|
||||
KartSelectionScreen::getRunningInstance()->playerConfirm(m_player_id);
|
||||
return EVENT_BLOCK;
|
||||
} // onSpinnerConfirmed
|
||||
|
||||
177
src/guiengine/widgets/player_kart_widget.hpp
Normal file
@@ -0,0 +1,177 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
//
|
||||
// Copyright (C) 2006-2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef PLAYER_KART_WIDGET_HPP
|
||||
#define PLAYER_KART_WIDGET_HPP
|
||||
|
||||
#include "guiengine/widgets/spinner_widget.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include <IGUIStaticText.h>
|
||||
#include <IGUIImage.h>
|
||||
#include <string>
|
||||
|
||||
namespace Online
|
||||
{
|
||||
class OnlineProfile;
|
||||
}
|
||||
|
||||
class KartSelectionScreen;
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
class PlayerNameSpinner;
|
||||
class KartStatsWidget;
|
||||
class ModelViewWidget;
|
||||
class LabelWidget;
|
||||
|
||||
/** A widget representing the kart selection for a player (i.e. the player's
|
||||
* number, name, the kart view, the kart's name) */
|
||||
class PlayerKartWidget : public GUIEngine::Widget,
|
||||
public GUIEngine::SpinnerWidget::ISpinnerConfirmListener
|
||||
{
|
||||
/** Whether this player confirmed their selection */
|
||||
bool m_ready;
|
||||
/** If the player is handicapped. */
|
||||
bool m_handicapped;
|
||||
|
||||
/** widget coordinates */
|
||||
int player_name_x, player_name_y, player_name_w, player_name_h;
|
||||
int model_x, model_y, model_w, model_h;
|
||||
int kart_name_x, kart_name_y, kart_name_w, kart_name_h;
|
||||
int m_kart_stats_x, m_kart_stats_y, m_kart_stats_w, m_kart_stats_h;
|
||||
|
||||
/** A reserved ID for this widget if any, -1 otherwise. (If no ID is
|
||||
* reserved, widget will not be in the regular tabbing order */
|
||||
int m_irrlicht_widget_id;
|
||||
|
||||
/** For animation purposes (see method 'move') */
|
||||
int target_x, target_y, target_w, target_h;
|
||||
float x_speed, y_speed, w_speed, h_speed;
|
||||
|
||||
/** Object representing this player */
|
||||
/** Local info about the player. */
|
||||
StateManager::ActivePlayer* m_associated_player;
|
||||
int m_player_id;
|
||||
|
||||
/** Network info about the user. */
|
||||
Online::OnlineProfile* m_associated_user;
|
||||
|
||||
/** Internal name of the spinner; useful to interpret spinner events,
|
||||
* which contain the name of the activated object */
|
||||
std::string spinnerID;
|
||||
|
||||
#ifdef DEBUG
|
||||
long m_magic_number;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
/** Sub-widgets created by this widget */
|
||||
PlayerNameSpinner* m_player_ident_spinner;
|
||||
KartStatsWidget* m_kart_stats;
|
||||
ModelViewWidget* m_model_view;
|
||||
LabelWidget* m_kart_name;
|
||||
|
||||
KartSelectionScreen* m_parent_screen;
|
||||
|
||||
irr::gui::IGUIStaticText* m_ready_text;
|
||||
|
||||
core::stringw deviceName;
|
||||
std::string m_kartInternalName;
|
||||
|
||||
bool m_not_updated_yet;
|
||||
|
||||
PlayerKartWidget(KartSelectionScreen* parent,
|
||||
StateManager::ActivePlayer* associated_player,
|
||||
Online::OnlineProfile* associated_user,
|
||||
core::recti area, const int player_id,
|
||||
std::string kart_group,
|
||||
const int irrlicht_idget_id=-1);
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
~PlayerKartWidget();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Called when players are renumbered (changes the player ID) */
|
||||
void setPlayerID(const int newPlayerID);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the ID of this player */
|
||||
int getPlayerID() const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Add the widgets to the current screen */
|
||||
virtual void add();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Get the associated ActivePlayer object*/
|
||||
StateManager::ActivePlayer* getAssociatedPlayer();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Starts a 'move/resize' animation, by simply passing destination coords.
|
||||
* The animation will then occur on each call to 'onUpdate'. */
|
||||
void move(const int x, const int y, const int w, const int h);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Call when player confirmed his identity and kart */
|
||||
void markAsReady();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** \return Whether this player confirmed his kart and indent selection */
|
||||
bool isReady();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** \return Whether this player is handicapped or not */
|
||||
bool isHandicapped();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** Updates the animation (moving/shrinking/etc.) */
|
||||
void onUpdate(float delta);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** Event callback */
|
||||
virtual GUIEngine::EventPropagation transmitEvent(
|
||||
GUIEngine::Widget* w,
|
||||
const std::string& originator,
|
||||
const int m_player_id);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/** Sets the size of the widget as a whole, and placed children widgets
|
||||
* inside itself */
|
||||
void setSize(const int x, const int y, const int w, const int h);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Sets which kart was selected for this player */
|
||||
void setKartInternalName(const std::string& whichKart);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
const std::string& getKartInternalName() const;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** \brief Event callback from ISpinnerConfirmListener */
|
||||
virtual GUIEngine::EventPropagation onSpinnerConfirmed();
|
||||
}; // PlayerKartWidget
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
77
src/guiengine/widgets/player_name_spinner.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
//
|
||||
// Copyright (C) 2006-2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "guiengine/widgets/player_name_spinner.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include <IGUIEnvironment.h>
|
||||
|
||||
using namespace GUIEngine;
|
||||
|
||||
PlayerNameSpinner::PlayerNameSpinner(KartSelectionScreen* parent,
|
||||
const int player_id)
|
||||
{
|
||||
m_player_id = player_id;
|
||||
m_incorrect = false;
|
||||
m_red_mark_widget = NULL;
|
||||
m_parent = parent;
|
||||
setUseBackgroundColor();//except for multiplayer kart selection, this is false
|
||||
setSpinnerWidgetPlayerID(m_player_id);
|
||||
} // PlayerNameSpinner
|
||||
// ------------------------------------------------------------------------
|
||||
void PlayerNameSpinner::setID(const int m_player_id)
|
||||
{
|
||||
PlayerNameSpinner::m_player_id = m_player_id;
|
||||
setSpinnerWidgetPlayerID(m_player_id);
|
||||
} // setID
|
||||
// ------------------------------------------------------------------------
|
||||
/** Add a red mark on the spinner to mean "invalid choice" */
|
||||
void PlayerNameSpinner::markAsIncorrect()
|
||||
{
|
||||
if (m_incorrect) return; // already flagged as incorrect
|
||||
|
||||
m_incorrect = true;
|
||||
|
||||
irr::video::ITexture* texture = irr_driver->getTexture(FileManager::GUI,
|
||||
"red_mark.png" );
|
||||
const int mark_size = m_h;
|
||||
const int mark_x = m_w - mark_size*2;
|
||||
const int mark_y = 0;
|
||||
core::recti red_mark_area(mark_x, mark_y, mark_x + mark_size,
|
||||
mark_y + mark_size);
|
||||
m_red_mark_widget = GUIEngine::getGUIEnv()->addImage( red_mark_area,
|
||||
/* parent */ m_element );
|
||||
m_red_mark_widget->setImage(texture);
|
||||
m_red_mark_widget->setScaleImage(true);
|
||||
m_red_mark_widget->setTabStop(false);
|
||||
m_red_mark_widget->setUseAlphaChannel(true);
|
||||
} // markAsIncorrect
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Remove any red mark set with 'markAsIncorrect' */
|
||||
void PlayerNameSpinner::markAsCorrect()
|
||||
{
|
||||
if (m_incorrect)
|
||||
{
|
||||
m_red_mark_widget->remove();
|
||||
m_red_mark_widget = NULL;
|
||||
m_incorrect = false;
|
||||
}
|
||||
} // markAsCorrect
|
||||
|
||||
54
src/guiengine/widgets/player_name_spinner.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
//
|
||||
// Copyright (C) 2006-2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef PLAYER_NAME_SPINNER_HPP
|
||||
#define PLAYER_NAME_SPINNER_HPP
|
||||
|
||||
#include "guiengine/widgets/spinner_widget.hpp"
|
||||
#include <IGUIImage.h>
|
||||
|
||||
class KartSelectionScreen;
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
/** A small extension to the spinner widget to add features like player ID
|
||||
* management or badging */
|
||||
class PlayerNameSpinner : public GUIEngine::SpinnerWidget
|
||||
{
|
||||
int m_player_id;
|
||||
bool m_incorrect;
|
||||
irr::gui::IGUIImage* m_red_mark_widget;
|
||||
KartSelectionScreen* m_parent;
|
||||
//virtual EventPropagation focused(const int m_playerID) ;
|
||||
|
||||
public:
|
||||
PlayerNameSpinner(KartSelectionScreen* parent, const int playerID);
|
||||
// ------------------------------------------------------------------------
|
||||
void setID(const int m_playerID);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Add a red mark on the spinner to mean "invalid choice" */
|
||||
void markAsIncorrect();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Remove any red mark set with 'markAsIncorrect' */
|
||||
void markAsCorrect();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,9 +33,17 @@ using namespace irr;
|
||||
ProgressBarWidget::ProgressBarWidget(bool show_label) : Widget(WTYPE_PROGRESS)
|
||||
{
|
||||
m_value = 0;
|
||||
m_target_value = 0;
|
||||
m_previous_value = 0;
|
||||
m_show_label = show_label;
|
||||
setFocusable(false);
|
||||
}
|
||||
} // ProgressBarWidget
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
ProgressBarWidget::~ProgressBarWidget()
|
||||
{
|
||||
GUIEngine::needsUpdate.remove(this);
|
||||
} // ~ProgressBarWidget
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -43,29 +51,68 @@ void ProgressBarWidget::add()
|
||||
{
|
||||
rect<s32> widget_size = rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h);
|
||||
stringw& message = m_text;
|
||||
m_element = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent, getNewNoFocusID(), message.c_str(), L"");
|
||||
m_element = GUIEngine::getGUIEnv()->addButton(widget_size, m_parent,
|
||||
getNewNoFocusID(),
|
||||
message.c_str(), L"");
|
||||
|
||||
m_id = m_element->getID();
|
||||
m_element->setTabStop(false);
|
||||
m_element->setTabGroup(false);
|
||||
}
|
||||
|
||||
/* Copied from model_view_widget.cpp
|
||||
FIXME: remove this unclean thing, I think irrlicht provides this feature:
|
||||
virtual void IGUIElement::OnPostRender (u32 timeMs)
|
||||
\brief animate the element and its children.
|
||||
*/
|
||||
GUIEngine::needsUpdate.push_back(this);
|
||||
} // add
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ProgressBarWidget::setValue(int value)
|
||||
{
|
||||
m_value = value;
|
||||
m_target_value = value;
|
||||
m_previous_value = value;
|
||||
if (m_show_label)
|
||||
{
|
||||
setLabel(std::string(StringUtils::toString(value) + "%").c_str());
|
||||
} // setValue
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ProgressBarWidget::moveValue(int value)
|
||||
{
|
||||
m_previous_value = m_value;
|
||||
m_target_value = value;
|
||||
if (m_show_label)
|
||||
setLabel(std::string(StringUtils::toString(value) + "%").c_str());
|
||||
} // moveValue
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ProgressBarWidget::update(float delta)
|
||||
{
|
||||
if (m_target_value != m_value)
|
||||
{
|
||||
// Compute current progress in the animation
|
||||
float cur = (static_cast<float>(m_value) - m_previous_value)
|
||||
/ (m_target_value - m_previous_value);
|
||||
// Animation time: 1.0 seconds
|
||||
cur += delta * 10;
|
||||
if (cur > 1)
|
||||
cur = 1;
|
||||
m_value = int(m_previous_value +
|
||||
cur * (m_target_value - m_previous_value) );
|
||||
}
|
||||
}
|
||||
} // update
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ProgressBarWidget::setLabel(irr::core::stringw label)
|
||||
{
|
||||
m_element->setText( label.c_str() );
|
||||
m_text = label;
|
||||
}
|
||||
} // setLabel
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -37,31 +37,39 @@ namespace GUIEngine
|
||||
/** 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 */
|
||||
virtual int getWidthNeededAroundLabel() const { return 35; }
|
||||
|
||||
|
||||
/** 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 */
|
||||
virtual int getHeightNeededAroundLabel() const { return 4; }
|
||||
|
||||
|
||||
/** Change the label on the widget */
|
||||
void setLabel(const irr::core::stringw label);
|
||||
int m_value;
|
||||
bool m_show_label;
|
||||
|
||||
|
||||
/** Values for animation */
|
||||
int m_target_value;
|
||||
int m_previous_value;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
LEAK_CHECK()
|
||||
ProgressBarWidget(bool show_label = true);
|
||||
virtual ~ProgressBarWidget() {}
|
||||
|
||||
virtual ~ProgressBarWidget();
|
||||
|
||||
/** Change the value of the widget, it must be a percent. */
|
||||
void setValue(int value);
|
||||
|
||||
|
||||
|
||||
/** Change the value of the widget smooth, it must be a percent. */
|
||||
void moveValue(int value);
|
||||
|
||||
virtual void update(float delta);
|
||||
|
||||
void add();
|
||||
|
||||
|
||||
/** Get the current value of the widget. */
|
||||
int getValue() {return m_value; };
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -38,10 +38,12 @@ using namespace irr;
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
SkillLevelWidget::SkillLevelWidget(core::recti area, const int player_id,
|
||||
bool multiplayer, const int value,
|
||||
const stringw& label) : Widget(WTYPE_DIV)
|
||||
bool multiplayer, bool display_text,
|
||||
const int value, const stringw& label)
|
||||
: Widget(WTYPE_DIV)
|
||||
{
|
||||
m_player_id = player_id;
|
||||
m_display_text = display_text;
|
||||
|
||||
setSize(area.UpperLeftCorner.X, area.UpperLeftCorner.Y,
|
||||
area.getWidth(), area.getHeight() );
|
||||
@@ -79,6 +81,7 @@ void SkillLevelWidget::add()
|
||||
{
|
||||
m_bar->add();
|
||||
m_label->add();
|
||||
m_label->setVisible(m_display_text);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -115,7 +118,10 @@ void SkillLevelWidget::setSize(const int x, const int y, const int w, const int
|
||||
m_h = h;
|
||||
|
||||
// -- sizes
|
||||
m_bar_w = 3*(w/2)/4;
|
||||
if (m_display_text)
|
||||
m_bar_w = (w / 2) * 3 / 4;
|
||||
else
|
||||
m_bar_w = w * 2 / 3;
|
||||
m_bar_h = h;
|
||||
m_label_w = w/2;
|
||||
m_label_h = h;
|
||||
@@ -128,7 +134,10 @@ void SkillLevelWidget::setSize(const int x, const int y, const int w, const int
|
||||
m_label_h = (int)(m_label_h*factor);
|
||||
}
|
||||
|
||||
m_bar_x = x + w/2;
|
||||
if (m_display_text)
|
||||
m_bar_x = x + w / 2;
|
||||
else
|
||||
m_bar_x = x + w / 6;
|
||||
m_bar_y = y + m_h/2 - m_bar_h/2;
|
||||
|
||||
m_label_x = x;
|
||||
@@ -139,8 +148,7 @@ void SkillLevelWidget::setSize(const int x, const int y, const int w, const int
|
||||
|
||||
void SkillLevelWidget::setValue(const int value)
|
||||
{
|
||||
m_bar->setValue(value);
|
||||
|
||||
m_bar->moveValue(value);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -150,3 +158,13 @@ void SkillLevelWidget::setLabel(const irr::core::stringw& label)
|
||||
m_label->setText(label, false);
|
||||
}
|
||||
|
||||
void SkillLevelWidget::setDisplayText(bool display_text)
|
||||
{
|
||||
if(m_display_text != display_text)
|
||||
{
|
||||
m_display_text = display_text;
|
||||
m_label->setVisible(display_text);
|
||||
setSize(m_x, m_y, m_w, m_h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,7 @@ namespace GUIEngine
|
||||
* \brief A skill level widget.
|
||||
* \ingroup widgetsgroup
|
||||
*/
|
||||
|
||||
class SkillLevelWidget : public Widget
|
||||
class SkillLevelWidget : public Widget
|
||||
{
|
||||
/** 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 */
|
||||
@@ -54,6 +53,7 @@ class SkillLevelWidget : public Widget
|
||||
std::string m_label_name;
|
||||
|
||||
int m_player_id;
|
||||
bool m_display_text;
|
||||
|
||||
public:
|
||||
|
||||
@@ -62,7 +62,7 @@ class SkillLevelWidget : public Widget
|
||||
LabelWidget* m_label;
|
||||
ProgressBarWidget* m_bar;
|
||||
|
||||
SkillLevelWidget(core::recti area, const int player_id, bool multiplayer,
|
||||
SkillLevelWidget(core::recti area, const int player_id, bool multiplayer, bool display_text,
|
||||
const int value = 0, const irr::core::stringw& label = "default");
|
||||
|
||||
virtual ~SkillLevelWidget() {};
|
||||
@@ -91,11 +91,13 @@ class SkillLevelWidget : public Widget
|
||||
void setLabel(const irr::core::stringw& label);
|
||||
|
||||
/** Get the current label of the widget. */
|
||||
const irr::core::stringw& getLabel()
|
||||
const irr::core::stringw getLabel()
|
||||
{
|
||||
return m_label->getText();
|
||||
}
|
||||
|
||||
/** If the label should be displayed. */
|
||||
void setDisplayText(bool display_text);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace GUIEngine
|
||||
* value is set to the new maximum. */
|
||||
void setMax(int n)
|
||||
{
|
||||
m_max = n;
|
||||
m_max = n;
|
||||
if(getValue()>m_max) setValue(m_max);
|
||||
} // setMax
|
||||
// --------------------------------------------------------------------
|
||||
@@ -179,7 +179,7 @@ namespace GUIEngine
|
||||
* value is set to the new minimum. */
|
||||
void setMin(int n)
|
||||
{
|
||||
m_min = n;
|
||||
m_min = n;
|
||||
if(getValue()<m_min) setValue(m_min);
|
||||
} // setMin
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include "input/device_config.hpp"
|
||||
|
||||
#include "input/gamepad_config.hpp"
|
||||
#include "input/keyboard_config.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
@@ -28,9 +30,42 @@
|
||||
|
||||
using namespace irr;
|
||||
|
||||
DeviceConfig::DeviceConfig(DeviceConfigType type)
|
||||
// ------------------------------------------------------------------------
|
||||
/** A simple factory that creates either a gamepad or a keyboard
|
||||
* configuration.
|
||||
* \param type "gamepad" or "keyboard".
|
||||
* \param config The XML node with additional configuration parameters.
|
||||
*/
|
||||
DeviceConfig* DeviceConfig::create(const XMLNode *config)
|
||||
{
|
||||
m_type = type;
|
||||
DeviceConfig *device_config = NULL;
|
||||
if(config->getName()=="keyboard")
|
||||
{
|
||||
device_config = new KeyboardConfig();
|
||||
}
|
||||
else if(config->getName()=="gamepad")
|
||||
{
|
||||
device_config = new GamepadConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("DeviceConfig", "Incorrect type: '%s'.",
|
||||
config->getName().c_str());
|
||||
return NULL;
|
||||
}
|
||||
// A default keyboard etc is created without
|
||||
if(config && !device_config->load(config))
|
||||
{
|
||||
delete device_config;
|
||||
return NULL;
|
||||
}
|
||||
return device_config;
|
||||
} // create
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
DeviceConfig::DeviceConfig()
|
||||
{
|
||||
m_name = "";
|
||||
m_enabled = true;
|
||||
m_plugged = 0;
|
||||
} // DeviceConfig
|
||||
@@ -38,7 +73,7 @@ DeviceConfig::DeviceConfig(DeviceConfigType type)
|
||||
// ------------------------------------------------------------------------
|
||||
/** Get a user-readable string describing the bound action.
|
||||
*/
|
||||
irr::core::stringw DeviceConfig::getBindingAsString (const PlayerAction action) const
|
||||
irr::core::stringw DeviceConfig::getBindingAsString(const PlayerAction action) const
|
||||
{
|
||||
irr::core::stringw return_string = "";
|
||||
|
||||
@@ -243,11 +278,16 @@ bool DeviceConfig::doGetAction(Input::InputType type,
|
||||
} // doGetAction
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** Saves the configuration to a file.
|
||||
/** Saves the configuration to a file. The calling node must have written
|
||||
* the beginning of the xml node, so that this function can immediately
|
||||
* start writing attributes.
|
||||
* \param stream The stream to save to.
|
||||
*/
|
||||
void DeviceConfig::save (std::ofstream& stream)
|
||||
{
|
||||
stream << "enabled=\""
|
||||
<< (m_enabled ? "true\">\n" : "false\">\n");
|
||||
|
||||
for(int n = 0; n < PA_COUNT; n++) // Start at 0?
|
||||
{
|
||||
stream << " "
|
||||
@@ -265,6 +305,8 @@ void DeviceConfig::save (std::ofstream& stream)
|
||||
*/
|
||||
bool DeviceConfig::load(const XMLNode *config)
|
||||
{
|
||||
config->get("name", &m_name);
|
||||
config->get("enabled", &m_enabled);
|
||||
bool error = false;
|
||||
for(unsigned int i=0; i<config->getNumNodes(); i++)
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "input/input.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <iosfwd>
|
||||
#include <irrString.h>
|
||||
#include <string>
|
||||
@@ -39,30 +40,23 @@
|
||||
*/
|
||||
class DeviceConfig : public NoCopy
|
||||
{
|
||||
public:
|
||||
enum DeviceConfigType
|
||||
{
|
||||
DEVICE_CONFIG_TYPE_GAMEPAD,
|
||||
DEVICE_CONFIG_TYPE_KEYBOARD
|
||||
};
|
||||
protected:
|
||||
|
||||
Binding m_bindings[PA_COUNT];
|
||||
|
||||
/** How many devices connected to the system which uses this config? */
|
||||
int m_plugged;
|
||||
|
||||
private:
|
||||
/** If set to false, this device will be ignored.
|
||||
* Currently for gamepads only. */
|
||||
bool m_enabled;
|
||||
|
||||
/** How many devices connected to the system which uses this config? */
|
||||
int m_plugged;
|
||||
|
||||
/** Name of this configuratiom. */
|
||||
std::string m_name;
|
||||
|
||||
/** Configuration type. */
|
||||
DeviceConfigType m_type;
|
||||
protected:
|
||||
|
||||
DeviceConfig(DeviceConfigType type);
|
||||
Binding m_bindings[PA_COUNT];
|
||||
|
||||
DeviceConfig();
|
||||
|
||||
bool doGetAction(Input::InputType type,
|
||||
const int id,
|
||||
@@ -78,8 +72,12 @@ protected:
|
||||
const int id,
|
||||
int* value, /* inout */
|
||||
PlayerAction* action /* out */);
|
||||
|
||||
public:
|
||||
|
||||
virtual ~DeviceConfig() {}
|
||||
|
||||
static DeviceConfig* create(const XMLNode *config);
|
||||
irr::core::stringw toString();
|
||||
bool hasBindingFor(const int buttonID) const;
|
||||
bool hasBindingFor(const int buttonID, PlayerAction from,
|
||||
@@ -95,11 +93,41 @@ public:
|
||||
int* value,
|
||||
PlayerAction* action /* out */);
|
||||
irr::core::stringw getMappingIdString (const PlayerAction action) const;
|
||||
irr::core::stringw getBindingAsString(const PlayerAction action) const;
|
||||
virtual irr::core::stringw getBindingAsString(const PlayerAction action) const;
|
||||
virtual bool isGamePad() const = 0;
|
||||
virtual bool isKeyboard() const = 0;
|
||||
|
||||
virtual DeviceConfigType getType() const = 0;
|
||||
virtual void save(std::ofstream& stream);
|
||||
virtual bool load(const XMLNode *config);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this device has analog axis, so that steering values
|
||||
* will not be affected by time-full-steer delays. */
|
||||
virtual bool isAnalog() const { return false;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this device should desensitize its input at values
|
||||
* close to 0 (to avoid 'oversteering'). */
|
||||
virtual bool desensitize() const { return false;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Should only be called for gamepads, which has its own implementation.
|
||||
* of this function. */
|
||||
virtual int getNumberOfButtons() const
|
||||
{
|
||||
assert(false); return 0;
|
||||
} // getNumberOfButtons
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Should only be called for gamepads, which has its own implementation.
|
||||
* of this function. */
|
||||
virtual int getNumberOfAxes() const
|
||||
{
|
||||
assert(false); return 0;
|
||||
} // getNumberOfAxes
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the name of this device. */
|
||||
void setName(const std::string &name) { m_name = name; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the name for this device configuration. */
|
||||
const std::string& getName() const { return m_name; };
|
||||
@@ -118,7 +146,7 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the binding of a given index. */
|
||||
Binding& getBinding(int i) {return m_bindings[i];}
|
||||
const Binding& getBinding(int i) const {return m_bindings[i];}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** At this time only relevant for gamepads, keyboards are always enabled */
|
||||
|
||||
@@ -101,13 +101,15 @@ bool DeviceManager::initialize()
|
||||
// Some linux systems report a disk accelerometer as a gamepad, skip that
|
||||
if (name.find("LIS3LV02DL") != -1) continue;
|
||||
|
||||
#ifdef WIN32
|
||||
// On Windows, unless we use DirectInput, all gamepads are given the
|
||||
// same name ('microsoft pc-joystick driver'). This makes configuration
|
||||
// totally useless, so append an ID to the name. We can't test for the
|
||||
// name, since the name is even translated.
|
||||
name = name + " " + StringUtils::toString(id).c_str();
|
||||
#endif
|
||||
if(m_irrlicht_gamepads[id].HasGenericName)
|
||||
{
|
||||
// On Windows all gamepads are given the same name ('microsoft
|
||||
// pc-joystick driver'). Irrlicht now tries to get a better name
|
||||
// from the registry, but in case this should fail we still have
|
||||
// all gamepads with the same name shown in the GUI. This makes
|
||||
// configuration totally useless, so append an ID to the name.
|
||||
name = name + " " + StringUtils::toString(id).c_str();
|
||||
}
|
||||
|
||||
if (UserConfigParams::logMisc())
|
||||
{
|
||||
@@ -115,7 +117,7 @@ bool DeviceManager::initialize()
|
||||
}
|
||||
|
||||
// Returns true if new configuration was created
|
||||
if (getConfigForGamepad(id, name, &gamepadConfig) == true)
|
||||
if (getConfigForGamepad(id, name.c_str(), &gamepadConfig) == true)
|
||||
{
|
||||
if(UserConfigParams::logMisc())
|
||||
Log::info("Device manager","creating new configuration.");
|
||||
@@ -184,7 +186,7 @@ GamePadDevice* DeviceManager::getGamePadFromIrrID(const int id)
|
||||
const int count = m_gamepads.size();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (m_gamepads[i].m_index == id)
|
||||
if (m_gamepads[i].getIrrIndex()== id)
|
||||
{
|
||||
|
||||
return m_gamepads.get(i);
|
||||
@@ -200,7 +202,7 @@ GamePadDevice* DeviceManager::getGamePadFromIrrID(const int id)
|
||||
* otherwise false.
|
||||
*/
|
||||
bool DeviceManager::getConfigForGamepad(const int irr_id,
|
||||
const core::stringc& name,
|
||||
const std::string& name,
|
||||
GamepadConfig **config)
|
||||
{
|
||||
bool found = false;
|
||||
@@ -209,7 +211,7 @@ bool DeviceManager::getConfigForGamepad(const int irr_id,
|
||||
// Find appropriate configuration
|
||||
for(unsigned int n=0; n < m_gamepad_configs.size(); n++)
|
||||
{
|
||||
if(m_gamepad_configs[n].getName() == name.c_str())
|
||||
if(m_gamepad_configs[n].getName() == name)
|
||||
{
|
||||
*config = m_gamepad_configs.get(n);
|
||||
found = true;
|
||||
@@ -221,7 +223,7 @@ bool DeviceManager::getConfigForGamepad(const int irr_id,
|
||||
{
|
||||
if(irr_id < (int)(m_irrlicht_gamepads.size()))
|
||||
{
|
||||
*config = new GamepadConfig( name.c_str(),
|
||||
*config = new GamepadConfig( name,
|
||||
m_irrlicht_gamepads[irr_id].Axes,
|
||||
m_irrlicht_gamepads[irr_id].Buttons );
|
||||
}
|
||||
@@ -317,7 +319,7 @@ InputDevice* DeviceManager::mapKeyboardInput(int button_id,
|
||||
{
|
||||
KeyboardDevice *keyboard = m_keyboards.get(n);
|
||||
|
||||
if (keyboard->processAndMapInput(action, Input::IT_KEYBOARD, button_id, mode))
|
||||
if (keyboard->processAndMapInput(Input::IT_KEYBOARD, button_id, mode, action))
|
||||
{
|
||||
if (m_single_player != NULL)
|
||||
{
|
||||
@@ -363,7 +365,7 @@ InputDevice *DeviceManager::mapGamepadInput(Input::InputType type,
|
||||
|
||||
if (gPad != NULL)
|
||||
{
|
||||
if (gPad->processAndMapInput(action, type, button_id, mode, value))
|
||||
if (gPad->processAndMapInput(type, button_id, mode, action, value))
|
||||
{
|
||||
if (m_single_player != NULL)
|
||||
{
|
||||
@@ -504,29 +506,24 @@ bool DeviceManager::load()
|
||||
for(unsigned int i=0; i<input->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *config = input->getNode(i);
|
||||
if(config->getName()=="keyboard")
|
||||
{
|
||||
KeyboardConfig* keyboard_config = new KeyboardConfig();
|
||||
if(!keyboard_config->load(config))
|
||||
{
|
||||
Log::error("Device manager",
|
||||
"Ignoring an ill-formed keyboard action in input config.");
|
||||
}
|
||||
m_keyboard_configs.push_back(keyboard_config);
|
||||
}
|
||||
else if (config->getName()=="gamepad")
|
||||
{
|
||||
GamepadConfig* gamepad_config = new GamepadConfig(config);
|
||||
gamepad_config->load(config);
|
||||
m_gamepad_configs.push_back(gamepad_config);
|
||||
}
|
||||
else
|
||||
DeviceConfig *device_config = DeviceConfig::create(config);
|
||||
if(!device_config)
|
||||
{
|
||||
Log::warn("DeviceManager",
|
||||
"Invalid node '%s' in input.xml - ignored.",
|
||||
config->getName().c_str());
|
||||
continue;
|
||||
}
|
||||
if(config->getName()=="keyboard")
|
||||
{
|
||||
KeyboardConfig *kc = static_cast<KeyboardConfig*>(device_config);
|
||||
m_keyboard_configs.push_back(kc);
|
||||
}
|
||||
else if (config->getName()=="gamepad")
|
||||
{
|
||||
GamepadConfig *gc = static_cast<GamepadConfig*>(device_config);
|
||||
m_gamepad_configs.push_back(gc);
|
||||
}
|
||||
} // for i < getNumNodes
|
||||
|
||||
if (UserConfigParams::logMisc())
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#ifndef DEVICE_MANAGER_HPP
|
||||
#define DEVICE_MANAGER_HPP
|
||||
|
||||
#include "input/device_config.hpp"
|
||||
#include "input/gamepad_config.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "input/keyboard_config.hpp"
|
||||
@@ -31,6 +30,7 @@
|
||||
#include <IEventReceiver.h>
|
||||
using namespace irr;
|
||||
|
||||
class DeviceConfig;
|
||||
class InputDevice;
|
||||
class GamePadDevice;
|
||||
class KeyboardDevice;
|
||||
@@ -115,7 +115,9 @@ public:
|
||||
GamePadDevice* getGamePadFromIrrID(const int i);
|
||||
void clearGamepads();
|
||||
/** Returns the keyboard that has a binding for this button, or NULL if none */
|
||||
bool getConfigForGamepad(const int sdl_id, const core::stringc& pname, GamepadConfig **config);
|
||||
bool getConfigForGamepad(const int sdl_id,
|
||||
const std::string& name,
|
||||
GamepadConfig **config);
|
||||
|
||||
// ---- Keyboard(s) ----
|
||||
void addEmptyKeyboard();
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "io/xml_node.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include <SKeyMap.h>
|
||||
|
||||
@@ -29,52 +31,95 @@
|
||||
using namespace irr;
|
||||
|
||||
|
||||
GamepadConfig::GamepadConfig ( const std::string &name,
|
||||
const int axis_count,
|
||||
const int button_count )
|
||||
: DeviceConfig( DEVICE_CONFIG_TYPE_GAMEPAD )
|
||||
GamepadConfig::GamepadConfig( const std::string &name,
|
||||
const int axis_count,
|
||||
const int button_count )
|
||||
: DeviceConfig()
|
||||
{
|
||||
m_name = name;
|
||||
setName(name);
|
||||
m_axis_count = axis_count;
|
||||
m_button_count = button_count;
|
||||
m_deadzone = 2000;
|
||||
m_plugged = 0;
|
||||
m_deadzone = 4096;
|
||||
m_is_analog = true;
|
||||
m_desensitize = false;
|
||||
setDefaultBinds();
|
||||
detectType();
|
||||
} // GamepadConfig
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
GamepadConfig::GamepadConfig(const XMLNode *config)
|
||||
: DeviceConfig( DEVICE_CONFIG_TYPE_GAMEPAD )
|
||||
GamepadConfig::GamepadConfig() : DeviceConfig()
|
||||
{
|
||||
if(!config->get("name", &m_name))
|
||||
Log::error("DeviceConfig", "Unnamed joystick in config file.");
|
||||
|
||||
config->get("enabled", &m_enabled);
|
||||
|
||||
m_plugged = 0;
|
||||
m_deadzone = 2000;
|
||||
m_axis_count = 0;
|
||||
m_button_count = 0;
|
||||
m_deadzone = 4096;
|
||||
m_is_analog = true;
|
||||
m_desensitize = false;
|
||||
setDefaultBinds();
|
||||
} // GamepadConfig(XMLNode)
|
||||
} // GamepadConfig
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** Loads this configuration from the given XML node.
|
||||
* \param config The XML tree.
|
||||
* \return False in case of an error.
|
||||
*/
|
||||
bool GamepadConfig::load(const XMLNode *config)
|
||||
{
|
||||
m_deadzone = 2000;
|
||||
config->get("deadzone", &m_deadzone);
|
||||
return DeviceConfig::load(config);
|
||||
config->get("deadzone", &m_deadzone );
|
||||
config->get("analog", &m_is_analog );
|
||||
config->get("desensitize", &m_desensitize );
|
||||
bool ok = DeviceConfig::load(config);
|
||||
|
||||
if(getName()=="")
|
||||
{
|
||||
Log::error("DeviceConfig", "Unnamed joystick in config file.");
|
||||
return false;
|
||||
}
|
||||
detectType();
|
||||
return ok;
|
||||
} // load
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Saves the configuration to a file. It writes the name for a gamepad
|
||||
* config, saves the device specific parameters, and calls
|
||||
* DeviceConfig::save() to save the rest.
|
||||
* \param stream The stream to save to.
|
||||
*/
|
||||
void GamepadConfig::save (std::ofstream& stream)
|
||||
{
|
||||
stream << "<gamepad name =\"" << m_name.c_str() << "\" enabled=\""
|
||||
<< (m_enabled ? "true\"\n" : "false\"\n");
|
||||
stream << " deadzone=\""<<m_deadzone << "\">\n";
|
||||
stream << "<gamepad name =\"" << getName()
|
||||
<< "\" deadzone=\"" << m_deadzone
|
||||
<< "\" desensitize=\"" << m_desensitize
|
||||
<< "\" analog=\"" << m_is_analog<<"\"\n";
|
||||
stream << " ";
|
||||
DeviceConfig::save(stream);
|
||||
stream << "</gamepad>\n\n";
|
||||
} // save
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Try to identify a gamepad type (e.g. 'xbox'), so that better defaults
|
||||
* and button names can be set. Atm the gamepad name is used.
|
||||
*/
|
||||
void GamepadConfig::detectType()
|
||||
{
|
||||
m_type = GP_UNIDENTIFIED;
|
||||
|
||||
std::string lower = StringUtils::toLowerCase(getName());
|
||||
|
||||
// xbox appears to be xbox 360
|
||||
if(lower.find("xbox")!=std::string::npos)
|
||||
{
|
||||
m_type = GP_XBOX360;
|
||||
return;
|
||||
}
|
||||
// The original xbox gamepad
|
||||
if(lower.find("x-box")!=std::string::npos)
|
||||
{
|
||||
m_type = GP_XBOX_ORIGINAL;
|
||||
return;
|
||||
}
|
||||
} // detectType
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void GamepadConfig::setDefaultBinds ()
|
||||
@@ -96,9 +141,99 @@ void GamepadConfig::setDefaultBinds ()
|
||||
setBinding(PA_MENU_RIGHT, Input::IT_STICKMOTION, 0, Input::AD_POSITIVE);
|
||||
setBinding(PA_MENU_SELECT, Input::IT_STICKBUTTON, 0);
|
||||
setBinding(PA_MENU_CANCEL, Input::IT_STICKBUTTON, 3);
|
||||
}
|
||||
} // setDefaultBinds
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
core::stringw GamepadConfig::getBindingAsString(const PlayerAction action) const
|
||||
{
|
||||
// Default names if gamepad is not identified
|
||||
if(m_type==GP_UNIDENTIFIED) return DeviceConfig::getBindingAsString(action);
|
||||
const Binding &b = getBinding(action);
|
||||
int id = b.getId();
|
||||
Input::AxisDirection ad = b.getDirection();
|
||||
Input::InputType it = b.getType();
|
||||
|
||||
// XBOX-360 controller
|
||||
// -------------------
|
||||
if(m_type==GP_XBOX_ORIGINAL)
|
||||
{
|
||||
// Handle only the differences to the xbox 360 controller, the rest
|
||||
// will 'fall trough' to the xbox 360 code below
|
||||
if(it==Input::IT_STICKBUTTON)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
// I18N: Name of the black button on xbox controller
|
||||
case 2: return _("Black");
|
||||
case 3: return "X";
|
||||
case 4: return "Y";
|
||||
// I18N: Name of the white button on xbox controller
|
||||
case 5: return _("White");
|
||||
}
|
||||
}
|
||||
if(it==Input::IT_STICKMOTION)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case 2: return _("Left trigger");
|
||||
case 3: return (ad==Input::AD_POSITIVE) ? _("Right thumb right")
|
||||
: _("Right thumb left");
|
||||
case 4: return (ad==Input::AD_POSITIVE) ? _("Right thumb down")
|
||||
: _("Right thumb up");
|
||||
case 5: return _("Right trigger");
|
||||
case 6: return (ad == Input::AD_POSITIVE) ? _("DPad right")
|
||||
: _("DPad left");
|
||||
case 7: return (ad == Input::AD_POSITIVE) ? _("DPad down")
|
||||
: _("DPad up");
|
||||
} // switch
|
||||
} // stickmotion
|
||||
} // xbox (original)
|
||||
if(m_type==GP_XBOX360 || m_type==GP_XBOX_ORIGINAL)
|
||||
{
|
||||
if(it==Input::IT_STICKBUTTON)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case 0: return "A";
|
||||
case 1: return "B";
|
||||
case 2: return "X";
|
||||
case 3: return "Y";
|
||||
case 4: return _("Left bumper");
|
||||
case 5: return _("Right bumper");
|
||||
case 6: return _("Back");
|
||||
case 7: return _("Start");
|
||||
case 8: return _("Left thumb button");
|
||||
case 9: return _("Right thumb button");
|
||||
default: return DeviceConfig::getBindingAsString(action);
|
||||
} // switch
|
||||
} // if IT_STICKBUTTON
|
||||
if(it==Input::IT_STICKMOTION)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case 0: return (ad==Input::AD_POSITIVE) ? _("Left thumb right")
|
||||
: _("Left thumb left");
|
||||
case 1: return (ad==Input::AD_POSITIVE) ? _("Left thumb down")
|
||||
: _("Left thumb up");
|
||||
case 2: return (ad==Input::AD_POSITIVE) ? _("Left trigger")
|
||||
: _("Right trigger");
|
||||
case 3: return (ad==Input::AD_POSITIVE) ? _("Right thumb down")
|
||||
: _("Right thumb up");
|
||||
case 4: return (ad==Input::AD_POSITIVE) ? _("Right thumb right")
|
||||
: _("Right thumb left");
|
||||
case Input::HAT_H_ID: return (ad == Input::AD_POSITIVE) ? _("DPad up")
|
||||
: _("DPad down");
|
||||
case Input::HAT_V_ID: return (ad == Input::AD_POSITIVE) ? _("DPad right")
|
||||
: _("DPad left");
|
||||
} // switch
|
||||
}
|
||||
} // xbox
|
||||
|
||||
// Offer a fallback ... just in case
|
||||
Log::warn("GamepadConfig", "Missing action string for pad '%s' action '%d'",
|
||||
getName().c_str(), action);
|
||||
return DeviceConfig::getBindingAsString(action);
|
||||
} // getBindingAsString
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** Converts the configuration to a string.
|
||||
|
||||
@@ -22,56 +22,91 @@
|
||||
#include "input/binding.hpp"
|
||||
#include "input/device_config.hpp"
|
||||
#include "input/input.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <irrString.h>
|
||||
#include <string>
|
||||
|
||||
//==== G A M E P A D C O N F I G ===============================================
|
||||
using namespace irr;
|
||||
|
||||
/**
|
||||
* \brief specialisation of DeviceConfig for gamepad type devices
|
||||
* \ingroup config
|
||||
*/
|
||||
/** \brief specialisation of DeviceConfig for gamepad type devices
|
||||
* \ingroup config
|
||||
*/
|
||||
class GamepadConfig : public DeviceConfig
|
||||
{
|
||||
|
||||
private:
|
||||
/** Number of axis this device has. */
|
||||
int m_axis_count;
|
||||
int m_axis_count;
|
||||
|
||||
/** Number of buttons this device has. */
|
||||
int m_button_count;
|
||||
int m_button_count;
|
||||
|
||||
/** Deadzone of this gamepad. */
|
||||
int m_deadzone;
|
||||
|
||||
/** If this device has analog axis, steering etc. must be set immediately
|
||||
* from the input values, not having a delayed time (time-full-steer). */
|
||||
bool m_is_analog;
|
||||
|
||||
/** If set to true, map any analog axis from x in [0,1] to x^x --> at
|
||||
* values close to 0 the joystick will react less sensitive. */
|
||||
bool m_desensitize;
|
||||
|
||||
/** A type to keep track if the gamepad has been identified (which is
|
||||
* used to display better button names and better defaults). */
|
||||
enum {GP_UNIDENTIFIED, GP_XBOX360, GP_XBOX_ORIGINAL} m_type;
|
||||
|
||||
void detectType();
|
||||
public:
|
||||
|
||||
irr::core::stringw toString ();
|
||||
GamepadConfig ();
|
||||
GamepadConfig(const std::string &name,
|
||||
const int axis_count=0,
|
||||
const int button_ount=0);
|
||||
virtual ~GamepadConfig() {}
|
||||
|
||||
core::stringw toString();
|
||||
|
||||
virtual void save(std::ofstream& stream);
|
||||
void setDefaultBinds ();
|
||||
GamepadConfig (const XMLNode *config);
|
||||
GamepadConfig (const std::string &name,
|
||||
const int axis_count=0,
|
||||
const int button_ount=0);
|
||||
virtual bool load(const XMLNode *config);
|
||||
virtual core::stringw getBindingAsString(const PlayerAction action) const OVERRIDE;
|
||||
virtual bool load(const XMLNode *config) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if this device uses analog axes. */
|
||||
virtual bool isAnalog() const OVERRIDE { return m_is_analog; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this device should desensitize its input at values
|
||||
* close to 0 (to avoid 'oversteering'). */
|
||||
virtual bool desensitize() const { return m_desensitize;}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of buttons in this configuration. */
|
||||
virtual int getNumberOfButtons() const OVERRIDE { return m_button_count; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the number of buttons this device has. */
|
||||
void setNumberOfButtons(int count) { m_button_count = count; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the number of axis this device has. */
|
||||
void setNumberOfAxis(int count) { m_axis_count = count; }
|
||||
// ~GamepadConfig();
|
||||
/** Returns the number of axis of this configufation. */
|
||||
virtual int getNumberOfAxes() const OVERRIDE { return m_axis_count; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the type of this configuration. */
|
||||
virtual DeviceConfig::DeviceConfigType getType() const
|
||||
{
|
||||
return DeviceConfig::DEVICE_CONFIG_TYPE_GAMEPAD;
|
||||
} // getType
|
||||
};
|
||||
/** Sets the number of axis this device has. */
|
||||
void setNumberOfAxis(int count) { m_axis_count = count; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return deadzone of this configuration. */
|
||||
int getDeadzone() const { return m_deadzone; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool isGamePad() const { return true; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool isKeyboard() const { return false; }
|
||||
|
||||
}; // class GamepadConfig
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,19 +23,31 @@
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/controller/player_controller.hpp"
|
||||
|
||||
GamePadDevice::GamePadDevice(const int irrIndex, const std::string name,
|
||||
/** Constructor for GamePadDevice from a connected gamepad for which no
|
||||
* configuration existed (defaults will be used)
|
||||
* \param irrIndex Index of stick as given by irrLicht.
|
||||
*/
|
||||
|
||||
GamePadDevice::GamePadDevice(const int irr_index, const std::string &name,
|
||||
const int axis_count, const int button_count,
|
||||
GamepadConfig *configuration)
|
||||
{
|
||||
m_type = DT_GAMEPAD;
|
||||
m_prev_axis_directions = NULL;
|
||||
m_configuration = configuration;
|
||||
m_axis_count = axis_count;
|
||||
GamepadConfig *config = static_cast<GamepadConfig*>(m_configuration);
|
||||
if(m_configuration->getNumberOfButtons()<button_count)
|
||||
{
|
||||
static_cast<GamepadConfig*>(m_configuration)->setNumberOfButtons(button_count);
|
||||
}
|
||||
if(m_configuration->getNumberOfAxes()<axis_count)
|
||||
{
|
||||
static_cast<GamepadConfig*>(m_configuration)->setNumberOfAxis(axis_count);
|
||||
}
|
||||
m_prev_axis_directions = new Input::AxisDirection[axis_count];
|
||||
m_prev_axis_value = new int[axis_count];
|
||||
m_axis_ok = new bool[axis_count];
|
||||
m_button_count = button_count;
|
||||
m_index = irrIndex;
|
||||
m_irr_index = irr_index;
|
||||
m_name = name;
|
||||
|
||||
for (int i = 0; i < axis_count; i++)
|
||||
@@ -62,7 +74,21 @@ GamePadDevice::~GamePadDevice()
|
||||
} // ~GamePadDevice
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns if the specified value is larger than the deadzone. */
|
||||
bool GamePadDevice::moved(int value) const
|
||||
{
|
||||
int dz = static_cast<GamepadConfig*>(m_configuration)->getDeadzone();
|
||||
return abs(value) > dz;
|
||||
} // moved
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the number of buttons of this gamepad. */
|
||||
int GamePadDevice::getNumberOfButtons() const
|
||||
{
|
||||
return m_configuration->getNumberOfButtons();
|
||||
} // getNumberOfButtons
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GamePadDevice::isButtonPressed(const int i)
|
||||
{
|
||||
return m_buttonPressed[i];
|
||||
@@ -90,9 +116,9 @@ void GamePadDevice::resetAxisDirection(const int axis,
|
||||
return;
|
||||
}
|
||||
|
||||
for(int n=0; n<PA_COUNT; n++)
|
||||
for(int n=PA_BEFORE_FIRST+1; n<PA_COUNT; n++)
|
||||
{
|
||||
Binding& bind = m_configuration->getBinding(n);
|
||||
const Binding& bind = m_configuration->getBinding(n);
|
||||
if(bind.getType() == Input::IT_STICKMOTION &&
|
||||
bind.getId() == axis &&
|
||||
bind.getDirection()== direction &&
|
||||
@@ -107,21 +133,59 @@ void GamePadDevice::resetAxisDirection(const int axis,
|
||||
} // resetAxisDirection
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Invoked when this device it used. Verifies if the key/button that was
|
||||
* pressed is associated with a binding. If yes, sets action and returns
|
||||
* true; otherwise returns false. It can also modify the value used.
|
||||
* \param type Type of input (e.g. IT_STICKMOTION, ...).
|
||||
* \param id ID of the key that was pressed or of the axis that was
|
||||
* triggered (depending on the value of the 'type' parameter).
|
||||
* \param mode Used to determine whether to map menu actions or
|
||||
* game actions
|
||||
* \param[out] action The action associated to this input (only check
|
||||
* this value if method returned true)
|
||||
* \param[in,out] value The value associated with this type (typically
|
||||
* how far a gamepad axis is moved).
|
||||
*
|
||||
* \return Whether the pressed key/button is bound with an action
|
||||
*/
|
||||
|
||||
bool GamePadDevice::processAndMapInput(PlayerAction* action /* out */,
|
||||
Input::InputType type, const int id,
|
||||
bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
|
||||
InputManager::InputDriverMode mode,
|
||||
int* value/* inout */)
|
||||
PlayerAction* action /* out */,
|
||||
int* value /* inout */ )
|
||||
{
|
||||
if (!m_configuration->isEnabled()) return false;
|
||||
|
||||
// A digital input value is 32767 or -32768 (which then triggers
|
||||
// time-full-steer to be used to adjust actual steering values.
|
||||
// To prevent this delay for analog gamesticks, make sure that
|
||||
// 32767/-32768 are never used.
|
||||
if(m_configuration->isAnalog())
|
||||
{
|
||||
if(*value==32767)
|
||||
*value = 32766;
|
||||
else if(*value==-32768)
|
||||
*value = -32767;
|
||||
}
|
||||
|
||||
// Desensitizing means to map an input in the range x in [0,1] to
|
||||
// x^2. This results in changes close to 0 to have less impact
|
||||
// (less sensitive).
|
||||
if(m_configuration->desensitize())
|
||||
{
|
||||
// x/32767 is in [-1,1], (x/32767)^2 is in [0,1]. Take care of the
|
||||
// sign and map this back to [0,32767] by multiplying by 32767.
|
||||
// Which all in all results in:
|
||||
*value = int( (*value / 32767.0f) * fabsf(float(*value)) );
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if(m_prev_axis_directions == NULL) return false; // device not open
|
||||
|
||||
if (type == Input::IT_STICKMOTION)
|
||||
{
|
||||
// this gamepad doesn't even have that many axes
|
||||
if (id >= m_axis_count) return false;
|
||||
if (id >= m_configuration->getNumberOfAxes()) return false;
|
||||
|
||||
if (getPlayer())
|
||||
{
|
||||
@@ -157,8 +221,9 @@ bool GamePadDevice::processAndMapInput(PlayerAction* action /* out */,
|
||||
}
|
||||
}
|
||||
|
||||
int dz = static_cast<GamepadConfig*>(m_configuration)->getDeadzone();
|
||||
// check if within deadzone
|
||||
if(*value > -m_deadzone && *value < m_deadzone && getPlayer())
|
||||
if(*value > -dz && *value < dz && getPlayer())
|
||||
{
|
||||
// Axis stands still: This is reported once for digital axes and
|
||||
// can be called multipled times for analog ones. Uses the
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
#define HEADER_GAMEPAD_DEVICE_HPP
|
||||
|
||||
#include "input/input_device.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
class GamepadConfig;
|
||||
|
||||
/**
|
||||
* \brief specialisation of Inputdevice for gamepad type devices
|
||||
* \ingroup input
|
||||
@@ -31,7 +33,6 @@ class GamePadDevice : public InputDevice
|
||||
void resetAxisDirection(const int axis, Input::AxisDirection direction);
|
||||
bool m_buttonPressed[SEvent::SJoystickEvent::NUMBER_OF_BUTTONS];
|
||||
|
||||
public:
|
||||
Input::AxisDirection *m_prev_axis_directions;
|
||||
|
||||
/** used to determine if an axis is valid; an axis is considered valid
|
||||
@@ -43,46 +44,35 @@ public:
|
||||
* uninteresting axis values)
|
||||
*/
|
||||
int *m_prev_axis_value;
|
||||
|
||||
/** \see m_prev_axis_value */
|
||||
bool *m_axis_ok;
|
||||
|
||||
int m_deadzone;
|
||||
int m_index;
|
||||
int m_axis_count;
|
||||
int m_button_count;
|
||||
/** Irrlicht index of this gamepad. */
|
||||
int m_irr_index;
|
||||
|
||||
/** Constructor for GamePadDevice from a connected gamepad for which no
|
||||
* configuration existed (defaults will be used)
|
||||
* \param irrIndex Index of stick as given by irrLicht.
|
||||
*/
|
||||
GamePadDevice(const int irrIndex, const std::string name,
|
||||
const int axis_number,
|
||||
const int btnAmount, GamepadConfig *configuration);
|
||||
public:
|
||||
GamePadDevice(const int irrIndex, const std::string &name,
|
||||
const int axis_number,
|
||||
const int button_count,
|
||||
GamepadConfig *configuration);
|
||||
virtual ~GamePadDevice();
|
||||
bool isButtonPressed(const int i);
|
||||
void setButtonPressed(const int i, bool isButtonPressed);
|
||||
|
||||
bool isButtonPressed(const int i);
|
||||
void setButtonPressed(const int i, bool isButtonPressed);
|
||||
virtual bool processAndMapInput(Input::InputType type, const int id,
|
||||
InputManager::InputDriverMode mode,
|
||||
PlayerAction *action, int* value = NULL
|
||||
) OVERRIDE;
|
||||
int getNumberOfButtons() const;
|
||||
bool moved(int value) const;
|
||||
|
||||
/**
|
||||
* Invoked when this device it used. Verifies if the key/button that
|
||||
* was pressed is associated with a binding. If yes, sets action and
|
||||
* returns true; otherwise returns false.
|
||||
*
|
||||
* \param id ID of the key that was pressed or of the axis
|
||||
* that was triggered (depending on
|
||||
* the value of the 'type' parameter)
|
||||
* \param mode Used to determine whether to map menu actions or
|
||||
* game actions
|
||||
* \param[out] action The action associated to this input (only check
|
||||
* this value if method returned true)
|
||||
*
|
||||
* \return Whether the pressed key/button is bound with an action
|
||||
*/
|
||||
bool processAndMapInput(PlayerAction* action, Input::InputType type,
|
||||
const int id,
|
||||
InputManager::InputDriverMode mode, int* value);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the irrlicht index of this gamepad. */
|
||||
int getIrrIndex() const { return m_irr_index; }
|
||||
|
||||
};
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
}; // class GamepadDevice
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,13 +28,6 @@
|
||||
#include <string>
|
||||
#include <irrString.h>
|
||||
|
||||
class Binding;
|
||||
|
||||
const int DEADZONE_MOUSE = 150;
|
||||
const int DEADZONE_MOUSE_SENSE = 200;
|
||||
const int DEADZONE_JOYSTICK = 2000;
|
||||
const int MULTIPLIER_MOUSE = 750;
|
||||
|
||||
/**
|
||||
* \ingroup input
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#define HEADER_INPUT_DEVICE_HPP
|
||||
|
||||
|
||||
#include "input/device_config.hpp"
|
||||
#include "input/input.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
@@ -28,6 +27,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
class DeviceConfig;
|
||||
|
||||
/**
|
||||
* \brief Input device type
|
||||
* \ingroup input
|
||||
@@ -62,20 +63,25 @@ public:
|
||||
|
||||
InputDevice();
|
||||
virtual ~InputDevice();
|
||||
bool processAndMapInput(PlayerAction* action, Input::InputType type, int id, InputManager::InputDriverMode mode);
|
||||
|
||||
bool processAndMapInput(PlayerAction* action, Input::InputType type, const int id,
|
||||
int* value, InputManager::InputDriverMode mode);
|
||||
|
||||
#ifdef NOTYET
|
||||
virtual bool processAndMapInput(PlayerAction *action,
|
||||
Input::InputType type,
|
||||
|
||||
const int id,
|
||||
int* value,
|
||||
/** Invoked when this device it used. Verifies if the key/button that was
|
||||
* pressed is associated with a binding. If yes, sets action and returns
|
||||
* true; otherwise returns false. It can also modify the value used.
|
||||
* \param type Type of input (e.g. IT_STICKMOTION, ...).
|
||||
* \param id ID of the key that was pressed or of the axis that was
|
||||
* triggered (depending on the value of the 'type' parameter).
|
||||
* \param mode Used to determine whether to map menu actions or
|
||||
* game actions
|
||||
* \param[out] action The action associated to this input (only check
|
||||
* this value if method returned true)
|
||||
* \param[in,out] value The value associated with this type (typically
|
||||
* how far a gamepad axis is moved).
|
||||
*
|
||||
* \return Whether the pressed key/button is bound with an action
|
||||
*/
|
||||
virtual bool processAndMapInput(Input::InputType type, const int id,
|
||||
InputManager::InputDriverMode mode,
|
||||
PlayerAction* action) = 0;
|
||||
#endif
|
||||
PlayerAction *action, int* value = NULL
|
||||
) = 0;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets which players uses this device; or pass NULL to say no player
|
||||
|
||||
@@ -352,9 +352,6 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
|
||||
break;
|
||||
case Input::IT_STICKMOTION:
|
||||
{
|
||||
Log::info("InputManager::inputSensing", "Storing new axis binding, value = %d; "
|
||||
"deviceID = %d; button = %d; axisDirection = %s", value, deviceID, button,
|
||||
axisDirection == Input::AD_NEGATIVE ? "-" : "+");
|
||||
// We have to save the direction in which the axis was moved.
|
||||
// This is done by storing it as a sign (and since button can
|
||||
// be zero, we add one before changing the sign).
|
||||
@@ -389,7 +386,10 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
|
||||
}
|
||||
else m_sensed_input_high_gamepad.insert(input_id);
|
||||
}
|
||||
else if ( abs(value) < Input::MAX_VALUE/8.0f )
|
||||
// At least with xbox controller they can come to a 'rest' with a value of
|
||||
// around 6000! So in order to detect that an axis was released, we need to
|
||||
// test with a rather high deadzone value
|
||||
else if ( abs(value) < Input::MAX_VALUE/3.0f )
|
||||
{
|
||||
if( id_was_high )
|
||||
{
|
||||
@@ -639,8 +639,8 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
|
||||
GamePadDevice* gp =
|
||||
getDeviceManager()->getGamePadFromIrrID(deviceID);
|
||||
|
||||
if (gp != NULL &&
|
||||
abs(value)>gp->m_deadzone)
|
||||
// Check for deadzone
|
||||
if (gp != NULL && gp->moved(value))
|
||||
{
|
||||
//I18N: message shown when an input device is used but
|
||||
// is not associated to any player
|
||||
@@ -778,7 +778,7 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
return EVENT_BLOCK;
|
||||
}
|
||||
|
||||
for(int i=0; i<gp->m_button_count; i++)
|
||||
for(int i=0; i<gp->getNumberOfButtons(); i++)
|
||||
{
|
||||
const bool isButtonPressed = event.JoystickEvent.IsButtonPressed(i);
|
||||
|
||||
|
||||
@@ -28,14 +28,23 @@
|
||||
|
||||
using namespace irr;
|
||||
|
||||
// KeyboardConfig & GamepadConfig classes really should be in a separate cpp
|
||||
// file but they are so small that we'll just leave them here for now.
|
||||
|
||||
//==== K E Y B O A R D C O N F I G =============================================
|
||||
KeyboardConfig::KeyboardConfig()
|
||||
: DeviceConfig()
|
||||
{
|
||||
setDefaultBinds();
|
||||
setPlugged();
|
||||
} // KeyboardConfig
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Saves the configuration to a file. It writes the name for a gamepad
|
||||
* config, saves the device specific parameters, and calls
|
||||
* DeviceConfig::save() to save the rest.
|
||||
* \param stream The stream to save to.
|
||||
*/
|
||||
void KeyboardConfig::save(std::ofstream& stream)
|
||||
{
|
||||
stream << "<keyboard>\n";
|
||||
stream << "<keyboard ";
|
||||
DeviceConfig::save(stream);
|
||||
stream << "</keyboard>\n\n";
|
||||
} // save
|
||||
@@ -65,10 +74,3 @@ void KeyboardConfig::setDefaultBinds()
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
KeyboardConfig::KeyboardConfig() : DeviceConfig(DEVICE_CONFIG_TYPE_KEYBOARD)
|
||||
{
|
||||
m_name = "Keyboard";
|
||||
m_plugged = 1;
|
||||
setDefaultBinds();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,9 @@
|
||||
#include "input/device_config.hpp"
|
||||
#include "input/input.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <irrString.h>
|
||||
#include <string>
|
||||
|
||||
//==== K E Y B O A R D C O N F I G =============================================
|
||||
|
||||
/**
|
||||
* \brief specialisation of DeviceConfig for keyboard type devices
|
||||
@@ -39,17 +36,17 @@ class KeyboardConfig : public DeviceConfig
|
||||
|
||||
public:
|
||||
|
||||
KeyboardConfig();
|
||||
virtual ~KeyboardConfig() {}
|
||||
|
||||
void setDefaultBinds ();
|
||||
virtual void save(std::ofstream& stream);
|
||||
|
||||
KeyboardConfig ();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the type of this configuration. */
|
||||
virtual DeviceConfigType getType() const
|
||||
{
|
||||
return DEVICE_CONFIG_TYPE_KEYBOARD;
|
||||
} // getType
|
||||
};
|
||||
virtual bool isGamePad() const { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool isKeyboard() const { return true; }
|
||||
|
||||
}; // class KeyboardConfig
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,11 +38,24 @@ KeyboardDevice::KeyboardDevice()
|
||||
} // KeyboardDevice
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool KeyboardDevice::processAndMapInput(PlayerAction* action /* out */,
|
||||
Input::InputType type,
|
||||
const int id,
|
||||
InputManager::InputDriverMode mode)
|
||||
/** Invoked when this device it used. Verifies if the key/button that was
|
||||
* pressed is associated with a binding. If yes, sets action and returns
|
||||
* true; otherwise returns false. It can also modify the value used.
|
||||
* \param type Type of input (e.g. IT_STICKMOTION, ...).
|
||||
* \param id ID of the key that was pressed or of the axis that was
|
||||
* triggered (depending on the value of the 'type' parameter).
|
||||
* \param mode Used to determine whether to map menu actions or
|
||||
* game actions
|
||||
* \param[out] action The action associated to this input (only check
|
||||
* this value if method returned true)
|
||||
* \param[in,out] value The value associated with this type (typically
|
||||
* how far a gamepad axis is moved).
|
||||
*
|
||||
* \return Whether the pressed key/button is bound with an action
|
||||
*/
|
||||
bool KeyboardDevice::processAndMapInput(Input::InputType type, const int id,
|
||||
InputManager::InputDriverMode mode,
|
||||
PlayerAction *action, int* value)
|
||||
{
|
||||
assert(type==Input::IT_KEYBOARD);
|
||||
if (mode == InputManager::INGAME)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include "input/input_device.hpp"
|
||||
|
||||
#include "input/input.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
class KeyboardConfig;
|
||||
|
||||
@@ -37,20 +37,10 @@ public:
|
||||
KeyboardDevice(KeyboardConfig *configuration);
|
||||
|
||||
virtual ~KeyboardDevice() {}
|
||||
|
||||
/**
|
||||
* Checks if this key belongs to this device. if yes, sets action and
|
||||
* returns true; otherwise returns false
|
||||
*
|
||||
* \param id ID of the key that was pressed
|
||||
* \param mode Used to determine whether to bind menu actions or
|
||||
* game actions
|
||||
* \param[out] action The action associated to this input (only check
|
||||
* this value if method returned true)
|
||||
*/
|
||||
bool processAndMapInput(PlayerAction* action, Input::InputType type,
|
||||
const int id,
|
||||
InputManager::InputDriverMode mode);
|
||||
virtual bool processAndMapInput(Input::InputType type, const int id,
|
||||
InputManager::InputDriverMode mode,
|
||||
PlayerAction *action, int* value = NULL
|
||||
) OVERRIDE;
|
||||
|
||||
}; // KeyboardDevice
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ Attachment::~Attachment()
|
||||
m_bomb_sound->deleteSFX();
|
||||
m_bomb_sound = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (m_bubble_explode_sound)
|
||||
{
|
||||
m_bubble_explode_sound->deleteSFX();
|
||||
@@ -125,7 +125,7 @@ void Attachment::set(AttachmentType type, float time,
|
||||
|
||||
clear();
|
||||
m_node_scale = 0.3f;
|
||||
|
||||
|
||||
// If necessary create the appropriate plugin which encapsulates
|
||||
// the associated behavior
|
||||
switch(type)
|
||||
@@ -266,7 +266,8 @@ void Attachment::hitBanana(Item *item, int new_attachment)
|
||||
// same banana again once the explosion animation is finished, giving
|
||||
// the kart the same penalty twice.
|
||||
float f = std::max(item->getDisableTime(),
|
||||
m_kart->getKartProperties()->getExplosionTime()+2.0f);
|
||||
m_kart->getKartProperties()->getExplosionTime() *
|
||||
m_kart->getPlayerDifficulty()->getExplosionTime() + 2.0f);
|
||||
item->setDisableTime(f);
|
||||
break;
|
||||
}
|
||||
@@ -329,7 +330,7 @@ void Attachment::hitBanana(Item *item, int new_attachment)
|
||||
void Attachment::handleCollisionWithKart(AbstractKart *other)
|
||||
{
|
||||
Attachment *attachment_other=other->getAttachment();
|
||||
|
||||
|
||||
if(getType()==Attachment::ATTACH_BOMB)
|
||||
{
|
||||
// Don't attach a bomb when the kart is shielded
|
||||
@@ -386,11 +387,11 @@ void Attachment::update(float dt)
|
||||
{
|
||||
if(m_type==ATTACH_NOTHING) return;
|
||||
m_time_left -=dt;
|
||||
|
||||
|
||||
|
||||
|
||||
bool is_shield = (m_type == ATTACH_BUBBLEGUM_SHIELD|| m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD);
|
||||
float m_wanted_node_scale = is_shield ? std::max(1.0f, m_kart->getHighestPoint()*1.1f) : 1.0f;
|
||||
|
||||
|
||||
if (m_node_scale < m_wanted_node_scale)
|
||||
{
|
||||
m_node_scale += dt*1.5f;
|
||||
@@ -476,7 +477,7 @@ void Attachment::update(float dt)
|
||||
m_bubble_explode_sound = SFXManager::get()->createSoundSource("bubblegum_explode");
|
||||
m_bubble_explode_sound->setPosition(m_kart->getXYZ());
|
||||
m_bubble_explode_sound->play();
|
||||
|
||||
|
||||
// drop a small bubble gum
|
||||
Vec3 hit_point;
|
||||
Vec3 normal;
|
||||
@@ -493,7 +494,7 @@ void Attachment::update(float dt)
|
||||
normal.normalize();
|
||||
|
||||
pos.setY(hit_point.getY()-0.05f);
|
||||
|
||||
|
||||
ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_kart);
|
||||
}
|
||||
}
|
||||
|
||||