[Example] Add example of Canvas Editor (#126)
* [Example] Add example of Canvas Editor * [Example] Adjust Canvas Editor example (#126) * [Example] Wrap examples to their own window * Tweaks Co-authored-by: SpaiR <klimbetoo@gmail.com>
This commit is contained in:
1 parent
5b0e867bfe
commit
3a494ba6a3
3 files changed
+165
-11
No files matched your search
@@ -0,0 +1,144 @@
|
||||
import imgui.*;
|
||||
import imgui.flag.ImGuiButtonFlags;
|
||||
import imgui.flag.ImGuiCond;
|
||||
import imgui.flag.ImGuiMouseButton;
|
||||
import imgui.flag.ImGuiPopupFlags;
|
||||
import imgui.type.ImBoolean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ExampleCanvasEditor {
|
||||
private static final List<ImVec2> pointList = new ArrayList<>();
|
||||
private static final ImVec2 scrolling = new ImVec2();
|
||||
|
||||
private static boolean addingLine = false;
|
||||
public static float thickness = 2.0f;
|
||||
|
||||
/**
|
||||
* Computes the floating-point remainder of a / b.
|
||||
*
|
||||
* @param a float
|
||||
* @param b float
|
||||
* @return computed floating-point remainder of a / b
|
||||
*/
|
||||
private static float fmodf(float a, float b) {
|
||||
int result = (int) Math.floor(a / b);
|
||||
return a - result * b;
|
||||
}
|
||||
|
||||
public static void show(final ImBoolean showCanvaWindow) {
|
||||
ImGui.setNextWindowSize(700, 400, ImGuiCond.Once);
|
||||
ImGui.setNextWindowPos(ImGui.getMainViewport().getPosX() + 200, ImGui.getMainViewport().getPosY() + 200, ImGuiCond.Once);
|
||||
|
||||
if (ImGui.begin("Canvas Demo Window", showCanvaWindow)) {
|
||||
ImGui.text("This a demo for ImGui Canvas editor");
|
||||
ImGui.sameLine();
|
||||
ImGui.text("Mouse Left: drag to add lines,\nMouse Right: drag to scroll, click for context menu.");
|
||||
|
||||
// Typically, you would use a BeginChild()/EndChild() pair to benefit from a clipping region + own scrolling.
|
||||
// Here we demonstrate that this can be replaced by simple offsetting + custom drawing + PushClipRect/PopClipRect() calls.
|
||||
// To use a child window instead we could use, e.g:
|
||||
// ImGui.pushStyleVar(ImGuiStyleVar.WindowPadding, 0, 0); // Disable padding
|
||||
// ImGui.pushStyleColor(ImGuiCol.ChildBg, ImColor.intToColor(50, 50, 50, 255)); // Set a background color
|
||||
// ImGui.beginChild("canvas", new ImVec2(0.0f, 0.0f), true, ImGuiWindowFlags.NoMove);
|
||||
// ImGui.popStyleColor();
|
||||
// ImGui.popStyleVar();
|
||||
// [...]
|
||||
// ImGui.endChild();
|
||||
|
||||
// Using InvisibleButton() as a convenience 1) it will advance the layout cursor and 2) allows us to use IsItemHovered()/IsItemActive()
|
||||
ImVec2 canvasP0 = ImGui.getCursorScreenPos(); // ImDrawList API uses screen coordinates!
|
||||
ImVec2 canvasSize = ImGui.getContentRegionAvail(); // Resize canvas to what's available
|
||||
|
||||
if (canvasSize.x < 50.0f) {
|
||||
canvasSize.x = 50.0f;
|
||||
}
|
||||
|
||||
if (canvasSize.y < 50.0f) {
|
||||
canvasSize.y = 50.0f;
|
||||
}
|
||||
|
||||
ImVec2 canvasP1 = new ImVec2(canvasP0.x + canvasSize.x, canvasP0.y + canvasSize.y);
|
||||
|
||||
// Draw border and background color
|
||||
ImGuiIO io = ImGui.getIO();
|
||||
ImDrawList drawList = ImGui.getWindowDrawList();
|
||||
drawList.addRectFilled(canvasP0.x, canvasP0.y, canvasP1.x, canvasP1.y,
|
||||
ImColor.intToColor(50, 50, 50, 255));
|
||||
drawList.addRect(canvasP0.x, canvasP0.y, canvasP1.x, canvasP1.y,
|
||||
ImColor.intToColor(255, 255, 255, 255));
|
||||
|
||||
// This will catch our interactions
|
||||
ImGui.invisibleButton("canvas", canvasSize.x, canvasSize.y,
|
||||
ImGuiButtonFlags.MouseButtonLeft | ImGuiButtonFlags.MouseButtonRight);
|
||||
|
||||
boolean isHovered = ImGui.isItemHovered(); // Hovered
|
||||
boolean isActive = ImGui.isItemActive(); // Held
|
||||
|
||||
ImVec2 origin = new ImVec2(canvasP0.x + scrolling.x, canvasP0.y + scrolling.y); // Lock scrolled origin
|
||||
|
||||
ImVec2 mousePosInCanvas = new ImVec2(io.getMousePos().x - origin.x, io.getMousePos().y - origin.y);
|
||||
|
||||
// Add first and second point
|
||||
if (isHovered && !addingLine && ImGui.isMouseClicked(ImGuiMouseButton.Left)) {
|
||||
pointList.add(mousePosInCanvas);
|
||||
pointList.add(mousePosInCanvas);
|
||||
addingLine = true;
|
||||
}
|
||||
if (addingLine) {
|
||||
pointList.set(pointList.size() - 1, mousePosInCanvas);
|
||||
if (!ImGui.isMouseDown(ImGuiMouseButton.Left)) {
|
||||
addingLine = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Pan (we use a zero mouse threshold when there's no context menu)
|
||||
// You may decide to make that threshold dynamic based on whether the mouse is hovering something etc.
|
||||
float mouseThresholdForPan = -1.0f;
|
||||
if (isActive && ImGui.isMouseDragging(ImGuiMouseButton.Right, mouseThresholdForPan)) {
|
||||
scrolling.x += io.getMouseDelta().x;
|
||||
scrolling.y += io.getMouseDelta().y;
|
||||
}
|
||||
|
||||
// Context menu (under default mouse threshold)
|
||||
ImVec2 dragDelta = ImGui.getMouseDragDelta(ImGuiMouseButton.Right);
|
||||
if (dragDelta.x == 0.0f && dragDelta.y == 0.0f) {
|
||||
ImGui.openPopupOnItemClick("context", ImGuiPopupFlags.MouseButtonRight);
|
||||
}
|
||||
|
||||
// Draw grid + all lines in the canvas
|
||||
drawList.pushClipRect(canvasP0.x, canvasP0.y, canvasP1.x, canvasP1.y, false);
|
||||
float GRID_STEP = 64.0f;
|
||||
for (float x = fmodf(scrolling.x, GRID_STEP); x < canvasSize.x; x += GRID_STEP) {
|
||||
drawList.addLine(canvasP0.x + x, canvasP0.y, canvasP0.x + x, canvasP1.y,
|
||||
ImColor.intToColor(200, 200, 200, 40));
|
||||
}
|
||||
for (float y = fmodf(scrolling.y, GRID_STEP); y < canvasSize.y; y += GRID_STEP) {
|
||||
drawList.addLine(canvasP0.x, canvasP0.y + y, canvasP1.x, canvasP0.y + y,
|
||||
ImColor.intToColor(200, 200, 200, 40));
|
||||
}
|
||||
for (int n = 0; n < pointList.size(); n += 2) {
|
||||
drawList.addLine(origin.x + pointList.get(n).x, origin.y + pointList.get(n).y,
|
||||
origin.x + pointList.get(n + 1).x, origin.y + pointList.get(n + 1).y,
|
||||
ImColor.intToColor(255, 255, 0, 255), thickness);
|
||||
}
|
||||
drawList.popClipRect();
|
||||
|
||||
// Menu properties
|
||||
if (ImGui.beginPopup("context")) {
|
||||
addingLine = false;
|
||||
if (ImGui.menuItem("Remove one", "", false, pointList.size() > 0)) {
|
||||
pointList.remove(pointList.size() - 1);
|
||||
pointList.remove(pointList.size() - 1);
|
||||
}
|
||||
if (ImGui.menuItem("Remove all", "", false, pointList.size() > 0)) {
|
||||
pointList.clear();
|
||||
}
|
||||
ImGui.endPopup();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.end();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user