Merge branch 'master' into Instancing

This commit is contained in:
Vincent Lejeune 2014-03-23 19:20:04 +01:00
commit 5dd2d28134
105 changed files with 3346 additions and 1955 deletions

View File

@ -6,9 +6,7 @@
language: cpp
compiler:
- gcc
#- clang
git:
submodules: false
# - clang
#branches:
# only:
# - master
@ -16,10 +14,13 @@ before_install:
# UPDATE REPOS
- sudo apt-get update -qq
# INSTALL DEPENDENCIES
- sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev
- sudo apt-get install build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev
script:
# BUILD COMMANDS
- ./tools/build-linux-travis.sh
- mkdir build
- cd build
- cmake .. -DCMAKE_BUILD_TYPE=Debug
- make VERBOSE=1 -j 4
notifications:
irc:
channels:

View File

@ -3,7 +3,7 @@ project(SuperTuxKart)
set(PROJECT_VERSION "0.8.1")
cmake_minimum_required(VERSION 2.8.1)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
include(BuildTypeSTKRelease)
if (NOT CMAKE_BUILD_TYPE)

Binary file not shown.

View File

@ -1,6 +1,6 @@
<?xml version="1.0"?>
<achievements>
<achievement id="1" check-type="all-at-least" reset-after-race="no"
<achievement id="1" check-type="all-at-least" reset-type="never"
title="Christoffel Columbus" description="Play every official track at least once." >
<farm goal="1"/>
<scotland goal="1"/>
@ -13,21 +13,35 @@
<hacienda goal="1"/>
<jungle goal="1"/>
</achievement>
<achievement id="2" check-type="all-at-least" reset-after-race="no"
<achievement id="2" check-type="all-at-least" reset-type="never"
title="Strike!" description="Hit 10 karts with a bowling-ball.">
<ball goal="10"/>
</achievement>
<achievement id="3" check-type="one-at-least" reset-after-race="yes"
<achievement id="3" check-type="one-at-least" reset-type="race"
title="Arch Enemy" description="Hit the same kart at least 5 times in one race">
<hit goal="5"/>
</achievement>
<achievement id="4" check-type="all-at-least" reset-after-race="yes"
<achievement id="4" check-type="all-at-least" reset-type="race"
title="Marathoner" description="Make a race with 5 laps or more">
<laps goal="5"/>
</achievement>
<achievement id="5" check-type="all-at-least" reset-after-race="yes"
title="Skid-row" description="Make 5 skidding in a single race">
<achievement id="5" check-type="all-at-least" reset-type="lap"
title="Skid-row" description="Make 5 skidding in a single lap">
<skidding goal="5"/>
</achievement>
</achievements>
<achievement id="6" check-type="all-at-least" reset-type="never"
title="Gold driver" description="Win in all single player modes, against at least 3 opponents.">
<standard goal="1"/>
<std_timetrial goal="1"/>
<follow_leader goal="1"/>
<opponents goal="3"/>
</achievement>
<achievement id="7" check-type="all-at-least" reset-type="race"
title="Powerup Love" description="Use 10 or more powerups in a race">
<poweruplover goal="10"/>
</achievement>
<achievement id="8" check-type="all-at-least" reset-type="never"
title="Unstoppable" description="Win 5 single races in a row">
<wins goal="5"/>
</achievement>
</achievements>

BIN
data/gui/down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,54 @@
<stkgui>
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row" padding="10">
<header id="selected_track" width="80%" height="30"
I18N="No neeed to translate this, it will be overwritten by the track name"
text="" align="center" text_align="center" />
<spacer height="20" />
<!-- Track selection -->
<box width="100%" height="60%" layout="vertical-row">
<ribbon_grid id="tracks" proportion="1" width="100%" height="100%" square_items="true"
label_location="each" align="center" child_width="240" child_height="160" />
</box>
<!-- Populated dynamically at runtime -->
<tabs width="100%" height="30" id="trackgroups"> </tabs>
<spacer height="50" />
<!-- Laps and reverse -->
<div width="100%" height="100" layout="horizontal-row" align="center">
<spacer proportion="1" />
<label id="laps_label" text_align="left"
I18N="In the edit track screen" text="Number of laps:" />
<spacer width="20" />
<spinner id="laps" proportion="1" width="100" min_value="1"
max_value="99" wrap_around="false" />
<spacer proportion="1" />
<label id="reverse_label" text_align="left"
I18N="In the edit track screen" text="Reverse:" />
<spacer width="20" />
<checkbox id="reverse" />
<spacer proportion="1" />
</div>
<!-- Dialog buttons -->
<div width="100%" height="60" layout="horizontal-row">
<spacer proportion="2" />
<button id="ok" text="OK" proportion="1" />
<spacer proportion="1" />
<button id="cancel" text="Cancel" proportion="1" />
<spacer proportion="2" />
</div>
</div>
</stkgui>

View File

@ -0,0 +1,21 @@
<stkgui>
<div x="2%" y="10%" width="96%" height="80%" layout="vertical-row" >
<label id="title" width="100%" text_align="center" word_wrap="true"
I18N="In the 'add new grand prix' dialog"
text="Please enter the name of the grand prix" proportion="1" />
<spacer height="25" width="10" />
<textbox id="textfield" width="75%" I18N="In the 'add new grand prix' dialog" align="center"/>
<spacer height="20" width="20" />
<button id="cancel" I18N="When configuring input" text="Press ESC to cancel" align="center"/>
<spacer height="15" width="20" />
</div>
</stkgui>

BIN
data/gui/gp_add_track.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
data/gui/gp_copy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
data/gui/gp_edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
data/gui/gp_edit_track.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
data/gui/gp_new.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
data/gui/gp_remove.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
data/gui/gp_rename.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
data/gui/gp_save.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

35
data/gui/gpedit.stkgui Normal file
View File

@ -0,0 +1,35 @@
<stkgui>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png" />
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row">
<header id="title" width="80%" I18N="Title in edit grand prix screen"
text="Edit Grand Prix" align="center" text_align="center" />
<spacer width="100%" height="2%" />
<box proportion="5" width="98%" align="center" layout="vertical-row" padding="6">
<list id="tracks" x="0" y="0" width="100%" height="100%" keep_selection="true" />
</box>
<spacer width="100%" height="2%" />
<buttonbar proportion="1" id="menu" height="135" width="100%" align="center">
<icon-button id="up" width="128" height="128" icon="gui/up.png"
I18N="Menu item" text="Move up" />
<icon-button id="down" width="128" height="128" icon="gui/down.png"
I18N="Menu item" text="Move down" />
<icon-button id="add" width="128" height="128" icon="gui/gp_add_track.png"
I18N="Menu item" text="Add" />
<icon-button id="edit" width="128" height="128" icon="gui/gp_edit_track.png"
I18N="Menu item" text="Edit" />
<icon-button id="remove" width="128" height="128" icon="gui/gp_remove_track.png"
I18N="Menu item" text="Remove" />
<icon-button id="save" width="128" height="128" icon="gui/gp_save.png"
I18N="Menu item" text="Save" />
</buttonbar>
</div>
</stkgui>

BIN
data/gui/gpeditor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

45
data/gui/gpeditor.stkgui Normal file
View File

@ -0,0 +1,45 @@
<stkgui>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row" >
<header width="80%" I18N="Title in grand prix editor screen" text="Grand Prix editor"
align="center" text_align="center" />
<spacer height="20" />
<box proportion="4" width="100%" layout="vertical-row">
<ribbon_grid id="gplist" proportion="1" width="100%" square_items="true"
label_location="each" align="left" max_rows="2" child_width="160"
child_height="120" keep_selection="true" />
</box>
<spacer height="10" />
<box proportion="2" width="100%" layout="vertical-row">
<label id="gpname" text_align="center" width="100%"
I18N="In the grand prix editor screen" text="" />
<ribbon_grid id="tracks" proportion="1" width="100%" square_items="true"
label_location="each" align="left" max_rows="1"
child_width="160" child_height="120" />
</box>
<spacer height="20" />
<buttonbar proportion="1" id="menu" height="135" width="100%" align="center">
<icon-button id="new" width="128" height="128" icon="gui/gp_new.png"
I18N="Menu item" text="New" />
<icon-button id="copy" width="128" height="128" icon="gui/gp_copy.png"
I18N="Menu item" text="Copy" />
<icon-button id="edit" width="128" height="128" icon="gui/gp_edit.png"
I18N="Menu item" text="Edit" />
<icon-button id="remove" width="128" height="128" icon="gui/gp_remove.png"
I18N="Menu item" text="Remove" />
<icon-button id="rename" width="128" height="128" icon="gui/gp_rename.png"
I18N="Menu item" text="Rename" />
</buttonbar>
</div>
</stkgui>

View File

@ -1,9 +1,9 @@
<stkgui>
<div x="0" y="0" width="100%" height="100%" layout="vertical-row" >
<icon id="logo" align="center" proportion="5" width="100%" icon="gui/logo.png"/>
<buttonbar id="menu_toprow" proportion="3" width="90%" align="center">
<icon-button id="story" width="128" height="128"
icon="gui/menu_story.png" focus_icon="gui/menu_story_focus.png"
@ -21,35 +21,37 @@
icon="gui/menu_addons.png" focus_icon="gui/menu_addons_focus.png"
I18N="Main menu button" text="Addons"/>
</buttonbar>
<spacer width="10" height="7%"/>
<bottombar width="100%" height="10%" layout="horizontal-row">
<spacer width="10" height="10" />
<label proportion="3" height="100%" id="info_addons"
I18N="In the main screen"
text=""
align="center" text_align="left" />
<spacer width="10" height="10" />
<buttonbar id="menu_bottomrow" x="0" y="0" width="30%" height="100%" align="center">
<buttonbar id="menu_bottomrow" x="0" y="0" width="38%" height="100%" align="center">
<icon-button id="options" width="64" height="64" icon="gui/main_options.png" extend_label="50"
I18N="Main menu button" text="Options" label_location="hover"/>
<icon-button id="help" width="64" height="64" icon="gui/main_help.png" extend_label="50"
I18N="Main menu button" text="Help" label_location="hover"/>
<icon-button id="startTutorial" width="64" height="64" icon="gui/tutorial.png" extend_label="150"
I18N="Main menu button" text="Tutorial" label_location="hover"/>
<icon-button id="gpEditor" width="64" height="64" icon="gui/gpeditor.png" extend_label="150"
I18N="Main menu button" text="Grand Prix Editor" label_location="hover"/>
<icon-button id="about" width="64" height="64" icon="gui/main_about.png" extend_label="50"
I18N="Main menu button" text="About" label_location="hover"/>
<icon-button id="quit" width="64" height="64" icon="gui/main_quit.png" extend_label="50"
I18N="Main menu button" text="Quit" label_location="hover"/>
</buttonbar>
</bottombar>
</div>
</stkgui>

BIN
data/gui/up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -1,9 +1,4 @@
uniform sampler2D Albedo;
uniform sampler2D DiffuseMap;
uniform sampler2D SpecularMap;
uniform sampler2D SSAO;
uniform vec2 screen;
uniform vec3 ambient;
uniform sampler2D caustictex;
uniform vec2 dir;
uniform vec2 dir2;
@ -16,17 +11,14 @@ varying vec2 uv;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(float specMapValue);
void main()
{
vec2 tc = gl_FragCoord.xy / screen;
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
vec4 color = texture(Albedo, uv);
float ao = texture(SSAO, tc).x;
float caustic = texture(caustictex, uv + dir).x;
float caustic2 = texture(caustictex, (uv.yx + dir2 * vec2(-0.6, 0.3)) * vec2(0.6)).x;
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent + caustic * caustic2 * 10;
vec3 LightFactor = getLightFactor(1.) + caustic * caustic2 * 10;
FragColor = vec4(color.xyz * LightFactor, 1.);
}

View File

@ -12,6 +12,208 @@ varying vec2 uv;
#define FragColor gl_FragColor
#endif
#define PI 3.14159265
/* ---------------------------------------------------------------------------------------------- */
// TEST
/* ---------------------------------------------------------------------------------------------- */
float width = 1920; //texture width
float height = 1080; //texture height
vec2 texel = vec2(1.0/width,1.0/height);
//------------------------------------------
//user variables
int samples = 3; //samples on the first ring
int rings = 5; //ring count
bool autofocus = false; //use autofocus in shader? disable if you use external focalDepth value
float focalDepth = 0.1;
vec2 focus = vec2(0.5,0.5); // autofocus point on screen (0.0,0.0 - left lower corner, 1.0,1.0 - upper right)
float range = 150.0; //focal range
float maxblur = 1.25; //clamp value of max blur
float threshold = 0.9; //highlight threshold;
float gain = 10.0; //highlight gain;
float bias = 0.4; //bokeh edge bias
float fringe = 0.5; //bokeh chromatic aberration/fringing
bool noise = true; //use noise instead of pattern for sample dithering
float namount = 0.0001; //dither amount
bool depthblur = false; //blur the depth buffer?
float dbsize = 2.0; //depthblursize
/* ---------------------------------------------------------------------------------------------- */
// Function
/* ---------------------------------------------------------------------------------------------- */
vec3 color(vec2 coords,float blur) //processing the sample
{
vec3 col = vec3(0.0);
col.r = texture2D(tex,coords + vec2(0.0,1.0)*texel*fringe*blur).r;
col.g = texture2D(tex,coords + vec2(-0.866,-0.5)*texel*fringe*blur).g;
col.b = texture2D(tex,coords + vec2(0.866,-0.5)*texel*fringe*blur).b;
vec3 lumcoeff = vec3(0.299,0.587,0.114);
float lum = dot(col.rgb, lumcoeff);
float thresh = max((lum-threshold)*gain, 0.0);
return col+mix(vec3(0.0),col,thresh*blur);
}
vec2 rand(in vec2 coord) //generating noise/pattern texture for dithering
{
float noiseX = ((fract(1.0-coord.s*(width/2.0))*0.25)+(fract(coord.t*(height/2.0))*0.75))*2.0-1.0;
float noiseY = ((fract(1.0-coord.s*(width/2.0))*0.75)+(fract(coord.t*(height/2.0))*0.25))*2.0-1.0;
if (noise)
{
noiseX = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233))) * 43758.5453),0.0,1.0)*2.0-1.0;
noiseY = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233)*2.0)) * 43758.5453),0.0,1.0)*2.0-1.0;
}
return vec2(noiseX,noiseY);
}
void main()
{
//float depth = texture2D(dtex,uv).x;
float curdepth = texture(dtex, uv).x;
vec4 FragPos = invprojm * (2.0f * vec4(uv, curdepth, 1.0f) - 1.0f);
FragPos /= FragPos.w;
float depth = clamp((FragPos.z/180), 0., 1.);
float blur = 0.0;
blur = clamp((abs(depth - focalDepth)/range)*100.0,-maxblur,maxblur);
vec2 noise = rand(uv)*namount*blur;
float w = (1.0/width)*blur+noise.x;
float h = (1.0/height)*blur+noise.y;
vec3 col = texture2D(tex, uv).rgb;
vec3 colDof = col;
float s = 1.0;
int ringsamples;
for (int i = 1; i <= rings; i += 1)
{
ringsamples = i * samples;
for (int j = 0 ; j < ringsamples ; j += 1)
{
float step = PI*2.0 / float(ringsamples);
float pw = (cos(float(j)*step)*float(i));
float ph = (sin(float(j)*step)*float(i));
float p = 1.0;
colDof += color(uv + vec2(pw*w,ph*h),blur)*mix(1.0,(float(i))/(float(rings)),bias)*p;
s += 1.0*mix(1.0,(float(i))/(float(rings)),bias)*p;
}
}
colDof /= s;
// get color correction values
float inBlack = inlevel.x;
float inWhite = inlevel.z;
float inGamma = inlevel.y;
float outBlack = outlevel.x;
float outWhite = outlevel.y;
vec3 colOut = (pow(((col.rgb * 255.0) - inBlack) / (inWhite - inBlack),
vec3(1.0 / inGamma)) * (outWhite - outBlack) + outBlack) / 255.0;
depth = (1 - depth);
vec3 final = colOut * depth + colDof.rgb * (1 - depth);
vec2 inTex = uv - 0.5;
float vignette = 1 - dot(inTex, inTex);
vignette = clamp(pow(vignette, 0.8), 0., 1.) ;
vignette = vignette + vignette - 0.5;
final.rgb *= clamp(vignette, 0., 1.15);
FragColor.rgb = final;
FragColor.a = 1.0;
}
/*
void main()
{
vec2 texc = uv;
//texc.y = 1.0 - texc.y;
vec4 col = texture(tex, texc);
float curdepth = texture(dtex, uv).x;
vec2 inTex = uv - 0.5;
float vignette = 1 - dot(inTex, inTex);
vec4 FragPos = invprojm * (2.0f * vec4(uv, curdepth, 1.0f) - 1.0f);
FragPos /= FragPos.w;
//col = col / (1 - col);
float inBlack = inlevel.x;
float inWhite = inlevel.z;
float inGamma = inlevel.y;
float outBlack = outlevel.x;
float outWhite = outlevel.y;
float depth1 = clamp((FragPos.z/180), 0., 1.);
vec3 colOut = (pow(((col.rgb * 255.0) - inBlack) / (inWhite - inBlack),
vec3(1.0 / inGamma)) * (outWhite - outBlack) + outBlack) / 255.0;
depth1 = (1 - depth1);
vec3 final = colOut * depth1 + col.rgb * (1 - depth1);
vignette = clamp(pow(vignette, 0.8), 0., 1.) ;
vignette = vignette + vignette - 0.5;
final.rgb *= clamp(vignette, 0., 1.15);
FragColor = vec4(final, 1.0);
}*/
/*uniform sampler2D tex;
uniform sampler2D dtex;
uniform vec3 inlevel;
uniform vec2 outlevel;
uniform mat4 invprojm;
#if __VERSION__ >= 130
in vec2 uv;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main()
@ -21,14 +223,14 @@ void main()
float curdepth = texture(dtex, uv).x;
vec4 FragPos = invprojm * (2.0 * vec4(uv, curdepth, 1.0f) - 1.0f);
FragPos /= FragPos.w;
float depth = clamp(FragPos.z / 180, 0, 1);
float depth = clamp(FragPos.z / 180, 0., 1.);
depth = (1 - depth);
// Compute the vignette
vec2 inside = uv - 0.5;
float vignette = 1 - dot(inside, inside);
vignette = clamp(pow(vignette, 0.8), 0, 1);
vignette = clamp(vignette + vignette - 0.5, 0, 1.15);
vignette = clamp(pow(vignette, 0.8), 0., 1.);
vignette = clamp(vignette + vignette - 0.5, 0., 1.15);
float inBlack = inlevel.x;
float inWhite = inlevel.z;
@ -44,4 +246,4 @@ void main()
FragColor = vec4(colFinal * vignette, 1.0);
//FragColor = vec4(vec3(depth), 1.0);
}
}*/

View File

@ -1,10 +1,5 @@
uniform sampler2D Albedo;
uniform sampler2D Detail;
uniform sampler2D DiffuseMap;
uniform sampler2D SpecularMap;
uniform sampler2D SSAO;
uniform vec2 screen;
uniform vec3 ambient;
#if __VERSION__ >= 130
in vec2 uv;
@ -16,17 +11,13 @@ varying vec2 uv_bis;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(float specMapValue);
void main(void)
{
vec2 tc = gl_FragCoord.xy / screen;
vec4 color = texture(Albedo, uv);
vec4 detail = texture(Detail, uv_bis);
color *= detail;
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
float ao = texture(SSAO, tc).x;
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent * (1. - color.a);
FragColor = vec4(color.xyz * LightFactor * ao, 1.);
vec4 detail = texture(Detail, uv_bis);
color *= detail;
vec3 LightFactor = getLightFactor(1. - color.a);
FragColor = vec4(color.xyz * LightFactor, 1.);
}

View File

