Merge branch 'master' into TangentsCaching
This commit is contained in:
commit
bf5c77d061
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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>
|
||||
|
22
data/fonts/materials.xml
Normal file
22
data/fonts/materials.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0"?>
|
||||
<materials>
|
||||
<!-- Fonts -->
|
||||
<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>
|
@ -9,9 +9,8 @@
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<icon-button id="tab_overview" width="128" height="128" icon="gui/options_ui.png" />
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"/>
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/options_players.png" I18N="Section in the profile menu" text="Achievements"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"/>
|
||||
<icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png"/>
|
||||
</tabs>
|
||||
|
||||
|
@ -9,9 +9,8 @@
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<icon-button id="tab_overview" width="128" height="128" icon="gui/options_ui.png" />
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" I18N="Section in the profile menu" text="Friends"/>
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/options_players.png"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" I18N="Section in the profile menu" text="Friends"/>
|
||||
<icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png"/>
|
||||
</tabs>
|
||||
|
||||
|
@ -9,9 +9,8 @@
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<icon-button id="tab_overview" width="128" height="128" icon="gui/options_ui.png"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" />
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/options_players.png"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" />
|
||||
<icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png" I18N="Section in the profile menu" text="Account Settings"/>
|
||||
</tabs>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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"/>
|
||||
|
||||
|
@ -13,32 +13,32 @@
|
||||
square_items="true" child_width="128" child_height="128" />
|
||||
|
||||
<spacer height="15" width="10"/>
|
||||
<div width="80%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="90%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
|
||||
<checkbox id="online" I18N="In the login screen" text_align="left"/>
|
||||
<label width="40%" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
|
||||
<checkbox width="fit" id="online" I18N="In the login screen" text_align="left"/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_remember" proportion="1" height="100%" text_align="left"
|
||||
<label width="40%" id="label_remember" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Remember password"/>
|
||||
<checkbox id="remember-user" I18N="In the login screen" text_align="left"/>
|
||||
<checkbox width="fit" id="remember-user" I18N="In the login screen" text_align="left"/>
|
||||
</div>
|
||||
<!-- Disable guest accounts for now
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_guest" proportion="1" height="100%" text_align="left"
|
||||
<label width="40%" id="label_guest" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Guest login"/>
|
||||
<checkbox id="guest" I18N="In the login screen" text_align="left"/>
|
||||
</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 login screen" text="Username"/>
|
||||
<textbox id="username" proportion="2" height="fit" I18N="In the registration dialog"/>
|
||||
</div>
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_password" proportion="1" height="100%" text_align="left"
|
||||
<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>
|
||||
@ -54,8 +54,6 @@
|
||||
I18N="Login dialog" text="Add user" label_location="bottom"/>
|
||||
<icon-button id="delete" width="64" height="64" icon="gui/gp_remove_track.png"
|
||||
I18N="Login dialog" text="Delete" label_location="bottom"/>
|
||||
<icon-button id="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/gp_rename.png"
|
||||
I18N="Login dialog" text="Rename" label_location="bottom"/>
|
||||
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
|
||||
|
@ -22,15 +22,15 @@
|
||||
square_items="true" child_width="128" child_height="128" />
|
||||
|
||||
<spacer height="15" width="10"/>
|
||||
<div width="80%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="90%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
|
||||
<checkbox id="online" I18N="In the login screen" text_align="left"/>
|
||||
<label width="40%" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
|
||||
<checkbox width="fit" id="online" I18N="In the login screen" text_align="left"/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_remember" proportion="1" height="100%" text_align="left"
|
||||
<label id="label_remember" width="40%" height="100%" text_align="left"
|
||||
I18N="In the login screen" text="Remember password"/>
|
||||
<checkbox id="remember-user" I18N="In the login screen" text_align="left"/>
|
||||
<checkbox width="fit" id="remember-user" I18N="In the login screen" text_align="left"/>
|
||||
</div>
|
||||
<!-- Disable guest accounts for now
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
@ -40,14 +40,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 login screen" text="Username"/>
|
||||
<textbox id="username" proportion="2" height="fit" I18N="In the registration dialog"/>
|
||||
</div>
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="label_password" proportion="1" height="100%" text_align="left"
|
||||
<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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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.));
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ void main(void)
|
||||
float updated_lifetime = lifetime + (float(dt)/lifetime_initial);
|
||||
if (updated_lifetime > 1.)
|
||||
{
|
||||
if (gl_VertexID <= level)
|
||||
if (gl_VertexID < level)
|
||||
{
|
||||
float dt_from_last_frame = fract(updated_lifetime) * lifetime_initial;
|
||||
vec4 updated_initialposition = sourcematrix * vec4(particle_position_initial, 1.0);
|
||||
|
@ -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);
|
||||
|
@ -11,8 +11,9 @@ void main(void)
|
||||
{
|
||||
vec3 eyedir = gl_FragCoord.xyz / vec3(screen, 1.);
|
||||
eyedir = 2.0 * eyedir - 1.0;
|
||||
vec4 tmp = (InverseViewMatrix * InverseProjectionMatrix * vec4(eyedir, 1.));
|
||||
eyedir = tmp.xyz / tmp.w;
|
||||
vec4 tmp = (InverseProjectionMatrix * vec4(eyedir, 1.));
|
||||
tmp /= tmp.w;
|
||||
eyedir = (InverseViewMatrix * vec4(tmp.xyz, 0.)).xyz;
|
||||
vec4 color = texture(tex, eyedir);
|
||||
FragColor = vec4(color.xyz, 1.);
|
||||
}
|
||||
|
@ -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.);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -153,8 +153,8 @@
|
||||
when the camera is pointing backwards. This is usually
|
||||
larger than the forward-up-angle, since the kart itself
|
||||
otherwise obstricts too much of the view. -->
|
||||
<camera distance="1.5" forward-up-angle="15"
|
||||
backward-up-angle="30"/>
|
||||
<camera distance="1.0" forward-up-angle="15"
|
||||
backward-up-angle="5"/>
|
||||
<!-- Additional offset to move graphical chassis with regards to the physics. -->
|
||||
<graphics y-offset="0.0"/>
|
||||
|
||||
@ -380,7 +380,7 @@
|
||||
<stability roll-influence="0.3"
|
||||
chassis-linear-damping="0.2"
|
||||
chassis-angular-damping="0"
|
||||
downward-impulse-factor="0"
|
||||
downward-impulse-factor="5"
|
||||
track-connection-accel="2"
|
||||
smooth-flying-impulse="25"/>
|
||||
|
||||
|
@ -77,6 +77,8 @@ struct btWheelInfo
|
||||
|
||||
bool m_bIsFrontWheel;
|
||||
|
||||
bool m_was_on_ground;
|
||||
|
||||
void* m_clientInfo;//can be used to store pointer to sync transforms...
|
||||
|
||||
btWheelInfo(btWheelInfoConstructionInfo& ci)
|
||||
@ -102,7 +104,7 @@ struct btWheelInfo
|
||||
m_rollInfluence = btScalar(0.1);
|
||||
m_bIsFrontWheel = ci.m_bIsFrontWheel;
|
||||
m_maxSuspensionForce = ci.m_maxSuspensionForce;
|
||||
|
||||
m_was_on_ground = true;
|
||||
}
|
||||
|
||||
void updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo);
|
||||
|
@ -9,7 +9,7 @@ endif()
|
||||
|
||||
add_library(glew STATIC
|
||||
include/GL/glew.h include/GL/glxew.h include/GL/wglew.h
|
||||
src/glew.c src/glewinfo.c src/visualinfo.c
|
||||
src/glew.c src/glewinfo.c
|
||||
)
|
||||
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -277,7 +277,7 @@ void CGUIButton::draw()
|
||||
pos.X += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X);
|
||||
pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y);
|
||||
}
|
||||
driver->draw2DImage(PressedImage,
|
||||
skin->draw2DImage(PressedImage,
|
||||
ScaleImage? AbsoluteRect :
|
||||
core::recti(pos, PressedImageRect.getSize()),
|
||||
PressedImageRect, &AbsoluteClippingRect,
|
||||
@ -285,7 +285,7 @@ void CGUIButton::draw()
|
||||
}
|
||||
}
|
||||
|
||||
if (SpriteBank)
|
||||
if (false) //SpriteBank)
|
||||
{
|
||||
// pressed / unpressed animation
|
||||
u32 state = Pressed ? (u32)EGBS_BUTTON_DOWN : (u32)EGBS_BUTTON_UP;
|
||||
|
@ -584,30 +584,30 @@ void CGUIContextMenu::draw()
|
||||
skin->getColor(c), false, true, clip);
|
||||
|
||||
// draw submenu symbol
|
||||
if (Items[i].SubMenu && sprites)
|
||||
{
|
||||
core::rect<s32> r = rect;
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X - 15;
|
||||
|
||||
sprites->draw2DSprite(skin->getIcon(EGDI_CURSOR_RIGHT),
|
||||
r.getCenter(), clip, skin->getColor(c),
|
||||
(i == HighLighted) ? ChangeTime : 0,
|
||||
(i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
(i == HighLighted), true);
|
||||
}
|
||||
//if (Items[i].SubMenu && sprites)
|
||||
//{
|
||||
// core::rect<s32> r = rect;
|
||||
// r.UpperLeftCorner.X = r.LowerRightCorner.X - 15;
|
||||
//
|
||||
// sprites->draw2DSprite(skin->getIcon(EGDI_CURSOR_RIGHT),
|
||||
// r.getCenter(), clip, skin->getColor(c),
|
||||
// (i == HighLighted) ? ChangeTime : 0,
|
||||
// (i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
// (i == HighLighted), true);
|
||||
//}
|
||||
|
||||
// draw checked symbol
|
||||
if (Items[i].Checked && sprites)
|
||||
{
|
||||
core::rect<s32> r = rect;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X - 15;
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X + 15;
|
||||
sprites->draw2DSprite(skin->getIcon(EGDI_CHECK_BOX_CHECKED),
|
||||
r.getCenter(), clip, skin->getColor(c),
|
||||
(i == HighLighted) ? ChangeTime : 0,
|
||||
(i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
(i == HighLighted), true);
|
||||
}
|
||||
//if (Items[i].Checked && sprites)
|
||||
//{
|
||||
// core::rect<s32> r = rect;
|
||||
// r.LowerRightCorner.X = r.UpperLeftCorner.X - 15;
|
||||
// r.UpperLeftCorner.X = r.LowerRightCorner.X + 15;
|
||||
// sprites->draw2DSprite(skin->getIcon(EGDI_CHECK_BOX_CHECKED),
|
||||
// r.getCenter(), clip, skin->getColor(c),
|
||||
// (i == HighLighted) ? ChangeTime : 0,
|
||||
// (i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
// (i == HighLighted), true);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,20 +78,20 @@ void CGUIImage::draw()
|
||||
|
||||
if (Texture)
|
||||
{
|
||||
if (ScaleImage)
|
||||
{
|
||||
//if (ScaleImage)
|
||||
//{
|
||||
const video::SColor Colors[] = {Color,Color,Color,Color};
|
||||
|
||||
driver->draw2DImage(Texture, AbsoluteRect,
|
||||
skin->draw2DImage(Texture, AbsoluteRect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(Texture->getOriginalSize())),
|
||||
&AbsoluteClippingRect, Colors, UseAlphaChannel);
|
||||
}
|
||||
else
|
||||
{
|
||||
driver->draw2DImage(Texture, AbsoluteRect.UpperLeftCorner,
|
||||
core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(Texture->getOriginalSize())),
|
||||
&AbsoluteClippingRect, Color, UseAlphaChannel);
|
||||
}
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// driver->draw2DImage(Texture, AbsoluteRect.UpperLeftCorner,
|
||||
// core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(Texture->getOriginalSize())),
|
||||
// &AbsoluteClippingRect, Color, UseAlphaChannel);
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Modify this file to change the last-modified date when you add/remove a file.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
||||
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
||||
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")
|
||||
|
@ -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++)
|
||||
@ -113,7 +115,7 @@ irr::core::stringw AchievementInfo::toString() const
|
||||
count = m_goal_values.begin()->second;
|
||||
break;
|
||||
default:
|
||||
Log::fatal("AchievementInfo", "Missing toString for tpye %d.",
|
||||
Log::fatal("AchievementInfo", "Missing toString for type %d.",
|
||||
m_check_type);
|
||||
}
|
||||
return StringUtils::toWString(count);
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "audio/sfx_base.hpp"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Dummy sound when ogg or openal aren't available
|
||||
* \ingroup audio
|
||||
@ -37,19 +36,28 @@ public:
|
||||
/** 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 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 bool isPlaying() { return false; }
|
||||
virtual const SFXBuffer* getBuffer() const { return NULL; }
|
||||
|
||||
}; // DummySFX
|
||||
|
||||
|
@ -42,26 +42,42 @@ 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_INITIAL = 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 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 bool isPlaying() = 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
@ -106,9 +109,9 @@ SFXManager::SFXManager()
|
||||
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 +127,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 +163,79 @@ 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();
|
||||
m_sfx_commands.getData().push_back(command);
|
||||
m_sfx_commands.unlock();
|
||||
} // queueCommand
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** 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_MUSIC, NULL, dt);
|
||||
// Wake up the sfx thread to handle all queued up audio commands.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
} // update
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Puts a NULL request into the queue, which will trigger the thread to
|
||||
* exit.
|
||||
*/
|
||||
void SFXManager::stopThread()
|
||||
{
|
||||
queue(NULL);
|
||||
queue(SFX_EXIT, NULL);
|
||||
// Make sure the thread wakes up.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
} // stopThread
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -198,40 +250,70 @@ 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();
|
||||
}
|
||||
|
||||
SFXBase *current = me->m_sfx_to_play.getData().front();
|
||||
me->m_sfx_to_play.getData().erase(me->m_sfx_to_play.getData().begin());
|
||||
SFXCommand *current = me->m_sfx_commands.getData().front();
|
||||
me->m_sfx_commands.getData().erase(me->m_sfx_commands.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: {
|
||||
current->m_sfx->reallyStopNow();
|
||||
me->deleteSFX(current->m_sfx); break;
|
||||
}
|
||||
case SFX_LISTENER: me->reallyPositionListenerNow(); break;
|
||||
case SFX_UPDATE_MUSIC: music_manager->update(
|
||||
current->m_parameter.getX()); 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 +330,19 @@ 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
|
||||
{
|
||||
pauseAll();
|
||||
}
|
||||
}
|
||||
} // soundToggled
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** Returns if sfx can be played. This means sfx are enabled and
|
||||
@ -437,7 +520,14 @@ 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();
|
||||
}
|
||||
else
|
||||
printf("");
|
||||
|
||||
return sfx;
|
||||
} // createSoundSource
|
||||
@ -497,21 +587,26 @@ 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);
|
||||
return;
|
||||
}
|
||||
|
||||
m_all_sfx.getData().erase(i);
|
||||
delete sfx;
|
||||
|
||||
m_all_sfx.erase(i);
|
||||
|
||||
m_all_sfx.unlock();
|
||||
} // deleteSFX
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -521,11 +616,13 @@ void SFXManager::deleteSFX(SFXBase *sfx)
|
||||
*/
|
||||
void SFXManager::pauseAll()
|
||||
{
|
||||
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();
|
||||
} // for i in m_all_sfx
|
||||
m_all_sfx.unlock();
|
||||
} // pauseAll
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -537,19 +634,20 @@ void SFXManager::resumeAll()
|
||||
// ignore unpausing if sound is disabled
|
||||
if (!sfxAllowed()) return;
|
||||
|
||||
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++)
|
||||
{
|
||||
SFXStatus status = (*i)->getStatus();
|
||||
// Initial happens when
|
||||
if (status==SFX_PAUSED) (*i)->resume();
|
||||
(*i)->resume();
|
||||
} // 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 +678,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 +721,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, NULL);
|
||||
} // 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
|
||||
|
@ -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,24 @@ 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_RESUME,
|
||||
SFX_DELETE,
|
||||
SFX_SPEED,
|
||||
SFX_POSITION,
|
||||
SFX_VOLUME,
|
||||
SFX_LOOP,
|
||||
SFX_LISTENER,
|
||||
SFX_UPDATE_MUSIC,
|
||||
SFX_EXIT,
|
||||
}; // SFXCommands
|
||||
|
||||
/**
|
||||
* Entries for custom SFX sounds. These are unique for each kart.
|
||||
* eg. kart->playCustomSFX(SFX_MANAGER::CUSTOM_HORN)
|
||||
@ -76,34 +95,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 ¶meter)
|
||||
{
|
||||
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 +174,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);
|
||||
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()
|
||||
@ -153,10 +212,10 @@ public:
|
||||
SFXBase* createSoundSource(const std::string &name,
|
||||
const bool addToSFXList=true);
|
||||
|
||||
void deleteSFX(SFXBase *sfx);
|
||||
void deleteSFXMapping(const std::string &name);
|
||||
void pauseAll();
|
||||
void resumeAll();
|
||||
void update(float dt);
|
||||
bool soundExist(const std::string &name);
|
||||
void setMasterSFXVolume(float gain);
|
||||
float getMasterSFXVolume() const { return m_master_gain; }
|
||||
@ -164,7 +223,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 +237,7 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current position of the listener. */
|
||||
Vec3 getListenerPos() const { return m_position; }
|
||||
Vec3 getListenerPos() const { return m_listener_position.getData(); }
|
||||
|
||||
};
|
||||
|
||||
|
@ -23,8 +23,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 +37,19 @@
|
||||
#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_UNKNOWN;
|
||||
m_is_playing = false;
|
||||
m_positional = positional;
|
||||
m_defaultGain = gain;
|
||||
m_loop = false;
|
||||
m_gain = -1.0f;
|
||||
m_master_gain = 1.0f;
|
||||
m_owns_buffer = owns_buffer;
|
||||
m_end_time = -1.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,18 +61,19 @@ 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
|
||||
|
||||
@ -79,56 +81,78 @@ SFXOpenAL::~SFXOpenAL()
|
||||
|
||||
bool SFXOpenAL::init()
|
||||
{
|
||||
alGenSources(1, &m_soundSource );
|
||||
alGenSources(1, &m_sound_source );
|
||||
if (!SFXManager::checkError("generating a source")) return false;
|
||||
|
||||
assert( alIsBuffer(m_soundBuffer->getBufferID()) );
|
||||
assert( alIsSource(m_soundSource) );
|
||||
assert( alIsBuffer(m_sound_buffer->getBufferID()) );
|
||||
assert( alIsSource(m_sound_source) );
|
||||
|
||||
//std::cout << "Setting a source with buffer " << m_soundBuffer
|
||||
// << ", rolloff " << rolloff
|
||||
// << ", gain=" << m_defaultGain << ", positional="
|
||||
// << (positional ? "true" : "false") << std::endl;
|
||||
|
||||
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_defaultGain * 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"))
|
||||
m_status = SFX_INITIAL;
|
||||
|
||||
return m_ok;
|
||||
return m_status==SFX_INITIAL;
|
||||
} // init
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the status of this sfx. */
|
||||
SFXBase::SFXStatus SFXOpenAL::getStatus()
|
||||
{
|
||||
if(m_status==SFX_PLAYING)
|
||||
{
|
||||
if(m_loop) return SFX_PLAYING;
|
||||
if(World::getWorld() && World::getWorld()->getTime() > m_end_time)
|
||||
{
|
||||
m_status = SFX_STOPPED;
|
||||
return m_status;
|
||||
}
|
||||
}
|
||||
return m_status;
|
||||
} // getStatus;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** 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) 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_UNKNOWN) return;
|
||||
//OpenAL only accepts pitches in the range of 0.5 to 2.0
|
||||
if(factor > 2.0f)
|
||||
{
|
||||
@ -138,23 +162,33 @@ 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)
|
||||
{
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
assert(!isnan(gain)) ;
|
||||
SFXManager::get()->queue(SFXManager::SFX_VOLUME, this, gain);
|
||||
} // setVolume
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** 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)
|
||||
{
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
m_gain = m_defaultGain * gain;
|
||||
|
||||
if(!m_ok) return;
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
|
||||
alSourcef(m_soundSource, AL_GAIN, m_gain * m_master_gain);
|
||||
SFXManager::checkError("setting volume");
|
||||
} // volume
|
||||
alSourcef(m_sound_source, AL_GAIN, m_gain * m_master_gain);
|
||||
} // reallySetVolume
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -162,9 +196,9 @@ void SFXOpenAL::setMasterVolume(float gain)
|
||||
{
|
||||
m_master_gain = gain;
|
||||
|
||||
if(!m_ok) return;
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
|
||||
alSourcef(m_soundSource, AL_GAIN,
|
||||
alSourcef(m_sound_source, AL_GAIN,
|
||||
(m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
|
||||
SFXManager::checkError("setting volume");
|
||||
} //setMasterVolume
|
||||
@ -174,55 +208,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
|
||||
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)
|
||||
{
|
||||
m_loop = status;
|
||||
|
||||
if(m_status==SFX_UNKNOWN) return;
|
||||
|
||||
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");
|
||||
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_UNKNOWN) return;
|
||||
|
||||
m_is_playing = false;
|
||||
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);
|
||||
// This updates the status, i.e. potentially switches from
|
||||
// playing to stopped.
|
||||
getStatus();
|
||||
if(m_status!=SFX_PLAYING) 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()
|
||||
{
|
||||
SFXManager::get()->queue(SFXManager::SFX_RESUME, this);
|
||||
} // resume
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Resumes a sound effect.
|
||||
*/
|
||||
void SFXOpenAL::resume()
|
||||
void SFXOpenAL::reallyResumeNow()
|
||||
{
|
||||
if (!m_ok)
|
||||
// Will init the sfx (lazy) if necessary.
|
||||
getStatus();
|
||||
if(m_status==SFX_PAUSED)
|
||||
{
|
||||
// lazily create OpenAL source when needed
|
||||
init();
|
||||
|
||||
// creation of OpenAL source failed, giving up
|
||||
if (!m_ok) return;
|
||||
alSourcePlay(m_sound_source);
|
||||
SFXManager::checkError("resuming");
|
||||
m_status = SFX_PLAYING;
|
||||
}
|
||||
} // reallyResumeNow
|
||||
|
||||
alSourcePlay(m_soundSource);
|
||||
SFXManager::checkError("resuming");
|
||||
} // resume
|
||||
//-----------------------------------------------------------------------------
|
||||
/** 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.
|
||||
*/
|
||||
void SFXOpenAL::deleteSFX()
|
||||
{
|
||||
SFXManager::get()->queue(SFXManager::SFX_DELETE, this);
|
||||
} // deleteSFX
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This actually queues up the sfx in the sfx manager. It will be started
|
||||
@ -230,7 +310,11 @@ void SFXOpenAL::resume()
|
||||
*/
|
||||
void SFXOpenAL::play()
|
||||
{
|
||||
SFXManager::get()->queue(this);
|
||||
// Technically the sfx is only playing after the sfx thread starts it,
|
||||
// but for STK this is correct since we don't want to start the same
|
||||
// sfx twice.
|
||||
m_is_playing = true;
|
||||
SFXManager::get()->queue(SFXManager::SFX_PLAY, this);
|
||||
} // play
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -239,30 +323,68 @@ void SFXOpenAL::play()
|
||||
void SFXOpenAL::reallyPlayNow()
|
||||
{
|
||||
if (!SFXManager::get()->sfxAllowed()) return;
|
||||
if (!m_ok)
|
||||
if (m_status==SFX_UNKNOWN)
|
||||
{
|
||||
// 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);
|
||||
m_status = SFX_PLAYING;
|
||||
SFXManager::checkError("playing");
|
||||
|
||||
// At non-race time the end time is not important
|
||||
if(World::getWorld())
|
||||
{
|
||||
float t= World::getWorld()->getTime();
|
||||
// A special case: the track intro music starts at world clock = 0,
|
||||
// and has a duration of 3.7 seconds. So if the game is paused in the
|
||||
// first 3.7 seconds, the sfx wil be considered to be not finished
|
||||
// (since the world clock stays at 0 before the race start), and
|
||||
// therefore resumed if the game is resumed, which means it is
|
||||
// played again. To avoid this, any sound starting at t=0 is set
|
||||
// to have an end time of 0 - which means the track intro music is
|
||||
// not resumed in this case.
|
||||
m_end_time = t>0 ? t+m_sound_buffer->getDuration() : 0;
|
||||
}
|
||||
else
|
||||
m_end_time = 1.0f;
|
||||
} // reallyPlayNow
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns true if the sound effect is currently playing.
|
||||
*/
|
||||
bool SFXOpenAL::isPlaying()
|
||||
{
|
||||
return m_is_playing;
|
||||
} // isPlaying
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** 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 (m_status == SFX_UNKNOWN) 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(!UserConfigParams::m_sfx)
|
||||
return;
|
||||
if (!m_ok)
|
||||
if (m_status==SFX_UNKNOWN)
|
||||
{
|
||||
Log::warn("SFX", "Position called on non-ok SFX <%s>", m_soundBuffer->getFileName().c_str());
|
||||
Log::warn("SFX", "Position called on non-ok SFX <%s>",
|
||||
m_sound_buffer->getFileName().c_str());
|
||||
return;
|
||||
}
|
||||
if (!m_positional)
|
||||
@ -277,39 +399,20 @@ void SFXOpenAL::position(const Vec3 &position)
|
||||
return;
|
||||
}
|
||||
|
||||
alSource3f(m_soundSource, AL_POSITION,
|
||||
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_defaultGain : m_gain) * m_master_gain);
|
||||
}
|
||||
|
||||
SFXManager::checkError("positioning");
|
||||
} // position
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the status of this sound effect.
|
||||
*/
|
||||
SFXManager::SFXStatus SFXOpenAL::getStatus()
|
||||
{
|
||||
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
|
||||
} // reallySetPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -317,22 +420,22 @@ void SFXOpenAL::onSoundEnabledBack()
|
||||
{
|
||||
if (m_loop)
|
||||
{
|
||||
if (!m_ok) init();
|
||||
if (m_ok)
|
||||
if (m_status==SFX_UNKNOWN) 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_defaultGain : 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
|
||||
|
@ -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,9 +37,17 @@
|
||||
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;
|
||||
|
||||
bool m_positional;
|
||||
float m_defaultGain;
|
||||
|
||||
@ -55,37 +62,52 @@ private:
|
||||
the sound source won't be created and we'll be left with no clue when enabling
|
||||
sounds later. */
|
||||
float m_gain;
|
||||
|
||||
/** True when the sfx is currently playing. */
|
||||
bool m_is_playing;
|
||||
|
||||
/** The master gain set in user preferences */
|
||||
float m_master_gain;
|
||||
|
||||
/** If this sfx should also free the sound buffer. */
|
||||
bool m_owns_buffer;
|
||||
|
||||
/** Time at which a sfx ends playing. Used to avoid frequently getting
|
||||
* the openl status (which can slow down stk). */
|
||||
float m_end_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 bool init();
|
||||
virtual void play();
|
||||
virtual void reallyPlayNow();
|
||||
virtual void setLoop(bool status);
|
||||
virtual void reallySetLoop(bool status);
|
||||
virtual bool isPlaying();
|
||||
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);
|
||||
virtual SFXStatus getStatus();
|
||||
|
||||
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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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>")
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -235,12 +235,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
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -121,7 +121,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. */
|
||||
|
@ -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);
|
||||
|
@ -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) &&
|
||||
|
@ -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
|
||||
|
@ -350,6 +350,18 @@ void Camera::smoothMoveCamera(float dt)
|
||||
current_position += (wanted_position - current_position) * dt * 5;
|
||||
}
|
||||
|
||||
// Avoid camera crash: if the speed is negative, the current_position
|
||||
// can oscillate between plus and minus, getting bigger and bigger. If
|
||||
// this happens often enough, floating point overflow happens (large
|
||||
// negative speeds can happen when the kart is tumbling/falling)
|
||||
// To avoid this, we just move the camera to the wanted position if
|
||||
// the distance becomes too large (see #1356).
|
||||
if( (current_position - wanted_position).getLengthSQ() > 100)
|
||||
{
|
||||
Log::debug("camera", "Resetting camera position to avoid crash");
|
||||
current_position = wanted_position;
|
||||
}
|
||||
|
||||
if(m_mode!=CM_FALLING)
|
||||
m_camera->setPosition(current_position);
|
||||
m_camera->setTarget(current_target);//set new target
|
||||
@ -360,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
|
||||
|
||||
@ -566,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,8 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound, const char
|
||||
{
|
||||
// short emision time, explosion, not constant flame
|
||||
m_remaining_time = burst_time;
|
||||
|
||||
m_emission_frames = 0;
|
||||
|
||||
ParticleKindManager* pkm = ParticleKindManager::get();
|
||||
ParticleKind* particles = pkm->getParticles(particle_file);
|
||||
m_emitter = new ParticleEmitter(particles, coord, NULL);
|
||||
@ -67,6 +68,7 @@ bool Explosion::updateAndDelete(float dt)
|
||||
// so no need to save the result of the update call.
|
||||
HitSFX::updateAndDelete(dt);
|
||||
|
||||
m_emission_frames++;
|
||||
m_remaining_time -= dt;
|
||||
|
||||
if (m_remaining_time < 0.0f && m_remaining_time >= -explosion_time)
|
||||
@ -77,15 +79,14 @@ bool Explosion::updateAndDelete(float dt)
|
||||
node->getMaterial(0).AmbientColor.setGreen(intensity);
|
||||
node->getMaterial(0).DiffuseColor.setGreen(intensity);
|
||||
node->getMaterial(0).EmissiveColor.setGreen(intensity);
|
||||
|
||||
|
||||
node->getMaterial(0).AmbientColor.setBlue(intensity);
|
||||
node->getMaterial(0).DiffuseColor.setBlue(intensity);
|
||||
node->getMaterial(0).EmissiveColor.setBlue(intensity);
|
||||
|
||||
|
||||
node->getMaterial(0).AmbientColor.setRed(intensity);
|
||||
node->getMaterial(0).DiffuseColor.setRed(intensity);
|
||||
node->getMaterial(0).EmissiveColor.setRed(intensity);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -97,9 +98,14 @@ bool Explosion::updateAndDelete(float dt)
|
||||
// object is removed.
|
||||
if (m_remaining_time > -explosion_time)
|
||||
{
|
||||
// Stop the emitter and wait a little while for all particles to have time to fade out
|
||||
m_emitter->getNode()->getEmitter()->setMinParticlesPerSecond(0);
|
||||
m_emitter->getNode()->getEmitter()->setMaxParticlesPerSecond(0);
|
||||
// if framerate is very low, emit for at least a few frames, in case
|
||||
// burst time is lower than the time of 1 frame
|
||||
if (m_emission_frames > 2)
|
||||
{
|
||||
// Stop the emitter and wait a little while for all particles to have time to fade out
|
||||
m_emitter->getNode()->getEmitter()->setMinParticlesPerSecond(0);
|
||||
m_emitter->getNode()->getEmitter()->setMaxParticlesPerSecond(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -32,7 +32,7 @@ class Vec3;
|
||||
class SFXBase;
|
||||
class ParticleEmitter;
|
||||
|
||||
const float explosion_time = 1.5f;
|
||||
const float explosion_time = 2.0f;
|
||||
|
||||
/**
|
||||
* \ingroup graphics
|
||||
@ -41,6 +41,7 @@ class Explosion : public HitSFX
|
||||
{
|
||||
private:
|
||||
float m_remaining_time;
|
||||
int m_emission_frames;
|
||||
ParticleEmitter* m_emitter;
|
||||
|
||||
public:
|
||||
|
@ -820,7 +820,6 @@ void getGLLimits(HardwareStats::Json *json)
|
||||
STRING(VERSION);
|
||||
STRING(VENDOR);
|
||||
STRING(RENDERER);
|
||||
STRING(EXTENSIONS);
|
||||
INTEGER(SUBPIXEL_BITS);
|
||||
INTEGER(MAX_TEXTURE_SIZE);
|
||||
INTEGER(MAX_CUBE_MAP_TEXTURE_SIZE);
|
||||
|
@ -449,21 +449,4 @@ void ParticleSystemProxy::render() {
|
||||
m_first_execution = false;
|
||||
simulate();
|
||||
draw();
|
||||
}
|
||||
|
||||
bool ParticleSystemProxy::update()
|
||||
{
|
||||
doParticleSystem(os::Timer::getTime());
|
||||
return (IsVisible && (Particles.size() != 0));
|
||||
}
|
||||
|
||||
void ParticleSystemProxy::OnRegisterSceneNode()
|
||||
{
|
||||
doParticleSystem(os::Timer::getTime());
|
||||
|
||||
if (IsVisible && (Particles.size() != 0))
|
||||
{
|
||||
SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT_EFFECT);
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
}
|
||||
}
|
@ -70,7 +70,6 @@ public:
|
||||
|
||||
virtual void setEmitter(scene::IParticleEmitter* emitter);
|
||||
virtual void render();
|
||||
virtual void OnRegisterSceneNode();
|
||||
void setAlphaAdditive(bool val) { m_alpha_additive = val; }
|
||||
void setIncreaseFactor(float val) { size_increase_factor = val; }
|
||||
void setColorFrom(float r, float g, float b) { m_color_from[0] = r; m_color_from[1] = g; m_color_from[2] = b; }
|
||||
@ -79,7 +78,6 @@ public:
|
||||
const float* getColorTo() const { return m_color_to; }
|
||||
void setHeightmap(const std::vector<std::vector<float> >&, float, float, float, float);
|
||||
void setFlip();
|
||||
bool update();
|
||||
};
|
||||
|
||||
#endif // GPUPARTICLES_H
|
||||
|
@ -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,7 @@ 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();
|
||||
if(status==SFXBase::SFX_INITIAL) return false;
|
||||
return status!= SFXBase::SFX_PLAYING;
|
||||
} // updateAndDelete
|
||||
|
@ -2279,7 +2279,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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,31 +108,6 @@ enum TypeFBO
|
||||
FBO_COUNT
|
||||
};
|
||||
|
||||
enum QueryPerf
|
||||
{
|
||||
Q_SOLID_PASS1,
|
||||
Q_SHADOWS,
|
||||
Q_RSM,
|
||||
Q_RH,
|
||||
Q_GI,
|
||||
Q_ENVMAP,
|
||||
Q_SUN,
|
||||
Q_POINTLIGHTS,
|
||||
Q_SSAO,
|
||||
Q_SOLID_PASS2,
|
||||
Q_TRANSPARENT,
|
||||
Q_PARTICLES,
|
||||
Q_DISPLACEMENT,
|
||||
Q_DOF,
|
||||
Q_GODRAYS,
|
||||
Q_BLOOM,
|
||||
Q_TONEMAP,
|
||||
Q_MOTIONBLUR,
|
||||
Q_MLAA,
|
||||
Q_GUI,
|
||||
Q_LAST
|
||||
};
|
||||
|
||||
enum TypeRTT
|
||||
{
|
||||
RTT_TMP1 = 0,
|
||||
|
@ -80,7 +80,11 @@ int LODNode::getLevel()
|
||||
if (camera == NULL)
|
||||
return (int)m_detail.size() - 1;
|
||||
AbstractKart* kart = camera->getKart();
|
||||
const Vec3 &pos = kart->getFrontXYZ();
|
||||
// use kart position and not camera position when a kart is available,
|
||||
// because for some effects the camera will be moved to various locations
|
||||
// (for instance shadows), so using camera position for LOD may result
|
||||
// in objects being culled when they shouldn't
|
||||
const Vec3 &pos = (kart != NULL ? kart->getFrontXYZ() : camera->getCameraSceneNode()->getAbsolutePosition());
|
||||
|
||||
const int dist =
|
||||
(int)((m_nodes[0]->getAbsolutePosition()).getDistanceFromSQ(pos.toIrrVector() ));
|
||||
|
@ -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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -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);
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "utils/profiler.hpp"
|
||||
#include "utils/tuple.hpp"
|
||||
#include "stkscenemanager.hpp"
|
||||
#include "utils/profiler.hpp"
|
||||
|
||||
#include <S3DVertex.h>
|
||||
|
||||
@ -74,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
|
||||
{
|
||||
@ -92,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
|
||||
{
|
||||
@ -145,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
|
||||
{
|
||||
@ -164,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
|
||||
{
|
||||
@ -182,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
|
||||
{
|
||||
@ -530,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())
|
||||
{
|
||||
@ -860,8 +861,6 @@ static void multidrawShadow(unsigned i, Args ...args)
|
||||
|
||||
void IrrDriver::renderShadows()
|
||||
{
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_SHADOWS));
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@ -875,7 +874,7 @@ void IrrDriver::renderShadows()
|
||||
|
||||
for (unsigned cascade = 0; cascade < 4; cascade++)
|
||||
{
|
||||
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_SHADOWS_CASCADE0 + cascade));
|
||||
std::vector<GLuint> noTexUnits;
|
||||
|
||||
renderShadow<MeshShader::ShadowShader, video::EVT_STANDARD, 1>(noTexUnits, cascade, ListMatDefault::getInstance()->Shadows[cascade]);
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -787,7 +787,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 +832,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 +854,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 +865,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 +876,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 +886,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 +897,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 +926,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 +936,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 +947,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 +1455,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 +1496,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 +1507,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");
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -142,7 +142,11 @@ void STKAnimatedMesh::updateGL()
|
||||
if (!rnd->isTransparent())
|
||||
{
|
||||
Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
|
||||
Material::ShaderType MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType(), material);
|
||||
Material* material2 = NULL;
|
||||
if (mb->getMaterial().getTexture(1) != NULL)
|
||||
material2 = material_manager->getMaterialFor(mb->getMaterial().getTexture(1), mb);
|
||||
|
||||
Material::ShaderType MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType(), material, material2);
|
||||
InitTextures(mesh, MatType);
|
||||
}
|
||||
|
||||
|
@ -11,12 +11,16 @@
|
||||
#include "modes/world.hpp"
|
||||
|
||||
|
||||
Material::ShaderType MaterialTypeToMeshMaterial(video::E_MATERIAL_TYPE MaterialType, video::E_VERTEX_TYPE tp, Material* material)
|
||||
Material::ShaderType MaterialTypeToMeshMaterial(video::E_MATERIAL_TYPE MaterialType, video::E_VERTEX_TYPE tp,
|
||||
Material* material, Material* layer2Material)
|
||||
{
|
||||
if (layer2Material != NULL && layer2Material->getShaderType() == Material::SHADERTYPE_SPLATTING)
|
||||
return Material::SHADERTYPE_SPLATTING;
|
||||
|
||||
switch (material->getShaderType())
|
||||
{
|
||||
default:
|
||||
return material->getShaderType();
|
||||
return material->getShaderType();
|
||||
case Material::SHADERTYPE_SOLID:
|
||||
if (MaterialType == irr_driver->getShader(ES_NORMAL_MAP))
|
||||
return Material::SHADERTYPE_NORMAL_MAP;
|
||||
|
@ -174,7 +174,8 @@ class ListDisplacement : public MiscList<ListDisplacement, GLMesh *, core::matri
|
||||
class ListInstancedGlow : public Singleton<ListInstancedGlow>, public std::vector<GLMesh *>
|
||||
{};
|
||||
|
||||
Material::ShaderType MaterialTypeToMeshMaterial(video::E_MATERIAL_TYPE MaterialType, video::E_VERTEX_TYPE tp, Material* material);
|
||||
Material::ShaderType MaterialTypeToMeshMaterial(video::E_MATERIAL_TYPE MaterialType, video::E_VERTEX_TYPE tp,
|
||||
Material* material, Material* layer2Material);
|
||||
TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE, f32 MaterialTypeParam, Material* material);
|
||||
|
||||
void InitTextures(GLMesh &mesh, Material::ShaderType);
|
||||
|
@ -143,7 +143,10 @@ void STKMeshSceneNode::updateNoGL()
|
||||
else
|
||||
{
|
||||
assert(!isDisplacement);
|
||||
Material::ShaderType MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType(), material);
|
||||
Material* material2 = NULL;
|
||||
if (mb->getMaterial().getTexture(1) != NULL)
|
||||
material2 = material_manager->getMaterialFor(mb->getMaterial().getTexture(1), mb);
|
||||
Material::ShaderType MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType(), material, material2);
|
||||
if (!immediate_draw)
|
||||
MeshSolidMaterial[MatType].push_back(&mesh);
|
||||
}
|
||||
@ -179,7 +182,10 @@ void STKMeshSceneNode::updateGL()
|
||||
if (!rnd->isTransparent())
|
||||
{
|
||||
Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
|
||||
Material::ShaderType MatType = material->getShaderType();// MaterialTypeToMeshMaterial(type, mb->getVertexType(), material);
|
||||
Material* material2 = NULL;
|
||||
if (mb->getMaterial().getTexture(1) != NULL)
|
||||
material2 = material_manager->getMaterialFor(mb->getMaterial().getTexture(1), mb);
|
||||
Material::ShaderType MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType(), material, material2);
|
||||
if (!immediate_draw)
|
||||
InitTextures(mesh, MatType);
|
||||
}
|
||||
@ -319,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);
|
||||
|
@ -435,7 +435,7 @@ parseSceneManager(core::list<scene::ISceneNode*> List, std::vector<scene::IScene
|
||||
|
||||
if (ParticleSystemProxy *node = dynamic_cast<ParticleSystemProxy *>(*I))
|
||||
{
|
||||
if (!isCulledPrecise(cam, *I) && node->update())
|
||||
if (!isCulledPrecise(cam, *I))
|
||||
ParticlesList::getInstance()->push_back(node);
|
||||
continue;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -199,7 +199,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 +414,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 +448,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 +474,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 +529,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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1512,13 +1512,13 @@ void Skin::drawIconButton(const core::recti &rect, Widget* widget,
|
||||
SColor(100,255,255,255),
|
||||
SColor(100,255,255,255) };
|
||||
core::recti r(0,0,icon_widget->m_texture_w, icon_widget->m_texture_h);
|
||||
draw2DImage(icon_widget->m_texture, sized_rect,
|
||||
draw2DImage(icon_widget->getTexture(), sized_rect,
|
||||
r, 0 /* no clipping */, colors,
|
||||
true /* alpha */);
|
||||
}
|
||||
else
|
||||
{
|
||||
video::ITexture* t = icon_widget->m_texture;
|
||||
const video::ITexture* t = icon_widget->getTexture();
|
||||
|
||||
const bool mouseInside =
|
||||
rect.isPointInside(irr_driver->getDevice()->getCursorControl()
|
||||
|
@ -16,13 +16,13 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "utils/vs.hpp"
|
||||
|
||||
#include <IGUIEnvironment.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
@ -36,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;
|
||||
@ -44,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++)
|
||||
@ -53,10 +55,14 @@ DynamicRibbonWidget::DynamicRibbonWidget(const bool combo, const bool multi_row)
|
||||
m_selected_item[0] = 0; // only player 0 has a selection by default
|
||||
|
||||
m_item_count_hint = 0;
|
||||
|
||||
m_font = GUIEngine::getFont()->getHollowCopy();
|
||||
m_max_label_width = 0;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
DynamicRibbonWidget::~DynamicRibbonWidget()
|
||||
{
|
||||
delete m_font;
|
||||
if (m_animated_contents)
|
||||
{
|
||||
GUIEngine::needsUpdate.remove(this);
|
||||
@ -252,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)
|
||||
{
|
||||
@ -270,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
|
||||
{
|
||||
@ -294,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();
|
||||
@ -328,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() );
|
||||
@ -379,6 +385,13 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
ribbon->m_properties[PROP_ID] = name.str();
|
||||
ribbon->m_event_handler = this;
|
||||
|
||||
// calculate font size
|
||||
if (m_col_amount > 0)
|
||||
{
|
||||
m_font->setScale(GUIEngine::getFont()->getScale() *
|
||||
getFontScale((ribbon->m_w / m_col_amount) - 30));
|
||||
}
|
||||
|
||||
// add columns
|
||||
for (int i=0; i<m_col_amount; i++)
|
||||
{
|
||||
@ -392,12 +405,13 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
icon->m_properties[PROP_HEIGHT] = m_properties[PROP_CHILD_HEIGHT];
|
||||
icon->m_w = atoi(icon->m_properties[PROP_WIDTH].c_str());
|
||||
icon->m_h = atoi(icon->m_properties[PROP_HEIGHT].c_str());
|
||||
icon->setLabelFont(m_font);
|
||||
|
||||
// If we want each icon to have its own label, we must make it non-empty, otherwise
|
||||
// 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++;
|
||||
@ -438,14 +452,14 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
assert(childrenCount == (int)m_items.size());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void DynamicRibbonWidget::addItem( const irr::core::stringw& user_name, const std::string& code_name,
|
||||
const std::string& image_file, const unsigned int badges,
|
||||
IconButtonWidget::IconPathType image_path_type)
|
||||
{
|
||||
ItemDescription desc;
|
||||
desc.m_user_name = user_name;
|
||||
desc.m_user_name = getUserName(user_name);
|
||||
desc.m_code_name = code_name;
|
||||
desc.m_sshot_file = image_file;
|
||||
desc.m_badges = badges;
|
||||
@ -453,6 +467,8 @@ void DynamicRibbonWidget::addItem( const irr::core::stringw& user_name, const st
|
||||
desc.m_image_path_type = image_path_type;
|
||||
|
||||
m_items.push_back(desc);
|
||||
|
||||
setLabelSize(desc.m_user_name);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -462,7 +478,7 @@ void DynamicRibbonWidget::addAnimatedItem( const irr::core::stringw& user_name,
|
||||
const unsigned int badges, IconButtonWidget::IconPathType image_path_type )
|
||||
{
|
||||
ItemDescription desc;
|
||||
desc.m_user_name = user_name;
|
||||
desc.m_user_name = getUserName(user_name);
|
||||
desc.m_code_name = code_name;
|
||||
desc.m_all_images = image_files;
|
||||
desc.m_badges = badges;
|
||||
@ -473,6 +489,8 @@ void DynamicRibbonWidget::addAnimatedItem( const irr::core::stringw& user_name,
|
||||
|
||||
m_items.push_back(desc);
|
||||
|
||||
setLabelSize(desc.m_user_name);
|
||||
|
||||
if (!m_animated_contents)
|
||||
{
|
||||
m_animated_contents = true;
|
||||
@ -498,6 +516,7 @@ void DynamicRibbonWidget::clearItems()
|
||||
m_items.clear();
|
||||
m_animated_contents = false;
|
||||
m_scroll_offset = 0;
|
||||
m_max_label_width = 0;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void DynamicRibbonWidget::elementRemoved()
|
||||
@ -593,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;
|
||||
}
|
||||
@ -663,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();
|
||||
@ -738,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;
|
||||
@ -1062,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)
|
||||
{
|
||||
@ -1097,7 +1115,9 @@ bool DynamicRibbonWidget::setSelection(int item_id, const int playerID,
|
||||
propagateSelection();
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool DynamicRibbonWidget::setSelection(const std::string &item_codename,
|
||||
const int playerID, const bool focusIt,
|
||||
bool evenIfDeactivated)
|
||||
@ -1117,4 +1137,29 @@ bool DynamicRibbonWidget::setSelection(const std::string &item_codename,
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void DynamicRibbonWidget::setLabelSize(const irr::core::stringw& text)
|
||||
{
|
||||
int w = GUIEngine::getFont()->getDimension(text.c_str()).Width;
|
||||
if (w > m_max_label_width)
|
||||
m_max_label_width = w;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
float DynamicRibbonWidget::getFontScale(int icon_width) const
|
||||
{
|
||||
if (m_max_label_width <= icon_width || m_max_label_width == 0 || icon_width == 0)
|
||||
return 1.0f;
|
||||
else
|
||||
return std::max (0.5f, ((float)icon_width / (float)m_max_label_width));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
irr::core::stringw DynamicRibbonWidget::getUserName(const irr::core::stringw& user_name) const
|
||||
{
|
||||
if (m_max_label_length == 0 || user_name.size() < m_max_label_length)
|
||||
return user_name;
|
||||
else
|
||||
return (user_name.subString(0, m_max_label_length - 3) + L"...");
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
namespace GUIEngine
|
||||
{
|
||||
class IconButtonWidget;
|
||||
|
||||
|
||||
/**
|
||||
* Even if you have a ribbon that only acts on click/enter, you may wish to know which
|
||||
* item is currently highlighted. In this case, create a listener and pass it to the ribbon.
|
||||
@ -44,7 +44,7 @@ namespace GUIEngine
|
||||
const irr::core::stringw& selectionText,
|
||||
const int playerID) = 0;
|
||||
};
|
||||
|
||||
|
||||
/** The description of an item added to a DynamicRibbonWidget */
|
||||
struct ItemDescription
|
||||
{
|
||||
@ -52,16 +52,16 @@ namespace GUIEngine
|
||||
std::string m_code_name;
|
||||
std::string m_sshot_file;
|
||||
IconButtonWidget::IconPathType m_image_path_type;
|
||||
|
||||
|
||||
bool m_animated;
|
||||
/** used instead of 'm_sshot_file' if m_animated is true */
|
||||
std::vector<std::string> m_all_images;
|
||||
float m_curr_time;
|
||||
float m_time_per_frame;
|
||||
|
||||
|
||||
unsigned int m_badges;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief An extended version of RibbonWidget, with more capabilities.
|
||||
* A dynamic ribbon builds upon RibbonWidget, adding dynamic contents creation and sizing,
|
||||
@ -73,55 +73,55 @@ namespace GUIEngine
|
||||
class DynamicRibbonWidget : public Widget, public RibbonWidget::IRibbonListener
|
||||
{
|
||||
friend class RibbonWidget;
|
||||
|
||||
|
||||
/** A list of all listeners that registered to be notified on hover/selection */
|
||||
PtrVector<DynamicRibbonHoverListener> m_hover_listeners;
|
||||
|
||||
|
||||
virtual ~DynamicRibbonWidget();
|
||||
|
||||
|
||||
/** Used for ribbon grids that have a label at the bottom */
|
||||
bool m_has_label;
|
||||
irr::gui::IGUIStaticText* m_label;
|
||||
|
||||
|
||||
/** Height of ONE label text line (if label is multiline only one line is measured here).
|
||||
* If there is no label, will be 0.
|
||||
*/
|
||||
int m_label_height;
|
||||
|
||||
|
||||
/** Whether this ribbon contains at least one animated item */
|
||||
bool m_animated_contents;
|
||||
|
||||
|
||||
/** Whether there are more items than can fit in a single screen; arrows will then appear
|
||||
* on each side of the ribbon to scroll the contents
|
||||
*/
|
||||
bool m_scrolling_enabled;
|
||||
|
||||
|
||||
/** Used to keep track of item count changes */
|
||||
int m_previous_item_count;
|
||||
|
||||
|
||||
/** List of items in the ribbon */
|
||||
std::vector<ItemDescription> m_items;
|
||||
|
||||
|
||||
/** Width of the scrolling arrows on each side */
|
||||
int m_arrows_w;
|
||||
|
||||
|
||||
/** Current scroll offset within items */
|
||||
int m_scroll_offset;
|
||||
|
||||
|
||||
/** Width and height of children as declared in the GUI file */
|
||||
int m_child_width, m_child_height;
|
||||
|
||||
|
||||
/** Number of rows and columns. Number of columns can dynamically change, number of row is
|
||||
determined at creation */
|
||||
int m_row_amount;
|
||||
int m_col_amount;
|
||||
|
||||
|
||||
/** The total number of columns given item count and row count (even counting not visible with current scrolling) */
|
||||
int m_needed_cols;
|
||||
|
||||
|
||||
/** Whether this ribbon can have multiple rows (i.e. ribbon grid) or is a single line */
|
||||
bool m_multi_row;
|
||||
|
||||
|
||||
/** irrlicht relies on consecutive IDs to perform keyboard navigation between widgets. However, since this
|
||||
widget is dynamic, irrlicht widgets are not created as early as all others, so by the time we're ready
|
||||
to create the full contents of this widget, the ID generator is already incremented, thus messing up
|
||||
@ -129,65 +129,81 @@ namespace GUIEngine
|
||||
number of IDs (the number of rows) and store them here. Then, when we're finally ready to create the
|
||||
contents dynamically, we can re-use these IDs and get correct navigation order. */
|
||||
std::vector<int> m_ids;
|
||||
|
||||
|
||||
/** Whether this is a "combo" style ribbon grid widget */
|
||||
bool m_combo;
|
||||
|
||||
|
||||
/* reference pointers only, the actual instances are owned by m_children */
|
||||
IconButtonWidget* m_left_widget;
|
||||
IconButtonWidget* m_right_widget;
|
||||
|
||||
|
||||
/** Returns the currently selected row */
|
||||
RibbonWidget* getSelectedRibbon(const int playerID);
|
||||
|
||||
|
||||
/** Returns the row */
|
||||
RibbonWidget* getRowContaining(Widget* w);
|
||||
|
||||
|
||||
/** Updates the visible label to match the currently selected item */
|
||||
void updateLabel(RibbonWidget* from_this_ribbon=NULL);
|
||||
|
||||
|
||||
/** Even though the ribbon grid widget looks like a grid, it is really a vertical stack of
|
||||
independant ribbons. When moving selection horizontally, this method is used to notify
|
||||
other rows above and below of which column is selected, so that moving vertically to
|
||||
another row keeps the same selected column. */
|
||||
void propagateSelection();
|
||||
|
||||
|
||||
/** Callback called widget is focused */
|
||||
EventPropagation focused(const int playerID);
|
||||
|
||||
|
||||
/** Removes all previously added contents icons, and re-adds them (calculating the new amount) */
|
||||
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];
|
||||
|
||||
|
||||
/** Callbacks */
|
||||
virtual void add();
|
||||
virtual EventPropagation mouseHovered(Widget* child, const int playerID);
|
||||
virtual EventPropagation transmitEvent(Widget* w, const std::string& originator, const int playerID);
|
||||
|
||||
|
||||
bool findItemInRows(const char* name, int* p_row, int* p_id);
|
||||
|
||||
|
||||
int m_item_count_hint;
|
||||
|
||||
|
||||
float getFontScale(int icon_width) const;
|
||||
void setLabelSize(const irr::core::stringw& text);
|
||||
irr::core::stringw getUserName(const irr::core::stringw& user_name) const;
|
||||
|
||||
/**
|
||||
* Font used to write the labels, can be scaled down depending on the
|
||||
* length of the text
|
||||
*/
|
||||
irr::gui::ScalableFont* m_font;
|
||||
|
||||
/** Max width of a label, in pixels */
|
||||
int m_max_label_width;
|
||||
|
||||
/** Max length of a label, in characters */
|
||||
unsigned int m_max_label_length;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
|
||||
/**
|
||||
* \param combo Whether this is a "combo" ribbon, i.e. whether there is always one selected item.
|
||||
* If set to false, will behave more like a toolbar.
|
||||
* \param multi_row Whether this ribbon can have more than one row
|
||||
*/
|
||||
DynamicRibbonWidget(const bool combo, const bool multi_row);
|
||||
|
||||
|
||||
/** Reference pointers only, the actual instances are owned by m_children. Used to create mtultiple-row
|
||||
ribbons (what appears to be a grid of icons is actually a vector of stacked basic ribbons) */
|
||||
PtrVector<RibbonWidget, REF> m_rows;
|
||||
|
||||
|
||||
/** Dynamically add an item to the ribbon's list of items (will not be visible until you
|
||||
* call 'updateItemDisplay' or 'add').
|
||||
*
|
||||
@ -200,7 +216,7 @@ namespace GUIEngine
|
||||
void addItem( const irr::core::stringw& user_name, const std::string& code_name,
|
||||
const std::string& image_file, const unsigned int badge=0,
|
||||
IconButtonWidget::IconPathType image_path_type=IconButtonWidget::ICON_PATH_TYPE_RELATIVE);
|
||||
|
||||
|
||||
/** Dynamically add an animated item to the ribbon's list of items (will not be visible until you
|
||||
* call 'updateItemDisplay' or 'add'). Animated means it has many images that will be shown in
|
||||
* a slideshown fashion.
|
||||
@ -220,7 +236,7 @@ namespace GUIEngine
|
||||
/** Clears all items added through 'addItem'. You can then add new items with 'addItem' and call
|
||||
'updateItemDisplay' to update the display. */
|
||||
void clearItems();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Register a listener to be notified of selection changes within the ribbon.
|
||||
* \note The ribbon takes ownership of this listener and will delete it.
|
||||
@ -228,26 +244,26 @@ namespace GUIEngine
|
||||
* want to add a listener in the "init" callback of your screen.
|
||||
*/
|
||||
void registerHoverListener(DynamicRibbonHoverListener* listener);
|
||||
|
||||
|
||||
/** Called when right key is pressed */
|
||||
EventPropagation rightPressed(const int playerID);
|
||||
|
||||
|
||||
/** Called when left key is pressed */
|
||||
EventPropagation leftPressed(const int playerID);
|
||||
|
||||
|
||||
/** Updates icons/labels given current items and scrolling offset, taking care of resizing
|
||||
the dynamic ribbon if the number of items changed */
|
||||
void updateItemDisplay();
|
||||
|
||||
|
||||
/** Get the internal name (ID) of the selected item */
|
||||
const std::string& getSelectionIDString(const int playerID);
|
||||
|
||||
|
||||
/** Get the user-visible text of the selected item */
|
||||
irr::core::stringw getSelectionText(const int playerID);
|
||||
|
||||
|
||||
/** Returns a read-only list of items added to this ribbon */
|
||||
const std::vector<ItemDescription>& getItems() const { return m_items; }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Select an item from its numerical ID. Only for [1-row] combo ribbons.
|
||||
*
|
||||
@ -255,7 +271,7 @@ namespace GUIEngine
|
||||
* \return Whether setting the selection was successful (whether the item exists)
|
||||
*/
|
||||
bool setSelection(int item_id, const int playerID, const bool focusIt, bool evenIfDeactivated=false);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Select an item from its codename.
|
||||
*
|
||||
@ -264,26 +280,29 @@ namespace GUIEngine
|
||||
bool setSelection(const std::string &item_codename,
|
||||
const int playerID, const bool focusIt,
|
||||
bool evenIfDeactivated=false);
|
||||
|
||||
|
||||
/** \brief Callback from parent class Widget. */
|
||||
virtual void elementRemoved();
|
||||
|
||||
|
||||
/** \brief callback from IRibbonListener */
|
||||
virtual void onRibbonWidgetScroll(const int delta_x);
|
||||
|
||||
|
||||
/** \brief callback from IRibbonListener */
|
||||
virtual void onRibbonWidgetFocus(RibbonWidget* emitter, const int playerID);
|
||||
|
||||
|
||||
/** \brief callback from IRibbonListener */
|
||||
virtual void onSelectionChange(){}
|
||||
|
||||
virtual void update(float delta);
|
||||
|
||||
|
||||
/** 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; }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <IGUIEnvironment.h>
|
||||
#include <IGUIButton.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace GUIEngine;
|
||||
using namespace irr::video;
|
||||
@ -39,10 +40,15 @@ IconButtonWidget::IconButtonWidget(ScaleMode scale_mode, const bool tab_stop,
|
||||
const bool focusable, IconPathType pathType) : Widget(WTYPE_ICON_BUTTON)
|
||||
{
|
||||
m_label = NULL;
|
||||
m_font = NULL;
|
||||
m_texture = NULL;
|
||||
m_deactivated_texture = NULL;
|
||||
m_highlight_texture = NULL;
|
||||
m_custom_aspect_ratio = 1.0f;
|
||||
|
||||
m_texture_w = 0;
|
||||
m_texture_h = 0;
|
||||
|
||||
m_tab_stop = tab_stop;
|
||||
m_focusable = focusable;
|
||||
m_scale_mode = scale_mode;
|
||||
@ -57,12 +63,12 @@ void IconButtonWidget::add()
|
||||
{
|
||||
if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE)
|
||||
{
|
||||
m_texture = irr_driver->getTexture(m_properties[PROP_ICON]);
|
||||
setTexture(irr_driver->getTexture(m_properties[PROP_ICON]));
|
||||
}
|
||||
else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE)
|
||||
{
|
||||
std::string file = file_manager->getAsset(m_properties[PROP_ICON]);
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,13 +78,11 @@ void IconButtonWidget::add()
|
||||
"add() : error, cannot find texture '%s'.",
|
||||
m_properties[PROP_ICON].c_str());
|
||||
std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png");
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
if(!m_texture)
|
||||
Log::fatal("IconButtonWidget",
|
||||
"Can't find fallback texture 'gui/main_help.png, aborting.");
|
||||
}
|
||||
m_texture_w = m_texture->getSize().Width;
|
||||
m_texture_h = m_texture->getSize().Height;
|
||||
|
||||
if (m_properties[PROP_FOCUS_ICON].size() > 0)
|
||||
{
|
||||
@ -174,13 +178,7 @@ void IconButtonWidget::add()
|
||||
m_label->setVisible(false);
|
||||
}
|
||||
|
||||
const int max_w = m_label->getAbsolutePosition().getWidth();
|
||||
|
||||
if (!word_wrap &&
|
||||
(int)GUIEngine::getFont()->getDimension(message.c_str()).Width > max_w + 4) // arbitrarily allow for 4 pixels
|
||||
{
|
||||
m_label->setOverrideFont( GUIEngine::getSmallFont() );
|
||||
}
|
||||
setLabelFont();
|
||||
|
||||
#if IRRLICHT_VERSION_MAJOR > 1 || (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8)
|
||||
m_label->setRightToLeft( translations->isRTLLanguage() );
|
||||
@ -192,6 +190,9 @@ void IconButtonWidget::add()
|
||||
m_id = m_element->getID();
|
||||
if (m_tab_stop) m_element->setTabOrder(m_id);
|
||||
m_element->setTabGroup(false);
|
||||
|
||||
if (!m_is_visible)
|
||||
m_element->setVisible(false);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -207,12 +208,12 @@ void IconButtonWidget::setImage(const char* path_to_texture, IconPathType pathTy
|
||||
|
||||
if (m_icon_path_type == ICON_PATH_TYPE_ABSOLUTE)
|
||||
{
|
||||
m_texture = irr_driver->getTexture(m_properties[PROP_ICON]);
|
||||
setTexture(irr_driver->getTexture(m_properties[PROP_ICON]));
|
||||
}
|
||||
else if (m_icon_path_type == ICON_PATH_TYPE_RELATIVE)
|
||||
{
|
||||
std::string file = file_manager->getAsset(m_properties[PROP_ICON]);
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
|
||||
if (!m_texture)
|
||||
@ -220,11 +221,8 @@ void IconButtonWidget::setImage(const char* path_to_texture, IconPathType pathTy
|
||||
Log::error("icon_button", "Texture '%s' not found!\n",
|
||||
m_properties[PROP_ICON].c_str());
|
||||
std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png");
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
|
||||
m_texture_w = m_texture->getSize().Width;
|
||||
m_texture_h = m_texture->getSize().Height;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -233,39 +231,28 @@ void IconButtonWidget::setImage(ITexture* texture)
|
||||
{
|
||||
if (texture != NULL)
|
||||
{
|
||||
m_texture = texture;
|
||||
|
||||
m_texture_w = m_texture->getSize().Width;
|
||||
m_texture_h = m_texture->getSize().Height;
|
||||
setTexture(texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("icon_button",
|
||||
"setImage invoked with NULL image pointer\n");
|
||||
std::string file = file_manager->getAsset(FileManager::GUI,"main_help.png");
|
||||
m_texture = irr_driver->getTexture(file);
|
||||
setTexture(irr_driver->getTexture(file));
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setLabel(stringw new_label)
|
||||
void IconButtonWidget::setLabel(const stringw& new_label)
|
||||
{
|
||||
if (m_label == NULL) return;
|
||||
|
||||
m_label->setText( new_label.c_str() );
|
||||
|
||||
const bool word_wrap = (m_properties[PROP_WORD_WRAP] == "true");
|
||||
const int max_w = m_label->getAbsolutePosition().getWidth();
|
||||
|
||||
if (!word_wrap &&
|
||||
(int)GUIEngine::getFont()->getDimension(new_label.c_str()).Width
|
||||
> max_w + 4) // arbitrarily allow for 4 pixels
|
||||
{
|
||||
m_label->setOverrideFont( GUIEngine::getSmallFont() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_label->setOverrideFont( NULL );
|
||||
}
|
||||
setLabelFont();
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setLabelFont(irr::gui::ScalableFont* font)
|
||||
{
|
||||
m_font = font;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation IconButtonWidget::focused(const int playerID)
|
||||
@ -287,5 +274,95 @@ 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)
|
||||
{
|
||||
m_texture = texture;
|
||||
if (texture == NULL)
|
||||
{
|
||||
m_deactivated_texture = NULL;
|
||||
m_texture_w = 0;
|
||||
m_texture_h = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_texture_w = texture->getSize().Width;
|
||||
m_texture_h = texture->getSize().Height;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void IconButtonWidget::setLabelFont()
|
||||
{
|
||||
if (m_font != NULL)
|
||||
{
|
||||
m_label->setOverrideFont( m_font );
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool word_wrap = (m_properties[PROP_WORD_WRAP] == "true");
|
||||
const int max_w = m_label->getAbsolutePosition().getWidth();
|
||||
|
||||
if (!word_wrap &&
|
||||
(int)GUIEngine::getFont()->getDimension(m_label->getText()).Width
|
||||
> max_w + 4) // arbitrarily allow for 4 pixels
|
||||
{
|
||||
m_label->setOverrideFont( GUIEngine::getSmallFont() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_label->setOverrideFont( NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,16 @@
|
||||
#include <irrString.h>
|
||||
namespace irr
|
||||
{
|
||||
namespace gui { class IGUIStaticText; }
|
||||
namespace gui
|
||||
{
|
||||
class IGUIStaticText;
|
||||
class ScalableFont;
|
||||
}
|
||||
namespace video { class ITexture; }
|
||||
}
|
||||
|
||||
#include "guiengine/widget.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
@ -38,6 +41,15 @@ namespace GUIEngine
|
||||
*/
|
||||
class IconButtonWidget : public Widget
|
||||
{
|
||||
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:
|
||||
enum ScaleMode
|
||||
{
|
||||
@ -54,42 +66,41 @@ namespace GUIEngine
|
||||
* the path type as it currently is */
|
||||
ICON_PATH_TYPE_NO_CHANGE
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
IconPathType m_icon_path_type;
|
||||
|
||||
friend class Skin;
|
||||
|
||||
irr::gui::IGUIStaticText* m_label;
|
||||
irr::video::ITexture* m_texture;
|
||||
irr::video::ITexture* m_highlight_texture;
|
||||
|
||||
int m_texture_w, m_texture_h;
|
||||
|
||||
protected:
|
||||
|
||||
IconPathType m_icon_path_type;
|
||||
|
||||
friend class Skin;
|
||||
|
||||
irr::gui::IGUIStaticText* m_label;
|
||||
irr::gui::ScalableFont* m_font;
|
||||
|
||||
ScaleMode m_scale_mode;
|
||||
float m_custom_aspect_ratio;
|
||||
|
||||
|
||||
void setTexture(video::ITexture* texture);
|
||||
|
||||
public:
|
||||
|
||||
LEAK_CHECK()
|
||||
|
||||
|
||||
/** Whether to make the widget included in keyboard navigation order when adding */
|
||||
bool m_tab_stop;
|
||||
|
||||
IconButtonWidget(ScaleMode scale_mode=SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO, const bool tab_stop=true,
|
||||
const bool focusable=true, IconPathType pathType=ICON_PATH_TYPE_RELATIVE);
|
||||
virtual ~IconButtonWidget() {}
|
||||
|
||||
virtual ~IconButtonWidget() {};
|
||||
|
||||
/** \brief Implement callback from base class Widget */
|
||||
virtual void add();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Call this if scale mode is SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO.
|
||||
* \param custom_aspect_ratio The width/height aspect ratio
|
||||
*/
|
||||
void setCustomAspectRatio(float custom_aspect_ratio) { m_custom_aspect_ratio = custom_aspect_ratio; }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Temporarily change the text label if there is a label (next time this screen is
|
||||
* visited, the previous label will be back. For a permanent change, edit the 'text'
|
||||
@ -98,8 +109,15 @@ namespace GUIEngine
|
||||
* \pre Must be called after this widget is add()ed to have any effect
|
||||
* \note Calling this method on a button without label will have no effect
|
||||
*/
|
||||
void setLabel(irr::core::stringw new_label);
|
||||
|
||||
void setLabel(const irr::core::stringw& new_label);
|
||||
|
||||
/**
|
||||
* \brief Sets the font used to draw the label.
|
||||
*
|
||||
* \note Calling this method on a button without label will have no effect
|
||||
*/
|
||||
void setLabelFont(irr::gui::ScalableFont* font);
|
||||
|
||||
/**
|
||||
* Change the texture used for this icon.
|
||||
* \pre At the moment, the new texture must have the same aspct ratio
|
||||
@ -109,7 +127,7 @@ namespace GUIEngine
|
||||
*/
|
||||
void setImage(const char* path_to_texture,
|
||||
IconPathType path_type=ICON_PATH_TYPE_NO_CHANGE);
|
||||
// --------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------
|
||||
/** Convenience function taking std::string. */
|
||||
void setImage(const std::string &path_to_texture,
|
||||
IconPathType path_type=ICON_PATH_TYPE_NO_CHANGE)
|
||||
@ -126,23 +144,23 @@ namespace GUIEngine
|
||||
* \note May safely be called no matter if the widget is add()ed or not
|
||||
*/
|
||||
void setImage(irr::video::ITexture* texture);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
void setHighlightedImage(irr::video::ITexture* texture)
|
||||
{
|
||||
m_highlight_texture = texture;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** \brief override from base class */
|
||||
virtual EventPropagation focused(const int playerID);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** \brief override from base class */
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -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?
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user