diff options
author | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
---|---|---|
committer | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
commit | abef6da56913f1c55528103e60a50451a39628b1 (patch) | |
tree | b3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/Window_Switch.c |
initial commit
Diffstat (limited to 'src/Window_Switch.c')
-rw-r--r-- | src/Window_Switch.c | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/src/Window_Switch.c b/src/Window_Switch.c new file mode 100644 index 0000000..fe892ed --- /dev/null +++ b/src/Window_Switch.c @@ -0,0 +1,309 @@ +#include "Core.h" +#if defined CC_BUILD_SWITCH +#include "_WindowBase.h" +#include "Window.h" +#include "Platform.h" +#include "Input.h" +#include "Event.h" +#include "Graphics.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Errors.h" +#include "ExtMath.h" +#include "Input.h" +#include "Gui.h" +#include <switch.h> + +static cc_bool launcherMode; +static Framebuffer fb; +static PadState pad; +static AppletHookCookie cookie; + +struct _DisplayData DisplayInfo; +struct _WindowData WindowInfo; + +static void SetResolution(void) { + // check whether the Switch is docked + // use 720p for handheld, 1080p for docked + AppletOperationMode opMode = appletGetOperationMode(); + int w = 1280; + int h = 720; + if (opMode == AppletOperationMode_Console) { + w = 1920; + h = 1080; + } + + DisplayInfo.Width = w; + DisplayInfo.Height = h; + + Window_Main.Width = w; + Window_Main.Height = h; +} + +static void Applet_Event(AppletHookType type, void* param) { + if (type == AppletHookType_OnOperationMode) { + SetResolution(); + Event_RaiseVoid(&WindowEvents.Resized); + } else if (type == AppletHookType_OnExitRequest) { + Window_Main.Exists = false; + Window_RequestClose(); + } +} + +void Window_PreInit(void) { + // Configure our supported input layout: a single player with standard controller styles + padConfigureInput(1, HidNpadStyleSet_NpadStandard); + hidInitializeTouchScreen(); + // Initialize the default gamepad (which reads handheld mode inputs as well as the first connected controller) + padInitializeDefault(&pad); + + appletHook(&cookie, Applet_Event, NULL); +} + +void Window_Init(void) { + DisplayInfo.Depth = 4; // 32 bit TODO wrong, this is actually 4 bit + DisplayInfo.ScaleX = 1; + DisplayInfo.ScaleY = 1; + + Window_Main.Focused = true; + Window_Main.Exists = true; + Window_Main.Handle = nwindowGetDefault(); + + Window_Main.SoftKeyboard = SOFT_KEYBOARD_RESIZE; + Input_SetTouchMode(true); + Gui_SetTouchUI(true); + Input.Sources = INPUT_SOURCE_GAMEPAD; + + nwindowSetDimensions(Window_Main.Handle, 1920, 1080); + SetResolution(); +} + +void Window_Free(void) { + appletUnhook(&cookie); +} + +void Window_Create2D(int width, int height) { + launcherMode = true; +} +void Window_Create3D(int width, int height) { + launcherMode = false; +} + +void Window_SetTitle(const cc_string* title) { } +void Clipboard_GetText(cc_string* value) { } +void Clipboard_SetText(const cc_string* value) { } + +int Window_GetWindowState(void) { return WINDOW_STATE_FULLSCREEN; } +cc_result Window_EnterFullscreen(void) { return 0; } +cc_result Window_ExitFullscreen(void) { return 0; } +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { } +void Window_SetSize(int width, int height) { } + +void Window_RequestClose(void) { + Event_RaiseVoid(&WindowEvents.Closing); +} + + +/*########################################################################################################################* +*----------------------------------------------------Input processing-----------------------------------------------------* +*#########################################################################################################################*/ +static void ProcessTouchInput(void) { + static int prev_touchcount = 0; + HidTouchScreenState state = {0}; + hidGetTouchScreenStates(&state, 1); + + if (state.count) { + Input_AddTouch(0, state.touches[0].x, state.touches[0].y); + } else if (prev_touchcount) { + Input_RemoveTouch(0, Pointers[0].x, Pointers[0].y); + } + prev_touchcount = state.count; +} + +void Window_ProcessEvents(float delta) { + // Scan the gamepad. This should be done once for each frame + padUpdate(&pad); + + if (!appletMainLoop()) { + Window_Main.Exists = false; + Window_RequestClose(); + return; + } + ProcessTouchInput(); +} + +void Cursor_SetPosition(int x, int y) { } // Makes no sense for PSP +void Window_EnableRawMouse(void) { Input.RawMode = true; } +void Window_DisableRawMouse(void) { Input.RawMode = false; } + +void Window_UpdateRawMouse(void) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Gamepads----------------------------------------------------------* +*#########################################################################################################################*/ +static void HandleButtons(int port, u64 mods) { + Gamepad_SetButton(port, CCPAD_L, mods & HidNpadButton_L); + Gamepad_SetButton(port, CCPAD_R, mods & HidNpadButton_R); + + Gamepad_SetButton(port, CCPAD_A, mods & HidNpadButton_A); + Gamepad_SetButton(port, CCPAD_B, mods & HidNpadButton_B); + Gamepad_SetButton(port, CCPAD_X, mods & HidNpadButton_X); + Gamepad_SetButton(port, CCPAD_Y, mods & HidNpadButton_Y); + + Gamepad_SetButton(port, CCPAD_START, mods & HidNpadButton_Plus); + Gamepad_SetButton(port, CCPAD_SELECT, mods & HidNpadButton_Minus); + + Gamepad_SetButton(port, CCPAD_LEFT, mods & HidNpadButton_Left); + Gamepad_SetButton(port, CCPAD_RIGHT, mods & HidNpadButton_Right); + Gamepad_SetButton(port, CCPAD_UP, mods & HidNpadButton_Up); + Gamepad_SetButton(port, CCPAD_DOWN, mods & HidNpadButton_Down); +} + +#define AXIS_SCALE 512.0f +static void ProcessJoystickInput(int port, int axis, HidAnalogStickState* pos, float delta) { + // May not be exactly 0 on actual hardware + if (Math_AbsI(pos->x) <= 16) pos->x = 0; + if (Math_AbsI(pos->y) <= 16) pos->y = 0; + + Gamepad_SetAxis(port, axis, pos->x / AXIS_SCALE, -pos->y / AXIS_SCALE, delta); +} + +void Window_ProcessGamepads(float delta) { + u64 keys = padGetButtons(&pad); + HandleButtons(0, keys); + + // Read the sticks' position + HidAnalogStickState analog_stick_l = padGetStickPos(&pad, 0); + HidAnalogStickState analog_stick_r = padGetStickPos(&pad, 1); + ProcessJoystickInput(0, PAD_AXIS_LEFT, &analog_stick_l, delta); + ProcessJoystickInput(0, PAD_AXIS_RIGHT, &analog_stick_r, delta); +} + + +/*########################################################################################################################* +*------------------------------------------------------Framebuffer--------------------------------------------------------* +*#########################################################################################################################*/ +void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { + framebufferCreate(&fb, nwindowGetDefault(), DisplayInfo.Width, DisplayInfo.Height, PIXEL_FORMAT_BGRA_8888, 2); + framebufferMakeLinear(&fb); + + bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, 4, "window pixels"); + bmp->width = width; + bmp->height = height; +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + // Retrieve the framebuffer + cc_uint32 stride; + cc_uint32* framebuf = (cc_uint32*)framebufferBegin(&fb, &stride); + + // flip upside down + for (cc_uint32 y = r.y; y < r.y + r.height; y++) + { + BitmapCol* src = Bitmap_GetRow(bmp, y); + cc_uint32* dst = framebuf + y * stride / sizeof(cc_uint32); + + for (cc_uint32 x = r.x; x < r.x + r.width; x++) + { + dst[x] = src[x]; + } + } + + // We're done rendering, so we end the frame here. + framebufferEnd(&fb); +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + framebufferClose(&fb); + Mem_Free(bmp->scan0); +} + +/*########################################################################################################################* +*-----------------------------------------------------OpenGL context------------------------------------------------------* +*#########################################################################################################################*/ +static void GLContext_InitSurface(void) { + NWindow* window = (NWindow*)Window_Main.Handle; + if (!window) return; /* window not created or lost */ + + // terrible, but fixes 720p/1080p resolution change on handheld/docked modes + int real_w = window->width; + int real_h = window->height; + window->width = Window_Main.Width; + window->height = Window_Main.Height; + + ctx_surface = eglCreateWindowSurface(ctx_display, ctx_config, window, NULL); + window->width = real_w; + window->height = real_h; + + if (!ctx_surface) return; + eglMakeCurrent(ctx_display, ctx_surface, ctx_surface, ctx_context); +} + +/*########################################################################################################################* +*------------------------------------------------------Soft keyboard------------------------------------------------------* +*#########################################################################################################################*/ +static void OnscreenTextChanged(const char* text) { + char tmpBuffer[NATIVE_STR_LEN]; + cc_string tmp = String_FromArray(tmpBuffer); + String_AppendUtf8(&tmp, text, String_Length(text)); + + Event_RaiseString(&InputEvents.TextChanged, &tmp); +} + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { + const char* btnText = args->type & KEYBOARD_FLAG_SEND ? "Send" : "Enter"; + char input[NATIVE_STR_LEN] = { 0 }; + char output[NATIVE_STR_LEN] = { 0 }; + String_EncodeUtf8(input, args->text); + + int mode = args->type & 0xFF; + SwkbdType type = (mode == KEYBOARD_TYPE_NUMBER || mode == KEYBOARD_TYPE_INTEGER) ? SwkbdType_NumPad : SwkbdType_Normal; + + SwkbdConfig kbd; + swkbdCreate(&kbd, 0); + + if (mode == KEYBOARD_TYPE_PASSWORD) { + swkbdConfigMakePresetPassword(&kbd); + } else { + swkbdConfigMakePresetDefault(&kbd); + swkbdConfigSetType(&kbd, type); + } + + swkbdConfigSetInitialText(&kbd, input); + swkbdConfigSetGuideText(&kbd, args->placeholder); + swkbdConfigSetOkButtonText(&kbd, btnText); + + Result rc = swkbdShow(&kbd, output, sizeof(output)); + if (R_SUCCEEDED(rc)) + OnscreenTextChanged(output); + + swkbdClose(&kbd); +} +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } +void OnscreenKeyboard_Draw3D(void) { } +void OnscreenKeyboard_Close(void) { /* TODO implement */ } + + +/*########################################################################################################################* +*-------------------------------------------------------Misc/Other--------------------------------------------------------* +*#########################################################################################################################*/ +//void Window_ShowDialog(const char* title, const char* msg) { +static void ShowDialogCore(const char* title, const char* msg) { + ErrorApplicationConfig c; + errorApplicationCreate(&c, title, msg); + errorApplicationShow(&c); +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} +#endif |