@ -14,12 +14,7 @@ varying vec2 uv;
#define Spec gl_FragData[1]
#endif
vec3 DecodeNormal(vec2 n)
{
float z = dot(n, n) * 2. - 1.;
vec2 xy = normalize(n) * sqrt(1. - z * z);
return vec3(xy,z);
}
vec3 DecodeNormal(vec2 n);
mat4 getMatrix(float L[9])
{

View File

@ -13,11 +13,8 @@ varying vec2 uv;
#endif
// from Crytek "a bit more deferred CryEngine"
vec2 EncodeNormal(vec3 n)
{
return normalize(n.xy) * sqrt(n.z * 0.5 + 0.5);
}
vec2 EncodeNormal(vec3 n);
void main()
{

View File

@ -6,13 +6,7 @@ varying vec3 nor;
#define EncodedNormal gl_FragColor.xy
#endif
// from Crytek "a bit more deferred CryEngine"
vec2 EncodeNormal(vec3 n)
{
return normalize(n.xy) * sqrt(n.z * 0.5 + 0.5);
}
vec2 EncodeNormal(vec3 n);
void main(void)
{

View File

@ -1,9 +1,4 @@
uniform sampler2D Albedo;
uniform sampler2D DiffuseMap;
uniform sampler2D SpecularMap;
uniform sampler2D SSAO;
uniform vec2 screen;
uniform vec3 ambient;
#if __VERSION__ >= 130
in vec2 uv;
@ -13,15 +8,11 @@ varying vec2 uv;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(float specMapValue);
void main(void)
{
vec2 tc = gl_FragCoord.xy / screen;
vec4 color = texture(Albedo, uv);
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
float ao = texture(SSAO, tc).x;
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent * (1. - color.a);
FragColor = vec4(color.xyz * LightFactor * (0.4 + ao*0.6), 1.);
//FragColor = vec4(color.xyz * LightFactor, 1.);
vec3 LightFactor = getLightFactor(1. - color.a);
FragColor = vec4(color.xyz * LightFactor, 1.);
}

View File

@ -10,12 +10,7 @@ varying vec2 uv;
#define EncodedNormal gl_FragColor.xy
#endif
// from Crytek "a bit more deferred CryEngine"
vec2 EncodeNormal(vec3 n)
{
return normalize(n.xy) * sqrt(n.z * 0.5 + 0.5);
}
vec2 EncodeNormal(vec3 n);
void main() {
vec4 col = texture(tex, uv);

View File

@ -1,9 +1,4 @@
uniform sampler2D Albedo;
uniform sampler2D DiffuseMap;
uniform sampler2D SpecularMap;
uniform sampler2D SSAO;
uniform vec2 screen;
uniform vec3 ambient;
#if __VERSION__ >= 130
in vec2 uv;
@ -13,15 +8,12 @@ varying vec2 uv;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(float specMapValue);
void main(void)
{
vec4 color = texture(Albedo, uv);
if (color.a < 0.5) discard;
vec2 tc = gl_FragCoord.xy / screen;
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
float ao = texture(SSAO, tc).x;
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent;
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(color.xyz * LightFactor, 1.);
}

View File

@ -1,4 +1,4 @@
#version 330
#version 140
uniform sampler2D tex;
in vec2 uv;

View File

@ -1,5 +1,5 @@
// Passthrough shader for drawQuad()
#version 330
#version 140
in vec3 Position;
in vec2 Texcoord;

View File

@ -12,12 +12,7 @@ flat in vec3 col;
out vec4 Diffuse;
out vec4 Specular;
vec3 DecodeNormal(vec2 n)
{
float z = dot(n, n) * 2. - 1.;
vec2 xy = normalize(n) * sqrt(1. - z * z);
return vec3(xy,z);
}
vec3 DecodeNormal(vec2 n);
void main() {
vec2 texc = gl_FragCoord.xy / screen;

View File

@ -25,12 +25,7 @@ vec3 rand(vec2 co)
return texture(noise_texture, co*20.16).xyz;
}
vec3 DecodeNormal(vec2 n)
{
float z = dot(n, n) * 2. - 1.;
vec2 xy = normalize(n) * sqrt(1. - z * z);
return vec3(xy,z);
}
vec3 DecodeNormal(vec2 n);
void main(void)
{

View File

@ -19,12 +19,7 @@ varying vec2 uv;
#endif
vec3 DecodeNormal(vec2 n)
{
float z = dot(n, n) * 2. - 1.;
vec2 xy = normalize(n) * sqrt(1. - z * z);
return vec3(xy,z);
}
vec3 DecodeNormal(vec2 n);
void main() {
float z = texture(dtex, uv).x;

View File

@ -23,18 +23,13 @@ varying vec2 uv;
#endif
vec3 DecodeNormal(vec2 n)
{
float z = dot(n, n) * 2. - 1.;
vec2 xy = normalize(n) * sqrt(1. - z * z);
return vec3(xy,z);
}
vec3 DecodeNormal(vec2 n);
float getShadowFactor(vec3 pos, float bias, int index)
{
//float a[5] = float[](3.4, 4.2, 5.0, 5.2, 1.1);
const vec2 shadowoffset[4] = vec2[](
vec2 shadowoffset[4] = vec2[](
vec2(-1., -1.),
vec2(-1., 1.),
vec2(1., -1.),

View File

@ -2,6 +2,7 @@ uniform sampler2D tex;
#if __VERSION__ >= 130
in vec2 uv;
in vec4 color;
out vec4 FragColor;
#else
varying vec2 uv;
@ -11,5 +12,5 @@ varying vec2 uv;
void main()
{
FragColor = texture(tex, uv);
FragColor = texture(tex, uv) * color;
}

View File

@ -4,7 +4,9 @@ uniform mat4 TextureMatrix;
#if __VERSION__ >= 130
in vec3 Position;
in vec2 Texcoord;
in vec4 Color;
out vec2 uv;
out vec4 color;
#else
attribute vec3 Position;
attribute vec2 Texcoord;
@ -16,4 +18,5 @@ void main()
{
uv = (TextureMatrix * vec4(Texcoord, 1., 1.)).xy;
gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.);
color = Color;
}

View File

@ -11,6 +11,7 @@ uniform vec2 screen;
#if __VERSION__ >= 130
in vec2 uv;
in vec4 color;
out vec4 FragColor;
#else
varying vec2 uv;
@ -20,7 +21,7 @@ varying vec2 uv;
void main()
{
vec4 color = texture(tex, uv);
vec4 diffusecolor = texture(tex, uv) * color;
vec3 tmp = vec3(gl_FragCoord.xy / screen, gl_FragCoord.z);
tmp = 2. * tmp - 1.;
@ -33,5 +34,5 @@ void main()
fog = min(fog, fogmax);
FragColor = vec4(vec4(col, 0.) * fog + color *(1. - fog));
FragColor = vec4(vec4(col, 0.) * fog + diffusecolor *(1. - fog));
}

View File

@ -1,8 +1,3 @@
uniform sampler2D DiffuseMap;
uniform sampler2D SpecularMap;
uniform sampler2D SSAO;
uniform vec2 screen;
uniform vec3 ambient;
#if __VERSION__ >= 130
in vec4 color;
@ -12,14 +7,10 @@ varying vec4 color;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(float specMapValue);
void main(void)
{
vec2 tc = gl_FragCoord.xy / screen;
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
float ao = texture(SSAO, tc).x;
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent * (1. - color.a);
FragColor = vec4(color.xyz * LightFactor * ao, 1.);
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(color.xyz * LightFactor, 1.);
}

View File

@ -0,0 +1,7 @@
vec3 DecodeNormal(vec2 n)
{
float z = dot(n, n) * 2. - 1.;
vec2 xy = normalize(n) * sqrt(1. - z * z);
return vec3(xy,z);
}

View File

@ -0,0 +1,5 @@
// from Crytek "a bit more deferred CryEngine"
vec2 EncodeNormal(vec3 n)
{
return normalize(n.xy) * sqrt(n.z * 0.5 + 0.5);
}

View File

@ -0,0 +1,15 @@
uniform sampler2D DiffuseMap;
uniform sampler2D SpecularMap;
uniform sampler2D SSAO;
uniform vec2 screen;
uniform vec3 ambient;
vec3 getLightFactor(float specMapValue)
{
vec2 tc = gl_FragCoord.xy / screen;
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
float ao = texture(SSAO, tc).x;
vec3 tmp = ao * ambient + DiffuseComponent + SpecularComponent * specMapValue;
return tmp * (0.4 + ao*0.6);
}

View File

@ -1,13 +1,13 @@
# CMakeLists.txt for Irrlicht in STK
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/
${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/jpeglib
${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/libpng
${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/zlib
${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/bzip2)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/"
"${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/jpeglib"
"${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/libpng"
"${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/zlib"
"${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/bzip2")
if(APPLE)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/MacOSX ${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/MacOSX" "${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch i386")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch i386 -F/Library/Frameworks")
endif()

View File

@ -368,6 +368,65 @@ void IrrPrintXGrabError(int grabResult, const c8 * grabCommand )
}
#endif
static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig)
{
GLXContext Context;
int compat33ctx[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
None
};
int core33ctx[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
None
};
int core31ctx[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
None
};
int legacyctx[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
None
};
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
// create compat 3.3 context (for proprietary drivers)
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, compat33ctx);
if (!XErrorSignaled)
return Context;
XErrorSignaled = false;
// create core 3.3 context (for mesa)
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, core33ctx);
if (!XErrorSignaled)
return Context;
XErrorSignaled = false;
// create core 3.1 context (for older mesa)
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, core31ctx);
if (!XErrorSignaled)
return Context;
XErrorSignaled = false;
// fall back to legacy context
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, legacyctx);
return Context;
}
bool CIrrDeviceLinux::createWindow()
{
@ -741,30 +800,7 @@ bool CIrrDeviceLinux::createWindow()
glxWin=glXCreateWindow(display,glxFBConfig,window,NULL);
if (glxWin)
{
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, //GLX_CONTEXT_CORE_PROFILE_BIT_ARB
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
None
};
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
// create glx context
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, context_attribs);
if (XErrorSignaled)
{
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
None
};
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, context_attribs);
XErrorSignaled = false;
}
Context = getMeAGLContext(display, glxFBConfig);
if (Context)
{
if (!glXMakeContextCurrent(display, glxWin, glxWin, Context))

View File

@ -868,16 +868,9 @@ bool COpenGLFBODepthTexture::attach(ITexture* renderTex)
#ifdef GL_EXT_framebuffer_object
if (UseStencil)
{
// attach stencil texture to stencil buffer
// attach depth stencil texture to depth buffer
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
GL_STENCIL_ATTACHMENT_EXT,
GL_TEXTURE_2D,
StencilRenderBuffer,
0);
// attach depth texture to depth buffer
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D,
DepthRenderBuffer,
0);

View File

@ -2,6 +2,16 @@
cmake_minimum_required(VERSION 2.8.1)
# libbluetooth is required on Unix platforms
if(UNIX)
include(FindPkgConfig)
pkg_check_modules(BLUETOOTH bluez)
if(NOT BLUETOOTH_FOUND)
message(FATAL_ERROR "Bluetooth library not found. "
"Either install libbluetooth or disable wiiuse support with -DUSE_WIIUSE=0")
endif()
endif()
set(WIIUSE_SOURCES
classic.c
dynamics.c

View File

@ -228,6 +228,7 @@ src/states_screens/dialogs/addons_loading.cpp
src/states_screens/dialogs/change_password_dialog.cpp
src/states_screens/dialogs/confirm_resolution_dialog.cpp
src/states_screens/dialogs/custom_video_settings.cpp
src/states_screens/dialogs/enter_gp_name_dialog.cpp
src/states_screens/dialogs/enter_player_name_dialog.cpp
src/states_screens/dialogs/gp_info_dialog.cpp
src/states_screens/dialogs/message_dialog.cpp
@ -244,7 +245,10 @@ src/states_screens/dialogs/tutorial_message_dialog.cpp
src/states_screens/dialogs/user_info_dialog.cpp
src/states_screens/dialogs/vote_dialog.cpp
src/states_screens/easter_egg_screen.cpp
src/states_screens/edit_gp_screen.cpp
src/states_screens/edit_track_screen.cpp
src/states_screens/feature_unlocked.cpp
src/states_screens/grand_prix_editor_screen.cpp
src/states_screens/grand_prix_lose.cpp
src/states_screens/grand_prix_win.cpp
src/states_screens/guest_login_screen.cpp
@ -565,6 +569,7 @@ src/states_screens/dialogs/addons_loading.hpp
src/states_screens/dialogs/change_password_dialog.hpp
src/states_screens/dialogs/confirm_resolution_dialog.hpp
src/states_screens/dialogs/custom_video_settings.hpp
src/states_screens/dialogs/enter_gp_name_dialog.hpp
src/states_screens/dialogs/enter_player_name_dialog.hpp
src/states_screens/dialogs/gp_info_dialog.hpp
src/states_screens/dialogs/message_dialog.hpp
@ -581,7 +586,10 @@ src/states_screens/dialogs/tutorial_message_dialog.hpp
src/states_screens/dialogs/user_info_dialog.hpp
src/states_screens/dialogs/vote_dialog.hpp
src/states_screens/easter_egg_screen.hpp
src/states_screens/edit_gp_screen.hpp
src/states_screens/edit_track_screen.hpp
src/states_screens/feature_unlocked.hpp
src/states_screens/grand_prix_editor_screen.hpp
src/states_screens/grand_prix_lose.hpp
src/states_screens/grand_prix_win.hpp
src/states_screens/guest_login_screen.hpp

View File

@ -179,6 +179,15 @@ void Achievement::onRaceEnd()
reset();
} // onRaceEnd
// ----------------------------------------------------------------------------
/** Called at the end of a lap to potentially reset values.
*/
void Achievement::onLapEnd()
{
if (m_achievement_info->needsResetAfterLap())
reset();
} // onLapEnd
// ----------------------------------------------------------------------------
/** Checks if this achievement has been achieved.
*/

View File

@ -69,7 +69,8 @@ public:
virtual void reset();
virtual irr::core::stringw getProgressAsString() const;
void onRaceEnd();
void onRaceEnd();
void onLapEnd();
// ------------------------------------------------------------------------
/** Returns the id of this achievement. */
uint32_t getID() const { return m_id; }

View File

@ -31,7 +31,7 @@
*/
AchievementInfo::AchievementInfo(const XMLNode * input)
{
m_reset_after_race = false;
m_reset_type = NEVER;
m_id = 0;
m_title = "";
m_description = "";
@ -47,10 +47,20 @@ AchievementInfo::AchievementInfo(const XMLNode * input)
"ID %d title '%s' description '%s'", m_id, m_title.c_str(),
m_description.c_str());
}
input->get("reset-after-race", &m_reset_after_race);
m_check_type = AC_ALL_AT_LEAST;
// Load the reset-type
std::string s;
input->get("reset-type", &s);
if (s == "race")
m_reset_type = AFTER_RACE;
else if (s == "lap")
m_reset_type = AFTER_LAP;
else if (s != "never")
Log::warn("AchievementInfo", "Achievement check type '%s' unknown.",
s.c_str());
// Load check-type
m_check_type = AC_ALL_AT_LEAST;
input->get("check-type", &s);
if (s == "all-at-least")
m_check_type = AC_ALL_AT_LEAST;

View File

@ -33,31 +33,45 @@
class Achievement;
/** This is the base class for storing the definition of an achievement, e.g.
/** This is the base class for storing the definition of an achievement, e.g.
* title, description (which is common for all achievements), but also how
* to achieve this achievement.
* \ingroup achievements
*/
* \ingroup achievements
*/
class AchievementInfo
{
public:
/** Some handy names for the various achievements. */
enum { ACHIEVE_COLUMBUS = 1,
ACHIEVE_FIRST = ACHIEVE_COLUMBUS,
ACHIEVE_STRIKE = 2,
ACHIEVE_ARCH_ENEMY = 3,
ACHIEVE_MARATHONER = 4,
ACHIEVE_SKIDDING = 5
enum { ACHIEVE_COLUMBUS = 1,
ACHIEVE_FIRST = ACHIEVE_COLUMBUS,
ACHIEVE_STRIKE = 2,
ACHIEVE_ARCH_ENEMY = 3,
ACHIEVE_MARATHONER = 4,
ACHIEVE_SKIDDING = 5,
ACHIEVE_GOLD_DRIVER = 6,
ACHIEVE_POWERUP_LOVER = 7,
ACHIEVE_UNSTOPPABLE = 8
};
/** Achievement check type:
/** Achievement check type:
* ALL_AT_LEAST: All goal values must be reached (or exceeded).
* ONE_AT_LEAST: At least one current value reaches or exceedes the goal.
*/
enum AchievementCheckType
enum AchievementCheckType
{
AC_ALL_AT_LEAST,
AC_ONE_AT_LEAST
};
/** Achievement reset type:
* AFTER_LAP: Achievement needs to be reset after each lap.
* AFTER_RACE: Achievement needs to be reset after each race.
* NEVER: Achievement does not need to be reset
*/
enum ResetType
{
AFTER_LAP = 1,
AFTER_RACE = 2,
NEVER = 3
};
private:
/** The id of this Achievement. */
@ -75,8 +89,8 @@ private:
/** The target values needed to be reached. */
std::map<std::string, int> m_goal_values;
/** True if the achievement needs to be reset after each race. */
bool m_reset_after_race;
/** Determines when the achievement needs to be reset */
ResetType m_reset_type;
public:
AchievementInfo(const XMLNode * input);
@ -96,7 +110,9 @@ public:
/** Returns the title of this achievement. */
irr::core::stringw getTitle() const { return m_title; }
// ------------------------------------------------------------------------
bool needsResetAfterRace() const { return m_reset_after_race; }
bool needsResetAfterRace() const { return m_reset_type == AFTER_RACE; }
// ------------------------------------------------------------------------
bool needsResetAfterLap() const { return m_reset_type == AFTER_LAP; }
// ------------------------------------------------------------------------
/** Returns the check type for this achievement. */
AchievementCheckType getCheckType() const { return m_check_type; }

View File

@ -95,14 +95,6 @@ AchievementsStatus*
return status;
} // createAchievementStatus
// ----------------------------------------------------------------------------
void AchievementsManager::onRaceEnd()
{
//reset all values that need to be reset
PlayerManager::get()->getCurrentPlayer()
->getAchievementsStatus()->onRaceEnd();
} // onRaceEnd
// ----------------------------------------------------------------------------
AchievementInfo * AchievementsManager::getAchievementInfo(uint32_t id) const
{

View File

@ -71,7 +71,6 @@ public:
} // destroy
// ========================================================================
void onRaceEnd();
AchievementInfo* getAchievementInfo(uint32_t id) const;
AchievementsStatus* createAchievementsStatus(const XMLNode *node=NULL);
// ------------------------------------------------------------------------

View File

@ -132,3 +132,12 @@ void AchievementsStatus::onRaceEnd()
iter->second->onRaceEnd();
}
} // onRaceEnd
void AchievementsStatus::onLapEnd()
{
//reset all values that need to be reset
std::map<uint32_t, Achievement *>::iterator iter;
for (iter = m_achievements.begin(); iter != m_achievements.end(); ++iter) {
iter->second->onLapEnd();
}
} // onLapEnd

View File

@ -60,6 +60,7 @@ public :
void add(Achievement *achievement);
void sync(const std::vector<uint32_t> & achieved_ids);
void onRaceEnd();
void onLapEnd();
// ------------------------------------------------------------------------
const std::map<uint32_t, Achievement *>& getAllAchievements()
{

View File

@ -314,16 +314,6 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
return sfx;
} // createSoundSource
//----------------------------------------------------------------------------
void SFXManager::dump()
{
for(int n=0; n<(int)m_all_sfx.size(); n++)
{
Log::debug("SFXManager", "Sound %i : %s \n", n, m_all_sfx[n]->getBuffer()->getFileName().c_str());
}
}
//----------------------------------------------------------------------------
SFXBase* SFXManager::createSoundSource(const std::string &name,
const bool addToSFXList)

View File

@ -65,8 +65,10 @@ PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
static bool is_gl_init = false;
#ifdef DEBUG
#ifdef WIN32
#define ARB_DEBUG_OUTPUT
#endif
#endif
#ifdef ARB_DEBUG_OUTPUT
static void
@ -202,15 +204,17 @@ void initGL()
#endif
#endif
#ifdef ARB_DEBUG_OUTPUT
glDebugMessageCallbackARB((GLDEBUGPROCARB)debugCallback, NULL);
glDebugMessageCallbackARB((GLDEBUGPROCARB)debugCallback, NULL);
#endif
}
// Mostly from shader tutorial
static GLuint LoadShader(const char * file, unsigned type)
GLuint LoadShader(const char * file, unsigned type)
{
GLuint Id = glCreateShader(type);
std::string Code = "#version 330\n";
char versionString[20];
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
std::string Code = versionString;
std::ifstream Stream(file, std::ios::in);
if (Stream.is_open())
{
@ -230,10 +234,11 @@ static GLuint LoadShader(const char * file, unsigned type)
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
if (Result == GL_FALSE)
{
Log::error("GLWrap", "Error in shader %s", file);
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
printf(ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
@ -246,80 +251,10 @@ static GLuint LoadShader(const char * file, unsigned type)
return Id;
}
GLuint LoadProgram(const char * vertex_file_path, const char * fragment_file_path)
{
GLuint VertexShaderID = LoadShader(vertex_file_path, GL_VERTEX_SHADER);
GLuint FragmentShaderID = LoadShader(fragment_file_path, GL_FRAGMENT_SHADER);
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE) {
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
printf(ErrorMessage);
delete[] ErrorMessage;
}
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
return ProgramID;
}
GLuint LoadProgram(const char * vertex_file_path, const char * geometry_file_path, const char * fragment_file_path)
{
GLuint VertexShaderID = LoadShader(vertex_file_path, GL_VERTEX_SHADER);
GLuint FragmentShaderID = LoadShader(fragment_file_path, GL_FRAGMENT_SHADER);
GLuint GeometryShaderID = LoadShader(geometry_file_path, GL_GEOMETRY_SHADER);
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, GeometryShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE) {
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
printf(ErrorMessage);
delete[] ErrorMessage;
}
glDeleteShader(VertexShaderID);
glDeleteShader(GeometryShaderID);
glDeleteShader(FragmentShaderID);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
return ProgramID;
}
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
{
GLuint Shader = LoadShader(vertex_file_path, GL_VERTEX_SHADER);
GLuint Program = glCreateProgram();
glAttachShader(Program, Shader);
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(Program);
@ -334,7 +269,6 @@ GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsi
printf(ErrorMessage);
delete[] ErrorMessage;
}
glDeleteShader(Shader);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
@ -428,6 +362,16 @@ void drawTexQuad(const video::ITexture *texture, float width, float height,
}
}
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, bool useAlphaChannelOfTexture)
{
video::SColor duplicatedArray[4] = {
colors, colors, colors, colors
};
draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
}
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor* const colors, bool useAlphaChannelOfTexture)

