Merge branch 'master' into NewRTTWidget

This commit is contained in:
Marianne Gagnon 2014-05-29 20:00:58 -04:00
commit 7e9252e5b3
99 changed files with 2905 additions and 2391 deletions
data
lib/irrlicht/source/Irrlicht
src

View File

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<!-- For sky particles, the size of the box is ignored -->
<particles emitter="box" box_x="10.0" box_y="0.5" box_z="10.0">
<spreading angle="3" />
<velocity x="-0.00"
y="-0.002"
z="-0.00" />
<material file="gfx_leaf_a.png" clampu="Y" clampv="Y" />
<!-- Amount of particles emitted per second -->
<rate min="2"
max="5" />
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
<lifetime min="30000"
max="30000" />
<!-- Size of the particles -->
<size min="0.40"
max="0.60" />
<color min="40 40 255"
max="255 255 255" />
<!-- How much time in milliseconds before the particle is fully faded out -->
<fadeout time="100" />
<wind speed="0.16"
flips="Y" />
</particles>

View File

@ -11,10 +11,10 @@
<spacer height="20" width="20" />
<!-- TODO: ok button? -->
<button id="cancel" I18N="When configuring input" text="Press ESC to cancel" align="center"/>
<buttonbar proportion="1" id="options" width="100%" height="100%">
<button id="ok" I18N="When configuring input" text="OK" align="center"/>
<button id="cancel" I18N="When configuring input" text="Cancel" align="center"/>
</buttonbar>
<spacer height="15" width="20" />
</div>

View File

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-16"?>
<stkgui>
<div x="1%" y="1%" width="98%" height="98%" layout="vertical-row" >
<header align="center" width="80%" text="Login" text_align="center"/>
<spacer height="15" width="10"/>
<tabs id="login_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
<icon-button id="tab_login" width="128" height="128" icon="gui/track_random.png"
I18N="Tab in login menu" text="Sign In"/>
<icon-button id="tab_guest_login" width="128" height="128" icon="gui/mode_ftl.png"
I18N="Tab in login menu" text="Sign In As Guest"/>
<icon-button id="tab_register" width="128" height="128" icon="gui/mode_ftl.png"
I18N="Tab in login menu" text="Register"/>
</tabs>
<box proportion="1" width="100%" layout="vertical-row">
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
I18N="In the login dialog" text="Sign in"/>
<spacer height="20" width="20"/>
<div width="80%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="left" I18N="In the login dialog" text="Username"/>
<textbox proportion="2" height="fit" id="username" I18N="In the login dialog"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="left" I18N="In the login dialog" text="Password"/>
<textbox x="5" proportion="2" height="fit" id="password" I18N="In the login dialog"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the login dialog" text="Stay signed in"/>
<div proportion="2" height="100%" layout="horizontal-row">
<checkbox width="fit" height="fit" id="remember" I18N="In the login dialog"/>
</div>
</div>
</div>
<label id="info" proportion="1" width="90%" align="center" text_align="center"
word_wrap="true" text=""/>
<spacer height="20" width="20"/>
<buttonbar id="options" width="90%" height="13%" align="bottom">
<icon-button id="sign_in" width="64" height="64" icon="gui/green_check.png"
I18N="Login dialog" text="Sign In" label_location="bottom"/>
<icon-button id="recovery" width="64" height="64" icon="gui/main_help.png"
I18N="Login dialog" text="Recovery" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Login dialog" text="Close" label_location="bottom"/>
</buttonbar>
<spacer height="20" width="20"/>
</box>
</div>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
</stkgui>

View File

@ -3,55 +3,59 @@
<div x="1%" y="1%" width="98%" height="98%" layout="vertical-row" >
<header align="center" width="80%" text="Login" text_align="center"/>
<header align="center" width="80%" text="Create User" text_align="center"
I18N="In the registration dialog" />
<spacer height="15" width="10"/>
<tabs id="login_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
<icon-button id="tab_login" width="128" height="128" icon="gui/track_random.png"
I18N="Tab in login menu" text="Sign In"/>
<icon-button id="tab_guest_login" width="128" height="128" icon="gui/mode_ftl.png"
I18N="Tab in login menu" text="Sign In As Guest"/>
<icon-button id="tab_register" width="128" height="128" icon="gui/mode_ftl.png"
I18N="Tab in login menu" text="Register"/>
</tabs>
<box proportion="1" width="100%" layout="vertical-row">
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
I18N="In the login dialog" text="Sign in"/>
<spacer height="40" width="20"/>
<div width="80%" align="center" layout="vertical-row" height="fit">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="left" I18N="In the registration dialog" text="Username"/>
<textbox proportion="2" height="fit" id="username" I18N="In the registration dialog"/>
<label proportion="1" height="100%" text_align="left"
I18N="In the registration dialog" text="Local Username"/>
<textbox id="local_username" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_online" proportion="1" height="100%" text_align="left"
I18N="In the login screen" text="Online"/>
<checkbox id="online" I18N="In the login screen" text_align="left"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_username" proportion="1" height="100%" text_align="left"
I18N="In the registration dialog" text="Online Username"/>
<textbox id="username" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="left" I18N="In the registration dialog" text="Password"/>
<textbox proportion="2" height="fit" id="password" I18N="In the registration dialog"/>
<label id="label_password" proportion="1" height="100%" text_align="left"
I18N="In the registration dialog" text="Password"/>
<textbox id="password" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="left" I18N="In the registration dialog" text="Confirm"/>
<textbox proportion="2" height="fit" id="password_confirm" I18N="In the registration dialog"/>
<label id="label_password_confirm" proportion="1" height="100%" text_align="left"
I18N="In the registration dialog" text="Confirm"/>
<textbox id="password_confirm" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="left" I18N="In the registration dialog" text="Email"/>
<textbox proportion="2" height="fit" id="email" I18N="In the registration dialog"/>
<label id="label_email" proportion="1" height="100%" text_align="left"
I18N="In the registration dialog" text="Email"/>
<textbox id="email" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="left" I18N="In the registration dialog" text="Confirm"/>
<textbox proportion="2" height="fit" id="email_confirm" I18N="In the registration dialog"/>
<label id="label_email_confirm" proportion="1" height="100%" text_align="left"
I18N="In the registration dialog" text="Confirm"/>
<textbox id="email_confirm" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="50"/>
@ -66,7 +70,7 @@
<buttonbar id="options" width="25%" height="14%" align="center">
<icon-button id="next" width="64" height="64" icon="gui/green_check.png"
I18N="Registration dialog" text="Next" label_location="none"/>
I18N="Registration dialog" text="OK" label_location="none"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Registration dialog" text="Cancel" label_location="none"/>
</buttonbar>

View File

@ -39,6 +39,12 @@
<label height="100%" I18N="In the ui settings" text="Allow STK to connect to the Internet"/>
</div>
<div width="75%" height="fit" layout="horizontal-row" >
<checkbox id="show-login"/>
<spacer width="20" height="100%" />
<label height="100%" I18N="In the ui settings" text="Always show login screen"/>
</div>
<spacer height="18" width="4"/>
<!-- ************ LANGUAGE CHOICE ************ -->

View File

@ -1,28 +0,0 @@
<stkgui>
<div x="2%" y="2%" width="96%" height="97%" layout="vertical-row" >
<header text_align="center" width="80%" align="center" text="Select a Player"/>
<spacer height="15" width="10"/>
<box proportion="6" width="75%" align="center" layout="vertical-row" padding="8">
<list id="gameslots" x="0" y="0" width="100%" height="100%"/>
</box>
<spacer width="20" height="25"/>
<div layout="horizontal-row" align="center" width="70%" height="fit">
<checkbox id="rememberme" />
<label text="Remember me" height="100%"/>
</div>
<spacer width="20" height="15"/>
<button id="creategame" x="20"
I18N="In story mode 'select a game slot' menu"
text="Create a new player" align="center"/>
<spacer width="20" height="15"/>
</div>
</stkgui>

View File

@ -1,36 +0,0 @@
<stkgui>
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
<header width="80%" text="New Game" align="center" text_align="center" />
<spacer proportion="1" width="25"/>
<div layout="horizontal-row" width="100%" height="50" align="center">
<label proportion="1" height="100%"
I18N="In the new story mode game dialog" text="Select your identity" text_align="right" />
<spacer width="50" height="25"/>
<spinner id="identity" proportion="1" height="100%" min_value="0" wrap_around="true"/>
</div>
<spacer proportion="1" width="25"/>
<ribbon id="difficulty" height="135" width="85%" align="center">
<icon-button id="novice" width="128" height="128" icon="gui/difficulty_easy.png"
I18N="Difficulty" text="Novice"/>
<icon-button id="intermediate" width="128" height="128" icon="gui/difficulty_medium.png"
I18N="Difficulty" text="Intermediate"/>
<icon-button id="expert" width="128" height="128" icon="gui/difficulty_hard.png"
I18N="Difficulty" text="Expert"/>
</ribbon>
<spacer width="25" proportion="1"/>
<button id="startgame" text="Start Game" align="center"/>
<spacer width="25" height="5"/>
<button id="cancel" text="Cancel" align="center"/>
</div>
</stkgui>

View File

@ -0,0 +1,65 @@
<stkgui>
<div x="1%" y="1%" width="98%" height="98%" layout="vertical-row" >
<header align="center" width="80%" text="Login" text_align="center"/>
<spacer height="15" width="10"/>
<box proportion="1" width="98%" layout="vertical-row">
<spacer height="15" width="10"/>
<scrollable_ribbon id="players" height="120" y="10" x="10" width="98%" align="center" label_location="each"
square_items="true" child_width="160" child_height="120" />
<spacer height="15" width="10"/>
<div width="80%" align="center" layout="vertical-row" height="fit">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
<checkbox id="online" I18N="In the login screen" text_align="left"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_remember" proportion="1" height="100%" text_align="left"
I18N="In the login screen" text="Remember password"/>
<checkbox id="remember-user" I18N="In the login screen" text_align="left"/>
</div>
<!-- Disable guest accounts for now
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_guest" proportion="1" height="100%" text_align="left"
I18N="In the login screen" text="Guest login"/>
<checkbox id="guest" I18N="In the login screen" text_align="left"/>
</div>
-->
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_username" proportion="1" height="100%" text_align="left"
I18N="In the login screen" text="Username"/>
<textbox id="username" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_password" proportion="1" height="100%" text_align="left"
I18N="In the registration dialog" text="Password"/>
<textbox id="password" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
</div>
<div width="80%" align="center" layout="vertical-row" height="fit">
<label id="message" width="80%" align="center" text_align="left"/>
</div>
<spacer width="20" height="25"/>
<buttonbar id="options" width="90%" height="13%" align="bottom">
<icon-button id="ok" width="64" height="64" icon="gui/green_check.png"
I18N="Login dialog" text="OK" label_location="bottom"/>
<icon-button id="new_user" width="64" height="64" icon="gui/gp_add_track.png"
I18N="Login dialog" text="Add user" label_location="bottom"/>
<icon-button id="delete" width="64" height="64" icon="gui/gp_remove_track.png"
I18N="Login dialog" text="Delete" label_location="bottom"/>
<icon-button id="rename" width="64" height="64" icon="gui/gp_rename.png"
I18N="Login dialog" text="Rename" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Login dialog" text="Cancel" label_location="bottom"/>
</buttonbar>
</box>
<spacer width="20" height="15"/>
</div>
</stkgui>

View File

@ -0,0 +1,74 @@
<stkgui>
<div x="1%" y="1%" width="98%" height="98%" layout="vertical-row" >
<header text_align="center" width="80%" align="center" text="SuperTuxKart Options"/>
<spacer height="15" width="10"/>
<tabs id="options_choice" height="10%" max_height="110" x="2%" width="98%" align="center">
<icon-button id="tab_video" width="128" height="128" icon="gui/options_video.png"/>
<icon-button id="tab_audio" width="128" height="128" icon="gui/options_audio.png"/>
<icon-button id="tab_ui" width="128" height="128" icon="gui/options_ui.png"/>
<icon-button id="tab_players" width="128" height="128" icon="gui/options_players.png"
I18N="Section in the settings menu" text="Players"/>
<icon-button id="tab_controls" width="128" height="128" icon="gui/options_input.png"/>
</tabs>
<box proportion="1" width="98%" layout="vertical-row">
<spacer height="15" width="10"/>
<scrollable_ribbon id="players" height="120" y="10" x="10" width="98%" align="center" label_location="each"
square_items="true" child_width="160" child_height="120" />
<spacer height="15" width="10"/>
<div width="80%" align="center" layout="vertical-row" height="fit">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
<checkbox id="online" I18N="In the login screen" text_align="left"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_remember" proportion="1" height="100%" text_align="left"
I18N="In the login screen" text="Remember password"/>
<checkbox id="remember-user" I18N="In the login screen" text_align="left"/>
</div>
<!-- Disable guest accounts for now
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_guest" proportion="1" height="100%" text_align="left"
I18N="In the login screen" text="Guest login"/>
<checkbox id="guest" I18N="In the login screen" text_align="left"/>
</div>
-->
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_username" proportion="1" height="100%" text_align="left"
I18N="In the login screen" text="Username"/>
<textbox id="username" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_password" proportion="1" height="100%" text_align="left"
I18N="In the registration dialog" text="Password"/>
<textbox id="password" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
</div>
<div width="80%" align="center" layout="vertical-row" height="fit">
<label id="message" width="80%" align="center" text_align="left"/>
</div>
<spacer width="20" height="25"/>
<buttonbar id="options" width="90%" height="13%" align="bottom">
<icon-button id="ok" width="64" height="64" icon="gui/green_check.png"
I18N="Login dialog" text="OK" label_location="bottom"/>
<icon-button id="new_user" width="64" height="64" icon="gui/gp_add_track.png"
I18N="Login dialog" text="Add user" label_location="bottom"/>
<icon-button id="delete" width="64" height="64" icon="gui/gp_remove_track.png"
I18N="Login dialog" text="Delete" label_location="bottom"/>
<icon-button id="rename" width="64" height="64" icon="gui/gp_rename.png"
I18N="Login dialog" text="Rename" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Login dialog" text="Cancel" label_location="bottom"/>
</buttonbar>
</box>
<spacer width="20" height="15"/>
</div>
</stkgui>

View File

@ -55,7 +55,7 @@
from BurningWell.
* zipper_collect
by Dakal, released under CC-BY-SA 3.0
by Connor, released as Public Domain
* rubber_ball and jump-bomb.jpg
by Samuncle, released under CC-BY-SA

View File

@ -2,34 +2,22 @@
<materials>
<material name="banana.png"/>
<material name="gift-box.png"/>
<material name="gift-loop.png" sphere="Y"/>
<material name="gold.png" light="Y" smooth-reflection="Y"/>
<material name="silver.png" light="Y" smooth-reflection="Y"/>
<material name="bronze.png" light="Y" smooth-reflection="Y"/>
<material name="gift-loop.png" shader="spheremap"/>
<material name="gold.png" light="Y" shader="spheremap"/>
<material name="silver.png" light="Y" shader="spheremap"/>
<material name="bronze.png" light="Y" shader="spheremap"/>
<material name="stk_mod_nitroBarrel.png" />
<material name="stk_mod_nitroBottle.png" />
<material name="stk_mod_nitroLogo.png" compositing="additive" light="N" disable-z-write="Y" />
<material name="stk_mod_nitroLogo.png" shader="additive" disable-z-write="Y" />
<material name="traffic_light_green.jpg" light="N"/>
<material name="traffic_light_yellow.jpg" light="N"/>
<material name="traffic_light_red.jpg" light="N"/>
<material name="traffic_light_green.jpg" shader="unlit"/>
<material name="traffic_light_yellow.jpg" shader="unlit"/>
<material name="traffic_light_red.jpg" shader="unlit"/>
<material name="bubblegum_shield.png" compositing="blend" disable-z-write="Y"/>
<material name="bubblegum_shield_nolok.png" compositing="blend" disable-z-write="Y"/>
<material name="bubblegum_shield.png" shader="alphablend" disable-z-write="Y"/>
<material name="bubblegum_shield_nolok.png" shader="alphablend" disable-z-write="Y"/>
<material name="parachute.png" backface-culling="n" ignore="Y"/>
<material name="zipper.png" light="N" zipper="Y"/>
<material name="zipper_collect.png" light="N" zipper="Y"/>
<material name="bowling-icon.png" transparency="Y" light="N"/>
<material name="bubblegum-icon.png" transparency="Y" light="N"/>
<material name="cake-icon.png" transparency="Y" light="N" />
<material name="anchor-icon.png" clampU="Y" clampV="Y" transparency="Y" light="N" ignore="Y"/>
<material name="plunger-icon.png" transparency="Y" light="N"/>
<material name="parachute-icon.png" clampU="Y" clampV="Y" ignore="Y"/>
<material name="anchor-attach-icon.png" clampU="Y" clampV="Y" transparency="Y" light="N" ignore="Y"/>
<material name="parachute-attach-icon.png" clampU="Y" clampV="Y" ignore="Y"/>
<material name="bomb-attach-icon.png" clampU="Y" clampV="Y" ignore="Y"/>
<material name="balldimpleddark.jpg"/>
<material name="zipper.png" shader="unlit" zipper="Y"/>
</materials>

Binary file not shown.

Before

(image error) Size: 12 KiB

After

(image error) Size: 7.0 KiB

101
data/shaders/gi.frag Normal file
View File

@ -0,0 +1,101 @@
// From http://graphics.cs.aueb.gr/graphics/research_illumination.html
// "Real-Time Diffuse Global Illumination Using Radiance Hints"
// paper and shader code
uniform sampler2D ntex;
uniform sampler2D dtex;
uniform sampler3D SHR;
uniform sampler3D SHG;
uniform sampler3D SHB;
uniform float R_wcs = 10.;
uniform vec3 extents;
uniform mat4 RHMatrix;
layout (std140) uniform MatrixesData
{
mat4 ViewMatrix;
mat4 ProjectionMatrix;
mat4 InverseViewMatrix;
mat4 InverseProjectionMatrix;
mat4 ShadowViewProjMatrixes[4];
vec2 screen;
};
vec4 SHBasis (const in vec3 dir)
{
float L00 = 0.282095;
float L1_1 = 0.488603 * dir.y;
float L10 = 0.488603 * dir.z;
float L11 = 0.488603 * dir.x;
return vec4 (L11, L1_1, L10, L00);
}
vec3 SH2RGB (in vec4 sh_r, in vec4 sh_g, in vec4 sh_b, in vec3 dir)
{
vec4 Y = vec4(1.023326*dir.x, 1.023326*dir.y, 1.023326*dir.z, 0.886226);
return vec3 (dot(Y,sh_r), dot(Y,sh_g), dot(Y,sh_b));
}
in vec2 uv;
layout (location = 0) out vec4 Diffuse;
layout (location = 1) out vec4 Specular;
vec3 DecodeNormal(vec2 n);
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
vec3 resolution = vec3(32, 16, 32);
void main()
{
vec3 GI = vec3(0.);
float depth = texture2D(dtex, uv).x;
// Discard background fragments
if (depth==1.0) discard;
vec4 pos_screen_space = getPosFromUVDepth(vec3(uv, depth), InverseProjectionMatrix);
vec4 tmp = (inverse(RHMatrix) * InverseViewMatrix * pos_screen_space);
vec3 pos = tmp.xyz / tmp.w;
vec3 normal_screen_space = normalize(DecodeNormal(2. * texture(ntex, uv).xy - 1.));
vec3 normal = (transpose(ViewMatrix) * vec4(normal_screen_space, 0.)).xyz;
// Convert to grid coordinates
vec3 uvw = .5 + 0.5 * pos / extents;
if (uvw.x < 0. || uvw.x > 1. || uvw.y < 0. || uvw.y > 1. || uvw.z < 0. || uvw.z > 1.) discard;
// Sample the RH volume at 4 locations, one directly above the shaded point,
// three on a ring 80degs away from the normal direction.
vec3 rnd = vec3(0,0,0);
// Generate the sample locations
vec3 v_rand = vec3(0.5);
vec3 tangent = normalize(cross(normal, v_rand));
vec3 bitangent = cross(normal, tangent);
vec3 D[4];
D[0] = vec3(1.0,0.0,0.0);
int i;
for (i=1; i<4; i++)
{
D[i] = vec3(0.1, 0.8*cos((rnd.x*1.5+i)*6.2832/3.0), 0.8*sin((rnd.x*1.5+i)*6.2832/3.0));
D[i] = normalize(D[i]);
}
for (i=0; i<4; i++)
{
vec3 SampleDir = normal * D[i].x + tangent * D[i].y + bitangent *D[i].z;
vec3 SampleOffset = (0.5 * normal + SampleDir) / resolution;
vec3 uvw_new = uvw + SampleOffset;
vec4 IncidentSHR = texture(SHR, uvw_new);
vec4 IncidentSHG = texture(SHG, uvw_new);
vec4 IncidentSHB = texture(SHB, uvw_new);
GI += SH2RGB(IncidentSHR, IncidentSHG, IncidentSHB, -normal);
}
GI /= 4;
Diffuse = max(16. * vec4(GI, 1.), vec4(0.));
Specular = vec4(0.);
}

View File

@ -29,6 +29,6 @@ void main(void)
vec4 color = texture(Albedo, uv);
if (color.a < 0.5) discard;
vec3 LightFactor = scattering + getLightFactor(1.);
vec3 LightFactor = (scattering * 0.3) + getLightFactor(1.);
FragColor = vec4(color.xyz * LightFactor, 1.);
}

96
data/shaders/rh.frag Normal file
View File

@ -0,0 +1,96 @@
// From http://graphics.cs.aueb.gr/graphics/research_illumination.html
// "Real-Time Diffuse Global Illumination Using Radiance Hints"
// paper and shader code
uniform float R_wcs = 10.; // Rmax: maximum sampling distance (in WCS units)
uniform vec3 extents;
uniform mat4 RHMatrix;
uniform mat4 RSMMatrix;
uniform sampler2D dtex;
uniform sampler2D ctex;
uniform sampler2D ntex;
flat in int slice;
layout (location = 0) out vec4 SHRed;
layout (location = 1) out vec4 SHGreen;
layout (location = 2) out vec4 SHBlue;
vec3 resolution = vec3(32, 16, 32);
#define SAMPLES 16
vec4 SHBasis (const in vec3 dir)
{
float L00 = 0.282095;
float L1_1 = 0.488603 * dir.y;
float L10 = 0.488603 * dir.z;
float L11 = 0.488603 * dir.x;
return vec4 (L11, L1_1, L10, L00);
}
vec4 DirToSh(vec3 dir, float flux)
{
return SHBasis (dir) * flux;
}
void main(void)
{
vec3 normalizedRHCenter = 2. * vec3(gl_FragCoord.xy, slice) / resolution - 1.;
vec3 RHcenter = (RHMatrix * vec4(normalizedRHCenter * extents, 1.)).xyz;
vec4 ShadowProjectedRH = RSMMatrix * vec4(RHcenter, 1.);
vec3 RHCellSize = extents / resolution;
vec2 RHuv = .5 * ShadowProjectedRH.xy / ShadowProjectedRH.w + .5;
float RHdepth = .5 * ShadowProjectedRH.z / ShadowProjectedRH.w + .5;
vec4 SHr = vec4(0.);
vec4 SHg = vec4(0.);
vec4 SHb = vec4(0.);
int x = int(gl_FragCoord.x), y = int(gl_FragCoord.y);
float phi = 30. * (x ^ y) + 10. * x * y;
for (int i = 0; i < SAMPLES; i++)
{
// produce a new sample location on the RSM texture
float alpha = (i + .5) / SAMPLES;
float theta = 2. * 3.14 * 7. * alpha;
float h = alpha;
vec2 offset = h * vec2(cos(theta), sin(theta));
vec2 uv = RHuv + offset * 0.01;
// Get world position and normal from the RSM sample
float depth = texture2D(dtex, uv).z;
vec4 RSMPos = inverse(RSMMatrix) * (2. * vec4(uv, depth, 1.) - 1.);
RSMPos /= RSMPos.w;
vec3 RSMAlbedo = texture(ctex, uv).xyz;
vec3 normal = normalize(2. * texture(ntex, uv).xyz - 1.);
// Sampled location inside the RH cell
vec3 offset3d = vec3(uv, 0);
vec3 SamplePos = RHcenter + .5 * offset3d.xzy * RHCellSize;
// Normalize distance to RSM sample
float dist = distance(SamplePos, RSMPos.xyz) / R_wcs;
// Determine the incident direction.
// Avoid very close samples (and numerical instability problems)
vec3 RSM_to_RH_dir = (dist <= 0.00) ? vec3(0.) : normalize(SamplePos - RSMPos.xyz);
float dotprod = max(dot(RSM_to_RH_dir, normal.xyz), 0.);
float factor = dotprod / (0.1 + dist * dist);
vec3 color = RSMAlbedo.rgb * factor;
SHr += DirToSh(RSM_to_RH_dir, color.r);
SHg += DirToSh(RSM_to_RH_dir, color.g);
SHb += DirToSh(RSM_to_RH_dir, color.b);
}
SHr /= 3.14159 * SAMPLES;
SHg /= 3.14159 * SAMPLES;
SHb /= 3.14159 * SAMPLES;
SHRed = SHr;
SHGreen = SHg;
SHBlue = SHb;
}

14
data/shaders/rhdebug.frag Normal file
View File

@ -0,0 +1,14 @@
uniform sampler3D SHR;
uniform sampler3D SHG;
uniform sampler3D SHB;
in vec3 uvw;
out vec4 FragColor;
void main()
{
float r = texture(SHR, uvw).w;
float g = texture(SHG, uvw).w;
float b = texture(SHB, uvw).w;
FragColor = max(vec4(r, g, b, 1.0), vec4(0.));
}

30
data/shaders/rhdebug.vert Normal file
View File

@ -0,0 +1,30 @@
uniform vec3 extents;
layout (std140) uniform MatrixesData
{
mat4 ViewMatrix;
mat4 ProjectionMatrix;
mat4 InverseViewMatrix;
mat4 InverseProjectionMatrix;
mat4 ShadowViewProjMatrixes[4];
vec2 screen;
};
uniform mat4 RHMatrix;
ivec3 resolution = ivec3(32, 16, 32);
out vec3 uvw;
void main(void)
{
// Determine the RH center
float gx = int(gl_VertexID) & (resolution.x - 1);
float gy = int(gl_VertexID >> 5) & (resolution.y - 1);
float gz = int(gl_VertexID >> 9) & (resolution.z - 1);
uvw = vec3(gx, gy, gz) / vec3(resolution);
vec3 WorldPos = (2. * uvw - 1.) * extents;
gl_Position = ProjectionMatrix * ViewMatrix * RHMatrix * vec4(WorldPos, 1.);
gl_PointSize = 100. / gl_Position.w;
}

View File

@ -0,0 +1,20 @@
layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;
in int layer[3];
in vec2 uv_in[3];
flat out int slice;
out vec2 uv;
void main(void)
{
gl_Layer = layer[0];
for(int i=0; i<3; i++)
{
slice = layer[0];
uv = uv_in[i];
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}

12
data/shaders/rsm.frag Normal file
View File

@ -0,0 +1,12 @@
uniform sampler2D tex;
in vec2 uv;
in vec3 nor;
layout (location = 0) out vec3 RSMColor;
layout (location = 1) out vec3 RSMNormals;
void main()
{
RSMColor = texture(tex, uv).xyz;
RSMNormals = .5 * normalize(nor) + .5;
}

26
data/shaders/rsm.vert Normal file
View File

@ -0,0 +1,26 @@
uniform mat4 ModelMatrix;
uniform mat4 InverseModelMatrix;
uniform mat4 RSMMatrix;
uniform mat4 TextureMatrix =
mat4(1., 0., 0., 0.,
0., 1., 0., 0.,
0., 0., 1., 0.,
0., 0., 0., 1.);
in vec3 Position;
in vec2 Texcoord;
in vec3 Normal;
out vec3 nor;
out vec2 uv;
void main(void)
{
mat4 ModelViewProjectionMatrix = RSMMatrix * ModelMatrix;
mat4 TransposeInverseModel = transpose(InverseModelMatrix);
gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.);
nor = (vec4(Normal, 0.)).xyz;
uv = (TextureMatrix * vec4(Texcoord, 1., 1.)).xy;
}

View File

