@@ -2,6 +2,7 @@ package imgui
22
33import glm_.*
44import imgui.internal.addClampOverflow
5+ import imgui.internal.charIsBlankA
56import imgui.internal.parseFormatSanitizeForScanning
67import imgui.internal.subClampOverflow
78import uno.kotlin.NUL
@@ -39,29 +40,42 @@ sealed interface NumberOps<N> where N : Number, N : Comparable<N> {
3940 val dataType: DataType
4041 val Number .coerced: N
4142
42- /* * return true if modified */
43- fun KMutableProperty0<N>.applyFromText (buf : String , format : String ): Boolean {
44- val initial = get()
43+ /* * User can input math operators (e.g. +100) to edit a numerical values.
44+ * NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
45+ *
46+ * ~DataTypeApplyFromText
47+ * @return true if modified */
48+ fun KMutableProperty0<N>.applyFromText (buf : ByteArray , format : String ): Boolean {
49+
50+ var ptr = 0
51+ while (charIsBlankA(buf[ptr].i))
52+ ptr++
53+ if (buf[ptr] == 0 .b)
54+ return false
55+
56+ // Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all.
57+ val backupData = get()
58+
4559 val v = parse(buf, format)
4660 return v?.let {
4761 this .set(v)
48- get() != initial
62+ get() != backupData
4963 } == true
5064 }
5165
52- fun parse (buf : String , format : String , radix : Int ): N
66+ fun parse (buf : ByteArray , format : String , radix : Int ): N
5367 val String .parsed: N
5468
5569 fun N.format (format : String ): String {
5670 // [JVM] we have to filter `.`, since `%.03d` causes `IllegalFormatPrecisionException`, but `%03d` doesn't
5771 return format.replace(" ." , " " ).format(when (this ) {
58- // we need to intervene since java printf cant handle %u
59- is Ubyte -> i
60- is Ushort -> i
61- is Uint -> L
62- is Ulong -> toBigInt()
63- else -> this
64- })
72+ // we need to intervene since java printf cant handle %u
73+ is Ubyte -> i
74+ is Ushort -> i
75+ is Uint -> L
76+ is Ulong -> toBigInt()
77+ else -> this
78+ })
6579 }
6680
6781 operator fun N.plus (other : N ): N
@@ -73,9 +87,13 @@ sealed interface NumberOps<N> where N : Number, N : Comparable<N> {
7387private fun <N , FP > NumberFpOps <N , FP >.nTimesN (n : N , other : N ): N where N : Number , N : Comparable<N>, FP : Number, FP : Comparable<FP> = (n.fp * other.fp).n
7488private fun <N , FP > NumberFpOps <N , FP >.nDivN (n : N , other : N ): N where N : Number , N : Comparable<N>, FP : Number, FP : Comparable<FP> = (n.fp / other.fp).n
7589
76- fun <N > NumberOps<N>.parse (buf : String , format : String ): N ? where N : Number , N : Comparable<N> {
90+ fun <N > NumberOps<N>.parse (buf : ByteArray , format : String ): N ? where N : Number , N : Comparable<N> {
7791 // ImCharIsBlankA
78- @Suppress(" NAME_SHADOWING" ) val buf = buf.replace(Regex (" \\ s+" ), " " ).replace(" \t " , " " ).removeSuffix(" \u0000 " )
92+ buf.cStr
93+ .replace(Regex (" \\ s+" ), " " )
94+ .replace(" \t " , " " )
95+ .removeSuffix(" \u0000 " )
96+ .toByteArray(buf)
7997
8098 if (buf.isEmpty()) return null
8199
@@ -92,6 +110,7 @@ fun NumberOps<*>.defaultInputCharsFilter(format: String): InputTextFlag.Single {
92110 else -> InputTextFlag .CharsDecimal
93111 }
94112}
113+
95114val NumberOps <* >.defaultFormat: String
96115 get() = when (dataType) {
97116 DataType .Float , DataType .Double -> " %.3f"
@@ -138,9 +157,11 @@ sealed interface FloatingPointOps<FP> where FP : Number, FP : Comparable<FP> {
138157 @Suppress(" INAPPLICABLE_JVM_NAME" )
139158 @JvmName(" fpMinus" )
140159 operator fun FP.minus (other : FP ): FP
160+
141161 @Suppress(" INAPPLICABLE_JVM_NAME" )
142162 @JvmName(" fpTimes" )
143163 operator fun FP.times (other : FP ): FP
164+
144165 @Suppress(" INAPPLICABLE_JVM_NAME" )
145166 @JvmName(" fpDiv" )
146167 operator fun FP.div (other : FP ): FP
@@ -169,7 +190,7 @@ object ByteOps : NumberFpOps<Byte, Float>, FloatingPointOps<Float> by FloatOps {
169190 override val one: Byte = 1
170191 override val Number .coerced get() = b
171192 override val dataType: DataType = DataType .Byte
172- override fun parse (buf : String , format : String , radix : Int ): Byte = format.format(buf.parseInt(radix)).toByte(radix)
193+ override fun parse (buf : ByteArray , format : String , radix : Int ): Byte = format.format(buf.cStr .parseInt(radix)).toByte(radix)
173194 override val String .parsed: Byte get() = b
174195 override fun Byte.plus (other : Byte ): Byte = addClampOverflow(i, other.i, min.i, max.i).b
175196 override fun Byte.minus (other : Byte ): Byte = subClampOverflow(i, other.i, min.i, max.i).b
@@ -183,7 +204,7 @@ object UbyteOps : NumberFpOps<Ubyte, Float>, FloatingPointOps<Float> by FloatOps
183204 override val Ubyte .isNegative: Boolean get() = false
184205 override val Number .coerced get() = ub
185206 override val dataType: DataType = DataType .Ubyte
186- override fun parse (buf : String , format : String , radix : Int ): Ubyte = format.format(buf.parseInt(radix)).toInt(radix).ub
207+ override fun parse (buf : ByteArray , format : String , radix : Int ): Ubyte = format.format(buf.cStr .parseInt(radix)).toInt(radix).ub
187208 override val String .parsed: Ubyte get() = ub
188209 override fun Ubyte.plus (other : Ubyte ): Ubyte = addClampOverflow(i, other.i, min.i, max.i).ub
189210 override fun Ubyte.minus (other : Ubyte ): Ubyte = subClampOverflow(i, other.i, min.i, max.i).ub
@@ -196,7 +217,7 @@ object ShortOps : NumberFpOps<Short, Float>, FloatingPointOps<Float> by FloatOps
196217 override val one: Short = 1
197218 override val Number .coerced get() = s
198219 override val dataType: DataType = DataType .Short
199- override fun parse (buf : String , format : String , radix : Int ): Short = format.format(buf.parseInt(radix)).toShort(radix)
220+ override fun parse (buf : ByteArray , format : String , radix : Int ): Short = format.format(buf.cStr .parseInt(radix)).toShort(radix)
200221 override val String .parsed: Short get() = s
201222 override fun Short.plus (other : Short ): Short = addClampOverflow(i, other.i, min.i, max.i).s
202223 override fun Short.minus (other : Short ): Short = subClampOverflow(i, other.i, min.i, max.i).s
@@ -210,7 +231,7 @@ object UshortOps : NumberFpOps<Ushort, Float>, FloatingPointOps<Float> by FloatO
210231 override val Ushort .isNegative: Boolean get() = false
211232 override val Number .coerced get() = us
212233 override val dataType: DataType = DataType .Ushort
213- override fun parse (buf : String , format : String , radix : Int ): Ushort = format.format(buf.parseInt(radix)).toInt(radix).us
234+ override fun parse (buf : ByteArray , format : String , radix : Int ): Ushort = format.format(buf.cStr .parseInt(radix)).toInt(radix).us
214235 override val String .parsed: Ushort get() = us
215236 override fun Ushort.plus (other : Ushort ): Ushort = addClampOverflow(i, other.i, min.i, max.i).us
216237 override fun Ushort.minus (other : Ushort ): Ushort = subClampOverflow(i, other.i, min.i, max.i).us
@@ -223,7 +244,7 @@ object IntOps : NumberFpOps<Int, Float>, FloatingPointOps<Float> by FloatOps {
223244 override val one = 1
224245 override val Number .coerced get() = i
225246 override val dataType: DataType = DataType .Int
226- override fun parse (buf : String , format : String , radix : Int ): Int = format.format(buf.parseInt(radix)).toInt(radix)
247+ override fun parse (buf : ByteArray , format : String , radix : Int ): Int = format.format(buf.cStr .parseInt(radix)).toInt(radix)
227248 override val String .parsed: Int get() = i
228249 override fun Int.plus (other : Int ): Int = addClampOverflow(this , other, min, max)
229250 override fun Int.minus (other : Int ): Int = subClampOverflow(this , other, min, max)
@@ -237,7 +258,7 @@ object UintOps : NumberFpOps<Uint, Float>, FloatingPointOps<Float> by FloatOps {
237258 override val Uint .isNegative: Boolean get() = false
238259 override val Number .coerced get() = ui
239260 override val dataType: DataType = DataType .Uint
240- override fun parse (buf : String , format : String , radix : Int ): Uint = format.format(buf.parseLong(radix)).toLong(radix).ui
261+ override fun parse (buf : ByteArray , format : String , radix : Int ): Uint = format.format(buf.cStr .parseLong(radix)).toLong(radix).ui
241262 override val String .parsed: Uint get() = ui
242263 override fun Uint.plus (other : Uint ): Uint = addClampOverflow(L , other.L , min.L , max.L ).ui
243264 override fun Uint.minus (other : Uint ): Uint = subClampOverflow(L , other.L , min.L , max.L ).ui
@@ -250,7 +271,7 @@ object LongOps : NumberFpOps<Long, Double>, FloatingPointOps<Double> by DoubleOp
250271 override val one = 1L
251272 override val Number .coerced get() = L
252273 override val dataType: DataType = DataType .Long
253- override fun parse (buf : String , format : String , radix : Int ): Long = format.format(buf.parseUnsignedLong(radix)).toLong(radix)
274+ override fun parse (buf : ByteArray , format : String , radix : Int ): Long = format.format(buf.cStr .parseUnsignedLong(radix)).toLong(radix)
254275 override val String .parsed: Long get() = L
255276 override fun Long.plus (other : Long ): Long = addClampOverflow(this , other, min, max)
256277 override fun Long.minus (other : Long ): Long = subClampOverflow(this , other, min, max)
@@ -264,7 +285,7 @@ object UlongOps : NumberFpOps<Ulong, Double>, FloatingPointOps<Double> by Double
264285 override val Ulong .isNegative: Boolean get() = false
265286 override val Number .coerced get() = ul
266287 override val dataType: DataType = DataType .Ulong
267- override fun parse (buf : String , format : String , radix : Int ): Ulong = format.format(buf.parseUnsignedLong(radix)).toBigInteger(radix).ul
288+ override fun parse (buf : ByteArray , format : String , radix : Int ): Ulong = format.format(buf.cStr .parseUnsignedLong(radix)).toBigInteger(radix).ul
268289 override val String .parsed: Ulong get() = ul
269290 override fun Ulong.plus (other : Ulong ): Ulong = addClampOverflow(toBigInt(), other.toBigInt(), min.toBigInt(), max.toBigInt()).ul
270291 override fun Ulong.minus (other : Ulong ): Ulong = subClampOverflow(toBigInt(), other.toBigInt(), min.toBigInt(), max.toBigInt()).ul
@@ -280,7 +301,7 @@ object FloatOps : NumberFpOps<Float, Float> {
280301 override val Number .coercedFp: Float get() = f
281302 override val dataType: DataType = DataType .Float
282303 override fun Float.format (format : String ): String = format.format(this )
283- override fun parse (buf : String , format : String , radix : Int ): Float = " %f" .format(buf.parseFloat).f
304+ override fun parse (buf : ByteArray , format : String , radix : Int ): Float = " %f" .format(buf.cStr .parseFloat).f
284305 override val String .parsed: Float get() = f
285306 override fun Float.unaryMinus (): Float = - this
286307
@@ -291,9 +312,11 @@ object FloatOps : NumberFpOps<Float, Float> {
291312 @Suppress(" INAPPLICABLE_JVM_NAME" )
292313 @JvmName(" fpMinus" )
293314 override fun Float.minus (other : Float ): Float = this - other
315+
294316 @Suppress(" INAPPLICABLE_JVM_NAME" )
295317 @JvmName(" fpTimes" )
296318 override fun Float.times (other : Float ): Float = this * other
319+
297320 @Suppress(" INAPPLICABLE_JVM_NAME" )
298321 @JvmName(" fpDiv" )
299322 override fun Float.div (other : Float ): Float = this / other
@@ -310,7 +333,7 @@ object DoubleOps : NumberFpOps<Double, Double> {
310333 override val Number .coercedFp: Double get() = d
311334 override val dataType: DataType = DataType .Double
312335 override fun Double.format (format : String ): String = format.format(this )
313- override fun parse (buf : String , format : String , radix : Int ): Double = " %f" .format(buf.parseDouble).d
336+ override fun parse (buf : ByteArray , format : String , radix : Int ): Double = " %f" .format(buf.cStr .parseDouble).d
314337 override val String .parsed: Double get() = d
315338 override fun Double.unaryMinus (): Double = - this
316339
@@ -321,9 +344,11 @@ object DoubleOps : NumberFpOps<Double, Double> {
321344 @Suppress(" INAPPLICABLE_JVM_NAME" )
322345 @JvmName(" fpMinus" )
323346 override fun Double.minus (other : Double ): Double = this - other
347+
324348 @Suppress(" INAPPLICABLE_JVM_NAME" )
325349 @JvmName(" fpTimes" )
326350 override fun Double.times (other : Double ): Double = this * other
351+
327352 @Suppress(" INAPPLICABLE_JVM_NAME" )
328353 @JvmName(" fpDiv" )
329354 override fun Double.div (other : Double ): Double = this / other
0 commit comments