Merge branch 'master' into Instancing
11
.travis.yml
@ -6,9 +6,7 @@
|
||||
language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
#- clang
|
||||
git:
|
||||
submodules: false
|
||||
# - clang
|
||||
#branches:
|
||||
# only:
|
||||
# - master
|
||||
@ -16,10 +14,13 @@ before_install:
|
||||
# UPDATE REPOS
|
||||
- sudo apt-get update -qq
|
||||
# INSTALL DEPENDENCIES
|
||||
- sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev
|
||||
- sudo apt-get install build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev
|
||||
script:
|
||||
# BUILD COMMANDS
|
||||
- ./tools/build-linux-travis.sh
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=Debug
|
||||
- make VERBOSE=1 -j 4
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
|
@ -3,7 +3,7 @@ project(SuperTuxKart)
|
||||
set(PROJECT_VERSION "0.8.1")
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.1)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
||||
|
||||
include(BuildTypeSTKRelease)
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
|
BIN
data/CREDITS
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<achievements>
|
||||
<achievement id="1" check-type="all-at-least" reset-after-race="no"
|
||||
<achievement id="1" check-type="all-at-least" reset-type="never"
|
||||
title="Christoffel Columbus" description="Play every official track at least once." >
|
||||
<farm goal="1"/>
|
||||
<scotland goal="1"/>
|
||||
@ -13,21 +13,35 @@
|
||||
<hacienda goal="1"/>
|
||||
<jungle goal="1"/>
|
||||
</achievement>
|
||||
<achievement id="2" check-type="all-at-least" reset-after-race="no"
|
||||
<achievement id="2" check-type="all-at-least" reset-type="never"
|
||||
title="Strike!" description="Hit 10 karts with a bowling-ball.">
|
||||
<ball goal="10"/>
|
||||
</achievement>
|
||||
<achievement id="3" check-type="one-at-least" reset-after-race="yes"
|
||||
<achievement id="3" check-type="one-at-least" reset-type="race"
|
||||
title="Arch Enemy" description="Hit the same kart at least 5 times in one race">
|
||||
<hit goal="5"/>
|
||||
</achievement>
|
||||
<achievement id="4" check-type="all-at-least" reset-after-race="yes"
|
||||
<achievement id="4" check-type="all-at-least" reset-type="race"
|
||||
title="Marathoner" description="Make a race with 5 laps or more">
|
||||
<laps goal="5"/>
|
||||
</achievement>
|
||||
<achievement id="5" check-type="all-at-least" reset-after-race="yes"
|
||||
title="Skid-row" description="Make 5 skidding in a single race">
|
||||
<achievement id="5" check-type="all-at-least" reset-type="lap"
|
||||
title="Skid-row" description="Make 5 skidding in a single lap">
|
||||
<skidding goal="5"/>
|
||||
</achievement>
|
||||
</achievements>
|
||||
|
||||
<achievement id="6" check-type="all-at-least" reset-type="never"
|
||||
title="Gold driver" description="Win in all single player modes, against at least 3 opponents.">
|
||||
<standard goal="1"/>
|
||||
<std_timetrial goal="1"/>
|
||||
<follow_leader goal="1"/>
|
||||
<opponents goal="3"/>
|
||||
</achievement>
|
||||
<achievement id="7" check-type="all-at-least" reset-type="race"
|
||||
title="Powerup Love" description="Use 10 or more powerups in a race">
|
||||
<poweruplover goal="10"/>
|
||||
</achievement>
|
||||
<achievement id="8" check-type="all-at-least" reset-type="never"
|
||||
title="Unstoppable" description="Win 5 single races in a row">
|
||||
<wins goal="5"/>
|
||||
</achievement>
|
||||
</achievements>
|
BIN
data/gui/down.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
54
data/gui/edit_track.stkgui
Normal file
@ -0,0 +1,54 @@
|
||||
<stkgui>
|
||||
|
||||
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row" padding="10">
|
||||
|
||||
<header id="selected_track" width="80%" height="30"
|
||||
I18N="No neeed to translate this, it will be overwritten by the track name"
|
||||
text="" align="center" text_align="center" />
|
||||
|
||||
<spacer height="20" />
|
||||
|
||||
<!-- Track selection -->
|
||||
<box width="100%" height="60%" layout="vertical-row">
|
||||
<ribbon_grid id="tracks" proportion="1" width="100%" height="100%" square_items="true"
|
||||
label_location="each" align="center" child_width="240" child_height="160" />
|
||||
</box>
|
||||
|
||||
<!-- Populated dynamically at runtime -->
|
||||
<tabs width="100%" height="30" id="trackgroups"> </tabs>
|
||||
|
||||
<spacer height="50" />
|
||||
|
||||
<!-- Laps and reverse -->
|
||||
<div width="100%" height="100" layout="horizontal-row" align="center">
|
||||
|
||||
<spacer proportion="1" />
|
||||
|
||||
<label id="laps_label" text_align="left"
|
||||
I18N="In the edit track screen" text="Number of laps:" />
|
||||
<spacer width="20" />
|
||||
<spinner id="laps" proportion="1" width="100" min_value="1"
|
||||
max_value="99" wrap_around="false" />
|
||||
|
||||
<spacer proportion="1" />
|
||||
|
||||
<label id="reverse_label" text_align="left"
|
||||
I18N="In the edit track screen" text="Reverse:" />
|
||||
<spacer width="20" />
|
||||
<checkbox id="reverse" />
|
||||
|
||||
<spacer proportion="1" />
|
||||
</div>
|
||||
|
||||
<!-- Dialog buttons -->
|
||||
<div width="100%" height="60" layout="horizontal-row">
|
||||
<spacer proportion="2" />
|
||||
<button id="ok" text="OK" proportion="1" />
|
||||
<spacer proportion="1" />
|
||||
<button id="cancel" text="Cancel" proportion="1" />
|
||||
<spacer proportion="2" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</stkgui>
|
21
data/gui/enter_gp_name_dialog.stkgui
Normal file
@ -0,0 +1,21 @@
|
||||
<stkgui>
|
||||
|
||||
<div x="2%" y="10%" width="96%" height="80%" layout="vertical-row" >
|
||||
|
||||
<label id="title" width="100%" text_align="center" word_wrap="true"
|
||||
I18N="In the 'add new grand prix' dialog"
|
||||
text="Please enter the name of the grand prix" proportion="1" />
|
||||
|
||||
<spacer height="25" width="10" />
|
||||
|
||||
<textbox id="textfield" width="75%" I18N="In the 'add new grand prix' dialog" align="center"/>
|
||||
|
||||
<spacer height="20" width="20" />
|
||||
|
||||
<button id="cancel" I18N="When configuring input" text="Press ESC to cancel" align="center"/>
|
||||
|
||||
<spacer height="15" width="20" />
|
||||
|
||||
</div>
|
||||
|
||||
</stkgui>
|
BIN
data/gui/gp_add_track.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
data/gui/gp_copy.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
data/gui/gp_edit.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
data/gui/gp_edit_track.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
data/gui/gp_new.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
data/gui/gp_remove.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
data/gui/gp_remove_track.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
data/gui/gp_rename.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
data/gui/gp_save.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
35
data/gui/gpedit.stkgui
Normal file
@ -0,0 +1,35 @@
|
||||
<stkgui>
|
||||
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png" />
|
||||
|
||||
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row">
|
||||
|
||||
<header id="title" width="80%" I18N="Title in edit grand prix screen"
|
||||
text="Edit Grand Prix" align="center" text_align="center" />
|
||||
|
||||
<spacer width="100%" height="2%" />
|
||||
|
||||
<box proportion="5" width="98%" align="center" layout="vertical-row" padding="6">
|
||||
<list id="tracks" x="0" y="0" width="100%" height="100%" keep_selection="true" />
|
||||
</box>
|
||||
|
||||
<spacer width="100%" height="2%" />
|
||||
|
||||
<buttonbar proportion="1" id="menu" height="135" width="100%" align="center">
|
||||
<icon-button id="up" width="128" height="128" icon="gui/up.png"
|
||||
I18N="Menu item" text="Move up" />
|
||||
<icon-button id="down" width="128" height="128" icon="gui/down.png"
|
||||
I18N="Menu item" text="Move down" />
|
||||
<icon-button id="add" width="128" height="128" icon="gui/gp_add_track.png"
|
||||
I18N="Menu item" text="Add" />
|
||||
<icon-button id="edit" width="128" height="128" icon="gui/gp_edit_track.png"
|
||||
I18N="Menu item" text="Edit" />
|
||||
<icon-button id="remove" width="128" height="128" icon="gui/gp_remove_track.png"
|
||||
I18N="Menu item" text="Remove" />
|
||||
<icon-button id="save" width="128" height="128" icon="gui/gp_save.png"
|
||||
I18N="Menu item" text="Save" />
|
||||
</buttonbar>
|
||||
|
||||
</div>
|
||||
|
||||
</stkgui>
|
BIN
data/gui/gpeditor.png
Normal file
After Width: | Height: | Size: 16 KiB |
45
data/gui/gpeditor.stkgui
Normal file
@ -0,0 +1,45 @@
|
||||
<stkgui>
|
||||
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row" >
|
||||
|
||||
<header width="80%" I18N="Title in grand prix editor screen" text="Grand Prix editor"
|
||||
align="center" text_align="center" />
|
||||
|
||||
<spacer height="20" />
|
||||
|
||||
<box proportion="4" width="100%" layout="vertical-row">
|
||||
<ribbon_grid id="gplist" proportion="1" width="100%" square_items="true"
|
||||
label_location="each" align="left" max_rows="2" child_width="160"
|
||||
child_height="120" keep_selection="true" />
|
||||
</box>
|
||||
|
||||
<spacer height="10" />
|
||||
|
||||
<box proportion="2" width="100%" layout="vertical-row">
|
||||
<label id="gpname" text_align="center" width="100%"
|
||||
I18N="In the grand prix editor screen" text="" />
|
||||
<ribbon_grid id="tracks" proportion="1" width="100%" square_items="true"
|
||||
label_location="each" align="left" max_rows="1"
|
||||
child_width="160" child_height="120" />
|
||||
</box>
|
||||
|
||||
<spacer height="20" />
|
||||
|
||||
<buttonbar proportion="1" id="menu" height="135" width="100%" align="center">
|
||||
<icon-button id="new" width="128" height="128" icon="gui/gp_new.png"
|
||||
I18N="Menu item" text="New" />
|
||||
<icon-button id="copy" width="128" height="128" icon="gui/gp_copy.png"
|
||||
I18N="Menu item" text="Copy" />
|
||||
<icon-button id="edit" width="128" height="128" icon="gui/gp_edit.png"
|
||||
I18N="Menu item" text="Edit" />
|
||||
<icon-button id="remove" width="128" height="128" icon="gui/gp_remove.png"
|
||||
I18N="Menu item" text="Remove" />
|
||||
<icon-button id="rename" width="128" height="128" icon="gui/gp_rename.png"
|
||||
I18N="Menu item" text="Rename" />
|
||||
</buttonbar>
|
||||
|
||||
</div>
|
||||
|
||||
</stkgui>
|
@ -1,9 +1,9 @@
|
||||
<stkgui>
|
||||
|
||||
|
||||
<div x="0" y="0" width="100%" height="100%" layout="vertical-row" >
|
||||
|
||||
<icon id="logo" align="center" proportion="5" width="100%" icon="gui/logo.png"/>
|
||||
|
||||
|
||||
<buttonbar id="menu_toprow" proportion="3" width="90%" align="center">
|
||||
<icon-button id="story" width="128" height="128"
|
||||
icon="gui/menu_story.png" focus_icon="gui/menu_story_focus.png"
|
||||
@ -21,35 +21,37 @@
|
||||
icon="gui/menu_addons.png" focus_icon="gui/menu_addons_focus.png"
|
||||
I18N="Main menu button" text="Addons"/>
|
||||
</buttonbar>
|
||||
|
||||
|
||||
<spacer width="10" height="7%"/>
|
||||
|
||||
|
||||
<bottombar width="100%" height="10%" layout="horizontal-row">
|
||||
|
||||
<spacer width="10" height="10" />
|
||||
|
||||
|
||||
<label proportion="3" height="100%" id="info_addons"
|
||||
I18N="In the main screen"
|
||||
text=""
|
||||
align="center" text_align="left" />
|
||||
|
||||
|
||||
<spacer width="10" height="10" />
|
||||
|
||||
<buttonbar id="menu_bottomrow" x="0" y="0" width="30%" height="100%" align="center">
|
||||
|
||||
<buttonbar id="menu_bottomrow" x="0" y="0" width="38%" height="100%" align="center">
|
||||
<icon-button id="options" width="64" height="64" icon="gui/main_options.png" extend_label="50"
|
||||
I18N="Main menu button" text="Options" label_location="hover"/>
|
||||
<icon-button id="help" width="64" height="64" icon="gui/main_help.png" extend_label="50"
|
||||
I18N="Main menu button" text="Help" label_location="hover"/>
|
||||
<icon-button id="startTutorial" width="64" height="64" icon="gui/tutorial.png" extend_label="150"
|
||||
I18N="Main menu button" text="Tutorial" label_location="hover"/>
|
||||
<icon-button id="gpEditor" width="64" height="64" icon="gui/gpeditor.png" extend_label="150"
|
||||
I18N="Main menu button" text="Grand Prix Editor" label_location="hover"/>
|
||||
<icon-button id="about" width="64" height="64" icon="gui/main_about.png" extend_label="50"
|
||||
I18N="Main menu button" text="About" label_location="hover"/>
|
||||
<icon-button id="quit" width="64" height="64" icon="gui/main_quit.png" extend_label="50"
|
||||
I18N="Main menu button" text="Quit" label_location="hover"/>
|
||||
</buttonbar>
|
||||
|
||||
|
||||
</bottombar>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</stkgui>
|
||||
|
BIN
data/gui/up.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
@ -1,9 +1,4 @@
|
||||
uniform sampler2D Albedo;
|
||||
uniform sampler2D DiffuseMap;
|
||||
uniform sampler2D SpecularMap;
|
||||
uniform sampler2D SSAO;
|
||||
uniform vec2 screen;
|
||||
uniform vec3 ambient;
|
||||
uniform sampler2D caustictex;
|
||||
uniform vec2 dir;
|
||||
uniform vec2 dir2;
|
||||
@ -16,17 +11,14 @@ varying vec2 uv;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
vec3 getLightFactor(float specMapValue);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 tc = gl_FragCoord.xy / screen;
|
||||
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
|
||||
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
|
||||
vec4 color = texture(Albedo, uv);
|
||||
float ao = texture(SSAO, tc).x;
|
||||
|
||||
float caustic = texture(caustictex, uv + dir).x;
|
||||
float caustic2 = texture(caustictex, (uv.yx + dir2 * vec2(-0.6, 0.3)) * vec2(0.6)).x;
|
||||
|
||||
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent + caustic * caustic2 * 10;
|
||||
vec3 LightFactor = getLightFactor(1.) + caustic * caustic2 * 10;
|
||||
FragColor = vec4(color.xyz * LightFactor, 1.);
|
||||
}
|
||||
|
@ -12,6 +12,208 @@ varying vec2 uv;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
#define PI 3.14159265
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
// TEST
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
float width = 1920; //texture width
|
||||
float height = 1080; //texture height
|
||||
|
||||
vec2 texel = vec2(1.0/width,1.0/height);
|
||||
|
||||
//------------------------------------------
|
||||
//user variables
|
||||
|
||||
int samples = 3; //samples on the first ring
|
||||
int rings = 5; //ring count
|
||||
|
||||
bool autofocus = false; //use autofocus in shader? disable if you use external focalDepth value
|
||||
float focalDepth = 0.1;
|
||||
vec2 focus = vec2(0.5,0.5); // autofocus point on screen (0.0,0.0 - left lower corner, 1.0,1.0 - upper right)
|
||||
float range = 150.0; //focal range
|
||||
float maxblur = 1.25; //clamp value of max blur
|
||||
|
||||
float threshold = 0.9; //highlight threshold;
|
||||
float gain = 10.0; //highlight gain;
|
||||
|
||||
float bias = 0.4; //bokeh edge bias
|
||||
float fringe = 0.5; //bokeh chromatic aberration/fringing
|
||||
|
||||
bool noise = true; //use noise instead of pattern for sample dithering
|
||||
float namount = 0.0001; //dither amount
|
||||
|
||||
bool depthblur = false; //blur the depth buffer?
|
||||
float dbsize = 2.0; //depthblursize
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
// Function
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
vec3 color(vec2 coords,float blur) //processing the sample
|
||||
{
|
||||
vec3 col = vec3(0.0);
|
||||
|
||||
col.r = texture2D(tex,coords + vec2(0.0,1.0)*texel*fringe*blur).r;
|
||||
col.g = texture2D(tex,coords + vec2(-0.866,-0.5)*texel*fringe*blur).g;
|
||||
col.b = texture2D(tex,coords + vec2(0.866,-0.5)*texel*fringe*blur).b;
|
||||
|
||||
vec3 lumcoeff = vec3(0.299,0.587,0.114);
|
||||
float lum = dot(col.rgb, lumcoeff);
|
||||
float thresh = max((lum-threshold)*gain, 0.0);
|
||||
return col+mix(vec3(0.0),col,thresh*blur);
|
||||
}
|
||||
|
||||
vec2 rand(in vec2 coord) //generating noise/pattern texture for dithering
|
||||
{
|
||||
float noiseX = ((fract(1.0-coord.s*(width/2.0))*0.25)+(fract(coord.t*(height/2.0))*0.75))*2.0-1.0;
|
||||
float noiseY = ((fract(1.0-coord.s*(width/2.0))*0.75)+(fract(coord.t*(height/2.0))*0.25))*2.0-1.0;
|
||||
|
||||
if (noise)
|
||||
{
|
||||
noiseX = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233))) * 43758.5453),0.0,1.0)*2.0-1.0;
|
||||
noiseY = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233)*2.0)) * 43758.5453),0.0,1.0)*2.0-1.0;
|
||||
}
|
||||
return vec2(noiseX,noiseY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
//float depth = texture2D(dtex,uv).x;
|
||||
|
||||
float curdepth = texture(dtex, uv).x;
|
||||
vec4 FragPos = invprojm * (2.0f * vec4(uv, curdepth, 1.0f) - 1.0f);
|
||||
FragPos /= FragPos.w;
|
||||
|
||||
float depth = clamp((FragPos.z/180), 0., 1.);
|
||||
|
||||
|
||||
float blur = 0.0;
|
||||
|
||||
|
||||
blur = clamp((abs(depth - focalDepth)/range)*100.0,-maxblur,maxblur);
|
||||
|
||||
vec2 noise = rand(uv)*namount*blur;
|
||||
|
||||
float w = (1.0/width)*blur+noise.x;
|
||||
float h = (1.0/height)*blur+noise.y;
|
||||
|
||||
vec3 col = texture2D(tex, uv).rgb;
|
||||
vec3 colDof = col;
|
||||
float s = 1.0;
|
||||
|
||||
int ringsamples;
|
||||
|
||||
for (int i = 1; i <= rings; i += 1)
|
||||
{
|
||||
ringsamples = i * samples;
|
||||
|
||||
for (int j = 0 ; j < ringsamples ; j += 1)
|
||||
{
|
||||
float step = PI*2.0 / float(ringsamples);
|
||||
float pw = (cos(float(j)*step)*float(i));
|
||||
float ph = (sin(float(j)*step)*float(i));
|
||||
float p = 1.0;
|
||||
|
||||
colDof += color(uv + vec2(pw*w,ph*h),blur)*mix(1.0,(float(i))/(float(rings)),bias)*p;
|
||||
s += 1.0*mix(1.0,(float(i))/(float(rings)),bias)*p;
|
||||
}
|
||||
}
|
||||
colDof /= s;
|
||||
|
||||
// get color correction values
|
||||
float inBlack = inlevel.x;
|
||||
float inWhite = inlevel.z;
|
||||
float inGamma = inlevel.y;
|
||||
|
||||
float outBlack = outlevel.x;
|
||||
float outWhite = outlevel.y;
|
||||
|
||||
vec3 colOut = (pow(((col.rgb * 255.0) - inBlack) / (inWhite - inBlack),
|
||||
vec3(1.0 / inGamma)) * (outWhite - outBlack) + outBlack) / 255.0;
|
||||
|
||||
depth = (1 - depth);
|
||||
vec3 final = colOut * depth + colDof.rgb * (1 - depth);
|
||||
|
||||
vec2 inTex = uv - 0.5;
|
||||
float vignette = 1 - dot(inTex, inTex);
|
||||
|
||||
vignette = clamp(pow(vignette, 0.8), 0., 1.) ;
|
||||
vignette = vignette + vignette - 0.5;
|
||||
final.rgb *= clamp(vignette, 0., 1.15);
|
||||
|
||||
FragColor.rgb = final;
|
||||
FragColor.a = 1.0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
vec2 texc = uv;
|
||||
//texc.y = 1.0 - texc.y;
|
||||
|
||||
|
||||
vec4 col = texture(tex, texc);
|
||||
float curdepth = texture(dtex, uv).x;
|
||||
|
||||
vec2 inTex = uv - 0.5;
|
||||
float vignette = 1 - dot(inTex, inTex);
|
||||
|
||||
vec4 FragPos = invprojm * (2.0f * vec4(uv, curdepth, 1.0f) - 1.0f);
|
||||
FragPos /= FragPos.w;
|
||||
|
||||
//col = col / (1 - col);
|
||||
|
||||
float inBlack = inlevel.x;
|
||||
float inWhite = inlevel.z;
|
||||
float inGamma = inlevel.y;
|
||||
|
||||
float outBlack = outlevel.x;
|
||||
float outWhite = outlevel.y;
|
||||
|
||||
float depth1 = clamp((FragPos.z/180), 0., 1.);
|
||||
|
||||
vec3 colOut = (pow(((col.rgb * 255.0) - inBlack) / (inWhite - inBlack),
|
||||
vec3(1.0 / inGamma)) * (outWhite - outBlack) + outBlack) / 255.0;
|
||||
|
||||
depth1 = (1 - depth1);
|
||||
vec3 final = colOut * depth1 + col.rgb * (1 - depth1);
|
||||
|
||||
vignette = clamp(pow(vignette, 0.8), 0., 1.) ;
|
||||
vignette = vignette + vignette - 0.5;
|
||||
final.rgb *= clamp(vignette, 0., 1.15);
|
||||
FragColor = vec4(final, 1.0);
|
||||
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/*uniform sampler2D tex;
|
||||
uniform sampler2D dtex;
|
||||
uniform vec3 inlevel;
|
||||
uniform vec2 outlevel;
|
||||
uniform mat4 invprojm;
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec2 uv;
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
varying vec2 uv;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void main()
|
||||
@ -21,14 +223,14 @@ void main()
|
||||
float curdepth = texture(dtex, uv).x;
|
||||
vec4 FragPos = invprojm * (2.0 * vec4(uv, curdepth, 1.0f) - 1.0f);
|
||||
FragPos /= FragPos.w;
|
||||
float depth = clamp(FragPos.z / 180, 0, 1);
|
||||
float depth = clamp(FragPos.z / 180, 0., 1.);
|
||||
depth = (1 - depth);
|
||||
|
||||
// Compute the vignette
|
||||
vec2 inside = uv - 0.5;
|
||||
float vignette = 1 - dot(inside, inside);
|
||||
vignette = clamp(pow(vignette, 0.8), 0, 1);
|
||||
vignette = clamp(vignette + vignette - 0.5, 0, 1.15);
|
||||
vignette = clamp(pow(vignette, 0.8), 0., 1.);
|
||||
vignette = clamp(vignette + vignette - 0.5, 0., 1.15);
|
||||
|
||||
float inBlack = inlevel.x;
|
||||
float inWhite = inlevel.z;
|
||||
@ -44,4 +246,4 @@ void main()
|
||||
|
||||
FragColor = vec4(colFinal * vignette, 1.0);
|
||||
//FragColor = vec4(vec3(depth), 1.0);
|
||||
}
|
||||
}*/
|
||||
|
@ -1,10 +1,5 @@
|
||||
uniform sampler2D Albedo;
|
||||
uniform sampler2D Detail;
|
||||
uniform sampler2D DiffuseMap;
|
||||
uniform sampler2D SpecularMap;
|
||||
uniform sampler2D SSAO;
|
||||
uniform vec2 screen;
|
||||
uniform vec3 ambient;
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec2 uv;
|
||||
@ -16,17 +11,13 @@ varying vec2 uv_bis;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
|
||||
vec3 getLightFactor(float specMapValue);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 tc = gl_FragCoord.xy / screen;
|
||||
vec4 color = texture(Albedo, uv);
|
||||
vec4 detail = texture(Detail, uv_bis);
|
||||
color *= detail;
|
||||
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
|
||||
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
|
||||
float ao = texture(SSAO, tc).x;
|
||||
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent * (1. - color.a);
|
||||
FragColor = vec4(color.xyz * LightFactor * ao, 1.);
|
||||
vec4 detail = texture(Detail, uv_bis);
|
||||
color *= detail;
|
||||
vec3 LightFactor = getLightFactor(1. - color.a);
|
||||
FragColor = vec4(color.xyz * LightFactor, 1.);
|
||||
}
|
||||
|
@ -14,12 +14,7 @@ varying vec2 uv;
|
||||
#define Spec gl_FragData[1]
|
||||
#endif
|
||||
|
||||
vec3 DecodeNormal(vec2 n)
|
||||
{
|
||||
float z = dot(n, n) * 2. - 1.;
|
||||
vec2 xy = normalize(n) * sqrt(1. - z * z);
|
||||
return vec3(xy,z);
|
||||
}
|
||||
vec3 DecodeNormal(vec2 n);
|
||||
|
||||
mat4 getMatrix(float L[9])
|
||||
{
|
||||
|
@ -13,11 +13,8 @@ varying vec2 uv;
|
||||
#endif
|
||||
|
||||
|
||||
// from Crytek "a bit more deferred CryEngine"
|
||||
vec2 EncodeNormal(vec3 n)
|
||||
{
|
||||
return normalize(n.xy) * sqrt(n.z * 0.5 + 0.5);
|
||||
}
|
||||
|
||||
vec2 EncodeNormal(vec3 n);
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -6,13 +6,7 @@ varying vec3 nor;
|
||||
#define EncodedNormal gl_FragColor.xy
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// from Crytek "a bit more deferred CryEngine"
|
||||
vec2 EncodeNormal(vec3 n)
|
||||
{
|
||||
return normalize(n.xy) * sqrt(n.z * 0.5 + 0.5);
|
||||
}
|
||||
vec2 EncodeNormal(vec3 n);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
@ -1,9 +1,4 @@
|
||||
uniform sampler2D Albedo;
|
||||
uniform sampler2D DiffuseMap;
|
||||
uniform sampler2D SpecularMap;
|
||||
uniform sampler2D SSAO;
|
||||
uniform vec2 screen;
|
||||
uniform vec3 ambient;
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec2 uv;
|
||||
@ -13,15 +8,11 @@ varying vec2 uv;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
vec3 getLightFactor(float specMapValue);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 tc = gl_FragCoord.xy / screen;
|
||||
vec4 color = texture(Albedo, uv);
|
||||
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
|
||||
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
|
||||
float ao = texture(SSAO, tc).x;
|
||||
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent * (1. - color.a);
|
||||
FragColor = vec4(color.xyz * LightFactor * (0.4 + ao*0.6), 1.);
|
||||
//FragColor = vec4(color.xyz * LightFactor, 1.);
|
||||
vec3 LightFactor = getLightFactor(1. - color.a);
|
||||
FragColor = vec4(color.xyz * LightFactor, 1.);
|
||||
}
|
||||
|
@ -10,12 +10,7 @@ varying vec2 uv;
|
||||
#define EncodedNormal gl_FragColor.xy
|
||||
#endif
|
||||
|
||||
|
||||
// from Crytek "a bit more deferred CryEngine"
|
||||
vec2 EncodeNormal(vec3 n)
|
||||
{
|
||||
return normalize(n.xy) * sqrt(n.z * 0.5 + 0.5);
|
||||
}
|
||||
vec2 EncodeNormal(vec3 n);
|
||||
|
||||
void main() {
|
||||
vec4 col = texture(tex, uv);
|
||||
|
@ -1,9 +1,4 @@
|
||||
uniform sampler2D Albedo;
|
||||
uniform sampler2D DiffuseMap;
|
||||
uniform sampler2D SpecularMap;
|
||||
uniform sampler2D SSAO;
|
||||
uniform vec2 screen;
|
||||
uniform vec3 ambient;
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec2 uv;
|
||||
@ -13,15 +8,12 @@ varying vec2 uv;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
vec3 getLightFactor(float specMapValue);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 color = texture(Albedo, uv);
|
||||
if (color.a < 0.5) discard;
|
||||
vec2 tc = gl_FragCoord.xy / screen;
|
||||
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
|
||||
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
|
||||
float ao = texture(SSAO, tc).x;
|
||||
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent;
|
||||
vec3 LightFactor = getLightFactor(1.);
|
||||
FragColor = vec4(color.xyz * LightFactor, 1.);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#version 330
|
||||
#version 140
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec2 uv;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Passthrough shader for drawQuad()
|
||||
#version 330
|
||||
#version 140
|
||||
|
||||
in vec3 Position;
|
||||
in vec2 Texcoord;
|
||||
|
@ -12,12 +12,7 @@ flat in vec3 col;
|
||||
out vec4 Diffuse;
|
||||
out vec4 Specular;
|
||||
|
||||
vec3 DecodeNormal(vec2 n)
|
||||
{
|
||||
float z = dot(n, n) * 2. - 1.;
|
||||
vec2 xy = normalize(n) * sqrt(1. - z * z);
|
||||
return vec3(xy,z);
|
||||
}
|
||||
vec3 DecodeNormal(vec2 n);
|
||||
|
||||
void main() {
|
||||
vec2 texc = gl_FragCoord.xy / screen;
|
||||
|
@ -25,12 +25,7 @@ vec3 rand(vec2 co)
|
||||
return texture(noise_texture, co*20.16).xyz;
|
||||
}
|
||||
|
||||
vec3 DecodeNormal(vec2 n)
|
||||
{
|
||||
float z = dot(n, n) * 2. - 1.;
|
||||
vec2 xy = normalize(n) * sqrt(1. - z * z);
|
||||
return vec3(xy,z);
|
||||
}
|
||||
vec3 DecodeNormal(vec2 n);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
@ -19,12 +19,7 @@ varying vec2 uv;
|
||||
#endif
|
||||
|
||||
|
||||
vec3 DecodeNormal(vec2 n)
|
||||
{
|
||||
float z = dot(n, n) * 2. - 1.;
|
||||
vec2 xy = normalize(n) * sqrt(1. - z * z);
|
||||
return vec3(xy,z);
|
||||
}
|
||||
vec3 DecodeNormal(vec2 n);
|
||||
|
||||
void main() {
|
||||
float z = texture(dtex, uv).x;
|
||||
|
@ -23,18 +23,13 @@ varying vec2 uv;
|
||||
#endif
|
||||
|
||||
|
||||
vec3 DecodeNormal(vec2 n)
|
||||
{
|
||||
float z = dot(n, n) * 2. - 1.;
|
||||
vec2 xy = normalize(n) * sqrt(1. - z * z);
|
||||
return vec3(xy,z);
|
||||
}
|
||||
vec3 DecodeNormal(vec2 n);
|
||||
|
||||
float getShadowFactor(vec3 pos, float bias, int index)
|
||||
{
|
||||
//float a[5] = float[](3.4, 4.2, 5.0, 5.2, 1.1);
|
||||
|
||||
const vec2 shadowoffset[4] = vec2[](
|
||||
vec2 shadowoffset[4] = vec2[](
|
||||
vec2(-1., -1.),
|
||||
vec2(-1., 1.),
|
||||
vec2(1., -1.),
|
||||
|
@ -2,6 +2,7 @@ uniform sampler2D tex;
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec2 uv;
|
||||
in vec4 color;
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
varying vec2 uv;
|
||||
@ -11,5 +12,5 @@ varying vec2 uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(tex, uv);
|
||||
FragColor = texture(tex, uv) * color;
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ uniform mat4 TextureMatrix;
|
||||
#if __VERSION__ >= 130
|
||||
in vec3 Position;
|
||||
in vec2 Texcoord;
|
||||
in vec4 Color;
|
||||
out vec2 uv;
|
||||
out vec4 color;
|
||||
#else
|
||||
attribute vec3 Position;
|
||||
attribute vec2 Texcoord;
|
||||
@ -16,4 +18,5 @@ void main()
|
||||
{
|
||||
uv = (TextureMatrix * vec4(Texcoord, 1., 1.)).xy;
|
||||
gl_Position = ModelViewProjectionMatrix * vec4(Position, 1.);
|
||||
color = Color;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ uniform vec2 screen;
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec2 uv;
|
||||
in vec4 color;
|
||||
out vec4 FragColor;
|
||||
#else
|
||||
varying vec2 uv;
|
||||
@ -20,7 +21,7 @@ varying vec2 uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture(tex, uv);
|
||||
vec4 diffusecolor = texture(tex, uv) * color;
|
||||
vec3 tmp = vec3(gl_FragCoord.xy / screen, gl_FragCoord.z);
|
||||
tmp = 2. * tmp - 1.;
|
||||
|
||||
@ -33,5 +34,5 @@ void main()
|
||||
|
||||
fog = min(fog, fogmax);
|
||||
|
||||
FragColor = vec4(vec4(col, 0.) * fog + color *(1. - fog));
|
||||
FragColor = vec4(vec4(col, 0.) * fog + diffusecolor *(1. - fog));
|
||||
}
|
||||
|
@ -1,8 +1,3 @@
|
||||
uniform sampler2D DiffuseMap;
|
||||
uniform sampler2D SpecularMap;
|
||||
uniform sampler2D SSAO;
|
||||
uniform vec2 screen;
|
||||
uniform vec3 ambient;
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
in vec4 color;
|
||||
@ -12,14 +7,10 @@ varying vec4 color;
|
||||
#define FragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
vec3 getLightFactor(float specMapValue);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 tc = gl_FragCoord.xy / screen;
|
||||
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
|
||||
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
|
||||
float ao = texture(SSAO, tc).x;
|
||||
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent * (1. - color.a);
|
||||
|
||||
FragColor = vec4(color.xyz * LightFactor * ao, 1.);
|
||||
vec3 LightFactor = getLightFactor(1.);
|
||||
FragColor = vec4(color.xyz * LightFactor, 1.);
|
||||
}
|
||||
|
7
data/shaders/utils/decodeNormal.frag
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
vec3 DecodeNormal(vec2 n)
|
||||
{
|
||||
float z = dot(n, n) * 2. - 1.;
|
||||
vec2 xy = normalize(n) * sqrt(1. - z * z);
|
||||
return vec3(xy,z);
|
||||
}
|
5
data/shaders/utils/encode_normal.frag
Normal file
@ -0,0 +1,5 @@
|
||||
// from Crytek "a bit more deferred CryEngine"
|
||||
vec2 EncodeNormal(vec3 n)
|
||||
{
|
||||
return normalize(n.xy) * sqrt(n.z * 0.5 + 0.5);
|
||||
}
|
15
data/shaders/utils/getLightFactor.frag
Normal file
@ -0,0 +1,15 @@
|
||||
uniform sampler2D DiffuseMap;
|
||||
uniform sampler2D SpecularMap;
|
||||
uniform sampler2D SSAO;
|
||||
uniform vec2 screen;
|
||||
uniform vec3 ambient;
|
||||
|
||||
vec3 getLightFactor(float specMapValue)
|
||||
{
|
||||
vec2 tc = gl_FragCoord.xy / screen;
|
||||
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
|
||||
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
|
||||
float ao = texture(SSAO, tc).x;
|
||||
vec3 tmp = ao * ambient + DiffuseComponent + SpecularComponent * specMapValue;
|
||||
return tmp * (0.4 + ao*0.6);
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
# CMakeLists.txt for Irrlicht in STK
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/jpeglib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/libpng
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/zlib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/bzip2)
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/jpeglib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/libpng"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/zlib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/bzip2")
|
||||
|
||||
if(APPLE)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/MacOSX ${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht)
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/MacOSX" "${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch i386")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch i386 -F/Library/Frameworks")
|
||||
endif()
|
||||
|
@ -368,6 +368,65 @@ void IrrPrintXGrabError(int grabResult, const c8 * grabCommand )
|
||||
}
|
||||
#endif
|
||||
|
||||
static GLXContext getMeAGLContext(Display *display, GLXFBConfig glxFBConfig)
|
||||
{
|
||||
GLXContext Context;
|
||||
int compat33ctx[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int core33ctx[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int core31ctx[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
None
|
||||
};
|
||||
int legacyctx[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
None
|
||||
};
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = 0;
|
||||
glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
|
||||
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
|
||||
|
||||
// create compat 3.3 context (for proprietary drivers)
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, compat33ctx);
|
||||
if (!XErrorSignaled)
|
||||
return Context;
|
||||
|
||||
XErrorSignaled = false;
|
||||
// create core 3.3 context (for mesa)
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, core33ctx);
|
||||
if (!XErrorSignaled)
|
||||
return Context;
|
||||
|
||||
XErrorSignaled = false;
|
||||
// create core 3.1 context (for older mesa)
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, core31ctx);
|
||||
if (!XErrorSignaled)
|
||||
return Context;
|
||||
|
||||
XErrorSignaled = false;
|
||||
// fall back to legacy context
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, legacyctx);
|
||||
return Context;
|
||||
}
|
||||
|
||||
bool CIrrDeviceLinux::createWindow()
|
||||
{
|
||||
@ -741,30 +800,7 @@ bool CIrrDeviceLinux::createWindow()
|
||||
glxWin=glXCreateWindow(display,glxFBConfig,window,NULL);
|
||||
if (glxWin)
|
||||
{
|
||||
int context_attribs[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, //GLX_CONTEXT_CORE_PROFILE_BIT_ARB
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
None
|
||||
};
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = 0;
|
||||
glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
|
||||
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
|
||||
// create glx context
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, context_attribs);
|
||||
if (XErrorSignaled)
|
||||
{
|
||||
int context_attribs[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
None
|
||||
};
|
||||
Context = glXCreateContextAttribsARB(display, glxFBConfig, 0, True, context_attribs);
|
||||
XErrorSignaled = false;
|
||||
}
|
||||
Context = getMeAGLContext(display, glxFBConfig);
|
||||
if (Context)
|
||||
{
|
||||
if (!glXMakeContextCurrent(display, glxWin, glxWin, Context))
|
||||
|
@ -868,16 +868,9 @@ bool COpenGLFBODepthTexture::attach(ITexture* renderTex)
|
||||
#ifdef GL_EXT_framebuffer_object
|
||||
if (UseStencil)
|
||||
{
|
||||
// attach stencil texture to stencil buffer
|
||||
// attach depth stencil texture to depth buffer
|
||||
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
|
||||
GL_STENCIL_ATTACHMENT_EXT,
|
||||
GL_TEXTURE_2D,
|
||||
StencilRenderBuffer,
|
||||
0);
|
||||
|
||||
// attach depth texture to depth buffer
|
||||
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
|
||||
GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_DEPTH_STENCIL_ATTACHMENT,
|
||||
GL_TEXTURE_2D,
|
||||
DepthRenderBuffer,
|
||||
0);
|
||||
|
@ -2,6 +2,16 @@
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.1)
|
||||
|
||||
# libbluetooth is required on Unix platforms
|
||||
if(UNIX)
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(BLUETOOTH bluez)
|
||||
if(NOT BLUETOOTH_FOUND)
|
||||
message(FATAL_ERROR "Bluetooth library not found. "
|
||||
"Either install libbluetooth or disable wiiuse support with -DUSE_WIIUSE=0")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(WIIUSE_SOURCES
|
||||
classic.c
|
||||
dynamics.c
|
||||
|
@ -228,6 +228,7 @@ src/states_screens/dialogs/addons_loading.cpp
|
||||
src/states_screens/dialogs/change_password_dialog.cpp
|
||||
src/states_screens/dialogs/confirm_resolution_dialog.cpp
|
||||
src/states_screens/dialogs/custom_video_settings.cpp
|
||||
src/states_screens/dialogs/enter_gp_name_dialog.cpp
|
||||
src/states_screens/dialogs/enter_player_name_dialog.cpp
|
||||
src/states_screens/dialogs/gp_info_dialog.cpp
|
||||
src/states_screens/dialogs/message_dialog.cpp
|
||||
@ -244,7 +245,10 @@ src/states_screens/dialogs/tutorial_message_dialog.cpp
|
||||
src/states_screens/dialogs/user_info_dialog.cpp
|
||||
src/states_screens/dialogs/vote_dialog.cpp
|
||||
src/states_screens/easter_egg_screen.cpp
|
||||
src/states_screens/edit_gp_screen.cpp
|
||||
src/states_screens/edit_track_screen.cpp
|
||||
src/states_screens/feature_unlocked.cpp
|
||||
src/states_screens/grand_prix_editor_screen.cpp
|
||||
src/states_screens/grand_prix_lose.cpp
|
||||
src/states_screens/grand_prix_win.cpp
|
||||
src/states_screens/guest_login_screen.cpp
|
||||
@ -565,6 +569,7 @@ src/states_screens/dialogs/addons_loading.hpp
|
||||
src/states_screens/dialogs/change_password_dialog.hpp
|
||||
src/states_screens/dialogs/confirm_resolution_dialog.hpp
|
||||
src/states_screens/dialogs/custom_video_settings.hpp
|
||||
src/states_screens/dialogs/enter_gp_name_dialog.hpp
|
||||
src/states_screens/dialogs/enter_player_name_dialog.hpp
|
||||
src/states_screens/dialogs/gp_info_dialog.hpp
|
||||
src/states_screens/dialogs/message_dialog.hpp
|
||||
@ -581,7 +586,10 @@ src/states_screens/dialogs/tutorial_message_dialog.hpp
|
||||
src/states_screens/dialogs/user_info_dialog.hpp
|
||||
src/states_screens/dialogs/vote_dialog.hpp
|
||||
src/states_screens/easter_egg_screen.hpp
|
||||
src/states_screens/edit_gp_screen.hpp
|
||||
src/states_screens/edit_track_screen.hpp
|
||||
src/states_screens/feature_unlocked.hpp
|
||||
src/states_screens/grand_prix_editor_screen.hpp
|
||||
src/states_screens/grand_prix_lose.hpp
|
||||
src/states_screens/grand_prix_win.hpp
|
||||
src/states_screens/guest_login_screen.hpp
|
||||
|
@ -179,6 +179,15 @@ void Achievement::onRaceEnd()
|
||||
reset();
|
||||
} // onRaceEnd
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called at the end of a lap to potentially reset values.
|
||||
*/
|
||||
void Achievement::onLapEnd()
|
||||
{
|
||||
if (m_achievement_info->needsResetAfterLap())
|
||||
reset();
|
||||
} // onLapEnd
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Checks if this achievement has been achieved.
|
||||
*/
|
||||
|
@ -69,7 +69,8 @@ public:
|
||||
|
||||
virtual void reset();
|
||||
virtual irr::core::stringw getProgressAsString() const;
|
||||
void onRaceEnd();
|
||||
void onRaceEnd();
|
||||
void onLapEnd();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the id of this achievement. */
|
||||
uint32_t getID() const { return m_id; }
|
||||
|
@ -31,7 +31,7 @@
|
||||
*/
|
||||
AchievementInfo::AchievementInfo(const XMLNode * input)
|
||||
{
|
||||
m_reset_after_race = false;
|
||||
m_reset_type = NEVER;
|
||||
m_id = 0;
|
||||
m_title = "";
|
||||
m_description = "";
|
||||
@ -47,10 +47,20 @@ AchievementInfo::AchievementInfo(const XMLNode * input)
|
||||
"ID %d title '%s' description '%s'", m_id, m_title.c_str(),
|
||||
m_description.c_str());
|
||||
}
|
||||
input->get("reset-after-race", &m_reset_after_race);
|
||||
|
||||
m_check_type = AC_ALL_AT_LEAST;
|
||||
// Load the reset-type
|
||||
std::string s;
|
||||
input->get("reset-type", &s);
|
||||
if (s == "race")
|
||||
m_reset_type = AFTER_RACE;
|
||||
else if (s == "lap")
|
||||
m_reset_type = AFTER_LAP;
|
||||
else if (s != "never")
|
||||
Log::warn("AchievementInfo", "Achievement check type '%s' unknown.",
|
||||
s.c_str());
|
||||
|
||||
// Load check-type
|
||||
m_check_type = AC_ALL_AT_LEAST;
|
||||
input->get("check-type", &s);
|
||||
if (s == "all-at-least")
|
||||
m_check_type = AC_ALL_AT_LEAST;
|
||||
|
@ -33,31 +33,45 @@
|
||||
|
||||
class Achievement;
|
||||
|
||||
/** This is the base class for storing the definition of an achievement, e.g.
|
||||
/** This is the base class for storing the definition of an achievement, e.g.
|
||||
* title, description (which is common for all achievements), but also how
|
||||
* to achieve this achievement.
|
||||
* \ingroup achievements
|
||||
*/
|
||||
* \ingroup achievements
|
||||
*/
|
||||
class AchievementInfo
|
||||
{
|
||||
public:
|
||||
/** Some handy names for the various achievements. */
|
||||
enum { ACHIEVE_COLUMBUS = 1,
|
||||
ACHIEVE_FIRST = ACHIEVE_COLUMBUS,
|
||||
ACHIEVE_STRIKE = 2,
|
||||
ACHIEVE_ARCH_ENEMY = 3,
|
||||
ACHIEVE_MARATHONER = 4,
|
||||
ACHIEVE_SKIDDING = 5
|
||||
enum { ACHIEVE_COLUMBUS = 1,
|
||||
ACHIEVE_FIRST = ACHIEVE_COLUMBUS,
|
||||
ACHIEVE_STRIKE = 2,
|
||||
ACHIEVE_ARCH_ENEMY = 3,
|
||||
ACHIEVE_MARATHONER = 4,
|
||||
ACHIEVE_SKIDDING = 5,
|
||||
ACHIEVE_GOLD_DRIVER = 6,
|
||||
ACHIEVE_POWERUP_LOVER = 7,
|
||||
ACHIEVE_UNSTOPPABLE = 8
|
||||
};
|
||||
/** Achievement check type:
|
||||
/** Achievement check type:
|
||||
* ALL_AT_LEAST: All goal values must be reached (or exceeded).
|
||||
* ONE_AT_LEAST: At least one current value reaches or exceedes the goal.
|
||||
*/
|
||||
enum AchievementCheckType
|
||||
enum AchievementCheckType
|
||||
{
|
||||
AC_ALL_AT_LEAST,
|
||||
AC_ONE_AT_LEAST
|
||||
};
|
||||
/** Achievement reset type:
|
||||
* AFTER_LAP: Achievement needs to be reset after each lap.
|
||||
* AFTER_RACE: Achievement needs to be reset after each race.
|
||||
* NEVER: Achievement does not need to be reset
|
||||
*/
|
||||
enum ResetType
|
||||
{
|
||||
AFTER_LAP = 1,
|
||||
AFTER_RACE = 2,
|
||||
NEVER = 3
|
||||
};
|
||||
|
||||
private:
|
||||
/** The id of this Achievement. */
|
||||
@ -75,8 +89,8 @@ private:
|
||||
/** The target values needed to be reached. */
|
||||
std::map<std::string, int> m_goal_values;
|
||||
|
||||
/** True if the achievement needs to be reset after each race. */
|
||||
bool m_reset_after_race;
|
||||
/** Determines when the achievement needs to be reset */
|
||||
ResetType m_reset_type;
|
||||
|
||||
public:
|
||||
AchievementInfo(const XMLNode * input);
|
||||
@ -96,7 +110,9 @@ public:
|
||||
/** Returns the title of this achievement. */
|
||||
irr::core::stringw getTitle() const { return m_title; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool needsResetAfterRace() const { return m_reset_after_race; }
|
||||
bool needsResetAfterRace() const { return m_reset_type == AFTER_RACE; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool needsResetAfterLap() const { return m_reset_type == AFTER_LAP; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the check type for this achievement. */
|
||||
AchievementCheckType getCheckType() const { return m_check_type; }
|
||||
|
@ -95,14 +95,6 @@ AchievementsStatus*
|
||||
return status;
|
||||
} // createAchievementStatus
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AchievementsManager::onRaceEnd()
|
||||
{
|
||||
//reset all values that need to be reset
|
||||
PlayerManager::get()->getCurrentPlayer()
|
||||
->getAchievementsStatus()->onRaceEnd();
|
||||
} // onRaceEnd
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
AchievementInfo * AchievementsManager::getAchievementInfo(uint32_t id) const
|
||||
{
|
||||
|
@ -71,7 +71,6 @@ public:
|
||||
} // destroy
|
||||
// ========================================================================
|
||||
|
||||
void onRaceEnd();
|
||||
AchievementInfo* getAchievementInfo(uint32_t id) const;
|
||||
AchievementsStatus* createAchievementsStatus(const XMLNode *node=NULL);
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -132,3 +132,12 @@ void AchievementsStatus::onRaceEnd()
|
||||
iter->second->onRaceEnd();
|
||||
}
|
||||
} // onRaceEnd
|
||||
|
||||
void AchievementsStatus::onLapEnd()
|
||||
{
|
||||
//reset all values that need to be reset
|
||||
std::map<uint32_t, Achievement *>::iterator iter;
|
||||
for (iter = m_achievements.begin(); iter != m_achievements.end(); ++iter) {
|
||||
iter->second->onLapEnd();
|
||||
}
|
||||
} // onLapEnd
|
@ -60,6 +60,7 @@ public :
|
||||
void add(Achievement *achievement);
|
||||
void sync(const std::vector<uint32_t> & achieved_ids);
|
||||
void onRaceEnd();
|
||||
void onLapEnd();
|
||||
// ------------------------------------------------------------------------
|
||||
const std::map<uint32_t, Achievement *>& getAllAchievements()
|
||||
{
|
||||
|
@ -314,16 +314,6 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
|
||||
return sfx;
|
||||
} // createSoundSource
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void SFXManager::dump()
|
||||
{
|
||||
for(int n=0; n<(int)m_all_sfx.size(); n++)
|
||||
{
|
||||
Log::debug("SFXManager", "Sound %i : %s \n", n, m_all_sfx[n]->getBuffer()->getFileName().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SFXBase* SFXManager::createSoundSource(const std::string &name,
|
||||
const bool addToSFXList)
|
||||
|
@ -65,8 +65,10 @@ PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
|
||||
static bool is_gl_init = false;
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef WIN32
|
||||
#define ARB_DEBUG_OUTPUT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ARB_DEBUG_OUTPUT
|
||||
static void
|
||||
@ -202,15 +204,17 @@ void initGL()
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ARB_DEBUG_OUTPUT
|
||||
glDebugMessageCallbackARB((GLDEBUGPROCARB)debugCallback, NULL);
|
||||
glDebugMessageCallbackARB((GLDEBUGPROCARB)debugCallback, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Mostly from shader tutorial
|
||||
static GLuint LoadShader(const char * file, unsigned type)
|
||||
GLuint LoadShader(const char * file, unsigned type)
|
||||
{
|
||||
GLuint Id = glCreateShader(type);
|
||||
std::string Code = "#version 330\n";
|
||||
char versionString[20];
|
||||
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
|
||||
std::string Code = versionString;
|
||||
std::ifstream Stream(file, std::ios::in);
|
||||
if (Stream.is_open())
|
||||
{
|
||||
@ -230,10 +234,11 @@ static GLuint LoadShader(const char * file, unsigned type)
|
||||
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
|
||||
if (Result == GL_FALSE)
|
||||
{
|
||||
Log::error("GLWrap", "Error in shader %s", file);
|
||||
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
|
||||
printf(ErrorMessage);
|
||||
Log::error("GLWrap", ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
@ -246,80 +251,10 @@ static GLuint LoadShader(const char * file, unsigned type)
|
||||
return Id;
|
||||
}
|
||||
|
||||
GLuint LoadProgram(const char * vertex_file_path, const char * fragment_file_path)
|
||||
{
|
||||
GLuint VertexShaderID = LoadShader(vertex_file_path, GL_VERTEX_SHADER);
|
||||
GLuint FragmentShaderID = LoadShader(fragment_file_path, GL_FRAGMENT_SHADER);
|
||||
|
||||
GLuint ProgramID = glCreateProgram();
|
||||
glAttachShader(ProgramID, VertexShaderID);
|
||||
glAttachShader(ProgramID, FragmentShaderID);
|
||||
glLinkProgram(ProgramID);
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
|
||||
if (Result == GL_FALSE) {
|
||||
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
|
||||
printf(ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
glDeleteShader(VertexShaderID);
|
||||
glDeleteShader(FragmentShaderID);
|
||||
|
||||
GLenum glErr = glGetError();
|
||||
if (glErr != GL_NO_ERROR)
|
||||
{
|
||||
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
|
||||
}
|
||||
|
||||
return ProgramID;
|
||||
}
|
||||
|
||||
GLuint LoadProgram(const char * vertex_file_path, const char * geometry_file_path, const char * fragment_file_path)
|
||||
{
|
||||
GLuint VertexShaderID = LoadShader(vertex_file_path, GL_VERTEX_SHADER);
|
||||
GLuint FragmentShaderID = LoadShader(fragment_file_path, GL_FRAGMENT_SHADER);
|
||||
GLuint GeometryShaderID = LoadShader(geometry_file_path, GL_GEOMETRY_SHADER);
|
||||
|
||||
GLuint ProgramID = glCreateProgram();
|
||||
glAttachShader(ProgramID, VertexShaderID);
|
||||
glAttachShader(ProgramID, GeometryShaderID);
|
||||
glAttachShader(ProgramID, FragmentShaderID);
|
||||
glLinkProgram(ProgramID);
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
|
||||
if (Result == GL_FALSE) {
|
||||
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
|
||||
printf(ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
glDeleteShader(VertexShaderID);
|
||||
glDeleteShader(GeometryShaderID);
|
||||
glDeleteShader(FragmentShaderID);
|
||||
|
||||
GLenum glErr = glGetError();
|
||||
if (glErr != GL_NO_ERROR)
|
||||
{
|
||||
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
|
||||
}
|
||||
|
||||
return ProgramID;
|
||||
}
|
||||
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
|
||||
{
|
||||
GLuint Shader = LoadShader(vertex_file_path, GL_VERTEX_SHADER);
|
||||
GLuint Program = glCreateProgram();
|
||||
glAttachShader(Program, Shader);
|
||||
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
|
||||
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
|
||||
glLinkProgram(Program);
|
||||
|
||||
@ -334,7 +269,6 @@ GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsi
|
||||
printf(ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
glDeleteShader(Shader);
|
||||
|
||||
GLenum glErr = glGetError();
|
||||
if (glErr != GL_NO_ERROR)
|
||||
@ -428,6 +362,16 @@ void drawTexQuad(const video::ITexture *texture, float width, float height,
|
||||
}
|
||||
}
|
||||
|
||||
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor &colors, bool useAlphaChannelOfTexture)
|
||||
{
|
||||
video::SColor duplicatedArray[4] = {
|
||||
colors, colors, colors, colors
|
||||
};
|
||||
draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
|
||||
}
|
||||
|
||||
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
|
||||
const video::SColor* const colors, bool useAlphaChannelOfTexture)
|
||||
|
@ -18,11 +18,7 @@
|
||||
# include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
void initGL();
|
||||
GLuint LoadProgram(const char * vertex_file_path, const char * fragment_file_path);
|
||||
GLuint LoadProgram(const char * vertex_file_path, const char * geometry_file_path, const char * fragment_file_path);
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
|
||||
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF = false);
|
||||
#include "utils/log.hpp"
|
||||
|
||||
// already includes glext.h, which defines useful GL constants.
|
||||
// COpenGLDriver has already loaded the extension GL functions we use (e.g glBeginQuery)
|
||||
@ -87,6 +83,53 @@ extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
|
||||
#endif
|
||||
|
||||
|
||||
void initGL();
|
||||
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
|
||||
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF = false);
|
||||
GLuint LoadShader(const char * file, unsigned type);
|
||||
|
||||
template<typename ... Types>
|
||||
void loadAndAttach(GLint ProgramID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename ... Types>
|
||||
void loadAndAttach(GLint ProgramID, GLint ShaderType, const char *filepath, Types ... args)
|
||||
{
|
||||
GLint ShaderID = LoadShader(filepath, ShaderType);
|
||||
glAttachShader(ProgramID, ShaderID);
|
||||
glDeleteShader(ShaderID);
|
||||
loadAndAttach(ProgramID, args...);
|
||||
}
|
||||
|
||||
template<typename ... Types>
|
||||
GLint LoadProgram(Types ... args)
|
||||
{
|
||||
GLint ProgramID = glCreateProgram();
|
||||
loadAndAttach(ProgramID, args...);
|
||||
glLinkProgram(ProgramID);
|
||||
|
||||
GLint Result = GL_FALSE;
|
||||
int InfoLogLength;
|
||||
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
|
||||
if (Result == GL_FALSE) {
|
||||
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
||||
char *ErrorMessage = new char[InfoLogLength];
|
||||
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
|
||||
printf(ErrorMessage);
|
||||
delete[] ErrorMessage;
|
||||
}
|
||||
|
||||
GLenum glErr = glGetError();
|
||||
if (glErr != GL_NO_ERROR)
|
||||
{
|
||||
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
|
||||
}
|
||||
|
||||
return ProgramID;
|
||||
}
|
||||
|
||||
// core::rect<s32> needs these includes
|
||||
#include <rect.h>
|
||||
#include "utils/vec3.hpp"
|
||||
@ -94,6 +137,10 @@ extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
|
||||
GLuint getTextureGLuint(irr::video::ITexture *tex);
|
||||
GLuint getDepthTexture(irr::video::ITexture *tex);
|
||||
|
||||
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<s32>& destRect,
|
||||
const irr::core::rect<s32>& sourceRect, const irr::core::rect<s32>* clipRect,
|
||||
const irr::video::SColor &color, bool useAlphaChannelOfTexture);
|
||||
|
||||
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<s32>& destRect,
|
||||
const irr::core::rect<s32>& sourceRect, const irr::core::rect<s32>* clipRect,
|
||||
const irr::video::SColor* const colors, bool useAlphaChannelOfTexture);
|
||||
|
@ -47,10 +47,6 @@ ParticleSystemProxy::ParticleSystemProxy(bool createDefaultEmitter,
|
||||
heighmapbuffer = 0;
|
||||
heightmaptexture = 0;
|
||||
current_simulation_vao = 0;
|
||||
non_currenthm__simulation_vao = 0;
|
||||
current_hm_simulation_vao = 0;
|
||||
current_rendering_flip_vao = 0;
|
||||
non_current_rendering_flip_vao = 0;
|
||||
has_height_map = false;
|
||||
flip = false;
|
||||
track_x = 0;
|
||||
@ -77,41 +73,17 @@ ParticleSystemProxy::~ParticleSystemProxy()
|
||||
{
|
||||
glDeleteBuffers(2, tfb_buffers);
|
||||
glDeleteBuffers(1, &initial_values_buffer);
|
||||
glDeleteBuffers(1, &quaternionsbuffer);
|
||||
if (has_height_map)
|
||||
{
|
||||
if (quaternionsbuffer)
|
||||
glDeleteBuffers(1, &quaternionsbuffer);
|
||||
if (heighmapbuffer)
|
||||
glDeleteBuffers(1, &heighmapbuffer);
|
||||
if (heightmaptexture)
|
||||
glDeleteTextures(1, &heightmaptexture);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ParticleSystemProxy::setFlip()
|
||||
{
|
||||
flip = true;
|
||||
float *quaternions = new float[4 * count];
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
core::vector3df rotationdir(0., 1., 0.);
|
||||
|
||||
quaternions[4 * i] = rotationdir.X;
|
||||
quaternions[4 * i + 1] = rotationdir.Y;
|
||||
quaternions[4 * i + 2] = rotationdir.Z;
|
||||
quaternions[4 * i + 3] = 3.14f * 3.f * (2.f * os::Randomizer::frand() - 1.f); // 3 half rotation during lifetime at max
|
||||
}
|
||||
glGenBuffers(1, &quaternionsbuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, 4 * count * sizeof(float), quaternions, GL_STATIC_DRAW);
|
||||
|
||||
glGenVertexArrays(1, ¤t_rendering_flip_vao);
|
||||
glBindVertexArray(current_rendering_flip_vao);
|
||||
FlipParticleVAOBind(tfb_buffers[0], quaternionsbuffer);
|
||||
glGenVertexArrays(1, &non_current_rendering_flip_vao);
|
||||
glBindVertexArray(non_current_rendering_flip_vao);
|
||||
FlipParticleVAOBind(tfb_buffers[1], quaternionsbuffer);
|
||||
glBindVertexArray(0);
|
||||
|
||||
delete[] quaternions;
|
||||
}
|
||||
|
||||
void ParticleSystemProxy::setHeightmap(const std::vector<std::vector<float> > &hm,
|
||||
@ -138,16 +110,6 @@ void ParticleSystemProxy::setHeightmap(const std::vector<std::vector<float> > &h
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, heighmapbuffer);
|
||||
glBindBuffer(GL_TEXTURE_BUFFER, 0);
|
||||
|
||||
glGenVertexArrays(1, ¤t_hm_simulation_vao);
|
||||
glBindVertexArray(current_hm_simulation_vao);
|
||||
HeightmapSimulationBind(tfb_buffers[0], initial_values_buffer);
|
||||
|
||||
glGenVertexArrays(1, &non_currenthm__simulation_vao);
|
||||
glBindVertexArray(non_currenthm__simulation_vao);
|
||||
HeightmapSimulationBind(tfb_buffers[1], initial_values_buffer);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
delete[] hm_array;
|
||||
}
|
||||
|
||||
@ -419,21 +381,6 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter)
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindVertexArray(current_rendering_vao);
|
||||
SimpleParticleVAOBind(tfb_buffers[0]);
|
||||
|
||||
glBindVertexArray(non_current_rendering_vao);
|
||||
SimpleParticleVAOBind(tfb_buffers[1]);
|
||||
|
||||
glGenVertexArrays(1, ¤t_simulation_vao);
|
||||
glBindVertexArray(current_simulation_vao);
|
||||
SimpleSimulationBind(tfb_buffers[0], initial_values_buffer);
|
||||
|
||||
glGenVertexArrays(1, &non_current_simulation_vao);
|
||||
glBindVertexArray(non_current_simulation_vao);
|
||||
SimpleSimulationBind(tfb_buffers[1], initial_values_buffer);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
texture = getTextureGLuint(getMaterial(0).getTexture(0));
|
||||
@ -459,7 +406,7 @@ void ParticleSystemProxy::simulateHeightmap()
|
||||
glUniform1f(ParticleShader::HeightmapSimulationShader::uniform_track_x_len, track_x_len);
|
||||
glUniform1f(ParticleShader::HeightmapSimulationShader::uniform_track_z_len, track_z_len);
|
||||
|
||||
glBindVertexArray(current_hm_simulation_vao);
|
||||
glBindVertexArray(current_simulation_vao);
|
||||
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_buffers[1]);
|
||||
|
||||
glBeginTransformFeedback(GL_POINTS);
|
||||
@ -469,8 +416,8 @@ void ParticleSystemProxy::simulateHeightmap()
|
||||
|
||||
glDisable(GL_RASTERIZER_DISCARD);
|
||||
std::swap(tfb_buffers[0], tfb_buffers[1]);
|
||||
std::swap(current_rendering_flip_vao, non_current_rendering_flip_vao);
|
||||
std::swap(current_hm_simulation_vao, non_currenthm__simulation_vao);
|
||||
std::swap(current_rendering_vao, non_current_rendering_vao);
|
||||
std::swap(current_simulation_vao, non_current_simulation_vao);
|
||||
}
|
||||
|
||||
void ParticleSystemProxy::simulateNoHeightmap()
|
||||
@ -523,7 +470,7 @@ void ParticleSystemProxy::drawFlip()
|
||||
|
||||
ParticleShader::FlipParticleRender::setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), irr_driver->getInvProjMatrix(), screen[0], screen[1], 0, 1);
|
||||
|
||||
glBindVertexArray(current_rendering_flip_vao);
|
||||
glBindVertexArray(current_rendering_vao);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
|
||||
}
|
||||
|
||||
@ -558,12 +505,66 @@ void ParticleSystemProxy::draw()
|
||||
drawNotFlip();
|
||||
}
|
||||
|
||||
void ParticleSystemProxy::generateVAOs()
|
||||
{
|
||||
glGenVertexArrays(1, ¤t_rendering_vao);
|
||||
glGenVertexArrays(1, &non_current_rendering_vao);
|
||||
glGenVertexArrays(1, ¤t_simulation_vao);
|
||||
glGenVertexArrays(1, &non_current_simulation_vao);
|
||||
|
||||
glBindVertexArray(current_simulation_vao);
|
||||
if (has_height_map)
|
||||
HeightmapSimulationBind(tfb_buffers[0], initial_values_buffer);
|
||||
else
|
||||
SimpleSimulationBind(tfb_buffers[0], initial_values_buffer);
|
||||
glBindVertexArray(non_current_simulation_vao);
|
||||
if (has_height_map)
|
||||
HeightmapSimulationBind(tfb_buffers[1], initial_values_buffer);
|
||||
else
|
||||
SimpleSimulationBind(tfb_buffers[1], initial_values_buffer);
|
||||
|
||||
float *quaternions = new float[4 * count];
|
||||
glBindVertexArray(0);
|
||||
if (flip)
|
||||
{
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
core::vector3df rotationdir(0., 1., 0.);
|
||||
|
||||
quaternions[4 * i] = rotationdir.X;
|
||||
quaternions[4 * i + 1] = rotationdir.Y;
|
||||
quaternions[4 * i + 2] = rotationdir.Z;
|
||||
quaternions[4 * i + 3] = 3.14f * 3.f * (2.f * os::Randomizer::frand() - 1.f); // 3 half rotation during lifetime at max
|
||||
}
|
||||
glGenBuffers(1, &quaternionsbuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, 4 * count * sizeof(float), quaternions, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
glBindVertexArray(current_rendering_vao);
|
||||
if (flip)
|
||||
FlipParticleVAOBind(tfb_buffers[0], quaternionsbuffer);
|
||||
else
|
||||
SimpleParticleVAOBind(tfb_buffers[0]);
|
||||
|
||||
glBindVertexArray(non_current_rendering_vao);
|
||||
if (flip)
|
||||
FlipParticleVAOBind(tfb_buffers[1], quaternionsbuffer);
|
||||
else
|
||||
SimpleParticleVAOBind(tfb_buffers[1]);
|
||||
glBindVertexArray(0);
|
||||
|
||||
delete[] quaternions;
|
||||
}
|
||||
|
||||
void ParticleSystemProxy::render() {
|
||||
if (!getEmitter() || !isGPUParticleType(getEmitter()->getType()))
|
||||
{
|
||||
CParticleSystemSceneNode::render();
|
||||
return;
|
||||
}
|
||||
if (!current_rendering_vao || !non_current_rendering_vao || !current_simulation_vao || !non_current_simulation_vao)
|
||||
generateVAOs();
|
||||
simulate();
|
||||
draw();
|
||||
}
|
||||
|
@ -14,9 +14,7 @@ class ParticleSystemProxy : public scene::CParticleSystemSceneNode
|
||||
protected:
|
||||
GLuint tfb_buffers[2], initial_values_buffer, heighmapbuffer, heightmaptexture, quaternionsbuffer;
|
||||
GLuint current_simulation_vao, non_current_simulation_vao;
|
||||
GLuint current_hm_simulation_vao, non_currenthm__simulation_vao;
|
||||
GLuint current_rendering_vao, non_current_rendering_vao;
|
||||
GLuint current_rendering_flip_vao, non_current_rendering_flip_vao;
|
||||
bool m_alpha_additive, has_height_map, flip;
|
||||
float size_increase_factor, track_x, track_z, track_x_len, track_z_len;
|
||||
float m_color_from[3];
|
||||
@ -31,6 +29,8 @@ protected:
|
||||
static void SimpleSimulationBind(GLuint PositionBuffer, GLuint InitialValuesBuffer);
|
||||
static void HeightmapSimulationBind(GLuint PositionBuffer, GLuint InitialValuesBuffer);
|
||||
|
||||
void generateVAOs();
|
||||
|
||||
void simulateHeightmap();
|
||||
void simulateNoHeightmap();
|
||||
void drawFlip();
|
||||
|
@ -422,12 +422,12 @@ void IrrDriver::initDevice()
|
||||
m_gui_env = m_device->getGUIEnvironment();
|
||||
m_video_driver = m_device->getVideoDriver();
|
||||
|
||||
int GLMajorVersion = 0, GLMinorVersion = 0;
|
||||
GLMajorVersion = 2;
|
||||
GLMinorVersion = 1;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &GLMajorVersion);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &GLMinorVersion);
|
||||
Log::info("IrrDriver", "OPENGL VERSION IS %d.%d", GLMajorVersion, GLMinorVersion);
|
||||
m_glsl = (GLMajorVersion > 3 || (GLMajorVersion == 3 && GLMinorVersion == 3)) && UserConfigParams::m_pixel_shaders;
|
||||
|
||||
m_glsl = (GLMajorVersion > 3 || (GLMajorVersion == 3 && GLMinorVersion >= 1)) && UserConfigParams::m_pixel_shaders;
|
||||
|
||||
// This remaps the window, so it has to be done before the clear to avoid flicker
|
||||
m_device->setResizable(false);
|
||||
|
@ -82,6 +82,7 @@ enum STKRenderingPass
|
||||
class IrrDriver : public IEventReceiver, public NoCopy
|
||||
{
|
||||
private:
|
||||
int GLMajorVersion, GLMinorVersion;
|
||||
/** The irrlicht device. */
|
||||
IrrlichtDevice *m_device;
|
||||
/** Irrlicht scene manager. */
|
||||
@ -148,6 +149,16 @@ public:
|
||||
float power;
|
||||
};
|
||||
|
||||
unsigned getGLSLVersion() const
|
||||
{
|
||||
if (GLMajorVersion > 3 || (GLMajorVersion == 3 && GLMinorVersion == 3))
|
||||
return GLMajorVersion * 100 + GLMinorVersion * 10;
|
||||
else if (GLMajorVersion == 3)
|
||||
return 100 + (GLMinorVersion + 3) * 10;
|
||||
else
|
||||
return 120;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<VideoMode> m_modes;
|
||||
|
||||
|
@ -755,50 +755,11 @@ void IrrDriver::renderGlow(video::SOverrideMaterial &overridemat,
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#define MAXLIGHT 16 // to be adjusted in pointlight.frag too
|
||||
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
|
||||
static LightShader::PointLightInfo PointLightsInfo[MAXLIGHT];
|
||||
|
||||
|
||||
static GLuint pointlightvbo = 0;
|
||||
static GLuint pointlightsvao = 0;
|
||||
|
||||
struct PointLightInfo
|
||||
{
|
||||
float posX;
|
||||
float posY;
|
||||
float posZ;
|
||||
float energy;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
float padding;
|
||||
};
|
||||
|
||||
void createPointLightVAO()
|
||||
{
|
||||
glGenVertexArrays(1, &pointlightsvao);
|
||||
glBindVertexArray(pointlightsvao);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::billboardvbo);
|
||||
glEnableVertexAttribArray(MeshShader::PointLightShader::attrib_Corner);
|
||||
glVertexAttribPointer(MeshShader::PointLightShader::attrib_Corner, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
||||
|
||||
glGenBuffers(1, &pointlightvbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, pointlightvbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, MAXLIGHT * sizeof(PointLightInfo), 0, GL_DYNAMIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(MeshShader::PointLightShader::attrib_Position);
|
||||
glVertexAttribPointer(MeshShader::PointLightShader::attrib_Position, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), 0);
|
||||
glEnableVertexAttribArray(MeshShader::PointLightShader::attrib_Energy);
|
||||
glVertexAttribPointer(MeshShader::PointLightShader::attrib_Energy, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(MeshShader::PointLightShader::attrib_Color);
|
||||
glVertexAttribPointer(MeshShader::PointLightShader::attrib_Color, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(4 * sizeof(float)));
|
||||
|
||||
glVertexAttribDivisor(MeshShader::PointLightShader::attrib_Position, 1);
|
||||
glVertexAttribDivisor(MeshShader::PointLightShader::attrib_Energy, 1);
|
||||
glVertexAttribDivisor(MeshShader::PointLightShader::attrib_Color, 1);
|
||||
}
|
||||
|
||||
static void renderPointLights()
|
||||
static void renderPointLights(unsigned count)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
@ -806,23 +767,18 @@ static void renderPointLights()
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glUseProgram(MeshShader::PointLightShader::Program);
|
||||
glBindVertexArray(pointlightsvao);
|
||||
glUseProgram(LightShader::PointLightShader::Program);
|
||||
glBindVertexArray(LightShader::PointLightShader::vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, LightShader::PointLightShader::vbo);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(LightShader::PointLightInfo), PointLightsInfo);
|
||||
|
||||
setTexture(0, getTextureGLuint(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH)), GL_NEAREST, GL_NEAREST);
|
||||
setTexture(1, getDepthTexture(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH)), GL_NEAREST, GL_NEAREST);
|
||||
MeshShader::PointLightShader::setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), irr_driver->getInvProjMatrix(), core::vector2df(UserConfigParams::m_width, UserConfigParams::m_height), 200, 0, 1);
|
||||
LightShader::PointLightShader::setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), irr_driver->getInvProjMatrix(), core::vector2df(UserConfigParams::m_width, UserConfigParams::m_height), 200, 0, 1);
|
||||
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, MAXLIGHT);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
|
||||
}
|
||||
|
||||
PointLightInfo PointLightsInfo[MAXLIGHT];
|
||||
|
||||
void IrrDriver::renderLights(const core::aabbox3df& cambox,
|
||||
scene::ICameraSceneNode * const camnode,
|
||||
video::SOverrideMaterial &overridemat,
|
||||
@ -860,7 +816,7 @@ void IrrDriver::renderLights(const core::aabbox3df& cambox,
|
||||
const core::vector3df &lightpos = (m_lights[i]->getAbsolutePosition() - campos);
|
||||
unsigned idx = (unsigned)(lightpos.getLength() / 10);
|
||||
if (idx > 14)
|
||||
continue;
|
||||
idx = 14;
|
||||
BucketedLN[idx].push_back(m_lights[i]);
|
||||
}
|
||||
|
||||
@ -907,17 +863,7 @@ void IrrDriver::renderLights(const core::aabbox3df& cambox,
|
||||
|
||||
lightnum++;
|
||||
|
||||
// Fill lights
|
||||
for (; lightnum < MAXLIGHT; lightnum++) {
|
||||
PointLightsInfo[lightnum].energy = 0;
|
||||
}
|
||||
|
||||
if (!pointlightsvao)
|
||||
createPointLightVAO();
|
||||
glBindVertexArray(pointlightsvao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, pointlightvbo);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, MAXLIGHT * sizeof(PointLightInfo), PointLightsInfo);
|
||||
renderPointLights();
|
||||
renderPointLights(MIN2(lightnum, MAXLIGHT));
|
||||
if (SkyboxCubeMap)
|
||||
m_post_processing->renderDiffuseEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff);
|
||||
// Handle SSAO
|
||||
@ -936,77 +882,6 @@ void IrrDriver::renderLights(const core::aabbox3df& cambox,
|
||||
m_video_driver->setRenderTarget(m_rtts->getRTT(RTT_COLOR), false, false);
|
||||
}
|
||||
|
||||
|
||||
static GLuint cubevao = 0;
|
||||
static GLuint cubevbo;
|
||||
static GLuint cubeidx;
|
||||
|
||||
static void createcubevao()
|
||||
{
|
||||
// From CSkyBoxSceneNode
|
||||
float corners[] =
|
||||
{
|
||||
// top side
|
||||
1., 1., -1.,
|
||||
1., 1., 1.,
|
||||
-1., 1., 1.,
|
||||
-1., 1., -1.,
|
||||
|
||||
// Bottom side
|
||||
1., -1., 1.,
|
||||
1., -1., -1.,
|
||||
-1., -1., -1.,
|
||||
-1., -1., 1.,
|
||||
|
||||
// right side
|
||||
1., -1, -1,
|
||||
1., -1, 1,
|
||||
1., 1., 1.,
|
||||
1., 1., -1.,
|
||||
|
||||
// left side
|
||||
-1., -1., 1.,
|
||||
-1., -1., -1.,
|
||||
-1., 1., -1.,
|
||||
-1., 1., 1.,
|
||||
|
||||
// back side
|
||||
-1., -1., -1.,
|
||||
1., -1, -1.,
|
||||
1, 1, -1.,
|
||||
-1, 1, -1.,
|
||||
|
||||
// front side
|
||||
1., -1., 1.,
|
||||
-1., -1., 1.,
|
||||
-1, 1., 1.,
|
||||
1., 1., 1.,
|
||||
};
|
||||
int indices[] = {
|
||||
0, 1, 2, 2, 3, 0,
|
||||
4, 5, 6, 6, 7, 4,
|
||||
8, 9, 10, 10, 11, 8,
|
||||
12, 13, 14, 14, 15, 12,
|
||||
16, 17, 18, 18, 19, 16,
|
||||
20, 21, 22, 22, 23, 20
|
||||
};
|
||||
|
||||
glGenBuffers(1, &cubevbo);
|
||||
glGenBuffers(1, &cubeidx);
|
||||
glGenVertexArrays(1, &cubevao);
|
||||
|
||||
glBindVertexArray(cubevao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubevbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * 3 * sizeof(float), corners, GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubeidx);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * 6 * sizeof(int), indices, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
static void getXYZ(GLenum face, float i, float j, float &x, float &y, float &z)
|
||||
{
|
||||
switch (face)
|
||||
@ -1399,11 +1274,9 @@ void IrrDriver::renderSkybox()
|
||||
if (SkyboxTextures.empty()) return;
|
||||
|
||||
scene::ICameraSceneNode *camera = m_scene_manager->getActiveCamera();
|
||||
if (!cubevao)
|
||||
createcubevao();
|
||||
if (!SkyboxCubeMap)
|
||||
generateSkyboxCubemap();
|
||||
glBindVertexArray(cubevao);
|
||||
glBindVertexArray(MeshShader::SkyboxShader::cubevao);
|
||||
glDisable(GL_CULL_FACE);
|
||||
assert(SkyboxTextures.size() == 6);
|
||||
core::matrix4 transform = irr_driver->getProjViewMatrix();
|
||||
|
@ -137,6 +137,8 @@ RTT::RTT()
|
||||
drv->setRenderTarget(0, false, false);
|
||||
|
||||
drv->endScene();
|
||||
if (irr_driver->getGLSLVersion() < 150)
|
||||
return;
|
||||
glGenFramebuffers(1, &shadowFBO);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);
|
||||
glGenTextures(1, &shadowColorTex);
|
||||
|
@ -105,6 +105,68 @@ static void initBillboardVBO()
|
||||
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), quad, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
GLuint SharedObject::cubevbo = 0;
|
||||
GLuint SharedObject::cubeindexes = 0;
|
||||
|
||||
static void initCubeVBO()
|
||||
{
|
||||
// From CSkyBoxSceneNode
|
||||
float corners[] =
|
||||
{
|
||||
// top side
|
||||
1., 1., -1.,
|
||||
1., 1., 1.,
|
||||
-1., 1., 1.,
|
||||
-1., 1., -1.,
|
||||
|
||||
// Bottom side
|
||||
1., -1., 1.,
|
||||
1., -1., -1.,
|
||||
-1., -1., -1.,
|
||||
-1., -1., 1.,
|
||||
|
||||
// right side
|
||||
1., -1, -1,
|
||||
1., -1, 1,
|
||||
1., 1., 1.,
|
||||
1., 1., -1.,
|
||||
|
||||
// left side
|
||||
-1., -1., 1.,
|
||||
-1., -1., -1.,
|
||||
-1., 1., -1.,
|
||||
-1., 1., 1.,
|
||||
|
||||
// back side
|
||||
-1., -1., -1.,
|
||||
1., -1, -1.,
|
||||
1, 1, -1.,
|
||||
-1, 1, -1.,
|
||||
|
||||
// front side
|
||||
1., -1., 1.,
|
||||
-1., -1., 1.,
|
||||
-1, 1., 1.,
|
||||
1., 1., 1.,
|
||||
};
|
||||
int indices[] = {
|
||||
0, 1, 2, 2, 3, 0,
|
||||
4, 5, 6, 6, 7, 4,
|
||||
8, 9, 10, 10, 11, 8,
|
||||
12, 13, 14, 14, 15, 12,
|
||||
16, 17, 18, 18, 19, 16,
|
||||
20, 21, 22, 22, 23, 20
|
||||
};
|
||||
|
||||
glGenBuffers(1, &SharedObject::cubevbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::cubevbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * 3 * sizeof(float), corners, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &SharedObject::cubeindexes);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::cubeindexes);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * 6 * sizeof(int), indices, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
void Shaders::loadShaders()
|
||||
{
|
||||
const std::string &dir = file_manager->getAsset(FileManager::SHADER, "");
|
||||
@ -232,6 +294,7 @@ void Shaders::loadShaders()
|
||||
initQuadVBO();
|
||||
initQuadBuffer();
|
||||
initBillboardVBO();
|
||||
initCubeVBO();
|
||||
FullScreenShader::BloomBlendShader::init();
|
||||
FullScreenShader::BloomShader::init();
|
||||
FullScreenShader::ColorLevelShader::init();
|
||||
@ -272,7 +335,7 @@ void Shaders::loadShaders()
|
||||
MeshShader::TransparentShader::init();
|
||||
MeshShader::TransparentFogShader::init();
|
||||
MeshShader::BillboardShader::init();
|
||||
MeshShader::PointLightShader::init();
|
||||
LightShader::PointLightShader::init();
|
||||
MeshShader::DisplaceShader::init();
|
||||
MeshShader::DisplaceMaskShader::init();
|
||||
MeshShader::ShadowShader::init();
|
||||
@ -326,7 +389,10 @@ namespace MeshShader
|
||||
|
||||
void ObjectPass1Shader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/object_pass1.vert").c_str(), file_manager->getAsset("shaders/object_pass1.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass1.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass1.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_normal = glGetAttribLocation(Program, "Normal");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -350,7 +416,10 @@ namespace MeshShader
|
||||
|
||||
void ObjectRefPass1Shader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/objectref_pass1.vert").c_str(), file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/objectref_pass1.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_normal = glGetAttribLocation(Program, "Normal");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
@ -380,7 +449,10 @@ namespace MeshShader
|
||||
|
||||
void GrassPass1Shader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/grass_pass1.vert").c_str(), file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass1.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_normal = glGetAttribLocation(Program, "Normal");
|
||||
@ -410,7 +482,10 @@ namespace MeshShader
|
||||
|
||||
void NormalMapShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/normalmap.vert").c_str(), file_manager->getAsset("shaders/normalmap.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/normalmap.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/normalmap.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_tangent = glGetAttribLocation(Program, "Tangent");
|
||||
@ -436,7 +511,10 @@ namespace MeshShader
|
||||
|
||||
void InstancedObjectPass1Shader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/instanced_object_pass1.vert").c_str(), file_manager->getAsset("shaders/object_pass1.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass1.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass1.frag").c_str());
|
||||
attrib_origin = glGetAttribLocation(Program, "Origin");
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_normal = glGetAttribLocation(Program, "Normal");
|
||||
@ -463,7 +541,10 @@ namespace MeshShader
|
||||
|
||||
void ObjectPass2Shader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/object_pass2.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -505,7 +586,10 @@ namespace MeshShader
|
||||
|
||||
void InstancedObjectPass2Shader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/instanced_object_pass2.vert").c_str(), file_manager->getAsset("shaders/object_pass2.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_origin = glGetAttribLocation(Program, "Origin");
|
||||
@ -548,7 +632,10 @@ namespace MeshShader
|
||||
|
||||
void DetailledObjectPass2Shader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/detailledobject_pass2.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/detailledobject_pass2.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_second_texcoord = glGetAttribLocation(Program, "SecondTexcoord");
|
||||
@ -588,7 +675,9 @@ namespace MeshShader
|
||||
|
||||
void ObjectUnlitShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/object_unlit.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -618,7 +707,9 @@ namespace MeshShader
|
||||
|
||||
void ObjectRimLimitShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/objectpass_rimlit.vert").c_str(), file_manager->getAsset("shaders/objectpass_rimlit.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/objectpass_rimlit.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectpass_rimlit.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_normal = glGetAttribLocation(Program, "Normal");
|
||||
@ -660,7 +751,10 @@ namespace MeshShader
|
||||
|
||||
void UntexturedObjectShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/untextured_object.vert").c_str(), file_manager->getAsset("shaders/untextured_object.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/untextured_object.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/untextured_object.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_color = glGetAttribLocation(Program, "Color");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -698,7 +792,10 @@ namespace MeshShader
|
||||
void ObjectRefPass2Shader::init()
|
||||
{
|
||||
initGL();
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -740,7 +837,10 @@ namespace MeshShader
|
||||
|
||||
void GrassPass2Shader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/grass_pass2.vert").c_str(), file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_color = glGetAttribLocation(Program, "Color");
|
||||
@ -783,7 +883,9 @@ namespace MeshShader
|
||||
|
||||
void SphereMapShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/object_pass1.vert").c_str(), file_manager->getAsset("shaders/objectpass_spheremap.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass1.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectpass_spheremap.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_normal = glGetAttribLocation(Program, "Normal");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -823,7 +925,9 @@ namespace MeshShader
|
||||
|
||||
void SplattingShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/splatting.vert").c_str(), file_manager->getAsset("shaders/splatting.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/splatting.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/splatting.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_second_texcoord = glGetAttribLocation(Program, "SecondTexcoord");
|
||||
@ -877,7 +981,10 @@ namespace MeshShader
|
||||
|
||||
void CausticsShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/caustics.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/caustics.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -922,7 +1029,9 @@ namespace MeshShader
|
||||
|
||||
void BubbleShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/bubble.vert").c_str(), file_manager->getAsset("shaders/bubble.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/bubble.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bubble.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -941,15 +1050,19 @@ namespace MeshShader
|
||||
GLuint TransparentShader::Program;
|
||||
GLuint TransparentShader::attrib_position;
|
||||
GLuint TransparentShader::attrib_texcoord;
|
||||
GLuint TransparentShader::attrib_color;
|
||||
GLuint TransparentShader::uniform_MVP;
|
||||
GLuint TransparentShader::uniform_TM;
|
||||
GLuint TransparentShader::uniform_tex;
|
||||
|
||||
void TransparentShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/transparent.vert").c_str(), file_manager->getAsset("shaders/transparent.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/transparent.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparent.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_color = glGetAttribLocation(Program, "Color");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
uniform_TM = glGetUniformLocation(Program, "TextureMatrix");
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
@ -965,6 +1078,7 @@ namespace MeshShader
|
||||
GLuint TransparentFogShader::Program;
|
||||
GLuint TransparentFogShader::attrib_position;
|
||||
GLuint TransparentFogShader::attrib_texcoord;
|
||||
GLuint TransparentFogShader::attrib_color;
|
||||
GLuint TransparentFogShader::uniform_MVP;
|
||||
GLuint TransparentFogShader::uniform_TM;
|
||||
GLuint TransparentFogShader::uniform_tex;
|
||||
@ -979,9 +1093,12 @@ namespace MeshShader
|
||||
|
||||
void TransparentFogShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/transparent.vert").c_str(), file_manager->getAsset("shaders/transparentfog.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/transparent.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparentfog.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_color = glGetAttribLocation(Program, "Color");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
uniform_TM = glGetUniformLocation(Program, "TextureMatrix");
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
@ -1009,47 +1126,6 @@ namespace MeshShader
|
||||
glUniformMatrix4fv(uniform_ipvmat, 1, GL_FALSE, ipvmat.pointer());
|
||||
glUniform1i(uniform_tex, TU_tex);
|
||||
}
|
||||
|
||||
GLuint PointLightShader::Program;
|
||||
GLuint PointLightShader::attrib_Position;
|
||||
GLuint PointLightShader::attrib_Color;
|
||||
GLuint PointLightShader::attrib_Energy;
|
||||
GLuint PointLightShader::attrib_Corner;
|
||||
GLuint PointLightShader::uniform_ntex;
|
||||
GLuint PointLightShader::uniform_dtex;
|
||||
GLuint PointLightShader::uniform_spec;
|
||||
GLuint PointLightShader::uniform_screen;
|
||||
GLuint PointLightShader::uniform_invproj;
|
||||
GLuint PointLightShader::uniform_VM;
|
||||
GLuint PointLightShader::uniform_PM;
|
||||
|
||||
void PointLightShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/pointlight.vert").c_str(), file_manager->getAsset("shaders/pointlight.frag").c_str());
|
||||
attrib_Position = glGetAttribLocation(Program, "Position");
|
||||
attrib_Color = glGetAttribLocation(Program, "Color");
|
||||
attrib_Energy = glGetAttribLocation(Program, "Energy");
|
||||
attrib_Corner = glGetAttribLocation(Program, "Corner");
|
||||
uniform_ntex = glGetUniformLocation(Program, "ntex");
|
||||
uniform_dtex = glGetUniformLocation(Program, "dtex");
|
||||
uniform_spec = glGetUniformLocation(Program, "spec");
|
||||
uniform_invproj = glGetUniformLocation(Program, "invproj");
|
||||
uniform_screen = glGetUniformLocation(Program, "screen");
|
||||
uniform_VM = glGetUniformLocation(Program, "ViewMatrix");
|
||||
uniform_PM = glGetUniformLocation(Program, "ProjectionMatrix");
|
||||
}
|
||||
|
||||
void PointLightShader::setUniforms(const core::matrix4 &ViewMatrix, const core::matrix4 &ProjMatrix, const core::matrix4 &InvProjMatrix, const core::vector2df &screen, unsigned spec, unsigned TU_ntex, unsigned TU_dtex)
|
||||
{
|
||||
glUniform1f(uniform_spec, 200);
|
||||
glUniform2f(uniform_screen, screen.X, screen.Y);
|
||||
glUniformMatrix4fv(uniform_invproj, 1, GL_FALSE, InvProjMatrix.pointer());
|
||||
glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer());
|
||||
glUniformMatrix4fv(uniform_PM, 1, GL_FALSE, ProjMatrix.pointer());
|
||||
|
||||
glUniform1i(uniform_ntex, TU_ntex);
|
||||
glUniform1i(uniform_dtex, TU_dtex);
|
||||
}
|
||||
|
||||
GLuint BillboardShader::Program;
|
||||
GLuint BillboardShader::attrib_corner;
|
||||
@ -1062,7 +1138,9 @@ namespace MeshShader
|
||||
|
||||
void BillboardShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/billboard.vert").c_str(), file_manager->getAsset("shaders/billboard.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/billboard.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/billboard.frag").c_str());
|
||||
attrib_corner = glGetAttribLocation(Program, "Corner");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
uniform_MV = glGetUniformLocation(Program, "ModelViewMatrix");
|
||||
@ -1088,7 +1166,9 @@ namespace MeshShader
|
||||
|
||||
void ColorizeShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/colorize.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/colorize.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
uniform_col = glGetUniformLocation(Program, "col");
|
||||
@ -1106,7 +1186,16 @@ namespace MeshShader
|
||||
|
||||
void ShadowShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/shadow.vert").c_str(), file_manager->getAsset("shaders/shadow.geom").c_str(), file_manager->getAsset("shaders/white.frag").c_str());
|
||||
// Geometry shader needed
|
||||
if (irr_driver->getGLSLVersion() < 150)
|
||||
{
|
||||
attrib_position = -1;
|
||||
return;
|
||||
}
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
|
||||
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
}
|
||||
@ -1130,7 +1219,17 @@ namespace MeshShader
|
||||
|
||||
void RefShadowShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/shadow.vert").c_str(), file_manager->getAsset("shaders/shadow.geom").c_str(), file_manager->getAsset("shaders/object_unlit.frag").c_str());
|
||||
// Geometry shader needed
|
||||
if (irr_driver->getGLSLVersion() < 150)
|
||||
{
|
||||
attrib_position = -1;
|
||||
attrib_texcoord = -1;
|
||||
return;
|
||||
}
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow.vert").c_str(),
|
||||
GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -1159,7 +1258,9 @@ namespace MeshShader
|
||||
|
||||
void GrassShadowShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/grass_pass2.vert").c_str(), file_manager->getAsset("shaders/object_unlit.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
@ -1181,7 +1282,9 @@ namespace MeshShader
|
||||
|
||||
void DisplaceMaskShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/displace.vert").c_str(), file_manager->getAsset("shaders/white.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/displace.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
}
|
||||
@ -1206,7 +1309,9 @@ namespace MeshShader
|
||||
|
||||
void DisplaceShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/displace.vert").c_str(), file_manager->getAsset("shaders/displace.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/displace.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/displace.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
|
||||
attrib_second_texcoord = glGetAttribLocation(Program, "SecondTexcoord");
|
||||
@ -1238,15 +1343,26 @@ namespace MeshShader
|
||||
GLuint SkyboxShader::uniform_tex;
|
||||
GLuint SkyboxShader::uniform_screen;
|
||||
GLuint SkyboxShader::uniform_InvProjView;
|
||||
GLuint SkyboxShader::cubevao;
|
||||
|
||||
void SkyboxShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/object_pass2.vert").c_str(), file_manager->getAsset("shaders/sky.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass2.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sky.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "Position");
|
||||
uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix");
|
||||
uniform_InvProjView = glGetUniformLocation(Program, "InvProjView");
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_screen = glGetUniformLocation(Program, "screen");
|
||||
|
||||
glGenVertexArrays(1, &cubevao);
|
||||
glBindVertexArray(cubevao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::cubevbo);
|
||||
glEnableVertexAttribArray(attrib_position);
|
||||
glVertexAttribPointer(attrib_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::cubeindexes);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void SkyboxShader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &InvProjView, const core::vector2df &screen, unsigned TU_tex)
|
||||
@ -1258,6 +1374,79 @@ namespace MeshShader
|
||||
}
|
||||
}
|
||||
|
||||
namespace LightShader
|
||||
{
|
||||
|
||||
GLuint PointLightShader::Program;
|
||||
GLuint PointLightShader::attrib_Position;
|
||||
GLuint PointLightShader::attrib_Color;
|
||||
GLuint PointLightShader::attrib_Energy;
|
||||
GLuint PointLightShader::attrib_Corner;
|
||||
GLuint PointLightShader::uniform_ntex;
|
||||
GLuint PointLightShader::uniform_dtex;
|
||||
GLuint PointLightShader::uniform_spec;
|
||||
GLuint PointLightShader::uniform_screen;
|
||||
GLuint PointLightShader::uniform_invproj;
|
||||
GLuint PointLightShader::uniform_VM;
|
||||
GLuint PointLightShader::uniform_PM;
|
||||
GLuint PointLightShader::vbo;
|
||||
GLuint PointLightShader::vao;
|
||||
|
||||
void PointLightShader::init()
|
||||
{
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/pointlight.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/pointlight.frag").c_str());
|
||||
attrib_Position = glGetAttribLocation(Program, "Position");
|
||||
attrib_Color = glGetAttribLocation(Program, "Color");
|
||||
attrib_Energy = glGetAttribLocation(Program, "Energy");
|
||||
attrib_Corner = glGetAttribLocation(Program, "Corner");
|
||||
uniform_ntex = glGetUniformLocation(Program, "ntex");
|
||||
uniform_dtex = glGetUniformLocation(Program, "dtex");
|
||||
uniform_spec = glGetUniformLocation(Program, "spec");
|
||||
uniform_invproj = glGetUniformLocation(Program, "invproj");
|
||||
uniform_screen = glGetUniformLocation(Program, "screen");
|
||||
uniform_VM = glGetUniformLocation(Program, "ViewMatrix");
|
||||
uniform_PM = glGetUniformLocation(Program, "ProjectionMatrix");
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::billboardvbo);
|
||||
glEnableVertexAttribArray(attrib_Corner);
|
||||
glVertexAttribPointer(attrib_Corner, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
||||
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, MAXLIGHT * sizeof(PointLightInfo), 0, GL_DYNAMIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(attrib_Position);
|
||||
glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), 0);
|
||||
glEnableVertexAttribArray(attrib_Energy);
|
||||
glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(attrib_Color);
|
||||
glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(4 * sizeof(float)));
|
||||
|
||||
glVertexAttribDivisor(attrib_Position, 1);
|
||||
glVertexAttribDivisor(attrib_Energy, 1);
|
||||
glVertexAttribDivisor(attrib_Color, 1);
|
||||
}
|
||||
|
||||
void PointLightShader::setUniforms(const core::matrix4 &ViewMatrix, const core::matrix4 &ProjMatrix, const core::matrix4 &InvProjMatrix, const core::vector2df &screen, unsigned spec, unsigned TU_ntex, unsigned TU_dtex)
|
||||
{
|
||||
glUniform1f(uniform_spec, 200);
|
||||
glUniform2f(uniform_screen, screen.X, screen.Y);
|
||||
glUniformMatrix4fv(uniform_invproj, 1, GL_FALSE, InvProjMatrix.pointer());
|
||||
glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer());
|
||||
glUniformMatrix4fv(uniform_PM, 1, GL_FALSE, ProjMatrix.pointer());
|
||||
|
||||
glUniform1i(uniform_ntex, TU_ntex);
|
||||
glUniform1i(uniform_dtex, TU_dtex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ParticleShader
|
||||
{
|
||||
@ -1367,7 +1556,9 @@ namespace ParticleShader
|
||||
|
||||
void SimpleParticleRender::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/particle.vert").c_str(), file_manager->getAsset("shaders/particle.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/particle.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/particle.frag").c_str());
|
||||
attrib_pos = glGetAttribLocation(Program, "position");
|
||||
attrib_sz = glGetAttribLocation(Program, "size");
|
||||
attrib_lf = glGetAttribLocation(Program, "lifetime");
|
||||
@ -1421,7 +1612,9 @@ namespace ParticleShader
|
||||
|
||||
void FlipParticleRender::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/flipparticle.vert").c_str(), file_manager->getAsset("shaders/particle.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/flipparticle.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/particle.frag").c_str());
|
||||
attrib_pos = glGetAttribLocation(Program, "position");
|
||||
attrib_sz = glGetAttribLocation(Program, "size");
|
||||
attrib_lf = glGetAttribLocation(Program, "lifetime");
|
||||
@ -1473,7 +1666,9 @@ namespace FullScreenShader
|
||||
GLuint BloomShader::vao;
|
||||
void BloomShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/bloom.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bloom.frag").c_str());
|
||||
uniform_texture = glGetUniformLocation(Program, "tex");
|
||||
uniform_low = glGetUniformLocation(Program, "low");
|
||||
vao = createVAO(Program);
|
||||
@ -1485,7 +1680,9 @@ namespace FullScreenShader
|
||||
GLuint BloomBlendShader::vao;
|
||||
void BloomBlendShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/bloomblend.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/bloomblend.frag").c_str());
|
||||
uniform_texture = glGetUniformLocation(Program, "tex");
|
||||
vao = createVAO(Program);
|
||||
}
|
||||
@ -1499,7 +1696,9 @@ namespace FullScreenShader
|
||||
GLuint ColorLevelShader::uniform_dtex;
|
||||
void ColorLevelShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/color_levels.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/color_levels.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_dtex = glGetUniformLocation(Program, "dtex");
|
||||
uniform_inlevel = glGetUniformLocation(Program, "inlevel");
|
||||
@ -1518,7 +1717,10 @@ namespace FullScreenShader
|
||||
|
||||
void SunLightShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/sunlight.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlight.frag").c_str());
|
||||
uniform_ntex = glGetUniformLocation(Program, "ntex");
|
||||
uniform_dtex = glGetUniformLocation(Program, "dtex");
|
||||
uniform_direction = glGetUniformLocation(Program, "direction");
|
||||
@ -1546,7 +1748,10 @@ namespace FullScreenShader
|
||||
|
||||
void DiffuseEnvMapShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/diffuseenvmap.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/diffuseenvmap.frag").c_str());
|
||||
uniform_ntex = glGetUniformLocation(Program, "ntex");
|
||||
uniform_blueLmn = glGetUniformLocation(Program, "blueLmn[0]");
|
||||
uniform_greenLmn = glGetUniformLocation(Program, "greenLmn[0]");
|
||||
@ -1576,7 +1781,10 @@ namespace FullScreenShader
|
||||
|
||||
void ShadowedSunLightShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/sunlightshadow.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlightshadow.frag").c_str());
|
||||
uniform_ntex = glGetUniformLocation(Program, "ntex");
|
||||
uniform_dtex = glGetUniformLocation(Program, "dtex");
|
||||
uniform_shadowtex = glGetUniformLocation(Program, "shadowtex");
|
||||
@ -1611,7 +1819,9 @@ namespace FullScreenShader
|
||||
GLuint Gaussian6HBlurShader::vao;
|
||||
void Gaussian6HBlurShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/gaussian6h.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian6h.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_pixel = glGetUniformLocation(Program, "pixel");
|
||||
vao = createVAO(Program);
|
||||
@ -1623,7 +1833,9 @@ namespace FullScreenShader
|
||||
GLuint Gaussian3HBlurShader::vao;
|
||||
void Gaussian3HBlurShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/gaussian3h.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian3h.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_pixel = glGetUniformLocation(Program, "pixel");
|
||||
vao = createVAO(Program);
|
||||
@ -1635,7 +1847,9 @@ namespace FullScreenShader
|
||||
GLuint Gaussian6VBlurShader::vao;
|
||||
void Gaussian6VBlurShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/gaussian6v.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian6v.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_pixel = glGetUniformLocation(Program, "pixel");
|
||||
vao = createVAO(Program);
|
||||
@ -1647,7 +1861,9 @@ namespace FullScreenShader
|
||||
GLuint Gaussian3VBlurShader::vao;
|
||||
void Gaussian3VBlurShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/gaussian3v.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gaussian3v.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_pixel = glGetUniformLocation(Program, "pixel");
|
||||
vao = createVAO(Program);
|
||||
@ -1659,7 +1875,9 @@ namespace FullScreenShader
|
||||
GLuint PenumbraHShader::vao;
|
||||
void PenumbraHShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/penumbrah.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/penumbrah.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_pixel = glGetUniformLocation(Program, "pixel");
|
||||
vao = createVAO(Program);
|
||||
@ -1677,7 +1895,9 @@ namespace FullScreenShader
|
||||
GLuint PenumbraVShader::vao;
|
||||
void PenumbraVShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/penumbrav.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/penumbrav.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_pixel = glGetUniformLocation(Program, "pixel");
|
||||
vao = createVAO(Program);
|
||||
@ -1696,7 +1916,9 @@ namespace FullScreenShader
|
||||
GLuint ShadowGenShader::vao;
|
||||
void ShadowGenShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/shadowgen.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/shadowgen.frag").c_str());
|
||||
uniform_halft = glGetUniformLocation(Program, "halft");
|
||||
uniform_quarter = glGetUniformLocation(Program, "quarter");
|
||||
uniform_height = glGetUniformLocation(Program, "height");
|
||||
@ -1715,7 +1937,9 @@ namespace FullScreenShader
|
||||
GLuint PassThroughShader::vao;
|
||||
void PassThroughShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/texturedquad.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/texturedquad.frag").c_str());
|
||||
uniform_texture = glGetUniformLocation(Program, "texture");
|
||||
vao = createVAO(Program);
|
||||
}
|
||||
@ -1725,7 +1949,9 @@ namespace FullScreenShader
|
||||
GLuint GlowShader::vao;
|
||||
void GlowShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/glow.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/glow.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
vao = createVAO(Program);
|
||||
}
|
||||
@ -1742,7 +1968,10 @@ namespace FullScreenShader
|
||||
|
||||
void SSAOShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/ssao.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/ssao.frag").c_str());
|
||||
uniform_ntex = glGetUniformLocation(Program, "ntex");
|
||||
uniform_dtex = glGetUniformLocation(Program, "dtex");
|
||||
uniform_noise_texture = glGetUniformLocation(Program, "noise_texture");
|
||||
@ -1889,7 +2118,9 @@ namespace FullScreenShader
|
||||
|
||||
void FogShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/fog.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/fog.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_fogmax = glGetUniformLocation(Program, "fogmax");
|
||||
uniform_startH = glGetUniformLocation(Program, "startH");
|
||||
@ -1924,7 +2155,9 @@ namespace FullScreenShader
|
||||
|
||||
void MotionBlurShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/motion_blur.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/motion_blur.frag").c_str());
|
||||
uniform_boost_amount = glGetUniformLocation(Program, "boost_amount");
|
||||
uniform_center = glGetUniformLocation(Program, "center");
|
||||
uniform_color_buffer = glGetUniformLocation(Program, "color_buffer");
|
||||
@ -1951,7 +2184,9 @@ namespace FullScreenShader
|
||||
|
||||
void GodFadeShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/godfade.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/godfade.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_col = glGetUniformLocation(Program, "col");
|
||||
vao = createVAO(Program);
|
||||
@ -1970,7 +2205,9 @@ namespace FullScreenShader
|
||||
|
||||
void GodRayShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/godray.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/godray.frag").c_str());
|
||||
uniform_tex = glGetUniformLocation(Program, "tex");
|
||||
uniform_sunpos = glGetUniformLocation(Program, "sunpos");
|
||||
vao = createVAO(Program);
|
||||
@ -1997,7 +2234,9 @@ namespace UIShader
|
||||
|
||||
void TextureRectShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/texturedquad.vert").c_str(), file_manager->getAsset("shaders/texturedquad.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/texturedquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/texturedquad.frag").c_str());
|
||||
|
||||
attrib_position = glGetAttribLocation(Program, "position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "texcoord");
|
||||
@ -2039,7 +2278,9 @@ namespace UIShader
|
||||
|
||||
void ColoredTextureRectShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/colortexturedquad.vert").c_str(), file_manager->getAsset("shaders/colortexturedquad.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/colortexturedquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/colortexturedquad.frag").c_str());
|
||||
|
||||
attrib_position = glGetAttribLocation(Program, "position");
|
||||
attrib_texcoord = glGetAttribLocation(Program, "texcoord");
|
||||
@ -2088,7 +2329,9 @@ namespace UIShader
|
||||
|
||||
void ColoredRectShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/coloredquad.vert").c_str(), file_manager->getAsset("shaders/coloredquad.frag").c_str());
|
||||
Program = LoadProgram(
|
||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/coloredquad.vert").c_str(),
|
||||
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/coloredquad.frag").c_str());
|
||||
attrib_position = glGetAttribLocation(Program, "position");
|
||||
uniform_color = glGetUniformLocation(Program, "color");
|
||||
uniform_center = glGetUniformLocation(Program, "center");
|
||||
|
@ -29,6 +29,7 @@ class SharedObject
|
||||
{
|
||||
public:
|
||||
static GLuint billboardvbo;
|
||||
static GLuint cubevbo, cubeindexes;
|
||||
};
|
||||
namespace MeshShader
|
||||
{
|
||||
@ -233,7 +234,7 @@ class TransparentShader
|
||||
{
|
||||
public:
|
||||
static GLuint Program;
|
||||
static GLuint attrib_position, attrib_texcoord;
|
||||
static GLuint attrib_position, attrib_texcoord, attrib_color;
|
||||
static GLuint uniform_MVP, uniform_TM, uniform_tex;
|
||||
|
||||
static void init();
|
||||
@ -244,25 +245,13 @@ class TransparentFogShader
|
||||
{
|
||||
public:
|
||||
static GLuint Program;
|
||||
static GLuint attrib_position, attrib_texcoord;
|
||||
static GLuint attrib_position, attrib_texcoord, attrib_color;
|
||||
static GLuint uniform_MVP, uniform_TM, uniform_tex, uniform_fogmax, uniform_startH, uniform_endH, uniform_start, uniform_end, uniform_col, uniform_screen, uniform_ipvmat;
|
||||
|
||||
static void init();
|
||||
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix, const core::matrix4 &ipvmat, float fogmax, float startH, float endH, float start, float end, const core::vector3df &col, const core::vector3df &campos, unsigned TU_tex);
|
||||
};
|
||||
|
||||
class PointLightShader
|
||||
{
|
||||
public:
|
||||
static GLuint Program;
|
||||
static GLuint attrib_Position, attrib_Energy, attrib_Color;
|
||||
static GLuint attrib_Corner;
|
||||
static GLuint uniform_ntex, uniform_dtex, uniform_spec, uniform_screen, uniform_invproj, uniform_VM, uniform_PM;
|
||||
|
||||
static void init();
|
||||
static void setUniforms(const core::matrix4 &ViewMatrix, const core::matrix4 &ProjMatrix, const core::matrix4 &InvProjMatrix, const core::vector2df &screen, unsigned spec, unsigned TU_ntex, unsigned TU_dtex);
|
||||
};
|
||||
|
||||
class BillboardShader
|
||||
{
|
||||
public:
|
||||
@ -347,6 +336,7 @@ public:
|
||||
static GLuint Program;
|
||||
static GLuint attrib_position;
|
||||
static GLuint uniform_MVP, uniform_InvProjView, uniform_tex, uniform_screen;
|
||||
static GLuint cubevao;
|
||||
|
||||
static void init();
|
||||
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &InvProjView, const core::vector2df &screen, unsigned TU_tex);
|
||||
@ -354,6 +344,38 @@ public:
|
||||
|
||||
}
|
||||
|
||||
#define MAXLIGHT 16
|
||||
|
||||
namespace LightShader
|
||||
{
|
||||
struct PointLightInfo
|
||||
{
|
||||
float posX;
|
||||
float posY;
|
||||
float posZ;
|
||||
float energy;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
float padding;
|
||||
};
|
||||
|
||||
|
||||
class PointLightShader
|
||||
{
|
||||
public:
|
||||
static GLuint Program;
|
||||
static GLuint attrib_Position, attrib_Energy, attrib_Color;
|
||||
static GLuint attrib_Corner;
|
||||
static GLuint uniform_ntex, uniform_dtex, uniform_spec, uniform_screen, uniform_invproj, uniform_VM, uniform_PM;
|
||||
static GLuint vbo;
|
||||
static GLuint vao;
|
||||
|
||||
static void init();
|
||||
static void setUniforms(const core::matrix4 &ViewMatrix, const core::matrix4 &ProjMatrix, const core::matrix4 &InvProjMatrix, const core::vector2df &screen, unsigned spec, unsigned TU_ntex, unsigned TU_dtex);
|
||||
};
|
||||
}
|
||||
|
||||
namespace ParticleShader
|
||||
{
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/skidding.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "graphics/stkmeshscenenode.hpp"
|
||||
|
||||
#include <IMeshSceneNode.h>
|
||||
#include <SMesh.h>
|
||||
@ -134,6 +135,8 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
// (till these skid mark quads are deleted)
|
||||
m_left[m_current]->setHardwareMappingHint(scene::EHM_STATIC);
|
||||
m_right[m_current]->setHardwareMappingHint(scene::EHM_STATIC);
|
||||
if (STKMeshSceneNode* stkm = dynamic_cast<STKMeshSceneNode*>(m_nodes[m_current]))
|
||||
stkm->setReloadEachFrame(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -188,6 +191,8 @@ void SkidMarks::update(float dt, bool force_skid_marks,
|
||||
m_material, m_avoid_z_fighting, custom_color);
|
||||
new_mesh->addMeshBuffer(smq_right);
|
||||
scene::IMeshSceneNode *new_node = irr_driver->addMesh(new_mesh);
|
||||
if (STKMeshSceneNode* stkm = dynamic_cast<STKMeshSceneNode*>(new_node))
|
||||
stkm->setReloadEachFrame(true);
|
||||
#ifdef DEBUG
|
||||
std::string debug_name = m_kart.getIdent()+" (skid-mark)";
|
||||
new_node->setName(debug_name.c_str());
|
||||
|
@ -171,11 +171,13 @@ void STKAnimatedMesh::render()
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
computeTIMV(TransposeInverseModelView);
|
||||
|
||||
glUseProgram(MeshShader::ObjectPass1Shader::Program);
|
||||
if (!GeometricMesh[FPSM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::ObjectPass1Shader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
|
||||
drawSolidPass1(*GeometricMesh[FPSM_DEFAULT][i], FPSM_DEFAULT);
|
||||
|
||||
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
|
||||
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
|
||||
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++)
|
||||
drawSolidPass1(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i], FPSM_ALPHA_REF_TEXTURE);
|
||||
|
||||
@ -184,36 +186,43 @@ void STKAnimatedMesh::render()
|
||||
|
||||
if (irr_driver->getPhase() == SOLID_LIT_PASS)
|
||||
{
|
||||
glUseProgram(MeshShader::ObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_DEFAULT][i], SM_DEFAULT);
|
||||
if (!ShadedMesh[SM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::ObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_DEFAULT][i], SM_DEFAULT);
|
||||
|
||||
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], SM_ALPHA_REF_TEXTURE);
|
||||
if (!ShadedMesh[SM_ALPHA_REF_TEXTURE].empty())
|
||||
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], SM_ALPHA_REF_TEXTURE);
|
||||
|
||||
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_RIMLIT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_RIMLIT][i], SM_RIMLIT);
|
||||
if (!ShadedMesh[SM_RIMLIT].empty())
|
||||
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_RIMLIT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_RIMLIT][i], SM_RIMLIT);
|
||||
|
||||
glUseProgram(MeshShader::ObjectUnlitShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_UNLIT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_UNLIT][i], SM_UNLIT);
|
||||
if (!ShadedMesh[SM_UNLIT].empty())
|
||||
glUseProgram(MeshShader::ObjectUnlitShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_UNLIT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_UNLIT][i], SM_UNLIT);
|
||||
|
||||
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_DETAILS].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_DETAILS][i], SM_DETAILS);
|
||||
if (!ShadedMesh[SM_DETAILS].empty())
|
||||
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_DETAILS].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_DETAILS][i], SM_DETAILS);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
if (irr_driver->getPhase() == SHADOW_PASS)
|
||||
{
|
||||
glUseProgram(MeshShader::ShadowShader::Program);
|
||||
if (!GeometricMesh[FPSM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::ShadowShader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
|
||||
drawShadow(*GeometricMesh[FPSM_DEFAULT][i]);
|
||||
|
||||
glUseProgram(MeshShader::RefShadowShader::Program);
|
||||
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
|
||||
glUseProgram(MeshShader::RefShadowShader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++)
|
||||
drawShadowRef(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i]);
|
||||
return;
|
||||
@ -223,13 +232,25 @@ void STKAnimatedMesh::render()
|
||||
{
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
|
||||
glUseProgram(MeshShader::BubbleShader::Program);
|
||||
if (!TransparentMesh[TM_BUBBLE].empty())
|
||||
glUseProgram(MeshShader::BubbleShader::Program);
|
||||
for (unsigned i = 0; i < TransparentMesh[TM_BUBBLE].size(); i++)
|
||||
drawBubble(*TransparentMesh[TM_BUBBLE][i], ModelViewProjectionMatrix);
|
||||
|
||||
glUseProgram(MeshShader::TransparentShader::Program);
|
||||
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
|
||||
drawTransparentObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
|
||||
if (World::getWorld()->getTrack()->isFogEnabled())
|
||||
{
|
||||
if (!TransparentMesh[TM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::TransparentFogShader::Program);
|
||||
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
|
||||
drawTransparentFogObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!TransparentMesh[TM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::TransparentShader::Program);
|
||||
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
|
||||
drawTransparentObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ STKBillboard::STKBillboard(irr::scene::ISceneNode* parent, irr::scene::ISceneMan
|
||||
|
||||
void STKBillboard::render()
|
||||
{
|
||||
if (irr_driver->getPhase() != TRANSPARENT_PASS)
|
||||
return;
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
glBindVertexArray(billboardvao);
|
||||
GLuint texid = getTextureGLuint(Material.getTexture(0));
|
||||
|
@ -55,6 +55,8 @@ TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE typ
|
||||
|
||||
GLuint createVAO(GLuint vbo, GLuint idx, GLuint attrib_position, GLuint attrib_texcoord, GLuint attrib_second_texcoord, GLuint attrib_normal, GLuint attrib_tangent, GLuint attrib_bitangent, GLuint attrib_color, size_t stride)
|
||||
{
|
||||
if (attrib_position == -1)
|
||||
return 0;
|
||||
GLuint vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
@ -401,6 +403,8 @@ void drawObjectRefPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjec
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
static video::ITexture *CausticTex = 0;
|
||||
|
||||
void drawCaustics(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector2df dir, core::vector2df dir2)
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
@ -419,7 +423,9 @@ void drawCaustics(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionM
|
||||
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
setTexture(MeshShader::CausticsShader::TU_caustictex, getTextureGLuint(irr_driver->getTexture(file_manager->getAsset("textures/caustics.png").c_str())), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
if (!CausticTex)
|
||||
CausticTex = irr_driver->getTexture(file_manager->getAsset("textures/caustics.png").c_str());
|
||||
setTexture(MeshShader::CausticsShader::TU_caustictex, getTextureGLuint(CausticTex), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
|
||||
MeshShader::CausticsShader::setUniforms(ModelViewProjectionMatrix, dir, dir2, core::vector2df(UserConfigParams::m_width, UserConfigParams::m_height));
|
||||
|
||||
@ -814,20 +820,18 @@ void initvaostate(GLMesh &mesh, TransparentMaterial TranspMat)
|
||||
MeshShader::BubbleShader::attrib_position, MeshShader::BubbleShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
|
||||
break;
|
||||
case TM_DEFAULT:
|
||||
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
|
||||
MeshShader::TransparentShader::attrib_position, MeshShader::TransparentShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
|
||||
if (World::getWorld()->getTrack()->isFogEnabled())
|
||||
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
|
||||
MeshShader::TransparentFogShader::attrib_position, MeshShader::TransparentFogShader::attrib_texcoord, -1, -1, -1, -1, MeshShader::TransparentFogShader::attrib_color, mesh.Stride);
|
||||
|
||||
else
|
||||
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
|
||||
MeshShader::TransparentShader::attrib_position, MeshShader::TransparentShader::attrib_texcoord, -1, -1, -1, -1, MeshShader::TransparentShader::attrib_color, mesh.Stride);
|
||||
break;
|
||||
}
|
||||
mesh.vao_glow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::ColorizeShader::attrib_position, -1, -1, -1, -1, -1, -1, mesh.Stride);
|
||||
mesh.vao_displace_mask_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::DisplaceShader::attrib_position, -1, -1, -1, -1, -1, -1, mesh.Stride);
|
||||
if (mesh.Stride >= 44)
|
||||
mesh.vao_displace_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, MeshShader::DisplaceShader::attrib_position, MeshShader::DisplaceShader::attrib_texcoord, MeshShader::DisplaceShader::attrib_second_texcoord, -1, -1, -1, -1, mesh.Stride);
|
||||
|
||||
/*
|
||||
else if (World::getWorld()->getTrack()->isFogEnabled())
|
||||
{
|
||||
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
|
||||
MeshShader::TransparentFogShader::attrib_position, MeshShader::TransparentFogShader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
@ -32,9 +32,15 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent,
|
||||
const irr::core::vector3df& scale) :
|
||||
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
|
||||
{
|
||||
reload_each_frame = false;
|
||||
createGLMeshes();
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::setReloadEachFrame(bool val)
|
||||
{
|
||||
reload_each_frame = val;
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::createGLMeshes()
|
||||
{
|
||||
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
|
||||
@ -137,6 +143,8 @@ void STKMeshSceneNode::drawGlow(const GLMesh &mesh)
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
static video::ITexture *displaceTex = 0;
|
||||
|
||||
void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
|
||||
{
|
||||
DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE);
|
||||
@ -161,8 +169,10 @@ void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
|
||||
// Render the effect
|
||||
if (!displaceTex)
|
||||
displaceTex = irr_driver->getTexture(FileManager::TEXTURE, "displace.png");
|
||||
irr_driver->getVideoDriver()->setRenderTarget(irr_driver->getRTT(RTT_DISPLACE), false, false);
|
||||
setTexture(0, getTextureGLuint(irr_driver->getTexture(FileManager::TEXTURE, "displace.png")), GL_LINEAR, GL_LINEAR, true);
|
||||
setTexture(0, getTextureGLuint(displaceTex), GL_LINEAR, GL_LINEAR, true);
|
||||
setTexture(1, getTextureGLuint(irr_driver->getRTT(RTT_TMP4)), GL_LINEAR, GL_LINEAR, true);
|
||||
setTexture(2, getTextureGLuint(irr_driver->getRTT(RTT_COLOR)), GL_LINEAR, GL_LINEAR, true);
|
||||
glUseProgram(MeshShader::DisplaceShader::Program);
|
||||
@ -270,6 +280,41 @@ void STKMeshSceneNode::drawSolidPass2(const GLMesh &mesh, ShadedMaterial type)
|
||||
}
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::updatevbo()
|
||||
{
|
||||
for (unsigned i = 0; i < Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
continue;
|
||||
GLMesh &mesh = GLmeshes[i];
|
||||
glBindVertexArray(0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_buffer);
|
||||
const void* vertices = mb->getVertices();
|
||||
const u32 vertexCount = mb->getVertexCount();
|
||||
const c8* vbuf = static_cast<const c8*>(vertices);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * mesh.Stride, vbuf, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_buffer);
|
||||
const void* indices = mb->getIndices();
|
||||
mesh.IndexCount = mb->getIndexCount();
|
||||
GLenum indexSize;
|
||||
switch (mb->getIndexType())
|
||||
{
|
||||
case irr::video::EIT_16BIT:
|
||||
indexSize = sizeof(u16);
|
||||
break;
|
||||
case irr::video::EIT_32BIT:
|
||||
indexSize = sizeof(u32);
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Wrong index size");
|
||||
}
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.IndexCount * indexSize, indices, GL_STATIC_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::render()
|
||||
{
|
||||
irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
|
||||
@ -277,6 +322,9 @@ void STKMeshSceneNode::render()
|
||||
if (!Mesh || !driver)
|
||||
return;
|
||||
|
||||
if (reload_each_frame)
|
||||
updatevbo();
|
||||
|
||||
bool isTransparentPass =
|
||||
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
|
||||
|
||||
@ -297,82 +345,113 @@ void STKMeshSceneNode::render()
|
||||
|
||||
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
|
||||
{
|
||||
if (reload_each_frame)
|
||||
glDisable(GL_CULL_FACE);
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
computeTIMV(TransposeInverseModelView);
|
||||
|
||||
glUseProgram(MeshShader::ObjectPass1Shader::Program);
|
||||
if (!GeometricMesh[FPSM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::ObjectPass1Shader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
|
||||
drawSolidPass1(*GeometricMesh[FPSM_DEFAULT][i], FPSM_DEFAULT);
|
||||
|
||||
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
|
||||
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
|
||||
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++)
|
||||
drawSolidPass1(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i], FPSM_ALPHA_REF_TEXTURE);
|
||||
|
||||
glUseProgram(MeshShader::NormalMapShader::Program);
|
||||
if (!GeometricMesh[FPSM_NORMAL_MAP].empty())
|
||||
glUseProgram(MeshShader::NormalMapShader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_NORMAL_MAP].size(); i++)
|
||||
drawSolidPass1(*GeometricMesh[FPSM_NORMAL_MAP][i], FPSM_NORMAL_MAP);
|
||||
|
||||
glUseProgram(MeshShader::GrassPass1Shader::Program);
|
||||
if (!GeometricMesh[FPSM_GRASS].empty())
|
||||
glUseProgram(MeshShader::GrassPass1Shader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_GRASS].size(); i++)
|
||||
drawSolidPass1(*GeometricMesh[FPSM_GRASS][i], FPSM_GRASS);
|
||||
|
||||
if (reload_each_frame)
|
||||
glEnable(GL_CULL_FACE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (irr_driver->getPhase() == SOLID_LIT_PASS)
|
||||
{
|
||||
glUseProgram(MeshShader::ObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_DEFAULT][i], SM_DEFAULT);
|
||||
if (reload_each_frame)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], SM_ALPHA_REF_TEXTURE);
|
||||
if (!ShadedMesh[SM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::ObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_DEFAULT][i], SM_DEFAULT);
|
||||
|
||||
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_RIMLIT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_RIMLIT][i], SM_RIMLIT);
|
||||
if (!ShadedMesh[SM_ALPHA_REF_TEXTURE].empty())
|
||||
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], SM_ALPHA_REF_TEXTURE);
|
||||
|
||||
glUseProgram(MeshShader::SphereMapShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_SPHEREMAP].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_SPHEREMAP][i], SM_SPHEREMAP);
|
||||
if (!ShadedMesh[SM_RIMLIT].empty())
|
||||
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_RIMLIT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_RIMLIT][i], SM_RIMLIT);
|
||||
|
||||
glUseProgram(MeshShader::SplattingShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_SPLATTING].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_SPLATTING][i], SM_SPLATTING);
|
||||
if (!ShadedMesh[SM_SPHEREMAP].empty())
|
||||
glUseProgram(MeshShader::SphereMapShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_SPHEREMAP].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_SPHEREMAP][i], SM_SPHEREMAP);
|
||||
|
||||
glUseProgram(MeshShader::GrassPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_GRASS].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_GRASS][i], SM_GRASS);
|
||||
if (!ShadedMesh[SM_SPLATTING].empty())
|
||||
glUseProgram(MeshShader::SplattingShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_SPLATTING].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_SPLATTING][i], SM_SPLATTING);
|
||||
|
||||
glUseProgram(MeshShader::ObjectUnlitShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_UNLIT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_UNLIT][i], SM_UNLIT);
|
||||
if (!ShadedMesh[SM_GRASS].empty())
|
||||
glUseProgram(MeshShader::GrassPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_GRASS].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_GRASS][i], SM_GRASS);
|
||||
|
||||
glUseProgram(MeshShader::CausticsShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_CAUSTICS].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_CAUSTICS][i], SM_CAUSTICS);
|
||||
if (!ShadedMesh[SM_UNLIT].empty())
|
||||
glUseProgram(MeshShader::ObjectUnlitShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_UNLIT].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_UNLIT][i], SM_UNLIT);
|
||||
|
||||
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_DETAILS].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_DETAILS][i], SM_DETAILS);
|
||||
if (!ShadedMesh[SM_CAUSTICS].empty())
|
||||
glUseProgram(MeshShader::CausticsShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_CAUSTICS].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_CAUSTICS][i], SM_CAUSTICS);
|
||||
|
||||
glUseProgram(MeshShader::UntexturedObjectShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_UNTEXTURED].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_UNTEXTURED][i], SM_UNTEXTURED);
|
||||
if (!ShadedMesh[SM_DETAILS].empty())
|
||||
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_DETAILS].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_DETAILS][i], SM_DETAILS);
|
||||
|
||||
return;
|
||||
if (!ShadedMesh[SM_UNTEXTURED].empty())
|
||||
glUseProgram(MeshShader::UntexturedObjectShader::Program);
|
||||
for (unsigned i = 0; i < ShadedMesh[SM_UNTEXTURED].size(); i++)
|
||||
drawSolidPass2(*ShadedMesh[SM_UNTEXTURED][i], SM_UNTEXTURED);
|
||||
|
||||
if (reload_each_frame)
|
||||
glEnable(GL_CULL_FACE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (irr_driver->getPhase() == SHADOW_PASS)
|
||||
{
|
||||
glUseProgram(MeshShader::ShadowShader::Program);
|
||||
if (reload_each_frame)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
if (!GeometricMesh[FPSM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::ShadowShader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
|
||||
drawShadow(*GeometricMesh[FPSM_DEFAULT][i]);
|
||||
|
||||
glUseProgram(MeshShader::RefShadowShader::Program);
|
||||
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
|
||||
glUseProgram(MeshShader::RefShadowShader::Program);
|
||||
for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++)
|
||||
drawShadowRef(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i]);
|
||||
|
||||
if (reload_each_frame)
|
||||
glEnable(GL_CULL_FACE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -392,13 +471,25 @@ void STKMeshSceneNode::render()
|
||||
{
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
|
||||
glUseProgram(MeshShader::BubbleShader::Program);
|
||||
if (!TransparentMesh[TM_BUBBLE].empty())
|
||||
glUseProgram(MeshShader::BubbleShader::Program);
|
||||
for (unsigned i = 0; i < TransparentMesh[TM_BUBBLE].size(); i++)
|
||||
drawBubble(*TransparentMesh[TM_BUBBLE][i], ModelViewProjectionMatrix);
|
||||
|
||||
glUseProgram(MeshShader::TransparentShader::Program);
|
||||
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
|
||||
drawTransparentObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
|
||||
if (World::getWorld()->getTrack()->isFogEnabled())
|
||||
{
|
||||
if (!TransparentMesh[TM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::TransparentFogShader::Program);
|
||||
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
|
||||
drawTransparentFogObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!TransparentMesh[TM_DEFAULT].empty())
|
||||
glUseProgram(MeshShader::TransparentShader::Program);
|
||||
for (unsigned i = 0; i < TransparentMesh[TM_DEFAULT].size(); i++)
|
||||
drawTransparentObject(*TransparentMesh[TM_DEFAULT][i], ModelViewProjectionMatrix, (*TransparentMesh[TM_DEFAULT][i]).TextureMatrix);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -23,15 +23,17 @@ protected:
|
||||
void createGLMeshes();
|
||||
void cleanGLMeshes();
|
||||
void setFirstTimeMaterial();
|
||||
void updatevbo();
|
||||
bool isMaterialInitialized;
|
||||
bool reload_each_frame;
|
||||
public:
|
||||
void setReloadEachFrame(bool);
|
||||
STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
const irr::core::vector3df& position = irr::core::vector3df(0, 0, 0),
|
||||
const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0),
|
||||
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
virtual void render();
|
||||
virtual void setMesh(irr::scene::IMesh* mesh);
|
||||
void MovingTexture(unsigned, unsigned);
|
||||
~STKMeshSceneNode();
|
||||
};
|
||||
|
||||
|
@ -26,6 +26,7 @@ STKModifiedSpriteBank::STKModifiedSpriteBank(IGUIEnvironment* env) :
|
||||
#endif
|
||||
|
||||
m_scale = 1.0f;
|
||||
m_height = 0;
|
||||
|
||||
if (Environment)
|
||||
{
|
||||
@ -62,8 +63,8 @@ core::array< core::rect<s32> >& STKModifiedSpriteBank::getPositions()
|
||||
|
||||
for (int n=0; n<(int)Rectangles.size(); n++)
|
||||
{
|
||||
const int h = (int)(Rectangles[n].getHeight()*m_scale);
|
||||
const int w = (int)(Rectangles[n].getWidth() *m_scale);
|
||||
const int h = getScaledHeight(Rectangles[n].getHeight());
|
||||
const int w = getScaledWidth(Rectangles[n].getWidth());
|
||||
copy.push_back( core::rect<s32>(Rectangles[n].UpperLeftCorner,
|
||||
core::dimension2d<s32>(w,h) )
|
||||
);
|
||||
@ -203,8 +204,8 @@ void STKModifiedSpriteBank::draw2DSprite(u32 index,
|
||||
const core::dimension2d<s32>& dim = r.getSize();
|
||||
|
||||
core::rect<s32> dest( pos,
|
||||
core::dimension2d<s32>((int)(dim.Width*m_scale),
|
||||
(int)(dim.Height*m_scale)) );
|
||||
core::dimension2d<s32>(getScaledWidth(dim.Width),
|
||||
getScaledHeight(dim.Height)));
|
||||
if (center)
|
||||
{
|
||||
dest -= dest.getSize() / 2;
|
||||
@ -295,6 +296,30 @@ void STKModifiedSpriteBank::draw2DSpriteBatch(const core::array<u32>& indices,
|
||||
}
|
||||
} // draw2DSpriteBatch
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void STKModifiedSpriteBank::scaleToHeight(int height)
|
||||
{
|
||||
m_height = height;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
s32 STKModifiedSpriteBank::getScaledWidth(s32 width) const
|
||||
{
|
||||
if (m_height == 0)
|
||||
return (s32)((float)width * m_scale);
|
||||
else
|
||||
return m_height;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
s32 STKModifiedSpriteBank::getScaledHeight(s32 height) const
|
||||
{
|
||||
if (m_height == 0)
|
||||
return (s32)((float)height * m_scale);
|
||||
else
|
||||
return m_height;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
} // namespace gui
|
||||
} // namespace irr
|
||||
|
@ -67,12 +67,15 @@ public:
|
||||
m_scale = scale;
|
||||
}
|
||||
|
||||
void scaleToHeight(int height);
|
||||
|
||||
protected:
|
||||
|
||||
// this object was getting access after being freed, I wanna see when/why
|
||||
unsigned int m_magic_number;
|
||||
|
||||
float m_scale;
|
||||
int m_height;
|
||||
|
||||
struct SDrawBatch
|
||||
{
|
||||
@ -91,6 +94,8 @@ protected:
|
||||
IGUIEnvironment* Environment;
|
||||
video::IVideoDriver* Driver;
|
||||
|
||||
s32 getScaledWidth(s32 width) const;
|
||||
s32 getScaledHeight(s32 height) const;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
|
@ -486,6 +486,14 @@ namespace GUIEngine
|
||||
Used on divs, indicate by how many pixels to pad contents
|
||||
|
||||
|
||||
\n
|
||||
\subsection prop20 PROP_KEEP_SELECTION
|
||||
<em> Name in XML files: </em> \c "keep_selection"
|
||||
|
||||
Used on lists, indicates that the list should keep showing the selected item
|
||||
even when it doesn't have the focus
|
||||
|
||||
|
||||
\n
|
||||
<HR>
|
||||
\section code Using the engine in code
|
||||
@ -723,20 +731,6 @@ namespace GUIEngine
|
||||
|
||||
std::vector<MenuMessage> gui_messages;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
Screen* getScreenNamed(const char* name)
|
||||
{
|
||||
const int screenCount = g_loaded_screens.size();
|
||||
for (int n=0; n<screenCount; n++)
|
||||
{
|
||||
if (g_loaded_screens[n].getName() == name)
|
||||
{
|
||||
return g_loaded_screens.get(n);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
} // getScreenNamed
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void showMessage(const wchar_t* message, const float time)
|
||||
{
|
||||
@ -800,13 +794,14 @@ namespace GUIEngine
|
||||
{
|
||||
return Private::small_font_height;
|
||||
} // getSmallFontHeight
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
int getLargeFontHeight()
|
||||
{
|
||||
{
|
||||
|
||||
return Private::large_font_height;
|
||||
} // getSmallFontHeight
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
|
@ -170,7 +170,7 @@ namespace GUIEngine
|
||||
inline Skin* getSkin() { return Private::g_skin; }
|
||||
|
||||
Screen* getScreenNamed(const char* name);
|
||||
|
||||
|
||||
/** \return the height of the title font in pixels */
|
||||
int getTitleFontHeight();
|
||||
|
||||
|
@ -602,8 +602,6 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
|
||||
core::rect<s32> dest(offsets[n] + core::position2di(0, y_shift), size);
|
||||
|
||||
video::SColor colors[] = {color, color, color, color};
|
||||
|
||||
video::ITexture* texture = (fallback[n] ?
|
||||
m_fallback_font->SpriteBank->getTexture(texID) :
|
||||
SpriteBank->getTexture(texID) );
|
||||
@ -644,7 +642,6 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
{
|
||||
// draw black border
|
||||
video::SColor black(color.getAlpha(),0,0,0);
|
||||
video::SColor black_colors[] = {black, black, black, black};
|
||||
|
||||
for (int x_delta=-2; x_delta<=2; x_delta++)
|
||||
{
|
||||
@ -652,10 +649,10 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
{
|
||||
if (x_delta == 0 || y_delta == 0) continue;
|
||||
draw2DImage(texture,
|
||||
dest + core::position2d<s32>(x_delta, y_delta),
|
||||
source,
|
||||
clip,
|
||||
black_colors, true);
|
||||
dest + core::position2d<s32>(x_delta, y_delta),
|
||||
source,
|
||||
clip,
|
||||
black, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -667,18 +664,18 @@ void ScalableFont::draw(const core::stringw& text,
|
||||
static video::SColor yellow(color.getAlpha(), 255, 220, 15);
|
||||
video::SColor title_colors[] = {yellow, orange, orange, yellow};
|
||||
draw2DImage(texture,
|
||||
dest,
|
||||
source,
|
||||
clip,
|
||||
title_colors, true);
|
||||
dest,
|
||||
source,
|
||||
clip,
|
||||
title_colors, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
draw2DImage(texture,
|
||||
dest,
|
||||
source,
|
||||
clip,
|
||||
colors, true);
|
||||
dest,
|
||||
source,
|
||||
clip,
|
||||
color, true);
|
||||
|
||||
#ifdef FONT_DEBUG
|
||||
driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y),
|
||||
|
@ -221,6 +221,7 @@ if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).
|
||||
READ_PROPERTY(max_rows, PROP_MAX_ROWS);
|
||||
READ_PROPERTY(wrap_around, PROP_WRAP_AROUND);
|
||||
READ_PROPERTY(padding, PROP_DIV_PADDING);
|
||||
READ_PROPERTY(keep_selection, PROP_KEEP_SELECTION);
|
||||
#undef READ_PROPERTY
|
||||
|
||||
const wchar_t* text = xml->getAttributeValue( L"text" );
|
||||
|
@ -103,7 +103,8 @@ namespace GUIEngine
|
||||
PROP_LABELS_LOCATION,
|
||||
PROP_MAX_ROWS,
|
||||
PROP_WRAP_AROUND,
|
||||
PROP_DIV_PADDING
|
||||
PROP_DIV_PADDING,
|
||||
PROP_KEEP_SELECTION,
|
||||
};
|
||||
|
||||
bool isWithinATextBox();
|
||||
|
@ -299,7 +299,8 @@ void ListWidget::unfocused(const int playerID, Widget* new_focus)
|
||||
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
|
||||
|
||||
// remove selection when leaving list
|
||||
if (list != NULL) list->setSelected(-1);
|
||||
if (list != NULL && m_properties[PROP_KEEP_SELECTION] != "true")
|
||||
list->setSelected(-1);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -188,10 +188,11 @@ FileManager::FileManager()
|
||||
addRootDirs(root_dir+"../../stk-assets");
|
||||
if ( getenv ( "SUPERTUXKART_ROOT_PATH" ) != NULL )
|
||||
addRootDirs(getenv("SUPERTUXKART_ROOT_PATH"));
|
||||
|
||||
|
||||
checkAndCreateConfigDir();
|
||||
checkAndCreateAddonsDir();
|
||||
checkAndCreateScreenshotDir();
|
||||
checkAndCreateGPDir();
|
||||
|
||||
#ifdef WIN32
|
||||
redirectOutput();
|
||||
@ -203,12 +204,14 @@ FileManager::FileManager()
|
||||
for(unsigned int i=0; i<m_root_dirs.size(); i++)
|
||||
Log::info("[FileManager]", "Data files will be fetched from: '%s'",
|
||||
m_root_dirs[i].c_str());
|
||||
Log::info("[FileManager]", "User directory is '%s'.",
|
||||
Log::info("[FileManager]", "User directory is '%s'.",
|
||||
m_user_config_dir.c_str());
|
||||
Log::info("[FileManager]", "Addons files will be stored in '%s'.",
|
||||
m_addons_dir.c_str());
|
||||
Log::info("[FileManager]", "Screenshots will be stored in '%s'.",
|
||||
m_screenshot_dir.c_str());
|
||||
Log::info("[FileManager]", "User-defined grand prix will be stored in '%s'.",
|
||||
m_gp_dir.c_str());
|
||||
|
||||
/** Now search for the path to all needed subdirectories. */
|
||||
// ==========================================================
|
||||
@ -270,7 +273,7 @@ void FileManager::reInit()
|
||||
|
||||
// Note that we can't push the texture search path in the constructor
|
||||
// since this also adds a file archive to te file system - and
|
||||
// m_file_system is deleted (in irr_driver) after
|
||||
// m_file_system is deleted (in irr_driver) after
|
||||
pushTextureSearchPath(m_subdir_name[TEXTURE]);
|
||||
if(fileExists(m_subdir_name[TEXTURE]+"deprecated/"))
|
||||
pushTextureSearchPath(m_subdir_name[TEXTURE]+"deprecated/");
|
||||
@ -543,7 +546,7 @@ std::string FileManager::getAssetChecked(FileManager::AssetType type,
|
||||
} // getAssetChecked
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the full path of a file of the given asset class. It is not
|
||||
/** Returns the full path of a file of the given asset class. It is not
|
||||
* checked if the file actually exists (use getAssetChecked() instead if
|
||||
* checking is needed).
|
||||
* \param type Type of the asset class.
|
||||
@ -577,7 +580,15 @@ std::string FileManager::getScreenshotDir() const
|
||||
} // getScreenshotDir
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the full path of a texture file name by searching in all
|
||||
/** Returns the directory in which user-defined grand prix should be stored.
|
||||
*/
|
||||
std::string FileManager::getGPDir() const
|
||||
{
|
||||
return m_gp_dir;
|
||||
} // getGPDir
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the full path of a texture file name by searching in all
|
||||
* directories currently in the texture search path. The difference to
|
||||
* a call getAsset(TEXTURE,...) is that the latter will only return
|
||||
* textures from .../textures, while the searchTexture will also
|
||||
@ -666,7 +677,7 @@ bool FileManager::checkAndCreateDirectoryP(const std::string &path)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Checks if the config directory exists, and it not, tries to create it.
|
||||
* It will set m_user_config_dir to the path to which user-specific config
|
||||
* It will set m_user_config_dir to the path to which user-specific config
|
||||
* files are stored.
|
||||
*/
|
||||
void FileManager::checkAndCreateConfigDir()
|
||||
@ -725,7 +736,7 @@ void FileManager::checkAndCreateConfigDir()
|
||||
}
|
||||
else if (!getenv("HOME"))
|
||||
{
|
||||
Log::error("[FileManager]",
|
||||
Log::error("[FileManager]",
|
||||
"No home directory, this should NOT happen "
|
||||
"- trying '.' for config files!");
|
||||
m_user_config_dir = ".";
|
||||
@ -737,7 +748,7 @@ void FileManager::checkAndCreateConfigDir()
|
||||
if(!checkAndCreateDirectory(m_user_config_dir))
|
||||
{
|
||||
// If $HOME/.config can not be created:
|
||||
Log::error("[FileManager]",
|
||||
Log::error("[FileManager]",
|
||||
"Cannot create directory '%s', falling back to use '%s'",
|
||||
m_user_config_dir.c_str(), getenv("HOME"));
|
||||
m_user_config_dir = getenv("HOME");
|
||||
@ -824,6 +835,32 @@ void FileManager::checkAndCreateScreenshotDir()
|
||||
|
||||
} // checkAndCreateScreenshotDir
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Creates the directories for user-defined grand prix. This will set m_gp_dir
|
||||
* with the appropriate path.
|
||||
*/
|
||||
void FileManager::checkAndCreateGPDir()
|
||||
{
|
||||
#if defined(WIN32) || defined(__CYGWIN__)
|
||||
m_gp_dir = m_user_config_dir + "grandprix/";
|
||||
#elif defined(__APPLE__)
|
||||
m_gp_dir = getenv("HOME");
|
||||
m_gp_dir += "/Library/Application Support/SuperTuxKart/grandprix/";
|
||||
#else
|
||||
m_gp_dir = checkAndCreateLinuxDir("XDG_DATA_HOME", "supertuxkart",
|
||||
".local/share", ".supertuxkart");
|
||||
m_gp_dir += "grandprix/";
|
||||
#endif
|
||||
|
||||
if(!checkAndCreateDirectory(m_gp_dir))
|
||||
{
|
||||
Log::error("FileManager", "Can not create user-defined grand prix directory '%s', "
|
||||
"falling back to '.'.", m_gp_dir.c_str());
|
||||
m_gp_dir = ".";
|
||||
}
|
||||
|
||||
} // checkAndCreateGPDir
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__APPLE__)
|
||||
|
||||
|
@ -46,10 +46,10 @@ class FileManager : public NoCopy
|
||||
public:
|
||||
/** The various asset types (and directories) STK might request.
|
||||
* The last entry ASSET_COUNT specifies the number of entries. */
|
||||
enum AssetType {ASSET_MIN,
|
||||
CHALLENGE=ASSET_MIN,
|
||||
enum AssetType {ASSET_MIN,
|
||||
CHALLENGE=ASSET_MIN,
|
||||
FONT, GFX, GRANDPRIX, GUI, MODEL, MUSIC,
|
||||
SFX, SHADER, SKIN, TEXTURE, TRANSLATION,
|
||||
SFX, SHADER, SKIN, TEXTURE, TRANSLATION,
|
||||
ASSET_MAX = TRANSLATION,
|
||||
ASSET_COUNT};
|
||||
private:
|
||||
@ -72,6 +72,9 @@ private:
|
||||
/** Directory to store screenshots in. */
|
||||
std::string m_screenshot_dir;
|
||||
|
||||
/** Directory where user-defined grand prix are stored. */
|
||||
std::string m_gp_dir;
|
||||
|
||||
std::vector<std::string>
|
||||
m_texture_search_path,
|
||||
m_model_search_path,
|
||||
@ -88,6 +91,7 @@ private:
|
||||
bool isDirectory(const std::string &path) const;
|
||||
void checkAndCreateAddonsDir();
|
||||
void checkAndCreateScreenshotDir();
|
||||
void checkAndCreateGPDir();
|
||||
#if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__APPLE__)
|
||||
std::string checkAndCreateLinuxDir(const char *env_name,
|
||||
const char *dir_name,
|
||||
@ -106,6 +110,7 @@ public:
|
||||
XMLNode *createXMLTreeFromString(const std::string & content);
|
||||
|
||||
std::string getScreenshotDir() const;
|
||||
std::string getGPDir() const;
|
||||
bool checkAndCreateDirectoryP(const std::string &path);
|
||||
const std::string &getAddonsDir() const;
|
||||
std::string getAddonsFile(const std::string &name);
|
||||
|
@ -18,6 +18,9 @@
|
||||
|
||||
#include "items/powerup.hpp"
|
||||
|
||||
#include "achievements/achievement_info.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
|
||||
#include "audio/sfx_base.hpp"
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "config/stk_config.hpp"
|
||||
@ -170,6 +173,14 @@ void Powerup::adjustSound()
|
||||
*/
|
||||
void Powerup::use()
|
||||
{
|
||||
// The player gets an achievement point for using a powerup
|
||||
StateManager::ActivePlayer * player = m_owner->getController()->getPlayer();
|
||||
if (m_type != PowerupManager::POWERUP_NOTHING &&
|
||||
player != NULL && player->getConstProfile() == PlayerManager::get()->getCurrentPlayer())
|
||||
{
|
||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_POWERUP_LOVER, "poweruplover");
|
||||
}
|
||||
|
||||
// Play custom kart sound when collectible is used //TODO: what about the bubble gum?
|
||||
if (m_type != PowerupManager::POWERUP_NOTHING &&
|
||||
m_type != PowerupManager::POWERUP_SWATTER &&
|
||||
@ -237,7 +248,7 @@ void Powerup::use()
|
||||
m_sound_use->play();
|
||||
|
||||
pos.setY(hit_point.getY()-0.05f);
|
||||
|
||||
|
||||
ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_owner);
|
||||
}
|
||||
else // if the kart is looking forward, use the bubblegum as a shield
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "graphics/stkmeshscenenode.hpp"
|
||||
#include "items/plunger.hpp"
|
||||
#include "items/projectile_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
@ -71,6 +72,8 @@ RubberBand::RubberBand(Plunger *plunger, AbstractKart *kart)
|
||||
updatePosition();
|
||||
m_node = irr_driver->addMesh(m_mesh);
|
||||
irr_driver->applyObjectPassShader(m_node);
|
||||
if (STKMeshSceneNode *stkm = dynamic_cast<STKMeshSceneNode *>(m_node))
|
||||
stkm->setReloadEachFrame(true);
|
||||
#ifdef DEBUG
|
||||
std::string debug_name = m_owner->getIdent()+" (rubber-band)";
|
||||
m_node->setName(debug_name.c_str());
|
||||
|
@ -560,9 +560,17 @@ void KartProperties::getAllData(const XMLNode * root)
|
||||
else if (s == "small") m_engine_sfx_type = "engine_small";
|
||||
else
|
||||
{
|
||||
Log::warn("[KartProperties]", "Kart '%s' has invalid engine '%s'.",
|
||||
m_name.c_str(), s.c_str());
|
||||
m_engine_sfx_type = "engine_small";
|
||||
if (sfx_manager->soundExist(s))
|
||||
{
|
||||
m_engine_sfx_type = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("[KartProperties]",
|
||||
"Kart '%s' has an invalid engine '%s'.",
|
||||
m_name.c_str(), s.c_str());
|
||||
m_engine_sfx_type = "engine_small";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WILL_BE_ENABLED_ONCE_DONE_PROPERLY
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#include "modes/linear_world.hpp"
|
||||
|
||||
#include "achievements/achievements_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "audio/music_manager.hpp"
|
||||
#include "audio/sfx_base.hpp"
|
||||
#include "audio/sfx_manager.hpp"
|
||||
@ -236,6 +238,14 @@ void LinearWorld::newLap(unsigned int kart_index)
|
||||
KartInfo &kart_info = m_kart_info[kart_index];
|
||||
AbstractKart *kart = m_karts[kart_index];
|
||||
|
||||
// Reset reset-after-lap achievements
|
||||
StateManager::ActivePlayer *c = kart->getController()->getPlayer();
|
||||
PlayerProfile *p = PlayerManager::get()->getCurrentPlayer();
|
||||
if (c && c->getConstProfile() == p)
|
||||
{
|
||||
p->getAchievementsStatus()->onLapEnd();
|
||||
}
|
||||
|
||||
// Only update the kart controller if a kart that has already finished
|
||||
// the race crosses the start line again. This avoids 'fastest lap'
|
||||
// messages if the end controller does a fastest lap, but especially
|
||||
|
@ -445,6 +445,7 @@ void World::terminateRace()
|
||||
&best_player);
|
||||
}
|
||||
|
||||
// Check achievements
|
||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_COLUMBUS,
|
||||
getTrack()->getIdent(), 1);
|
||||
if (raceHasLaps())
|
||||
@ -452,6 +453,64 @@ void World::terminateRace()
|
||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_MARATHONER,
|
||||
"laps", race_manager->getNumLaps());
|
||||
}
|
||||
|
||||
Achievement *achiev = PlayerManager::getCurrentAchievementsStatus()->getAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER);
|
||||
if (achiev)
|
||||
{
|
||||
std::string mode_name = getIdent(); // Get the race mode name
|
||||
int winner_position = 1;
|
||||
int opponents = achiev->getInfo()->getGoalValue("opponents"); // Get the required opponents number
|
||||
if (mode_name == IDENT_FTL)
|
||||
{
|
||||
winner_position = 2;
|
||||
opponents++;
|
||||
}
|
||||
for(unsigned int i = 0; i < kart_amount; i++)
|
||||
{
|
||||
// Retrieve the current player
|
||||
StateManager::ActivePlayer* p = m_karts[i]->getController()->getPlayer();
|
||||
if (p && p->getConstProfile() == PlayerManager::get()->getCurrentPlayer())
|
||||
{
|
||||
// Check if the player has won
|
||||
if (m_karts[i]->getPosition() == winner_position && kart_amount > opponents )
|
||||
{
|
||||
// Update the achievement
|
||||
mode_name = StringUtils::toLowerCase(mode_name);
|
||||
if (achiev->getValue("opponents") <= 0)
|
||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER,
|
||||
"opponents", opponents);
|
||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER,
|
||||
mode_name, 1);
|
||||
}
|
||||
}
|
||||
} // for i < kart_amount
|
||||
} // if (achiev)
|
||||
|
||||
Achievement *win = PlayerManager::getCurrentAchievementsStatus()->getAchievement(AchievementInfo::ACHIEVE_UNSTOPPABLE);
|
||||
//if achivement has been unlocked
|
||||
if (win->getValue("wins") < 5 )
|
||||
{
|
||||
for(unsigned int i = 0; i < kart_amount; i++)
|
||||
{
|
||||
// Retrieve the current player
|
||||
StateManager::ActivePlayer* p = m_karts[i]->getController()->getPlayer();
|
||||
if (p && p->getConstProfile() == PlayerManager::get()->getCurrentPlayer())
|
||||
{
|
||||
// Check if the player has won
|
||||
if (m_karts[i]->getPosition() == 1 )
|
||||
{
|
||||
// Increase number of consecutive wins
|
||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_UNSTOPPABLE,
|
||||
"wins", 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Set number of consecutive wins to 0
|
||||
win->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PlayerManager::get()->getCurrentPlayer()->raceFinished();
|
||||
|
||||
if (m_race_gui) m_race_gui->clearAllMessages();
|
||||
|
@ -23,37 +23,62 @@
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/utf_writer.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
GrandPrixData::GrandPrixData(const std::string filename)
|
||||
{
|
||||
load_from_file(file_manager->getAsset(FileManager::GRANDPRIX, filename),
|
||||
filename);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixData::GrandPrixData(const std::string dir, const std::string filename)
|
||||
{
|
||||
assert(dir[dir.size() - 1] == '/');
|
||||
load_from_file(dir + filename, filename);
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::load_from_file(const std::string fullpath,
|
||||
const std::string filename)
|
||||
GrandPrixData::GrandPrixData(const std::string& filename) throw(std::logic_error)
|
||||
{
|
||||
m_filename = filename;
|
||||
m_id = StringUtils::getBasename(StringUtils::removeExtension(filename));
|
||||
m_editable = (filename.find(file_manager->getGPDir(), 0) == 0);
|
||||
reload();
|
||||
}
|
||||
|
||||
XMLNode * root = file_manager->createXMLTree(fullpath);
|
||||
if (!root)
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::setId(const std::string& id)
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::setName(const irr::core::stringw& name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::setFilename(const std::string& filename)
|
||||
{
|
||||
m_filename = filename;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::setEditable(const bool editable)
|
||||
{
|
||||
m_editable = editable;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::reload()
|
||||
{
|
||||
m_tracks.clear();
|
||||
m_laps.clear();
|
||||
m_reversed.clear();
|
||||
|
||||
std::auto_ptr<XMLNode> root(file_manager->createXMLTree(m_filename));
|
||||
if (root.get() == NULL)
|
||||
{
|
||||
Log::error("GrandPrixData","Error while trying to read grandprix file "
|
||||
"'%s'", fullpath.c_str());
|
||||
Log::error("GrandPrixData","Error while trying to read grandprix file '%s'",
|
||||
m_filename.c_str());
|
||||
throw std::logic_error("File not found");
|
||||
}
|
||||
|
||||
@ -61,24 +86,18 @@ void GrandPrixData::load_from_file(const std::string fullpath,
|
||||
|
||||
if (root->getName() == "supertuxkart_grand_prix")
|
||||
{
|
||||
std::string temp_name;
|
||||
if (root->get("name", &temp_name) == 0)
|
||||
if (root->get("name", &m_name) == 0)
|
||||
{
|
||||
Log::error("GrandPrixData", "Error while trying to read grandprix "
|
||||
"file '%s' : missing 'name' attribute\n",
|
||||
fullpath.c_str());
|
||||
delete root;
|
||||
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
|
||||
"missing 'name' attribute\n", m_filename.c_str());
|
||||
throw std::logic_error("File contents are incomplete or corrupt");
|
||||
}
|
||||
m_name = temp_name.c_str();
|
||||
foundName = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("GrandPrixData", "Error while trying to read grandprix file "
|
||||
"'%s' : Root node has an unexpected name\n",
|
||||
fullpath.c_str());
|
||||
delete root;
|
||||
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
|
||||
"Root node has an unexpected name\n", m_filename.c_str());
|
||||
throw std::logic_error("File contents are incomplete or corrupt");
|
||||
}
|
||||
|
||||
@ -95,20 +114,17 @@ void GrandPrixData::load_from_file(const std::string fullpath,
|
||||
int numLaps;
|
||||
bool reversed = false;
|
||||
|
||||
const int idFound = node->get("id", &trackID);
|
||||
const int lapFound = node->get("laps", &numLaps);
|
||||
const int idFound = node->get("id", &trackID );
|
||||
const int lapFound = node->get("laps", &numLaps );
|
||||
// Will stay false if not found
|
||||
node->get("reverse", &reversed );
|
||||
|
||||
if (!idFound || !lapFound)
|
||||
{
|
||||
Log::error("GrandPrixData", "Error while trying to read "
|
||||
"grandprix file '%s' : <track> tag does not have "
|
||||
"idi and laps reverse attributes. \n",
|
||||
fullpath.c_str());
|
||||
delete root;
|
||||
throw std::logic_error("File contents are incomplete or "
|
||||
"corrupt");
|
||||
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
|
||||
"<track> tag does not have idi and laps reverse attributes. \n",
|
||||
m_filename.c_str());
|
||||
throw std::logic_error("File contents are incomplete or corrupt");
|
||||
}
|
||||
|
||||
// Make sure the track really is reversible
|
||||
@ -127,27 +143,58 @@ void GrandPrixData::load_from_file(const std::string fullpath,
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("Unknown node in Grand Prix XML file: %s/n",
|
||||
node->getName().c_str());
|
||||
delete root;
|
||||
std::cerr << "Unknown node in Grand Prix XML file : " << node->getName().c_str() << std::endl;
|
||||
throw std::runtime_error("Unknown node in sfx XML file");
|
||||
}
|
||||
}// end for
|
||||
|
||||
delete root;
|
||||
}// nend for
|
||||
|
||||
// sanity checks
|
||||
if (!foundName)
|
||||
{
|
||||
Log::error("GrandPrixData", "Error while trying to read grandprix file "
|
||||
"'%s' : missing 'name' attribute\n", fullpath.c_str());
|
||||
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
|
||||
"missing 'name' attribute\n", m_filename.c_str());
|
||||
throw std::logic_error("File contents are incomplete or corrupt");
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GrandPrixData::writeToFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
UTFWriter file(m_filename.c_str());
|
||||
if (file.is_open())
|
||||
{
|
||||
file << L"\n<supertuxkart_grand_prix name=\"" << m_name << L"\">\n\n";
|
||||
for (unsigned int i = 0; i < m_tracks.size(); i++)
|
||||
{
|
||||
file <<
|
||||
L"\t<track id=\"" << m_tracks[i] <<
|
||||
L"\" laps=\"" << m_laps[i] <<
|
||||
L"\" reverse=\"" << (m_reversed[i] ? L"true" : L"false") <<
|
||||
L"\" />\n";
|
||||
}
|
||||
file << L"\n</supertuxkart_grand_prix>\n";
|
||||
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
Log::error("GrandPrixData", "Failed to write '%s'; cause: %s\n",
|
||||
m_filename.c_str(), e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GrandPrixData::checkConsistency(bool chatty) const
|
||||
{
|
||||
for(unsigned int i=0; i<m_tracks.size(); i++)
|
||||
for (unsigned int i = 0; i<m_tracks.size(); i++)
|
||||
{
|
||||
Track* t = track_manager->getTrack(m_tracks[i]);
|
||||
|
||||
@ -166,6 +213,7 @@ bool GrandPrixData::checkConsistency(bool chatty) const
|
||||
return true;
|
||||
} // checkConsistency
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns true if the track is available. This is used to test if Fort Magma
|
||||
* is available (this way FortMagma is not used in the last Grand Prix in
|
||||
@ -182,7 +230,7 @@ bool GrandPrixData::isTrackAvailable(const std::string &id) const
|
||||
void GrandPrixData::getLaps(std::vector<int> *laps) const
|
||||
{
|
||||
laps->clear();
|
||||
for(unsigned int i=0; i< m_tracks.size(); i++)
|
||||
for (unsigned int i = 0; i< m_tracks.size(); i++)
|
||||
if(isTrackAvailable(m_tracks[i]))
|
||||
laps->push_back(m_laps[i]);
|
||||
} // getLaps
|
||||
@ -191,16 +239,129 @@ void GrandPrixData::getLaps(std::vector<int> *laps) const
|
||||
void GrandPrixData::getReverse(std::vector<bool> *reverse) const
|
||||
{
|
||||
reverse->clear();
|
||||
for(unsigned int i=0; i< m_tracks.size(); i++)
|
||||
for (unsigned int i = 0; i< m_tracks.size(); i++)
|
||||
if(isTrackAvailable(m_tracks[i]))
|
||||
reverse->push_back(m_reversed[i]);
|
||||
} // getReverse
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GrandPrixData::isEditable() const
|
||||
{
|
||||
return m_editable;
|
||||
} // isEditable
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
unsigned int GrandPrixData::getNumberOfTracks() const
|
||||
{
|
||||
return m_tracks.size();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
irr::core::stringw GrandPrixData::getTrackName(const unsigned int track) const
|
||||
{
|
||||
assert(track < getNumberOfTracks());
|
||||
Track* t = track_manager->getTrack(m_tracks[track]);
|
||||
assert(t != NULL);
|
||||
return t->getName();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
const std::string& GrandPrixData::getTrackId(const unsigned int track) const
|
||||
{
|
||||
assert(track < getNumberOfTracks());
|
||||
return m_tracks[track];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
unsigned int GrandPrixData::getLaps(const unsigned int track) const
|
||||
{
|
||||
assert(track < getNumberOfTracks());
|
||||
return m_laps[track];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GrandPrixData::getReverse(const unsigned int track) const
|
||||
{
|
||||
assert(track < getNumberOfTracks());
|
||||
return m_reversed[track];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::moveUp(const unsigned int track)
|
||||
{
|
||||
assert (track > 0 && track < getNumberOfTracks());
|
||||
|
||||
std::swap(m_tracks[track], m_tracks[track - 1]);
|
||||
std::swap(m_laps[track], m_laps[track - 1]);
|
||||
m_reversed.swap(m_reversed[track], m_reversed[track - 1]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::moveDown(const unsigned int track)
|
||||
{
|
||||
assert (track < (getNumberOfTracks() - 1));
|
||||
|
||||
std::swap(m_tracks[track], m_tracks[track + 1]);
|
||||
std::swap(m_laps[track], m_laps[track + 1]);
|
||||
m_reversed.swap(m_reversed[track], m_reversed[track + 1]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::addTrack(Track* track, unsigned int laps, bool reverse,
|
||||
int position)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = getNumberOfTracks();
|
||||
assert (track != NULL);
|
||||
assert (laps > 0);
|
||||
assert (position >= -1 && position < n);
|
||||
|
||||
if (position < 0 || position == (n - 1) || m_tracks.empty())
|
||||
{
|
||||
//Append new track to the end of the list
|
||||
m_tracks.push_back(track->getIdent());
|
||||
m_laps.push_back(laps);
|
||||
m_reversed.push_back(reverse);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Insert new track right after the specified position. Caution:
|
||||
//std::vector inserts elements _before_ the specified position
|
||||
m_tracks.insert(m_tracks.begin() + position + 1, track->getIdent());
|
||||
m_laps.insert(m_laps.begin() + position + 1, laps);
|
||||
m_reversed.insert(m_reversed.begin() + position + 1, reverse);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::editTrack(unsigned int t, Track* track,
|
||||
unsigned int laps, bool reverse)
|
||||
{
|
||||
assert (t < getNumberOfTracks());
|
||||
assert (track != NULL);
|
||||
assert (laps > 0);
|
||||
|
||||
m_tracks[t] = track->getIdent();
|
||||
m_laps[t] = laps;
|
||||
m_reversed[t] = reverse;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixData::remove(const unsigned int track)
|
||||
{
|
||||
assert (track < getNumberOfTracks());
|
||||
|
||||
m_tracks.erase(m_tracks.begin() + track);
|
||||
m_laps.erase(m_laps.begin() + track);
|
||||
m_reversed.erase(m_reversed.begin() + track);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
const std::vector<std::string>& GrandPrixData::getTrackNames() const
|
||||
{
|
||||
m_really_available_tracks.clear();
|
||||
for(unsigned int i=0; i< m_tracks.size(); i++)
|
||||
for (unsigned int i = 0; i < m_tracks.size(); i++)
|
||||
{
|
||||
if(isTrackAvailable(m_tracks[i]))
|
||||
m_really_available_tracks.push_back(m_tracks[i]);
|
||||
|
@ -27,7 +27,8 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#include "utils/translation.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
|
||||
class Track;
|
||||
|
||||
/** Simple class that hold the data relevant to a 'grand_prix', aka. a number
|
||||
* of races that has to be completed one after the other
|
||||
@ -65,28 +66,49 @@ private:
|
||||
/** Whether the track in question should be done in reverse mode */
|
||||
std::vector<bool> m_reversed;
|
||||
|
||||
void load_from_file(const std::string fullpath, const std::string filename);
|
||||
/** Wether the user can edit this grand prix or not */
|
||||
bool m_editable;
|
||||
|
||||
bool isTrackAvailable(const std::string &id) const;
|
||||
|
||||
public:
|
||||
|
||||
/** Load the GrandPrixData from the given filename */
|
||||
#if (defined(WIN32) || defined(_WIN32)) && !defined(__MINGW32__)
|
||||
#pragma warning(disable:4290)
|
||||
#endif
|
||||
GrandPrixData () {}; // empty for initialising
|
||||
GrandPrixData(const std::string filename);
|
||||
GrandPrixData (const std::string dir, const std::string filename);
|
||||
GrandPrixData (const std::string& filename) throw(std::logic_error);
|
||||
GrandPrixData () {}; // empty for initialising
|
||||
|
||||
void setId(const std::string& id);
|
||||
void setName(const irr::core::stringw& name);
|
||||
void setFilename(const std::string& filename);
|
||||
void setEditable(const bool editable);
|
||||
void reload();
|
||||
bool writeToFile();
|
||||
|
||||
bool checkConsistency(bool chatty=true) const;
|
||||
bool checkConsistency(bool chatty=true) const;
|
||||
const std::vector<std::string>& getTrackNames() const;
|
||||
void getLaps(std::vector<int> *laps) const;
|
||||
void getReverse(std::vector<bool> *reverse) const;
|
||||
void getLaps(std::vector<int> *laps) const;
|
||||
void getReverse(std::vector<bool> *reverse) const;
|
||||
bool isEditable() const;
|
||||
unsigned int getNumberOfTracks() const;
|
||||
const std::string& getTrackId(const unsigned int track) const;
|
||||
irr::core::stringw getTrackName(const unsigned int track) const;
|
||||
unsigned int getLaps(const unsigned int track) const;
|
||||
bool getReverse(const unsigned int track) const;
|
||||
void moveUp(const unsigned int track);
|
||||
void moveDown(const unsigned int track);
|
||||
void addTrack(Track* track, unsigned int laps,
|
||||
bool reverse, int position=-1);
|
||||
void editTrack(unsigned int t, Track* track,
|
||||
unsigned int laps, bool reverse);
|
||||
void remove(const unsigned int track);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** @return the (potentially translated) user-visible name of the Grand
|
||||
* Prix (apply fribidi as needed) */
|
||||
const irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
|
||||
irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** @return the internal name identifier of the Grand Prix (not translated) */
|
||||
|
@ -18,66 +18,126 @@
|
||||
|
||||
#include "race/grand_prix_manager.hpp"
|
||||
|
||||
#include <set>
|
||||
#include "config/user_config.hpp"
|
||||
#include "grand_prix_data.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
GrandPrixManager *grand_prix_manager = NULL;
|
||||
|
||||
const char* GrandPrixManager::SUFFIX = ".grandprix";
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::loadFiles()
|
||||
{
|
||||
std::set<std::string> dirs;
|
||||
|
||||
//Add all the directories to a set to avoid duplicates
|
||||
dirs.insert(file_manager->getAsset(FileManager::GRANDPRIX, ""));
|
||||
dirs.insert(file_manager->getGPDir());
|
||||
dirs.insert(UserConfigParams::m_additional_gp_directory);
|
||||
|
||||
for (std::set<std::string>::const_iterator it = dirs.begin(); it != dirs.end(); ++it)
|
||||
{
|
||||
std::string dir = *it;
|
||||
if (!dir.empty() && dir[dir.size() - 1] == '/')
|
||||
loadDir(dir);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::loadDir(const std::string& dir)
|
||||
{
|
||||
Log::info("GrandPrixManager", "Loading Grand Prix files from %s", dir.c_str());
|
||||
assert(!dir.empty() && dir[dir.size() - 1] == '/');
|
||||
|
||||
// Findout which grand prixs are available and load them
|
||||
std::set<std::string> result;
|
||||
file_manager->listFiles(result, dir);
|
||||
for(std::set<std::string>::iterator i = result.begin(); i != result.end(); i++)
|
||||
{
|
||||
if (StringUtils::hasSuffix(*i, SUFFIX))
|
||||
load(dir + *i);
|
||||
} // for i
|
||||
} // loadDir
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::load(const std::string& filename)
|
||||
{
|
||||
GrandPrixData* gp;
|
||||
|
||||
try
|
||||
{
|
||||
gp = new GrandPrixData(filename);
|
||||
m_gp_data.push_back(gp);
|
||||
Log::debug("GrandPrixManager", "Grand Prix '%s' loaded from %s",
|
||||
gp->getId().c_str(), filename.c_str());
|
||||
}
|
||||
catch (std::logic_error& er)
|
||||
{
|
||||
Log::error("GrandPrixManager", "Ignoring GP %s (%s)\n",
|
||||
filename.c_str(), er.what());
|
||||
}
|
||||
} // load
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::reload()
|
||||
{
|
||||
for(unsigned int i=0; i<m_gp_data.size(); i++)
|
||||
delete m_gp_data[i];
|
||||
m_gp_data.clear();
|
||||
|
||||
loadFiles();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string GrandPrixManager::generateId()
|
||||
{
|
||||
std::stringstream s;
|
||||
|
||||
do
|
||||
{
|
||||
s.clear();
|
||||
s << "usr_gp_" << ((rand() % 90000000) + 10000000);
|
||||
} while (existsId(s.str()));
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GrandPrixManager::existsId(const std::string& id) const
|
||||
{
|
||||
bool exists;
|
||||
|
||||
exists = false;
|
||||
for (unsigned int i = 0; !exists && i < m_gp_data.size(); i++)
|
||||
exists = (m_gp_data[i]->getId() == id);
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool GrandPrixManager::existsName(const irr::core::stringw& name) const
|
||||
{
|
||||
bool exists;
|
||||
|
||||
exists = false;
|
||||
for (unsigned int i = 0; !exists && i < m_gp_data.size(); i++)
|
||||
exists = (m_gp_data[i]->getName() == name);
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixManager::GrandPrixManager()
|
||||
{
|
||||
// Findout which grand prixs are available and load them
|
||||
// Grand Prix in the standart directory
|
||||
std::set<std::string> result;
|
||||
std::string gp_dir = file_manager->getAsset(FileManager::GRANDPRIX, "");
|
||||
file_manager->listFiles(result, gp_dir);
|
||||
for(std::set<std::string>::iterator i = result.begin();
|
||||
i != result.end() ; i++)
|
||||
{
|
||||
if (StringUtils::hasSuffix(*i, ".grandprix"))
|
||||
{
|
||||
try
|
||||
{
|
||||
m_gp_data.push_back(new GrandPrixData(*i));
|
||||
Log::debug("GrandPrixManager", "Grand Prix %s loaded.",
|
||||
i->c_str());
|
||||
}
|
||||
catch (std::logic_error& e)
|
||||
{
|
||||
Log::error("GrandPrixManager", "Ignoring GP %s ( %s ) \n",
|
||||
i->c_str(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load additional Grand Prix
|
||||
const std::string dir = UserConfigParams::m_additional_gp_directory;
|
||||
if(dir != "") {
|
||||
Log::info("GrandPrixManager", "Loading additional Grand Prix from "
|
||||
"%s ...", dir.c_str());
|
||||
file_manager->listFiles(result, dir);
|
||||
for(std::set<std::string>::iterator i = result.begin();
|
||||
i != result.end() ; i++)
|
||||
{
|
||||
if (StringUtils::hasSuffix(*i, ".grandprix"))
|
||||
{
|
||||
try
|
||||
{
|
||||
m_gp_data.push_back(new GrandPrixData(dir, *i));
|
||||
Log::debug("GrandPrixManager", "Grand Prix %s loaded from "
|
||||
"%s", i->c_str(),
|
||||
dir.c_str());
|
||||
}
|
||||
catch (std::logic_error& e)
|
||||
{
|
||||
Log::error("GrandPrixManager", "Ignoring GP %s ( %s ) \n",
|
||||
i->c_str(), e.what());
|
||||
}
|
||||
}
|
||||
} // end for
|
||||
} // end if
|
||||
loadFiles();
|
||||
} // GrandPrixManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixManager::~GrandPrixManager()
|
||||
{
|
||||
@ -87,15 +147,21 @@ GrandPrixManager::~GrandPrixManager()
|
||||
} // for i
|
||||
|
||||
} // ~GrandPrixManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
const GrandPrixData* GrandPrixManager::getGrandPrix(const std::string& s) const
|
||||
{
|
||||
for(unsigned int i=0; i<m_gp_data.size(); i++)
|
||||
if(m_gp_data[i]->getId() == s)
|
||||
return m_gp_data[i];
|
||||
|
||||
return NULL;
|
||||
return editGrandPrix(s);
|
||||
} // getGrandPrix
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixData* GrandPrixManager::editGrandPrix(const std::string& s) const
|
||||
{
|
||||
for(unsigned int i=0; i<m_gp_data.size(); i++)
|
||||
if(m_gp_data[i]->getId()==s) return m_gp_data[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::checkConsistency()
|
||||
{
|
||||
@ -104,9 +170,64 @@ void GrandPrixManager::checkConsistency()
|
||||
if(!m_gp_data[i]->checkConsistency())
|
||||
{
|
||||
// delete this GP, since a track is missing
|
||||
m_gp_data.erase(m_gp_data.begin()+i);
|
||||
delete *(m_gp_data.erase(m_gp_data.begin()+i));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
} // checkConsistency
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixData* GrandPrixManager::createNew(const irr::core::stringw& newName)
|
||||
{
|
||||
if (existsName(newName))
|
||||
return NULL;
|
||||
|
||||
std::string newID = generateId();
|
||||
|
||||
GrandPrixData* gp = new GrandPrixData;
|
||||
gp->setId(newID);
|
||||
gp->setName(newName);
|
||||
gp->setFilename(file_manager->getGPDir() + newID + SUFFIX);
|
||||
gp->setEditable(true);
|
||||
gp->writeToFile();
|
||||
m_gp_data.push_back(gp);
|
||||
|
||||
return gp;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GrandPrixData* GrandPrixManager::copy(const std::string& id,
|
||||
const irr::core::stringw& newName)
|
||||
{
|
||||
if (existsName(newName))
|
||||
return NULL;
|
||||
|
||||
std::string newID = generateId();
|
||||
|
||||
GrandPrixData* gp = new GrandPrixData(*getGrandPrix(id));
|
||||
gp->setId(newID);
|
||||
gp->setName(newName);
|
||||
gp->setFilename(file_manager->getGPDir() + newID + SUFFIX);
|
||||
gp->setEditable(true);
|
||||
gp->writeToFile();
|
||||
m_gp_data.push_back(gp);
|
||||
|
||||
return gp;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GrandPrixManager::remove(const std::string& id)
|
||||
{
|
||||
const GrandPrixData* gp = getGrandPrix(id);
|
||||
assert(gp != NULL);
|
||||
|
||||
if (gp->isEditable())
|
||||
{
|
||||
file_manager->removeFile(gp->getFilename());
|
||||
reload();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::warn("GrandPrixManager", "Grand Prix '%s' cannot be removed\n", gp->getId().c_str());
|
||||
}
|
||||
}
|
||||
|
@ -30,16 +30,31 @@
|
||||
class GrandPrixManager
|
||||
{
|
||||
private:
|
||||
static const char* SUFFIX;
|
||||
|
||||
void loadFiles();
|
||||
void loadDir(const std::string& dir);
|
||||
void load(const std::string &filename);
|
||||
|
||||
std::string generateId();
|
||||
|
||||
bool existsId(const std::string& id) const;
|
||||
bool existsName(const irr::core::stringw& name) const;
|
||||
|
||||
std::vector<GrandPrixData*> m_gp_data;
|
||||
public:
|
||||
GrandPrixManager();
|
||||
~GrandPrixManager();
|
||||
void load(const std::string &filename);
|
||||
const GrandPrixData* getGrandPrix(int i) const { return m_gp_data[i]; }
|
||||
void reload();
|
||||
const GrandPrixData* getGrandPrix(const int i) const { return m_gp_data[i]; }
|
||||
const GrandPrixData* getGrandPrix(const std::string& s) const;
|
||||
GrandPrixData* editGrandPrix(const std::string& s) const;
|
||||
unsigned int getNumberOfGrandPrix() const { return m_gp_data.size(); }
|
||||
void checkConsistency();
|
||||
|
||||
GrandPrixData* createNew(const irr::core::stringw& newName);
|
||||
GrandPrixData* copy(const std::string& id, const irr::core::stringw& newName);
|
||||
void remove(const std::string& id);
|
||||
}; // GrandPrixManager
|
||||
|
||||
extern GrandPrixManager *grand_prix_manager;
|
||||
|
137
src/states_screens/dialogs/enter_gp_name_dialog.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014 Marc Coll
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "states_screens/dialogs/enter_gp_name_dialog.hpp"
|
||||
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/widgets/button_widget.hpp"
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "guiengine/widgets/text_box_widget.hpp"
|
||||
#include "race/grand_prix_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include <IGUIEnvironment.h>
|
||||
|
||||
|
||||
using namespace GUIEngine;
|
||||
using namespace irr::core;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
EnterGPNameDialog::EnterGPNameDialog(INewGPListener* listener,
|
||||
const float w, const float h)
|
||||
: ModalDialog(w, h), m_listener(listener), m_self_destroy(false)
|
||||
{
|
||||
assert(listener != NULL);
|
||||
loadFromFile("enter_gp_name_dialog.stkgui");
|
||||
|
||||
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
|
||||
assert(textCtrl != NULL);
|
||||
textCtrl->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
EnterGPNameDialog::~EnterGPNameDialog()
|
||||
{
|
||||
// FIXME: what is this code for?
|
||||
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
|
||||
textCtrl->getIrrlichtElement()->remove();
|
||||
textCtrl->clearListeners();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
GUIEngine::EventPropagation EnterGPNameDialog::processEvent(const std::string& eventSource)
|
||||
{
|
||||
if (eventSource == "cancel")
|
||||
{
|
||||
dismiss();
|
||||
return GUIEngine::EVENT_BLOCK;
|
||||
}
|
||||
return GUIEngine::EVENT_LET;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EnterGPNameDialog::onEnterPressedInternal()
|
||||
{
|
||||
//Cancel button pressed
|
||||
ButtonWidget* cancelButton = getWidget<ButtonWidget>("cancel");
|
||||
if (GUIEngine::isFocusedForPlayer(cancelButton, PLAYER_ID_GAME_MASTER))
|
||||
{
|
||||
std::string fakeEvent = "cancel";
|
||||
processEvent(fakeEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
//Otherwise, see if we can accept the new name
|
||||
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
|
||||
assert(textCtrl != NULL);
|
||||
stringw name = textCtrl->getText().trim();
|
||||
if (name.size() > 0)
|
||||
{
|
||||
// check for duplicate names
|
||||
for (int i = 0; i < grand_prix_manager->getNumberOfGrandPrix(); i++)
|
||||
{
|
||||
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(i);
|
||||
if (gp->getName() == name)
|
||||
{
|
||||
LabelWidget* label = getWidget<LabelWidget>("title");
|
||||
assert(label != NULL);
|
||||
label->setText(_("Another grand prix with this name already exists."), false);
|
||||
sfx_manager->quickSound("anvil");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// It's unsafe to delete from inside the event handler so we do it
|
||||
// in onUpdate (which checks for m_self_destroy)
|
||||
m_self_destroy = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LabelWidget* label = getWidget<LabelWidget>("title");
|
||||
assert(label != NULL);
|
||||
label->setText(_("Cannot add a grand prix with this name"), false);
|
||||
sfx_manager->quickSound("anvil");
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EnterGPNameDialog::onUpdate(float dt)
|
||||
{
|
||||
// It's unsafe to delete from inside the event handler so we do it here
|
||||
if (m_self_destroy)
|
||||
{
|
||||
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
|
||||
stringw name = textCtrl->getText().trim();
|
||||
|
||||
// irrLicht is too stupid to remove focus from deleted widgets
|
||||
// so do it by hand
|
||||
GUIEngine::getGUIEnv()->removeFocus( textCtrl->getIrrlichtElement() );
|
||||
GUIEngine::getGUIEnv()->removeFocus( m_irrlicht_window );
|
||||
|
||||
// we will destroy the dialog before notifying the listener to be safer.
|
||||
// but in order not to crash we must make a local copy of the listern
|
||||
// otherwise we will crash
|
||||
INewGPListener* listener = m_listener;
|
||||
|
||||
ModalDialog::dismiss();
|
||||
|
||||
if (listener != NULL)
|
||||
listener->onNewGPWithName(name);
|
||||
}
|
||||
}
|
70
src/states_screens/dialogs/enter_gp_name_dialog.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014 Marc Coll
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
#ifndef HEADER_ENTER_GP_NAME_DIALOG_HPP
|
||||
#define HEADER_ENTER_GP_NAME_DIALOG_HPP
|
||||
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
|
||||
#include <irrString.h>
|
||||
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
class TextBoxWidget;
|
||||
class ButtonWidget;
|
||||
class LabelWidget;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Dialog that allows the player to enter the name for a new grand prix
|
||||
* \ingroup states_screens
|
||||
*/
|
||||
class EnterGPNameDialog : public GUIEngine::ModalDialog
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
class INewGPListener
|
||||
{
|
||||
public:
|
||||
virtual void onNewGPWithName(const irr::core::stringw& newName) = 0;
|
||||
virtual ~INewGPListener(){}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
INewGPListener* m_listener;
|
||||
bool m_self_destroy;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates a modal dialog with given percentage of screen width and height
|
||||
*/
|
||||
EnterGPNameDialog(INewGPListener* listener, const float percentWidth,
|
||||
const float percentHeight);
|
||||
~EnterGPNameDialog();
|
||||
|
||||
void onEnterPressedInternal();
|
||||
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
|
||||
|
||||
virtual void onUpdate(float dt);
|
||||
};
|
||||
|
||||
#endif
|
@ -278,6 +278,24 @@ void UserInfoDialog::declineFriendRequest()
|
||||
|
||||
} // declineFriendRequest
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Removes an existing friend.
|
||||
*/
|
||||
void UserInfoDialog::removeExistingFriend()
|
||||
{
|
||||
CurrentUser::get()->requestRemoveFriend(m_profile->getID());
|
||||
|
||||
} // removeExistingFriend
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Removes a pending friend request.
|
||||
*/
|
||||
void UserInfoDialog::removePendingFriend()
|
||||
{
|
||||
CurrentUser::get()->requestCancelFriend(m_profile->getID());
|
||||
|
||||
} // removePendingFriend
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
GUIEngine::EventPropagation UserInfoDialog::processEvent(const std::string& eventSource)
|
||||
{
|
||||
@ -304,10 +322,12 @@ GUIEngine::EventPropagation UserInfoDialog::processEvent(const std::string& even
|
||||
}
|
||||
else if(selection == m_remove_widget->m_properties[PROP_ID])
|
||||
{
|
||||
if(m_profile->getRelationInfo()->isPending())
|
||||
CurrentUser::get()->requestCancelFriend(m_profile->getID());
|
||||
if (m_profile->getRelationInfo() &&
|
||||
m_profile->getRelationInfo()->isPending() )
|
||||
removePendingFriend();
|
||||
else
|
||||
CurrentUser::get()->requestRemoveFriend(m_profile->getID());
|
||||
removeExistingFriend();
|
||||
|
||||
m_processing = true;
|
||||
m_options_widget->setDeactivated();
|
||||
return GUIEngine::EVENT_BLOCK;
|
||||
|
@ -63,6 +63,8 @@ private:
|
||||
void sendFriendRequest();
|
||||
void acceptFriendRequest();
|
||||
void declineFriendRequest();
|
||||
void removeExistingFriend();
|
||||
void removePendingFriend();
|
||||
|
||||
public:
|
||||
UserInfoDialog(uint32_t showing_id, const core::stringw info = "", bool error = false, bool from_queue = false);
|
||||
|
334
src/states_screens/edit_gp_screen.cpp
Normal file
@ -0,0 +1,334 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014 Marc Coll
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "states_screens/edit_gp_screen.hpp"
|
||||
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "guiengine/CGUISpriteBank.h"
|
||||
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
|
||||
#include "guiengine/widgets/icon_button_widget.hpp"
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "guiengine/widgets/list_widget.hpp"
|
||||
#include "race/grand_prix_data.hpp"
|
||||
#include "states_screens/edit_track_screen.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
|
||||
|
||||
using namespace GUIEngine;
|
||||
|
||||
DEFINE_SCREEN_SINGLETON( EditGPScreen );
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
EditGPScreen::EditGPScreen()
|
||||
: Screen("gpedit.stkgui"), m_gp(NULL), m_list(NULL), m_icon_bank(NULL),
|
||||
m_selected(-1), m_modified(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
EditGPScreen::~EditGPScreen()
|
||||
{
|
||||
delete m_icon_bank;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::setSelectedGP(GrandPrixData* gp)
|
||||
{
|
||||
assert(gp != NULL);
|
||||
m_gp = gp;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::loadedFromFile()
|
||||
{
|
||||
if (m_icon_bank == NULL)
|
||||
m_icon_bank = new irr::gui::STKModifiedSpriteBank(GUIEngine::getGUIEnv());
|
||||
|
||||
m_list = getWidget<ListWidget>("tracks");
|
||||
assert(m_list != NULL);
|
||||
m_list->addColumn(_("Track"), 3);
|
||||
m_list->addColumn(_("Laps"), 1);
|
||||
m_list->addColumn(_("Reversed"), 1);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::eventCallback(GUIEngine::Widget* widget, const std::string& name,
|
||||
const int playerID)
|
||||
{
|
||||
setSelected(m_list->getSelectionID());
|
||||
|
||||
if (name == "tracks")
|
||||
{
|
||||
m_action = "edit";
|
||||
edit();
|
||||
}
|
||||
else if (name == "menu")
|
||||
{
|
||||
RibbonWidget* menu = getWidget<RibbonWidget>("menu");
|
||||
assert(menu != NULL);
|
||||
m_action = menu->getSelectionIDString(PLAYER_ID_GAME_MASTER);
|
||||
|
||||
if (m_action == "up")
|
||||
{
|
||||
if (canMoveUp())
|
||||
{
|
||||
m_gp->moveUp(m_selected--);
|
||||
loadList(m_selected);
|
||||
setModified(true);
|
||||
}
|
||||
}
|
||||
else if (m_action == "down")
|
||||
{
|
||||
if (canMoveDown())
|
||||
{
|
||||
m_gp->moveDown(m_selected++);
|
||||
loadList(m_selected);
|
||||
setModified(true);
|
||||
}
|
||||
}
|
||||
else if (m_action == "add" || m_action == "edit")
|
||||
{
|
||||
if (m_action == "edit")
|
||||
{
|
||||
edit();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditTrackScreen* edit = EditTrackScreen::getInstance();
|
||||
assert(edit != NULL);
|
||||
//By default, 3 laps and no reversing
|
||||
edit->setSelection(NULL, 3, false);
|
||||
StateManager::get()->pushScreen(edit);
|
||||
}
|
||||
}
|
||||
else if (m_action == "remove")
|
||||
{
|
||||
if (m_selected >= 0 && m_selected < m_list->getItemCount())
|
||||
{
|
||||
new MessageDialog(
|
||||
_("Are you sure you want to remove '%s'?",
|
||||
m_gp->getTrackName(m_selected).c_str()),
|
||||
MessageDialog::MESSAGE_DIALOG_CONFIRM,
|
||||
this, false);
|
||||
}
|
||||
}
|
||||
else if (m_action == "save")
|
||||
{
|
||||
save();
|
||||
}
|
||||
}
|
||||
else if (name == "back")
|
||||
{
|
||||
if (m_modified)
|
||||
{
|
||||
m_action = "back";
|
||||
new MessageDialog(
|
||||
_("Do you want to save your changes?"),
|
||||
MessageDialog::MESSAGE_DIALOG_CONFIRM,
|
||||
this, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::init()
|
||||
{
|
||||
if (m_action.empty())
|
||||
{
|
||||
LabelWidget* header = getWidget<LabelWidget>("title");
|
||||
assert(header != NULL);
|
||||
header->setText(m_gp->getName(), true);
|
||||
|
||||
IconButtonWidget* button = getWidget<IconButtonWidget>("save");
|
||||
assert(button != NULL);
|
||||
button->setDeactivated();
|
||||
|
||||
loadList(0);
|
||||
setModified(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditTrackScreen* edit = EditTrackScreen::getInstance();
|
||||
assert(edit != NULL);
|
||||
|
||||
if (edit->getResult())
|
||||
{
|
||||
if (m_action == "add")
|
||||
{
|
||||
m_gp->addTrack(edit->getTrack(), edit->getLaps(), edit->getReverse(),
|
||||
m_selected);
|
||||
setSelected(m_selected + 1);
|
||||
}
|
||||
else if (m_action == "edit")
|
||||
{
|
||||
m_gp->editTrack(m_selected, edit->getTrack(), edit->getLaps(),
|
||||
edit->getReverse());
|
||||
}
|
||||
setModified(true);
|
||||
}
|
||||
loadList(m_selected);
|
||||
m_action.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::onConfirm()
|
||||
{
|
||||
ModalDialog::dismiss();
|
||||
if (m_action == "remove")
|
||||
{
|
||||
m_gp->remove(m_selected);
|
||||
setSelected(m_selected >= m_gp->getNumberOfTracks() ?
|
||||
m_gp->getNumberOfTracks() - 1 : m_selected);
|
||||
loadList(m_selected);
|
||||
setModified(true);
|
||||
}
|
||||
else if (m_action == "back")
|
||||
{
|
||||
save();
|
||||
back();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::onCancel()
|
||||
{
|
||||
ModalDialog::dismiss();
|
||||
if (m_action == "back")
|
||||
back();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::loadList(const int selected)
|
||||
{
|
||||
m_list->clear();
|
||||
m_icons.clear();
|
||||
m_icon_bank->clear();
|
||||
m_icon_bank->scaleToHeight (64);
|
||||
m_list->setIcons(m_icon_bank, 64);
|
||||
|
||||
for (unsigned int i = 0; i < m_gp->getNumberOfTracks(); i++)
|
||||
{
|
||||
std::vector<GUIEngine::ListWidget::ListCell> row;
|
||||
|
||||
Track* t = track_manager->getTrack(m_gp->getTrackId(i));
|
||||
assert(t != NULL);
|
||||
video::ITexture* screenShot = irr_driver->getTexture(t->getScreenshotFile());
|
||||
assert(screenShot != NULL);
|
||||
m_icons.push_back(m_icon_bank->addTextureAsSprite(screenShot));
|
||||
|
||||
row.push_back(GUIEngine::ListWidget::ListCell(
|
||||
_LTR(m_gp->getTrackName(i).c_str()), m_icons[i], 3, false));
|
||||
row.push_back(GUIEngine::ListWidget::ListCell(
|
||||
StringUtils::toWString<unsigned int>(m_gp->getLaps(i)), -1, 1, true));
|
||||
row.push_back(GUIEngine::ListWidget::ListCell(
|
||||
m_gp->getReverse(i) ? _("Yes") : _("No"), -1, 1, true));
|
||||
|
||||
m_list->addItem(m_gp->getId(), row);
|
||||
}
|
||||
m_list->setIcons(m_icon_bank);
|
||||
|
||||
if (selected < m_list->getItemCount())
|
||||
{
|
||||
m_list->setSelectionID(selected);
|
||||
setSelected(selected);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::setModified(const bool modified)
|
||||
{
|
||||
m_modified = modified;
|
||||
|
||||
IconButtonWidget* save_button = getWidget<IconButtonWidget>("save");
|
||||
assert(save_button != NULL);
|
||||
if (modified)
|
||||
save_button->setActivated();
|
||||
else
|
||||
save_button->setDeactivated();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::setSelected(const int selected)
|
||||
{
|
||||
IconButtonWidget* button_up = getWidget<IconButtonWidget>("up");
|
||||
assert(button_up != NULL);
|
||||
IconButtonWidget* button_down = getWidget<IconButtonWidget>("down");
|
||||
assert(button_down != NULL);
|
||||
|
||||
m_selected = selected;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::edit()
|
||||
{
|
||||
EditTrackScreen* edit_screen = EditTrackScreen::getInstance();
|
||||
assert(edit_screen != NULL);
|
||||
|
||||
if (m_selected >= 0 && m_selected < m_list->getItemCount())
|
||||
{
|
||||
edit_screen->setSelection(track_manager->getTrack(
|
||||
m_gp->getTrackId(m_selected)),
|
||||
m_gp->getLaps(m_selected),
|
||||
m_gp->getReverse(m_selected));
|
||||
StateManager::get()->pushScreen(edit_screen);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool EditGPScreen::save()
|
||||
{
|
||||
if (m_gp->writeToFile())
|
||||
{
|
||||
setModified(false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
new MessageDialog(
|
||||
_("An error occurred while trying to save your grand prix"),
|
||||
MessageDialog::MESSAGE_DIALOG_OK, NULL, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditGPScreen::back ()
|
||||
{
|
||||
m_action.clear();
|
||||
m_modified = false;
|
||||
StateManager::get()->popMenu();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool EditGPScreen::canMoveUp() const
|
||||
{
|
||||
return (m_selected > 0 && m_selected < m_list->getItemCount());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool EditGPScreen::canMoveDown() const
|
||||
{
|
||||
return (m_selected >= 0 && m_selected < (m_list->getItemCount() - 1));
|
||||
}
|
85
src/states_screens/edit_gp_screen.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014 Marc Coll
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_EDIT_GP_SCREEN_HPP
|
||||
#define HEADER_EDIT_GP_SCREEN_HPP
|
||||
|
||||
#include "guiengine/screen.hpp"
|
||||
#include "guiengine/widgets/list_widget.hpp"
|
||||
#include "states_screens/dialogs/message_dialog.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace GUIEngine { class Widget; }
|
||||
namespace irr { namespace gui { class STKModifiedSpriteBank; } }
|
||||
|
||||
class GrandPrixData;
|
||||
|
||||
/**
|
||||
* \brief screen where the user can edit a grand prix
|
||||
* \ingroup states_screens
|
||||
*/
|
||||
class EditGPScreen :
|
||||
public GUIEngine::Screen,
|
||||
public GUIEngine::ScreenSingleton<EditGPScreen>,
|
||||
public MessageDialog::IConfirmDialogListener
|
||||
{
|
||||
friend class GUIEngine::ScreenSingleton<EditGPScreen>;
|
||||
|
||||
EditGPScreen();
|
||||
|
||||
void onConfirm();
|
||||
void onCancel();
|
||||
|
||||
void loadList(const int selected);
|
||||
void setModified(const bool modified);
|
||||
void setSelected(const int selected);
|
||||
void edit();
|
||||
bool save();
|
||||
void back();
|
||||
|
||||
bool canMoveUp() const;
|
||||
bool canMoveDown() const;
|
||||
|
||||
GrandPrixData* m_gp;
|
||||
GUIEngine::ListWidget* m_list;
|
||||
irr::gui::STKModifiedSpriteBank* m_icon_bank;
|
||||
std::vector<int> m_icons;
|
||||
int m_selected;
|
||||
bool m_modified;
|
||||
|
||||
std::string m_action;
|
||||
|
||||
public:
|
||||
|
||||
~EditGPScreen();
|
||||
|
||||
void setSelectedGP(GrandPrixData* gp);
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void loadedFromFile() OVERRIDE;
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name,
|
||||
const int playerID) OVERRIDE;
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void init() OVERRIDE;
|
||||
};
|
||||
|
||||
#endif
|
240
src/states_screens/edit_track_screen.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014 Marc Coll
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "states_screens/edit_track_screen.hpp"
|
||||
|
||||
#include "guiengine/widgets/button_widget.hpp"
|
||||
#include "guiengine/widgets/check_box_widget.hpp"
|
||||
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
|
||||
#include "guiengine/widgets/label_widget.hpp"
|
||||
#include "guiengine/widgets/ribbon_widget.hpp"
|
||||
#include "guiengine/widgets/spinner_widget.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
|
||||
|
||||
using namespace GUIEngine;
|
||||
using namespace irr::core;
|
||||
|
||||
const char* EditTrackScreen::ALL_TRACKS_GROUP_ID = "all";
|
||||
|
||||
DEFINE_SCREEN_SINGLETON( EditTrackScreen );
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
EditTrackScreen::EditTrackScreen()
|
||||
: Screen("edit_track.stkgui"), m_track_group(ALL_TRACKS_GROUP_ID),
|
||||
m_track(NULL), m_laps(0), m_reverse(false), m_result(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
EditTrackScreen::~EditTrackScreen()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditTrackScreen::setSelection(Track* track, unsigned int laps, bool reverse)
|
||||
{
|
||||
assert(laps > 0);
|
||||
m_track = track;
|
||||
m_laps = laps;
|
||||
m_reverse = reverse;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
Track* EditTrackScreen::getTrack() const
|
||||
{
|
||||
return m_track;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
unsigned int EditTrackScreen::getLaps() const
|
||||
{
|
||||
return m_laps;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool EditTrackScreen::getReverse() const
|
||||
{
|
||||
return m_reverse;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool EditTrackScreen::getResult() const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditTrackScreen::loadedFromFile()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditTrackScreen::eventCallback(GUIEngine::Widget* widget, const std::string& name,
|
||||
const int playerID)
|
||||
{
|
||||
if (name == "ok")
|
||||
{
|
||||
m_result = true;
|
||||
StateManager::get()->popMenu();
|
||||
}
|
||||
else if (name == "cancel")
|
||||
{
|
||||
m_result = false;
|
||||
StateManager::get()->popMenu();
|
||||
}
|
||||
else if (name == "tracks")
|
||||
{
|
||||
DynamicRibbonWidget* tracks = getWidget<DynamicRibbonWidget>("tracks");
|
||||
assert(tracks != NULL);
|
||||
selectTrack(tracks->getSelectionIDString(PLAYER_ID_GAME_MASTER));
|
||||
}
|
||||
else if (name == "trackgroups")
|
||||
{
|
||||
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
|
||||
assert(tabs != NULL);
|
||||
m_track_group = tabs->getSelectionIDString(PLAYER_ID_GAME_MASTER);
|
||||
loadTrackList();
|
||||
}
|
||||
else if (name == "laps")
|
||||
{
|
||||
SpinnerWidget* laps = getWidget<SpinnerWidget>("laps");
|
||||
assert(laps != NULL);
|
||||
m_laps = laps->getValue();
|
||||
}
|
||||
else if (name == "reverse")
|
||||
{
|
||||
CheckBoxWidget* reverse = getWidget<CheckBoxWidget>("reverse");
|
||||
assert(reverse != NULL);
|
||||
m_reverse = reverse->getState();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditTrackScreen::beforeAddingWidget()
|
||||
{
|
||||
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
|
||||
assert (tabs != NULL);
|
||||
|
||||
tabs->clearAllChildren();
|
||||
|
||||
const std::vector<std::string>& groups = track_manager->getAllTrackGroups();
|
||||
if (groups.size() > 1)
|
||||
{
|
||||
tabs->addTextChild(_("All"), ALL_TRACKS_GROUP_ID);
|
||||
for (unsigned int i = 0; i < groups.size(); i++)
|
||||
tabs->addTextChild(_(groups[i].c_str()), groups[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditTrackScreen::init()
|
||||
{
|
||||
RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
|
||||
assert (tabs != NULL);
|
||||
SpinnerWidget* laps = getWidget<SpinnerWidget>("laps");
|
||||
assert(laps != NULL);
|
||||
CheckBoxWidget* reverse = getWidget<CheckBoxWidget>("reverse");
|
||||
assert(reverse != NULL);
|
||||
|
||||
if (m_track_group.empty())
|
||||
tabs->select (ALL_TRACKS_GROUP_ID, PLAYER_ID_GAME_MASTER);
|
||||
else
|
||||
tabs->select (m_track_group, PLAYER_ID_GAME_MASTER);
|
||||
laps->setValue(m_laps);
|
||||
reverse->setState(m_reverse);
|
||||
|
||||
loadTrackList();
|
||||
if (m_track == NULL)
|
||||
selectTrack("");
|
||||
else
|
||||
selectTrack(m_track->getIdent());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditTrackScreen::loadTrackList()
|
||||
{
|
||||
bool belongsToGroup;
|
||||
|
||||
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
|
||||
assert(tracks_widget != NULL);
|
||||
|
||||
tracks_widget->clearItems();
|
||||
|
||||
for (unsigned int i = 0; i < track_manager->getNumberOfTracks(); i++)
|
||||
{
|
||||
Track* t = track_manager->getTrack(i);
|
||||
const std::vector<std::string>& groups = t->getGroups();
|
||||
belongsToGroup = (m_track_group.empty() || m_track_group == ALL_TRACKS_GROUP_ID ||
|
||||
std::find(groups.begin(), groups.end(), m_track_group) != groups.end());
|
||||
if (!t->isArena() && !t->isSoccer() && !t->isInternal() && belongsToGroup)
|
||||
{
|
||||
tracks_widget->addItem(translations->fribidize(t->getName()), t->getIdent(),
|
||||
t->getScreenshotFile(), 0, IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE );
|
||||
}
|
||||
}
|
||||
|
||||
tracks_widget->updateItemDisplay();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void EditTrackScreen::selectTrack(const std::string& id)
|
||||
{
|
||||
DynamicRibbonWidget* tracks = getWidget<DynamicRibbonWidget>("tracks");
|
||||
assert(tracks != NULL);
|
||||
LabelWidget* selected_track = getWidget<LabelWidget>("selected_track");
|
||||
assert(selected_track != NULL);
|
||||
SpinnerWidget* laps = getWidget<SpinnerWidget>("laps");
|
||||
assert(laps != NULL);
|
||||
LabelWidget* label_reverse = getWidget<LabelWidget>("reverse_label");
|
||||
assert(label_reverse != NULL);
|
||||
CheckBoxWidget* reverse = getWidget<CheckBoxWidget>("reverse");
|
||||
assert(reverse != NULL);
|
||||
ButtonWidget* ok_button = getWidget<ButtonWidget>("ok");
|
||||
assert(ok_button != NULL);
|
||||
|
||||
m_track = track_manager->getTrack(id);
|
||||
if (m_track != NULL)
|
||||
{
|
||||
tracks->setSelection(m_track->getIdent(), PLAYER_ID_GAME_MASTER, true);
|
||||
selected_track->setText(m_track->getName(), true);
|
||||
|
||||
laps->setValue(m_laps);
|
||||
|
||||
reverse->setVisible(m_track->reverseAvailable());
|
||||
label_reverse->setVisible(m_track->reverseAvailable());
|
||||
|
||||
ok_button->setActivated();
|
||||
}
|
||||
else
|
||||
{
|
||||
tracks->setSelection("", PLAYER_ID_GAME_MASTER, true);
|
||||
selected_track->setText(_("Select a track"), true);
|
||||
|
||||
laps->setValue(3);
|
||||
|
||||
reverse->setVisible(true);
|
||||
reverse->setState(false);
|
||||
|
||||
ok_button->setDeactivated();
|
||||
}
|
||||
}
|