Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental

This commit is contained in:
Gliniak
2022-12-31 10:53:25 +01:00
38 changed files with 632 additions and 6570 deletions

View File

@@ -148,14 +148,16 @@ bool Win32FilePicker::Show(Window* parent_window) {
if (type() == Type::kFile) {
// Set the file types to display only. Notice that this is a 1-based array.
std::vector<std::pair<std::u16string, std::u16string>> file_pairs;
using u16sPair = std::pair<std::u16string, std::u16string>;
std::vector<std::unique_ptr<u16sPair>> file_pairs;
std::vector<COMDLG_FILTERSPEC> file_types;
for (const auto& extension : this->extensions()) {
const auto& file_pair =
file_pairs.emplace_back(std::move(xe::to_utf16(extension.first)),
std::move(xe::to_utf16(extension.second)));
file_types.push_back({(LPCWSTR)file_pair.first.c_str(),
(LPCWSTR)file_pair.second.c_str()});
file_pairs.emplace_back(std::make_unique<u16sPair>(
xe::to_utf16(extension.first), xe::to_utf16(extension.second)));
file_types.push_back(
{reinterpret_cast<LPCWSTR>(file_pair->first.c_str()),
reinterpret_cast<LPCWSTR>(file_pair->second.c_str())});
}
hr = file_dialog->SetFileTypes(static_cast<UINT>(file_types.size()),
file_types.data());

View File

@@ -62,11 +62,11 @@ void ImGuiDrawer::AddDialog(ImGuiDialog* dialog) {
dialogs_.cend()) {
return;
}
if (dialog_loop_next_index_ == SIZE_MAX && dialogs_.empty()) {
// First dialog added. dialog_loop_next_index_ == SIZE_MAX is also checked
// because in a situation of removing the only dialog, then adding a dialog,
// from within a dialog's Draw function, the removal would not cause the
// listener and the drawer to be removed (it's deferred in this case).
if (dialogs_.empty() && !IsDrawingDialogs()) {
// First dialog added. !IsDrawingDialogs() is also checked because in a
// situation of removing the only dialog, then adding a dialog, from within
// a dialog's Draw function, re-registering the ImGuiDrawer may result in
// ImGui being drawn multiple times in the current frame.
window_->AddInputListener(this, z_order_);
if (presenter_) {
presenter_->AddUIDrawerFromUIThread(this, z_order_);
@@ -81,7 +81,7 @@ void ImGuiDrawer::RemoveDialog(ImGuiDialog* dialog) {
if (it == dialogs_.cend()) {
return;
}
if (dialog_loop_next_index_ != SIZE_MAX) {
if (IsDrawingDialogs()) {
// Actualize the next dialog index after the erasure from the vector.
size_t existing_index = size_t(std::distance(dialogs_.cbegin(), it));
if (dialog_loop_next_index_ > existing_index) {
@@ -89,17 +89,7 @@ void ImGuiDrawer::RemoveDialog(ImGuiDialog* dialog) {
}
}
dialogs_.erase(it);
if (dialog_loop_next_index_ == SIZE_MAX && dialogs_.empty()) {
if (presenter_) {
presenter_->RemoveUIDrawerFromUIThread(this);
}
window_->RemoveInputListener(this);
// Clear all input since no input will be received anymore, and when the
// drawer becomes active again, it'd have an outdated input state otherwise
// which will be persistent until new events actualize individual input
// properties.
ClearInput();
}
DetachIfLastDialogRemoved();
}
void ImGuiDrawer::Initialize() {
@@ -194,24 +184,6 @@ void ImGuiDrawer::Initialize() {
style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 1.00f, 0.00f, 0.21f);
style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
io.KeyMap[ImGuiKey_Tab] = int(ui::VirtualKey::kTab);
io.KeyMap[ImGuiKey_LeftArrow] = int(ui::VirtualKey::kLeft);
io.KeyMap[ImGuiKey_RightArrow] = int(ui::VirtualKey::kRight);
io.KeyMap[ImGuiKey_UpArrow] = int(ui::VirtualKey::kUp);
io.KeyMap[ImGuiKey_DownArrow] = int(ui::VirtualKey::kDown);
io.KeyMap[ImGuiKey_Home] = int(ui::VirtualKey::kHome);
io.KeyMap[ImGuiKey_End] = int(ui::VirtualKey::kEnd);
io.KeyMap[ImGuiKey_Delete] = int(ui::VirtualKey::kDelete);
io.KeyMap[ImGuiKey_Backspace] = int(ui::VirtualKey::kBack);
io.KeyMap[ImGuiKey_Enter] = int(ui::VirtualKey::kReturn);
io.KeyMap[ImGuiKey_Escape] = int(ui::VirtualKey::kEscape);
io.KeyMap[ImGuiKey_A] = int(ui::VirtualKey::kA);
io.KeyMap[ImGuiKey_C] = int(ui::VirtualKey::kC);
io.KeyMap[ImGuiKey_V] = int(ui::VirtualKey::kV);
io.KeyMap[ImGuiKey_X] = int(ui::VirtualKey::kX);
io.KeyMap[ImGuiKey_Y] = int(ui::VirtualKey::kY);
io.KeyMap[ImGuiKey_Z] = int(ui::VirtualKey::kZ);
frame_time_tick_frequency_ = double(Clock::QueryHostTickFrequency());
last_frame_time_ticks_ = Clock::QueryHostTickCount();
@@ -219,6 +191,33 @@ void ImGuiDrawer::Initialize() {
reset_mouse_position_after_next_frame_ = false;
}
std::optional<ImGuiKey> ImGuiDrawer::VirtualKeyToImGuiKey(VirtualKey vkey) {
static const std::map<VirtualKey, ImGuiKey> map = {
{ui::VirtualKey::kTab, ImGuiKey_Tab},
{ui::VirtualKey::kLeft, ImGuiKey_LeftArrow},
{ui::VirtualKey::kRight, ImGuiKey_RightArrow},
{ui::VirtualKey::kUp, ImGuiKey_UpArrow},
{ui::VirtualKey::kDown, ImGuiKey_DownArrow},
{ui::VirtualKey::kHome, ImGuiKey_Home},
{ui::VirtualKey::kEnd, ImGuiKey_End},
{ui::VirtualKey::kDelete, ImGuiKey_Delete},
{ui::VirtualKey::kBack, ImGuiKey_Backspace},
{ui::VirtualKey::kReturn, ImGuiKey_Enter},
{ui::VirtualKey::kEscape, ImGuiKey_Escape},
{ui::VirtualKey::kA, ImGuiKey_A},
{ui::VirtualKey::kC, ImGuiKey_C},
{ui::VirtualKey::kV, ImGuiKey_V},
{ui::VirtualKey::kX, ImGuiKey_X},
{ui::VirtualKey::kY, ImGuiKey_Y},
{ui::VirtualKey::kZ, ImGuiKey_Z},
};
if (auto search = map.find(vkey); search != map.end()) {
return search->second;
} else {
return std::nullopt;
}
}
void ImGuiDrawer::SetupFontTexture() {
if (font_texture_ || !immediate_drawer_) {
return;
@@ -301,7 +300,7 @@ void ImGuiDrawer::Draw(UIDrawContext& ui_draw_context) {
ImGui::NewFrame();
assert_true(dialog_loop_next_index_ == SIZE_MAX);
assert_true(!IsDrawingDialogs());
dialog_loop_next_index_ = 0;
while (dialog_loop_next_index_ < dialogs_.size()) {
dialogs_[dialog_loop_next_index_++]->Draw();
@@ -319,11 +318,11 @@ void ImGuiDrawer::Draw(UIDrawContext& ui_draw_context) {
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
}
if (dialogs_.empty()) {
// All dialogs have removed themselves during the draw, detach.
presenter_->RemoveUIDrawerFromUIThread(this);
window_->RemoveInputListener(this);
} else {
// Detaching is deferred if the last dialog is removed during drawing, perform
// it now if needed.
DetachIfLastDialogRemoved();
if (!dialogs_.empty()) {
// Repaint (and handle input) continuously if still active.
presenter_->RequestUIPaintFromUIThread();
}
@@ -346,14 +345,13 @@ void ImGuiDrawer::RenderDrawLists(ImDrawData* data,
batch.index_count = cmd_list->IdxBuffer.size();
immediate_drawer_->BeginDrawBatch(batch);
int index_offset = 0;
for (int j = 0; j < cmd_list->CmdBuffer.size(); ++j) {
const auto& cmd = cmd_list->CmdBuffer[j];
ImmediateDraw draw;
draw.primitive_type = ImmediatePrimitiveType::kTriangles;
draw.count = cmd.ElemCount;
draw.index_offset = index_offset;
draw.index_offset = cmd.IdxOffset;
draw.texture = reinterpret_cast<ImmediateTexture*>(cmd.TextureId);
draw.scissor = true;
draw.scissor_left = cmd.ClipRect.x;
@@ -361,8 +359,6 @@ void ImGuiDrawer::RenderDrawLists(ImDrawData* data,
draw.scissor_right = cmd.ClipRect.z;
draw.scissor_bottom = cmd.ClipRect.w;
immediate_drawer_->Draw(draw);
index_offset += cmd.ElemCount;
}
immediate_drawer_->EndDrawBatch();
@@ -497,13 +493,7 @@ void ImGuiDrawer::ClearInput() {
}
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
std::memset(io.MouseDown, 0, sizeof(io.MouseDown));
io.MouseWheel = 0.0f;
io.MouseWheelH = 0.0f;
io.KeyCtrl = false;
io.KeyShift = false;
io.KeyAlt = false;
io.KeySuper = false;
std::memset(io.KeysDown, 0, sizeof(io.KeysDown));
io.ClearInputKeys();
io.ClearInputCharacters();
touch_pointer_id_ = TouchEvent::kPointerIDNone;
reset_mouse_position_after_next_frame_ = false;
@@ -511,9 +501,9 @@ void ImGuiDrawer::ClearInput() {
void ImGuiDrawer::OnKey(KeyEvent& e, bool is_down) {
auto& io = GetIO();
VirtualKey virtual_key = e.virtual_key();
if (size_t(virtual_key) < xe::countof(io.KeysDown)) {
io.KeysDown[size_t(virtual_key)] = is_down;
const VirtualKey virtual_key = e.virtual_key();
if (auto imGuiKey = VirtualKeyToImGuiKey(virtual_key); imGuiKey) {
io.AddKeyEvent(*imGuiKey, is_down);
}
switch (virtual_key) {
case VirtualKey::kShift:
@@ -557,5 +547,24 @@ void ImGuiDrawer::SwitchToPhysicalMouseAndUpdateMousePosition(
UpdateMousePosition(float(e.x()), float(e.y()));
}
void ImGuiDrawer::DetachIfLastDialogRemoved() {
// IsDrawingDialogs() is also checked because in a situation of removing the
// only dialog, then adding a dialog, from within a dialog's Draw function,
// re-registering the ImGuiDrawer may result in ImGui being drawn multiple
// times in the current frame.
if (!dialogs_.empty() || IsDrawingDialogs()) {
return;
}
if (presenter_) {
presenter_->RemoveUIDrawerFromUIThread(this);
}
window_->RemoveInputListener(this);
// Clear all input since no input will be received anymore, and when the
// drawer becomes active again, it'd have an outdated input state otherwise
// which will be persistent until new events actualize individual input
// properties.
ClearInput();
}
} // namespace ui
} // namespace xe

View File

@@ -23,6 +23,7 @@
struct ImDrawData;
struct ImGuiContext;
struct ImGuiIO;
enum ImGuiKey : int;
namespace xe {
namespace ui {
@@ -74,6 +75,11 @@ class ImGuiDrawer : public WindowInputListener, public UIDrawer {
void UpdateMousePosition(float x, float y);
void SwitchToPhysicalMouseAndUpdateMousePosition(const MouseEvent& e);
bool IsDrawingDialogs() const { return dialog_loop_next_index_ != SIZE_MAX; }
void DetachIfLastDialogRemoved();
std::optional<ImGuiKey> VirtualKeyToImGuiKey(VirtualKey vkey);
Window* window_;
size_t z_order_;