1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-15 09:34:18 +02:00

#15 touch controls (windows, android, web)

This commit is contained in:
XProger
2017-03-19 06:16:04 +03:00
parent 765693299e
commit bb5a50d274
13 changed files with 113 additions and 118 deletions

View File

@@ -73,6 +73,8 @@ struct ShaderCache {
compile(Core::passCompose, Shader::ENTITY, FX_CLIP_PLANE); compile(Core::passCompose, Shader::ENTITY, FX_CLIP_PLANE);
compile(Core::passCompose, Shader::ENTITY, FX_UNDERWATER); compile(Core::passCompose, Shader::ENTITY, FX_UNDERWATER);
compile(Core::passCompose, Shader::ENTITY, FX_UNDERWATER | FX_CLIP_PLANE); compile(Core::passCompose, Shader::ENTITY, FX_UNDERWATER | FX_CLIP_PLANE);
compile(Core::passCompose, Shader::ENTITY, FX_ALPHA_TEST);
compile(Core::passCompose, Shader::ENTITY, FX_ALPHA_TEST | FX_CLIP_PLANE);
compile(Core::passCompose, Shader::SPRITE, FX_ALPHA_TEST); compile(Core::passCompose, Shader::SPRITE, FX_ALPHA_TEST);
compile(Core::passCompose, Shader::SPRITE, FX_ALPHA_TEST | FX_CLIP_PLANE); compile(Core::passCompose, Shader::SPRITE, FX_ALPHA_TEST | FX_CLIP_PLANE);
compile(Core::passCompose, Shader::SPRITE, FX_UNDERWATER | FX_ALPHA_TEST); compile(Core::passCompose, Shader::SPRITE, FX_UNDERWATER | FX_ALPHA_TEST);
@@ -107,7 +109,7 @@ struct ShaderCache {
} }
} }
const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT", "FILTER", "WATER" }; const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT", "WATER", "FILTER", "GUI" };
const char *src = NULL; const char *src = NULL;
const char *typ = NULL; const char *typ = NULL;
switch (pass) { switch (pass) {
@@ -146,6 +148,13 @@ struct ShaderCache {
sprintf(def, "%s#define PASS_%s\n#define FILTER_%s\n", ext, passNames[pass], typ); sprintf(def, "%s#define PASS_%s\n#define FILTER_%s\n", ext, passNames[pass], typ);
break; break;
} }
case Core::passGUI : {
static const char *typeNames[] = { "DEFAULT" };
src = GUI;
typ = typeNames[type];
sprintf(def, "%s#define PASS_%s\n", ext, passNames[pass]);
break;
}
default : ASSERT(false); default : ASSERT(false);
} }
LOG("shader: compile %s -> %s %s%s%s\n", passNames[pass], typ, (fx & FX_UNDERWATER) ? "underwater " : "", (fx & FX_ALPHA_TEST) ? "alphaTest " : "", (fx & FX_CLIP_PLANE) ? "clipPlane" : ""); LOG("shader: compile %s -> %s %s%s%s\n", passNames[pass], typ, (fx & FX_UNDERWATER) ? "underwater " : "", (fx & FX_ALPHA_TEST) ? "alphaTest " : "", (fx & FX_CLIP_PLANE) ? "clipPlane" : "");
@@ -610,7 +619,7 @@ struct WaterCache {
Core::setCulling(cfFront); Core::setCulling(cfFront);
// get refraction texture // get refraction texture
if (!refract || Core::width > refract->width || Core::height > refract->height) { if (!refract || Core::width != refract->width || Core::height != refract->height) {
delete refract; delete refract;
refract = new Texture(Core::width, Core::height, Texture::RGBA, false); refract = new Texture(Core::width, Core::height, Texture::RGBA, false);
} }

View File

@@ -242,7 +242,7 @@ namespace Core {
Texture *blackTex, *whiteTex; Texture *blackTex, *whiteTex;
enum Pass { passCompose, passShadow, passAmbient, passFilter, passWater, passMAX } pass; enum Pass { passCompose, passShadow, passAmbient, passWater, passFilter, passGUI, passMAX } pass;
GLuint FBO; GLuint FBO;
struct RenderTargetCache { struct RenderTargetCache {

View File

@@ -4,13 +4,17 @@
#include "core.h" #include "core.h"
#include "format.h" #include "format.h"
#include "level.h" #include "level.h"
#include "ui.h"
namespace Game { namespace Game {
Level *level; Level *level;
UI *ui;
void startLevel(Stream *lvl, Stream *snd, bool demo, bool home) { void startLevel(Stream *lvl, Stream *snd, bool demo, bool home) {
delete ui;
delete level; delete level;
level = new Level(*lvl, snd, demo, home); level = new Level(*lvl, snd, demo, home);
ui = new UI(level);
delete lvl; delete lvl;
} }
@@ -23,6 +27,7 @@ namespace Game {
Core::settings.water = Core::support.texFloat || Core::support.texHalf; Core::settings.water = Core::support.texFloat || Core::support.texHalf;
level = NULL; level = NULL;
ui = NULL;
startLevel(lvl, snd, false, false); startLevel(lvl, snd, false, false);
} }
@@ -35,17 +40,13 @@ namespace Game {
} }
void free() { void free() {
delete ui;
delete level; delete level;
Core::free(); Core::free();
} }
void updateTick() { void updateTick() {
float dt = Core::deltaTime; float dt = Core::deltaTime;
if (Input::down[ikV]) { // third <-> first person view
level->camera->changeView(!level->camera->firstPerson);
Input::down[ikV] = false;
}
if (Input::down[ikR]) // slow motion (for animation debugging) if (Input::down[ikR]) // slow motion (for animation debugging)
Core::deltaTime /= 10.0f; Core::deltaTime /= 10.0f;
@@ -59,7 +60,14 @@ namespace Game {
} }
void update(float delta) { void update(float delta) {
delta = min(1.0f, delta); if (Input::down[ikV]) { // third <-> first person view
level->camera->changeView(!level->camera->firstPerson);
Input::down[ikV] = false;
}
Core::deltaTime = delta = min(1.0f, delta);
ui->update();
while (delta > EPS) { while (delta > EPS) {
Core::deltaTime = min(delta, 1.0f / 30.0f); Core::deltaTime = min(delta, 1.0f / 30.0f);
Game::updateTick(); Game::updateTick();
@@ -71,6 +79,7 @@ namespace Game {
PROFILE_TIMING(Core::stats.tFrame); PROFILE_TIMING(Core::stats.tFrame);
Core::beginFrame(); Core::beginFrame();
level->render(); level->render();
ui->renderTouch();
Core::endFrame(); Core::endFrame();
} }
} }

View File

@@ -1,6 +1,6 @@
R"====( R"====(
#ifdef GL_ES #ifdef GL_ES
precision highp int; precision lowp int;
precision highp float; precision highp float;
#endif #endif
@@ -8,7 +8,7 @@ varying vec2 vTexCoord;
#ifdef VERTEX #ifdef VERTEX
uniform mat4 uViewProj; uniform mat4 uViewProj;
uniform mat4 uModel; uniform vec4 uPosScale;
attribute vec4 aCoord; attribute vec4 aCoord;
attribute vec4 aTexCoord; attribute vec4 aTexCoord;
@@ -16,17 +16,15 @@ varying vec2 vTexCoord;
#define TEXCOORD_SCALE (1.0 / 32767.0) #define TEXCOORD_SCALE (1.0 / 32767.0)
void main() { void main() {
vec4 coord = uModel * vec4(aCoord.xyz, 1.0);
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE; vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
coord.xy += aTexCoord.zw; gl_Position = uViewProj * vec4(aCoord.xy * uPosScale.zw + uPosScale.xy, 0.0, 1.0);
gl_Position = uViewProj * coord;
} }
#else #else
uniform sampler2D sDiffuse; uniform sampler2D sDiffuse;
uniform vec4 uColor; uniform vec4 uMaterial;
void main() { void main() {
gl_FragColor = texture2D(sDiffuse, vTexCoord) * uColor; gl_FragColor = /* texture2D(sDiffuse, vTexCoord) * */ uMaterial;
} }
#endif #endif
)====" )===="

View File

@@ -12,7 +12,7 @@ enum InputKey { ikNone,
// mouse // mouse
ikMouseL, ikMouseR, ikMouseM, ikMouseL, ikMouseR, ikMouseM,
// touch // touch
ikTouchA, ikTouchB, ikTouchA, ikTouchB, ikTouchC, ikTouchD, ikTouchE, ikTouchF,
// gamepad // gamepad
ikJoyA, ikJoyB, ikJoyX, ikJoyY, ikJoyLB, ikJoyRB, ikJoySelect, ikJoyStart, ikJoyL, ikJoyR, ikJoyLT, ikJoyRT, ikJoyPOV, ikJoyA, ikJoyB, ikJoyX, ikJoyY, ikJoyLB, ikJoyRB, ikJoySelect, ikJoyStart, ikJoyL, ikJoyR, ikJoyLT, ikJoyRT, ikJoyPOV,
ikMAX }; ikMAX };
@@ -34,13 +34,11 @@ namespace Input {
int POV; int POV;
} joy; } joy;
struct { struct Touch {
vec2 A, B; int id;
vec2 start;
struct { vec2 pos;
vec2 A, B; } touch[6];
} start;
} touch;
void reset() { void reset() {
memset(down, 0, sizeof(down)); memset(down, 0, sizeof(down));
@@ -58,8 +56,12 @@ namespace Input {
case ikMouseL : mouse.start.L = mouse.pos; break; case ikMouseL : mouse.start.L = mouse.pos; break;
case ikMouseR : mouse.start.R = mouse.pos; break; case ikMouseR : mouse.start.R = mouse.pos; break;
case ikMouseM : mouse.start.M = mouse.pos; break; case ikMouseM : mouse.start.M = mouse.pos; break;
case ikTouchA : touch.start.A = touch.A; break; case ikTouchA :
case ikTouchB : touch.start.B = touch.B; break; case ikTouchB :
case ikTouchC :
case ikTouchD :
case ikTouchE :
case ikTouchF : touch[key - ikTouchA].start = touch[key - ikTouchA].pos; break;
default : ; default : ;
} }
down[key] = value; down[key] = value;
@@ -72,14 +74,32 @@ namespace Input {
case ikMouseM : mouse.pos = pos; return; case ikMouseM : mouse.pos = pos; return;
case ikJoyL : joy.L = pos; return; case ikJoyL : joy.L = pos; return;
case ikJoyR : joy.R = pos; return; case ikJoyR : joy.R = pos; return;
case ikTouchA : touch.A = pos; return;
case ikTouchB : touch.B = pos; return;
case ikJoyLT : joy.LT = pos.x; break; case ikJoyLT : joy.LT = pos.x; break;
case ikJoyRT : joy.RT = pos.x; break; case ikJoyRT : joy.RT = pos.x; break;
case ikJoyPOV : joy.POV = (int)pos.x; break; case ikJoyPOV : joy.POV = (int)pos.x; break;
case ikTouchA :
case ikTouchB :
case ikTouchC :
case ikTouchD :
case ikTouchE :
case ikTouchF : touch[key - ikTouchA].pos = pos; return;
default : return; default : return;
} }
setDown(key, pos.x > 0.0f); setDown(key, pos.x > 0.0f); // gamepad LT, RT, POV auto-down state
}
InputKey getTouch(int id) {
for (int i = 0; i < COUNT(touch); i++)
if (down[ikTouchA + i] && touch[i].id == id)
return InputKey(ikTouchA + i);
for (int i = 0; i < COUNT(touch); i++)
if (!down[ikTouchA + i]) {
touch[i].id = id;
return InputKey(ikTouchA + i);
}
return ikNone;
} }
} }

