From 7a99b72f20bfcfd50851d3502be366e68e6648df Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Sat, 11 Nov 2017 16:02:38 -0800 Subject: [PATCH] Allow different colorschemes with HUD devices --- .../apple2ix/Apple2VideoSettingsMenu.java | 93 ++++++++++++++++++- .../app/src/main/res/values-de/strings.xml | 9 ++ .../app/src/main/res/values-es/strings.xml | 9 ++ .../app/src/main/res/values-fr/strings.xml | 9 ++ Android/app/src/main/res/values/strings.xml | 7 ++ src/display.c | 18 ++-- src/interface.h | 7 +- src/prefs.h | 1 + src/video/SolidColor.fsh | 8 +- src/video/glalert.c | 3 +- src/video/glhudmodel.c | 5 +- src/video/glhudmodel.h | 3 + src/video/gltouchjoy.c | 39 ++++++++ src/video/gltouchkbd.c | 7 +- src/video/gltouchmenu.c | 4 +- src/video/ncvideo.c | 3 + 16 files changed, 204 insertions(+), 21 deletions(-) diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2VideoSettingsMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2VideoSettingsMenu.java index 84612bd0..b009e6c7 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2VideoSettingsMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2VideoSettingsMenu.java @@ -62,6 +62,21 @@ public class Apple2VideoSettingsMenu extends Apple2AbstractMenu { INTERPOLATED } + // must match interface_colorscheme_t + public enum DeviceColor { + GREEN_ON_BLACK(0), + GREEN_ON_BLUE(1), // ... + RED_ON_BLACK(2), + BLUE_ON_BLACK(3), + WHITE_ON_BLACK(4); + + private int val; + + DeviceColor(int val) { + this.val = val; + } + } + protected enum SETTINGS implements Apple2AbstractMenu.IMenuEnum { LANDSCAPE_MODE { @Override @@ -97,7 +112,7 @@ public class Apple2VideoSettingsMenu extends Apple2AbstractMenu { cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - Apple2Preferences.setJSONPref((IMenuEnum)self, isChecked); + Apple2Preferences.setJSONPref((IMenuEnum) self, isChecked); applyLandscapeMode(activity); } }); @@ -196,6 +211,82 @@ public class Apple2VideoSettingsMenu extends Apple2AbstractMenu { } }); } + }, + COLOR_DEVICE_CONFIGURE { + @Override + public final String getTitle(Apple2Activity activity) { + return activity.getResources().getString(R.string.touch_device_color); + } + + @Override + public final String getSummary(Apple2Activity activity) { + return activity.getResources().getString(R.string.touch_device_color_summary); + } + + @Override + public String getPrefDomain() { + return Apple2Preferences.PREF_DOMAIN_INTERFACE; + } + + @Override + public String getPrefKey() { + return "hudColorMode"; + } + + @Override + public Object getPrefDefault() { + return 0; + } + + @Override + public View getView(Apple2Activity activity, View convertView) { + convertView = _basicView(activity, this, convertView); + _addPopupIcon(activity, this, convertView); + return convertView; + } + + @Override + public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) { + final Apple2AbstractMenu.IMenuEnum self = this; + _alertDialogHandleSelection(activity, R.string.touch_device_color_configure, new String[]{ + settingsMenu.mActivity.getResources().getString(R.string.color_red_on_black), + settingsMenu.mActivity.getResources().getString(R.string.color_green_on_black), + settingsMenu.mActivity.getResources().getString(R.string.color_blue_on_black), + settingsMenu.mActivity.getResources().getString(R.string.color_white_on_black), + }, new IPreferenceLoadSave() { + @Override + public int intValue() { + int colorscheme = (int) Apple2Preferences.getJSONPref(self); + if (colorscheme == DeviceColor.GREEN_ON_BLACK.ordinal()) { + return 1; + } else if (colorscheme == DeviceColor.BLUE_ON_BLACK.ordinal()) { + return 2; + } else if (colorscheme == DeviceColor.WHITE_ON_BLACK.ordinal()) { + return 3; + } else { + return 0; + } + } + + @Override + public void saveInt(int value) { + switch (value) { + case 1: + Apple2Preferences.setJSONPref(self, (int) DeviceColor.GREEN_ON_BLACK.ordinal()); + break; + case 2: + Apple2Preferences.setJSONPref(self, (int) DeviceColor.BLUE_ON_BLACK.ordinal()); + break; + case 3: + Apple2Preferences.setJSONPref(self, (int) DeviceColor.WHITE_ON_BLACK.ordinal()); + break; + default: + Apple2Preferences.setJSONPref(self, (int) DeviceColor.RED_ON_BLACK.ordinal()); + break; + } + } + }); + } }; public static final int size = SETTINGS.values().length; diff --git a/Android/app/src/main/res/values-de/strings.xml b/Android/app/src/main/res/values-de/strings.xml index 66713989..030efe9f 100644 --- a/Android/app/src/main/res/values-de/strings.xml +++ b/Android/app/src/main/res/values-de/strings.xml @@ -179,5 +179,14 @@ Reset settings Self Test Soft + Configure touch device color + Configure color of HUD elements + Error restoring state… + /storage/ + Configure HUD color… + Red on black + Green on black + Blue on black + White on black diff --git a/Android/app/src/main/res/values-es/strings.xml b/Android/app/src/main/res/values-es/strings.xml index 133a4ace..d93a7527 100644 --- a/Android/app/src/main/res/values-es/strings.xml +++ b/Android/app/src/main/res/values-es/strings.xml @@ -179,5 +179,14 @@ Reset settings Self Test Soft + Configure touch device color + Configure color of HUD elements + Error restoring state… + /storage/ + Configure HUD color… + Red on black + Green on black + Blue on black + White on black diff --git a/Android/app/src/main/res/values-fr/strings.xml b/Android/app/src/main/res/values-fr/strings.xml index 1bbb163f..3cef03ab 100644 --- a/Android/app/src/main/res/values-fr/strings.xml +++ b/Android/app/src/main/res/values-fr/strings.xml @@ -179,5 +179,14 @@ Self Test Reset settings Soft + Configure touch device color + Configure color of HUD elements + Error restoring state… + /storage/ + Configure HUD color… + Red on black + Green on black + Blue on black + White on black diff --git a/Android/app/src/main/res/values/strings.xml b/Android/app/src/main/res/values/strings.xml index 4937771d..8469d8df 100644 --- a/Android/app/src/main/res/values/strings.xml +++ b/Android/app/src/main/res/values/strings.xml @@ -181,5 +181,12 @@ Enables soft menu buttons in top screen corners Configure video… Color landscape/portrait, color, etc + Configure touch device color + Configure color of HUD elements + Configure HUD color… + Red on black + Green on black + Blue on black + White on black diff --git a/src/display.c b/src/display.c index b090f1ef..4ee5c71f 100644 --- a/src/display.c +++ b/src/display.c @@ -35,7 +35,7 @@ static pthread_mutex_t display_scan_mutex = PTHREAD_MUTEX_INITIALIZER; static uint8_t video__wider_font[0x8000] = { 0 }; static uint8_t video__font[0x4000] = { 0 }; -static uint8_t video__int_font[3][0x4000] = { { 0 } }; // interface font +static uint8_t video__int_font[5][0x4000] = { { 0 } }; // interface font static color_mode_t color_mode = COLOR_NONE; @@ -521,13 +521,17 @@ static void _loadfont_int(int first, int quantity, const uint8_t *data) { while (j--) { unsigned int y = (first << 6) + (i << 3) + j; if (x & 128) { - video__int_font[0][y] = COLOR_LIGHT_GREEN; - video__int_font[1][y] = COLOR_LIGHT_GREEN; - video__int_font[2][y] = COLOR_LIGHT_RED; + video__int_font[GREEN_ON_BLACK][y] = COLOR_LIGHT_GREEN; + video__int_font[GREEN_ON_BLUE][y] = COLOR_LIGHT_GREEN; + video__int_font[RED_ON_BLACK][y] = COLOR_LIGHT_RED; + video__int_font[BLUE_ON_BLACK][y] = COLOR_LIGHT_BLUE; + video__int_font[WHITE_ON_BLACK][y] = COLOR_LIGHT_WHITE; } else { - video__int_font[0][y] = COLOR_BLACK; - video__int_font[1][y] = COLOR_MEDIUM_BLUE; - video__int_font[2][y] = COLOR_BLACK; + video__int_font[GREEN_ON_BLACK][y] = COLOR_BLACK; + video__int_font[GREEN_ON_BLUE][y] = COLOR_MEDIUM_BLUE; + video__int_font[RED_ON_BLACK][y] = COLOR_BLACK; + video__int_font[BLUE_ON_BLACK][y] = COLOR_BLACK; + video__int_font[WHITE_ON_BLACK][y] = COLOR_BLACK; } x <<= 1; } diff --git a/src/interface.h b/src/interface.h index 7231149a..9ee01121 100644 --- a/src/interface.h +++ b/src/interface.h @@ -22,9 +22,14 @@ typedef enum interface_colorscheme_t { GREEN_ON_BLACK = 0, GREEN_ON_BLUE, RED_ON_BLACK, + BLUE_ON_BLACK, + WHITE_ON_BLACK, + + // WARNING : changing here requires updating display.c ncvideo.c + BLACK_ON_RED, - // 16 COLORS + // 16 COLORS -- ncvideo.c BLACK_ON_BLACK, BLACK_ON_MAGENTA, BLACK_ON_DARKBLUE, diff --git a/src/prefs.h b/src/prefs.h index ea519460..40d428a3 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -39,6 +39,7 @@ #define PREF_DEVICE_LANDSCAPE "landscapeEnabled" #define PREF_DISK_PATH "diskPath" #define PREF_DISK_ANIMATIONS_ENABLED "diskAnimationsEnabled" +#define PREF_SOFTHUD_COLOR "hudColorMode" // joystick #define PREF_JOYSTICK_KPAD_AUTO_RECENTER "kpAutoRecenter" diff --git a/src/video/SolidColor.fsh b/src/video/SolidColor.fsh index 50232353..a0ab4898 100644 --- a/src/video/SolidColor.fsh +++ b/src/video/SolidColor.fsh @@ -9,17 +9,19 @@ precision highp float; // but we must explicitly declared this in shaders version 1.40 and // above. +uniform vec4 solidColor; + #if __VERSION__ >= 140 out vec4 fragColor; #endif #if __VERSION__ >= 140 -#define OUTPUT_RED fragColor = vec4(1.0, 0.0, 0.0, 1.0) +#define OUTPUT_COLOR fragColor = vec4(solidColor.r, solidColor.g, solidColor.b, solidColor.a) #else -#define OUTPUT_RED gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) +#define OUTPUT_COLOR gl_FragColor = vec4(solidColor.r, solidColor.g, solidColor.b, solidColor.a) #endif void main(void) { - OUTPUT_RED; + OUTPUT_COLOR; } diff --git a/src/video/glalert.c b/src/video/glalert.c index 22e8515a..01989ebc 100644 --- a/src/video/glalert.c +++ b/src/video/glalert.c @@ -35,7 +35,6 @@ static void *_create_alert(GLModel *parent) { parent->custom = glhud_createDefault(); GLModelHUDElement *hudElement = (GLModelHUDElement *)parent->custom; if (hudElement) { - hudElement->colorScheme = RED_ON_BLACK; hudElement->blackIsTransparent = false; hudElement->opaquePixelHalo = false; } @@ -390,6 +389,8 @@ static void alert_applyPrefs(void) { long height = prefs_parseLongValue (PREF_DOMAIN_INTERFACE, PREF_DEVICE_HEIGHT, &lVal, 10) ? lVal : (long)(SCANHEIGHT*1.5); bool isLandscape = prefs_parseBoolValue (PREF_DOMAIN_INTERFACE, PREF_DEVICE_LANDSCAPE, &bVal) ? bVal : true; + glhud_currentColorScheme = prefs_parseLongValue(PREF_DOMAIN_INTERFACE, PREF_SOFTHUD_COLOR, &lVal, 10) ? (interface_colorscheme_t)lVal : RED_ON_BLACK; + alert_reshape((int)width, (int)height, isLandscape); } diff --git a/src/video/glhudmodel.c b/src/video/glhudmodel.c index 0b7dbdb9..26b35984 100644 --- a/src/video/glhudmodel.c +++ b/src/video/glhudmodel.c @@ -38,6 +38,8 @@ typedef struct EightPatchArgs_s { } while (0); #endif +interface_colorscheme_t glhud_currentColorScheme = RED_ON_BLACK; + // Generates a semi-opaque halo effect around each glyph static void _eightpatch_opaquePixelHaloFilter(const EightPatchArgs_s args) { @@ -134,7 +136,6 @@ void *glhud_createCustom(unsigned int sizeofModel) { GLModelHUDElement *hudElement = (GLModelHUDElement *)CALLOC(sizeofModel, 1); if (hudElement) { hudElement->glyphMultiplier = 1; - hudElement->colorScheme = RED_ON_BLACK; } return hudElement; } @@ -144,6 +145,8 @@ void glhud_setupDefault(GLModel *parent) { GLModelHUDElement *hudElement = (GLModelHUDElement *)parent->custom; assert(hudElement->glyphMultiplier > 0); + hudElement->colorScheme = glhud_currentColorScheme; + char *submenu = (char *)(hudElement->tpl); const unsigned int cols = hudElement->tplWidth; const unsigned int rows = hudElement->tplHeight; diff --git a/src/video/glhudmodel.h b/src/video/glhudmodel.h index 33f92ac0..bde08a92 100644 --- a/src/video/glhudmodel.h +++ b/src/video/glhudmodel.h @@ -63,4 +63,7 @@ void glhud_quadModelToScreen(const GLModel *model, const int screenW, const int // helper method to sync timing of fade out float glhud_getTimedVisibility(struct timespec timingBegin, float minAlpha, float maxAlpha); +// current color of HUD elements +extern interface_colorscheme_t glhud_currentColorScheme; + #endif diff --git a/src/video/gltouchjoy.c b/src/video/gltouchjoy.c index acaaf4a5..8963a8a9 100644 --- a/src/video/gltouchjoy.c +++ b/src/video/gltouchjoy.c @@ -76,6 +76,7 @@ static struct { GLuint vertShader; \ GLuint fragShader; \ GLuint program; \ + GLint uniformSolidColorIdx; \ GLint uniformMVPIdx;); AZIMUTH_CLASS(GLModelJoystickAzimuth); @@ -136,6 +137,7 @@ static void *_azimuth_create_model(GLModel *parent) { azimuthJoystick->vertShader = UNINITIALIZED_GL; azimuthJoystick->fragShader = UNINITIALIZED_GL; azimuthJoystick->program = UNINITIALIZED_GL; + azimuthJoystick->uniformSolidColorIdx = UNINITIALIZED_GL; azimuthJoystick->uniformMVPIdx = UNINITIALIZED_GL; bool err = true; @@ -159,6 +161,14 @@ static void *_azimuth_create_model(GLModel *parent) { // Build/use Program azimuthJoystick->program = glshader_buildProgram(vtxSource, frgSource, /*withTexcoord:*/false, &azimuthJoystick->vertShader, &azimuthJoystick->fragShader); + // Get uniforms locations + + azimuthJoystick->uniformSolidColorIdx = glGetUniformLocation(azimuthJoystick->program, "solidColor"); + if (azimuthJoystick->uniformSolidColorIdx < 0) { + LOG("OOPS, no solidColor uniform in Azimuth shader : %d", azimuthJoystick->uniformSolidColorIdx); + break; + } + azimuthJoystick->uniformMVPIdx = glGetUniformLocation(azimuthJoystick->program, "modelViewProjectionMatrix"); if (azimuthJoystick->uniformMVPIdx < 0) { LOG("OOPS, no modelViewProjectionMatrix in Azimuth shader : %d", azimuthJoystick->uniformMVPIdx); @@ -197,6 +207,33 @@ static void _azimuth_render(void) { glUniformMatrix4fv(azimuthJoystick->uniformMVPIdx, 1, GL_FALSE, mvpIdentity); + // set the solid color values + { + float R = 0.f; + float G = 0.f; + float B = 0.f; + float A = 1.f; + switch (glhud_currentColorScheme) { + case GREEN_ON_BLACK: + G = 1.f; + break; + case GREEN_ON_BLUE: + G = 1.f; // TODO FIXME : background colors ... + break; + case BLUE_ON_BLACK: + B = 1.f; + break; + case WHITE_ON_BLACK: + R = 1.f; G = 1.f; B = 1.f; + break; + case RED_ON_BLACK: + default: + R = 1.f; + break; + } + glUniform4f(azimuthJoystick->uniformSolidColorIdx, R, G, B, A); + } + // NOTE : assuming we should just upload new postion data every time ... glBindBuffer(GL_ARRAY_BUFFER, axes.azimuthModel->posBufferName); glBufferData(GL_ARRAY_BUFFER, axes.azimuthModel->positionArraySize, axes.azimuthModel->positions, GL_DYNAMIC_DRAW); @@ -890,6 +927,8 @@ static void gltouchjoy_applyPrefs(void) { long height = prefs_parseLongValue (PREF_DOMAIN_INTERFACE, PREF_DEVICE_HEIGHT, &lVal, 10) ? lVal : (long)(SCANHEIGHT*1.5); bool isLandscape = prefs_parseBoolValue (PREF_DOMAIN_INTERFACE, PREF_DEVICE_LANDSCAPE, &bVal) ? bVal : true; + glhud_currentColorScheme = prefs_parseLongValue(PREF_DOMAIN_INTERFACE, PREF_SOFTHUD_COLOR, &lVal, 10) ? (interface_colorscheme_t)lVal : RED_ON_BLACK; + gltouchjoy_reshape(width, height, isLandscape); } diff --git a/src/video/gltouchkbd.c b/src/video/gltouchkbd.c index 51401a08..76768e8e 100644 --- a/src/video/gltouchkbd.c +++ b/src/video/gltouchkbd.c @@ -251,7 +251,6 @@ static inline void _switch_keyboard(GLModel *parent, uint8_t *template) { memcpy(hudKeyboard->tpl, template, sizeof(kbdTemplateUCase/* assuming all the same size */)); // setup normal color pixels - hudKeyboard->colorScheme = RED_ON_BLACK; glhud_setupDefault(parent); // find the CTRL visual(s) and render them engaged @@ -518,9 +517,6 @@ static void *_create_touchkbd_hud(GLModel *parent) { memcpy(hudKeyboard->tpl, template, sizeof(kbdTemplateUCase/* assuming all the same dimensions */)); - // setup normal color pixels - hudKeyboard->colorScheme = RED_ON_BLACK; - glhud_setupDefault(parent); return hudKeyboard; @@ -917,7 +913,6 @@ static void gltouchkbd_applyPrefs(void) { if (kbd.model) { GLModelHUDElement *hudKeyboard = (GLModelHUDElement *)kbd.model->custom; - hudKeyboard->colorScheme = RED_ON_BLACK; glhud_setupDefault(kbd.model); } @@ -936,6 +931,8 @@ static void gltouchkbd_applyPrefs(void) { long height = prefs_parseLongValue (PREF_DOMAIN_INTERFACE, PREF_DEVICE_HEIGHT, &lVal, 10) ? lVal : (long)(SCANHEIGHT*1.5); bool isLandscape = prefs_parseBoolValue (PREF_DOMAIN_INTERFACE, PREF_DEVICE_LANDSCAPE, &bVal) ? bVal : true; + glhud_currentColorScheme = prefs_parseLongValue(PREF_DOMAIN_INTERFACE, PREF_SOFTHUD_COLOR, &lVal, 10) ? (interface_colorscheme_t)lVal : RED_ON_BLACK; + gltouchkbd_reshape(width, height, isLandscape); } diff --git a/src/video/gltouchmenu.c b/src/video/gltouchmenu.c index 9a20beca..2c7a440f 100644 --- a/src/video/gltouchmenu.c +++ b/src/video/gltouchmenu.c @@ -85,8 +85,6 @@ static void gltouchmenu_applyPrefs(void); static inline void _present_menu(GLModel *parent) { GLModelHUDElement *hudMenu = (GLModelHUDElement *)parent->custom; memcpy(hudMenu->tpl, topMenuTemplate, sizeof(topMenuTemplate)); - - hudMenu->colorScheme = RED_ON_BLACK; glhud_setupDefault(parent); } @@ -611,6 +609,8 @@ static void gltouchmenu_applyPrefs(void) { long height = prefs_parseLongValue (PREF_DOMAIN_INTERFACE, PREF_DEVICE_HEIGHT, &lVal, 10) ? lVal : (long)(SCANHEIGHT*1.5); bool isLandscape = prefs_parseBoolValue (PREF_DOMAIN_INTERFACE, PREF_DEVICE_LANDSCAPE, &bVal) ? bVal : true; + glhud_currentColorScheme = prefs_parseLongValue(PREF_DOMAIN_INTERFACE, PREF_SOFTHUD_COLOR, &lVal, 10) ? (interface_colorscheme_t)lVal : RED_ON_BLACK; + gltouchmenu_reshape(width, height, isLandscape); } diff --git a/src/video/ncvideo.c b/src/video/ncvideo.c index 18966b14..cebf0fce 100644 --- a/src/video/ncvideo.c +++ b/src/video/ncvideo.c @@ -441,6 +441,9 @@ static void _nc_initColors(void) { init_pair(1+GREEN_ON_BLACK, COLOR_GREEN, COLOR_BLACK ); init_pair(1+GREEN_ON_BLUE, COLOR_GREEN, COLOR_BLUE ); init_pair(1+RED_ON_BLACK, COLOR_RED, COLOR_BLACK ); + init_pair(1+BLUE_ON_BLACK, COLOR_BLUE, COLOR_BLACK ); + init_pair(1+WHITE_ON_BLACK, COLOR_WHITE, COLOR_BLACK ); + init_pair(1+BLACK_ON_RED, COLOR_BLACK, COLOR_RED ); // 16 COLORS: