Merge remote-tracking branch 'origin/master' into perPlayerDifficulties, this time the right branch...

Conflicts:
	data/gui/user_screen.stkgui
	data/gui/user_screen_tab.stkgui
	src/graphics/glwrap.cpp
	src/graphics/weather.cpp
	src/states_screens/user_screen.cpp
This commit is contained in:
Flakebi 2014-10-20 22:36:54 +02:00
commit 57afd1d585
149 changed files with 2795 additions and 1775 deletions

View File

@ -10,7 +10,7 @@
* Added Tutorial
* Added new Supertux difficulty
* New bubblegum shield weapon
* New Speeodmeter and nitro meter
* New Speedometer and nitro meter
* Add ability to filter addons
* Updated nitro models
* Add ability to save and resume Grand Prix

View File

@ -87,11 +87,7 @@ if(WIN32)
set(ENV{PATH} "$ENV{PATH};${PROJECT_SOURCE_DIR}/dependencies/include")
set(ENV{LIB} ${PROJECT_SOURCE_DIR}/dependencies/lib)
set(ENV{OPENALDIR} ${PROJECT_SOURCE_DIR}/dependencies)
if(MSVC)
add_definitions(/D_IRR_STATIC_LIB_)
elseif(MINGW)
add_definitions(-D_IRR_STATIC_LIB_)
endif()
add_definitions(-D_IRR_STATIC_LIB_)
endif()
@ -149,7 +145,7 @@ endif()
if(UNIX OR MINGW)
# if(USE_CPP2011)
add_definitions("-std=gnu++0x")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
# endif()
endif()
@ -172,7 +168,7 @@ endif()
# Set some compiler options
if(UNIX OR MINGW)
add_definitions(-Wall)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif()
if(WIN32)
@ -200,7 +196,7 @@ endif()
# TODO: remove this switch
add_definitions(-DHAVE_OGGVORBIS)
if(WIN32 AND NOT MINGW)
if(WIN32)
configure_file("${STK_SOURCE_DIR}/windows_installer/icon_rc.template" "${PROJECT_BINARY_DIR}/tmp/icon.rc")
endif()
@ -291,8 +287,7 @@ if(UNIX AND NOT APPLE)
target_link_libraries(supertuxkart ${IRRLICHT_XF86VM_LIBRARY})
endif()
if(USE_ASAN)
add_definitions("-fsanitize=address")
add_definitions("-fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
target_link_libraries(supertuxkart "-fsanitize=address")
endif()
endif()
@ -318,11 +313,7 @@ if(USE_WIIUSE)
find_library(BLUETOOTH_LIBRARY NAMES IOBluetooth PATHS /Developer/Library/Frameworks/IOBluetooth.framework)
target_link_libraries(supertuxkart wiiuse ${BLUETOOTH_LIBRARY})
elseif(WIN32)
if(MSVC)
add_definitions("/DWIIUSE_STATIC")
else()
add_definitions("-DWIIUSE_STATIC")
endif()
add_definitions(-DWIIUSE_STATIC)
if(WIIUSE_BUILD)
target_link_libraries(supertuxkart wiiuse)
else()

View File

@ -48,4 +48,8 @@
title="Banana Lover" description="Collect at least 5 bananas in one race.">
<banana goal="5"/>
</achievement>
<achievement id="10" secret="yes" check-type="all-at-least" reset-type="race"
title="It's secret" description="Really ... a secret.">
</achievement>
</achievements>

View File

@ -1,22 +1,22 @@
<?xml version="1.0"?>
<materials>
<!-- Fonts -->
<material name="title_font.png" shader="unlit"/>
<material name="title_font_2.png" shader="unlit"/>
<material name="sigmar0.png" shader="unlit"/>
<material name="AR_PL_SungtiL_GB0.png" shader="unlit"/>
<material name="comix.png" shader="unlit"/>
<material name="LayneHansom0.png" shader="unlit"/>
<material name="LayneHansomBigDigits.png" shader="unlit"/>
<material name="Mplus2p_JP0.png" shader="unlit"/>
<material name="rasheeq0.png" shader="unlit"/>
<material name="rasheeq3.png" shader="unlit"/>
<material name="rasheeq4.png" shader="unlit"/>
<material name="wqyMicroHei0.png" shader="unlit"/>
<material name="wqyMicroHei1.png" shader="unlit"/>
<material name="wqyMicroHei2.png" shader="unlit"/>
<material name="wqyMicroHei3.png" shader="unlit"/>
<material name="wqyMicroHei4.png" shader="unlit"/>
<material name="wqyMicroHei5.png" shader="unlit"/>
<material name="title_font.png" shader="unlit" lazy-load="Y"/>
<material name="title_font_2.png" shader="unlit" lazy-load="Y"/>
<material name="sigmar0.png" shader="unlit" lazy-load="Y"/>
<material name="comix.png" shader="unlit" lazy-load="Y"/>
<material name="LayneHansom0.png" shader="unlit" lazy-load="Y"/>
<material name="Mplus2p_JP0.png" shader="unlit" lazy-load="Y"/>
<material name="rasheeq0.png" shader="unlit" lazy-load="Y"/>
<material name="rasheeq3.png" shader="unlit" lazy-load="Y"/>
<material name="rasheeq4.png" shader="unlit" lazy-load="Y"/>
<material name="wqyMicroHei0.png" shader="unlit" lazy-load="Y"/>
<material name="wqyMicroHei1.png" shader="unlit" lazy-load="Y"/>
<material name="wqyMicroHei2.png" shader="unlit" lazy-load="Y"/>
<material name="wqyMicroHei3.png" shader="unlit" lazy-load="Y"/>
<material name="wqyMicroHei4.png" shader="unlit" lazy-load="Y"/>
<material name="wqyMicroHei5.png" shader="unlit" lazy-load="Y"/>
<material name="AR_PL_SungtiL_GB0.png" shader="unlit" lazy-load="Y"/>
<material name="LayneHansomBigDigits.png" shader="unlit" lazy-load="Y"/>
</materials>

View File

@ -8,6 +8,8 @@
<button id="assignEsc" I18N="When configuring input" text="Assign to ESC key" align="center"/>
<spacer height="10" width="10" />
<button id="assignNone" I18N="When configuring input" text="Assign nothing" align="center"/>
<spacer height="10" width="10" />
<button id="cancel" I18N="When configuring input" text="Press ESC to cancel" align="center"/>
</div>

View File

@ -2,7 +2,7 @@
<stkgui>
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
<header id="title" width="80%" text="Race Setup" align="center" text_align="center" />
<header id="title" width="100%" text="Race Setup" align="center" text_align="center" />
<spacer height="2%" width="1"/>

View File

@ -15,42 +15,32 @@
<spacer height="15" width="10"/>
<div width="90%" align="center" layout="vertical-row" height="fit">
<div width="100%" height="fit" layout="horizontal-row" >
<gauge id="difficulty" min_value="0" max_value="4" width="300" align="center" />
<checkbox width="fit" id="online" I18N="In the user screen" text_align="left"/>
<spacer width="10"/>
<label id="label_difficulty" height="100%" text_align="left" I18N="In the user screen" text="Multiplayer Boost/Handicap"/>
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<checkbox id="singleplayer-difficulty" I18N="In the user screen" text_align="left"/>
<checkbox width="fit" id="remember-user" I18N="In the login screen" text_align="left"/>
<spacer width="10"/>
<label id="label_singleplayer-difficulty" height="100%" text_align="left" I18N="In the user screen" text="Apply Boost/Handicap in singleplayer too"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<checkbox id="online" I18N="In the login screen" text_align="left"/>
<spacer width="10"/>
<label height="100%" text_align="left" I18N="In the login screen" text="Online"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<checkbox id="remember-user" I18N="In the login screen" text_align="left"/>
<spacer width="10"/>
<label id="label_remember" height="100%" text_align="left"
<label proportion="1" id="label_remember" height="100%" text_align="left"
I18N="In the login screen" text="Remember password"/>
</div>
<!-- Disable guest accounts for now
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_guest" proportion="1" height="100%" text_align="left"
<label width="40%" id="label_guest" height="100%" text_align="left"
I18N="In the user screen" text="Guest login"/>
<checkbox id="guest" I18N="In the user screen" text_align="left"/>
</div>
-->
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_username" proportion="1" height="100%" text_align="left"
<label width="40%" id="label_username" height="100%" text_align="left"
I18N="In the user screen" text="Username"/>
<textbox id="username" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_password" proportion="1" height="100%" text_align="left"
<label id="label_password" width="40%" height="100%" text_align="left"
I18N="In the registration dialog" text="Password"/>
<textbox id="password" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
@ -66,9 +56,7 @@
I18N="Login dialog" text="Add user" label_location="bottom"/>
<icon-button id="delete" width="64" height="64" icon="gui/remove.png"
I18N="Login dialog" text="Delete" label_location="bottom"/>
<icon-button id="recover" width="64" height="64" icon="gui/main_options.png"
I18N="Login dialog" text="Recovery" label_location="bottom"/>
<icon-button id="rename" width="64" height="64" icon="gui/rename.png"
<icon-button id="rename" width="64" height="64" icon="gui/gp_rename.png"
I18N="Login dialog" text="Rename" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Login dialog" text="Cancel" label_location="bottom"/>

View File

@ -16,30 +16,22 @@
<box proportion="1" width="100%" layout="vertical-row">
<spacer height="15" width="10"/>
<scrollable_ribbon id="players" height="120" y="10" x="10" width="98%" align="center" label_location="each"
square_items="true" child_width="128" child_height="128" />
<spacer height="5" width="10"/>
<spacer height="15" width="10"/>
<div width="90%" align="center" layout="vertical-row" height="fit">
<div width="100%" height="fit" layout="horizontal-row" >
<gauge id="difficulty" min_value="0" max_value="4" width="300" align="center" />
<checkbox width="fit" id="online" I18N="In the login screen" text_align="left"/>
<spacer width="10"/>
<label id="label_difficulty" height="100%" text_align="left" I18N="In the user screen" text="Multiplayer Boost/Handicap"/>
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<checkbox id="singleplayer-difficulty" I18N="In the user screen" text_align="left"/>
<checkbox width="fit" id="remember-user" I18N="In the login screen" text_align="left"/>
<spacer width="10"/>
<label id="label_singleplayer-difficulty" height="100%" text_align="left" I18N="In the user screen" text="Apply Boost/Handicap in singleplayer too"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<checkbox id="online" I18N="In the user screen" text_align="left"/>
<spacer width="10"/>
<label height="100%" text_align="left" I18N="In the user screen" text="Online"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<checkbox id="remember-user" I18N="In the user screen" text_align="left"/>
<spacer width="10"/>
<label id="label_remember" height="100%" text_align="left"
<label id="label_remember" proportion="1" height="100%" text_align="left"
I18N="In the user screen" text="Remember password"/>
</div>
<!-- Disable guest accounts for now
@ -50,14 +42,14 @@
</div>
-->
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_username" proportion="1" height="100%" text_align="left"
<label id="label_username" width="40%" height="100%" text_align="left"
I18N="In the user screen" text="Username"/>
<textbox id="username" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
<spacer height="5" width="20"/>
<spacer height="20" width="20"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_password" proportion="1" height="100%" text_align="left"
<label id="label_password" width="40%" height="100%" text_align="left"
I18N="In the registration dialog" text="Password"/>
<textbox id="password" proportion="2" height="fit" I18N="In the registration dialog"/>
</div>
@ -65,6 +57,7 @@
<div width="80%" align="center" layout="vertical-row" height="fit">
<label id="message" width="80%" align="center" text_align="left"/>
</div>
<spacer width="20" height="25"/>
<buttonbar id="options" width="90%" height="13%" align="center">
<icon-button id="ok" width="64" height="64" icon="gui/green_check.png"
I18N="Login dialog" text="OK" label_location="bottom"/>

View File

@ -14,5 +14,5 @@ void main()
Yxy.x = smoothstep(WhiteYxy.x, WhiteYxy.x * 4, Yxy.x);
FragColor = vec4(getRGBFromCIEXxy(Yxy), 1.0);
FragColor = vec4(max(vec3(0.), getRGBFromCIEXxy(Yxy)), 1.0);
}

View File

@ -1,9 +1,11 @@
#ifdef GL_ARB_bindless_texture
layout(bindless_sampler) uniform sampler2D Albedo;
layout(bindless_sampler) uniform sampler2D Detail;
layout(bindless_sampler) uniform sampler2D SpecMap;
#else
uniform sampler2D Albedo;
uniform sampler2D Detail;
uniform sampler2D SpecMap;
#endif
#if __VERSION__ >= 130
@ -16,7 +18,7 @@ varying vec2 uv_bis;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
@ -28,6 +30,6 @@ void main(void)
#endif
vec4 detail = texture(Detail, uv_bis);
color *= detail;
vec3 LightFactor = getLightFactor(1. - color.a);
FragColor = vec4(color.xyz * LightFactor, 1.);
float specmap = texture(SpecMap, uv).g;
FragColor = vec4(getLightFactor(color.xyz, vec3(1.), specmap), 1.);
}

View File

@ -2,11 +2,15 @@ uniform float blueLmn[9];
uniform float greenLmn[9];
uniform float redLmn[9];
uniform sampler2D ntex;
uniform sampler2D dtex;
uniform samplerCube tex;
uniform mat4 TransposeViewMatrix;
out vec4 Diff;
out vec4 Spec;
vec3 DecodeNormal(vec2 n);
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
mat4 getMatrix(float L[9])
{
@ -24,8 +28,9 @@ void main(void)
{
vec2 uv = gl_FragCoord.xy / screen;
vec3 normal = normalize(DecodeNormal(2. * texture(ntex, uv).xy - 1.));
// Convert normal in world space (where SH coordinates were computed)
vec4 extendednormal = TransposeViewMatrix * vec4(normal, 1.);
vec4 extendednormal = TransposeViewMatrix * vec4(normal, 0.);
extendednormal.w = 1.;
mat4 rmat = getMatrix(redLmn);
mat4 gmat = getMatrix(greenLmn);
@ -36,4 +41,16 @@ void main(void)
float b = dot(extendednormal, bmat * extendednormal);
Diff = max(0.25 * vec4(r, g, b, .1), vec4(0.));
float z = texture(dtex, uv).x;
vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix);
vec3 eyedir = -normalize(xpos.xyz);
vec3 sampleDirection = reflect(-eyedir, normal);
sampleDirection = (InverseViewMatrix * vec4(sampleDirection, 0.)).xyz;
float specval = texture(ntex, uv).z;
float lodval = 16 * (1. - ((log2(specval) - 1.) / 10.));
vec4 specular = textureLod(tex, sampleDirection, lodval);
Spec = max(specular, vec4(0.));
}

View File

@ -1,9 +1,11 @@
#ifdef GL_ARB_bindless_texture
layout(bindless_sampler) uniform sampler2D Albedo;
layout(bindless_sampler) uniform sampler2D dtex;
layout(bindless_sampler) uniform sampler2D SpecMap;
#else
uniform sampler2D Albedo;
uniform sampler2D dtex;
uniform sampler2D SpecMap;
#endif
uniform vec3 SunDir;
@ -12,10 +14,18 @@ in vec3 nor;
in vec2 uv;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
vec4 color = texture(Albedo, uv);
#ifdef GL_ARB_bindless_texture
#ifdef SRGBBindlessFix
color.xyz = pow(color.xyz, vec3(2.2));
#endif
#endif
if (color.a < 0.5) discard;
vec2 texc = gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
@ -30,14 +40,8 @@ void main(void)
float fLdotNBack = max(0., - dot(nor, SunDir) * 0.6 + 0.4);
float scattering = mix(fPowEdotL, fLdotNBack, .5);
float specmap = texture(SpecMap, uv).g;
vec4 color = texture(Albedo, uv);
#ifdef GL_ARB_bindless_texture
#ifdef SRGBBindlessFix
color.xyz = pow(color.xyz, vec3(2.2));
#endif
#endif
if (color.a < 0.5) discard;
vec3 LightFactor = (scattering * 0.3) + getLightFactor(1.);
vec3 LightFactor = color.xyz * (scattering * 0.3) + getLightFactor(color.xyz, vec3(1.), specmap);
FragColor = vec4(color.xyz * LightFactor, 1.);
}

View File

@ -1,22 +1,25 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D Albedo;
uniform sampler2D Detail;
uniform sampler2D SpecMap;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
flat in sampler2D secondhandle;
flat in sampler2D thirdhandle;
#endif
in vec2 uv;
in vec2 uv_bis;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 color = texture(handle, uv);
float specmap = texture(secondhandle, uv).g;
#ifdef SRGBBindlessFix
color.xyz = pow(color.xyz, vec3(2.2));
#endif
@ -24,8 +27,8 @@ void main(void)
#else
vec4 color = texture(Albedo, uv);
vec4 detail = texture(Detail, uv_bis);
float specmap = texture(SpecMap, uv).g;
#endif
color *= detail;
vec3 LightFactor = getLightFactor(1. - color.a);
FragColor = vec4(color.xyz * LightFactor, 1.);
FragColor = vec4(getLightFactor(color.xyz, vec3(1.), specmap), 1.);
}

View File

@ -11,6 +11,7 @@ layout(location = 8) in vec3 Orientation;
layout(location = 9) in vec3 Scale;
#ifdef GL_ARB_bindless_texture
layout(location = 10) in sampler2D Handle;
layout(location = 11) in sampler2D SecondHandle;
#endif
#else
@ -28,6 +29,7 @@ out vec3 nor;
out vec2 uv;
#ifdef GL_ARB_bindless_texture
flat out sampler2D handle;
flat out sampler2D secondhandle;
#endif
mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale);
@ -42,5 +44,6 @@ void main()
uv = Texcoord;
#ifdef GL_ARB_bindless_texture
handle = Handle;
secondhandle = SecondHandle;
#endif
}

View File

@ -2,6 +2,7 @@
layout(bindless_sampler) uniform sampler2D dtex;
#else
uniform sampler2D Albedo;
uniform sampler2D SpecMap;
uniform sampler2D dtex;
#endif
@ -9,15 +10,28 @@ uniform vec3 SunDir;
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
flat in sampler2D secondhandle;
#endif
in vec3 nor;
in vec2 uv;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 color = texture(handle, uv);
float specmap = texture(secondhandle, uv).g;
#ifdef SRGBBindlessFix
color.xyz = pow(color.xyz, vec3(2.2));
#endif
#else
vec4 color = texture(Albedo, uv);
float specmap = texture(SpecMap, uv).g;
#endif
if (color.a < 0.5) discard;
vec2 texc = gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
@ -33,15 +47,7 @@ void main(void)
float fLdotNBack = max(0., - dot(nor, SunDir) * 0.6 + 0.4);
float scattering = mix(fPowEdotL, fLdotNBack, .5);
#ifdef GL_ARB_bindless_texture
vec4 color = texture(handle, uv);
#ifdef SRGBBindlessFix
color.xyz = pow(color.xyz, vec3(2.2));
#endif
#else
vec4 color = texture(Albedo, uv);
#endif
if (color.a < 0.5) discard;
vec3 LightFactor = (scattering * 0.3) + getLightFactor(1.);
FragColor = vec4(color.xyz * LightFactor, 1.);
vec3 LightFactor = color.xyz * (scattering * 0.3) + getLightFactor(color.xyz, vec3(1.), specmap);
FragColor = vec4(LightFactor, 1.);
}

View File

@ -1,27 +1,30 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D Albedo;
uniform sampler2D SpecMap;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
flat in sampler2D secondhandle;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 col = texture(handle, uv);
float specmap = texture(secondhandle, uv).g;
#ifdef SRGBBindlessFix
col.xyz = pow(col.xyz, vec3(2.2));
#endif
#else
vec4 col = texture(Albedo, uv);
float specmap = texture(SpecMap, uv).g;
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(col.xyz * LightFactor, 1.);
FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap), 1.);
}

View File

@ -12,7 +12,7 @@ out vec4 FragColor;
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main() {
vec3 texc = gl_FragCoord.xyz / vec3(screen, 1.);
@ -29,7 +29,6 @@ void main() {
#else
vec4 detail0 = texture(tex, r.xy / m + .5);
#endif
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(detail0.xyz * LightFactor, 1.);
FragColor = vec4(getLightFactor(detail0.xyz, vec3(1.), 0.), 1.);
}

View File

@ -1,28 +1,31 @@
#ifndef GL_ARB_bindless_texture
uniform sampler2D Albedo;
uniform sampler2D SpecMap;
#endif
#ifdef GL_ARB_bindless_texture
flat in sampler2D handle;
flat in sampler2D secondhandle;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
#ifdef GL_ARB_bindless_texture
vec4 col = texture(handle, uv);
float specmap = texture(secondhandle, uv).g;
#ifdef SRGBBindlessFix
col.xyz = pow(col.xyz, vec3(2.2));
#endif
#else
vec4 col = texture(Albedo, uv);
float specmap = texture(SpecMap, uv).g;
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
if (col.a * color.a < 0.5) discard;
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(col.xyz * LightFactor, 1.);
FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap), 1.);
}

View File

@ -1,14 +1,16 @@
#ifdef GL_ARB_bindless_texture
layout(bindless_sampler) uniform sampler2D Albedo;
layout(bindless_sampler) uniform sampler2D SpecMap;
#else
uniform sampler2D Albedo;
uniform sampler2D SpecMap;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
@ -21,6 +23,6 @@ void main(void)
vec4 col = texture(Albedo, uv);
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(col.xyz * LightFactor, 1.);
float specmap = texture(SpecMap, uv).g;
FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap), 1.);
}

View File

@ -15,7 +15,7 @@ varying vec3 nor;
#endif
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main() {
vec3 texc = gl_FragCoord.xyz / vec3(screen, 1.);
@ -30,7 +30,6 @@ void main() {
detail0.xyz = pow(detail0.xyz, vec3(2.2));
#endif
#endif
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(detail0.xyz * LightFactor, 1.);
FragColor = vec4(getLightFactor(detail0.xyz, vec3(1.), 0.), 1.);
}

View File

@ -1,14 +1,16 @@
#ifdef GL_ARB_bindless_texture
layout(bindless_sampler) uniform sampler2D Albedo;
layout(bindless_sampler) uniform sampler2D SpecMap;
#else
uniform sampler2D Albedo;
uniform sampler2D SpecMap;
#endif
in vec2 uv;
in vec4 color;
out vec4 FragColor;
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main(void)
{
@ -20,6 +22,6 @@ void main(void)
#endif
col.xyz *= pow(color.xyz, vec3(2.2));
if (col.a * color.a < 0.5) discard;
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(col.xyz * LightFactor, 1.);
float specmap = texture(SpecMap, uv).g;
FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap), 1.);
}

View File

@ -0,0 +1,30 @@
#if __VERSION__ >= 330
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;
layout(location = 3) in vec2 Texcoord;
layout(location = 4) in vec2 SecondTexcoord;
layout(location = 5) in vec3 Tangent;
layout(location = 6) in vec3 Bitangent;
#else
in vec3 Position;
in vec3 Normal;
in vec4 Color;
in vec2 Texcoord;
in vec2 SecondTexcoord;
in vec3 Tangent;
in vec3 Bitangent;
#endif
out vec2 uv;
out vec4 color;
void main(void)
{
color = Color.zyxw;
vec3 P = Position / vec3(screen, 1.);
P = 2. * P - 1.;
P.y *= -1;
gl_Position = vec4(P, 1.);
uv = Texcoord;
}

View File

@ -9,6 +9,7 @@ uniform mat4 RSMMatrix;
uniform sampler2D dtex;
uniform sampler2D ctex;
uniform sampler2D ntex;
uniform vec3 suncol;
flat in int slice;
layout (location = 0) out vec4 SHRed;
@ -63,7 +64,7 @@ void loop(in int i,
float dotprod = max(dot(RSM_to_RH_dir, normal.xyz), 0.);
float factor = dotprod / (0.1 + dist * dist);
vec3 color = RSMAlbedo.rgb * factor;
vec3 color = RSMAlbedo.rgb * factor * suncol.rgb;
SHr += DirToSh(RSM_to_RH_dir, color.r);
SHg += DirToSh(RSM_to_RH_dir, color.g);

View File

@ -22,7 +22,7 @@ varying vec2 uv_bis;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(float specMapValue);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue);
void main() {
// Splatting part
@ -46,6 +46,5 @@ void main() {
splatting.b * detail2 +
max(0., (1.0 - splatting.r - splatting.g - splatting.b)) * detail3;
vec3 LightFactor = getLightFactor(1.);
FragColor = vec4(splatted.xyz * LightFactor, 1.);
FragColor = vec4(getLightFactor(splatted.xyz, vec3(1.), 0.), 1.);
}

View File

@ -8,12 +8,12 @@ uniform sampler2D SpecularMap;
uniform sampler2D SSAO;
#endif
vec3 getLightFactor(float specMapValue)
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, 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 = DiffuseComponent + SpecularComponent * specMapValue;
vec3 tmp = diffuseMatColor * DiffuseComponent * (1. - specMapValue) + specularMatColor * SpecularComponent * specMapValue;
return tmp * ao;
}

View File

@ -35,6 +35,7 @@ AchievementInfo::AchievementInfo(const XMLNode * input)
m_id = 0;
m_title = "";
m_description = "";
m_is_secret = false;
bool all;
all = input->get("id", &m_id ) &&
input->get("title", &m_title ) &&
@ -69,6 +70,7 @@ AchievementInfo::AchievementInfo(const XMLNode * input)
else
Log::warn("AchievementInfo", "Achievement check type '%s' unknown.",
s.c_str());
input->get("secret", &m_is_secret);
// Now load the goal nodes
for (unsigned int n = 0; n < input->getNumNodes(); n++)

View File

@ -94,6 +94,9 @@ private:
/** Determines when the achievement needs to be reset */
ResetType m_reset_type;
/** A secret achievement has its progress not shown. */
bool m_is_secret;
public:
AchievementInfo(const XMLNode * input);
virtual ~AchievementInfo() {};
@ -119,6 +122,9 @@ public:
/** Returns the check type for this achievement. */
AchievementCheckType getCheckType() const { return m_check_type; }
// ------------------------------------------------------------------------
/** Returns if this achievement is a secret achievement. */
bool isSecret() const { return m_is_secret; }
// ------------------------------------------------------------------------
}; // class AchievementInfo

View File

