OXYGENHUB
◆ main openmsx / src / imgui / ImGuiPlotterViewer.cc
3.9 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "ImGuiPlotterViewer.hh"
2
3
#include "Connector.hh"
4
#include "ImGuiManager.hh"
5
#include "ImGuiUtils.hh"
6
#include "MSXMotherBoard.hh"
7
#include "Plotter.hh"
8
#include "Pluggable.hh"
9
#include "PluggingController.hh"
10
11
#include <imgui.h>
12
13
using namespace std::literals;
14
15
namespace openmsx {
16
17
ImGuiPlotterViewer::ImGuiPlotterViewer(ImGuiManager& manager_)
18
	: ImGuiPart(manager_)
19
{
20
}
21
22
void ImGuiPlotterViewer::save(ImGuiTextBuffer& buf)
23
{
24
  savePersistent(buf, *this, persistentElements);
25
}
26
27
void ImGuiPlotterViewer::loadLine(std::string_view name, zstring_view value)
28
{
29
	loadOnePersistent(name, value, *this, persistentElements);
30
}
31
32
void ImGuiPlotterViewer::paint(MSXMotherBoard* motherBoard)
33
{
34
	if (!show) return;
35
36
	ImGui::SetNextWindowSize({480, 720}, ImGuiCond_FirstUseEver);
37
	im::Window("Plotter viewer", &show, [&]{
38
		if (!motherBoard) {
39
			ImGui::TextUnformatted("No machine present.");
40
			return;
41
		}
42
43
		// Find MSXPlotter
44
		MSXPlotter* plotter = nullptr;
45
		const auto& controller = motherBoard->getPluggingController();
46
		for (auto* connector : controller.getConnectors()) {
47
			if (auto* pluggable = &connector->getPlugged()) {
48
				if (auto* p = dynamic_cast<MSXPlotter*>(pluggable)) {
49
					plotter = p;
50
					break;
51
				}
52
			}
53
		}
54
55
		if (!plotter) {
56
			ImGui::TextUnformatted("Plotter not plugged in.");
57
			return;
58
		}
59
60
		auto* paper = plotter->getPaper();
61
		if (!paper) {
62
			ImGui::TextUnformatted("Plotter has no paper.");
63
			return;
64
		}
65
66
		// Calculate available space and aspect ratio
67
		const auto& style = ImGui::GetStyle();
68
		auto panelHeight = 2.0f * ImGui::GetTextLineHeight() + 4.0f * style.ItemSpacing.y + 2.0f * style.FramePadding.y + 2.0f;
69
		auto availableSize = max(ImGui::GetContentRegionAvail() - gl::vec2{0.0f, panelHeight}, gl::vec2{0.0f});
70
71
		auto paperSize = gl::vec2(paper->size());
72
		auto scaleVec = availableSize / paperSize;
73
		float scale = min_component(scaleVec);
74
		auto displaySize = paperSize * scale; // largest fit with same aspect ratio
75
76
		auto screenPos = ImGui::GetCursorScreenPos();
77
		auto& texture = paper->updateTexture(max(trunc(displaySize), gl::ivec2{1}));
78
		ImGui::Image(texture.getImGui(), displaySize);
79
80
		// Draw crosshair at pen position
81
		// MSXPlotter: X-axis is short axis (carriage), Y-axis is long axis (paper feed).
82
		// Origin (0,0) is bottom-left of plotting area.
83
		auto plotPos = plotter->getPlotterPos();
84
		auto paperPos = gl::vec2{MSXPlotter::MARGIN.x, MSXPlotter::FULL_AREA.y - MSXPlotter::MARGIN.y}
85
		              + plotPos * gl::vec2{1, -1};
86
		auto stepToPixel = paperSize / MSXPlotter::FULL_AREA;
87
		auto penScrnPos = screenPos + (paperPos * stepToPixel * scale);
88
89
		auto* drawList = ImGui::GetWindowDrawList();
90
		float crossSize = 10.0f;
91
		drawList->AddLine(penScrnPos + gl::vec2{-crossSize, 0.0f},
92
		                  penScrnPos + gl::vec2{ crossSize, 0.0f}, 0xFF0000FF);
93
		drawList->AddLine(penScrnPos + gl::vec2{0.0f, -crossSize},
94
		                  penScrnPos + gl::vec2{0.0f,  crossSize}, 0xFF0000FF);
95
96
		ImGui::Separator();
97
		auto pen = plotter->getSelectedPen();
98
		static constexpr std::array<std::string_view, 4> penNames = {
99
			"Black", "Blue", "Green", "Red"
100
		};
101
		ImGui::StrCat("Pen: ", penNames[pen]);
102
		ImGui::SameLine();
103
		auto c = gl::vec4{gl::vec3(1.0f) - MSXPlotter::inkColors[pen], 1.0f};
104
		ImGui::ColorButton("##pencolor", c, ImGuiColorEditFlags_NoTooltip,
105
		                   gl::vec2{ImGui::GetFontSize()});
106
		ImGui::SameLine();
107
		ImGui::Text("  Pos: (%.1f, %.1f)", double(plotPos.x), double(plotPos.y));
108
		ImGui::SameLine();
109
		ImGui::StrCat("  Mode: ", plotter->isGraphicMode() ? "Graphic"sv : "Text"sv);
110
111
		ImGui::Separator();
112
		if (ImGui::Button("Cycle Pen")) {
113
			plotter->cyclePen();
114
		}
115
		ImGui::SameLine();
116
		if (ImGui::Button("Up")) {
117
			plotter->moveStep({0.0f, 10.0f});
118
		}
119
		ImGui::SameLine();
120
		if (ImGui::Button("Down")) {
121
			plotter->moveStep({0.0f, -10.0f});
122
		}
123
		ImGui::SameLine();
124
		if (ImGui::Button("Eject Paper")) {
125
			plotter->ejectPaper();
126
		}
127
	});
128
}
129
130
} // namespace openmsx