View File

@ -18,11 +18,7 @@
# include <GL/gl.h>
#endif
void initGL();
GLuint LoadProgram(const char * vertex_file_path, const char * fragment_file_path);
GLuint LoadProgram(const char * vertex_file_path, const char * geometry_file_path, const char * fragment_file_path);
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF = false);
#include "utils/log.hpp"
// already includes glext.h, which defines useful GL constants.
// COpenGLDriver has already loaded the extension GL functions we use (e.g glBeginQuery)
@ -87,6 +83,53 @@ extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
#endif
void initGL();
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF = false);
GLuint LoadShader(const char * file, unsigned type);
template<typename ... Types>
void loadAndAttach(GLint ProgramID)
{
return;
}
template<typename ... Types>
void loadAndAttach(GLint ProgramID, GLint ShaderType, const char *filepath, Types ... args)
{
GLint ShaderID = LoadShader(filepath, ShaderType);
glAttachShader(ProgramID, ShaderID);
glDeleteShader(ShaderID);
loadAndAttach(ProgramID, args...);
}
template<typename ... Types>
GLint LoadProgram(Types ... args)
{
GLint ProgramID = glCreateProgram();
loadAndAttach(ProgramID, args...);
glLinkProgram(ProgramID);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE) {
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
printf(ErrorMessage);
delete[] ErrorMessage;
}
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
return ProgramID;
}
// core::rect<s32> needs these includes
#include <rect.h>
#include "utils/vec3.hpp"
@ -94,6 +137,10 @@ extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
GLuint getTextureGLuint(irr::video::ITexture *tex);
GLuint getDepthTexture(irr::video::ITexture *tex);
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<s32>& destRect,
const irr::core::rect<s32>& sourceRect, const irr::core::rect<s32>* clipRect,
const irr::video::SColor &color, bool useAlphaChannelOfTexture);
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<s32>& destRect,
const irr::core::rect<s32>& sourceRect, const irr::core::rect<s32>* clipRect,
const irr::video::SColor* const colors, bool useAlphaChannelOfTexture);

View File

@ -47,10 +47,6 @@ ParticleSystemProxy::ParticleSystemProxy(bool createDefaultEmitter,
heighmapbuffer = 0;
heightmaptexture = 0;
current_simulation_vao = 0;
non_currenthm__simulation_vao = 0;
current_hm_simulation_vao = 0;
current_rendering_flip_vao = 0;
non_current_rendering_flip_vao = 0;
has_height_map = false;
flip = false;
track_x = 0;
@ -77,41 +73,17 @@ ParticleSystemProxy::~ParticleSystemProxy()
{
glDeleteBuffers(2, tfb_buffers);
glDeleteBuffers(1, &initial_values_buffer);
glDeleteBuffers(1, &quaternionsbuffer);
if (has_height_map)
{
if (quaternionsbuffer)
glDeleteBuffers(1, &quaternionsbuffer);
if (heighmapbuffer)
glDeleteBuffers(1, &heighmapbuffer);
if (heightmaptexture)
glDeleteTextures(1, &heightmaptexture);
}
}
void ParticleSystemProxy::setFlip()
{
flip = true;
float *quaternions = new float[4 * count];
for (unsigned i = 0; i < count; i++)
{
core::vector3df rotationdir(0., 1., 0.);
quaternions[4 * i] = rotationdir.X;
quaternions[4 * i + 1] = rotationdir.Y;
quaternions[4 * i + 2] = rotationdir.Z;
quaternions[4 * i + 3] = 3.14f * 3.f * (2.f * os::Randomizer::frand() - 1.f); // 3 half rotation during lifetime at max
}
glGenBuffers(1, &quaternionsbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer);
glBufferData(GL_ARRAY_BUFFER, 4 * count * sizeof(float), quaternions, GL_STATIC_DRAW);
glGenVertexArrays(1, &current_rendering_flip_vao);
glBindVertexArray(current_rendering_flip_vao);
FlipParticleVAOBind(tfb_buffers[0], quaternionsbuffer);
glGenVertexArrays(1, &non_current_rendering_flip_vao);
glBindVertexArray(non_current_rendering_flip_vao);
FlipParticleVAOBind(tfb_buffers[1], quaternionsbuffer);
glBindVertexArray(0);
delete[] quaternions;
}
void ParticleSystemProxy::setHeightmap(const std::vector<std::vector<float> > &hm,
@ -138,16 +110,6 @@ void ParticleSystemProxy::setHeightmap(const std::vector<std::vector<float> > &h
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, heighmapbuffer);
glBindBuffer(GL_TEXTURE_BUFFER, 0);
glGenVertexArrays(1, &current_hm_simulation_vao);
glBindVertexArray(current_hm_simulation_vao);
HeightmapSimulationBind(tfb_buffers[0], initial_values_buffer);
glGenVertexArrays(1, &non_currenthm__simulation_vao);
glBindVertexArray(non_currenthm__simulation_vao);
HeightmapSimulationBind(tfb_buffers[1], initial_values_buffer);
glBindVertexArray(0);
delete[] hm_array;
}
@ -419,21 +381,6 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter)
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(current_rendering_vao);
SimpleParticleVAOBind(tfb_buffers[0]);
glBindVertexArray(non_current_rendering_vao);
SimpleParticleVAOBind(tfb_buffers[1]);
glGenVertexArrays(1, &current_simulation_vao);
glBindVertexArray(current_simulation_vao);
SimpleSimulationBind(tfb_buffers[0], initial_values_buffer);
glGenVertexArrays(1, &non_current_simulation_vao);
glBindVertexArray(non_current_simulation_vao);
SimpleSimulationBind(tfb_buffers[1], initial_values_buffer);
glBindVertexArray(0);
texture = getTextureGLuint(getMaterial(0).getTexture(0));
@ -459,7 +406,7 @@ void ParticleSystemProxy::simulateHeightmap()
glUniform1f(ParticleShader::HeightmapSimulationShader::uniform_track_x_len, track_x_len);
glUniform1f(ParticleShader::HeightmapSimulationShader::uniform_track_z_len, track_z_len);
glBindVertexArray(current_hm_simulation_vao);
glBindVertexArray(current_simulation_vao);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_buffers[1]);
glBeginTransformFeedback(GL_POINTS);
@ -469,8 +416,8 @@ void ParticleSystemProxy::simulateHeightmap()
glDisable(GL_RASTERIZER_DISCARD);
std::swap(tfb_buffers[0], tfb_buffers[1]);
std::swap(current_rendering_flip_vao, non_current_rendering_flip_vao);
std::swap(current_hm_simulation_vao, non_currenthm__simulation_vao);
std::swap(current_rendering_vao, non_current_rendering_vao);
std::swap(current_simulation_vao, non_current_simulation_vao);
}
void ParticleSystemProxy::simulateNoHeightmap()
@ -523,7 +470,7 @@ void ParticleSystemProxy::drawFlip()
ParticleShader::FlipParticleRender::setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), irr_driver->getInvProjMatrix(), screen[0], screen[1], 0, 1);
glBindVertexArray(current_rendering_flip_vao);
glBindVertexArray(current_rendering_vao);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
}
@ -558,12 +505,66 @@ void ParticleSystemProxy::draw()
drawNotFlip();
}
void ParticleSystemProxy::generateVAOs()
{
glGenVertexArrays(1, &current_rendering_vao);
glGenVertexArrays(1, &non_current_rendering_vao);
glGenVertexArrays(1, &current_simulation_vao);
glGenVertexArrays(1, &non_current_simulation_vao);
glBindVertexArray(current_simulation_vao);
if (has_height_map)
HeightmapSimulationBind(tfb_buffers[0], initial_values_buffer);
else
SimpleSimulationBind(tfb_buffers[0], initial_values_buffer);
glBindVertexArray(non_current_simulation_vao);
if (has_height_map)
HeightmapSimulationBind(tfb_buffers[1], initial_values_buffer);
else
SimpleSimulationBind(tfb_buffers[1], initial_values_buffer);
float *quaternions = new float[4 * count];
glBindVertexArray(0);
if (flip)
{
for (unsigned i = 0; i < count; i++)
{
core::vector3df rotationdir(0., 1., 0.);
quaternions[4 * i] = rotationdir.X;
quaternions[4 * i + 1] = rotationdir.Y;
quaternions[4 * i + 2] = rotationdir.Z;
quaternions[4 * i + 3] = 3.14f * 3.f * (2.f * os::Randomizer::frand() - 1.f); // 3 half rotation during lifetime at max
}
glGenBuffers(1, &quaternionsbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer);
glBufferData(GL_ARRAY_BUFFER, 4 * count * sizeof(float), quaternions, GL_STATIC_DRAW);
}
glBindVertexArray(current_rendering_vao);
if (flip)
FlipParticleVAOBind(tfb_buffers[0], quaternionsbuffer);
else
SimpleParticleVAOBind(tfb_buffers[0]);
glBindVertexArray(non_current_rendering_vao);
if (flip)
FlipParticleVAOBind(tfb_buffers[1], quaternionsbuffer);
else
SimpleParticleVAOBind(tfb_buffers[1]);
glBindVertexArray(0);
delete[] quaternions;
}
void ParticleSystemProxy::render() {
if (!getEmitter() || !isGPUParticleType(getEmitter()->getType()))
{
CParticleSystemSceneNode::render();
return;
}
if (!current_rendering_vao || !non_current_rendering_vao || !current_simulation_vao || !non_current_simulation_vao)
generateVAOs();
simulate();
draw();
}

View File

@ -14,9 +14,7 @@ class ParticleSystemProxy : public scene::CParticleSystemSceneNode
protected:
GLuint tfb_buffers[2], initial_values_buffer, heighmapbuffer, heightmaptexture, quaternionsbuffer;
GLuint current_simulation_vao, non_current_simulation_vao;
GLuint current_hm_simulation_vao, non_currenthm__simulation_vao;
GLuint current_rendering_vao, non_current_rendering_vao;
GLuint current_rendering_flip_vao, non_current_rendering_flip_vao;
bool m_alpha_additive, has_height_map, flip;
float size_increase_factor, track_x, track_z, track_x_len, track_z_len;
float m_color_from[3];
@ -31,6 +29,8 @@ protected:
static void SimpleSimulationBind(GLuint PositionBuffer, GLuint InitialValuesBuffer);
static void HeightmapSimulationBind(GLuint PositionBuffer, GLuint InitialValuesBuffer);
void generateVAOs();
void simulateHeightmap();
void simulateNoHeightmap();
void drawFlip();

View File

@ -422,12 +422,12 @@ void IrrDriver::initDevice()
m_gui_env = m_device->getGUIEnvironment();
m_video_driver = m_device->getVideoDriver();
int GLMajorVersion = 0, GLMinorVersion = 0;
GLMajorVersion = 2;
GLMinorVersion = 1;
glGetIntegerv(GL_MAJOR_VERSION, &GLMajorVersion);
glGetIntegerv(GL_MINOR_VERSION, &GLMinorVersion);
Log::info("IrrDriver", "OPENGL VERSION IS %d.%d", GLMajorVersion, GLMinorVersion);
m_glsl = (GLMajorVersion > 3 || (GLMajorVersion == 3 && GLMinorVersion == 3)) && UserConfigParams::m_pixel_shaders;
m_glsl = (GLMajorVersion > 3 || (GLMajorVersion == 3 && GLMinorVersion >= 1)) && UserConfigParams::m_pixel_shaders;
// This remaps the window, so it has to be done before the clear to avoid flicker
m_device->setResizable(false);

View File

@ -82,6 +82,7 @@ enum STKRenderingPass
class IrrDriver : public IEventReceiver, public NoCopy
{
private:
int GLMajorVersion, GLMinorVersion;
/** The irrlicht device. */
IrrlichtDevice *m_device;
/** Irrlicht scene manager. */
@ -148,6 +149,16 @@ public:
float power;
};
unsigned getGLSLVersion() const
{
if (GLMajorVersion > 3 || (GLMajorVersion == 3 && GLMinorVersion == 3))
return GLMajorVersion * 100 + GLMinorVersion * 10;
else if (GLMajorVersion == 3)
return 100 + (GLMinorVersion + 3) * 10;
else
return 120;
}
private:
std::vector<VideoMode> m_modes;

View File

@ -755,50 +755,11 @@ void IrrDriver::renderGlow(video::SOverrideMaterial &overridemat,
}
// ----------------------------------------------------------------------------
#define MAXLIGHT 16 // to be adjusted in pointlight.frag too
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
static LightShader::PointLightInfo PointLightsInfo[MAXLIGHT];
static GLuint pointlightvbo = 0;
static GLuint pointlightsvao = 0;
struct PointLightInfo
{
float posX;
float posY;
float posZ;
float energy;
float red;
float green;
float blue;
float padding;
};
void createPointLightVAO()
{
glGenVertexArrays(1, &pointlightsvao);
glBindVertexArray(pointlightsvao);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::billboardvbo);
glEnableVertexAttribArray(MeshShader::PointLightShader::attrib_Corner);
glVertexAttribPointer(MeshShader::PointLightShader::attrib_Corner, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glGenBuffers(1, &pointlightvbo);
glBindBuffer(GL_ARRAY_BUFFER, pointlightvbo);
glBufferData(GL_ARRAY_BUFFER, MAXLIGHT * sizeof(PointLightInfo), 0, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(MeshShader::PointLightShader::attrib_Position);
glVertexAttribPointer(MeshShader::PointLightShader::attrib_Position, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), 0);
glEnableVertexAttribArray(MeshShader::PointLightShader::attrib_Energy);
glVertexAttribPointer(MeshShader::PointLightShader::attrib_Energy, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(3 * sizeof(float)));
glEnableVertexAttribArray(MeshShader::PointLightShader::attrib_Color);
glVertexAttribPointer(MeshShader::PointLightShader::attrib_Color, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(4 * sizeof(float)));
glVertexAttribDivisor(MeshShader::PointLightShader::attrib_Position, 1);
glVertexAttribDivisor(MeshShader::PointLightShader::attrib_Energy, 1);
glVertexAttribDivisor(MeshShader::PointLightShader::attrib_Color, 1);
}
static void renderPointLights()
static void renderPointLights(unsigned count)
{
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
@ -806,23 +767,18 @@ static void renderPointLights()
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glUseProgram(MeshShader::PointLightShader::Program);
glBindVertexArray(pointlightsvao);
glUseProgram(LightShader::PointLightShader::Program);
glBindVertexArray(LightShader::PointLightShader::vao);
glBindBuffer(GL_ARRAY_BUFFER, LightShader::PointLightShader::vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(LightShader::PointLightInfo), PointLightsInfo);
setTexture(0, getTextureGLuint(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH)), GL_NEAREST, GL_NEAREST);
setTexture(1, getDepthTexture(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH)), GL_NEAREST, GL_NEAREST);
MeshShader::PointLightShader::setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), irr_driver->getInvProjMatrix(), core::vector2df(UserConfigParams::m_width, UserConfigParams::m_height), 200, 0, 1);
LightShader::PointLightShader::setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), irr_driver->getInvProjMatrix(), core::vector2df(UserConfigParams::m_width, UserConfigParams::m_height), 200, 0, 1);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, MAXLIGHT);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
}
PointLightInfo PointLightsInfo[MAXLIGHT];
void IrrDriver::renderLights(const core::aabbox3df& cambox,
scene::ICameraSceneNode * const camnode,
video::SOverrideMaterial &overridemat,
@ -860,7 +816,7 @@ void IrrDriver::renderLights(const core::aabbox3df& cambox,
const core::vector3df &lightpos = (m_lights[i]->getAbsolutePosition() - campos);
unsigned idx = (unsigned)(lightpos.getLength() / 10);
if (idx > 14)
continue;
idx = 14;
BucketedLN[idx].push_back(m_lights[i]);
}
@ -907,17 +863,7 @@ void IrrDriver::renderLights(const core::aabbox3df& cambox,
lightnum++;
// Fill lights
for (; lightnum < MAXLIGHT; lightnum++) {
PointLightsInfo[lightnum].energy = 0;
}
if (!pointlightsvao)
createPointLightVAO();
glBindVertexArray(pointlightsvao);
glBindBuffer(GL_ARRAY_BUFFER, pointlightvbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, MAXLIGHT * sizeof(PointLightInfo), PointLightsInfo);
renderPointLights();
renderPointLights(MIN2(lightnum, MAXLIGHT));
if (SkyboxCubeMap)
m_post_processing->renderDiffuseEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff);
// Handle SSAO
@ -936,77 +882,6 @@ void IrrDriver::renderLights(const core::aabbox3df& cambox,
m_video_driver->setRenderTarget(m_rtts->getRTT(RTT_COLOR), false, false);
}
static GLuint cubevao = 0;
static GLuint cubevbo;
static GLuint cubeidx;
static void createcubevao()
{
// From CSkyBoxSceneNode
float corners[] =
{
// top side
1., 1., -1.,
1., 1., 1.,
-1., 1., 1.,
-1., 1., -1.,
// Bottom side
1., -1., 1.,
1., -1., -1.,
-1., -1., -1.,
-1., -1., 1.,
// right side
1., -1, -1,
1., -1, 1,
1., 1., 1.,
1., 1., -1.,
// left side
-1., -1., 1.,
-1., -1., -1.,
-1., 1., -1.,
-1., 1., 1.,
// back side
-1., -1., -1.,
1., -1, -1.,
1, 1, -1.,
-1, 1, -1.,
// front side
1., -1., 1.,
-1., -1., 1.,
-1, 1., 1.,
1., 1., 1.,
};
int indices[] = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12,
16, 17, 18, 18, 19, 16,
20, 21, 22, 22, 23, 20
};
glGenBuffers(1, &cubevbo);
glGenBuffers(1, &cubeidx);
glGenVertexArrays(1, &cubevao);
glBindVertexArray(cubevao);
glBindBuffer(GL_ARRAY_BUFFER, cubevbo);
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * 3 * sizeof(float), corners, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubeidx);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * 6 * sizeof(int), indices, GL_STATIC_DRAW);
}
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
static void getXYZ(GLenum face, float i, float j, float &x, float &y, float &z)
{
switch (face)
@ -1399,11 +1274,9 @@ void IrrDriver::renderSkybox()
if (SkyboxTextures.empty()) return;
scene::ICameraSceneNode *camera = m_scene_manager->getActiveCamera();
if (!cubevao)
createcubevao();
if (!SkyboxCubeMap)
generateSkyboxCubemap();
glBindVertexArray(cubevao);
glBindVertexArray(MeshShader::SkyboxShader::cubevao);
glDisable(GL_CULL_FACE);
assert(SkyboxTextures.size() == 6);
core::matrix4 transform = irr_driver->getProjViewMatrix();

View File

@ -137,6 +137,8 @@ RTT::RTT()
drv->setRenderTarget(0, false, false);
drv->endScene();
if (irr_driver->getGLSLVersion() < 150)
return;
glGenFramebuffers(1, &shadowFBO);
glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);
glGenTextures(1, &shadowColorTex);

View File