@ -23,7 +23,6 @@
#include "audio/sfx_base.hpp"
/**
* \brief Dummy sound when ogg or openal aren't available
* \ingroup audio
@ -31,25 +30,35 @@
class DummySFX : public SFXBase
{
public:
DummySFX(SFXBuffer* buffer, bool positional, float gain) {}
DummySFX(SFXBuffer* buffer, bool positional,
float gain) {}
virtual ~DummySFX() {}
/** Late creation, if SFX was initially disabled */
virtual bool init() { return true; }
virtual void position(const Vec3 &position) {}
virtual void setLoop(bool status) {}
virtual void play() {}
virtual void stop() {}
virtual void pause() {}
virtual void resume() {}
virtual void speed(float factor) {}
virtual void volume(float gain) {}
virtual SFXManager::SFXStatus getStatus() { return SFXManager::SFX_STOPPED; }
virtual void onSoundEnabledBack() {}
virtual void setRolloff(float rolloff) {}
virtual const SFXBuffer* getBuffer() const { return NULL; }
virtual bool init() { return true; }
virtual bool isLooped() { return false; }
virtual void updatePlayingSFX(float dt) {}
virtual void setLoop(bool status) {}
virtual void reallySetLoop(bool status) {}
virtual void setPosition(const Vec3 &p) {}
virtual void reallySetPosition(const Vec3 &p) {}
virtual void play() {}
virtual void reallyPlayNow() {}
virtual void stop() {}
virtual void reallyStopNow() {}
virtual void pause() {}
virtual void reallyPauseNow() {}
virtual void resume() {}
virtual void reallyResumeNow() {}
virtual void deleteSFX() { delete this; }
virtual void setSpeed(float factor) {}
virtual void reallySetSpeed(float factor) {}
virtual void setVolume(float gain) {}
virtual void reallySetVolume(float gain) {}
virtual SFXStatus getStatus() { return SFX_STOPPED; }
virtual void onSoundEnabledBack() {}
virtual void setRolloff(float rolloff) {}
virtual const SFXBuffer* getBuffer() const { return NULL; }
}; // DummySFX

View File

@ -42,26 +42,43 @@ class Vec3;
class SFXBase : public NoCopy
{
public:
/** Status of a sound effect. */
enum SFXStatus
{
SFX_UNKNOWN = -1, SFX_STOPPED = 0, SFX_PAUSED = 1, SFX_PLAYING = 2,
SFX_NOT_INITIALISED = 3
};
virtual ~SFXBase() {}
/** Late creation, if SFX was initially disabled */
virtual bool init() = 0;
virtual void position(const Vec3 &position) = 0;
virtual void setLoop(bool status) = 0;
virtual void play() = 0;
virtual void reallyPlayNow() = 0;
virtual void stop() = 0;
virtual void pause() = 0;
virtual void resume() = 0;
virtual void speed(float factor) = 0;
virtual void volume(float gain) = 0;
virtual void setMasterVolume(float gain) = 0;
virtual void onSoundEnabledBack() = 0;
virtual void setRolloff(float rolloff) = 0;
virtual const SFXBuffer* getBuffer() const = 0;
virtual SFXManager::SFXStatus getStatus() = 0;
virtual bool init() = 0;
virtual bool isLooped() = 0;
virtual void updatePlayingSFX(float dt) = 0;
virtual void setPosition(const Vec3 &p) = 0;
virtual void reallySetPosition(const Vec3 &p) = 0;
virtual void setLoop(bool status) = 0;
virtual void reallySetLoop(bool status) = 0;
virtual void play() = 0;
virtual void reallyPlayNow() = 0;
virtual void stop() = 0;
virtual void reallyStopNow() = 0;
virtual void pause() = 0;
virtual void reallyPauseNow() = 0;
virtual void resume() = 0;
virtual void reallyResumeNow() = 0;
virtual void deleteSFX() = 0;
virtual void setSpeed(float factor) = 0;
virtual void reallySetSpeed(float factor) = 0;
virtual void setVolume(float gain) = 0;
virtual void reallySetVolume(float gain) = 0;
virtual void setMasterVolume(float gain) = 0;
virtual void onSoundEnabledBack() = 0;
virtual void setRolloff(float rolloff) = 0;
virtual const SFXBuffer* getBuffer() const = 0;
virtual SFXStatus getStatus() = 0;
}; // SfxBase
}; // SFXBase
#endif // HEADER_SFX_HPP

View File

@ -36,27 +36,37 @@
#endif
//----------------------------------------------------------------------------
/** Creates a sfx. The parameter are taken from the parameters:
* \param file File name of the buffer.
* \param positional If the sfx is positional.
* \param rolloff Rolloff value of this sfx.
* \param max_dist Maximum distance the sfx can be heard.
* \param gain Gain value of this sfx.
*/
SFXBuffer::SFXBuffer(const std::string& file,
bool positional,
float rolloff,
float max_width,
float max_dist,
float gain)
{
m_buffer = 0;
m_gain = 1.0f;
m_rolloff = 0.1f;
m_loaded = false;
m_max_dist = max_width;
m_max_dist = max_dist;
m_duration = -1.0f;
m_file = file;
m_rolloff = rolloff;
m_positional = positional;
m_gain = gain;
}
} // SFXBuffer
//----------------------------------------------------------------------------
/** Constructor getting the sfx parameters from an XML node.
* \param file File name of the data.
* \param node XML Node with the data for this sfx.
*/
SFXBuffer::SFXBuffer(const std::string& file,
const XMLNode* node)
{
@ -64,6 +74,7 @@ SFXBuffer::SFXBuffer(const std::string& file,
m_gain = 1.0f;
m_rolloff = 0.1f;
m_max_dist = 300.0f;
m_duration = -1.0f;
m_positional = false;
m_loaded = false;
m_file = file;
@ -72,10 +83,15 @@ SFXBuffer::SFXBuffer(const std::string& file,
node->get("positional", &m_positional );
node->get("volume", &m_gain );
node->get("max_dist", &m_max_dist );
}
node->get("duration", &m_duration );
} // SFXBuffer(XMLNode)
//----------------------------------------------------------------------------
/** \brief load the buffer from file into OpenAL.
* \note If this buffer is already loaded, this call does nothing and
* returns false.
* \return Whether loading was successful.
*/
bool SFXBuffer::load()
{
if (UserConfigParams::m_sfx == false) return false;
@ -103,9 +119,13 @@ bool SFXBuffer::load()
m_loaded = true;
return true;
}
} // load
//----------------------------------------------------------------------------
/** \brief Frees the loaded buffer.
* Cannot appear in destructor because copy-constructors may be used,
* and the OpenAL source must not be deleted on a copy
*/
void SFXBuffer::unload()
{
@ -117,7 +137,7 @@ void SFXBuffer::unload()
}
#endif
m_loaded = false;
}
} // unload
//----------------------------------------------------------------------------
/** Load a vorbis file into an OpenAL buffer
@ -164,7 +184,7 @@ bool SFXBuffer::loadVorbisBuffer(const std::string &name, ALuint buffer)
if(!data)
{
ov_clear(&oggFile);
Log::error("SFXBuffer", "[SFXBuffer] loadVorbisBuffer() - Error : LoadVorbisBuffer() - couldn't allocate decode buffer\n");
Log::error("SFXBuffer", "[SFXBuffer] Could not allocate decode buffer.");
return false;
}
@ -188,9 +208,21 @@ bool SFXBuffer::loadVorbisBuffer(const std::string &name, ALuint buffer)
ov_clear(&oggFile);
fclose(file);
// Allow the xml data to overwrite the duration, but if there is no
// duration (which is the norm), compute it:
if(m_duration < 0)
{
ALint buffer_size, frequency, bits_per_sample, channels;
alGetBufferi(buffer, AL_SIZE, &buffer_size );
alGetBufferi(buffer, AL_FREQUENCY, &frequency );
alGetBufferi(buffer, AL_CHANNELS, &channels );
alGetBufferi(buffer, AL_BITS, &bits_per_sample);
m_duration = float(buffer_size) / (frequency*channels*(bits_per_sample / 8));
}
return success;
#else
return false;
#endif
}
} // loadVorbisBuffer

View File

@ -46,18 +46,32 @@ class SFXBuffer
{
private:
LEAK_CHECK()
/** Whether the contents of the file was loaded */
bool m_loaded;
/** The file that contains the OGG audio data */
std::string m_file;
/** The openal buffer id. */
ALuint m_buffer;
/** If the sound is positional. */
bool m_positional;
/** The roll-off value. */
float m_rolloff;
/** The volume gain value. */
float m_gain;
/** Maximum distance the sfx can be heard. */
float m_max_dist;
/** Duration of the sfx. */
float m_duration;
bool loadVorbisBuffer(const std::string &name, ALuint buffer);
public:
@ -70,41 +84,43 @@ public:
SFXBuffer(const std::string& file,
const XMLNode* node);
~SFXBuffer()
{
}
} // ~SFXBuffer
/**
* \brief load the buffer from file into OpenAL.
* \note If this buffer is already loaded, this call does nothing and returns false
* \return whether loading was successful
*/
bool load();
/**
* \brief Frees the loaded buffer
* Cannot appear in destructor because copy-constructors may be used,
* and the OpenAL source must not be deleted on a copy
*/
void unload();
bool load();
void unload();
// ------------------------------------------------------------------------
/** \return whether this buffer was loaded from disk */
bool isLoaded() const { return m_loaded; }
bool isLoaded() const { return m_loaded; }
// ------------------------------------------------------------------------
/** Only returns a valid buffer if isLoaded() returned true */
ALuint getBufferID() const { return m_buffer; }
ALuint getBufferID() const { return m_buffer; }
// ------------------------------------------------------------------------
/** Returns if the buffer is positional. */
bool isPositional() const { return m_positional; }
// ------------------------------------------------------------------------
/** Returns the rolloff value of this buffer. */
float getRolloff() const { return m_rolloff; }
// ------------------------------------------------------------------------
/** Returns the gain for this sfx. */
float getGain() const { return m_gain; }
// ------------------------------------------------------------------------
/** Returns the maximum distance this sfx can be heard. */
float getMaxDist() const { return m_max_dist; }
// ------------------------------------------------------------------------
/** Returns the file name of this buffer. */
const std::string& getFileName() const { return m_file; }
// ------------------------------------------------------------------------
/** Sets if this buffer is positional or not. */
void setPositional(bool positional) { m_positional = positional; }
// ------------------------------------------------------------------------
/** Returns how long this buffer will play. */
float getDuration() const { return m_duration; }
bool isPositional() const { return m_positional; }
float getRolloff() const { return m_rolloff; }
float getGain() const { return m_gain; }
float getMaxDist() const { return m_max_dist; }
std::string getFileName() const { return m_file; }
void setPositional(bool positional) { m_positional = positional; }
LEAK_CHECK()
};
}; // class SFXBuffer
#endif // HEADER_SFX_BUFFER_HPP

View File

@ -74,7 +74,10 @@ SFXManager::SFXManager()
m_initialized = music_manager->initialized();
m_master_gain = UserConfigParams::m_sfx_volume;
// Init position, since it can be used before positionListener is called.
m_position = Vec3(0,0,0);
// No need to use lock here, since the thread will be created later.
m_listener_position.getData() = Vec3(0, 0, 0);
m_listener_front = Vec3(0, 0, 1);
m_listener_up = Vec3(0, 1, 0);
loadSfx();
@ -98,17 +101,15 @@ SFXManager::SFXManager()
delete m_thread_id.getData();
m_thread_id.unlock();
m_thread_id.setAtomic(0);
Log::error("HTTP Manager", "Could not create thread, error=%d.",
Log::error("SFXManager", "Could not create thread, error=%d.",
errno);
}
pthread_attr_destroy(&attr);
if (!sfxAllowed()) return;
setMasterSFXVolume( UserConfigParams::m_sfx_volume );
m_sfx_to_play.lock();
m_sfx_to_play.getData().clear();
m_sfx_to_play.unlock();
m_sfx_commands.lock();
m_sfx_commands.getData().clear();
m_sfx_commands.unlock();
} // SoundManager
@ -124,13 +125,15 @@ SFXManager::~SFXManager()
pthread_cond_destroy(&m_cond_request);
// ---- clear m_all_sfx
const int sfx_amount = (int) m_all_sfx.size();
// not strictly necessary, but might avoid copy&paste problems
m_all_sfx.lock();
const int sfx_amount = (int) m_all_sfx.getData().size();
for (int n=0; n<sfx_amount; n++)
{
delete m_all_sfx[n];
delete m_all_sfx.getData()[n];
}
m_all_sfx.clear();
m_all_sfx.getData().clear();
m_all_sfx.unlock();
// ---- clear m_quick_sounds
{
std::map<std::string, SFXBase*>::iterator i = m_quick_sounds.begin();
@ -158,32 +161,84 @@ SFXManager::~SFXManager()
} // ~SFXManager
//----------------------------------------------------------------------------
/** Adds a sound effect to the queue of sfx to be started by the sfx manager.
* Starting a sfx can sometimes cause a 5ms delay, so it is done in a
* separate thread.
/** Adds a sound effect command to the queue of the sfx manager. Openal
* commands can sometimes cause a 5ms delay, so it is done in a separate
* thread.
* \param command The command to execute.
* \param sfx The sound effect to be started.
*/
void SFXManager::queue(SFXBase *sfx)
void SFXManager::queue(SFXCommands command, SFXBase *sfx)
{
// Don't add sfx that are either not working correctly (e.g. because sfx
// are disabled);
if(sfx && sfx->getStatus()==SFX_UNKNOWN ) return;
m_sfx_to_play.lock();
m_sfx_to_play.getData().push_back(sfx);
m_sfx_to_play.unlock();
// Wake up the sfx thread
pthread_cond_signal(&m_cond_request);
SFXCommand *sfx_command = new SFXCommand(command, sfx);
queueCommand(sfx_command);
} // queue
//----------------------------------------------------------------------------
/** Adds a sound effect command with a single floating point parameter to the
* queue of the sfx manager. Openal commands can sometimes cause a 5ms delay,
* so it is done in a separate thread.
* \param command The command to execute.
* \param sfx The sound effect to be started.
* \param f Floating point parameter for the command.
*/
void SFXManager::queue(SFXCommands command, SFXBase *sfx, float f)
{
SFXCommand *sfx_command = new SFXCommand(command, sfx, f);
queueCommand(sfx_command);
} // queue(float)
//----------------------------------------------------------------------------
/** Adds a sound effect command with a Vec3 parameter to the queue of the sfx
* manager. Openal commands can sometimes cause a 5ms delay, so it is done in
* a separate thread.
* \param command The command to execute.
* \param sfx The sound effect to be started.
* \param p A Vec3 parameter for the command.
*/
void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p)
{
SFXCommand *sfx_command = new SFXCommand(command, sfx, p);
queueCommand(sfx_command);
} // queue (Vec3)
//----------------------------------------------------------------------------
/** Enqueues a command to the sfx queue threadsafe. Then signal the
* sfx manager to wake up.
* \param command Pointer to the command to queue up.
*/
void SFXManager::queueCommand(SFXCommand *command)
{
m_sfx_commands.lock();
if(m_sfx_commands.getData().size() > 20*race_manager->getNumberOfKarts()+20)
{
if(command->m_command==SFX_POSITION || command->m_command==SFX_LOOP ||
command->m_command==SFX_PLAY || command->m_command==SFX_SPEED )
{
delete command;
static int count_messages = 0;
if(count_messages < 5)
{
Log::warn("SFXManager", "Throttling sfx - queue size %d",
m_sfx_commands.getData().size());
count_messages++;
}
m_sfx_commands.unlock();
return;
} // if throttling
}
m_sfx_commands.getData().push_back(command);
m_sfx_commands.unlock();
} // queueCommand
//----------------------------------------------------------------------------
/** Puts a NULL request into the queue, which will trigger the thread to
* exit.
*/
void SFXManager::stopThread()
{
queue(NULL);
queue(SFX_EXIT);
// Make sure the thread wakes up.
pthread_cond_signal(&m_cond_request);
} // stopThread
//----------------------------------------------------------------------------
@ -198,40 +253,68 @@ void* SFXManager::mainLoop(void *obj)
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
me->m_sfx_to_play.lock();
me->m_sfx_commands.lock();
// Wait till we have an empty sfx in the queue
while (me->m_sfx_to_play.getData().empty() ||
me->m_sfx_to_play.getData().front()!=NULL )
while (me->m_sfx_commands.getData().empty() ||
me->m_sfx_commands.getData().front()->m_command!=SFX_EXIT)
{
bool empty = me->m_sfx_to_play.getData().empty();
bool empty = me->m_sfx_commands.getData().empty();
// Wait in cond_wait for a request to arrive. The 'while' is necessary
// since "spurious wakeups from the pthread_cond_wait ... may occur"
// (pthread_cond_wait man page)!
while (empty)
{
pthread_cond_wait(&me->m_cond_request, me->m_sfx_to_play.getMutex());
empty = me->m_sfx_to_play.getData().empty();
pthread_cond_wait(&me->m_cond_request, me->m_sfx_commands.getMutex());
empty = me->m_sfx_commands.getData().empty();
}
SFXCommand *current = me->m_sfx_commands.getData().front();
me->m_sfx_commands.getData().erase(me->m_sfx_commands.getData().begin());
SFXBase *current = me->m_sfx_to_play.getData().front();
me->m_sfx_to_play.getData().erase(me->m_sfx_to_play.getData().begin());
if (!current) // empty sfx indicates to abort the sfx manager
if (current->m_command == SFX_EXIT)
break;
me->m_sfx_to_play.unlock();
current->reallyPlayNow();
me->m_sfx_to_play.lock();
me->m_sfx_commands.unlock();
switch(current->m_command)
{
case SFX_PLAY: current->m_sfx->reallyPlayNow(); break;
case SFX_STOP: current->m_sfx->reallyStopNow(); break;
case SFX_PAUSE: current->m_sfx->reallyPauseNow(); break;
case SFX_RESUME: current->m_sfx->reallyResumeNow(); break;
case SFX_SPEED: current->m_sfx->reallySetSpeed(
current->m_parameter.getX()); break;
case SFX_POSITION: current->m_sfx->reallySetPosition(
current->m_parameter); break;
case SFX_VOLUME: current->m_sfx->reallySetVolume(
current->m_parameter.getX()); break;
case SFX_LOOP: current->m_sfx->reallySetLoop(
current->m_parameter.getX()!=0); break;
case SFX_DELETE: {
me->deleteSFX(current->m_sfx); break;
}
case SFX_PAUSE_ALL: me->reallyPauseAllNow(); break;
case SFX_RESUME_ALL: me->reallyResumeAllNow(); break;
case SFX_LISTENER: me->reallyPositionListenerNow(); break;
case SFX_UPDATE: me->reallyUpdateNow(current); break;
default: assert("Not yet supported.");
}
delete current;
current = NULL;
me->m_sfx_commands.lock();
} // while
// Clean up memory to avoid leak detection
while(!me->m_sfx_commands.getData().empty())
{
delete me->m_sfx_commands.getData().front();
me->m_sfx_commands.getData().erase(me->m_sfx_commands.getData().begin());
}
return NULL;
} // mainLoop
//----------------------------------------------------------------------------
/** Called then sound is globally switched on or off. It either pauses or
/** Called when sound is globally switched on or off. It either pauses or
* resumes all sound effects.
* \param on If sound is switched on or off.
*/
@ -248,18 +331,30 @@ void SFXManager::soundToggled(const bool on)
}
resumeAll();
const int sfx_amount = (int)m_all_sfx.size();
m_all_sfx.lock();
const int sfx_amount = (int)m_all_sfx.getData().size();
for (int n=0; n<sfx_amount; n++)
{
m_all_sfx[n]->onSoundEnabledBack();
m_all_sfx.getData()[n]->onSoundEnabledBack();
}
m_all_sfx.unlock();
}
else
{
// First stop all sfx that are not looped
const int sfx_amount = (int)m_all_sfx.getData().size();
m_all_sfx.lock();
for (int i=0; i<sfx_amount; i++)
{
if(!m_all_sfx.getData()[i]->isLooped())
{
m_all_sfx.getData()[i]->reallyStopNow();
}
}
m_all_sfx.unlock();
pauseAll();
}
}
} // soundToggled
//----------------------------------------------------------------------------
/** Returns if sfx can be played. This means sfx are enabled and
@ -359,7 +454,7 @@ SFXBuffer* SFXManager::addSingleSfx(const std::string &sfx_name,
}
if (UserConfigParams::logMisc())
Log::debug("SFXManager", "Loading SFX %s\n", sfx_file.c_str());
Log::debug("SFXManager", "Loading SFX %s", sfx_file.c_str());
if (load && buffer->load()) return buffer;
@ -379,7 +474,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
if (node->get("filename", &filename) == 0)
{
Log::error("SFXManager",
"/!\\ The 'filename' attribute is mandatory in the SFX XML file!\n");
"The 'filename' attribute is mandatory in the SFX XML file!");
return NULL;
}
@ -388,7 +483,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
if(m_all_sfx_types.find(sfx_name)!=m_all_sfx_types.end())
{
Log::error("SFXManager",
"There is already a sfx named '%s' installed - new one is ignored.\n",
"There is already a sfx named '%s' installed - new one is ignored.",
sfx_name.c_str());
return NULL;
}
@ -437,7 +532,12 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
sfx->setMasterVolume(m_master_gain);
if (add_to_SFX_list) m_all_sfx.push_back(sfx);
if (add_to_SFX_list)
{
m_all_sfx.lock();
m_all_sfx.getData().push_back(sfx);
m_all_sfx.unlock();
}
return sfx;
} // createSoundSource
@ -451,7 +551,7 @@ SFXBase* SFXManager::createSoundSource(const std::string &name,
{
Log::error("SFXManager",
"SFXManager::createSoundSource could not find the "
"requested sound effect : '%s'\n", name.c_str());
"requested sound effect : '%s'.", name.c_str());
return NULL;
}
@ -489,6 +589,38 @@ void SFXManager::deleteSFXMapping(const std::string &name)
} // deleteSFXMapping
//----------------------------------------------------------------------------
/** Make sures that the sfx thread is started at least one per frame. It also
* adds an update command for the music manager.
* \param dt Time step size.
*/
void SFXManager::update(float dt)
{
queue(SFX_UPDATE, NULL, dt);
// Wake up the sfx thread to handle all queued up audio commands.
pthread_cond_signal(&m_cond_request);
} // update
//----------------------------------------------------------------------------
/** Updates the status of all playing sfx (to test if they are finished).
* This function is executed once per thread (triggered by the
*/
void SFXManager::reallyUpdateNow(SFXCommand *current)
{
assert(current->m_command==SFX_UPDATE);
float dt = current->m_parameter.getX();
music_manager->update(dt);
m_all_sfx.lock();
for (std::vector<SFXBase*>::iterator i = m_all_sfx.getData().begin();
i != m_all_sfx.getData().end(); i++)
{
if((*i)->getStatus()==SFXBase::SFX_PLAYING)
(*i)->updatePlayingSFX(dt);
} // for i in m_all_sfx
m_all_sfx.unlock();
} // reallyUpdateNow
//----------------------------------------------------------------------------
/** Delete a sound effect object, and removes it from the internal list of
* all SFXs. This call deletes the object, and removes it from the list of
@ -497,59 +629,85 @@ void SFXManager::deleteSFXMapping(const std::string &name)
*/
void SFXManager::deleteSFX(SFXBase *sfx)
{
if(sfx) sfx->stop();
if(sfx) sfx->reallyStopNow();
std::vector<SFXBase*>::iterator i;
i=std::find(m_all_sfx.begin(), m_all_sfx.end(), sfx);
// The whole block needs to be locked, otherwise the iterator
// could become invalid.
m_all_sfx.lock();
i=std::find(m_all_sfx.getData().begin(), m_all_sfx.getData().end(), sfx);
if(i==m_all_sfx.end())
if(i==m_all_sfx.getData().end())
{
Log::warn("SFXManager",
"SFXManager::deleteSFX : Warning: sfx not found in list.");
"SFXManager::deleteSFX : Warning: sfx '%s' %lx not found in list.",
sfx->getBuffer()->getFileName().c_str(), sfx);
m_all_sfx.unlock();
return;
}
m_all_sfx.getData().erase(i);
m_all_sfx.unlock();
delete sfx;
m_all_sfx.erase(i);
} // deleteSFX
//----------------------------------------------------------------------------
/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
* otherwise not possible to determine which SFX must be resumed (i.e. were
* actually playing at the time pause was called).
*/
void SFXManager::pauseAll()
{
if (!sfxAllowed()) return;
queue(SFX_PAUSE_ALL);
} // pauseAll
//----------------------------------------------------------------------------
/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
* otherwise not possible to determine which SFX must be resumed (i.e. were
* actually playing at the time pause was called.
*/
void SFXManager::pauseAll()
void SFXManager::reallyPauseAllNow()
{
for (std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
i!=m_all_sfx.end(); i++)
m_all_sfx.lock();
for (std::vector<SFXBase*>::iterator i= m_all_sfx.getData().begin();
i!=m_all_sfx.getData().end(); i++)
{
(*i)->pause();
(*i)->reallyPauseNow();
} // for i in m_all_sfx
m_all_sfx.unlock();
} // pauseAll
//----------------------------------------------------------------------------
/**
* Resumes all paused SFXs. If sound is disabled, does nothing.
/** Resumes all paused SFXs. If sound is disabled, does nothing.
*/
void SFXManager::resumeAll()
{
// ignore unpausing if sound is disabled
if (!sfxAllowed()) return;
queue(SFX_RESUME_ALL);
} // resumeAll
for (std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
i!=m_all_sfx.end(); i++)
//----------------------------------------------------------------------------
/** Resumes all paused SFXs. If sound is disabled, does nothing.
*/
void SFXManager::reallyResumeAllNow()
{
m_all_sfx.lock();
for (std::vector<SFXBase*>::iterator i =m_all_sfx.getData().begin();
i!=m_all_sfx.getData().end(); i++)
{
SFXStatus status = (*i)->getStatus();
// Initial happens when
if (status==SFX_PAUSED) (*i)->resume();
(*i)->reallyResumeNow();
} // for i in m_all_sfx
m_all_sfx.unlock();
} // resumeAll
//-----------------------------------------------------------------------------
/** Returns whether or not an openal error has occurred. If so, an error
* message is printed containing the given context.
* \param context Context to specify in the error message.
* \return True if no error happened.
*/
bool SFXManager::checkError(const std::string &context)
{
@ -580,11 +738,13 @@ void SFXManager::setMasterSFXVolume(float gain)
// regular SFX
{
for (std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
i!=m_all_sfx.end(); i++)
m_all_sfx.lock();
for (std::vector<SFXBase*>::iterator i =m_all_sfx.getData().begin();
i!=m_all_sfx.getData().end(); i++)
{
(*i)->setMasterVolume(m_master_gain);
} // for i in m_all_sfx
m_all_sfx.unlock();
}
// quick SFX
@ -621,28 +781,51 @@ const std::string SFXManager::getErrorString(int err)
/** Sets the position and orientation of the listener.
* \param position Position of the listener.
* \param front Which way the listener is facing.
* \param up The up direction of the listener.
*/
void SFXManager::positionListener(const Vec3 &position, const Vec3 &front)
void SFXManager::positionListener(const Vec3 &position, const Vec3 &front,
const Vec3 &up)
{
m_listener_position.lock();
m_listener_position.getData() = position;
m_listener_front = front;
m_listener_up = up;
m_listener_position.unlock();
queue(SFX_LISTENER);
} // positionListener
//-----------------------------------------------------------------------------
/** Sets the position and orientation of the listener.
* \param position Position of the listener.
* \param front Which way the listener is facing.
*/
void SFXManager::reallyPositionListenerNow()
{
#if HAVE_OGGVORBIS
if (!UserConfigParams::m_sfx || !m_initialized) return;
m_position = position;
m_listener_position.lock();
{
//forward vector
m_listenerVec[0] = front.getX();
m_listenerVec[1] = front.getY();
m_listenerVec[2] = front.getZ();
//forward vector
float orientation[6];
orientation[0] = m_listener_front.getX();
orientation[1] = m_listener_front.getY();
orientation[2] = m_listener_front.getZ();
//up vector
m_listenerVec[3] = 0;
m_listenerVec[4] = 0;
m_listenerVec[5] = 1;
//up vector
orientation[3] = m_listener_up.getX();
orientation[4] = m_listener_up.getY();
orientation[5] = m_listener_up.getZ();
const Vec3 &pos = m_listener_position.getData();
alListener3f(AL_POSITION, pos.getX(), pos.getY(), pos.getZ());
alListenerfv(AL_ORIENTATION, orientation);
}
m_listener_position.unlock();
alListener3f(AL_POSITION, position.getX(), position.getY(), position.getZ());
alListenerfv(AL_ORIENTATION, m_listenerVec);
#endif
}
} // reallyPositionListenerNow
//-----------------------------------------------------------------------------
/** Positional sound is cool, but creating a new object just to play a simple

View File

@ -19,6 +19,7 @@
#ifndef HEADER_SFX_MANAGER_HPP
#define HEADER_SFX_MANAGER_HPP
#include "utils/leak_check.hpp"
#include "utils/no_copy.hpp"
#include "utils/synchronised.hpp"
#include "utils/vec3.hpp"
@ -57,6 +58,26 @@ private:
public:
/** The various commands to be executed by the sfx manager thread
* for each sfx. */
enum SFXCommands
{
SFX_PLAY = 1,
SFX_STOP,
SFX_PAUSE,
SFX_PAUSE_ALL,
SFX_RESUME,
SFX_RESUME_ALL,
SFX_DELETE,
SFX_SPEED,
SFX_POSITION,
SFX_VOLUME,
SFX_LOOP,
SFX_LISTENER,
SFX_UPDATE,
SFX_EXIT,
}; // SFXCommands
/**
* Entries for custom SFX sounds. These are unique for each kart.
* eg. kart->playCustomSFX(SFX_MANAGER::CUSTOM_HORN)
@ -76,34 +97,68 @@ public:
NUM_CUSTOMS
};
/** Status of a sound effect. */
enum SFXStatus
{
SFX_UNKNOWN = -1, SFX_STOPPED = 0, SFX_PAUSED = 1, SFX_PLAYING = 2,
SFX_INITIAL = 3
};
private:
/** Listener position */
Vec3 m_position;
/** Data structure for the queue, which stores a sfx and the command to
* execute for it. */
class SFXCommand : public NoCopy
{
private:
LEAK_CHECK()
public:
/** The sound effect for which the command should be executed. */
SFXBase *m_sfx;
/** The command to execute. */
SFXCommands m_command;
/** Optional parameter for commands that need more input. */
Vec3 m_parameter;
// --------------------------------------------------------------------
SFXCommand(SFXCommands command, SFXBase *base)
{
m_command = command;
m_sfx = base;
} // SFXCommand()
// --------------------------------------------------------------------
SFXCommand(SFXCommands command, SFXBase *base, float parameter)
{
m_command = command;
m_sfx = base;
m_parameter.setX(parameter);
} // SFXCommand(float)
// --------------------------------------------------------------------
SFXCommand(SFXCommands command, SFXBase *base, const Vec3 &parameter)
{
m_command = command;
m_sfx = base;
m_parameter = parameter;
} // SFXCommand(Vec3)
}; // SFXCommand
// ========================================================================
/** The position of the listener. Its lock will be used to
* access m_listener_{position,front, up}. */
Synchronised<Vec3> m_listener_position;
/** The direction the listener is facing. */
Vec3 m_listener_front;
/** Up vector of the listener. */
Vec3 m_listener_up;
/** The buffers and info for all sound effects. These are shared among all
* instances of SFXOpenal. */
std::map<std::string, SFXBuffer*> m_all_sfx_types;
/** The actual instances (sound sources) */
std::vector<SFXBase*> m_all_sfx;
Synchronised<std::vector<SFXBase*> > m_all_sfx;
/** The list of sound effects to be played in the next update. */
Synchronised< std::vector<SFXBase*> > m_sfx_to_play;
Synchronised< std::vector<SFXCommand*> > m_sfx_commands;
/** To play non-positional sounds without having to create a new object for each */
std::map<std::string, SFXBase*> m_quick_sounds;
/** listener vector (position vector + up vector) */
float m_listenerVec[6];
/** If the sfx manager has been initialised. */
bool m_initialized;
@ -121,10 +176,16 @@ private:
virtual ~SFXManager();
static void* mainLoop(void *obj);
void deleteSFX(SFXBase *sfx);
void queueCommand(SFXCommand *command);
void reallyPositionListenerNow();
public:
static void create();
static void destroy();
void queue(SFXBase *sfx);
void queue(SFXCommands command, SFXBase *sfx=NULL);
void queue(SFXCommands command, SFXBase *sfx, float f);
void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p);
// ------------------------------------------------------------------------
/** Static function to get the singleton sfx manager. */
static SFXManager *get()
@ -148,15 +209,18 @@ public:
const bool load = true);
SFXBase* createSoundSource(SFXBuffer* info,
const bool addToSFXList=true,
const bool add_to_SFX_list=true,
const bool owns_buffer=false);
SFXBase* createSoundSource(const std::string &name,
const bool addToSFXList=true);
void deleteSFX(SFXBase *sfx);
void deleteSFXMapping(const std::string &name);
void pauseAll();
void reallyPauseAllNow();
void resumeAll();
void reallyResumeAllNow();
void update(float dt);
void reallyUpdateNow(SFXCommand *current);
bool soundExist(const std::string &name);
void setMasterSFXVolume(float gain);
float getMasterSFXVolume() const { return m_master_gain; }
@ -164,7 +228,8 @@ public:
static bool checkError(const std::string &context);
static const std::string getErrorString(int err);
void positionListener(const Vec3 &position, const Vec3 &front);
void positionListener(const Vec3 &position,
const Vec3 &front, const Vec3 &up);
SFXBase* quickSound(const std::string &soundName);
/** Called when sound was muted/unmuted */
@ -177,7 +242,7 @@ public:
// ------------------------------------------------------------------------
/** Returns the current position of the listener. */
Vec3 getListenerPos() const { return m_position; }
Vec3 getListenerPos() const { return m_listener_position.getData(); }
};

