mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-23 03:02:53 +01:00
cellGem/overlays: show cursor if necessary
This commit is contained in:
parent
3840015e7d
commit
b683110e72
@ -430,6 +430,7 @@ target_sources(rpcs3_emu PRIVATE
|
||||
RSX/Null/NullGSRender.cpp
|
||||
RSX/Overlays/overlay_animation.cpp
|
||||
RSX/Overlays/overlay_controls.cpp
|
||||
RSX/Overlays/overlay_cursor.cpp
|
||||
RSX/Overlays/overlay_edit_text.cpp
|
||||
RSX/Overlays/overlay_fonts.cpp
|
||||
RSX/Overlays/overlay_list_view.cpp
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "Emu/system_config.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/RSX/Overlays/overlay_cursor.h"
|
||||
#include "Input/pad_thread.h"
|
||||
|
||||
#include <cmath> // for fmod
|
||||
@ -107,6 +108,23 @@ public:
|
||||
g = std::clamp(g_, 0.0f, 1.0f);
|
||||
b = std::clamp(b_, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
static inline const gem_color& get_default_color(u32 gem_num)
|
||||
{
|
||||
static const gem_color gold = gem_color(1.0f, 0.85f, 0.0f);
|
||||
static const gem_color green = gem_color(0.0f, 1.0f, 0.0f);
|
||||
static const gem_color red = gem_color(1.0f, 0.0f, 0.0f);
|
||||
static const gem_color pink = gem_color(0.9f, 0.0f, 0.5f);
|
||||
|
||||
switch (gem_num)
|
||||
{
|
||||
case 0: return green;
|
||||
case 1: return gold;
|
||||
case 2: return red;
|
||||
case 3: return pink;
|
||||
default: fmt::throw_exception("unexpected gem_num %d", gem_num);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct gem_controller
|
||||
@ -183,6 +201,11 @@ public:
|
||||
|
||||
void reset_controller(u32 gem_num)
|
||||
{
|
||||
if (gem_num >= CELL_GEM_MAX_NUM)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (g_cfg.io.move)
|
||||
{
|
||||
case move_handler::fake:
|
||||
@ -196,12 +219,15 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
gem_controller& controller = controllers.at(gem_num);
|
||||
controller = {};
|
||||
controller.sphere_rgb = gem_color::get_default_color(gem_num);
|
||||
|
||||
// Assign status and port number
|
||||
if (gem_num < connected_controllers)
|
||||
{
|
||||
controllers[gem_num] = {};
|
||||
controllers[gem_num].status = CELL_GEM_STATUS_READY;
|
||||
controllers[gem_num].port = 7u - gem_num;
|
||||
controller.status = CELL_GEM_STATUS_READY;
|
||||
controller.port = CELL_PAD_MAX_PORT_NUM - gem_num;
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,7 +446,19 @@ static bool check_gem_num(const u32 gem_num)
|
||||
return gem_num < CELL_GEM_MAX_NUM;
|
||||
}
|
||||
|
||||
static inline void pos_to_gem_image_state(const gem_config::gem_controller& controller, vm::ptr<CellGemImageState>& gem_image_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
|
||||
static inline void draw_overlay_cursor(u32 gem_num, const gem_config::gem_controller& controller, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
|
||||
{
|
||||
const u16 x = static_cast<u16>(x_pos / (x_max / static_cast<f32>(rsx::overlays::overlay::virtual_width)));
|
||||
const u16 y = static_cast<u16>(y_pos / (y_max / static_cast<f32>(rsx::overlays::overlay::virtual_height)));
|
||||
|
||||
// Note: We shouldn't use sphere_rgb here. The game will set it to black in many cases.
|
||||
const gem_config_data::gem_color& rgb = gem_config_data::gem_color::get_default_color(gem_num);
|
||||
const color4f color = { rgb.r, rgb.g, rgb.b, 0.85f };
|
||||
|
||||
rsx::overlays::set_cursor(rsx::overlays::cursor_offset::cell_gem + gem_num, x, y, color, 2'000'000, false);
|
||||
}
|
||||
|
||||
static inline void pos_to_gem_image_state(u32 gem_num, const gem_config::gem_controller& controller, vm::ptr<CellGemImageState>& gem_image_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
|
||||
{
|
||||
const auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
|
||||
@ -450,9 +488,14 @@ static inline void pos_to_gem_image_state(const gem_config::gem_controller& cont
|
||||
// Projected camera coordinates in mm
|
||||
gem_image_state->projectionx = camera_x / controller.distance;
|
||||
gem_image_state->projectiony = camera_y / controller.distance;
|
||||
|
||||
if (g_cfg.io.show_move_cursor)
|
||||
{
|
||||
draw_overlay_cursor(gem_num, controller, x_pos, y_pos, x_max, y_max);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void pos_to_gem_state(const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
|
||||
static inline void pos_to_gem_state(u32 gem_num, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
|
||||
{
|
||||
const auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
|
||||
@ -490,6 +533,11 @@ static inline void pos_to_gem_state(const gem_config::gem_controller& controller
|
||||
gem_state->handle_pos[1] = camera_y;
|
||||
gem_state->handle_pos[2] = static_cast<f32>(controller.distance + 10);
|
||||
gem_state->handle_pos[3] = 0.f;
|
||||
|
||||
if (g_cfg.io.show_move_cursor)
|
||||
{
|
||||
draw_overlay_cursor(gem_num, controller, x_pos, y_pos, x_max, y_max);
|
||||
}
|
||||
}
|
||||
|
||||
extern bool is_input_allowed();
|
||||
@ -587,10 +635,10 @@ static inline void ds3_get_stick_values(const std::shared_ptr<Pad>& pad, s32& x_
|
||||
switch (stick.m_offset)
|
||||
{
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X:
|
||||
x_pos = stick.m_value - 128;
|
||||
x_pos = stick.m_value;
|
||||
break;
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
|
||||
y_pos = stick.m_value - 128;
|
||||
y_pos = stick.m_value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -618,7 +666,7 @@ static void ds3_pos_to_gem_image_state(const u32 port_no, const gem_config::gem_
|
||||
s32 ds3_pos_x, ds3_pos_y;
|
||||
ds3_get_stick_values(pad, ds3_pos_x, ds3_pos_y);
|
||||
|
||||
pos_to_gem_image_state(controller, gem_image_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
pos_to_gem_image_state(port_no, controller, gem_image_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
}
|
||||
|
||||
static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state)
|
||||
@ -641,7 +689,7 @@ static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_contro
|
||||
s32 ds3_pos_x, ds3_pos_y;
|
||||
ds3_get_stick_values(pad, ds3_pos_x, ds3_pos_y);
|
||||
|
||||
pos_to_gem_state(controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
pos_to_gem_state(port_no, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -776,7 +824,7 @@ static void mouse_pos_to_gem_image_state(const u32 mouse_no, const gem_config::g
|
||||
|
||||
const auto& mouse = handler.GetMice().at(mouse_no);
|
||||
|
||||
pos_to_gem_image_state(controller, gem_image_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
|
||||
pos_to_gem_image_state(mouse_no, controller, gem_image_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
|
||||
}
|
||||
|
||||
static void mouse_pos_to_gem_state(const u32 mouse_no, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state)
|
||||
@ -800,7 +848,7 @@ static void mouse_pos_to_gem_state(const u32 mouse_no, const gem_config::gem_con
|
||||
|
||||
const auto& mouse = handler.GetMice().at(mouse_no);
|
||||
|
||||
pos_to_gem_state(controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
|
||||
pos_to_gem_state(mouse_no, controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
|
||||
}
|
||||
|
||||
// *********************
|
||||
@ -1319,7 +1367,7 @@ error_code cellGemGetRGB(u32 gem_num, vm::ptr<float> r, vm::ptr<float> g, vm::pt
|
||||
return CELL_GEM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
auto& sphere_color = gem.controllers[gem_num].sphere_rgb;
|
||||
const gem_config_data::gem_color& sphere_color = gem.controllers[gem_num].sphere_rgb;
|
||||
*r = sphere_color.r;
|
||||
*g = sphere_color.g;
|
||||
*b = sphere_color.b;
|
||||
|
150
rpcs3/Emu/RSX/Overlays/overlay_cursor.cpp
Normal file
150
rpcs3/Emu/RSX/Overlays/overlay_cursor.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include "stdafx.h"
|
||||
#include "overlay_cursor.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
namespace overlays
|
||||
{
|
||||
cursor_item::cursor_item()
|
||||
{
|
||||
m_cross_h.set_size(15, 1);
|
||||
m_cross_v.set_size(1, 15);
|
||||
}
|
||||
|
||||
bool cursor_item::set_position(u16 x, u16 y)
|
||||
{
|
||||
if (m_x == x && m_y == y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
|
||||
m_cross_h.set_pos(m_x - m_cross_h.w / 2, m_y - m_cross_h.h / 2);
|
||||
m_cross_v.set_pos(m_x - m_cross_v.w / 2, m_y - m_cross_v.h / 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cursor_item::set_color(color4f color)
|
||||
{
|
||||
if (m_cross_h.back_color == color && m_cross_v.back_color == color)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_cross_h.back_color = color;
|
||||
m_cross_h.refresh();
|
||||
|
||||
m_cross_v.back_color = color;
|
||||
m_cross_v.refresh();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cursor_item::set_expiration(u64 expiration_time)
|
||||
{
|
||||
m_expiration_time = expiration_time;
|
||||
}
|
||||
|
||||
bool cursor_item::update_visibility(u64 time)
|
||||
{
|
||||
m_visible = time <= m_expiration_time;
|
||||
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
compiled_resource cursor_item::get_compiled()
|
||||
{
|
||||
if (!m_visible)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
compiled_resource cr = m_cross_h.get_compiled();
|
||||
cr.add(m_cross_v.get_compiled());
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
void cursor_manager::update()
|
||||
{
|
||||
if (!visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
const u64 cur_time = get_system_time();
|
||||
bool any_cursor_visible = false;
|
||||
|
||||
for (auto& entry : m_cursors)
|
||||
{
|
||||
any_cursor_visible |= entry.second.update_visibility(cur_time);
|
||||
}
|
||||
|
||||
if (!any_cursor_visible)
|
||||
{
|
||||
visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
compiled_resource cursor_manager::get_compiled()
|
||||
{
|
||||
if (!visible)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
compiled_resource cr{};
|
||||
|
||||
for (auto& entry : m_cursors)
|
||||
{
|
||||
cr.add(entry.second.get_compiled());
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
void cursor_manager::update_cursor(u32 id, u16 x, u16 y, const color4f& color, u64 duration_us, bool force_update)
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
cursor_item& cursor = m_cursors[id];
|
||||
|
||||
bool is_dirty = cursor.set_position(x, y);
|
||||
is_dirty |= cursor.set_color(color);
|
||||
|
||||
if (is_dirty || force_update)
|
||||
{
|
||||
const u64 expiration_time = get_system_time() + duration_us;
|
||||
cursor.set_expiration(expiration_time);
|
||||
|
||||
if (cursor.update_visibility(expiration_time))
|
||||
{
|
||||
visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_cursor(u32 id, u16 x, u16 y, const color4f& color, u64 duration_us, bool force_update)
|
||||
{
|
||||
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())
|
||||
{
|
||||
auto cursor_overlay = manager->get<rsx::overlays::cursor_manager>();
|
||||
if (!cursor_overlay)
|
||||
{
|
||||
cursor_overlay = std::make_shared<rsx::overlays::cursor_manager>();
|
||||
cursor_overlay = manager->add(cursor_overlay);
|
||||
}
|
||||
cursor_overlay->update_cursor(id, x, y, color, duration_us, force_update);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace overlays
|
||||
} // namespace rsx
|
54
rpcs3/Emu/RSX/Overlays/overlay_cursor.h
Normal file
54
rpcs3/Emu/RSX/Overlays/overlay_cursor.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "overlays.h"
|
||||
#include <map>
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
namespace overlays
|
||||
{
|
||||
enum cursor_offset : u32
|
||||
{
|
||||
cell_gem = 0, // CELL_GEM_MAX_NUM = 4 Move controllers
|
||||
last = 4
|
||||
};
|
||||
|
||||
class cursor_item
|
||||
{
|
||||
public:
|
||||
cursor_item();
|
||||
|
||||
void set_expiration(u64 expiration_time);
|
||||
bool set_position(u16 x, u16 y);
|
||||
bool set_color(color4f color);
|
||||
|
||||
bool update_visibility(u64 time);
|
||||
|
||||
compiled_resource get_compiled();
|
||||
|
||||
private:
|
||||
bool m_visible = false;
|
||||
overlay_element m_cross_h{};
|
||||
overlay_element m_cross_v{};
|
||||
u64 m_expiration_time = 0;
|
||||
u16 m_x = 0;
|
||||
u16 m_y = 0;
|
||||
};
|
||||
|
||||
class cursor_manager final : public overlay
|
||||
{
|
||||
public:
|
||||
void update() override;
|
||||
compiled_resource get_compiled() override;
|
||||
|
||||
void update_cursor(u32 id, u16 x, u16 y, const color4f& color, u64 duration_us, bool force_update);
|
||||
|
||||
private:
|
||||
shared_mutex m_mutex;
|
||||
std::map<u32, cursor_item> m_cursors;
|
||||
};
|
||||
|
||||
void set_cursor(u32 id, u16 x, u16 y, const color4f& color, u64 duration_us, bool force_update);
|
||||
|
||||
} // namespace overlays
|
||||
} // namespace rsx
|
@ -26,7 +26,7 @@ namespace rsx
|
||||
usz m_cur_pos = umax;
|
||||
};
|
||||
|
||||
class message final : public user_interface
|
||||
class message final : public overlay
|
||||
{
|
||||
public:
|
||||
void update() override;
|
||||
|
@ -22,8 +22,8 @@ namespace rsx
|
||||
u32 uid = umax;
|
||||
u32 type_index = umax;
|
||||
|
||||
u16 virtual_width = 1280;
|
||||
u16 virtual_height = 720;
|
||||
static const u16 virtual_width = 1280;
|
||||
static const u16 virtual_height = 720;
|
||||
|
||||
u32 min_refresh_duration_us = 16600;
|
||||
atomic_t<bool> visible = false;
|
||||
|
@ -280,6 +280,7 @@ struct cfg_root : cfg::node
|
||||
cfg::_enum<pad_handler_mode> pad_mode{this, "Pad handler mode", pad_handler_mode::single_threaded, true};
|
||||
cfg::uint<0, 100'000> pad_sleep{this, "Pad handler sleep (microseconds)", 1'000, true};
|
||||
cfg::_bool background_input_enabled{this, "Background input enabled", true, true};
|
||||
cfg::_bool show_move_cursor{this, "Show move cursor", false, true};
|
||||
} io{ this };
|
||||
|
||||
struct node_sys : cfg::node
|
||||
|
@ -78,6 +78,7 @@
|
||||
<ClCompile Include="Emu\perf_monitor.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Common\texture_cache.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_controls.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_cursor.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_media_list_dialog.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_osk_panel.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_user_list_dialog.cpp" />
|
||||
@ -506,6 +507,7 @@
|
||||
<ClInclude Include="Emu\RSX\Common\ranged_map.hpp" />
|
||||
<ClInclude Include="Emu\RSX\Common\simple_array.hpp" />
|
||||
<ClInclude Include="Emu\RSX\Common\time.hpp" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_cursor.h" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_edit_text.hpp" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_list_view.hpp" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_media_list_dialog.h" />
|
||||
|
@ -1081,6 +1081,9 @@
|
||||
<ClCompile Include="Loader\disc.cpp">
|
||||
<Filter>Loader</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_cursor.cpp">
|
||||
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
@ -2149,6 +2152,9 @@
|
||||
<ClInclude Include="Loader\disc.h">
|
||||
<Filter>Loader</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_cursor.h">
|
||||
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">
|
||||
|
@ -138,6 +138,7 @@ enum class emu_settings_type
|
||||
|
||||
// Input / Output
|
||||
BackgroundInput,
|
||||
ShowMoveCursor,
|
||||
PadHandlerMode,
|
||||
KeyboardHandler,
|
||||
MouseHandler,
|
||||
@ -312,6 +313,7 @@ inline static const QMap<emu_settings_type, cfg_location> settings_location =
|
||||
|
||||
// Input / Output
|
||||
{ emu_settings_type::BackgroundInput, { "Input/Output", "Background input enabled"}},
|
||||
{ emu_settings_type::ShowMoveCursor, { "Input/Output", "Show move cursor"}},
|
||||
{ emu_settings_type::PadHandlerMode, { "Input/Output", "Pad handler mode"}},
|
||||
{ emu_settings_type::KeyboardHandler, { "Input/Output", "Keyboard"}},
|
||||
{ emu_settings_type::MouseHandler, { "Input/Output", "Mouse"}},
|
||||
|
@ -1179,6 +1179,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||
m_emu_settings->EnhanceCheckBox(ui->backgroundInputBox, emu_settings_type::BackgroundInput);
|
||||
SubscribeTooltip(ui->backgroundInputBox, tooltips.settings.background_input);
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->showMoveCursorBox, emu_settings_type::ShowMoveCursor);
|
||||
SubscribeTooltip(ui->showMoveCursorBox, tooltips.settings.show_move_cursor);
|
||||
|
||||
// _____ _ _______ _
|
||||
// / ____| | | |__ __| | |
|
||||
// | (___ _ _ ___| |_ ___ _ __ ___ | | __ _| |__
|
||||
|
@ -1685,6 +1685,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showMoveCursorBox">
|
||||
<property name="text">
|
||||
<string>Show PS Move Cursor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -215,6 +215,7 @@ public:
|
||||
const QString turntable = tr("DJ Hero Turntable controller support.\nSelect 1 or 2 controllers if the game requires DJ Hero Turntable controllers and you don't have real turntable controllers.\nSelect Null if the game has support for DualShock or if you have real turntable controllers.\nA real turntable controller can be used at the same time as an emulated turntable controller.");
|
||||
const QString ghltar = tr("Guitar Hero Live (GHL) Guitar controller support.\nSelect 1 or 2 controllers if the game requires GHL Guitar controllers and you don't have real guitar controllers.\nSelect Null if the game has support for DualShock or if you have real guitar controllers.\nA real guitar controller can be used at the same time as an emulated guitar controller.");
|
||||
const QString background_input = tr("Allows pad and keyboard input while the game window is unfocused.");
|
||||
const QString show_move_cursor = tr("Shows the raw position of the PS Move input.\nThis can be very helpful during calibration screens.");
|
||||
|
||||
// network
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user