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 91b57d3..84bccdc 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt @@ -27,10 +27,6 @@ import net.minecraft.world.World import java.util.* -// TODO: finish the particle ticking -// TODO: make custom commands to create particles easier (only temporarily saved) - - var ALL_PARTICLE_EMITTERS: Array = emptyArray() val sessionUuid: UUID = UUID.randomUUID() @@ -122,27 +118,26 @@ fun onRightClick(player: PlayerEntity, world: ServerWorld, hand: Hand) : TypedAc fun emitterParamsToJson(params: EmitterParams) : Map { val allParticleParamsJSON: MutableList> = mutableListOf() + val particle = params.particle - for (particle in params.particleTypes) { - val particleParamsJSON = mapOf( - "shape" to particle.shape, - "blockCurve" to particle.blockCurve, - "rotRandom" to particle.rotRandom, - "rotVelRandom" to particle.rotVelRandom, - "rotVelCurve" to particle.rotVelCurve, - "sizeRandom" to particle.sizeRandom, - "uniformSize" to particle.uniformSize, - "sizeCurve" to particle.sizeCurve, - "velRandom" to particle.velRandom, - "forceFields" to particle.forceFields, - "gravity" to particle.gravity, - "drag" to particle.drag, - "minVel" to particle.minVel, - "lifeTime" to particle.lifeTime - ) + val particleParamsJSON = mapOf( + "shape" to particle.shape, + "blockCurve" to particle.blockCurve, + "rotRandom" to particle.rotRandom, + "rotVelRandom" to particle.rotVelRandom, + "rotVelCurve" to particle.rotVelCurve, + "sizeRandom" to particle.sizeRandom, + "uniformSize" to particle.uniformSize, + "sizeCurve" to particle.sizeCurve, + "velRandom" to particle.velRandom, + "forceFields" to particle.forceFields, + "gravity" to particle.gravity, + "drag" to particle.drag, + "minVel" to particle.minVel, + "lifeTime" to particle.lifeTime + ) allParticleParamsJSON.add(particleParamsJSON) - } val emitterParamsJSON = mapOf( "maxCount" to params.maxCount, diff --git a/src/main/kotlin/com/bytedice/bde_particles/Math.kt b/src/main/kotlin/com/bytedice/bde_particles/Math.kt index b1e00d9..8418ac1 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/Math.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/Math.kt @@ -224,24 +224,25 @@ fun interpolateCurve(start: Vector3f, end: Vector3f, t: Float, curve: Interpolat } -fun sdfSphere(point: Vec3d, radius: Double): Double { - val x = point.x - val y = point.y - val z = point.z +fun sdfSphere(pos: Vector3f, radius: Float, objectPos: Vector3f): Float { + val dx = objectPos.x - pos.x + val dy = objectPos.y - pos.y + val dz = objectPos.z - pos.z - val distanceFromCenter = sqrt(x * x + y * y + z * z) - return distanceFromCenter - radius + val distanceFromCenter = sqrt(dx * dx + dy * dy + dz * dz) + return (distanceFromCenter - radius) } -fun sdfCube(point: Vec3d, size: Vec3d): Double { - val px = point.x - val py = point.y - val pz = point.z - val sx = size.x - val sy = size.y - val sz = size.z +fun sdfCube(pos: Vector3f, size: Vector3f, objectPos: Vector3f): Float { + val px = objectPos.x - pos.x + val py = objectPos.y - pos.y + val pz = objectPos.z - pos.z + + val sx = size.x.toDouble() + val sy = size.y.toDouble() + val sz = size.z.toDouble() val halfSize = Triple(sx / 2, sy / 2, sz / 2) @@ -256,5 +257,10 @@ fun sdfCube(point: Vec3d, size: Vec3d): Double { val insideDistance = min(max(dx, max(dy, dz)), 0.0) - return outsideDistance + insideDistance + return (outsideDistance + insideDistance).toFloat() +} + + +fun normalizeSdf(sdf: Float, radius: Float): Float { + return if (sdf < 0) (sdf + radius) / radius else 0f } \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/commands/ManageConfigArgs.kt b/src/main/kotlin/com/bytedice/bde_particles/commands/ManageConfigArgs.kt index e7f3213..ad74f0d 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/commands/ManageConfigArgs.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/commands/ManageConfigArgs.kt @@ -24,9 +24,10 @@ import java.util.concurrent.CompletableFuture val curves = arrayOf("LINEAR", "SQRT", "EXPONENT", "CUBIC", "SINE", "COSINE", "INVERSE", "LOG", "EXP", "BOUNCE") -fun argUpdateEmitterParam(context: CommandContext, paramName: String, typeValue: Any) : MutableText { + +fun updateEmitterParam(context: CommandContext, paramName: String, typeValue: Any) : MutableText { val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID") - val success = updateSingleParam(emitterIdVal, -1, paramName, typeValue) + val success = updateSingleEmitterParam(emitterIdVal, paramName, typeValue) val feedback = if (success) { Text.literal("BPS - Successfully updated Emitter ID \"$emitterIdVal\": Parameter \"$paramName\", value \"$typeValue\"") @@ -42,17 +43,18 @@ fun argUpdateEmitterParam(context: CommandContext, paramNam } -fun argUpdateParticleParam(context: CommandContext, particleIndex: Int, paramName: String, typeValue: Any) : MutableText { +fun updateParticleParam(context: CommandContext, paramName: String, typeValue: Any) : MutableText { val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID") - val success = updateSingleParam(emitterIdVal, particleIndex, paramName, typeValue) + val particle = getEmitterParams(emitterIdVal)?.particle + val success = updateSingleParticleParam(emitterIdVal, paramName, typeValue) val feedback = if (success) { - Text.literal("BPS - Successfully updated Emitter ID \"$emitterIdVal\": Index \"$particleIndex\", parameter \"$paramName\", value \"$typeValue\"") + Text.literal("BPS - Successfully updated Particle of Emitter ID \"$emitterIdVal\": parameter \"$paramName\", value \"$typeValue\"") .setStyle(Style.EMPTY.withColor(Color(0, 200, 0).rgb)) } else { - Text.literal("BPS - Failed to update Emitter ID \"$emitterIdVal\": Index \"$particleIndex\", parameter \"$paramName\", value \"$typeValue\": Unknown Error\n" + - "Try checking if the emitter, particle index, and parameter exist, and the value is the correct type.") + Text.literal("BPS - Failed to update Emitter ID \"$emitterIdVal\": parameter \"$paramName\", value \"$typeValue\": Unknown Error\n" + + "Try checking if the Emitter ID and parameter exist, and the value is the correct type.") .setStyle(Style.EMPTY.withColor(Color(200, 0, 0).rgb)) } @@ -63,62 +65,57 @@ fun argUpdateParticleParam(context: CommandContext, particl class ArgConfigEmitterKeys { fun maxCount() : LiteralArgumentBuilder { return CommandManager.literal("maxCount") - .then( - CommandManager.argument("Int", IntegerArgumentType.integer()) - .executes { context -> - val typeValue = IntegerArgumentType.getInteger(context, "Int") - val feedback = argUpdateEmitterParam(context, "maxCount", typeValue) - context.source.sendFeedback({ feedback }, false) - Command.SINGLE_SUCCESS - } + .then(CommandManager.argument("Int", IntegerArgumentType.integer()) + .executes { context -> + val typeValue = IntegerArgumentType.getInteger(context, "Int") + val feedback = updateEmitterParam(context, "maxCount", typeValue) + context.source.sendFeedback({ feedback }, false) + Command.SINGLE_SUCCESS + } ) } fun spawnsPerTick() : LiteralArgumentBuilder { return CommandManager.literal("spawnsPerTick") - .then( - CommandManager.argument("Int", IntegerArgumentType.integer()) - .executes { context -> - val typeValue = IntegerArgumentType.getInteger(context, "Int") - val feedback = argUpdateEmitterParam(context, "spawnsPerTick", typeValue) - context.source.sendFeedback({ feedback }, false) - Command.SINGLE_SUCCESS - } + .then(CommandManager.argument("Int", IntegerArgumentType.integer()) + .executes { context -> + val typeValue = IntegerArgumentType.getInteger(context, "Int") + val feedback = updateEmitterParam(context, "spawnsPerTick", typeValue) + context.source.sendFeedback({ feedback }, false) + Command.SINGLE_SUCCESS + } ) } fun loopDur() : LiteralArgumentBuilder { return CommandManager.literal("loopDur") - .then( - CommandManager.argument("Int", IntegerArgumentType.integer()) - .executes { context -> - val typeValue = IntegerArgumentType.getInteger(context, "Int") - val feedback = argUpdateEmitterParam(context, "loopDur", typeValue) - context.source.sendFeedback({ feedback }, false) - Command.SINGLE_SUCCESS - } + .then(CommandManager.argument("Int", IntegerArgumentType.integer()) + .executes { context -> + val typeValue = IntegerArgumentType.getInteger(context, "Int") + val feedback = updateEmitterParam(context, "loopDur", typeValue) + context.source.sendFeedback({ feedback }, false) + Command.SINGLE_SUCCESS + } ) } fun loopDelay() : LiteralArgumentBuilder { return CommandManager.literal("loopDelay") - .then( - CommandManager.argument("Int", IntegerArgumentType.integer()) - .executes { context -> - val typeValue = IntegerArgumentType.getInteger(context, "Int") - val feedback = argUpdateEmitterParam(context, "loopDelay", typeValue) - context.source.sendFeedback({ feedback }, false) - Command.SINGLE_SUCCESS - } + .then(CommandManager.argument("Int", IntegerArgumentType.integer()) + .executes { context -> + val typeValue = IntegerArgumentType.getInteger(context, "Int") + val feedback = updateEmitterParam(context, "loopDelay", typeValue) + context.source.sendFeedback({ feedback }, false) + Command.SINGLE_SUCCESS + } ) } fun loopCount() : LiteralArgumentBuilder { return CommandManager.literal("loopCount") - .then( - CommandManager.argument("Int", IntegerArgumentType.integer()) - .executes { context -> - val typeValue = IntegerArgumentType.getInteger(context, "Int") - val feedback = argUpdateEmitterParam(context, "loopCount", typeValue) - context.source.sendFeedback({ feedback }, false) - Command.SINGLE_SUCCESS - } + .then(CommandManager.argument("Int", IntegerArgumentType.integer()) + .executes { context -> + val typeValue = IntegerArgumentType.getInteger(context, "Int") + val feedback = updateEmitterParam(context, "loopCount", typeValue) + context.source.sendFeedback({ feedback }, false) + Command.SINGLE_SUCCESS + } ) } } @@ -130,9 +127,8 @@ class ArgConfigParticleKeys { .then(CommandManager.literal("circle") .then(CommandManager.argument("Radius", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val radius = FloatArgumentType.getFloat(context, "Radius") - val feedback = argUpdateParticleParam(context, particleIndex, "shape", SpawningShape.CIRCLE(radius)) + val feedback = updateParticleParam(context, "shape", SpawningShape.CIRCLE(radius)) context.source.sendFeedback( { feedback }, false) Command.SINGLE_SUCCESS } @@ -142,10 +138,9 @@ class ArgConfigParticleKeys { .then(CommandManager.argument("Width", FloatArgumentType.floatArg()) .then(CommandManager.argument("Height", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val w = FloatArgumentType.getFloat(context, "Width") val h = FloatArgumentType.getFloat(context, "Height") - val feedback = argUpdateParticleParam(context, particleIndex, "shape", SpawningShape.RECT(Vector2f(w, h))) + val feedback = updateParticleParam(context, "shape", SpawningShape.RECT(Vector2f(w, h))) context.source.sendFeedback( { feedback }, false) Command.SINGLE_SUCCESS } @@ -157,11 +152,10 @@ class ArgConfigParticleKeys { .then(CommandManager.argument("Y", FloatArgumentType.floatArg()) .then(CommandManager.argument("Z", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val x = FloatArgumentType.getFloat(context, "X") val y = FloatArgumentType.getFloat(context, "Y") val z = FloatArgumentType.getFloat(context, "Z") - val feedback = argUpdateParticleParam(context, particleIndex, "shape", SpawningShape.CUBE(Vector3f(x, y, z))) + val feedback = updateParticleParam(context, "shape", SpawningShape.CUBE(Vector3f(x, y, z))) context.source.sendFeedback( { feedback }, false) Command.SINGLE_SUCCESS } @@ -172,9 +166,8 @@ class ArgConfigParticleKeys { .then(CommandManager.literal("sphere") .then(CommandManager.argument("Radius", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val radius = FloatArgumentType.getFloat(context, "Radius") - val feedback = argUpdateParticleParam(context, particleIndex, "shape", SpawningShape.SPHERE(radius)) + val feedback = updateParticleParam(context, "shape", SpawningShape.SPHERE(radius)) context.source.sendFeedback( { feedback }, false) Command.SINGLE_SUCCESS } @@ -185,10 +178,9 @@ class ArgConfigParticleKeys { return CommandManager.literal("blockCurve") .then(CommandManager.argument("Array (separate by comma)", StringArgumentType.string()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val typeValue = StringArgumentType.getString(context, "Array (separate by comma)") val typeArray = typeValue.split(",").toTypedArray() - val feedback = argUpdateParticleParam(context, particleIndex, "blockCurve", typeArray) + val feedback = updateParticleParam(context, "blockCurve", typeArray) context.source.sendFeedback({ feedback }, false) Command.SINGLE_SUCCESS } @@ -203,10 +195,8 @@ class ArgConfigParticleKeys { .then(CommandManager.argument("Max Y", FloatArgumentType.floatArg()) .then(CommandManager.argument("Max Z", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val vectors = x1x2ToPairVector3f(context) - - val feedback = argUpdateParticleParam(context, particleIndex, "rotRandom", vectors) + val feedback = updateParticleParam(context, "rotRandom", vectors) context.source.sendFeedback({ feedback }, false) Command.SINGLE_SUCCESS } @@ -226,10 +216,8 @@ class ArgConfigParticleKeys { .then(CommandManager.argument("Max Y", FloatArgumentType.floatArg()) .then(CommandManager.argument("Max Z", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val vectors = x1x2ToPairVector3f(context) - - val feedback = argUpdateParticleParam(context, particleIndex, "rotVelRandom", vectors) + val feedback = updateParticleParam(context, "rotVelRandom", vectors) context.source.sendFeedback({ feedback }, false) Command.SINGLE_SUCCESS } @@ -249,10 +237,8 @@ class ArgConfigParticleKeys { .then(CommandManager.argument("Max Y", FloatArgumentType.floatArg()) .then(CommandManager.argument("Max Z", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val vectors = x1x2ToPairVector3f(context) - - val feedback = argUpdateParticleParam(context, particleIndex, "sizeRandom", vectors) + val feedback = updateParticleParam(context, "sizeRandom", vectors) context.source.sendFeedback({ feedback }, false) Command.SINGLE_SUCCESS } @@ -267,9 +253,8 @@ class ArgConfigParticleKeys { return CommandManager.literal("uniformSize") .then(CommandManager.argument("Bool", BoolArgumentType.bool()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val uniform = BoolArgumentType.getBool(context, "Bool") - val feedback = argUpdateParticleParam(context, particleIndex, "uniformSize", uniform) + val feedback = updateParticleParam(context, "uniformSize", uniform) context.source.sendFeedback( { feedback }, false) Command.SINGLE_SUCCESS } @@ -284,10 +269,8 @@ class ArgConfigParticleKeys { .then(CommandManager.argument("Max Y", FloatArgumentType.floatArg()) .then(CommandManager.argument("Max Z", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val vectors = x1x2ToPairVector3f(context) - - val feedback = argUpdateParticleParam(context, particleIndex, "velRandom", vectors) + val feedback = updateParticleParam(context, "velRandom", vectors) context.source.sendFeedback({ feedback }, false) Command.SINGLE_SUCCESS } @@ -299,7 +282,7 @@ class ArgConfigParticleKeys { ) } fun forceFields() : LiteralArgumentBuilder { - return CommandManager.literal("ForceFields") + return CommandManager.literal("forceFields") .then(argAddForceField()) .then(argRemoveForceField()) } @@ -309,12 +292,11 @@ class ArgConfigParticleKeys { .then(CommandManager.argument("Y", FloatArgumentType.floatArg()) .then(CommandManager.argument("Z", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val x1 = FloatArgumentType.getFloat(context, "X") val y1 = FloatArgumentType.getFloat(context, "Y") val z1 = FloatArgumentType.getFloat(context, "Z") - val feedback = argUpdateParticleParam(context, particleIndex, "gravity", Vector3f(x1, y1, z1)) + val feedback = updateParticleParam(context, "gravity", Vector3f(x1, y1, z1)) context.source.sendFeedback({ feedback }, false) Command.SINGLE_SUCCESS } @@ -326,9 +308,8 @@ class ArgConfigParticleKeys { return CommandManager.literal("drag") .then(CommandManager.argument("Float", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val value = FloatArgumentType.getFloat(context, "Float") - val feedback = argUpdateParticleParam(context, particleIndex, "drag", value) + val feedback = updateParticleParam(context, "drag", value) context.source.sendFeedback( { feedback }, false) Command.SINGLE_SUCCESS } @@ -338,9 +319,8 @@ class ArgConfigParticleKeys { return CommandManager.literal("minVel") .then(CommandManager.argument("Float", FloatArgumentType.floatArg()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val value = FloatArgumentType.getFloat(context, "Float") - val feedback = argUpdateParticleParam(context, particleIndex, "minVel", value) + val feedback = updateParticleParam(context, "minVel", value) context.source.sendFeedback( { feedback }, false) Command.SINGLE_SUCCESS } @@ -351,10 +331,9 @@ class ArgConfigParticleKeys { .then(CommandManager.argument("min", IntegerArgumentType.integer()) .then(CommandManager.argument("max", IntegerArgumentType.integer()) .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val min = IntegerArgumentType.getInteger(context, "min") val max = IntegerArgumentType.getInteger(context, "max") - val feedback = argUpdateParticleParam(context, particleIndex, "lifeTime", Pair(min, max)) + val feedback = updateParticleParam(context, "lifeTime", Pair(min, max)) context.source.sendFeedback( { feedback }, false) Command.SINGLE_SUCCESS } @@ -375,13 +354,11 @@ class ArgConfigParticleKeys { CompletableFuture.completedFuture(builder.build()) } .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val vectors = x1x2ToPairVector3f(context) val curveString = StringArgumentType.getString(context, "Curve") - val feedback = argUpdateParticleParam( + val feedback = updateParticleParam( context, - particleIndex, "rotVelCurve", Triple(vectors.first, vectors.second, getCurveByString(curveString))) @@ -410,13 +387,11 @@ class ArgConfigParticleKeys { CompletableFuture.completedFuture(builder.build()) } .executes { context -> - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val vectors = x1x2ToPairVector3f(context) val curveString = StringArgumentType.getString(context, "Curve") - val feedback = argUpdateParticleParam( + val feedback = updateParticleParam( context, - particleIndex, "sizeCurve", Triple(vectors.first, vectors.second, getCurveByString(curveString))) @@ -503,10 +478,10 @@ fun argRemoveForceField() : LiteralArgumentBuilder { return CommandManager.literal("remove") .then(CommandManager.argument("Force Field Name", StringArgumentType.string()) .suggests { context, builder -> - val particleId = StringArgumentType.getString(context, "Registered Emitter ID") - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") - val params = getEmitterParams(particleId) - val forceFields = params!!.particleTypes[particleIndex].forceFields + val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID") + + val params = getEmitterParams(emitterIdVal) + val forceFields = params!!.particle.forceFields forceFields.iterator().forEach { builder.suggest(it.name) @@ -516,11 +491,10 @@ fun argRemoveForceField() : LiteralArgumentBuilder { } .executes { context -> val ffName = StringArgumentType.getString(context, "Force Field Name") - val particleId = StringArgumentType.getString(context, "Registered Emitter ID") - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") + val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID") - val params = getEmitterParams(particleId) - val forceFields = params!!.particleTypes[particleIndex].forceFields + val params = getEmitterParams(emitterIdVal) + val forceFields = params!!.particle.forceFields val newForceFields: MutableList = forceFields.toMutableList() for (forceField in forceFields) { @@ -529,9 +503,8 @@ fun argRemoveForceField() : LiteralArgumentBuilder { } } - val feedback = argUpdateParticleParam( + val feedback = updateParticleParam( context, - particleIndex, "forceFields", newForceFields ) @@ -543,19 +516,20 @@ fun argRemoveForceField() : LiteralArgumentBuilder { fun forceFieldAddSphereExec(context: CommandContext) : Int { - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") - val radius = FloatArgumentType.getFloat(context, "Radius") val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID") + + val radius = FloatArgumentType.getFloat(context, "Radius") + val minForce = FloatArgumentType.getFloat(context, "Min Force") + val maxForce = FloatArgumentType.getFloat(context, "Max Force") - val shape = ForceFieldShape.SPHERE(radius) + val shape = ForceFieldShape.SPHERE(radius, Pair(minForce, maxForce)) val forceField = forceFieldGenericParams(context, shape) val currentParams = getEmitterParams(emitterIdVal) - val forceFields = currentParams!!.particleTypes[particleIndex].forceFields + val forceFields = currentParams!!.particle.forceFields - val feedback = argUpdateParticleParam( + val feedback = updateParticleParam( context, - particleIndex, "forceFields", forceFields.toMutableList().add(forceField) ) @@ -568,7 +542,6 @@ fun forceFieldAddSphereExec(context: CommandContext) : Int fun forceFieldAddCubeExec(context: CommandContext) : Int { - val particleIndex = IntegerArgumentType.getInteger(context, "Particle Index") val xSize = FloatArgumentType.getFloat(context, "X Size") val ySize = FloatArgumentType.getFloat(context, "Y Size") val zSize = FloatArgumentType.getFloat(context, "Z Size") @@ -581,11 +554,10 @@ fun forceFieldAddCubeExec(context: CommandContext) : Int { val forceField = forceFieldGenericParams(context, shape) val currentParams = getEmitterParams(emitterIdVal) - val forceFields = currentParams!!.particleTypes[particleIndex].forceFields + val forceFields = currentParams!!.particle.forceFields - val feedback = argUpdateParticleParam( + val feedback = updateParticleParam( context, - particleIndex, "forceFields", forceFields.toMutableList().add(forceField) ) @@ -602,13 +574,10 @@ fun forceFieldGenericParams(context: CommandContext, shape: val posX = FloatArgumentType.getFloat(context, "X Pos") val posY = FloatArgumentType.getFloat(context, "Y Pos") val posZ = FloatArgumentType.getFloat(context, "Z Pos") - val minForce = FloatArgumentType.getFloat(context, "Min Force") - val maxForce = FloatArgumentType.getFloat(context, "Max Force") return ForceField( name.replace(" ", "_"), Vector3f(posX, posY, posZ), - Pair(minForce, maxForce), shape ) } \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/commands/ManageEmitters.kt b/src/main/kotlin/com/bytedice/bde_particles/commands/ManageEmitters.kt index 3348ab6..4734b11 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/commands/ManageEmitters.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/commands/ManageEmitters.kt @@ -36,7 +36,7 @@ import java.util.concurrent.CompletableFuture // config // - // <[particle index] / EMITTER> + // // // HARDCODED KEYS, if EMITTER use emitter params. // // HARDCODED TYPES // output -> update the selected parameter of the selected emitter id to the new value @@ -69,7 +69,7 @@ object ManageEmitters { val allEmitterIds = emitterIdRegister.keys -// TODO: maybe make this a Command.literal() if possible +// TODO: perhaps make this a Command.literal() if possible val emitterIdSuggestion: RequiredArgumentBuilder = CommandManager.argument("Registered Emitter ID", StringArgumentType.string()) .suggests { _, builder -> allEmitterIds.forEach { key -> @@ -212,30 +212,21 @@ fun argCopy() : LiteralArgumentBuilder { // config // - // <[particle index] / EMITTER> + // // // HARDCODED KEYS, if EMITTER use emitter params. // // HARDCODED TYPES // output -> update the selected parameter of the selected emitter id to the new value fun argConfig() : LiteralArgumentBuilder { return CommandManager.literal("config") .then(emitterIdSuggestion - .then(CommandManager.literal("EMITTER") + .then(CommandManager.literal("emitter") .then(emitterConfigKeys.maxCount()) .then(emitterConfigKeys.spawnsPerTick()) .then(emitterConfigKeys.loopDur()) .then(emitterConfigKeys.loopDelay()) .then(emitterConfigKeys.loopCount()) ) - .then(CommandManager.argument("Particle Index", IntegerArgumentType.integer()) - .suggests { context, builder -> - val emitterId = StringArgumentType.getString(context, "Registered Emitter ID") - - getEmitterParams(emitterId)?.particleTypes?.indices?.forEach { - builder.suggest(it) - } - - CompletableFuture.completedFuture(builder.build()) - } + .then(CommandManager.literal("particle") .then(particleConfigKeys.shape()) .then(particleConfigKeys.blockCurve()) .then(particleConfigKeys.rotRandom()) 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 41eb314..31f2f0c 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt @@ -9,15 +9,15 @@ package com.bytedice.bde_particles.particles * @param loopDur The duration for which the loop runs, in ticks. A value 0 or below means the loop is infinite, and `loopDelay` and `loopCount` will be ignored. * @param loopDelay The delay between each loop cycle, in ticks. Negative values are treated as 0, meaning no delay. * @param loopCount The number of times the loop will repeat. 0 means it will shoot a single burst of particles. A value below 0 means it will repeat indefinitely. - * @param particleTypes An array of `ParticleParams` defining the types of particles to spawn. If empty, no particles will spawn. + * @param particle The particle params of the particle that will spawn. */ data class EmitterParams ( - var maxCount: Int = 200, - var spawnsPerTick: Int = 1, - var loopDur: Int = 25, - var loopDelay: Int = 0, - var loopCount: Int = 0, - var particleTypes: Array = arrayOf(ParticleParams()), + var maxCount: Int = 200, + var spawnsPerTick: Int = 1, + var loopDur: Int = 25, + var loopDelay: Int = 0, + var loopCount: Int = 0, + var particle: ParticleParams = ParticleParams(), ) { companion object Presets { @@ -28,7 +28,7 @@ data class EmitterParams ( 25, 0, 0, - arrayOf(ParticleParams.DEFAULT) + ParticleParams.FIRE_GEYSER ) } } \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ForceFields.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ForceFields.kt index 782337f..ec77bf3 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ForceFields.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ForceFields.kt @@ -4,7 +4,6 @@ import org.joml.Vector3f data class ForceField ( val name: String = "DEFAULT", - val pos: Vector3f = Vector3f(0.0f, 0.0f, 0.0f), - val force: Pair = Pair(0.0f, 1.0f), + val pos: Vector3f = Vector3f(0.0f, 5.0f, 0.0f), val shape: ForceFieldShape = ForceFieldShape.SPHERE() ) \ No newline at end of file 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 25c593e..794abe5 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt @@ -5,8 +5,7 @@ import net.minecraft.server.world.ServerWorld import net.minecraft.util.math.Vec3d import org.joml.Vector3f import org.joml.Vector4f -import kotlin.math.abs -import kotlin.math.round +import kotlin.math.* class Particle(private val particleParams: ParticleParams) { @@ -124,13 +123,28 @@ class Particle(private val particleParams: ParticleParams) { return particleParams.blockCurve[newBlockIdx] } - /*fun calcVel() { - for (forceField in particleParams.forceFields) { - if (forceField.shape::class == ForceFieldShape.Sphere::class) { + fun sphereSdfVel(forceField: ForceField) : Vector3f { + if (forceField.shape !is ForceFieldShape.SPHERE) { return Vector3f(0.0f, 0.0f, 0.0f) } + val shape = forceField.shape - } - } - }*/ + val sdfVal = sdfSphere(forceField.pos, shape.radius, offset) + val normalizedSdf = normalizeSdf(sdfVal, shape.radius) + val velDir = Vector3f(offset).sub(forceField.pos).normalize() + val velMul = lerp(shape.force.second, shape.force.second, 1 - normalizedSdf) + + return velDir.mul(velMul) + } + + fun cubeSdfVel(forceField: ForceField) : Vector3f { + if (forceField.shape !is ForceFieldShape.CUBE) { return Vector3f(0.0f, 0.0f, 0.0f) } + val shape = forceField.shape + + val sdfVal = sdfCube(forceField.pos, shape.size, offset) + val velDir = if (sdfVal < 0) { shape.forceDir } + else { Vector3f(0.0f, 0.0f, 0.0f) } + + return velDir + } fun calcRot(timeAliveClamped: Float) : Vector3f { val newRot = Vector3f(rot) @@ -174,6 +188,11 @@ class Particle(private val particleParams: ParticleParams) { offset = newOffset rot = newRot + for (forceField in particleParams.forceFields) { + if (forceField.shape is ForceFieldShape.SPHERE) { vel.add(sphereSdfVel(forceField)) } + else if (forceField.shape is ForceFieldShape.CUBE) { vel.add(cubeSdfVel(forceField)) } + } + val (quatRot, transformOffset) = calcTransformOffset(newRot, initOffset, newScale) val combinedOffset = transformOffset.add(newOffset) diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt index 6dbfeeb..207ca73 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt @@ -33,16 +33,14 @@ class ParticleEmitter(private val emitterPos: Vec3d, private val emitterWorld: S private fun addParticle() { if (loopDelayActive) { return } - for (i in emitterParams.particleTypes.indices) { - repeat(this.emitterParams.spawnsPerTick) { - if (allParticles.size >= emitterParams.maxCount) { return } + repeat(this.emitterParams.spawnsPerTick) { + if (allParticles.size >= emitterParams.maxCount) { return } - val particle = Particle(emitterParams.particleTypes[i]) - particle.init(this.emitterPos) - particle.spawn(emitterWorld) + val particle = Particle(emitterParams.particle) + particle.init(this.emitterPos) + particle.spawn(emitterWorld) - allParticles += particle - } + allParticles += particle } } diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt index 1cb1682..8dc4502 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt @@ -40,28 +40,25 @@ fun updateEmitterParams(id: String, newParams: EmitterParams) { } -fun updateSingleParam(id: String, particleIndex: Int, paramName: String, paramValue: Any) : Boolean { +fun updateSingleEmitterParam(id: String, paramName: String, paramValue: Any) : Boolean { val emitter = getEmitterParams(id) ?: return false + val updatedValues = updateSingleEmitterParam(emitter, paramName, paramValue) + updateEmitterParams(id, updatedValues.first) - if (particleIndex == -1) { - val updatedValues = updateSingleEmitterParam(emitter, paramName, paramValue) - updateEmitterParams(id, updatedValues.first) + return updatedValues.second +} - return updatedValues.second - } - else if (emitter.particleTypes.isNotEmpty()) { - val particle = emitter.particleTypes[particleIndex] - val updatedValues = updateSingleParticleParam(particle, paramName, paramValue) +fun updateSingleParticleParam(emitterId: String, paramName: String, paramValue: Any) : Boolean { + val emitter = getEmitterParams(emitterId) ?: return false + val particle = emitter.particle - emitter.particleTypes[particleIndex] = updatedValues.first - updateEmitterParams(id, emitter) + val updatedValues = updateSingleParticleParam(particle, paramName, paramValue) - return updatedValues.second - } - else { - return false - } + emitter.particle = updatedValues.first + updateEmitterParams(emitterId, emitter) + + return updatedValues.second } diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleParams.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleParams.kt index 4fe87a2..1e9c3d1 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleParams.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleParams.kt @@ -29,7 +29,7 @@ data class ParticleParams ( var sizeRandom: Pair = Pair(Vector3f(0.5f, 0.5f, 0.5f), Vector3f(1.0f, 1.0f, 1.0f)), var uniformSize: Boolean = true, var velRandom: Pair = Pair(Vector3f(-0.1f, 0.4f, -0.1f), Vector3f(0.1f, 0.8f, 0.1f)), - var forceFields: Array = emptyArray(), + var forceFields: Array = arrayOf(ForceField()), var gravity: Vector3f = Vector3f(0.0f, -0.01f, 0.0f), var drag: Float = 0.075f, var minVel: Float = 0.0f, diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/Shapes.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/Shapes.kt index 0914c3d..162cc26 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/Shapes.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/Shapes.kt @@ -11,9 +11,12 @@ sealed class SpawningShape { } sealed class ForceFieldShape { - data class SPHERE(val radius: Float = 1.0f) : ForceFieldShape() + data class SPHERE( + val radius: Float = 3.0f, + val force: Pair = Pair(0.0f, 0.02f), + ) : ForceFieldShape() data class CUBE( val size: Vector3f = Vector3f(1.0f, 1.0f, 1.0f), - val forceDir: Vector3f = Vector3f(0.0f, 0.0f, 0.0f) // 0.0 on all means from center + val forceDir: Vector3f = Vector3f(0.0f, 0.0f, 0.0f) ) : ForceFieldShape() } \ No newline at end of file