Merge branch 'master' into improve-xbox-gamepad-support

This commit is contained in:
hiker 2017-08-14 10:05:26 +10:00
commit 5a2b92d79d
35 changed files with 380 additions and 242 deletions

View File

@ -10,6 +10,7 @@
* Hardware skinning
* New smoother camera by Auria
* New grand prix win scene
* Gamepad configuration bugfixes
* Various improvements (wall driving fixes, parachutes, GP points, cannon fixes, colorization shader)
## SuperTuxKart 0.9.2

View File

@ -10,7 +10,7 @@ SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++-posix)
SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
# figure out folder to look in
execute_process(COMMAND sh -c "ls /usr/lib/gcc/x86_64-w64-mingw32/ | grep posix | tr -d '\n'" OUTPUT_VARIABLE MINGW_DEPS_FOLDER)
execute_process(COMMAND sh -c "ls /usr/lib/gcc/i686-w64-mingw32/ | grep posix | tr -d '\n'" OUTPUT_VARIABLE MINGW_DEPS_FOLDER)
# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32 /usr/lib/gcc/i686-w64-mingw32/${MINGW_DEPS_FOLDER}/ ${PROJECT_SOURCE_DIR}/dependencies)

View File

@ -1,10 +1,12 @@
uniform sampler2D tex;
in vec2 uv;
in vec4 vertex_color;
out vec4 FragColor;
void main(void)
{
vec4 color = texture(tex, uv);
color *= vertex_color;
FragColor = vec4(color.a * color.rgb, color.a);
}

View File

@ -1,4 +1,4 @@
uniform mat4 ModelViewMatrix;
uniform mat4 color_matrix;
uniform vec3 Position;
uniform vec2 Size;
@ -11,10 +11,12 @@ in vec2 Texcoord;
#endif
out vec2 uv;
out vec4 vertex_color;
void main(void)
{
uv = Texcoord;
vec4 Center = ModelViewMatrix * vec4(Position, 1.);
vec4 Center = ViewMatrix * vec4(Position, 1.);
gl_Position = ProjectionMatrix * (Center + vec4(Size * Corner, 0., 0.));
vertex_color = color_matrix[gl_VertexID];
}

View File

@ -20,7 +20,7 @@ out vec2 uv;
void main()
{
vec3 test = sin(windDir * (Position.y* 0.5)) * 0.5;
vec3 test = sin(windDir * (Position.y * 0.1)) * 1.;
test += cos(windDir) * 0.7;
mat4 new_model_matrix = ModelMatrix;

View File

@ -1,11 +1,9 @@
#ifdef Use_Bindless_Texture
layout(bindless_sampler) uniform sampler2D Albedo;
layout(bindless_sampler) uniform sampler2D dtex;
layout(bindless_sampler) uniform sampler2D SpecMap;
layout(bindless_sampler) uniform sampler2D colorization_mask;
#else
uniform sampler2D Albedo;
uniform sampler2D dtex;
uniform sampler2D SpecMap;
uniform sampler2D colorization_mask;
#endif
@ -36,25 +34,8 @@ void main(void)
vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(color_change.x, max(old_hsv.y, color_change.y)), vec2(mask_step, mask_step));
color.xyz = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
}
vec2 texc = gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
vec4 xpos = 2.0 * vec4(texc, z, 1.0) - 1.0f;
xpos = InverseProjectionMatrix * xpos;
xpos /= xpos.w;
vec3 eyedir = normalize(xpos.xyz);
// Inspired from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch16.html
vec3 L = normalize((transpose(InverseViewMatrix) * vec4(sun_direction, 0.)).xyz);
float fEdotL = clamp(dot(L, eyedir), 0., 1.);
float fPowEdotL = pow(fEdotL, 4.);
float fLdotNBack = max(0., - dot(nor, L) * 0.6 + 0.4);
float scattering = mix(fPowEdotL, fLdotNBack, .5);
float specmap = texture(SpecMap, uv).g;
float emitmap = texture(SpecMap, uv).b;
vec3 LightFactor = color.xyz * (scattering * 0.1) + getLightFactor(color.xyz, vec3(1.), specmap, emitmap);
vec3 LightFactor = getLightFactor(color.xyz, vec3(1.), specmap, emitmap);
FragColor = vec4(LightFactor, 1.);
}

View File

@ -41,7 +41,7 @@ flat out sampler2D thirdhandle;
void main()
{
vec3 test = sin(windDir * (Position.y* 0.5)) * 0.5;
vec3 test = sin(windDir * (Position.y * 0.1)) * 1.;
test += cos(windDir) * 0.7;
mat4 ModelMatrix = getWorldMatrix(Origin + test * Color.r, Orientation, Scale);
mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin + test * Color.r, Orientation, Scale) * InverseViewMatrix);

View File