@ -0,0 +1,24 @@
in vec2 Position;
in vec2 Texcoord;
#ifndef VSLayer
out int layer;
out vec2 uv_in;
#else
out vec2 uv;
flat out int slice;
#endif
void main() {
#ifdef VSLayer
gl_Layer = gl_InstanceID;
uv = Texcoord;
slice = gl_InstanceID;
#else
layer = gl_InstanceID;
uv_in = Texcoord;
#endif
gl_Position = vec4(Position, 0., 1.);
}

View File

@ -25,6 +25,8 @@ Note that checkboxes are an exception and have the following styles :
"neutral+checked"
"focused+unchecked"
"focused+checked"
"deactivated+unchecked"
"deactivated+checked"
"Advanced stretching" images are split this way :
@ -66,11 +68,15 @@ when the border that intersect at this corner are enabled.
<!-- Stateless -->
<element type="background" image="ocean/background.jpg" />
<element type="button" state="neutral" image="ocean/glassbutton.png"
left_border="13" right_border="13" top_border="13" bottom_border="13"
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
<element type="button" state="focused" image="ocean/glassbutton_focused.png"
left_border="13" right_border="13" top_border="13" bottom_border="13"
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
<element type="button" state="neutral" image="ocean/glassbutton.png"
<element type="button" state="deactivated" image="ocean/glassbutton_deactivated.png"
left_border="13" right_border="13" top_border="13" bottom_border="13"
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
@ -131,6 +137,10 @@ when the border that intersect at this corner are enabled.
left_border="110" right_border="110" top_border="0" bottom_border="36"
preserve_h_aspect_ratios="true" hborder_out_portion="0.0" />
<element type="spinner" state="deactivated" image="ocean/glassspinner_deactivated.png"
left_border="110" right_border="110" top_border="0" bottom_border="36"
preserve_h_aspect_ratios="true" hborder_out_portion="0.0" />
<!-- player name spinner color in multiplayer-->
<element type="spinner1" state="neutral" image="ocean/glass_square1.png"
left_border="110" right_border="110" top_border="0" bottom_border="36"
@ -157,6 +167,8 @@ when the border that intersect at this corner are enabled.
<element type="checkbox" state="neutral+checked" image="ocean/glasscheckbox_checked.png"/>
<element type="checkbox" state="focused+unchecked" image="ocean/glasscheckbox_focus.png"/>
<element type="checkbox" state="focused+checked" image="ocean/glasscheckbox_checked_focus.png"/>
<element type="checkbox" state="deactivated+unchecked" image="ocean/glasscheckbox_deactivated.png"/>
<element type="checkbox" state="deactivated+checked" image="ocean/glasscheckbox_checked_deactivated.png"/>
<!-- are always in neutral state for now. No splitting into 9 areas is done; the image is just stretched.
Note: the body of a guage is the same as for for spinners. -->

View File

@ -25,6 +25,8 @@ Note that checkboxes are an exception and have the following styles :
"neutral+checked"
"focused+unchecked"
"focused+checked"
"deactivated+unchecked"
"deactivated+checked"
"Advanced stretching" images are split this way :
@ -66,11 +68,15 @@ when the border that intersect at this corner are enabled.
<!-- Stateless -->
<element type="background" image="peach/background.jpg" />
<element type="button" state="neutral" image="peach/glassbutton.png"
left_border="13" right_border="13" top_border="13" bottom_border="13"
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
<element type="button" state="focused" image="peach/glassbutton_focused.png"
left_border="13" right_border="13" top_border="13" bottom_border="13"
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
<element type="button" state="neutral" image="peach/glassbutton.png"
<element type="button" state="deactivated" image="peach/glassbutton_deactivated.png"
left_border="13" right_border="13" top_border="13" bottom_border="13"
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
@ -132,6 +138,10 @@ when the border that intersect at this corner are enabled.
left_border="110" right_border="110" top_border="0" bottom_border="36"
preserve_h_aspect_ratios="true" hborder_out_portion="0.0" />
<element type="spinner" state="deactivated" image="peach/glassspinner_deactivated.png"
left_border="110" right_border="110" top_border="0" bottom_border="36"
preserve_h_aspect_ratios="true" hborder_out_portion="0.0" />
<element type="spinner1" state="neutral" image="peach/glass_square1.png"
left_border="110" right_border="110" top_border="0" bottom_border="36"
preserve_h_aspect_ratios="true" hborder_out_portion="0.0" />
@ -156,6 +166,8 @@ when the border that intersect at this corner are enabled.
<element type="checkbox" state="neutral+checked" image="peach/glasscheckbox_checked.png"/>
<element type="checkbox" state="focused+unchecked" image="peach/glasscheckbox_focus.png"/>
<element type="checkbox" state="focused+checked" image="peach/glasscheckbox_checked_focus.png"/>
<element type="checkbox" state="deactivated+unchecked" image="peach/glasscheckbox_deactivated.png"/>
<element type="checkbox" state="deactivated+checked" image="peach/glasscheckbox_checked_deactivated.png"/>
<!-- are always in neutral state for now. No splitting into 9 areas is done; the image is just stretched.
Note: the body of a guage is the same as for for spinners. -->

Binary file not shown.

After

(image error) Size: 7.4 KiB

Binary file not shown.

After

(image error) Size: 2.3 KiB

Binary file not shown.

After

(image error) Size: 2.0 KiB

Binary file not shown.

After

(image error) Size: 9.6 KiB

Binary file not shown.

After

(image error) Size: 7.4 KiB

Binary file not shown.

After

(image error) Size: 2.3 KiB

Binary file not shown.

After

(image error) Size: 2.0 KiB

Binary file not shown.

After

(image error) Size: 9.6 KiB

View File

@ -273,7 +273,7 @@ bool CIrrDeviceLinux::switchToFullscreen(bool reset)
{
if (bestMode==-1 && modes[i]->hdisplay >= Width && modes[i]->vdisplay >= Height)
{
float pixels_per_second = modes[i]->dotclock * 1000.0;
float pixels_per_second = modes[i]->dotclock * 1000.0;
float pixels_per_frame = modes[i]->htotal * modes[i]->vtotal;
refresh_rate = pixels_per_second / pixels_per_frame;
bestMode = i;
@ -282,15 +282,15 @@ bool CIrrDeviceLinux::switchToFullscreen(bool reset)
modes[i]->hdisplay == modes[bestMode]->hdisplay &&
modes[i]->vdisplay == modes[bestMode]->vdisplay)
{
float pixels_per_second = modes[i]->dotclock * 1000.0;
float pixels_per_second = modes[i]->dotclock * 1000.0;
float pixels_per_frame = modes[i]->htotal * modes[i]->vtotal;
float refresh_rate_tmp = pixels_per_second / pixels_per_frame;
if (refresh_rate_tmp > refresh_rate)
{
refresh_rate = refresh_rate_tmp;
bestMode = i;
}
}
}
else if (bestMode!=-1 &&
modes[i]->hdisplay >= Width &&
@ -298,7 +298,7 @@ bool CIrrDeviceLinux::switchToFullscreen(bool reset)
modes[i]->hdisplay <= modes[bestMode]->hdisplay &&
modes[i]->vdisplay <= modes[bestMode]->vdisplay)
{
float pixels_per_second = modes[i]->dotclock * 1000.0;
float pixels_per_second = modes[i]->dotclock * 1000.0;
float pixels_per_frame = modes[i]->htotal * modes[i]->vtotal;
refresh_rate = pixels_per_second / pixels_per_frame;
bestMode = i;
@ -746,8 +746,21 @@ bool CIrrDeviceLinux::createWindow()
if (!CreationParams.WindowId)
{
Atom *list;
Atom type;
int form;
unsigned long remain, len;
Atom WMCheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", false);
Status s = XGetWindowProperty(display, DefaultRootWindow(display),
WMCheck, 0L, 1L, False, XA_WINDOW,
&type, &form, &len, &remain,
(unsigned char **)&list);
bool netWM = (s == Success) && len;
attributes.override_redirect = !netWM && CreationParams.Fullscreen;
// create new Window
attributes.override_redirect = false;
window = XCreateWindow(display,
RootWindow(display, visual->screen),
0, 0, Width, Height, 0, visual->depth,
@ -762,31 +775,45 @@ bool CIrrDeviceLinux::createWindow()
if (CreationParams.Fullscreen)
{
// Workaround for Gnome which sometimes creates window smaller than display
XSizeHints *hints = XAllocSizeHints();
hints->flags=PMinSize;
hints->min_width=Width;
hints->min_height=Height;
XSetWMNormalHints(display, window, hints);
XFree(hints);
if (netWM)
{
// Workaround for Gnome which sometimes creates window smaller than display
XSizeHints *hints = XAllocSizeHints();
hints->flags=PMinSize;
hints->min_width=Width;
hints->min_height=Height;
XSetWMNormalHints(display, window, hints);
XFree(hints);
// Set the fullscreen mode via the window manager. This allows alt-tabing, volume hot keys & others.
// Get the needed atom from there freedesktop names
Atom WMStateAtom = XInternAtom(display, "_NET_WM_STATE", true);
Atom WMFullscreenAtom = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", true);
// Set the fullscreen property
XChangeProperty(display, window, WMStateAtom, XA_ATOM, 32, PropModeReplace, reinterpret_cast<unsigned char *>(& WMFullscreenAtom), 1);
// Notify the root window
XEvent xev = {0}; // The event should be filled with zeros before setting its attributes
xev.type = ClientMessage;
xev.xclient.window = window;
xev.xclient.message_type = WMStateAtom;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 1;
xev.xclient.data.l[1] = WMFullscreenAtom;
XSendEvent(display, DefaultRootWindow(display), false, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
// Set the fullscreen mode via the window manager. This allows alt-tabing, volume hot keys & others.
// Get the needed atom from there freedesktop names
Atom WMStateAtom = XInternAtom(display, "_NET_WM_STATE", true);
Atom WMFullscreenAtom = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", true);
// Set the fullscreen property
XChangeProperty(display, window, WMStateAtom, XA_ATOM, 32, PropModeReplace, reinterpret_cast<unsigned char *>(& WMFullscreenAtom), 1);
// Notify the root window
XEvent xev = {0}; // The event should be filled with zeros before setting its attributes
xev.type = ClientMessage;
xev.xclient.window = window;
xev.xclient.message_type = WMStateAtom;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 1;
xev.xclient.data.l[1] = WMFullscreenAtom;
XSendEvent(display, DefaultRootWindow(display), false, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}
else
{
XSetInputFocus(display, window, RevertToParent, CurrentTime);
int grabKb = XGrabKeyboard(display, window, True, GrabModeAsync,
GrabModeAsync, CurrentTime);
IrrPrintXGrabError(grabKb, "XGrabKeyboard");
int grabPointer = XGrabPointer(display, window, True, ButtonPressMask,
GrabModeAsync, GrabModeAsync, window, None, CurrentTime);
IrrPrintXGrabError(grabPointer, "XGrabPointer");
XWarpPointer(display, None, window, 0, 0, 0, 0, 0, 0);
}
}
}
else

View File

@ -297,33 +297,6 @@ public:
return true;
} // operator<
// ------------------------------------------------------------------------
/** Compares two addons according to the sort order currently defined.
* Comparison is done for sorting in descending order.
* \param a The addon to compare this addon to.
*/
bool operator>(const Addon &a) const
{
switch(m_sort_order)
{
case SO_DEFAULT:
if(testStatus(AS_FEATURED) &&
!a.testStatus(AS_FEATURED)) return true;
if(!testStatus(AS_FEATURED) &&
a.testStatus(AS_FEATURED)) return false;
// Otherwise fall through to name comparison!
case SO_NAME:
// m_id is the lower case name
return m_id > a.m_id;
break;
case SO_DATE:
return m_date < a.m_date;
break;
} // switch
// Fix compiler warning.
return true;
} // operator>
}; // Addon

View File

@ -20,6 +20,7 @@
#include "achievements/achievements_manager.hpp"
#include "config/player_profile.hpp"
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include "io/utf_writer.hpp"
#include "io/xml_node.hpp"
@ -38,12 +39,6 @@ void PlayerManager::create()
{
assert(!m_player_manager);
m_player_manager = new PlayerManager();
if(m_player_manager->getNumPlayers() == 0)
{
m_player_manager->addDefaultPlayer();
m_player_manager->save();
}
} // create
// ----------------------------------------------------------------------------
@ -120,7 +115,8 @@ void PlayerManager::resumeSavedSession()
*/
void PlayerManager::onSTKQuit()
{
getCurrentPlayer()->onSTKQuit();
if (getCurrentPlayer() && getCurrentPlayer()->isLoggedIn())
getCurrentPlayer()->requestSignOut();
} // onSTKQuit
// ----------------------------------------------------------------------------
@ -134,12 +130,9 @@ void PlayerManager::onSTKQuit()
*/
Online::XMLRequest *PlayerManager::requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password,
bool save_session,
bool request_now)
const irr::core::stringw &password)
{
return getCurrentPlayer()->requestSignIn(username, password, save_session,
request_now);
return getCurrentPlayer()->requestSignIn(username, password);
} // requestSignIn
// ----------------------------------------------------------------------------
@ -173,7 +166,18 @@ PlayerManager::PlayerManager()
*/
PlayerManager::~PlayerManager()
{
// If the passwords should not be remembered, clear all saved sessions.
if(!UserConfigParams::m_remember_user)
{
PlayerProfile *player;
for_in(player, m_all_players)
{
player->clearSession();
}
}
save();
} // ~PlayerManager
// ----------------------------------------------------------------------------
@ -197,14 +201,21 @@ void PlayerManager::load()
return;
}
m_current_player = NULL;
for(unsigned int i=0; i<m_player_data->getNumNodes(); i++)
std::vector<XMLNode*> player_list;
m_player_data->getNodes("player", player_list);
for(unsigned int i=0; i<player_list.size(); i++)
{
const XMLNode *player_xml = m_player_data->getNode(i);
const XMLNode *player_xml = player_list[i];
PlayerProfile *player = new Online::OnlinePlayerProfile(player_xml);
m_all_players.push_back(player);
if(player->isDefault())
m_current_player = player;
}
m_current_player = NULL;
const XMLNode *current = m_player_data->getNode("current");
if(current)
{
stringw name;
current->get("player", &name);
m_current_player = getPlayer(name);
}
} // load
@ -218,6 +229,12 @@ void PlayerManager::load()
*/
void PlayerManager::initRemainingData()
{
// Filter the player nodes out (there is one additional node 'online-ids'
// which makes this necessary), otherwise the index of m_all_players
// is not identical with the index in the xml file.
std::vector<XMLNode*> player_nodes;
if(m_player_data)
m_player_data->getNodes("player", player_nodes);
for (unsigned int i = 0; i<m_all_players.size(); i++)
{
// On the first time STK is run, there is no player data,
@ -226,7 +243,7 @@ void PlayerManager::initRemainingData()
if (!m_player_data)
m_all_players[i].initRemainingData();
else // not a first time start, load remaining data
m_all_players[i].loadRemainingData(m_player_data->getNode(i));
m_all_players[i].loadRemainingData(player_nodes[i]);
}
delete m_player_data;
@ -249,6 +266,12 @@ void PlayerManager::save()
players_file << L"<?xml version=\"1.0\"?>\n";
players_file << L"<players version=\"1\" >\n";
if(m_current_player && UserConfigParams::m_remember_user)
{
players_file << L" <current player=\""
<< m_current_player->getName() << L"\"/>\n";
}
PlayerProfile *player;
for_in(player, m_all_players)
{
@ -270,9 +293,11 @@ void PlayerManager::save()
/** Adds a new player to the list of all players.
* \param name Name of the new player.
*/
void PlayerManager::addNewPlayer(const core::stringw& name)
PlayerProfile* PlayerManager::addNewPlayer(const core::stringw& name)
{
m_all_players.push_back( new Online::OnlinePlayerProfile(name) );
PlayerProfile *profile = new Online::OnlinePlayerProfile(name);
m_all_players.push_back(profile);
return profile;
} // addNewPlayer
// ----------------------------------------------------------------------------
@ -281,6 +306,8 @@ void PlayerManager::addNewPlayer(const core::stringw& name)
void PlayerManager::deletePlayer(PlayerProfile *player)
{
m_all_players.erase(player);
if(player==m_current_player)
m_current_player = NULL;
} // deletePlayer
// ----------------------------------------------------------------------------
@ -315,7 +342,7 @@ void PlayerManager::enforceCurrentPlayer()
if (!player->isGuestAccount())
{
Log::info("PlayerManager", "Enfocring current player '%s'.",
player->getName().c_str());
player->getName().c_str());
m_current_player = player;
return;
}
@ -350,6 +377,20 @@ void PlayerManager::addDefaultPlayer()
m_all_players.push_back(new Online::OnlinePlayerProfile(_LTR("Guest"), /*guest*/true));
} // addDefaultPlayer
// ----------------------------------------------------------------------------
/** Returns the number of 'real' (non-guest) players.
*/
unsigned int PlayerManager::getNumNonGuestPlayers() const
{
unsigned int count=0;
const PlayerProfile *player;
for_in(player, m_all_players)
{
if(!player->isGuestAccount()) count ++;
}
return count;
} // getNumNonGuestPlayers
// ----------------------------------------------------------------------------
/** This returns a unique id. This is 1 + largest id used so far.
*/
@ -399,24 +440,15 @@ PlayerProfile *PlayerManager::getPlayer(const irr::core::stringw &name)
} // getPlayer
// ----------------------------------------------------------------------------
/** Sets the current player. This is the player that is used for story mode
* and achievements. If 'remember_me' is set, this information will be
* stored in the players.xml file, and automatically loaded next time
* STK is started.
* and achievements.
* \param Player profile to be the current player.
* \param remember_me If this player should be marked as default
* player in players.xml
*/
void PlayerManager::setCurrentPlayer(PlayerProfile *player, bool remember_me)
void PlayerManager::setCurrentPlayer(PlayerProfile *player)
{
// Reset current default player
if(m_current_player)
m_current_player->setDefault(false);
m_current_player = player;
if(m_current_player)
{
m_current_player->setDefault(remember_me);
m_current_player->computeActive();
}
} // setCurrentPlayer
// ----------------------------------------------------------------------------

View File

@ -91,11 +91,12 @@ public:
void initRemainingData();
unsigned int getUniqueId() const;
void addDefaultPlayer();
void addNewPlayer(const irr::core::stringw& name);
PlayerProfile* addNewPlayer(const irr::core::stringw& name);
void deletePlayer(PlayerProfile *player);
void setCurrentPlayer(PlayerProfile *player, bool remember_me);
void setCurrentPlayer(PlayerProfile *player);
const PlayerProfile *getPlayerById(unsigned int id);
void enforceCurrentPlayer();
unsigned int getNumNonGuestPlayers() const;
static void setUserDetails(Online::HTTPRequest *request,
const std::string &action,
const std::string &php_name = "");
@ -110,9 +111,7 @@ public:
static void onSTKQuit();
static void requestSignOut();
static Online::XMLRequest *requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password,
bool save_session,
bool request_now = true);
const irr::core::stringw &password);
// ------------------------------------------------------------------------
/** Returns the current player. */

View File

@ -21,14 +21,13 @@
#include "achievements/achievements_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
#include "online/online_player_profile.hpp"
#include "io/xml_node.hpp"
#include "io/utf_writer.hpp"
#include "utils/string_utils.hpp"
#include <sstream>
#include <stdlib.h>
//------------------------------------------------------------------------------
/** Constructor to create a new player that didn't exist before.
* \param name Name of the player.
@ -43,13 +42,12 @@ PlayerProfile::PlayerProfile(const core::stringw& name, bool is_guest)
m_is_guest_account = is_guest;
m_use_frequency = is_guest ? -1 : 0;
m_unique_id = PlayerManager::get()->getUniqueId();
m_is_default = false;
m_is_default = false;
m_saved_session = false;
m_saved_token = "";
m_saved_user_id = 0;
m_achievements_status = NULL;
m_story_mode_status = NULL;
m_last_online_name = "";
m_last_was_online = false;
initRemainingData();
} // PlayerProfile
//------------------------------------------------------------------------------
@ -59,11 +57,12 @@ PlayerProfile::PlayerProfile(const core::stringw& name, bool is_guest)
* that the achievement and story mode data depends on other data to be
* read first (challenges and achievement files), which in turn can only be
* created later in the startup process (they depend on e.g. all tracks to
* be known). On the other hand, automatic login needs to happen asap
* (i.e. as soon as the network thread is started), which needs the main
* player data (i.e. the default player, and saved session data). So the
* constructor only reads this data, the rest of the player data is handled
* in loadRemainingData later in the initialisation process.
* be known). On the other hand, automatic login needs to happen asap (i.e.
* as soon as the network thread is started) to avoid the player having to
* wait for the login to finish , which needs the main player data (i.e.
* the default player, and saved session data). So the constructor only
* reads this data, the rest of the player data is handled in
* loadRemainingData later in the initialisation process.
* \param node The XML node representing this player.
*/
PlayerProfile::PlayerProfile(const XMLNode* node)
@ -71,21 +70,27 @@ PlayerProfile::PlayerProfile(const XMLNode* node)
m_saved_session = false;
m_saved_token = "";
m_saved_user_id = 0;
m_last_online_name = "";
m_last_was_online = false;
m_story_mode_status = NULL;
m_achievements_status = NULL;
m_icon_filename = "";
node->get("name", &m_local_name );
node->get("guest", &m_is_guest_account);
node->get("use-frequency", &m_use_frequency );
node->get("unique-id", &m_unique_id );
node->get("is-default", &m_is_default );
node->get("saved-session", &m_saved_session );
node->get("saved-user", &m_saved_user_id );
node->get("saved-token", &m_saved_token );
node->get("name", &m_local_name );
node->get("guest", &m_is_guest_account);
node->get("use-frequency", &m_use_frequency );
node->get("unique-id", &m_unique_id );
node->get("saved-session", &m_saved_session );
node->get("saved-user", &m_saved_user_id );
node->get("saved-token", &m_saved_token );
node->get("last-online-name", &m_last_online_name);
node->get("last-was-online", &m_last_was_online );
node->get("icon-filename", &m_icon_filename );
#ifdef DEBUG
m_magic_number = 0xABCD1234;
#endif
} // PlayerProfile
//------------------------------------------------------------------------------
@ -110,6 +115,8 @@ void PlayerProfile::loadRemainingData(const XMLNode *node)
const XMLNode *xml_achievements = node->getNode("achievements");
m_achievements_status = AchievementsManager::get()
->createAchievementsStatus(xml_achievements);
// Fix up any potentially missing icons.
addIcon();
} // initRemainingData
//------------------------------------------------------------------------------
@ -121,8 +128,63 @@ void PlayerProfile::initRemainingData()
m_story_mode_status = unlock_manager->createStoryModeStatus();
m_achievements_status =
AchievementsManager::get()->createAchievementsStatus();
addIcon();
} // initRemainingData
//------------------------------------------------------------------------------
/** Creates an icon for a player if non exist so far. It takes the unique
* player id modulo the number of karts to pick an icon from the karts. It
* then uses the unique number plus the extentsion of the original icon as the
* file name (it's not possible to use the player name, since the name is in
* utf-16, but typically the file systems are not, resulting in incorrect file
* names). The icon is then copied to the user config directory, so that it
* can be replaced by an icon made by the user.
* If there should be an error copying the file, the icon filename is set
* to "". Every time stk is started, it will try to fix missing icons
* (which allows it to start from old/incompatible config files).
* \pre This function must only be called after all karts are read in.
*/
void PlayerProfile::addIcon()
{
if (m_icon_filename.size() > 0)
return;
int n = m_unique_id % kart_properties_manager->getNumberOfKarts();
std::string source = kart_properties_manager->getKartById(n)
->getAbsoluteIconFile();
// Create the filename for the icon of this player: the unique id
// followed by .png or .jpg.
std::ostringstream out;
out << m_unique_id <<"."<<StringUtils::getExtension(source);
if(file_manager->copyFile(source,
file_manager->getUserConfigFile(out.str())) )
{
m_icon_filename = out.str();
}
else
{
m_icon_filename = "";
}
} // addIcon
//------------------------------------------------------------------------------
/** Returns the name of the icon file for this player. If the player icon
* file is undefined, it returns a "?" mark texture. Note, getAsset does
* not return a reference, but only a temporary string. So we must return a
* copy of the string (not a reference to).
*/
const std::string PlayerProfile::getIconFilename() const
{
// If the icon file is undefined or does not exist, return the "?" icon
if(m_icon_filename.size()==0 ||
!file_manager->fileExists(file_manager->getUserConfigFile(m_icon_filename)))
{
return file_manager->getAsset(FileManager::GUI, "main_help.png");
}
return file_manager->getUserConfigFile(m_icon_filename);
} // getIconFilename
//------------------------------------------------------------------------------
/** Writes the data for this player to the specified UTFWriter.
* \param out The utf writer to write the data to.
@ -133,13 +195,15 @@ void PlayerProfile::save(UTFWriter &out)
<< L"\" guest=\"" << m_is_guest_account
<< L"\" use-frequency=\"" << m_use_frequency << L"\"\n";
out << L" is-default=\"" << m_is_default
<< L"\" unique-id=\"" << m_unique_id
out << L" icon-filename=\"" << m_icon_filename <<L"\"\n";
out << L" unique-id=\"" << m_unique_id
<< L"\" saved-session=\"" << m_saved_session << L"\"\n";
out << L" saved-user=\"" << m_saved_user_id
<< L"\" saved-token=\"" << m_saved_token << L"\">\n";
<< L"\" saved-token=\"" << m_saved_token << L"\"\n";
out << L" last-online-name=\"" << m_last_online_name
<< L"\" last-was-online=\"" << m_last_was_online<< L"\">\n";
{
if(m_story_mode_status)
m_story_mode_status->save(out);
@ -202,11 +266,4 @@ bool PlayerProfile::operator<(const PlayerProfile &other)
} // operator<
// -----------------------------------------------------------------------------
/** \brief Needed for toggling sort order **/
bool PlayerProfile::operator>(const PlayerProfile &other)
{
return m_use_frequency > other.m_use_frequency;
} // operator>
// -----------------------------------------------------------------------------

View File

@ -83,8 +83,8 @@ private:
/** A unique number for this player, used to link it to challenges etc. */
unsigned int m_unique_id;
/** True if this is the default (last used) player. */
bool m_is_default;
/** Absolute path of the icon file for this player. */
std::string m_icon_filename;
/** True if this user has a saved session. */
bool m_saved_session;
@ -95,6 +95,12 @@ private:
/** The token of the saved session. */
std::string m_saved_token;
/** The online user name used last (empty if not used online). */
core::stringw m_last_online_name;
/** True if the last time this player was used as online. */
bool m_last_was_online;
/** The complete challenge state. */
StoryModeStatus *m_story_mode_status;
@ -110,29 +116,28 @@ public:
void initRemainingData();
void incrementUseFrequency();
bool operator<(const PlayerProfile &other);
bool operator>(const PlayerProfile &other);
void raceFinished();
void saveSession(int user_id, const std::string &token);
void clearSession();
void addIcon();
/** Abstract virtual classes, to be implemented by the OnlinePlayer. */
virtual void setUserDetails(Online::HTTPRequest *request,
const std::string &action,
const std::string &php_script = "") = 0;
const std::string &php_script = "") const = 0;
virtual uint32_t getOnlineId() const = 0;
virtual PlayerProfile::OnlineState getOnlineState() const = 0;
virtual Online::OnlineProfile* getProfile() const = 0;
virtual void requestPoll() const = 0;
virtual void requestSavedSession() = 0;
virtual void onSTKQuit() const = 0;
virtual Online::XMLRequest* requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password,
bool save_session,
bool request_now = true) = 0;
const irr::core::stringw &password) = 0;
virtual void signIn(bool success, const XMLNode * input) = 0;
virtual void signOut(bool success, const XMLNode * input) = 0;
virtual void signOut(bool success, const XMLNode * input,
const irr::core::stringw &info) = 0;
virtual void requestSignOut() = 0;
virtual bool isLoggedIn() const { return false; }
const std::string getIconFilename() const;
// ------------------------------------------------------------------------
/** Sets the name of this player. */
void setName(const core::stringw& name)
@ -160,16 +165,21 @@ public:
#endif
return m_is_guest_account;
} // isGuestAccount
// ------------------------------------------------------------------------
/** Returns the last used online name. */
const core::stringw& getLastOnlineName() const
{
return m_last_online_name;
} // getLastOnlineName
// ------------------------------------------------------------------------
/** Sets the last used online name. */
void setLastOnlineName(const core::stringw &name)
{
m_last_online_name = name;
} // setLastOnlineName
// ------------------------------------------------------------------------
/** Returns the unique id of this player. */
unsigned int getUniqueID() const { return m_unique_id; }
// -----------------------------------------------------------------------
/** Returns true if this is the default (last used) player. */
bool isDefault() const { return m_is_default; }
// ------------------------------------------------------------------------
/** Sets if this player is the default player or not. */
void setDefault(bool is_default) { m_is_default = is_default; }
// ------------------------------------------------------------------------
/** Returnes if the feature (kart, track) is locked. */
bool isLocked(const std::string &feature) const
@ -252,6 +262,13 @@ public:
return m_saved_token;
} // getSavedToken
// ------------------------------------------------------------------------
/** Returns if the last time this player was used it was used online or
* offline. */
bool wasOnlineLastTime() const { return m_last_was_online; }
// ------------------------------------------------------------------------
/** Sets if this player was logged in last time it was used. */
void setWasOnlineLastTime(bool b) { m_last_was_online = b; }
// ------------------------------------------------------------------------
}; // class PlayerProfile
#endif

