Skip to content

Commit

Permalink
🚧 (broken) Window, Clipper: store initial precision loss and apply in…
Browse files Browse the repository at this point in the history
… clipper. (#3609, #3962 + ocornut/imgui_club#20)
  • Loading branch information
elect86 committed Jan 28, 2023
1 parent 9ddd0a2 commit a487f09
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 8 deletions.
12 changes: 8 additions & 4 deletions core/src/main/kotlin/imgui/api/windows.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package imgui.api

import gli_.has
import gli_.hasnt
import glm_.d
import glm_.f
import glm_.max
import glm_.vec2.Vec2
Expand All @@ -10,7 +11,6 @@ import imgui.ImGui.endColumns
import imgui.ImGui.findBestWindowPosForPopup
import imgui.ImGui.findWindowByName
import imgui.ImGui.focusWindow
import imgui.ImGui.getColorU32
import imgui.ImGui.io
import imgui.ImGui.isMouseHoveringRect
import imgui.ImGui.logFinish
Expand All @@ -20,7 +20,6 @@ import imgui.ImGui.popClipRect
import imgui.ImGui.pushClipRect
import imgui.ImGui.setLastItemData
import imgui.ImGui.style
import imgui.ImGui.topMostPopupModal
import imgui.internal.classes.Rect
import imgui.internal.classes.WindowStackData
import imgui.internal.floor
Expand Down Expand Up @@ -573,8 +572,13 @@ interface windows {
dc.indent = 0f + windowPadding.x - scroll.x
dc.groupOffset = 0f
dc.columnsOffset = 0f
dc.cursorStartPos.put(pos.x + dc.indent + dc.columnsOffset,
pos.y + decorationUpHeight + windowPadding.y - scroll.y)

// Record the loss of precision of CursorStartPos which can happen due to really large scrolling amount.
// This is used by clipper to compensate and fix the most common use case of large scroll area. Easy and cheap, next best thing compared to switching everything to double or ImU64.
val startPosHighpX = window.pos.x.d + window.windowPadding.x - window.scroll.x.d + window.dc.columnsOffset
val startPosHighpY = window.pos.y.d + window.windowPadding.y - window.scroll.y.d + decorationUpHeight
window.dc.cursorStartPos = Vec2(startPosHighpX, startPosHighpY)
window.dc.cursorStartPosLossyness.put(startPosHighpX - window.dc.cursorStartPos.x, startPosHighpY - window.dc.cursorStartPos.y)
dc.cursorPos put dc.cursorStartPos
dc.cursorPosPrevLine put dc.cursorPos
dc.cursorMaxPos put dc.cursorStartPos
Expand Down
7 changes: 4 additions & 3 deletions core/src/main/kotlin/imgui/classes/ListClipper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class ListClipper {
g.clipperTempData += ListClipperData()
val data = g.clipperTempData[g.clipperTempDataStacked - 1]
data.reset(this)
data.lossynessOffset = window.dc.cursorStartPosLossyness.y
tempData = data
}

Expand Down Expand Up @@ -188,8 +189,8 @@ class ListClipper {
// which with the flooring/ceiling tend to lead to 2 items instead of one being submitted.
for (i in data.ranges.indices)
if (data.ranges[i].posToIndexConvert) {
val m1 = ((data.ranges[i].min.d - window.dc.cursorPos.y) / itemsHeight).i
val m2 = (((data.ranges[i].max.d - window.dc.cursorPos.y) / itemsHeight) + 0.999999f).i
val m1 = ((data.ranges[i].min.d - window.dc.cursorPos.y - data.lossynessOffset) / itemsHeight).i
val m2 = (((data.ranges[i].max.d - window.dc.cursorPos.y - data.lossynessOffset) / itemsHeight) + 0.999999f).i
data.ranges[i].min = clamp(alreadySubmitted + m1 + floor((data.ranges[i].min - window.dc.cursorPos.y) / itemsHeight).i + data.ranges[i].posToIndexOffsetMin, alreadySubmitted, itemsCount - 1)
data.ranges[i].max = clamp(alreadySubmitted + m2 + ceil((data.ranges[i].max - window.dc.cursorPos.y) / itemsHeight).i + 0 + data.ranges[i].posToIndexOffsetMax, data.ranges[i].min + 1, itemsCount)
data.ranges[i].posToIndexConvert = false
Expand Down Expand Up @@ -245,7 +246,7 @@ class ListClipper {
// StartPosY starts from ItemsFrozen hence the subtraction
// Perform the add and multiply with double to allow seeking through larger ranges
val data = clipper.tempData as ListClipperData
val posY = (clipper.startPosY.d + (itemN - data.itemsFrozen).d * clipper.itemsHeight).f
val posY = (clipper.startPosY.d + data.lossynessOffset + (itemN - data.itemsFrozen).d * clipper.itemsHeight).f
seekCursorAndSetupPrevLine(posY, clipper.itemsHeight)
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/kotlin/imgui/imgui.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const val IMGUI_VERSION_BUILD = "$IMGUI_VERSION.$IMGUI_BUILD"

/** Integer encoded as XYYZZ for use in #if preprocessor conditionals.
Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) */
const val IMGUI_VERSION_NUM = 18514
const val IMGUI_VERSION_NUM = 18515


// Helpers macros to generate 32-bits encoded colors
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/kotlin/imgui/internal/classes/WindowTempData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class WindowTempData {

var groupOffset = 0f

/** Record the loss of precision of CursorStartPos due to really large scrolling amount. This is used by clipper to compensentate and fix the most common use case of large scroll area. */
val cursorStartPosLossyness = Vec2()

// Keyboard/Gamepad navigation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class ListClipperRange {
// Temporary clipper data, buffers shared/reused between instances
class ListClipperData {
lateinit var listClipper: ListClipper
var lossynessOffset = 0f
var stepNo = 0
var itemsFrozen = 0
val ranges = ArrayList<ListClipperRange>()
Expand Down

0 comments on commit a487f09

Please sign in to comment.