@ -1,9 +1,6 @@
#ifdef Use_Bindless_Texture
layout(bindless_sampler) uniform sampler2D dtex;
#else
#ifndef Use_Bindless_Texture
uniform sampler2D Albedo;
uniform sampler2D SpecMap;
uniform sampler2D dtex;
uniform sampler2D colorization_mask;
#endif
@ -45,24 +42,6 @@ void main(void)
vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(color_change.x, max(old_hsv.y, color_change.y)), vec2(mask_step, mask_step));
color.xyz = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
}
vec2 texc = gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
vec4 xpos = 2.0 * vec4(texc, z, 1.0) - 1.0f;
xpos = InverseProjectionMatrix * xpos;
xpos /= xpos.w;
vec3 eyedir = normalize(xpos.xyz);
// Inspired from http://http.developer.nvidia.com/GPUGems3/gpugems3_ch16.html
vec3 L = normalize((transpose(InverseViewMatrix) * vec4(sun_direction, 0.)).xyz);
float fEdotL = clamp(dot(L, eyedir), 0., 1.);
float fPowEdotL = pow(fEdotL, 4.);
float fLdotNBack = max(0., - dot(nor, L) * 0.6 + 0.4);
float scattering = mix(fPowEdotL, fLdotNBack, .5);
vec3 LightFactor = color.xyz * (scattering * 0.1) + getLightFactor(color.xyz, vec3(1.), specmap, emitmap);
vec3 LightFactor = getLightFactor(color.xyz, vec3(1.), specmap, emitmap);
FragColor = vec4(LightFactor, 1.);
}

View File

@ -177,8 +177,9 @@ namespace scene
\param newManager An optional new scene manager.
\return The newly created clone of this node. */
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) = 0;
virtual void setFrameLoopOnce(s32 begin, s32 end) = 0;
virtual u32 getAnimationSetNum() = 0;
virtual s32 getAnimationSet() const = 0;
virtual void addAnimationSet(u32 start, u32 end) = 0;
virtual void useAnimationSet(u32 set_num) = 0;
};

View File

@ -1002,5 +1002,60 @@ void CAnimatedMeshSceneNode::useAnimationSet(u32 set_num)
setFrameLoop(m_animation_set[set_num * 2], m_animation_set[set_num * 2 + 1]);
}
void CAnimatedMeshSceneNode::setFrameLoopOnce(s32 begin, s32 end)
{
if (LoopCallBack != NULL || !Looping)
{
return;
}
Looping = false;
class MiniLoopSetter : public IAnimationEndCallBack
{
private:
int m_old_start, m_old_end, m_new_start, m_new_end;
bool m_run_cb;
public:
MiniLoopSetter(int old_start, int old_end, int new_start, int new_end)
: m_old_start(old_start), m_old_end(old_end),
m_new_start(new_start), m_new_end(new_end), m_run_cb(false) {}
virtual void OnAnimationEnd(IAnimatedMeshSceneNode* node)
{
if (!m_run_cb)
{
m_run_cb = true;
node->setFrameLoop(m_new_start, m_new_end);
return;
}
if (m_run_cb)
{
node->setFrameLoop(m_old_start, m_old_end);
node->setLoopMode(true);
node->setAnimationEndCallback(NULL);
return;
}
}
};
MiniLoopSetter* mls = new MiniLoopSetter(StartFrame, EndFrame,
begin, end);
setAnimationEndCallback(mls);
mls->drop();
}
s32 CAnimatedMeshSceneNode::getAnimationSet() const
{
for (u32 i = 0; i < m_animation_set.size(); i += 2)
{
if (m_animation_set[i] == (u32)StartFrame &&
m_animation_set[i + 1] == (u32)EndFrame)
{
return (s32)(i >> 1);
}
}
return -1;
}
} // end namespace scene
} // end namespace irr

View File

@ -161,13 +161,14 @@ namespace scene
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
virtual u32 getAnimationSetNum() { return m_animation_set.size() / 2; }
virtual s32 getAnimationSet() const;
virtual void addAnimationSet(u32 start, u32 end)
{
m_animation_set.push_back(start);
m_animation_set.push_back(end);
}
virtual void useAnimationSet(u32 set_num);
virtual void setFrameLoopOnce(s32 begin, s32 end);
protected:
//! Get a static mesh for the current frame of this animated mesh

View File

