added more args
This commit is contained in:
@@ -49,12 +49,11 @@ import java.util.concurrent.CompletableFuture
|
|||||||
// Allowing the use of regular Minecraft particles instead of just BDEs.
|
// Allowing the use of regular Minecraft particles instead of just BDEs.
|
||||||
// Cylinder and cone force field shape.
|
// Cylinder and cone force field shape.
|
||||||
// Copying particle params in-game
|
// Copying particle params in-game
|
||||||
|
// Custom curve equation command args (parse from strings)
|
||||||
|
|
||||||
|
|
||||||
// TODO: (project)
|
// TODO: (project)
|
||||||
// fix ManageEmitter command
|
// fix ManageEmitter command
|
||||||
// add SpawnEmitter command for spawning emitters via commands
|
|
||||||
// Custom curve equation command args (parse from strings)
|
|
||||||
// Better command auto-completion. (and change names of args)
|
// Better command auto-completion. (and change names of args)
|
||||||
// force field "config" option
|
// force field "config" option
|
||||||
|
|
||||||
@@ -91,7 +90,7 @@ class Bde_particles : ModInitializer {
|
|||||||
|
|
||||||
CommandRegistrationCallback.EVENT.register { dispatcher, registryAccess, _ ->
|
CommandRegistrationCallback.EVENT.register { dispatcher, registryAccess, _ ->
|
||||||
GiveEmitterTool.register(dispatcher, registryAccess)
|
GiveEmitterTool.register(dispatcher, registryAccess)
|
||||||
ManageEmitters .register(dispatcher)
|
ManageEmitters .register(dispatcher, registryAccess)
|
||||||
KillAllEmitters.register(dispatcher)
|
KillAllEmitters.register(dispatcher)
|
||||||
SpawnEmitter .register(dispatcher)
|
SpawnEmitter .register(dispatcher)
|
||||||
}
|
}
|
||||||
@@ -207,6 +206,23 @@ fun emitterListArg (argName: String) : RequiredArgumentBuilder<ServerCommandSour
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun curveListArg(argName: String) : RequiredArgumentBuilder<ServerCommandSource, String> {
|
||||||
|
return CommandManager.argument(argName, StringArgumentType.string())
|
||||||
|
.suggests { _, builder ->
|
||||||
|
LerpCurves::class.nestedClasses.forEach { nestClass ->
|
||||||
|
builder.suggest(nestClass.simpleName)
|
||||||
|
}
|
||||||
|
CompletableFuture.completedFuture(builder.build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun stringToCurve(curveName: String): LerpCurves? {
|
||||||
|
return LerpCurves::class.members
|
||||||
|
.filter { it.name == curveName }.firstNotNullOfOrNull { it.call(LerpCurves) as? LerpCurves }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun spawnEmitter(emitter: ParticleEmitter) {
|
fun spawnEmitter(emitter: ParticleEmitter) {
|
||||||
ALL_PARTICLE_EMITTERS += emitter
|
ALL_PARTICLE_EMITTERS += emitter
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import kotlin.random.Random
|
|||||||
|
|
||||||
class LerpCurves(val function: (Float) -> Float) {
|
class LerpCurves(val function: (Float) -> Float) {
|
||||||
companion object {
|
companion object {
|
||||||
val Constant = LerpCurves { _ -> 1.0f }
|
|
||||||
val Linear = LerpCurves { y -> y }
|
val Linear = LerpCurves { y -> y }
|
||||||
val Sqrt = LerpCurves { y -> sqrt(y) }
|
val Sqrt = LerpCurves { y -> sqrt(y) }
|
||||||
val Exponent = LerpCurves { y -> y.pow(2.0f) }
|
val Exponent = LerpCurves { y -> y.pow(2.0f) }
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.bytedice.bde_particles.commands
|
package com.bytedice.bde_particles.commands
|
||||||
|
|
||||||
import com.bytedice.bde_particles.particles.EmitterParams
|
import com.bytedice.bde_particles.curveListArg
|
||||||
import com.bytedice.bde_particles.particles.ParamClasses
|
import com.bytedice.bde_particles.negativeFeedback
|
||||||
import com.bytedice.bde_particles.particles.SpawningShape
|
import com.bytedice.bde_particles.particles.*
|
||||||
import com.bytedice.bde_particles.particles.updateParam
|
|
||||||
import com.bytedice.bde_particles.positiveFeedback
|
import com.bytedice.bde_particles.positiveFeedback
|
||||||
|
import com.bytedice.bde_particles.stringToCurve
|
||||||
import com.mojang.brigadier.Command
|
import com.mojang.brigadier.Command
|
||||||
import com.mojang.brigadier.arguments.BoolArgumentType
|
import com.mojang.brigadier.arguments.BoolArgumentType
|
||||||
import com.mojang.brigadier.arguments.FloatArgumentType
|
import com.mojang.brigadier.arguments.FloatArgumentType
|
||||||
@@ -14,13 +14,15 @@ import com.mojang.brigadier.builder.ArgumentBuilder
|
|||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder
|
||||||
import com.mojang.brigadier.context.CommandContext
|
import com.mojang.brigadier.context.CommandContext
|
||||||
|
import net.minecraft.command.CommandRegistryAccess
|
||||||
|
import net.minecraft.command.argument.ItemStackArgumentType
|
||||||
import net.minecraft.server.command.CommandManager
|
import net.minecraft.server.command.CommandManager
|
||||||
import net.minecraft.server.command.ServerCommandSource
|
import net.minecraft.server.command.ServerCommandSource
|
||||||
import org.joml.Vector2f
|
import org.joml.Vector2f
|
||||||
import org.joml.Vector3f
|
import org.joml.Vector3f
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
import kotlin.reflect.*
|
import kotlin.reflect.*
|
||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
|
import net.minecraft.server.command.GiveCommand
|
||||||
|
|
||||||
|
|
||||||
typealias CommandArgumentBuilder = KFunction<ArgumentBuilder<ServerCommandSource, *>>
|
typealias CommandArgumentBuilder = KFunction<ArgumentBuilder<ServerCommandSource, *>>
|
||||||
@@ -28,7 +30,11 @@ typealias CommandArgumentBuilder = KFunction<ArgumentBuilder<ServerCommandSource
|
|||||||
|
|
||||||
// TODO: doesn't apply shape & duration. Error applying shape other than circle
|
// TODO: doesn't apply shape & duration. Error applying shape other than circle
|
||||||
|
|
||||||
fun listConfigArgs(configArgs: Array<String>, rootArg: RequiredArgumentBuilder<ServerCommandSource, *>) : RequiredArgumentBuilder<ServerCommandSource, *> {
|
fun listConfigArgs(configArgs: Array<String>,
|
||||||
|
rootArg: RequiredArgumentBuilder<ServerCommandSource, *>,
|
||||||
|
registryAccess: CommandRegistryAccess
|
||||||
|
) : RequiredArgumentBuilder<ServerCommandSource, *>
|
||||||
|
{
|
||||||
configArgs.forEach { arg ->
|
configArgs.forEach { arg ->
|
||||||
var configArg = CommandManager.literal(arg)
|
var configArg = CommandManager.literal(arg)
|
||||||
|
|
||||||
@@ -36,11 +42,17 @@ fun listConfigArgs(configArgs: Array<String>, rootArg: RequiredArgumentBuilder<S
|
|||||||
val func = parseArgTypeToFunc(argAccess.returnType)
|
val func = parseArgTypeToFunc(argAccess.returnType)
|
||||||
|
|
||||||
if (func != null) {
|
if (func != null) {
|
||||||
if (func.parameters.lastIndex == 0) { configArg.then(func.call(argAccess)) }
|
if (func.parameters.lastIndex == 0) {
|
||||||
else { configArg = func.call(argAccess, configArg) as LiteralArgumentBuilder<ServerCommandSource>? }
|
configArg.then(func.call(argAccess))
|
||||||
|
}
|
||||||
|
else if (func.parameters.lastIndex == 1) {
|
||||||
|
configArg = func.call(argAccess, configArg) as LiteralArgumentBuilder<ServerCommandSource>?
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
configArg = func.call(argAccess, configArg, registryAccess) as LiteralArgumentBuilder<ServerCommandSource>?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the configArg to the root command builder
|
|
||||||
rootArg.then(configArg)
|
rootArg.then(configArg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,26 +72,23 @@ fun parseArgNameToAccess(name: String) : KProperty1<EmitterParams, *>? {
|
|||||||
return access
|
return access
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add forceField & implement rest of args
|
||||||
fun parseArgTypeToFunc(type: KType) : CommandArgumentBuilder? {
|
fun parseArgTypeToFunc(type: KType) : CommandArgumentBuilder? {
|
||||||
when (type.classifier) {
|
return when (type.classifier) {
|
||||||
Int::class -> return ::intArg
|
Int::class -> ::intArg
|
||||||
Float::class -> return ::floatArg
|
Float::class -> ::floatArg
|
||||||
String::class -> return ::stringArg
|
String::class -> ::stringArg
|
||||||
ParamClasses.Duration::class -> return ::durArg
|
ParamClasses.Duration::class -> ::durArg
|
||||||
Vector3f::class -> return ::vec3fArg
|
Vector3f::class -> ::vec3fArg
|
||||||
ParamClasses.PairInt::class -> return ::pairIntArg
|
ParamClasses.PairInt::class -> ::pairIntArg
|
||||||
SpawningShape::class -> return ::shapeArg
|
SpawningShape::class -> ::shapeArg
|
||||||
ParamClasses.PairVec3f::class -> println("Type is PairVec3f")
|
ParamClasses.PairVec3f::class -> ::pairVec3fArg
|
||||||
ParamClasses.PairFloat::class -> println("Type is PairFloat")
|
ParamClasses.PairFloat::class -> ::pairFloatArg
|
||||||
ParamClasses.TransformWithVel::class -> println("Type is TransformWithVel")
|
ParamClasses.TransformWithVel::class -> ::transformWithVelArg
|
||||||
Array::class -> println("Type is Array")
|
ParamClasses.StringCurve::class -> ::stringCurveArg
|
||||||
ParamClasses.LerpVal::class -> println("Type is LerpVal")
|
ParamClasses.LerpVal::class -> null
|
||||||
Pair::class -> println("Type is Pair")
|
else -> null
|
||||||
else -> return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -134,14 +143,14 @@ fun durArg(access: KProperty1<EmitterParams, ParamClasses.Duration>,
|
|||||||
return configArg
|
return configArg
|
||||||
.then(CommandManager.literal("SingleBurst")
|
.then(CommandManager.literal("SingleBurst")
|
||||||
.then(CommandManager.argument("loopDur", IntegerArgumentType.integer())
|
.then(CommandManager.argument("loopDur", IntegerArgumentType.integer())
|
||||||
.executes { context -> durArgExec(access, context); Command.SINGLE_SUCCESS }
|
.executes { context -> durArgExec("SingleBurst", access, context); Command.SINGLE_SUCCESS }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.then(CommandManager.literal("MultiBurst")
|
.then(CommandManager.literal("MultiBurst")
|
||||||
.then(CommandManager.argument("loopDur", IntegerArgumentType.integer())
|
.then(CommandManager.argument("loopDur", IntegerArgumentType.integer())
|
||||||
.then(CommandManager.argument("loopDelay", IntegerArgumentType.integer())
|
.then(CommandManager.argument("loopDelay", IntegerArgumentType.integer())
|
||||||
.then(CommandManager.argument("loopCount", IntegerArgumentType.integer())
|
.then(CommandManager.argument("loopCount", IntegerArgumentType.integer())
|
||||||
.executes { context -> durArgExec(access, context); Command.SINGLE_SUCCESS }
|
.executes { context -> durArgExec("MultiBurst", access, context); Command.SINGLE_SUCCESS }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -149,34 +158,33 @@ fun durArg(access: KProperty1<EmitterParams, ParamClasses.Duration>,
|
|||||||
.then(CommandManager.literal("InfiniteLoop")
|
.then(CommandManager.literal("InfiniteLoop")
|
||||||
.then(CommandManager.argument("loopDur", IntegerArgumentType.integer())
|
.then(CommandManager.argument("loopDur", IntegerArgumentType.integer())
|
||||||
.then(CommandManager.argument("loopDelay", IntegerArgumentType.integer())
|
.then(CommandManager.argument("loopDelay", IntegerArgumentType.integer())
|
||||||
.executes { context -> durArgExec(access, context); Command.SINGLE_SUCCESS }
|
.executes { context -> durArgExec("InfiniteLoop", access, context); Command.SINGLE_SUCCESS }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun durArgExec(access: KProperty1<EmitterParams, ParamClasses.Duration>, context: CommandContext<ServerCommandSource>) {
|
fun durArgExec(paramName: String, access: KProperty1<EmitterParams, ParamClasses.Duration>, context: CommandContext<ServerCommandSource>) {
|
||||||
val id = StringArgumentType.getString(context, "Emitter ID")
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
val loopDur = IntegerArgumentType.getInteger(context, "loopDur")
|
val loopDur = IntegerArgumentType.getInteger(context, "loopDur")
|
||||||
|
|
||||||
val eParams = EmitterParams.DEFAULT
|
|
||||||
|
|
||||||
when (access.get(eParams)) {
|
when (paramName) {
|
||||||
is ParamClasses.Duration.SingleBurst -> {
|
"SingleBurst" -> {
|
||||||
updateParam(id, access, ParamClasses.Duration.SingleBurst(loopDur))
|
updateParam(id, access, ParamClasses.Duration.SingleBurst(loopDur))
|
||||||
}
|
}
|
||||||
is ParamClasses.Duration.MultiBurst -> {
|
"MultiBurst" -> {
|
||||||
val loopDelay = IntegerArgumentType.getInteger(context, "loopDelay")
|
val loopDelay = IntegerArgumentType.getInteger(context, "loopDelay")
|
||||||
val loopCount = IntegerArgumentType.getInteger(context, "loopCount")
|
val loopCount = IntegerArgumentType.getInteger(context, "loopCount")
|
||||||
updateParam(id, access, ParamClasses.Duration.MultiBurst(loopDur, loopDelay, loopCount))
|
updateParam(id, access, ParamClasses.Duration.MultiBurst(loopDur, loopDelay, loopCount))
|
||||||
}
|
}
|
||||||
is ParamClasses.Duration.InfiniteLoop -> {
|
"InfiniteLoop" -> {
|
||||||
val loopDelay = IntegerArgumentType.getInteger(context, "loopDelay")
|
val loopDelay = IntegerArgumentType.getInteger(context, "loopDelay")
|
||||||
updateParam(id, access, ParamClasses.Duration.InfiniteLoop(loopDur, loopDelay))
|
updateParam(id, access, ParamClasses.Duration.InfiniteLoop(loopDur, loopDelay))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
successText(access, access.get(eParams)::class.simpleName ?: "UNKNOWN", id, context)
|
successText(access, access::class.simpleName ?: "UNKNOWN", id, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun vec3fArg(access: KProperty1<EmitterParams, Vector3f>) : RequiredArgumentBuilder<ServerCommandSource, Float> {
|
fun vec3fArg(access: KProperty1<EmitterParams, Vector3f>) : RequiredArgumentBuilder<ServerCommandSource, Float> {
|
||||||
@@ -199,12 +207,12 @@ fun vec3fArg(access: KProperty1<EmitterParams, Vector3f>) : RequiredArgumentBuil
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun pairIntArg(access: KProperty1<EmitterParams, ParamClasses.PairInt>) : RequiredArgumentBuilder<ServerCommandSource, Int> {
|
fun pairIntArg(access: KProperty1<EmitterParams, ParamClasses.PairInt>) : RequiredArgumentBuilder<ServerCommandSource, Int> {
|
||||||
return CommandManager.argument("First Int", IntegerArgumentType.integer())
|
return CommandManager.argument("Min Int", IntegerArgumentType.integer())
|
||||||
.then(CommandManager.argument("Second Int", IntegerArgumentType.integer())
|
.then(CommandManager.argument("Max Int", IntegerArgumentType.integer())
|
||||||
.executes { context ->
|
.executes { context ->
|
||||||
val id = StringArgumentType.getString(context, "Emitter ID")
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
val valueX = IntegerArgumentType.getInteger(context, "First Int")
|
val valueX = IntegerArgumentType.getInteger(context, "Min Int")
|
||||||
val valueY = IntegerArgumentType.getInteger(context, "Second Int")
|
val valueY = IntegerArgumentType.getInteger(context, "Max Int")
|
||||||
|
|
||||||
updateParam(id, access, ParamClasses.PairInt(valueX, valueY))
|
updateParam(id, access, ParamClasses.PairInt(valueX, valueY))
|
||||||
successText(access, "[$valueX, $valueY]", id, context)
|
successText(access, "[$valueX, $valueY]", id, context)
|
||||||
@@ -221,7 +229,7 @@ fun shapeArg(access: KProperty1<EmitterParams, SpawningShape>,
|
|||||||
.then(CommandManager.literal("Circle")
|
.then(CommandManager.literal("Circle")
|
||||||
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
|
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
|
||||||
.then(CommandManager.argument("Spawn On Edge", BoolArgumentType.bool())
|
.then(CommandManager.argument("Spawn On Edge", BoolArgumentType.bool())
|
||||||
.executes { context -> shapeArgExec(access, context); Command.SINGLE_SUCCESS }
|
.executes { context -> shapeArgExec("Circle", access, context); Command.SINGLE_SUCCESS }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -229,7 +237,7 @@ fun shapeArg(access: KProperty1<EmitterParams, SpawningShape>,
|
|||||||
.then(CommandManager.argument("X", FloatArgumentType.floatArg())
|
.then(CommandManager.argument("X", FloatArgumentType.floatArg())
|
||||||
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
|
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
|
||||||
.then(CommandManager.argument("Spawn On Edge", BoolArgumentType.bool())
|
.then(CommandManager.argument("Spawn On Edge", BoolArgumentType.bool())
|
||||||
.executes { context -> shapeArgExec(access, context); Command.SINGLE_SUCCESS }
|
.executes { context -> shapeArgExec("Rect", access, context); Command.SINGLE_SUCCESS }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -239,7 +247,7 @@ fun shapeArg(access: KProperty1<EmitterParams, SpawningShape>,
|
|||||||
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
|
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
|
||||||
.then(CommandManager.argument("Z", FloatArgumentType.floatArg())
|
.then(CommandManager.argument("Z", FloatArgumentType.floatArg())
|
||||||
.then(CommandManager.argument("Spawn On Edge", BoolArgumentType.bool())
|
.then(CommandManager.argument("Spawn On Edge", BoolArgumentType.bool())
|
||||||
.executes { context -> shapeArgExec(access, context); Command.SINGLE_SUCCESS }
|
.executes { context -> shapeArgExec("Cube", access, context); Command.SINGLE_SUCCESS }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -248,51 +256,258 @@ fun shapeArg(access: KProperty1<EmitterParams, SpawningShape>,
|
|||||||
.then(CommandManager.literal("Sphere")
|
.then(CommandManager.literal("Sphere")
|
||||||
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
|
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
|
||||||
.then(CommandManager.argument("Spawn On Edge", BoolArgumentType.bool())
|
.then(CommandManager.argument("Spawn On Edge", BoolArgumentType.bool())
|
||||||
.executes { context -> shapeArgExec(access, context); Command.SINGLE_SUCCESS }
|
.executes { context -> shapeArgExec("Sphere", access, context); Command.SINGLE_SUCCESS }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.then(CommandManager.literal("Point")
|
.then(CommandManager.literal("Point")
|
||||||
.executes { context -> shapeArgExec(access, context); Command.SINGLE_SUCCESS }
|
.executes { context -> shapeArgExec("Point", access, context); Command.SINGLE_SUCCESS }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shapeArgExec(access: KProperty1<EmitterParams, SpawningShape>, context: CommandContext<ServerCommandSource>) {
|
fun shapeArgExec(paramName: String, access: KProperty1<EmitterParams, SpawningShape>, context: CommandContext<ServerCommandSource>) {
|
||||||
val id = StringArgumentType.getString(context, "Emitter ID")
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
|
||||||
val eParams = EmitterParams.DEFAULT
|
when (paramName) {
|
||||||
|
"Circle" -> {
|
||||||
println(access.get(eParams)::class)
|
|
||||||
|
|
||||||
when (access.get(eParams)) {
|
|
||||||
is SpawningShape.Circle -> {
|
|
||||||
val radius = FloatArgumentType.getFloat(context, "Radius")
|
val radius = FloatArgumentType.getFloat(context, "Radius")
|
||||||
val onEdge = BoolArgumentType.getBool(context, "Spawn On Edge")
|
val onEdge = BoolArgumentType.getBool(context, "Spawn On Edge")
|
||||||
updateParam(id, access, SpawningShape.Circle(radius, onEdge))
|
updateParam(id, access, SpawningShape.Circle(radius, onEdge))
|
||||||
}
|
}
|
||||||
is SpawningShape.Rect -> {
|
"Rect" -> {
|
||||||
val onEdge = BoolArgumentType.getBool(context, "Spawn On Edge")
|
val onEdge = BoolArgumentType.getBool(context, "Spawn On Edge")
|
||||||
val x = FloatArgumentType.getFloat(context, "X")
|
val x = FloatArgumentType.getFloat(context, "X")
|
||||||
val y = FloatArgumentType.getFloat(context, "Y")
|
val y = FloatArgumentType.getFloat(context, "Y")
|
||||||
updateParam(id, access, SpawningShape.Rect(Vector2f(x, y), onEdge))
|
updateParam(id, access, SpawningShape.Rect(Vector2f(x, y), onEdge))
|
||||||
}
|
}
|
||||||
is SpawningShape.Cube -> {
|
"Cube" -> {
|
||||||
val onEdge = BoolArgumentType.getBool(context, "Spawn On Edge")
|
val onEdge = BoolArgumentType.getBool(context, "Spawn On Edge")
|
||||||
val x = FloatArgumentType.getFloat(context, "X")
|
val x = FloatArgumentType.getFloat(context, "X")
|
||||||
val y = FloatArgumentType.getFloat(context, "Y")
|
val y = FloatArgumentType.getFloat(context, "Y")
|
||||||
val z = FloatArgumentType.getFloat(context, "Z")
|
val z = FloatArgumentType.getFloat(context, "Z")
|
||||||
updateParam(id, access, SpawningShape.Cube(Vector3f(x, y, z), onEdge))
|
updateParam(id, access, SpawningShape.Cube(Vector3f(x, y, z), onEdge))
|
||||||
}
|
}
|
||||||
is SpawningShape.Sphere -> {
|
"Sphere" -> {
|
||||||
val radius = FloatArgumentType.getFloat(context, "Radius")
|
val radius = FloatArgumentType.getFloat(context, "Radius")
|
||||||
val onEdge = BoolArgumentType.getBool(context, "Spawn On Edge")
|
val onEdge = BoolArgumentType.getBool(context, "Spawn On Edge")
|
||||||
updateParam(id, access, SpawningShape.Sphere(radius, onEdge))
|
updateParam(id, access, SpawningShape.Sphere(radius, onEdge))
|
||||||
println("$id, ${access.name}, $radius, $onEdge")
|
|
||||||
}
|
}
|
||||||
is SpawningShape.Point -> {
|
"Point" -> {
|
||||||
updateParam(id, access, SpawningShape.Point)
|
updateParam(id, access, SpawningShape.Point)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
successText(access, access.get(eParams)::class.simpleName ?: "UNKNOWN", id, context)
|
successText(access, access::class.simpleName ?: "UNKNOWN", id, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pairVec3fArg(access: KProperty1<EmitterParams,ParamClasses.PairVec3f>,
|
||||||
|
configArg: LiteralArgumentBuilder<ServerCommandSource>
|
||||||
|
) : LiteralArgumentBuilder<ServerCommandSource>
|
||||||
|
{
|
||||||
|
return configArg
|
||||||
|
.then(CommandManager.literal("NonUniform")
|
||||||
|
.then(CommandManager.argument("Min X", FloatArgumentType.floatArg())
|
||||||
|
.then(CommandManager.argument("Min Y", FloatArgumentType.floatArg())
|
||||||
|
.then(CommandManager.argument("Min Z", FloatArgumentType.floatArg())
|
||||||
|
.then(CommandManager.argument("Max X", FloatArgumentType.floatArg())
|
||||||
|
.then(CommandManager.argument("Max Y", FloatArgumentType.floatArg())
|
||||||
|
.then(CommandManager.argument("Max Z", FloatArgumentType.floatArg())
|
||||||
|
.executes { context ->
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
val minX = FloatArgumentType.getFloat(context, "Min X")
|
||||||
|
val minY = FloatArgumentType.getFloat(context, "Min Y")
|
||||||
|
val minZ = FloatArgumentType.getFloat(context, "Min Z")
|
||||||
|
val maxX = FloatArgumentType.getFloat(context, "Max X")
|
||||||
|
val maxY = FloatArgumentType.getFloat(context, "Max Y")
|
||||||
|
val maxZ = FloatArgumentType.getFloat(context, "Max Z")
|
||||||
|
|
||||||
|
updateParam(id, access, ParamClasses.PairVec3f.NonUniform(minX, minY, minZ, maxX, maxY, maxZ))
|
||||||
|
|
||||||
|
successText(access, "NonUniform", id, context)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(CommandManager.literal("Uniform")
|
||||||
|
.then(CommandManager.argument("X", FloatArgumentType.floatArg())
|
||||||
|
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
|
||||||
|
.executes { context ->
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
val min = FloatArgumentType.getFloat(context, "X")
|
||||||
|
val max = FloatArgumentType.getFloat(context, "Y")
|
||||||
|
|
||||||
|
updateParam(id, access, ParamClasses.PairVec3f.Uniform(min, max))
|
||||||
|
|
||||||
|
successText(access, "Uniform", id, context)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(CommandManager.literal("Null")
|
||||||
|
.executes { context ->
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
|
||||||
|
updateParam(id, access, ParamClasses.PairVec3f.Null)
|
||||||
|
|
||||||
|
successText(access, "Null", id, context)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pairFloatArg(access: KProperty1<EmitterParams, ParamClasses.PairInt>) : RequiredArgumentBuilder<ServerCommandSource, Float> {
|
||||||
|
return CommandManager.argument("Min Float", FloatArgumentType.floatArg())
|
||||||
|
.then(CommandManager.argument("Max Float", FloatArgumentType.floatArg())
|
||||||
|
.executes { context ->
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
val valueX = FloatArgumentType.getFloat(context, "Min Int")
|
||||||
|
val valueY = FloatArgumentType.getFloat(context, "Max Int")
|
||||||
|
|
||||||
|
updateParam(id, access, ParamClasses.PairFloat(valueX, valueY))
|
||||||
|
successText(access, "[$valueX, $valueY]", id, context)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun transformWithVelArg(access: KProperty1<EmitterParams, ParamClasses.TransformWithVel>,
|
||||||
|
configArg: LiteralArgumentBuilder<ServerCommandSource>
|
||||||
|
) : LiteralArgumentBuilder<ServerCommandSource>
|
||||||
|
{
|
||||||
|
return configArg
|
||||||
|
.then(CommandManager.literal("RotOnly")
|
||||||
|
.executes { context ->
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
|
||||||
|
updateParam(id, access, ParamClasses.TransformWithVel.RotOnly)
|
||||||
|
successText(access, "RotOnly", id, context)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(CommandManager.literal("ScaleAndRot")
|
||||||
|
.then(CommandManager.argument("Scale Multiplier", FloatArgumentType.floatArg())
|
||||||
|
.executes { context ->
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
val scaleMul = FloatArgumentType.getFloat(context, "Scale Multiplier")
|
||||||
|
|
||||||
|
updateParam(id, access, ParamClasses.TransformWithVel.ScaleAndRot(scaleMul))
|
||||||
|
successText(access, "ScaleAndRot", id, context)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(CommandManager.literal("None")
|
||||||
|
.executes { context ->
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
|
||||||
|
updateParam(id, access, ParamClasses.TransformWithVel.None)
|
||||||
|
successText(access, "None", id, context)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stringCurveArg(access: KProperty1<EmitterParams, ParamClasses.StringCurve>,
|
||||||
|
configArg: LiteralArgumentBuilder<ServerCommandSource>,
|
||||||
|
registryAccess: CommandRegistryAccess
|
||||||
|
) : LiteralArgumentBuilder<ServerCommandSource>
|
||||||
|
{
|
||||||
|
return configArg
|
||||||
|
.then(CommandManager.literal("Add")
|
||||||
|
.then(CommandManager.argument("Item", ItemStackArgumentType.itemStack(registryAccess))
|
||||||
|
.then(CommandManager.argument("Index", IntegerArgumentType.integer())
|
||||||
|
.executes { context ->
|
||||||
|
val index = IntegerArgumentType.getInteger(context, "Index")
|
||||||
|
stringCurveAddArg(context, access, index)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.executes { context ->
|
||||||
|
stringCurveAddArg(context, access, -1)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(CommandManager.literal("Remove")
|
||||||
|
.then(CommandManager.argument("Index", IntegerArgumentType.integer())
|
||||||
|
.executes { context ->
|
||||||
|
val index = IntegerArgumentType.getInteger(context, "Index")
|
||||||
|
stringCurveRemoveArg(context, access, index)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.executes { context ->
|
||||||
|
stringCurveRemoveArg(context, access, -1)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(CommandManager.literal("Curve")
|
||||||
|
.then(curveListArg("Curve")
|
||||||
|
.executes { context ->
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
val curveName = StringArgumentType.getString(context, "Curve")
|
||||||
|
|
||||||
|
val curve = stringToCurve(curveName)
|
||||||
|
val modelCurve = getEmitterDataById(id)?.modelCurve
|
||||||
|
|
||||||
|
if (curve != null && modelCurve != null) {
|
||||||
|
modelCurve.curve = curve
|
||||||
|
updateParam(id, access, modelCurve)
|
||||||
|
successText(access, curveName, id, context)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
negativeFeedback("Failed to update param \"modelCurve.curve\"! The curve is most likely invalid!", context)
|
||||||
|
Command.SINGLE_SUCCESS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stringCurveAddArg(context: CommandContext<ServerCommandSource>,
|
||||||
|
access: KProperty1<EmitterParams, ParamClasses.StringCurve>,
|
||||||
|
index: Int
|
||||||
|
) {
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
val item = ItemStackArgumentType.getItemStackArgument(context, "Item").item.name.string
|
||||||
|
|
||||||
|
val modelCurve = getEmitterDataById(id)?.modelCurve
|
||||||
|
|
||||||
|
if (index == -1 && modelCurve != null) {
|
||||||
|
modelCurve.array.toMutableList().apply { add(item) }.toTypedArray()
|
||||||
|
updateParam(id, access, modelCurve)
|
||||||
|
}
|
||||||
|
else if (modelCurve != null) {
|
||||||
|
modelCurve.array.toMutableList().apply { add(index.coerceIn(0, modelCurve.array.lastIndex), item) }.toTypedArray()
|
||||||
|
updateParam(id, access, modelCurve)
|
||||||
|
}
|
||||||
|
|
||||||
|
successText(access, "++$item", id, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stringCurveRemoveArg(context: CommandContext<ServerCommandSource>,
|
||||||
|
access: KProperty1<EmitterParams, ParamClasses.StringCurve>,
|
||||||
|
index: Int
|
||||||
|
) {
|
||||||
|
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||||
|
|
||||||
|
val modelCurve = getEmitterDataById(id)?.modelCurve
|
||||||
|
|
||||||
|
if (index == -1 && modelCurve != null) {
|
||||||
|
modelCurve.array.toMutableList().apply { removeLast() }.toTypedArray()
|
||||||
|
updateParam(id, access, modelCurve)
|
||||||
|
}
|
||||||
|
else if (modelCurve != null) {
|
||||||
|
modelCurve.array.toMutableList().apply { removeAt(index.coerceIn(0, modelCurve.array.lastIndex)) }.toTypedArray()
|
||||||
|
updateParam(id, access, modelCurve)
|
||||||
|
}
|
||||||
|
|
||||||
|
successText(access, "--item at $index", id, context)
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.mojang.brigadier.CommandDispatcher
|
|||||||
import com.mojang.brigadier.arguments.StringArgumentType
|
import com.mojang.brigadier.arguments.StringArgumentType
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder
|
||||||
import com.mojang.brigadier.context.CommandContext
|
import com.mojang.brigadier.context.CommandContext
|
||||||
|
import net.minecraft.command.CommandRegistryAccess
|
||||||
import net.minecraft.server.command.CommandManager
|
import net.minecraft.server.command.CommandManager
|
||||||
import net.minecraft.server.command.ServerCommandSource
|
import net.minecraft.server.command.ServerCommandSource
|
||||||
import net.minecraft.text.Style
|
import net.minecraft.text.Style
|
||||||
@@ -77,7 +78,7 @@ blockCurve: Pair<Array<String>, LerpCurves>,
|
|||||||
|
|
||||||
object ManageEmitters {
|
object ManageEmitters {
|
||||||
|
|
||||||
fun register(dispatcher: CommandDispatcher<ServerCommandSource>) {
|
fun register(dispatcher: CommandDispatcher<ServerCommandSource>, registryAccess: CommandRegistryAccess) {
|
||||||
val command = CommandManager.literal("ManageEmitters")
|
val command = CommandManager.literal("ManageEmitters")
|
||||||
.requires { source -> source.hasPermissionLevel(2) }
|
.requires { source -> source.hasPermissionLevel(2) }
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ object ManageEmitters {
|
|||||||
command
|
command
|
||||||
.then(CommandManager.literal("create").then(create()))
|
.then(CommandManager.literal("create").then(create()))
|
||||||
.then(CommandManager.literal("remove").then(remove()))
|
.then(CommandManager.literal("remove").then(remove()))
|
||||||
.then(CommandManager.literal("config").then(config()))
|
.then(CommandManager.literal("config").then(config(registryAccess)))
|
||||||
.then(CommandManager.literal("list")
|
.then(CommandManager.literal("list")
|
||||||
.executes { context ->
|
.executes { context ->
|
||||||
val emitterIdList = idRegister.keys.sorted().joinToString(" ")
|
val emitterIdList = idRegister.keys.sorted().joinToString(" ")
|
||||||
@@ -173,10 +174,10 @@ object ManageEmitters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun config() : RequiredArgumentBuilder<ServerCommandSource, String> {
|
private fun config(registryAccess: CommandRegistryAccess) : RequiredArgumentBuilder<ServerCommandSource, String> {
|
||||||
var emitterList = emitterListArg("Emitter ID")
|
var emitterList = emitterListArg("Emitter ID")
|
||||||
|
|
||||||
emitterList = listConfigArgs(dataClassToArray(EmitterParams::class), emitterList) as RequiredArgumentBuilder<ServerCommandSource, String>
|
emitterList = listConfigArgs(dataClassToArray(EmitterParams::class), emitterList, registryAccess) as RequiredArgumentBuilder<ServerCommandSource, String>
|
||||||
|
|
||||||
return emitterList
|
return emitterList
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ data class EmitterParams (
|
|||||||
var offsetCurve: ParamClasses.LerpVal,
|
var offsetCurve: ParamClasses.LerpVal,
|
||||||
var rotVelCurve: ParamClasses.LerpVal,
|
var rotVelCurve: ParamClasses.LerpVal,
|
||||||
var scaleCurve: ParamClasses.LerpVal,
|
var scaleCurve: ParamClasses.LerpVal,
|
||||||
var modelCurve: Pair<Array<String>, LerpCurves>,
|
var modelCurve: ParamClasses.StringCurve,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
companion object Presets {
|
companion object Presets {
|
||||||
@@ -55,8 +55,8 @@ data class EmitterParams (
|
|||||||
minVel = 0.0f,
|
minVel = 0.0f,
|
||||||
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
||||||
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt),
|
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt),
|
||||||
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 2.5f, LerpCurves.Constant),
|
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 2.5f, LerpCurves.Linear),
|
||||||
modelCurve = Pair(
|
modelCurve = ParamClasses.StringCurve(
|
||||||
arrayOf(
|
arrayOf(
|
||||||
"shroomlight",
|
"shroomlight",
|
||||||
"orange_concrete",
|
"orange_concrete",
|
||||||
@@ -88,9 +88,9 @@ data class EmitterParams (
|
|||||||
drag = 0.075f,
|
drag = 0.075f,
|
||||||
minVel = 0.0f,
|
minVel = 0.0f,
|
||||||
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
||||||
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Constant),
|
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Linear),
|
||||||
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.0f, LerpCurves.Constant),
|
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.0f, LerpCurves.Linear),
|
||||||
modelCurve = Pair(
|
modelCurve = ParamClasses.StringCurve(
|
||||||
arrayOf(
|
arrayOf(
|
||||||
"shroomlight",
|
"shroomlight",
|
||||||
"orange_concrete",
|
"orange_concrete",
|
||||||
@@ -99,7 +99,7 @@ data class EmitterParams (
|
|||||||
"gray_stained_glass",
|
"gray_stained_glass",
|
||||||
"light_gray_stained_glass"
|
"light_gray_stained_glass"
|
||||||
),
|
),
|
||||||
LerpCurves.Constant
|
LerpCurves.Linear
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val STRESS_TEST = EmitterParams(
|
val STRESS_TEST = EmitterParams(
|
||||||
@@ -126,9 +126,9 @@ data class EmitterParams (
|
|||||||
drag = 0.075f,
|
drag = 0.075f,
|
||||||
minVel = 0.0f,
|
minVel = 0.0f,
|
||||||
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
||||||
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Constant),
|
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Linear),
|
||||||
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.5f, LerpCurves.Constant),
|
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.5f, LerpCurves.Linear),
|
||||||
modelCurve = Pair(
|
modelCurve = ParamClasses.StringCurve(
|
||||||
arrayOf(
|
arrayOf(
|
||||||
"shroomlight",
|
"shroomlight",
|
||||||
"orange_concrete",
|
"orange_concrete",
|
||||||
@@ -137,7 +137,7 @@ data class EmitterParams (
|
|||||||
"gray_stained_glass",
|
"gray_stained_glass",
|
||||||
"light_gray_stained_glass"
|
"light_gray_stained_glass"
|
||||||
),
|
),
|
||||||
LerpCurves.Constant
|
LerpCurves.Linear
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.bytedice.bde_particles.particles
|
package com.bytedice.bde_particles.particles
|
||||||
|
|
||||||
import com.bytedice.bde_particles.LerpCurves
|
import com.bytedice.bde_particles.LerpCurves
|
||||||
|
import com.bytedice.bde_particles.lerpArray
|
||||||
import com.bytedice.bde_particles.randomFloatBetween
|
import com.bytedice.bde_particles.randomFloatBetween
|
||||||
import com.bytedice.bde_particles.randomIntBetween
|
import com.bytedice.bde_particles.randomIntBetween
|
||||||
import org.joml.Vector3f
|
import org.joml.Vector3f
|
||||||
@@ -60,9 +61,9 @@ class ParamClasses {
|
|||||||
private val curve: LerpCurves,
|
private val curve: LerpCurves,
|
||||||
) : LerpVal() {
|
) : LerpVal() {
|
||||||
fun lerp(t: Float): Vector3f {
|
fun lerp(t: Float): Vector3f {
|
||||||
val x = com.bytedice.bde_particles.lerp(fromX, toX, t) * curve.function(t)
|
val x = com.bytedice.bde_particles.lerp(fromX, toX, curve.function(t))
|
||||||
val y = com.bytedice.bde_particles.lerp(fromY, toY, t) * curve.function(t)
|
val y = com.bytedice.bde_particles.lerp(fromY, toY, curve.function(t))
|
||||||
val z = com.bytedice.bde_particles.lerp(fromZ, toZ, t) * curve.function(t)
|
val z = com.bytedice.bde_particles.lerp(fromZ, toZ, curve.function(t))
|
||||||
return Vector3f(x, y, z)
|
return Vector3f(x, y, z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,9 +79,9 @@ class ParamClasses {
|
|||||||
private val curveZ: LerpCurves
|
private val curveZ: LerpCurves
|
||||||
) : LerpVal() {
|
) : LerpVal() {
|
||||||
fun lerp(t: Float): Vector3f {
|
fun lerp(t: Float): Vector3f {
|
||||||
val x = com.bytedice.bde_particles.lerp(fromX, toX, t) * curveX.function(t)
|
val x = com.bytedice.bde_particles.lerp(fromX, toX, curveX.function(t))
|
||||||
val y = com.bytedice.bde_particles.lerp(fromY, toY, t) * curveY.function(t)
|
val y = com.bytedice.bde_particles.lerp(fromY, toY, curveY.function(t))
|
||||||
val z = com.bytedice.bde_particles.lerp(fromZ, toZ, t) * curveZ.function(t)
|
val z = com.bytedice.bde_particles.lerp(fromZ, toZ, curveZ.function(t))
|
||||||
return Vector3f(x, y, z)
|
return Vector3f(x, y, z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,7 +91,7 @@ class ParamClasses {
|
|||||||
private val curve: LerpCurves,
|
private val curve: LerpCurves,
|
||||||
) : LerpVal() {
|
) : LerpVal() {
|
||||||
fun lerp(t: Float) : Float {
|
fun lerp(t: Float) : Float {
|
||||||
return com.bytedice.bde_particles.lerp(from, to, t) * curve.function(t)
|
return com.bytedice.bde_particles.lerp(from, to, curve.function(t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data object NoLerpVec3f : LerpVal()
|
data object NoLerpVec3f : LerpVal()
|
||||||
@@ -155,4 +156,10 @@ class ParamClasses {
|
|||||||
}
|
}
|
||||||
data object None : TransformWithVel()
|
data object None : TransformWithVel()
|
||||||
}
|
}
|
||||||
|
class StringCurve (
|
||||||
|
var array: Array<String>,
|
||||||
|
var curve: LerpCurves
|
||||||
|
) {
|
||||||
|
fun lerp(t: Float) : String { return lerpArray(array as Array<Any>, t, curve) as String }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ class Particle(
|
|||||||
val properties = DisplayEntityProperties(
|
val properties = DisplayEntityProperties(
|
||||||
pos = entityPos,
|
pos = entityPos,
|
||||||
rot = entityRot,
|
rot = entityRot,
|
||||||
model = lerpArray(emitterParams.modelCurve.first as Array<Any>, 0.0f, emitterParams.modelCurve.second) as String,
|
model = emitterParams.modelCurve.lerp(0.0f),
|
||||||
translation = newPos.add(pos),
|
translation = newPos.add(pos),
|
||||||
leftRotation = quatRot,
|
leftRotation = quatRot,
|
||||||
scale = Vector3f(scale).mul(emitterParams.scaleCurve.lerpToVector3f(0.0f)),
|
scale = Vector3f(scale).mul(emitterParams.scaleCurve.lerpToVector3f(0.0f)),
|
||||||
@@ -130,7 +130,7 @@ class Particle(
|
|||||||
private fun calcNewProperties() : DisplayEntityProperties {
|
private fun calcNewProperties() : DisplayEntityProperties {
|
||||||
val timeAliveClamped = (timeAlive.toFloat() / lifeTime.toFloat()).coerceIn(0.0f, 1.0f)
|
val timeAliveClamped = (timeAlive.toFloat() / lifeTime.toFloat()).coerceIn(0.0f, 1.0f)
|
||||||
|
|
||||||
val newModel = lerpArray(emitterParams.modelCurve.first as Array<Any>, timeAliveClamped, emitterParams.modelCurve.second) as String
|
val newModel = emitterParams.modelCurve.lerp(timeAliveClamped)
|
||||||
val (newVel, newPos) = calcPos()
|
val (newVel, newPos) = calcPos()
|
||||||
val newOriginOffset = Vector3f(originOffset.mul(emitterParams.offsetCurve.lerpToVector3f(timeAliveClamped)))
|
val newOriginOffset = Vector3f(originOffset.mul(emitterParams.offsetCurve.lerpToVector3f(timeAliveClamped)))
|
||||||
|
|
||||||
|
|||||||
@@ -98,10 +98,17 @@ class ParticleEmitter(
|
|||||||
val loopDelay = (params.spawnDuration as ParamClasses.Duration.MultiBurst).loopDelay
|
val loopDelay = (params.spawnDuration as ParamClasses.Duration.MultiBurst).loopDelay
|
||||||
val loopCount = (params.spawnDuration as ParamClasses.Duration.MultiBurst).loopCount
|
val loopCount = (params.spawnDuration as ParamClasses.Duration.MultiBurst).loopCount
|
||||||
|
|
||||||
if (timeAlive >= loopDur && timesLooped >= loopCount) { isTicking = false; return }
|
if (timeAlive >= loopDur && timesLooped + 1 >= loopCount) { isTicking = false; return }
|
||||||
|
|
||||||
if (timePaused >= loopDelay) { isPaused = false; timePaused = 0 }
|
if (timePaused >= loopDelay) {
|
||||||
if (timeAlive >= loopDur && loopDelay > 0) { isPaused = true; timeAlive = 0 }
|
isPaused = false
|
||||||
|
timePaused = 0
|
||||||
|
timesLooped += 1
|
||||||
|
}
|
||||||
|
if (timeAlive >= loopDur && loopDelay > 0) {
|
||||||
|
isPaused = true
|
||||||
|
timeAlive = 0
|
||||||
|
}
|
||||||
|
|
||||||
if (!isPaused) { timeAlive += 1 }
|
if (!isPaused) { timeAlive += 1 }
|
||||||
else { timePaused += 1 }
|
else { timePaused += 1 }
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package com.bytedice.bde_particles.particles
|
package com.bytedice.bde_particles.particles
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KMutableProperty1
|
import kotlin.reflect.KMutableProperty1
|
||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
|
import kotlin.reflect.full.isSubclassOf
|
||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
import kotlin.reflect.jvm.isAccessible
|
import kotlin.reflect.jvm.isAccessible
|
||||||
|
|
||||||
@@ -80,7 +82,10 @@ fun updateParam(id: String, paramAccess: KProperty1<EmitterParams, *>, paramValu
|
|||||||
fun updateParams(params: EmitterParams, paramAccess: KProperty1<EmitterParams, Any>, paramValue: Any): Pair<EmitterParams, Boolean> {
|
fun updateParams(params: EmitterParams, paramAccess: KProperty1<EmitterParams, Any>, paramValue: Any): Pair<EmitterParams, Boolean> {
|
||||||
val newParams = params.copy()
|
val newParams = params.copy()
|
||||||
|
|
||||||
if (paramAccess.returnType.classifier == paramValue::class) {
|
if (paramAccess.returnType.classifier == paramValue::class
|
||||||
|
|| (paramAccess.returnType.classifier as? KClass<*>)?.let { paramValue::class.isSubclassOf(it) } == true
|
||||||
|
)
|
||||||
|
{
|
||||||
paramAccess as KMutableProperty1<EmitterParams, Any>
|
paramAccess as KMutableProperty1<EmitterParams, Any>
|
||||||
paramAccess.set(newParams, paramValue)
|
paramAccess.set(newParams, paramValue)
|
||||||
return Pair(newParams, true)
|
return Pair(newParams, true)
|
||||||
|
|||||||
Reference in New Issue
Block a user