@ -105,6 +105,68 @@ static void initBillboardVBO()
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), quad, GL_STATIC_DRAW);
}
GLuint SharedObject::cubevbo = 0;
GLuint SharedObject::cubeindexes = 0;
static void initCubeVBO()
{
// From CSkyBoxSceneNode
float corners[] =
{
// top side
1., 1., -1.,
1., 1., 1.,
-1., 1., 1.,
-1., 1., -1.,
// Bottom side
1., -1., 1.,
1., -1., -1.,
-1., -1., -1.,
-1., -1., 1.,
// right side
1., -1, -1,
1., -1, 1,
1., 1., 1.,
1., 1., -1.,
// left side
-1., -1., 1.,
-1., -1., -1.,
-1., 1., -1.,
-1., 1., 1.,
// back side
-1., -1., -1.,
1., -1, -1.,
1, 1, -1.,
-1, 1, -1.,
// front side
1., -1., 1.,
-1., -1., 1.,
-1, 1., 1.,
1., 1., 1.,
};
int indices[] = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12,
16, 17, 18, 18, 19, 16,
20, 21, 22, 22, 23, 20
};
glGenBuffers(1, &SharedObject::cubevbo);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::cubevbo);
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * 3 * sizeof(float), corners, GL_STATIC_DRAW);
glGenBuffers(1, &SharedObject::cubeindexes);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::cubeindexes);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * 6 * sizeof(int), indices, GL_STATIC_DRAW);
}
void Shaders::loadShaders()
{
const std::string &dir = file_manager->getAsset(FileManager::SHADER, "");
@ -232,6 +294,7 @@ void Shaders::loadShaders()
initQuadVBO();
initQuadBuffer();
initBillboardVBO();
initCubeVBO();
FullScreenShader::BloomBlendShader::init();
FullScreenShader::BloomShader::init();
FullScreenShader::ColorLevelShader::init();
@ -272,7 +335,7 @@ void Shaders::loadShaders()
MeshShader::TransparentShader::init();
MeshShader::TransparentFogShader::init();
MeshShader::BillboardShader::init();
MeshShader::PointLightShader::init();
LightShader::PointLightShader::init();
MeshShader::DisplaceShader::init();
MeshShader::DisplaceMaskShader::init();
MeshShader::ShadowShader::init();
@ -326,7 +389,10 @@ namespace MeshShader
void ObjectPass1Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/object_pass1.vert").c_str(), file_manager->getAsset("shaders/object_pass1.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass1.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass1.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_normal = glGetAttribLocation(Program, "Normal");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -350,7 +416,10 @@ namespace MeshShader
void ObjectRefPass1Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/objectref_pass1.vert").c_str(), file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/objectref_pass1.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_normal = glGetAttribLocation(Program, "Normal");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
@ -380,7 +449,10 @@ namespace MeshShader
void GrassPass1Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/grass_pass1.vert").c_str(), file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass1.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_normal = glGetAttribLocation(Program, "Normal");
@ -410,7 +482,10 @@ namespace MeshShader
void NormalMapShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/normalmap.vert").c_str(), file_manager->getAsset("shaders/normalmap.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/normalmap.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/normalmap.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_tangent = glGetAttribLocation(Program, "Tangent");
@ -436,7 +511,10 @@ namespace MeshShader
void InstancedObjectPass1Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/instanced_object_pass1.vert").c_str(), file_manager->getAsset("shaders/object_pass1.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass1.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass1.frag").c_str());
attrib_origin = glGetAttribLocation(Program, "Origin");
attrib_position = glGetAttribLocation(Program, "Position");
attrib_normal = glGetAttribLocation(Program, "Normal");
@ -463,7 +541,10 @@ namespace MeshShader
void ObjectPass2Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/object_pass2.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -505,7 +586,10 @@ namespace MeshShader
void InstancedObjectPass2Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/instanced_object_pass2.vert").c_str(), file_manager->getAsset("shaders/object_pass2.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_origin = glGetAttribLocation(Program, "Origin");
@ -548,7 +632,10 @@ namespace MeshShader
void DetailledObjectPass2Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/detailledobject_pass2.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/detailledobject_pass2.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_second_texcoord = glGetAttribLocation(Program, "SecondTexcoord");
@ -588,7 +675,9 @@ namespace MeshShader
void ObjectUnlitShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/object_unlit.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -618,7 +707,9 @@ namespace MeshShader
void ObjectRimLimitShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/objectpass_rimlit.vert").c_str(), file_manager->getAsset("shaders/objectpass_rimlit.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/objectpass_rimlit.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectpass_rimlit.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_normal = glGetAttribLocation(Program, "Normal");
@ -660,7 +751,10 @@ namespace MeshShader
void UntexturedObjectShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/untextured_object.vert").c_str(), file_manager->getAsset("shaders/untextured_object.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/untextured_object.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/untextured_object.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_color = glGetAttribLocation(Program, "Color");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -698,7 +792,10 @@ namespace MeshShader
void ObjectRefPass2Shader::init()
{
initGL();
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -740,7 +837,10 @@ namespace MeshShader
void GrassPass2Shader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/grass_pass2.vert").c_str(), file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_color = glGetAttribLocation(Program, "Color");
@ -783,7 +883,9 @@ namespace MeshShader
void SphereMapShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/object_pass1.vert").c_str(), file_manager->getAsset("shaders/objectpass_spheremap.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass1.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectpass_spheremap.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_normal = glGetAttribLocation(Program, "Normal");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -823,7 +925,9 @@ namespace MeshShader
void SplattingShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/splatting.vert").c_str(), file_manager->getAsset("shaders/splatting.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/splatting.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/splatting.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_second_texcoord = glGetAttribLocation(Program, "SecondTexcoord");
@ -877,7 +981,10 @@ namespace MeshShader
void CausticsShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/caustics.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/caustics.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -922,7 +1029,9 @@ namespace MeshShader
void BubbleShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/bubble.vert").c_str(), file_manager->getAsset("shaders/bubble.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/bubble.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bubble.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -941,15 +1050,19 @@ namespace MeshShader
GLuint TransparentShader::Program;
GLuint TransparentShader::attrib_position;
GLuint TransparentShader::attrib_texcoord;
GLuint TransparentShader::attrib_color;
GLuint TransparentShader::uniform_MVP;
GLuint TransparentShader::uniform_TM;
GLuint TransparentShader::uniform_tex;
void TransparentShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/transparent.vert").c_str(), file_manager->getAsset("shaders/transparent.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/transparent.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparent.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_color = glGetAttribLocation(Program, "Color");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
uniform_TM = glGetUniformLocation(Program, "TextureMatrix");
uniform_tex = glGetUniformLocation(Program, "tex");
@ -965,6 +1078,7 @@ namespace MeshShader
GLuint TransparentFogShader::Program;
GLuint TransparentFogShader::attrib_position;
GLuint TransparentFogShader::attrib_texcoord;
GLuint TransparentFogShader::attrib_color;
GLuint TransparentFogShader::uniform_MVP;
GLuint TransparentFogShader::uniform_TM;
GLuint TransparentFogShader::uniform_tex;
@ -979,9 +1093,12 @@ namespace MeshShader
void TransparentFogShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/transparent.vert").c_str(), file_manager->getAsset("shaders/transparentfog.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/transparent.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparentfog.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_color = glGetAttribLocation(Program, "Color");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
uniform_TM = glGetUniformLocation(Program, "TextureMatrix");
uniform_tex = glGetUniformLocation(Program, "tex");
@ -1009,47 +1126,6 @@ namespace MeshShader
glUniformMatrix4fv(uniform_ipvmat, 1, GL_FALSE, ipvmat.pointer());
glUniform1i(uniform_tex, TU_tex);
}
GLuint PointLightShader::Program;
GLuint PointLightShader::attrib_Position;
GLuint PointLightShader::attrib_Color;
GLuint PointLightShader::attrib_Energy;
GLuint PointLightShader::attrib_Corner;
GLuint PointLightShader::uniform_ntex;
GLuint PointLightShader::uniform_dtex;
GLuint PointLightShader::uniform_spec;
GLuint PointLightShader::uniform_screen;
GLuint PointLightShader::uniform_invproj;
GLuint PointLightShader::uniform_VM;
GLuint PointLightShader::uniform_PM;
void PointLightShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/pointlight.vert").c_str(), file_manager->getAsset("shaders/pointlight.frag").c_str());
attrib_Position = glGetAttribLocation(Program, "Position");
attrib_Color = glGetAttribLocation(Program, "Color");
attrib_Energy = glGetAttribLocation(Program, "Energy");
attrib_Corner = glGetAttribLocation(Program, "Corner");
uniform_ntex = glGetUniformLocation(Program, "ntex");
uniform_dtex = glGetUniformLocation(Program, "dtex");
uniform_spec = glGetUniformLocation(Program, "spec");
uniform_invproj = glGetUniformLocation(Program, "invproj");
uniform_screen = glGetUniformLocation(Program, "screen");
uniform_VM = glGetUniformLocation(Program, "ViewMatrix");
uniform_PM = glGetUniformLocation(Program, "ProjectionMatrix");
}
void PointLightShader::setUniforms(const core::matrix4 &ViewMatrix, const core::matrix4 &ProjMatrix, const core::matrix4 &InvProjMatrix, const core::vector2df &screen, unsigned spec, unsigned TU_ntex, unsigned TU_dtex)
{
glUniform1f(uniform_spec, 200);
glUniform2f(uniform_screen, screen.X, screen.Y);
glUniformMatrix4fv(uniform_invproj, 1, GL_FALSE, InvProjMatrix.pointer());
glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer());
glUniformMatrix4fv(uniform_PM, 1, GL_FALSE, ProjMatrix.pointer());
glUniform1i(uniform_ntex, TU_ntex);
glUniform1i(uniform_dtex, TU_dtex);
}
GLuint BillboardShader::Program;
GLuint BillboardShader::attrib_corner;
@ -1062,7 +1138,9 @@ namespace MeshShader
void BillboardShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/billboard.vert").c_str(), file_manager->getAsset("shaders/billboard.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/billboard.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/billboard.frag").c_str());
attrib_corner = glGetAttribLocation(Program, "Corner");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MV = glGetUniformLocation(Program, "ModelViewMatrix");
@ -1088,7 +1166,9 @@ namespace MeshShader
void ColorizeShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/colorize.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/colorize.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
uniform_col = glGetUniformLocation(Program, "col");
@ -1106,7 +1186,16 @@ namespace MeshShader
void ShadowShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/shadow.vert").c_str(), file_manager->getAsset("shaders/shadow.geom").c_str(), file_manager->getAsset("shaders/white.frag").c_str());
// Geometry shader needed
if (irr_driver->getGLSLVersion() < 150)
{
attrib_position = -1;
return;
}
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
}
@ -1130,7 +1219,17 @@ namespace MeshShader
void RefShadowShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/shadow.vert").c_str(), file_manager->getAsset("shaders/shadow.geom").c_str(), file_manager->getAsset("shaders/object_unlit.frag").c_str());
// Geometry shader needed
if (irr_driver->getGLSLVersion() < 150)
{
attrib_position = -1;
attrib_texcoord = -1;
return;
}
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -1159,7 +1258,9 @@ namespace MeshShader
void GrassShadowShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/grass_pass2.vert").c_str(), file_manager->getAsset("shaders/object_unlit.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
@ -1181,7 +1282,9 @@ namespace MeshShader
void DisplaceMaskShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/displace.vert").c_str(), file_manager->getAsset("shaders/white.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/displace.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
}
@ -1206,7 +1309,9 @@ namespace MeshShader
void DisplaceShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/displace.vert").c_str(), file_manager->getAsset("shaders/displace.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/displace.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/displace.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_second_texcoord = glGetAttribLocation(Program, "SecondTexcoord");
@ -1238,15 +1343,26 @@ namespace MeshShader
GLuint SkyboxShader::uniform_tex;
GLuint SkyboxShader::uniform_screen;
GLuint SkyboxShader::uniform_InvProjView;
GLuint SkyboxShader::cubevao;
void SkyboxShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/sky.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sky.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
uniform_InvProjView = glGetUniformLocation(Program, "InvProjView");
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_screen = glGetUniformLocation(Program, "screen");
glGenVertexArrays(1, &cubevao);
glBindVertexArray(cubevao);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::cubevbo);
glEnableVertexAttribArray(attrib_position);
glVertexAttribPointer(attrib_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::cubeindexes);
glBindVertexArray(0);
}
void SkyboxShader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &InvProjView, const core::vector2df &screen, unsigned TU_tex)
@ -1258,6 +1374,79 @@ namespace MeshShader
}
}
namespace LightShader
{
GLuint PointLightShader::Program;
GLuint PointLightShader::attrib_Position;
GLuint PointLightShader::attrib_Color;
GLuint PointLightShader::attrib_Energy;
GLuint PointLightShader::attrib_Corner;
GLuint PointLightShader::uniform_ntex;
GLuint PointLightShader::uniform_dtex;
GLuint PointLightShader::uniform_spec;
GLuint PointLightShader::uniform_screen;
GLuint PointLightShader::uniform_invproj;
GLuint PointLightShader::uniform_VM;
GLuint PointLightShader::uniform_PM;
GLuint PointLightShader::vbo;
GLuint PointLightShader::vao;
void PointLightShader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/pointlight.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/pointlight.frag").c_str());
attrib_Position = glGetAttribLocation(Program, "Position");
attrib_Color = glGetAttribLocation(Program, "Color");
attrib_Energy = glGetAttribLocation(Program, "Energy");
attrib_Corner = glGetAttribLocation(Program, "Corner");
uniform_ntex = glGetUniformLocation(Program, "ntex");
uniform_dtex = glGetUniformLocation(Program, "dtex");
uniform_spec = glGetUniformLocation(Program, "spec");
uniform_invproj = glGetUniformLocation(Program, "invproj");
uniform_screen = glGetUniformLocation(Program, "screen");
uniform_VM = glGetUniformLocation(Program, "ViewMatrix");
uniform_PM = glGetUniformLocation(Program, "ProjectionMatrix");
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::billboardvbo);
glEnableVertexAttribArray(attrib_Corner);
glVertexAttribPointer(attrib_Corner, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, MAXLIGHT * sizeof(PointLightInfo), 0, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(attrib_Position);
glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), 0);
glEnableVertexAttribArray(attrib_Energy);
glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(3 * sizeof(float)));
glEnableVertexAttribArray(attrib_Color);
glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(4 * sizeof(float)));
glVertexAttribDivisor(attrib_Position, 1);
glVertexAttribDivisor(attrib_Energy, 1);
glVertexAttribDivisor(attrib_Color, 1);
}
void PointLightShader::setUniforms(const core::matrix4 &ViewMatrix, const core::matrix4 &ProjMatrix, const core::matrix4 &InvProjMatrix, const core::vector2df &screen, unsigned spec, unsigned TU_ntex, unsigned TU_dtex)
{
glUniform1f(uniform_spec, 200);
glUniform2f(uniform_screen, screen.X, screen.Y);
glUniformMatrix4fv(uniform_invproj, 1, GL_FALSE, InvProjMatrix.pointer());
glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer());
glUniformMatrix4fv(uniform_PM, 1, GL_FALSE, ProjMatrix.pointer());
glUniform1i(uniform_ntex, TU_ntex);
glUniform1i(uniform_dtex, TU_dtex);
}
}
namespace ParticleShader
{
@ -1367,7 +1556,9 @@ namespace ParticleShader
void SimpleParticleRender::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/particle.vert").c_str(), file_manager->getAsset("shaders/particle.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/particle.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/particle.frag").c_str());
attrib_pos = glGetAttribLocation(Program, "position");
attrib_sz = glGetAttribLocation(Program, "size");
attrib_lf = glGetAttribLocation(Program, "lifetime");
@ -1421,7 +1612,9 @@ namespace ParticleShader
void FlipParticleRender::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/flipparticle.vert").c_str(), file_manager->getAsset("shaders/particle.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/flipparticle.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/particle.frag").c_str());
attrib_pos = glGetAttribLocation(Program, "position");
attrib_sz = glGetAttribLocation(Program, "size");
attrib_lf = glGetAttribLocation(Program, "lifetime");
@ -1473,7 +1666,9 @@ namespace FullScreenShader
GLuint BloomShader::vao;
void BloomShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/bloom.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bloom.frag").c_str());
uniform_texture = glGetUniformLocation(Program, "tex");
uniform_low = glGetUniformLocation(Program, "low");
vao = createVAO(Program);
@ -1485,7 +1680,9 @@ namespace FullScreenShader
GLuint BloomBlendShader::vao;
void BloomBlendShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/bloomblend.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bloomblend.frag").c_str());
uniform_texture = glGetUniformLocation(Program, "tex");
vao = createVAO(Program);
}
@ -1499,7 +1696,9 @@ namespace FullScreenShader
GLuint ColorLevelShader::uniform_dtex;
void ColorLevelShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/color_levels.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/color_levels.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_dtex = glGetUniformLocation(Program, "dtex");
uniform_inlevel = glGetUniformLocation(Program, "inlevel");
@ -1518,7 +1717,10 @@ namespace FullScreenShader
void SunLightShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/sunlight.frag").c_str());
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/sunlight.frag").c_str());
uniform_ntex = glGetUniformLocation(Program, "ntex");
uniform_dtex = glGetUniformLocation(Program, "dtex");
uniform_direction = glGetUniformLocation(Program, "direction");
@ -1546,7 +1748,10 @@ namespace FullScreenShader
void DiffuseEnvMapShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/diffuseenvmap.frag").c_str());
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/diffuseenvmap.frag").c_str());
uniform_ntex = glGetUniformLocation(Program, "ntex");
uniform_blueLmn = glGetUniformLocation(Program, "blueLmn[0]");
uniform_greenLmn = glGetUniformLocation(Program, "greenLmn[0]");
@ -1576,7 +1781,10 @@ namespace FullScreenShader
void ShadowedSunLightShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/sunlightshadow.frag").c_str());
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/sunlightshadow.frag").c_str());
uniform_ntex = glGetUniformLocation(Program, "ntex");
uniform_dtex = glGetUniformLocation(Program, "dtex");
uniform_shadowtex = glGetUniformLocation(Program, "shadowtex");
@ -1611,7 +1819,9 @@ namespace FullScreenShader
GLuint Gaussian6HBlurShader::vao;
void Gaussian6HBlurShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/gaussian6h.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian6h.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_pixel = glGetUniformLocation(Program, "pixel");
vao = createVAO(Program);
@ -1623,7 +1833,9 @@ namespace FullScreenShader
GLuint Gaussian3HBlurShader::vao;
void Gaussian3HBlurShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/gaussian3h.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian3h.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_pixel = glGetUniformLocation(Program, "pixel");
vao = createVAO(Program);
@ -1635,7 +1847,9 @@ namespace FullScreenShader
GLuint Gaussian6VBlurShader::vao;
void Gaussian6VBlurShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/gaussian6v.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian6v.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_pixel = glGetUniformLocation(Program, "pixel");
vao = createVAO(Program);
@ -1647,7 +1861,9 @@ namespace FullScreenShader
GLuint Gaussian3VBlurShader::vao;
void Gaussian3VBlurShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/gaussian3v.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian3v.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_pixel = glGetUniformLocation(Program, "pixel");
vao = createVAO(Program);
@ -1659,7 +1875,9 @@ namespace FullScreenShader
GLuint PenumbraHShader::vao;
void PenumbraHShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/penumbrah.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/penumbrah.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_pixel = glGetUniformLocation(Program, "pixel");
vao = createVAO(Program);
@ -1677,7 +1895,9 @@ namespace FullScreenShader
GLuint PenumbraVShader::vao;
void PenumbraVShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/penumbrav.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/penumbrav.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_pixel = glGetUniformLocation(Program, "pixel");
vao = createVAO(Program);
@ -1696,7 +1916,9 @@ namespace FullScreenShader
GLuint ShadowGenShader::vao;
void ShadowGenShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/shadowgen.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadowgen.frag").c_str());
uniform_halft = glGetUniformLocation(Program, "halft");
uniform_quarter = glGetUniformLocation(Program, "quarter");
uniform_height = glGetUniformLocation(Program, "height");
@ -1715,7 +1937,9 @@ namespace FullScreenShader
GLuint PassThroughShader::vao;
void PassThroughShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/texturedquad.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/texturedquad.frag").c_str());
uniform_texture = glGetUniformLocation(Program, "texture");
vao = createVAO(Program);
}
@ -1725,7 +1949,9 @@ namespace FullScreenShader
GLuint GlowShader::vao;
void GlowShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/glow.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/glow.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
vao = createVAO(Program);
}
@ -1742,7 +1968,10 @@ namespace FullScreenShader
void SSAOShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/ssao.frag").c_str());
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/ssao.frag").c_str());
uniform_ntex = glGetUniformLocation(Program, "ntex");
uniform_dtex = glGetUniformLocation(Program, "dtex");
uniform_noise_texture = glGetUniformLocation(Program, "noise_texture");
@ -1889,7 +2118,9 @@ namespace FullScreenShader
void FogShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/fog.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/fog.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_fogmax = glGetUniformLocation(Program, "fogmax");
uniform_startH = glGetUniformLocation(Program, "startH");
@ -1924,7 +2155,9 @@ namespace FullScreenShader
void MotionBlurShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/motion_blur.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/motion_blur.frag").c_str());
uniform_boost_amount = glGetUniformLocation(Program, "boost_amount");
uniform_center = glGetUniformLocation(Program, "center");
uniform_color_buffer = glGetUniformLocation(Program, "color_buffer");
@ -1951,7 +2184,9 @@ namespace FullScreenShader
void GodFadeShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/godfade.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/godfade.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_col = glGetUniformLocation(Program, "col");
vao = createVAO(Program);
@ -1970,7 +2205,9 @@ namespace FullScreenShader
void GodRayShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/godray.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/godray.frag").c_str());
uniform_tex = glGetUniformLocation(Program, "tex");
uniform_sunpos = glGetUniformLocation(Program, "sunpos");
vao = createVAO(Program);
@ -1997,7 +2234,9 @@ namespace UIShader
void TextureRectShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/texturedquad.vert").c_str(), file_manager->getAsset("shaders/texturedquad.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/texturedquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/texturedquad.frag").c_str());
attrib_position = glGetAttribLocation(Program, "position");
attrib_texcoord = glGetAttribLocation(Program, "texcoord");
@ -2039,7 +2278,9 @@ namespace UIShader
void ColoredTextureRectShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/colortexturedquad.vert").c_str(), file_manager->getAsset("shaders/colortexturedquad.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/colortexturedquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/colortexturedquad.frag").c_str());
attrib_position = glGetAttribLocation(Program, "position");
attrib_texcoord = glGetAttribLocation(Program, "texcoord");
@ -2088,7 +2329,9 @@ namespace UIShader
void ColoredRectShader::init()
{
Program = LoadProgram(file_manager->getAsset("shaders/coloredquad.vert").c_str(), file_manager->getAsset("shaders/coloredquad.frag").c_str());
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/coloredquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/coloredquad.frag").c_str());
attrib_position = glGetAttribLocation(Program, "position");
uniform_color = glGetUniformLocation(Program, "color");
uniform_center = glGetUniformLocation(Program, "center");

View File

@ -29,6 +29,7 @@ class SharedObject
{
public:
static GLuint billboardvbo;
static GLuint cubevbo, cubeindexes;
};
namespace MeshShader
{
@ -233,7 +234,7 @@ class TransparentShader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_texcoord;
static GLuint attrib_position, attrib_texcoord, attrib_color;
static GLuint uniform_MVP, uniform_TM, uniform_tex;
static void init();
@ -244,25 +245,13 @@ class TransparentFogShader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_texcoord;
static GLuint attrib_position, attrib_texcoord, attrib_color;
static GLuint uniform_MVP, uniform_TM, uniform_tex, uniform_fogmax, uniform_startH, uniform_endH, uniform_start, uniform_end, uniform_col, uniform_screen, uniform_ipvmat;
static void init();
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix, const core::matrix4 &ipvmat, float fogmax, float startH, float endH, float start, float end, const core::vector3df &col, const core::vector3df &campos, unsigned TU_tex);
};
class PointLightShader
{
public:
static GLuint Program;
static GLuint attrib_Position, attrib_Energy, attrib_Color;
static GLuint attrib_Corner;
static GLuint uniform_ntex, uniform_dtex, uniform_spec, uniform_screen, uniform_invproj, uniform_VM, uniform_PM;
static void init();
static void setUniforms(const core::matrix4 &ViewMatrix, const core::matrix4 &ProjMatrix, const core::matrix4 &InvProjMatrix, const core::vector2df &screen, unsigned spec, unsigned TU_ntex, unsigned TU_dtex);
};
class BillboardShader
{
public:
@ -347,6 +336,7 @@ public:
static GLuint Program;
static GLuint attrib_position;
static GLuint uniform_MVP, uniform_InvProjView, uniform_tex, uniform_screen;
static GLuint cubevao;
static void init();
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &InvProjView, const core::vector2df &screen, unsigned TU_tex);
@ -354,6 +344,38 @@ public:
}
#define MAXLIGHT 16
namespace LightShader
{
struct PointLightInfo
{
float posX;
float posY;
float posZ;
float energy;
float red;
float green;
float blue;
float padding;
};
class PointLightShader
{
public:
static GLuint Program;
static GLuint attrib_Position, attrib_Energy, attrib_Color;
static GLuint attrib_Corner;
static GLuint uniform_ntex, uniform_dtex, uniform_spec, uniform_screen, uniform_invproj, uniform_VM, uniform_PM;
static GLuint vbo;
static GLuint vao;
static void init();
static void setUniforms(const core::matrix4 &ViewMatrix, const core::matrix4 &ProjMatrix, const core::matrix4 &InvProjMatrix, const core::vector2df &screen, unsigned spec, unsigned TU_ntex, unsigned TU_dtex);
};
}
namespace ParticleShader
{

View File

@ -25,6 +25,7 @@
#include "karts/abstract_kart.hpp"
#include "karts/skidding.hpp"
#include "physics/btKart.hpp"
#include "graphics/stkmeshscenenode.hpp"
#include <IMeshSceneNode.h>
#include <SMesh.h>
@ -134,6 +135,8 @@ void SkidMarks::update(float dt, bool force_skid_marks,
// (till these skid mark quads are deleted)
m_left[m_current]->setHardwareMappingHint(scene::EHM_STATIC);
m_right[m_current]->setHardwareMappingHint(scene::EHM_STATIC);
if (STKMeshSceneNode* stkm = dynamic_cast<STKMeshSceneNode*>(m_nodes[m_current]))
stkm->setReloadEachFrame(false);
return;
}
@ -188,6 +191,8 @@ void SkidMarks::update(float dt, bool force_skid_marks,
m_material, m_avoid_z_fighting, custom_color);
new_mesh->addMeshBuffer(smq_right);
scene::IMeshSceneNode *new_node = irr_driver->addMesh(new_mesh);
if (STKMeshSceneNode* stkm = dynamic_cast<STKMeshSceneNode*>(new_node))
stkm->setReloadEachFrame(true);
#ifdef DEBUG
std::string debug_name = m_kart.getIdent()+" (skid-mark)";
new_node->setName(debug_name.c_str());

View File

@ -171,11 +171,13 @@ void STKAnimatedMesh::render()
computeMVP(ModelViewProjectionMatrix);
computeTIMV(TransposeInverseModelView);
glUseProgram(MeshShader::ObjectPass1Shader::Program);
if (!GeometricMesh[FPSM_DEFAULT].empty())
glUseProgram(MeshShader::ObjectPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
drawSolidPass1(*GeometricMesh[FPSM_DEFAULT][i], FPSM_DEFAULT);
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++)
drawSolidPass1(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i], FPSM_ALPHA_REF_TEXTURE);
@ -184,36 +186,43 @@ void STKAnimatedMesh::render()
if (irr_driver->getPhase() == SOLID_LIT_PASS)
{
glUseProgram(MeshShader::ObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_DEFAULT][i], SM_DEFAULT);
if (!ShadedMesh[SM_DEFAULT].empty())
glUseProgram(MeshShader::ObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_DEFAULT][i], SM_DEFAULT);
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++)
drawSolidPass2(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], SM_ALPHA_REF_TEXTURE);
if (!ShadedMesh[SM_ALPHA_REF_TEXTURE].empty())
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++)
drawSolidPass2(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], SM_ALPHA_REF_TEXTURE);
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_RIMLIT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_RIMLIT][i], SM_RIMLIT);
if (!ShadedMesh[SM_RIMLIT].empty())
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_RIMLIT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_RIMLIT][i], SM_RIMLIT);
glUseProgram(MeshShader::ObjectUnlitShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_UNLIT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_UNLIT][i], SM_UNLIT);
if (!ShadedMesh[SM_UNLIT].empty())
glUseProgram(MeshShader::ObjectUnlitShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_UNLIT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_UNLIT][i], SM_UNLIT);
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_DETAILS].size(); i++)
drawSolidPass2(*ShadedMesh[SM_DETAILS][i], SM_DETAILS);
if (!ShadedMesh[SM_DETAILS].empty())
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_DETAILS].size(); i++)
drawSolidPass2(*ShadedMesh[SM_DETAILS][i], SM_DETAILS);
return;
return;
}
if (irr_driver->getPhase() == SHADOW_PASS)
{
glUseProgram(MeshShader::ShadowShader::Program);
if (!GeometricMesh[FPSM_DEFAULT].empty())
glUseProgram(MeshShader::ShadowShader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
drawShadow(*GeometricMesh[FPSM_DEFAULT][i]);
glUseProgram(MeshShader::RefShadowShader::Program);
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
glUseProgram(MeshShader::RefShadowShader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++)
drawShadowRef(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i]);
return;
@ -223,13 +232,25 @@ void STKAnimatedMesh::render()
{
computeMVP(ModelViewProjectionMatrix);
glUseProgram(MeshShader::BubbleShader::Program);
if (!TransparentMesh[TM_BUBBLE].empty())
glUseProgram(MeshShader::BubbleShader::Program);
for (unsigned i = 0; i < TransparentMesh[TM_BUBBLE].size(); i++)
drawBubble(*TransparentMesh[TM_BUBBLE][i], ModelViewProjectionMatrix);
glUseProgram(MeshShader::TransparentShader::Program);
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
drawTransparentObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
if (World::getWorld()->getTrack()->isFogEnabled())
{
if (!TransparentMesh[TM_DEFAULT].empty())
glUseProgram(MeshShader::TransparentFogShader::Program);
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
drawTransparentFogObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
}
else
{
if (!TransparentMesh[TM_DEFAULT].empty())
glUseProgram(MeshShader::TransparentShader::Program);
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
drawTransparentObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
}
return;
}
}