View File

@ -464,6 +464,9 @@ namespace UserConfigParams
PARAM_PREFIX BoolUserConfigParam m_dof
PARAM_DEFAULT(BoolUserConfigParam(false, "enable_dof",
&m_video_group, "Enable Depth of Field"));
PARAM_PREFIX BoolUserConfigParam m_gi
PARAM_DEFAULT(BoolUserConfigParam(false, "enable_gi",
&m_video_group, "Enable Global Illumination"));
// ---- Debug - not saved to config file
/** If gamepad debugging is enabled. */
@ -677,6 +680,15 @@ namespace UserConfigParams
"wasn't asked, 1: allowed, 2: "
"not allowed") );
// ---- User managerment
PARAM_PREFIX BoolUserConfigParam m_remember_user
PARAM_DEFAULT( BoolUserConfigParam(true, "remember_me",
"Automatically remember login data"));
PARAM_PREFIX BoolUserConfigParam m_always_show_login_screen
PARAM_DEFAULT( BoolUserConfigParam(false, "always_show_login_screen",
"Always show the login screen even if last player's session was saved."));
// ---- Online gameplay related
PARAM_PREFIX GroupUserConfigParam m_online_group

View File

@ -353,10 +353,10 @@ void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha)
{
float alpha = data[4 * i + 3];
if (alpha > 0.)
alpha = pow(alpha / 255., 1. / 2.2);
data[4 * i] *= alpha;
data[4 * i + 1] *= alpha;
data[4 * i + 2] *= alpha;
alpha = pow(alpha / 255.f, 1.f / 2.2f);
data[4 * i ] = (unsigned char)(data[4 * i ] * alpha);
data[4 * i + 1] = (unsigned char)(data[4 * i + 1] * alpha);
data[4 * i + 2] = (unsigned char)(data[4 * i + 2] * alpha);
}
}
@ -518,13 +518,21 @@ unsigned GPUTimer::elapsedTimeus()
FrameBuffer::FrameBuffer() {}
FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, size_t w, size_t h) :
FrameBuffer::FrameBuffer(const std::vector<GLuint> &RTTs, size_t w, size_t h, bool layered) :
DepthTexture(0), RenderTargets(RTTs), width(w), height(h)
{
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
for (unsigned i = 0; i < RTTs.size(); i++)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, RTTs[i], 0);
if (layered)
{
for (unsigned i = 0; i < RTTs.size(); i++)
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, RTTs[i], 0);
}
else
{
for (unsigned i = 0; i < RTTs.size(); i++)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, RTTs[i], 0);
}
GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(result == GL_FRAMEBUFFER_COMPLETE_EXT);
}
@ -560,7 +568,7 @@ void FrameBuffer::Bind()
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, width, height);
irr::video::COpenGLDriver *gl_driver = (irr::video::COpenGLDriver*)irr_driver->getDevice()->getVideoDriver();
GLenum bufs[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
GLenum bufs[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
gl_driver->extGlDrawBuffers(RenderTargets.size(), bufs);
}

View File

@ -190,7 +190,7 @@ private:
size_t width, height;
public:
FrameBuffer();
FrameBuffer(const std::vector <GLuint> &RTTs, size_t w, size_t h);
FrameBuffer(const std::vector <GLuint> &RTTs, size_t w, size_t h, bool layered = false);
FrameBuffer(const std::vector <GLuint> &RTTs, GLuint DS, size_t w, size_t h, bool layered = false);
~FrameBuffer();
void Bind();

View File

@ -1,14 +1,14 @@
#ifndef GPUPARTICLES_H
#define GPUPARTICLES_H
#include "graphics/glwrap.hpp"
#include "../lib/irrlicht/source/Irrlicht/CParticleSystemSceneNode.h"
#include <ISceneManager.h>
#include <IParticleSystemSceneNode.h>
namespace irr { namespace video{ class ITexture; } }
class ParticleSystemProxy : public scene::CParticleSystemSceneNode
{
protected:
@ -19,18 +19,18 @@ protected:
float size_increase_factor, track_x, track_z, track_x_len, track_z_len;
float m_color_from[3];
float m_color_to[3];
static GLuint quad_vertex_buffer;
GLuint texture;
unsigned count;
static void SimpleParticleVAOBind(GLuint PositionBuffer);
static void FlipParticleVAOBind(GLuint PositionBuffer, GLuint QuaternionBuffer);
static void SimpleSimulationBind(GLuint PositionBuffer, GLuint InitialValuesBuffer);
static void HeightmapSimulationBind(GLuint PositionBuffer, GLuint InitialValuesBuffer);
void generateVAOs();
void simulateHeightmap();
void simulateNoHeightmap();
void drawFlip();
@ -46,14 +46,14 @@ public:
const core::vector3df& position = core::vector3df(0, 0, 0),
const core::vector3df& rotation = core::vector3df(0, 0, 0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
ParticleSystemProxy(bool createDefaultEmitter,
ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
const core::vector3df& position,
const core::vector3df& rotation,
const core::vector3df& scale);
~ParticleSystemProxy();
virtual void setEmitter(scene::IParticleEmitter* emitter);
virtual void render();
virtual void OnRegisterSceneNode();
@ -66,5 +66,5 @@ public:
void setHeightmap(const std::vector<std::vector<float> >&, float, float, float, float);
void setFlip();
};
#endif // GPUPARTICLES_H

View File

@ -110,7 +110,7 @@ IrrDriver::IrrDriver()
m_post_processing = NULL;
m_wind = new Wind();
m_mipviz = m_wireframe = m_normals = m_ssaoviz = \
m_lightviz = m_shadowviz = m_distortviz = 0;
m_lightviz = m_shadowviz = m_distortviz = m_rsm = m_rh = m_gi = 0;
SkyboxCubeMap = 0;
} // IrrDriver

View File

@ -203,6 +203,9 @@ private:
/** RTTs. */
RTT *m_rtts;
std::vector<core::matrix4> sun_ortho_matrix;
core::vector3df rh_extend;
core::matrix4 rh_matrix;
core::matrix4 rsm_matrix;
/** Additional details to be shown in case that a texture is not found.
* This is used to specify details like: "while loading kart '...'" */
@ -233,7 +236,7 @@ private:
RES_CHANGE_CANCEL} m_resolution_changing;
public:
GLuint SkyboxCubeMap, FakeSkybox;
GLuint SkyboxCubeMap;
/** A simple class to store video resolutions. */
class VideoMode
{
@ -312,6 +315,9 @@ private:
bool m_mipviz;
bool m_normals;
bool m_ssaoviz;
bool m_rsm;
bool m_rh;
bool m_gi;
bool m_shadowviz;
bool m_lightviz;
bool m_distortviz;
@ -573,6 +579,9 @@ public:
m_mipviz = false;
m_normals = false;
m_ssaoviz = false;
m_rsm = false;
m_rh = false;
m_gi = false;
m_shadowviz = false;
m_lightviz = false;
m_distortviz = false;
@ -594,6 +603,18 @@ public:
// ------------------------------------------------------------------------
bool getSSAOViz() { return m_ssaoviz; }
// ------------------------------------------------------------------------
void toggleRSM() { m_rsm = !m_rsm; }
// ------------------------------------------------------------------------
bool getRSM() { return m_rsm; }
// ------------------------------------------------------------------------
void toggleRH() { m_rh = !m_rh; }
// ------------------------------------------------------------------------
bool getRH() { return m_rh; }
// ------------------------------------------------------------------------
void toggleGI() { m_gi = !m_gi; }
// ------------------------------------------------------------------------
bool getGI() { return m_gi; }
// ------------------------------------------------------------------------
void toggleShadowViz() { m_shadowviz = !m_shadowviz; }
// ------------------------------------------------------------------------
bool getShadowViz() { return m_shadowviz; }

View File

@ -243,6 +243,17 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
if (b)
m_shader_type = SHADERTYPE_SPHERE_MAP;
if (node->get("compositing", &s))
{
if (s == "blend") m_shader_type = SHADERTYPE_ALPHA_BLEND;
else if (s == "test") m_shader_type = SHADERTYPE_ALPHA_TEST;
else if (s == "additive") m_shader_type = SHADERTYPE_ADDITIVE;
else if (s == "coverage") m_shader_type = SHADERTYPE_ALPHA_TEST;
else if (s != "none")
Log::warn("material", "Unknown compositing mode '%s'", s.c_str());
}
s = "";
node->get("graphical-effect", &s);
@ -294,10 +305,6 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
"Invalid graphical effect specification: '%s' - ignored.",
s.c_str());
}
else
{
m_shader_type = SHADERTYPE_SOLID;
}
bool use_normal_map = false;
node->get("use-normal-map", &use_normal_map);
@ -322,16 +329,6 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
m_shader_type = SHADERTYPE_SPHERE_MAP;
}
if (node->get("compositing", &s))
{
if (s == "blend") m_shader_type = SHADERTYPE_ALPHA_BLEND;
else if (s == "test") m_shader_type = SHADERTYPE_ALPHA_TEST;
else if (s == "additive") m_shader_type = SHADERTYPE_ADDITIVE;
else if (s == "coverage") m_shader_type = SHADERTYPE_ALPHA_TEST;
else if (s != "none")
Log::warn("material", "Unknown compositing mode '%s'", s.c_str());
}
bool water_shader = false;
node->get("water-shader", &water_shader);
if (water_shader)
@ -697,12 +694,17 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
if (m_shader_type == SHADERTYPE_SOLID_UNLIT)
{
m->MaterialType = irr_driver->getShader(ES_OBJECT_UNLIT);
m->AmbientColor = video::SColor(255, 255, 255, 255);
m->DiffuseColor = video::SColor(255, 255, 255, 255);
m->EmissiveColor = video::SColor(255, 255, 255, 255);
m->SpecularColor = video::SColor(255, 255, 255, 255);
if (irr_driver->isGLSL())
{
m->MaterialType = irr_driver->getShader(ES_OBJECT_UNLIT);
}
else
{
m->AmbientColor = video::SColor(255, 255, 255, 255);
m->DiffuseColor = video::SColor(255, 255, 255, 255);
m->EmissiveColor = video::SColor(255, 255, 255, 255);
m->SpecularColor = video::SColor(255, 255, 255, 255);
}
}
if (m_shader_type == SHADERTYPE_ALPHA_TEST)

View File

@ -264,6 +264,35 @@ void PostProcessing::renderDiffuseEnvMap(const float *bSHCoeff, const float *gSH
glDisable(GL_BLEND);
}
void PostProcessing::renderGI(const core::matrix4 &RHMatrix, const core::vector3df &rh_extend, GLuint shr, GLuint shg, GLuint shb)
{
glDisable(GL_DEPTH_TEST);
glUseProgram(FullScreenShader::GlobalIlluminationReconstructionShader::Program);
glBindVertexArray(FullScreenShader::GlobalIlluminationReconstructionShader::vao);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, shr);
{
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_3D, shg);
{
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_3D, shb);
{
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
setTexture(3, irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), GL_NEAREST, GL_NEAREST);
setTexture(4, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST);
FullScreenShader::GlobalIlluminationReconstructionShader::setUniforms(RHMatrix, rh_extend, 3, 4, 0, 1, 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void PostProcessing::renderSunlight()
{
SunLightProvider * const cb = (SunLightProvider *) irr_driver->getCallback(ES_SUNLIGHT);
@ -476,7 +505,9 @@ void PostProcessing::renderSSAO()
glGenerateMipmap(GL_TEXTURE_2D);
setTexture(1, getTextureGLuint(noise_tex), GL_LINEAR, GL_LINEAR);
FullScreenShader::SSAOShader::setUniforms(core::vector2df(UserConfigParams::m_width, UserConfigParams::m_height), 0, 1);
FullScreenShader::SSAOShader::setUniforms(core::vector2df(float(UserConfigParams::m_width),
float(UserConfigParams::m_height)),
0, 1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

View File

@ -81,6 +81,7 @@ public:
void renderFog();
void renderSSAO();
void renderDiffuseEnvMap(const float *bSHCoeff, const float *gSHCoeff, const float *rSHCoeff);
void renderGI(const core::matrix4 &RHMatrix, const core::vector3df &rh_extend, unsigned shr, unsigned shg, unsigned shb);
/** Blur the in texture */
void renderGaussian3Blur(FrameBuffer &in_fbo, FrameBuffer &auxiliary);

View File

@ -170,7 +170,7 @@ void IrrDriver::renderGLSL(float dt)
UtilShader::ColoredLine::setUniforms(it->first);
const std::vector<float> &vertex = it->second;
const float *tmp = vertex.data();
for (int i = 0; i < vertex.size(); i += 1024 * 6)
for (unsigned int i = 0; i < vertex.size(); i += 1024 * 6)
{
unsigned count = MIN2(vertex.size() - i, 1024 * 6);
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float), &tmp[i]);
@ -195,6 +195,12 @@ void IrrDriver::renderGLSL(float dt)
irr_driver->getFBO(FBO_NORMAL_AND_DEPTHS).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
else if (irr_driver->getSSAOViz())
irr_driver->getFBO(FBO_SSAO).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
else if (irr_driver->getRSM())
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
m_post_processing->renderPassThrough(m_rtts->getRSM().getRTT()[0]);
}
else
fbo->BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
@ -314,9 +320,32 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, std::vector
}
PROFILER_PUSH_CPU_MARKER("- Skybox", 0xFF, 0x00, 0xFF);
renderSkybox(camnode);
if (!SkyboxTextures.empty())
renderSkybox(camnode);
PROFILER_POP_CPU_MARKER();
if (getRH())
{
glEnable(GL_PROGRAM_POINT_SIZE);
m_rtts->getFBO(FBO_COLORS).Bind();
glUseProgram(FullScreenShader::RHDebug::Program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, m_rtts->getRH().getRTT()[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_3D, m_rtts->getRH().getRTT()[1]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_3D, m_rtts->getRH().getRTT()[2]);
FullScreenShader::RHDebug::setUniforms(rh_matrix, rh_extend, 0, 1, 2);
glDrawArrays(GL_POINTS, 0, 32 * 16 * 32);
glDisable(GL_PROGRAM_POINT_SIZE);
}
if (getGI())
{
m_rtts->getFBO(FBO_COLORS).Bind();
m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
}
PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00);
// Render anything glowing.
if (!m_mipviz && !m_wireframe && UserConfigParams::m_glow)
@ -501,17 +530,44 @@ void IrrDriver::renderSolidFirstPass()
glUseProgram(MeshShader::ObjectPass1Shader::Program);
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT>::MeshSet.size(); ++i)
{
drawObjectPass1(*GroupedFPSM<FPSM_DEFAULT>::MeshSet[i], GroupedFPSM<FPSM_DEFAULT>::MVPSet[i], GroupedFPSM<FPSM_DEFAULT>::TIMVSet[i]);
const GLMesh &mesh = *GroupedFPSM<FPSM_DEFAULT>::MeshSet[i];
if (mesh.textures[0])
{
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
}
else
{
setTexture(0, 0, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, false);
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ONE };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
draw<MeshShader::ObjectPass1Shader>(mesh, mesh.vao_first_pass, GroupedFPSM<FPSM_DEFAULT>::MVPSet[i], GroupedFPSM<FPSM_DEFAULT>::TIMVSet[i], 0);
if (!mesh.textures[0])
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
}
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
for (unsigned i = 0; i < GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet.size(); ++i)
{
drawObjectRefPass1(*GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MVPSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::TIMVSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i]->TextureMatrix);
const GLMesh &mesh = *GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i];
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::ObjectRefPass1Shader>(mesh, mesh.vao_first_pass, GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MVPSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::TIMVSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i]->TextureMatrix, 0);
}
glUseProgram(MeshShader::NormalMapShader::Program);
for (unsigned i = 0; i < GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet.size(); ++i)
{
drawNormalPass(*GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet[i], GroupedFPSM<FPSM_NORMAL_MAP>::MVPSet[i], GroupedFPSM<FPSM_NORMAL_MAP>::TIMVSet[i]);
const GLMesh &mesh = *GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet[i];
assert(mesh.textures[1]);
compressTexture(mesh.textures[1], false);
setTexture(0, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
compressTexture(mesh.textures[0], true);
setTexture(1, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::NormalMapShader>(mesh, mesh.vao_first_pass, GroupedFPSM<FPSM_NORMAL_MAP>::MVPSet[i], GroupedFPSM<FPSM_NORMAL_MAP>::TIMVSet[i], 0, 1);
}
}
}
@ -613,6 +669,8 @@ void IrrDriver::renderParticles()
void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height)
{
static int tick = 0;
tick++;
m_scene_manager->drawAll(scene::ESNRP_CAMERA);
irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
@ -701,6 +759,13 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW));
}
if (!(tick % 100))
rsm_matrix = sun_ortho_matrix[3];
rh_extend = core::vector3df(128, 64, 128);
core::vector3df campos = camnode->getAbsolutePosition();
core::vector3df translation(8 * floor(campos.X / 8), 8 * floor(campos.Y / 8), 8 * floor(campos.Z / 8));
rh_matrix.setTranslation(translation);
assert(sun_ortho_matrix.size() == 4);
camnode->setNearValue(oldnear);
camnode->setFarValue(oldfar);
@ -708,10 +773,8 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
size_t size = irr_driver->getShadowViewProj().size();
for (unsigned i = 0; i < size; i++)
memcpy(&tmp[16 * i + 64], irr_driver->getShadowViewProj()[i].pointer(), 16 * sizeof(float));
}
tmp[128] = width;
tmp[129] = height;
tmp[128] = float(width);
tmp[129] = float(height);
glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 8 + 2) * sizeof(float), tmp);
@ -747,7 +810,22 @@ void IrrDriver::renderShadows()
glDisable(GL_POLYGON_OFFSET_FILL);
glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height);
if (!UserConfigParams::m_gi)
return;
m_rtts->getRSM().Bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(MeshShader::RSMShader::Program);
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT>::MeshSet.size(); ++i)
{
const GLMesh mesh = *GroupedFPSM<FPSM_DEFAULT>::MeshSet[i];
if (!mesh.textures[0])
continue;
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::RSMShader>(mesh, mesh.vao_rsm_pass, rsm_matrix, GroupedFPSM<FPSM_DEFAULT>::MVPSet[i], 0);
}
}
// ----------------------------------------------------------------------------
@ -837,6 +915,19 @@ static void renderPointLights(unsigned count)
void IrrDriver::renderLights(scene::ICameraSceneNode * const camnode, float dt)
{
//RH
if (UserConfigParams::m_gi)
{
glDisable(GL_BLEND);
m_rtts->getRH().Bind();
glUseProgram(FullScreenShader::RadianceHintsConstructionShader::Program);
glBindVertexArray(FullScreenShader::RadianceHintsConstructionShader::vao);
setTexture(0, m_rtts->getRSM().getRTT()[0], GL_LINEAR, GL_LINEAR);
setTexture(1, m_rtts->getRSM().getRTT()[1], GL_LINEAR, GL_LINEAR);
setTexture(2, m_rtts->getRSM().getDepthTexture(), GL_LINEAR, GL_LINEAR);
FullScreenShader::RadianceHintsConstructionShader::setUniforms(rsm_matrix, rh_matrix, rh_extend, 0, 1, 2);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32);
}
for (unsigned i = 0; i < sun_ortho_matrix.size(); i++)
sun_ortho_matrix[i] *= getInvViewMatrix();
@ -845,10 +936,10 @@ void IrrDriver::renderLights(scene::ICameraSceneNode * const camnode, float dt)
glClearColor(.5, .5, .5, .5);
glClear(GL_COLOR_BUFFER_BIT);
if (!UserConfigParams::m_dynamic_lights)
{
//gl_driver->extGlDrawBuffers(1, bufs);
return;
}
if (UserConfigParams::m_gi)
m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
if (SkyboxCubeMap)
irr_driver->getSceneManager()->setAmbientLight(SColor(0, 0, 0, 0));
@ -929,7 +1020,6 @@ void IrrDriver::renderLights(scene::ICameraSceneNode * const camnode, float dt)
renderPointLights(MIN2(lightnum, MAXLIGHT));
if (SkyboxCubeMap)
m_post_processing->renderDiffuseEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff);
// gl_driver->extGlDrawBuffers(1, bufs);
}
void IrrDriver::renderSSAO()
@ -1395,20 +1485,6 @@ void IrrDriver::generateSkyboxCubemap()
void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera)
{
if (SkyboxTextures.empty() && FakeSkybox)
{
glGenTextures(1, &FakeSkybox);
unsigned w = 1, h = 1;
char *rgba[6];
for (unsigned i = 0; i < 6; i++)
rgba[i] = new char[w * h * 4];
for (unsigned i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_COMPRESSED_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
return;
}
if (!SkyboxCubeMap)
generateSkyboxCubemap();
glBindVertexArray(MeshShader::SkyboxShader::cubevao);

View File

@ -54,7 +54,7 @@ static GLuint generateFBO(GLuint ColorAttachement, GLuint DepthAttachement)
RTT::RTT(size_t width, size_t height)
{
m_shadow_FBO = NULL;
initGL();
m_RSM = NULL;
using namespace video;
using namespace core;
@ -199,6 +199,38 @@ RTT::RTT(size_t width, size_t height)
somevector.clear();
somevector.push_back(shadowColorTex);
m_shadow_FBO = new FrameBuffer(somevector, shadowDepthTex, 1024, 1024, true);
//Todo : use "normal" shadowtex
glGenTextures(1, &RSM_Color);
glBindTexture(GL_TEXTURE_2D, RSM_Color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1024, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glGenTextures(1, &RSM_Normal);
glBindTexture(GL_TEXTURE_2D, RSM_Normal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 1024, 1024, 0, GL_RGB, GL_FLOAT, 0);
glGenTextures(1, &RSM_Depth);
glBindTexture(GL_TEXTURE_2D, RSM_Depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, 1024, 1024, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
somevector.clear();
somevector.push_back(RSM_Color);
somevector.push_back(RSM_Normal);
m_RSM = new FrameBuffer(somevector, RSM_Depth, 1024, 1024, true);
glGenTextures(1, &RH_Red);
glBindTexture(GL_TEXTURE_3D, RH_Red);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16F, 32, 16, 32, 0, GL_RGBA, GL_FLOAT, 0);
glGenTextures(1, &RH_Green);
glBindTexture(GL_TEXTURE_3D, RH_Green);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16F, 32, 16, 32, 0, GL_RGBA, GL_FLOAT, 0);
glGenTextures(1, &RH_Blue);
glBindTexture(GL_TEXTURE_3D, RH_Blue);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16F, 32, 16, 32, 0, GL_RGBA, GL_FLOAT, 0);
somevector.clear();
somevector.push_back(RH_Red);
somevector.push_back(RH_Green);
somevector.push_back(RH_Blue);
m_RH_FBO = new FrameBuffer(somevector, 32, 16, true);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
@ -206,11 +238,19 @@ RTT::RTT(size_t width, size_t height)
RTT::~RTT()
{
delete m_shadow_FBO;
delete m_RH_FBO;
delete m_RSM;
glDeleteTextures(RTT_COUNT, RenderTargetTextures);
glDeleteTextures(1, &DepthStencilTexture);
if (irr_driver->getGLSLVersion() >= 150)
{
glDeleteTextures(1, &shadowColorTex);
glDeleteTextures(1, &shadowDepthTex);
glDeleteTextures(1, &RSM_Color);
glDeleteTextures(1, &RSM_Normal);
glDeleteTextures(1, &RSM_Depth);
glDeleteTextures(1, &RH_Red);
glDeleteTextures(1, &RH_Green);
glDeleteTextures(1, &RH_Blue);
}
}

View File

@ -38,6 +38,8 @@ public:
~RTT();
FrameBuffer &getShadowFBO() { return *m_shadow_FBO; }
FrameBuffer &getRH() { return *m_RH_FBO; }
FrameBuffer &getRSM() { return *m_RSM; }
unsigned getShadowDepthTex() const { return shadowDepthTex; }
unsigned getDepthStencilTexture() const { return DepthStencilTexture; }
@ -48,8 +50,10 @@ private:
PtrVector<FrameBuffer> FrameBuffers;
unsigned DepthStencilTexture;
unsigned shadowColorTex, shadowDepthTex;
FrameBuffer* m_shadow_FBO;
unsigned shadowColorTex, shadowNormalTex, shadowDepthTex;
unsigned RSM_Color, RSM_Normal, RSM_Depth;
unsigned RH_Red, RH_Green, RH_Blue;
FrameBuffer* m_shadow_FBO, *m_RSM, *m_RH_FBO;
LEAK_CHECK();
};

View File

@ -281,6 +281,9 @@ void Shaders::loadShaders()
FullScreenShader::DiffuseEnvMapShader::init();
FullScreenShader::ShadowedSunLightShader::init();
FullScreenShader::ShadowedSunLightDebugShader::init();
FullScreenShader::RadianceHintsConstructionShader::init();
FullScreenShader::RHDebug::init();
FullScreenShader::GlobalIlluminationReconstructionShader::init();
FullScreenShader::MotionBlurShader::init();
FullScreenShader::GodFadeShader::init();
FullScreenShader::GodRayShader::init();
@ -317,6 +320,7 @@ void Shaders::loadShaders()
MeshShader::DisplaceShader::init();
MeshShader::DisplaceMaskShader::init();
MeshShader::ShadowShader::init();
MeshShader::RSMShader::init();
MeshShader::InstancedShadowShader::init();
MeshShader::RefShadowShader::init();
MeshShader::InstancedRefShadowShader::init();
@ -1487,6 +1491,36 @@ namespace MeshShader
glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer());
}
GLuint RSMShader::Program;
GLuint RSMShader::attrib_position;
GLuint RSMShader::attrib_texcoord;
GLuint RSMShader::attrib_normal;
GLuint RSMShader::uniform_MM;
GLuint RSMShader::uniform_tex;
GLuint RSMShader::uniform_RSMMatrix;
void RSMShader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/rsm.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rsm.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
uniform_MM = glGetUniformLocation(Program, "ModelMatrix");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_normal = glGetAttribLocation(Program, "Normal");
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_RSMMatrix = glGetUniformLocation(Program, "RSMMatrix");
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0);
}
void RSMShader::setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &ModelMatrix, unsigned TU_tex)
{
glUniformMatrix4fv(uniform_RSMMatrix, 1, GL_FALSE, RSMMatrix.pointer());
glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer());
glUniform1i(uniform_tex, TU_tex);
}
GLuint InstancedShadowShader::Program;
GLuint InstancedShadowShader::attrib_position;
GLuint InstancedShadowShader::attrib_origin;
@ -2273,6 +2307,122 @@ namespace FullScreenShader
glUniform1i(uniform_shadowtex, TU_shadowtex);
}
GLuint RadianceHintsConstructionShader::Program;
GLuint RadianceHintsConstructionShader::uniform_ctex;
GLuint RadianceHintsConstructionShader::uniform_ntex;
GLuint RadianceHintsConstructionShader::uniform_dtex;
GLuint RadianceHintsConstructionShader::uniform_extents;
GLuint RadianceHintsConstructionShader::uniform_RHMatrix;
GLuint RadianceHintsConstructionShader::uniform_RSMMatrix;
GLuint RadianceHintsConstructionShader::vao;
void RadianceHintsConstructionShader::init()
{
if (irr_driver->hasVSLayerExtension())
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/slicedscreenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rh.frag").c_str());
}
else
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/slicedscreenquad.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/rhpassthrough.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rh.frag").c_str());
}
uniform_ctex = glGetUniformLocation(Program, "ctex");
uniform_ntex = glGetUniformLocation(Program, "ntex");
uniform_dtex = glGetUniformLocation(Program, "dtex");
uniform_extents = glGetUniformLocation(Program, "extents");
uniform_RHMatrix = glGetUniformLocation(Program, "RHMatrix");
uniform_RSMMatrix = glGetUniformLocation(Program, "RSMMatrix");
vao = createVAO(Program);
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0);
}
void RadianceHintsConstructionShader::setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &RHMatrix, const core::vector3df &extents, unsigned TU_ctex, unsigned TU_ntex, unsigned TU_dtex)
{
glUniformMatrix4fv(uniform_RSMMatrix, 1, GL_FALSE, RSMMatrix.pointer());
glUniformMatrix4fv(uniform_RHMatrix, 1, GL_FALSE, RHMatrix.pointer());
glUniform1i(uniform_ctex, TU_ctex);
glUniform1i(uniform_ntex, TU_ntex);
glUniform1i(uniform_dtex, TU_dtex);
glUniform3f(uniform_extents, extents.X, extents.Y, extents.Z);
}
GLuint RHDebug::Program;
GLuint RHDebug::uniform_extents;
GLuint RHDebug::uniform_SHR;
GLuint RHDebug::uniform_SHG;
GLuint RHDebug::uniform_SHB;
GLuint RHDebug::uniform_RHMatrix;
void RHDebug::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/rhdebug.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rhdebug.frag").c_str());
uniform_extents = glGetUniformLocation(Program, "extents");
uniform_SHR = glGetUniformLocation(Program, "SHR");
uniform_SHG = glGetUniformLocation(Program, "SHG");
uniform_SHB = glGetUniformLocation(Program, "SHB");
uniform_RHMatrix = glGetUniformLocation(Program, "RHMatrix");
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0);
}
void RHDebug::setUniforms(const core::matrix4 &RHMatrix, const core::vector3df &extents, unsigned TU_SHR, unsigned TU_SHG, unsigned TU_SHB)
{
glUniformMatrix4fv(uniform_RHMatrix, 1, GL_FALSE, RHMatrix.pointer());
glUniform3f(uniform_extents, extents.X, extents.Y, extents.Z);
glUniform1i(uniform_SHR, TU_SHR);
glUniform1i(uniform_SHG, TU_SHG);
glUniform1i(uniform_SHB, TU_SHB);
}
GLuint GlobalIlluminationReconstructionShader::Program;
GLuint GlobalIlluminationReconstructionShader::uniform_ntex;
GLuint GlobalIlluminationReconstructionShader::uniform_dtex;
GLuint GlobalIlluminationReconstructionShader::uniform_SHR;
GLuint GlobalIlluminationReconstructionShader::uniform_SHG;
GLuint GlobalIlluminationReconstructionShader::uniform_SHB;
GLuint GlobalIlluminationReconstructionShader::uniform_extents;
GLuint GlobalIlluminationReconstructionShader::uniform_RHMatrix;
GLuint GlobalIlluminationReconstructionShader::vao;
void GlobalIlluminationReconstructionShader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gi.frag").c_str());
uniform_ntex = glGetUniformLocation(Program, "ntex");
uniform_dtex = glGetUniformLocation(Program, "dtex");
uniform_SHR = glGetUniformLocation(Program, "SHR");
uniform_SHG = glGetUniformLocation(Program, "SHG");
uniform_SHB = glGetUniformLocation(Program, "SHB");
uniform_RHMatrix = glGetUniformLocation(Program, "RHMatrix");
uniform_extents = glGetUniformLocation(Program, "extents");
vao = createVAO(Program);
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0);
}
void GlobalIlluminationReconstructionShader::setUniforms(const core::matrix4 &RHMatrix, const core::vector3df &extents, unsigned TU_ntex, unsigned TU_dtex, unsigned TU_SHR, unsigned TU_SHG, unsigned TU_SHB)
{
glUniformMatrix4fv(uniform_RHMatrix, 1, GL_FALSE, RHMatrix.pointer());
glUniform1i(uniform_ntex, TU_ntex);
glUniform1i(uniform_dtex, TU_dtex);
glUniform1i(uniform_SHR, TU_SHR);
glUniform1i(uniform_SHG, TU_SHG);
glUniform1i(uniform_SHB, TU_SHB);
glUniform3f(uniform_extents, extents.X, extents.Y, extents.Z);
}
GLuint Gaussian17TapHShader::Program;
GLuint Gaussian17TapHShader::uniform_tex;
GLuint Gaussian17TapHShader::uniform_pixel;