View File

@@ -1656,13 +1656,13 @@ struct Lara : Character {
if (Input::joy.L.x != 0.0f) { if (Input::joy.L.x != 0.0f) {
input |= (Input::joy.L.x < 0.0f) ? LEFT : RIGHT; input |= (Input::joy.L.x < 0.0f) ? LEFT : RIGHT;
if (moving || stand == STAND_UNDERWATER || stand == STAND_ONWATER) if (moving || stand == STAND_UNDERWATER || stand == STAND_ONWATER)
rotFactor.y = min(fabsf(Input::joy.L.x) / 0.75f, 1.0f); rotFactor.y = min(fabsf(Input::joy.L.x) / 0.9f, 1.0f);
} }
if (Input::joy.L.y != 0.0f) { if (Input::joy.L.y != 0.0f) {
input |= (Input::joy.L.y < 0.0f) ? FORTH : BACK; input |= (Input::joy.L.y < 0.0f) ? FORTH : BACK;
if (stand == STAND_UNDERWATER) if (stand == STAND_UNDERWATER)
rotFactor.x = min(fabsf(Input::joy.L.y) / 0.75f, 1.0f); rotFactor.x = min(fabsf(Input::joy.L.y) / 0.9f, 1.0f);
} }
return input; return input;

View File

@@ -70,7 +70,7 @@ struct Level : IGame {
} }
virtual void setShader(Core::Pass pass, Shader::Type type, bool underwater = false, bool alphaTest = false) { virtual void setShader(Core::Pass pass, Shader::Type type, bool underwater = false, bool alphaTest = false) {
shaderCache->bind(pass, type, (underwater ? ShaderCache::FX_UNDERWATER : 0) | (alphaTest ? ShaderCache::FX_ALPHA_TEST : 0) | (params->clipHeight != NO_CLIP_PLANE ? ShaderCache::FX_CLIP_PLANE : 0)); shaderCache->bind(pass, type, (underwater ? ShaderCache::FX_UNDERWATER : 0) | (alphaTest ? ShaderCache::FX_ALPHA_TEST : 0) | ((params->clipHeight != NO_CLIP_PLANE && pass == Core::passCompose) ? ShaderCache::FX_CLIP_PLANE : 0));
} }
virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) { virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) {
@@ -824,7 +824,7 @@ struct Level : IGame {
glEnd(); glEnd();
Core::setDepthTest(true); Core::setDepthTest(true);
/*
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
@@ -834,9 +834,9 @@ struct Level : IGame {
glLoadIdentity(); glLoadIdentity();
glOrtho(0, Core::width, 0, Core::height, 0, 1); glOrtho(0, Core::width, 0, Core::height, 0, 1);
// if (waterCache->count) if (waterCache->count)
// waterCache->refract->bind(sDiffuse); waterCache->refract->bind(sDiffuse);
// else else
shadow->bind(sDiffuse); shadow->bind(sDiffuse);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);

View File

@@ -7,16 +7,16 @@
<supports-screens android:smallScreens="true" android:largeScreens="true" android:normalScreens="true" android:xlargeScreens="true" /> <supports-screens android:smallScreens="true" android:largeScreens="true" android:normalScreens="true" android:xlargeScreens="true" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" /> <uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.qti.permission.PROFILER" />
<!-- <!--
android:debuggable="true" android:debuggable="true"
--> -->
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"
android:label="@string/app_name"> android:label="@string/app_name"
android:debuggable="true">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"

View File

@@ -107,7 +107,6 @@ int getPOV(int x, int y) {
} }
JNI_METHOD(void, nativeTouch)(JNIEnv* env, jobject obj, jint id, jint state, jfloat x, jfloat y) { JNI_METHOD(void, nativeTouch)(JNIEnv* env, jobject obj, jint id, jint state, jfloat x, jfloat y) {
if (id > 1) return;
// gamepad // gamepad
if (state < 0) { if (state < 0) {
switch (state) { switch (state) {
@@ -118,32 +117,12 @@ JNI_METHOD(void, nativeTouch)(JNIEnv* env, jobject obj, jint id, jint state, jfl
} }
return; return;
} }
// touch
if (state == 3 && x < Core::width / 2) { InputKey key = Input::getTouch(id);
vec2 center(Core::width * 0.25f, Core::height * 0.6f); if (key == ikNone) return;
vec2 pos(x, y); Input::setPos(key, vec2(x, y));
vec2 d = pos - center; if (state == 1 || state == 2)
Input::setPos(ikJoyL, d.normal()); Input::setDown(key, state == 2);
};
if (state == 2 && x > Core::width / 2) {
int i = y / (Core::height / 3);
InputKey key;
if (i == 0)
key = ikJoyX;
else if (i == 1)
key = ikJoyA;
else
key = ikJoyY;
Input::setDown(key, true);
}
if (state == 1) {
Input::setPos(ikJoyL, vec2(0.0f));
Input::setDown(ikJoyA, false);
Input::setDown(ikJoyX, false);
Input::setDown(ikJoyY, false);
}
} }
JNI_METHOD(void, nativeSoundFill)(JNIEnv* env, jobject obj, jshortArray buffer) { JNI_METHOD(void, nativeSoundFill)(JNIEnv* env, jobject obj, jshortArray buffer) {

View File

@@ -199,44 +199,16 @@ EM_BOOL keyCallback(int eventType, const EmscriptenKeyboardEvent *e, void *userD
} }
EM_BOOL touchCallback(int eventType, const EmscriptenTouchEvent *e, void *userData) { EM_BOOL touchCallback(int eventType, const EmscriptenTouchEvent *e, void *userData) {
bool flag = false; for (int i = 0; i < e->numTouches; i++) {
/* InputKey key = Input::getTouch(e->touches[i].identifier);
for (int i = 0; i < e->numTouches; i++) { if (key == ikNone) continue;
long x = e->touches[i].canvasX; Input::setPos(key, vec2(e->touches[i].canvasX, e->touches[i].canvasY));
long y = e->touches[i].canvasY;
if (x < 0 || y < 0 || x >= Core::width || y >= Core::height) continue;
flag = true;
switch (eventType) { if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART || eventType == EMSCRIPTEN_EVENT_TOUCHEND || eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL)
case EMSCRIPTEN_EVENT_TOUCHSTART : Input::setDown(key, eventType == EMSCRIPTEN_EVENT_TOUCHSTART);
if (x > Core::width / 2)
Input::joy.down[(y > Core::height / 2) ? 1 : 4] = true;
break;
case EMSCRIPTEN_EVENT_TOUCHMOVE :
if (x < Core::width / 2) {
vec2 center(Core::width * 0.25f, Core::height * 0.6f);
vec2 pos(x, y);
vec2 d = pos - center;
Input::Joystick &joy = Input::joy;
joy.L.x = d.x;
joy.L.y = d.y;
if (joy.L != vec2(0.0f))
joy.L.normalize();
}
break;
case EMSCRIPTEN_EVENT_TOUCHEND :
case EMSCRIPTEN_EVENT_TOUCHCANCEL : {
Input::joy.L = vec2(0.0f);
Input::joy.down[1] = false;
Input::joy.down[4] = false;
break;
}
}
} }
*/
return flag; return 1;
} }
EM_BOOL mouseCallback(int eventType, const EmscriptenMouseEvent *e, void *userData) { EM_BOOL mouseCallback(int eventType, const EmscriptenMouseEvent *e, void *userData) {
@@ -267,10 +239,10 @@ int main() {
emscripten_set_keyup_callback(0, 0, 1, keyCallback); emscripten_set_keyup_callback(0, 0, 1, keyCallback);
emscripten_set_resize_callback(0, 0, 1, resizeCallback); emscripten_set_resize_callback(0, 0, 1, resizeCallback);
emscripten_set_touchstart_callback(0, 0, 1, touchCallback); emscripten_set_touchstart_callback(0, 0, 0, touchCallback);
emscripten_set_touchend_callback(0, 0, 1, touchCallback); emscripten_set_touchend_callback(0, 0, 0, touchCallback);
emscripten_set_touchmove_callback(0, 0, 1, touchCallback); emscripten_set_touchmove_callback(0, 0, 0, touchCallback);
emscripten_set_touchcancel_callback(0, 0, 1, touchCallback); emscripten_set_touchcancel_callback(0, 0, 0, touchCallback);
emscripten_set_mousedown_callback(0, 0, 1, mouseCallback); emscripten_set_mousedown_callback(0, 0, 1, mouseCallback);
emscripten_set_mouseup_callback(0, 0, 1, mouseCallback); emscripten_set_mouseup_callback(0, 0, 1, mouseCallback);

View File

@@ -198,6 +198,7 @@
<ClInclude Include="..\..\enemy.h" /> <ClInclude Include="..\..\enemy.h" />
<ClInclude Include="..\..\frustum.h" /> <ClInclude Include="..\..\frustum.h" />
<ClInclude Include="..\..\game.h" /> <ClInclude Include="..\..\game.h" />
<ClInclude Include="..\..\ui.h" />
<ClInclude Include="..\..\input.h" /> <ClInclude Include="..\..\input.h" />
<ClInclude Include="..\..\inventory.h" /> <ClInclude Include="..\..\inventory.h" />
<ClInclude Include="..\..\lara.h" /> <ClInclude Include="..\..\lara.h" />

View File

@@ -128,7 +128,7 @@ PREGISTERTOUCHWINDOW RegisterTouchWindowX;
PGETTOUCHINPUTINFO GetTouchInputInfoX; PGETTOUCHINPUTINFO GetTouchInputInfoX;
PCLOSETOUCHINPUTHANDLE CloseTouchInputHandleX; PCLOSETOUCHINPUTHANDLE CloseTouchInputHandleX;
#define MAX_TOUCH_COUNT 10 #define MAX_TOUCH_COUNT 6
void touchInit(HWND hWnd) { void touchInit(HWND hWnd) {
int value = GetSystemMetrics(SM_DIGITIZER); int value = GetSystemMetrics(SM_DIGITIZER);
@@ -142,17 +142,23 @@ void touchInit(HWND hWnd) {
} }
} }
void touchUpdate(HTOUCHINPUT hTouch, int count) { void touchUpdate(HWND hWnd, HTOUCHINPUT hTouch, int count) {
TOUCHINPUT touches[MAX_TOUCH_COUNT]; TOUCHINPUT touch[MAX_TOUCH_COUNT];
count = min(count, MAX_TOUCH_COUNT); count = min(count, MAX_TOUCH_COUNT);
if (!GetTouchInputInfoX(hTouch, count, touches, sizeof(TOUCHINPUT))) if (!GetTouchInputInfoX(hTouch, count, touch, sizeof(TOUCHINPUT)))
return; return;
LOG("touch [ ", count); for (int i = 0; i < count; i++) {
for (int i = 0; i < count; i++) InputKey key = Input::getTouch(touch[i].dwID);
LOG("%d (%d, %d) ", i, touches[i].x, touches[i].y); if (key == ikNone) continue;
LOG("]\n"); POINT pos = { touch[i].x / 100, touch[i].y / 100 };
ScreenToClient(hWnd, &pos);
Input::setPos(key, vec2(float(pos.x), float(pos.y)));
if (touch[i].dwFlags & (TOUCHEVENTF_DOWN | TOUCHEVENTF_UP))
Input::setDown(key, (touch[i].dwFlags & TOUCHEVENTF_DOWN) != 0);
}
CloseTouchInputHandleX(hTouch); CloseTouchInputHandleX(hTouch);
} }
@@ -283,10 +289,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
return 1; return 1;
// touch // touch
case WM_TOUCH : case WM_TOUCH :
touchUpdate((HTOUCHINPUT)lParam, wParam); touchUpdate(hWnd, (HTOUCHINPUT)lParam, wParam);
break; break;
// TODO
// sound
default : default :
return DefWindowProc(hWnd, msg, wParam, lParam); return DefWindowProc(hWnd, msg, wParam, lParam);
} }