View File

@ -1,7 +1,8 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2009-2013 Marianne Gagnon
// Copyright (C) 2014 Joerg Henrichs
// Copyright (C) 2006-2014 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2009-2014 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -23,8 +24,7 @@
#include "audio/sfx_buffer.hpp"
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include "race/race_manager.hpp"
#include "modes/world.hpp"
#include "utils/vs.hpp"
#ifdef __APPLE__
@ -38,17 +38,20 @@
#include <stdio.h>
#include <string>
SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain, bool ownsBuffer) : SFXBase()
SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
bool owns_buffer)
: SFXBase()
{
m_soundBuffer = buffer;
m_soundSource = 0;
m_ok = false;
m_positional = positional;
m_defaultGain = gain;
m_loop = false;
m_gain = -1.0f;
m_master_gain = 1.0f;
m_owns_buffer = ownsBuffer;
m_sound_buffer = buffer;
m_sound_source = 0;
m_status = SFX_NOT_INITIALISED;
m_positional = positional;
m_default_gain = gain;
m_loop = false;
m_gain = -1.0f;
m_master_gain = 1.0f;
m_owns_buffer = owns_buffer;
m_play_time = 0.0f;
// Don't initialise anything else if the sfx manager was not correctly
// initialised. First of all the initialisation will not work, and it
@ -60,74 +63,106 @@ SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain, bool ownsBu
} // SFXOpenAL
//-----------------------------------------------------------------------------
/** Deletes the sfx source, and if it owns the buffer, also deletes the sound
* buffer. */
SFXOpenAL::~SFXOpenAL()
{
if (m_ok)
if (m_status!=SFX_UNKNOWN)
{
alDeleteSources(1, &m_soundSource);
alDeleteSources(1, &m_sound_source);
}
if (m_owns_buffer && m_soundBuffer != NULL)
if (m_owns_buffer && m_sound_buffer)
{
m_soundBuffer->unload();
delete m_soundBuffer;
m_sound_buffer->unload();
delete m_sound_buffer;
}
} // ~SFXOpenAL
//-----------------------------------------------------------------------------
/** Initialises the sfx.
*/
bool SFXOpenAL::init()
{
alGenSources(1, &m_soundSource );
if (!SFXManager::checkError("generating a source")) return false;
m_status = SFX_UNKNOWN;
assert( alIsBuffer(m_soundBuffer->getBufferID()) );
assert( alIsSource(m_soundSource) );
alGenSources(1, &m_sound_source );
if (!SFXManager::checkError("generating a source"))
return false;
//std::cout << "Setting a source with buffer " << m_soundBuffer
// << ", rolloff " << rolloff
// << ", gain=" << m_defaultGain << ", positional="
// << (positional ? "true" : "false") << std::endl;
assert( alIsBuffer(m_sound_buffer->getBufferID()) );
assert( alIsSource(m_sound_source) );
alSourcei (m_soundSource, AL_BUFFER, m_soundBuffer->getBufferID());
alSourcei (m_sound_source, AL_BUFFER, m_sound_buffer->getBufferID());
if (!SFXManager::checkError("attaching the buffer to the source"))
return false;
alSource3f(m_soundSource, AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(m_soundSource, AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(m_soundSource, AL_DIRECTION, 0.0, 0.0, 0.0);
alSource3f(m_sound_source, AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(m_sound_source, AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(m_sound_source, AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, m_soundBuffer->getRolloff());
alSourcef (m_soundSource, AL_MAX_DISTANCE, m_soundBuffer->getMaxDist());
alSourcef (m_sound_source, AL_ROLLOFF_FACTOR, m_sound_buffer->getRolloff());
alSourcef (m_sound_source, AL_MAX_DISTANCE, m_sound_buffer->getMaxDist());
if (m_gain < 0.0f)
{
alSourcef (m_soundSource, AL_GAIN, m_defaultGain * m_master_gain);
alSourcef (m_sound_source, AL_GAIN, m_default_gain * m_master_gain);
}
else
{
alSourcef (m_soundSource, AL_GAIN, m_gain * m_master_gain);
alSourcef (m_sound_source, AL_GAIN, m_gain * m_master_gain);
}
if (m_positional) alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_FALSE);
else alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_TRUE);
if (m_positional) alSourcei (m_sound_source, AL_SOURCE_RELATIVE, AL_FALSE);
else alSourcei (m_sound_source, AL_SOURCE_RELATIVE, AL_TRUE);
alSourcei(m_soundSource, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE);
alSourcei(m_sound_source, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE);
m_ok = SFXManager::checkError("setting up the source");
if(!SFXManager::checkError("setting up the source"))
return false;
return m_ok;
m_status = SFX_STOPPED;
return true;
} // init
// ------------------------------------------------------------------------
/** Updates the status of a playing sfx. If the sound has been played long
* enough, mark it to be finished. This avoid (a potentially costly)
* call to openal.
* \param dt Time step size.
*/
void SFXOpenAL::updatePlayingSFX(float dt)
{
assert(m_status==SFX_PLAYING);
m_play_time += dt;
if(!m_loop && m_play_time > m_sound_buffer->getDuration())
m_status = SFX_STOPPED;
} // updatePlayingSFX
//-----------------------------------------------------------------------------
/** Changes the pitch of a sound effect.
/** Queues up a change of the pitch of a sound effect to the sfx manager.
* \param factor Speedup/slowdown between 0.5 and 2.0
*/
void SFXOpenAL::speed(float factor)
void SFXOpenAL::setSpeed(float factor)
{
if(!m_ok || isnan(factor)) return;
if(m_status==SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
assert(!isnan(factor));
SFXManager::get()->queue(SFXManager::SFX_SPEED, this, factor);
} // setSpeed
//-----------------------------------------------------------------------------
/** Changes the pitch of a sound effect. Executed from the sfx manager thread.
* \param factor Speedup/slowdown between 0.5 and 2.0
*/
void SFXOpenAL::reallySetSpeed(float factor)
{
if(m_status==SFX_NOT_INITIALISED)
{
init();
if(m_status==SFX_UNKNOWN)
return;
}
//OpenAL only accepts pitches in the range of 0.5 to 2.0
if(factor > 2.0f)
@ -138,23 +173,39 @@ void SFXOpenAL::speed(float factor)
{
factor = 0.5f;
}
alSourcef(m_soundSource,AL_PITCH,factor);
SFXManager::checkError("changing the speed");
} // speed
alSourcef(m_sound_source,AL_PITCH,factor);
} // reallySetSpeed
//-----------------------------------------------------------------------------
/** Changes the volume of a sound effect.
* \param gain Volume adjustment between 0.0 (mute) and 1.0 (full volume).
*/
void SFXOpenAL::volume(float gain)
void SFXOpenAL::setVolume(float gain)
{
m_gain = m_defaultGain * gain;
if(m_status==SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
assert(!isnan(gain)) ;
SFXManager::get()->queue(SFXManager::SFX_VOLUME, this, gain);
} // setVolume
if(!m_ok) return;
//-----------------------------------------------------------------------------
/** Changes the volume of a sound effect.
* \param gain Volume adjustment between 0.0 (mute) and 1.0 (full volume).
*/
void SFXOpenAL::reallySetVolume(float gain)
{
m_gain = m_default_gain * gain;
alSourcef(m_soundSource, AL_GAIN, m_gain * m_master_gain);
SFXManager::checkError("setting volume");
} // volume
if(m_status==SFX_UNKNOWN) return;
if(m_status==SFX_NOT_INITIALISED)
{
init();
if(m_status==SFX_UNKNOWN)
return;
}
alSourcef(m_sound_source, AL_GAIN, m_gain * m_master_gain);
} // reallySetVolume
//-----------------------------------------------------------------------------
@ -162,10 +213,17 @@ void SFXOpenAL::setMasterVolume(float gain)
{
m_master_gain = gain;
if(!m_ok) return;
if(m_status==SFX_UNKNOWN) return;
if(m_status==SFX_NOT_INITIALISED)
{
init();
if(m_status==SFX_UNKNOWN)
return;
}
alSourcef(m_soundSource, AL_GAIN,
(m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
alSourcef(m_sound_source, AL_GAIN,
(m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
SFXManager::checkError("setting volume");
} //setMasterVolume
@ -174,55 +232,101 @@ void SFXOpenAL::setMasterVolume(float gain)
*/
void SFXOpenAL::setLoop(bool status)
{
m_loop = status;
if(!m_ok) return;
alSourcei(m_soundSource, AL_LOOPING, status ? AL_TRUE : AL_FALSE);
SFXManager::checkError("looping");
} // loop
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
SFXManager::get()->queue(SFXManager::SFX_LOOP, this, status ? 1.0f : 0.0f);
} // setLoop
//-----------------------------------------------------------------------------
/** Stops playing this sound effect.
/** Loops this sound effect.
*/
void SFXOpenAL::reallySetLoop(bool status)
{
if(m_status==SFX_NOT_INITIALISED)
{
init();
if(m_status==SFX_UNKNOWN)
return;
}
m_loop = status;
alSourcei(m_sound_source, AL_LOOPING, status ? AL_TRUE : AL_FALSE);
SFXManager::checkError("looping");
} // reallySetLoop
//-----------------------------------------------------------------------------
/** Queues a stop for this effect to the sound manager.
*/
void SFXOpenAL::stop()
{
if(!m_ok) return;
m_loop = false;
alSourcei(m_soundSource, AL_LOOPING, AL_FALSE);
alSourceStop(m_soundSource);
SFXManager::checkError("stoping");
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
SFXManager::get()->queue(SFXManager::SFX_STOP, this);
} // stop
//-----------------------------------------------------------------------------
/** The sfx manager thread executes a stop for this sfx.
*/
void SFXOpenAL::reallyStopNow()
{
if(m_status==SFX_PLAYING || m_status==SFX_PAUSED)
{
m_status = SFX_STOPPED;
m_loop = false;
alSourcei(m_sound_source, AL_LOOPING, AL_FALSE);
alSourceStop(m_sound_source);
SFXManager::checkError("stoping");
}
} // reallyStopNow
//-----------------------------------------------------------------------------
/** Queues up a pause command for this sfx.
*/
void SFXOpenAL::pause()
{
SFXManager::get()->queue(SFXManager::SFX_PAUSE, this);
} // pause
//-----------------------------------------------------------------------------
/** Pauses a SFX that's currently played. Nothing happens it the effect is
* currently not being played.
*/
void SFXOpenAL::pause()
void SFXOpenAL::reallyPauseNow()
{
if(!m_ok) return;
alSourcePause(m_soundSource);
// Need to be tested again here, since this function can be called
// from pauseAll, and we have to make sure to only pause playing sfx.
if (m_status != SFX_PLAYING || !SFXManager::get()->sfxAllowed()) return;
m_status = SFX_PAUSED;
alSourcePause(m_sound_source);
SFXManager::checkError("pausing");
} // pause
} // reallyPauseNow
//-----------------------------------------------------------------------------
/** Queues up a resume command for this sound effect.
*/
void SFXOpenAL::resume()
{
if (m_status != SFX_PLAYING || !SFXManager::get()->sfxAllowed()) return;
SFXManager::get()->queue(SFXManager::SFX_RESUME, this);
} // resume
//-----------------------------------------------------------------------------
/** Resumes a sound effect.
*/
void SFXOpenAL::resume()
void SFXOpenAL::reallyResumeNow()
{
if (!m_ok)
if(m_status==SFX_NOT_INITIALISED)
{
// lazily create OpenAL source when needed
init();
// creation of OpenAL source failed, giving up
if (!m_ok) return;
if(m_status==SFX_UNKNOWN)
return;
}
alSourcePlay(m_soundSource);
SFXManager::checkError("resuming");
} // resume
if(m_status==SFX_PAUSED)
{
alSourcePlay(m_sound_source);
SFXManager::checkError("resuming");
m_status = SFX_PLAYING;
}
} // reallyResumeNow
//-----------------------------------------------------------------------------
/** This actually queues up the sfx in the sfx manager. It will be started
@ -230,7 +334,18 @@ void SFXOpenAL::resume()
*/
void SFXOpenAL::play()
{
SFXManager::get()->queue(this);
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
if(m_status==SFX_STOPPED)
m_play_time = 0.0f;
// Technically the sfx is only playing after the sfx thread starts it,
// but it is important to set this here since stk might decide to
// delete a sfx if it has finished playing (i.e. is in stopped state)
// - which can happen if the sfx thread had no time to actually start
// it yet.
m_status = SFX_PLAYING;
SFXManager::get()->queue(SFXManager::SFX_PLAY, this);
} // play
//-----------------------------------------------------------------------------
@ -239,16 +354,16 @@ void SFXOpenAL::play()
void SFXOpenAL::reallyPlayNow()
{
if (!SFXManager::get()->sfxAllowed()) return;
if (!m_ok)
if (m_status==SFX_NOT_INITIALISED)
{
// lazily create OpenAL source when needed
init();
// creation of OpenAL source failed, giving up
if (!m_ok) return;
if (m_status==SFX_UNKNOWN) return;
}
alSourcePlay(m_soundSource);
alSourcePlay(m_sound_source);
SFXManager::checkError("playing");
} // reallyPlayNow
@ -256,20 +371,31 @@ void SFXOpenAL::reallyPlayNow()
/** Sets the position where this sound effects is played.
* \param position Position of the sound effect.
*/
void SFXOpenAL::position(const Vec3 &position)
void SFXOpenAL::setPosition(const Vec3 &position)
{
if(!UserConfigParams::m_sfx)
return;
if (!m_ok)
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
SFXManager::get()->queue(SFXManager::SFX_POSITION, this, position);
} // setPosition
//-----------------------------------------------------------------------------
/** Sets the position where this sound effects is played.
* \param position Position of the sound effect.
*/
void SFXOpenAL::reallySetPosition(const Vec3 &position)
{
if(m_status==SFX_NOT_INITIALISED)
{
Log::warn("SFX", "Position called on non-ok SFX <%s>", m_soundBuffer->getFileName().c_str());
return;
init();
if(m_status==SFX_UNKNOWN)
return;
}
if (!m_positional)
{
// in multiplayer, all sounds are positional, so in this case don't bug users with
// an error message if (race_manager->getNumLocalPlayers() > 1)
// (note that 0 players is also possible, in cutscenes)
// in multiplayer, all sounds are positional, so in this case don't
// bug users with an error message if (note that 0 players is also
// possible, in cutscenes)
if (race_manager->getNumLocalPlayers() < 2)
{
Log::warn("SFX", "Position called on non-positional SFX");
@ -277,39 +403,32 @@ void SFXOpenAL::position(const Vec3 &position)
return;
}
alSource3f(m_soundSource, AL_POSITION,
(float)position.getX(), (float)position.getY(), (float)position.getZ());
alSource3f(m_sound_source, AL_POSITION, (float)position.getX(),
(float)position.getY(), (float)position.getZ());
if (SFXManager::get()->getListenerPos().distance(position) > m_soundBuffer->getMaxDist())
if (SFXManager::get()->getListenerPos().distance(position)
> m_sound_buffer->getMaxDist())
{
alSourcef(m_soundSource, AL_GAIN, 0);
alSourcef(m_sound_source, AL_GAIN, 0);
}
else
{
alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
alSourcef(m_sound_source, AL_GAIN,
(m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
}
SFXManager::checkError("positioning");
} // position
} // reallySetPosition
//-----------------------------------------------------------------------------
/** Returns the status of this sound effect.
/** Queues up a delete request for this object. This is necessary to avoid
* a crash if the sfx manager thread might be delayed and access this object
* after it was deleted.
*/
SFXManager::SFXStatus SFXOpenAL::getStatus()
void SFXOpenAL::deleteSFX()
{
if(!m_ok) return SFXManager::SFX_UNKNOWN;
int state = 0;
alGetSourcei(m_soundSource, AL_SOURCE_STATE, &state);
switch(state)
{
case AL_STOPPED: return SFXManager::SFX_STOPPED;
case AL_PLAYING: return SFXManager::SFX_PLAYING;
case AL_PAUSED: return SFXManager::SFX_PAUSED;
case AL_INITIAL: return SFXManager::SFX_INITIAL;
default: return SFXManager::SFX_UNKNOWN;
}
} // getStatus
SFXManager::get()->queue(SFXManager::SFX_DELETE, this);
} // deleteSFX
//-----------------------------------------------------------------------------
@ -317,22 +436,23 @@ void SFXOpenAL::onSoundEnabledBack()
{
if (m_loop)
{
if (!m_ok) init();
if (m_ok)
if (m_status==SFX_NOT_INITIALISED) init();
if (m_status!=SFX_UNKNOWN)
{
alSourcef(m_soundSource, AL_GAIN, 0);
alSourcef(m_sound_source, AL_GAIN, 0);
play();
pause();
alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
alSourcef(m_sound_source, AL_GAIN,
(m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
}
}
}
} // onSoundEnabledBack
//-----------------------------------------------------------------------------
void SFXOpenAL::setRolloff(float rolloff)
{
alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, rolloff);
alSourcef (m_sound_source, AL_ROLLOFF_FACTOR, rolloff);
}
#endif //if HAVE_OGGVORBIS

View File

@ -28,7 +28,6 @@
# include <AL/al.h>
#endif
#include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp"
#include "utils/leak_check.hpp"
/**
@ -38,11 +37,22 @@
class SFXOpenAL : public SFXBase
{
private:
SFXBuffer* m_soundBuffer; //!< Buffers hold sound data.
ALuint m_soundSource; //!< Sources are points emitting sound.
bool m_ok;
LEAK_CHECK()
/** Buffers hold sound data. */
SFXBuffer* m_sound_buffer;
/** Sources are points emitting sound. */
ALuint m_sound_source;
/** The status of this SFX. */
SFXStatus m_status;
/** If the sfx is positional. */
bool m_positional;
float m_defaultGain;
/** Default gain value. */
float m_default_gain;
/** The OpenAL source contains this info, but if audio is disabled initially then
the sound source won't be created and we'll be left with no clue when enabling
@ -59,33 +69,49 @@ private:
/** The master gain set in user preferences */
float m_master_gain;
/** If this sfx should also free the sound buffer. */
bool m_owns_buffer;
/** How long the sfx has been playing. */
float m_play_time;
public:
SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
bool owns_buffer = false);
virtual ~SFXOpenAL();
SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
bool owns_buffer = false);
virtual ~SFXOpenAL();
/** Late creation, if SFX was initially disabled */
virtual bool init();
virtual void updatePlayingSFX(float dt);
virtual bool init();
virtual void play();
virtual void reallyPlayNow();
virtual void setLoop(bool status);
virtual void reallySetLoop(bool status);
virtual void stop();
virtual void reallyStopNow();
virtual void pause();
virtual void reallyPauseNow();
virtual void resume();
virtual void reallyResumeNow();
virtual void deleteSFX();
virtual void setSpeed(float factor);
virtual void reallySetSpeed(float factor);
virtual void setPosition(const Vec3 &position);
virtual void reallySetPosition(const Vec3 &p);
virtual void setVolume(float gain);
virtual void reallySetVolume(float gain);
virtual void setMasterVolume(float gain);
virtual void onSoundEnabledBack();
virtual void setRolloff(float rolloff);
// ------------------------------------------------------------------------
/** Returns if this sfx is looped or not. */
virtual bool isLooped() { return m_loop; }
// ------------------------------------------------------------------------
/** Returns the status of this sfx. */
virtual SFXStatus getStatus() { return m_status; }
virtual void play();
virtual void reallyPlayNow();
virtual void setLoop(bool status);
virtual void stop();
virtual void pause();
virtual void resume();
virtual void speed(float factor);
virtual void position(const Vec3 &position);
virtual void volume(float gain);
virtual void setMasterVolume(float gain);
virtual SFXManager::SFXStatus getStatus();
virtual void onSoundEnabledBack();
virtual void setRolloff(float rolloff);
virtual const SFXBuffer* getBuffer() const { return m_soundBuffer; }
LEAK_CHECK()
// ------------------------------------------------------------------------
/** Returns the buffer associated with this sfx. */
virtual const SFXBuffer* getBuffer() const { return m_sound_buffer; }
}; // SFXOpenAL

View File

@ -83,6 +83,10 @@ irr::core::stringw DeviceConfig::getMappingIdString (const PlayerAction action)
returnString += id;
break;
case Input::IT_NONE:
returnString += "none";
break;
default:
assert(false);
returnString += type;

View File

@ -23,15 +23,31 @@
#include "graphics/irr_driver.hpp"
#include "online/http_request.hpp"
#include "utils/random_generator.hpp"
#include "utils/string_utils.hpp"
#ifdef __APPLE__
# include <sys/sysctl.h>
#endif
#include <fstream>
#include <set>
#include <sstream>
#include <string>
#ifndef WIN32
# include <sys/param.h> // To get BSD macro
# include <sys/utsname.h>
#endif
#include <vector>
namespace HardwareStats
{
namespace Private
{
/** Stores the OS version, e.g. "Windows 7", or "Fedora 21". */
static std::string m_os_version;
} // namespace Private
using namespace Private;
// ----------------------------------------------------------------------------
/** Returns the amount of RAM in MB.
@ -40,7 +56,7 @@ namespace HardwareStats
int getRAM()
{
#ifdef __linux__
const uint64_t memory_size = (uint64_t)sysconf(_SC_PHYS_PAGES)
const uint64_t memory_size = (uint64_t)sysconf(_SC_PHYS_PAGES)
* sysconf(_SC_PAGESIZE);
return int(memory_size / (1024*1024));
#endif
@ -102,6 +118,138 @@ int getNumProcessors()
return 0;
} // getNumProcessors
// ----------------------------------------------------------------------------
/** Tries opening and parsing the specified release file in /etc to find
* information about the distro used.
* \param filename Full path of the file to open.
* \return True if file could be read and valid information was paresed,
* false otherwise.
*/
bool readEtcReleaseFile(const std::string &filename)
{
std::ifstream in(filename);
std::string s, distro, version;
while( (distro.empty() || version.empty()) &&
std::getline(in, s) )
{
std::vector<std::string> l = StringUtils::split(s, '=');
if(l.size()==0) continue;
if (l[0]=="NAME" ) distro = l[1];
else if(l[0]=="VERSION_ID") version = l[1];
}
if(!distro.empty() && !version.empty())
{
distro = StringUtils::replace(distro, "\"", "");
version = StringUtils::replace(version, "\"", "");
m_os_version = distro + " " + version;
return true;
}
return false;
} // readEtcReleaseFile
// ----------------------------------------------------------------------------
/** Identify more details about the OS, e.g. on linux which distro
* and which verison; on windows the version number.
* \param json Json data structure to store the os info in.
*/
void determineOSVersion()
{
std::string version, distro;
#ifdef __linux__
// First try the standard /etc/os-release. Then check for older versions
// e.g. /etc/fedora-release, /etc/SuSE-release, /etc/redhat-release
if(readEtcReleaseFile("/etc/os-release")) return;
std::set<std::string> file_list;
file_manager->listFiles(file_list, "./", true);
for(std::set<std::string>::iterator i = file_list.begin();
i != file_list.end(); i++)
{
// Only try reading /etc/*-release files
if(StringUtils::hasSuffix(*i, "-release"))
if (readEtcReleaseFile(*i)) return;
}
// Fallback in case that we can't find any valid information in /etc/*release
struct utsname u;
if (uname(&u))
{
m_os_version = "Linux unknown";
return;
}
// Ignore data after "-", since it could identify a system (self compiled
// kernels).
std::vector<std::string> l = StringUtils::split(std::string(u.release),'-');
m_os_version = std::string(u.sysname) + " " + l[0];
#endif
#ifdef BSD
struct utsname u;
if (uname(&u))
{
m_os_version = "BSD unknown";
return;
}
// Ignore data after "-", since it could identify a system (self compiled
// kernels).
std::vector<std::string> l = StringUtils::split(std::string(u.release),'-');
m_os_version = std::string(u.sysname) + " " + l[0];
#endif
#ifdef WIN32
// (C) 2014 by Wildfire Games (0 A.D.), ported by Joerg Henrichs.
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0,
KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
{
m_os_version = "windows-unknown";
return;
}
char windows_version_string[20];
DWORD size = sizeof(windows_version_string);
RegQueryValueEx(hKey, "CurrentVersion", 0, 0, (LPBYTE)windows_version_string, &size);
unsigned major = 0, minor = 0;
std::stringstream sstr(windows_version_string);
sstr >> major;
if (sstr.peek() == '.')
sstr.ignore();
sstr >> minor;
int windows_version = (major << 8) | minor;
RegCloseKey(hKey);
switch(windows_version)
{
case 0x0500: m_os_version="Windows 2000"; break;
case 0x0501: m_os_version="Windows XP"; break;
case 0x0502: m_os_version="Windows XP64"; break;
case 0x0600: m_os_version="Windows Vista"; break;
case 0x0601: m_os_version="Windows 7"; break;
case 0x0602: m_os_version="Windows 8"; break;
default: {
m_os_version = StringUtils::insertValues("Windows %d",
windows_version);
break;
}
} // switch
#endif
} // determineOSVersion
// ----------------------------------------------------------------------------
/** Returns the OS version, e.g.: "Windows 7", or "Fedora 21".
*/
const std::string& getOSVersion()
{
if(m_os_version.empty())
determineOSVersion();
return m_os_version;
} // getOSVersion
// ----------------------------------------------------------------------------
/** If the configuration of this installation has not been reported for the
* current version, collect the hardware statistics and send it to STK's
@ -144,10 +292,12 @@ void reportHardwareStats()
json.add("build_debug", 1);
#endif
json.add("os_version", getOSVersion());
unsigned int ogl_version = irr_driver->getGLSLVersion();
unsigned int major = ogl_version/100;
unsigned int minor = ogl_version - 100*major;
std::string version =
std::string version =
StringUtils::insertValues("%d.%d", major, minor);
json.add("GL_SHADING_LANGUAGE_VERSION", version);
@ -166,7 +316,7 @@ void reportHardwareStats()
else if(StringUtils::startsWith(card_name, "S3 Graphics"))
card_name="S3";
json.add("gfx_card", card_name+" "+renderer);
json.add("video_xres", UserConfigParams::m_width );
json.add("video_yres", UserConfigParams::m_height);
@ -195,14 +345,14 @@ void reportHardwareStats()
int m_version;
public:
HWReportRequest(int version) : Online::HTTPRequest(/*manage memory*/true, 1)
,m_version(version)
, m_version(version)
{}
// --------------------------------------------------------------------
/** Callback after the request has been executed.
/** Callback after the request has been executed.
*/
virtual void callback()
{
// If the request contains incorrect data, it will not have a
// If the request contains incorrect data, it will not have a
// download error, but return an error string as return value:
if(hadDownloadError() || getData()=="<h1>Bad Request (400)</h1>")
{

View File

@ -25,11 +25,14 @@
#include "utils/no_copy.hpp"
#include "utils/string_utils.hpp"
namespace HardwareStats
{
/** A class to manage json data. */
class Json : public NoCopy
{
private:
/** The accumulated json data. */
std::string m_data;
public:
/** Constructor. */
@ -78,6 +81,7 @@ namespace HardwareStats
// ========================================================================
void reportHardwareStats();
const std::string& getOSVersion();
}; // HardwareStats
#endif

View File

@ -170,7 +170,11 @@ PlayerManager::~PlayerManager()
for_var_in(PlayerProfile*, player, m_all_players)
{
if(!player->rememberPassword())
player->clearSession();
{
// Don't let the player trigger a save, since it
// will be done below anyway.
player->clearSession(/*save*/false);
}
}
save();

View File

@ -244,12 +244,13 @@ void PlayerProfile::saveSession(int user_id, const std::string &token)
// ------------------------------------------------------------------------
/** Unsets any saved session data. */
void PlayerProfile::clearSession()
void PlayerProfile::clearSession(bool save)
{
m_saved_session = false;
m_saved_user_id = 0;
m_saved_token = "";
PlayerManager::get()->save();
if(save)
PlayerManager::get()->save();
} // clearSession
//------------------------------------------------------------------------------

View File

@ -129,7 +129,7 @@ public:
bool operator<(const PlayerProfile &other);
void raceFinished();
void saveSession(int user_id, const std::string &token);
void clearSession();
void clearSession(bool save=true);
void addIcon();
/** Abstract virtual classes, to be implemented by the OnlinePlayer. */

View File

@ -71,7 +71,7 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
const std::vector<RaceManager::KartStatus> &kart_list)
: m_savedgp_group("SavedGP",
"Represents the saved state of a GP"),
m_player_id(player_id),
m_player_id(player_id, "player_id", &m_savedgp_group),
m_gp_id(gp_id.c_str(), "gp_id", &m_savedgp_group),
m_difficulty((int)difficulty,"difficulty", &m_savedgp_group),
m_player_karts(player_karts,"player_karts", &m_savedgp_group),
@ -94,13 +94,14 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
SavedGrandPrix::SavedGrandPrix(const XMLNode* node)
: m_savedgp_group("SavedGP",
"Represents the saved state of a GP"),
m_player_id(0),
m_player_id(0, "player_id", &m_savedgp_group),
m_gp_id("-", "gp_id", &m_savedgp_group),
m_difficulty(0,"difficulty", &m_savedgp_group),
m_player_karts(0,"player_karts", &m_savedgp_group),
m_next_track(0,"last_track", &m_savedgp_group)
{
//m_player_group.findYourDataInAChildOf(node);
m_player_id.findYourDataInAnAttributeOf(node);
m_gp_id.findYourDataInAnAttributeOf(node);
m_difficulty.findYourDataInAnAttributeOf(node);
m_player_karts.findYourDataInAnAttributeOf(node);

View File

@ -60,7 +60,7 @@ protected:
* WARNING : m_savedgp_group has to be declared before the other userconfigparams!
*/
GroupUserConfigParam m_savedgp_group;
unsigned int m_player_id;
IntUserConfigParam m_player_id;
/** Identifier of this GP. */
StringUserConfigParam m_gp_id;
@ -145,6 +145,7 @@ public:
for (unsigned int n=0; n<UserConfigParams::m_saved_grand_prix_list.size(); n++)
{
SavedGrandPrix* gp = &UserConfigParams::m_saved_grand_prix_list[n];
if ((gp->getGPID() == gpid) &&
(gp->getPlayerID() == player) &&
(gp->getDifficulty() == difficulty) &&

View File

@ -140,8 +140,7 @@ void GroupUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
const XMLNode* child = node->getNode( m_param_name );
if (child == NULL)
{
//std::cerr << "/!\\ User Config : Couldn't find parameter group "
// << paramName << std::endl;
//Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str());
return;
}
@ -271,8 +270,7 @@ void ListUserConfigParam<T, U>::findYourDataInAChildOf(const XMLNode* node)
const XMLNode* child = node->getNode( m_param_name );
if (child == NULL)
{
//std::cerr << "/!\\ User Config : Couldn't find parameter group "
// << paramName << std::endl;
//Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str());
return;
}
@ -374,12 +372,12 @@ void IntUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
const XMLNode* child = node->getNode( m_param_name );
if(child == NULL)
{
//std::cout << "Couldn't find int parameter " << paramName << std::endl;
//Log::error("UserConfigParam", "Couldn't find int parameter %s", m_param_name.c_str());
return;
}
child->get( "value", &m_value );
//std::cout << "read int " << paramName << ", value=" << value << std::endl;
//Log::info("UserConfigParam", "Read int %s ,value = %d", m_param_name.c_str(), value);
} // findYourDataInAChildOf
// ----------------------------------------------------------------------------
@ -442,7 +440,7 @@ void TimeUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
const XMLNode* child = node->getNode( m_param_name );
if(child == NULL)
{
//std::cout << "Couldn't find int parameter " << paramName <<std::endl;
//Log::error("UserConfigParam", "Couldn't find int parameter %s", m_param_name.c_str());
return;
}
@ -564,8 +562,7 @@ void BoolUserConfigParam::findYourDataInAChildOf(const XMLNode* node)
}
else
{
std::cerr << "Unknown value for " << m_param_name
<< "; expected true or false\n";
Log::error("User Config", "Unknown value for %s; expected true or false", m_param_name.c_str());
}
} // findYourDataInAChildOf
@ -585,8 +582,7 @@ void BoolUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node)
}
else
{
std::cerr << "Unknown value for " << m_param_name
<< "; expected true or false\n";
Log::error("User Config", "Unknown value for %s; expected true or false", m_param_name.c_str());
}
} // findYourDataInAnAttributeOf
@ -760,7 +756,7 @@ void UserConfig::saveConfig()
const int paramAmount = all_params.size();
for(int i=0; i<paramAmount; i++)
{
//std::cout << "saving parameter " << i << " to file\n";
//Log::info("UserConfig", "Saving parameter %d to file", i);
all_params[i].write(configfile);
}
@ -769,8 +765,8 @@ void UserConfig::saveConfig()
}
catch (std::runtime_error& e)
{
std::cerr << "[UserConfig::saveConfig] ERROR: Failed to write config to " << filename.c_str()
<< "; cause : " << e.what() << "\n";
Log::error("UserConfig::saveConfig", "Failed to write config to %s, because %s",
filename.c_str(), e.what());
}
} // saveConfig

