forked from ocornut/imgui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Android backend and example (ocornut#3446)
- Loading branch information
Showing
14 changed files
with
770 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
// dear imgui: Platform Binding for Android native app | ||
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3) | ||
|
||
// Implemented features: | ||
// [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE). | ||
// [ ] Platform: Clipboard support. | ||
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. | ||
// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android. | ||
|
||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. | ||
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. | ||
// https://github.com/ocornut/imgui | ||
|
||
// CHANGELOG | ||
// (minor and older changes stripped away, please see git history for details) | ||
// 2021-03-02: Support for physical pointer device input (such as physical mouse) | ||
// 2020-09-13: Support for Unicode characters | ||
// 2020-08-31: On-screen and physical keyboard input (ASCII characters only) | ||
// 2020-03-02: basic draft, touch input | ||
|
||
#include "imgui.h" | ||
#include "imgui_impl_android.h" | ||
#include <time.h> | ||
#include <map> | ||
#include <queue> | ||
|
||
// Android | ||
#include <android/native_window.h> | ||
#include <android/input.h> | ||
#include <android/keycodes.h> | ||
#include <android/log.h> | ||
|
||
static double g_Time = 0.0; | ||
static ANativeWindow* g_Window; | ||
static char g_LogTag[] = "ImguiExample"; | ||
static std::map<int32_t, std::queue<int32_t>> g_KeyEventQueues; // FIXME: Remove dependency on map and queue once we use upcoming input queue. | ||
|
||
int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* inputEvent) | ||
{ | ||
ImGuiIO& io = ImGui::GetIO(); | ||
int32_t event_type = AInputEvent_getType(inputEvent); | ||
switch (event_type) | ||
{ | ||
case AINPUT_EVENT_TYPE_KEY: | ||
{ | ||
int32_t event_key_code = AKeyEvent_getKeyCode(inputEvent); | ||
int32_t event_action = AKeyEvent_getAction(inputEvent); | ||
int32_t event_meta_state = AKeyEvent_getMetaState(inputEvent); | ||
|
||
io.KeyCtrl = ((event_meta_state & AMETA_CTRL_ON) != 0); | ||
io.KeyShift = ((event_meta_state & AMETA_SHIFT_ON) != 0); | ||
io.KeyAlt = ((event_meta_state & AMETA_ALT_ON) != 0); | ||
|
||
switch (event_action) | ||
{ | ||
// FIXME: AKEY_EVENT_ACTION_DOWN and AKEY_EVENT_ACTION_UP occur at once | ||
// as soon as a touch pointer goes up from a key. We use a simple key event queue | ||
// and process one event per key per ImGui frame in ImGui_ImplAndroid_NewFrame(). | ||
// ...or consider ImGui IO queue, if suitable: https://github.com/ocornut/imgui/issues/2787 | ||
case AKEY_EVENT_ACTION_DOWN: | ||
case AKEY_EVENT_ACTION_UP: | ||
g_KeyEventQueues[event_key_code].push(event_action); | ||
break; | ||
default: | ||
break; | ||
} | ||
break; | ||
} | ||
case AINPUT_EVENT_TYPE_MOTION: | ||
{ | ||
int32_t event_action = AMotionEvent_getAction(inputEvent); | ||
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; | ||
event_action &= AMOTION_EVENT_ACTION_MASK; | ||
switch (event_action) | ||
{ | ||
case AMOTION_EVENT_ACTION_DOWN: | ||
case AMOTION_EVENT_ACTION_UP: | ||
// Physical mouse buttons (and probably other physical devices) also invoke the actions AMOTION_EVENT_ACTION_DOWN/_UP, | ||
// but we have to process them separately to identify the actual button pressed. This is done below via | ||
// AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback). | ||
if((AMotionEvent_getToolType(inputEvent, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER) | ||
|| (AMotionEvent_getToolType(inputEvent, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) | ||
{ | ||
io.MouseDown[0] = (event_action == AMOTION_EVENT_ACTION_DOWN) ? true : false; | ||
io.MousePos = ImVec2( | ||
AMotionEvent_getX(inputEvent, event_pointer_index), | ||
AMotionEvent_getY(inputEvent, event_pointer_index)); | ||
} | ||
break; | ||
case AMOTION_EVENT_ACTION_BUTTON_PRESS: | ||
case AMOTION_EVENT_ACTION_BUTTON_RELEASE: | ||
{ | ||
int32_t button_state = AMotionEvent_getButtonState(inputEvent); | ||
io.MouseDown[0] = (button_state & AMOTION_EVENT_BUTTON_PRIMARY) ? true : false; | ||
io.MouseDown[1] = (button_state & AMOTION_EVENT_BUTTON_SECONDARY) ? true : false; | ||
io.MouseDown[2] = (button_state & AMOTION_EVENT_BUTTON_TERTIARY) ? true : false; | ||
} | ||
break; | ||
case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse) | ||
case AMOTION_EVENT_ACTION_MOVE: // Touch pointer moves while DOWN | ||
io.MousePos = ImVec2( | ||
AMotionEvent_getX(inputEvent, event_pointer_index), | ||
AMotionEvent_getY(inputEvent, event_pointer_index)); | ||
break; | ||
case AMOTION_EVENT_ACTION_SCROLL: | ||
io.MouseWheel = AMotionEvent_getAxisValue(inputEvent, AMOTION_EVENT_AXIS_VSCROLL, event_pointer_index); | ||
io.MouseWheelH = AMotionEvent_getAxisValue(inputEvent, AMOTION_EVENT_AXIS_HSCROLL, event_pointer_index); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
return 1; | ||
default: | ||
break; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
bool ImGui_ImplAndroid_Init(ANativeWindow* window) | ||
{ | ||
g_Window = window; | ||
g_Time = 0.0; | ||
|
||
// Setup back-end capabilities flags | ||
ImGuiIO& io = ImGui::GetIO(); | ||
io.BackendPlatformName = "imgui_impl_android"; | ||
|
||
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array. | ||
io.KeyMap[ImGuiKey_Tab] = AKEYCODE_TAB; | ||
io.KeyMap[ImGuiKey_LeftArrow] = AKEYCODE_DPAD_LEFT; // also covers physical keyboard arrow key | ||
io.KeyMap[ImGuiKey_RightArrow] = AKEYCODE_DPAD_RIGHT; // also covers physical keyboard arrow key | ||
io.KeyMap[ImGuiKey_UpArrow] = AKEYCODE_DPAD_UP; // also covers physical keyboard arrow key | ||
io.KeyMap[ImGuiKey_DownArrow] = AKEYCODE_DPAD_DOWN; // also covers physical keyboard arrow key | ||
io.KeyMap[ImGuiKey_PageUp] = AKEYCODE_PAGE_UP; | ||
io.KeyMap[ImGuiKey_PageDown] = AKEYCODE_PAGE_DOWN; | ||
io.KeyMap[ImGuiKey_Home] = AKEYCODE_MOVE_HOME; | ||
io.KeyMap[ImGuiKey_End] = AKEYCODE_MOVE_END; | ||
io.KeyMap[ImGuiKey_Insert] = AKEYCODE_INSERT; | ||
io.KeyMap[ImGuiKey_Delete] = AKEYCODE_FORWARD_DEL; | ||
io.KeyMap[ImGuiKey_Backspace] = AKEYCODE_DEL; | ||
io.KeyMap[ImGuiKey_Space] = AKEYCODE_SPACE; | ||
io.KeyMap[ImGuiKey_Enter] = AKEYCODE_ENTER; | ||
io.KeyMap[ImGuiKey_Escape] = AKEYCODE_ESCAPE; | ||
io.KeyMap[ImGuiKey_KeyPadEnter] = AKEYCODE_NUMPAD_ENTER; | ||
io.KeyMap[ImGuiKey_A] = AKEYCODE_A; | ||
io.KeyMap[ImGuiKey_C] = AKEYCODE_C; | ||
io.KeyMap[ImGuiKey_V] = AKEYCODE_V; | ||
io.KeyMap[ImGuiKey_X] = AKEYCODE_X; | ||
io.KeyMap[ImGuiKey_Y] = AKEYCODE_Y; | ||
io.KeyMap[ImGuiKey_Z] = AKEYCODE_Z; | ||
|
||
return true; | ||
} | ||
|
||
void ImGui_ImplAndroid_Shutdown() | ||
{ | ||
} | ||
|
||
void ImGui_ImplAndroid_NewFrame() | ||
{ | ||
ImGuiIO& io = ImGui::GetIO(); | ||
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); | ||
|
||
// Process queued key events | ||
// FIXME: This is a workaround for multiple key event actions occuring at once (see above) and can be removed once we use upcoming input queue. | ||
for (auto& key_queue : g_KeyEventQueues) | ||
{ | ||
if (key_queue.second.empty()) | ||
continue; | ||
io.KeysDown[key_queue.first] = (key_queue.second.front() == AKEY_EVENT_ACTION_DOWN); | ||
key_queue.second.pop(); | ||
} | ||
|
||
// Setup display size (every frame to accommodate for window resizing) | ||
int32_t window_width = ANativeWindow_getWidth(g_Window); | ||
int32_t window_height = ANativeWindow_getHeight(g_Window); | ||
int display_width = window_width; | ||
int display_height = window_height; | ||
|
||
io.DisplaySize = ImVec2((float)window_width, (float)window_height); | ||
if (window_width > 0 && window_height > 0) | ||
io.DisplayFramebufferScale = ImVec2((float)display_width / window_width, (float)display_height / window_height); | ||
|
||
// Setup time step | ||
struct timespec current_timespec; | ||
clock_gettime(CLOCK_MONOTONIC, ¤t_timespec); | ||
double current_time = (double)(current_timespec.tv_sec) + (current_timespec.tv_nsec / 1000000000.0); | ||
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); | ||
g_Time = current_time; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// dear imgui: Platform Binding for Android native app | ||
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3) | ||
|
||
// Implemented features: | ||
// [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE). | ||
// [ ] Platform: Clipboard support. | ||
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. | ||
// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android. | ||
|
||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. | ||
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. | ||
// https://github.com/ocornut/imgui | ||
|
||
#pragma once | ||
|
||
struct ANativeWindow; | ||
struct AInputEvent; | ||
|
||
IMGUI_IMPL_API int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* inputEvent); | ||
IMGUI_IMPL_API bool ImGui_ImplAndroid_Init(ANativeWindow* window); | ||
IMGUI_IMPL_API void ImGui_ImplAndroid_Shutdown(); | ||
IMGUI_IMPL_API void ImGui_ImplAndroid_NewFrame(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
cmake_minimum_required(VERSION 3.6) | ||
|
||
project(ImguiExample) | ||
|
||
set(CMAKE_CXX_STANDARD 11) | ||
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
set(CMAKE_CXX_EXTENSIONS OFF) | ||
|
||
add_library(${CMAKE_PROJECT_NAME} SHARED | ||
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_demo.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_draw.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_tables.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_widgets.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/../../backends/imgui_impl_android.cpp | ||
${CMAKE_CURRENT_SOURCE_DIR}/../../backends/imgui_impl_opengl3.cpp | ||
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c | ||
) | ||
|
||
set(CMAKE_SHARED_LINKER_FLAGS | ||
"${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate" | ||
) | ||
|
||
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE | ||
IMGUI_IMPL_OPENGL_ES3 | ||
) | ||
|
||
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE | ||
${CMAKE_CURRENT_SOURCE_DIR}/../.. | ||
${CMAKE_CURRENT_SOURCE_DIR}/../../backends | ||
${ANDROID_NDK}/sources/android/native_app_glue | ||
) | ||
|
||
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE | ||
android | ||
EGL | ||
GLESv3 | ||
log | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
.cxx | ||
.externalNativeBuild | ||
build/ | ||
*.iml | ||
|
||
.idea | ||
.gradle | ||
local.properties | ||
|
||
# Android Studio puts a Gradle wrapper here, that we don't want: | ||
gradle/ | ||
gradlew* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
apply plugin: 'com.android.application' | ||
apply plugin: 'kotlin-android' | ||
|
||
android { | ||
compileSdkVersion 29 | ||
buildToolsVersion "30.0.3" | ||
ndkVersion "21.4.7075529" | ||
defaultConfig { | ||
applicationId "imgui.example.android" | ||
minSdkVersion 23 | ||
targetSdkVersion 29 | ||
versionCode 1 | ||
versionName "1.0" | ||
} | ||
|
||
buildTypes { | ||
release { | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') | ||
} | ||
} | ||
|
||
externalNativeBuild { | ||
cmake { | ||
path "../../CMakeLists.txt" | ||
} | ||
} | ||
} | ||
repositories { | ||
mavenCentral() | ||
} | ||
dependencies { | ||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" | ||
} |
24 changes: 24 additions & 0 deletions
24
examples/example_android_opengl3/android/app/src/main/AndroidManifest.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="imgui.example.android"> | ||
|
||
<application | ||
android:label="ImguiExample" | ||
android:allowBackup="false" | ||
android:fullBackupContent="false" | ||
android:hasCode="true"> | ||
|
||
<activity | ||
android:name="imgui.example.android.MainActivity" | ||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" | ||
android:configChanges="orientation|keyboardHidden|screenSize"> | ||
<meta-data android:name="android.app.lib_name" | ||
android:value="ImguiExample" /> | ||
|
||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN" /> | ||
<category android:name="android.intent.category.LAUNCHER" /> | ||
</intent-filter> | ||
</activity> | ||
</application> | ||
</manifest> |
Oops, something went wrong.