View File

@ -336,6 +336,17 @@ public:
static void setUniforms(const core::matrix4 &ModelMatrix);
};
class RSMShader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_texcoord, attrib_normal;
static GLuint uniform_MM, uniform_tex, uniform_RSMMatrix;
static void init();
static void setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &ModelMatrix, unsigned TU_tex);
};
class InstancedShadowShader
{
public:
@ -598,6 +609,38 @@ public:
static void setUniforms(const core::vector3df &direction, float r, float g, float b, unsigned TU_ntex, unsigned TU_dtex, unsigned TU_shadowtex);
};
class RadianceHintsConstructionShader
{
public:
static GLuint Program;
static GLuint uniform_ctex, uniform_ntex, uniform_dtex, uniform_extents, uniform_RHMatrix, uniform_RSMMatrix;
static GLuint vao;
static void init();
static void setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &RHMatrix, const core::vector3df &extents, unsigned TU_ctex, unsigned TU_ntex, unsigned TU_dtex);
};
class RHDebug
{
public:
static GLuint Program;
static GLuint uniform_extents, uniform_SHR, uniform_SHG, uniform_SHB, uniform_RHMatrix;
static void init();
static void setUniforms(const core::matrix4 &RHMatrix, const core::vector3df &extents, unsigned TU_SHR, unsigned TU_SHG, unsigned TU_SHB);
};
class GlobalIlluminationReconstructionShader
{
public:
static GLuint Program;
static GLuint uniform_ntex, uniform_dtex, uniform_extents, uniform_SHR, uniform_SHG, uniform_SHB, uniform_RHMatrix;
static GLuint vao;
static void init();
static void setUniforms(const core::matrix4 &RHMatrix, const core::vector3df &extents, unsigned TU_ntex, unsigned TU_dtex, unsigned TU_SHR, unsigned TU_SHG, unsigned TU_SHB);
};
class Gaussian17TapHShader
{
public:

View File

@ -179,7 +179,6 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb)
case scene::EPT_QUADS:
assert(0 && "Unsupported primitive type");
}
ITexture *tex;
for (unsigned i = 0; i < 6; i++)
result.textures[i] = mb->getMaterial().getTexture(i);
result.TextureMatrix = 0;
@ -213,56 +212,6 @@ core::vector3df getWind()
return m_speed * vector3df(1., 0., 0.) * cos(time);
}
void drawObjectPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
if (mesh.textures[0])
{
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
}
else
{
setTexture(0, 0, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, false);
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ONE };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
MeshShader::ObjectPass1Shader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, 0);
assert(mesh.vao_first_pass);
glBindVertexArray(mesh.vao_first_pass);
glDrawElements(ptype, count, itype, 0);
if (!mesh.textures[0])
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
}
void drawObjectRefPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &TextureMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::ObjectRefPass1Shader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, TextureMatrix, 0);
assert(mesh.vao_first_pass);
glBindVertexArray(mesh.vao_first_pass);
glDrawElements(ptype, count, itype, 0);
}
void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, core::vector3df windDir)
{
irr_driver->IncreaseObjectCount();
@ -280,26 +229,6 @@ void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio
glDrawElements(ptype, count, itype, 0);
}
void drawNormalPass(const GLMesh &mesh, const core::matrix4 & ModelMatrix, const core::matrix4 &InverseModelMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
assert(mesh.textures[1]);
compressTexture(mesh.textures[1], false);
setTexture(0, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
compressTexture(mesh.textures[0], true);
setTexture(1, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::NormalMapShader::setUniforms(ModelMatrix, InverseModelMatrix, 0, 1);
assert(mesh.vao_first_pass);
glBindVertexArray(mesh.vao_first_pass);
glDrawElements(ptype, count, itype, 0);
}
void drawSphereMap(const GLMesh &mesh, const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix)
{
irr_driver->IncreaseObjectCount();
@ -730,6 +659,7 @@ void initvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedM
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::ObjectPass1Shader::attrib_position, MeshShader::ObjectPass1Shader::attrib_texcoord, -1, MeshShader::ObjectPass1Shader::attrib_normal, -1, -1, -1, mesh.Stride);
mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::ShadowShader::attrib_position, -1, -1, -1, -1, -1, -1, mesh.Stride);
mesh.vao_rsm_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::RSMShader::attrib_position, MeshShader::RSMShader::attrib_texcoord, -1, MeshShader::RSMShader::attrib_normal, -1, -1, -1, mesh.Stride);
break;
case FPSM_ALPHA_REF_TEXTURE:
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,

View File

@ -1,11 +1,13 @@
#ifndef STKMESH_H
#define STKMESH_H
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include <IMeshSceneNode.h>
#include <IMesh.h>
#include "../lib/irrlicht/source/Irrlicht/CMeshSceneNode.h"
#include "glwrap.hpp"
#include <vector>
enum GeometricMaterial
@ -45,6 +47,7 @@ struct GLMesh {
GLuint vao_glow_pass;
GLuint vao_displace_pass;
GLuint vao_displace_mask_pass;
GLuint vao_rsm_pass;
GLuint vao_shadow_pass;
GLuint vertex_buffer;
GLuint index_buffer;
@ -89,9 +92,22 @@ std::vector<core::matrix4> GroupedFPSM<T>::MVPSet;
template<enum GeometricMaterial T>
std::vector<core::matrix4> GroupedFPSM<T>::TIMVSet;
void drawObjectPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView);
void drawNormalPass(const GLMesh &mesh, const core::matrix4 & ModelMatrix, const core::matrix4 &InverseModelMatrix);
void drawObjectRefPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &TextureMatrix);
template<typename Shader, typename...uniforms>
void draw(const GLMesh &mesh, GLuint vao, uniforms... Args)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
Shader::setUniforms(Args...);
assert(vao);
glBindVertexArray(vao);
glDrawElements(ptype, count, itype, 0);
}
void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, core::vector3df windDir);
// Pass 2 shader (ie shaders that outputs final color)

View File

@ -197,18 +197,9 @@ void STKMeshSceneNode::drawSolidPass1(const GLMesh &mesh, GeometricMaterial type
windDir = getWind();
switch (type)
{
case FPSM_NORMAL_MAP:
drawNormalPass(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
break;
case FPSM_ALPHA_REF_TEXTURE:
drawObjectRefPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView, mesh.TextureMatrix);
break;
case FPSM_GRASS:
drawGrassPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir);
break;
case FPSM_DEFAULT:
drawObjectPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
break;
default:
assert(0 && "wrong geometric material");
}

View File

@ -714,7 +714,13 @@ void Skin::drawButton(Widget* w, const core::recti &rect,
center.Y + (int)(((int)rect.LowerRightCorner.Y
- (int)center.Y)*texture_size);
if (focused)
if (w->m_deactivated)
{
drawBoxFromStretchableTexture(w, sized_rect,
SkinConfig::m_render_params["button::deactivated"],
w->m_deactivated);
}
else if (focused)
{
drawBoxFromStretchableTexture(w, sized_rect,
SkinConfig::m_render_params["button::focused"],
@ -725,11 +731,17 @@ void Skin::drawButton(Widget* w, const core::recti &rect,
drawBoxFromStretchableTexture(w, sized_rect,
SkinConfig::m_render_params["button::neutral"],
w->m_deactivated);
}
} // if not deactivated or focused
}
else // not within an appearing dialog
{
if (focused)
if (w->m_deactivated)
{
drawBoxFromStretchableTexture(w, rect,
SkinConfig::m_render_params["button::deactivated"],
w->m_deactivated);
}
else if (focused)
{
drawBoxFromStretchableTexture(w, rect,
SkinConfig::m_render_params["button::focused"],
@ -740,7 +752,7 @@ void Skin::drawButton(Widget* w, const core::recti &rect,
drawBoxFromStretchableTexture(w, rect,
SkinConfig::m_render_params["button::neutral"],
w->m_deactivated);
} // if not focused
} // if not deactivated or focused
} // not within an appearing dialog
} // drawButton
@ -818,7 +830,7 @@ void Skin::drawRatingBar(Widget *w, const core::recti &rect,
const int texture_w = texture->getSize().Width / 4;
const int texture_h = texture->getSize().Height;
const float aspect_ratio = 1.0f;
const int star_number = ratingBar->getStarNumber();
int star_h = rect.getHeight();
@ -830,7 +842,7 @@ void Skin::drawRatingBar(Widget *w, const core::recti &rect,
star_w = (int)(star_w * scale_factor);
star_h = (int)(star_h * scale_factor);
}
// center horizontally and vertically
const int x_from = rect.UpperLeftCorner.X;
const int y_from = rect.UpperLeftCorner.Y;
@ -853,9 +865,9 @@ void Skin::drawRatingBar(Widget *w, const core::recti &rect,
star_rect.UpperLeftCorner.Y = y_from;
star_rect.LowerRightCorner.X = x_from + (i + 1) * star_w;
star_rect.LowerRightCorner.Y = y_from + star_h;
int step = ratingBar->getStepsOfStar(i);
const core::recti source_area(texture_w * step, 0,
texture_w * (step + 1), texture_h);
@ -1236,7 +1248,11 @@ void Skin::drawSpinnerBody(const core::recti &rect, Widget* widget,
else if(player_id==3)
params=&SkinConfig::m_render_params["spinner4::neutral"];
}
else if (focused|| pressed)
else if (widget->m_deactivated)
{
params=&SkinConfig::m_render_params["spinner::deactivated"];
}
else if (focused || pressed)
{
params=&SkinConfig::m_render_params["spinner::focused"];
}
@ -1253,7 +1269,7 @@ void Skin::drawSpinnerBody(const core::recti &rect, Widget* widget,
rect2.LowerRightCorner.Y += 5;
drawBoxFromStretchableTexture(widget, rect2,
SkinConfig::m_render_params["squareFocusHalo::neutral"]);
}
else if (widget->isFocusedForPlayer(1))
@ -1314,7 +1330,7 @@ void Skin::drawSpinnerBody(const core::recti &rect, Widget* widget,
// ---- If this spinner is of "gauge" type, draw filling
const SpinnerWidget* w = dynamic_cast<const SpinnerWidget*>(widget);
if (w->isGauge() && !w->m_deactivated)
{
const int handle_size = (int)( widget->m_h*params->m_left_border
@ -1361,7 +1377,7 @@ void Skin::drawSpinnerChild(const core::recti &rect, Widget* widget,
{
if (!widget->isVisible()) return;
if (pressed)
if (!widget->m_deactivated && pressed)
{
Widget* spinner = widget->m_event_handler;
int areas = 0;
@ -1516,19 +1532,39 @@ void Skin::drawCheckBox(const core::recti &rect, Widget* widget, bool focused)
if (w->getState() == true)
{
texture = focused
? SkinConfig::m_render_params["checkbox::focused+checked"]
.getImage()
: SkinConfig::m_render_params["checkbox::neutral+checked"]
.getImage();
if (w->m_deactivated)
{
texture = SkinConfig::m_render_params["checkbox::deactivated+checked"]
.getImage();
}
else if(focused)
{
texture = SkinConfig::m_render_params["checkbox::focused+checked"]
.getImage();
}
else
{
texture = SkinConfig::m_render_params["checkbox::neutral+checked"]
.getImage();
}
}
else
{
texture = focused
? SkinConfig::m_render_params["checkbox::focused+unchecked"]
.getImage()
: SkinConfig::m_render_params["checkbox::neutral+unchecked"]
.getImage();
if (w->m_deactivated)
{
texture = SkinConfig::m_render_params["checkbox::deactivated+unchecked"]
.getImage();
}
else if(focused)
{
texture = SkinConfig::m_render_params["checkbox::focused+unchecked"]
.getImage();
}
else
{
texture = SkinConfig::m_render_params["checkbox::neutral+unchecked"]
.getImage();
}
}
const int texture_w = texture->getSize().Width;
@ -1651,7 +1687,7 @@ void Skin::renderSections(PtrVector<Widget>* within_vector)
drawBoxFromStretchableTexture(&widget, rect,
SkinConfig::m_render_params["section::neutral"]);
}
renderSections( &widget.m_children );
}
else if (widget.isBottomBar())

View File

@ -17,6 +17,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef ENABLE_WIIUSE
#define WCONST
#include "input/wiimote_manager.hpp"
@ -61,24 +62,99 @@ WiimoteManager::~WiimoteManager()
*/
void WiimoteManager::launchDetection(int timeout)
{
// It's only needed on systems with bluez, because wiiuse_find does not find alredy connected wiimotes
#ifdef WIIUSE_BLUEZ
//Cleans up the config and the disconnected wiimotes
int number_previous_wiimotes = 0;
wiimote_t** previous_wiimotes = (wiimote_t**) malloc(sizeof(struct wiimote_t*) * MAX_WIIMOTES);
memset(previous_wiimotes,0,sizeof(struct wiimote_t*) * MAX_WIIMOTES);
for (unsigned int i = 0; i < m_wiimotes.size(); i++)
{
if (WIIMOTE_IS_CONNECTED(m_all_wiimote_handles[i]))
{
previous_wiimotes[i]=m_all_wiimote_handles[i];
m_all_wiimote_handles[i] = NULL;
number_previous_wiimotes++;
}
}
//To prevent segmentation fault, have to delete NULLs
wiimote_t** deletable_wiimotes = (wiimote_t**) malloc(sizeof(struct wiimote_t*) * (m_wiimotes.size()-number_previous_wiimotes));
memset(deletable_wiimotes,0,sizeof(struct wiimote_t*) * (m_wiimotes.size()-number_previous_wiimotes));
int number_deletables = 0;
for (unsigned int i = 0; i < m_wiimotes.size(); i++)
{
if (m_all_wiimote_handles[i] != NULL)
{
deletable_wiimotes[number_deletables++] = m_all_wiimote_handles[i];
}
}
m_all_wiimote_handles = wiiuse_init(MAX_WIIMOTES);
wiiuse_cleanup(deletable_wiimotes, number_deletables);
#endif
// Stop WiiUse, remove wiimotes, gamepads, gamepad configs.
cleanup();
m_all_wiimote_handles = wiiuse_init(MAX_WIIMOTES);
m_all_wiimote_handles = wiiuse_init(MAX_WIIMOTES);
// Detect wiimotes
int nb_found_wiimotes = wiiuse_find(m_all_wiimote_handles, MAX_WIIMOTES, timeout);
#ifndef WIIUSE_BLUEZ
// Couldn't find any wiimote?
if(nb_found_wiimotes == 0)
return;
#endif
#ifdef WIIUSE_BLUEZ
// Couldn't find any wiimote?
if(nb_found_wiimotes + number_previous_wiimotes == 0)
return;
#endif
// Try to connect to all found wiimotes
int nb_wiimotes = wiiuse_connect(m_all_wiimote_handles, nb_found_wiimotes);
#ifndef WIIUSE_BLUEZ
// Couldn't connect to any wiimote?
if(nb_wiimotes == 0)
return;
#endif
#ifdef WIIUSE_BLUEZ
// Couldn't connect to any wiimote?
if(nb_wiimotes + number_previous_wiimotes == 0)
return;
//Merges previous and new wiimote's list
int number_merged_wiimotes = 0;
for (int i = 0; i < number_previous_wiimotes && i + nb_wiimotes < MAX_WIIMOTES; i++)
{
m_all_wiimote_handles[i+nb_wiimotes] = previous_wiimotes[i];
previous_wiimotes[i] = NULL;
m_all_wiimote_handles[i]->unid = nb_wiimotes+i+1;
number_merged_wiimotes++;
}
nb_wiimotes += number_merged_wiimotes;
//To prevent segmentation fault, have to delete NULLs
number_deletables = 0;
number_deletables = 0;
deletable_wiimotes = (wiimote_t**) malloc(sizeof(struct wiimote_t*) * (number_previous_wiimotes-number_merged_wiimotes));
memset(deletable_wiimotes,0,sizeof(struct wiimote_t*) * (number_previous_wiimotes-number_merged_wiimotes));
for (int i = 0; i < number_previous_wiimotes; i++)
{
if (previous_wiimotes[i] != NULL)
{
deletable_wiimotes[number_deletables++] = previous_wiimotes[i];
}
}
// Cleans up wiimotes which ones didn't fit in limit
wiiuse_cleanup(deletable_wiimotes, number_deletables);
#endif
// ---------------------------------------------------
// Create or find a GamepadConfig for all wiimotes

View File

@ -1213,7 +1213,47 @@ bool FileManager::removeDirectory(const std::string &name) const
#endif
} // remove directory
// ----------------------------------------------------------------------------
/** Copies the file source to dest.
* \param source The file to read.
* \param dest The new filename.
* \return True if the copy was successful, false otherwise.
*/
bool FileManager::copyFile(const std::string &source, const std::string &dest)
{
FILE *f_source = fopen(source.c_str(), "rb");
if(!f_source) return false;
FILE *f_dest = fopen(dest.c_str(), "wb");
if(!f_dest)
{
fclose(f_source);
return false;
}
const int BUFFER_SIZE=32768;
char *buffer = new char[BUFFER_SIZE];
if(!buffer) return false;
size_t n;
while((n=fread(buffer, 1, BUFFER_SIZE, f_source))>0)
{
if(fwrite(buffer, 1, n, f_dest)!=n)
{
Log::error("FileManager", "Write error copying '%s' to '%s",
source.c_str(), dest.c_str());
delete buffer;
fclose(f_source);
fclose(f_dest);
return false;
} // if fwrite()!=n
} // while
delete buffer;
fclose(f_source);
fclose(f_dest);
return true;
} // copyFile
// ----------------------------------------------------------------------------
/** Returns true if the first file is newer than the second. The comparison is
* based on the modification time of the two files.

View File

@ -123,6 +123,7 @@ public:
void checkAndCreateDirForAddons(const std::string &dir);
bool removeFile(const std::string &name) const;
bool removeDirectory(const std::string &name) const;
bool copyFile(const std::string &source, const std::string &dest);
std::vector<std::string>getMusicDirs() const;
std::string getAssetChecked(AssetType type, const std::string& name,
bool abort_on_error=false) const;

View File

@ -2291,7 +2291,7 @@ void Kart::updateFlying()
{
float orientation = getHeading();
m_body->applyCentralImpulse(btVector3(-100.0f*sin(orientation), 0.0,
-100.0*cos(orientation)));
-100.0f*cos(orientation)));
}
}

View File

@ -1,3 +1,4 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004-2013 Steve Baker <sjbaker1@airmail.net>
@ -187,9 +188,10 @@
#include "race/race_manager.hpp"
#include "replay/replay_play.hpp"
#include "replay/replay_recorder.hpp"
#include "states_screens/story_mode_lobby.hpp"
#include "states_screens/main_menu_screen.hpp"
#include "states_screens/register_screen.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
@ -383,6 +385,43 @@ void handleXmasMode()
if(xmas)
kart_properties_manager->setHatMeshName("christmas_hat.b3d");
} // handleXmasMode
// ============================================================================
/** This function sets up all data structure for an immediate race start.
* It is used when the -N or -R command line options are used.
*/
void setupRaceStart()
{
// Skip the start screen. This esp. means that no login screen is
// displayed (if necessary), so we have to make sure there is
// a current player
PlayerManager::get()->enforceCurrentPlayer();
InputDevice *device;
// Use keyboard 0 by default in --no-start-screen
device = input_manager->getDeviceList()->getKeyboard(0);
// Create player and associate player with keyboard
StateManager::get()->createActivePlayer(
PlayerManager::get()->getPlayer(0), device, NULL);
if (kart_properties_manager->getKart(UserConfigParams::m_default_kart) == NULL)
{
Log::warn("main", "Kart '%s' is unknown so will use the "
"default kart.",
UserConfigParams::m_default_kart.c_str());
race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart.getDefaultValue());
}
else
{
// Set up race manager appropriately
race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart);
}
// ASSIGN should make sure that only input from assigned devices
// is read.
input_manager->getDeviceList()->setAssignMode(ASSIGN);
} // setupRaceMode
// ----------------------------------------------------------------------------
/** Prints help for command line options to stdout.
@ -962,8 +1001,7 @@ int handleCmdLine()
{
irr::core::stringw s;
Online::XMLRequest* request =
PlayerManager::requestSignIn(login, password, false, false);
request->executeNow();
PlayerManager::requestSignIn(login, password);
if (request->isSuccess())
{
@ -1250,7 +1288,24 @@ int main(int argc, char *argv[] )
if(!UserConfigParams::m_no_start_screen)
{
StateManager::get()->pushScreen(StoryModeLobbyScreen::getInstance());
// If there is a current player, it was saved in the config file,
// so we immediately start the main menu (unless it was requested
// to always show the login screen). Otherwise show the login
// screen first.
if(PlayerManager::getCurrentPlayer() && !
UserConfigParams::m_always_show_login_screen)
{
StateManager::get()->pushScreen(MainMenuScreen::getInstance());
}
else
{
StateManager::get()->pushScreen(UserScreen::getInstance());
// If there is no player, push the RegisterScreen on top of
// the login screen. This way on first start players are
// forced to create a player.
if(PlayerManager::get()->getNumPlayers()==0)
StateManager::get()->pushScreen(RegisterScreen::getInstance());
}
#ifdef ENABLE_WIIUSE
// Show a dialog to allow connection of wiimotes. */
if(WiimoteManager::isEnabled())
@ -1262,37 +1317,7 @@ int main(int argc, char *argv[] )
}
else
{
// Skip the start screen. This esp. means that no login screen is
// displayed (if necessary), so we have to make sure there is
// a current player
PlayerManager::get()->enforceCurrentPlayer();
InputDevice *device;
// Use keyboard 0 by default in --no-start-screen
device = input_manager->getDeviceList()->getKeyboard(0);
// Create player and associate player with keyboard
StateManager::get()->createActivePlayer(
PlayerManager::get()->getPlayer(0), device, NULL);
if (kart_properties_manager->getKart(UserConfigParams::m_default_kart) == NULL)
{
Log::warn("main", "Kart '%s' is unknown so will use the "
"default kart.",
UserConfigParams::m_default_kart.c_str());
race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart.getDefaultValue());
}
else
{
// Set up race manager appropriately
race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart);
}
// ASSIGN should make sure that only input from assigned devices
// is read.
input_manager->getDeviceList()->setAssignMode(ASSIGN);
setupRaceStart();
// Go straight to the race
StateManager::get()->enterGameState();
}

View File

@ -85,6 +85,12 @@ namespace Online
return irr::core::stringw(_("Processing")) + loadingDots();
}
// ------------------------------------------------------------------------
/** Convenience function to type less in calls. */
irr::core::stringw loadingDots(const wchar_t *s)
{
return irr::core::stringw(s)+loadingDots();
}
// ------------------------------------------------------------------------
/**
* Shows a increasing number of dots.

View File

@ -31,6 +31,7 @@ namespace Online
namespace Messages
{
irr::core::stringw loadingDots (float interval = 0.5f, int max_dots = 3);
irr::core::stringw loadingDots (const wchar_t *s);
irr::core::stringw signingIn ();
irr::core::stringw signingOut ();
irr::core::stringw validatingInfo ();

View File

@ -27,11 +27,11 @@
#include "online/online_profile.hpp"
#include "online/profile_manager.hpp"
#include "online/servers_manager.hpp"
#include "states_screens/login_screen.hpp"
#include "states_screens/online_profile_friends.hpp"
#include "states_screens/user_screen.hpp"
#include "states_screens/dialogs/change_password_dialog.hpp"
#include "states_screens/dialogs/user_info_dialog.hpp"
#include "states_screens/dialogs/notification_dialog.hpp"
#include "states_screens/dialogs/user_info_dialog.hpp"
#include "utils/log.hpp"
#include "utils/translation.hpp"
@ -52,8 +52,8 @@ namespace Online
* \param action If not empty, the action to be set.
*/
void OnlinePlayerProfile::setUserDetails(HTTPRequest *request,
const std::string &action,
const std::string &php_script)
const std::string &action,
const std::string &php_script) const
{
if (php_script.size()>0)
request->setServerURL(php_script);
@ -74,7 +74,6 @@ namespace Online
{
m_online_state = OS_SIGNED_OUT;
m_token = "";
m_save_session = false;
m_profile = NULL;
} // OnlinePlayerProfile
@ -84,7 +83,6 @@ namespace Online
{
m_online_state = OS_SIGNED_OUT;
m_token = "";
m_save_session = false;
m_profile = NULL;
} // OnlinePlayerProfile
@ -94,11 +92,12 @@ namespace Online
void OnlinePlayerProfile::requestSavedSession()
{
SignInRequest * request = NULL;
if (m_online_state == OS_SIGNED_OUT && hasSavedSession() )
if (m_online_state == OS_SIGNED_OUT && hasSavedSession())
{
request = new SignInRequest(true);
request->setServerURL("client-user.php");
request->addParameter("action", "saved-session" );
setUserDetails(request, "saved-session");
// The userid must be taken from the saved data,
// setUserDetails takes it from current data.
request->addParameter("userid", getSavedUserId());
request->addParameter("token", getSavedToken() );
request->queue();
@ -110,29 +109,26 @@ namespace Online
/** Create a signin request.
* \param username Name of user.
* \param password Password.
* \param save_session If true, the login credential will be saved to
* allow a password-less login.
* \param request_now Immediately submit this request to the
* RequestManager.
*/
OnlinePlayerProfile::SignInRequest*
OnlinePlayerProfile::requestSignIn(const core::stringw &username,
const core::stringw &password,
bool save_session, bool request_now)
const core::stringw &password)
{
assert(m_online_state == OS_SIGNED_OUT);
m_save_session = save_session;
// If the player changes the online account, there can be a
// logout stil happening.
assert(m_online_state == OS_SIGNED_OUT ||
m_online_state == OS_SIGNING_OUT );
SignInRequest * request = new SignInRequest(false);
// We can't use setUserDetail here, since there is no token yet
request->setServerURL("client-user.php");
request->addParameter("action","connect");
request->addParameter("username",username);
request->addParameter("password",password);
request->addParameter("save-session", save_session);
if (request_now)
{
request->queue();
m_online_state = OS_SIGNING_IN;
}
request->addParameter("save-session",
UserConfigParams::m_remember_user ? "true"
: "false");
request->queue();
m_online_state = OS_SIGNING_IN;
return request;
} // requestSignIn
@ -143,7 +139,24 @@ namespace Online
{
PlayerManager::getCurrentPlayer()->signIn(isSuccess(), getXMLData());
GUIEngine::Screen *screen = GUIEngine::getCurrentScreen();
LoginScreen *login = dynamic_cast<LoginScreen*>(screen);
BaseUserScreen *login = dynamic_cast<BaseUserScreen*>(screen);
// If the login is successful, reset any saved session of other
// local players using the same online account (which are now invalid)
if(isSuccess())
{
PlayerProfile *current = PlayerManager::getCurrentPlayer();
for(unsigned int i=0; i<PlayerManager::get()->getNumPlayers(); i++)
{
PlayerProfile *player = PlayerManager::get()->getPlayer(i);
if(player!=current &&
player->hasSavedSession() &&
player->getLastOnlineName() == current->getLastOnlineName())
{
player->clearSession();
}
}
}
if(login)
{
if(isSuccess())
@ -170,10 +183,11 @@ namespace Online
int username_fetched = input->get("username", &username);
uint32_t userid(0);
int userid_fetched = input->get("userid", &userid);
setLastOnlineName(username);
m_profile = new OnlineProfile(userid, username, true);
assert(token_fetched && username_fetched && userid_fetched);
m_online_state = OS_SIGNED_IN;
if(doSaveSession())
if(UserConfigParams::m_remember_user)
{
saveSession(getOnlineId(), getToken() );
}
@ -194,38 +208,81 @@ namespace Online
} // signIn
// ------------------------------------------------------------------------
/** Requests a sign out from the server. If the user should be remembered,
* a 'client-quit' request is sent (which will log the user out, but
* remember the token), otherwise a 'disconnect' is sent.
*/
void OnlinePlayerProfile::requestSignOut()
{
assert(m_online_state == OS_SIGNED_IN || m_online_state == OS_GUEST);
SignOutRequest * request = new SignOutRequest();
request->setServerURL("client-user.php");
request->addParameter("action","disconnect");
request->addParameter("token", getToken());
request->addParameter("userid", getOnlineId());
// ----------------------------------------------------------------
class SignOutRequest : public XMLRequest
{
private:
PlayerProfile *m_player;
virtual void callback()
{
m_player->signOut(isSuccess(), getXMLData(), getInfo());
}
public:
/** Sign out request, which have the highest priority (same as
* quit-stk request). This allows the final logout request at
* the end of STK to be handled, even if a quit request gets
* added (otherwise if quit has higher priority, the quit can
* be executed before signout, resulting in players not being
* logged out properly). It also guarantees that the logout
* happens before a following logout.
*/
SignOutRequest(PlayerProfile *player)
: XMLRequest(true,/*priority*/RequestManager::HTTP_MAX_PRIORITY)
{
m_player = player;
m_player->setUserDetails(this,
UserConfigParams::m_remember_user ? "client-quit"
:"disconnect");
} // SignOutRequest
}; // SignOutRequest
// ----------------------------------------------------------------
HTTPRequest *request = new SignOutRequest(this);
request->queue();
m_online_state = OS_SIGNING_OUT;
} // requestSignOut
// --------------------------------------------------------------------
void OnlinePlayerProfile::SignOutRequest::callback()
{
PlayerManager::getCurrentPlayer()->signOut(isSuccess(), getXMLData());
} // SignOutRequest::callback
// ------------------------------------------------------------------------
void OnlinePlayerProfile::signOut(bool success, const XMLNode * input)
/** Callback once the logout event has been processed.
* \param success If the request was successful.
* \param input
*/
void OnlinePlayerProfile::signOut(bool success, const XMLNode *input,
const irr::core::stringw &info)
{
if(!success)
GUIEngine::Screen *screen = GUIEngine::getCurrentScreen();
BaseUserScreen *user_screen = dynamic_cast<BaseUserScreen*>(screen);
// We can't do much of error handling here, no screen waits for
// a logout to finish, so we can only log the message to screen,
// and otherwise mark the player logged out internally.
if (!success)
{
Log::warn("OnlinePlayerProfile::signOut", "%s",
Log::warn("OnlinePlayerProfile::signOut",
"There were some connection issues while signing out. "
"Report a bug if this caused issues.");
Log::warn("OnlinePlayerProfile::signOut", core::stringc(info.c_str()).c_str());
if(user_screen)
user_screen->logoutError(info);
}
m_token = "";
else
{
if(user_screen)
user_screen->logoutSuccessful();
}
ProfileManager::get()->clearPersistent();
m_profile = NULL;
m_online_state = OS_SIGNED_OUT;
PlayerManager::getCurrentPlayer()->clearSession();
// Discard token if session should not be saved.
if(!UserConfigParams::m_remember_user)
clearSession();
} // signOut
// ------------------------------------------------------------------------
@ -236,10 +293,7 @@ namespace Online
{
assert(m_online_state == OS_SIGNED_IN);
OnlinePlayerProfile::PollRequest * request = new OnlinePlayerProfile::PollRequest();
request->setServerURL("client-user.php");
request->addParameter("action", "poll");
request->addParameter("token", getToken());
request->addParameter("userid", getOnlineId());
setUserDetails(request, "poll");
request->queue();
} // requestPoll()
@ -379,24 +433,6 @@ namespace Online
} // PollRequest::callback
// ------------------------------------------------------------------------
/** Sends a message to the server that the client has been closed, if a
* user is signed in.
*/
void OnlinePlayerProfile::onSTKQuit() const
{
if(isLoggedIn())
{
HTTPRequest * request =
new HTTPRequest(true, RequestManager::HTTP_MAX_PRIORITY);
request->setServerURL("client-user.php");
request->addParameter("action", "client-quit");
request->addParameter("token", getToken());
request->addParameter("userid", getOnlineId());
request->queue();
}
}
// ------------------------------------------------------------------------
/** \return the online id, or 0 if the user is not signed in.
*/

View File

@ -58,14 +58,6 @@ namespace Online
: XMLRequest(manage_memory, /*priority*/10) {}
}; // SignInRequest
// ----------------------------------------------------------------
class SignOutRequest : public XMLRequest
{
virtual void callback ();
public:
SignOutRequest() : XMLRequest(true,/*priority*/10) {}
}; // SignOutRequest
// ----------------------------------------------------------------
class PollRequest : public XMLRequest {
virtual void callback ();
@ -75,38 +67,20 @@ namespace Online
private:
std::string m_token;
bool m_save_session;
OnlineProfile *m_profile;
/** The state of the player (logged in, logging in, ...) */
PlayerProfile::OnlineState m_online_state;
bool doSaveSession() const { return m_save_session; }
virtual void signIn(bool success, const XMLNode * input);
virtual void signOut(bool success, const XMLNode * input);
// For now declare functions that will become part of PlayerManager
// or Playerprofile to be private, and give only PlayerManager
// access to them. FIXME
// FIXME: This apparently does not compile on linux :(
// So for now (while this is needed) I'll only add this on
// windows only (where it works).
#ifdef WIN32
friend class PlayerManager;
public:
#else
public:
#endif
virtual void signOut(bool success, const XMLNode * input,
const irr::core::stringw &info);
virtual uint32_t getOnlineId() const;
virtual void setUserDetails(Online::HTTPRequest *request,
const std::string &action,
const std::string &php_script = "");
const std::string &php_script = "") const;
virtual void requestPoll() const;
virtual void onSTKQuit() const;
// ----------------------------------------------------------------
/** Returns if this user is logged in. */
virtual bool isLoggedIn() const
@ -131,9 +105,7 @@ namespace Online
virtual void requestSavedSession();
virtual void requestSignOut();
virtual SignInRequest *requestSignIn(const irr::core::stringw &username,
const irr::core::stringw &password,
bool save_session,
bool request_now = true);
const irr::core::stringw &password);
public:
OnlinePlayerProfile(const XMLNode *player);

View File

@ -21,6 +21,7 @@
#include "online/request_manager.hpp"
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "states_screens/state_manager.hpp"
#include <iostream>
@ -130,8 +131,12 @@ namespace Online
pthread_attr_destroy(&attr);
// In case that login id was not saved (or first start of stk),
// current player would not be defined at this stage.
if(PlayerManager::getCurrentPlayer())
PlayerProfile *player = PlayerManager::getCurrentPlayer();
if(player && player->wasOnlineLastTime() &&
!UserConfigParams::m_always_show_login_screen)
{
PlayerManager::resumeSavedSession();
}
} // startNetworkThread
// ------------------------------------------------------------------------