View File

@ -30,6 +30,8 @@ STKBillboard::STKBillboard(irr::scene::ISceneNode* parent, irr::scene::ISceneMan
void STKBillboard::render()
{
if (irr_driver->getPhase() != TRANSPARENT_PASS)
return;
core::vector3df pos = getAbsolutePosition();
glBindVertexArray(billboardvao);
GLuint texid = getTextureGLuint(Material.getTexture(0));

View File

@ -55,6 +55,8 @@ TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE typ
GLuint createVAO(GLuint vbo, GLuint idx, GLuint attrib_position, GLuint attrib_texcoord, GLuint attrib_second_texcoord, GLuint attrib_normal, GLuint attrib_tangent, GLuint attrib_bitangent, GLuint attrib_color, size_t stride)
{
if (attrib_position == -1)
return 0;
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
@ -401,6 +403,8 @@ void drawObjectRefPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjec
glDrawElements(ptype, count, itype, 0);
}
static video::ITexture *CausticTex = 0;
void drawCaustics(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector2df dir, core::vector2df dir2)
{
irr_driver->IncreaseObjectCount();
@ -419,7 +423,9 @@ void drawCaustics(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionM
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
setTexture(MeshShader::CausticsShader::TU_caustictex, getTextureGLuint(irr_driver->getTexture(file_manager->getAsset("textures/caustics.png").c_str())), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (!CausticTex)
CausticTex = irr_driver->getTexture(file_manager->getAsset("textures/caustics.png").c_str());
setTexture(MeshShader::CausticsShader::TU_caustictex, getTextureGLuint(CausticTex), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::CausticsShader::setUniforms(ModelViewProjectionMatrix, dir, dir2, core::vector2df(UserConfigParams::m_width, UserConfigParams::m_height));
@ -814,20 +820,18 @@ void initvaostate(GLMesh &mesh, TransparentMaterial TranspMat)
MeshShader::BubbleShader::attrib_position, MeshShader::BubbleShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
break;
case TM_DEFAULT:
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::TransparentShader::attrib_position, MeshShader::TransparentShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
if (World::getWorld()->getTrack()->isFogEnabled())
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::TransparentFogShader::attrib_position, MeshShader::TransparentFogShader::attrib_texcoord, -1, -1, -1, -1, MeshShader::TransparentFogShader::attrib_color, mesh.Stride);
else
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::TransparentShader::attrib_position, MeshShader::TransparentShader::attrib_texcoord, -1, -1, -1, -1, MeshShader::TransparentShader::attrib_color, mesh.Stride);
break;
}
mesh.vao_glow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::ColorizeShader::attrib_position, -1, -1, -1, -1, -1, -1, mesh.Stride);
mesh.vao_displace_mask_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::DisplaceShader::attrib_position, -1, -1, -1, -1, -1, -1, mesh.Stride);
if (mesh.Stride >= 44)
mesh.vao_displace_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::DisplaceShader::attrib_position, MeshShader::DisplaceShader::attrib_texcoord, MeshShader::DisplaceShader::attrib_second_texcoord, -1, -1, -1, -1, mesh.Stride);
/*
else if (World::getWorld()->getTrack()->isFogEnabled())
{
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::TransparentFogShader::attrib_position, MeshShader::TransparentFogShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
}*/
}

View File

@ -32,9 +32,15 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent,
const irr::core::vector3df& scale) :
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
{
reload_each_frame = false;
createGLMeshes();
}
void STKMeshSceneNode::setReloadEachFrame(bool val)
{
reload_each_frame = val;
}
void STKMeshSceneNode::createGLMeshes()
{
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
@ -137,6 +143,8 @@ void STKMeshSceneNode::drawGlow(const GLMesh &mesh)
glDrawElements(ptype, count, itype, 0);
}
static video::ITexture *displaceTex = 0;
void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
{
DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE);
@ -161,8 +169,10 @@ void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
glDrawElements(ptype, count, itype, 0);
// Render the effect
if (!displaceTex)
displaceTex = irr_driver->getTexture(FileManager::TEXTURE, "displace.png");
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_DISPLACE), false, false);
setTexture(0, getTextureGLuint(irr_driver->getTexture(FileManager::TEXTURE, "displace.png")), GL_LINEAR, GL_LINEAR, true);
setTexture(0, getTextureGLuint(displaceTex), GL_LINEAR, GL_LINEAR, true);
setTexture(1, getTextureGLuint(irr_driver->getRTT(RTT_TMP4)), GL_LINEAR, GL_LINEAR, true);
setTexture(2, getTextureGLuint(irr_driver->getRTT(RTT_COLOR)), GL_LINEAR, GL_LINEAR, true);
glUseProgram(MeshShader::DisplaceShader::Program);
@ -270,6 +280,41 @@ void STKMeshSceneNode::drawSolidPass2(const GLMesh &mesh, ShadedMaterial type)
}
}
void STKMeshSceneNode::updatevbo()
{
for (unsigned i = 0; i < Mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
if (!mb)
continue;
GLMesh &mesh = GLmeshes[i];
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_buffer);
const void* vertices = mb->getVertices();
const u32 vertexCount = mb->getVertexCount();
const c8* vbuf = static_cast<const c8*>(vertices);
glBufferData(GL_ARRAY_BUFFER, vertexCount * mesh.Stride, vbuf, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_buffer);
const void* indices = mb->getIndices();
mesh.IndexCount = mb->getIndexCount();
GLenum indexSize;
switch (mb->getIndexType())
{
case irr::video::EIT_16BIT:
indexSize = sizeof(u16);
break;
case irr::video::EIT_32BIT:
indexSize = sizeof(u32);
break;
default:
assert(0 && "Wrong index size");
}
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.IndexCount * indexSize, indices, GL_STATIC_DRAW);
}
}
void STKMeshSceneNode::render()
{
irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
@ -277,6 +322,9 @@ void STKMeshSceneNode::render()
if (!Mesh || !driver)
return;
if (reload_each_frame)
updatevbo();
bool isTransparentPass =
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
@ -297,82 +345,113 @@ void STKMeshSceneNode::render()
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
{
if (reload_each_frame)
glDisable(GL_CULL_FACE);
computeMVP(ModelViewProjectionMatrix);
computeTIMV(TransposeInverseModelView);
glUseProgram(MeshShader::ObjectPass1Shader::Program);
if (!GeometricMesh[FPSM_DEFAULT].empty())
glUseProgram(MeshShader::ObjectPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
drawSolidPass1(*GeometricMesh[FPSM_DEFAULT][i], FPSM_DEFAULT);
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++)
drawSolidPass1(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i], FPSM_ALPHA_REF_TEXTURE);
glUseProgram(MeshShader::NormalMapShader::Program);
if (!GeometricMesh[FPSM_NORMAL_MAP].empty())
glUseProgram(MeshShader::NormalMapShader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_NORMAL_MAP].size(); i++)
drawSolidPass1(*GeometricMesh[FPSM_NORMAL_MAP][i], FPSM_NORMAL_MAP);
glUseProgram(MeshShader::GrassPass1Shader::Program);
if (!GeometricMesh[FPSM_GRASS].empty())
glUseProgram(MeshShader::GrassPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_GRASS].size(); i++)
drawSolidPass1(*GeometricMesh[FPSM_GRASS][i], FPSM_GRASS);
if (reload_each_frame)
glEnable(GL_CULL_FACE);
return;
}
if (irr_driver->getPhase() == SOLID_LIT_PASS)
{
glUseProgram(MeshShader::ObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_DEFAULT][i], SM_DEFAULT);
if (reload_each_frame)
glDisable(GL_CULL_FACE);
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++)
drawSolidPass2(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], SM_ALPHA_REF_TEXTURE);
if (!ShadedMesh[SM_DEFAULT].empty())
glUseProgram(MeshShader::ObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_DEFAULT][i], SM_DEFAULT);
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_RIMLIT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_RIMLIT][i], SM_RIMLIT);
if (!ShadedMesh[SM_ALPHA_REF_TEXTURE].empty())
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++)
drawSolidPass2(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], SM_ALPHA_REF_TEXTURE);
glUseProgram(MeshShader::SphereMapShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_SPHEREMAP].size(); i++)
drawSolidPass2(*ShadedMesh[SM_SPHEREMAP][i], SM_SPHEREMAP);
if (!ShadedMesh[SM_RIMLIT].empty())
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_RIMLIT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_RIMLIT][i], SM_RIMLIT);
glUseProgram(MeshShader::SplattingShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_SPLATTING].size(); i++)
drawSolidPass2(*ShadedMesh[SM_SPLATTING][i], SM_SPLATTING);
if (!ShadedMesh[SM_SPHEREMAP].empty())
glUseProgram(MeshShader::SphereMapShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_SPHEREMAP].size(); i++)
drawSolidPass2(*ShadedMesh[SM_SPHEREMAP][i], SM_SPHEREMAP);
glUseProgram(MeshShader::GrassPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_GRASS].size(); i++)
drawSolidPass2(*ShadedMesh[SM_GRASS][i], SM_GRASS);
if (!ShadedMesh[SM_SPLATTING].empty())
glUseProgram(MeshShader::SplattingShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_SPLATTING].size(); i++)
drawSolidPass2(*ShadedMesh[SM_SPLATTING][i], SM_SPLATTING);
glUseProgram(MeshShader::ObjectUnlitShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_UNLIT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_UNLIT][i], SM_UNLIT);
if (!ShadedMesh[SM_GRASS].empty())
glUseProgram(MeshShader::GrassPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_GRASS].size(); i++)
drawSolidPass2(*ShadedMesh[SM_GRASS][i], SM_GRASS);
glUseProgram(MeshShader::CausticsShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_CAUSTICS].size(); i++)
drawSolidPass2(*ShadedMesh[SM_CAUSTICS][i], SM_CAUSTICS);
if (!ShadedMesh[SM_UNLIT].empty())
glUseProgram(MeshShader::ObjectUnlitShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_UNLIT].size(); i++)
drawSolidPass2(*ShadedMesh[SM_UNLIT][i], SM_UNLIT);
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_DETAILS].size(); i++)
drawSolidPass2(*ShadedMesh[SM_DETAILS][i], SM_DETAILS);
if (!ShadedMesh[SM_CAUSTICS].empty())
glUseProgram(MeshShader::CausticsShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_CAUSTICS].size(); i++)
drawSolidPass2(*ShadedMesh[SM_CAUSTICS][i], SM_CAUSTICS);
glUseProgram(MeshShader::UntexturedObjectShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_UNTEXTURED].size(); i++)
drawSolidPass2(*ShadedMesh[SM_UNTEXTURED][i], SM_UNTEXTURED);
if (!ShadedMesh[SM_DETAILS].empty())
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_DETAILS].size(); i++)
drawSolidPass2(*ShadedMesh[SM_DETAILS][i], SM_DETAILS);
return;
if (!ShadedMesh[SM_UNTEXTURED].empty())
glUseProgram(MeshShader::UntexturedObjectShader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_UNTEXTURED].size(); i++)
drawSolidPass2(*ShadedMesh[SM_UNTEXTURED][i], SM_UNTEXTURED);
if (reload_each_frame)
glEnable(GL_CULL_FACE);
return;
}
if (irr_driver->getPhase() == SHADOW_PASS)
{
glUseProgram(MeshShader::ShadowShader::Program);
if (reload_each_frame)
glDisable(GL_CULL_FACE);
if (!GeometricMesh[FPSM_DEFAULT].empty())
glUseProgram(MeshShader::ShadowShader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
drawShadow(*GeometricMesh[FPSM_DEFAULT][i]);
glUseProgram(MeshShader::RefShadowShader::Program);
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
glUseProgram(MeshShader::RefShadowShader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++)
drawShadowRef(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i]);
if (reload_each_frame)
glEnable(GL_CULL_FACE);
return;
}
@ -392,13 +471,25 @@ void STKMeshSceneNode::render()
{
computeMVP(ModelViewProjectionMatrix);
glUseProgram(MeshShader::BubbleShader::Program);
if (!TransparentMesh[TM_BUBBLE].empty())
glUseProgram(MeshShader::BubbleShader::Program);
for (unsigned i = 0; i < TransparentMesh[TM_BUBBLE].size(); i++)
drawBubble(*TransparentMesh[TM_BUBBLE][i], ModelViewProjectionMatrix);
glUseProgram(MeshShader::TransparentShader::Program);
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
drawTransparentObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
if (World::getWorld()->getTrack()->isFogEnabled())
{
if (!TransparentMesh[TM_DEFAULT].empty())
glUseProgram(MeshShader::TransparentFogShader::Program);
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
drawTransparentFogObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
}
else
{
if (!TransparentMesh[TM_DEFAULT].empty())
glUseProgram(MeshShader::TransparentShader::Program);
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
drawTransparentObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
}
return;
}

