Also cleanup the code involved in dialog registration, and update the explanation of why dialog removal is delayed until the end of drawing (the original was written back when window listener and UI drawer callback registration during the execution of the callbacks was deferred, but that was wrong as that might result in execution of callbacks belonging to now-deleted objects).
118 lines
3.8 KiB
C++
118 lines
3.8 KiB
C++
/**
|
|
******************************************************************************
|
|
* Xenia : Xbox 360 Emulator Research Project *
|
|
******************************************************************************
|
|
* Copyright 2022 Ben Vanik. All rights reserved. *
|
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifndef XENIA_UI_IMGUI_DRAWER_H_
|
|
#define XENIA_UI_IMGUI_DRAWER_H_
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "xenia/ui/immediate_drawer.h"
|
|
#include "xenia/ui/presenter.h"
|
|
#include "xenia/ui/window.h"
|
|
#include "xenia/ui/window_listener.h"
|
|
|
|
struct ImDrawData;
|
|
struct ImGuiContext;
|
|
struct ImGuiIO;
|
|
|
|
namespace xe {
|
|
namespace ui {
|
|
|
|
class ImGuiDialog;
|
|
class Window;
|
|
|
|
class ImGuiDrawer : public WindowInputListener, public UIDrawer {
|
|
public:
|
|
ImGuiDrawer(Window* window, size_t z_order);
|
|
~ImGuiDrawer();
|
|
|
|
ImGuiIO& GetIO();
|
|
|
|
void AddDialog(ImGuiDialog* dialog);
|
|
void RemoveDialog(ImGuiDialog* dialog);
|
|
|
|
// SetPresenter may be called from the destructor.
|
|
void SetPresenter(Presenter* new_presenter);
|
|
void SetImmediateDrawer(ImmediateDrawer* new_immediate_drawer);
|
|
void SetPresenterAndImmediateDrawer(Presenter* new_presenter,
|
|
ImmediateDrawer* new_immediate_drawer) {
|
|
SetPresenter(new_presenter);
|
|
SetImmediateDrawer(new_immediate_drawer);
|
|
}
|
|
|
|
void Draw(UIDrawContext& ui_draw_context) override;
|
|
|
|
protected:
|
|
void OnKeyDown(KeyEvent& e) override;
|
|
void OnKeyUp(KeyEvent& e) override;
|
|
void OnKeyChar(KeyEvent& e) override;
|
|
void OnMouseDown(MouseEvent& e) override;
|
|
void OnMouseMove(MouseEvent& e) override;
|
|
void OnMouseUp(MouseEvent& e) override;
|
|
void OnMouseWheel(MouseEvent& e) override;
|
|
void OnTouchEvent(TouchEvent& e) override;
|
|
// For now, no need for OnDpiChanged because redrawing is done continuously.
|
|
|
|
private:
|
|
void Initialize();
|
|
|
|
void SetupFontTexture();
|
|
|
|
void RenderDrawLists(ImDrawData* data, UIDrawContext& ui_draw_context);
|
|
|
|
void ClearInput();
|
|
void OnKey(KeyEvent& e, bool is_down);
|
|
void UpdateMousePosition(float x, float y);
|
|
void SwitchToPhysicalMouseAndUpdateMousePosition(const MouseEvent& e);
|
|
|
|
bool IsDrawingDialogs() const { return dialog_loop_next_index_ != SIZE_MAX; }
|
|
void DetachIfLastDialogRemoved();
|
|
|
|
Window* window_;
|
|
size_t z_order_;
|
|
|
|
ImGuiContext* internal_state_ = nullptr;
|
|
|
|
// All currently-attached dialogs that get drawn.
|
|
std::vector<ImGuiDialog*> dialogs_;
|
|
// Using an index, not an iterator, because after the erasure, the adjustment
|
|
// must be done for the vector element indices that would be in the iterator
|
|
// range that would be invalidated.
|
|
// SIZE_MAX if not currently in the dialog loop.
|
|
size_t dialog_loop_next_index_ = SIZE_MAX;
|
|
|
|
Presenter* presenter_ = nullptr;
|
|
|
|
ImmediateDrawer* immediate_drawer_ = nullptr;
|
|
// Resources specific to an immediate drawer - must be destroyed before
|
|
// detaching the presenter.
|
|
std::unique_ptr<ImmediateTexture> font_texture_;
|
|
|
|
// If there's an active pointer, the ImGui mouse is controlled by this touch.
|
|
// If it's TouchEvent::kPointerIDNone, the ImGui mouse is controlled by the
|
|
// mouse.
|
|
uint32_t touch_pointer_id_ = TouchEvent::kPointerIDNone;
|
|
// Whether after the next frame (since the mouse up event needs to be handled
|
|
// with the correct mouse position still), the ImGui mouse position should be
|
|
// reset (for instance, after releasing a touch), so it's not hovering over
|
|
// anything.
|
|
bool reset_mouse_position_after_next_frame_ = false;
|
|
|
|
double frame_time_tick_frequency_;
|
|
uint64_t last_frame_time_ticks_;
|
|
};
|
|
|
|
} // namespace ui
|
|
} // namespace xe
|
|
|
|
#endif // XENIA_UI_IMGUI_DRAWER_H_
|