View File

@@ -47,6 +47,8 @@ typedef unsigned int uint32;
#define FOURCC(str) (*((uint32*)str)) #define FOURCC(str) (*((uint32*)str))
#define COUNT(arr) (sizeof(arr) / sizeof(arr[0]))
template <typename T> template <typename T>
inline const T& min(const T &a, const T &b) { inline const T& min(const T &a, const T &b) {
return a < b ? a : b; return a < b ? a : b;
@@ -231,7 +233,7 @@ struct vec3 {
struct vec4 { struct vec4 {
union { union {
struct { vec2 xy; }; struct { vec2 xy, zw; };
struct { vec3 xyz; }; struct { vec3 xyz; };
struct { float x, y, z, w; }; struct { float x, y, z, w; };
}; };
@@ -240,6 +242,7 @@ struct vec4 {
vec4(float s) : x(s), y(s), z(s), w(s) {} vec4(float s) : x(s), y(s), z(s), w(s) {}
vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {} vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
vec4(const vec3 &xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {} vec4(const vec3 &xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
vec4(const vec2 &xy, const vec2 &zw) : x(xy.x), y(xy.y), z(zw.x), w(zw.y) {}
vec4 operator * (const vec4 &v) const { return vec4(x*v.x, y*v.y, z*v.z, w*v.w); } vec4 operator * (const vec4 &v) const { return vec4(x*v.x, y*v.y, z*v.z, w*v.w); }
vec4& operator *= (const vec4 &v) { x*=v.x; y*=v.y; z*=v.z; w*=v.w; return *this; } vec4& operator *= (const vec4 &v) { x*=v.x; y*=v.y; z*=v.z; w*=v.w; return *this; }