View File

@ -23,15 +23,17 @@ protected:
void createGLMeshes();
void cleanGLMeshes();
void setFirstTimeMaterial();
void updatevbo();
bool isMaterialInitialized;
bool reload_each_frame;
public:
void setReloadEachFrame(bool);
STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
const irr::core::vector3df& position = irr::core::vector3df(0, 0, 0),
const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0),
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
virtual void render();
virtual void setMesh(irr::scene::IMesh* mesh);
void MovingTexture(unsigned, unsigned);
~STKMeshSceneNode();
};

View File

@ -26,6 +26,7 @@ STKModifiedSpriteBank::STKModifiedSpriteBank(IGUIEnvironment* env) :
#endif
m_scale = 1.0f;
m_height = 0;
if (Environment)
{
@ -62,8 +63,8 @@ core::array< core::rect<s32> >& STKModifiedSpriteBank::getPositions()
for (int n=0; n<(int)Rectangles.size(); n++)
{
const int h = (int)(Rectangles[n].getHeight()*m_scale);
const int w = (int)(Rectangles[n].getWidth() *m_scale);
const int h = getScaledHeight(Rectangles[n].getHeight());
const int w = getScaledWidth(Rectangles[n].getWidth());
copy.push_back( core::rect<s32>(Rectangles[n].UpperLeftCorner,
core::dimension2d<s32>(w,h) )
);
@ -203,8 +204,8 @@ void STKModifiedSpriteBank::draw2DSprite(u32 index,
const core::dimension2d<s32>& dim = r.getSize();
core::rect<s32> dest( pos,
core::dimension2d<s32>((int)(dim.Width*m_scale),
(int)(dim.Height*m_scale)) );
core::dimension2d<s32>(getScaledWidth(dim.Width),
getScaledHeight(dim.Height)));
if (center)
{
dest -= dest.getSize() / 2;
@ -295,6 +296,30 @@ void STKModifiedSpriteBank::draw2DSpriteBatch(const core::array<u32>& indices,
}
} // draw2DSpriteBatch
// ----------------------------------------------------------------------------
void STKModifiedSpriteBank::scaleToHeight(int height)
{
m_height = height;
}
// ----------------------------------------------------------------------------
s32 STKModifiedSpriteBank::getScaledWidth(s32 width) const
{
if (m_height == 0)
return (s32)((float)width * m_scale);
else
return m_height;
}
// ----------------------------------------------------------------------------
s32 STKModifiedSpriteBank::getScaledHeight(s32 height) const
{
if (m_height == 0)
return (s32)((float)height * m_scale);
else
return m_height;
}
// ----------------------------------------------------------------------------
} // namespace gui
} // namespace irr

View File

@ -67,12 +67,15 @@ public:
m_scale = scale;
}
void scaleToHeight(int height);
protected:
// this object was getting access after being freed, I wanna see when/why
unsigned int m_magic_number;
float m_scale;
int m_height;
struct SDrawBatch
{
@ -91,6 +94,8 @@ protected:
IGUIEnvironment* Environment;
video::IVideoDriver* Driver;
s32 getScaledWidth(s32 width) const;
s32 getScaledHeight(s32 height) const;
};
} // end namespace gui

View File

@ -486,6 +486,14 @@ namespace GUIEngine
Used on divs, indicate by how many pixels to pad contents
\n
\subsection prop20 PROP_KEEP_SELECTION
<em> Name in XML files: </em> \c "keep_selection"
Used on lists, indicates that the list should keep showing the selected item
even when it doesn't have the focus
\n
<HR>
\section code Using the engine in code
@ -723,20 +731,6 @@ namespace GUIEngine
std::vector<MenuMessage> gui_messages;
// ------------------------------------------------------------------------
Screen* getScreenNamed(const char* name)
{
const int screenCount = g_loaded_screens.size();
for (int n=0; n<screenCount; n++)
{
if (g_loaded_screens[n].getName() == name)
{
return g_loaded_screens.get(n);
}
}
return NULL;
} // getScreenNamed
// ------------------------------------------------------------------------
void showMessage(const wchar_t* message, const float time)
{
@ -800,13 +794,14 @@ namespace GUIEngine
{
return Private::small_font_height;
} // getSmallFontHeight
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
int getLargeFontHeight()
{
{
return Private::large_font_height;
} // getSmallFontHeight
// ------------------------------------------------------------------------
void clear()
{

View File

@ -170,7 +170,7 @@ namespace GUIEngine
inline Skin* getSkin() { return Private::g_skin; }
Screen* getScreenNamed(const char* name);
/** \return the height of the title font in pixels */
int getTitleFontHeight();

View File

@ -602,8 +602,6 @@ void ScalableFont::draw(const core::stringw& text,
core::rect<s32> dest(offsets[n] + core::position2di(0, y_shift), size);
video::SColor colors[] = {color, color, color, color};
video::ITexture* texture = (fallback[n] ?
m_fallback_font->SpriteBank->getTexture(texID) :
SpriteBank->getTexture(texID) );
@ -644,7 +642,6 @@ void ScalableFont::draw(const core::stringw& text,
{
// draw black border
video::SColor black(color.getAlpha(),0,0,0);
video::SColor black_colors[] = {black, black, black, black};
for (int x_delta=-2; x_delta<=2; x_delta++)
{
@ -652,10 +649,10 @@ void ScalableFont::draw(const core::stringw& text,
{
if (x_delta == 0 || y_delta == 0) continue;
draw2DImage(texture,
dest + core::position2d<s32>(x_delta, y_delta),
source,
clip,
black_colors, true);
dest + core::position2d<s32>(x_delta, y_delta),
source,
clip,
black, true);
}
}
}
@ -667,18 +664,18 @@ void ScalableFont::draw(const core::stringw& text,
static video::SColor yellow(color.getAlpha(), 255, 220, 15);
video::SColor title_colors[] = {yellow, orange, orange, yellow};
draw2DImage(texture,
dest,
source,
clip,
title_colors, true);
dest,
source,
clip,
title_colors, true);
}
else
{
draw2DImage(texture,
dest,
source,
clip,
colors, true);
dest,
source,
clip,
color, true);
#ifdef FONT_DEBUG
driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y),

View File

@ -221,6 +221,7 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).
READ_PROPERTY(max_rows, PROP_MAX_ROWS);
READ_PROPERTY(wrap_around, PROP_WRAP_AROUND);
READ_PROPERTY(padding, PROP_DIV_PADDING);
READ_PROPERTY(keep_selection, PROP_KEEP_SELECTION);
#undef READ_PROPERTY
const wchar_t* text = xml->getAttributeValue( L"text" );

View File

@ -103,7 +103,8 @@ namespace GUIEngine
PROP_LABELS_LOCATION,
PROP_MAX_ROWS,
PROP_WRAP_AROUND,
PROP_DIV_PADDING
PROP_DIV_PADDING,
PROP_KEEP_SELECTION,
};
bool isWithinATextBox();

View File

@ -299,7 +299,8 @@ void ListWidget::unfocused(const int playerID, Widget* new_focus)
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
// remove selection when leaving list
if (list != NULL) list->setSelected(-1);
if (list != NULL && m_properties[PROP_KEEP_SELECTION] != "true")
list->setSelected(-1);
}
// -----------------------------------------------------------------------------

View File

@ -188,10 +188,11 @@ FileManager::FileManager()
addRootDirs(root_dir+"../../stk-assets");
if ( getenv ( "SUPERTUXKART_ROOT_PATH" ) != NULL )
addRootDirs(getenv("SUPERTUXKART_ROOT_PATH"));
checkAndCreateConfigDir();
checkAndCreateAddonsDir();
checkAndCreateScreenshotDir();
checkAndCreateGPDir();
#ifdef WIN32
redirectOutput();
@ -203,12 +204,14 @@ FileManager::FileManager()
for(unsigned int i=0; i<m_root_dirs.size(); i++)
Log::info("[FileManager]", "Data files will be fetched from: '%s'",
m_root_dirs[i].c_str());
Log::info("[FileManager]", "User directory is '%s'.",
Log::info("[FileManager]", "User directory is '%s'.",
m_user_config_dir.c_str());
Log::info("[FileManager]", "Addons files will be stored in '%s'.",
m_addons_dir.c_str());
Log::info("[FileManager]", "Screenshots will be stored in '%s'.",
m_screenshot_dir.c_str());
Log::info("[FileManager]", "User-defined grand prix will be stored in '%s'.",
m_gp_dir.c_str());
/** Now search for the path to all needed subdirectories. */
// ==========================================================
@ -270,7 +273,7 @@ void FileManager::reInit()
// Note that we can't push the texture search path in the constructor
// since this also adds a file archive to te file system - and
// m_file_system is deleted (in irr_driver) after
// m_file_system is deleted (in irr_driver) after
pushTextureSearchPath(m_subdir_name[TEXTURE]);
if(fileExists(m_subdir_name[TEXTURE]+"deprecated/"))
pushTextureSearchPath(m_subdir_name[TEXTURE]+"deprecated/");
@ -543,7 +546,7 @@ std::string FileManager::getAssetChecked(FileManager::AssetType type,
} // getAssetChecked
//-----------------------------------------------------------------------------
/** Returns the full path of a file of the given asset class. It is not
/** Returns the full path of a file of the given asset class. It is not
* checked if the file actually exists (use getAssetChecked() instead if
* checking is needed).
* \param type Type of the asset class.
@ -577,7 +580,15 @@ std::string FileManager::getScreenshotDir() const
} // getScreenshotDir
//-----------------------------------------------------------------------------
/** Returns the full path of a texture file name by searching in all
/** Returns the directory in which user-defined grand prix should be stored.
*/
std::string FileManager::getGPDir() const
{
return m_gp_dir;
} // getGPDir
//-----------------------------------------------------------------------------
/** Returns the full path of a texture file name by searching in all
* directories currently in the texture search path. The difference to
* a call getAsset(TEXTURE,...) is that the latter will only return
* textures from .../textures, while the searchTexture will also
@ -666,7 +677,7 @@ bool FileManager::checkAndCreateDirectoryP(const std::string &path)
//-----------------------------------------------------------------------------
/** Checks if the config directory exists, and it not, tries to create it.
* It will set m_user_config_dir to the path to which user-specific config
* It will set m_user_config_dir to the path to which user-specific config
* files are stored.
*/
void FileManager::checkAndCreateConfigDir()
@ -725,7 +736,7 @@ void FileManager::checkAndCreateConfigDir()
}
else if (!getenv("HOME"))
{
Log::error("[FileManager]",
Log::error("[FileManager]",
"No home directory, this should NOT happen "
"- trying '.' for config files!");
m_user_config_dir = ".";
@ -737,7 +748,7 @@ void FileManager::checkAndCreateConfigDir()
if(!checkAndCreateDirectory(m_user_config_dir))
{
// If $HOME/.config can not be created:
Log::error("[FileManager]",
Log::error("[FileManager]",
"Cannot create directory '%s', falling back to use '%s'",
m_user_config_dir.c_str(), getenv("HOME"));
m_user_config_dir = getenv("HOME");
@ -824,6 +835,32 @@ void FileManager::checkAndCreateScreenshotDir()
} // checkAndCreateScreenshotDir
// ----------------------------------------------------------------------------
/** Creates the directories for user-defined grand prix. This will set m_gp_dir
* with the appropriate path.
*/
void FileManager::checkAndCreateGPDir()
{
#if defined(WIN32) || defined(__CYGWIN__)
m_gp_dir = m_user_config_dir + "grandprix/";
#elif defined(__APPLE__)
m_gp_dir = getenv("HOME");
m_gp_dir += "/Library/Application Support/SuperTuxKart/grandprix/";
#else
m_gp_dir = checkAndCreateLinuxDir("XDG_DATA_HOME", "supertuxkart",
".local/share", ".supertuxkart");
m_gp_dir += "grandprix/";
#endif
if(!checkAndCreateDirectory(m_gp_dir))
{
Log::error("FileManager", "Can not create user-defined grand prix directory '%s', "
"falling back to '.'.", m_gp_dir.c_str());
m_gp_dir = ".";
}
} // checkAndCreateGPDir
// ----------------------------------------------------------------------------
#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__APPLE__)

File diff suppressed because it is too large Load Diff

View File

@ -46,10 +46,10 @@ class FileManager : public NoCopy
public:
/** The various asset types (and directories) STK might request.
* The last entry ASSET_COUNT specifies the number of entries. */
enum AssetType {ASSET_MIN,
CHALLENGE=ASSET_MIN,
enum AssetType {ASSET_MIN,
CHALLENGE=ASSET_MIN,
FONT, GFX, GRANDPRIX, GUI, MODEL, MUSIC,
SFX, SHADER, SKIN, TEXTURE, TRANSLATION,
SFX, SHADER, SKIN, TEXTURE, TRANSLATION,
ASSET_MAX = TRANSLATION,
ASSET_COUNT};
private:
@ -72,6 +72,9 @@ private:
/** Directory to store screenshots in. */
std::string m_screenshot_dir;
/** Directory where user-defined grand prix are stored. */
std::string m_gp_dir;
std::vector<std::string>
m_texture_search_path,
m_model_search_path,
@ -88,6 +91,7 @@ private:
bool isDirectory(const std::string &path) const;
void checkAndCreateAddonsDir();
void checkAndCreateScreenshotDir();
void checkAndCreateGPDir();
#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__APPLE__)
std::string checkAndCreateLinuxDir(const char *env_name,
const char *dir_name,
@ -106,6 +110,7 @@ public:
XMLNode *createXMLTreeFromString(const std::string & content);
std::string getScreenshotDir() const;
std::string getGPDir() const;
bool checkAndCreateDirectoryP(const std::string &path);
const std::string &getAddonsDir() const;
std::string getAddonsFile(const std::string &name);

View File

@ -18,6 +18,9 @@
#include "items/powerup.hpp"
#include "achievements/achievement_info.hpp"
#include "config/player_manager.hpp"
#include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp"
#include "config/stk_config.hpp"
@ -170,6 +173,14 @@ void Powerup::adjustSound()
*/
void Powerup::use()
{
// The player gets an achievement point for using a powerup
StateManager::ActivePlayer * player = m_owner->getController()->getPlayer();
if (m_type != PowerupManager::POWERUP_NOTHING &&
player != NULL && player->getConstProfile() == PlayerManager::get()->getCurrentPlayer())
{
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_POWERUP_LOVER, "poweruplover");
}
// Play custom kart sound when collectible is used //TODO: what about the bubble gum?
if (m_type != PowerupManager::POWERUP_NOTHING &&
m_type != PowerupManager::POWERUP_SWATTER &&
@ -237,7 +248,7 @@ void Powerup::use()
m_sound_use->play();
pos.setY(hit_point.getY()-0.05f);
ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_owner);
}
else // if the kart is looking forward, use the bubblegum as a shield

View File

@ -22,6 +22,7 @@
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/stkmeshscenenode.hpp"
#include "items/plunger.hpp"
#include "items/projectile_manager.hpp"
#include "karts/abstract_kart.hpp"
@ -71,6 +72,8 @@ RubberBand::RubberBand(Plunger *plunger, AbstractKart *kart)
updatePosition();
m_node = irr_driver->addMesh(m_mesh);
irr_driver->applyObjectPassShader(m_node);
if (STKMeshSceneNode *stkm = dynamic_cast<STKMeshSceneNode *>(m_node))
stkm->setReloadEachFrame(true);
#ifdef DEBUG
std::string debug_name = m_owner->getIdent()+" (rubber-band)";
m_node->setName(debug_name.c_str());

View File

@ -560,9 +560,17 @@ void KartProperties::getAllData(const XMLNode * root)
else if (s == "small") m_engine_sfx_type = "engine_small";
else
{
Log::warn("[KartProperties]", "Kart '%s' has invalid engine '%s'.",
m_name.c_str(), s.c_str());
m_engine_sfx_type = "engine_small";
if (sfx_manager->soundExist(s))
{
m_engine_sfx_type = s;
}
else
{
Log::error("[KartProperties]",
"Kart '%s' has an invalid engine '%s'.",
m_name.c_str(), s.c_str());
m_engine_sfx_type = "engine_small";
}
}
#ifdef WILL_BE_ENABLED_ONCE_DONE_PROPERLY

View File

@ -17,6 +17,8 @@
#include "modes/linear_world.hpp"
#include "achievements/achievements_manager.hpp"
#include "config/player_manager.hpp"
#include "audio/music_manager.hpp"
#include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp"
@ -236,6 +238,14 @@ void LinearWorld::newLap(unsigned int kart_index)
KartInfo &kart_info = m_kart_info[kart_index];
AbstractKart *kart = m_karts[kart_index];
// Reset reset-after-lap achievements
StateManager::ActivePlayer *c = kart->getController()->getPlayer();
PlayerProfile *p = PlayerManager::get()->getCurrentPlayer();
if (c && c->getConstProfile() == p)
{
p->getAchievementsStatus()->onLapEnd();
}
// Only update the kart controller if a kart that has already finished
// the race crosses the start line again. This avoids 'fastest lap'
// messages if the end controller does a fastest lap, but especially

View File

@ -445,6 +445,7 @@ void World::terminateRace()
&best_player);
}
// Check achievements
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_COLUMBUS,
getTrack()->getIdent(), 1);
if (raceHasLaps())
@ -452,6 +453,64 @@ void World::terminateRace()
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_MARATHONER,
"laps", race_manager->getNumLaps());
}
Achievement *achiev = PlayerManager::getCurrentAchievementsStatus()->getAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER);
if (achiev)
{
std::string mode_name = getIdent(); // Get the race mode name
int winner_position = 1;
int opponents = achiev->getInfo()->getGoalValue("opponents"); // Get the required opponents number
if (mode_name == IDENT_FTL)
{
winner_position = 2;
opponents++;
}
for(unsigned int i = 0; i < kart_amount; i++)
{
// Retrieve the current player
StateManager::ActivePlayer* p = m_karts[i]->getController()->getPlayer();
if (p && p->getConstProfile() == PlayerManager::get()->getCurrentPlayer())
{
// Check if the player has won
if (m_karts[i]->getPosition() == winner_position && kart_amount > opponents )
{
// Update the achievement
mode_name = StringUtils::toLowerCase(mode_name);
if (achiev->getValue("opponents") <= 0)
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER,
"opponents", opponents);
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER,
mode_name, 1);
}
}
} // for i < kart_amount
} // if (achiev)
Achievement *win = PlayerManager::getCurrentAchievementsStatus()->getAchievement(AchievementInfo::ACHIEVE_UNSTOPPABLE);
//if achivement has been unlocked
if (win->getValue("wins") < 5 )
{
for(unsigned int i = 0; i < kart_amount; i++)
{
// Retrieve the current player
StateManager::ActivePlayer* p = m_karts[i]->getController()->getPlayer();
if (p && p->getConstProfile() == PlayerManager::get()->getCurrentPlayer())
{
// Check if the player has won
if (m_karts[i]->getPosition() == 1 )
{
// Increase number of consecutive wins
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_UNSTOPPABLE,
"wins", 1);
}
else
{
//Set number of consecutive wins to 0
win->reset();
}
}
}
}
PlayerManager::get()->getCurrentPlayer()->raceFinished();
if (m_race_gui) m_race_gui->clearAllMessages();

View File