338
src/graphics/2dutils.cpp Normal file
View File

@ -0,0 +1,338 @@
#include "2dutils.hpp"
#include "glwrap.hpp"
#include "utils/cpp2011.hpp"
#include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h"
static void drawTexColoredQuad(const video::ITexture *texture, const video::SColor *col, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
unsigned colors[] = {
col[0].getRed(), col[0].getGreen(), col[0].getBlue(), col[0].getAlpha(),
col[1].getRed(), col[1].getGreen(), col[1].getBlue(), col[1].getAlpha(),
col[2].getRed(), col[2].getGreen(), col[2].getBlue(), col[2].getAlpha(),
col[3].getRed(), col[3].getGreen(), col[3].getBlue(), col[3].getAlpha(),
};
glBindBuffer(GL_ARRAY_BUFFER, UIShader::ColoredTextureRectShader::getInstance()->colorvbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(unsigned), colors);
glUseProgram(UIShader::ColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(UIShader::ColoredTextureRectShader::getInstance()->vao);
UIShader::ColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
UIShader::ColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGetError();
}
static
void drawTexQuad(GLuint texture, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
glUseProgram(UIShader::TextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::TextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
UIShader::TextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y),
core::vector2df(tex_width, tex_height));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGetError();
}
static void
getSize(unsigned texture_width, unsigned texture_height, bool textureisRTT,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect,
float &width, float &height,
float &center_pos_x, float &center_pos_y,
float &tex_width, float &tex_height,
float &tex_center_pos_x, float &tex_center_pos_y
)
{
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
center_pos_x = float(destRect.UpperLeftCorner.X + destRect.LowerRightCorner.X);
center_pos_x /= screen_w;
center_pos_x -= 1.;
center_pos_y = float(destRect.UpperLeftCorner.Y + destRect.LowerRightCorner.Y);
center_pos_y /= screen_h;
center_pos_y = float(1.f - center_pos_y);
width = float(destRect.LowerRightCorner.X - destRect.UpperLeftCorner.X);
width /= screen_w;
height = float(destRect.LowerRightCorner.Y - destRect.UpperLeftCorner.Y);
height /= screen_h;
tex_center_pos_x = float(sourceRect.UpperLeftCorner.X + sourceRect.LowerRightCorner.X);
tex_center_pos_x /= texture_width * 2.f;
tex_center_pos_y = float(sourceRect.UpperLeftCorner.Y + sourceRect.LowerRightCorner.Y);
tex_center_pos_y /= texture_height * 2.f;
tex_width = float(sourceRect.LowerRightCorner.X - sourceRect.UpperLeftCorner.X);
tex_width /= texture_width * 2.f;
tex_height = float(sourceRect.LowerRightCorner.Y - sourceRect.UpperLeftCorner.Y);
tex_height /= texture_height * 2.f;
if (textureisRTT)
tex_height = -tex_height;
const f32 invW = 1.f / static_cast<f32>(texture_width);
const f32 invH = 1.f / static_cast<f32>(texture_height);
const core::rect<f32> tcoords(
sourceRect.UpperLeftCorner.X * invW,
sourceRect.UpperLeftCorner.Y * invH,
sourceRect.LowerRightCorner.X * invW,
sourceRect.LowerRightCorner.Y *invH);
}
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)
{
if (!irr_driver->isGLSL()) {
video::SColor duplicatedArray[4] = {
colors, colors, colors, colors
};
draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height), colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, bool useAlphaChannelOfTexture)
{
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize((int)texture_w, (int)texture_h, true,
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height),
colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
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)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DImage(texture, destRect, sourceRect, clipRect, colors, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
if (colors)
drawTexColoredQuad(texture, colors, width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
else
drawTexQuad(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName(), width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
void draw2DVertexPrimitiveList(video::ITexture *tex, const void* vertices,
u32 vertexCount, const void* indexList, u32 primitiveCount,
video::E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, video::E_INDEX_TYPE iType)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);
return;
}
GLuint tmpvao, tmpvbo, tmpibo;
primitiveCount += 2;
glGenVertexArrays(1, &tmpvao);
glBindVertexArray(tmpvao);
glGenBuffers(1, &tmpvbo);
glBindBuffer(GL_ARRAY_BUFFER, tmpvbo);
glBufferData(GL_ARRAY_BUFFER, vertexCount * getVertexPitchFromType(vType), vertices, GL_STREAM_DRAW);
glGenBuffers(1, &tmpibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tmpibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, primitiveCount * sizeof(u16), indexList, GL_STREAM_DRAW);
VertexUtils::bindVertexArrayAttrib(vType);
glUseProgram(UIShader::Primitive2DList::getInstance()->Program);
UIShader::Primitive2DList::getInstance()->setUniforms();
const video::SOverrideMaterial &m = irr_driver->getVideoDriver()->getOverrideMaterial();
compressTexture(tex, false);
UIShader::Primitive2DList::getInstance()->SetTextureUnits({ getTextureGLuint(tex) });
glDrawElements(GL_TRIANGLE_FAN, primitiveCount, GL_UNSIGNED_SHORT, 0);
glDeleteVertexArrays(1, &tmpvao);
glDeleteBuffers(1, &tmpvbo);
glDeleteBuffers(1, &tmpibo);
}
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position,
const core::rect<s32>* clip)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip);
return;
}
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
float center_pos_x = float(position.UpperLeftCorner.X + position.LowerRightCorner.X);
center_pos_x /= screen_w;
center_pos_x -= 1;
float center_pos_y = float(position.UpperLeftCorner.Y + position.LowerRightCorner.Y);
center_pos_y /= screen_h;
center_pos_y = 1 - center_pos_y;
float width = float(position.LowerRightCorner.X - position.UpperLeftCorner.X);
width /= screen_w;
float height = float(position.LowerRightCorner.Y - position.UpperLeftCorner.Y);
height /= screen_h;
if (color.getAlpha() < 255)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clip)
{
if (!clip->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y,
clip->getWidth(), clip->getHeight());
}
glUseProgram(UIShader::ColoredRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::ColoredRectShader::getInstance()->setUniforms(core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), color);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
if (clip)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}

33
src/graphics/2dutils.hpp Normal file
View File

@ -0,0 +1,33 @@
#ifndef UTILS2D_HPP
#define UTILS2D_HPP
#include "gl_headers.hpp"
#include <rect.h>
#include <SColor.h>
#include <S3DVertex.h>
#include <SVertexIndex.h>
#include <EPrimitiveTypes.h>
#include <ITexture.h>
#include <irrTypes.h>
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
const irr::core::rect<irr::s32>& destRect,
const irr::core::rect<irr::s32>& sourceRect, const irr::core::rect<irr::s32>* clipRect,
const irr::video::SColor &colors, bool useAlphaChannelOfTexture);
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<irr::s32>& destRect,
const irr::core::rect<irr::s32>& sourceRect, const irr::core::rect<irr::s32>* clipRect,
const irr::video::SColor &color, bool useAlphaChannelOfTexture);
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<irr::s32>& destRect,
const irr::core::rect<irr::s32>& sourceRect, const irr::core::rect<irr::s32>* clipRect,
const irr::video::SColor* const colors, bool useAlphaChannelOfTexture);
void draw2DVertexPrimitiveList(irr::video::ITexture *t, const void* vertices,
irr::u32 vertexCount, const void* indexList, irr::u32 primitiveCount,
irr::video::E_VERTEX_TYPE vType = irr::video::EVT_STANDARD, irr::scene::E_PRIMITIVE_TYPE pType = irr::scene::EPT_TRIANGLES, irr::video::E_INDEX_TYPE iType = irr::video::EIT_16BIT);
void GL32_draw2DRectangle(irr::video::SColor color, const irr::core::rect<irr::s32>& position,
const irr::core::rect<irr::s32>* clip = 0);
#endif

View File

@ -372,7 +372,9 @@ void Camera::smoothMoveCamera(float dt)
if (race_manager->getNumLocalPlayers() < 2)
{
SFXManager::get()->positionListener(current_position, current_target - current_position);
SFXManager::get()->positionListener(current_position,
current_target - current_position,
Vec3(0,1,0));
}
} // smoothMoveCamera
@ -578,7 +580,8 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle,
if (race_manager->getNumLocalPlayers() < 2)
{
SFXManager::get()->positionListener(m_camera->getPosition(),
wanted_target - m_camera->getPosition());
wanted_target - m_camera->getPosition(),
Vec3(0, 1, 0));
}
}

View File