@ -1218,6 +1218,9 @@ bool CIrrDeviceLinux::createInputContext()
return false;
}
// It's showed as memory leak, but we shouldn't delete it. From the xlib
// documentation: "The returned modifiers string is owned by Xlib and
// should not be modified or freed by the client."
char* p = XSetLocaleModifiers("");
if (p == NULL)
{

View File

@ -537,6 +537,7 @@ public:
device->m_seat = static_cast<wl_seat*>(wl_registry_bind(registry,
name, &wl_seat_interface,
version < 4 ? version : 4));
wl_seat_add_listener(device->m_seat, &seat_listener, device);
}
else if (interface_str == "wl_shm")
{
@ -547,6 +548,7 @@ public:
{
device->m_output = static_cast<wl_output*>(wl_registry_bind(registry,
name, &wl_output_interface, 2));
wl_output_add_listener(device->m_output, &output_listener, device);
}
}
@ -700,9 +702,6 @@ CIrrDeviceWayland::CIrrDeviceWayland(const SIrrlichtCreationParameters& params)
return;
}
wl_seat_add_listener(m_seat, &WaylandCallbacks::seat_listener, this);
wl_output_add_listener(m_output, &WaylandCallbacks::output_listener, this);
createDriver();
if (VideoDriver)
@ -716,6 +715,9 @@ CIrrDeviceWayland::~CIrrDeviceWayland()
{
delete m_egl_context;
if (m_egl_window)
wl_egl_window_destroy(m_egl_window);
if (m_keyboard)
wl_keyboard_destroy(m_keyboard);
@ -731,14 +733,45 @@ CIrrDeviceWayland::~CIrrDeviceWayland()
if (m_shell_surface)
wl_shell_surface_destroy(m_shell_surface);
wl_output_destroy(m_output);
wl_seat_destroy(m_seat);
wl_registry_destroy(m_registry);
if (m_surface)
wl_surface_destroy(m_surface);
if (m_shell)
wl_shell_destroy(m_shell);
if (m_shm)
wl_shm_destroy(m_shm);
if (m_compositor)
wl_compositor_destroy(m_compositor);
if (m_output)
wl_output_destroy(m_output);
if (m_seat)
wl_seat_destroy(m_seat);
if (m_registry)
wl_registry_destroy(m_registry);
if (m_xkb_state)
xkb_state_unref(m_xkb_state);
if (m_xkb_keymap)
xkb_keymap_unref(m_xkb_keymap);
if (m_xkb_compose_state)
xkb_compose_state_unref(m_xkb_compose_state);
if (m_xkb_compose_table)
xkb_compose_table_unref(m_xkb_compose_table);
if (m_xkb_context)
xkb_context_unref(m_xkb_context);
wl_display_flush(m_display);
wl_display_disconnect(m_display);
xkb_context_unref(m_xkb_context);
closeJoysticks();
}

View File

@ -433,6 +433,13 @@ namespace video
addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_ONETEXTURE_BLEND, this));
delete[] FPVSData;
delete[] FPFSData;
delete[] NMVSData;
delete[] NMFSData;
delete[] PMVSData;
delete[] PMFSData;
// Create 2D material renderer.
core::stringc R2DVSPath = shaders_path;
@ -476,6 +483,9 @@ namespace video
R2DFSFile->drop();
MaterialRenderer2D = new COGLES2Renderer2D(R2DVSData, R2DFSData, this);
delete[] R2DVSData;
delete[] R2DFSData;
}

View File