@ -23,37 +23,62 @@
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
#include "io/file_manager.hpp"
#include "io/utf_writer.hpp"
#include "tracks/track_manager.hpp"
#include "tracks/track.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
#include <iostream>
#include <memory>
#include <algorithm>
#include <stdexcept>
GrandPrixData::GrandPrixData(const std::string filename)
{
load_from_file(file_manager->getAsset(FileManager::GRANDPRIX, filename),
filename);
}
// ----------------------------------------------------------------------------
GrandPrixData::GrandPrixData(const std::string dir, const std::string filename)
{
assert(dir[dir.size() - 1] == '/');
load_from_file(dir + filename, filename);
}
// ----------------------------------------------------------------------------
void GrandPrixData::load_from_file(const std::string fullpath,
const std::string filename)
GrandPrixData::GrandPrixData(const std::string& filename) throw(std::logic_error)
{
m_filename = filename;
m_id = StringUtils::getBasename(StringUtils::removeExtension(filename));
m_editable = (filename.find(file_manager->getGPDir(), 0) == 0);
reload();
}
XMLNode * root = file_manager->createXMLTree(fullpath);
if (!root)
// ----------------------------------------------------------------------------
void GrandPrixData::setId(const std::string& id)
{
m_id = id;
}
// ----------------------------------------------------------------------------
void GrandPrixData::setName(const irr::core::stringw& name)
{
m_name = name;
}
// ----------------------------------------------------------------------------
void GrandPrixData::setFilename(const std::string& filename)
{
m_filename = filename;
}
// ----------------------------------------------------------------------------
void GrandPrixData::setEditable(const bool editable)
{
m_editable = editable;
}
// ----------------------------------------------------------------------------
void GrandPrixData::reload()
{
m_tracks.clear();
m_laps.clear();
m_reversed.clear();
std::auto_ptr<XMLNode> root(file_manager->createXMLTree(m_filename));
if (root.get() == NULL)
{
Log::error("GrandPrixData","Error while trying to read grandprix file "
"'%s'", fullpath.c_str());
Log::error("GrandPrixData","Error while trying to read grandprix file '%s'",
m_filename.c_str());
throw std::logic_error("File not found");
}
@ -61,24 +86,18 @@ void GrandPrixData::load_from_file(const std::string fullpath,
if (root->getName() == "supertuxkart_grand_prix")
{
std::string temp_name;
if (root->get("name", &temp_name) == 0)
if (root->get("name", &m_name) == 0)
{
Log::error("GrandPrixData", "Error while trying to read grandprix "
"file '%s' : missing 'name' attribute\n",
fullpath.c_str());
delete root;
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
"missing 'name' attribute\n", m_filename.c_str());
throw std::logic_error("File contents are incomplete or corrupt");
}
m_name = temp_name.c_str();
foundName = true;
}
else
{
Log::error("GrandPrixData", "Error while trying to read grandprix file "
"'%s' : Root node has an unexpected name\n",
fullpath.c_str());
delete root;
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
"Root node has an unexpected name\n", m_filename.c_str());
throw std::logic_error("File contents are incomplete or corrupt");
}
@ -95,20 +114,17 @@ void GrandPrixData::load_from_file(const std::string fullpath,
int numLaps;
bool reversed = false;
const int idFound = node->get("id", &trackID);
const int lapFound = node->get("laps", &numLaps);
const int idFound = node->get("id", &trackID );
const int lapFound = node->get("laps", &numLaps );
// Will stay false if not found
node->get("reverse", &reversed );
if (!idFound || !lapFound)
{
Log::error("GrandPrixData", "Error while trying to read "
"grandprix file '%s' : <track> tag does not have "
"idi and laps reverse attributes. \n",
fullpath.c_str());
delete root;
throw std::logic_error("File contents are incomplete or "
"corrupt");
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
"<track> tag does not have idi and laps reverse attributes. \n",
m_filename.c_str());
throw std::logic_error("File contents are incomplete or corrupt");
}
// Make sure the track really is reversible
@ -127,27 +143,58 @@ void GrandPrixData::load_from_file(const std::string fullpath,
}
else
{
Log::error("Unknown node in Grand Prix XML file: %s/n",
node->getName().c_str());
delete root;
std::cerr << "Unknown node in Grand Prix XML file : " << node->getName().c_str() << std::endl;
throw std::runtime_error("Unknown node in sfx XML file");
}
}// end for
delete root;
}// nend for
// sanity checks
if (!foundName)
{
Log::error("GrandPrixData", "Error while trying to read grandprix file "
"'%s' : missing 'name' attribute\n", fullpath.c_str());
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
"missing 'name' attribute\n", m_filename.c_str());
throw std::logic_error("File contents are incomplete or corrupt");
}
}
// ----------------------------------------------------------------------------
bool GrandPrixData::writeToFile()
{
try
{
UTFWriter file(m_filename.c_str());
if (file.is_open())
{
file << L"\n<supertuxkart_grand_prix name=\"" << m_name << L"\">\n\n";
for (unsigned int i = 0; i < m_tracks.size(); i++)
{
file <<
L"\t<track id=\"" << m_tracks[i] <<
L"\" laps=\"" << m_laps[i] <<
L"\" reverse=\"" << (m_reversed[i] ? L"true" : L"false") <<
L"\" />\n";
}
file << L"\n</supertuxkart_grand_prix>\n";
file.close();
return true;
}
return false;
}
catch (std::runtime_error& e)
{
Log::error("GrandPrixData", "Failed to write '%s'; cause: %s\n",
m_filename.c_str(), e.what());
return false;
}
}
// ----------------------------------------------------------------------------
bool GrandPrixData::checkConsistency(bool chatty) const
{
for(unsigned int i=0; i<m_tracks.size(); i++)
for (unsigned int i = 0; i<m_tracks.size(); i++)
{
Track* t = track_manager->getTrack(m_tracks[i]);
@ -166,6 +213,7 @@ bool GrandPrixData::checkConsistency(bool chatty) const
return true;
} // checkConsistency
// ----------------------------------------------------------------------------
/** Returns true if the track is available. This is used to test if Fort Magma
* is available (this way FortMagma is not used in the last Grand Prix in
@ -182,7 +230,7 @@ bool GrandPrixData::isTrackAvailable(const std::string &id) const
void GrandPrixData::getLaps(std::vector<int> *laps) const
{
laps->clear();
for(unsigned int i=0; i< m_tracks.size(); i++)
for (unsigned int i = 0; i< m_tracks.size(); i++)
if(isTrackAvailable(m_tracks[i]))
laps->push_back(m_laps[i]);
} // getLaps
@ -191,16 +239,129 @@ void GrandPrixData::getLaps(std::vector<int> *laps) const
void GrandPrixData::getReverse(std::vector<bool> *reverse) const
{
reverse->clear();
for(unsigned int i=0; i< m_tracks.size(); i++)
for (unsigned int i = 0; i< m_tracks.size(); i++)
if(isTrackAvailable(m_tracks[i]))
reverse->push_back(m_reversed[i]);
} // getReverse
// ----------------------------------------------------------------------------
bool GrandPrixData::isEditable() const
{
return m_editable;
} // isEditable
// ----------------------------------------------------------------------------
unsigned int GrandPrixData::getNumberOfTracks() const
{
return m_tracks.size();
}
// ----------------------------------------------------------------------------
irr::core::stringw GrandPrixData::getTrackName(const unsigned int track) const
{
assert(track < getNumberOfTracks());
Track* t = track_manager->getTrack(m_tracks[track]);
assert(t != NULL);
return t->getName();
}
// ----------------------------------------------------------------------------
const std::string& GrandPrixData::getTrackId(const unsigned int track) const
{
assert(track < getNumberOfTracks());
return m_tracks[track];
}
// ----------------------------------------------------------------------------
unsigned int GrandPrixData::getLaps(const unsigned int track) const
{
assert(track < getNumberOfTracks());
return m_laps[track];
}
// ----------------------------------------------------------------------------
bool GrandPrixData::getReverse(const unsigned int track) const
{
assert(track < getNumberOfTracks());
return m_reversed[track];
}
// ----------------------------------------------------------------------------
void GrandPrixData::moveUp(const unsigned int track)
{
assert (track > 0 && track < getNumberOfTracks());
std::swap(m_tracks[track], m_tracks[track - 1]);
std::swap(m_laps[track], m_laps[track - 1]);
m_reversed.swap(m_reversed[track], m_reversed[track - 1]);
}
// ----------------------------------------------------------------------------
void GrandPrixData::moveDown(const unsigned int track)
{
assert (track < (getNumberOfTracks() - 1));
std::swap(m_tracks[track], m_tracks[track + 1]);
std::swap(m_laps[track], m_laps[track + 1]);
m_reversed.swap(m_reversed[track], m_reversed[track + 1]);
}
// ----------------------------------------------------------------------------
void GrandPrixData::addTrack(Track* track, unsigned int laps, bool reverse,
int position)
{
int n;
n = getNumberOfTracks();
assert (track != NULL);
assert (laps > 0);
assert (position >= -1 && position < n);
if (position < 0 || position == (n - 1) || m_tracks.empty())
{
//Append new track to the end of the list
m_tracks.push_back(track->getIdent());
m_laps.push_back(laps);
m_reversed.push_back(reverse);
}
else
{
//Insert new track right after the specified position. Caution:
//std::vector inserts elements _before_ the specified position
m_tracks.insert(m_tracks.begin() + position + 1, track->getIdent());
m_laps.insert(m_laps.begin() + position + 1, laps);
m_reversed.insert(m_reversed.begin() + position + 1, reverse);
}
}
// ----------------------------------------------------------------------------
void GrandPrixData::editTrack(unsigned int t, Track* track,
unsigned int laps, bool reverse)
{
assert (t < getNumberOfTracks());
assert (track != NULL);
assert (laps > 0);
m_tracks[t] = track->getIdent();
m_laps[t] = laps;
m_reversed[t] = reverse;
}
// ----------------------------------------------------------------------------
void GrandPrixData::remove(const unsigned int track)
{
assert (track < getNumberOfTracks());
m_tracks.erase(m_tracks.begin() + track);
m_laps.erase(m_laps.begin() + track);
m_reversed.erase(m_reversed.begin() + track);
}
// ----------------------------------------------------------------------------
const std::vector<std::string>& GrandPrixData::getTrackNames() const
{
m_really_available_tracks.clear();
for(unsigned int i=0; i< m_tracks.size(); i++)
for (unsigned int i = 0; i < m_tracks.size(); i++)
{
if(isTrackAvailable(m_tracks[i]))
m_really_available_tracks.push_back(m_tracks[i]);

View File

@ -27,7 +27,8 @@
#include <stdexcept>
#include "utils/translation.hpp"
#include "io/file_manager.hpp"
class Track;
/** Simple class that hold the data relevant to a 'grand_prix', aka. a number
* of races that has to be completed one after the other
@ -65,28 +66,49 @@ private:
/** Whether the track in question should be done in reverse mode */
std::vector<bool> m_reversed;
void load_from_file(const std::string fullpath, const std::string filename);
/** Wether the user can edit this grand prix or not */
bool m_editable;
bool isTrackAvailable(const std::string &id) const;
public:
/** Load the GrandPrixData from the given filename */
#if (defined(WIN32) || defined(_WIN32)) && !defined(__MINGW32__)
#pragma warning(disable:4290)
#endif
GrandPrixData () {}; // empty for initialising
GrandPrixData(const std::string filename);
GrandPrixData (const std::string dir, const std::string filename);
GrandPrixData (const std::string& filename) throw(std::logic_error);
GrandPrixData () {}; // empty for initialising
void setId(const std::string& id);
void setName(const irr::core::stringw& name);
void setFilename(const std::string& filename);
void setEditable(const bool editable);
void reload();
bool writeToFile();
bool checkConsistency(bool chatty=true) const;
bool checkConsistency(bool chatty=true) const;
const std::vector<std::string>& getTrackNames() const;
void getLaps(std::vector<int> *laps) const;
void getReverse(std::vector<bool> *reverse) const;
void getLaps(std::vector<int> *laps) const;
void getReverse(std::vector<bool> *reverse) const;
bool isEditable() const;
unsigned int getNumberOfTracks() const;
const std::string& getTrackId(const unsigned int track) const;
irr::core::stringw getTrackName(const unsigned int track) const;
unsigned int getLaps(const unsigned int track) const;
bool getReverse(const unsigned int track) const;
void moveUp(const unsigned int track);
void moveDown(const unsigned int track);
void addTrack(Track* track, unsigned int laps,
bool reverse, int position=-1);
void editTrack(unsigned int t, Track* track,
unsigned int laps, bool reverse);
void remove(const unsigned int track);
// ------------------------------------------------------------------------
/** @return the (potentially translated) user-visible name of the Grand
* Prix (apply fribidi as needed) */
const irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
// ------------------------------------------------------------------------
/** @return the internal name identifier of the Grand Prix (not translated) */

View File

@ -18,66 +18,126 @@
#include "race/grand_prix_manager.hpp"
#include <set>
#include "config/user_config.hpp"
#include "grand_prix_data.hpp"
#include "io/file_manager.hpp"
#include "utils/string_utils.hpp"
#include "config/user_config.hpp"
#include <algorithm>
#include <set>
#include <sstream>
GrandPrixManager *grand_prix_manager = NULL;
const char* GrandPrixManager::SUFFIX = ".grandprix";
// ----------------------------------------------------------------------------
void GrandPrixManager::loadFiles()
{
std::set<std::string> dirs;
//Add all the directories to a set to avoid duplicates
dirs.insert(file_manager->getAsset(FileManager::GRANDPRIX, ""));
dirs.insert(file_manager->getGPDir());
dirs.insert(UserConfigParams::m_additional_gp_directory);
for (std::set<std::string>::const_iterator it = dirs.begin(); it != dirs.end(); ++it)
{
std::string dir = *it;
if (!dir.empty() && dir[dir.size() - 1] == '/')
loadDir(dir);
}
}
// ----------------------------------------------------------------------------
void GrandPrixManager::loadDir(const std::string& dir)
{
Log::info("GrandPrixManager", "Loading Grand Prix files from %s", dir.c_str());
assert(!dir.empty() && dir[dir.size() - 1] == '/');
// Findout which grand prixs are available and load them
std::set<std::string> result;
file_manager->listFiles(result, dir);
for(std::set<std::string>::iterator i = result.begin(); i != result.end(); i++)
{
if (StringUtils::hasSuffix(*i, SUFFIX))
load(dir + *i);
} // for i
} // loadDir
// ----------------------------------------------------------------------------
void GrandPrixManager::load(const std::string& filename)
{
GrandPrixData* gp;
try
{
gp = new GrandPrixData(filename);
m_gp_data.push_back(gp);
Log::debug("GrandPrixManager", "Grand Prix '%s' loaded from %s",
gp->getId().c_str(), filename.c_str());
}
catch (std::logic_error& er)
{
Log::error("GrandPrixManager", "Ignoring GP %s (%s)\n",
filename.c_str(), er.what());
}
} // load
// ----------------------------------------------------------------------------
void GrandPrixManager::reload()
{
for(unsigned int i=0; i<m_gp_data.size(); i++)
delete m_gp_data[i];
m_gp_data.clear();
loadFiles();
}
// ----------------------------------------------------------------------------
std::string GrandPrixManager::generateId()
{
std::stringstream s;
do
{
s.clear();
s << "usr_gp_" << ((rand() % 90000000) + 10000000);
} while (existsId(s.str()));
return s.str();
}
// ----------------------------------------------------------------------------
bool GrandPrixManager::existsId(const std::string& id) const
{
bool exists;
exists = false;
for (unsigned int i = 0; !exists && i < m_gp_data.size(); i++)
exists = (m_gp_data[i]->getId() == id);
return exists;
}
// ----------------------------------------------------------------------------
bool GrandPrixManager::existsName(const irr::core::stringw& name) const
{
bool exists;
exists = false;
for (unsigned int i = 0; !exists && i < m_gp_data.size(); i++)
exists = (m_gp_data[i]->getName() == name);
return exists;
}
// ----------------------------------------------------------------------------
GrandPrixManager::GrandPrixManager()
{
// Findout which grand prixs are available and load them
// Grand Prix in the standart directory
std::set<std::string> result;
std::string gp_dir = file_manager->getAsset(FileManager::GRANDPRIX, "");
file_manager->listFiles(result, gp_dir);
for(std::set<std::string>::iterator i = result.begin();
i != result.end() ; i++)
{
if (StringUtils::hasSuffix(*i, ".grandprix"))
{
try
{
m_gp_data.push_back(new GrandPrixData(*i));
Log::debug("GrandPrixManager", "Grand Prix %s loaded.",
i->c_str());
}
catch (std::logic_error& e)
{
Log::error("GrandPrixManager", "Ignoring GP %s ( %s ) \n",
i->c_str(), e.what());
}
}
}
// Load additional Grand Prix
const std::string dir = UserConfigParams::m_additional_gp_directory;
if(dir != "") {
Log::info("GrandPrixManager", "Loading additional Grand Prix from "
"%s ...", dir.c_str());
file_manager->listFiles(result, dir);
for(std::set<std::string>::iterator i = result.begin();
i != result.end() ; i++)
{
if (StringUtils::hasSuffix(*i, ".grandprix"))
{
try
{
m_gp_data.push_back(new GrandPrixData(dir, *i));
Log::debug("GrandPrixManager", "Grand Prix %s loaded from "
"%s", i->c_str(),
dir.c_str());
}
catch (std::logic_error& e)
{
Log::error("GrandPrixManager", "Ignoring GP %s ( %s ) \n",
i->c_str(), e.what());
}
}
} // end for
} // end if
loadFiles();
} // GrandPrixManager
// ----------------------------------------------------------------------------
GrandPrixManager::~GrandPrixManager()
{
@ -87,15 +147,21 @@ GrandPrixManager::~GrandPrixManager()
} // for i
} // ~GrandPrixManager
// ----------------------------------------------------------------------------
const GrandPrixData* GrandPrixManager::getGrandPrix(const std::string& s) const
{
for(unsigned int i=0; i<m_gp_data.size(); i++)
if(m_gp_data[i]->getId() == s)
return m_gp_data[i];
return NULL;
return editGrandPrix(s);
} // getGrandPrix
// ----------------------------------------------------------------------------
GrandPrixData* GrandPrixManager::editGrandPrix(const std::string& s) const
{
for(unsigned int i=0; i<m_gp_data.size(); i++)
if(m_gp_data[i]->getId()==s) return m_gp_data[i];
return NULL;
}
// ----------------------------------------------------------------------------
void GrandPrixManager::checkConsistency()
{
@ -104,9 +170,64 @@ void GrandPrixManager::checkConsistency()
if(!m_gp_data[i]->checkConsistency())
{
// delete this GP, since a track is missing
m_gp_data.erase(m_gp_data.begin()+i);
delete *(m_gp_data.erase(m_gp_data.begin()+i));
i--;
}
}
} // checkConsistency
// ----------------------------------------------------------------------------
GrandPrixData* GrandPrixManager::createNew(const irr::core::stringw& newName)
{
if (existsName(newName))
return NULL;
std::string newID = generateId();
GrandPrixData* gp = new GrandPrixData;
gp->setId(newID);
gp->setName(newName);
gp->setFilename(file_manager->getGPDir() + newID + SUFFIX);
gp->setEditable(true);
gp->writeToFile();
m_gp_data.push_back(gp);
return gp;
}
// ----------------------------------------------------------------------------
GrandPrixData* GrandPrixManager::copy(const std::string& id,
const irr::core::stringw& newName)
{
if (existsName(newName))
return NULL;
std::string newID = generateId();
GrandPrixData* gp = new GrandPrixData(*getGrandPrix(id));
gp->setId(newID);
gp->setName(newName);
gp->setFilename(file_manager->getGPDir() + newID + SUFFIX);
gp->setEditable(true);
gp->writeToFile();
m_gp_data.push_back(gp);
return gp;
}
// ----------------------------------------------------------------------------
void GrandPrixManager::remove(const std::string& id)
{
const GrandPrixData* gp = getGrandPrix(id);
assert(gp != NULL);
if (gp->isEditable())
{
file_manager->removeFile(gp->getFilename());
reload();
}
else
{
Log::warn("GrandPrixManager", "Grand Prix '%s' cannot be removed\n", gp->getId().c_str());
}
}

View File

@ -30,16 +30,31 @@
class GrandPrixManager
{
private:
static const char* SUFFIX;
void loadFiles();
void loadDir(const std::string& dir);
void load(const std::string &filename);
std::string generateId();
bool existsId(const std::string& id) const;
bool existsName(const irr::core::stringw& name) const;
std::vector<GrandPrixData*> m_gp_data;
public:
GrandPrixManager();
~GrandPrixManager();
void load(const std::string &filename);
const GrandPrixData* getGrandPrix(int i) const { return m_gp_data[i]; }
void reload();
const GrandPrixData* getGrandPrix(const int i) const { return m_gp_data[i]; }
const GrandPrixData* getGrandPrix(const std::string& s) const;
GrandPrixData* editGrandPrix(const std::string& s) const;
unsigned int getNumberOfGrandPrix() const { return m_gp_data.size(); }
void checkConsistency();
GrandPrixData* createNew(const irr::core::stringw& newName);
GrandPrixData* copy(const std::string& id, const irr::core::stringw& newName);
void remove(const std::string& id);
}; // GrandPrixManager
extern GrandPrixManager *grand_prix_manager;

