Unicode codepoint input

This commit is contained in:
Kevin Trogant 2022-12-08 12:36:39 +01:00
parent 232494cc46
commit 8ec2da45a2
2 changed files with 156 additions and 112 deletions

View File

@ -15,7 +15,7 @@
#include <swappy/swappyGL.h>
#include <GLES3/gl3.h>
static GameState g_app_state = { false };
static GameState g_app_state = {false};
static void _handle_cmd_proxy(struct android_app* app, int32_t cmd)
{
@ -23,16 +23,16 @@ static void _handle_cmd_proxy(struct android_app* app, int32_t cmd)
engine->handleAppCmd(cmd);
}
NativeEngine::NativeEngine(struct android_app *app)
: m_app(app),
m_egl_display(EGL_NO_DISPLAY),
m_egl_surface(EGL_NO_SURFACE),
m_egl_context(EGL_NO_CONTEXT),
m_jni_env(nullptr),
m_has_focus(false),
m_has_window(false),
m_is_visible(false),
m_in_motion(false)
NativeEngine::NativeEngine(struct android_app* app)
: m_app(app),
m_egl_display(EGL_NO_DISPLAY),
m_egl_surface(EGL_NO_SURFACE),
m_egl_context(EGL_NO_CONTEXT),
m_jni_env(nullptr),
m_has_focus(false),
m_has_window(false),
m_is_visible(false),
m_in_motion(false)
{
SwappyGL_init(getJniEnv(), m_app->activity->javaGameActivity);
SwappyGL_setSwapIntervalNS(SWAPPY_SWAP_20FPS);
@ -42,7 +42,6 @@ NativeEngine::NativeEngine(struct android_app *app)
AndroidAssetManager::create(m_app->activity->assetManager);
// INTEGRATION
// Hier kannst du Initialisierungscode aufrufen.
// Beachte das Renderer noch _nicht_ gültig ist.
@ -54,8 +53,8 @@ NativeEngine::NativeEngine(struct android_app *app)
// BEISPIELCODE
m_smiley = StringRepository::global->internString("smiley_PNG42.png");
//m_smiley_pos = { 100, 100 };
// ENDE VOM BEISPIELCODE
// m_smiley_pos = { 100, 100 };
// ENDE VOM BEISPIELCODE
}
NativeEngine::~NativeEngine()
@ -84,8 +83,7 @@ void NativeEngine::gameLoop()
struct android_poll_source* source;
// Poll commands
while ((ALooper_pollAll(isAnimating() ? 0 : -1, nullptr,
&events, reinterpret_cast<void**>(&source))) >= 0) {
while ((ALooper_pollAll(isAnimating() ? 0 : -1, nullptr, &events, reinterpret_cast<void**>(&source))) >= 0) {
if (source)
source->process(source->app, source);
if (m_app->destroyRequested)
@ -104,11 +102,11 @@ void NativeEngine::gameLoop()
}
if (input_buffer->motionEventsCount > 0) {
float rel_size = m_display_height;
if (m_display_height > m_display_width){
if (m_display_height > m_display_width) {
rel_size = m_display_width;
}
rel_size *= 0.04f;
//float rel_size = MIN(m_display_height, m_display_width) * 0.04f;
// float rel_size = MIN(m_display_height, m_display_width) * 0.04f;
for (unsigned int i = 0; i < input_buffer->motionEventsCount; ++i) {
GameActivityMotionEvent motion_event = input_buffer->motionEvents[i];
if (motion_event.action == AMOTION_EVENT_ACTION_DOWN) {
@ -158,20 +156,18 @@ void NativeEngine::gameLoop()
float y = GameActivityPointerAxes_getY(&pointer);
float dist = sqrtf((x - m_last_down.x) * (x - m_last_down.x) +
(y - m_last_down.y) * (y - m_last_down.y));
(y - m_last_down.y) * (y - m_last_down.y));
if (dist < rel_size) {
// TAP
ALOGI("TAP at %f %f", x, y);
input_events[input_event_count].kind = TouchInputEventKind::Tap;
input_events[input_event_count].start = { x, y };
input_events[input_event_count].end = { x, y };
input_events[input_event_count].start = {x, y};
input_events[input_event_count].end = {x, y};
++input_event_count;
}
else {
// Swipe
ALOGI("Swipe from %f %f to %f %f",
m_last_down.x, m_last_down.y,
x, y);
ALOGI("Swipe from %f %f to %f %f", m_last_down.x, m_last_down.y, x, y);
input_events[input_event_count].kind = TouchInputEventKind::EndSwipe;
input_events[input_event_count].start = {m_last_down.x, m_last_down.y};
input_events[input_event_count].end = {x, y};
@ -197,33 +193,28 @@ void NativeEngine::gameLoop()
// INTEGRATION Rufe hier deine "gameloop"/"update" funktion auf, die als Parameter
// den GameState, input_events und input_event_count und die Displaygröße bekommen sollte:
//
// kUpdate(&m_state, input_events, input_event_count, m_display_width, m_display_height)
// kUpdate(&m_state, input_events, input_event_count,
// nullptr, 0,
// m_display_width, m_display_height)
//
// (Für Kompatibilität zu Windows sollte die funktion auch tastatur input akzeptieren,
// den es unter Android aber momentan nicht gibt.)
//
// Die Funktion könnte folgende Definition haben:
// void kUpdate(GameState* state,
// const TouchInputEvent* touch_events,
// unsigned int touch_event_count,
// unsigned int* pressed_codepoints,
// unsigned int codepoint_count,
// float display_width,
// float display_height)
/*static bool erster_aufruf = true;
if (erster_aufruf){
computeWindowWidthHeight(m_display_width, m_display_height);
initKrimiDinner();
erster_aufruf = false;
}
krimiDinnerLoop(&m_state, input_events, input_event_count,
m_display_width, m_display_height);*/
//ENDE INTEGRATION
// ENDE INTEGRATION
// BEISPIELCODE
static float x = 1.f;
static float d = -0.01f;
x += d;
if ( x <= 0.f)
if (x <= 0.f)
d *= -1.f;
else if (x >= 1.f)
d *= -1.f;
@ -235,7 +226,7 @@ void NativeEngine::gameLoop()
}
Renderer::ptr->addRect(100, 100, 500, 500, 0.3f, 0.3f, 0.3f, 1.f);
Renderer::ptr->addRect(m_smiley_pos.x, m_smiley_pos.y, 500, 500, 0.f, x*x, 1.f - x*x, 1.f, m_smiley);
Renderer::ptr->addRect(m_smiley_pos.x, m_smiley_pos.y, 500, 500, 0.f, x * x, 1.f - x * x, 1.f, m_smiley);
// ENDE VOM BEISPIELCODE
}
@ -250,68 +241,71 @@ bool NativeEngine::isAnimating() const
return m_has_window && m_has_focus && m_is_visible;
}
void NativeEngine::handleAppCmd(int32_t cmd)
{
ALOGV("NativeEngine: Handling command %d.", cmd);
switch (cmd) {
case APP_CMD_SAVE_STATE:
ALOGV("NativeEngine:: APP_CMD_SAVE_STATE");
m_state.has_focus = m_has_focus;
m_app->savedState = malloc(sizeof(m_state));
*reinterpret_cast<GameState*>(m_app->savedState) = m_state;
m_app->savedStateSize = sizeof(m_state);
break;
case APP_CMD_INIT_WINDOW:
ALOGV("NativeEngine:: APP_CMD_INIT_WINDOW");
if (m_app->window) {
m_has_window = true;
SwappyGL_setWindow(m_app->window);
if (m_app->savedStateSize == sizeof(m_state) && m_app->savedState) {
m_state = *reinterpret_cast<GameState*>(m_app->savedState);
m_has_focus = m_state.has_focus;
}
else {
// Workaround APP_CMD_GAINED_FOCUS issue where the focus state is not passed
// down from GameActivity when restarting Activity
m_has_focus = g_app_state.has_focus;
}
case APP_CMD_SAVE_STATE:
ALOGV("NativeEngine:: APP_CMD_SAVE_STATE");
m_state.has_focus = m_has_focus;
m_app->savedState = malloc(sizeof(m_state));
*reinterpret_cast<GameState*>(m_app->savedState) = m_state;
m_app->savedStateSize = sizeof(m_state);
break;
case APP_CMD_INIT_WINDOW:
ALOGV("NativeEngine:: APP_CMD_INIT_WINDOW");
if (m_app->window) {
m_has_window = true;
SwappyGL_setWindow(m_app->window);
if (m_app->savedStateSize == sizeof(m_state) && m_app->savedState) {
m_state = *reinterpret_cast<GameState*>(m_app->savedState);
m_has_focus = m_state.has_focus;
}
ALOGV("HandleCommand(%d): hasWindow = %d, hasFocus = %d", cmd,
m_has_window ? 1 : 0, m_has_focus ? 1 : 0);
break;
case APP_CMD_TERM_WINDOW:
ALOGV("NativeEngine: APP_CMD_TERM_WINDOW");
killSurface();
m_has_window = false;
break;
case APP_CMD_GAINED_FOCUS:
ALOGV("NativeEngine: APP_CMD_GAINED_FOCUS");
m_has_focus = true;
m_state.has_focus = g_app_state.has_focus = m_has_focus;
break;
case APP_CMD_LOST_FOCUS:
ALOGV("NativeEngine: APP_CMD_LOST_FOCUS");
m_has_focus = false;
m_state.has_focus = g_app_state.has_focus = m_has_focus;
break;
case APP_CMD_START:
ALOGV("NativeEngine: APP_CMD_START");
m_is_visible = true;
break;
case APP_CMD_STOP:
ALOGV("NativeEngine: APP_CMD_STOP");
m_is_visible = false;
break;
case APP_CMD_RESUME:
ALOGV("NativeEngine: APP_CMD_RESUME");
break;
default:
ALOGW("Unhandled command.");
break;
else {
// Workaround APP_CMD_GAINED_FOCUS issue where the focus state is not passed
// down from GameActivity when restarting Activity
m_has_focus = g_app_state.has_focus;
}
}
ALOGV("HandleCommand(%d): hasWindow = %d, hasFocus = %d", cmd, m_has_window ? 1 : 0, m_has_focus ? 1 : 0);
break;
case APP_CMD_TERM_WINDOW:
ALOGV("NativeEngine: APP_CMD_TERM_WINDOW");
killSurface();
m_has_window = false;
break;
case APP_CMD_GAINED_FOCUS:
ALOGV("NativeEngine: APP_CMD_GAINED_FOCUS");
m_has_focus = true;
m_state.has_focus = g_app_state.has_focus = m_has_focus;
break;
case APP_CMD_LOST_FOCUS:
ALOGV("NativeEngine: APP_CMD_LOST_FOCUS");
m_has_focus = false;
m_state.has_focus = g_app_state.has_focus = m_has_focus;
break;
case APP_CMD_START:
ALOGV("NativeEngine: APP_CMD_START");
m_is_visible = true;
break;
case APP_CMD_STOP:
ALOGV("NativeEngine: APP_CMD_STOP");
m_is_visible = false;
break;
case APP_CMD_RESUME:
ALOGV("NativeEngine: APP_CMD_RESUME");
break;
default:
ALOGW("Unhandled command.");
break;
}
ALOGV("NativeEngine STATUS: F%d, V%d, W%d, EGL: D %p, S %p, CTX %p, CFG %p",
m_has_focus, m_is_visible, m_has_window, m_egl_display, m_egl_surface, m_egl_context,
m_has_focus,
m_is_visible,
m_has_window,
m_egl_display,
m_egl_surface,
m_egl_context,
m_egl_config);
}
@ -346,7 +340,9 @@ bool NativeEngine::prepareToRender()
}
ALOGI("NativeEngine: binding surface and context (display %p, surface %p, context %p)",
m_egl_display, m_egl_surface, m_egl_context);
m_egl_display,
m_egl_surface,
m_egl_context);
if (eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context) == EGL_FALSE) {
ALOGE("NativeEngine: eglMakeCurrent failed, EGL error: %d", eglGetError());
@ -396,13 +392,19 @@ bool NativeEngine::initSurface()
EGLint num_configs;
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_NONE,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES3_BIT,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_BLUE_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_RED_SIZE,
8,
EGL_DEPTH_SIZE,
16,
EGL_NONE,
};
eglChooseConfig(m_egl_display, attribs, &m_egl_config, 1, &num_configs);
@ -429,10 +431,7 @@ bool NativeEngine::initContext()
ALOGI("NativeEngine: initializing context");
assert(m_egl_display != EGL_NO_DISPLAY);
EGLint attrib_list[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
EGLint attrib_list[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
if (m_egl_context != EGL_NO_CONTEXT)
return true;

View File

@ -6,16 +6,34 @@
#include "Win32AssetManager.h"
#include "TouchInput.h"
#include "Position.h"
#include "GameState.h"
#undef APIENTRY
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <assert.h>
struct CodePointsArray
{
unsigned int* cps; // codepoints
unsigned int count;
unsigned int cap;
};
static void errorCallback(int error, const char* desc)
{
MessageBoxA(NULL, desc, "Error", MB_ICONERROR | MB_OK);
}
static void charCallback(GLFWwindow* window, unsigned int cp)
{
CodePointsArray* cp_array = reinterpret_cast<CodePointsArray*>(glfwGetWindowUserPointer(window));
assert(cp_array != nullptr);
if (cp_array->count < cp_array->cap)
cp_array->cps[cp_array->count++] = cp;
}
int main()
{
glfwSetErrorCallback(errorCallback);
@ -24,6 +42,12 @@ int main()
return 1;
}
unsigned int pressed_codepoints[100];
CodePointsArray cp_array;
cp_array.cps = pressed_codepoints;
cp_array.cap = 100;
cp_array.count = 0;
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
@ -32,6 +56,9 @@ int main()
glfwTerminate();
return 1;
}
glfwSetWindowUserPointer(window, &cp_array);
glfwSetCharCallback(window, charCallback);
glfwMakeContextCurrent(window);
int ret = gladLoadGLES2Loader((GLADloadproc)glfwGetProcAddress);
if (!ret) {
@ -41,6 +68,8 @@ int main()
return 1;
}
GameState state = {};
const char* asset_dir = "app\\src\\main\\assets";
Win32AssetManager::create(asset_dir);
@ -53,35 +82,51 @@ int main()
glfwSwapInterval(1);
while (!glfwWindowShouldClose(window)) {
/* Reset the pressed codepoints array,
* because glfwPollEvents() will call our characterCallback
*/
cp_array.count = 0;
glfwPollEvents();
/* Gather keyboard input */
/* Gather mouse input */
TouchInputEvent touch_event = {};
TouchInputEvent input_events[1] = {};
int input_event_count = 0;
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {
double x, y;
glfwGetCursorPos(window, &x, &y);
touch_event.kind = TouchInputEventKind::Tap;
touch_event.start = {static_cast<float>(x), static_cast<float>(y)};
touch_event.end = touch_event.start;
input_events[0].kind = TouchInputEventKind::Tap;
input_events[0].start = {static_cast<float>(x), static_cast<float>(y)};
input_events[0].end = input_events[0].start;
input_event_count = 1;
}
if (cp_array.count > 0) {
printf("CP: %u\n", cp_array.cps[0]);
}
int w, h;
glfwGetFramebufferSize(window, &w, &h);
float display_width = static_cast<float>(w);
float display_height = static_cast<float>(h);
// INTEGRATION Rufe hier deine "gameloop"/"update" funktion auf, die als Parameter
// den GameState, input_events und input_event_count und die Displaygröße bekommen sollte:
//
// kUpdate(&m_state, input_events, input_event_count, m_display_width, m_display_height)
// kUpdate(&state, input_events, input_event_count,
// cp_array.cps, cp_array.count,
// display_width, display_height)
//
//
// Die Funktion könnte folgende Definition haben:
// void kUpdate(GameState* state,
// const TouchInputEvent* touch_events,
// unsigned int touch_event_count,
// unsigned int* pressed_codepoints,
// unsigned int codepoint_count,
// float display_width,
// float display_height)
// ENDE INTEGRATION
@ -96,7 +141,7 @@ int main()
d *= -1.f;
if (input_event_count > 0) {
smiley_pos = touch_event.end;
smiley_pos = input_events[0].end;
smiley_pos.x -= 250;
smiley_pos.y -= 250;
}