View File

@ -100,7 +100,7 @@ namespace Online{
break;
case SO_NAME:
// m_id is the lower case name
return m_name < server.getName();
return m_lower_case_name < server.m_lower_case_name;
break;
case SO_PLAYERS:
return m_current_players < server.getCurrentPlayers();
@ -109,28 +109,6 @@ namespace Online{
return true;
} // operator<
// ------------------------------------------------------------------------
/** Compares two addons according to the sort order currently defined.
* Comparison is done for sorting in descending order.
* \param a The addon to compare this addon to.
*/
bool operator>(const Server &server) const
{
switch(m_sort_order)
{
case SO_SCORE:
return m_satisfaction_score > server.getScore();
break;
case SO_NAME:
return m_lower_case_name > server.getLowerCaseName();
break;
case SO_PLAYERS:
return m_current_players > server.getCurrentPlayers();
break;
} // switch
return true;
} // operator>
}; // Server
} // namespace Online

View File

@ -555,13 +555,6 @@ namespace computeGPRanksData
(m_score == a.m_score && m_race_time < a.m_race_time) );
}
// --------------------------------------------------------------------
bool operator>(const SortData &a)
{
return ( (m_score < a.m_score) ||
(m_score == a.m_score && m_race_time > a.m_race_time) );
}
}; // SortData
} // namespace

View File

@ -24,7 +24,6 @@
#include "input/device_manager.hpp"
#include "input/input_manager.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "states_screens/options_screen_players.hpp"
#include "states_screens/options_screen_input.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/cpp2011.h"

View File

@ -51,11 +51,11 @@ DebugSliderDialog::DebugSliderDialog(std::string id, irr::core::stringw msg) :
float val;
if (m_id == "lwhite")
val = irr_driver->getLwhite() * 10.;
val = irr_driver->getLwhite() * 10.f;
if (m_id == "exposure")
val = irr_driver->getExposure() * 100.;
val = irr_driver->getExposure() * 100.f;
getWidget<SpinnerWidget>("value_slider")->setValue(val);
getWidget<SpinnerWidget>("value_slider")->setValue(int(val));
}
// ------------------------------------------------------------------------------------------------------
@ -83,9 +83,9 @@ GUIEngine::EventPropagation DebugSliderDialog::processEvent(const std::string& e
int value = getWidget<SpinnerWidget>("value_slider")->getValue();
Log::info("DebugSlider", "Value for <%s> : %i", m_id.c_str(), value);
if (m_id == "lwhite")
irr_driver->setLwhite(value / 10.);
irr_driver->setLwhite(value / 10.f);
if (m_id == "exposure")
irr_driver->setExposure(value / 100.);
irr_driver->setExposure(value / 100.f);
return GUIEngine::EVENT_BLOCK;
}

View File

@ -1,162 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "states_screens/dialogs/enter_player_name_dialog.hpp"
#include <IGUIEnvironment.h>
#include "audio/sfx_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
#include "config/player_profile.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/widgets/button_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
#include "utils/string_utils.hpp"
using namespace GUIEngine;
using namespace irr;
using namespace irr::core;
using namespace irr::gui;
// -----------------------------------------------------------------------------
EnterPlayerNameDialog::EnterPlayerNameDialog(INewPlayerListener* listener,
const float w, const float h) :
ModalDialog(w, h)
{
m_listener = listener;
m_self_destroy = false;
loadFromFile("enter_player_name_dialog.stkgui");
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
assert(textCtrl != NULL);
textCtrl->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
//if (translations->isRTLLanguage()) textCtrl->addListener(this);
}
// -----------------------------------------------------------------------------
EnterPlayerNameDialog::~EnterPlayerNameDialog()
{
// FIXME: what is this code for?
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
textCtrl->getIrrlichtElement()->remove();
textCtrl->clearListeners();
}
// -----------------------------------------------------------------------------
/*
void EnterPlayerNameDialog::onTextUpdated()
{
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
LabelWidget* lbl = getWidget<LabelWidget>("preview");
lbl->setText( core::stringw(translations->fribidize(textCtrl->getText())), false );
}
*/
// -----------------------------------------------------------------------------
GUIEngine::EventPropagation EnterPlayerNameDialog::processEvent(const std::string& eventSource)
{
if (eventSource == "cancel")
{
dismiss();
return GUIEngine::EVENT_BLOCK;
}
return GUIEngine::EVENT_LET;
}
// -----------------------------------------------------------------------------
void EnterPlayerNameDialog::onEnterPressedInternal()
{
// ---- Cancel button pressed
const int playerID = PLAYER_ID_GAME_MASTER;
ButtonWidget* cancelButton = getWidget<ButtonWidget>("cancel");
if (GUIEngine::isFocusedForPlayer(cancelButton, playerID))
{
std::string fakeEvent = "cancel";
processEvent(fakeEvent);
return;
}
// ---- Otherwise, see if we can accept the new name
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
stringw player_name = textCtrl->getText().trim();
if (StringUtils::notEmpty(player_name))
{
// check for duplicates
const int amount = PlayerManager::get()->getNumPlayers();
for (int n=0; n<amount; n++)
{
if (PlayerManager::get()->getPlayer(n)->getName() == player_name)
{
LabelWidget* label = getWidget<LabelWidget>("title");
label->setText(_("Cannot add a player with this name."), false);
sfx_manager->quickSound( "anvil" );
return;
}
}
// Finally, add the new player.
PlayerManager::get()->addNewPlayer(player_name);
PlayerManager::get()->save();
// It's unsafe to delete from inside the event handler so we do it
// in onUpdate (which checks for m_self_destroy)
m_self_destroy = true;
} // if valid name
else
{
LabelWidget* label = getWidget<LabelWidget>("title");
label->setText(_("Cannot add a player with this name."), false);
sfx_manager->quickSound( "anvil" );
}
}
// -----------------------------------------------------------------------------
void EnterPlayerNameDialog::onUpdate(float dt)
{
// It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy)
{
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
stringw player_name = textCtrl->getText().trim();
// irrLicht is too stupid to remove focus from deleted widgets
// so do it by hand
GUIEngine::getGUIEnv()->removeFocus( textCtrl->getIrrlichtElement() );
GUIEngine::getGUIEnv()->removeFocus( m_irrlicht_window );
// we will destroy the dialog before notifying the listener to be safer.
// but in order not to crash we must make a local copy of the listern
// otherwise we will crash
INewPlayerListener* listener = m_listener;
ModalDialog::dismiss();
if (listener != NULL) listener->onNewPlayerWithName( player_name );
}
}

View File

@ -1,71 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_ENTERPLAYERNAME_DIALOG_HPP
#define HEADER_ENTERPLAYERNAME_DIALOG_HPP
#include <irrString.h>
#include "guiengine/modaldialog.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
namespace GUIEngine
{
class TextBoxWidget;
class ButtonWidget;
class LabelWidget;
}
/**
* \brief Dialog that allows the player to enter the name for a new player
* \ingroup states_screens
*/
class EnterPlayerNameDialog : public GUIEngine::ModalDialog//, public GUIEngine::ITextBoxWidgetListener
{
public:
class INewPlayerListener
{
public:
virtual void onNewPlayerWithName(const irr::core::stringw& newName) = 0;
virtual ~INewPlayerListener(){}
};
private:
INewPlayerListener* m_listener;
bool m_self_destroy;
public:
/**
* Creates a modal dialog with given percentage of screen width and height
*/
EnterPlayerNameDialog(INewPlayerListener* listener, const float percentWidth,
const float percentHeight);
~EnterPlayerNameDialog();
void onEnterPressedInternal();
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
virtual void onUpdate(float dt);
//virtual void onTextUpdated();
};
#endif

View File

@ -1,312 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "states_screens/dialogs/player_info_dialog.hpp"
#include <IGUIStaticText.h>
#include <IGUIEnvironment.h>
#include "audio/sfx_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
#include "config/player_profile.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/widgets/button_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/scalable_font.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include "states_screens/options_screen_players.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
using namespace GUIEngine;
using namespace irr::gui;
using namespace irr::core;
// -----------------------------------------------------------------------------
/** Creates a modal dialog with given percentage of screen width and height.
*/
PlayerInfoDialog::PlayerInfoDialog(PlayerProfile* player, const float w,
const float h)
: ModalDialog(w, h)
{
m_player = player;
doInit();
showRegularDialog();
} // PlayerInfoDialog
// -----------------------------------------------------------------------------
/** When the dialog is finished, select the just edited player again in the
* option screen.
*/
PlayerInfoDialog::~PlayerInfoDialog()
{
if (m_player != NULL)
{
OptionsScreenPlayers::getInstance()->selectPlayer(
translations->fribidize(m_player->getName()) );
}
} // ~PlayerInfoDialog
// -----------------------------------------------------------------------------
/** Show the current data of this player.
*/
void PlayerInfoDialog::showRegularDialog()
{
if (m_irrlicht_window)
clearWindow();
const int y1 = m_area.getHeight()/6;
const int y2 = m_area.getHeight()*2/6;
const int y3 = m_area.getHeight()*3/6;
const int y4 = m_area.getHeight()*5/6;
ScalableFont* font = GUIEngine::getFont();
const int textHeight = GUIEngine::getFontHeight();
const int buttonHeight = textHeight + 10;
{
textCtrl = new TextBoxWidget();
textCtrl->m_properties[PROP_ID] = "newname";
textCtrl->setText(m_player->getName());
textCtrl->m_x = 50;
textCtrl->m_y = y1 - textHeight/2;
textCtrl->m_w = m_area.getWidth()-100;
textCtrl->m_h = textHeight + 5;
textCtrl->setParent(m_irrlicht_window);
m_widgets.push_back(textCtrl);
textCtrl->add();
}
{
ButtonWidget* widget = new ButtonWidget();
widget->m_properties[PROP_ID] = "renameplayer";
//I18N: In the player info dialog
widget->setText( _("Rename") );
const int textWidth =
font->getDimension( widget->getText().c_str() ).Width + 40;
widget->m_x = m_area.getWidth()/2 - textWidth/2;
widget->m_y = y2;
widget->m_w = textWidth;
widget->m_h = buttonHeight;
widget->setParent(m_irrlicht_window);
m_widgets.push_back(widget);
widget->add();
}
{
ButtonWidget* widget = new ButtonWidget();
widget->m_properties[PROP_ID] = "cancel";
widget->setText( _("Cancel") );
const int textWidth =
font->getDimension(widget->getText().c_str()).Width + 40;
widget->m_x = m_area.getWidth()/2 - textWidth/2;
widget->m_y = y3;
widget->m_w = textWidth;
widget->m_h = buttonHeight;
widget->setParent(m_irrlicht_window);
m_widgets.push_back(widget);
widget->add();
}
{
ButtonWidget* widget = new ButtonWidget();
widget->m_properties[PROP_ID] = "removeplayer";
//I18N: In the player info dialog
widget->setText( _("Remove"));
const int textWidth =
font->getDimension(widget->getText().c_str()).Width + 40;
widget->m_x = m_area.getWidth()/2 - textWidth/2;
widget->m_y = y4;
widget->m_w = textWidth;
widget->m_h = buttonHeight;
widget->setParent(m_irrlicht_window);
m_widgets.push_back(widget);
widget->add();
}
textCtrl->setFocusForPlayer( PLAYER_ID_GAME_MASTER );
} // showRegularDialog
// -----------------------------------------------------------------------------
/** Changes this dialog to confirm the changes.
*/
void PlayerInfoDialog::showConfirmDialog()
{
clearWindow();
IGUIFont* font = GUIEngine::getFont();
const int textHeight = GUIEngine::getFontHeight();
const int buttonHeight = textHeight + 10;
irr::core::stringw message =
//I18N: In the player info dialog (when deleting)
_("Do you really want to delete player '%s' ?", m_player->getName());
if (PlayerManager::getCurrentPlayer() == m_player)
{
message = _("You cannot delete this player "
"because it is currently in use.");
}
core::rect< s32 > area_left(5, 0, m_area.getWidth()-5, m_area.getHeight()/2);
// When there is no need to tab through / click on images/labels,
// we can add irrlicht labels directly
// (more complicated uses require the use of our widget set)
IGUIStaticText* a = GUIEngine::getGUIEnv()->addStaticText( message.c_str(),
area_left, false /* border */,
true /* word wrap */,
m_irrlicht_window);
a->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
if (PlayerManager::getCurrentPlayer() != m_player)
{
ButtonWidget* widget = new ButtonWidget();
widget->m_properties[PROP_ID] = "confirmremove";
//I18N: In the player info dialog (when deleting)
widget->setText( _("Confirm Remove") );
const int textWidth =
font->getDimension(widget->getText().c_str()).Width + 40;
widget->m_x = m_area.getWidth()/2 - textWidth/2;
widget->m_y = m_area.getHeight()/2;
widget->m_w = textWidth;
widget->m_h = buttonHeight;
widget->setParent(m_irrlicht_window);
m_widgets.push_back(widget);
widget->add();
}
{
ButtonWidget* widget = new ButtonWidget();
widget->m_properties[PROP_ID] = "cancelremove";
//I18N: In the player info dialog (when deleting)
widget->setText( _("Cancel Remove") );
const int textWidth =
font->getDimension( widget->getText().c_str() ).Width + 40;
widget->m_x = m_area.getWidth()/2 - textWidth/2;
widget->m_y = m_area.getHeight()*3/4;
widget->m_w = textWidth;
widget->m_h = buttonHeight;
widget->setParent(m_irrlicht_window);
m_widgets.push_back(widget);
widget->add();
widget->setFocusForPlayer( PLAYER_ID_GAME_MASTER );
}
} // showConfirmDialog
// -----------------------------------------------------------------------------
void PlayerInfoDialog::onEnterPressedInternal()
{
} // onEnterPressedInternal
// -----------------------------------------------------------------------------
GUIEngine::EventPropagation
PlayerInfoDialog::processEvent(const std::string& eventSource)
{
if (eventSource == "renameplayer")
{
// accept entered name
stringw player_name = textCtrl->getText().trim();
const int player_amount = PlayerManager::get()->getNumPlayers();
for(int n=0; n<player_amount; n++)
{
const PlayerProfile *player = PlayerManager::get()->getPlayer(n);
if (player == m_player) continue;
if (player->getName() == player_name)
{
ButtonWidget* label = getWidget<ButtonWidget>("renameplayer");
label->setBadge(BAD_BADGE);
sfx_manager->quickSound( "anvil" );
return GUIEngine::EVENT_BLOCK;
}
}
if (player_name.size() <= 0) return GUIEngine::EVENT_BLOCK;
OptionsScreenPlayers::getInstance()->renamePlayer(player_name,m_player);
// irrLicht is too stupid to remove focus from deleted widgets
// so do it by hand
GUIEngine::getGUIEnv()->removeFocus( textCtrl->getIrrlichtElement() );
GUIEngine::getGUIEnv()->removeFocus( m_irrlicht_window );
ModalDialog::dismiss();
dismiss();
return GUIEngine::EVENT_BLOCK;
}
else if (eventSource == "removeplayer")
{
showConfirmDialog();
return GUIEngine::EVENT_BLOCK;
}
else if (eventSource == "confirmremove")
{
OptionsScreenPlayers::getInstance()->deletePlayer( m_player );
m_player = NULL;
// irrLicht is too stupid to remove focus from deleted widgets
// so do it by hand
GUIEngine::getGUIEnv()->removeFocus( textCtrl->getIrrlichtElement() );
GUIEngine::getGUIEnv()->removeFocus( m_irrlicht_window );
ModalDialog::dismiss();
return GUIEngine::EVENT_BLOCK;
}
else if(eventSource == "cancelremove")
{
showRegularDialog();
return GUIEngine::EVENT_BLOCK;
}
else if(eventSource == "cancel")
{
// irrLicht is too stupid to remove focus from deleted widgets
// so do it by hand
GUIEngine::getGUIEnv()->removeFocus( textCtrl->getIrrlichtElement() );
GUIEngine::getGUIEnv()->removeFocus( m_irrlicht_window );
ModalDialog::dismiss();
return GUIEngine::EVENT_BLOCK;
}
return GUIEngine::EVENT_LET;
} // processEvent
// -----------------------------------------------------------------------------

View File

@ -1,53 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_PLAYERINFO_DIALOG_HPP
#define HEADER_PLAYERINFO_DIALOG_HPP
#include "guiengine/modaldialog.hpp"
class PlayerProfile;
namespace GUIEngine
{
class TextBoxWidget;
}
/**
* \brief Dialog that allows renaming and deleting players
* \ingroup states_screens
*/
class PlayerInfoDialog : public GUIEngine::ModalDialog
{
GUIEngine::TextBoxWidget* textCtrl;
PlayerProfile* m_player;
void showRegularDialog();
void showConfirmDialog();
public:
PlayerInfoDialog(PlayerProfile* PlayerInfoDialog,
const float percentWidth, const float percentHeight);
virtual ~PlayerInfoDialog();
void onEnterPressedInternal();
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
};
#endif

View File

@ -135,7 +135,8 @@ SelectChallengeDialog::SelectChallengeDialog(const float percentWidth,
}
else
{
const wchar_t* track_name = track_manager->getTrack(c->getData()->getTrackId())->getName();
const core::stringw track_name =
track_manager->getTrack(c->getData()->getTrackId())->getName();
getWidget<LabelWidget>("title")->setText( track_name, true );
}

View File