@ -93,7 +93,7 @@ COGLES2MaterialRenderer::~COGLES2MaterialRenderer()
if (Program)
{
GLuint shaders[8];
GLint count;
GLint count = 0;
glGetAttachedShaders(Program, 8, &count, shaders);
count=core::min_(count,8);

View File

@ -80,26 +80,6 @@ void InstanceFiller<GlowInstanceData>::add(GLMesh* mesh,
instance.Color = nd->getGlowColor().color;
}
// ----------------------------------------------------------------------------
template<>
void expandTexSecondPass<GrassMat>(const GLMesh &mesh,
const std::vector<GLuint> &prefilled_tex)
{
TexExpander<typename GrassMat::InstancedSecondPassShader>::
expandTex(mesh, GrassMat::SecondPassTextures, prefilled_tex[0],
prefilled_tex[1], prefilled_tex[2], prefilled_tex[3]);
}
// ----------------------------------------------------------------------------
template<>
void expandHandlesSecondPass<GrassMat>(const std::vector<uint64_t> &handles)
{
uint64_t nulltex[10] = {};
HandleExpander<GrassMat::InstancedSecondPassShader>::
expand(nulltex, GrassMat::SecondPassTextures,
handles[0], handles[1], handles[2], handles[3]);
}
#if !defined(USE_GLES2)
// ----------------------------------------------------------------------------
template<int N>

View File

@ -113,10 +113,6 @@ void expandTexSecondPass(const GLMesh &mesh,
prefilled_tex[1], prefilled_tex[2]);
}
template<>
void expandTexSecondPass<GrassMat>(const GLMesh &mesh,
const std::vector<GLuint> &prefilled_tex);
// ----------------------------------------------------------------------------
/** Give acces textures for second rendering pass in shaders
* without first binding them in order to reduce driver overhead.
@ -133,10 +129,6 @@ void expandHandlesSecondPass(const std::vector<uint64_t> &handles)
handles[0], handles[1], handles[2]);
}
template<>
void expandHandlesSecondPass<GrassMat>(const std::vector<uint64_t> &handles);
#if !defined(USE_GLES2)
// ----------------------------------------------------------------------------
/**

View File

@ -89,49 +89,6 @@ void renderMeshes2ndPass( const std::vector<uint64_t> &Prefilled_Handle,
}
} // renderMeshes2ndPass
// ----------------------------------------------------------------------------
template<>
void renderMeshes2ndPass<GrassMat, 4, 3, 1>
(const std::vector<uint64_t> &Prefilled_Handle,
const std::vector<GLuint> &Prefilled_Tex)
{
auto &meshes = GrassMat::List::getInstance()->SolidPass;
GrassMat::SecondPassShader::getInstance()->use();
if (CVS->isARBBaseInstanceUsable())
glBindVertexArray(VAOManager::getInstance()->getVAO(GrassMat::VertexType));
for (unsigned i = 0; i < meshes.size(); i++)
{
GLMesh &mesh = *(std::get<0>(meshes.at(i)));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh.vao);
if (mesh.VAOType != GrassMat::VertexType)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to pass 2 "
"(hint texture : %s)",
mesh.textures[0]->getName().getPath().c_str());
#endif
continue;
}
if (CVS->isAZDOEnabled())
{
HandleExpander<GrassMat::SecondPassShader>::
expand(mesh.TextureHandles, GrassMat::SecondPassTextures,
Prefilled_Handle[0], Prefilled_Handle[1],
Prefilled_Handle[2], Prefilled_Handle[3]);
}
else
{
TexExpander<GrassMat::SecondPassShader>::
expandTex(mesh, GrassMat::SecondPassTextures, Prefilled_Tex[0],
Prefilled_Tex[1], Prefilled_Tex[2], Prefilled_Tex[3]);
}
CustomUnrollArgs<4, 3, 1>::drawMesh<GrassMat::SecondPassShader>(meshes.at(i));
}
} // renderMeshes2ndPass
// ----------------------------------------------------------------------------
template<typename T, int...List>
void renderShadow(unsigned cascade)

View File

@ -432,10 +432,9 @@ GrassPass2Shader::GrassPass2Shader()
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
1, "SpecularMap", ST_NEAREST_FILTERED,
2, "SSAO", ST_BILINEAR_FILTERED,
3, "dtex", ST_NEAREST_FILTERED,
4, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED,
5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
6, "colorization_mask",
3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED,
4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
5, "colorization_mask",
ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // GrassPass2Shader
@ -448,10 +447,9 @@ InstancedGrassPass2Shader::InstancedGrassPass2Shader()
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
1, "SpecularMap", ST_NEAREST_FILTERED,
2, "SSAO", ST_BILINEAR_FILTERED,
3, "dtex", ST_NEAREST_FILTERED,
4, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED,
5, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
6, "colorization_mask",
3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED,
4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
5, "colorization_mask",
ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // InstancedGrassPass2Shader

View File

@ -260,7 +260,7 @@ public:
}; // InstancedGrassShadowShader
// ============================================================================
class GrassPass2Shader : public TextureShader<GrassPass2Shader, 7,
class GrassPass2Shader : public TextureShader<GrassPass2Shader, 6,
core::matrix4, core::vector3df,
core::vector2df>
{
@ -270,7 +270,7 @@ public:
// ============================================================================
class InstancedGrassPass2Shader
: public TextureShader<InstancedGrassPass2Shader, 7, core::vector3df>
: public TextureShader<InstancedGrassPass2Shader, 6, core::vector3df>
{
public:
InstancedGrassPass2Shader();

View File

@ -33,6 +33,7 @@
#include "graphics/rtts.hpp"
#include "graphics/shaders.hpp"
#include "graphics/skybox.hpp"
#include "graphics/stk_billboard.hpp"
#include "graphics/stk_mesh_scene_node.hpp"
#include "graphics/spherical_harmonics.hpp"
#include "items/item_manager.hpp"
@ -58,12 +59,9 @@ void ShaderBasedRenderer::setRTT(RTT* rtts)
rtts->getDepthStencilTexture());
m_geometry_passes->setFirstPassRenderTargets(prefilled_textures,
rtts->getPrefilledHandles());
m_rtts = rtts;
}
else if (rtts == NULL)
{
m_rtts = NULL;
}
m_rtts = rtts;
} //setRTT
// ----------------------------------------------------------------------------
@ -659,6 +657,7 @@ ShaderBasedRenderer::~ShaderBasedRenderer()
delete m_skybox;
delete m_rtts;
ShaderFilesManager::kill();
STKBillboard::destroyBillboardVAO();
}
// ----------------------------------------------------------------------------

View File

@ -30,10 +30,10 @@
using namespace irr;
static GLuint billboardvao = 0;
GLuint STKBillboard::m_billboard_vao = 0;
class BillboardShader : public TextureShader<BillboardShader, 1, core::matrix4,
class BillboardShader : public TextureShader<BillboardShader, 1,
core::matrix4, core::vector3df,
core::dimension2df>
{
@ -43,18 +43,16 @@ public:
loadProgram(OBJECT, GL_VERTEX_SHADER, "billboard.vert",
GL_FRAGMENT_SHADER, "billboard.frag");
assignUniforms("ModelViewMatrix", "ProjectionMatrix", "Position",
"Size");
assignUniforms("color_matrix", "Position", "Size");
assignSamplerNames(0, "tex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // BillboardShader
}; // BillboardShader
// ============================================================================
static void createBillboardVAO()
void STKBillboard::createBillboardVAO()
{
glGenVertexArrays(1, &billboardvao);
glBindVertexArray(billboardvao);
glGenVertexArrays(1, &m_billboard_vao);
glBindVertexArray(m_billboard_vao);
glBindBuffer(GL_ARRAY_BUFFER, SharedGPUObjects::getBillboardVBO());
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(3);
@ -64,6 +62,16 @@ static void createBillboardVAO()
glBindVertexArray(0);
} // createBillboardVAO
// ----------------------------------------------------------------------------
void STKBillboard::destroyBillboardVAO()
{
if (m_billboard_vao != 0)
{
glDeleteVertexArrays(1, &m_billboard_vao);
m_billboard_vao = 0;
}
} // destroyBillboardVAO
// ----------------------------------------------------------------------------
STKBillboard::STKBillboard(irr::scene::ISceneNode* parent,
irr::scene::ISceneManager* mgr, irr::s32 id,
@ -75,7 +83,7 @@ STKBillboard::STKBillboard(irr::scene::ISceneNode* parent,
CBillboardSceneNode(parent, mgr, id, position, size,
colorTop, colorBottom)
{
if (!billboardvao)
if (!m_billboard_vao)
createBillboardVAO();
} // STKBillboard
@ -97,9 +105,9 @@ void STKBillboard::render()
return;
core::vector3df pos = getAbsolutePosition();
glBindVertexArray(billboardvao);
glBindVertexArray(m_billboard_vao);
video::ITexture *tex = Material.getTexture(0);
if (!tex )
if (!tex)
return;
::Material* material = material_manager->getMaterialFor(tex,
@ -109,11 +117,24 @@ void STKBillboard::render()
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
video::SColor col[2];
getColor(col[0], col[1]);
const float colors[] =
{
col[1].getRed() / 255.f, col[1].getGreen() / 255.f,
col[1].getBlue() / 255.f, col[1].getAlpha() / 255.f,
col[0].getRed() / 255.f, col[0].getGreen() / 255.f,
col[0].getBlue() / 255.f, col[0].getAlpha() / 255.f,
col[1].getRed() / 255.f, col[1].getGreen() / 255.f,
col[1].getBlue() / 255.f, col[1].getAlpha() / 255.f,
col[0].getRed() / 255.f, col[0].getGreen() / 255.f,
col[0].getBlue() / 255.f, col[0].getAlpha() / 255.f,
};
core::matrix4 color_matrix;
color_matrix.setM(colors);
BillboardShader::getInstance()->use();
BillboardShader::getInstance()->setTextureUnits(tex->getOpenGLTextureName());
BillboardShader::getInstance()->setUniforms(irr_driver->getViewMatrix(),
irr_driver->getProjMatrix(),
pos, Size);
BillboardShader::getInstance()->setUniforms(color_matrix, pos, Size);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
} // render

View File

@ -21,10 +21,14 @@
#include "../lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h"
#include <IBillboardSceneNode.h>
#include <irrTypes.h>
#include "graphics/gl_headers.hpp"
#include "utils/cpp2011.hpp"
class STKBillboard : public irr::scene::CBillboardSceneNode
{
private:
static GLuint m_billboard_vao;
static void createBillboardVAO();
public:
STKBillboard(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr,
irr::s32 id, const irr::core::vector3df& position,
@ -35,6 +39,7 @@ public:
virtual void OnRegisterSceneNode() OVERRIDE;
virtual void render() OVERRIDE;
static void destroyBillboardVAO();
}; // STKBillboard
#endif

View File

@ -47,6 +47,12 @@ DeviceManager::DeviceManager()
m_multitouch_device = NULL;
} // DeviceManager
// -----------------------------------------------------------------------------
DeviceManager::~DeviceManager()
{
delete m_multitouch_device;
} // ~DeviceManager
// -----------------------------------------------------------------------------
bool DeviceManager::initialize()
{

View File

@ -103,6 +103,7 @@ public:
DeviceManager();
~DeviceManager();
// ---- Assign mode ----
PlayerAssignMode getAssignMode() const { return m_assign_mode; }

View File

@ -488,11 +488,13 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
// We have to save the direction in which the axis was moved.
// This is done by storing it as a sign (and since button can
// be zero, we add one before changing the sign).
int input_id = value>=0 ? 1+button : -(1+button);
int input_button_id = value>=0 ? 1+button : -(1+button);
std::tuple<int, int> input_id(deviceID, input_button_id);
std::tuple<int, int> input_id_inv(deviceID, -input_button_id);
bool id_was_high = m_sensed_input_high_gamepad.find(input_id)
!= m_sensed_input_high_gamepad.end();
bool inverse_id_was_high = m_sensed_input_high_gamepad.find(-input_id)
bool inverse_id_was_high = m_sensed_input_high_gamepad.find(input_id_inv)
!= m_sensed_input_high_gamepad.end();
bool id_was_zero = m_sensed_input_zero_gamepad.find(button)
!= m_sensed_input_zero_gamepad.end();

View File

@ -53,7 +53,7 @@ public:
private:
DeviceManager *m_device_manager;
std::set<int> m_sensed_input_high_gamepad;
std::set<std::tuple<int, int>> m_sensed_input_high_gamepad;
std::set<int> m_sensed_input_high_kbd;
std::set<int> m_sensed_input_zero_gamepad;

View File

@ -273,7 +273,6 @@ KartModel::~KartModel()
for (size_t i = 0; i < m_headlight_objects.size(); i++)
{
HeadlightObject& obj = m_headlight_objects[i];
obj.setNode(NULL);
if (obj.getNode())
{
// Master KartModels should never have a headlight attached.

View File

@ -256,7 +256,7 @@ void MainLoop::run()
// enabled.
if (!m_abort && !ProfileWorld::isNoGraphics())
{
PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
PROFILER_PUSH_CPU_MARKER("Input/GUI", 0x7F, 0x00, 0x00);
input_manager->update(dt);
#ifdef ENABLE_WIIUSE
@ -269,7 +269,7 @@ void MainLoop::run()
// Update sfx and music after graphics, so that graphics code
// can use as many threads as possible without interfering
// with audio
PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
PROFILER_PUSH_CPU_MARKER("Music", 0x7F, 0x00, 0x00);
SFXManager::get()->update();
PROFILER_POP_CPU_MARKER();

View File

@ -127,6 +127,23 @@ namespace Scripting
#endif
}
/** Function for re-enable a trigger after a specific timeout*/
void setTriggerReenableTimeout(std::string* triggerID, std::string* lib_id,
float reenable_time)
{
::TrackObject* tobj = ::Track::getCurrentTrack()->getTrackObjectManager()
->getTrackObject(*lib_id, *triggerID);
if (tobj != NULL)
{
TrackObjectPresentationActionTrigger* topat =
tobj->getPresentation<TrackObjectPresentationActionTrigger>();
if (topat != NULL)
{
topat->setReenableTimeout(reenable_time);
}
}
}
/** Exits the race to the main menu */
void exitRace()
{
@ -231,22 +248,52 @@ namespace Scripting
/** Sets a loop for a skeletal animation */
// TODO: can we use a type and avoid void* ?
void setLoop(int start, int end /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
void setFrameLoop(int start, int end /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
{
((TrackObjectPresentationMesh*)(memory))->setLoop(start, end);
if (memory)
{
((scene::IAnimatedMeshSceneNode*)(memory))->setFrameLoop(start, end);
}
}
/** Sets a loop once for a skeletal animation */
void setFrameLoopOnce(int start, int end /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
{
if (memory)
{
((scene::IAnimatedMeshSceneNode*)(memory))->setFrameLoopOnce(start, end);
}
}
/** Get current frame in a skeletal animation */
int getFrameNr(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
{
if (memory)
{
return ((scene::IAnimatedMeshSceneNode*)(memory))->getFrameNr();
}
return -1;
}
/** Gets the animation set for a skeletal animation */
int getAnimationSet(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
{
if (memory)
{
return ((scene::IAnimatedMeshSceneNode*)(memory))->getAnimationSet();
}
return -1;
}
/** Sets the current frame for a skeletal animation */
void setCurrentFrame(int frame /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
{
((TrackObjectPresentationMesh*)(memory))->setCurrentFrame(frame);
if (memory)
{
((scene::IAnimatedMeshSceneNode*)(memory))->setCurrentFrame(frame);
}
}
/** Get current frame in a skeletal animation */
int getCurrentFrame(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
{
return ((TrackObjectPresentationMesh*)(memory))->getCurrentFrame();
}
/** @} */
}
@ -384,6 +431,8 @@ namespace Scripting
asFUNCTION(createTrigger), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void createTextBillboard(const string &in, const Vec3 &in)",
asFUNCTION(createTextBillboard), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void setTriggerReenableTimeout(const string &in, const string &in, float reenable_time)",
asFUNCTION(setTriggerReenableTimeout), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("TrackObject@ getTrackObject(const string &in, const string &in)", asFUNCTION(getTrackObject), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void exitRace()", asFUNCTION(exitRace), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("void pauseRace()", asFUNCTION(pauseRace), asCALL_CDECL); assert(r >= 0);
@ -410,9 +459,11 @@ namespace Scripting
r = engine->RegisterObjectMethod("PhysicalObject", "void disable()", asMETHOD(PhysicalObject, disable), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("PhysicalObject", "void enable()", asMETHOD(PhysicalObject, enable), asCALL_THISCALL); assert(r >= 0);
// TrackObjectPresentationMesh (Mesh or Skeletal Animation)
r = engine->RegisterObjectMethod("Mesh", "void setLoop(int start, int end)", asFUNCTION(Mesh::setLoop), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "int getCurrentFrame()", asFUNCTION(Mesh::getCurrentFrame), asCALL_CDECL_OBJLAST); assert(r >= 0);
// Animated Mesh
r = engine->RegisterObjectMethod("Mesh", "void setFrameLoop(int start, int end)", asFUNCTION(Mesh::setFrameLoop), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "void setFrameLoopOnce(int start, int end)", asFUNCTION(Mesh::setFrameLoopOnce), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "int getFrameNr()", asFUNCTION(Mesh::getFrameNr), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "int getAnimationSet()", asFUNCTION(Mesh::getAnimationSet), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "void setCurrentFrame(int frame)", asFUNCTION(Mesh::setCurrentFrame), asCALL_CDECL_OBJLAST); assert(r >= 0);
//r = engine->RegisterObjectMethod("Mesh", "void move(Vec3 &in)", asFUNCTION(movePresentation), asCALL_CDECL_OBJLAST); assert(r >= 0);

View File

@ -434,6 +434,10 @@ void OptionsScreenDevice::gotSensedInput(const Input& sensed_input)
// refresh display
updateInputButtons();
}
else
{
return;
}
}
else if (sensed_input.m_type == Input::IT_NONE)
{

View File

@ -20,6 +20,7 @@
#include "animations/three_d_animation.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/lod_node.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/render_info.hpp"
@ -32,6 +33,7 @@
#include "scriptengine/script_engine.hpp"
#include "tracks/model_definition_loader.hpp"
#include <IAnimatedMeshSceneNode.h>
#include <ISceneManager.h>
/** A track object: any additional object on the track. This object implements
@ -156,6 +158,7 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
}
else if (xml_node.getName() == "library")
{
xml_node.get("name", &m_name);
m_presentation = new TrackObjectPresentationLibraryNode(this, xml_node, model_def_loader);
}
else if (type == "sfx-emitter")
@ -170,7 +173,7 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
std::string action;
xml_node.get("action", &action);
m_name = action; //adds action as name so that it can be found by using getName()
m_presentation = new TrackObjectPresentationActionTrigger(xml_node);
m_presentation = new TrackObjectPresentationActionTrigger(xml_node, parent_library);
}
else if (type == "billboard")
{
@ -661,3 +664,35 @@ void TrackObject::moveTo(const Scripting::SimpleVec3* pos, bool isAbsoluteCoord)
isAbsoluteCoord);
}
}
// ----------------------------------------------------------------------------
scene::IAnimatedMeshSceneNode* TrackObject::getMesh()
{
if (getPresentation<TrackObjectPresentationLOD>())
{
LODNode* ln = dynamic_cast<LODNode*>
(getPresentation<TrackObjectPresentationLOD>()->getNode());
if (ln && !ln->getAllNodes().empty())
{
scene::IAnimatedMeshSceneNode* an =
dynamic_cast<scene::IAnimatedMeshSceneNode*>
(ln->getFirstNode());
if (an)
{
return an;
}
}
}
else if (getPresentation<TrackObjectPresentationMesh>())
{
scene::IAnimatedMeshSceneNode* an =
dynamic_cast<scene::IAnimatedMeshSceneNode*>
(getPresentation<TrackObjectPresentationMesh>()->getNode());
if (an)
{
return an;
}
}
Log::debug("TrackObject", "No animated mesh");
return NULL;
} // getMesh

View File

@ -190,7 +190,7 @@ public:
/** Should only be used on mesh track objects.
* On the script side, the returned object is of type : @ref Scripting_Mesh
*/
TrackObjectPresentationMesh* getMesh() { return getPresentation<TrackObjectPresentationMesh>(); }
scene::IAnimatedMeshSceneNode* getMesh();
/** Should only be used on particle emitter track objects.
* On the script side, the returned object is of type : @ref Scripting_ParticleEmitter
*/

View File

@ -358,11 +358,13 @@ void TrackObjectPresentationLOD::reset()
dynamic_cast<scene::IAnimatedMeshSceneNode*>(node);
if (a_node)
{
a_node->setLoopMode(true);
a_node->setAnimationEndCallback(NULL);
RandomGenerator rg;
int animation_set = 0;
if (a_node->getAnimationSetNum() > 0)
animation_set = rg.get(a_node->getAnimationSetNum());
a_node->useAnimationSet(animation_set);
a_node->useAnimationSet(animation_set);
}
}
}
@ -642,6 +644,7 @@ void TrackObjectPresentationMesh::reset()
a_node->setRotation(m_init_hpr);
a_node->setScale(m_init_scale);
a_node->setLoopMode(m_is_looped);
a_node->setAnimationEndCallback(NULL);
a_node->setCurrentFrame((float)(a_node->getStartFrame()));
// trick to reset the animation AND also the timer inside it
@ -658,49 +661,6 @@ void TrackObjectPresentationMesh::reset()
}
} // reset
// ----------------------------------------------------------------------------
int TrackObjectPresentationMesh::getCurrentFrame()
{
if (m_node->getType() == scene::ESNT_ANIMATED_MESH)
{
scene::IAnimatedMeshSceneNode *a_node =
(scene::IAnimatedMeshSceneNode*)m_node;
return (int)a_node->getFrameNr();
}
return -1; //Not a skeletal animation
} // getCurrentFrame
// ----------------------------------------------------------------------------
void TrackObjectPresentationMesh::setCurrentFrame(int frame)
{
if (m_node->getType() == scene::ESNT_ANIMATED_MESH)
{
scene::IAnimatedMeshSceneNode *a_node =
(scene::IAnimatedMeshSceneNode*)m_node;
a_node->setCurrentFrame((f32)frame);
}
} // setCurrentFrame
// ----------------------------------------------------------------------------
/** Set custom loops, as well as pause by scripts.
* \param start Start frame.
* \param end End frame.
*/
void TrackObjectPresentationMesh::setLoop(int start, int end)
{
if (m_node->getType() == scene::ESNT_ANIMATED_MESH)
{
scene::IAnimatedMeshSceneNode *a_node =
(scene::IAnimatedMeshSceneNode*)m_node;
// irrlicht's "setFrameLoop" is a misnomer, it just sets the first and
// last frame, even if looping is disabled
a_node->setFrameLoop(start, end);
}
} // setLoop
// ----------------------------------------------------------------------------
TrackObjectPresentationSound::TrackObjectPresentationSound(
const XMLNode& xml_node,
@ -1094,7 +1054,8 @@ void TrackObjectPresentationLight::setEnergy(float energy)
}
// ----------------------------------------------------------------------------
TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
const XMLNode& xml_node)
const XMLNode& xml_node,
TrackObject* parent)
: TrackObjectPresentation(xml_node)
{
float trigger_distance = 1.0f;
@ -1115,11 +1076,36 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
{
assert(false);
}
m_xml_reenable_timeout = 999999.9f;
xml_node.get("reenable-timeout", &m_xml_reenable_timeout);
m_reenable_timeout = 0.0f;
m_action_active = true;
if (m_action.size() == 0)
if (m_action.empty())
{
Log::warn("TrackObject", "Action-trigger has no action defined.");
return;
}
if (parent != NULL)
{
core::vector3df parent_xyz = parent->getInitXYZ();
core::vector3df parent_rot = parent->getInitRotation();
core::vector3df parent_scale = parent->getInitScale();
core::matrix4 lm, sm, rm;
lm.setTranslation(parent_xyz);
sm.setScale(parent_scale);
rm.setRotationDegrees(parent_rot);
core::matrix4 abs_trans = lm * rm * sm;
m_library_id = parent->getID();
m_library_name = parent->getName();
xml_node.get("triggered-object", &m_triggered_object);
if (!m_library_id.empty() && !m_triggered_object.empty() &&
!m_library_name.empty())
{
abs_trans.transformVect(m_init_xyz);
}
}
if (m_type == TRIGGER_TYPE_POINT)
{
@ -1149,7 +1135,8 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
m_init_scale = core::vector3df(1, 1, 1);
float trigger_distance = distance;
m_action = script_name;
m_action_active = true;
m_xml_reenable_timeout = 999999.9f;
m_reenable_timeout = 0.0f;
m_type = TRIGGER_TYPE_POINT;
ItemManager::get()->newItem(m_init_xyz, trigger_distance, this);
} // TrackObjectPresentationActionTrigger
@ -1157,13 +1144,36 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
// ----------------------------------------------------------------------------
void TrackObjectPresentationActionTrigger::onTriggerItemApproached()
{
if (!m_action_active) return;
if (m_reenable_timeout > 0.0f)
{
return;
}
m_reenable_timeout = m_xml_reenable_timeout;
m_action_active = false; // TODO: allow auto re-activating?
int idKart = 0;
int kart_id = 0;
Camera* camera = Camera::getActiveCamera();
if (camera != NULL && camera->getKart() != NULL)
idKart = camera->getKart()->getWorldKartId();
Scripting::ScriptEngine::getInstance()->runFunction(true, "void " + m_action + "(int)",
[=](asIScriptContext* ctx) { ctx->SetArgDWord(0, idKart); });
{
kart_id = camera->getKart()->getWorldKartId();
}
if (!m_library_id.empty() && !m_triggered_object.empty() &&
!m_library_name.empty())
{
Scripting::ScriptEngine::getInstance()->runFunction(true, "void "
+ m_library_name + "::" + m_action +
"(int, const string, const string)", [=](asIScriptContext* ctx)
{
ctx->SetArgDWord(0, kart_id);
ctx->SetArgObject(1, &m_library_id);
ctx->SetArgObject(2, &m_triggered_object);
});
}
else
{
Scripting::ScriptEngine::getInstance()->runFunction(true,
"void " + m_action + "(int)", [=](asIScriptContext* ctx)
{
ctx->SetArgDWord(0, kart_id);
});
}
} // onTriggerItemApproached

View File

@ -251,9 +251,6 @@ public:
const core::vector3df& hpr,
const core::vector3df& scale);
virtual ~TrackObjectPresentationMesh();
void setLoop(int start, int end);
void setCurrentFrame(int frame);
int getCurrentFrame();
virtual void reset() OVERRIDE;
// ------------------------------------------------------------------------
/** Returns the mode file name. */
@ -382,14 +379,15 @@ class TrackObjectPresentationActionTrigger : public TrackObjectPresentation,
{
private:
/** For action trigger objects */
std::string m_action;
std::string m_action, m_library_id, m_triggered_object, m_library_name;
bool m_action_active;
float m_xml_reenable_timeout, m_reenable_timeout;
ActionTriggerType m_type;
public:
TrackObjectPresentationActionTrigger(const XMLNode& xml_node);
TrackObjectPresentationActionTrigger(const XMLNode& xml_node,
TrackObject* parent);
TrackObjectPresentationActionTrigger(const core::vector3df& xyz,
const std::string& scriptname,
float distance);
@ -399,11 +397,23 @@ public:
virtual void onTriggerItemApproached() OVERRIDE;
// ------------------------------------------------------------------------
/** Reset the trigger (i.e. sets it to active again). */
virtual void reset() OVERRIDE { m_action_active = true; }
virtual void reset() OVERRIDE { m_reenable_timeout = 0.0f; }
// ------------------------------------------------------------------------
virtual void update(float dt) OVERRIDE
{
if (m_reenable_timeout < 900000.0f)
{
m_reenable_timeout -= dt;
}
}
// ------------------------------------------------------------------------
/** Sets the trigger to be enabled or disabled. */
virtual void setEnable(bool status) OVERRIDE{ m_action_active = status; }
virtual void setEnable(bool status) OVERRIDE
{ m_reenable_timeout = status ? 0.0f : 999999.9f; }
// ------------------------------------------------------------------------
void setReenableTimeout(float time) { m_reenable_timeout = time; }
}; // class TrackObjectPresentationActionTrigger
#endif // TRACKOBJECTPRESENTATION_HPP