diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp index fc606186a1..5e866d1366 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp @@ -60,6 +60,20 @@ OskDialogBase::~OskDialogBase() { } +struct osk_window_layout +{ + u32 layout_mode = CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT | CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP; + u32 x_align = CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT; + u32 y_align = CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP; + f32 x_offset = 0.0f; + f32 y_offset = 0.0f; + + std::string to_string() const + { + return fmt::format("{ layout_mode=0x%x, x_align=0x%x, y_align=0x%x, x_offset=%.2f, y_offset=%.2f }", layout_mode, x_align, y_align, x_offset, y_offset); + } +}; + struct osk_info { std::shared_ptr dlg; @@ -73,8 +87,8 @@ struct osk_info atomic_t device_mask = 0; // OSK ignores input from the specified devices. 0 means all devices can influence the OSK atomic_t input_field_window_width = 0; atomic_t input_field_background_transparency = 0.0f; - CellOskDialogLayoutInfo input_field_layout_info{}; - CellOskDialogLayoutInfo input_panel_layout_info{}; + osk_window_layout input_field_layout_info{}; + osk_window_layout input_panel_layout_info{}; atomic_t key_layout_options = CELL_OSKDIALOG_10KEY_PANEL; atomic_t initial_key_layout = CELL_OSKDIALOG_INITIAL_PANEL_LAYOUT_SYSTEM; // TODO: use atomic_t initial_input_device = CELL_OSKDIALOG_INPUT_DEVICE_PAD; // OSK at first only receives input from the initial device @@ -90,9 +104,7 @@ struct osk_info CellOskDialogPoint pointer_pos{0.0f, 0.0f}; atomic_t initial_scale = 1.0f; - atomic_t layout_mode = CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT | CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP; - atomic_t x_align = CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT; - atomic_t y_align = CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP; + osk_window_layout layout = {}; atomic_t osk_continuous_mode = CELL_OSKDIALOG_CONTINUOUS_MODE_NONE; atomic_t last_dialog_state = CELL_SYSUTIL_OSKDIALOG_UNLOADED; // Used for continuous seperate window dialog @@ -128,9 +140,7 @@ struct osk_info pointer_enabled = false; pointer_pos = {0.0f, 0.0f}; initial_scale = 1.0f; - layout_mode = CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT | CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP; - x_align = CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT; - y_align = CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP; + layout = {}; osk_continuous_mode = CELL_OSKDIALOG_CONTINUOUS_MODE_NONE; last_dialog_state = CELL_SYSUTIL_OSKDIALOG_UNLOADED; osk_confirm_callback.store({}); @@ -220,6 +230,9 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia return CELL_OSKDIALOG_ERROR_PARAM; } + cellOskDialog.notice("cellOskDialogLoadAsync: dialogParam={ allowOskPanelFlg=0x%x, prohibitFlgs=0x%x, firstViewPanel=%d, controlPoint=(%.2f,%.2f) }", + dialogParam->allowOskPanelFlg, dialogParam->prohibitFlgs, dialogParam->firstViewPanel, dialogParam->controlPoint.x, dialogParam->controlPoint.y); + auto osk = _get_osk_dialog(true); // Can't open another dialog if this one is already open. @@ -234,6 +247,8 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia const u32 prohibitFlgs = dialogParam->prohibitFlgs; const u32 allowOskPanelFlg = dialogParam->allowOskPanelFlg; const u32 firstViewPanel = dialogParam->firstViewPanel; + info.layout.x_offset = dialogParam->controlPoint.x; + info.layout.y_offset = dialogParam->controlPoint.y; // Get init text and prepare return value osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK; @@ -596,8 +611,10 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia .panel_flag = allowOskPanelFlg, .support_language = info.supported_languages, .first_view_panel = firstViewPanel, - .x_align = info.x_align, - .y_align = info.y_align, + .x_align = info.layout.x_align, + .y_align = info.layout.y_align, + .x_offset = info.layout.x_offset, + .y_offset = info.layout.y_offset, .initial_scale = info.initial_scale, .base_color = info.base_color.load(), .dimmer_enabled = info.dimmer_enabled.load(), @@ -832,11 +849,14 @@ error_code cellOskDialogSetSeparateWindowOption(vm::ptr(windowOption->inputFieldBackgroundTrans, 0.0f, 1.0f); // Choose proper alignments, since the devs didn't make them exclusive for some reason. - const auto aligned_layout = [](const CellOskDialogLayoutInfo& info) -> CellOskDialogLayoutInfo + const auto aligned_layout = [](const CellOskDialogLayoutInfo& info) -> osk_window_layout { - CellOskDialogLayoutInfo res = info; - res.position.x = osk_info::get_aligned_x(res.layoutMode); - res.position.y = osk_info::get_aligned_y(res.layoutMode); + osk_window_layout res{}; + res.layout_mode = info.layoutMode; + res.x_align = osk_info::get_aligned_x(res.layout_mode); + res.y_align = osk_info::get_aligned_y(res.layout_mode); + res.x_offset = info.position.x; + res.y_offset = info.position.y; return res; }; @@ -853,7 +873,8 @@ error_code cellOskDialogSetSeparateWindowOption(vm::ptrget(); - osk.layout_mode = layoutMode; + osk.layout.layout_mode = layoutMode; // Choose proper alignments, since the devs didn't make them exclusive for some reason. - osk.x_align = osk_info::get_aligned_x(layoutMode); - osk.y_align = osk_info::get_aligned_y(layoutMode); + osk.layout.x_align = osk_info::get_aligned_x(layoutMode); + osk.layout.y_align = osk_info::get_aligned_y(layoutMode); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.h b/rpcs3/Emu/Cell/Modules/cellOskDialog.h index c0674cb1d5..e68809a9b4 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.h +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.h @@ -273,6 +273,8 @@ public: u32 first_view_panel = 0; u32 x_align = 0; u32 y_align = 0; + f32 x_offset = 0.0f; + f32 y_offset = 0.0f; f32 initial_scale = 1.0f; color base_color{}; bool dimmer_enabled = false; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp b/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp index 7829e3ff3d..f0e87dc7cc 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp @@ -223,42 +223,43 @@ namespace rsx const u16 preview_height = get_scaled((flags & CELL_OSKDIALOG_NO_RETURN) ? 40 : 90); // Place elements with absolute positioning - const u16 margin = get_scaled(100); const u16 button_margin = get_scaled(30); const u16 button_height = get_scaled(30); const u16 frame_w = num_columns * cell_size_x; const u16 frame_h = num_rows * cell_size_y + title_height + preview_height; - u16 frame_x = 0; - u16 frame_y = 0; + f32 origin_x = 0.0f; + f32 origin_y = 0.0f; switch (m_x_align) { - case CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT: - frame_x = margin; - break; case CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_RIGHT: - frame_x = virtual_width - (frame_w + margin); + origin_x = virtual_width; break; case CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_CENTER: + origin_x = static_cast(virtual_width - frame_w) / 2.0f; + break; + case CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT: default: - frame_x = (virtual_width - frame_w) / 2; break; } switch (m_y_align) { - case CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP: - frame_y = margin; - break; case CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_BOTTOM: - frame_y = virtual_height - (frame_h + button_height + button_margin + margin); + origin_y = virtual_height; break; case CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_CENTER: + origin_y = static_cast(virtual_height - frame_h) / 2.0f; + break; + case CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP: default: - frame_y = (virtual_height - (frame_h + button_height + button_margin)) / 2; break; } + constexpr f32 margin = 50.0f; // Let's add a minimal margin on all sides + const u16 frame_x = static_cast(std::clamp(origin_x + m_x_offset, margin, static_cast(virtual_width - frame_w) - margin)); + const u16 frame_y = static_cast(std::clamp(origin_y + m_y_offset, margin, static_cast(virtual_height - (frame_h + button_height + button_margin)) - margin)); + m_frame.set_pos(frame_x, frame_y); m_frame.set_size(frame_w, frame_h); @@ -1034,6 +1035,8 @@ namespace rsx char_limit = params.charlimit; m_x_align = params.x_align; m_y_align = params.y_align; + m_x_offset = params.x_offset; + m_y_offset = params.y_offset; m_scaling = params.initial_scale; m_frame.back_color.r = params.base_color.r; m_frame.back_color.g = params.base_color.g; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_osk.h b/rpcs3/Emu/RSX/Overlays/overlay_osk.h index 0c4007260f..e97f967a35 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_osk.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_osk.h @@ -41,6 +41,8 @@ namespace rsx // Base UI u32 m_x_align = 0; u32 m_y_align = 0; + f32 m_x_offset = 0.0f; + f32 m_y_offset = 0.0f; f32 m_scaling = 1.0f; overlay_element m_frame; overlay_element m_background;