@ -1,78 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "states_screens/guest_login_screen.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "states_screens/login_screen.hpp"
#include "states_screens/register_screen.hpp"
#include "states_screens/state_manager.hpp"
using namespace GUIEngine;
DEFINE_SCREEN_SINGLETON( GuestLoginScreen );
// -----------------------------------------------------------------------------
GuestLoginScreen::GuestLoginScreen() : Screen("online/guest_login.stkgui")
{
} // GuestLoginScreen
// -----------------------------------------------------------------------------
/** Make sure this tab is actually selected.
*/
void GuestLoginScreen::init()
{
Screen::init();
RibbonWidget* tabs = this->getWidget<RibbonWidget>("login_tabs");
if (tabs) tabs->select( "tab_guest_login", PLAYER_ID_GAME_MASTER );
} // init
// -----------------------------------------------------------------------------
void GuestLoginScreen::eventCallback(Widget* widget, const std::string& name,
const int playerID)
{
if (name == "login_tabs")
{
const std::string selection =
((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == "tab_login")
StateManager::get()->replaceTopMostScreen(LoginScreen::getInstance());
else if (selection == "tab_register")
StateManager::get()->replaceTopMostScreen(RegisterScreen::getInstance());
}
else if (name=="options")
{
const std::string button =
getWidget<RibbonWidget>("options")
->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if(button=="sign_in")
{
// FIXME TODO: guest login
}
else if(button=="cancel")
StateManager::get()->escapePressed();
}
else if (name == "back")
{
StateManager::get()->escapePressed();
}
} // eventCallback
// -----------------------------------------------------------------------------

View File

@ -1,48 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_GUEST_LOGIN_SCREEN_HPP
#define HEADER_GUEST_LOGIN_SCREEN_HPP
#include "guiengine/screen.hpp"
namespace GUIEngine { class Widget; }
/**
* \brief Gest-Login screen.
* \ingroup states_screens
*/
class GuestLoginScreen : public GUIEngine::Screen,
public GUIEngine::ScreenSingleton<GuestLoginScreen>
{
friend class GUIEngine::ScreenSingleton<GuestLoginScreen>;
GuestLoginScreen();
public:
virtual void init() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() OVERRIDE {};
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void eventCallback(GUIEngine::Widget* widget,
const std::string& name,
const int playerID) OVERRIDE;
}; // GuestLoginScreen
#endif

View File

@ -1,189 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "states_screens/login_screen.hpp"
#include "audio/sfx_manager.hpp"
#include "config/player_manager.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
#include "online/messages.hpp"
#include "states_screens/guest_login_screen.hpp"
#include "states_screens/online_screen.hpp"
#include "states_screens/register_screen.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/dialogs/recovery_dialog.hpp"
#include "utils/log.hpp"
#include "utils/translation.hpp"
#include <irrString.h>
using namespace GUIEngine;
using namespace irr;
DEFINE_SCREEN_SINGLETON( LoginScreen );
// -----------------------------------------------------------------------------
LoginScreen::LoginScreen() : Screen("online/login.stkgui")
{
} // LoginScreen
// -----------------------------------------------------------------------------
void LoginScreen::init()
{
Screen::init();
// Make sure this tab is actually focused.
RibbonWidget* tabs = this->getWidget<RibbonWidget>("login_tabs");
if (tabs) tabs->select( "tab_login", PLAYER_ID_GAME_MASTER );
TextBoxWidget *password_widget = getWidget<TextBoxWidget>("password");
password_widget->setPasswordBox(true,L'*');
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget);
m_options_widget->setActivated();
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
m_success = false;
// As default don't select 'remember'
getWidget<CheckBoxWidget>("remember")->setState(false);
} // init
// -----------------------------------------------------------------------------
/** Collects the data entered into the gui and submits a login request.
* The login request is processes asynchronously b the ReqeustManager.
*/
void LoginScreen::login()
{
// Reset any potential error message shown.
LabelWidget *info_widget = getWidget<LabelWidget>("info");
info_widget->setDefaultColor();
info_widget->setText("", false);
const core::stringw username = getWidget<TextBoxWidget>("username")
->getText().trim();
const core::stringw password = getWidget<TextBoxWidget>("password")
->getText().trim();
if (username.size() < 4 || username.size() > 30 ||
password.size() < 8 || password.size() > 30 )
{
sfx_manager->quickSound("anvil");
info_widget->setErrorColor();
info_widget->setText(_("Username and/or password too short or too long."),
false);
}
else
{
m_options_widget->setDeactivated();
info_widget->setDefaultColor();
bool remember = getWidget<CheckBoxWidget>("remember")->getState();
PlayerManager::requestSignIn(username, password, remember);
}
} // login
// -----------------------------------------------------------------------------
/** Called from the login request when it was successfully exected.
*/
void LoginScreen::loginSuccessful()
{
// The callback is done from the main thread, so no need to sync
// access to m_success
m_success = true;
} // loginSuccessful
// -----------------------------------------------------------------------------
/** Called from the login request when the login was not successful.
* \param error_message The error message from the server (or curl).
*/
void LoginScreen::loginError(const irr::core::stringw & error_message)
{
sfx_manager->quickSound("anvil");
LabelWidget *info_widget = getWidget<LabelWidget>("info");
info_widget->setErrorColor();
info_widget->setText(error_message, false);
m_options_widget->setActivated();
} // loginError
// -----------------------------------------------------------------------------
/** Called in each frame. If a successful login is detected, the online screen
* will be displayed.
*/
void LoginScreen::onUpdate(float dt)
{
if(!m_options_widget->isActivated())
m_info_widget->setText(Online::Messages::signingIn(), false);
// Login was successful, so put the online main menu on the screen
if(m_success)
{
StateManager::get()->replaceTopMostScreen(OnlineScreen::getInstance());
}
} // onUpdate
// -----------------------------------------------------------------------------
/** Called when the user clicks on a widget.
* \param widget that was clicked on.
* \param name Name of the widget.
* \param playerID The id of the player who clicked the item.
*/
void LoginScreen::eventCallback(Widget* widget, const std::string& name,
const int playerID)
{
if (name == "login_tabs")
{
StateManager *sm = StateManager::get();
const std::string selection =
((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == "tab_guest_login")
sm->replaceTopMostScreen(GuestLoginScreen::getInstance());
else if (selection == "tab_register")
sm->replaceTopMostScreen(RegisterScreen::getInstance());
}
else if (name=="options")
{
const std::string button =
getWidget<RibbonWidget>("options")
->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if(button=="sign_in")
{
login();
}
else if(button=="recovery")
{
new RecoveryDialog();
}
else if(button=="cancel")
StateManager::get()->escapePressed();
}
else if (name == "back")
{
StateManager::get()->escapePressed();
}
} // eventCallback
// -----------------------------------------------------------------------------

View File

@ -1,63 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_LOGIN_SCREEN_HPP
#define HEADER_LOGIN_SCREEN_HPP
#include "guiengine/screen.hpp"
namespace GUIEngine { class LabelWidget;
class RibbonWidget;
class Widget; }
/**
* \brief Login screen.
* \ingroup states_screens
*/
class LoginScreen : public GUIEngine::Screen,
public GUIEngine::ScreenSingleton<LoginScreen>
{
private:
friend class GUIEngine::ScreenSingleton<LoginScreen>;
LoginScreen();
void login();
/** Store a pointer to the options buttons. */
GUIEngine::RibbonWidget *m_options_widget;
GUIEngine::LabelWidget * m_info_widget;
bool m_success;
public:
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() OVERRIDE {};
virtual void init() OVERRIDE;
virtual void onUpdate(float dt) OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void eventCallback(GUIEngine::Widget* widget,
const std::string& name,
const int playerID) OVERRIDE;
void loginSuccessful();
void loginError(const irr::core::stringw & error_message);
}; // class LoginScreen
#endif

View File

@ -41,11 +41,11 @@
#include "states_screens/credits.hpp"
#include "states_screens/grand_prix_editor_screen.hpp"
#include "states_screens/help_screen_1.hpp"
#include "states_screens/login_screen.hpp"
#include "states_screens/offline_kart_selection.hpp"
#include "states_screens/online_screen.hpp"
#include "states_screens/options_screen_video.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
#if DEBUG_MENU_ITEM
#include "states_screens/feature_unlocked.hpp"
#include "states_screens/grand_prix_lose.hpp"
@ -424,7 +424,10 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
if (PlayerManager::getCurrentOnlineId())
StateManager::get()->pushScreen(OnlineScreen::getInstance());
else
StateManager::get()->pushScreen(LoginScreen::getInstance());
{
BaseUserScreen *login = UserScreen::getInstance();
StateManager::get()->pushScreen(login);
}
}
else if (selection == "addons")
{

View File

@ -28,10 +28,10 @@
#include "guiengine/widget.hpp"
#include "io/file_manager.hpp"
#include "states_screens/options_screen_input.hpp"
#include "states_screens/options_screen_players.hpp"
#include "states_screens/options_screen_ui.hpp"
#include "states_screens/options_screen_video.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
#include "utils/translation.hpp"
#include <iostream>
@ -107,7 +107,7 @@ void OptionsScreenAudio::eventCallback(Widget* widget, const std::string& name,
if (selection == "tab_audio") StateManager::get()->replaceTopMostScreen(OptionsScreenAudio::getInstance());
else if (selection == "tab_video") StateManager::get()->replaceTopMostScreen(OptionsScreenVideo::getInstance());
else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(OptionsScreenPlayers::getInstance());
else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(TabbedUserScreen::getInstance());
else if (selection == "tab_controls") StateManager::get()->replaceTopMostScreen(OptionsScreenInput::getInstance());
else if (selection == "tab_ui") StateManager::get()->replaceTopMostScreen(OptionsScreenUI::getInstance());
}

View File

@ -29,11 +29,11 @@
#include "io/file_manager.hpp"
#include "states_screens/options_screen_input2.hpp"
#include "states_screens/options_screen_audio.hpp"
#include "states_screens/options_screen_players.hpp"
#include "states_screens/options_screen_video.hpp"
#include "states_screens/options_screen_ui.hpp"
#include "states_screens/dialogs/add_device_dialog.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
@ -188,7 +188,7 @@ void OptionsScreenInput::eventCallback(Widget* widget, const std::string& name,
if (selection == "tab_audio") StateManager::get()->replaceTopMostScreen(OptionsScreenAudio::getInstance());
else if (selection == "tab_video") StateManager::get()->replaceTopMostScreen(OptionsScreenVideo::getInstance());
else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(OptionsScreenPlayers::getInstance());
else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(TabbedUserScreen::getInstance());
else if (selection == "tab_controls") StateManager::get()->replaceTopMostScreen(OptionsScreenInput::getInstance());
else if (selection == "tab_ui") StateManager::get()->replaceTopMostScreen(OptionsScreenUI::getInstance());
}

View File

@ -32,10 +32,10 @@
#include "states_screens/dialogs/press_a_key_dialog.hpp"
#include "states_screens/options_screen_audio.hpp"
#include "states_screens/options_screen_input.hpp"
#include "states_screens/options_screen_players.hpp"
#include "states_screens/options_screen_video.hpp"
#include "states_screens/options_screen_ui.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
#include "utils/translation.hpp"
#include <iostream>
@ -320,7 +320,7 @@ void OptionsScreenInput2::updateInputButtons()
getWidget<GUIEngine::LabelWidget>("conflict");
if (conflicts)
conflict_label->setText(
_("* A blue item means a conflict with another configuration") );
_("* A red item means a conflict with another configuration") );
else
conflict_label->setText("");
@ -442,7 +442,7 @@ void OptionsScreenInput2::eventCallback(Widget* widget,
else if (selection == "tab_video")
sm->replaceTopMostScreen(OptionsScreenVideo::getInstance());
else if (selection == "tab_players")
sm->replaceTopMostScreen(OptionsScreenPlayers::getInstance());
sm->replaceTopMostScreen(UserScreen::getInstance());
else if (selection == "tab_ui")
sm->replaceTopMostScreen(OptionsScreenUI::getInstance());
else if (selection == "tab_controls") {}
@ -453,7 +453,7 @@ void OptionsScreenInput2::eventCallback(Widget* widget,
}
else if (name == "back")
{
sm->popMenu();
sm->replaceTopMostScreen(OptionsScreenInput::getInstance());
}
else if (name == "actions")
{

View File

@ -1,228 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "states_screens/options_screen_players.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/device_config.hpp"
#include "config/player_manager.hpp"
#include "config/player_profile.hpp"
#include "config/user_config.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/scalable_font.hpp"
#include "guiengine/screen.hpp"
#include "guiengine/widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "states_screens/dialogs/enter_player_name_dialog.hpp"
#include "states_screens/dialogs/player_info_dialog.hpp"
#include "states_screens/options_screen_audio.hpp"
#include "states_screens/options_screen_input.hpp"
#include "states_screens/options_screen_video.hpp"
#include "states_screens/options_screen_ui.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/story_mode_lobby.hpp"
#include <IGUIButton.h>
#include <iostream>
#include <sstream>
using namespace GUIEngine;
using namespace irr::core;
using namespace irr::gui;
DEFINE_SCREEN_SINGLETON( OptionsScreenPlayers );
// -----------------------------------------------------------------------------
OptionsScreenPlayers::OptionsScreenPlayers() : Screen("options_players.stkgui")
{
} // OptionsScreenPlayers
// -----------------------------------------------------------------------------
void OptionsScreenPlayers::loadedFromFile()
{
} // loadedFromFile
// -----------------------------------------------------------------------------
void OptionsScreenPlayers::init()
{
Screen::init();
RibbonWidget* tabBar = this->getWidget<RibbonWidget>("options_choice");
if (tabBar != NULL) tabBar->select( "tab_players", PLAYER_ID_GAME_MASTER );
tabBar->getRibbonChildren()[0].setTooltip( _("Graphics") );
tabBar->getRibbonChildren()[1].setTooltip( _("Audio") );
tabBar->getRibbonChildren()[2].setTooltip( _("User Interface") );
tabBar->getRibbonChildren()[4].setTooltip( _("Controls") );
ListWidget* players = this->getWidget<ListWidget>("players");
assert(players != NULL);
refreshPlayerList();
ButtonWidget* you = getWidget<ButtonWidget>("playername");
unsigned int playerID = PlayerManager::getCurrentPlayer()->getUniqueID();
core::stringw player_name = L"-";
const PlayerProfile* curr = PlayerManager::get()->getPlayerById(playerID);
if(curr)
player_name = curr->getName();
you->setText( player_name );
((gui::IGUIButton*)you->getIrrlichtElement())->setOverrideFont( GUIEngine::getSmallFont() );
if (StateManager::get()->getGameState() == GUIEngine::INGAME_MENU)
{
players->setDeactivated();
you->setDeactivated();
}
else
{
players->setActivated();
you->setActivated();
}
} // init
// -----------------------------------------------------------------------------
bool OptionsScreenPlayers::renamePlayer(const stringw& newName, PlayerProfile* player)
{
player->setName( newName );
refreshPlayerList();
return true;
} // renamePlayer
// -----------------------------------------------------------------------------
void OptionsScreenPlayers::onNewPlayerWithName(const stringw& newName)
{
ListWidget* players = this->getWidget<ListWidget>("players");
if (players != NULL)
{
core::stringc newNameC(newName.c_str());
players->addItem( newNameC.c_str(), translations->fribidize(newName) );
}
}
// -----------------------------------------------------------------------------
void OptionsScreenPlayers::deletePlayer(PlayerProfile* player)
{
PlayerManager::get()->deletePlayer(player);
refreshPlayerList();
} // deletePlayer
// -----------------------------------------------------------------------------
void OptionsScreenPlayers::tearDown()
{
Screen::tearDown();
user_config->saveConfig();
} // tearDown
// -----------------------------------------------------------------------------
void OptionsScreenPlayers::eventCallback(Widget* widget, const std::string& name, const int playerID)
{
if (name == "options_choice")
{
std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str();
if (selection == "tab_audio") StateManager::get()->replaceTopMostScreen(OptionsScreenAudio::getInstance());
else if (selection == "tab_video") StateManager::get()->replaceTopMostScreen(OptionsScreenVideo::getInstance());
else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(OptionsScreenPlayers::getInstance());
else if (selection == "tab_controls") StateManager::get()->replaceTopMostScreen(OptionsScreenInput::getInstance());
else if (selection == "tab_ui") StateManager::get()->replaceTopMostScreen(OptionsScreenUI::getInstance());
}
else if (name == "back")
{
StateManager::get()->escapePressed();
}
else if (name == "addplayer")
{
new EnterPlayerNameDialog(this, 0.5f, 0.4f);
}
else if (name == "players")
{
// Find which player in the list was clicked
ListWidget* players = this->getWidget<ListWidget>("players");
assert(players != NULL);
core::stringw selectedPlayer = players->getSelectionLabel();
const int player_amount = PlayerManager::get()->getNumPlayers();
for (int i=0; i<player_amount; i++)
{
PlayerProfile *player = PlayerManager::get()->getPlayer(i);
if (selectedPlayer == translations->fribidize(player->getName()))
{
if (!(player->isGuestAccount()))
{
new PlayerInfoDialog( player, 0.5f, 0.6f );
}
return;
}
} // end for
}
else if (name == "playername")
{
race_manager->clearKartLastPositionOnOverworld();
PlayerManager::get()->setCurrentPlayer(NULL,false);
StateManager::get()->pushScreen(StoryModeLobbyScreen::getInstance());
}
} // eventCallback
// -----------------------------------------------------------------------------
void OptionsScreenPlayers::selectPlayer(const irr::core::stringw& name)
{
ListWidget* players = this->getWidget<ListWidget>("players");
assert(players != NULL);
players->selectItemWithLabel(name);
players->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
}
// ----------------------------------------------------------------------------
/** Refreshes the list of players.
*/
bool OptionsScreenPlayers::refreshPlayerList()
{
ListWidget* players = this->getWidget<ListWidget>("players");
if (players == NULL) return false;
// Get rid of previous
players->clear();
// Rebuild it
const int player_amount = PlayerManager::get()->getNumPlayers();
for (int i = 0; i < player_amount; i++)
{
// FIXME: Using a truncated ASCII string for internal ID. Let's cross
// our fingers and hope no one enters two player names that,
// when stripped down to ASCII, give the same identifier...
const PlayerProfile *player = PlayerManager::get()->getPlayer(i);
players->addItem(
core::stringc(player->getName().c_str()).c_str(),
translations->fribidize(player->getName()));
}
return true;
}

View File

@ -1,71 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __HEADER_OPTIONS_SCREEN_PLAYERS_HPP__
#define __HEADER_OPTIONS_SCREEN_PLAYERS_HPP__
#include <string>
#include <irrString.h>
#include "guiengine/screen.hpp"
#include "states_screens/dialogs/enter_player_name_dialog.hpp"
namespace GUIEngine { class Widget; }
struct Input;
class PlayerProfile;
/**
* \brief Player management options screen
* \ingroup states_screens
*/
class OptionsScreenPlayers : public GUIEngine::Screen, public EnterPlayerNameDialog::INewPlayerListener,
public GUIEngine::ScreenSingleton<OptionsScreenPlayers>
{
private:
OptionsScreenPlayers();
bool refreshPlayerList();
public:
friend class GUIEngine::ScreenSingleton<OptionsScreenPlayers>;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name,
const int playerID) OVERRIDE;
/**
* \brief Adds a new player (if 'player' is NULL) or renames an existing player (if 'player' is not NULL)
* \return whether adding was successful (can fail e.g. if trying to add a duplicate)
*/
bool renamePlayer(const irr::core::stringw& newName, PlayerProfile* player=NULL);
void deletePlayer(PlayerProfile* player);
void selectPlayer(const irr::core::stringw& name);
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void init() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void tearDown() OVERRIDE;
/** \brief implement callback from EnterPlayerNameDialog::INewPlayerListener */
virtual void onNewPlayerWithName(const irr::core::stringw& newName);
};
#endif

View File

@ -35,9 +35,9 @@
#include "states_screens/main_menu_screen.hpp"
#include "states_screens/options_screen_audio.hpp"
#include "states_screens/options_screen_input.hpp"
#include "states_screens/options_screen_players.hpp"
#include "states_screens/options_screen_video.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
#include "utils/log.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
@ -131,6 +131,10 @@ void OptionsScreenUI::init()
news->setState( UserConfigParams::m_internet_status
==RequestManager::IPERM_ALLOWED );
CheckBoxWidget* show_login = getWidget<CheckBoxWidget>("show-login");
assert( show_login!= NULL );
show_login->setState( UserConfigParams::m_always_show_login_screen);
// --- select the right skin in the spinner
bool currSkinFound = false;
const int skinCount = m_skins.size();
@ -206,7 +210,7 @@ void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, con
if (selection == "tab_audio") StateManager::get()->replaceTopMostScreen(OptionsScreenAudio::getInstance());
else if (selection == "tab_video") StateManager::get()->replaceTopMostScreen(OptionsScreenVideo::getInstance());
else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(OptionsScreenPlayers::getInstance());
else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(TabbedUserScreen::getInstance());
else if (selection == "tab_controls") StateManager::get()->replaceTopMostScreen(OptionsScreenInput::getInstance());
}
else if(name == "back")
@ -241,6 +245,12 @@ void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, con
if(internet->getState())
NewsManager::get()->init(false);
}
else if (name=="show-login")
{
CheckBoxWidget* show_login = getWidget<CheckBoxWidget>("show-login");
assert( show_login != NULL );
UserConfigParams::m_always_show_login_screen = show_login->getState();
}
else if (name == "language")
{
ListWidget* list_widget = getWidget<ListWidget>("language");

View File

@ -32,9 +32,9 @@
#include "states_screens/dialogs/custom_video_settings.hpp"
#include "states_screens/options_screen_audio.hpp"
#include "states_screens/options_screen_input.hpp"
#include "states_screens/options_screen_players.hpp"
#include "states_screens/options_screen_ui.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
@ -464,7 +464,7 @@ void OptionsScreenVideo::eventCallback(Widget* widget, const std::string& name,
else if (selection == "tab_video")
screen = OptionsScreenVideo::getInstance();
else if (selection == "tab_players")
screen = OptionsScreenPlayers::getInstance();
screen = TabbedUserScreen::getInstance();
else if (selection == "tab_controls")
screen = OptionsScreenInput::getInstance();
else if (selection == "tab_ui")

View File

@ -17,7 +17,9 @@
#include "states_screens/register_screen.hpp"
#include "config/player_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
@ -25,15 +27,16 @@
#include "online/xml_request.hpp"
#include "states_screens/dialogs/registration_dialog.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "states_screens/guest_login_screen.hpp"
#include "states_screens/login_screen.hpp"
#include "states_screens/main_menu_screen.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
#include "utils/log.hpp"
#include "utils/translation.hpp"
using namespace GUIEngine;
using namespace Online;
using namespace irr;
using namespace core;
DEFINE_SCREEN_SINGLETON( RegisterScreen );
@ -41,15 +44,32 @@ DEFINE_SCREEN_SINGLETON( RegisterScreen );
RegisterScreen::RegisterScreen() : Screen("online/register.stkgui")
{
m_existing_player = NULL;
} // RegisterScreen
// -----------------------------------------------------------------------------
void RegisterScreen::init()
{
Screen::init();
// Make sure this tab is actually focused.
RibbonWidget* tabs = this->getWidget<RibbonWidget>("login_tabs");
if (tabs) tabs->select( "tab_register", PLAYER_ID_GAME_MASTER );
// If there is no player (i.e. first start of STK), try to pick
// a good default name
stringw username = "";
if(m_existing_player)
{
username = m_existing_player->getName();
}
else if (PlayerManager::get()->getNumPlayers() == 0)
{
if (getenv("USERNAME") != NULL) // for windows
username = getenv("USERNAME");
else if (getenv("USER") != NULL) // Linux, Macs
username = getenv("USER");
else if (getenv("LOGNAME") != NULL) // Linux, Macs
username = getenv("LOGNAME");
}
getWidget<TextBoxWidget>("local_username")->setText(username);
TextBoxWidget *password_widget = getWidget<TextBoxWidget>("password");
password_widget->setPasswordBox(true,L'*');
@ -63,21 +83,111 @@ void RegisterScreen::init()
m_signup_request = NULL;
m_info_message_shown = false;
makeEntryFieldsVisible(true);
} // init
// -----------------------------------------------------------------------------
void RegisterScreen::setRename(PlayerProfile *player)
{
m_existing_player = player;
} // setRename
// -----------------------------------------------------------------------------
/** Shows or hides the entry fields for online registration, depending on
* online mode.
* \param online True if an online account should be created.
*/
void RegisterScreen::makeEntryFieldsVisible(bool online)
{
// In case of a rename, hide all other fields.
if(m_existing_player)
{
m_info_widget->setVisible(false);
getWidget<CheckBoxWidget>("online")->setVisible(false);
getWidget<LabelWidget>("label_online")->setVisible(false);
online = false;
}
getWidget<TextBoxWidget>("username")->setVisible(online);
getWidget<LabelWidget >("label_username")->setVisible(online);
getWidget<TextBoxWidget>("password")->setVisible(online);
getWidget<LabelWidget >("label_password")->setVisible(online);
getWidget<TextBoxWidget>("password_confirm")->setVisible(online);
getWidget<LabelWidget >("label_password_confirm")->setVisible(online);
getWidget<TextBoxWidget>("email")->setVisible(online);
getWidget<LabelWidget >("label_email")->setVisible(online);
getWidget<TextBoxWidget>("email_confirm")->setVisible(online);
getWidget<LabelWidget >("label_email_confirm")->setVisible(online);
} // makeEntryFieldsVisible
// -----------------------------------------------------------------------------
/** If necessary creates the local user.
* \param local_name Name of the local user.
*/
void RegisterScreen::handleLocalName(const stringw &local_name)
{
if (local_name.size()==0)
return;
// If a local player with that name does not exist, create one
if(!PlayerManager::get()->getPlayer(local_name))
{
PlayerProfile *player;
// If it's a rename, change the name of the player
if(m_existing_player && local_name.size()>0)
{
m_existing_player->setName(local_name);
player = m_existing_player;
}
else
{
player = PlayerManager::get()->addNewPlayer(local_name);
}
PlayerManager::get()->save();
if (player)
{
PlayerManager::get()->setCurrentPlayer(player);
}
else
{
m_info_widget->setErrorColor();
m_info_widget->setText(_("Could not create player '%s'.", local_name),
false);
}
}
else
{
m_info_widget->setErrorColor();
m_info_widget->setText(_("Could not create player '%s'.", local_name),
false);
}
} // handleLocalName
// -----------------------------------------------------------------------------
/** Handles the actual registration process. It does some tests on id, password
* and email address, then submits a corresponding request.
*/
void RegisterScreen::doRegister()
{
core::stringw username = getWidget<TextBoxWidget>("username")->getText().trim();
core::stringw password = getWidget<TextBoxWidget>("password")->getText().trim();
core::stringw password_confirm = getWidget<TextBoxWidget>("password_confirm")
->getText().trim();
core::stringw email = getWidget<TextBoxWidget>("email")->getText().trim();
core::stringw email_confirm = getWidget<TextBoxWidget>("email_confirm")
->getText().trim();
stringw local_name = getWidget<TextBoxWidget>("local_username")
->getText().trim();
handleLocalName(local_name);
// If no online account is requested, don't register
if(!getWidget<CheckBoxWidget>("online")->getState() || m_existing_player)
{
StateManager::get()->popMenu();
m_existing_player = NULL;
return;
}
stringw username = getWidget<TextBoxWidget>("username")->getText().trim();
stringw password = getWidget<TextBoxWidget>("password")->getText().trim();
stringw password_confirm = getWidget<TextBoxWidget>("password_confirm")
->getText().trim();
stringw email = getWidget<TextBoxWidget>("email")->getText().trim();
stringw email_confirm = getWidget<TextBoxWidget>("email_confirm")
->getText().trim();
m_info_widget->setErrorColor();
@ -89,7 +199,7 @@ void RegisterScreen::doRegister()
{
m_info_widget->setText(_("Emails don't match!"), false);
}
else if (username.size() < 4 || username.size() > 30)
else if (username.size() < 3 || username.size() > 30)
{
m_info_widget->setText(_("Username has to be between 4 and 30 characters long!"), false);
}
@ -101,6 +211,12 @@ void RegisterScreen::doRegister()
{
m_info_widget->setText(_("Email has to be between 4 and 50 characters long!"), false);
}
else if ( email.find(L"@")== -1 || email.find(L".")== -1 ||
(email.findLast(L'.') - email.findLast(L'@') <= 2 ) ||
email.findLast(L'@')==0 )
{
m_info_widget->setText(_("Email is invalid!"), false);
}
else
{
m_info_widget->setDefaultColor();
@ -109,7 +225,12 @@ void RegisterScreen::doRegister()
}
sfx_manager->quickSound( "anvil" );
if(local_name.size()>0)
{
PlayerProfile *player = PlayerManager::get()->getPlayer(local_name);
if (player)
player->setLastOnlineName(username);
}
} // doRegister
// -----------------------------------------------------------------------------
@ -180,15 +301,9 @@ void RegisterScreen::onUpdate(float dt)
void RegisterScreen::eventCallback(Widget* widget, const std::string& name,
const int playerID)
{
if (name == "login_tabs")
if (name == "online")
{
const std::string selection =
((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER);
StateManager *sm = StateManager::get();
if (selection == "tab_login")
sm->replaceTopMostScreen(LoginScreen::getInstance());
else if (selection == "tab_guest_login")
sm->replaceTopMostScreen(GuestLoginScreen::getInstance());
makeEntryFieldsVisible(getWidget<CheckBoxWidget>("online")->getState());
}
else if (name=="options")
{
@ -199,13 +314,34 @@ void RegisterScreen::eventCallback(Widget* widget, const std::string& name,
doRegister();
}
else if(button=="cancel")
StateManager::get()->escapePressed();
{
// We poop this menu, onEscapePress will handle the special case
// of e.g. a fresh start of stk that is aborted.
StateManager::get()->popMenu();
onEscapePressed();
}
}
else if (name == "back")
{
m_existing_player = NULL;
StateManager::get()->escapePressed();
}
} // eventCallback
// -----------------------------------------------------------------------------
bool RegisterScreen::onEscapePressed()
{
m_existing_player = NULL;
if (PlayerManager::get()->getNumPlayers() == 0)
{
// Must be first time start, and player cancelled player creation
// so quit stk. At this stage there are two menus on the stack:
// 1) The UserScreen, 2) RegisterStreen
// Popping them both will trigger STK to close.
StateManager::get()->popMenu();
return true;
}
return true;
} // onEscapePressed

View File

@ -23,6 +23,9 @@
namespace GUIEngine { class Widget; class LabelWidget;
class RibbonWidget; }
namespace Online { class XMLRequest; }
class PlayerProfile;
/**
* \brief Screen to register an online account.
* \ingroup states_screens
@ -33,6 +36,8 @@ class RegisterScreen : public GUIEngine::Screen,
private:
friend class GUIEngine::ScreenSingleton<RegisterScreen>;
void makeEntryFieldsVisible(bool online);
void handleLocalName(const irr::core::stringw &local_name);
void doRegister();
void init();
RegisterScreen();
@ -46,6 +51,10 @@ private:
/** The XML request to the server. */
Online::XMLRequest *m_signup_request;
/** Pointer to an existing player if the screen is doing a rename,
* NULL otherwise. */
PlayerProfile *m_existing_player;
/** True if the info message (email was sent...) is shown. */
bool m_info_message_shown;
@ -54,6 +63,8 @@ public:
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() OVERRIDE {};
virtual void onUpdate(float dt) OVERRIDE;
virtual bool onEscapePressed() OVERRIDE;
void setRename(PlayerProfile *player);
void acceptTerms();
/** \brief implement callback from parent class GUIEngine::Screen */

View File

@ -1,157 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "states_screens/story_mode_lobby.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "states_screens/dialogs/enter_player_name_dialog.hpp"
#include "states_screens/main_menu_screen.hpp"
#include "states_screens/state_manager.hpp"
using namespace GUIEngine;
DEFINE_SCREEN_SINGLETON( StoryModeLobbyScreen );
// ----------------------------------------------------------------------------
StoryModeLobbyScreen::StoryModeLobbyScreen() : Screen("story_mode_lobby.stkgui")
{
} // StoryModeLobbyScreen
// ----------------------------------------------------------------------------
void StoryModeLobbyScreen::loadedFromFile()
{
} // loadedFromFile
// ----------------------------------------------------------------------------
void StoryModeLobbyScreen::init()
{
Screen::init();
CheckBoxWidget* cb = getWidget<CheckBoxWidget>("rememberme");
cb->setState(false);
ListWidget* list = getWidget<ListWidget>("gameslots");
list->clear();
PlayerProfile *player = PlayerManager::getCurrentPlayer();
if(player)
{
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
return;
}
for (unsigned int n=0; n<PlayerManager::get()->getNumPlayers(); n++)
{
const PlayerProfile *player = PlayerManager::get()->getPlayer(n);
if (player->isGuestAccount()) continue;
// FIXME: we're using a trunacted ascii version of the player name as
// identifier, let's hope this causes no issues...
list->addItem(core::stringc(player->getName().c_str()).c_str(),
player->getName() );
}
list->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
list->setSelectionID(0);
} // init
// ----------------------------------------------------------------------------
void StoryModeLobbyScreen::tearDown()
{
Screen::tearDown();
} // tearDown
// ----------------------------------------------------------------------------
void StoryModeLobbyScreen::eventCallback(Widget* widget,
const std::string& name,
const int player_id)
{
if (name == "back")
{
StateManager::get()->escapePressed();
}
else if (name == "creategame")
{
new EnterPlayerNameDialog(this, 0.5f, 0.4f);
}
else if (name == "gameslots")
{
ListWidget* list = getWidget<ListWidget>("gameslots");
PlayerProfile *player = PlayerManager::get()
->getPlayer(list->getSelectionLabel());
if(player)
{
player->computeActive();
CheckBoxWidget* cb = getWidget<CheckBoxWidget>("rememberme");
PlayerManager::get()->setCurrentPlayer(player,cb->getState());
}
else
{
Log::error("StoryModeLobby",
"Cannot find player corresponding to slot '%s'.",
core::stringc(list->getSelectionLabel().c_str()).c_str());
}
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
// Since only now the current player is defined, we have to request
// a login (if an online login was saved). If the current player was
// saved, this request will be started much earlier in the startup
// sequence from the RequestManager.
PlayerManager::resumeSavedSession();
}
} // eventCallback
// ----------------------------------------------------------------------------
void StoryModeLobbyScreen::unloaded()
{
} // unloaded
// ----------------------------------------------------------------------------
void StoryModeLobbyScreen::onNewPlayerWithName(const stringw& new_name)
{
PlayerProfile *player = PlayerManager::get()->getPlayer(new_name);
if(player)
{
PlayerManager::get()->setCurrentPlayer(player,false);
player->computeActive();
}
else
{
Log::error("StoryModeLobbyScreen",
"Cannot find player corresponding to slot '%s'.",
core::stringc(new_name.c_str()).c_str());
}
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
} // onNewPlayerWithName
// -----------------------------------------------------------------------------

View File

@ -1,61 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __HEADER_STORY_MODE_LOBBY_HPP__
#define __HEADER_STORY_MODE_LOBBY_HPP__
#include <string>
#include "guiengine/screen.hpp"
#include "states_screens/dialogs/enter_player_name_dialog.hpp"
namespace GUIEngine { class Widget; }
/**
* \brief Audio options screen
* \ingroup states_screens
*/
class StoryModeLobbyScreen : public GUIEngine::Screen, public EnterPlayerNameDialog::INewPlayerListener,
public GUIEngine::ScreenSingleton<StoryModeLobbyScreen>
{
StoryModeLobbyScreen();
public:
friend class GUIEngine::ScreenSingleton<StoryModeLobbyScreen>;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile();
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name, const int playerID);
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void init();
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void tearDown();
/** \brief implement optional callback from parent class GUIEngine::Screen */
virtual void unloaded();
/** \brief implement callback from EnterPlayerNameDialog::INewPlayerListener */
virtual void onNewPlayerWithName(const irr::core::stringw& newName);
};
#endif

View File

@ -48,87 +48,91 @@ DEFINE_SCREEN_SINGLETON( TracksScreen );
TracksScreen::TracksScreen() : Screen("tracks.stkgui")
{
}
} // TracksScreen
// -----------------------------------------------------------------------------
void TracksScreen::loadedFromFile()
{
}
} // loadedFromFile
// -----------------------------------------------------------------------------
void TracksScreen::eventCallback(Widget* widget, const std::string& name, const int playerID)
void TracksScreen::eventCallback(Widget* widget, const std::string& name,
const int playerID )
{
// -- track selection screen
if (name == "tracks")
{
DynamicRibbonWidget* w2 = dynamic_cast<DynamicRibbonWidget*>(widget);
if (w2 != NULL)
if(!w2) return;
const std::string &selection =
w2->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (UserConfigParams::logGUI())
{
const std::string selection = w2->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if(UserConfigParams::logGUI())
std::cout << "Clicked on track " << selection.c_str()
<< std::endl;
Log::info("TracksScreen", "Clicked on track '%s'.",
selection.c_str());
}
UserConfigParams::m_last_track = selection;
UserConfigParams::m_last_track = selection;
if (selection == "random_track")
if (selection == "random_track")
{
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
assert(tabs);
if (m_random_track_list.empty()) return;
std::string track = m_random_track_list.front();
m_random_track_list.pop_front();
m_random_track_list.push_back(track);
Track* clicked_track = track_manager->getTrack(track);
if (clicked_track)
{
RibbonWidget* tabs = this->getWidget<RibbonWidget>("trackgroups");
assert( tabs != NULL );
ITexture* screenshot =
irr_driver->getTexture(clicked_track->getScreenshotFile(),
"While loading screenshot for track '%s':",
clicked_track->getFilename() );
if (m_random_track_list.empty()) return;
new TrackInfoDialog(selection, clicked_track->getIdent(),
translations->fribidize(clicked_track->getName()),
screenshot, 0.8f, 0.7f);
} // if clicked_track
std::string track = m_random_track_list.front();
m_random_track_list.pop_front();
m_random_track_list.push_back(track);
Track* clickedTrack = track_manager->getTrack( track );
if (clickedTrack != NULL)
{
ITexture* screenshot =
irr_driver->getTexture( clickedTrack->getScreenshotFile(),
"While loading screenshot for track '%s':",
clickedTrack->getFilename() );
new TrackInfoDialog(selection, clickedTrack->getIdent(),
translations->fribidize(clickedTrack->getName()),
screenshot, 0.8f, 0.7f);
}
}
else if (selection == "locked")
} // selection=="random_track"
else if (selection == "locked")
{
unlock_manager->playLockSound();
}
else if (selection == RibbonWidget::NO_ITEM_ID)
{
}
else
{
Track* clicked_track = track_manager->getTrack(selection);
if (clicked_track)
{
unlock_manager->playLockSound();
}
else if (selection == RibbonWidget::NO_ITEM_ID)
{
}
else
{
Track* clickedTrack = track_manager->getTrack(selection);
if (clickedTrack != NULL)
{
ITexture* screenshot =
irr_driver->getTexture( clickedTrack->getScreenshotFile(),
"While loading screenshot for track '%s'",
clickedTrack->getFilename());
ITexture* screenshot =
irr_driver->getTexture(clicked_track->getScreenshotFile(),
"While loading screenshot for track '%s'",
clicked_track->getFilename());
new TrackInfoDialog(selection, clickedTrack->getIdent(),
translations->fribidize(clickedTrack->getName()),
screenshot, 0.8f, 0.7f);
}
new TrackInfoDialog(selection, clicked_track->getIdent(),
translations->fribidize(clicked_track->getName()),
screenshot, 0.8f, 0.7f);
}
}
}
} // name=="tracks"
else if (name == "gps")
{
DynamicRibbonWidget* gps_widget = dynamic_cast<DynamicRibbonWidget*>(widget);
if (gps_widget != NULL)
if (gps_widget)
{
std::string selection = gps_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
const std::string &selection =
gps_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == "locked")
{
@ -143,11 +147,11 @@ void TracksScreen::eventCallback(Widget* widget, const std::string& name, const
{
assert(false);
}
}
} // name=="gps"
else if (name == "trackgroups")
{
RibbonWidget* tabs = this->getWidget<RibbonWidget>("trackgroups");
assert( tabs != NULL );
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
assert( tabs );
UserConfigParams::m_last_used_track_group = tabs->getSelectionIDString(0);
buildTrackList();
}
@ -155,7 +159,7 @@ void TracksScreen::eventCallback(Widget* widget, const std::string& name, const
{
StateManager::get()->escapePressed();
}
}
} // eventCallback
// -----------------------------------------------------------------------------
@ -163,8 +167,8 @@ void TracksScreen::beforeAddingWidget()
{
Screen::init();
// Dynamically add tabs
RibbonWidget* tabs = this->getWidget<RibbonWidget>("trackgroups");
assert( tabs != NULL );
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
assert( tabs );
tabs->clearAllChildren();
@ -191,20 +195,20 @@ void TracksScreen::beforeAddingWidget()
tabs->addTextChild( _(groups[n].c_str()), groups[n] );
}
DynamicRibbonWidget* tracks_widget = this->getWidget<DynamicRibbonWidget>("tracks");
assert( tracks_widget != NULL );
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
assert( tracks_widget );
tracks_widget->setItemCountHint( track_manager->getNumberOfTracks()+1 );
}
} // beforeAddingWidget
// -----------------------------------------------------------------------------
void TracksScreen::init()
{
DynamicRibbonWidget* gps_widget = this->getWidget<DynamicRibbonWidget>("gps");
assert( gps_widget != NULL );
DynamicRibbonWidget* gps_widget = getWidget<DynamicRibbonWidget>("gps");
assert( gps_widget );
DynamicRibbonWidget* tracks_widget = this->getWidget<DynamicRibbonWidget>("tracks");
assert( tracks_widget != NULL );
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
assert( tracks_widget );
// Reset GP list everytime (accounts for locking changes, etc.)
gps_widget->clearItems();
@ -221,10 +225,11 @@ void TracksScreen::init()
for (unsigned int t=0; t<tracks.size(); t++)
{
Track* curr = track_manager->getTrack(tracks[t]);
if (curr == NULL)
if (!curr )
{
std::cerr << "/!\\ WARNING: Grand Prix '" << gp->getId() << "' refers to track '"
<< tracks[t] << "', which does not exist.\n";
Log::warn("TracksScreen", "Grand Prix '%s' refers to track '%s',"
"which does not exist.",
gp->getId().c_str(), tracks[t].c_str());
}
else
{
@ -233,20 +238,23 @@ void TracksScreen::init()
}
if (sshot_files.size() == 0)
{
std::cerr << "/!\\ WARNING: Grand Prix '" << gp->getId()
<< "' does not contain any valid track.\n";
Log::warn("TracksScreen",
"Grand Prix '%s' does not contain any valid track.",
gp->getId().c_str());
sshot_files.push_back("gui/main_help.png");
}
if (PlayerManager::getCurrentPlayer()->isLocked(gp->getId()))
{
gps_widget->addAnimatedItem(_("Locked!"),
"locked", sshot_files, 1.5f, LOCKED_BADGE | TROPHY_BADGE,
"locked", sshot_files, 1.5f,
LOCKED_BADGE | TROPHY_BADGE,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
}
else
{
gps_widget->addAnimatedItem(translations->fribidize(gp->getName()), gp->getId(),
gps_widget->addAnimatedItem(translations->fribidize(gp->getName()),
gp->getId(),
sshot_files, 1.5f, TROPHY_BADGE,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE );
}
@ -254,8 +262,8 @@ void TracksScreen::init()
gps_widget->updateItemDisplay();
RibbonWidget* tabs = this->getWidget<RibbonWidget>("trackgroups");
assert( tabs != NULL );
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
assert( tabs );
tabs->select(UserConfigParams::m_last_used_track_group, PLAYER_ID_GAME_MASTER);
@ -271,113 +279,95 @@ void TracksScreen::init()
tracks_widget->setSelection(0, PLAYER_ID_GAME_MASTER, true);
}
irr_driver->unsetTextureErrorMessage();
}
} // init
// -----------------------------------------------------------------------------
/** Rebuild the list of tracks and GPs. This need to be recomputed e.g. to
* take unlocked tracks into account.
*/
void TracksScreen::buildTrackList()
{
DynamicRibbonWidget* tracks_widget = this->getWidget<DynamicRibbonWidget>("tracks");
assert( tracks_widget != NULL );
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
assert( tracks_widget);
RibbonWidget* tabs = this->getWidget<RibbonWidget>("trackgroups");
assert( tabs != NULL );
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
assert( tabs );
// Reset track list everytime (accounts for locking changes, etc.)
tracks_widget->clearItems();
m_random_track_list.clear();
const std::string curr_group_name = tabs->getSelectionIDString(0);
const std::string& curr_group_name = tabs->getSelectionIDString(0);
// Build track list
if (curr_group_name == ALL_TRACK_GROUPS_ID)
const int track_amount = track_manager->getNumberOfTracks();
// First build a list of all tracks to be displayed
// (e.g. exclude arenas, ...)
PtrVector<Track, REF> tracks;
for (int n = 0; n < track_amount; n++)
{
const int trackAmount = track_manager->getNumberOfTracks();
Track* curr = track_manager->getTrack(n);
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_EASTER_EGG
&& !curr->hasEasterEggs())
continue;
if (curr->isArena() || curr->isSoccer()||curr->isInternal()) continue;
if (curr_group_name != ALL_TRACK_GROUPS_ID &&
!curr->isInGroup(curr_group_name)) continue;
for (int n=0; n<trackAmount; n++)
tracks.push_back(curr);
} // for n<track_amount
tracks.insertionSort();
for (unsigned int i = 0; i < tracks.size(); i++)
{
Track *curr = tracks.get(i);
if (PlayerManager::getCurrentPlayer()->isLocked(curr->getIdent()))
{
Track* curr = track_manager->getTrack( n );
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_EASTER_EGG
&& !curr->hasEasterEggs())
continue;
if (curr->isArena() || curr->isSoccer()) continue;
if (curr->isInternal()) continue;
if(PlayerManager::getCurrentPlayer()->isLocked(curr->getIdent()))
{
tracks_widget->addItem( _("Locked : solve active challenges to gain access to more!"),
"locked", curr->getScreenshotFile(), LOCKED_BADGE,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
}
else
{
tracks_widget->addItem(translations->fribidize(curr->getName()), curr->getIdent(),
curr->getScreenshotFile(), 0,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE );
m_random_track_list.push_back(curr->getIdent());
}
tracks_widget->addItem(
_("Locked : solve active challenges to gain access to more!"),
"locked", curr->getScreenshotFile(), LOCKED_BADGE,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
}
}
else
{
const std::vector<int>& curr_group = track_manager->getTracksInGroup( curr_group_name );
const int trackAmount = curr_group.size();
for (int n=0; n<trackAmount; n++)
else
{
Track* curr = track_manager->getTrack( curr_group[n] );
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_EASTER_EGG
&& !curr->hasEasterEggs())
continue;
if (curr->isArena()) continue;
if (curr->isSoccer()) continue;
if (curr->isInternal()) continue;
if (PlayerManager::getCurrentPlayer()->isLocked(curr->getIdent()))
{
tracks_widget->addItem( _("Locked : solve active challenges to gain access to more!"),
"locked", curr->getScreenshotFile(), LOCKED_BADGE,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
}
else
{
tracks_widget->addItem(translations->fribidize(curr->getName()), curr->getIdent(),
curr->getScreenshotFile(), 0 /* no badge */,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE );
m_random_track_list.push_back(curr->getIdent());
}
tracks_widget->addItem(translations->fribidize(curr->getName()),
curr->getIdent(),
curr->getScreenshotFile(), 0,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
m_random_track_list.push_back(curr->getIdent());
}
}
tracks_widget->addItem(_("Random Track"), "random_track", "/gui/track_random.png",
0 /* no badge */, IconButtonWidget::ICON_PATH_TYPE_RELATIVE);
tracks_widget->addItem(_("Random Track"), "random_track",
"/gui/track_random.png", 0 /* no badge */,
IconButtonWidget::ICON_PATH_TYPE_RELATIVE);
tracks_widget->updateItemDisplay();
std::random_shuffle( m_random_track_list.begin(), m_random_track_list.end() );
}
} // buildTrackList
// -----------------------------------------------------------------------------
void TracksScreen::setFocusOnTrack(const std::string& trackName)
{
DynamicRibbonWidget* tracks_widget = this->getWidget<DynamicRibbonWidget>("tracks");
assert( tracks_widget != NULL );
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
assert( tracks_widget);
// only the game master can select tracks, so it's safe to use 'PLAYER_ID_GAME_MASTER'
// only the game master can select tracks,
// so it's safe to use 'PLAYER_ID_GAME_MASTER'
tracks_widget->setSelection(trackName, PLAYER_ID_GAME_MASTER, true);
}
} // setFocusOnTrack
// -----------------------------------------------------------------------------
void TracksScreen::setFocusOnGP(const std::string& gpName)
{
DynamicRibbonWidget* gps_widget = this->getWidget<DynamicRibbonWidget>("gps");
assert( gps_widget != NULL );
DynamicRibbonWidget* gps_widget = getWidget<DynamicRibbonWidget>("gps");
assert( gps_widget );
// only the game master can select tracks/GPs, so it's safe to use 'PLAYER_ID_GAME_MASTER'
// only the game master can select tracks/GPs,
// so it's safe to use 'PLAYER_ID_GAME_MASTER'
gps_widget->setSelection(gpName, PLAYER_ID_GAME_MASTER, true);
}
} // setFocusOnGP
// -----------------------------------------------------------------------------