View File

@ -0,0 +1,137 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 Marc Coll
//
// 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_gp_name_dialog.hpp"
#include "audio/sfx_manager.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 "race/grand_prix_manager.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
#include <IGUIEnvironment.h>
using namespace GUIEngine;
using namespace irr::core;
// -----------------------------------------------------------------------------
EnterGPNameDialog::EnterGPNameDialog(INewGPListener* listener,
const float w, const float h)
: ModalDialog(w, h), m_listener(listener), m_self_destroy(false)
{
assert(listener != NULL);
loadFromFile("enter_gp_name_dialog.stkgui");
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
assert(textCtrl != NULL);
textCtrl->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
}
// -----------------------------------------------------------------------------
EnterGPNameDialog::~EnterGPNameDialog()
{
// FIXME: what is this code for?
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
textCtrl->getIrrlichtElement()->remove();
textCtrl->clearListeners();
}
// -----------------------------------------------------------------------------
GUIEngine::EventPropagation EnterGPNameDialog::processEvent(const std::string& eventSource)
{
if (eventSource == "cancel")
{
dismiss();
return GUIEngine::EVENT_BLOCK;
}
return GUIEngine::EVENT_LET;
}
// -----------------------------------------------------------------------------
void EnterGPNameDialog::onEnterPressedInternal()
{
//Cancel button pressed
ButtonWidget* cancelButton = getWidget<ButtonWidget>("cancel");
if (GUIEngine::isFocusedForPlayer(cancelButton, PLAYER_ID_GAME_MASTER))
{
std::string fakeEvent = "cancel";
processEvent(fakeEvent);
return;
}
//Otherwise, see if we can accept the new name
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
assert(textCtrl != NULL);
stringw name = textCtrl->getText().trim();
if (name.size() > 0)
{
// check for duplicate names
for (int i = 0; i < grand_prix_manager->getNumberOfGrandPrix(); i++)
{
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(i);
if (gp->getName() == name)
{
LabelWidget* label = getWidget<LabelWidget>("title");
assert(label != NULL);
label->setText(_("Another grand prix with this name already exists."), false);
sfx_manager->quickSound("anvil");
return;
}
}
// 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;
}
else
{
LabelWidget* label = getWidget<LabelWidget>("title");
assert(label != NULL);
label->setText(_("Cannot add a grand prix with this name"), false);
sfx_manager->quickSound("anvil");
}
}
// -----------------------------------------------------------------------------
void EnterGPNameDialog::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 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
INewGPListener* listener = m_listener;
ModalDialog::dismiss();
if (listener != NULL)
listener->onNewGPWithName(name);
}
}

View File

@ -0,0 +1,70 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 Marc Coll
//
// 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_ENTER_GP_NAME_DIALOG_HPP
#define HEADER_ENTER_GP_NAME_DIALOG_HPP
#include "guiengine/modaldialog.hpp"
#include <irrString.h>
namespace GUIEngine
{
class TextBoxWidget;
class ButtonWidget;
class LabelWidget;
}
/**
* \brief Dialog that allows the player to enter the name for a new grand prix
* \ingroup states_screens
*/
class EnterGPNameDialog : public GUIEngine::ModalDialog
{
public:
class INewGPListener
{
public:
virtual void onNewGPWithName(const irr::core::stringw& newName) = 0;
virtual ~INewGPListener(){}
};
private:
INewGPListener* m_listener;
bool m_self_destroy;
public:
/**
* Creates a modal dialog with given percentage of screen width and height
*/
EnterGPNameDialog(INewGPListener* listener, const float percentWidth,
const float percentHeight);
~EnterGPNameDialog();
void onEnterPressedInternal();
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
virtual void onUpdate(float dt);
};
#endif

View File

@ -278,6 +278,24 @@ void UserInfoDialog::declineFriendRequest()
} // declineFriendRequest
// -----------------------------------------------------------------------------
/** Removes an existing friend.
*/
void UserInfoDialog::removeExistingFriend()
{
CurrentUser::get()->requestRemoveFriend(m_profile->getID());
} // removeExistingFriend
// -----------------------------------------------------------------------------
/** Removes a pending friend request.
*/
void UserInfoDialog::removePendingFriend()
{
CurrentUser::get()->requestCancelFriend(m_profile->getID());
} // removePendingFriend
// -----------------------------------------------------------------------------
GUIEngine::EventPropagation UserInfoDialog::processEvent(const std::string& eventSource)
{
@ -304,10 +322,12 @@ GUIEngine::EventPropagation UserInfoDialog::processEvent(const std::string& even
}
else if(selection == m_remove_widget->m_properties[PROP_ID])
{
if(m_profile->getRelationInfo()->isPending())
CurrentUser::get()->requestCancelFriend(m_profile->getID());
if (m_profile->getRelationInfo() &&
m_profile->getRelationInfo()->isPending() )
removePendingFriend();
else
CurrentUser::get()->requestRemoveFriend(m_profile->getID());
removeExistingFriend();
m_processing = true;
m_options_widget->setDeactivated();
return GUIEngine::EVENT_BLOCK;

View File

@ -63,6 +63,8 @@ private:
void sendFriendRequest();
void acceptFriendRequest();
void declineFriendRequest();
void removeExistingFriend();
void removePendingFriend();
public:
UserInfoDialog(uint32_t showing_id, const core::stringw info = "", bool error = false, bool from_queue = false);

View File

@ -0,0 +1,334 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 Marc Coll
//
// 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/edit_gp_screen.hpp"
#include "graphics/irr_driver.hpp"
#include "guiengine/CGUISpriteBank.h"
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "race/grand_prix_data.hpp"
#include "states_screens/edit_track_screen.hpp"
#include "states_screens/state_manager.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
using namespace GUIEngine;
DEFINE_SCREEN_SINGLETON( EditGPScreen );
// -----------------------------------------------------------------------------
EditGPScreen::EditGPScreen()
: Screen("gpedit.stkgui"), m_gp(NULL), m_list(NULL), m_icon_bank(NULL),
m_selected(-1), m_modified(false)
{
}
// -----------------------------------------------------------------------------
EditGPScreen::~EditGPScreen()
{
delete m_icon_bank;
}
// -----------------------------------------------------------------------------
void EditGPScreen::setSelectedGP(GrandPrixData* gp)
{
assert(gp != NULL);
m_gp = gp;
}
// -----------------------------------------------------------------------------
void EditGPScreen::loadedFromFile()
{
if (m_icon_bank == NULL)
m_icon_bank = new irr::gui::STKModifiedSpriteBank(GUIEngine::getGUIEnv());
m_list = getWidget<ListWidget>("tracks");
assert(m_list != NULL);
m_list->addColumn(_("Track"), 3);
m_list->addColumn(_("Laps"), 1);
m_list->addColumn(_("Reversed"), 1);
}
// -----------------------------------------------------------------------------
void EditGPScreen::eventCallback(GUIEngine::Widget* widget, const std::string& name,
const int playerID)
{
setSelected(m_list->getSelectionID());
if (name == "tracks")
{
m_action = "edit";
edit();
}
else if (name == "menu")
{
RibbonWidget* menu = getWidget<RibbonWidget>("menu");
assert(menu != NULL);
m_action = menu->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (m_action == "up")
{
if (canMoveUp())
{
m_gp->moveUp(m_selected--);
loadList(m_selected);
setModified(true);
}
}
else if (m_action == "down")
{
if (canMoveDown())
{
m_gp->moveDown(m_selected++);
loadList(m_selected);
setModified(true);
}
}
else if (m_action == "add" || m_action == "edit")
{
if (m_action == "edit")
{
edit();
}
else
{
EditTrackScreen* edit = EditTrackScreen::getInstance();
assert(edit != NULL);
//By default, 3 laps and no reversing
edit->setSelection(NULL, 3, false);
StateManager::get()->pushScreen(edit);
}
}
else if (m_action == "remove")
{
if (m_selected >= 0 && m_selected < m_list->getItemCount())
{
new MessageDialog(
_("Are you sure you want to remove '%s'?",
m_gp->getTrackName(m_selected).c_str()),
MessageDialog::MESSAGE_DIALOG_CONFIRM,
this, false);
}
}
else if (m_action == "save")
{
save();
}
}
else if (name == "back")
{
if (m_modified)
{
m_action = "back";
new MessageDialog(
_("Do you want to save your changes?"),
MessageDialog::MESSAGE_DIALOG_CONFIRM,
this, false);
}
else
{
back();
}
}
}
// -----------------------------------------------------------------------------
void EditGPScreen::init()
{
if (m_action.empty())
{
LabelWidget* header = getWidget<LabelWidget>("title");
assert(header != NULL);
header->setText(m_gp->getName(), true);
IconButtonWidget* button = getWidget<IconButtonWidget>("save");
assert(button != NULL);
button->setDeactivated();
loadList(0);
setModified(false);
}
else
{
EditTrackScreen* edit = EditTrackScreen::getInstance();
assert(edit != NULL);
if (edit->getResult())
{
if (m_action == "add")
{
m_gp->addTrack(edit->getTrack(), edit->getLaps(), edit->getReverse(),
m_selected);
setSelected(m_selected + 1);
}
else if (m_action == "edit")
{
m_gp->editTrack(m_selected, edit->getTrack(), edit->getLaps(),
edit->getReverse());
}
setModified(true);
}
loadList(m_selected);
m_action.clear();
}
}
// -----------------------------------------------------------------------------
void EditGPScreen::onConfirm()
{
ModalDialog::dismiss();
if (m_action == "remove")
{
m_gp->remove(m_selected);
setSelected(m_selected >= m_gp->getNumberOfTracks() ?
m_gp->getNumberOfTracks() - 1 : m_selected);
loadList(m_selected);
setModified(true);
}
else if (m_action == "back")
{
save();
back();
}
}
// -----------------------------------------------------------------------------
void EditGPScreen::onCancel()
{
ModalDialog::dismiss();
if (m_action == "back")
back();
}
// -----------------------------------------------------------------------------
void EditGPScreen::loadList(const int selected)
{
m_list->clear();
m_icons.clear();
m_icon_bank->clear();
m_icon_bank->scaleToHeight (64);
m_list->setIcons(m_icon_bank, 64);
for (unsigned int i = 0; i < m_gp->getNumberOfTracks(); i++)
{
std::vector<GUIEngine::ListWidget::ListCell> row;
Track* t = track_manager->getTrack(m_gp->getTrackId(i));
assert(t != NULL);
video::ITexture* screenShot = irr_driver->getTexture(t->getScreenshotFile());
assert(screenShot != NULL);
m_icons.push_back(m_icon_bank->addTextureAsSprite(screenShot));
row.push_back(GUIEngine::ListWidget::ListCell(
_LTR(m_gp->getTrackName(i).c_str()), m_icons[i], 3, false));
row.push_back(GUIEngine::ListWidget::ListCell(
StringUtils::toWString<unsigned int>(m_gp->getLaps(i)), -1, 1, true));
row.push_back(GUIEngine::ListWidget::ListCell(
m_gp->getReverse(i) ? _("Yes") : _("No"), -1, 1, true));
m_list->addItem(m_gp->getId(), row);
}
m_list->setIcons(m_icon_bank);
if (selected < m_list->getItemCount())
{
m_list->setSelectionID(selected);
setSelected(selected);
}
}
// -----------------------------------------------------------------------------
void EditGPScreen::setModified(const bool modified)
{
m_modified = modified;
IconButtonWidget* save_button = getWidget<IconButtonWidget>("save");
assert(save_button != NULL);
if (modified)
save_button->setActivated();
else
save_button->setDeactivated();
}
// -----------------------------------------------------------------------------
void EditGPScreen::setSelected(const int selected)
{
IconButtonWidget* button_up = getWidget<IconButtonWidget>("up");
assert(button_up != NULL);
IconButtonWidget* button_down = getWidget<IconButtonWidget>("down");
assert(button_down != NULL);
m_selected = selected;
}
// -----------------------------------------------------------------------------
void EditGPScreen::edit()
{
EditTrackScreen* edit_screen = EditTrackScreen::getInstance();
assert(edit_screen != NULL);
if (m_selected >= 0 && m_selected < m_list->getItemCount())
{
edit_screen->setSelection(track_manager->getTrack(
m_gp->getTrackId(m_selected)),
m_gp->getLaps(m_selected),
m_gp->getReverse(m_selected));
StateManager::get()->pushScreen(edit_screen);
}
}
// -----------------------------------------------------------------------------
bool EditGPScreen::save()
{
if (m_gp->writeToFile())
{
setModified(false);
return true;
}
else
{
new MessageDialog(
_("An error occurred while trying to save your grand prix"),
MessageDialog::MESSAGE_DIALOG_OK, NULL, false);
return false;
}
}
// -----------------------------------------------------------------------------
void EditGPScreen::back ()
{
m_action.clear();
m_modified = false;
StateManager::get()->popMenu();
}
// -----------------------------------------------------------------------------
bool EditGPScreen::canMoveUp() const
{
return (m_selected > 0 && m_selected < m_list->getItemCount());
}
// -----------------------------------------------------------------------------
bool EditGPScreen::canMoveDown() const
{
return (m_selected >= 0 && m_selected < (m_list->getItemCount() - 1));
}

View File

@ -0,0 +1,85 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 Marc Coll
//
// 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_EDIT_GP_SCREEN_HPP
#define HEADER_EDIT_GP_SCREEN_HPP
#include "guiengine/screen.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include <vector>
namespace GUIEngine { class Widget; }
namespace irr { namespace gui { class STKModifiedSpriteBank; } }
class GrandPrixData;
/**
* \brief screen where the user can edit a grand prix
* \ingroup states_screens
*/
class EditGPScreen :
public GUIEngine::Screen,
public GUIEngine::ScreenSingleton<EditGPScreen>,
public MessageDialog::IConfirmDialogListener
{
friend class GUIEngine::ScreenSingleton<EditGPScreen>;
EditGPScreen();
void onConfirm();
void onCancel();
void loadList(const int selected);
void setModified(const bool modified);
void setSelected(const int selected);
void edit();
bool save();
void back();
bool canMoveUp() const;
bool canMoveDown() const;
GrandPrixData* m_gp;
GUIEngine::ListWidget* m_list;
irr::gui::STKModifiedSpriteBank* m_icon_bank;
std::vector<int> m_icons;
int m_selected;
bool m_modified;
std::string m_action;
public:
~EditGPScreen();
void setSelectedGP(GrandPrixData* gp);
/** \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 implement callback from parent class GUIEngine::Screen */
virtual void init() OVERRIDE;
};
#endif

View File

@ -0,0 +1,240 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 Marc Coll
//
// 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/edit_track_screen.hpp"
#include "guiengine/widgets/button_widget.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/spinner_widget.hpp"
#include "states_screens/state_manager.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
using namespace GUIEngine;
using namespace irr::core;
const char* EditTrackScreen::ALL_TRACKS_GROUP_ID = "all";
DEFINE_SCREEN_SINGLETON( EditTrackScreen );
// -----------------------------------------------------------------------------
EditTrackScreen::EditTrackScreen()
: Screen("edit_track.stkgui"), m_track_group(ALL_TRACKS_GROUP_ID),
m_track(NULL), m_laps(0), m_reverse(false), m_result(false)
{
}
// -----------------------------------------------------------------------------
EditTrackScreen::~EditTrackScreen()
{
}
// -----------------------------------------------------------------------------
void EditTrackScreen::setSelection(Track* track, unsigned int laps, bool reverse)
{
assert(laps > 0);
m_track = track;
m_laps = laps;
m_reverse = reverse;
}
// -----------------------------------------------------------------------------
Track* EditTrackScreen::getTrack() const
{
return m_track;
}
// -----------------------------------------------------------------------------
unsigned int EditTrackScreen::getLaps() const
{
return m_laps;
}
// -----------------------------------------------------------------------------
bool EditTrackScreen::getReverse() const
{
return m_reverse;
}
// -----------------------------------------------------------------------------
bool EditTrackScreen::getResult() const
{
return m_result;
}
// -----------------------------------------------------------------------------
void EditTrackScreen::loadedFromFile()
{
}
// -----------------------------------------------------------------------------
void EditTrackScreen::eventCallback(GUIEngine::Widget* widget, const std::string& name,
const int playerID)
{
if (name == "ok")
{
m_result = true;
StateManager::get()->popMenu();
}
else if (name == "cancel")
{
m_result = false;
StateManager::get()->popMenu();
}
else if (name == "tracks")
{
DynamicRibbonWidget* tracks = getWidget<DynamicRibbonWidget>("tracks");
assert(tracks != NULL);
selectTrack(tracks->getSelectionIDString(PLAYER_ID_GAME_MASTER));
}
else if (name == "trackgroups")
{
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
assert(tabs != NULL);
m_track_group = tabs->getSelectionIDString(PLAYER_ID_GAME_MASTER);
loadTrackList();
}
else if (name == "laps")
{
SpinnerWidget* laps = getWidget<SpinnerWidget>("laps");
assert(laps != NULL);
m_laps = laps->getValue();
}
else if (name == "reverse")
{
CheckBoxWidget* reverse = getWidget<CheckBoxWidget>("reverse");
assert(reverse != NULL);
m_reverse = reverse->getState();
}
}
// -----------------------------------------------------------------------------
void EditTrackScreen::beforeAddingWidget()
{
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
assert (tabs != NULL);
tabs->clearAllChildren();
const std::vector<std::string>& groups = track_manager->getAllTrackGroups();
if (groups.size() > 1)
{
tabs->addTextChild(_("All"), ALL_TRACKS_GROUP_ID);
for (unsigned int i = 0; i < groups.size(); i++)
tabs->addTextChild(_(groups[i].c_str()), groups[i]);
}
}
// -----------------------------------------------------------------------------
void EditTrackScreen::init()
{
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
assert (tabs != NULL);
SpinnerWidget* laps = getWidget<SpinnerWidget>("laps");
assert(laps != NULL);
CheckBoxWidget* reverse = getWidget<CheckBoxWidget>("reverse");
assert(reverse != NULL);
if (m_track_group.empty())
tabs->select (ALL_TRACKS_GROUP_ID, PLAYER_ID_GAME_MASTER);
else
tabs->select (m_track_group, PLAYER_ID_GAME_MASTER);
laps->setValue(m_laps);
reverse->setState(m_reverse);
loadTrackList();
if (m_track == NULL)
selectTrack("");
else
selectTrack(m_track->getIdent());
}
// -----------------------------------------------------------------------------
void EditTrackScreen::loadTrackList()
{
bool belongsToGroup;
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
assert(tracks_widget != NULL);
tracks_widget->clearItems();
for (unsigned int i = 0; i < track_manager->getNumberOfTracks(); i++)
{
Track* t = track_manager->getTrack(i);
const std::vector<std::string>& groups = t->getGroups();
belongsToGroup = (m_track_group.empty() || m_track_group == ALL_TRACKS_GROUP_ID ||
std::find(groups.begin(), groups.end(), m_track_group) != groups.end());
if (!t->isArena() && !t->isSoccer() && !t->isInternal() && belongsToGroup)
{
tracks_widget->addItem(translations->fribidize(t->getName()), t->getIdent(),
t->getScreenshotFile(), 0, IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE );
}
}
tracks_widget->updateItemDisplay();
}
// -----------------------------------------------------------------------------
void EditTrackScreen::selectTrack(const std::string& id)
{
DynamicRibbonWidget* tracks = getWidget<DynamicRibbonWidget>("tracks");
assert(tracks != NULL);
LabelWidget* selected_track = getWidget<LabelWidget>("selected_track");
assert(selected_track != NULL);
SpinnerWidget* laps = getWidget<SpinnerWidget>("laps");
assert(laps != NULL);
LabelWidget* label_reverse = getWidget<LabelWidget>("reverse_label");
assert(label_reverse != NULL);
CheckBoxWidget* reverse = getWidget<CheckBoxWidget>("reverse");
assert(reverse != NULL);
ButtonWidget* ok_button = getWidget<ButtonWidget>("ok");
assert(ok_button != NULL);
m_track = track_manager->getTrack(id);
if (m_track != NULL)
{
tracks->setSelection(m_track->getIdent(), PLAYER_ID_GAME_MASTER, true);
selected_track->setText(m_track->getName(), true);
laps->setValue(m_laps);
reverse->setVisible(m_track->reverseAvailable());
label_reverse->setVisible(m_track->reverseAvailable());
ok_button->setActivated();
}
else
{
tracks->setSelection("", PLAYER_ID_GAME_MASTER, true);
selected_track->setText(_("Select a track"), true);
laps->setValue(3);
reverse->setVisible(true);
reverse->setState(false);
ok_button->setDeactivated();
}
}

Some files were not shown because too many files have changed in this diff Show More