diff --git a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt index 9af7b4b..00044e1 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt @@ -52,6 +52,9 @@ import kotlin.reflect.full.declaredMemberProperties // Copying particle params in-game. // Custom curve equation command args (parse from strings). // Force field "config" option. + +// TODO: (now) +// add lerpValInt to commands // Better particle debug tools. // Use more BDEs instead of particles, and show more values than origin and velocity. diff --git a/src/main/kotlin/com/bytedice/bde_particles/commands/ConfigArgs.kt b/src/main/kotlin/com/bytedice/bde_particles/commands/ConfigArgs.kt index 4bc324d..ad207df 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/commands/ConfigArgs.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/commands/ConfigArgs.kt @@ -103,12 +103,15 @@ fun parseArgTypeToFunc(type: KType, configArg: LiteralArgumentBuilder { access, config, reg -> stringCurveArg(access as KProperty1, config, reg) } - ParamClasses.LerpVal::class -> { access, config, _ -> - lerpValArg(access as KProperty1, config) + ParamClasses.LerpValVec3f::class -> { access, config, _ -> + lerpValVec3fArg(access as KProperty1, config) } ParamClasses.ForceFieldArray::class -> { access, config, _ -> forceFieldArg(access as KProperty1, config) } + ParamClasses.LerpValInt::class -> { access, config, _ -> + lerpValIntArg(access as KProperty1, config) + } else -> null } } @@ -550,8 +553,8 @@ fun stringCurveRemoveArg(context: CommandContext, successText(access, "--$item", id, context) } -fun lerpValArg(access: KProperty1, - configArg: LiteralArgumentBuilder +fun lerpValVec3fArg(access: KProperty1, + configArg: LiteralArgumentBuilder ) : LiteralArgumentBuilder { return configArg @@ -575,7 +578,7 @@ fun lerpValArg(access: KProperty1, val curve = stringToCurve(curveName) - updateParam(id, access, ParamClasses.LerpVal.LerpVec3f(minX, minY, minZ, maxX, maxY, maxZ, curve!!)) + updateParam(id, access, ParamClasses.LerpValVec3f.LerpVec3f(minX, minY, minZ, maxX, maxY, maxZ, curve!!)) successText(access, "LerpVec3f", id, context) Command.SINGLE_SUCCESS @@ -614,7 +617,7 @@ fun lerpValArg(access: KProperty1, val curveY = stringToCurve(curveNameY) val curveZ = stringToCurve(curveNameZ) - updateParam(id, access, ParamClasses.LerpVal.MultiLerpVec3f(minX, minY, minZ, maxX, maxY, maxZ, curveX!!, curveY!!, curveZ!!)) + updateParam(id, access, ParamClasses.LerpValVec3f.MultiLerpVec3f(minX, minY, minZ, maxX, maxY, maxZ, curveX!!, curveY!!, curveZ!!)) successText(access, "MultiLerpVec3f", id, context) Command.SINGLE_SUCCESS @@ -629,11 +632,51 @@ fun lerpValArg(access: KProperty1, ) ) ) + .then(CommandManager.literal("LerpUniform") + .then(CommandManager.argument("Min", FloatArgumentType.floatArg()) + .then(CommandManager.argument("Max", FloatArgumentType.floatArg()) + .then(curveListArg("Curve") + .executes { context -> + val id = StringArgumentType.getString(context, "Emitter ID") + val min = FloatArgumentType.getFloat(context, "Min") + val max = FloatArgumentType.getFloat(context, "Max") + val curveName = StringArgumentType.getString(context, "Curve") + + val curve = stringToCurve(curveName) + + updateParam(id, access, ParamClasses.LerpValVec3f.LerpUniform(min, max, curve!!)) + + successText(access, "LerpUniform", id, context) + Command.SINGLE_SUCCESS + } + ) + ) + ) + ) + .then(CommandManager.literal("Constant") + .then(CommandManager.argument("X", FloatArgumentType.floatArg()) + .then(CommandManager.argument("Y", FloatArgumentType.floatArg()) + .then(CommandManager.argument("Z", FloatArgumentType.floatArg()) + .executes { context -> + val id = StringArgumentType.getString(context, "Emitter ID") + val x = FloatArgumentType.getFloat(context, "X") + val y = FloatArgumentType.getFloat(context, "Y") + val z = FloatArgumentType.getFloat(context, "Z") + + updateParam(id, access, ParamClasses.LerpValVec3f.Constant(Vector3f(x, y, z))) + + successText(access, "Constant", id, context) + Command.SINGLE_SUCCESS + } + ) + ) + ) + ) .then(CommandManager.literal("Null") .executes { context -> val id = StringArgumentType.getString(context, "Emitter ID") - updateParam(id, access, ParamClasses.LerpVal.Null) + updateParam(id, access, ParamClasses.LerpValVec3f.Null) successText(access, "Null", id, context) Command.SINGLE_SUCCESS @@ -777,4 +820,55 @@ fun forceFieldRemoveArg(context: CommandContext, val calcIndex = if (index == -1) { forceFields.array.size } else { index.coerceIn(0, forceFields.array.size) } successText(access, "--ForceField at $calcIndex", id, context) +} + +fun lerpValIntArg(access: KProperty1, + configArg: LiteralArgumentBuilder + ) : LiteralArgumentBuilder +{ + return configArg + .then(CommandManager.literal("LerpInt") + .then(CommandManager.argument("Min", IntegerArgumentType.integer()) + .then(CommandManager.argument("Max", IntegerArgumentType.integer()) + .then(curveListArg("Curve") + .executes { context -> + val id = StringArgumentType.getString(context, "Emitter ID") + val min = IntegerArgumentType.getInteger(context, "Min") + val max = IntegerArgumentType.getInteger(context, "Max") + val curveName = StringArgumentType.getString(context, "Curve") + + val curve = stringToCurve(curveName) + + updateParam(id, access, ParamClasses.LerpValInt.LerpInt(min, max, curve!!)) + + successText(access, "LerpInt", id, context) + Command.SINGLE_SUCCESS + } + ) + ) + ) + ) + .then(CommandManager.literal("Constant") + .then(CommandManager.argument("Value", IntegerArgumentType.integer()) + .executes { context -> + val id = StringArgumentType.getString(context, "Emitter ID") + val value = IntegerArgumentType.getInteger(context, "Value") + + updateParam(id, access, ParamClasses.LerpValInt.Constant(value)) + + successText(access, "Constant", id, context) + Command.SINGLE_SUCCESS + } + ) + ) + .then(CommandManager.literal("Null") + .executes { context -> + val id = StringArgumentType.getString(context, "Emitter ID") + + updateParam(id, access, ParamClasses.LerpValInt.Null) + + successText(access, "Null", id, context) + Command.SINGLE_SUCCESS + } + ) } \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt index da62180..6fbc636 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt @@ -27,10 +27,11 @@ data class EmitterParams ( var drag: Float, var minVel: Float, // curves - var offsetCurve: ParamClasses.LerpVal, - var rotVelCurve: ParamClasses.LerpVal, - var scaleCurve: ParamClasses.LerpVal, - var modelCurve: ParamClasses.StringCurve, + var offsetCurve: ParamClasses.LerpValVec3f, + var rotVelCurve: ParamClasses.LerpValVec3f, + var scaleCurve: ParamClasses.LerpValVec3f, + var modelCurve: ParamClasses.StringCurve, + var brightnessCurve: ParamClasses.LerpValInt, ) { companion object Presets { @@ -53,9 +54,9 @@ data class EmitterParams ( constVel = Vector3f(0.0f, 0.0f, 0.0f), drag = 0.075f, minVel = 0.0f, - offsetCurve = ParamClasses.LerpVal.Null, - rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt), - scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 2.5f, LerpCurves.Linear), + offsetCurve = ParamClasses.LerpValVec3f.Null, + rotVelCurve = ParamClasses.LerpValVec3f.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt), + scaleCurve = ParamClasses.LerpValVec3f.LerpUniform(1.0f, 2.5f, LerpCurves.Linear), modelCurve = ParamClasses.StringCurve( arrayOf( "shroomlight", @@ -66,7 +67,8 @@ data class EmitterParams ( "light_gray_stained_glass" ), LerpCurves.Sqrt - ) + ), + brightnessCurve = ParamClasses.LerpValInt.LerpInt(15, 0, LerpCurves.Sqrt) ) val DEBUG = EmitterParams( maxCount = 50, @@ -87,9 +89,9 @@ data class EmitterParams ( constVel = Vector3f(0.0f, -0.05f, 0.0f), drag = 0.075f, minVel = 0.0f, - offsetCurve = ParamClasses.LerpVal.Null, - rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Linear), - scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.0f, LerpCurves.Linear), + offsetCurve = ParamClasses.LerpValVec3f.Null, + rotVelCurve = ParamClasses.LerpValVec3f.LerpUniform(1.0f, 0.0f, LerpCurves.Linear), + scaleCurve = ParamClasses.LerpValVec3f.LerpUniform(1.0f, 1.0f, LerpCurves.Linear), modelCurve = ParamClasses.StringCurve( arrayOf( "shroomlight", @@ -100,7 +102,8 @@ data class EmitterParams ( "light_gray_stained_glass" ), LerpCurves.Linear - ) + ), + brightnessCurve = ParamClasses.LerpValInt.Null ) val STRESS_TEST = EmitterParams( maxCount = 10000, @@ -126,9 +129,9 @@ data class EmitterParams ( constVel = Vector3f(0.0f, 0.001f, 0.0f), drag = 0.075f, minVel = 0.0f, - offsetCurve = ParamClasses.LerpVal.Null, - rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Linear), - scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.5f, LerpCurves.Linear), + offsetCurve = ParamClasses.LerpValVec3f.Null, + rotVelCurve = ParamClasses.LerpValVec3f.LerpUniform(1.0f, 0.0f, LerpCurves.Linear), + scaleCurve = ParamClasses.LerpValVec3f.LerpUniform(1.0f, 1.5f, LerpCurves.Linear), modelCurve = ParamClasses.StringCurve( arrayOf( "shroomlight", @@ -139,7 +142,8 @@ data class EmitterParams ( "light_gray_stained_glass" ), LerpCurves.Linear - ) + ), + brightnessCurve = ParamClasses.LerpValInt.Null ) } } \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt index 54f7fe7..8442cb7 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParamClasses.kt @@ -38,19 +38,22 @@ class ParamClasses { } data object Null : PairVec3f() } + class PairInt ( private val min: Int, private val max: Int, ) { fun randomize() : Int { return randomIntBetween(min, max) } } + class PairFloat( private val min: Float, private val max: Float, ) { fun randomize() : Float { return randomFloatBetween(min, max) } } - sealed class LerpVal { + + sealed class LerpValVec3f { class LerpVec3f( private val fromX: Float, private val fromY: Float, @@ -59,7 +62,7 @@ class ParamClasses { private val toY: Float, private val toZ: Float, private val curve: LerpCurves, - ) : LerpVal() { + ) : LerpValVec3f() { fun lerp(t: Float): Vector3f { val x = com.bytedice.bde_particles.lerp(fromX, toX, curve.function(t)) val y = com.bytedice.bde_particles.lerp(fromY, toY, curve.function(t)) @@ -77,7 +80,7 @@ class ParamClasses { private val curveX: LerpCurves, private val curveY: LerpCurves, private val curveZ: LerpCurves - ) : LerpVal() { + ) : LerpValVec3f() { fun lerp(t: Float): Vector3f { val x = com.bytedice.bde_particles.lerp(fromX, toX, curveX.function(t)) val y = com.bytedice.bde_particles.lerp(fromY, toY, curveY.function(t)) @@ -89,12 +92,13 @@ class ParamClasses { private val from: Float, private val to: Float, private val curve: LerpCurves, - ) : LerpVal() { + ) : LerpValVec3f() { fun lerp(t: Float) : Float { return com.bytedice.bde_particles.lerp(from, to, curve.function(t)) } } - data object Null : LerpVal() + data class Constant(val value: Vector3f) : LerpValVec3f() + data object Null : LerpValVec3f() fun lerpToVector3f(t: Float) : Vector3f { when (this) { @@ -104,10 +108,34 @@ class ParamClasses { val x = this.lerp(t) return Vector3f(x, x, x) } + is Constant -> return this.value is Null -> return Vector3f(1.0f, 1.0f, 1.0f) } } } + + sealed class LerpValInt { + class LerpInt( + private val from: Int, + private val to: Int, + private val curve: LerpCurves, + ) : LerpValInt() { + fun lerp(t: Float): Int { + return Math.round(com.bytedice.bde_particles.lerp(from.toFloat(), to.toFloat(), curve.function(t))) + } + } + data class Constant(val value: Int) : LerpValInt() + data object Null: LerpValInt() + + fun lerpToInt(t: Float) : Int? { + return when (this) { + is LerpInt -> this.lerp(t) + is Constant -> this.value + is Null -> null + } + } + } + sealed class Duration { data class SingleBurst( val loopDur: Int @@ -122,6 +150,7 @@ class ParamClasses { val loopDelay: Int ) : Duration() } + sealed class TransformWithVel { data object RotOnly : TransformWithVel() { fun velToRot(velocity: Vector3f): Vector3f { @@ -156,12 +185,14 @@ class ParamClasses { } data object None : TransformWithVel() } + class StringCurve ( var array: Array, var curve: LerpCurves ) { fun lerp(t: Float) : String { return lerpArray(array as Array, t, curve) as String } } + data class ForceFieldArray ( var array: Array ) diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt index 026c6a4..9238062 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt @@ -73,13 +73,14 @@ class Particle( val (quatRot, newPos) = calcTransformOffset(this.rot, originOffset, scale) val properties = DisplayEntityProperties( - pos = entityPos, - rot = entityRot, - model = if (emitterParams.modelCurve.array.isNotEmpty()) { emitterParams.modelCurve.lerp(0.0f) } else "none", - translation = newPos.add(pos), - leftRotation = quatRot, - scale = Vector3f(scale).mul(emitterParams.scaleCurve.lerpToVector3f(0.0f)), - tags = arrayOf("BPS_Particle", "BPS_UUID", SESSION_UUID.toString()) + pos = entityPos, + rot = entityRot, + model = if (emitterParams.modelCurve.array.isNotEmpty()) { emitterParams.modelCurve.lerp(0.0f) } else "none", + translation = newPos.add(pos), + leftRotation = quatRot, + scale = Vector3f(scale).mul(emitterParams.scaleCurve.lerpToVector3f(0.0f)), + tags = arrayOf("BPS_Particle", "BPS_UUID", SESSION_UUID.toString()), + brightnessOverride = emitterParams.brightnessCurve.lerpToInt(0.0f) ) particleEntity = DisplayEntity(properties) @@ -133,6 +134,7 @@ class Particle( val newModel = if (emitterParams.modelCurve.array.isNotEmpty()) { emitterParams.modelCurve.lerp(timeAliveClamped) } else "none" val (newVel, newPos) = calcPos() val newOriginOffset = Vector3f(originOffset.mul(emitterParams.offsetCurve.lerpToVector3f(timeAliveClamped))) + val newBrightness = emitterParams.brightnessCurve.lerpToInt(timeAliveClamped) val newScale: Vector3f val newRot: Vector3f @@ -166,12 +168,13 @@ class Particle( val combinedOffset = transformOffset.add(newPos) val newProperties = DisplayEntityProperties( - pos = entityPos, - model = newModel, - translation = combinedOffset.add(newOriginOffset), - leftRotation = quatRot, - scale = newScale, - tags = arrayOf("BPS_Particle", "BPS_UUID", SESSION_UUID.toString()) + pos = entityPos, + model = newModel, + translation = combinedOffset.add(newOriginOffset), + leftRotation = quatRot, + scale = newScale, + tags = arrayOf("BPS_Particle", "BPS_UUID", SESSION_UUID.toString()), + brightnessOverride = newBrightness ) return newProperties