View File

@ -0,0 +1,618 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "states_screens/user_screen.hpp"
#include "audio/sfx_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include "online/messages.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "states_screens/main_menu_screen.hpp"
#include "states_screens/options_screen_audio.hpp"
#include "states_screens/options_screen_input.hpp"
#include "states_screens/options_screen_ui.hpp"
#include "states_screens/options_screen_video.hpp"
#include "states_screens/register_screen.hpp"
#include "states_screens/state_manager.hpp"
using namespace GUIEngine;
DEFINE_SCREEN_SINGLETON( UserScreen );
DEFINE_SCREEN_SINGLETON( TabbedUserScreen );
// ----------------------------------------------------------------------------
BaseUserScreen::BaseUserScreen(const std::string &name) : Screen(name.c_str())
{
} // BaseUserScreen
// ----------------------------------------------------------------------------
void BaseUserScreen::loadedFromFile()
{
} // loadedFromFile
// ----------------------------------------------------------------------------
void BaseUserScreen::init()
{
m_online_cb = getWidget<CheckBoxWidget>("online");
assert(m_online_cb);
m_username_tb = getWidget<TextBoxWidget >("username");
assert(m_username_tb);
m_password_tb = getWidget<TextBoxWidget >("password");
assert(m_password_tb);
m_password_tb->setPasswordBox(true, L'*');
m_players = getWidget<DynamicRibbonWidget>("players");
assert(m_players);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget);
m_info_widget = getWidget<LabelWidget>("message");
assert(m_info_widget);
getWidget<CheckBoxWidget>("remember-user")
->setState(UserConfigParams::m_always_show_login_screen);
m_sign_out_name = "";
m_sign_in_name = "";
// It should always be activated ... but just in case
m_options_widget->setActivated();
// Clean any error message still shown
m_info_widget->setText("", true);
m_info_widget->setErrorColor();
Screen::init();
m_players->clearItems();
std::string current_player_index="";
for (unsigned int n=0; n<PlayerManager::get()->getNumPlayers(); n++)
{
const PlayerProfile *player = PlayerManager::get()->getPlayer(n);
if (player->isGuestAccount()) continue;
std::string s = StringUtils::toString(n);
m_players->addItem(player->getName(), s, player->getIconFilename(), 0,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
if(player==PlayerManager::getCurrentPlayer())
current_player_index = s;
}
m_players->updateItemDisplay();
// Select the current player. That can only be done after
// updateItemDisplay is called.
if(current_player_index.size()>0)
{
m_players->setSelection(current_player_index, PLAYER_ID_GAME_MASTER,
/*focus*/ true);
PlayerProfile *player = PlayerManager::getCurrentPlayer();
const stringw &online_name = player->getLastOnlineName();
m_username_tb->setText(online_name);
// Select 'online
m_online_cb->setState(player->wasOnlineLastTime() ||
player->isLoggedIn() );
makeEntryFieldsVisible();
}
else // no current player found
{
// The first player is the most frequently used, so select it
if (PlayerManager::get()->getNumPlayers() > 0)
selectUser(0);
}
} // init
// ----------------------------------------------------------------------------
PlayerProfile* BaseUserScreen::getSelectedPlayer()
{
const std::string &s_id = m_players
->getSelectionIDString(PLAYER_ID_GAME_MASTER);
unsigned int n_id;
StringUtils::fromString(s_id, n_id);
return PlayerManager::get()->getPlayer(n_id);
} // getSelectedPlayer
// ----------------------------------------------------------------------------
void BaseUserScreen::tearDown()
{
Screen::tearDown();
} // tearDown
// ----------------------------------------------------------------------------
/** Called when a user is selected. It updates the online checkbox and
* entrye fields.
*/
void BaseUserScreen::selectUser(int index)
{
PlayerProfile *profile = PlayerManager::get()->getPlayer(index);
assert(profile);
getWidget<TextBoxWidget >("username")->setText(profile
->getLastOnlineName());
m_players->setSelection(StringUtils::toString(index), 0, /*focusIt*/true);
// Last game was not online, so make the offline settings the default
// (i.e. unckeck online checkbox, and make entry fields invisible).
if (!profile->wasOnlineLastTime() || profile->getLastOnlineName() == "")
{
m_online_cb->setState(false);
makeEntryFieldsVisible();
return;
}
// Now last use was with online --> Display the saved data
m_online_cb->setState(true);
makeEntryFieldsVisible();
m_username_tb->setText(profile->getLastOnlineName());
// And make the password invisible if the session is saved (i.e
// the user does not need to enter a password).
if (profile->hasSavedSession())
{
m_password_tb->setVisible(false);
getWidget<LabelWidget>("label_password")->setVisible(false);
}
} // selectUser
// ----------------------------------------------------------------------------
/** Make the entry fields either visible or invisible.
* \param online Online state, which dicates if the entry fields are
* visible (true) or not.
*/
void BaseUserScreen::makeEntryFieldsVisible()
{
#ifdef GUEST_ACCOUNTS_ENABLED
getWidget<LabelWidget>("label_guest")->setVisible(online);
getWidget<CheckBoxWidget>("guest")->setVisible(online);
#endif
bool online = m_online_cb->getState();
getWidget<LabelWidget>("label_username")->setVisible(online);
m_username_tb->setVisible(online);
getWidget<LabelWidget>("label_remember")->setVisible(online);
getWidget<CheckBoxWidget>("remember-user")->setVisible(online);
PlayerProfile *player = getSelectedPlayer();
if(player && player->hasSavedSession() && online)
{
// If we show the online login fields, but the player has a
// saved session, don't show the password field.
getWidget<LabelWidget>("label_password")->setVisible(false);
m_password_tb->setVisible(false);
}
else
{
getWidget<LabelWidget>("label_password")->setVisible(online);
m_password_tb->setVisible(online);
}
} // makeEntryFieldsVisible
// ----------------------------------------------------------------------------
/** Called when the user selects anything on the screen.
*/
void BaseUserScreen::eventCallback(Widget* widget,
const std::string& name,
const int player_id)
{
// Clean any error message still shown
m_info_widget->setText("", true);
m_info_widget->setErrorColor();
if (name == "players")
{
// Clicked on a name --> Find the corresponding online data
// and display them
const std::string &s_index = getWidget<DynamicRibbonWidget>("players")
->getSelectionIDString(player_id);
if (s_index == "") return; // can happen if the list is empty
unsigned int id;
if (StringUtils::fromString(s_index, id))
selectUser(id);
}
else if (name == "remember-user")
{
UserConfigParams::m_remember_user =
getWidget<CheckBoxWidget>("remember-user")->getState();
}
else if (name == "online")
{
// If online access is not allowed, do not accept an online account
// but advice the user where to enable this option.
if (m_online_cb->getState() && UserConfigParams::m_internet_status ==
Online::RequestManager::IPERM_NOT_ALLOWED)
{
m_info_widget->setText(
"Internet access is disabled, please enable it in the options",
true);
sfx_manager->quickSound( "anvil" );
m_online_cb->setState(false);
}
makeEntryFieldsVisible();
}
else if (name == "options")
{
const std::string &button =
m_options_widget->getSelectionIDString(player_id);
if (button == "ok")
{
login();
} // button==ok
else if (button == "new_user")
{
StateManager::get()->pushScreen(RegisterScreen::getInstance());
}
else if (button == "cancel")
{
StateManager::get()->popMenu();
onEscapePressed();
}
else if (button == "rename")
{
PlayerProfile *cp = getSelectedPlayer();
RegisterScreen::getInstance()->setRename(cp);
StateManager::get()->pushScreen(RegisterScreen::getInstance());
// Init will automatically be called, which
// refreshes the player list
}
else if (button == "delete")
{
deletePlayer();
}
} // options
return;
} // eventCallback
// ----------------------------------------------------------------------------
/** Closes the BaseUserScreen, and makes sure that the right screen is displayed
* next.
*/
void BaseUserScreen::closeScreen()
{
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
} // closeScreen
// ----------------------------------------------------------------------------
/** Called when OK or OK-and-save is clicked.
* This will trigger the actual login (if requested) etc.
* \param remember_me True if the login details should be remembered,
* so that next time this menu can be skipped.
*/
void BaseUserScreen::login()
{
// If an error occurs, the callback informing this screen about the
// problem will activate the widget again.
m_options_widget->setDeactivated();
m_state = STATE_NONE;
PlayerProfile *player = getSelectedPlayer();
PlayerProfile *current = PlayerManager::getCurrentPlayer();
core::stringw new_username = m_username_tb->getText();
// If a different player is connecting, or the same local player with
// a different online account, log out the current player.
if(current && current->isLoggedIn() &&
(player!=current || current->getLastOnlineName()!=new_username) )
{
m_sign_out_name = current->getLastOnlineName();
current->requestSignOut();
m_state = (UserScreenState)(m_state | STATE_LOGOUT);
// If the online user name was changed, reset the save data
// for this user (otherwise later the saved session will be
// resumed, not logging the user with the new account).
if(current->getLastOnlineName()!=new_username)
current->clearSession();
}
PlayerManager::get()->setCurrentPlayer(player);
assert(player);
// If no online login requested, log the player out (if necessary)
// and go to the main menu screen (though logout needs to finish first)
if(!m_online_cb->getState())
{
if(player->isLoggedIn())
{
m_sign_out_name =player->getLastOnlineName();
player->requestSignOut();
m_state =(UserScreenState)(m_state| STATE_LOGOUT);
}
player->setWasOnlineLastTime(false);
if(m_state==STATE_NONE)
{
closeScreen();
}
return;
}
// Player wants to be online, and is already online - nothing to do
if(player->isLoggedIn())
{
player->setWasOnlineLastTime(true);
closeScreen();
return;
}
m_state = (UserScreenState) (m_state | STATE_LOGIN);
// Now we need to start a login request to the server
// This implies that this screen will wait till the server responds, so
// that error messages ('invalid password') can be shown, and the user
// can decide what to do about them.
if (player->hasSavedSession())
{
m_sign_in_name = player->getLastOnlineName();
// Online login with saved token
player->requestSavedSession();
}
else
{
// Online login with password --> we need a valid password
if (m_password_tb->getText() == "")
{
m_info_widget->setText(_("You need to enter a password."), true);
sfx_manager->quickSound("anvil");
m_options_widget->setActivated();
return;
}
m_sign_in_name = m_username_tb->getText();
player->requestSignIn(m_username_tb->getText(),
m_password_tb->getText());
} // !hasSavedSession
} // login
// ----------------------------------------------------------------------------
/** Called once every frame. It will replace this screen with the main menu
* screen if a successful login happened.
*/
void BaseUserScreen::onUpdate(float dt)
{
if (!m_options_widget->isActivated())
{
core::stringw message = (m_state & STATE_LOGOUT)
? _(L"Signing out '%s'",m_sign_out_name.c_str())
: _(L"Signing in '%s'", m_sign_in_name.c_str());
m_info_widget->setText(Online::Messages::loadingDots(message.c_str()),
false );
}
PlayerProfile *player = getSelectedPlayer();
if(player)
{
// If the player changes the online name, clear the saved session
// flag, and make the password field visible again.
if (m_username_tb->getText()!=player->getLastOnlineName())
{
player->clearSession();
makeEntryFieldsVisible();
}
}
} // onUpdate
// ----------------------------------------------------------------------------
/** Callback from player profile if login was successful.
*/
void BaseUserScreen::loginSuccessful()
{
PlayerProfile *player = getSelectedPlayer();
player->setWasOnlineLastTime(true);
m_options_widget->setActivated();
// Clean any error message still shown
m_info_widget->setText("", true);
m_info_widget->setErrorColor();
// The callback is done from the main thread, so no need to sync
// access to m_success. OnUpdate will check this flag
closeScreen();
} // loginSuccessful
// ----------------------------------------------------------------------------
/** Callback from player profile if login was unsuccessful.
* \param error_message Contains the error message.
*/
void BaseUserScreen::loginError(const irr::core::stringw & error_message)
{
m_state = (UserScreenState) (m_state & ~STATE_LOGIN);
PlayerProfile *player = getSelectedPlayer();
// Clear information about saved session in case of a problem,
// which allows the player to enter a new password.
if(player && player->hasSavedSession())
player->clearSession();
makeEntryFieldsVisible();
sfx_manager->quickSound("anvil");
m_info_widget->setErrorColor();
m_info_widget->setText(error_message, false);
m_options_widget->setActivated();
} // loginError
// ----------------------------------------------------------------------------
/** Callback from player profile if logout was successful.
*/
void BaseUserScreen::logoutSuccessful()
{
m_state = (UserScreenState) (m_state & ~STATE_LOGOUT);
if(m_state==STATE_NONE)
closeScreen();
// Otherwise the screen still has to wait for a login request to finish.
} // loginSuccessful
// ----------------------------------------------------------------------------
/** Callback from player profile if login was unsuccessful.
* \param error_message Contains the error message.
*/
void BaseUserScreen::logoutError(const irr::core::stringw & error_message)
{
m_state = (UserScreenState) (m_state & ~STATE_LOGOUT);
PlayerProfile *player = getSelectedPlayer();
// Clear information about saved session in case of a problem,
// which allows the player to enter a new password.
if(player && player->hasSavedSession())
player->clearSession();
makeEntryFieldsVisible();
sfx_manager->quickSound("anvil");
m_info_widget->setErrorColor();
m_info_widget->setText(error_message, false);
m_options_widget->setActivated();
} // logoutError
// ----------------------------------------------------------------------------
/** Called when a player will be deleted.
*/
void BaseUserScreen::deletePlayer()
{
// Check that there is at least one player left: we need to have a
// valid current player, so the last player can not be deleted.
if(PlayerManager::get()->getNumNonGuestPlayers()==1)
{
m_info_widget->setText("You can't delete the only player.", true);
m_info_widget->setErrorColor();
return;
}
PlayerProfile *player = getSelectedPlayer();
irr::core::stringw message =
//I18N: In the player info dialog (when deleting)
_("Do you really want to delete player '%s' ?", player->getName());
class ConfirmServer : public MessageDialog::IConfirmDialogListener
{
BaseUserScreen *m_parent_screen;
public:
virtual void onConfirm()
{
m_parent_screen->doDeletePlayer();
} // onConfirm
// ------------------------------------------------------------
ConfirmServer(BaseUserScreen *parent)
{
m_parent_screen = parent;
}
}; // ConfirmServer
new MessageDialog(message, MessageDialog::MESSAGE_DIALOG_CONFIRM,
new ConfirmServer(this), true);
} // deletePlayer
// ----------------------------------------------------------------------------
/** Callback when the user confirms to delete a player. This function actually
* deletes the player, discards the dialog, and re-initialised the BaseUserScreen
* to display only the available players.
*/
void BaseUserScreen::doDeletePlayer()
{
PlayerProfile *player = getSelectedPlayer();
PlayerManager::get()->deletePlayer(player);
GUIEngine::ModalDialog::dismiss();
// Special case: the current player was deleted. We have to make sure
// that there is still a current player (all of STK depends on that).
if(!PlayerManager::getCurrentPlayer())
{
for(unsigned int i=0; i<PlayerManager::get()->getNumPlayers(); i++)
{
PlayerProfile *player = PlayerManager::get()->getPlayer(i);
if(!player->isGuestAccount())
{
PlayerManager::get()->setCurrentPlayer(player);
break;
}
}
}
init();
} // doDeletePlayer
// ----------------------------------------------------------------------------
void BaseUserScreen::unloaded()
{
} // unloaded
// ----------------------------------------------------------------------------
/** Gets called when a dialog closes. At a first time start of STK the
* internet dialog is shown first. Only when this dialog closes is it possible
* to open the next dialog, which is the one to create a new player (which
* is conventient on a first start).
*/
void BaseUserScreen::onDialogClose()
{
return;
// To allow players to exit the game without creating a player, we count
// how often this function was called. The first time is after the
// internet allowed dialog, the 2nd time
static int number_of_calls = 0;
number_of_calls++;
if(PlayerManager::get()->getNumPlayers() == 0)
{
// Still 0 players after the enter player dialog was shown
// --> User wanted to abort, so pop this menu, which will
// trigger the end of STK.
if (number_of_calls > 1)
{
StateManager::get()->popMenu();
return;
}
StateManager::get()->pushScreen(RegisterScreen::getInstance());
} // getNumPlayers == 0
} // onDialogClose
// ============================================================================
/** In the tab version, make sure the right tab is selected.
*/
void TabbedUserScreen::init()
{
RibbonWidget* tab_bar = this->getWidget<RibbonWidget>("options_choice");
if (tab_bar != NULL) tab_bar->select("tab_players", PLAYER_ID_GAME_MASTER);
tab_bar->getRibbonChildren()[0].setTooltip( _("Graphics") );
tab_bar->getRibbonChildren()[1].setTooltip( _("Audio") );
tab_bar->getRibbonChildren()[2].setTooltip(_("User Interface"));
tab_bar->getRibbonChildren()[4].setTooltip( _("Controls") );
BaseUserScreen::init();
} // init
// ----------------------------------------------------------------------------
/** Switch to the correct tab.
*/
void TabbedUserScreen::eventCallback(GUIEngine::Widget* widget,
const std::string& name,
const int player_id)
{
if (name == "options_choice")
{
const std::string &selection =
((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER);
Screen *s;
if (selection=="tab_audio" ) s = OptionsScreenAudio::getInstance();
else if (selection=="tab_video" ) s = OptionsScreenVideo::getInstance();
else if (selection=="tab_players" ) s = TabbedUserScreen::getInstance();
else if (selection=="tab_controls") s = OptionsScreenInput::getInstance();
else if (selection=="tab_ui" ) s = OptionsScreenUI::getInstance();
assert(s);
StateManager::get()->replaceTopMostScreen(s);
}
else
BaseUserScreen::eventCallback(widget, name, player_id);
} // eventCallback

View File

@ -0,0 +1,145 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __HEADER_USER_SCREEN_HPP__
#define __HEADER_USER_SCREEN_HPP__
#include <string>
#include "guiengine/screen.hpp"
namespace GUIEngine
{
class CheckBoxWidget;
class LabelWidget;
class RibbonWidget;
class TextBoxWidget;
class Widget;
}
class PlayerProfile;
/**
* \brief The user management screen. The screen cames in two variations:
* either as a stand-alone screen before the main menu (on first time STK
* is started, or it the user is not remembered), but also as tab in the
* options menu. To implement this, we use one common base class that
* implements nearly all functionality, and derive to classes - one for
* the stand alone version, one for the version with tabs.
* \ingroup states_screens.
*/
class BaseUserScreen : public GUIEngine::Screen
{
protected:
BaseUserScreen(const std::string &name);
private:
/** The state of the user screen. Note that this is a bit mask, since the
* current user can be logged out, and the new one logged in at the
* same time. */
enum UserScreenState { STATE_NONE=0, STATE_LOGIN=1, STATE_LOGOUT=2} m_state;
/** The user name that is currently being logged out. Used to
* display more meaningful sign-out message. */
irr::core::stringw m_sign_out_name;
/** The user name that is currently being logged out. Used to
* display more meaningful sign-out message. */
irr::core::stringw m_sign_in_name;
/** Online check box. */
GUIEngine::CheckBoxWidget *m_online_cb;
/** User name entry field. */
GUIEngine::TextBoxWidget *m_username_tb;
/** Password widget. */
GUIEngine::TextBoxWidget *m_password_tb;
/** Label field for warning and error messages. */
GUIEngine::LabelWidget * m_info_widget;
/** The ribbon with all buttons. */
GUIEngine::RibbonWidget *m_options_widget;
/** The dynamic ribbon containing all players. */
GUIEngine::DynamicRibbonWidget* m_players;
void selectUser(int index);
void makeEntryFieldsVisible();
void login();
void closeScreen();
void deletePlayer();
void doDeletePlayer();
PlayerProfile* getSelectedPlayer();
virtual void onDialogClose();
virtual void onUpdate(float dt) OVERRIDE;
public:
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile();
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void eventCallback(GUIEngine::Widget* widget,
const std::string& name, const int playerID);
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void init();
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void tearDown();
/** \brief implement optional callback from parent class GUIEngine::Screen */
virtual void unloaded();
void loginSuccessful();
void loginError(const irr::core::stringw &error_message);
void logoutSuccessful();
void logoutError(const irr::core::stringw &error_message);
}; // class BaseUserScreen
// ============================================================================
class UserScreen : public BaseUserScreen,
public GUIEngine::ScreenSingleton<UserScreen>
{
private:
UserScreen() : BaseUserScreen("user_screen.stkgui")
{};
public:
friend class GUIEngine::ScreenSingleton<UserScreen>;
}; // class UserScreenTabed
// ============================================================================
class TabbedUserScreen : public BaseUserScreen,
public GUIEngine::ScreenSingleton<TabbedUserScreen>
{
private:
TabbedUserScreen() : BaseUserScreen("user_screen_tab.stkgui")
{}
public:
friend class GUIEngine::ScreenSingleton<TabbedUserScreen>;
virtual void init();
virtual void eventCallback(GUIEngine::Widget* widget,
const std::string& name, const int playerID);
}; // class TabbedUserScreen
#endif

View File

@ -73,6 +73,7 @@
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <wchar.h>
using namespace irr;
@ -152,6 +153,69 @@ Track::~Track()
#endif
} // ~Track
//-----------------------------------------------------------------------------
/** A < comparison of tracks. This is used to sort the tracks when displaying
* them in the gui.
*/
bool Track::operator<(const Track &other) const
{
PlayerProfile *p = PlayerManager::getCurrentPlayer();
bool this_is_locked = p->isLocked(getIdent());
bool other_is_locked = p->isLocked(other.getIdent());
if(this_is_locked == other_is_locked)
{
return getSortName() < other.getSortName();
}
else
return other_is_locked;
} // operator<
//-----------------------------------------------------------------------------
/** Returns the name of the track, which is e.g. displayed on the screen.
\note this is the LTR name, invoke fribidi as needed. */
core::stringw Track::getName() const
{
core::stringw translated = translations->w_gettext(m_name.c_str());
int index = translated.find("|");
if(index>-1)
{
translated = translated.subString(0, index);
}
return translated;
} // getName
//-----------------------------------------------------------------------------
/** Returns the name of the track used to sort the tracks alphabetically.
* This can be used to e.g. sort 'The Island' as 'Island,The'; or
* to replace certain language-specific characters (e.g. German 'ae' with 'a')
* The sort name can be specified by setting the name of a track to:
* "normal name|sort name"
*/
core::stringw Track::getSortName() const
{
core::stringw translated = translations->w_gettext(m_name.c_str());
translated.make_lower();
int index = translated.find("|");
if(index>-1)
{
translated = translated.subString(index+1, translated.size());
}
return translated;
} // getSortName
//-----------------------------------------------------------------------------
/** Returns true if this track belongs to the specified track group.
* \param group_name Group name to test for.
*/
bool Track::isInGroup(const std::string &group_name)
{
for(unsigned int i=0; i<m_groups.size(); i++)
{
if(m_groups[i]==group_name) return true;
}
return false;
} // isInGroup
//-----------------------------------------------------------------------------
/** Returns number of completed challenges */
unsigned int Track::getNumOfCompletedChallenges()
@ -362,7 +426,7 @@ void Track::cleanup()
void Track::loadTrackInfo()
{
irr_driver->setLwhite(1.);
irr_driver->setExposure(0.09);
irr_driver->setExposure(0.09f);
// Default values
m_use_fog = false;
m_fog_max = 1.0f;

View File

@ -350,6 +350,9 @@ private:
/** Name of the track to display. */
std::string m_name;
/** The name used in sorting the track. */
core::stringw m_sort_name;
bool m_use_fog;
/** True if this track supports using smoothed normals. */
bool m_smooth_normals;
@ -428,6 +431,11 @@ public:
void adjustForFog(scene::IMesh* mesh,
scene::ISceneNode* parent_scene_node);
void itemCommand(const XMLNode *node);
core::stringw getName() const;
core::stringw getSortName() const;
// ------------------------------------------------------------------------
bool isInGroup(const std::string &group_name);
// ------------------------------------------------------------------------
const core::vector3df& getSunRotation();
/** Sets the current ambient color for a kart with index k. */
void setAmbientColor(const video::SColor &color,
@ -472,11 +480,6 @@ public:
/** Returns a unique identifier for this track (the directory name). */
const std::string& getIdent () const {return m_ident; }
// ------------------------------------------------------------------------
/** Returns the name of the track, which is e.g. displayed on the screen.
\note this is the LTR name, invoke fribidi as needed. */
const wchar_t* getName () const
{return translations->w_gettext(m_name.c_str()); }
// ------------------------------------------------------------------------
/** Returns all groups this track belongs to. */
const std::vector<std::string>&
getGroups () const {return m_groups; }
@ -612,6 +615,7 @@ public:
float getDisplacementSpeed() const { return m_displacement_speed; }
float getCausticsSpeed() const { return m_caustics_speed; }
bool operator<(const Track &other) const;
}; // class Track
#endif

View File

@ -698,7 +698,7 @@ TrackObjectPresentationLight::TrackObjectPresentationLight(const XMLNode& xml_no
m_energy = 1.0f;
xml_node.get("energy", &m_energy);
m_distance = 20. * m_energy;
m_distance = 20.f * m_energy;
xml_node.get("distance", &m_distance);
if (irr_driver->isGLSL())

View File

@ -15,7 +15,7 @@
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "debug.hpp"
#include "config/user_config.hpp"
#include "karts/controller/controller.hpp"
@ -36,13 +36,13 @@
#include <IGUIContextMenu.h>
using namespace irr;
using namespace gui;
namespace Debug {
/** This is to let mouse input events go through when the debug menu is visible, otherwise
GUI events would be blocked while in a race... */
static bool g_debug_menu_visible = false;
// -----------------------------------------------------------------------------
// Commands for the debug menu
enum DebugMenuCommand
@ -54,6 +54,9 @@ enum DebugMenuCommand
DEBUG_GRAPHICS_MIPMAP_VIZ,
DEBUG_GRAPHICS_NORMALS_VIZ,
DEBUG_GRAPHICS_SSAO_VIZ,
DEBUG_GRAPHICS_RSM_VIZ,
DEBUG_GRAPHICS_RH_VIZ,
DEBUG_GRAPHICS_GI_VIZ,
DEBUG_GRAPHICS_SHADOW_VIZ,
DEBUG_GRAPHICS_LIGHT_VIZ,
DEBUG_GRAPHICS_DISTORT_VIZ,
@ -83,7 +86,7 @@ enum DebugMenuCommand
DEBUG_TWEAK_SHADER_EXPOSURE,
DEBUG_TWEAK_SHADER_LWHITE
};
// -----------------------------------------------------------------------------
// Add powerup selected from debug menu for all player karts
void addPowerup(PowerupManager::PowerupType powerup)
@ -96,7 +99,7 @@ void addPowerup(PowerupManager::PowerupType powerup)
kart->setPowerup(powerup, 10000);
}
}
void addAttachment(Attachment::AttachmentType type)
{
@ -136,7 +139,7 @@ bool onEvent(const SEvent &event)
// Only activated in artist debug mode
if(!UserConfigParams::m_artist_debug_mode)
return true; // keep handling the events
if(event.EventType == EET_MOUSE_INPUT_EVENT)
{
// Create the menu (only one menu at a time)
@ -147,22 +150,25 @@ bool onEvent(const SEvent &event)
IGUIContextMenu* mnu = guienv->addContextMenu(
core::rect<s32>(event.MouseInput.X, event.MouseInput.Y, event.MouseInput.Y+100, event.MouseInput.Y+100),NULL);
int graphicsMenuIndex = mnu->addItem(L"Graphics >",-1,true,true);
// graphics menu
IGUIContextMenu* sub = mnu->getSubMenu(graphicsMenuIndex);
sub->addItem(L"Reload shaders", DEBUG_GRAPHICS_RELOAD_SHADERS );
sub->addItem(L"Reset debug views", DEBUG_GRAPHICS_RESET );
sub->addItem(L"Wireframe", DEBUG_GRAPHICS_WIREFRAME );
sub->addItem(L"Mipmap viz", DEBUG_GRAPHICS_MIPMAP_VIZ );
sub->addItem(L"Normals viz", DEBUG_GRAPHICS_NORMALS_VIZ );
sub->addItem(L"SSAO viz", DEBUG_GRAPHICS_SSAO_VIZ );
sub->addItem(L"RSM viz", DEBUG_GRAPHICS_RSM_VIZ);
sub->addItem(L"RH viz", DEBUG_GRAPHICS_RH_VIZ);
sub->addItem(L"GI viz", DEBUG_GRAPHICS_GI_VIZ);
sub->addItem(L"Shadow viz", DEBUG_GRAPHICS_SHADOW_VIZ );
sub->addItem(L"Light viz", DEBUG_GRAPHICS_LIGHT_VIZ );
sub->addItem(L"Distort viz", DEBUG_GRAPHICS_DISTORT_VIZ );
sub->addItem(L"Physics debug", DEBUG_GRAPHICS_BULLET_1);
sub->addItem(L"Physics debug (no kart)", DEBUG_GRAPHICS_BULLET_2);
mnu->addItem(L"Items >",-1,true,true);
sub = mnu->getSubMenu(1);
sub->addItem(L"Basketball", DEBUG_POWERUP_RUBBERBALL );
@ -175,7 +181,7 @@ bool onEvent(const SEvent &event)
sub->addItem(L"Switch", DEBUG_POWERUP_SWITCH );
sub->addItem(L"Zipper", DEBUG_POWERUP_ZIPPER );
sub->addItem(L"Nitro", DEBUG_POWERUP_NITRO );
mnu->addItem(L"Attachments >",-1,true, true);
sub = mnu->getSubMenu(2);
sub->addItem(L"Bomb", DEBUG_ATTACHMENT_BOMB);
@ -183,8 +189,8 @@ bool onEvent(const SEvent &event)
sub->addItem(L"Parachute", DEBUG_ATTACHMENT_PARACHUTE);
//mnu->addItem(L"Adjust shaders >", -1, true, true);
//sub = mnu->getSubMenu(3);
//sub->addItem(L"Exposure", DEBUG_TWEAK_SHADER_EXPOSURE);
//sub = mnu->getSubMenu(3);
//sub->addItem(L"Exposure", DEBUG_TWEAK_SHADER_EXPOSURE);
//sub->addItem(L"LWhite", DEBUG_TWEAK_SHADER_LWHITE);
mnu->addItem(L"Profiler",DEBUG_PROFILER);
@ -196,29 +202,29 @@ bool onEvent(const SEvent &event)
mnu->addItem(L"Save history", DEBUG_SAVE_HISTORY);
mnu->addItem(L"Toggle GUI", DEBUG_TOGGLE_GUI);
mnu->addItem(L"Hide karts", DEBUG_HIDE_KARTS);
g_debug_menu_visible = true;
irr_driver->showPointer();
}
// Let Irrlicht handle the event while the menu is visible - otherwise in a race the GUI events won't be generated
if(g_debug_menu_visible)
return false;
}
if (event.EventType == EET_GUI_EVENT)
{
if (event.GUIEvent.Caller != NULL && event.GUIEvent.Caller->getType() == EGUIET_CONTEXT_MENU )
{
IGUIContextMenu *menu = (IGUIContextMenu*)event.GUIEvent.Caller;
s32 cmdID = menu->getItemCommandId(menu->getSelectedItem());
if(event.GUIEvent.EventType == EGET_ELEMENT_CLOSED)
{
g_debug_menu_visible = false;
}
if (event.GUIEvent.EventType == gui::EGET_MENU_ITEM_SELECTED)
{
if(cmdID == DEBUG_GRAPHICS_RELOAD_SHADERS)
@ -230,14 +236,14 @@ bool onEvent(const SEvent &event)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
}
else if (cmdID == DEBUG_GRAPHICS_WIREFRAME)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleWireframe();
}
@ -245,7 +251,7 @@ bool onEvent(const SEvent &event)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleMipVisualization();
}
@ -253,7 +259,7 @@ bool onEvent(const SEvent &event)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleNormals();
}
@ -261,15 +267,39 @@ bool onEvent(const SEvent &event)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleSSAOViz();
}
else if (cmdID == DEBUG_GRAPHICS_RSM_VIZ)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleRSM();
}
else if (cmdID == DEBUG_GRAPHICS_RH_VIZ)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleRH();
}
else if (cmdID == DEBUG_GRAPHICS_GI_VIZ)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleGI();
}
else if (cmdID == DEBUG_GRAPHICS_SHADOW_VIZ)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleShadowViz();
}
@ -277,7 +307,7 @@ bool onEvent(const SEvent &event)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleLightViz();
}
@ -285,14 +315,14 @@ bool onEvent(const SEvent &event)
{
World* world = World::getWorld();
if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleDistortViz();
}
else if (cmdID == DEBUG_GRAPHICS_BULLET_1)
{
irr_driver->resetDebugModes();
World* world = World::getWorld();
if (world == NULL) return false;
world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_KARTS_PHYSICS);
@ -300,7 +330,7 @@ bool onEvent(const SEvent &event)
else if (cmdID == DEBUG_GRAPHICS_BULLET_2)
{
irr_driver->resetDebugModes();
World* world = World::getWorld();
if (world == NULL) return false;
world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NO_KARTS_GRAPHICS);
@ -417,13 +447,13 @@ bool onEvent(const SEvent &event)
new DebugSliderDialog("lwhite", "LWhite");
}
}
return false; // event has been handled
}
}
return true; // continue event handling
}
bool isOpen()
{
return g_debug_menu_visible;

View File

@ -320,7 +320,7 @@ void Profiler::draw()
long hovered_gpu_marker_elapsed = 0;
if (hovered_markers.size() == 0)
{
int gpu_y = y_offset + nb_thread_infos*line_height + line_height/2;
int gpu_y = int(y_offset + nb_thread_infos*line_height + line_height/2);
float total = 0;
for (unsigned i = 0; i < Q_LAST; i++)
{
@ -341,7 +341,7 @@ void Profiler::draw()
{
//Log::info("GPU Perf", "Phase %d : %d us\n", i, irr_driver->getGPUTimer(i).elapsedTimeus());
float elapsed = irr_driver->getGPUTimer(i).elapsedTimeus();
float elapsed = float(irr_driver->getGPUTimer(i).elapsedTimeus());
core::rect<s32> pos((s32)(x_offset + (curr_val / total)*profiler_width),
(s32)(y_offset + gpu_y),
(s32)(x_offset + ((curr_val + elapsed) / total)*profiler_width),

View File

@ -277,7 +277,7 @@ public:
{
for(int j=(int)start; j<(int)m_contents_vector.size()-1; j++)
{
if(*(m_contents_vector[j])>*(m_contents_vector[j+1])) continue;
if(*(m_contents_vector[j+1])<*(m_contents_vector[j])) continue;
// Now search the proper place for m_contents_vector[j+1]
// in the sorted section contentsVectot[start:j]
TYPE* t=m_contents_vector[j+1];
@ -286,7 +286,7 @@ public:
{
m_contents_vector[i] = m_contents_vector[i-1];
i--;
} while (i>start && *t>*(m_contents_vector[i-1]));
} while (i>start && *(m_contents_vector[i-1]) <*t);
m_contents_vector[i]=t;
}
}