@ -6,9 +6,6 @@
#include "utils/profiler.hpp"
#include "utils/cpp2011.hpp"
#include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h"
#include <fstream>
#include <string>
#include <sstream>
@ -122,159 +119,6 @@ void initGL()
#endif
}
static std::string LoadHeader()
{
std::string result;
std::ifstream Stream(file_manager->getAsset("shaders/header.txt").c_str(), std::ios::in);
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
result += "\n" + Line;
Stream.close();
}
return result;
}
// Mostly from shader tutorial
GLuint LoadShader(const char * file, unsigned type)
{
GLuint Id = glCreateShader(type);
char versionString[20];
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
std::string Code = versionString;
if (irr_driver->hasVSLayerExtension())
Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
if (UserConfigParams::m_azdo)
Code += "#extension GL_ARB_bindless_texture : enable\n";
else
{
Code += "#extension GL_ARB_bindless_texture : disable\n";
Code += "#undef GL_ARB_bindless_texture\n";
}
std::ifstream Stream(file, std::ios::in);
Code += "//" + std::string(file) + "\n";
if (irr_driver->needUBOWorkaround())
Code += "#define UBO_DISABLED\n";
if (irr_driver->hasVSLayerExtension())
Code += "#define VSLayer\n";
if (irr_driver->needsRGBBindlessWorkaround())
Code += "#define SRGBBindlessFix\n";
Code += LoadHeader();
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
Code += "\n" + Line;
Stream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
Log::info("GLWrap", "Compiling shader : %s", file);
char const * SourcePointer = Code.c_str();
int length = (int)strlen(SourcePointer);
glShaderSource(Id, 1, &SourcePointer, &length);
glCompileShader(Id);
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);
if(InfoLogLength<0)
InfoLogLength = 1024;
char *ErrorMessage = new char[InfoLogLength];
ErrorMessage[0]=0;
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Id;
}
void setAttribute(AttributeType Tp, GLuint ProgramID)
{
switch (Tp)
{
case OBJECT:
glBindAttribLocation(ProgramID, 0, "Position");
glBindAttribLocation(ProgramID, 1, "Normal");
glBindAttribLocation(ProgramID, 2, "Color");
glBindAttribLocation(ProgramID, 3, "Texcoord");
glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
glBindAttribLocation(ProgramID, 5, "Tangent");
glBindAttribLocation(ProgramID, 6, "Bitangent");
glBindAttribLocation(ProgramID, 7, "Origin");
glBindAttribLocation(ProgramID, 8, "Orientation");
glBindAttribLocation(ProgramID, 9, "Scale");
break;
case PARTICLES_SIM:
glBindAttribLocation(ProgramID, 0, "particle_position");
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "particle_velocity");
glBindAttribLocation(ProgramID, 3, "size");
glBindAttribLocation(ProgramID, 4, "particle_position_initial");
glBindAttribLocation(ProgramID, 5, "lifetime_initial");
glBindAttribLocation(ProgramID, 6, "particle_velocity_initial");
glBindAttribLocation(ProgramID, 7, "size_initial");
break;
case PARTICLES_RENDERING:
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "size");
glBindAttribLocation(ProgramID, 4, "quadcorner");
glBindAttribLocation(ProgramID, 5, "rotationvec");
glBindAttribLocation(ProgramID, 6, "anglespeed");
break;
}
}
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
{
GLuint Program = glCreateProgram();
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
if (irr_driver->getGLSLVersion() < 330)
setAttribute(PARTICLES_SIM, Program);
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(Program);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(Program, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE)
{
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Program;
}
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF)
{
glActiveTexture(GL_TEXTURE0 + TextureUnit);
glBindTexture(GL_TEXTURE_2D, TextureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, allowAF ? (float)aniso : 1.0f);
glGetError();
}
ScopedGPUTimer::ScopedGPUTimer(GPUTimer &t) : timer(t)
{
if (!UserConfigParams::m_profiler_enabled) return;
@ -417,305 +261,7 @@ void draw3DLine(const core::vector3df& start,
glGetError();
}
static void drawTexColoredQuad(const video::ITexture *texture, const video::SColor *col, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
unsigned colors[] = {
col[0].getRed(), col[0].getGreen(), col[0].getBlue(), col[0].getAlpha(),
col[1].getRed(), col[1].getGreen(), col[1].getBlue(), col[1].getAlpha(),
col[2].getRed(), col[2].getGreen(), col[2].getBlue(), col[2].getAlpha(),
col[3].getRed(), col[3].getGreen(), col[3].getBlue(), col[3].getAlpha(),
};
glBindBuffer(GL_ARRAY_BUFFER, UIShader::ColoredTextureRectShader::getInstance()->colorvbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(unsigned), colors);
glUseProgram(UIShader::ColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(UIShader::ColoredTextureRectShader::getInstance()->vao);
UIShader::ColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
UIShader::ColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGetError();
}
static
void drawTexQuad(GLuint texture, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
glUseProgram(UIShader::TextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::TextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
UIShader::TextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y),
core::vector2df(tex_width, tex_height));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGetError();
}
static void
getSize(unsigned texture_width, unsigned texture_height, bool textureisRTT,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect,
float &width, float &height,
float &center_pos_x, float &center_pos_y,
float &tex_width, float &tex_height,
float &tex_center_pos_x, float &tex_center_pos_y
)
{
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
center_pos_x = float(destRect.UpperLeftCorner.X + destRect.LowerRightCorner.X);
center_pos_x /= screen_w;
center_pos_x -= 1.;
center_pos_y = float(destRect.UpperLeftCorner.Y + destRect.LowerRightCorner.Y);
center_pos_y /= screen_h;
center_pos_y = float(1.f - center_pos_y);
width = float(destRect.LowerRightCorner.X - destRect.UpperLeftCorner.X);
width /= screen_w;
height = float(destRect.LowerRightCorner.Y - destRect.UpperLeftCorner.Y);
height /= screen_h;
tex_center_pos_x = float(sourceRect.UpperLeftCorner.X + sourceRect.LowerRightCorner.X);
tex_center_pos_x /= texture_width * 2.f;
tex_center_pos_y = float(sourceRect.UpperLeftCorner.Y + sourceRect.LowerRightCorner.Y);
tex_center_pos_y /= texture_height * 2.f;
tex_width = float(sourceRect.LowerRightCorner.X - sourceRect.UpperLeftCorner.X);
tex_width /= texture_width * 2.f;
tex_height = float(sourceRect.LowerRightCorner.Y - sourceRect.UpperLeftCorner.Y);
tex_height /= texture_height * 2.f;
if (textureisRTT)
tex_height = -tex_height;
const f32 invW = 1.f / static_cast<f32>(texture_width);
const f32 invH = 1.f / static_cast<f32>(texture_height);
const core::rect<f32> tcoords(
sourceRect.UpperLeftCorner.X * invW,
sourceRect.UpperLeftCorner.Y * invH,
sourceRect.LowerRightCorner.X * invW,
sourceRect.LowerRightCorner.Y *invH);
}
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)
{
if (!irr_driver->isGLSL()) {
video::SColor duplicatedArray[4] = {
colors, colors, colors, colors
};
draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height), colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, bool useAlphaChannelOfTexture)
{
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize((int)texture_w, (int)texture_h, true,
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height),
colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
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)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DImage(texture, destRect, sourceRect, clipRect, colors, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
if (colors)
drawTexColoredQuad(texture, colors, width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
else
drawTexQuad(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName(), width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position,
const core::rect<s32>* clip)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip);
return;
}
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
float center_pos_x = float(position.UpperLeftCorner.X + position.LowerRightCorner.X);
center_pos_x /= screen_w;
center_pos_x -= 1;
float center_pos_y = float(position.UpperLeftCorner.Y + position.LowerRightCorner.Y);
center_pos_y /= screen_h;
center_pos_y = 1 - center_pos_y;
float width = float(position.LowerRightCorner.X - position.UpperLeftCorner.X);
width /= screen_w;
float height = float(position.LowerRightCorner.Y - position.UpperLeftCorner.Y);
height /= screen_h;
if (color.getAlpha() < 255)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clip)
{
if (!clip->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y,
clip->getWidth(), clip->getHeight());
}
glUseProgram(UIShader::ColoredRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::ColoredRectShader::getInstance()->setUniforms(core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), color);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
if (clip)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
bool hasGLExtension(const char* extension)
bool hasGLExtension(const char* extension)
{
if (glGetStringi != NULL)
{

View File

@ -15,78 +15,7 @@ namespace HardwareStats
}
void initGL();
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
video::ITexture* getUnicolorTexture(const video::SColor &c);
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>
void printFileList()
{
return;
}
template<typename ...Types>
void printFileList(GLint ShaderType, const char *filepath, Types ... args)
{
Log::error("GLWrapp", filepath);
printFileList(args...);
}
enum AttributeType
{
OBJECT,
PARTICLES_SIM,
PARTICLES_RENDERING,
};
void setAttribute(AttributeType Tp, GLuint ProgramID);
template<typename ... Types>
GLint LoadProgram(AttributeType Tp, Types ... args)
{
GLint ProgramID = glCreateProgram();
loadAndAttach(ProgramID, args...);
if (irr_driver->getGLSLVersion() < 330)
setAttribute(Tp, ProgramID);
glLinkProgram(ProgramID);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE) {
Log::error("GLWrapp", "Error when linking these shaders :");
printFileList(args...);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrapp", ErrorMessage);
delete[] ErrorMessage;
}
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
return ProgramID;
}
class GPUTimer;
@ -132,30 +61,74 @@ public:
void BlitToDefault(size_t, size_t, size_t, size_t);
};
// core::rect<s32> needs these includes
#include <rect.h>
class VertexUtils
{
public:
static void bindVertexArrayAttrib(enum video::E_VERTEX_TYPE tp)
{
switch (tp)
{
case video::EVT_STANDARD:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
break;
case video::EVT_2TCOORDS:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
// SecondTexcoord
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)36);
break;
case video::EVT_TANGENTS:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
// Tangent
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)36);
// Bitangent
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)48);
break;
}
}
};
#include "utils/vec3.hpp"
#include "texturemanager.hpp"
void draw3DLine(const core::vector3df& start,
const core::vector3df& end, irr::video::SColor color);
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, 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 &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);
void GL32_draw2DRectangle(irr::video::SColor color, const irr::core::rect<s32>& position,
const irr::core::rect<s32>* clip = 0);
bool hasGLExtension(const char* extension);
const std::string getGLExtensions();
void getGLLimits(HardwareStats::Json *json);

View File

@ -27,13 +27,13 @@ HitSFX::HitSFX(const Vec3& coord, const char* explosion_sound)
: HitEffect()
{
m_sfx = SFXManager::get()->createSoundSource( explosion_sound );
m_sfx->position(coord);
m_sfx->setPosition(coord);
// in multiplayer mode, sounds are NOT positional (because we have
// multiple listeners) so the sounds of all AIs are constantly heard.
// Therefore reduce volume of sounds.
float vol = race_manager->getNumLocalPlayers() > 1 ? 0.5f : 1.0f;
m_sfx->volume(vol);
m_sfx->setVolume(vol);
m_sfx->play();
} // HitSFX
@ -42,10 +42,7 @@ HitSFX::HitSFX(const Vec3& coord, const char* explosion_sound)
*/
HitSFX::~HitSFX()
{
if (m_sfx->getStatus() == SFXManager::SFX_PLAYING)
m_sfx->stop();
SFXManager::get()->deleteSFX(m_sfx);
m_sfx->deleteSFX();
} // ~HitEffect
//-----------------------------------------------------------------------------
@ -56,7 +53,7 @@ HitSFX::~HitSFX()
void HitSFX::setPlayerKartHit()
{
if(race_manager->getNumLocalPlayers())
m_sfx->volume(1.0f);
m_sfx->setVolume(1.0f);
} // setPlayerKartHit
//-----------------------------------------------------------------------------
@ -67,7 +64,6 @@ void HitSFX::setPlayerKartHit()
*/
bool HitSFX::updateAndDelete(float dt)
{
SFXManager::SFXStatus status = m_sfx->getStatus();
if(status==SFXManager::SFX_INITIAL) return false;
return status!= SFXManager::SFX_PLAYING;
SFXBase::SFXStatus status = m_sfx->getStatus();
return status!= SFXBase::SFX_PLAYING;
} // updateAndDelete

View File

@ -22,6 +22,7 @@
#include "graphics/callbacks.hpp"
#include "graphics/camera.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
#include "graphics/hardware_skinning.hpp"
#include "graphics/lens_flare.hpp"
#include "graphics/light.hpp"
@ -2279,7 +2280,7 @@ void IrrDriver::RTTProvider::setupRTTScene(PtrVector<scene::IMesh, REF>& mesh,
node->setAnimationSpeed(0);
node->updateAbsolutePosition();
node->setScale( mesh_scale[n].toIrrVector() );
//std::cout << "(((( set frame " << model_frames[n] << " ))))\n";
//Log::info("RTTProvider::setupRTTScene", "Set frame %d", model_frames[n]);
}
}

View File

@ -57,8 +57,7 @@ Material::Material(const XMLNode *node, bool deprecated)
m_shader_type = SHADERTYPE_SOLID;
m_deprecated = deprecated;
node->get("name", &m_texname);
node->get("name", &m_texname);
if (m_texname=="")
{
throw std::runtime_error("[Material] No texture name specified "
@ -66,6 +65,7 @@ Material::Material(const XMLNode *node, bool deprecated)
}
init();
node->get("lazy-load", &m_lazy_load);
bool b = false;
node->get("clampu", &b); if (b) m_clamp_tex |= UCLAMP; //blender 2.4 style
@ -412,10 +412,10 @@ Material::Material(const std::string& fname, bool is_full_path,
*/
void Material::init()
{
m_lazy_load = false;
m_texture = NULL;
m_clamp_tex = 0;
m_shader_type = SHADERTYPE_SOLID;
//m_lightmap = false;
//m_adjust_image = ADJ_NONE;
m_backface_culling = true;
m_high_tire_adhesion = false;
m_below_surface = false;
@ -455,6 +455,9 @@ void Material::init()
//-----------------------------------------------------------------------------
void Material::install(bool is_full_path, bool complain_if_not_found)
{
// Don't load a texture that is lazily loaded.
if(m_lazy_load) return;
const std::string &full_path = is_full_path
? m_texname
: file_manager->searchTexture(m_texname);
@ -643,14 +646,14 @@ void Material::setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) con
if (speed < 0) speed = -speed;
// If we paused it due to too low speed earlier, we can continue now.
if (sfx->getStatus() == SFXManager::SFX_PAUSED)
if (sfx->getStatus() == SFXBase::SFX_PAUSED)
{
if (speed<m_sfx_min_speed || should_be_paused == 1) return;
// TODO: Do we first need to stop the sound completely so it
// starts over?
sfx->play();
}
else if (sfx->getStatus() == SFXManager::SFX_PLAYING)
else if (sfx->getStatus() == SFXBase::SFX_PLAYING)
{
if (speed<m_sfx_min_speed || should_be_paused == 1)
{
@ -661,12 +664,12 @@ void Material::setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) con
}
if (speed > m_sfx_max_speed)
{
sfx->speed(m_sfx_max_pitch);
sfx->setSpeed(m_sfx_max_pitch);
return;
}
float f = m_sfx_pitch_per_speed*(speed-m_sfx_min_speed) + m_sfx_min_pitch;
sfx->speed(f);
sfx->setSpeed(f);
} // setSFXSpeed
//-----------------------------------------------------------------------------

View File

@ -22,13 +22,11 @@
#include "utils/no_copy.hpp"
#include <assert.h>
#include <map>
#include <string>
#include <vector>
#include <IShaderConstantSetCallBack.h>
namespace irr
{
namespace video { class ITexture; class SMaterial; }
@ -81,9 +79,18 @@ public:
private:
/** Pointer to the texture. */
video::ITexture *m_texture;
//unsigned int m_index;
/** Name of the texture. */
std::string m_texname;
/** If true, the texture will not automatically be loaded and bound
* at load time, it must be loaded elsewhere. This is used to store
* material settings for font textures, without loading fonts for
* languages that might not be needed at all. */
bool m_lazy_load;
/** Name of a special sfx to play when a kart is on this terrain, or
* "" if no special sfx exists. */
std::string m_sfx_name;
@ -114,7 +121,7 @@ private:
/** If a kart is rescued when driving on this surface. */
bool m_drive_reset;
/** True if this is a texture that will start the jump animatoin when
/** True if this is a texture that will start the jump animation when
* leaving it and being in the air. */
bool m_is_jump_texture;
@ -244,27 +251,45 @@ public:
void setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) const;
void setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* mb);
void adjustForFog(scene::ISceneNode* parent, video::SMaterial *m, bool use_fog) const;
void adjustForFog(scene::ISceneNode* parent, video::SMaterial *m,
bool use_fog) const;
void onMadeVisible(scene::IMeshBuffer* who);
void onHidden(scene::IMeshBuffer* who);
void isInitiallyHidden(scene::IMeshBuffer* who);
/** Returns the ITexture associated with this material. */
video::ITexture *getTexture() const { return m_texture; }
video::ITexture *getTexture() const
{
// Note that atm lazy load means that the textures are not loaded
// via the material. So getTexture should only get called for non
// lazily loaded textures (used atm for font textures.
assert(!m_lazy_load);
return m_texture;
} // getTexture
// ------------------------------------------------------------------------
bool isIgnore () const { return m_ignore; }
// ------------------------------------------------------------------------
/** Returns true if this material is a zipper. */
bool isZipper () const { return m_zipper; }
// ------------------------------------------------------------------------
/** Returns if this material should trigger a rescue if a kart
* is driving on it. */
bool isDriveReset () const { return m_drive_reset; }
// ------------------------------------------------------------------------
/** Returns if this material should trigger a rescue if a kart
* crashes against it. */
CollisionReaction getCollisionReaction() const { return m_collision_reaction; }
// ------------------------------------------------------------------------
std::string getCrashResetParticles() const { return m_collision_particles; }
// ------------------------------------------------------------------------
bool highTireAdhesion () const { return m_high_tire_adhesion; }
// ------------------------------------------------------------------------
const std::string&
getTexFname () const { return m_texname; }
//int getIndex () const { return m_index; }
// ------------------------------------------------------------------------
bool isTransparent () const
{
return m_shader_type == SHADERTYPE_ADDITIVE ||
@ -272,12 +297,6 @@ public:
m_shader_type == SHADERTYPE_ALPHA_TEST;
}
// ------------------------------------------------------------------------
/** Returns true if this materials need pre-multiply of alpha. */
//bool isPreMul() const {return m_adjust_image==ADJ_PREMUL; }
// ------------------------------------------------------------------------
/** Returns true if this materials need pre-division of alpha. */
//bool isPreDiv() const {return m_adjust_image==ADJ_DIV; }
// ------------------------------------------------------------------------
/** Returns the fraction of maximum speed on this material. */
float getMaxSpeedFraction() const { return m_max_speed_fraction; }
@ -300,17 +319,20 @@ public:
// ------------------------------------------------------------------------
/** Returns the name of a special sfx to play while a kart is on this
* terrain. The string will be "" if no special sfx exists. */
const std::string &
getSFXName () const { return m_sfx_name; }
const std::string &getSFXName() const { return m_sfx_name; }
// ------------------------------------------------------------------------
/** Returns if fog is enabled. */
bool isFogEnabled() const { return m_fog; }
/**
* \brief Get the kind of particles that are to be used on this material, in the given conditions
* \return The particles to use, or NULL if none
*/
const ParticleKind* getParticlesWhen(ParticleConditions cond) const { return m_particles_effects[cond]; }
// ------------------------------------------------------------------------
/** \brief Get the kind of particles that are to be used on this material,
* in the given conditions.
* \return The particles to use, or NULL if none. */
const ParticleKind* getParticlesWhen(ParticleConditions cond) const
{
return m_particles_effects[cond];
} // getParticlesWhen
// ------------------------------------------------------------------------
/** Returns true if a kart falling over this kind of material triggers
* the special falling camera. */
@ -346,9 +368,6 @@ public:
// ------------------------------------------------------------------------
ShaderType getShaderType() const { return m_shader_type; }
// ------------------------------------------------------------------------
void onMadeVisible(scene::IMeshBuffer* who);
void onHidden(scene::IMeshBuffer* who);
void isInitiallyHidden(scene::IMeshBuffer* who);
} ;

View File

