Merge remote-tracking branch 'origin/master' into renderer_refactoring
82
INSTALL.md
@ -1,82 +0,0 @@
|
||||
# SuperTuxKart Installation Instructions
|
||||
|
||||
Note: If you obtained this source code from Github, you also need to download
|
||||
the game assets from Sourceforge using SVN.
|
||||
|
||||
`svn checkout https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets`
|
||||
|
||||
Place the `stk-assets` folder next to the source root `stk-code` folder.
|
||||
See <https://supertuxkart.net/Source_control> for more information
|
||||
|
||||
|
||||
## Building STK on Linux
|
||||
|
||||
First, make sure that you have the following packages installed:
|
||||
|
||||
* OpenGL (mesa)
|
||||
* OpenAL (recommended: openal-soft-devel)
|
||||
* Ogg (libogg-dev)
|
||||
* Vorbis (libvorbis-dev)
|
||||
* Freetype (libfreetype6-dev)
|
||||
* libcurl (libcurl-devel)
|
||||
* libbluetooth (bluez-devel)
|
||||
* libpng (libpng-devel)
|
||||
* zlib (zlib-devel)
|
||||
* jpeg (libjpeg-turbo-devel)
|
||||
|
||||
Ubuntu command:
|
||||
|
||||
```
|
||||
sudo apt-get install build-essential cmake libbluetooth-dev \
|
||||
libcurl4-gnutls-dev libfreetype6-dev libfribidi-dev libgl1-mesa-dev \
|
||||
libjpeg-dev libogg-dev libopenal-dev libpng-dev libvorbis-dev libxrandr-dev \
|
||||
mesa-common-dev pkg-config zlib1g-dev
|
||||
```
|
||||
|
||||
Unpack the files from the tarball like this:
|
||||
|
||||
```
|
||||
tar xzf supertuxkart-*.tar.gz
|
||||
cd supertuxkart-*
|
||||
```
|
||||
|
||||
where `*` is the version of SuperTuxkart you downloaded - eg `0.8.0`. Then:
|
||||
|
||||
|
||||
Compile SuperTuxKart:
|
||||
|
||||
```
|
||||
mkdir cmake_build
|
||||
cd cmake_build
|
||||
cmake ..
|
||||
make VERBOSE=1 -j2
|
||||
```
|
||||
|
||||
To create a debug version of STK, use:
|
||||
|
||||
```
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug
|
||||
```
|
||||
|
||||
To test the compilation, supertuxkart can be run from the build
|
||||
directory by ./bin/supertuxkart
|
||||
|
||||
To install the file, as root execute:
|
||||
|
||||
```
|
||||
make install
|
||||
```
|
||||
|
||||
The default install location is `/usr/local`, i.e. the data files will
|
||||
be written to `/usr/local/share/games/supertuxkart`, the executable
|
||||
will be copied to `/usr/local/bin`. To change the default installation
|
||||
location, specify `CMAKE_INSTALL_PREFIX` when running cmake, e.g.:
|
||||
`cmake .. -DCMAKE_INSTALL_PREFIX=/opt/stk`
|
||||
|
||||
|
||||
## Building STK on OS X
|
||||
See <https://supertuxkart.net/Building_and_packaging_on_OSX>
|
||||
|
||||
|
||||
## Building STK on Windows
|
||||
See <https://supertuxkart.net/How_to_build_the_Windows_version>
|
184
README.md
@ -3,13 +3,7 @@
|
||||
|
||||
SuperTuxKart is a free kart racing game. It focuses on fun and not on realistic kart physics. Instructions can be found on the in-game help page.
|
||||
|
||||
The SuperTuxKart homepage can be found at: <https://supertuxkart.net/>
|
||||
|
||||
The official SuperTuxKart forum is at <http://forum.freegamedev.net/viewforum.php?f=16>. If you need support, this would be the best place to start.
|
||||
|
||||
Hope you enjoy the game.
|
||||
|
||||
-- The SuperTuxKart development team.
|
||||
The SuperTuxKart homepage can be found at <https://supertuxkart.net/>. There is also our [FAQ](https://supertuxkart.net/FAQ) and information on how get in touch with the [community](https://supertuxkart.net/Community)
|
||||
|
||||
## Hardware Requirements
|
||||
* You need a 3D graphics card. (NVIDIA GeForce 8xxx and higher, ATI Radeon HD 4xxx and higher or Intel HD 3000 and higher.)
|
||||
@ -18,28 +12,6 @@ Hope you enjoy the game.
|
||||
* Disk space: 400MB
|
||||
* Ideally, you want a joystick with at least 6 buttons.
|
||||
|
||||
## Compiling SuperTuxKart
|
||||
|
||||
### Windows
|
||||
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](https://supertuxkart.net/Source_control).
|
||||
3. Download the latest dependency package 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 directories (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 the 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 you 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.
|
||||
|
||||
See <https://supertuxkart.net/How_to_build_the_Windows_version> for more information.
|
||||
|
||||
Compilation with cygwin is not officially supported, but this has been done (check with the forum for details).
|
||||
|
||||
### Mac OS X
|
||||
The latest information about compilation on Mac are at our site: <https://supertuxkart.net/Building_and_packaging_on_OSX>
|
||||
|
||||
### UNIX
|
||||
See [`INSTALL.md`](INSTALL.md) for details.
|
||||
|
||||
## License
|
||||
This software is released under the GNU General Public License (GPL) which can be found in the file [`COPYING`](/COPYING) in the same directory as this file. Information about the licenses for artwork are contained in `data/licenses`.
|
||||
|
||||
@ -51,3 +23,157 @@ STK : X right, Y up, Z forwards
|
||||
Blender: X right, Y forwards, Z up
|
||||
|
||||
The exporters perform the needed transform, so in Blender you just work with XY plane as ground, and things will appear fine in STK (using XZ as ground in the code, obviously).
|
||||
|
||||
## Building from source
|
||||
|
||||
First, you need both the code and the assets (See <https://supertuxkart.net/Source_control> for more information):
|
||||
|
||||
```
|
||||
git clone https://github.com/supertuxkart/stk-code
|
||||
svn checkout https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets
|
||||
```
|
||||
|
||||
## Building on Linux
|
||||
|
||||
### Dependencies
|
||||
|
||||
Install the following packages:
|
||||
|
||||
* OpenGL (mesa)
|
||||
* OpenAL (recommended: openal-soft-devel)
|
||||
* Ogg (libogg-dev)
|
||||
* Vorbis (libvorbis-dev)
|
||||
* Freetype (libfreetype6-dev)
|
||||
* libcurl (libcurl-devel)
|
||||
* libbluetooth (bluez-devel)
|
||||
* libpng (libpng-devel)
|
||||
* zlib (zlib-devel)
|
||||
* jpeg (libjpeg-turbo-devel)
|
||||
|
||||
Ubuntu command:
|
||||
|
||||
```
|
||||
sudo apt-get install build-essential cmake libbluetooth-dev \
|
||||
libcurl4-gnutls-dev libfreetype6-dev libfribidi-dev libgl1-mesa-dev \
|
||||
libjpeg-dev libogg-dev libopenal-dev libpng-dev libvorbis-dev libxrandr-dev \
|
||||
mesa-common-dev pkg-config zlib1g-dev
|
||||
```
|
||||
|
||||
### Compiling
|
||||
|
||||
Compile SuperTuxKart:
|
||||
|
||||
```
|
||||
mkdir cmake_build
|
||||
cd cmake_build
|
||||
cmake ..
|
||||
make -j4
|
||||
```
|
||||
STK can then be run from the build directory with `bin/supertuxkart`
|
||||
|
||||
### Further options
|
||||
|
||||
To create a debug version of STK, use:
|
||||
|
||||
```
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug
|
||||
```
|
||||
|
||||
You can install your build system-wide:
|
||||
|
||||
```
|
||||
sudo make install
|
||||
```
|
||||
|
||||
The default install location is `/usr/local`, i.e. the data files will
|
||||
be written to `/usr/local/share/games/supertuxkart`, the executable
|
||||
will be copied to `/usr/local/bin`. To change the default installation
|
||||
location, specify `CMAKE_INSTALL_PREFIX` when running cmake, e.g.:
|
||||
`cmake .. -DCMAKE_INSTALL_PREFIX=/opt/stk`
|
||||
|
||||
|
||||
## Windows
|
||||
|
||||
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](https://supertuxkart.net/Source_control).
|
||||
3. Download the latest dependency package 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 directories (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 the 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 you 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.
|
||||
|
||||
## OS X
|
||||
|
||||
### Getting Started
|
||||
|
||||
Install developer tools, either from the OS X Install DVD or from Apple's website.
|
||||
|
||||
If you have never built anything before, you have create `/usr/local/include/` first:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /usr/local/include/
|
||||
```
|
||||
|
||||
Symlink the `include`-folder of OpenGL framework to `/usr/local/include/GL` (Unix programs have an easier time finding it this way):
|
||||
|
||||
```bash
|
||||
sudo ln -s /System/Library/Frameworks/OpenGL.framework/Versions/A/Headers/ /usr/local/include/GL
|
||||
```
|
||||
|
||||
On OS X 10.9.5, you might need the following workaround:
|
||||
|
||||
```bash
|
||||
sudo ln -s `xcrun --show-sdk-path`/usr/include/ /usr/include
|
||||
sudo ln -s `xcrun --show-sdk-path`/System/Library/Frameworks/OpenGL.framework/Headers/ /usr/local/include/OpenGL
|
||||
```
|
||||
|
||||
The first link is required in order to find libcurl, the second to find opengl.
|
||||
|
||||
Download pre-built dependencies from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/OSX/) and put the frameworks in [hard disk root]/Library/Frameworks
|
||||
|
||||
### CMake
|
||||
|
||||
CMake is used to build STK. At this time CMake will not make a binary that is ready for distribution.
|
||||
|
||||
You'll have to run these commands inside your stk-code directory.
|
||||
|
||||
### Building
|
||||
|
||||
With clang:
|
||||
|
||||
```
|
||||
mkdir cmake_build
|
||||
cd cmake_build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
With GCC :
|
||||
```
|
||||
mkdir cmake_build
|
||||
cd cmake_build
|
||||
cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DCMAKE_C_COMPILER=/usr/bin/gcc
|
||||
make
|
||||
```
|
||||
|
||||
Building on 10.10 with 10.9 compat
|
||||
```
|
||||
cmake .. -DCMAKE_OSX_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9
|
||||
```
|
||||
|
||||
### Xcode
|
||||
|
||||
Place an additional copy of the dependencies into `Users/<YOUR_USERNAME>/Library/Frameworks`.
|
||||
Then cd to your cloned stk-code directory and execute the following commands:
|
||||
|
||||
```bash
|
||||
mkdir xcode_build && cd xcode_build
|
||||
cmake .. -GXcode
|
||||
```
|
||||
|
||||
Use Finder to navigate to your stk-code/xcode_build folder and open the newly generated Xcode project (SuperTuxKart.xcodeproj).
|
||||
|
||||
You can then build the project in Xcode using Product -> Build
|
||||
|
||||
Note: Xcode is much less well tested than makefiles, so there may be issues when trying to use Xcode.
|
||||
|
34
SVN-CONFIG
@ -1,34 +0,0 @@
|
||||
# Please, make sure your SVN client uses something that matches the
|
||||
# following config. Specially the autoprops part, that way new files
|
||||
# will be added with the right settings. Default config for command line
|
||||
# svn is in ~/.subversion/config. If you use SVN for multiple projects
|
||||
# simultaneously, remember you can use different configs, at least in
|
||||
# cmd line (via --config-dir and for example ~/.subversion/supertuxkart/
|
||||
# with a new config file inside).
|
||||
|
||||
[miscellany]
|
||||
global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* ._* .DS_Store *.blend1 *.blend2
|
||||
enable-auto-props = yes
|
||||
|
||||
[auto-props]
|
||||
*.c = svn:eol-style=native;svn:keywords=Author Date Id Revision
|
||||
*.cpp = svn:eol-style=native;svn:keywords=Author Date Id Revision
|
||||
*.h = svn:eol-style=native;svn:keywords=Author Date Id Revision
|
||||
*.hpp = svn:eol-style=native;svn:keywords=Author Date Id Revision
|
||||
*.dsp = svn:eol-style=CRLF
|
||||
*.dsw = svn:eol-style=CRLF
|
||||
*.sh = svn:eol-style=native;svn:executable;svn:keywords=Author Date Id Revision
|
||||
*.txt = svn:eol-style=native
|
||||
*.png = svn:mime-type=image/png
|
||||
*.jpg = svn:mime-type=image/jpeg
|
||||
Makefile = svn:eol-style=native;svn:keywords=Author Date Id Revision
|
||||
*.jpeg = svn:mime-type=image/jpeg
|
||||
*.gif = svn:mime-type=image/gif
|
||||
*.svg = svn:mime-type=image/svg+xml
|
||||
*.htm = svn:mime-type=text/html
|
||||
*.html = svn:mime-type=text/html
|
||||
*.css = svn:mime-type=text/css
|
||||
*.pdf = svn:mime-type=application/pdf
|
||||
SConstruct = svn:eol-style=native;svn:keywords=Author Date Id Revision
|
||||
*.xml = svn:eol-style=LF;svn:mime-type=text/xml
|
||||
*.py = svn:eol-style=native;svn:keywords=Author Date Id Revision
|
30
TODO.md
@ -1,30 +0,0 @@
|
||||
##TODO
|
||||
|
||||
SuperTuxKart is looking for additional man power to make this
|
||||
one of the best free linux games out there :) We need (in
|
||||
no particular order):
|
||||
|
||||
- Musicians/sound engineers
|
||||
- Create additional background soundtracks
|
||||
- Create sound effects
|
||||
- Artists and track designer
|
||||
- Create additional tracks
|
||||
- Create additional artwork for tracks and background images
|
||||
- Developers
|
||||
- Work on network play support
|
||||
- Check our bug and enhancement request tracker on
|
||||
https://github.com/supertuxkart/stk-code/issues
|
||||
- Extend the current web page and keep it up to date
|
||||
- Testers
|
||||
- For just about everything, especially different platforms and graphics cards
|
||||
- Writers
|
||||
- Write documentation, ranging from man page, to a description for the web, to a design document, etc...
|
||||
|
||||
If you want to help the SuperTuxKart Project, please contact us on the email list: [supertuxkart-devel@lists.sourceforge.net](mailto:supertuxkart-devel@lists.sourceforge.net)
|
||||
|
||||
Thanks in advance!
|
||||
|
||||
-- The SuperTuxKart Team
|
||||
|
||||
|
||||
For details, see <http://supertuxkart.net/Community>
|
BIN
data/CREDITS
@ -3,6 +3,7 @@
|
||||
<card is="Intel(R) HD Graphics 3000" os="windows" disable="UniformBufferObject"/>
|
||||
<card is="Intel(R) HD Graphics 3000" os="windows" disable="AdvancedPipeline"/>
|
||||
<card is="Intel(R) HD Graphics 3000" os="windows" disable="FramebufferSRGBWorking"/>
|
||||
<card is="Intel(R) HD Graphics" os="windows" disable="ForceLegacyDevice"/>
|
||||
<card contains="Intel" os="osx" disable="GI"/>
|
||||
<card contains="Intel" os="linux" version="<11.2" disable="ComputeShader"/>
|
||||
<card contains="Intel" os="linux" version="<11.2" disable="GeometryShader"/>
|
||||
@ -27,5 +28,7 @@
|
||||
<card contains="Radeon" os="linux" version="<14.300" disable="DriverRecentEnough"/>
|
||||
<card contains="Radeon" os="windows" version="<14.300" disable="DriverRecentEnough"/>
|
||||
<card contains="ATI" os="windows" version="<14.300" disable="DriverRecentEnough"/>
|
||||
<card contains="ATI" os="windows" version="<=3.1.8787" disable="ForceLegacyDevice"/>
|
||||
<card os="android" disable="TextureFormatBGRA8888"/>
|
||||
<card os="android" disable="ColorBufferFloat"/>
|
||||
</graphical-restrictions>
|
||||
|
||||
|
@ -12,6 +12,8 @@ mode_tt, released under Creative-Commons BY-SA 3, incorporatings artwork from ye
|
||||
|
||||
mode_easter, mode_ftl, mode_soccer, mode_normal, race_giveup: by Totoplus62, released under CC-BY-SA 3.0
|
||||
|
||||
soccer balls released under CC-BY-SA 3.0 by Néd J. Édoire
|
||||
|
||||
tutorial.png by Totoplus62, released under CC-BY-SA 3.0
|
||||
|
||||
Logo and Logo_slim : under CC-BY-SA 3.0+ by 'rastapax'
|
||||
|
@ -33,5 +33,8 @@
|
||||
<box proportion="1" width="98%" align="center" layout="vertical-row" padding="6">
|
||||
<list id="list_addons" x="0" y="0" width="100%" height="100%"/>
|
||||
</box>
|
||||
|
||||
<bright width="97%" id="tips_label" text="" align="center"/>
|
||||
|
||||
</div>
|
||||
</stkgui>
|
||||
|
BIN
data/gui/heart.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 16 KiB |
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: supertuxkart\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-05-30 18:52-0400\n"
|
||||
"POT-Creation-Date: 2016-08-23 20:00-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -437,7 +437,7 @@ msgstr ""
|
||||
#. I18N: ./data/gui/user_screen_tab.stkgui
|
||||
#. I18N: In the user screen
|
||||
#: src/states_screens/dialogs/message_dialog.cpp:123
|
||||
#: src/states_screens/dialogs/message_dialog.cpp:136
|
||||
#: src/states_screens/dialogs/message_dialog.cpp:135
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
@ -825,7 +825,7 @@ msgstr ""
|
||||
|
||||
#. I18N: ./data/gui/main_menu.stkgui
|
||||
#. I18N: In the main screen
|
||||
#: src/states_screens/race_gui_overworld.cpp:462
|
||||
#: src/states_screens/race_gui_overworld.cpp:465
|
||||
msgid "Tutorial"
|
||||
msgstr ""
|
||||
|
||||
@ -996,7 +996,8 @@ msgstr ""
|
||||
|
||||
#. I18N: ./data/gui/online/guest_login.stkgui
|
||||
#. I18N: ./data/gui/user_screen.stkgui
|
||||
#: src/states_screens/main_menu_screen.cpp:79
|
||||
#. I18N: Used as a verb, appears on the main menu (login button)
|
||||
#: src/states_screens/main_menu_screen.cpp:80
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
@ -1317,7 +1318,7 @@ msgstr ""
|
||||
#. I18N: Section in the settings menu
|
||||
#: src/states_screens/options_screen_device.cpp:86
|
||||
#: src/states_screens/options_screen_input.cpp:140
|
||||
#: src/states_screens/options_screen_ui.cpp:119
|
||||
#: src/states_screens/options_screen_ui.cpp:122
|
||||
#: src/states_screens/options_screen_video.cpp:172
|
||||
#: src/states_screens/user_screen.cpp:660
|
||||
msgid "Audio"
|
||||
@ -1351,7 +1352,7 @@ msgstr ""
|
||||
#. I18N: ./data/gui/options_input.stkgui
|
||||
#. I18N: Section in the settings menu
|
||||
#: src/states_screens/options_screen_audio.cpp:68
|
||||
#: src/states_screens/options_screen_ui.cpp:121
|
||||
#: src/states_screens/options_screen_ui.cpp:124
|
||||
#: src/states_screens/options_screen_video.cpp:175
|
||||
#: src/states_screens/user_screen.cpp:662
|
||||
msgid "Controls"
|
||||
@ -1393,7 +1394,7 @@ msgstr ""
|
||||
#: src/states_screens/options_screen_audio.cpp:67
|
||||
#: src/states_screens/options_screen_device.cpp:88
|
||||
#: src/states_screens/options_screen_input.cpp:142
|
||||
#: src/states_screens/options_screen_ui.cpp:120
|
||||
#: src/states_screens/options_screen_ui.cpp:123
|
||||
#: src/states_screens/options_screen_video.cpp:174
|
||||
#: src/states_screens/server_selection.cpp:103
|
||||
msgid "Players"
|
||||
@ -1405,7 +1406,7 @@ msgstr ""
|
||||
|
||||
#. I18N: ./data/gui/options_players.stkgui
|
||||
#. I18N: In the player configuration screen
|
||||
msgid "Press enter or double-click on a player to edit him/her"
|
||||
msgid "Press enter or double-click on a player to edit their settings"
|
||||
msgstr ""
|
||||
|
||||
#. I18N: ./data/gui/options_players.stkgui
|
||||
@ -1458,7 +1459,7 @@ msgstr ""
|
||||
#: src/states_screens/options_screen_audio.cpp:65
|
||||
#: src/states_screens/options_screen_device.cpp:85
|
||||
#: src/states_screens/options_screen_input.cpp:139
|
||||
#: src/states_screens/options_screen_ui.cpp:118
|
||||
#: src/states_screens/options_screen_ui.cpp:121
|
||||
#: src/states_screens/user_screen.cpp:659
|
||||
msgid "Graphics"
|
||||
msgstr ""
|
||||
@ -1871,46 +1872,47 @@ msgstr ""
|
||||
msgid "Completed achievement \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#: src/addons/addons_manager.cpp:97 src/addons/news_manager.cpp:317
|
||||
#: src/addons/addons_manager.cpp:104 src/addons/news_manager.cpp:325
|
||||
msgid "Can't access stkaddons server..."
|
||||
msgstr ""
|
||||
|
||||
#: src/addons/news_manager.cpp:174
|
||||
#: src/addons/news_manager.cpp:182
|
||||
#, c-format
|
||||
msgid "Error downloading news: '%s'."
|
||||
msgstr ""
|
||||
|
||||
#. I18N: number of laps to race in a challenge
|
||||
#: src/challenges/challenge_data.cpp:259
|
||||
#: src/challenges/challenge_data.cpp:266
|
||||
#: src/states_screens/race_result_gui.cpp:1422
|
||||
#, c-format
|
||||
msgid "Laps : %i"
|
||||
msgid "Laps: %i"
|
||||
msgstr ""
|
||||
|
||||
#: src/challenges/challenge_data.cpp:265
|
||||
#: src/challenges/challenge_data.cpp:272
|
||||
msgid "Follow the leader"
|
||||
msgstr ""
|
||||
|
||||
#: src/challenges/challenge_data.cpp:511
|
||||
#: src/challenges/challenge_data.cpp:518
|
||||
#, c-format
|
||||
msgid "New track '%s' now available"
|
||||
msgstr ""
|
||||
|
||||
#: src/challenges/challenge_data.cpp:516
|
||||
#: src/challenges/challenge_data.cpp:523
|
||||
#, c-format
|
||||
msgid "New game mode '%s' now available"
|
||||
msgstr ""
|
||||
|
||||
#: src/challenges/challenge_data.cpp:526
|
||||
#: src/challenges/challenge_data.cpp:533
|
||||
#, c-format
|
||||
msgid "New Grand Prix '%s' now available"
|
||||
msgstr ""
|
||||
|
||||
#: src/challenges/challenge_data.cpp:530
|
||||
#: src/challenges/challenge_data.cpp:537
|
||||
#, c-format
|
||||
msgid "New difficulty '%s' now available"
|
||||
msgstr ""
|
||||
|
||||
#: src/challenges/challenge_data.cpp:540
|
||||
#: src/challenges/challenge_data.cpp:547
|
||||
#, c-format
|
||||
msgid "New kart '%s' now available"
|
||||
msgstr ""
|
||||
@ -1942,17 +1944,17 @@ msgid ""
|
||||
"created."
|
||||
msgstr ""
|
||||
|
||||
#: src/graphics/irr_driver.cpp:1896
|
||||
#: src/graphics/irr_driver.cpp:1950
|
||||
#, c-format
|
||||
msgid "FPS: %d/%d/%d - PolyCount: %d Solid, %d Shadows - LightDist : %d"
|
||||
msgstr ""
|
||||
|
||||
#: src/graphics/irr_driver.cpp:1907
|
||||
#: src/graphics/irr_driver.cpp:1961
|
||||
#, c-format
|
||||
msgid "FPS: %d/%d/%d - %d KTris"
|
||||
msgstr ""
|
||||
|
||||
#: src/guiengine/engine.cpp:1346
|
||||
#: src/guiengine/engine.cpp:1289
|
||||
msgid "Loading"
|
||||
msgstr ""
|
||||
|
||||
@ -2467,11 +2469,11 @@ msgid "Mouse axis %d %s"
|
||||
msgstr ""
|
||||
|
||||
#. I18N: shown when config file is too old
|
||||
#: src/input/device_manager.cpp:500
|
||||
#: src/input/device_manager.cpp:501
|
||||
msgid "Please re-configure your key bindings."
|
||||
msgstr ""
|
||||
|
||||
#: src/input/device_manager.cpp:501
|
||||
#: src/input/device_manager.cpp:502
|
||||
msgid "Your input config file is not compatible with this version of STK."
|
||||
msgstr ""
|
||||
|
||||
@ -2586,25 +2588,25 @@ msgstr ""
|
||||
msgid "Left thumb up"
|
||||
msgstr ""
|
||||
|
||||
#: src/input/input_manager.cpp:776
|
||||
#: src/input/input_manager.cpp:768
|
||||
#, c-format
|
||||
msgid "Ignoring '%s'. You needed to join earlier to play!"
|
||||
msgstr ""
|
||||
|
||||
#: src/input/input_manager.cpp:806
|
||||
#: src/input/input_manager.cpp:798
|
||||
msgid "Only the Game Master may act at this point!"
|
||||
msgstr ""
|
||||
|
||||
#: src/input/wiimote_manager.cpp:389
|
||||
msgid ""
|
||||
"Connect your wiimote to the Bluetooth manager, then click on Ok.Detailed "
|
||||
"Connect your wiimote to the Bluetooth manager, then click on Ok. Detailed "
|
||||
"instructions at supertuxkart.net/Wiimote"
|
||||
msgstr ""
|
||||
|
||||
#: src/input/wiimote_manager.cpp:392
|
||||
msgid ""
|
||||
"Press the buttons 1+2 simultaneously on your wiimote to put it in discovery "
|
||||
"mode, then click on Ok.Detailed instructions at supertuxkart.net/Wiimote"
|
||||
"mode, then click on Ok. Detailed instructions at supertuxkart.net/Wiimote"
|
||||
msgstr ""
|
||||
|
||||
#: src/input/wiimote_manager.cpp:415
|
||||
@ -2618,23 +2620,23 @@ msgstr[1] ""
|
||||
msgid "Could not detect any wiimote :/"
|
||||
msgstr ""
|
||||
|
||||
#: src/karts/controller/local_player_controller.cpp:204
|
||||
#: src/karts/controller/local_player_controller.cpp:206
|
||||
msgid "Penalty time!!"
|
||||
msgstr ""
|
||||
|
||||
#: src/karts/controller/local_player_controller.cpp:206
|
||||
#: src/karts/controller/local_player_controller.cpp:208
|
||||
msgid "Don't accelerate before go"
|
||||
msgstr ""
|
||||
|
||||
#: src/karts/kart.cpp:867 src/karts/kart.cpp:872
|
||||
#: src/karts/kart.cpp:852 src/karts/kart.cpp:857
|
||||
msgid "You won the race!"
|
||||
msgstr ""
|
||||
|
||||
#: src/karts/kart.cpp:872
|
||||
#: src/karts/kart.cpp:857
|
||||
msgid "You finished the race!"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1296
|
||||
#: src/main.cpp:1413
|
||||
msgid ""
|
||||
"SuperTuxKart may connect to a server to download add-ons and notify you of "
|
||||
"updates. We also collect anonymous hardware statistics to help with the "
|
||||
@ -2644,15 +2646,16 @@ msgid ""
|
||||
"edit \"Connect to the Internet\" and \"Send anonymous HW statistics\")."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1446
|
||||
#: src/main.cpp:1563
|
||||
msgid ""
|
||||
"Your driver version is too old. Please install the latest video drivers."
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:1458
|
||||
#: src/main.cpp:1580
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Your OpenGL version appears to be too old. Please verify if an update for "
|
||||
"your video driver is available. SuperTuxKart requires OpenGL 3.1 or better."
|
||||
"your video driver is available. SuperTuxKart requires %s or better."
|
||||
msgstr ""
|
||||
|
||||
#: src/modes/easter_egg_hunt.cpp:202
|
||||
@ -2660,7 +2663,7 @@ msgstr ""
|
||||
msgid "Eggs: %d / %d"
|
||||
msgstr ""
|
||||
|
||||
#: src/modes/follow_the_leader.cpp:61 src/modes/follow_the_leader.cpp:293
|
||||
#: src/modes/follow_the_leader.cpp:61 src/modes/follow_the_leader.cpp:284
|
||||
msgid "Leader"
|
||||
msgstr ""
|
||||
|
||||
@ -2687,11 +2690,11 @@ msgstr ""
|
||||
msgid "WRONG WAY!"
|
||||
msgstr ""
|
||||
|
||||
#: src/modes/world.cpp:1208
|
||||
#: src/modes/world.cpp:1207
|
||||
msgid "You have been eliminated!"
|
||||
msgstr ""
|
||||
|
||||
#: src/modes/world.cpp:1211
|
||||
#: src/modes/world.cpp:1210
|
||||
#, c-format
|
||||
msgid "'%s' has been eliminated."
|
||||
msgstr ""
|
||||
@ -2700,7 +2703,7 @@ msgstr ""
|
||||
msgid "Failed to register server"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/servers_manager.cpp:195
|
||||
#: src/network/servers_manager.cpp:197
|
||||
msgid "No LAN server detected"
|
||||
msgstr ""
|
||||
|
||||
@ -2815,27 +2818,33 @@ msgstr ""
|
||||
msgid "2 years"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/addons_screen.cpp:110
|
||||
#: src/states_screens/addons_screen.cpp:115
|
||||
msgid "Add-on name"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/addons_screen.cpp:111
|
||||
#: src/states_screens/addons_screen.cpp:116
|
||||
msgid "Updated date"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/addons_screen.cpp:147
|
||||
msgid ""
|
||||
"Access to the Internet is disabled. (To enable it, go to options and select "
|
||||
"tab 'User Interface')"
|
||||
msgstr ""
|
||||
|
||||
#. I18N: as in: The Old Island by Johannes Sjolund
|
||||
#: src/states_screens/addons_screen.cpp:304
|
||||
#: src/states_screens/addons_screen.cpp:343
|
||||
#, c-format
|
||||
msgctxt "addons"
|
||||
msgid "%s by %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/addons_screen.cpp:435
|
||||
#: src/states_screens/addons_screen.cpp:474
|
||||
msgid "Please wait while addons are updated"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/addons_screen.cpp:512
|
||||
#: src/states_screens/main_menu_screen.cpp:553
|
||||
#: src/states_screens/addons_screen.cpp:551
|
||||
#: src/states_screens/main_menu_screen.cpp:554
|
||||
msgid ""
|
||||
"Sorry, an error occurred while contacting the add-ons website. Make sure you "
|
||||
"are connected to the Internet and that SuperTuxKart is not blocked by a "
|
||||
@ -3210,32 +3219,32 @@ msgstr ""
|
||||
msgid "Select a track"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/feature_unlocked.cpp:199
|
||||
#: src/states_screens/feature_unlocked.cpp:200
|
||||
#, c-format
|
||||
msgid "You completed the easy challenge! Points earned on this level: %i/%i"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/feature_unlocked.cpp:203
|
||||
#: src/states_screens/feature_unlocked.cpp:204
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You completed the intermediate challenge! Points earned on this level: %i/%i"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/feature_unlocked.cpp:207
|
||||
#: src/states_screens/feature_unlocked.cpp:208
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You completed the difficult challenge! Points earned on this level: %i/%i"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/feature_unlocked.cpp:492
|
||||
#: src/states_screens/feature_unlocked.cpp:493
|
||||
msgid "Challenge Completed"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/feature_unlocked.cpp:529
|
||||
#: src/states_screens/feature_unlocked.cpp:530
|
||||
msgid "You unlocked track %0"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/feature_unlocked.cpp:567
|
||||
#: src/states_screens/feature_unlocked.cpp:568
|
||||
msgid "You unlocked grand prix %0"
|
||||
msgstr ""
|
||||
|
||||
@ -3271,16 +3280,16 @@ msgid "User defined"
|
||||
msgstr ""
|
||||
|
||||
#. I18N: when failing a GP
|
||||
#: src/states_screens/grand_prix_lose.cpp:153
|
||||
#: src/states_screens/grand_prix_lose.cpp:154
|
||||
msgid "Better luck next time!"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/grand_prix_win.cpp:126
|
||||
#: src/states_screens/grand_prix_win.cpp:127
|
||||
#: src/states_screens/race_result_gui.cpp:194
|
||||
msgid "You completed a challenge!"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/grand_prix_win.cpp:283
|
||||
#: src/states_screens/grand_prix_win.cpp:284
|
||||
msgid "You completed the Grand Prix!"
|
||||
msgstr ""
|
||||
|
||||
@ -3299,25 +3308,25 @@ msgid ""
|
||||
"Press the 'Select' button to join the game"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/main_menu_screen.cpp:492
|
||||
#: src/states_screens/main_menu_screen.cpp:493
|
||||
msgid ""
|
||||
"You can not play online without internet access. If you want to play online, "
|
||||
"go to options, select tab 'User Interface', and edit \"Connect to the "
|
||||
"Internet\"."
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/main_menu_screen.cpp:516
|
||||
#: src/states_screens/main_menu_screen.cpp:517
|
||||
msgid ""
|
||||
"You can not download addons without internet access. If you want to download "
|
||||
"addons, go to options, select tab 'User Interface', and edit \"Connect to "
|
||||
"the Internet\"."
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/main_menu_screen.cpp:548
|
||||
#: src/states_screens/main_menu_screen.cpp:549
|
||||
msgid "The add-ons module is currently disabled in the Options screen"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/main_menu_screen.cpp:560
|
||||
#: src/states_screens/main_menu_screen.cpp:561
|
||||
msgid "Please wait while the add-ons are loading"
|
||||
msgstr ""
|
||||
|
||||
@ -3505,14 +3514,14 @@ msgstr ""
|
||||
msgid "Keyboard %i"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/options_screen_ui.cpp:155
|
||||
#: src/states_screens/options_screen_ui.cpp:158
|
||||
msgid ""
|
||||
"In multiplayer mode, players can select handicapped (more difficult) "
|
||||
"profiles on the kart selection screen"
|
||||
msgstr ""
|
||||
|
||||
#. I18N: in the language choice, to select the same language as the OS
|
||||
#: src/states_screens/options_screen_ui.cpp:187
|
||||
#: src/states_screens/options_screen_ui.cpp:190
|
||||
msgid "System Language"
|
||||
msgstr ""
|
||||
|
||||
@ -3642,20 +3651,20 @@ msgid "GOAL!"
|
||||
msgstr ""
|
||||
|
||||
#. I18N: string used to show the author of the music. (e.g. "Sunny Song" by "John Doe")
|
||||
#: src/states_screens/race_gui_base.cpp:504
|
||||
#: src/states_screens/race_gui_base.cpp:496
|
||||
msgid "by"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_gui_base.cpp:612
|
||||
#: src/states_screens/race_gui_base.cpp:604
|
||||
msgid "Collect nitro!"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_gui_base.cpp:614
|
||||
#: src/states_screens/race_gui_base.cpp:606
|
||||
msgid "Follow the leader!"
|
||||
msgstr ""
|
||||
|
||||
#. I18N: When some GlobalPlayerIcons are hidden, write "Top 10" to show it
|
||||
#: src/states_screens/race_gui_base.cpp:780
|
||||
#: src/states_screens/race_gui_base.cpp:772
|
||||
#, c-format
|
||||
msgid "Top %i"
|
||||
msgstr ""
|
||||
@ -3669,15 +3678,15 @@ msgstr ""
|
||||
msgid "Rank"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_gui_overworld.cpp:469
|
||||
#: src/states_screens/race_gui_overworld.cpp:472
|
||||
msgid "Press fire to play the tutorial"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_gui_overworld.cpp:508
|
||||
#: src/states_screens/race_gui_overworld.cpp:511
|
||||
msgid "Type: Grand Prix"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_gui_overworld.cpp:539
|
||||
#: src/states_screens/race_gui_overworld.cpp:548
|
||||
msgid "Press fire to start the challenge"
|
||||
msgstr ""
|
||||
|
||||
@ -3745,10 +3754,20 @@ msgstr ""
|
||||
msgid "Grand Prix progress:"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_result_gui.cpp:1341
|
||||
#: src/states_screens/race_result_gui.cpp:1344
|
||||
msgid "Highscores"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_result_gui.cpp:1430
|
||||
#, c-format
|
||||
msgid "Difficulty: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_result_gui.cpp:1438
|
||||
#, c-format
|
||||
msgid "Best lap time: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_setup_screen.cpp:87
|
||||
msgid "All blows allowed, so catch weapons and make clever use of them!"
|
||||
msgstr ""
|
||||
@ -3767,7 +3786,7 @@ msgid "Hit others with weapons until they lose all their lives."
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_setup_screen.cpp:119
|
||||
msgid "Push the ball to the opposite cage to score goals."
|
||||
msgid "Push the ball into the opposite cage to score goals."
|
||||
msgstr ""
|
||||
|
||||
#: src/states_screens/race_setup_screen.cpp:129
|
||||
|
@ -1,23 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Library directory
|
||||
LIBDIR="bin"
|
||||
|
||||
# If we are launching from a symlink, such as /usr/local/bin/run_supertux.sh, we need to get where
|
||||
# the symlink points to
|
||||
pth="`readlink $0`"
|
||||
|
||||
# $pth will be empty if our start path wasnt a symlink
|
||||
if [ $pth ]; then
|
||||
GAMEDIR="`dirname $pth`"
|
||||
else
|
||||
GAMEDIR="`dirname $0`"
|
||||
fi
|
||||
|
||||
# Change to the game dir, and go!
|
||||
cd $GAMEDIR
|
||||
# export game library directory
|
||||
test -n "${LIBDIR}" && export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${GAMEDIR}/${LIBDIR}"
|
||||
|
||||
bin/supertuxkart $*
|
||||
|
@ -1,8 +1,13 @@
|
||||
uniform sampler2D ntex;
|
||||
uniform sampler2D dtex;
|
||||
|
||||
#ifdef GL_ES
|
||||
layout (location = 0) out vec4 Diff;
|
||||
layout (location = 1) out vec4 Spec;
|
||||
#else
|
||||
out vec4 Diff;
|
||||
out vec4 Spec;
|
||||
#endif
|
||||
|
||||
#stk_include "utils/decodeNormal.frag"
|
||||
#stk_include "utils/getPosFromUVDepth.frag"
|
||||
|
@ -1,7 +1,12 @@
|
||||
uniform sampler2D ntex;
|
||||
|
||||
#ifdef GL_ES
|
||||
layout (location = 0) out vec4 Diff;
|
||||
layout (location = 1) out vec4 Spec;
|
||||
#else
|
||||
out vec4 Diff;
|
||||
out vec4 Spec;
|
||||
#endif
|
||||
|
||||
#stk_include "utils/decodeNormal.frag"
|
||||
#stk_include "utils/getPosFromUVDepth.frag"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#version 300 es
|
||||
|
||||
precision mediump float;
|
||||
|
||||
in vec3 Position;
|
||||
in vec2 Texcoord;
|
||||
out vec2 uv;
|
||||
|
@ -6,8 +6,13 @@ flat in float energy;
|
||||
flat in vec3 col;
|
||||
flat in float radius;
|
||||
|
||||
#ifdef GL_ES
|
||||
layout (location = 0) out vec4 Diff;
|
||||
layout (location = 1) out vec4 Spec;
|
||||
#else
|
||||
out vec4 Diff;
|
||||
out vec4 Spec;
|
||||
#endif
|
||||
|
||||
#stk_include "utils/decodeNormal.frag"
|
||||
#stk_include "utils/SpecularBRDF.frag"
|
||||
|
@ -1,8 +1,13 @@
|
||||
uniform sampler2D ntex;
|
||||
uniform sampler2D dtex;
|
||||
|
||||
#ifdef GL_ES
|
||||
layout (location = 0) out vec4 Diff;
|
||||
layout (location = 1) out vec4 Spec;
|
||||
#else
|
||||
out vec4 Diff;
|
||||
out vec4 Spec;
|
||||
#endif
|
||||
|
||||
#stk_include "utils/decodeNormal.frag"
|
||||
#stk_include "utils/SpecularBRDF.frag"
|
||||
|
@ -9,8 +9,13 @@ uniform float splitmax;
|
||||
uniform float shadow_res;
|
||||
|
||||
in vec2 uv;
|
||||
#ifdef GL_ES
|
||||
layout (location = 0) out vec4 Diff;
|
||||
layout (location = 1) out vec4 Spec;
|
||||
#else
|
||||
out vec4 Diff;
|
||||
out vec4 Spec;
|
||||
#endif
|
||||
|
||||
#stk_include "utils/decodeNormal.frag"
|
||||
#stk_include "utils/SpecularBRDF.frag"
|
||||
|
@ -8,8 +8,13 @@ uniform float split2;
|
||||
uniform float splitmax;
|
||||
|
||||
in vec2 uv;
|
||||
#ifdef GL_ES
|
||||
layout (location = 0) out vec4 Diff;
|
||||
layout (location = 1) out vec4 Spec;
|
||||
#else
|
||||
out vec4 Diff;
|
||||
out vec4 Spec;
|
||||
#endif
|
||||
|
||||
#stk_include "utils/decodeNormal.frag"
|
||||
#stk_include "utils/SpecularBRDF.frag"
|
||||
|
@ -3,6 +3,7 @@ layout(bindless_sampler) uniform sampler2D tex;
|
||||
#else
|
||||
uniform sampler2D tex;
|
||||
#endif
|
||||
uniform float custom_alpha;
|
||||
|
||||
in vec2 uv;
|
||||
in vec4 color;
|
||||
@ -18,5 +19,5 @@ void main()
|
||||
Color.xyz *= pow(color.xyz, vec3(2.2));
|
||||
Color.a *= color.a;
|
||||
// Premultiply alpha
|
||||
FragColor = vec4(Color.rgb * Color.a, Color.a);
|
||||
FragColor = vec4(Color.rgb * (Color.a * custom_alpha), Color.a * custom_alpha);
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
Here are the guidelines to follow when coding SuperTuxKart:
|
||||
|
||||
Filenames
|
||||
=========
|
||||
|
||||
The filenames should be, with underscores between words. Use the .cpp
|
||||
extension for C++ implementation files and .hpp for C++ headers, .c for
|
||||
C files and .h for C headers.
|
||||
|
||||
|
||||
Coding style
|
||||
============
|
||||
|
||||
The coding style used in Super Tux Kart can be found at
|
||||
http://supertuxkart.net/Coding_Style
|
||||
|
||||
|
||||
Documentation line length
|
||||
=========================
|
||||
|
||||
All the documentation files should have at most 80 characters, because
|
||||
on some displays and on paper you often are limited to 80 characters, and
|
||||
also under some conditions appendices (for example, line numbers) are
|
||||
added. The exception if the player's manual, because it's long, so to
|
||||
understand it better it should be limited to 65 characters.
|
@ -67,6 +67,7 @@ set(ANGELSCRIPT_SOURCE
|
||||
../../source/as_builder.cpp
|
||||
../../source/as_bytecode.cpp
|
||||
../../source/as_callfunc.cpp
|
||||
../../source/as_callfunc_mips.cpp
|
||||
../../source/as_callfunc_x86.cpp
|
||||
../../source/as_callfunc_x64_gcc.cpp
|
||||
../../source/as_callfunc_x64_msvc.cpp
|
||||
|
@ -844,7 +844,7 @@
|
||||
#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
|
||||
#define AS_X86
|
||||
#undef AS_NO_THISCALL_FUNCTOR_METHOD
|
||||
#elif defined(__LP64__) && !defined(__arm64__)
|
||||
#elif defined(__x86_64__)
|
||||
#define AS_X64_GCC
|
||||
#undef AS_NO_THISCALL_FUNCTOR_METHOD
|
||||
#define HAS_128_BIT_PRIMITIVES
|
||||
|
@ -16,3 +16,5 @@ add_library(glew STATIC
|
||||
include/GL/glew.h include/GL/glxew.h include/GL/wglew.h
|
||||
src/glew.c src/glewinfo.c
|
||||
)
|
||||
|
||||
target_link_libraries(glew ${OPENGL_LIBRARIES})
|
||||
|
@ -86,7 +86,7 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param)
|
||||
: CIrrDeviceStub(param),
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
display(0), visual(0), screennr(0), window(0), StdHints(0), SoftwareImage(0),
|
||||
XInputMethod(0), XInputContext(0),
|
||||
XInputMethod(0), XInputContext(0), numlock_mask(0),
|
||||
#ifdef _IRR_COMPILE_WITH_OPENGL_
|
||||
glxWin(0),
|
||||
Context(0),
|
||||
@ -140,6 +140,7 @@ CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param)
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
createInputContext();
|
||||
numlock_mask = getNumlockMask(display);
|
||||
#endif
|
||||
|
||||
createGUIAndScene();
|
||||
@ -898,7 +899,7 @@ bool CIrrDeviceLinux::createWindow()
|
||||
WMCheck, 0L, 1L, False, XA_WINDOW,
|
||||
&type, &form, &len, &remain,
|
||||
(unsigned char **)&list);
|
||||
|
||||
XFree(list);
|
||||
bool netWM = (s == Success) && len;
|
||||
attributes.override_redirect = !netWM && CreationParams.Fullscreen;
|
||||
|
||||
@ -1260,13 +1261,59 @@ void CIrrDeviceLinux::destroyInputContext()
|
||||
}
|
||||
}
|
||||
|
||||
int CIrrDeviceLinux::getNumlockMask(Display* display)
|
||||
{
|
||||
int mask_table[8] = {ShiftMask, LockMask, ControlMask, Mod1Mask,
|
||||
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask};
|
||||
|
||||
if (!display)
|
||||
return 0;
|
||||
|
||||
KeyCode numlock_keycode = XKeysymToKeycode(display, XK_Num_Lock);
|
||||
|
||||
if (numlock_keycode == NoSymbol)
|
||||
return 0;
|
||||
|
||||
XModifierKeymap* map = XGetModifierMapping(display);
|
||||
if (!map)
|
||||
return 0;
|
||||
|
||||
int mask = 0;
|
||||
for (int i = 0; i < 8 * map->max_keypermod; i++)
|
||||
{
|
||||
if (map->modifiermap[i] != numlock_keycode)
|
||||
continue;
|
||||
|
||||
mask = mask_table[i/map->max_keypermod];
|
||||
break;
|
||||
}
|
||||
|
||||
XFreeModifiermap(map);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
EKEY_CODE CIrrDeviceLinux::getKeyCode(XEvent &event)
|
||||
{
|
||||
EKEY_CODE keyCode = (EKEY_CODE)0;
|
||||
|
||||
SKeyMap mp;
|
||||
mp.X11Key = XkbKeycodeToKeysym(display, event.xkey.keycode, 0, 0);
|
||||
// mp.X11Key = XKeycodeToKeysym(XDisplay, event.xkey.keycode, 0); // deprecated, if we still find platforms which need that we have to use some define
|
||||
|
||||
// First check for numpad keys
|
||||
bool is_numpad_key = false;
|
||||
if (event.xkey.state & numlock_mask)
|
||||
{
|
||||
mp.X11Key = XkbKeycodeToKeysym(display, event.xkey.keycode, 0, 1);
|
||||
|
||||
if (mp.X11Key >=XK_KP_0 && mp.X11Key <= XK_KP_9)
|
||||
is_numpad_key = true;
|
||||
}
|
||||
|
||||
// If it's not numpad key, then get keycode in typical way
|
||||
if (!is_numpad_key)
|
||||
{
|
||||
mp.X11Key = XkbKeycodeToKeysym(display, event.xkey.keycode, 0, 0);
|
||||
}
|
||||
|
||||
const s32 idx = KeyMap.binary_search(mp);
|
||||
if (idx != -1)
|
||||
{
|
||||
|
@ -156,6 +156,7 @@ namespace irr
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
bool createInputContext();
|
||||
void destroyInputContext();
|
||||
int getNumlockMask(Display* display);
|
||||
EKEY_CODE getKeyCode(XEvent &event);
|
||||
#endif
|
||||
|
||||
@ -399,6 +400,7 @@ namespace irr
|
||||
XIM XInputMethod;
|
||||
XIC XInputContext;
|
||||
mutable core::stringc Clipboard;
|
||||
int numlock_mask;
|
||||
#ifdef _IRR_LINUX_X11_VIDMODE_
|
||||
XF86VidModeModeInfo oldVideoMode;
|
||||
#endif
|
||||
|
@ -123,13 +123,6 @@ namespace video
|
||||
EGL_NONE, 0
|
||||
#endif
|
||||
};
|
||||
EGLint contextAttrib[] =
|
||||
{
|
||||
#ifdef EGL_VERSION_1_3
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
#endif
|
||||
EGL_NONE, 0
|
||||
};
|
||||
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
@ -242,11 +235,41 @@ namespace video
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
os::Printer::log("Creating EglContext...");
|
||||
EglContext = eglCreateContext(EglDisplay, config, EGL_NO_CONTEXT, contextAttrib);
|
||||
EglContext = EGL_NO_CONTEXT;
|
||||
|
||||
if (!Params.ForceLegacyDevice)
|
||||
{
|
||||
os::Printer::log("Trying to create Context for OpenGL-ES3.");
|
||||
|
||||
EGLint contextAttrib[] =
|
||||
{
|
||||
#ifdef EGL_VERSION_1_3
|
||||
EGL_CONTEXT_CLIENT_VERSION, 3,
|
||||
#endif
|
||||
EGL_NONE, 0
|
||||
};
|
||||
|
||||
EglContext = eglCreateContext(EglDisplay, config, EGL_NO_CONTEXT, contextAttrib);
|
||||
}
|
||||
|
||||
if (EGL_NO_CONTEXT == EglContext)
|
||||
{
|
||||
os::Printer::log("FAILED\n");
|
||||
os::Printer::log("Could not create Context for OpenGL-ES2 display.");
|
||||
os::Printer::log("Trying to create Context for OpenGL-ES2.");
|
||||
|
||||
EGLint contextAttrib[] =
|
||||
{
|
||||
#ifdef EGL_VERSION_1_3
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
#endif
|
||||
EGL_NONE, 0
|
||||
};
|
||||
|
||||
EglContext = eglCreateContext(EglDisplay, config, EGL_NO_CONTEXT, contextAttrib);
|
||||
if (EGL_NO_CONTEXT == EglContext)
|
||||
{
|
||||
os::Printer::log("FAILED\n");
|
||||
os::Printer::log("Could not create Context for OpenGL-ES2 display.");
|
||||
}
|
||||
}
|
||||
|
||||
eglMakeCurrent(EglDisplay, EglSurface, EglSurface, EglContext);
|
||||
|
@ -1474,77 +1474,6 @@ void CSkinnedMesh::calculateTangents(
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Copies a mesh.
|
||||
*/
|
||||
CSkinnedMesh *CSkinnedMesh::clone()
|
||||
{
|
||||
|
||||
CSkinnedMesh* skinned_mesh = new CSkinnedMesh();
|
||||
|
||||
for (u32 i = 0; i < getMeshBuffers().size(); i++)
|
||||
{
|
||||
SSkinMeshBuffer * buffer = skinned_mesh->addMeshBuffer();
|
||||
*buffer = *(getMeshBuffers()[i]);
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < getAllJoints().size(); ++j)
|
||||
{
|
||||
ISkinnedMesh::SJoint *joint = skinned_mesh->addJoint();
|
||||
*joint = *(getAllJoints()[j]);
|
||||
}
|
||||
|
||||
// fix children pointers (they still have old pointers)
|
||||
core::array<ISkinnedMesh::SJoint*> & new_joints = skinned_mesh->getAllJoints();
|
||||
for (u32 i = 0; i < new_joints.size(); ++i)
|
||||
{
|
||||
ISkinnedMesh::SJoint * joint = new_joints[i];
|
||||
for (u32 c = 0; c < joint->Children.size(); ++c)
|
||||
{
|
||||
// the child is one of the oldJoints and must be replaced by the newjoint on the same index
|
||||
bool found = false;
|
||||
for (u32 k = 0; k < AllJoints.size(); ++k)
|
||||
{
|
||||
if (joint->Children[c] == AllJoints[k])
|
||||
{
|
||||
joint->Children[c] = new_joints[k];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
} // k < old_joints.size
|
||||
|
||||
if (!found)
|
||||
found = true;
|
||||
} // c < joint->Children.size()
|
||||
} // i < new_joints.size()
|
||||
|
||||
// In finalize the values from LocalBuffers are copied into
|
||||
// Weights[].StaticPos. Since skinned_mesh already has the correct
|
||||
// values in Weights, we have to copy the values from Weights
|
||||
// into LocalBuffer (so that in the copy from LocalBuffer to weights
|
||||
// no values are overwritten).
|
||||
// FIXME: Not ideal, better would be not to copy the values in
|
||||
// finalize().
|
||||
for (unsigned int i = 0; i<AllJoints.size(); ++i)
|
||||
{
|
||||
SJoint *joint = AllJoints[i];
|
||||
for (unsigned int j = 0; j<joint->Weights.size(); ++j)
|
||||
{
|
||||
const u16 buffer_id = joint->Weights[j].buffer_id;
|
||||
const u32 vertex_id = joint->Weights[j].vertex_id;
|
||||
|
||||
skinned_mesh->LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos = joint->Weights[j].StaticPos;
|
||||
skinned_mesh->LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal;
|
||||
}
|
||||
}
|
||||
skinned_mesh->finalize();
|
||||
|
||||
|
||||
|
||||
return skinned_mesh;
|
||||
|
||||
} // clone
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
|
@ -159,7 +159,6 @@ namespace scene
|
||||
void addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
|
||||
IAnimatedMeshSceneNode* node,
|
||||
ISceneManager* smgr);
|
||||
CSkinnedMesh *clone();
|
||||
private:
|
||||
void checkForAnimation();
|
||||
|
||||
|
@ -333,11 +333,10 @@ bool MusicOggStream::streamIntoBuffer(ALuint buffer)
|
||||
|
||||
int size = 0;
|
||||
int portion;
|
||||
int result;
|
||||
|
||||
while(size < m_buffer_size)
|
||||
{
|
||||
result = ov_read(&m_oggStream, pcm + size, m_buffer_size - size,
|
||||
int result = ov_read(&m_oggStream, pcm + size, m_buffer_size - size,
|
||||
isBigEndian, 2, 1, &portion);
|
||||
|
||||
if(result > 0)
|
||||
|
@ -424,7 +424,7 @@ void SFXOpenAL::setPosition(const Vec3 &position)
|
||||
{
|
||||
// Don't send a position command to the thread if the sound is not playing
|
||||
// (or sfx disabled or the sound was not initialised correctly)
|
||||
// if (m_status != SFX_PLAYING|| !SFXManager::get()->sfxAllowed()) return;
|
||||
if (!SFXManager::get()->sfxAllowed()) return;
|
||||
SFXManager::get()->queue(SFXManager::SFX_POSITION, this, position);
|
||||
|
||||
} // setPosition
|
||||
|
@ -516,7 +516,6 @@ const irr::core::stringw
|
||||
if (track == NULL) return irr::core::stringw( L"????" );
|
||||
|
||||
return _("New track '%s' now available", track->getName());
|
||||
break;
|
||||
}
|
||||
case UNLOCK_MODE:
|
||||
{
|
||||
|
@ -678,7 +678,7 @@ namespace UserConfigParams
|
||||
"Enable Screen Space Ambient Occlusion") );
|
||||
PARAM_PREFIX IntUserConfigParam m_shadows_resolution
|
||||
PARAM_DEFAULT( IntUserConfigParam(0,
|
||||
"shadows_resoltion", &m_graphics_quality,
|
||||
"shadows_resolution", &m_graphics_quality,
|
||||
"Shadow resolution (0 = disabled") );
|
||||
PARAM_PREFIX BoolUserConfigParam m_degraded_IBL
|
||||
PARAM_DEFAULT(BoolUserConfigParam(true,
|
||||
|
@ -18,9 +18,10 @@
|
||||
|
||||
#include "font/bold_face.hpp"
|
||||
|
||||
#include "font/face_ttf.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor of BoldFace.
|
||||
* \param ttf \ref FaceTTF for BoldFace to use.
|
||||
*/
|
||||
BoldFace::BoldFace(FaceTTF* ttf) : FontWithFace("BoldFace", ttf)
|
||||
{
|
||||
} // BoldFace
|
||||
@ -53,3 +54,12 @@ void BoldFace::reset()
|
||||
insertCharacters(preload_chars.c_str());
|
||||
updateCharactersList();
|
||||
} // reset
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Embolden the glyph to make bold font using FT_Outline_Embolden.
|
||||
* \return A FT_Error value.
|
||||
*/
|
||||
int BoldFace::shapeOutline(FT_Outline* outline) const
|
||||
{
|
||||
return FT_Outline_Embolden(outline, getDPI() * 2);
|
||||
} // shapeOutline
|
||||
|
@ -23,24 +23,28 @@
|
||||
|
||||
class FaceTTF;
|
||||
|
||||
/** A font which uses regular TTFs to render title or important message in STK
|
||||
* with a bold outline, it shares the same \ref FaceTTF with \ref RegularFace.
|
||||
* \ingroup font
|
||||
*/
|
||||
class BoldFace : public FontWithFace
|
||||
{
|
||||
private:
|
||||
virtual bool supportLazyLoadChar() const OVERRIDE { return true; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual unsigned int getGlyphPageSize() const OVERRIDE { return 1024; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getScalingFactorOne() const OVERRIDE { return 0.2f; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual unsigned int getScalingFactorTwo() const OVERRIDE { return 120; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool isBold() const { return true; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual int shapeOutline(FT_Outline* outline) const OVERRIDE;
|
||||
|
||||
public:
|
||||
LEAK_CHECK()
|
||||
// ------------------------------------------------------------------------
|
||||
BoldFace(FaceTTF* ttf);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual ~BoldFace() {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void init() OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void reset() OVERRIDE;
|
||||
|
@ -18,9 +18,10 @@
|
||||
|
||||
#include "font/digit_face.hpp"
|
||||
|
||||
#include "font/face_ttf.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor of DigitFace.
|
||||
* \param ttf \ref FaceTTF for DigitFace to use.
|
||||
*/
|
||||
DigitFace::DigitFace(FaceTTF* ttf) : FontWithFace("DigitFace", ttf)
|
||||
{
|
||||
} // DigitFace
|
||||
|
@ -23,6 +23,9 @@
|
||||
|
||||
class FaceTTF;
|
||||
|
||||
/** A font which uses a more cartonish style TTF to render big numbers in STK.
|
||||
* \ingroup font
|
||||
*/
|
||||
class DigitFace : public FontWithFace
|
||||
{
|
||||
private:
|
||||
@ -39,8 +42,6 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
DigitFace(FaceTTF* ttf);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual ~DigitFace() {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void init() OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void reset() OVERRIDE;
|
||||
|
@ -18,22 +18,29 @@
|
||||
|
||||
#include "font/face_ttf.hpp"
|
||||
|
||||
#include "font/font_manager.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor. Load all TTFs from a list.
|
||||
* \param ttf_list List of TTFs to be loaded.
|
||||
*/
|
||||
FaceTTF::FaceTTF(const std::vector<std::string>& ttf_list)
|
||||
{
|
||||
for (const std::string& font : ttf_list)
|
||||
{
|
||||
FT_Face face = NULL;
|
||||
const std::string loc = file_manager
|
||||
->getAssetChecked(FileManager::TTF, font.c_str(), true);
|
||||
font_manager->checkFTError(FT_New_Face(font_manager->getFTLibrary(),
|
||||
(file_manager->getAssetChecked(FileManager::TTF,
|
||||
font.c_str(), true)).c_str(), 0, &face), "loading fonts");
|
||||
loc.c_str(), 0, &face), loc + " is loaded");
|
||||
m_faces.push_back(face);
|
||||
}
|
||||
} // FaceTTF
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Destructor. Clears all TTFs.
|
||||
*/
|
||||
FaceTTF::~FaceTTF()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_faces.size(); i++)
|
||||
@ -42,6 +49,9 @@ FaceTTF::~FaceTTF()
|
||||
}
|
||||
} // ~FaceTTF
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Return a TTF in \ref m_faces.
|
||||
* \param i index of TTF file in \ref m_faces.
|
||||
*/
|
||||
FT_Face FaceTTF::getFace(unsigned int i) const
|
||||
{
|
||||
assert(i < m_faces.size());
|
||||
|
@ -19,15 +19,30 @@
|
||||
#ifndef HEADER_FACE_TTF_HPP
|
||||
#define HEADER_FACE_TTF_HPP
|
||||
|
||||
#include "font/font_manager.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
/** This class will load a list of TTF files from \ref STKConfig, and save
|
||||
* them inside \ref m_faces for \ref FontWithFace to load glyph.
|
||||
* Each FaceTTF can be used more than once in each instantiation of \ref
|
||||
* FontWithFace, so it can render characters differently using the same TTF
|
||||
* file to save memory, for example different outline size.
|
||||
* \ingroup font
|
||||
*/
|
||||
class FaceTTF : public NoCopy
|
||||
{
|
||||
private:
|
||||
/** Contains all TTF files loaded. */
|
||||
std::vector<FT_Face> m_faces;
|
||||
|
||||
public:
|
||||
LEAK_CHECK();
|
||||
LEAK_CHECK()
|
||||
// ------------------------------------------------------------------------
|
||||
FaceTTF(const std::vector<std::string>& ttf_list);
|
||||
// ------------------------------------------------------------------------
|
||||
@ -35,6 +50,7 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
FT_Face getFace(unsigned int i) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the total TTF files loaded. */
|
||||
unsigned int getTotalFaces() const { return m_faces.size(); }
|
||||
|
||||
}; // FaceTTF
|
||||
|
@ -28,15 +28,22 @@
|
||||
|
||||
FontManager *font_manager = NULL;
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor. It will initialize the \ref m_ft_library.
|
||||
*/
|
||||
FontManager::FontManager()
|
||||
{
|
||||
checkFTError(FT_Init_FreeType(&m_ft_library), "loading freetype library");
|
||||
} // FontManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Destructor. Clears all fonts and related stuff.
|
||||
*/
|
||||
FontManager::~FontManager()
|
||||
{
|
||||
m_fonts.clearAndDeleteAll();
|
||||
for (unsigned int i = 0; i < m_fonts.size(); i++)
|
||||
delete m_fonts[i];
|
||||
m_fonts.clear();
|
||||
|
||||
delete m_normal_ttf;
|
||||
m_normal_ttf = NULL;
|
||||
delete m_digit_ttf;
|
||||
@ -47,6 +54,8 @@ FontManager::~FontManager()
|
||||
} // ~FontManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialize all \ref FaceTTF and \ref FontWithFace members.
|
||||
*/
|
||||
void FontManager::loadFonts()
|
||||
{
|
||||
// First load the TTF files required by each font
|
||||
@ -72,15 +81,10 @@ void FontManager::loadFonts()
|
||||
} // loadFonts
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void FontManager::checkFTError(FT_Error err, const std::string& desc) const
|
||||
{
|
||||
if (err > 0)
|
||||
{
|
||||
Log::error("FontManager", "Something wrong when %s!", desc.c_str());
|
||||
}
|
||||
} // checkFTError
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Unit testing that will try to load all translations in STK, and discover if
|
||||
* there is any characters required by it are not supported in \ref
|
||||
* m_normal_ttf.
|
||||
*/
|
||||
void FontManager::unitTesting()
|
||||
{
|
||||
std::vector<std::string> list = *(translations->getLanguageList());
|
||||
|
@ -19,14 +19,18 @@
|
||||
#ifndef HEADER_FONT_MANAGER_HPP
|
||||
#define HEADER_FONT_MANAGER_HPP
|
||||
|
||||
/** \defgroup font Font
|
||||
* This module stores font files and tools used to draw characters in STK.
|
||||
*/
|
||||
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
@ -34,17 +38,26 @@
|
||||
class FaceTTF;
|
||||
class FontWithFace;
|
||||
|
||||
/** This class stores all font files required in STK.
|
||||
* \ingroup font
|
||||
*/
|
||||
class FontManager : public NoCopy
|
||||
{
|
||||
private:
|
||||
PtrVector<FontWithFace> m_fonts;
|
||||
/** Stores all \ref FontWithFace used in STK. */
|
||||
std::vector<FontWithFace*> m_fonts;
|
||||
|
||||
/** A FreeType library, it holds the FT_Face internally inside freetype. */
|
||||
FT_Library m_ft_library;
|
||||
|
||||
/** TTF files used in \ref BoldFace and \ref RegularFace. */
|
||||
FaceTTF* m_normal_ttf;
|
||||
|
||||
/** TTF files used in \ref DigitFace. */
|
||||
FaceTTF* m_digit_ttf;
|
||||
|
||||
/** Map type for each \ref FontWithFace with a index, save getting time in
|
||||
* \ref getFont. */
|
||||
std::unordered_map<std::type_index, int> m_font_type_map;
|
||||
|
||||
public:
|
||||
@ -54,11 +67,12 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
~FontManager();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return a specfic type of \ref FontWithFace found in \ref m_fonts. */
|
||||
template <typename T> T* getFont()
|
||||
{
|
||||
T* out = NULL;
|
||||
const unsigned int n = m_font_type_map[std::type_index(typeid(T))];
|
||||
out = dynamic_cast<T*>(m_fonts.get(n));
|
||||
out = dynamic_cast<T*>(m_fonts[n]);
|
||||
if (out != NULL)
|
||||
{
|
||||
return out;
|
||||
@ -68,16 +82,23 @@ public:
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Check for any error discovered in a freetype function that will return
|
||||
* a FT_Error value.
|
||||
* a FT_Error value, and log into the terminal.
|
||||
* \param err The Freetype function.
|
||||
* \param desc The description of what is the function doing.
|
||||
*/
|
||||
void checkFTError(FT_Error err, const std::string& desc) const;
|
||||
* \param desc The description of what is the function doing. */
|
||||
void checkFTError(FT_Error err, const std::string& desc) const
|
||||
{
|
||||
if (err > 0)
|
||||
{
|
||||
Log::error("FontManager", "Something wrong when %s! The error "
|
||||
"code was %d.", desc.c_str(), err);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void loadFonts();
|
||||
// ------------------------------------------------------------------------
|
||||
void unitTesting();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the \ref m_ft_library. */
|
||||
FT_Library getFTLibrary() const { return m_ft_library; }
|
||||
|
||||
}; // FontManager
|
||||
|
@ -25,21 +25,34 @@
|
||||
|
||||
using namespace irr;
|
||||
|
||||
/** This class stores settings when rendering fonts, used when instantiating
|
||||
* \ref irr::gui::ScalableFont.
|
||||
* \ingroup font
|
||||
*/
|
||||
class FontSettings
|
||||
{
|
||||
private:
|
||||
/** True if black border will be drawn when rendering. */
|
||||
bool m_black_border;
|
||||
|
||||
/** If true, characters will have right alignment when rendering, for RTL
|
||||
* language. */
|
||||
bool m_rtl;
|
||||
|
||||
/** Scaling when rendering. */
|
||||
float m_scale;
|
||||
|
||||
/** True if shadow will be drawn when rendering. */
|
||||
bool m_shadow;
|
||||
|
||||
/** Save the color of shadow when rendering. */
|
||||
video::SColor m_shadow_color;
|
||||
|
||||
public:
|
||||
LEAK_CHECK()
|
||||
// ------------------------------------------------------------------------
|
||||
/** Constructor. It will initialize all members with default values if no
|
||||
* parameter is given. */
|
||||
FontSettings(bool black_border = false, bool rtl = false,
|
||||
float scale = 1.0f, bool shadow = false,
|
||||
const video::SColor& color = video::SColor(0, 0, 0, 0))
|
||||
@ -51,26 +64,39 @@ public:
|
||||
m_shadow_color = color;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
~FontSettings() {}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Set the scaling.
|
||||
* \param scale Scaling to be set. */
|
||||
void setScale(float scale) { m_scale = scale; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the scaling. */
|
||||
float getScale() const { return m_scale; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Set the color of shadow.
|
||||
* \param col The color of shadow to be set. */
|
||||
void setShadowColor(const video::SColor &col) { m_shadow_color = col; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the color of shadow. */
|
||||
const video::SColor& getShadowColor() const { return m_shadow_color; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return if shadow is enabled. */
|
||||
bool useShadow() const { return m_shadow; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Set whether shadow is enabled.
|
||||
* \param shadow If it's enabled. */
|
||||
void setShadow(bool shadow) { m_shadow = shadow; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Set whether black border is enabled.
|
||||
* \param border If it's enabled. */
|
||||
void setBlackBorder(bool border) { m_black_border = border; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return if black border is enabled. */
|
||||
bool useBlackBorder() const { return m_black_border; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Set right text alignment for RTL language.
|
||||
* \param rtl If it's enabled. */
|
||||
void setRTL(bool rtl) { m_rtl = rtl; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return if right text alignment for RTL language is enabled. */
|
||||
bool isRTL() const { return m_rtl; }
|
||||
|
||||
}; // FontSettings
|
||||
|
@ -18,17 +18,20 @@
|
||||
|
||||
#include "font/font_with_face.hpp"
|
||||
|
||||
#include "font/bold_face.hpp"
|
||||
#include "font/face_ttf.hpp"
|
||||
#include "font/font_manager.hpp"
|
||||
#include "font/font_settings.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/skin.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
#include FT_OUTLINE_H
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor. It will initialize the \ref m_spritebank and TTF files to use.
|
||||
* \param name The name of face, used by irrlicht to distinguish spritebank.
|
||||
* \param ttf \ref FaceTTF for this face to use.
|
||||
*/
|
||||
FontWithFace::FontWithFace(const std::string& name, FaceTTF* ttf)
|
||||
{
|
||||
m_spritebank = irr_driver->getGUI()->addEmptySpriteBank(name.c_str());
|
||||
@ -43,6 +46,8 @@ FontWithFace::FontWithFace(const std::string& name, FaceTTF* ttf)
|
||||
|
||||
} // FontWithFace
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Destructor. Clears the glyph page and sprite bank.
|
||||
*/
|
||||
FontWithFace::~FontWithFace()
|
||||
{
|
||||
m_page->drop();
|
||||
@ -56,6 +61,8 @@ FontWithFace::~FontWithFace()
|
||||
} // ~FontWithFace
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialize the font structure, but don't load glyph here.
|
||||
*/
|
||||
void FontWithFace::init()
|
||||
{
|
||||
setDPI();
|
||||
@ -83,7 +90,11 @@ void FontWithFace::init()
|
||||
|
||||
reset();
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Clear all the loaded characters, sub-class can do pre-loading of characters
|
||||
* after this.
|
||||
*/
|
||||
void FontWithFace::reset()
|
||||
{
|
||||
m_new_char_holder.clear();
|
||||
@ -94,6 +105,12 @@ void FontWithFace::reset()
|
||||
} // reset
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Convert a character to a glyph index in one of the font in \ref m_face_ttf,
|
||||
* it will find the first TTF that supports this character, if the final
|
||||
* glyph_index is 0, this means such character is not supported by all TTFs in
|
||||
* \ref m_face_ttf.
|
||||
* \param c The character to be loaded.
|
||||
*/
|
||||
void FontWithFace::loadGlyphInfo(wchar_t c)
|
||||
{
|
||||
unsigned int font_number = 0;
|
||||
@ -108,11 +125,12 @@ void FontWithFace::loadGlyphInfo(wchar_t c)
|
||||
} // loadGlyphInfo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Create a new glyph page by filling it with transparent content.
|
||||
*/
|
||||
void FontWithFace::createNewGlyphPage()
|
||||
{
|
||||
// Clean the current glyph page by filling it with transparent content
|
||||
m_page->fill(video::SColor(0, 255, 255, 255));
|
||||
m_temp_height = 0;
|
||||
m_current_height = 0;
|
||||
m_used_width = 0;
|
||||
m_used_height = 0;
|
||||
|
||||
@ -140,6 +158,10 @@ void FontWithFace::createNewGlyphPage()
|
||||
} // createNewGlyphPage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Render a glyph for a character into bitmap and save it into the glyph page.
|
||||
* \param c The character to be loaded.
|
||||
* \param c \ref GlyphInfo for the character.
|
||||
*/
|
||||
void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
|
||||
{
|
||||
assert(gi.glyph_index > 0);
|
||||
@ -147,7 +169,7 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
|
||||
FT_Face cur_face = m_face_ttf->getFace(gi.font_number);
|
||||
FT_GlyphSlot slot = cur_face->glyph;
|
||||
|
||||
// Faces may be shared across regular and bold,
|
||||
// Same face may be shared across the different FontWithFace,
|
||||
// so reset dpi each time
|
||||
font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()),
|
||||
"setting DPI");
|
||||
@ -155,15 +177,11 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
|
||||
font_manager->checkFTError(FT_Load_Glyph(cur_face, gi.glyph_index,
|
||||
FT_LOAD_DEFAULT), "loading a glyph");
|
||||
|
||||
if (dynamic_cast<BoldFace*>(this) != NULL)
|
||||
{
|
||||
// Embolden the outline of the glyph
|
||||
font_manager->checkFTError(FT_Outline_Embolden(&(slot->outline),
|
||||
getDPI() * 2), "embolden a glyph");
|
||||
}
|
||||
font_manager->checkFTError(shapeOutline(&(slot->outline)),
|
||||
"shaping outline");
|
||||
|
||||
font_manager->checkFTError(FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL),
|
||||
"render a glyph to bitmap");
|
||||
"rendering a glyph to bitmap");
|
||||
|
||||
// Convert to an anti-aliased bitmap
|
||||
FT_Bitmap bits = slot->bitmap;
|
||||
@ -176,7 +194,7 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
|
||||
true, 0);
|
||||
|
||||
if ((m_used_width + texture_size.Width > getGlyphPageSize() &&
|
||||
m_used_height + m_temp_height + texture_size.Height >
|
||||
m_used_height + m_current_height + texture_size.Height >
|
||||
getGlyphPageSize()) ||
|
||||
m_used_height + texture_size.Height > getGlyphPageSize())
|
||||
{
|
||||
@ -244,8 +262,8 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
|
||||
if (m_used_width + texture_size.Width > getGlyphPageSize())
|
||||
{
|
||||
m_used_width = 0;
|
||||
m_used_height += m_temp_height;
|
||||
m_temp_height = 0;
|
||||
m_used_height += m_current_height;
|
||||
m_current_height = 0;
|
||||
}
|
||||
|
||||
// Copy to the full glyph page
|
||||
@ -283,11 +301,13 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
|
||||
|
||||
// Store used area
|
||||
m_used_width += texture_size.Width;
|
||||
if (m_temp_height < texture_size.Height)
|
||||
m_temp_height = texture_size.Height;
|
||||
if (m_current_height < texture_size.Height)
|
||||
m_current_height = texture_size.Height;
|
||||
} // insertGlyph
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Update the supported characters for this font if required.
|
||||
*/
|
||||
void FontWithFace::updateCharactersList()
|
||||
{
|
||||
if (m_fallback_font != NULL)
|
||||
@ -321,6 +341,10 @@ void FontWithFace::updateCharactersList()
|
||||
} // updateCharactersList
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Write the current glyph page in png inside current running directory.
|
||||
* Mainly for debug use.
|
||||
* \param name The file name.
|
||||
*/
|
||||
void FontWithFace::dumpGlyphPage(const std::string& name)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_spritebank->getTextureCount(); i++)
|
||||
@ -341,20 +365,23 @@ void FontWithFace::dumpGlyphPage(const std::string& name)
|
||||
} // dumpGlyphPage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Write the current glyph page in png inside current running directory.
|
||||
* Useful in gdb without parameter.
|
||||
*/
|
||||
void FontWithFace::dumpGlyphPage()
|
||||
{
|
||||
dumpGlyphPage("face");
|
||||
} // dumpGlyphPage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Set the face dpi which is resolution-dependent.
|
||||
* Normal text will range from 0.8, in 640x* resolutions (won't scale below
|
||||
* that) to 1.0, in 1024x* resolutions, and linearly up.
|
||||
* Bold text will range from 0.2, in 640x* resolutions (won't scale below
|
||||
* that) to 0.4, in 1024x* resolutions, and linearly up.
|
||||
*/
|
||||
void FontWithFace::setDPI()
|
||||
{
|
||||
// Set face dpi:
|
||||
// Font size is resolution-dependent.
|
||||
// Normal text will range from 0.8, in 640x* resolutions (won't scale
|
||||
// below that) to 1.0, in 1024x* resolutions, and linearly up
|
||||
// Bold text will range from 0.2, in 640x* resolutions (won't scale
|
||||
// below that) to 0.4, in 1024x* resolutions, and linearly up
|
||||
const int screen_width = irr_driver->getFrameSize().Width;
|
||||
const int screen_height = irr_driver->getFrameSize().Height;
|
||||
float scale = std::max(0, screen_width - 640) / 564.0f;
|
||||
@ -371,6 +398,10 @@ void FontWithFace::setDPI()
|
||||
} // setDPI
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Return the \ref FontArea about a character.
|
||||
* \param c The character to get.
|
||||
* \param[out] fallback_font Whether fallback font is used.
|
||||
*/
|
||||
const FontWithFace::FontArea&
|
||||
FontWithFace::getAreaFromCharacter(const wchar_t c,
|
||||
bool* fallback_font) const
|
||||
@ -397,6 +428,12 @@ const FontWithFace::FontArea&
|
||||
} // getAreaFromCharacter
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Get the dimension of text with support to different \ref FontSettings,
|
||||
* it will also do checking for missing characters in font and lazy load them.
|
||||
* \param text The text to be calculated.
|
||||
* \param font_settings \ref FontSettings to use.
|
||||
* \return The dimension of text
|
||||
*/
|
||||
core::dimension2d<u32> FontWithFace::getDimension(const wchar_t* text,
|
||||
FontSettings* font_settings)
|
||||
{
|
||||
@ -441,6 +478,12 @@ core::dimension2d<u32> FontWithFace::getDimension(const wchar_t* text,
|
||||
} // getDimension
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Calculate the index of the character in the text on a specific position.
|
||||
* \param text The text to be calculated.
|
||||
* \param pixel_x The specific position.
|
||||
* \param font_settings \ref FontSettings to use.
|
||||
* \return The index of the character, -1 means no character in such position.
|
||||
*/
|
||||
int FontWithFace::getCharacterFromPos(const wchar_t* text, int pixel_x,
|
||||
FontSettings* font_settings) const
|
||||
{
|
||||
@ -466,6 +509,17 @@ int FontWithFace::getCharacterFromPos(const wchar_t* text, int pixel_x,
|
||||
} // getCharacterFromPos
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Render text and clip it to the specified rectangle if wanted, it will also
|
||||
* do checking for missing characters in font and lazy load them.
|
||||
* \param text The text to be rendering.
|
||||
* \param position The position to be rendering.
|
||||
* \param color The color used when rendering.
|
||||
* \param hcenter If rendered horizontally center.
|
||||
* \param vcenter If rendered vertically center.
|
||||
* \param clip If clipping is needed.
|
||||
* \param font_settings \ref FontSettings to use.
|
||||
* \param char_collector \ref FontCharCollector to render billboard text.
|
||||
*/
|
||||
void FontWithFace::render(const core::stringw& text,
|
||||
const core::rect<s32>& position,
|
||||
const video::SColor& color, bool hcenter,
|
||||
@ -473,7 +527,6 @@ void FontWithFace::render(const core::stringw& text,
|
||||
FontSettings* font_settings,
|
||||
FontCharCollector* char_collector)
|
||||
{
|
||||
const bool is_bold_face = (dynamic_cast<BoldFace*>(this) != NULL);
|
||||
const bool black_border = font_settings ?
|
||||
font_settings->useBlackBorder() : false;
|
||||
const bool rtl = font_settings ? font_settings->isRTL() : false;
|
||||
@ -621,7 +674,7 @@ void FontWithFace::render(const core::stringw& text,
|
||||
|
||||
const int sprite_amount = sprites.size();
|
||||
|
||||
if ((black_border || is_bold_face) && char_collector == NULL)
|
||||
if ((black_border || isBold()) && char_collector == NULL)
|
||||
{
|
||||
// Draw black border first, to make it behind the real character
|
||||
// which make script language display better
|
||||
@ -693,7 +746,7 @@ void FontWithFace::render(const core::stringw& text,
|
||||
m_fallback_font->m_spritebank->getTexture(tex_id) :
|
||||
m_spritebank->getTexture(tex_id));
|
||||
|
||||
if (fallback[n] || is_bold_face)
|
||||
if (fallback[n] || isBold())
|
||||
{
|
||||
video::SColor top = GUIEngine::getSkin()->getColor("font::top");
|
||||
video::SColor bottom = GUIEngine::getSkin()
|
||||
|
@ -19,47 +19,84 @@
|
||||
#ifndef HEADER_FONT_WITH_FACE_HPP
|
||||
#define HEADER_FONT_WITH_FACE_HPP
|
||||
|
||||
#include "font/font_manager.hpp"
|
||||
#include "font/font_settings.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_OUTLINE_H
|
||||
|
||||
#include <irrlicht.h>
|
||||
|
||||
using namespace irr;
|
||||
|
||||
const int BEARING = 64;
|
||||
|
||||
class FaceTTF;
|
||||
class FontSettings;
|
||||
|
||||
/** An abstract class which contains functions which convert vector fonts into
|
||||
* bitmap and render them in STK. To make STK draw characters with different
|
||||
* render option (like scaling, shadow) using a same FontWithFace, you need
|
||||
* to wrap this with \ref irr::gui::ScalableFont and configure the
|
||||
* \ref FontSettings for it.
|
||||
* \ingroup font
|
||||
*/
|
||||
class FontWithFace : public NoCopy
|
||||
{
|
||||
public:
|
||||
/** A class for \ref STKTextBillboard to get font info to render billboard
|
||||
* text. */
|
||||
class FontCharCollector
|
||||
{
|
||||
public:
|
||||
/** Collect the character info for billboard text.
|
||||
* \param texture The texture of the character.
|
||||
* \param destRect The destination rectangle
|
||||
* \param sourceRect The source rectangle in the glyph page
|
||||
* \param colors The color to render it. */
|
||||
virtual void collectChar(video::ITexture* texture,
|
||||
const core::rect<float>& destRect,
|
||||
const core::rect<s32>& sourceRect,
|
||||
const video::SColor* const colors) = 0;
|
||||
};
|
||||
|
||||
/** Glyph metrics for each glyph loaded. */
|
||||
struct FontArea
|
||||
{
|
||||
FontArea() : advance_x(0), bearing_x(0) ,offset_y(0), offset_y_bt(0),
|
||||
spriteno(0) {}
|
||||
/** Advance width for horizontal layout. */
|
||||
int advance_x;
|
||||
/** Left side bearing for horizontal layout. */
|
||||
int bearing_x;
|
||||
/** Top side bearing for horizontal layout. */
|
||||
int offset_y;
|
||||
/** Top side bearing for horizontal layout used in billboard text. */
|
||||
int offset_y_bt;
|
||||
/** Index number in sprite bank. */
|
||||
int spriteno;
|
||||
};
|
||||
|
||||
protected:
|
||||
int m_font_max_height;
|
||||
/** Used in vertical dimension calculation. */
|
||||
int m_font_max_height;
|
||||
|
||||
int m_glyph_max_height;
|
||||
/** Used in top side bearing calculation. */
|
||||
int m_glyph_max_height;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Check characters to see if they are loaded in font, if not load them.
|
||||
* For font that doesn't need lazy loading, nothing will be done.
|
||||
* \param in_ptr Characters to check.
|
||||
* \param first_load If true, it will ignore \ref supportLazyLoadChar,
|
||||
* which is called in \ref reset. */
|
||||
void insertCharacters(const wchar_t* in_ptr, bool first_load = false)
|
||||
{
|
||||
if (!supportLazyLoadChar() && !first_load) return;
|
||||
@ -88,44 +125,69 @@ protected:
|
||||
// ------------------------------------------------------------------------
|
||||
void updateCharactersList();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Set the fallback font for this font, so if some character is missing in
|
||||
* this font, it will use that fallback font to try rendering it.
|
||||
* \param face A \ref FontWithFace font. */
|
||||
void setFallbackFont(FontWithFace* face) { m_fallback_font = face; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Set the scaling of fallback font.
|
||||
* \param scale The scaling to set. */
|
||||
void setFallbackFontScale(float scale) { m_fallback_font_scale = scale; }
|
||||
|
||||
private:
|
||||
/** Mapping of glyph index to a TTF in \ref FaceTTF. */
|
||||
struct GlyphInfo
|
||||
{
|
||||
GlyphInfo(unsigned int font_num = 0, unsigned int glyph_idx = 0) :
|
||||
font_number(font_num), glyph_index(glyph_idx) {}
|
||||
/** Index to a TTF in \ref FaceTTF. */
|
||||
unsigned int font_number;
|
||||
/** Glyph index in the TTF, 0 means no such glyph. */
|
||||
unsigned int glyph_index;
|
||||
GlyphInfo(unsigned int first = 0, unsigned int second = 0)
|
||||
{
|
||||
font_number = first;
|
||||
glyph_index = second;
|
||||
}
|
||||
};
|
||||
|
||||
/** \ref FaceTTF to load glyph from. */
|
||||
FaceTTF* m_face_ttf;
|
||||
|
||||
/** Fallback font to use if some character isn't supported by this font. */
|
||||
FontWithFace* m_fallback_font;
|
||||
|
||||
/** Scaling for fallback font. */
|
||||
float m_fallback_font_scale;
|
||||
|
||||
/** A temporary holder stored new char to be inserted. */
|
||||
/** A temporary holder to store new characters to be inserted. */
|
||||
std::set<wchar_t> m_new_char_holder;
|
||||
|
||||
/** Sprite bank to store each glyph. */
|
||||
gui::IGUISpriteBank* m_spritebank;
|
||||
|
||||
/** A full glyph page for this font. */
|
||||
video::IImage* m_page;
|
||||
|
||||
unsigned int m_temp_height;
|
||||
/** The current max height at current drawing line in glyph page. */
|
||||
unsigned int m_current_height;
|
||||
|
||||
/** The used width in glyph page. */
|
||||
unsigned int m_used_width;
|
||||
|
||||
/** The used height in glyph page. */
|
||||
unsigned int m_used_height;
|
||||
|
||||
/** The dpi of this font. */
|
||||
unsigned int m_face_dpi;
|
||||
|
||||
/** Store a list of supported character to a \ref FontArea. */
|
||||
std::map<wchar_t, FontArea> m_character_area_map;
|
||||
|
||||
/** Store a list of loaded and tested character to a \ref GlyphInfo. */
|
||||
std::map<wchar_t, GlyphInfo> m_character_glyph_info_map;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return a character width.
|
||||
* \param area \ref FontArea to get glyph metrics.
|
||||
* \param fallback If fallback font is used.
|
||||
* \param scale The scaling of the character.
|
||||
* \return The calculated width with suitable scaling. */
|
||||
float getCharWidth(const FontArea& area, bool fallback, float scale) const
|
||||
{
|
||||
if (fallback)
|
||||
@ -134,6 +196,9 @@ private:
|
||||
return area.advance_x * scale;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Test if a character has already been tried to be loaded.
|
||||
* \param c Character to test.
|
||||
* \return True if tested. */
|
||||
bool loadedChar(wchar_t c) const
|
||||
{
|
||||
std::map<wchar_t, GlyphInfo>::const_iterator n =
|
||||
@ -143,6 +208,10 @@ private:
|
||||
return false;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Get the \ref GlyphInfo from \ref m_character_glyph_info_map about a
|
||||
* character.
|
||||
* \param c Character to get.
|
||||
* \return \ref GlyphInfo of this character. */
|
||||
const GlyphInfo& getGlyphInfo(wchar_t c) const
|
||||
{
|
||||
std::map<wchar_t, GlyphInfo>::const_iterator n =
|
||||
@ -152,6 +221,10 @@ private:
|
||||
return n->second;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Tells whether a character is supported by all TTFs in \ref m_face_ttf
|
||||
* which is determined by \ref GlyphInfo of this character.
|
||||
* \param c Character to test.
|
||||
* \return True if it's supported. */
|
||||
bool supportChar(wchar_t c)
|
||||
{
|
||||
std::map<wchar_t, GlyphInfo>::const_iterator n =
|
||||
@ -167,22 +240,36 @@ private:
|
||||
// ------------------------------------------------------------------------
|
||||
void createNewGlyphPage();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Add a character into \ref m_new_char_holder for lazy loading later. */
|
||||
void addLazyLoadChar(wchar_t c) { m_new_char_holder.insert(c); }
|
||||
// ------------------------------------------------------------------------
|
||||
void insertGlyph(wchar_t c, const GlyphInfo& gi);
|
||||
// ------------------------------------------------------------------------
|
||||
void setDPI();
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool supportLazyLoadChar() const = 0;
|
||||
/** Override it if sub-class should not do lazy loading characters. */
|
||||
virtual bool supportLazyLoadChar() const { return true; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Defined by sub-class about the texture size of glyph page, it should be
|
||||
* a power of two. */
|
||||
virtual unsigned int getGlyphPageSize() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Defined by sub-class about the scaling factor 1. */
|
||||
virtual float getScalingFactorOne() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Defined by sub-class about the scaling factor 2. */
|
||||
virtual unsigned int getScalingFactorTwo() const = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Override it if sub-class has bold outline. */
|
||||
virtual bool isBold() const { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Override it if any outline shaping is needed to be done before
|
||||
* rendering the glyph into bitmap.
|
||||
* \return A FT_Error value if needed. */
|
||||
virtual int shapeOutline(FT_Outline* outline) const { return 0; }
|
||||
|
||||
public:
|
||||
LEAK_CHECK();
|
||||
LEAK_CHECK()
|
||||
// ------------------------------------------------------------------------
|
||||
FontWithFace(const std::string& name, FaceTTF* ttf);
|
||||
// ------------------------------------------------------------------------
|
||||
@ -204,22 +291,17 @@ public:
|
||||
FontSettings* font_settings,
|
||||
FontCharCollector* char_collector = NULL);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Write the current glyph page in png inside current running directory.
|
||||
* Mainly for debug use.
|
||||
* \param name The file name.
|
||||
*/
|
||||
void dumpGlyphPage(const std::string& name);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Write the current glyph page in png inside current running directory.
|
||||
* Useful in gdb without parameter.
|
||||
*/
|
||||
void dumpGlyphPage();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the sprite bank. */
|
||||
gui::IGUISpriteBank* getSpriteBank() const { return m_spritebank; }
|
||||
// ------------------------------------------------------------------------
|
||||
const FontArea& getAreaFromCharacter(const wchar_t c,
|
||||
bool* fallback_font) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the dpi of this face. */
|
||||
unsigned int getDPI() const { return m_face_dpi; }
|
||||
|
||||
}; // FontWithFace
|
||||
|
@ -16,11 +16,12 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "font/face_ttf.hpp"
|
||||
|
||||
#include "font/regular_face.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor of RegularFace.
|
||||
* \param ttf \ref FaceTTF for RegularFace to use.
|
||||
*/
|
||||
RegularFace::RegularFace(FaceTTF* ttf) : FontWithFace("RegularFace", ttf)
|
||||
{
|
||||
} // RegularFace
|
||||
|
@ -23,11 +23,12 @@
|
||||
|
||||
class FaceTTF;
|
||||
|
||||
/** A font which uses regular TTFs to render most text in STK.
|
||||
* \ingroup font
|
||||
*/
|
||||
class RegularFace : public FontWithFace
|
||||
{
|
||||
private:
|
||||
virtual bool supportLazyLoadChar() const OVERRIDE { return true; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual unsigned int getGlyphPageSize() const OVERRIDE { return 512; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getScalingFactorOne() const OVERRIDE { return 0.7f; }
|
||||
@ -39,8 +40,6 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
RegularFace(FaceTTF* ttf);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual ~RegularFace() {}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void init() OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void reset() OVERRIDE;
|
||||
|
@ -34,14 +34,14 @@
|
||||
|
||||
|
||||
// ============================================================================
|
||||
class Primitive2DList : public TextureShader<Primitive2DList, 1>
|
||||
class Primitive2DList : public TextureShader<Primitive2DList, 1, float>
|
||||
{
|
||||
public:
|
||||
Primitive2DList()
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "primitive2dlist.vert",
|
||||
GL_FRAGMENT_SHADER, "transparent.frag");
|
||||
assignUniforms();
|
||||
assignUniforms("custom_alpha");
|
||||
assignSamplerNames(0, "tex", ST_BILINEAR_FILTERED);
|
||||
} // Primitive2DList
|
||||
}; //Primitive2DList
|
||||
@ -703,7 +703,7 @@ void draw2DVertexPrimitiveList(video::ITexture *tex, const void* vertices,
|
||||
VertexUtils::bindVertexArrayAttrib(vType);
|
||||
|
||||
Primitive2DList::getInstance()->use();
|
||||
Primitive2DList::getInstance()->setUniforms();
|
||||
Primitive2DList::getInstance()->setUniforms(1.0f);
|
||||
compressTexture(tex, false);
|
||||
Primitive2DList::getInstance()->setTextureUnits(getTextureGLuint(tex));
|
||||
glDrawElements(GL_TRIANGLE_FAN, primitiveCount, GL_UNSIGNED_SHORT, 0);
|
||||
|
@ -245,8 +245,11 @@ void Camera::setMode(Mode mode)
|
||||
{
|
||||
Vec3 start_offset(0, 1.6f, -3);
|
||||
Vec3 current_position = m_kart->getTrans()(start_offset);
|
||||
Vec3 target_position = m_kart->getTrans()(Vec3(0, 0, 1));
|
||||
// Don't set position and target the same, otherwise
|
||||
// nan values will be calculated in ViewArea of camera
|
||||
m_camera->setPosition(current_position.toIrrVector());
|
||||
m_camera->setTarget(m_camera->getPosition());
|
||||
m_camera->setTarget(target_position.toIrrVector());
|
||||
}
|
||||
|
||||
m_mode = mode;
|
||||
@ -291,9 +294,9 @@ void Camera::setInitialTransform()
|
||||
// direction till smoothMoveCamera has corrected this. Setting target
|
||||
// to position doesn't make sense, but smoothMoves will adjust the
|
||||
// value before the first frame is rendered
|
||||
m_camera->setTarget(m_camera->getPosition());
|
||||
Vec3 target_position = m_kart->getTrans()(Vec3(0, 0, 1));
|
||||
m_camera->setTarget(target_position.toIrrVector());
|
||||
m_camera->setRotation(core::vector3df(0, 0, 0));
|
||||
m_camera->setRotation( core::vector3df( 0.0f, 0.0f, 0.0f ) );
|
||||
m_camera->setFOV(m_fov);
|
||||
} // setInitialTransform
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/drive_graph.hpp"
|
||||
|
||||
#include "ICameraSceneNode.h"
|
||||
|
||||
@ -62,7 +62,7 @@ void CameraEnd::readEndCamera(const XMLNode &root)
|
||||
unsigned int index = i;
|
||||
// In reverse mode, reverse the order in which the
|
||||
// end cameras are read.
|
||||
if(QuadGraph::get()->isReverse())
|
||||
if(DriveGraph::get() != NULL && DriveGraph::get()->isReverse())
|
||||
index = root.getNumNodes() - 1 - i;
|
||||
const XMLNode *node = root.getNode(index);
|
||||
EndCameraInformation eci;
|
||||
|
@ -81,7 +81,7 @@ void CameraNormal::smoothMoveCamera(float dt)
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
float max_increase_with_zipper = kp->getZipperMaxSpeedIncrease();
|
||||
float max_speed_without_zipper = kp->getEngineMaxSpeed();
|
||||
float current_speed = m_kart->getSpeed();
|
||||
float current_speed = m_kart->getSmoothedSpeed();
|
||||
|
||||
const Skidding *ks = m_kart->getSkidding();
|
||||
float skid_factor = ks->getVisualSkidRotation();
|
||||
@ -101,16 +101,15 @@ void CameraNormal::smoothMoveCamera(float dt)
|
||||
Vec3 m_kart_camera_position_with_offset = m_kart->getTrans()(camera_offset);
|
||||
|
||||
// next target
|
||||
core::vector3df current_target = m_kart->getXYZ().toIrrVector();
|
||||
current_target.Y += 0.5f;
|
||||
Vec3 current_target = m_kart->getTrans()(Vec3(0, 0.5f, 0));
|
||||
// new required position of camera
|
||||
core::vector3df wanted_position = m_kart_camera_position_with_offset.toIrrVector();
|
||||
|
||||
float f = 5.0f;
|
||||
if ((m_kart->getSpeed() > 5 ) || (m_kart->getSpeed() < 0 ))
|
||||
if ((current_speed > 5 ) || (current_speed < 0 ))
|
||||
{
|
||||
f = m_kart->getSpeed()>0 ? m_kart->getSpeed()/3 + 1.0f
|
||||
: -1.5f * m_kart->getSpeed() + 2.0f;
|
||||
f = current_speed >0 ? current_speed/3 + 1.0f
|
||||
: -1.5f * current_speed + 2.0f;
|
||||
}
|
||||
current_position += (wanted_position - current_position) * (dt *f);
|
||||
|
||||
@ -128,7 +127,7 @@ void CameraNormal::smoothMoveCamera(float dt)
|
||||
|
||||
if(getMode()!=CM_FALLING)
|
||||
m_camera->setPosition(current_position);
|
||||
m_camera->setTarget(current_target);//set new target
|
||||
m_camera->setTarget(current_target.toIrrVector());//set new target
|
||||
|
||||
assert(!std::isnan(m_camera->getPosition().X));
|
||||
assert(!std::isnan(m_camera->getPosition().Y));
|
||||
@ -252,8 +251,7 @@ void CameraNormal::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
float side_way, float distance, float smoothing)
|
||||
{
|
||||
Vec3 wanted_position;
|
||||
Vec3 wanted_target = m_kart->getXYZ();
|
||||
wanted_target.setY(wanted_target.getY() + above_kart);
|
||||
Vec3 wanted_target = m_kart->getTrans()(Vec3(0, above_kart, 0));
|
||||
|
||||
float tan_up = tan(cam_angle);
|
||||
Vec3 relative_position(side_way,
|
||||
|
@ -49,6 +49,12 @@ void CentralVideoSettings::init()
|
||||
hasUBO = false;
|
||||
hasExplicitAttribLocation = false;
|
||||
hasGS = false;
|
||||
hasTextureFilterAnisotropic = false;
|
||||
|
||||
#if defined(USE_GLES2)
|
||||
hasBGRA = false;
|
||||
hasColorBufferFloat = false;
|
||||
#endif
|
||||
|
||||
m_GI_has_artifact = false;
|
||||
m_need_rh_workaround = false;
|
||||
@ -84,7 +90,7 @@ void CentralVideoSettings::init()
|
||||
std::string card((char*)(glGetString(GL_RENDERER)));
|
||||
GraphicsRestrictions::init(driver, card);
|
||||
|
||||
#if !defined(USE_GLES2)
|
||||
#if !defined(USE_GLES2)
|
||||
if (hasGLExtension("GL_AMD_vertex_shader_layer")) {
|
||||
hasVSLayer = true;
|
||||
Log::info("GLDriver", "AMD Vertex Shader Layer Present");
|
||||
@ -165,6 +171,11 @@ void CentralVideoSettings::init()
|
||||
hasExplicitAttribLocation = true;
|
||||
Log::info("GLDriver", "ARB Explicit Attrib Location Present");
|
||||
}
|
||||
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_FILTER_ANISOTROPIC) &&
|
||||
hasGLExtension("GL_EXT_texture_filter_anisotropic")) {
|
||||
hasTextureFilterAnisotropic = true;
|
||||
Log::info("GLDriver", "EXT Texture Filter Anisotropic Present");
|
||||
}
|
||||
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_GEOMETRY_SHADER) &&
|
||||
(m_gl_major_version > 3 || (m_gl_major_version == 3 && m_gl_minor_version >= 2))) {
|
||||
hasGS = true;
|
||||
@ -218,6 +229,21 @@ void CentralVideoSettings::init()
|
||||
hasAtomics = true;
|
||||
hasSSBO = true;
|
||||
}
|
||||
|
||||
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_FORMAT_BGRA8888) &&
|
||||
(hasGLExtension("GL_IMG_texture_format_BGRA8888") ||
|
||||
hasGLExtension("GL_EXT_texture_format_BGRA8888")))
|
||||
{
|
||||
hasBGRA = true;
|
||||
Log::info("GLDriver", "EXT texture format BGRA8888 Present");
|
||||
}
|
||||
|
||||
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_COLOR_BUFFER_FLOAT) &&
|
||||
hasGLExtension("GL_EXT_color_buffer_float"))
|
||||
{
|
||||
hasColorBufferFloat = true;
|
||||
Log::info("GLDriver", "EXT Color Buffer Float Present");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -337,6 +363,23 @@ bool CentralVideoSettings::isARBMultiDrawIndirectUsable() const
|
||||
return hasMultiDrawIndirect;
|
||||
}
|
||||
|
||||
bool CentralVideoSettings::isEXTTextureFilterAnisotropicUsable() const
|
||||
{
|
||||
return hasTextureFilterAnisotropic;
|
||||
}
|
||||
|
||||
#if defined(USE_GLES2)
|
||||
bool CentralVideoSettings::isEXTTextureFormatBGRA8888Usable() const
|
||||
{
|
||||
return hasBGRA;
|
||||
}
|
||||
|
||||
bool CentralVideoSettings::isEXTColorBufferFloatUsable() const
|
||||
{
|
||||
return hasColorBufferFloat;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CentralVideoSettings::supportsShadows() const
|
||||
{
|
||||
return isARBGeometryShadersUsable() && isARBUniformBufferObjectUsable() && isARBExplicitAttribLocationUsable();
|
||||
|
@ -42,6 +42,12 @@ private:
|
||||
bool hasSSBO;
|
||||
bool hasImageLoadStore;
|
||||
bool hasMultiDrawIndirect;
|
||||
bool hasTextureFilterAnisotropic;
|
||||
|
||||
#if defined(USE_GLES2)
|
||||
bool hasBGRA;
|
||||
bool hasColorBufferFloat;
|
||||
#endif
|
||||
|
||||
bool m_need_rh_workaround;
|
||||
bool m_need_srgb_workaround;
|
||||
@ -75,6 +81,12 @@ public:
|
||||
bool isARBImageLoadStoreUsable() const;
|
||||
bool isARBMultiDrawIndirectUsable() const;
|
||||
bool isARBExplicitAttribLocationUsable() const;
|
||||
bool isEXTTextureFilterAnisotropicUsable() const;
|
||||
|
||||
#if defined(USE_GLES2)
|
||||
bool isEXTTextureFormatBGRA8888Usable() const;
|
||||
bool isEXTColorBufferFloatUsable() const;
|
||||
#endif
|
||||
|
||||
|
||||
// Are all required extensions available for feature support
|
||||
|
@ -27,32 +27,8 @@
|
||||
#include "graphics/vao_manager.hpp"
|
||||
#include <irrlicht.h>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
class MeshRenderInfoHash
|
||||
{
|
||||
public:
|
||||
size_t operator() (const std::pair<scene::IMeshBuffer*, RenderInfo*> &p) const
|
||||
{
|
||||
return (std::hash<scene::IMeshBuffer*>()(p.first) ^
|
||||
(std::hash<RenderInfo*>()(p.second) << 1));
|
||||
}
|
||||
};
|
||||
|
||||
struct MeshRenderInfoEquals : std::binary_function
|
||||
<const std::pair<scene::IMeshBuffer*, RenderInfo*>&,
|
||||
const std::pair<scene::IMeshBuffer*, RenderInfo*>&, bool>
|
||||
{
|
||||
result_type operator() (first_argument_type lhs,
|
||||
second_argument_type rhs) const
|
||||
{
|
||||
return (lhs.first == rhs.first) &&
|
||||
(lhs.second == rhs.second);
|
||||
}
|
||||
};
|
||||
|
||||
struct InstanceList
|
||||
{
|
||||
GLMesh *m_mesh;
|
||||
|
@ -50,6 +50,8 @@ void DrawCalls::clearLists()
|
||||
{
|
||||
ListBlendTransparent::getInstance()->clear();
|
||||
ListAdditiveTransparent::getInstance()->clear();
|
||||
ListGhostKart::getInstance()->clear();
|
||||
ListGhostKartTangents::getInstance()->clear();
|
||||
ListBlendTransparentFog::getInstance()->clear();
|
||||
ListAdditiveTransparentFog::getInstance()->clear();
|
||||
ListDisplacement::getInstance()->clear();
|
||||
@ -159,10 +161,24 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
||||
else
|
||||
{
|
||||
for (GLMesh *mesh : node->TransparentMesh[TM_DEFAULT])
|
||||
pushVector(ListBlendTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix);
|
||||
pushVector(ListBlendTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix, 1.0f);
|
||||
for (GLMesh *mesh : node->TransparentMesh[TM_ADDITIVE])
|
||||
pushVector(ListAdditiveTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix);
|
||||
pushVector(ListAdditiveTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix, 1.0f);
|
||||
}
|
||||
|
||||
// Use sun color to determine custom alpha for ghost karts
|
||||
float custom_alpha = 1.0f;
|
||||
if (World::getWorld())
|
||||
{
|
||||
const video::SColor& c = World::getWorld()->getTrack()->getSunColor();
|
||||
float y = 0.2126f * c.getRed() + 0.7152f * c.getGreen() + 0.0722f * c.getBlue();
|
||||
custom_alpha = y > 128.0f ? 0.5f : 0.35f;
|
||||
}
|
||||
|
||||
for (GLMesh *mesh : node->TransparentMesh[TM_GHOST_KART])
|
||||
pushVector(ListGhostKart::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix, custom_alpha);
|
||||
for (GLMesh *mesh : node->TransparentMesh[TM_GHOST_KART_TANGENTS])
|
||||
pushVector(ListGhostKartTangents::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->TextureMatrix, custom_alpha);
|
||||
for (GLMesh *mesh : node->TransparentMesh[TM_DISPLACEMENT])
|
||||
pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation());
|
||||
|
||||
@ -532,10 +548,13 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices,
|
||||
PROFILER_PUSH_CPU_MARKER("- Sync Stall", 0xFF, 0x0, 0x0);
|
||||
GLenum reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
|
||||
|
||||
while (reason != GL_ALREADY_SIGNALED)
|
||||
if (reason != GL_ALREADY_SIGNALED)
|
||||
{
|
||||
if (reason == GL_WAIT_FAILED) break;
|
||||
reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000);
|
||||
do
|
||||
{
|
||||
reason = glClientWaitSync(m_sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000);
|
||||
}
|
||||
while (reason == GL_TIMEOUT_EXPIRED);
|
||||
}
|
||||
glDeleteSync(m_sync);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
@ -1,4 +1,4 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2015 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
@ -241,15 +241,24 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
|
||||
const FrameBuffer& colors_framebuffer,
|
||||
const PostProcessing* post_processing)
|
||||
{
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
irr_driver->setPhase(TRANSPARENT_PASS);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
renderTransparenPass<Shaders::TransparentShader, video::EVT_STANDARD, 3, 2, 1>(
|
||||
TexUnits(RenderGeometry::TexUnit(0, true)),
|
||||
ListGhostKart::getInstance());
|
||||
|
||||
renderTransparenPass<Shaders::TransparentShader, video::EVT_TANGENTS, 3, 2, 1>(
|
||||
TexUnits(RenderGeometry::TexUnit(0, true)),
|
||||
ListGhostKartTangents::getInstance());
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
glDisable(GL_CULL_FACE);
|
||||
draw_calls.renderImmediateDrawList();
|
||||
|
||||
if (CVS->isARBBaseInstanceUsable())
|
||||
@ -263,20 +272,20 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
|
||||
TexUnits(RenderGeometry::TexUnit(0, true)),
|
||||
ListBlendTransparentFog::getInstance());
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
renderTransparenPass<Shaders::TransparentFogShader,
|
||||
renderTransparenPass<Shaders::TransparentFogShader,
|
||||
video::EVT_STANDARD, 8, 7, 6, 5, 4, 3, 2, 1>(
|
||||
TexUnits(RenderGeometry::TexUnit(0, true)),
|
||||
TexUnits(RenderGeometry::TexUnit(0, true)),
|
||||
ListAdditiveTransparentFog::getInstance());
|
||||
}
|
||||
else
|
||||
{
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
renderTransparenPass<Shaders::TransparentShader,
|
||||
video::EVT_STANDARD, 2, 1>(
|
||||
video::EVT_STANDARD, 3, 2, 1>(
|
||||
TexUnits(RenderGeometry::TexUnit(0, true)),
|
||||
ListBlendTransparent::getInstance());
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
renderTransparenPass<Shaders::TransparentShader, video::EVT_STANDARD, 2, 1>(
|
||||
renderTransparenPass<Shaders::TransparentShader, video::EVT_STANDARD, 3, 2, 1>(
|
||||
TexUnits(RenderGeometry::TexUnit(0, true)),
|
||||
ListAdditiveTransparent::getInstance());
|
||||
}
|
||||
|
@ -57,12 +57,18 @@ namespace GraphicsRestrictions
|
||||
"TextureCompressionS3TC",
|
||||
"AMDVertexShaderLayer",
|
||||
"ExplicitAttribLocation",
|
||||
"TextureFilterAnisotropic",
|
||||
#if defined(USE_GLES2)
|
||||
"TextureFormatBGRA8888",
|
||||
"ColorBufferFloat",
|
||||
#endif
|
||||
"DriverRecentEnough",
|
||||
"HighDefinitionTextures",
|
||||
"AdvancedPipeline",
|
||||
"FramebufferSRGBWorking",
|
||||
"FramebufferSRGBCapable",
|
||||
"GI",
|
||||
"ForceLegacyDevice"
|
||||
};
|
||||
} // namespace Private
|
||||
using namespace Private;
|
||||
@ -272,7 +278,7 @@ class Rule : public NoCopy
|
||||
{
|
||||
private:
|
||||
/** Operators to test for a card. */
|
||||
enum {CARD_IS, CARD_CONTAINS} m_card_test;
|
||||
enum {CARD_IGNORE, CARD_IS, CARD_CONTAINS} m_card_test;
|
||||
|
||||
/** Name of the card for which this rule applies. */
|
||||
std::string m_card_name;
|
||||
@ -293,6 +299,8 @@ public:
|
||||
Rule(const XMLNode *rule)
|
||||
{
|
||||
m_version_test = VERSION_IGNORE;
|
||||
m_card_test = CARD_IGNORE;
|
||||
|
||||
if(rule->get("is", &m_card_name))
|
||||
{
|
||||
m_card_test = CARD_IS;
|
||||
@ -340,7 +348,7 @@ public:
|
||||
// -----------
|
||||
if(m_os.size()>0)
|
||||
{
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) && !defined(ANDROID)
|
||||
if(m_os!="linux") return false;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
@ -351,6 +359,9 @@ public:
|
||||
#endif
|
||||
#ifdef BSD
|
||||
if(m_os!="bsd") return false;
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
if(m_os!="android") return false;
|
||||
#endif
|
||||
} // m_os.size()>0
|
||||
|
||||
@ -358,6 +369,7 @@ public:
|
||||
// -------------
|
||||
switch(m_card_test)
|
||||
{
|
||||
case CARD_IGNORE: break; // always true
|
||||
case CARD_IS:
|
||||
if(card!=m_card_name) return false;
|
||||
break;
|
||||
|
@ -32,7 +32,7 @@ namespace GraphicsRestrictions
|
||||
* the variable m_names_of_restrictions in the cpp file contains the
|
||||
* string representation used in the XML files. Any change to this
|
||||
* type declaration needs a change in that variable as well. */
|
||||
enum GraphicsRestrictionsType
|
||||
enum GraphicsRestrictionsType
|
||||
{
|
||||
GR_UNIFORM_BUFFER_OBJECT,
|
||||
GR_GEOMETRY_SHADER,
|
||||
@ -51,12 +51,18 @@ namespace GraphicsRestrictions
|
||||
GR_EXT_TEXTURE_COMPRESSION_S3TC,
|
||||
GR_AMD_VERTEX_SHADER_LAYER,
|
||||
GR_EXPLICIT_ATTRIB_LOCATION,
|
||||
GR_TEXTURE_FILTER_ANISOTROPIC,
|
||||
#if defined(USE_GLES2)
|
||||
GR_TEXTURE_FORMAT_BGRA8888,
|
||||
GR_COLOR_BUFFER_FLOAT,
|
||||
#endif
|
||||
GR_DRIVER_RECENT_ENOUGH,
|
||||
GR_HIGHDEFINITION_TEXTURES,
|
||||
GR_ADVANCED_PIPELINE,
|
||||
GR_FRAMEBUFFER_SRGB_WORKING,
|
||||
GR_FRAMEBUFFER_SRGB_CAPABLE,
|
||||
GR_GI,
|
||||
GR_FORCE_LEGACY_DEVICE,
|
||||
GR_COUNT /** MUST be last entry. */
|
||||
} ;
|
||||
|
||||
|
@ -143,6 +143,7 @@ IrrDriver::~IrrDriver()
|
||||
{
|
||||
assert(m_device != NULL);
|
||||
|
||||
cleanUnicolorTextures();
|
||||
m_device->drop();
|
||||
m_device = NULL;
|
||||
m_modes.clear();
|
||||
@ -329,7 +330,7 @@ void IrrDriver::createListOfVideoModes()
|
||||
void IrrDriver::initDevice()
|
||||
{
|
||||
SIrrlichtCreationParameters params;
|
||||
|
||||
|
||||
// If --no-graphics option was used, the null device can still be used.
|
||||
if (!ProfileWorld::isNoGraphics())
|
||||
{
|
||||
@ -412,7 +413,7 @@ void IrrDriver::initDevice()
|
||||
m_device->drop();
|
||||
m_device = NULL;
|
||||
|
||||
params.ForceLegacyDevice = (UserConfigParams::m_force_legacy_device ||
|
||||
params.ForceLegacyDevice = (UserConfigParams::m_force_legacy_device ||
|
||||
UserConfigParams::m_gamepad_visualisation);
|
||||
|
||||
// Try 32 and, upon failure, 24 then 16 bit per pixels
|
||||
@ -437,9 +438,9 @@ void IrrDriver::initDevice()
|
||||
core::dimension2du(UserConfigParams::m_width,
|
||||
UserConfigParams::m_height);
|
||||
params.HandleSRGB = true;
|
||||
params.ShadersPath = (file_manager->getShadersDir() +
|
||||
params.ShadersPath = (file_manager->getShadersDir() +
|
||||
"irrlicht/").c_str();
|
||||
|
||||
|
||||
/*
|
||||
switch ((int)UserConfigParams::m_antialiasing)
|
||||
{
|
||||
@ -500,29 +501,54 @@ void IrrDriver::initDevice()
|
||||
{
|
||||
Log::fatal("irr_driver", "Couldn't initialise irrlicht device. Quitting.\n");
|
||||
}
|
||||
|
||||
|
||||
CVS->init();
|
||||
|
||||
|
||||
bool recreate_device = false;
|
||||
|
||||
// Some drivers are able to create OpenGL 3.1 context, but shader-based
|
||||
// pipeline doesn't work for them. For example some radeon drivers
|
||||
// support only GLSL 1.3 and it causes STK to crash. We should force to use
|
||||
// fixed pipeline in this case.
|
||||
if (!ProfileWorld::isNoGraphics() &&
|
||||
GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_FORCE_LEGACY_DEVICE))
|
||||
{
|
||||
Log::warn("irr_driver", "Driver doesn't support shader-based pipeline. "
|
||||
"Re-creating device to workaround the issue.");
|
||||
|
||||
params.ForceLegacyDevice = true;
|
||||
recreate_device = true;
|
||||
}
|
||||
|
||||
// This is the ugly hack for intel driver on linux, which doesn't
|
||||
// use sRGB-capable visual, even if we request it. This causes
|
||||
// the screen to be darker than expected. It affects mesa 10.6 and newer.
|
||||
// Though we are able to force to use the proper format on mesa side by
|
||||
// the screen to be darker than expected. It affects mesa 10.6 and newer.
|
||||
// Though we are able to force to use the proper format on mesa side by
|
||||
// setting WithAlphaChannel parameter.
|
||||
if (!ProfileWorld::isNoGraphics() && CVS->needsSRGBCapableVisualWorkaround())
|
||||
else if (CVS->needsSRGBCapableVisualWorkaround())
|
||||
{
|
||||
Log::warn("irr_driver", "Created visual is not sRGB-capable. "
|
||||
"Re-creating device to workaround the issue.");
|
||||
m_device->closeDevice();
|
||||
m_device->drop();
|
||||
|
||||
params.WithAlphaChannel = true;
|
||||
|
||||
recreate_device = true;
|
||||
}
|
||||
|
||||
if (!ProfileWorld::isNoGraphics() && recreate_device)
|
||||
{
|
||||
m_device->closeDevice();
|
||||
m_device->clearSystemMessages();
|
||||
m_device->run();
|
||||
m_device->drop();
|
||||
|
||||
m_device = createDeviceEx(params);
|
||||
|
||||
|
||||
if(!m_device)
|
||||
{
|
||||
Log::fatal("irr_driver", "Couldn't initialise irrlicht device. Quitting.\n");
|
||||
}
|
||||
|
||||
CVS->init();
|
||||
}
|
||||
|
||||
m_scene_manager = m_device->getSceneManager();
|
||||
@ -540,7 +566,7 @@ void IrrDriver::initDevice()
|
||||
(UserConfigParams::m_shadows_resolution < 512 ||
|
||||
UserConfigParams::m_shadows_resolution > 2048))
|
||||
{
|
||||
Log::warn("irr_driver",
|
||||
Log::warn("irr_driver",
|
||||
"Invalid value for UserConfigParams::m_shadows_resolution : %i",
|
||||
(int)UserConfigParams::m_shadows_resolution);
|
||||
UserConfigParams::m_shadows_resolution = 0;
|
||||
@ -646,7 +672,7 @@ void IrrDriver::setMaxTextureSize()
|
||||
{
|
||||
io::IAttributes &att = m_video_driver->getNonConstDriverAttributes();
|
||||
att.setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(
|
||||
UserConfigParams::m_max_texture_size,
|
||||
UserConfigParams::m_max_texture_size,
|
||||
UserConfigParams::m_max_texture_size));
|
||||
}
|
||||
} // setMaxTextureSize
|
||||
@ -674,7 +700,7 @@ void IrrDriver::createSunInterposer()
|
||||
mb->getMaterial().setTexture(7,
|
||||
getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
||||
}
|
||||
m_sun_interposer = new STKMeshSceneNode(sphere,
|
||||
m_sun_interposer = new STKMeshSceneNode(sphere,
|
||||
m_scene_manager->getRootSceneNode(),
|
||||
NULL, -1, "sun_interposer");
|
||||
|
||||
@ -816,11 +842,11 @@ void IrrDriver::applyResolutionSettings()
|
||||
UserConfigParams::m_prev_height) );
|
||||
m_video_driver->endScene();
|
||||
track_manager->removeAllCachedData();
|
||||
attachment_manager->removeTextures();
|
||||
delete attachment_manager;
|
||||
projectile_manager->removeTextures();
|
||||
ItemManager::removeTextures();
|
||||
kart_properties_manager->unloadAllKarts();
|
||||
powerup_manager->unloadPowerups();
|
||||
delete powerup_manager;
|
||||
Referee::cleanup();
|
||||
ParticleKindManager::get()->cleanup();
|
||||
delete input_manager;
|
||||
@ -843,11 +869,13 @@ void IrrDriver::applyResolutionSettings()
|
||||
ShaderBase::updateShaders();
|
||||
VAOManager::getInstance()->kill();
|
||||
resetTextureTable();
|
||||
cleanUnicolorTextures();
|
||||
// initDevice will drop the current device.
|
||||
if (CVS->isGLSL())
|
||||
{
|
||||
Shaders::destroy();
|
||||
}
|
||||
delete m_renderer;
|
||||
initDevice();
|
||||
|
||||
font_manager = new FontManager();
|
||||
@ -860,6 +888,8 @@ void IrrDriver::applyResolutionSettings()
|
||||
material_manager->loadMaterial();
|
||||
input_manager = new InputManager ();
|
||||
input_manager->setMode(InputManager::MENU);
|
||||
powerup_manager = new PowerupManager();
|
||||
attachment_manager = new AttachmentManager();
|
||||
|
||||
GUIEngine::addLoadingIcon(
|
||||
irr_driver->getTexture(file_manager
|
||||
@ -997,28 +1027,6 @@ scene::IMesh *IrrDriver::getMesh(const std::string &filename)
|
||||
return am->getMesh(0);
|
||||
} // getMesh
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Create a skinned mesh which has copied all meshbuffers and joints of the
|
||||
* original mesh. Note, that this will not copy any other information like
|
||||
* joints data.
|
||||
* \param mesh Original mesh
|
||||
* \return Newly created skinned mesh. You should call drop() when you don't
|
||||
* need it anymore.
|
||||
*/
|
||||
scene::IAnimatedMesh *IrrDriver::copyAnimatedMesh(scene::IAnimatedMesh *orig)
|
||||
{
|
||||
using namespace scene;
|
||||
CSkinnedMesh *mesh = dynamic_cast<CSkinnedMesh*>(orig);
|
||||
if (!mesh)
|
||||
{
|
||||
Log::error("copyAnimatedMesh", "Given mesh was not a skinned mesh.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scene::IAnimatedMesh* out = mesh->clone();
|
||||
return out;
|
||||
} // copyAnimatedMesh
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sets the material flags in this mesh depending on the settings in
|
||||
* material_manager.
|
||||
@ -1121,7 +1129,7 @@ scene::IMeshSceneNode *IrrDriver::addSphere(float radius,
|
||||
{
|
||||
scene::IMesh *mesh = m_scene_manager->getGeometryCreator()
|
||||
->createSphereMesh(radius);
|
||||
|
||||
|
||||
mesh->setMaterialFlag(video::EMF_COLOR_MATERIAL, true);
|
||||
video::SMaterial &m = mesh->getMeshBuffer(0)->getMaterial();
|
||||
m.AmbientColor = color;
|
||||
@ -1164,7 +1172,8 @@ scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh,
|
||||
const std::string& debug_name,
|
||||
scene::ISceneNode *parent,
|
||||
RenderInfo* render_info,
|
||||
bool all_parts_colorized)
|
||||
bool all_parts_colorized,
|
||||
int frame_for_mesh)
|
||||
{
|
||||
if (!CVS->isGLSL())
|
||||
return m_scene_manager->addMeshSceneNode(mesh, parent);
|
||||
@ -1172,14 +1181,15 @@ scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh,
|
||||
if (!parent)
|
||||
parent = m_scene_manager->getRootSceneNode();
|
||||
|
||||
scene::IMeshSceneNode* node = new STKMeshSceneNode(mesh, parent,
|
||||
scene::IMeshSceneNode* node = new STKMeshSceneNode(mesh, parent,
|
||||
m_scene_manager, -1,
|
||||
debug_name,
|
||||
core::vector3df(0, 0, 0),
|
||||
core::vector3df(0, 0, 0),
|
||||
core::vector3df(1.0f, 1.0f, 1.0f),
|
||||
true, render_info,
|
||||
all_parts_colorized);
|
||||
all_parts_colorized,
|
||||
frame_for_mesh);
|
||||
node->drop();
|
||||
|
||||
return node;
|
||||
@ -1211,7 +1221,7 @@ scene::ISceneNode *IrrDriver::addBillboard(const core::dimension2d< f32 > size,
|
||||
if (!parent)
|
||||
parent = m_scene_manager->getRootSceneNode();
|
||||
|
||||
node = new STKBillboard(parent, m_scene_manager, -1,
|
||||
node = new STKBillboard(parent, m_scene_manager, -1,
|
||||
vector3df(0., 0., 0.), size);
|
||||
node->drop();
|
||||
}
|
||||
@ -1424,7 +1434,7 @@ scene::ISceneNode *IrrDriver::addSkyBox(const std::vector<video::ITexture*> &tex
|
||||
assert(texture.size() == 6);
|
||||
|
||||
m_renderer->addSkyBox(texture, spherical_harmonics_textures);
|
||||
|
||||
|
||||
return m_scene_manager->addSkyBoxSceneNode(texture[0], texture[1],
|
||||
texture[2], texture[3],
|
||||
texture[4], texture[5]);
|
||||
@ -1534,7 +1544,7 @@ std::string IrrDriver::getSmallerTexture(const std::string& filename)
|
||||
{
|
||||
core::dimension2d<u32> dim = img->getDimension();
|
||||
core::dimension2d<u32> new_dim; // Dimension of the cached texture
|
||||
const int scale_factor = 2;
|
||||
const unsigned scale_factor = 2;
|
||||
// Resize the texture only if it can be done properly
|
||||
if (dim.Width < scale_factor || dim.Height < scale_factor)
|
||||
new_dim = dim;
|
||||
@ -1982,13 +1992,13 @@ void IrrDriver::update(float dt)
|
||||
if (world)
|
||||
{
|
||||
m_renderer->render(dt);
|
||||
|
||||
|
||||
GUIEngine::Screen* current_screen = GUIEngine::getCurrentScreen();
|
||||
if (current_screen != NULL && current_screen->needs3D())
|
||||
{
|
||||
GUIEngine::render(dt);
|
||||
}
|
||||
|
||||
|
||||
if (world->getPhysics() != NULL)
|
||||
{
|
||||
IrrDebugDrawer* debug_drawer = world->getPhysics()->getDebugDrawer();
|
||||
@ -2007,7 +2017,7 @@ void IrrDriver::update(float dt)
|
||||
|
||||
m_video_driver->endScene();
|
||||
}
|
||||
|
||||
|
||||
if (m_request_screenshot) doScreenShot();
|
||||
|
||||
// Enable this next print statement to get render information printed
|
||||
@ -2070,7 +2080,6 @@ bool IrrDriver::supportsSplatting()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void IrrDriver::applyObjectPassShader(scene::ISceneNode * const node, bool rimlit)
|
||||
{
|
||||
if (!CVS->isGLSL())
|
||||
@ -2083,9 +2092,9 @@ void IrrDriver::applyObjectPassShader(scene::ISceneNode * const node, bool rimli
|
||||
|
||||
const u32 mcount = node->getMaterialCount();
|
||||
u32 i;
|
||||
const video::E_MATERIAL_TYPE ref =
|
||||
const video::E_MATERIAL_TYPE ref =
|
||||
Shaders::getShader(rimlit ? ES_OBJECTPASS_RIMLIT : ES_OBJECTPASS_REF);
|
||||
const video::E_MATERIAL_TYPE pass =
|
||||
const video::E_MATERIAL_TYPE pass =
|
||||
Shaders::getShader(rimlit ? ES_OBJECTPASS_RIMLIT : ES_OBJECTPASS);
|
||||
|
||||
const video::E_MATERIAL_TYPE origref = Shaders::getShader(ES_OBJECTPASS_REF);
|
||||
@ -2112,7 +2121,7 @@ void IrrDriver::applyObjectPassShader(scene::ISceneNode * const node, bool rimli
|
||||
for (i = 0; i < mcount; i++)
|
||||
{
|
||||
video::SMaterial &nodemat = node->getMaterial(i);
|
||||
video::SMaterial &mbmat = mesh ? mesh->getMeshBuffer(i)->getMaterial()
|
||||
video::SMaterial &mbmat = mesh ? mesh->getMeshBuffer(i)->getMaterial()
|
||||
: nodemat;
|
||||
video::SMaterial *mat = &nodemat;
|
||||
|
||||
@ -2166,8 +2175,6 @@ scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos,
|
||||
else
|
||||
light = new SunNode(m_scene_manager, parent, r, g, b);
|
||||
|
||||
light->grab();
|
||||
|
||||
light->setPosition(pos);
|
||||
light->updateAbsolutePosition();
|
||||
|
||||
@ -2197,9 +2204,7 @@ scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos,
|
||||
|
||||
void IrrDriver::clearLights()
|
||||
{
|
||||
u32 i;
|
||||
const u32 max = (int)m_lights.size();
|
||||
for (i = 0; i < max; i++)
|
||||
for (unsigned int i = 0; i < m_lights.size(); i++)
|
||||
{
|
||||
m_lights[i]->drop();
|
||||
}
|
||||
|
@ -72,7 +72,6 @@ class ShadowImportance;
|
||||
class ShadowMatrices;
|
||||
class RenderTarget;
|
||||
|
||||
|
||||
/**
|
||||
* \brief class that creates the irrLicht device and offers higher-level
|
||||
* ways to manage the 3D scene
|
||||
@ -215,7 +214,6 @@ public:
|
||||
void setAllMaterialFlags(scene::IMesh *mesh) const;
|
||||
scene::IAnimatedMesh *getAnimatedMesh(const std::string &name);
|
||||
scene::IMesh *getMesh(const std::string &name);
|
||||
scene::IAnimatedMesh *copyAnimatedMesh(scene::IAnimatedMesh *orig);
|
||||
video::ITexture *applyMask(video::ITexture* texture,
|
||||
const std::string& mask_path);
|
||||
void displayFPS();
|
||||
@ -251,7 +249,8 @@ public:
|
||||
const std::string& debug_name,
|
||||
scene::ISceneNode *parent = NULL,
|
||||
RenderInfo* render_info = NULL,
|
||||
bool all_parts_colorized = false);
|
||||
bool all_parts_colorized = false,
|
||||
int frame_for_mesh = -1);
|
||||
PerCameraNode *addPerCameraNode(scene::ISceneNode* node,
|
||||
scene::ICameraSceneNode* cam,
|
||||
scene::ISceneNode *parent = NULL);
|
||||
|
@ -740,6 +740,26 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
|
||||
m->setTexture(7, colorization_mask_tex);
|
||||
}
|
||||
|
||||
|
||||
if (race_manager->getReverseTrack() &&
|
||||
m_mirror_axis_when_reverse != ' ')
|
||||
{
|
||||
if (m_mirrorred_mesh_buffers.find((void*)mb) == m_mirrorred_mesh_buffers.end())
|
||||
{
|
||||
m_mirrorred_mesh_buffers[(void*)mb] = true;
|
||||
//irr::video::S3DVertex* mbVertices = (video::S3DVertex*)mb->getVertices();
|
||||
for (unsigned int i = 0; i < mb->getVertexCount(); i++)
|
||||
{
|
||||
core::vector2df &tc = mb->getTCoords(i);
|
||||
if (m_mirror_axis_when_reverse == 'V')
|
||||
tc.Y = 1 - tc.Y;
|
||||
else
|
||||
tc.X = 1 - tc.X;
|
||||
}
|
||||
}
|
||||
} // reverse track and texture needs mirroring
|
||||
|
||||
|
||||
switch (m_shader_type)
|
||||
{
|
||||
case SHADERTYPE_SOLID_UNLIT:
|
||||
@ -986,21 +1006,6 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (race_manager->getReverseTrack() &&
|
||||
m_mirror_axis_when_reverse != ' ')
|
||||
{
|
||||
//irr::video::S3DVertex* mbVertices = (video::S3DVertex*)mb->getVertices();
|
||||
for (unsigned int i = 0; i < mb->getVertexCount(); i++)
|
||||
{
|
||||
core::vector2df &tc = mb->getTCoords(i);
|
||||
if (m_mirror_axis_when_reverse == 'V')
|
||||
tc.Y = 1 - tc.Y;
|
||||
else
|
||||
tc.X = 1 - tc.X;
|
||||
}
|
||||
} // reverse track and texture needs mirroring
|
||||
|
||||
} // setMaterialProperties
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -162,6 +162,12 @@ private:
|
||||
* the direction. */
|
||||
char m_mirror_axis_when_reverse;
|
||||
|
||||
/**
|
||||
* Associated with m_mirror_axis_when_reverse, to avoid mirroring the same material twice
|
||||
* (setAllMaterialFlags can be called multiple times on the same mesh buffer)
|
||||
*/
|
||||
std::map<void*, bool> m_mirrorred_mesh_buffers;
|
||||
|
||||
ParticleKind* m_particles_effects[EMIT_KINDS_COUNT];
|
||||
|
||||
/** For normal maps */
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <irrlicht.h>
|
||||
#include <IMesh.h>
|
||||
#include <IMeshBuffer.h>
|
||||
#include <SSkinMeshBuffer.h>
|
||||
|
||||
void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
|
||||
|
||||
@ -444,29 +445,86 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
|
||||
clone->recalculateBoundingBox();
|
||||
if (calculate_tangents)
|
||||
recalculateTangents(clone, recalculate_normals, smooth, angle_weighted);
|
||||
|
||||
int mbcount = clone->getMeshBufferCount();
|
||||
for (int i = 0; i < mbcount; i++)
|
||||
{
|
||||
scene::IMeshBuffer* mb = clone->getMeshBuffer(i);
|
||||
|
||||
for (u32 t = 0; t < video::MATERIAL_MAX_TEXTURES; t++)
|
||||
{
|
||||
video::ITexture* texture = mb->getMaterial().TextureLayer[t].Texture;
|
||||
if (texture != NULL)
|
||||
texture->grab();
|
||||
}
|
||||
}
|
||||
|
||||
scene::IMeshCache* meshCache = irr_driver->getSceneManager()->getMeshCache();
|
||||
io::SNamedPath path = meshCache->getMeshName(mesh);
|
||||
irr_driver->removeMeshFromCache(mesh);
|
||||
if (path.getPath() == "")
|
||||
{
|
||||
// This mesh is not in irrlicht cache, drop it directly
|
||||
assert(mesh->getReferenceCount() == 1);
|
||||
mesh->drop();
|
||||
return clone;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cache the calcuated tangent mesh with path
|
||||
irr_driver->removeMeshFromCache(mesh);
|
||||
scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
|
||||
clone->drop();
|
||||
meshCache->addMesh(path, amesh);
|
||||
if (World::getWorld())
|
||||
{
|
||||
irr_driver->grabAllTextures(amesh);
|
||||
World::getWorld()->getTrack()->addCachedMesh(amesh);
|
||||
return amesh;
|
||||
}
|
||||
amesh->drop();
|
||||
return amesh;
|
||||
}
|
||||
|
||||
scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
|
||||
meshCache->addMesh(path, amesh);
|
||||
|
||||
World::getWorld()->getTrack()->addCachedMesh(amesh);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
|
||||
bool(*predicate)(scene::IMeshBuffer*))
|
||||
{
|
||||
core::array<scene::SSkinMeshBuffer*>& all_mb = mesh->getMeshBuffers();
|
||||
const int all_mb_size = all_mb.size();
|
||||
for (int i = 0; i < all_mb_size; i++)
|
||||
{
|
||||
scene::SSkinMeshBuffer* mb = all_mb[i];
|
||||
if (mb && predicate(mb))
|
||||
{
|
||||
mb->convertToTangents();
|
||||
const int index_count = mb->getIndexCount();
|
||||
uint16_t* idx = mb->getIndices();
|
||||
video::S3DVertexTangents* v =
|
||||
(video::S3DVertexTangents*)mb->getVertices();
|
||||
|
||||
for (int i = 0; i < index_count; i += 3)
|
||||
{
|
||||
calculateTangents(
|
||||
v[idx[i+0]].Normal,
|
||||
v[idx[i+0]].Tangent,
|
||||
v[idx[i+0]].Binormal,
|
||||
v[idx[i+0]].Pos,
|
||||
v[idx[i+1]].Pos,
|
||||
v[idx[i+2]].Pos,
|
||||
v[idx[i+0]].TCoords,
|
||||
v[idx[i+1]].TCoords,
|
||||
v[idx[i+2]].TCoords);
|
||||
|
||||
calculateTangents(
|
||||
v[idx[i+1]].Normal,
|
||||
v[idx[i+1]].Tangent,
|
||||
v[idx[i+1]].Binormal,
|
||||
v[idx[i+1]].Pos,
|
||||
v[idx[i+2]].Pos,
|
||||
v[idx[i+0]].Pos,
|
||||
v[idx[i+1]].TCoords,
|
||||
v[idx[i+2]].TCoords,
|
||||
v[idx[i+0]].TCoords);
|
||||
|
||||
calculateTangents(
|
||||
v[idx[i+2]].Normal,
|
||||
v[idx[i+2]].Tangent,
|
||||
v[idx[i+2]].Binormal,
|
||||
v[idx[i+2]].Pos,
|
||||
v[idx[i+0]].Pos,
|
||||
v[idx[i+1]].Pos,
|
||||
v[idx[i+2]].TCoords,
|
||||
v[idx[i+0]].TCoords,
|
||||
v[idx[i+1]].TCoords);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene { class IMesh; class IMeshBuffer; }
|
||||
namespace scene { class IMesh; class IMeshBuffer; class ISkinnedMesh; }
|
||||
}
|
||||
using namespace irr;
|
||||
|
||||
@ -37,8 +37,14 @@ namespace MeshTools
|
||||
bool isNormalMap(scene::IMeshBuffer* mb);
|
||||
|
||||
// Copied from irrlicht
|
||||
scene::IMesh* createMeshWithTangents(scene::IMesh* mesh, bool(*predicate)(scene::IMeshBuffer*),
|
||||
bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false, bool calculateTangents = true);
|
||||
scene::IMesh* createMeshWithTangents(scene::IMesh* mesh,
|
||||
bool(*predicate)(scene::IMeshBuffer*), bool recalculateNormals = false,
|
||||
bool smooth = false, bool angleWeighted = false,
|
||||
bool calculateTangents = true);
|
||||
|
||||
void createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
|
||||
bool(*predicate)(scene::IMeshBuffer*));
|
||||
|
||||
} // MeshTools
|
||||
|
||||
#endif
|
||||
|
@ -78,45 +78,70 @@ RTT::RTT(size_t width, size_t height)
|
||||
|
||||
// All RTTs are currently RGBA16F mostly with stencil. The four tmp RTTs are the same size
|
||||
// as the screen, for use in post-processing.
|
||||
|
||||
GLint rgba_internal_format = GL_RGBA16F;
|
||||
GLint rgba_format = GL_BGRA;
|
||||
GLint red_internal_format = GL_R16F;
|
||||
GLint red32_internal_format = GL_R32F;
|
||||
GLint red_format = GL_RED;
|
||||
GLint rgb_format = GL_BGR;
|
||||
GLint diffuse_specular_internal_format = GL_R11F_G11F_B10F;
|
||||
GLint type = GL_FLOAT;
|
||||
|
||||
#if defined(USE_GLES2)
|
||||
if (!CVS->isEXTColorBufferFloatUsable())
|
||||
{
|
||||
rgba_internal_format = GL_RGBA8;
|
||||
rgba_format = GL_RGBA;
|
||||
red_internal_format = GL_R8;
|
||||
red32_internal_format = GL_R8;
|
||||
red_format = GL_RED;
|
||||
rgb_format = GL_RGB;
|
||||
diffuse_specular_internal_format = GL_RGBA8;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
#endif
|
||||
|
||||
RenderTargetTextures[RTT_TMP1] = generateRTT(res, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_TMP2] = generateRTT(res, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_TMP3] = generateRTT(res, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_TMP4] = generateRTT(res, GL_R16F, GL_RED, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_LINEAR_DEPTH] = generateRTT(res, GL_R32F, GL_RED, GL_FLOAT, linear_depth_mip_levels);
|
||||
RenderTargetTextures[RTT_NORMAL_AND_DEPTH] = generateRTT(res, GL_RGBA16F, GL_RGBA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_COLOR] = generateRTT(res, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_MLAA_COLORS] = generateRTT(res, GL_SRGB8_ALPHA8, GL_BGR, GL_UNSIGNED_BYTE);
|
||||
RenderTargetTextures[RTT_MLAA_TMP] = generateRTT(res, GL_SRGB8_ALPHA8, GL_BGR, GL_UNSIGNED_BYTE);
|
||||
RenderTargetTextures[RTT_MLAA_BLEND] = generateRTT(res, GL_SRGB8_ALPHA8, GL_BGR, GL_UNSIGNED_BYTE);
|
||||
RenderTargetTextures[RTT_SSAO] = generateRTT(res, GL_R16F, GL_RED, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_DISPLACE] = generateRTT(res, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_DIFFUSE] = generateRTT(res, GL_R11F_G11F_B10F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_SPECULAR] = generateRTT(res, GL_R11F_G11F_B10F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_TMP1] = generateRTT(res, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_TMP2] = generateRTT(res, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_TMP3] = generateRTT(res, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_TMP4] = generateRTT(res, red_internal_format, red_format, type);
|
||||
RenderTargetTextures[RTT_LINEAR_DEPTH] = generateRTT(res, red32_internal_format, red_format, type, linear_depth_mip_levels);
|
||||
RenderTargetTextures[RTT_NORMAL_AND_DEPTH] = generateRTT(res, rgba_internal_format, GL_RGBA, type);
|
||||
RenderTargetTextures[RTT_COLOR] = generateRTT(res, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_MLAA_COLORS] = generateRTT(res, GL_SRGB8_ALPHA8, rgb_format, GL_UNSIGNED_BYTE);
|
||||
RenderTargetTextures[RTT_MLAA_TMP] = generateRTT(res, GL_SRGB8_ALPHA8, rgb_format, GL_UNSIGNED_BYTE);
|
||||
RenderTargetTextures[RTT_MLAA_BLEND] = generateRTT(res, GL_SRGB8_ALPHA8, rgb_format, GL_UNSIGNED_BYTE);
|
||||
RenderTargetTextures[RTT_SSAO] = generateRTT(res, red_internal_format, red_format, type);
|
||||
RenderTargetTextures[RTT_DISPLACE] = generateRTT(res, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_DIFFUSE] = generateRTT(res, diffuse_specular_internal_format, rgb_format, type);
|
||||
RenderTargetTextures[RTT_SPECULAR] = generateRTT(res, diffuse_specular_internal_format, rgb_format, type);
|
||||
|
||||
RenderTargetTextures[RTT_HALF1] = generateRTT(half, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_QUARTER1] = generateRTT(quarter, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_EIGHTH1] = generateRTT(eighth, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_HALF1_R] = generateRTT(half, GL_R16F, GL_RED, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_HALF1] = generateRTT(half, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_QUARTER1] = generateRTT(quarter, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_EIGHTH1] = generateRTT(eighth, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_HALF1_R] = generateRTT(half, red_internal_format, red_format, type);
|
||||
|
||||
RenderTargetTextures[RTT_HALF2] = generateRTT(half, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_QUARTER2] = generateRTT(quarter, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_EIGHTH2] = generateRTT(eighth, GL_RGBA16F, GL_BGRA, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_HALF2_R] = generateRTT(half, GL_R16F, GL_RED, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_HALF2] = generateRTT(half, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_QUARTER2] = generateRTT(quarter, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_EIGHTH2] = generateRTT(eighth, rgba_internal_format, rgba_format, type);
|
||||
RenderTargetTextures[RTT_HALF2_R] = generateRTT(half, red_internal_format, red_format, type);
|
||||
|
||||
RenderTargetTextures[RTT_BLOOM_1024] = generateRTT(shadowsize0, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_SCALAR_1024] = generateRTT(shadowsize0, GL_R32F, GL_RED, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_BLOOM_512] = generateRTT(shadowsize1, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_TMP_512] = generateRTT(shadowsize1, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_LENS_512] = generateRTT(shadowsize1, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_BLOOM_1024] = generateRTT(shadowsize0, rgba_internal_format, rgb_format, type);
|
||||
#if !defined(USE_GLES2)
|
||||
RenderTargetTextures[RTT_SCALAR_1024] = generateRTT(shadowsize0, red32_internal_format, red_format, type);
|
||||
#endif
|
||||
RenderTargetTextures[RTT_BLOOM_512] = generateRTT(shadowsize1, rgba_internal_format, rgb_format, type);
|
||||
RenderTargetTextures[RTT_TMP_512] = generateRTT(shadowsize1, rgba_internal_format, rgb_format, type);
|
||||
RenderTargetTextures[RTT_LENS_512] = generateRTT(shadowsize1, rgba_internal_format, rgb_format, type);
|
||||
|
||||
RenderTargetTextures[RTT_BLOOM_256] = generateRTT(shadowsize2, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_TMP_256] = generateRTT(shadowsize2, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_LENS_256] = generateRTT(shadowsize2, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_BLOOM_256] = generateRTT(shadowsize2, rgba_internal_format, rgb_format, type);
|
||||
RenderTargetTextures[RTT_TMP_256] = generateRTT(shadowsize2, rgba_internal_format, rgb_format, type);
|
||||
RenderTargetTextures[RTT_LENS_256] = generateRTT(shadowsize2, rgba_internal_format, rgb_format, type);
|
||||
|
||||
RenderTargetTextures[RTT_BLOOM_128] = generateRTT(shadowsize3, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_TMP_128] = generateRTT(shadowsize3, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_LENS_128] = generateRTT(shadowsize3, GL_RGBA16F, GL_BGR, GL_FLOAT);
|
||||
RenderTargetTextures[RTT_BLOOM_128] = generateRTT(shadowsize3, rgba_internal_format, rgb_format, type);
|
||||
RenderTargetTextures[RTT_TMP_128] = generateRTT(shadowsize3, rgba_internal_format, rgb_format, type);
|
||||
RenderTargetTextures[RTT_LENS_128] = generateRTT(shadowsize3, rgba_internal_format, rgb_format, type);
|
||||
|
||||
std::vector<GLuint> somevector;
|
||||
somevector.push_back(RenderTargetTextures[RTT_SSAO]);
|
||||
@ -191,9 +216,11 @@ RTT::RTT(size_t width, size_t height)
|
||||
somevector.push_back(RenderTargetTextures[RTT_BLOOM_1024]);
|
||||
FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize0.Width, shadowsize0.Height));
|
||||
somevector.clear();
|
||||
#if !defined(USE_GLES2)
|
||||
somevector.push_back(RenderTargetTextures[RTT_SCALAR_1024]);
|
||||
FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize0.Width, shadowsize0.Height));
|
||||
somevector.clear();
|
||||
#endif
|
||||
|
||||
somevector.push_back(RenderTargetTextures[RTT_BLOOM_512]);
|
||||
FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize1.Width, shadowsize1.Height));
|
||||
@ -244,7 +271,7 @@ RTT::RTT(size_t width, size_t height)
|
||||
somevector.clear();
|
||||
somevector.push_back(RSM_Color);
|
||||
somevector.push_back(RSM_Normal);
|
||||
m_RSM = new FrameBuffer(somevector, RSM_Depth, 1024, 1024, true);
|
||||
m_RSM = new FrameBuffer(somevector, RSM_Depth, shadowsize0.Width, shadowsize0.Height, true);
|
||||
|
||||
RH_Red = generateRTT3D(GL_TEXTURE_3D, 32, 16, 32, GL_RGBA16F, GL_RGBA, GL_FLOAT);
|
||||
RH_Green = generateRTT3D(GL_TEXTURE_3D, 32, 16, 32, GL_RGBA16F, GL_RGBA, GL_FLOAT);
|
||||
|
@ -60,7 +60,9 @@ enum TypeFBO
|
||||
FBO_EIGHTH2,
|
||||
FBO_DISPLACE,
|
||||
FBO_BLOOM_1024,
|
||||
#if !defined(USE_GLES2)
|
||||
FBO_SCALAR_1024,
|
||||
#endif
|
||||
FBO_BLOOM_512,
|
||||
FBO_TMP_512,
|
||||
FBO_LENS_512,
|
||||
@ -122,7 +124,9 @@ enum TypeRTT
|
||||
RTT_MLAA_TMP,
|
||||
|
||||
RTT_BLOOM_1024,
|
||||
#if !defined(USE_GLES2)
|
||||
RTT_SCALAR_1024,
|
||||
#endif
|
||||
RTT_BLOOM_512,
|
||||
RTT_TMP_512,
|
||||
RTT_LENS_512,
|
||||
|
@ -62,7 +62,7 @@ const std::string& ShaderBase::getHeader()
|
||||
GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
|
||||
{
|
||||
GLuint id = glCreateShader(type);
|
||||
|
||||
|
||||
std::ostringstream code;
|
||||
#if !defined(USE_GLES2)
|
||||
code << "#version " << CVS->getGLSLVersion()<<"\n";
|
||||
@ -87,13 +87,13 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
|
||||
code << "#extension GL_ARB_arrays_of_arrays : enable\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (CVS->isAMDVertexShaderLayerUsable())
|
||||
code << "#extension GL_AMD_vertex_shader_layer : enable\n";
|
||||
|
||||
|
||||
if (CVS->isARBExplicitAttribLocationUsable())
|
||||
code << "#extension GL_ARB_explicit_attrib_location : enable\n";
|
||||
|
||||
|
||||
if (CVS->isAZDOEnabled())
|
||||
{
|
||||
code << "#extension GL_ARB_bindless_texture : enable\n";
|
||||
@ -107,10 +107,20 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
|
||||
if (CVS->needsRGBBindlessWorkaround())
|
||||
code << "#define SRGBBindlessFix\n";
|
||||
|
||||
#if !defined(USE_GLES2)
|
||||
//shader compilation fails with some drivers if there is no precision qualifier
|
||||
if (type == GL_FRAGMENT_SHADER)
|
||||
code << "precision mediump float;\n";
|
||||
#else
|
||||
int range[2], precision;
|
||||
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);
|
||||
|
||||
if (precision > 0)
|
||||
code << "precision highp float;\n";
|
||||
else
|
||||
code << "precision mediump float;\n";
|
||||
#endif
|
||||
|
||||
code << getHeader();
|
||||
|
||||
std::ifstream stream(file_manager->getShader(file), std::ios::in);
|
||||
@ -129,31 +139,31 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
|
||||
Log::error("shader", "Invalid #stk_include line: '%s'.", Line.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
std::string filename = Line.substr(pos+1);
|
||||
|
||||
|
||||
pos = filename.find("\"");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
Log::error("shader", "Invalid #stk_include line: '%s'.", Line.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
filename = filename.substr(0, pos);
|
||||
|
||||
|
||||
std::ifstream include_stream(file_manager->getShader(filename), std::ios::in);
|
||||
if (!include_stream.is_open())
|
||||
{
|
||||
Log::error("shader", "Couldn't open included shader: '%s'.", filename.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
std::string include_line = "";
|
||||
while (getline(include_stream, include_line))
|
||||
{
|
||||
code << "\n" << include_line;
|
||||
}
|
||||
|
||||
|
||||
include_stream.close();
|
||||
}
|
||||
else
|
||||
@ -161,7 +171,7 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
|
||||
code << "\n" << Line;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stream.close();
|
||||
}
|
||||
else
|
||||
@ -201,7 +211,7 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
|
||||
/** Loads a transform feedback buffer shader with a given number of varying
|
||||
* parameters.
|
||||
*/
|
||||
int ShaderBase::loadTFBProgram(const std::string &shader_name,
|
||||
int ShaderBase::loadTFBProgram(const std::string &shader_name,
|
||||
const char **varyings,
|
||||
unsigned varying_count)
|
||||
{
|
||||
@ -250,7 +260,7 @@ void ShaderBase::bypassUBO() const
|
||||
glUniformMatrix4fv(IPM, 1, GL_FALSE, irr_driver->getInvProjMatrix().pointer());
|
||||
|
||||
GLint Screen = glGetUniformLocation(m_program, "screen");
|
||||
glUniform2f(Screen, irr_driver->getCurrentScreenSize().X,
|
||||
glUniform2f(Screen, irr_driver->getCurrentScreenSize().X,
|
||||
irr_driver->getCurrentScreenSize().Y);
|
||||
|
||||
const SHCoefficients* sh_coeff = irr_driver->getSHCoefficients();
|
||||
|
@ -231,11 +231,11 @@ void ShaderBasedRenderer::uploadLightingData() const
|
||||
void ShaderBasedRenderer::computeMatrixesAndCameras(scene::ICameraSceneNode *const camnode,
|
||||
size_t width, size_t height)
|
||||
{
|
||||
|
||||
float w = width * UserConfigParams::m_scale_rtts_factor;
|
||||
float h = height * UserConfigParams::m_scale_rtts_factor;
|
||||
m_current_screen_size = core::vector2df(w, h);
|
||||
m_shadow_matrices.computeMatrixesAndCameras(camnode, w, h, m_rtts->getDepthStencilTexture());
|
||||
m_shadow_matrices.computeMatrixesAndCameras(camnode, int(w), int(h),
|
||||
m_rtts->getDepthStencilTexture());
|
||||
} // computeMatrixesAndCameras
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -250,6 +250,11 @@ void ShaderBasedRenderer::renderSkybox(const scene::ICameraSceneNode *camera) co
|
||||
// ----------------------------------------------------------------------------
|
||||
void ShaderBasedRenderer::renderSSAO() const
|
||||
{
|
||||
#if defined(USE_GLES2)
|
||||
if (!CVS->isEXTColorBufferFloatUsable())
|
||||
return;
|
||||
#endif
|
||||
|
||||
m_rtts->getFBO(FBO_SSAO).bind();
|
||||
glClearColor(1., 1., 1., 1.);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
@ -607,19 +612,32 @@ void ShaderBasedRenderer::renderPostProcessing(Camera * const camera)
|
||||
|
||||
bool isRace = StateManager::get()->getGameState() == GUIEngine::GAME;
|
||||
FrameBuffer *fbo = m_post_processing->render(camnode, isRace, m_rtts);
|
||||
|
||||
// The viewport has been changed using glViewport function directly
|
||||
// during scene rendering, but irrlicht thinks that nothing changed
|
||||
// when single camera is used. In this case we set the viewport
|
||||
// to whole screen manually.
|
||||
glViewport(0, 0, irr_driver->getActualScreenSize().Width,
|
||||
irr_driver->getActualScreenSize().Height);
|
||||
|
||||
if (irr_driver->getNormals())
|
||||
m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
|
||||
{
|
||||
m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).BlitToDefault(
|
||||
viewport.UpperLeftCorner.X,
|
||||
irr_driver->getActualScreenSize().Height - viewport.LowerRightCorner.Y,
|
||||
viewport.LowerRightCorner.X,
|
||||
irr_driver->getActualScreenSize().Height - viewport.UpperLeftCorner.Y);
|
||||
}
|
||||
else if (irr_driver->getSSAOViz())
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
|
||||
camera->activate();
|
||||
m_post_processing->renderPassThrough(m_rtts->getFBO(FBO_HALF1_R).getRTT()[0], viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
|
||||
}
|
||||
else if (irr_driver->getRSM())
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
|
||||
camera->activate();
|
||||
m_post_processing->renderPassThrough(m_rtts->getReflectiveShadowMapFrameBuffer().getRTT()[0], viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
|
||||
}
|
||||
else if (irr_driver->getShadowViz())
|
||||
@ -631,7 +649,6 @@ void ShaderBasedRenderer::renderPostProcessing(Camera * const camera)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
camera->activate();
|
||||
glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
|
||||
m_post_processing->renderPassThrough(fbo->getRTT()[0], viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ Shaders::TransparentShader::TransparentShader()
|
||||
{
|
||||
loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert",
|
||||
GL_FRAGMENT_SHADER, "transparent.frag");
|
||||
assignUniforms("ModelMatrix", "TextureMatrix");
|
||||
assignUniforms("ModelMatrix", "TextureMatrix", "custom_alpha");
|
||||
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||
} // TransparentShader
|
||||
|
||||
|
@ -120,7 +120,8 @@ public:
|
||||
|
||||
// ========================================================================
|
||||
class TransparentShader : public TextureShader<TransparentShader, 1,
|
||||
core::matrix4, core::matrix4 >
|
||||
core::matrix4, core::matrix4,
|
||||
float >
|
||||
{
|
||||
public:
|
||||
TransparentShader();
|
||||
|
@ -125,15 +125,34 @@ ShadowMatrices::ShadowMatrices()
|
||||
m_shadow_cam_nodes[1] = NULL;
|
||||
m_shadow_cam_nodes[2] = NULL;
|
||||
m_shadow_cam_nodes[3] = NULL;
|
||||
m_rsm_map_available = false;
|
||||
m_rsm_matrix_initialized = false;
|
||||
} // ShadowMatrices
|
||||
// ----------------------------------------------------------------------------
|
||||
ShadowMatrices::~ShadowMatrices()
|
||||
{
|
||||
resetShadowCamNodes();
|
||||
m_sun_cam->drop();
|
||||
} // ~ShadowMatrices
|
||||
// ----------------------------------------------------------------------------
|
||||
void ShadowMatrices::resetShadowCamNodes()
|
||||
{
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
if (m_shadow_cam_nodes[i])
|
||||
{
|
||||
m_shadow_cam_nodes[i]->drop();
|
||||
m_shadow_cam_nodes[i] = NULL;
|
||||
}
|
||||
}
|
||||
} // resetShadowCamNodes
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ShadowMatrices::addLight(const core::vector3df &pos)
|
||||
{
|
||||
m_sun_cam->setPosition(pos);
|
||||
m_sun_cam->updateAbsolutePosition();
|
||||
|
||||
m_rsm_matrix_initialized = false;
|
||||
|
||||
} // addLight
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -315,20 +334,6 @@ void ShadowMatrices::computeMatrixesAndCameras(scene::ICameraSceneNode *const ca
|
||||
|
||||
const float oldfar = camnode->getFarValue();
|
||||
const float oldnear = camnode->getNearValue();
|
||||
float FarValues[] =
|
||||
{
|
||||
ShadowMatrices::m_shadow_split[1],
|
||||
ShadowMatrices::m_shadow_split[2],
|
||||
ShadowMatrices::m_shadow_split[3],
|
||||
ShadowMatrices::m_shadow_split[4],
|
||||
};
|
||||
float NearValues[] =
|
||||
{
|
||||
ShadowMatrices::m_shadow_split[0],
|
||||
ShadowMatrices::m_shadow_split[1],
|
||||
ShadowMatrices::m_shadow_split[2],
|
||||
ShadowMatrices::m_shadow_split[3]
|
||||
};
|
||||
|
||||
float tmp[16 * 9 + 2];
|
||||
memcpy(tmp, irr_driver->getViewMatrix().pointer(), 16 * sizeof(float));
|
||||
@ -349,16 +354,20 @@ void ShadowMatrices::computeMatrixesAndCameras(scene::ICameraSceneNode *const ca
|
||||
|
||||
if (World::getWorld() && World::getWorld()->getTrack())
|
||||
{
|
||||
// Compute track extent
|
||||
btVector3 btmin, btmax;
|
||||
if (World::getWorld()->getTrack()->getPtrTriangleMesh())
|
||||
float FarValues[] =
|
||||
{
|
||||
World::getWorld()->getTrack()->getTriangleMesh().getCollisionShape()
|
||||
.getAabb(btTransform::getIdentity(), btmin, btmax);
|
||||
}
|
||||
const Vec3 vmin = btmin, vmax = btmax;
|
||||
core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
|
||||
core::vector3df(0, 30, 0));
|
||||
ShadowMatrices::m_shadow_split[1],
|
||||
ShadowMatrices::m_shadow_split[2],
|
||||
ShadowMatrices::m_shadow_split[3],
|
||||
ShadowMatrices::m_shadow_split[4],
|
||||
};
|
||||
float NearValues[] =
|
||||
{
|
||||
ShadowMatrices::m_shadow_split[0],
|
||||
ShadowMatrices::m_shadow_split[1],
|
||||
ShadowMatrices::m_shadow_split[2],
|
||||
ShadowMatrices::m_shadow_split[3]
|
||||
};
|
||||
|
||||
// Shadow Matrixes and cameras
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
@ -411,8 +420,16 @@ void ShadowMatrices::computeMatrixesAndCameras(scene::ICameraSceneNode *const ca
|
||||
}
|
||||
|
||||
// Rsm Matrix and camera
|
||||
if (!m_rsm_matrix_initialized)
|
||||
if (!m_rsm_matrix_initialized &&
|
||||
World::getWorld()->getTrack()->getPtrTriangleMesh())
|
||||
{
|
||||
// Compute track extent
|
||||
Vec3 vmin, vmax;
|
||||
World::getWorld()->getTrack()->getTriangleMesh().getCollisionShape()
|
||||
.getAabb(btTransform::getIdentity(), vmin, vmax);
|
||||
core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
|
||||
core::vector3df(0, 30, 0));
|
||||
|
||||
if (trackbox.MinEdge.X != trackbox.MaxEdge.X &&
|
||||
trackbox.MinEdge.Y != trackbox.MaxEdge.Y &&
|
||||
// Cover the case where sun_cam_view_matrix is null
|
||||
|
@ -64,6 +64,7 @@ private:
|
||||
public:
|
||||
|
||||
ShadowMatrices();
|
||||
~ShadowMatrices();
|
||||
|
||||
void computeMatrixesAndCameras(scene::ICameraSceneNode *const camnode,
|
||||
unsigned int width, unsigned int height,
|
||||
@ -74,10 +75,7 @@ public:
|
||||
const PostProcessing *post_processing);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void resetShadowCamNodes()
|
||||
{
|
||||
memset(m_shadow_cam_nodes, 0, 4 * sizeof(void*));
|
||||
} // resetShadowCamNodes
|
||||
void resetShadowCamNodes();
|
||||
// ------------------------------------------------------------------------
|
||||
scene::ICameraSceneNode** getShadowCamNodes()
|
||||
{
|
||||
|
@ -153,9 +153,9 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
float distance = (newPoint - start).length();
|
||||
|
||||
m_left [m_current]->add(raycast_left-delta, raycast_left+delta,
|
||||
distance);
|
||||
m_kart.getNormal(), distance);
|
||||
m_right[m_current]->add(raycast_right-delta, raycast_right+delta,
|
||||
distance);
|
||||
m_kart.getNormal(), distance);
|
||||
// Adjust the boundary box of the mesh to include the
|
||||
// adjusted aabb of its buffers.
|
||||
core::aabbox3df aabb=m_nodes[m_current]->getMesh()
|
||||
@ -180,14 +180,16 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
delta *= m_width*0.5f;
|
||||
|
||||
SkidMarkQuads *smq_left =
|
||||
new SkidMarkQuads(raycast_left-delta, raycast_left+delta ,
|
||||
m_material, m_avoid_z_fighting, custom_color);
|
||||
new SkidMarkQuads(raycast_left-delta, raycast_left+delta,
|
||||
m_kart.getNormal(), m_material, m_avoid_z_fighting,
|
||||
custom_color);
|
||||
scene::SMesh *new_mesh = new scene::SMesh();
|
||||
new_mesh->addMeshBuffer(smq_left);
|
||||
|
||||
SkidMarkQuads *smq_right =
|
||||
new SkidMarkQuads(raycast_right-delta, raycast_right+delta,
|
||||
m_material, m_avoid_z_fighting, custom_color);
|
||||
m_kart.getNormal(), m_material, m_avoid_z_fighting,
|
||||
custom_color);
|
||||
new_mesh->addMeshBuffer(smq_right);
|
||||
scene::IMeshSceneNode *new_node = irr_driver->addMesh(new_mesh, "skidmark");
|
||||
if (STKMeshSceneNode* stkm = dynamic_cast<STKMeshSceneNode*>(new_node))
|
||||
@ -233,6 +235,7 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
//=============================================================================
|
||||
SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
|
||||
const Vec3 &right,
|
||||
const Vec3 &normal,
|
||||
video::SMaterial *material,
|
||||
float z_offset,
|
||||
video::SColor* custom_color)
|
||||
@ -250,7 +253,7 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
|
||||
|
||||
Material = *material;
|
||||
m_aabb = core::aabbox3df(left.toIrrVector());
|
||||
add(left, right, 0.0f);
|
||||
add(left, right, normal, 0.0f);
|
||||
|
||||
|
||||
} // SkidMarkQuads
|
||||
@ -261,6 +264,7 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left,
|
||||
*/
|
||||
void SkidMarks::SkidMarkQuads::add(const Vec3 &left,
|
||||
const Vec3 &right,
|
||||
const Vec3 &normal,
|
||||
float distance)
|
||||
{
|
||||
// The skid marks must be raised slightly higher, otherwise it blends
|
||||
@ -280,13 +284,11 @@ void SkidMarks::SkidMarkQuads::add(const Vec3 &left,
|
||||
Vertices[n - 2].Color.setAlpha(m_start_alpha);
|
||||
}
|
||||
|
||||
v.Pos = left.toIrrVector();
|
||||
v.Pos.Y += m_z_offset;
|
||||
v.Normal = core::vector3df(0, 1, 0);
|
||||
v.Pos = Vec3(left + normal * m_z_offset).toIrrVector();
|
||||
v.Normal = normal.toIrrVector();
|
||||
v.TCoords = core::vector2df(0.0f, distance*0.5f);
|
||||
Vertices.push_back(v);
|
||||
v.Pos = right.toIrrVector();
|
||||
v.Pos.Y += m_z_offset;
|
||||
v.Pos = Vec3(right + normal * m_z_offset).toIrrVector();
|
||||
v.TCoords = core::vector2df(1.0f, distance*0.5f);
|
||||
Vertices.push_back(v);
|
||||
// Out of the box Irrlicht only supports triangle meshes and not
|
||||
|
@ -85,10 +85,11 @@ private:
|
||||
|
||||
public:
|
||||
SkidMarkQuads (const Vec3 &left, const Vec3 &right,
|
||||
video::SMaterial *material, float z_offset,
|
||||
video::SColor* custom_color = NULL);
|
||||
const Vec3 &normal, video::SMaterial *material,
|
||||
float z_offset, video::SColor* custom_color = NULL);
|
||||
void add (const Vec3 &left,
|
||||
const Vec3 &right,
|
||||
const Vec3 &normal,
|
||||
float distance);
|
||||
void fade (float f);
|
||||
/** Returns the aabb of this skid mark quads. */
|
||||
|
@ -170,6 +170,15 @@ void Skybox::generateCubeMapFromTextures()
|
||||
image->copyToScaling(rgba[i], size, size);
|
||||
image->drop();
|
||||
|
||||
#if defined(USE_GLES2)
|
||||
for (unsigned int j = 0; j < size * size; j++)
|
||||
{
|
||||
char tmp_val = rgba[i][j*4];
|
||||
rgba[i][j*4] = rgba[i][j*4 + 2];
|
||||
rgba[i][j*4 + 2] = tmp_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (i == 2 || i == 3)
|
||||
{
|
||||
char *tmp = new char[size * size * 4];
|
||||
@ -188,15 +197,14 @@ void Skybox::generateCubeMapFromTextures()
|
||||
#if !defined(USE_GLES2)
|
||||
GLint internal_format = CVS->isTextureCompressionEnabled() ?
|
||||
GL_COMPRESSED_SRGB_ALPHA : GL_SRGB_ALPHA;
|
||||
GLint format = GL_BGRA;
|
||||
#else
|
||||
// The GL_SRGB_ALPHA_EXT and GL_SRGB8_ALPHA8 formats are available in
|
||||
// OpenGL ES, but they produce black texture for some reason.
|
||||
// The basic GL_RGBA format works fine though.
|
||||
GLint internal_format = GL_RGBA;
|
||||
GLint internal_format = GL_RGBA8;
|
||||
GLint format = GL_RGBA;
|
||||
#endif
|
||||
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
|
||||
internal_format, size, size, 0, GL_BGRA,
|
||||
internal_format, size, size, 0, format,
|
||||
GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]);
|
||||
}
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
@ -213,8 +221,13 @@ void Skybox::generateSpecularCubemap()
|
||||
size_t cubemap_size = 256;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
#if !defined(USE_GLES2)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F,
|
||||
cubemap_size, cubemap_size, 0, GL_BGRA, GL_FLOAT, 0);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8,
|
||||
cubemap_size, cubemap_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
#endif
|
||||
}
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
|
||||
|
@ -77,7 +77,6 @@ SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
|
||||
p[1]=Vec3(-ew*0.5f, 0, -kl*0.5f-length);
|
||||
p[2]=Vec3( ew*0.5f, 0, -kl*0.5f-length);
|
||||
p[3]=Vec3( kw*0.5f, 0, -kl*0.5f );
|
||||
m_slipstream_original_quad = new Quad(p[0], p[1], p[2], p[3]);
|
||||
m_slipstream_quad = new Quad(p[0], p[1], p[2], p[3]);
|
||||
if(UserConfigParams::m_slipstream_debug)
|
||||
{
|
||||
@ -127,7 +126,6 @@ SlipStream::~SlipStream()
|
||||
m_debug_node->drop();
|
||||
m_debug_mesh->drop();
|
||||
}
|
||||
delete m_slipstream_original_quad;
|
||||
delete m_slipstream_quad;
|
||||
|
||||
} // ~SlipStream
|
||||
@ -369,12 +367,6 @@ void SlipStream::update(float dt)
|
||||
|
||||
MovingTexture::update(dt);
|
||||
|
||||
// Update this karts slipstream quad (even for low level AI which don't
|
||||
// use slipstream, since even then player karts can get slipstream,
|
||||
// and so have to compare with the modified slipstream quad.
|
||||
m_slipstream_original_quad->transform(m_kart->getTrans(),
|
||||
m_slipstream_quad);
|
||||
|
||||
if(m_slipstream_mode==SS_USE)
|
||||
{
|
||||
m_slipstream_time -= dt;
|
||||
@ -418,12 +410,13 @@ void SlipStream::update(float dt)
|
||||
m_target_kart->getKartAnimation() ||
|
||||
m_target_kart->isEliminated() ) continue;
|
||||
|
||||
float diff = fabsf(m_target_kart->getXYZ().getY()
|
||||
- m_kart->getXYZ().getY() );
|
||||
// Transform this kart location into target kart point of view
|
||||
Vec3 lc = m_target_kart->getTrans().inverse()(m_kart->getXYZ());
|
||||
|
||||
// If the kart is 'on top' of this kart (e.g. up on a bridge),
|
||||
// don't consider it for slipstreaming.
|
||||
if (fabsf(lc.y()) > 6.0f) continue;
|
||||
|
||||
if(diff>6.0f) continue;
|
||||
// If the kart we are testing against is too slow, no need to test
|
||||
// slipstreaming. Note: We compare the speed of the other kart
|
||||
// against the minimum slipstream speed kart of this kart - not
|
||||
@ -447,7 +440,7 @@ void SlipStream::update(float dt)
|
||||
float l = kp->getSlipstreamLength()
|
||||
+ 0.5f*( m_target_kart->getKartLength()
|
||||
+m_kart->getKartLength() );
|
||||
if(delta.length2_2d() > l*l)
|
||||
if(delta.length2() > l*l)
|
||||
{
|
||||
if(UserConfigParams::m_slipstream_debug &&
|
||||
m_kart->getController()->isLocalPlayerController())
|
||||
@ -457,7 +450,7 @@ void SlipStream::update(float dt)
|
||||
}
|
||||
// Real test: if in slipstream quad of other kart
|
||||
if(m_target_kart->getSlipstream()->m_slipstream_quad
|
||||
->pointInQuad(m_kart->getXYZ()))
|
||||
->pointInside(lc))
|
||||
{
|
||||
is_sstreaming = true;
|
||||
break;
|
||||
|
@ -66,14 +66,9 @@ private:
|
||||
* 'slipstream credits', or the kart is using accumulated credits. */
|
||||
enum {SS_NONE, SS_COLLECT, SS_USE} m_slipstream_mode;
|
||||
|
||||
/** The quad inside which another kart is considered to be slipstreaming.
|
||||
* This value is current area, i.e. takes the kart position into account. */
|
||||
/** This is slipstream area if the kart is at 0,0,0 without rotation. */
|
||||
Quad *m_slipstream_quad;
|
||||
|
||||
/** This is slipstream area if the kart is at 0,0,0 without rotation. From
|
||||
* this value m_slipstream_area is computed by applying the kart transform. */
|
||||
Quad *m_slipstream_original_quad;
|
||||
|
||||
/** The kart from which this kart gets slipstream. Used by the AI to
|
||||
** overtake the right kart. */
|
||||
AbstractKart* m_target_kart;
|
||||
|
@ -99,6 +99,16 @@ void STKAnimatedMesh::updateNoGL()
|
||||
|
||||
if (!isMaterialInitialized)
|
||||
{
|
||||
// Use a default render info to distinguish same mesh buffer created by
|
||||
// different animated mesh node in vao manager when using instanced
|
||||
// rendering
|
||||
RenderInfo* default_ri = NULL;
|
||||
if (CVS->isARBBaseInstanceUsable())
|
||||
{
|
||||
default_ri = new RenderInfo();
|
||||
m_static_render_info.push_back(default_ri);
|
||||
}
|
||||
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
const u32 mb_count = m->getMeshBufferCount();
|
||||
for (u32 i = 0; i < mb_count; ++i)
|
||||
@ -121,7 +131,7 @@ void STKAnimatedMesh::updateNoGL()
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_ri = NULL;
|
||||
cur_ri = default_ri;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -137,7 +147,7 @@ void STKAnimatedMesh::updateNoGL()
|
||||
assert(cur_ri ? cur_ri->isStatic() : true);
|
||||
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name,
|
||||
affected || m_all_parts_colorized || (cur_ri
|
||||
&& cur_ri->isTransparent()) ? cur_ri : NULL));
|
||||
&& cur_ri->isTransparent()) ? cur_ri : default_ri));
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
|
||||
@ -165,11 +175,14 @@ void STKAnimatedMesh::updateNoGL()
|
||||
}
|
||||
else if (mesh.m_render_info != NULL && mesh.m_render_info->isTransparent())
|
||||
{
|
||||
TransparentMesh[TM_ADDITIVE].push_back(&mesh);
|
||||
if (mesh.VAOType == video::EVT_TANGENTS)
|
||||
TransparentMesh[TM_GHOST_KART_TANGENTS].push_back(&mesh);
|
||||
else
|
||||
TransparentMesh[TM_GHOST_KART].push_back(&mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
Material::ShaderType MatType = material->getShaderType();// getMeshMaterialFromType(type, mb->getVertexType(), material);
|
||||
Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, NULL);
|
||||
MeshSolidMaterial[MatType].push_back(&mesh);
|
||||
}
|
||||
}
|
||||
@ -218,7 +231,7 @@ void STKAnimatedMesh::updateGL()
|
||||
|
||||
if (CVS->isARBBaseInstanceUsable())
|
||||
{
|
||||
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb);
|
||||
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb, GLmeshes[i].m_render_info);
|
||||
mesh.vaoBaseVertex = p.first;
|
||||
mesh.vaoOffset = p.second;
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ enum TransparentMaterial
|
||||
TM_DEFAULT,
|
||||
TM_ADDITIVE,
|
||||
TM_DISPLACEMENT,
|
||||
TM_GHOST_KART,
|
||||
TM_GHOST_KART_TANGENTS,
|
||||
TM_COUNT
|
||||
}; // TransparentMaterial
|
||||
|
||||
@ -156,13 +158,26 @@ class MiscList : public Singleton<T>, public std::vector<STK::Tuple<Args...> >
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListBlendTransparent : public MiscList<ListBlendTransparent, GLMesh *,
|
||||
core::matrix4, core::matrix4>
|
||||
core::matrix4, core::matrix4,
|
||||
float>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListAdditiveTransparent : public MiscList<ListAdditiveTransparent,
|
||||
GLMesh *, core::matrix4,
|
||||
core::matrix4>
|
||||
core::matrix4, float>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListGhostKart : public MiscList<ListGhostKart,
|
||||
GLMesh *, core::matrix4,
|
||||
core::matrix4, float>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ListGhostKartTangents : public MiscList<ListGhostKartTangents,
|
||||
GLMesh *, core::matrix4,
|
||||
core::matrix4, float>
|
||||
{};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -32,8 +32,8 @@
|
||||
#include "utils/helpers.hpp"
|
||||
#include "utils/tuple.hpp"
|
||||
|
||||
#include <ISceneManager.h>
|
||||
#include <IMaterialRenderer.h>
|
||||
#include <ISceneManager.h>
|
||||
|
||||
// ============================================================================
|
||||
class ColorizeShader : public Shader<ColorizeShader, core::matrix4,
|
||||
@ -54,12 +54,14 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent,
|
||||
irr::s32 id, const std::string& debug_name,
|
||||
const irr::core::vector3df& position,
|
||||
const irr::core::vector3df& rotation,
|
||||
const irr::core::vector3df& scale, bool createGLMeshes, RenderInfo* render_info, bool all_parts_colorized) :
|
||||
const irr::core::vector3df& scale, bool createGLMeshes, RenderInfo* render_info, bool all_parts_colorized,
|
||||
int frame_for_mesh) :
|
||||
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
|
||||
{
|
||||
isDisplacement = false;
|
||||
immediate_draw = false;
|
||||
update_each_frame = false;
|
||||
m_frame_for_mesh = frame_for_mesh;
|
||||
isGlow = false;
|
||||
|
||||
m_debug_name = debug_name;
|
||||
@ -207,12 +209,13 @@ void STKMeshSceneNode::updateNoGL()
|
||||
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
|
||||
if (mesh.m_render_info != NULL && mesh.m_render_info->isTransparent())
|
||||
if (mesh.m_render_info != NULL && mesh.m_render_info->isTransparent() && !rnd->isTransparent())
|
||||
{
|
||||
if (!immediate_draw)
|
||||
TransparentMesh[TM_ADDITIVE].push_back(&mesh);
|
||||
assert(!immediate_draw);
|
||||
if (mesh.VAOType == video::EVT_TANGENTS)
|
||||
TransparentMesh[TM_GHOST_KART_TANGENTS].push_back(&mesh);
|
||||
else
|
||||
additive = true;
|
||||
TransparentMesh[TM_GHOST_KART].push_back(&mesh);
|
||||
}
|
||||
else if (rnd->isTransparent())
|
||||
{
|
||||
@ -249,9 +252,18 @@ void STKMeshSceneNode::updateGL()
|
||||
{
|
||||
if (isGLInitialized)
|
||||
return;
|
||||
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
|
||||
|
||||
scene::IAnimatedMesh* am = dynamic_cast<scene::IAnimatedMesh*>(Mesh);
|
||||
scene::IMesh* m = Mesh;
|
||||
if (am && m_frame_for_mesh > -1)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
// Get the correct frame of animation for animated mesh
|
||||
m = am->getMesh(m_frame_for_mesh);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
@ -561,7 +573,7 @@ void STKMeshSceneNode::render()
|
||||
#endif
|
||||
Shaders::TransparentShader::getInstance()->setTextureUnits(getTextureGLuint(mesh.textures[0]));
|
||||
|
||||
Shaders::TransparentShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix);
|
||||
Shaders::TransparentShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix, 1.0f);
|
||||
assert(mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
|
@ -29,6 +29,7 @@ class STKMeshSceneNode : public irr::scene::CMeshSceneNode, public STKMeshCommon
|
||||
{
|
||||
protected:
|
||||
PtrVector<RenderInfo> m_static_render_info;
|
||||
int m_frame_for_mesh;
|
||||
std::vector<GLMesh> GLmeshes;
|
||||
core::matrix4 ModelViewProjectionMatrix;
|
||||
core::vector3df windDir;
|
||||
@ -58,7 +59,8 @@ public:
|
||||
const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0),
|
||||
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f),
|
||||
bool createGLMeshes = true,
|
||||
RenderInfo* render_info = NULL, bool all_parts_colorized = false);
|
||||
RenderInfo* render_info = NULL, bool all_parts_colorized = false,
|
||||
int frame_for_mesh = -1);
|
||||
virtual void render();
|
||||
virtual void setMesh(irr::scene::IMesh* mesh);
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
@ -43,7 +43,6 @@ void addEdge(const core::vector3df &P0, const core::vector3df &P1)
|
||||
BoundingBoxes.push_back(P1.Z);
|
||||
}
|
||||
|
||||
|
||||
bool isCulledPrecise(const scene::ICameraSceneNode *cam, const scene::ISceneNode *node)
|
||||
{
|
||||
if (!node->getAutomaticCulling())
|
||||
|
@ -50,14 +50,28 @@ STKTextBillboard::STKTextBillboard(core::stringw text, FontWithFace* font,
|
||||
|
||||
void STKTextBillboard::updateAbsolutePosition()
|
||||
{
|
||||
// Make billboard always face the camera
|
||||
scene::ICameraSceneNode* curr_cam =
|
||||
irr_driver->getSceneManager()->getActiveCamera();
|
||||
if (!curr_cam) return;
|
||||
core::quaternion q(curr_cam->getViewMatrix());
|
||||
q.W = -q.W;
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
// Override to not use the parent's rotation
|
||||
AbsoluteTransformation = getRelativeTransformation();
|
||||
AbsoluteTransformation.setTranslation(AbsoluteTransformation.getTranslation() + Parent->getAbsolutePosition());
|
||||
core::vector3df wc = RelativeTranslation;
|
||||
Parent->getAbsoluteTransformation().transformVect(wc);
|
||||
AbsoluteTransformation.setTranslation(wc);
|
||||
q.getMatrix(AbsoluteTransformation, wc);
|
||||
}
|
||||
else
|
||||
AbsoluteTransformation = getRelativeTransformation();
|
||||
{
|
||||
q.getMatrix(AbsoluteTransformation, RelativeTranslation);
|
||||
}
|
||||
core::matrix4 m;
|
||||
m.setScale(RelativeScale);
|
||||
AbsoluteTransformation *= m;
|
||||
}
|
||||
|
||||
scene::IMesh* STKTextBillboard::getTextMesh(core::stringw text, FontWithFace* font)
|
||||
@ -171,18 +185,6 @@ scene::IMesh* STKTextBillboard::getTextMesh(core::stringw text, FontWithFace* fo
|
||||
return Mesh;
|
||||
}
|
||||
|
||||
void STKTextBillboard::updateNoGL()
|
||||
{
|
||||
scene::ICameraSceneNode* curr_cam = irr_driver->getSceneManager()->getActiveCamera();
|
||||
core::vector3df cam_pos = curr_cam->getPosition();
|
||||
core::vector3df text_pos = this->getAbsolutePosition();
|
||||
float angle = atan2(text_pos.X - cam_pos.X, text_pos.Z - cam_pos.Z);
|
||||
this->setRotation(core::vector3df(0.0f, angle * 180.0f / M_PI, 0.0f));
|
||||
updateAbsolutePosition();
|
||||
|
||||
STKMeshSceneNode::updateNoGL();
|
||||
}
|
||||
|
||||
void STKTextBillboard::collectChar(video::ITexture* texture,
|
||||
const core::rect<float>& destRect,
|
||||
const core::rect<s32>& sourceRect,
|
||||
|
@ -74,8 +74,6 @@ public:
|
||||
const irr::core::vector3df& position,
|
||||
const irr::core::vector3df& size);
|
||||
|
||||
virtual void updateNoGL() OVERRIDE;
|
||||
|
||||
virtual scene::ESCENE_NODE_TYPE getType() const OVERRIDE
|
||||
{
|
||||
return scene::ESNT_TEXT;
|
||||
|
@ -34,6 +34,8 @@
|
||||
|
||||
GLuint getTextureGLuint(irr::video::ITexture *tex)
|
||||
{
|
||||
if (tex == NULL)
|
||||
return 0;
|
||||
#if defined(USE_GLES2)
|
||||
return static_cast<irr::video::COGLES2Texture*>(tex)->getOpenGLTextureName();
|
||||
#else
|
||||
@ -57,6 +59,14 @@ static std::map<int, video::ITexture*> unicolor_cache;
|
||||
void resetTextureTable()
|
||||
{
|
||||
AlreadyTransformedTexture.clear();
|
||||
}
|
||||
|
||||
void cleanUnicolorTextures()
|
||||
{
|
||||
for (std::pair<const int, video::ITexture*>& uc : unicolor_cache)
|
||||
{
|
||||
uc.second->drop();
|
||||
}
|
||||
unicolor_cache.clear();
|
||||
}
|
||||
|
||||
@ -87,10 +97,20 @@ void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha)
|
||||
memcpy(data, tex->lock(), w * h * 4);
|
||||
tex->unlock();
|
||||
unsigned internalFormat, Format;
|
||||
if (tex->hasAlpha())
|
||||
Format = GL_BGRA;
|
||||
else
|
||||
Format = GL_BGR;
|
||||
Format = tex->hasAlpha() ? GL_BGRA : GL_BGR;
|
||||
#if defined(USE_GLES2)
|
||||
if (!CVS->isEXTTextureFormatBGRA8888Usable())
|
||||
{
|
||||
Format = tex->hasAlpha() ? GL_RGBA : GL_RGB;
|
||||
|
||||
for (unsigned int i = 0; i < w * h; i++)
|
||||
{
|
||||
char tmp_val = data[i*4];
|
||||
data[i*4] = data[i*4 + 2];
|
||||
data[i*4 + 2] = tmp_val;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (premul_alpha)
|
||||
{
|
||||
@ -216,7 +236,6 @@ video::ITexture* getUnicolorTexture(const video::SColor &c)
|
||||
std::map<int, video::ITexture*>::iterator it = unicolor_cache.find(c.color);
|
||||
if (it != unicolor_cache.end())
|
||||
{
|
||||
it->second->grab();
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
@ -228,10 +247,12 @@ video::ITexture* getUnicolorTexture(const video::SColor &c)
|
||||
c.color
|
||||
};
|
||||
video::IImage *img = irr_driver->getVideoDriver()->createImageFromData(video::ECF_A8R8G8B8, core::dimension2d<u32>(2, 2), tmp);
|
||||
img->grab();
|
||||
std::stringstream name;
|
||||
name << "color" << c.color;
|
||||
video::ITexture* tex = irr_driver->getVideoDriver()->addTexture(name.str().c_str(), img);
|
||||
tex->grab();
|
||||
// Only let our map hold the unicolor texture
|
||||
irr_driver->getVideoDriver()->removeTexture(tex);
|
||||
unicolor_cache[c.color] = tex;
|
||||
img->drop();
|
||||
return tex;
|
||||
|
@ -26,6 +26,7 @@
|
||||
GLuint getTextureGLuint(irr::video::ITexture *tex);
|
||||
GLuint getDepthTexture(irr::video::ITexture *tex);
|
||||
void resetTextureTable();
|
||||
void cleanUnicolorTextures();
|
||||
void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = false);
|
||||
bool loadCompressedTexture(const std::string& compressed_tex);
|
||||
void saveCompressedTexture(const std::string& compressed_tex);
|
||||
|
@ -17,6 +17,7 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/texture_shader.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
|
||||
@ -33,7 +34,7 @@ TextureShaderBase::BindFunction TextureShaderBase::m_all_bind_functions[] =
|
||||
/* ST_SEMI_TRILINEAR */ &TextureShaderBase::bindTextureSemiTrilinear
|
||||
};
|
||||
|
||||
GLuint TextureShaderBase::m_all_texture_types[] =
|
||||
GLuint TextureShaderBase::m_all_texture_types[] =
|
||||
{ /* ST_NEAREST_FILTERED */ GL_TEXTURE_2D,
|
||||
/* ST_TRILINEAR_ANISOTROPIC_FILTERED */ GL_TEXTURE_2D,
|
||||
/* ST_TRILINEAR_CUBEMAP */ GL_TEXTURE_CUBE_MAP,
|
||||
@ -55,7 +56,8 @@ void TextureShaderBase::bindTextureNearest(GLuint texture_unit, GLuint tex)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
|
||||
} // bindTextureNearest
|
||||
|
||||
@ -69,9 +71,13 @@ void TextureShaderBase::bindTextureTrilinearAnisotropic(GLuint tex_unit, GLuint
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
{
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
(float)aniso);
|
||||
}
|
||||
} // bindTextureTrilinearAnisotropic
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -84,10 +90,13 @@ void TextureShaderBase::bindCubemapTrilinear(unsigned tex_unit, unsigned tex)
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
(float)aniso);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
{
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
(float)aniso);
|
||||
}
|
||||
} // bindCubemapTrilinear
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -100,7 +109,8 @@ void TextureShaderBase::bindTextureNearestClamped(GLuint texture_unit,
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
} // bindTextureNearestClamped
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -114,7 +124,8 @@ void TextureShaderBase::bindTextureBilinear(GLuint texture_unit, GLuint tex)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
} // bindTextureBilinear
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -126,7 +137,8 @@ void TextureShaderBase::bindTextureBilinearClamped(GLuint tex_unit, GLuint tex)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
} // bindTextureBilinearClamped
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -138,7 +150,8 @@ void TextureShaderBase::bindTextureSemiTrilinear(GLuint tex_unit, GLuint tex_id)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
} // bindTextureSemiTrilinear
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -165,9 +178,13 @@ void TextureShaderBase::bindTrilinearClampedArrayTexture(unsigned tex_unit,
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
{
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
(float)aniso);
|
||||
}
|
||||
} // bindTrilinearClampedArrayTexture
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -179,7 +196,8 @@ void TextureShaderBase::bindTextureVolume(unsigned tex_unit, unsigned tex_id)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
} // bindTextureVolume
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -211,7 +229,8 @@ GLuint TextureShaderBase::createSamplers(SamplerTypeNew sampler_type)
|
||||
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
return createNearestSampler();
|
||||
}
|
||||
case ST_BILINEAR_CLAMPED_FILTERED:
|
||||
@ -234,7 +253,8 @@ GLuint TextureShaderBase::createNearestSampler()
|
||||
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
return id;
|
||||
#endif
|
||||
} // createNearestSampler
|
||||
@ -250,9 +270,12 @@ GLuint TextureShaderBase::createTrilinearSampler()
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
{
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
||||
}
|
||||
return id;
|
||||
#endif
|
||||
} // createTrilinearSampler
|
||||
@ -267,7 +290,8 @@ GLuint TextureShaderBase::createBilinearSampler()
|
||||
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
return id;
|
||||
#endif
|
||||
} // createBilinearSampler
|
||||
@ -297,7 +321,8 @@ GLuint TextureShaderBase::createBilinearClampedSampler()
|
||||
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
return id;
|
||||
#endif
|
||||
} // createBilinearClampedSampler
|
||||
@ -314,9 +339,12 @@ GLuint TextureShaderBase::createTrilinearClampedArray()
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
{
|
||||
int aniso = UserConfigParams::m_anisotropic;
|
||||
if (aniso == 0) aniso = 1;
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
||||
}
|
||||
return id;
|
||||
#endif
|
||||
} // createTrilinearClampedArray
|
||||
@ -330,7 +358,8 @@ GLuint TextureShaderBase::createSemiTrilinearSampler()
|
||||
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
if (CVS->isEXTTextureFilterAnisotropicUsable())
|
||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
|
||||
return id;
|
||||
#endif
|
||||
} // createSemiTrilinearSampler
|
||||
|
@ -287,7 +287,7 @@ irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp)
|
||||
}
|
||||
}
|
||||
|
||||
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
|
||||
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp, RenderInfo* ri)
|
||||
{
|
||||
size_t old_vtx_cnt = last_vertex[tp];
|
||||
size_t old_idx_cnt = last_index[tp];
|
||||
@ -318,26 +318,28 @@ void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, old_idx_cnt * sizeof(u16), mb->getIndexCount() * sizeof(u16), mb->getIndices());
|
||||
}
|
||||
|
||||
mappedBaseVertex[tp][mb] = old_vtx_cnt;
|
||||
mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16);
|
||||
std::pair<scene::IMeshBuffer*, RenderInfo*> key(mb, ri);
|
||||
mappedBaseVertex[tp][key] = old_vtx_cnt;
|
||||
mappedBaseIndex[tp][key] = old_idx_cnt * sizeof(u16);
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
|
||||
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb, RenderInfo* ri)
|
||||
{
|
||||
VTXTYPE tp = getVTXTYPE(mb->getVertexType());
|
||||
if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end())
|
||||
std::pair<scene::IMeshBuffer*, RenderInfo*> key(mb, ri);
|
||||
if (mappedBaseVertex[tp].find(key) == mappedBaseVertex[tp].end())
|
||||
{
|
||||
assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end());
|
||||
append(mb, tp);
|
||||
assert(mappedBaseIndex[tp].find(key) == mappedBaseIndex[tp].end());
|
||||
append(mb, tp, ri);
|
||||
regenerateVAO(tp);
|
||||
regenerateInstancedVAO();
|
||||
}
|
||||
|
||||
std::unordered_map<scene::IMeshBuffer*, unsigned>::iterator It;
|
||||
It = mappedBaseVertex[tp].find(mb);
|
||||
std::unordered_map<std::pair<scene::IMeshBuffer*, RenderInfo*>, unsigned, MeshRenderInfoHash, MeshRenderInfoEquals>::iterator It;
|
||||
It = mappedBaseVertex[tp].find(key);
|
||||
assert(It != mappedBaseVertex[tp].end());
|
||||
unsigned vtx = It->second;
|
||||
It = mappedBaseIndex[tp].find(mb);
|
||||
It = mappedBaseIndex[tp].find(key);
|
||||
assert(It != mappedBaseIndex[tp].end());
|
||||
return std::pair<unsigned, unsigned>(vtx, It->second);
|
||||
}
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
class RenderInfo;
|
||||
|
||||
enum InstanceType
|
||||
{
|
||||
InstanceTypeDualTex,
|
||||
@ -153,6 +155,30 @@ struct GlowInstanceData
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#include <functional>
|
||||
|
||||
class MeshRenderInfoHash
|
||||
{
|
||||
public:
|
||||
size_t operator() (const std::pair<irr::scene::IMeshBuffer*, RenderInfo*> &p) const
|
||||
{
|
||||
return (std::hash<irr::scene::IMeshBuffer*>()(p.first) ^
|
||||
(std::hash<RenderInfo*>()(p.second) << 1));
|
||||
}
|
||||
};
|
||||
|
||||
struct MeshRenderInfoEquals : std::binary_function
|
||||
<const std::pair<irr::scene::IMeshBuffer*, RenderInfo*>&,
|
||||
const std::pair<irr::scene::IMeshBuffer*, RenderInfo*>&, bool>
|
||||
{
|
||||
result_type operator() (first_argument_type lhs,
|
||||
second_argument_type rhs) const
|
||||
{
|
||||
return (lhs.first == rhs.first) &&
|
||||
(lhs.second == rhs.second);
|
||||
}
|
||||
};
|
||||
|
||||
class VAOManager : public Singleton<VAOManager>
|
||||
{
|
||||
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
|
||||
@ -162,7 +188,7 @@ class VAOManager : public Singleton<VAOManager>
|
||||
void *VBOPtr[VTXTYPE_COUNT], *IBOPtr[VTXTYPE_COUNT];
|
||||
size_t RealVBOSize[VTXTYPE_COUNT], RealIBOSize[VTXTYPE_COUNT];
|
||||
size_t last_vertex[VTXTYPE_COUNT], last_index[VTXTYPE_COUNT];
|
||||
std::unordered_map<irr::scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
|
||||
std::unordered_map <std::pair<irr::scene::IMeshBuffer*, RenderInfo*>, unsigned, MeshRenderInfoHash, MeshRenderInfoEquals> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
|
||||
std::map<std::pair<irr::video::E_VERTEX_TYPE, InstanceType>, GLuint> InstanceVAO;
|
||||
|
||||
void cleanInstanceVAOs();
|
||||
@ -172,10 +198,10 @@ class VAOManager : public Singleton<VAOManager>
|
||||
size_t getVertexPitch(enum VTXTYPE) const;
|
||||
VTXTYPE getVTXTYPE(irr::video::E_VERTEX_TYPE type);
|
||||
irr::video::E_VERTEX_TYPE getVertexType(enum VTXTYPE tp);
|
||||
void append(irr::scene::IMeshBuffer *, VTXTYPE tp);
|
||||
void append(irr::scene::IMeshBuffer *, VTXTYPE tp, RenderInfo* ri = NULL);
|
||||
public:
|
||||
VAOManager();
|
||||
std::pair<unsigned, unsigned> getBase(irr::scene::IMeshBuffer *);
|
||||
std::pair<unsigned, unsigned> getBase(irr::scene::IMeshBuffer *, RenderInfo* ri = NULL);
|
||||
GLuint getInstanceBuffer(InstanceType it) { return instance_vbo[it]; }
|
||||
void *getInstanceBufferPtr(InstanceType it) { return Ptr[it]; }
|
||||
unsigned getVBO(irr::video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; }
|
||||
|
@ -659,6 +659,8 @@ namespace GUIEngine
|
||||
#include "config/user_config.hpp"
|
||||
#include "font/bold_face.hpp"
|
||||
#include "font/digit_face.hpp"
|
||||
#include "font/font_manager.hpp"
|
||||
#include "font/font_settings.hpp"
|
||||
#include "font/regular_face.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
|
@ -387,7 +387,7 @@ const bool NAVIGATION_DEBUG = false;
|
||||
*/
|
||||
void EventHandler::navigate(const int playerID, Input::InputType type, const bool pressedDown, const bool reverse)
|
||||
{
|
||||
IGUIElement *el = NULL, *closest = NULL;
|
||||
IGUIElement *el = NULL;
|
||||
|
||||
if (type == Input::IT_STICKBUTTON && !pressedDown)
|
||||
return;
|
||||
@ -450,7 +450,7 @@ void EventHandler::navigate(const int playerID, Input::InputType type, const boo
|
||||
// Down: if the current widget is e.g. 5, search for widget 6, 7, 8, 9, ..., 15 (up to 10 IDs may be missing)
|
||||
for (int n = 1; n < 10 && !found; n++)
|
||||
{
|
||||
closest = GUIEngine::getGUIEnv()->getRootGUIElement()->getElementFromId(el->getTabOrder() + (reverse ? -n : n), true);
|
||||
IGUIElement *closest = GUIEngine::getGUIEnv()->getRootGUIElement()->getElementFromId(el->getTabOrder() + (reverse ? -n : n), true);
|
||||
|
||||
if (closest != NULL && Widget::isFocusableId(closest->getID()))
|
||||
{
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
|
||||
#include "font/font_settings.hpp"
|
||||
#include "font/font_with_face.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
|
@ -927,7 +927,6 @@ void Skin::drawRibbonChild(const core::recti &rect, Widget* widget,
|
||||
//if (widget->m_deactivated) return;
|
||||
|
||||
bool mark_selected = widget->isSelected(PLAYER_ID_GAME_MASTER);
|
||||
bool always_show_selection = false;
|
||||
|
||||
IGUIElement* focusedElem = NULL;
|
||||
if (GUIEngine::getFocusForPlayer(PLAYER_ID_GAME_MASTER) != NULL)
|
||||
@ -1007,6 +1006,7 @@ void Skin::drawRibbonChild(const core::recti &rect, Widget* widget,
|
||||
|
||||
/* in combo ribbons, always show selection */
|
||||
RibbonWidget* parentRibbonWidget = NULL;
|
||||
bool always_show_selection = false;
|
||||
|
||||
if (widget->m_event_handler != NULL &&
|
||||
widget->m_event_handler->m_type == WTYPE_RIBBON)
|
||||
|
@ -1321,11 +1321,10 @@ void CGUIEditBox::breakText()
|
||||
s32 size = Text.size();
|
||||
s32 length = 0;
|
||||
s32 elWidth = RelativeRect.getWidth() - 6;
|
||||
wchar_t c;
|
||||
|
||||
for (s32 i=0; i<size; ++i)
|
||||
{
|
||||
c = Text[i];
|
||||
wchar_t c = Text[i];
|
||||
bool lineBreak = false;
|
||||
|
||||
if (c == L'\r') // Mac or Windows breaks
|
||||
|