[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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ public class Extra {
|
|||||||
private static final ImBoolean SHOW_IMGUI_COLOR_TEXT_EDIT_WINDOW = new ImBoolean(false);
|
private static final ImBoolean SHOW_IMGUI_COLOR_TEXT_EDIT_WINDOW = new ImBoolean(false);
|
||||||
private static final ImBoolean SHOW_IMGUI_FILE_DIALOG_WINDOW = new ImBoolean(false);
|
private static final ImBoolean SHOW_IMGUI_FILE_DIALOG_WINDOW = new ImBoolean(false);
|
||||||
private static final ImBoolean SHOW_IMGUI_MEMORY_EDITOR_WINDOW = new ImBoolean(false);
|
private static final ImBoolean SHOW_IMGUI_MEMORY_EDITOR_WINDOW = new ImBoolean(false);
|
||||||
|
private static final ImBoolean SHOW_IMGUI_CANVAS_EDITOR_WINDOW = new ImBoolean(false);
|
||||||
|
|
||||||
private static final Graph GRAPH = new Graph();
|
private static final Graph GRAPH = new Graph();
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ public class Extra {
|
|||||||
ImGui.checkbox("Show ImGuiColorTextEdit Demo Window", SHOW_IMGUI_COLOR_TEXT_EDIT_WINDOW);
|
ImGui.checkbox("Show ImGuiColorTextEdit Demo Window", SHOW_IMGUI_COLOR_TEXT_EDIT_WINDOW);
|
||||||
ImGui.checkbox("Show ImGuiFileDialog Demo Window", SHOW_IMGUI_FILE_DIALOG_WINDOW);
|
ImGui.checkbox("Show ImGuiFileDialog Demo Window", SHOW_IMGUI_FILE_DIALOG_WINDOW);
|
||||||
ImGui.checkbox("Show ImGui MemoryEditor Demo Window", SHOW_IMGUI_MEMORY_EDITOR_WINDOW);
|
ImGui.checkbox("Show ImGui MemoryEditor Demo Window", SHOW_IMGUI_MEMORY_EDITOR_WINDOW);
|
||||||
|
ImGui.checkbox("Show ImGui Canvas Demo Window", SHOW_IMGUI_CANVAS_EDITOR_WINDOW);
|
||||||
|
|
||||||
if (SHOW_DEMO_WINDOW.get()) {
|
if (SHOW_DEMO_WINDOW.get()) {
|
||||||
ImGui.showDemoWindow(SHOW_DEMO_WINDOW);
|
ImGui.showDemoWindow(SHOW_DEMO_WINDOW);
|
||||||
@@ -62,5 +64,9 @@ public class Extra {
|
|||||||
if (SHOW_IMGUI_MEMORY_EDITOR_WINDOW.get()) {
|
if (SHOW_IMGUI_MEMORY_EDITOR_WINDOW.get()) {
|
||||||
ExampleImGuiMemoryEditor.show(SHOW_IMGUI_MEMORY_EDITOR_WINDOW);
|
ExampleImGuiMemoryEditor.show(SHOW_IMGUI_MEMORY_EDITOR_WINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SHOW_IMGUI_CANVAS_EDITOR_WINDOW.get()) {
|
||||||
|
ExampleCanvasEditor.show(SHOW_IMGUI_CANVAS_EDITOR_WINDOW);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import imgui.app.Application;
|
|||||||
import imgui.app.Configuration;
|
import imgui.app.Configuration;
|
||||||
import imgui.flag.ImGuiConfigFlags;
|
import imgui.flag.ImGuiConfigFlags;
|
||||||
import imgui.flag.ImGuiInputTextFlags;
|
import imgui.flag.ImGuiInputTextFlags;
|
||||||
|
import imgui.flag.ImGuiWindowFlags;
|
||||||
import imgui.type.ImString;
|
import imgui.type.ImString;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -70,18 +71,21 @@ public class Main extends Application {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process() {
|
public void process() {
|
||||||
ImGui.text("Hello, World! " + FontAwesomeIcons.Smile);
|
if (ImGui.begin("Demo", ImGuiWindowFlags.AlwaysAutoResize)) {
|
||||||
if (ImGui.button(FontAwesomeIcons.Save + " Save")) {
|
ImGui.text("Hello, World! " + FontAwesomeIcons.Smile);
|
||||||
count++;
|
if (ImGui.button(FontAwesomeIcons.Save + " Save")) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
ImGui.sameLine();
|
||||||
|
ImGui.text(String.valueOf(count));
|
||||||
|
ImGui.inputText("string", str, ImGuiInputTextFlags.CallbackResize);
|
||||||
|
ImGui.text("Result: " + str.get());
|
||||||
|
ImGui.sliderFloat("float", flt, 0, 1);
|
||||||
|
ImGui.separator();
|
||||||
|
ImGui.text("Extra");
|
||||||
|
Extra.show(this);
|
||||||
}
|
}
|
||||||
ImGui.sameLine();
|
ImGui.end();
|
||||||
ImGui.text(String.valueOf(count));
|
|
||||||
ImGui.inputText("string", str, ImGuiInputTextFlags.CallbackResize);
|
|
||||||
ImGui.text("Result: " + str.get());
|
|
||||||
ImGui.sliderFloat("float", flt, 0, 1);
|
|
||||||
ImGui.separator();
|
|
||||||
ImGui.text("Extra");
|
|
||||||
Extra.show(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] loadFromResources(String name) {
|
private static byte[] loadFromResources(String name) {
|
||||||
|
|||||||
Reference in new issue
Block a user