@ -22,6 +22,8 @@
#include <IMeshBuffer.h>
#include "utils/log.hpp"
#include "graphics/irr_driver.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
@ -325,7 +327,8 @@ bool MeshTools::isNormalMap(scene::IMeshBuffer* mb)
{
if (!irr_driver->isGLSL())
return false;
return (mb->getMaterial().MaterialType == irr_driver->getShader(ES_NORMAL_MAP));
return (mb->getMaterial().MaterialType == irr_driver->getShader(ES_NORMAL_MAP) &&
mb->getVertexType() != video::EVT_TANGENTS);
}
// Copied from irrlicht
@ -385,28 +388,28 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predic
{
switch (vType)
{
case video::EVT_STANDARD:
{
const video::S3DVertex* v =
(const video::S3DVertex*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
case video::EVT_STANDARD:
{
const video::S3DVertex* v =
(const video::S3DVertex*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
case video::EVT_2TCOORDS:
{
const video::S3DVertex2TCoords* v =
(const video::S3DVertex2TCoords*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
case video::EVT_2TCOORDS:
{
const video::S3DVertex2TCoords* v =
(const video::S3DVertex2TCoords*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
case video::EVT_TANGENTS:
{
const video::S3DVertexTangents* v =
(const video::S3DVertexTangents*)original->getVertices();
vNew = v[idx[i]];
}
case video::EVT_TANGENTS:
{
const video::S3DVertexTangents* v =
(const video::S3DVertexTangents*)original->getVertices();
vNew = v[idx[i]];
}
break;
}
core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
@ -435,8 +438,28 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predic
if (calculateTangents)
recalculateTangents(clone, recalculateNormals, smooth, angleWeighted);
int mbcount = clone->getMeshBufferCount();
for (int i = 0; i < mbcount; i++)
{
scene::IMeshBuffer* mb = clone->getMeshBuffer(i);
for (int t = 0; t < video::MATERIAL_MAX_TEXTURES; t++)
{
video::ITexture* texture = mb->getMaterial().TextureLayer[t].Texture;
if (texture != NULL)
texture->grab();
}
}
scene::IMeshCache* meshCache = irr_driver->getSceneManager()->getMeshCache();
io::SNamedPath path = meshCache->getMeshName(mesh);
irr_driver->removeMeshFromCache(mesh);
scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
meshCache->addMesh(path, amesh);
World::getWorld()->getTrack()->addCachedMesh(amesh);
return clone;
}

View File

@ -221,19 +221,19 @@ void renderBloom(GLuint in)
DrawFullScreenEffect<FullScreenShader::BloomShader>();
}
void PostProcessing::renderDiffuseEnvMap(const float *bSHCoeff, const float *gSHCoeff, const float *rSHCoeff)
void PostProcessing::renderEnvMap(const float *bSHCoeff, const float *gSHCoeff, const float *rSHCoeff, GLuint skybox)
{
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glUseProgram(FullScreenShader::DiffuseEnvMapShader::getInstance()->Program);
glUseProgram(FullScreenShader::EnvMapShader::getInstance()->Program);
glBindVertexArray(SharedObject::FullScreenQuadVAO);
FullScreenShader::DiffuseEnvMapShader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH)));
FullScreenShader::EnvMapShader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), skybox));
core::matrix4 TVM = irr_driver->getViewMatrix().getTransposed();
FullScreenShader::DiffuseEnvMapShader::getInstance()->setUniforms(TVM, std::vector<float>(bSHCoeff, bSHCoeff + 9), std::vector<float>(gSHCoeff, gSHCoeff + 9), std::vector<float>(rSHCoeff, rSHCoeff + 9));
FullScreenShader::EnvMapShader::getInstance()->setUniforms(TVM, std::vector<float>(bSHCoeff, bSHCoeff + 9), std::vector<float>(gSHCoeff, gSHCoeff + 9), std::vector<float>(rSHCoeff, rSHCoeff + 9));
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
@ -662,7 +662,8 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, boo
// Blend
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glBlendColor(0., 0., 0., track->getGodRaysOpacity());
glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
in_fbo->Bind();

View File

@ -81,7 +81,7 @@ public:
void renderFog();
void renderSSAO();
void renderDiffuseEnvMap(const float *bSHCoeff, const float *gSHCoeff, const float *rSHCoeff);
void renderEnvMap(const float *bSHCoeff, const float *gSHCoeff, const float *rSHCoeff, unsigned skycubemap);
void renderRHDebug(unsigned SHR, unsigned SHG, unsigned SHB, const core::matrix4 &rh_matrix, const core::vector3df &rh_extend);
void renderGI(const core::matrix4 &RHMatrix, const core::vector3df &rh_extend, unsigned shr, unsigned shg, unsigned shb);

View File

@ -75,7 +75,7 @@ struct DefaultMaterial
};
const std::vector<size_t> DefaultMaterial::FirstPassTextures = { 1 };
const std::vector<size_t> DefaultMaterial::SecondPassTextures = { 0 };
const std::vector<size_t> DefaultMaterial::SecondPassTextures = { 0, 1 };
struct AlphaRef
{
@ -93,7 +93,7 @@ struct AlphaRef
};
const std::vector<size_t> AlphaRef::FirstPassTextures = { 0, 1 };
const std::vector<size_t> AlphaRef::SecondPassTextures = { 0 };
const std::vector<size_t> AlphaRef::SecondPassTextures = { 0, 1 };
struct SphereMap
{
@ -146,8 +146,8 @@ struct GrassMat
static const std::vector<size_t> SecondPassTextures;
};
const std::vector<size_t> GrassMat::FirstPassTextures = { 0 };
const std::vector<size_t> GrassMat::SecondPassTextures = { 0 };
const std::vector<size_t> GrassMat::FirstPassTextures = { 0, 1 };
const std::vector<size_t> GrassMat::SecondPassTextures = { 0, 1 };
struct NormalMat
{
@ -165,7 +165,7 @@ struct NormalMat
};
const std::vector<size_t> NormalMat::FirstPassTextures = { 2, 1 };
const std::vector<size_t> NormalMat::SecondPassTextures = { 0 };
const std::vector<size_t> NormalMat::SecondPassTextures = { 0, 1 };
struct DetailMat
{
@ -183,7 +183,7 @@ struct DetailMat
};
const std::vector<size_t> DetailMat::FirstPassTextures = { 1 };
const std::vector<size_t> DetailMat::SecondPassTextures = { 0, 2 };
const std::vector<size_t> DetailMat::SecondPassTextures = { 0, 2, 1 };
struct SplattingMat
{
@ -531,15 +531,15 @@ void IrrDriver::renderSolidSecondPass()
if (UserConfigParams::m_azdo)
{
multidraw2ndPass<DefaultMaterial>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
multidraw2ndPass<AlphaRef>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
multidraw2ndPass<DefaultMaterial>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0));
multidraw2ndPass<AlphaRef>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0));
multidraw2ndPass<SphereMap>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
multidraw2ndPass<UnlitMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
multidraw2ndPass<GrassMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, DepthHandle, 0), windDir, cb->getPosition());
multidraw2ndPass<GrassMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, DepthHandle, 0, 0), windDir, cb->getPosition());
multidraw2ndPass<NormalMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
multidraw2ndPass<DetailMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0));
multidraw2ndPass<NormalMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0));
multidraw2ndPass<DetailMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0, 0));
}
else if (irr_driver->hasARB_draw_indirect())
{

View File

@ -9,6 +9,7 @@
#include "modes/world.hpp"
#include "tracks/track.hpp"
#include "utils/profiler.hpp"
#include "callbacks.hpp"
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
@ -114,6 +115,7 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
glDisable(GL_BLEND);
m_rtts->getRH().Bind();
glBindVertexArray(SharedObject::FullScreenQuadVAO);
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
if (irr_driver->needRHWorkaround())
{
glUseProgram(FullScreenShader::NVWorkaroundRadianceHintsConstructionShader::getInstance()->Program);
@ -121,7 +123,7 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
createVector<GLuint>(m_rtts->getRSM().getRTT()[0], m_rtts->getRSM().getRTT()[1], m_rtts->getRSM().getDepthTexture()));
for (unsigned i = 0; i < 32; i++)
{
FullScreenShader::NVWorkaroundRadianceHintsConstructionShader::getInstance()->setUniforms(rsm_matrix, rh_matrix, rh_extend, i);
FullScreenShader::NVWorkaroundRadianceHintsConstructionShader::getInstance()->setUniforms(rsm_matrix, rh_matrix, rh_extend, i, video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue()));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
@ -135,7 +137,7 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
m_rtts->getRSM().getDepthTexture()
)
);
FullScreenShader::RadianceHintsConstructionShader::getInstance()->setUniforms(rsm_matrix, rh_matrix, rh_extend);
FullScreenShader::RadianceHintsConstructionShader::getInstance()->setUniforms(rsm_matrix, rh_matrix, rh_extend, video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue()));
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32);
}
}
@ -152,13 +154,13 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
}
m_rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).Bind();
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP));
m_post_processing->renderDiffuseEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff);
m_post_processing->renderEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff, SkyboxCubeMap);
}
m_rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).Bind();
// Render sunlight if and only if track supports shadow
if (!World::getWorld() || World::getWorld()->getTrack()->hasShadows())
{

View File

@ -123,6 +123,145 @@ Shaders::Shaders()
loadShaders();
}
// Shader loading related hook
static std::string LoadHeader()
{
std::string result;
std::ifstream Stream(file_manager->getAsset("shaders/header.txt").c_str(), std::ios::in);
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
result += "\n" + Line;
Stream.close();
}
return result;
}
// Mostly from shader tutorial
GLuint LoadShader(const char * file, unsigned type)
{
GLuint Id = glCreateShader(type);
char versionString[20];
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
std::string Code = versionString;
if (irr_driver->hasVSLayerExtension())
Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
if (UserConfigParams::m_azdo)
Code += "#extension GL_ARB_bindless_texture : enable\n";
else
{
Code += "#extension GL_ARB_bindless_texture : disable\n";
Code += "#undef GL_ARB_bindless_texture\n";
}
std::ifstream Stream(file, std::ios::in);
Code += "//" + std::string(file) + "\n";
if (irr_driver->needUBOWorkaround())
Code += "#define UBO_DISABLED\n";
if (irr_driver->hasVSLayerExtension())
Code += "#define VSLayer\n";
if (irr_driver->needsRGBBindlessWorkaround())
Code += "#define SRGBBindlessFix\n";
Code += LoadHeader();
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
Code += "\n" + Line;
Stream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
Log::info("GLWrap", "Compiling shader : %s", file);
char const * SourcePointer = Code.c_str();
int length = (int)strlen(SourcePointer);
glShaderSource(Id, 1, &SourcePointer, &length);
glCompileShader(Id);
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);
if (InfoLogLength<0)
InfoLogLength = 1024;
char *ErrorMessage = new char[InfoLogLength];
ErrorMessage[0] = 0;
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Id;
}
void setAttribute(AttributeType Tp, GLuint ProgramID)
{
switch (Tp)
{
case OBJECT:
glBindAttribLocation(ProgramID, 0, "Position");
glBindAttribLocation(ProgramID, 1, "Normal");
glBindAttribLocation(ProgramID, 2, "Color");
glBindAttribLocation(ProgramID, 3, "Texcoord");
glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
glBindAttribLocation(ProgramID, 5, "Tangent");
glBindAttribLocation(ProgramID, 6, "Bitangent");
glBindAttribLocation(ProgramID, 7, "Origin");
glBindAttribLocation(ProgramID, 8, "Orientation");
glBindAttribLocation(ProgramID, 9, "Scale");
break;
case PARTICLES_SIM:
glBindAttribLocation(ProgramID, 0, "particle_position");
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "particle_velocity");
glBindAttribLocation(ProgramID, 3, "size");
glBindAttribLocation(ProgramID, 4, "particle_position_initial");
glBindAttribLocation(ProgramID, 5, "lifetime_initial");
glBindAttribLocation(ProgramID, 6, "particle_velocity_initial");
glBindAttribLocation(ProgramID, 7, "size_initial");
break;
case PARTICLES_RENDERING:
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "size");
glBindAttribLocation(ProgramID, 4, "quadcorner");
glBindAttribLocation(ProgramID, 5, "rotationvec");
glBindAttribLocation(ProgramID, 6, "anglespeed");
break;
}
}
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
{
GLuint Program = glCreateProgram();
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
if (irr_driver->getGLSLVersion() < 330)
setAttribute(PARTICLES_SIM, Program);
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(Program);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(Program, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE)
{
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Program;
}
GLuint quad_vbo, tri_vbo;
GLuint SharedObject::FullScreenQuadVAO = 0;
@ -787,7 +926,7 @@ namespace MeshShader
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());
AssignUniforms("ModelMatrix", "InverseModelMatrix", "windDir");
AssignSamplerNames(Program, 0, "tex");
AssignSamplerNames(Program, 0, "tex", 1, "glosstex");
}
NormalMapShader::NormalMapShader()
@ -832,7 +971,7 @@ namespace MeshShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_objectref_pass1.frag").c_str());
AssignUniforms("windDir");
AssignSamplerNames(Program, 0, "tex");
AssignSamplerNames(Program, 0, "tex", 1, "glosstex");
}
InstancedNormalMapShader::InstancedNormalMapShader()
@ -854,7 +993,7 @@ namespace MeshShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str());
AssignUniforms("ModelMatrix", "TextureMatrix");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
InstancedObjectPass2Shader::InstancedObjectPass2Shader()
@ -865,7 +1004,7 @@ namespace MeshShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_object_pass2.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
InstancedObjectRefPass2Shader::InstancedObjectRefPass2Shader()
@ -876,7 +1015,7 @@ namespace MeshShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_objectref_pass2.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
DetailledObjectPass2Shader::DetailledObjectPass2Shader()
@ -886,7 +1025,7 @@ namespace MeshShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/detailledobject_pass2.frag").c_str());
AssignUniforms("ModelMatrix");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "Detail");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "Detail", 5, "SpecMap");
}
InstancedDetailledObjectPass2Shader::InstancedDetailledObjectPass2Shader()
@ -897,7 +1036,7 @@ namespace MeshShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_detailledobject_pass2.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "Detail");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "Detail", 5, "SpecMap");
}
ObjectUnlitShader::ObjectUnlitShader()
@ -926,7 +1065,7 @@ namespace MeshShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
AssignUniforms("ModelMatrix", "TextureMatrix");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
GrassPass2Shader::GrassPass2Shader()
@ -936,7 +1075,7 @@ namespace MeshShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/grass_pass2.frag").c_str());
AssignUniforms("ModelMatrix", "windDir");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "Albedo", 4, "SpecMap");
}
InstancedGrassPass2Shader::InstancedGrassPass2Shader()
@ -947,7 +1086,7 @@ namespace MeshShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/instanced_grass_pass2.frag").c_str());
AssignUniforms("windDir", "SunDir");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "dtex", 4, "Albedo");
AssignSamplerNames(Program, 0, "DiffuseMap", 1, "SpecularMap", 2, "SSAO", 3, "dtex", 4, "Albedo", 5, "SpecMap");
}
SphereMapShader::SphereMapShader()
@ -1455,14 +1594,15 @@ namespace FullScreenShader
AssignUniforms("direction", "col");
}
DiffuseEnvMapShader::DiffuseEnvMapShader()
EnvMapShader::EnvMapShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/diffuseenvmap.frag").c_str());
AssignUniforms("TransposeViewMatrix", "blueLmn[0]", "greenLmn[0]", "redLmn[0]");
AssignSamplerNames(Program, 0, "ntex");
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 2, "tex");
}
ShadowedSunLightShader::ShadowedSunLightShader()
@ -1495,7 +1635,7 @@ namespace FullScreenShader
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rh.frag").c_str());
}
AssignUniforms("RSMMatrix", "RHMatrix", "extents");
AssignUniforms("RSMMatrix", "RHMatrix", "extents", "suncol");
AssignSamplerNames(Program, 0, "ctex", 1, "ntex", 2, "dtex");
}
@ -1506,7 +1646,7 @@ namespace FullScreenShader
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/rhpassthrough.geom").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rh.frag").c_str());
AssignUniforms("RSMMatrix", "RHMatrix", "extents", "slice");
AssignUniforms("RSMMatrix", "RHMatrix", "extents", "slice", "suncol");
AssignSamplerNames(Program, 0, "ctex", 1, "ntex", 2, "dtex");
}
@ -1748,6 +1888,16 @@ namespace FullScreenShader
namespace UIShader
{
Primitive2DList::Primitive2DList()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/primitive2dlist.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparent.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex");
}
TextureRectShader::TextureRectShader()
{
Program = LoadProgram(OBJECT,

View File

@ -65,7 +65,7 @@ public:
ObjectRefPass1Shader();
};
class GrassPass1Shader : public ShaderHelperSingleton<GrassPass1Shader, core::matrix4, core::matrix4, core::vector3df>, public TextureRead<Trilinear_Anisotropic_Filtered>
class GrassPass1Shader : public ShaderHelperSingleton<GrassPass1Shader, core::matrix4, core::matrix4, core::vector3df>, public TextureRead<Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
GrassPass1Shader();
@ -89,7 +89,7 @@ public:
InstancedObjectRefPass1Shader();
};
class InstancedGrassPass1Shader : public ShaderHelperSingleton<InstancedGrassPass1Shader, core::vector3df>, public TextureRead<Trilinear_Anisotropic_Filtered>
class InstancedGrassPass1Shader : public ShaderHelperSingleton<InstancedGrassPass1Shader, core::vector3df>, public TextureRead<Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
InstancedGrassPass1Shader();
@ -101,31 +101,31 @@ public:
InstancedNormalMapShader();
};
class ObjectPass2Shader : public ShaderHelperSingleton<ObjectPass2Shader, core::matrix4, core::matrix4>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered>
class ObjectPass2Shader : public ShaderHelperSingleton<ObjectPass2Shader, core::matrix4, core::matrix4>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
ObjectPass2Shader();
};
class InstancedObjectPass2Shader : public ShaderHelperSingleton<InstancedObjectPass2Shader>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered>
class InstancedObjectPass2Shader : public ShaderHelperSingleton<InstancedObjectPass2Shader>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
InstancedObjectPass2Shader();
};
class InstancedObjectRefPass2Shader : public ShaderHelperSingleton<InstancedObjectRefPass2Shader>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered>
class InstancedObjectRefPass2Shader : public ShaderHelperSingleton<InstancedObjectRefPass2Shader>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
InstancedObjectRefPass2Shader();
};
class DetailledObjectPass2Shader : public ShaderHelperSingleton<DetailledObjectPass2Shader, core::matrix4>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
class DetailledObjectPass2Shader : public ShaderHelperSingleton<DetailledObjectPass2Shader, core::matrix4>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
DetailledObjectPass2Shader();
};
class InstancedDetailledObjectPass2Shader : public ShaderHelperSingleton<InstancedDetailledObjectPass2Shader>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
class InstancedDetailledObjectPass2Shader : public ShaderHelperSingleton<InstancedDetailledObjectPass2Shader>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
InstancedDetailledObjectPass2Shader();
@ -143,19 +143,19 @@ public:
InstancedObjectUnlitShader();
};
class ObjectRefPass2Shader : public ShaderHelperSingleton<ObjectRefPass2Shader, core::matrix4, core::matrix4>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered>
class ObjectRefPass2Shader : public ShaderHelperSingleton<ObjectRefPass2Shader, core::matrix4, core::matrix4>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
ObjectRefPass2Shader();
};
class GrassPass2Shader : public ShaderHelperSingleton<GrassPass2Shader, core::matrix4, core::vector3df>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered>
class GrassPass2Shader : public ShaderHelperSingleton<GrassPass2Shader, core::matrix4, core::vector3df>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
GrassPass2Shader();
};
class InstancedGrassPass2Shader : public ShaderHelperSingleton<InstancedGrassPass2Shader, core::vector3df, core::vector3df>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Nearest_Filtered, Trilinear_Anisotropic_Filtered>
class InstancedGrassPass2Shader : public ShaderHelperSingleton<InstancedGrassPass2Shader, core::vector3df, core::vector3df>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Bilinear_Filtered, Nearest_Filtered, Trilinear_Anisotropic_Filtered, Trilinear_Anisotropic_Filtered>
{
public:
InstancedGrassPass2Shader();
@ -395,10 +395,10 @@ public:
SunLightShader();
};
class DiffuseEnvMapShader : public ShaderHelperSingleton<DiffuseEnvMapShader, core::matrix4, std::vector<float>, std::vector<float>, std::vector<float> >, public TextureRead<Nearest_Filtered>
class EnvMapShader : public ShaderHelperSingleton<EnvMapShader, core::matrix4, std::vector<float>, std::vector<float>, std::vector<float> >, public TextureRead<Nearest_Filtered, Nearest_Filtered, Trilinear_cubemap>
{
public:
DiffuseEnvMapShader();
EnvMapShader();
};
class ShadowedSunLightShader : public ShaderHelperSingleton<ShadowedSunLightShader, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Shadow_Sampler>
@ -407,14 +407,14 @@ public:
ShadowedSunLightShader();
};
class RadianceHintsConstructionShader : public ShaderHelperSingleton<RadianceHintsConstructionShader, core::matrix4, core::matrix4, core::vector3df>, public TextureRead<Bilinear_Filtered, Bilinear_Filtered, Bilinear_Filtered>
class RadianceHintsConstructionShader : public ShaderHelperSingleton<RadianceHintsConstructionShader, core::matrix4, core::matrix4, core::vector3df, video::SColorf>, public TextureRead<Bilinear_Filtered, Bilinear_Filtered, Bilinear_Filtered>
{
public:
RadianceHintsConstructionShader();
};
// Workaround for a bug found in kepler nvidia linux and fermi nvidia windows
class NVWorkaroundRadianceHintsConstructionShader : public ShaderHelperSingleton<NVWorkaroundRadianceHintsConstructionShader, core::matrix4, core::matrix4, core::vector3df, int>, public TextureRead<Bilinear_Filtered, Bilinear_Filtered, Bilinear_Filtered>
class NVWorkaroundRadianceHintsConstructionShader : public ShaderHelperSingleton<NVWorkaroundRadianceHintsConstructionShader, core::matrix4, core::matrix4, core::vector3df, int, video::SColorf>, public TextureRead<Bilinear_Filtered, Bilinear_Filtered, Bilinear_Filtered>
{
public:
NVWorkaroundRadianceHintsConstructionShader();
@ -580,6 +580,13 @@ public:
namespace UIShader
{
class Primitive2DList : public ShaderHelperSingleton<Primitive2DList>, public TextureRead < Bilinear_Filtered >
{
public:
Primitive2DList();
};
class TextureRectShader : public ShaderHelperSingleton<TextureRectShader, core::vector2df, core::vector2df, core::vector2df, core::vector2df>, public TextureRead<Bilinear_Filtered>
{
public:

View File

@ -12,6 +12,77 @@ bool needsUBO();
unsigned getGLSLVersion();
GLuint LoadShader(const char * file, unsigned type);
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
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>
void printFileList()
{
return;
}
template<typename ...Types>
void printFileList(GLint ShaderType, const char *filepath, Types ... args)
{
Log::error("GLWrapp", filepath);
printFileList(args...);
}
enum AttributeType
{
OBJECT,
PARTICLES_SIM,
PARTICLES_RENDERING,
};
void setAttribute(AttributeType Tp, GLuint ProgramID);
template<typename ... Types>
GLint LoadProgram(AttributeType Tp, Types ... args)
{
GLint ProgramID = glCreateProgram();
loadAndAttach(ProgramID, args...);
if (getGLSLVersion() < 330)
setAttribute(Tp, ProgramID);
glLinkProgram(ProgramID);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE) {
Log::error("GLWrapp", "Error when linking these shaders :");
printFileList(args...);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrapp", ErrorMessage);
delete[] ErrorMessage;
}
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
return ProgramID;
}
struct UniformHelper
{
template<unsigned N = 0>

View File

@ -325,7 +325,8 @@ void STKMeshSceneNode::render()
irr_driver->getRenderTargetTexture(RTT_DIFFUSE),
irr_driver->getRenderTargetTexture(RTT_SPECULAR),
irr_driver->getRenderTargetTexture(RTT_HALF1_R),
getTextureGLuint(mesh.textures[0])));
getTextureGLuint(mesh.textures[0]),
getTextureGLuint(mesh.textures[1])));
MeshShader::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);

View File

@ -1,6 +1,7 @@
#include "vaomanager.hpp"
#include "irr_driver.hpp"
#include "stkmesh.hpp"
#include "glwrap.hpp"
VAOManager::VAOManager()
{
@ -121,61 +122,8 @@ void VAOManager::regenerateVAO(enum VTXTYPE tp)
glGenVertexArrays(1, &vao[tp]);
glBindVertexArray(vao[tp]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
switch (tp)
{
case VTXTYPE_COUNT: break; // avoid compiler warning
case VTXTYPE_STANDARD:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
break;
case VTXTYPE_TCOORD:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
// SecondTexcoord
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
break;
case VTXTYPE_TANGENT:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
// Tangent
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
// Bitangent
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48);
break;
}
VertexUtils::bindVertexArrayAttrib(getVertexType(tp));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
glBindVertexArray(0);
@ -319,6 +267,20 @@ VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type)
}
};
irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp)
{
switch (tp)
{
default:
case VTXTYPE_STANDARD:
return video::EVT_STANDARD;
case VTXTYPE_TCOORD:
return video::EVT_2TCOORDS;
case VTXTYPE_TANGENT:
return video::EVT_TANGENTS;
}
}
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
{
size_t old_vtx_cnt = last_vertex[tp];

View File

@ -154,6 +154,7 @@ class VAOManager : public Singleton<VAOManager>
void regenerateInstancedVAO();
size_t getVertexPitch(enum VTXTYPE) const;
VTXTYPE getVTXTYPE(irr::video::E_VERTEX_TYPE type);
irr::video::E_VERTEX_TYPE getVertexType(enum VTXTYPE tp);
void append(irr::scene::IMeshBuffer *, VTXTYPE tp);
public:
VAOManager();

View File

@ -51,11 +51,11 @@ Weather::Weather(bool lightning, std::string sound)
Weather::~Weather()
{
if (m_thunder_sound != NULL)
SFXManager::get()->deleteSFX(m_thunder_sound);
m_thunder_sound->deleteSFX();
if (m_weather_sound != NULL)
SFXManager::get()->deleteSFX(m_weather_sound);
}
m_weather_sound->deleteSFX();
} // ~Weather
// ----------------------------------------------------------------------------

View File

@ -9,7 +9,7 @@
#include "IVideoDriver.h"
#include "ITexture.h"
#include <cassert>
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
namespace irr
{

View File

@ -93,8 +93,8 @@ void AbstractStateManager::pushMenu(std::string name)
if (UserConfigParams::logGUI())
{
std::cout << "[AbstractStateManager::pushMenu] switching to screen "
<< name.c_str() << std::endl;
Log::info("AbstractStateManager::pushMenu", "Switching to screen %s",
name.c_str());
}
// Send tear-down event to previous menu
@ -125,8 +125,8 @@ void AbstractStateManager::pushScreen(Screen* screen)
if (UserConfigParams::logGUI())
{
std::cout << "[AbstractStateManager::pushScreen] switching to screen "
<< screen->getName().c_str() << std::endl;
Log::info("AbstractStateManager::pushScreen", "Switching to screen %s",
screen->getName().c_str());
}
if (!screen->isLoaded()) screen->loadFromFile();
@ -152,8 +152,8 @@ void AbstractStateManager::replaceTopMostScreen(Screen* screen, GUIEngine::GameS
if (UserConfigParams::logGUI())
{
std::cout << "[AbstractStateManager::replaceTopmostScreen] "
"switching to screen " << name.c_str() << std::endl;
Log::info("AbstractStateManager::replaceTopMostScreen", "Switching to screen %s",
name.c_str());
}
assert(m_menu_stack.size() > 0);
@ -215,8 +215,8 @@ void AbstractStateManager::popMenu()
if (UserConfigParams::logGUI())
{
std::cout << "[AbstractStateManager::popMenu] switching to screen "
<< m_menu_stack[m_menu_stack.size()-1].c_str() << std::endl;
Log::info("AbstractStateManager::popMenu", "Switching to screen %s",
m_menu_stack[m_menu_stack.size()-1].c_str());
}
if (m_menu_stack[m_menu_stack.size()-1] == RACE_STATE_NAME)
@ -247,10 +247,8 @@ void AbstractStateManager::resetAndGoToScreen(Screen* screen)
std::string name = screen->getName();
if (UserConfigParams::logGUI())
{
std::cout << "[AbstractStateManager::resetAndGoToScreen] "
"switching to screen " << name.c_str() << std::endl;
}
Log::info("AbstractStateManager::resetAndGoToScreen", "Switching to screen %s",
name.c_str());
if (m_game_mode != GAME) getCurrentScreen()->tearDown();
m_menu_stack.clear();

View File

@ -167,6 +167,10 @@ namespace GUIEngine
virtual void onTopMostScreenChanged() = 0;
// --------------------------------------------------------------------
/** Returns the number of screens on the stack. Is used to decide
* if exiting a screen would cause STK to end or not. */
unsigned int getMenuStackSize() const { return m_menu_stack.size(); }
}; // Class AbstractStateManager
} // GUIEngine

View File

@ -72,18 +72,16 @@ void AbstractTopLevelContainer::addWidgetsRecursively(
widgets[n].getType() != WTYPE_ICON_BUTTON &&
widgets[n].getType() != WTYPE_SPACER)
{
std::cerr << "/!\\ Warning /!\\ : widget "
<< widgets[n].m_properties[PROP_ID].c_str()
<< " of type " << widgets[n].getType()
<< " has no dimensions" << std::endl;
Log::warn("AbstractTopLevelContainer::addWidgetsRecursively",
"Widget %s of type %d has no dimensions",
widgets[n].m_properties[PROP_ID].c_str(), widgets[n].getType());
}
if (widgets[n].m_x == -1 || widgets[n].m_y == -1)
{
std::cerr << "/!\\ Warning /!\\ : widget "
<< widgets[n].m_properties[PROP_ID].c_str()
<< " of type " << widgets[n].getType()
<< " has no position" << std::endl;
Log::warn("AbstractTopLevelContainer::addWidgetsRecursively",
"Widget %s of type %d has no position",
widgets[n].m_properties[PROP_ID].c_str(), widgets[n].getType());
}
widgets[n].add();
@ -197,10 +195,8 @@ Widget* AbstractTopLevelContainer::getWidget(const int id,
if (widget.searchInsideMe() && widget.getChildren().size() > 0)
{
// std::cout << "widget = <"
// << widget.m_properties[PROP_ID].c_str()
// << "> widget.m_children.size()="
// << widget.m_children.size() << std::endl;
//Log::info("AbstractTopLevelContainer", "widget = <%s> widget.m_children.size() = ",
// widget.m_properties[PROP_ID].c_str(), widget.m_children.size());
Widget* el = getWidget(id, &(widget.m_children));
if(el != NULL) return el;
}

View File

@ -657,7 +657,7 @@ namespace GUIEngine
#include "guiengine/engine.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/2dutils.hpp"
#include "input/input_manager.hpp"
#include "io/file_manager.hpp"
#include "guiengine/event_handler.hpp"
@ -1019,12 +1019,10 @@ namespace GUIEngine
g_skin->drop(); // GUI env grabbed it
assert(g_skin->getReferenceCount() == 1);
}
catch (std::runtime_error& err)
catch (std::runtime_error& /*err*/)
{
(void)err; // avoid warning about unused variable
std::cerr <<
"ERROR, cannot load skin specified in user config. Falling "
"back to defaults.\n";
Log::error("Engine::init", "Cannot load skin specified in user config. "
"Falling back to defaults.");
UserConfigParams::m_skin_file.revertToDefaults();
try
@ -1036,8 +1034,7 @@ namespace GUIEngine
}
catch (std::runtime_error& err)
{
std::cerr << "FATAL, cannot load default GUI skin\n";
throw err;
Log::fatal("Engine::init", "Canot load default GUI skin");
}
}
@ -1135,10 +1132,9 @@ namespace GUIEngine
// one so that the fallback skin is not dropped
newSkin = new Skin(fallbackSkin);
}
catch (std::runtime_error& err)
catch (std::runtime_error& /*err*/)
{
(void)err; // avoid warning about unused variable
std::cerr << "ERROR, cannot load newly specified skin!\n";
Log::error("Engine::reloadSkin", "Canot load newly specified skin");
return;
}
@ -1369,8 +1365,8 @@ namespace GUIEngine
}
else
{
std::cerr << "WARNING: GUIEngine::addLoadingIcon given "
"NULL icon\n";
Log::warn("Engine::addLoadingIcon", "Given "
"NULL icon");
}
} // addLoadingIcon

View File

