Skip to content

Commit 0166fdb

Browse files
committed
Add Custom Rendering example
1 parent 61be49c commit 0166fdb

File tree

1 file changed

+124
-95
lines changed

1 file changed

+124
-95
lines changed
Lines changed: 124 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package imgui.imgui.demo.showExampleApp
22

33
import glm_.vec2.Vec2
4-
import imgui.Cond
4+
import glm_.vec4.Vec4
5+
import imgui.*
56
import imgui.ImGui.begin_
7+
import imgui.ImGui.dummy
68
import imgui.ImGui.end
9+
import imgui.ImGui.getColorU32
10+
import imgui.ImGui.invisibleButton
11+
import imgui.ImGui.sameLine
712
import imgui.ImGui.setNextWindowSize
813
import imgui.ImGui.text
14+
import imgui.functionalProgramming.button
15+
import imgui.internal.DrawCornerFlag
916
import kotlin.reflect.KMutableProperty0
1017
import imgui.ColorEditFlag as Cef
1118
import imgui.InputTextFlag as Itf
@@ -15,6 +22,13 @@ import imgui.WindowFlag as Wf
1522

1623
object CustomRendering {
1724

25+
var sz = 36f
26+
var thickness = 4f
27+
val col = Vec4(1.0f, 1.0f, 0.4f, 1.0f)
28+
29+
var addingLine = false
30+
val points = ArrayList<Vec2>()
31+
1832
/** Demonstrate using the low-level ImDrawList to draw custom shapes. */
1933
operator fun invoke(open: KMutableProperty0<Boolean>) {
2034

@@ -24,108 +38,123 @@ object CustomRendering {
2438
return
2539
}
2640

27-
text("TODO")
28-
2941
/* Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and
3042
benefit of overloaded operators, etc.
3143
Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and
3244
ImVec2/ImVec4.
3345
ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside
3446
(to avoid messing with your types)
3547
In this example we are not using the maths operators! */
36-
// ImDrawList* draw_list = ImGui::GetWindowDrawList();
37-
//
38-
// // Primitives
39-
// ImGui::Text("Primitives");
40-
// static float sz = 36.0f;
41-
// static float thickness = 4.0f;
42-
// static ImVec4 col = ImVec4(1.0f,1.0f,0.4f,1.0f);
43-
// ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
44-
// ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
45-
// ImGui::ColorEdit4("Color", &col.x);
46-
// {
47-
// const ImVec2 p = ImGui::GetCursorScreenPos();
48-
// const ImU32 col32 = ImColor(col);
49-
// float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
50-
// for (int n = 0; n < 2; n++)
51-
// {
52-
// // First line uses a thickness of 1.0, second line uses the configurable thickness
53-
// float th = (n == 0) ? 1.0f : thickness;
54-
// draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 6, th); x += sz+spacing; // Hexagon
55-
// draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, th); x += sz+spacing; // Circle
56-
// draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, th); x += sz+spacing;
57-
// draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, th); x += sz+spacing;
58-
// draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, th); x += sz+spacing;
59-
// draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, th); x += sz+spacing;
60-
// draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, th); x += sz+spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
61-
// draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
62-
// draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, th); x += sz+spacing; // Diagonal line
63-
// draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, th);
64-
// x = p.x + 4;
65-
// y += sz+spacing;
66-
// }
67-
// draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 6); x += sz+spacing; // Hexagon
68-
// draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing; // Circle
69-
// draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;
70-
// draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;
71-
// draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing;
72-
// draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing;
73-
// draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+thickness), col32); x += sz+spacing; // Horizontal line (faster than AddLine, but only handle integer thickness)
74-
// draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+thickness, y+sz), col32); x += spacing+spacing; // Vertical line (faster than AddLine, but only handle integer thickness)
75-
// draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+1, y+1), col32); x += sz; // Pixel (faster than AddLine)
76-
// draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), IM_COL32(0,0,0,255), IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255));
77-
// ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3));
78-
// }
79-
// ImGui::Separator();
48+
val drawList = ImGui.windowDrawList
49+
50+
// Primitives
51+
ImGui.text("Primitives")
52+
ImGui.dragFloat("Size", ::sz, 0.2f, 2.0f, 72.0f, "%.0f")
53+
ImGui.dragFloat("Thickness", ::thickness, 0.05f, 1.0f, 8.0f, "%.02f")
54+
ImGui.colorEdit4("Color", col)
8055
// {
81-
// static ImVector<ImVec2> points;
82-
// static bool adding_line = false;
83-
// ImGui::Text("Canvas example");
84-
// if (ImGui::Button("Clear")) points.clear();
85-
// if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
86-
// ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
87-
//
88-
// // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
89-
// // But you can also draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
90-
// // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
91-
// ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
92-
// ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available
93-
// if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
94-
// if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
95-
// draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(50,50,50,255), IM_COL32(50,50,60,255), IM_COL32(60,60,70,255), IM_COL32(50,50,60,255));
96-
// draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255,255,255,255));
97-
//
98-
// bool adding_preview = false;
99-
// ImGui::InvisibleButton("canvas", canvas_size);
100-
// ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
101-
// if (adding_line)
102-
// {
103-
// adding_preview = true;
104-
// points.push_back(mouse_pos_in_canvas);
105-
// if (!ImGui::IsMouseDown[0])
106-
// adding_line = adding_preview = false;
107-
// }
108-
// if (ImGui::IsItemHovered())
109-
// {
110-
// if (!adding_line && ImGui::IsMouseClicked(0))
111-
// {
112-
// points.push_back(mouse_pos_in_canvas);
113-
// adding_line = true;
114-
// }
115-
// if (ImGui::IsMouseClicked(1) && !points.empty())
116-
// {
117-
// adding_line = adding_preview = false;
118-
// points.pop_back();
119-
// points.pop_back();
120-
// }
121-
// }
122-
// draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y), true); // clip lines within the canvas (if we resize it, etc.)
123-
// for (int i = 0; i < points.Size - 1; i += 2)
124-
// draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), IM_COL32(255,255,0,255), 2.0f);
125-
// draw_list->PopClipRect();
126-
// if (adding_preview)
127-
// points.pop_back();
128-
// }
56+
val p = ImGui.cursorScreenPos
57+
val col32 = getColorU32(col)
58+
var x = p.x + 4.0f
59+
var y = p.y + 4.0f
60+
var spacing = 8.0f
61+
for (n in 0 until 2) {
62+
val th = if (n == 0) 1.0f else thickness
63+
drawList.addCircle(Vec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col32, 6, th)
64+
x += sz + spacing
65+
drawList.addCircle(Vec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, th)
66+
x += sz + spacing
67+
drawList.addRect(Vec2(x, y), Vec2(x+sz, y+sz), col32, 0.0f, DrawCornerFlag.All.i, th)
68+
x += sz + spacing
69+
drawList.addRect(Vec2(x, y), Vec2(x+sz, y+sz), col32, 10.0f, DrawCornerFlag.All.i, th)
70+
x += sz + spacing
71+
drawList.addRect(Vec2(x, y), Vec2(x+sz, y+sz), col32, 10.0f, DrawCornerFlag.TopLeft.i or DrawCornerFlag.BotRight.i, th)
72+
x += sz + spacing
73+
drawList.addTriangle(Vec2(x+sz*0.5f, y), Vec2(x+sz,y+sz-0.5f), Vec2(x,y+sz-0.5f), col32, th)
74+
x += sz + spacing
75+
drawList.addLine(Vec2(x, y), Vec2(x+sz, y ), col32, th)
76+
x += sz + spacing
77+
drawList.addLine(Vec2(x, y), Vec2(x, y+sz), col32, th)
78+
x += spacing
79+
drawList.addLine(Vec2(x, y), Vec2(x+sz, y+sz), col32, th)
80+
x += sz + spacing
81+
drawList.addBezierCurve(Vec2(x, y), Vec2(x+sz*1.3f,y+sz*0.3f), Vec2(x+sz-sz*1.3f,y+sz-sz*0.3f), Vec2(x+sz, y+sz), col32, th)
82+
x = p.x + 4
83+
y += sz+spacing
84+
}
85+
drawList.addCircleFilled(Vec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 6)
86+
x += sz + spacing
87+
drawList.addCircleFilled(Vec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32)
88+
x += sz + spacing
89+
drawList.addRectFilled(Vec2(x, y), Vec2(x+sz, y+sz), col32)
90+
x += sz + spacing
91+
drawList.addRectFilled(Vec2(x, y), Vec2(x+sz, y+sz), col32, 10.0f)
92+
x += sz + spacing
93+
drawList.addRectFilled(Vec2(x, y), Vec2(x+sz, y+sz), col32, 10.0f, DrawCornerFlag.TopLeft.i or DrawCornerFlag.BotRight.i)
94+
x += sz + spacing
95+
drawList.addTriangleFilled(Vec2(x+sz*0.5f, y), Vec2(x+sz,y+sz-0.5f), Vec2(x,y+sz-0.5f), col32)
96+
x += sz + spacing
97+
drawList.addRectFilled(Vec2(x, y), Vec2(x + sz, y + thickness), col32)
98+
x += sz + spacing
99+
drawList.addRectFilled(Vec2(x, y), Vec2(x+thickness, y+sz), col32)
100+
x += spacing + spacing
101+
drawList.addRectFilled(Vec2(x, y), Vec2(x+1, y+1), col32)
102+
x += sz
103+
drawList.addRectFilledMultiColor(Vec2(x, y), Vec2(x+sz, y+sz), getColorU32(0, 0, 0, 255), getColorU32(255, 0, 0, 255),
104+
getColorU32(255, 255, 0, 255), getColorU32(0, 255, 0, 255))
105+
dummy(Vec2((sz+spacing)*8, (sz+spacing)*3))
106+
ImGui.separator()
107+
108+
text("Canvas Example")
109+
button("Clear") { points.clear() }
110+
if(points.size >= 2) {
111+
sameLine()
112+
button("Undo") {
113+
points.removeAt(points.size - 1)
114+
points.removeAt(points.size - 1)
115+
}
116+
}
117+
text("Left-click and drag to add lines,\nRight-click to undo")
118+
119+
val canvasPos = ImGui.cursorScreenPos
120+
val canvasSize = ImGui.contentRegionAvail
121+
if (canvasSize.x < 50.0f) canvasSize.x = 50.0f
122+
if (canvasSize.y < 50.0f) canvasSize.y = 50.0f
123+
drawList.addRectFilledMultiColor(canvasPos, canvasPos + canvasSize, getColorU32(50, 50, 50, 255), getColorU32(50, 50, 60, 255), getColorU32(60, 60, 70, 255), getColorU32(50, 50, 60, 255))
124+
drawList.addRect(canvasPos, canvasPos + canvasSize, getColorU32(255, 255, 255, 255))
125+
126+
var addingPreview = false
127+
invisibleButton("canvas", canvasSize)
128+
129+
val mousePosInCanvas = ImGui.io.mousePos - canvasPos
130+
if(addingLine) {
131+
addingPreview = true
132+
points.add(mousePosInCanvas)
133+
if(!ImGui.isMouseDown(0)) {
134+
addingLine = false
135+
addingPreview = false
136+
}
137+
}
138+
if(ImGui.isItemHovered()) {
139+
if(!addingLine and ImGui.isMouseClicked(0)) {
140+
points.add(mousePosInCanvas)
141+
addingLine = true
142+
}
143+
if(ImGui.isMouseClicked(1) and points.isNotEmpty()) {
144+
addingLine = false
145+
addingPreview = false
146+
points.removeAt(points.size - 1)
147+
points.removeAt(points.size - 1)
148+
}
149+
}
150+
val rootPos = Vec2(canvasPos.x, canvasPos.y - canvasSize.y - 4)
151+
drawList.pushClipRect(rootPos, rootPos + canvasSize, true) //TODO: Fix
152+
for(i in 0 until points.size - 1 step 2) {
153+
drawList.addLine(canvasPos + points[i], canvasPos + points[i + 1], getColorU32(255, 255, 0, 255), 2.0f)
154+
}
155+
drawList.popClipRect()
156+
if(addingPreview)
157+
points.removeAt(points.size - 1)
129158
end()
130159
}
131160
}

0 commit comments

Comments
 (0)