Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental
This commit is contained in:
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user