@ -184,6 +184,15 @@ bool EventHandler::OnEvent (const SEvent &event)
// FIXME? it may be a bit unclean that all input events go trough
// the gui module
const EventPropagation blockPropagation = input_manager->input(event);
if (event.EventType == EET_KEY_INPUT_EVENT &&
event.KeyInput.Key == irr::KEY_TAB)
{
// block all tab events, if we let them go, irrlicht will try
// to apply its own focus code
return true; // EVENT_BLOCK
}
return blockPropagation == EVENT_BLOCK;
}
else if (event.EventType == EET_LOG_TEXT_EVENT)
@ -199,7 +208,7 @@ bool EventHandler::OnEvent (const SEvent &event)
// mode ignore this error message, but leave it in for debugging.
if(std::string(event.LogEvent.Text)=="Unsupported texture format")
#ifdef DEBUG
printf("The following message will not be printed in release mode:\n");
Log::info("EventHandler", "The following message will not be printed in release mode");
#else
return true; // EVENT_BLOCK
#endif
@ -414,7 +423,7 @@ void EventHandler::navigate(const int playerID, Input::InputType type, const boo
if (el == NULL)
{
std::cerr << "WARNING : m_tab_down/up_root is set to an ID for which I can't find the widget\n";
Log::warn("EventHandler::navigate", "m_tab_down/up_root is set to an ID for which I can't find the widget");
return;
}
}
@ -448,7 +457,7 @@ void EventHandler::navigate(const int playerID, Input::InputType type, const boo
if (NAVIGATION_DEBUG)
{
std::cout << "Navigating " << (reverse ? "up" : "down") << " to " << closest->getID() << std::endl;
Log::info("EventHandler", "Navigating %s to %d", (reverse ? "up" : "down"), closest->getID());
}
assert(closestWidget != NULL);
@ -474,7 +483,7 @@ void EventHandler::navigate(const int playerID, Input::InputType type, const boo
if (!found)
{
if (NAVIGATION_DEBUG)
std::cout << "EventHandler::navigat : wrap around\n";
Log::info( "EventHandler::navigate", "Wrap around");
// select the last/first widget
Widget* wrapWidget = NULL;
@ -529,7 +538,7 @@ EventPropagation EventHandler::onWidgetActivated(GUIEngine::Widget* w, const int
if (w->m_event_handler == NULL) return EVENT_LET;
}
//std::cout << "**** widget activated : " << w->m_properties[PROP_ID].c_str() << " ****" << std::endl;
//Log::info("EventHandler", "Widget activated: %s", w->m_properties[PROP_ID].c_str());
if (w->m_event_handler != NULL)
{

View File

@ -21,9 +21,6 @@
#include <IGUIFont.h>
#include <ITexture.h>
using namespace irr;
using namespace gui;
using namespace video;
#include "graphics/irr_driver.hpp"
#include "guiengine/abstract_top_level_container.hpp"
@ -35,6 +32,9 @@ using namespace video;
#include "utils/string_utils.hpp"
#include "utils/vs.hpp"
using namespace irr;
using namespace gui;
using namespace video;
using namespace GUIEngine;
/** Like atoi, but on error prints an error message to stderr */
@ -420,7 +420,7 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
horizontal = false;
else
{
std::cerr << "Unknown layout name : " << layout_name.c_str() << std::endl;
Log::error("LayoutManager::doCalculateLayout", "Unknown layout name: %s", layout_name.c_str());
break;
}
@ -475,11 +475,9 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
int proportion = 1;
std::istringstream myStream(prop);
if (!(myStream >> proportion))
{
std::cerr << "/!\\ Warning /!\\ : proportion '" << prop.c_str()
<< "' is not a number for widget " << widgets[n].m_properties[PROP_ID].c_str()
<< std::endl;
}
Log::warn("LayoutManager::doCalculateLayout",
"Proportion '%s' is not a number for widget %s", prop.c_str(),
widgets[n].m_properties[PROP_ID].c_str());
const float fraction = (float)proportion/(float)total_proportion;
@ -522,9 +520,9 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
}
else
{
std::cerr << "/!\\ Warning /!\\ : alignment '" << align.c_str()
<< "' is unknown (widget '" << widgets[n].m_properties[PROP_ID].c_str()
<< "', in a horiozntal-row layout)\n";
Log::warn("LayoutManager::doCalculateLayout",
"Alignment '%s' is unknown (widget '%s', in a horiozntal-row layout)",
align.c_str(), widgets[n].m_properties[PROP_ID].c_str());
}
widgets[n].m_w = (int)(left_space*fraction);
@ -597,9 +595,9 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
}
else
{
std::cerr << "/!\\ Warning /!\\ : alignment '" << align.c_str()
<< "' is unknown (widget '" << widgets[n].m_properties[PROP_ID].c_str()
<< "', in a vertical-row layout)\n";
Log::warn("LayoutManager::doCalculateLayout",
"Alignment '%s' is unknown (widget '%s', in a vertical-row layout)",
align.c_str(), widgets[n].m_properties[PROP_ID].c_str());
}
widgets[n].m_y = y;
@ -651,9 +649,9 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
}
else
{
std::cerr << "/!\\ Warning /!\\ : alignment '" << align.c_str()
<< "' is unknown in widget " << widgets[n].m_properties[PROP_ID].c_str()
<< std::endl;
Log::warn("LayoutManager::doCalculateLayout",
"Alignment '%s' is unknown in widget '%s'",
align.c_str(), widgets[n].m_properties[PROP_ID].c_str());
}
x += widgets[n].m_w;
@ -697,8 +695,9 @@ void LayoutManager::doCalculateLayout(PtrVector<Widget>& widgets, AbstractTopLev
}
else
{
std::cerr << "/!\\ Warning /!\\ : alignment '" << align.c_str()
<< "' is unknown in widget " << widgets[n].m_properties[PROP_ID].c_str() << std::endl;
Log::warn("LayoutManager::doCalculateLayout",
"Alignment '%s' is unknown in widget '%s'",
align.c_str(), widgets[n].m_properties[PROP_ID].c_str());
}
widgets[n].m_y = y;

View File

@ -95,7 +95,7 @@ std::priority_queue<Message*, std::vector<Message*>,
float g_current_display_time = -1.0f;
/** How long the current message should be displaed. */
float g_max_display_time = -1.0f;
float g_max_display_time = 5.0f;
/** The label widget used to show the current message. */
SkinWidgetContainer *g_container = NULL;

View File

@ -13,7 +13,7 @@
#include "guiengine/engine.hpp"
#include "io/file_manager.hpp"
#include "utils/translation.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
namespace irr
{
@ -101,7 +101,7 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
/*
const wchar_t* iflangis = xml->getAttributeValue(L"iflanguage");
printf("langcode = %s\n", translations->getCurrentLanguageCode().c_str());
Log::info("ScalableFont", "langcode = %s", translations->getCurrentLanguageCode().c_str());
if (iflangis != NULL &&
core::stringc(iflangis) != translations->getCurrentLanguageCode().c_str())
@ -128,8 +128,10 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
float scale=1.0f;
if(xml->getAttributeValue(L"scale"))
{
scale = xml->getAttributeValueAsFloat(L"scale");
//std::cout << "scale = " << scale << std::endl;
//Log::info("ScalableFont", "scale = %f", scale);
}
bool excludeFromMaxHeightCalculation = false;
if (xml->getAttributeValue(L"excludeFromMaxHeightCalculation"))
@ -137,7 +139,7 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
//std::cout << "---- Adding font texture " << fn.c_str() << "; alpha=" << alpha.c_str() << std::endl;
//Log::info("ScalableFont", "Adding font texture %s; alpha = %s", fn.c_str(), alpha.c_str());
// make sure the sprite bank has enough textures in it
@ -227,7 +229,7 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
CharacterMap[ch] = Areas.size();
//std::cout << "Inserting character '" << (int)ch << "' with area " << Areas.size() << std::endl;
//Log::info("ScalableFont", "Inserting character '%d' with area %d", (int)ch, Areas.size());
// make frame
f.rectNumber = SpriteBank->getPositions().size();
@ -366,18 +368,18 @@ s32 ScalableFont::getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) c
if (n != CharacterMap.end())
{
if (fallback_font != NULL) *fallback_font = false;
// std::cout << "Character " << (int)c << " found in font\n";
//Log::info("ScalableFont", "Character %d found in font", (int)c);
return (*n).second;
}
else if (m_fallback_font != NULL && fallback_font != NULL)
{
// std::cout << "Font does not have this character : <" << (int)c << ">, trying fallback font" << std::endl;
//Log::warn("ScalableFont", "Font does not have this character: <%d>, try fallback font", (int)c);
*fallback_font = true;
return m_fallback_font->getAreaIDFromCharacter(c, NULL);
}
else
{
// std::cout << "The font does not have this character : <" << (int)c << ">" << std::endl;
//Log::warn("ScalableFont", "The font does not have this character: <%d>", (int)c);
if (fallback_font != NULL) *fallback_font = false;
return WrongCharacter;
}
@ -453,12 +455,12 @@ core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
dim.Height += thisLine.Height;
if (dim.Width < thisLine.Width) dim.Width = thisLine.Width;
// std::cout << "ScalableFont::getDimension returns : " << dim.Width << ", " << dim.Height << " --> ";
//Log::info("ScalableFont", "ScalableFont::getDimension returns: %d, %d", dim.Width, dim.Height);
dim.Width = (int)(dim.Width + 0.9f); // round up
dim.Height = (int)(dim.Height + 0.9f);
//std::cout << dim.Width << ", " << dim.Height << std::endl;
//Log::info("ScalableFont", "After: %d, %d", dim.Width, dim.Height);
return dim;
}
@ -616,10 +618,9 @@ void ScalableFont::doDraw(const core::stringw& text,
/*
if (fallback[n])
{
std::cout << "USING fallback font " << core::stringc(texture->getName()).c_str()
<< "; source area is " << source.UpperLeftCorner.X << ", " << source.UpperLeftCorner.Y
<< ", size " << source.getWidth() << ", " << source.getHeight() << "; dest = "
<< offsets[n].X << ", " << offsets[n].Y << std::endl;
Log::info("ScalableFont", "Using fallback font %s; source area is %d, %d; size %d, %d; dest = %d, %d",
core::stringc(texture->getName()).c_str(), source.UpperLeftCorner.X, source.UpperLeftCorner.Y,
source.getWidth(), source.getHeight(), offsets[n].X, offsets[n].Y);
}
*/
@ -773,7 +774,7 @@ int ScalableFont::getCharWidth(const SFontArea& area, const bool fallback) const
assert(info.m_file_name.size() > 0);
const float char_scale = info.m_scale;
//std::cout << "area.spriteno=" << area.spriteno << ", char_scale=" << char_scale << std::endl;
//Log::info("ScalableFont", "area.spriteno = %d, char_scale = %f", area.spriteno, char_scale);
if (fallback) return (int)(((area.width + area.overhang)*m_fallback_font_scale + m_fallback_kerning_width) * m_scale * char_scale);
else return (int)((area.width + area.overhang + GlobalKerningWidth) * m_scale * char_scale);

View File

@ -187,11 +187,11 @@ void Screen::addWidgets()
addWidgetsRecursively( m_widgets );
//std::cout << "*****ScreenAddWidgets " << m_filename.c_str() << " : focusing the first widget*****\n";
//Log::info("Screen::AddWidgets", "%s: focusing the first widget", m_filename.c_str());
// select the first widget (for first players only; if other players need some focus the Screen must provide it).
Widget* w = getFirstWidget();
//std::cout << "First widget is " << (w == NULL ? "null" : w->m_properties[PROP_ID].c_str()) << std::endl;
//Log::info("Screen::AddWidgets", "First widget is %s", (w == NULL ? "null" : w->m_properties[PROP_ID].c_str()));
if (w != NULL) w->setFocusForPlayer( PLAYER_ID_GAME_MASTER );
else Log::warn("Screen::AddWidgets", "Couldn't select first widget, NULL was returned");
} // addWidgets

View File

@ -181,8 +181,7 @@ void Screen::parseScreenFileDiv(irr::io::IXMLReader* xml, PtrVector<Widget>& app
}
else
{
std::cerr << "/!\\ Warning /!\\ : unknown tag found in STK GUI file : '"
<< xml->getNodeName() << "'" << std::endl;
Log::warn("Screen::parseScreenFileDiv", "unknown tag found in STK GUI file '%s'", xml->getNodeName());
continue;
}

View File

@ -23,7 +23,7 @@
#include <algorithm>
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/2dutils.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/modaldialog.hpp"
#include "guiengine/scalable_font.hpp"

View File

@ -12,8 +12,7 @@
//#include "os.h"
#include "Keycodes.h"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/2dutils.hpp"
#include "utils/translation.hpp"
#include "utils/time.hpp"

View File

@ -23,7 +23,6 @@
#include "utils/vs.hpp"
#include <IGUIEnvironment.h>
#include <sstream>
#include <iostream>
#include <algorithm>
@ -37,6 +36,7 @@ DynamicRibbonWidget::DynamicRibbonWidget(const bool combo, const bool multi_row)
m_needed_cols = 0;
m_col_amount = 0;
m_previous_item_count = 0;
m_max_label_length = 0;
m_multi_row = multi_row;
m_combo = combo;
m_has_label = false;
@ -45,6 +45,7 @@ DynamicRibbonWidget::DynamicRibbonWidget(const bool combo, const bool multi_row)
m_check_inside_me = true;
m_supports_multiplayer = true;
m_scrolling_enabled = true;
m_animated_contents = false;
// by default, set all players to have no selection in this ribbon
for (unsigned int n=0; n<MAX_PLAYER_COUNT; n++)
@ -61,7 +62,7 @@ DynamicRibbonWidget::DynamicRibbonWidget(const bool combo, const bool multi_row)
// -----------------------------------------------------------------------------
DynamicRibbonWidget::~DynamicRibbonWidget()
{
m_font->drop();
delete m_font;
if (m_animated_contents)
{
GUIEngine::needsUpdate.remove(this);
@ -257,9 +258,9 @@ void DynamicRibbonWidget::add()
const float score = log(2.0f*visible_items) *
std::min(ratio, 1.0f) * std::min(taken_area/total_area, 1.0f);
//std::cout << " " << row_count << " rows : " << visible_items << " visible items; area = "
// << taken_area << "; size penalty = " << std::min((float)item_height / (float)m_child_height, 1.0f)
// << "; score = " << score << "\n";
//Log::info("DynamicRibbonWidget", "%d rown: %d visible items; area = %f; "
// "size penalty = %f; score = %f", row_count, visible_items, taken_area,
// std::min((float)item_height / (float)m_child_height, 1.0f), score);
if (score > max_score_so_far)
{
@ -275,8 +276,8 @@ void DynamicRibbonWidget::add()
const int max_rows = atoi(m_properties[PROP_MAX_ROWS].c_str());
if (max_rows < 1)
{
std::cout << "/!\\ WARNING : the 'max_rows' property must be an integer greater than zero."
<< " Ingoring current value '" << m_properties[PROP_MAX_ROWS] << "'\n";
Log::warn("DynamicRibbonWidget", "The 'max_rows' property must be an integer greater than zero; "
"Ignoring current value '%s'", m_properties[PROP_MAX_ROWS].c_str());
}
else
{
@ -299,7 +300,7 @@ void DynamicRibbonWidget::add()
for (int i=0; i<m_row_amount; i++)
{
m_ids[i] = getNewID();
//std::cout << "ribbon : getNewID returns " << m_ids[i] << std::endl;
//Log::info("DynamicRibbonWidget", "getNewID returns %d", m_ids[i]);
}
buildInternalStructure();
@ -333,11 +334,11 @@ void DynamicRibbonWidget::buildInternalStructure()
// ajust column amount to not add more item slots than we actually need
const int item_count = (int) m_items.size();
//std::cout << "item_count=" << item_count << ", row_amount*m_col_amount=" << m_row_amount*m_col_amount << std::endl;
//Log::info("DynamicRibbonWidget", "%d items; %d cells", item_count, row_amount * m_col_amount);
if (m_row_amount*m_col_amount > item_count)
{
m_col_amount = (int)ceil((float)item_count/(float)m_row_amount);
//std::cout << "Adjusting m_col_amount to be " << m_col_amount << std::endl;
//Log::info("DynamicRibbonWidget", "Adjusting m_col_amount to be %d", m_col_amount);
}
assert( m_left_widget->ok() );
@ -410,7 +411,7 @@ void DynamicRibbonWidget::buildInternalStructure()
// it will assume there is no label and none will be created (FIXME: that's ugly)
if (m_properties[PROP_LABELS_LOCATION] == "each") icon->m_text = " ";
// std::cout << "ribbon text = " << m_properties[PROP_TEXT].c_str() << std::endl;
//Log::info("DynamicRibbonWidget", "Ribbon text = %s", m_properties[PROP_TEXT].c_str());
ribbon->m_children.push_back( icon );
added_item_count++;
@ -611,12 +612,12 @@ EventPropagation DynamicRibbonWidget::rightPressed(const int playerID)
getSelectedRibbon(playerID)->getSelectionText(playerID), playerID);
}
}
//std::cout << "rightpressed (dynamic ribbon) " << m_properties[PROP_ID] << "\n";
//Log::info("DynamicRibbonWidget", "Rightpressed %s", m_properties[PROP_ID].c_str());
assert(m_rows.size() >= 1);
if (m_rows[0].m_ribbon_type == RIBBON_TOOLBAR) return EVENT_BLOCK;
//std::cout << " rightpressed returning EVENT_LET\n";
//Log::info("DynamicRibbonWidget", "Rightpressed returning EVENT_LET");
return EVENT_LET;
}
@ -681,7 +682,7 @@ EventPropagation DynamicRibbonWidget::transmitEvent(Widget* w,
EventPropagation DynamicRibbonWidget::mouseHovered(Widget* child, const int playerID)
{
if (m_deactivated) return EVENT_LET;
//std::cout << "DynamicRibbonWidget::mouseHovered " << playerID << std::endl;
//Log::info("DynamicRibbonWidget", "mouseHovered %d", playerID);
updateLabel();
propagateSelection();
@ -756,9 +757,9 @@ void DynamicRibbonWidget::onRibbonWidgetFocus(RibbonWidget* emitter, const int p
#pragma mark Setters / Actions
#endif
void DynamicRibbonWidget::scroll(const int x_delta)
void DynamicRibbonWidget::scroll(int x_delta, bool evenIfDeactivated)
{
if (m_deactivated) return;
if (m_deactivated && !evenIfDeactivated) return;
// Refuse to scroll when everything is visible
if ((int)m_items.size() <= m_row_amount*m_col_amount) return;
@ -1080,19 +1081,18 @@ bool DynamicRibbonWidget::setSelection(int item_id, const int playerID,
while (!findItemInRows(name.c_str(), &row, &id))
{
// if we get here it means the item is scrolled out. Try to find it.
scroll(1);
scroll(1, evenIfDeactivated);
if (iterations > 50)
{
assert(false);
std::cerr << "DynamicRibbonWidget::setSelection cannot find item " << item_id << " (" << name.c_str() << ")\n";
Log::error("DynamicRibbonWidget::setSelection", "Cannot find item %d (%s)", item_id, name.c_str());
return false;
}
iterations++;
}
//std::cout << "Player " << playerID << " has item " << item_id << " (" << name.c_str() << ") in row " << row << std::endl;
//Log::info("DynamicRibbonWidget", "Player %d has item %d (%s) in row %d", playerID, item_id, name.c_str(), row);
m_rows[row].setSelection(id, playerID);
if (focusIt)
{
@ -1158,8 +1158,8 @@ float DynamicRibbonWidget::getFontScale(int icon_width) const
irr::core::stringw DynamicRibbonWidget::getUserName(const irr::core::stringw& user_name) const
{
if (user_name.size() < MAX_LABEL_LENGTH)
if (m_max_label_length == 0 || user_name.size() < m_max_label_length)
return user_name;
else
return (user_name.subString(0, MAX_LABEL_LENGTH - 3) + L"...");
return (user_name.subString(0, m_max_label_length - 3) + L"...");
}

View File

@ -159,7 +159,7 @@ namespace GUIEngine
void buildInternalStructure();
/** Call this to scroll within a scrollable ribbon */
void scroll(const int x_delta);
void scroll(int x_delta, bool evenIfDeactivated = false);
/** Used for combo ribbons, to contain the ID of the currently selected item for each player */
int m_selected_item[MAX_PLAYER_COUNT];
@ -187,7 +187,7 @@ namespace GUIEngine
int m_max_label_width;
/** Max length of a label, in characters */
static const int MAX_LABEL_LENGTH = 30;
unsigned int m_max_label_length;
public:
@ -298,6 +298,9 @@ namespace GUIEngine
/** Set approximately how many items are expected to be in this ribbon; will help the layout
* algorithm next time add() is called */
void setItemCountHint(int hint) { m_item_count_hint = hint; }
/** Set max length of displayed text. */
void setMaxLabelLength(int length) { m_max_label_length = length; }
};
}

View File

@ -42,6 +42,7 @@ IconButtonWidget::IconButtonWidget(ScaleMode scale_mode, const bool tab_stop,
m_label = NULL;
m_font = NULL;
m_texture = NULL;
m_deactivated_texture = NULL;
m_highlight_texture = NULL;
m_custom_aspect_ratio = 1.0f;
@ -273,6 +274,56 @@ void IconButtonWidget::unfocused(const int playerID, Widget* new_focus)
m_label->setVisible(false);
}
}
// -----------------------------------------------------------------------------
const video::ITexture* IconButtonWidget::getTexture()
{
if (Widget::isActivated())
{
return m_texture;
}
else
{
if (m_deactivated_texture == NULL)
m_deactivated_texture = getDeactivatedTexture(m_texture);
return m_deactivated_texture;
}
}
// -----------------------------------------------------------------------------
video::ITexture* IconButtonWidget::getDeactivatedTexture(video::ITexture* texture)
{
video::ITexture* t;
std::string name = texture->getName().getPath().c_str();
name += "_disabled";
t = irr_driver->getTexture(name);
if (t == NULL)
{
SColor c;
u32 g;
video::IVideoDriver* driver = irr_driver->getVideoDriver();
std::auto_ptr<video::IImage> image (driver->createImageFromData (texture->getColorFormat(),
texture->getSize(), texture->lock(), false));
texture->unlock();
//Turn the image into grayscale
for (u32 x = 0; x < image->getDimension().Width; x++)
{
for (u32 y = 0; y < image->getDimension().Height; y++)
{
c = image->getPixel(x, y);
g = ((c.getRed() + c.getGreen() + c.getBlue()) / 3);
c.set(std::max (0, (int)c.getAlpha() - 120), g, g, g);
image->setPixel(x, y, c);
}
}
t = driver->addTexture(name.c_str(), image.get ());
}
return t;
}
// -----------------------------------------------------------------------------
void IconButtonWidget::setTexture(video::ITexture* texture)
@ -280,6 +331,7 @@ void IconButtonWidget::setTexture(video::ITexture* texture)
m_texture = texture;
if (texture == NULL)
{
m_deactivated_texture = NULL;
m_texture_w = 0;
m_texture_h = 0;
}

View File

@ -43,9 +43,11 @@ namespace GUIEngine
{
private:
irr::video::ITexture* m_texture;
irr::video::ITexture* m_deactivated_texture;
irr::video::ITexture* m_highlight_texture;
int m_texture_w, m_texture_h;
video::ITexture* getDeactivatedTexture(video::ITexture* texture);
void setLabelFont();
public:
@ -158,7 +160,7 @@ namespace GUIEngine
virtual void unfocused(const int playerID, Widget* new_focus);
// --------------------------------------------------------------------
/** Returns the texture of this button. */
const video::ITexture* getTexture() const { return m_texture; }
const video::ITexture* getTexture();
};
}

View File

@ -136,8 +136,9 @@ void ModelViewWidget::update(float delta)
distance_with_negative_rotation = (int)(angle - m_rotation_target);
}
//std::cout << "distance_with_positive_rotation=" << distance_with_positive_rotation <<
//" distance_with_negative_rotation=" << distance_with_negative_rotation << " angle="<< angle <<std::endl;
//Log::info("ModelViewWidget", "distance_with_positive_rotation = %d; "
// "distance_with_negative_rotation = %d; angle = %f", distance_with_positive_rotation,
// distance_with_negative_rotation, angle);
if (distance_with_positive_rotation < distance_with_negative_rotation)
{
@ -242,7 +243,7 @@ void ModelViewWidget::setupRTTScene(PtrVector<scene::IMesh, REF>& mesh,
node->setAnimationSpeed(0);
node->updateAbsolutePosition();
node->setScale(mesh_scale[n].toIrrVector());
//std::cout << "(((( set frame " << model_frames[n] << " ))))\n";
//Log::info("ModelViewWidget", "Set frame %d", model_frames[n]);
}
}

View File

@ -141,14 +141,8 @@ void RibbonWidget::add()
total_needed_space += m_active_children[i].m_w;
}
int free_w_space = m_w - total_needed_space;
//int biggest_y = 0;
const int button_y = 10;
float global_zoom = 1;
const int min_free_space = 50;
global_zoom = (float)m_w / (float)( m_w - free_w_space + min_free_space );
const int one_button_space =
int(roundf((float)m_w / (float)subbuttons_amount));
@ -320,22 +314,10 @@ void RibbonWidget::add()
float image_h = (float)image->getSize().Height;
float image_w = image_h*imageRatio;
// scale to fit (FIXME: calculate the right value directly...)
float zoom = global_zoom;
if (button_y + image_h*zoom + needed_space_under_button > m_h)
{
// scale down
while (button_y + image_h*zoom +
needed_space_under_button > m_h) zoom -= 0.01f;
}
else
{
// scale up
while (button_y + image_h*zoom +
needed_space_under_button < m_h) zoom += 0.01f;
}
float zoom = (float) (m_h - button_y - needed_space_under_button) / image_h;
float zoom_x = (float) one_button_space / image_w;
if(zoom_x < zoom)
zoom = zoom_x;
// ---- add bitmap button part
// backup and restore position in case the same object is added
@ -612,7 +594,7 @@ EventPropagation RibbonWidget::mouseHovered(Widget* child,
if (m_ribbon_type == RIBBON_COMBO || m_ribbon_type == RIBBON_TABS)
{
//std::cout << "SETTING m_mouse_focus\n";
//Log::info("RibbonWidget", "Setting m_mouse_focus");
m_mouse_focus = child;
}
@ -660,7 +642,6 @@ void RibbonWidget::updateSelection()
// FIXME: m_selection, m_selected, m_mouse_focus... what a mess...
//std::cout << "----\n";
// Update selection flags for mouse player
for (unsigned int p=0; p<MAX_PLAYER_COUNT; p++)
{

View File

@ -231,7 +231,7 @@ EventPropagation SpinnerWidget::rightPressed(const int playerID)
// if widget is deactivated, do nothing
if (m_deactivated) return EVENT_BLOCK;
//std::cout << "Right pressed\n";
//Log::info("SpinnerWidget", "Right pressed");
if (m_value+1 <= m_max)
{
setValue(m_value+1);
@ -253,7 +253,7 @@ EventPropagation SpinnerWidget::leftPressed(const int playerID)
// if widget is deactivated, do nothing
if (m_deactivated) return EVENT_BLOCK;
//std::cout << "Left pressed\n";
//Log::info("SpinnerWidget", "Left pressed");
if (m_value-1 >= m_min)
{
setValue(m_value-1);
@ -386,9 +386,7 @@ void SpinnerWidget::setValue(irr::core::stringw new_value)
}
}
std::cerr << "ERROR [SpinnerWidget::setValue] : cannot find element named '"
<< irr::core::stringc(new_value.c_str()).c_str() << "'\n";
assert(false);
Log::fatal("SpinnerWidget::setValue", "Cannot find element named '%s'", irr::core::stringc(new_value.c_str()).c_str());
}
// -----------------------------------------------------------------------------

View File

@ -145,9 +145,9 @@ void DeviceManager::setAssignMode(const PlayerAssignMode assignMode)
m_assign_mode = assignMode;
#if INPUT_MODE_DEBUG
if (assignMode == NO_ASSIGN) std::cout << "====== DeviceManager::setAssignMode(NO_ASSIGN) ======\n";
if (assignMode == ASSIGN) std::cout << "====== DeviceManager::setAssignMode(ASSIGN) ======\n";
if (assignMode == DETECT_NEW) std::cout << "====== DeviceManager::setAssignMode(DETECT_NEW) ======\n";
if (assignMode == NO_ASSIGN) Log::info("DeviceManager::setAssignMode(NO_ASSIGN)");
if (assignMode == ASSIGN) Log::info("DeviceManager::setAssignMode(ASSIGN)");
if (assignMode == DETECT_NEW) Log::info("DeviceManager::setAssignMode(DETECT_NEW)");
#endif
// when going back to no-assign mode, do some cleanup
@ -289,7 +289,7 @@ InputDevice* DeviceManager::mapKeyboardInput( int btnID, InputManager::InputDriv
{
const int keyboard_amount = m_keyboards.size();
//std::cout << "mapKeyboardInput " << btnID << " to " << keyboard_amount << " keyboards\n";
//Log::info("DeviceManager::mapKeyboardInput", "Map %d to %d", btnID, keyboard_amount);
for (int n=0; n<keyboard_amount; n++)
{
@ -297,10 +297,10 @@ InputDevice* DeviceManager::mapKeyboardInput( int btnID, InputManager::InputDriv
if (keyboard->processAndMapInput(btnID, mode, action))
{
//std::cout << " binding found in keyboard #" << (n+1) << "; action is " << KartActionStrings[*action] << "\n";
//Log::info("DeviceManager::mapKeyboardInput", "Binding found in keyboard #%d; action is %s", n + 1, KartActionStrings[*action]);
if (m_single_player != NULL)
{
//printf("Single player\n");
//Log::info("DeviceManager", "Single player");
*player = m_single_player;
}
else if (m_assign_mode == NO_ASSIGN) // Don't set the player in NO_ASSIGN mode
@ -423,7 +423,7 @@ InputDevice* DeviceManager::getLatestUsedDevice()
if (m_latest_used_device == NULL)
{
//std::cout<< "========== No latest device, returning keyboard ==========\n";
//Log::info("DeviceManager", "No latest device, returning keyboard);
return m_keyboards.get(0); // FIXME: is this right?
}

View File

@ -298,7 +298,7 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
int value)
{
#if INPUT_MODE_DEBUG
std::cout << "INPUT SENSING... ";
Log::info("InputManager::inputSensing", "Start sensing input");
#endif
// don't store if we're trying to do something like bindings keyboard
@ -310,7 +310,7 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
return;
#if INPUT_MODE_DEBUG
std::cout << (store_new ? "storing it" : "ignoring it") << "\n";
Log::info("InputManager::inputSensing", store_new ? "storing it" : "ignoring it");
#endif
@ -350,10 +350,9 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
break;
case Input::IT_STICKMOTION:
{
std::cout << "%% storing new axis binding, value=" << value <<
" deviceID=" << deviceID << " button=" << button <<
" axisDirection=" <<
(axisDirection == Input::AD_NEGATIVE ? "-" : "+") << "\n";
Log::info("InputManager::inputSensing", "Storing new axis binding, value = %d; "
"deviceID = %d; button = %d; axisDirection = %s", value, deviceID, button,
axisDirection == Input::AD_NEGATIVE ? "-" : "+");
// We have to save the direction in which the axis was moved.
// This is done by storing it as a sign (and since button can
// be zero, we add one before changing the sign).
@ -573,8 +572,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
InputDevice *device = NULL;
if (type == Input::IT_KEYBOARD)
{
//std::cout << "==== New Player Joining with Key " <<
// button << " ====" << std::endl;
//Log::info("InputManager", "New Player Joining with Key %d", button);
device = m_device_manager->getKeyboardFromBtnID(button);
}
else if (type == Input::IT_STICKBUTTON ||
@ -609,8 +607,8 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
if (pk == NULL)
{
std::cerr <<
"Error, trying to process action for an unknown player\n";
Log::error("InputManager::dispatchInput", "Trying to process "
"action for an unknown player");
return;
}
@ -700,8 +698,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
void InputManager::setMasterPlayerOnly(bool enabled)
{
#if INPUT_MODE_DEBUG
std::cout <<
"====== InputManager::setMasterPlayerOnly(" << enabled << ") ======\n";
Log::info("InputManager::setMasterPlayerOnly", enabled ? "enabled" : "disabled");
#endif
m_master_player_only = enabled;
}
@ -955,7 +952,7 @@ void InputManager::setMode(InputDriverMode new_mode)
{
case MENU:
#if INPUT_MODE_DEBUG
std::cout << "====== InputManager::setMode(MENU) ======\n";
Log::info("InputManager::setMode", "MENU");
#endif
switch (m_mode)
{
@ -1017,7 +1014,7 @@ void InputManager::setMode(InputDriverMode new_mode)
break;
case INGAME:
#if INPUT_MODE_DEBUG
std::cout << "====== InputManager::setMode(INGAME) ======\n";
Log::info("InputManager::setMode", "INGAME");
#endif
// We must be in menu mode now in order to switch.
assert (m_mode == MENU);
@ -1036,7 +1033,7 @@ void InputManager::setMode(InputDriverMode new_mode)
case INPUT_SENSE_KEYBOARD:
case INPUT_SENSE_GAMEPAD:
#if INPUT_MODE_DEBUG
std::cout << "====== InputManager::setMode(INPUT_SENSE_*) ======\n";
Log::info("InputManager::setMode", "INPUT_SENSE_*");
#endif
// We must be in menu mode now in order to switch.
assert (m_mode == MENU);
@ -1050,7 +1047,7 @@ void InputManager::setMode(InputDriverMode new_mode)
/*
case LOWLEVEL:
#if INPUT_MODE_DEBUG
std::cout << "====== InputManager::setMode(LOWLEVEL) ======\n";
Log::info("InputManager::setMode", "LOWLEVEL");
#endif
// We must be in menu mode now in order to switch.
assert (m_mode == MENU);

View File

@ -80,13 +80,13 @@ Attachment::~Attachment()
if (m_bomb_sound)
{
SFXManager::get()->deleteSFX(m_bomb_sound);
m_bomb_sound->deleteSFX();
m_bomb_sound = NULL;
}
if (m_bubble_explode_sound)
{
SFXManager::get()->deleteSFX(m_bubble_explode_sound);
m_bubble_explode_sound->deleteSFX();
m_bubble_explode_sound = NULL;
}
} // ~Attachment
@ -139,10 +139,10 @@ void Attachment::set(AttachmentType type, float time,
break;
case ATTACH_BOMB:
m_node->setMesh(attachment_manager->getMesh(type));
if (m_bomb_sound) SFXManager::get()->deleteSFX(m_bomb_sound);
if (m_bomb_sound) m_bomb_sound->deleteSFX();
m_bomb_sound = SFXManager::get()->createSoundSource("clock");
m_bomb_sound->setLoop(true);
m_bomb_sound->position(m_kart->getXYZ());
m_bomb_sound->setPosition(m_kart->getXYZ());
m_bomb_sound->play();
break;
default:
@ -198,8 +198,7 @@ void Attachment::clear()
if (m_bomb_sound)
{
m_bomb_sound->stop();
SFXManager::get()->deleteSFX(m_bomb_sound);
m_bomb_sound->deleteSFX();
m_bomb_sound = NULL;
}
@ -441,7 +440,7 @@ void Attachment::update(float dt)
break;
case ATTACH_BOMB:
if (m_bomb_sound) m_bomb_sound->position(m_kart->getXYZ());
if (m_bomb_sound) m_bomb_sound->setPosition(m_kart->getXYZ());
// Mesh animation frames are 1 to 61 frames (60 steps)
// The idea is change second by second, counterclockwise 60 to 0 secs
@ -461,8 +460,7 @@ void Attachment::update(float dt)
if (m_bomb_sound)
{
m_bomb_sound->stop();
SFXManager::get()->deleteSFX(m_bomb_sound);
m_bomb_sound->deleteSFX();
m_bomb_sound = NULL;
}
}
@ -475,9 +473,9 @@ void Attachment::update(float dt)
if (m_time_left < 0)
{
m_time_left = 0.0f;
if (m_bubble_explode_sound) SFXManager::get()->deleteSFX(m_bubble_explode_sound);
if (m_bubble_explode_sound) m_bubble_explode_sound->deleteSFX();
m_bubble_explode_sound = SFXManager::get()->createSoundSource("bubblegum_explode");
m_bubble_explode_sound->position(m_kart->getXYZ());
m_bubble_explode_sound->setPosition(m_kart->getXYZ());
m_bubble_explode_sound->play();
// drop a small bubble gum

View File

@ -87,9 +87,9 @@ Bowling::Bowling(AbstractKart *kart)
*/
Bowling::~Bowling()
{
if(m_roll_sfx->getStatus()==SFXManager::SFX_PLAYING)
m_roll_sfx->stop();
SFXManager::get()->deleteSFX(m_roll_sfx);
// This will stop the sfx and delete the object.
m_roll_sfx->deleteSFX();
} // ~RubberBall
// -----------------------------------------------------------------------------
@ -172,8 +172,8 @@ bool Bowling::updateAndDelete(float dt)
return true;
}
if (m_roll_sfx->getStatus()==SFXManager::SFX_PLAYING)
m_roll_sfx->position(getXYZ());
if (m_roll_sfx->getStatus()==SFXBase::SFX_PLAYING)
m_roll_sfx->setPosition(getXYZ());
return false;
} // updateAndDelete

View File

@ -53,7 +53,7 @@ Powerup::Powerup(AbstractKart* kart)
*/
Powerup::~Powerup()
{
if(m_sound_use) SFXManager::get()->deleteSFX(m_sound_use);
if(m_sound_use) m_sound_use->deleteSFX();
} // ~Powerup
//-----------------------------------------------------------------------------
@ -88,7 +88,7 @@ void Powerup::set(PowerupManager::PowerupType type, int n)
if(m_sound_use != NULL)
{
SFXManager::get()->deleteSFX(m_sound_use);
m_sound_use->deleteSFX();
m_sound_use = NULL;
}
@ -140,18 +140,14 @@ Material *Powerup::getIcon() const
// Check if it's one of the types which have a separate
// data file which includes the icon:
return powerup_manager->getIcon(m_type);
}
} // getIcon
//-----------------------------------------------------------------------------
/** Does the sound configuration.
*/
void Powerup::adjustSound()
{
m_sound_use->position(m_owner->getXYZ());
m_sound_use->setPosition(m_owner->getXYZ());
// in multiplayer mode, sounds are NOT positional (because we have multiple listeners)
// so the sounds of all AIs are constantly heard. So reduce volume of sounds.
if (race_manager->getNumLocalPlayers() > 1)
@ -160,14 +156,16 @@ void Powerup::adjustSound()
if (m_owner->getController()->isPlayerController())
{
m_sound_use->volume( 1.0f );
m_sound_use->setVolume( 1.0f );
}
else
{
m_sound_use->volume( std::min(0.5f, 1.0f / race_manager->getNumberOfKarts()) );
m_sound_use->setVolume(
std::min(0.5f, 1.0f / race_manager->getNumberOfKarts()) );
}
}
}
} // adjustSound
//-----------------------------------------------------------------------------
/** Use (fire) this powerup.
*/
@ -205,7 +203,7 @@ void Powerup::use()
case PowerupManager::POWERUP_SWITCH:
{
ItemManager::get()->switchItems();
m_sound_use->position(m_owner->getXYZ());
m_sound_use->setPosition(m_owner->getXYZ());
m_sound_use->play();
break;
}
@ -311,9 +309,9 @@ void Powerup::use()
// Meanwhile, don't play it near AI karts since they obviously
// don't hear anything
if(kart->getController()->isPlayerController())
m_sound_use->position(kart->getXYZ());
m_sound_use->setPosition(kart->getXYZ());
else
m_sound_use->position(m_owner->getXYZ());
m_sound_use->setPosition(m_owner->getXYZ());
m_sound_use->play();
break;
@ -353,9 +351,9 @@ void Powerup::use()
// Meanwhile, don't play it near AI karts since they obviously
// don't hear anything
if(m_owner->getController()->isPlayerController())
m_sound_use->position(m_owner->getXYZ());
m_sound_use->setPosition(m_owner->getXYZ());
else if(player_kart)
m_sound_use->position(player_kart->getXYZ());
m_sound_use->setPosition(player_kart->getXYZ());
m_sound_use->play();
}
break;

View File

@ -107,9 +107,9 @@ RubberBall::RubberBall(AbstractKart *kart)
*/
RubberBall::~RubberBall()
{
if(m_ping_sfx->getStatus()==SFXManager::SFX_PLAYING)
if(m_ping_sfx->getStatus()==SFXBase::SFX_PLAYING)
m_ping_sfx->stop();
SFXManager::get()->deleteSFX(m_ping_sfx);
m_ping_sfx->deleteSFX();
} // ~RubberBall
// ----------------------------------------------------------------------------
@ -541,9 +541,9 @@ float RubberBall::updateHeight()
if(m_height_timer>m_interval)
{
m_height_timer -= m_interval;
if(m_ping_sfx->getStatus()!=SFXManager::SFX_PLAYING)
if(m_ping_sfx->getStatus()!=SFXBase::SFX_PLAYING)
{
m_ping_sfx->position(getXYZ());
m_ping_sfx->setPosition(getXYZ());
m_ping_sfx->play();
}

View File

@ -100,7 +100,7 @@ Swatter::~Swatter()
}
if (m_swat_sound)
{
SFXManager::get()->deleteSFX(m_swat_sound);
m_swat_sound->deleteSFX();
}
} // ~Swatter
@ -275,7 +275,7 @@ void Swatter::squashThingsAround()
assert(swatter_node);
Vec3 swatter_pos = swatter_node->getAbsolutePosition();
m_swat_sound->position(swatter_pos);
m_swat_sound->setPosition(swatter_pos);
m_swat_sound->play();
// Squash karts around

View File

@ -74,11 +74,11 @@ PlayerController::PlayerController(AbstractKart *kart,
*/
PlayerController::~PlayerController()
{
SFXManager::get()->deleteSFX(m_bzzt_sound);
SFXManager::get()->deleteSFX(m_wee_sound );
SFXManager::get()->deleteSFX(m_ugh_sound );
SFXManager::get()->deleteSFX(m_grab_sound);
SFXManager::get()->deleteSFX(m_full_sound);
m_bzzt_sound->deleteSFX();
m_wee_sound ->deleteSFX();
m_ugh_sound ->deleteSFX();
m_grab_sound->deleteSFX();
m_full_sound->deleteSFX();
} // ~PlayerController
//-----------------------------------------------------------------------------
@ -439,7 +439,7 @@ void PlayerController::handleZipper(bool play_sound)
// Only play a zipper sound if it's not already playing, and
// if the material has changed (to avoid machine gun effect
// on conveyor belt zippers).
if (play_sound || (m_wee_sound->getStatus() != SFXManager::SFX_PLAYING &&
if (play_sound || (m_wee_sound->getStatus() != SFXBase::SFX_PLAYING &&
m_kart->getMaterial()!=m_kart->getLastMaterial() ) )
{
m_wee_sound->play();

View File

@ -185,19 +185,19 @@ void Kart::init(RaceManager::KartType type)
{
// players have louder sounds than AIs
const float factor = std::min(1.0f, race_manager->getNumLocalPlayers()/2.0f);
m_goo_sound->volume( 1.0f / factor );
m_skid_sound->volume( 1.0f / factor );
m_crash_sound->volume( 1.0f / factor );
m_boing_sound->volume( 1.0f / factor );
m_beep_sound->volume( 1.0f / factor );
m_goo_sound->setVolume( 1.0f / factor );
m_skid_sound->setVolume( 1.0f / factor );
m_crash_sound->setVolume( 1.0f / factor );
m_boing_sound->setVolume( 1.0f / factor );
m_beep_sound->setVolume( 1.0f / factor );
}
else
{
m_goo_sound->volume( 1.0f / race_manager->getNumberOfKarts() );
m_skid_sound->volume( 1.0f / race_manager->getNumberOfKarts() );
m_crash_sound->volume( 1.0f / race_manager->getNumberOfKarts() );
m_beep_sound->volume( 1.0f / race_manager->getNumberOfKarts() );
m_boing_sound->volume( 1.0f / race_manager->getNumberOfKarts() );
m_goo_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_skid_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_crash_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_beep_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_boing_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
}
}
@ -248,15 +248,15 @@ Kart::~Kart()
SFXManager::get()->deleteSFX(m_custom_sounds[n]);
}*/
SFXManager::get()->deleteSFX(m_engine_sound );
SFXManager::get()->deleteSFX(m_crash_sound );
SFXManager::get()->deleteSFX(m_skid_sound );
SFXManager::get()->deleteSFX(m_goo_sound );
SFXManager::get()->deleteSFX(m_beep_sound );
SFXManager::get()->deleteSFX(m_boing_sound );
m_engine_sound->deleteSFX();
m_crash_sound ->deleteSFX();
m_skid_sound ->deleteSFX();
m_goo_sound ->deleteSFX();
m_beep_sound ->deleteSFX();
m_boing_sound ->deleteSFX();
delete m_kart_gfx;
if(m_terrain_sound) SFXManager::get()->deleteSFX(m_terrain_sound);
if(m_previous_terrain_sound) SFXManager::get()->deleteSFX(m_previous_terrain_sound);
if(m_terrain_sound) m_terrain_sound->deleteSFX();
if(m_previous_terrain_sound) m_previous_terrain_sound->deleteSFX();
if(m_collision_particles) delete m_collision_particles;
if(m_slipstream) delete m_slipstream;
if(m_sky_particles_emitter) delete m_sky_particles_emitter;
@ -365,16 +365,15 @@ void Kart::reset()
if(m_terrain_sound)
{
SFXManager::get()->deleteSFX(m_terrain_sound);
m_terrain_sound->deleteSFX();
m_terrain_sound = NULL;
}
if(m_previous_terrain_sound)
{
SFXManager::get()->deleteSFX(m_previous_terrain_sound);
m_previous_terrain_sound->deleteSFX();
m_previous_terrain_sound = NULL;
}
m_terrain_sound = NULL;
m_previous_terrain_sound = NULL;
if(m_engine_sound)
m_engine_sound->stop();
@ -759,12 +758,12 @@ void Kart::startEngineSFX()
const float players_volume = (np * 2.0f) / (np*2.0f + np);
if (m_controller->isPlayerController())
m_engine_sound->volume( players_volume / np );
m_engine_sound->setVolume( players_volume / np );
else
m_engine_sound->volume( (1.0f - players_volume) / nai );
m_engine_sound->setVolume( (1.0f - players_volume) / nai );
}
m_engine_sound->speed(0.6f);
m_engine_sound->setSpeed(0.6f);
m_engine_sound->setLoop(true);
m_engine_sound->play();
} // startEngineSFX
@ -934,7 +933,7 @@ void Kart::collectedItem(Item *item, int add_info)
m_kart_properties->getBubblegumFadeInTime() *
m_difficulty->getBubblegumFadeInTime(),
m_bubblegum_time);
m_goo_sound->position(getXYZ());
m_goo_sound->setPosition(getXYZ());
m_goo_sound->play();
// Play appropriate custom character sound
playCustomSFX(SFXManager::CUSTOM_GOO);
@ -1194,11 +1193,11 @@ void Kart::update(float dt)
}
*/
m_beep_sound->position ( getXYZ() );
m_engine_sound->position ( getXYZ() );
m_crash_sound->position ( getXYZ() );
m_skid_sound->position ( getXYZ() );
m_boing_sound->position ( getXYZ() );
m_beep_sound->setPosition ( getXYZ() );
m_engine_sound->setPosition ( getXYZ() );
m_crash_sound->setPosition ( getXYZ() );
m_skid_sound->setPosition ( getXYZ() );
m_boing_sound->setPosition ( getXYZ() );
// Check if a kart is (nearly) upside down and not moving much -->
// automatic rescue
@ -1439,28 +1438,21 @@ void Kart::handleMaterialSFX(const Material *material)
// can be used again.
if(m_previous_terrain_sound)
{
SFXManager::get()->deleteSFX(m_previous_terrain_sound);
m_previous_terrain_sound->deleteSFX();
}
m_previous_terrain_sound = m_terrain_sound;
if(m_previous_terrain_sound)
m_previous_terrain_sound->setLoop(false);
const std::string &s = material->getSFXName();
if (s != "")
// In multiplayer mode sounds are NOT positional, because we have
// multiple listeners. This would make the sounds of all AIs be
// audible at all times. So silence AI karts.
if (s.size()!=0 && (race_manager->getNumPlayers()==1 ||
m_controller->isPlayerController() ) )
{
m_terrain_sound = SFXManager::get()->createSoundSource(s);
// In multiplayer mode sounds are NOT positional, because we have
// multiple listeners. This would make the sounds of all AIs be
// audible at all times. So silence AI karts.
if (race_manager->getNumLocalPlayers() > 1)
{
if (!m_controller->isPlayerController())
{
m_terrain_sound->volume( 0.0f );
}
}
m_terrain_sound->play();
m_terrain_sound->setLoop(true);
}
@ -1471,12 +1463,12 @@ void Kart::handleMaterialSFX(const Material *material)
}
if(m_previous_terrain_sound &&
m_previous_terrain_sound->getStatus()==SFXManager::SFX_STOPPED)
m_previous_terrain_sound->getStatus()==SFXBase::SFX_STOPPED)
{
// We don't modify the position of m_previous_terrain_sound
// anymore, so that it keeps on playing at the place where the
// kart left the material.
SFXManager::get()->deleteSFX(m_previous_terrain_sound);
m_previous_terrain_sound->deleteSFX();
m_previous_terrain_sound = NULL;
}
@ -1487,10 +1479,10 @@ void Kart::handleMaterialSFX(const Material *material)
// terrain sound is not necessarily a looping sound so check its status before
// setting its speed, to avoid 'ressuscitating' sounds that had already stopped
if(m_terrain_sound &&
(m_terrain_sound->getStatus()==SFXManager::SFX_PLAYING ||
m_terrain_sound->getStatus()==SFXManager::SFX_PAUSED))
(m_terrain_sound->getStatus()==SFXBase::SFX_PLAYING ||
m_terrain_sound->getStatus()==SFXBase::SFX_PAUSED))
{
m_terrain_sound->position(getXYZ());
m_terrain_sound->setPosition(getXYZ());
material->setSFXSpeed(m_terrain_sound, m_speed, m_schedule_pause);
}
@ -1599,9 +1591,9 @@ void Kart::handleMaterialGFX()
const std::string &s = surface_material->getSFXName();
if (s != "" && !dynamic_cast<RescueAnimation*>(getKartAnimation())&&
(m_terrain_sound == NULL ||
m_terrain_sound->getStatus() == SFXManager::SFX_STOPPED))
m_terrain_sound->getStatus() == SFXBase::SFX_STOPPED))
{
if (m_previous_terrain_sound) SFXManager::get()->deleteSFX(m_previous_terrain_sound);
if (m_previous_terrain_sound) m_previous_terrain_sound->deleteSFX();
m_previous_terrain_sound = m_terrain_sound;
if(m_previous_terrain_sound)
m_previous_terrain_sound->setLoop(false);
@ -1917,12 +1909,12 @@ void Kart::crashed(const Material* m, AbstractKart *k)
// it's not already playing.
if (isShielded() || (k != NULL && k->isShielded()))
{
if (m_boing_sound->getStatus() != SFXManager::SFX_PLAYING)
if (m_boing_sound->getStatus() != SFXBase::SFX_PLAYING)
m_boing_sound->play();
}
else
{
if(m_crash_sound->getStatus() != SFXManager::SFX_PLAYING)
if(m_crash_sound->getStatus() != SFXBase::SFX_PLAYING)
m_crash_sound->play();
}
}
@ -2043,10 +2035,10 @@ void Kart::updatePhysics(float dt)
m_skidding->getSkidState() == Skidding::SKID_ACCUMULATE_RIGHT ) &&
m_skidding->getGraphicalJumpOffset()==0)
{
if(m_skid_sound->getStatus() != SFXManager::SFX_PLAYING &&!isWheeless())
if(m_skid_sound->getStatus()!=SFXBase::SFX_PLAYING && !isWheeless())
m_skid_sound->play();
}
else if(m_skid_sound->getStatus() == SFXManager::SFX_PLAYING)
else if(m_skid_sound->getStatus()==SFXBase::SFX_PLAYING)
{
m_skid_sound->stop();
}
@ -2149,15 +2141,15 @@ void Kart::updateEngineSFX()
if (f>1.0f) f=1.0f;
float gears = 3.0f * fmod(f, 0.333334f);
m_engine_sound->speed(0.6f + (f +gears)* 0.35f);
m_engine_sound->setSpeed(0.6f + (f +gears)* 0.35f);
}
else
{
// When flying, fixed value but not too high pitch
// This gives some variation (vs previous "on wheels" one)
m_engine_sound->speed(0.9f);
m_engine_sound->setSpeed(0.9f);
}
m_engine_sound->position(getXYZ());
m_engine_sound->setPosition(getXYZ());
} // updateEngineSFX
//-----------------------------------------------------------------------------

View File

@ -622,9 +622,9 @@ void KartModel::loadWheelInfo(const XMLNode &node,
// stk_config file is read (which has no model information).
if(m_model_filename!="")
{
Log::error("Kart_Model", "Missing wheel information '%s' for model"
Log::error("Kart_Model", "Missing wheel information '%s' for model "
"'%s'.", wheel_name.c_str(), m_model_filename.c_str());
Log::error("Kart_Model", "This can be ignored, but the wheels will"
Log::error("Kart_Model", "This can be ignored, but the wheels will "
"not rotate.");
}
return;

View File

@ -1208,12 +1208,11 @@ int main(int argc, char *argv[] )
main_loop = new MainLoop();
material_manager->loadMaterial();
// Load the font textures
file_manager->pushTextureSearchPath(
file_manager->getAsset(FileManager::FONT,""));
// Load the font textures - they are all lazily loaded
// so no need to push a texture search path. They will actually
// be loaded from ScalableFont.
material_manager->addSharedMaterial(
file_manager->getAsset(FileManager::FONT,"materials.xml"));
file_manager->popTextureSearchPath();
GUIEngine::addLoadingIcon( irr_driver->getTexture(FileManager::GUI,
"options_video.png"));

View File

@ -21,7 +21,7 @@
#include <assert.h>
#include "audio/music_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
@ -138,7 +138,6 @@ void MainLoop::run()
if (!m_abort && !ProfileWorld::isNoGraphics())
{
PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
music_manager->update(dt);
input_manager->update(dt);
#ifdef ENABLE_WIIUSE
@ -152,6 +151,13 @@ void MainLoop::run()
irr_driver->update(dt);
PROFILER_POP_CPU_MARKER();
// Update sfx and music after graphics, so that graphics code
// can use as many threads as possible without interfering
// with audia
PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
SFXManager::get()->update(dt);
PROFILER_POP_CPU_MARKER();
PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
ProtocolManager::getInstance()->update();
PROFILER_POP_CPU_MARKER();

View File

@ -309,7 +309,8 @@ void CutsceneWorld::update(float dt)
SFXManager::get()->positionListener(m_camera->getAbsolutePosition(),
m_camera->getTarget() -
m_camera->getAbsolutePosition());
m_camera->getAbsolutePosition(),
Vec3(0,1,0));
break;
}

View File

@ -73,7 +73,7 @@ void LinearWorld::init()
*/
LinearWorld::~LinearWorld()
{
SFXManager::get()->deleteSFX(m_last_lap_sfx);
m_last_lap_sfx->deleteSFX();
} // ~LinearWorld
//-----------------------------------------------------------------------------
@ -155,7 +155,7 @@ void LinearWorld::update(float dt)
WorldWithRank::update(dt);
if (m_last_lap_sfx_playing &&
m_last_lap_sfx->getStatus() != SFXManager::SFX_PLAYING)
m_last_lap_sfx->getStatus() != SFXBase::SFX_PLAYING)
{
if(music_manager->getCurrentMusic())
music_manager->getCurrentMusic()->resetTemporaryVolume();

View File

@ -60,7 +60,7 @@ SoccerWorld::SoccerWorld() : WorldWithRank()
*/
SoccerWorld::~SoccerWorld()
{
SFXManager::get()->deleteSFX(m_goal_sound);
m_goal_sound->deleteSFX();
} // ~SoccerWorld
//-----------------------------------------------------------------------------
@ -121,7 +121,7 @@ void SoccerWorld::reset()
}
if (m_goal_sound != NULL &&
m_goal_sound->getStatus() == SFXManager::SFX_PLAYING)
m_goal_sound->getStatus() == SFXBase::SFX_PLAYING)
{
m_goal_sound->stop();
}
@ -436,6 +436,11 @@ void SoccerWorld::initKartList()
for(unsigned int n=0; n<kart_amount; n++)
{
SoccerTeam team = race_manager->getLocalKartInfo(n).getSoccerTeam();
#ifdef DEBUG
// In debug mode it's possible to play soccer with a single player
// (in artist debug mode). Avoid overwriting memory in this case.
if(team==SOCCER_TEAM_NONE) team=SOCCER_TEAM_RED;
#endif
m_karts[n]->setPosition(team_cur_position[team]);
team_cur_position[team]++;
} // next kart

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