added force field arg. Testing required for ALL args
This commit is contained in:
@@ -50,12 +50,7 @@ import java.util.concurrent.CompletableFuture
|
||||
// Cylinder and cone force field shape.
|
||||
// Copying particle params in-game
|
||||
// Custom curve equation command args (parse from strings)
|
||||
|
||||
|
||||
// TODO: (project)
|
||||
// fix ManageEmitter command
|
||||
// Better command auto-completion. (and change names of args)
|
||||
// force field "config" option
|
||||
// force field "config" option
|
||||
|
||||
|
||||
var ALL_PARTICLE_EMITTERS: Array<ParticleEmitter> = emptyArray()
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.joml.Vector2f
|
||||
import org.joml.Vector3f
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import net.minecraft.server.command.GiveCommand
|
||||
|
||||
|
||||
typealias CommandArgumentBuilder = KFunction<ArgumentBuilder<ServerCommandSource, *>>
|
||||
@@ -72,7 +71,6 @@ fun parseArgNameToAccess(name: String) : KProperty1<EmitterParams, *>? {
|
||||
return access
|
||||
}
|
||||
|
||||
// TODO: add forceField & implement rest of args
|
||||
fun parseArgTypeToFunc(type: KType) : CommandArgumentBuilder? {
|
||||
return when (type.classifier) {
|
||||
Int::class -> ::intArg
|
||||
@@ -86,7 +84,8 @@ fun parseArgTypeToFunc(type: KType) : CommandArgumentBuilder? {
|
||||
ParamClasses.PairFloat::class -> ::pairFloatArg
|
||||
ParamClasses.TransformWithVel::class -> ::transformWithVelArg
|
||||
ParamClasses.StringCurve::class -> ::stringCurveArg
|
||||
ParamClasses.LerpVal::class -> null
|
||||
ParamClasses.LerpVal::class -> ::lerpValArg
|
||||
ParamClasses.ForceFieldArray::class -> ::forceFieldArg
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -511,3 +510,212 @@ fun stringCurveRemoveArg(context: CommandContext<ServerCommandSource>,
|
||||
|
||||
successText(access, "--item at $index", id, context)
|
||||
}
|
||||
|
||||
fun lerpValArg(access: KProperty1<EmitterParams,ParamClasses.PairVec3f>,
|
||||
configArg: LiteralArgumentBuilder<ServerCommandSource>
|
||||
) : LiteralArgumentBuilder<ServerCommandSource>
|
||||
{
|
||||
return configArg
|
||||
.then(CommandManager.literal("LerpVec3f")
|
||||
.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())
|
||||
.then(curveListArg("Curve")
|
||||
.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")
|
||||
val curveName = StringArgumentType.getString(context, "Curve")
|
||||
|
||||
val curve = stringToCurve(curveName)
|
||||
|
||||
updateParam(id, access, ParamClasses.LerpVal.LerpVec3f(minX, minY, minZ, maxX, maxY, maxZ, curve!!))
|
||||
|
||||
successText(access, "LerpVec3f", id, context)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(CommandManager.literal("MultiLerpVec3f")
|
||||
.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())
|
||||
.then(curveListArg("CurveX")
|
||||
.then(curveListArg("CurveY")
|
||||
.then(curveListArg("CurveZ")
|
||||
.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")
|
||||
val curveNameX = StringArgumentType.getString(context, "CurveX")
|
||||
val curveNameY = StringArgumentType.getString(context, "CurveY")
|
||||
val curveNameZ = StringArgumentType.getString(context, "CurveZ")
|
||||
|
||||
val curveX = stringToCurve(curveNameX)
|
||||
val curveY = stringToCurve(curveNameY)
|
||||
val curveZ = stringToCurve(curveNameZ)
|
||||
|
||||
updateParam(id, access, ParamClasses.LerpVal.MultiLerpVec3f(minX, minY, minZ, maxX, maxY, maxZ, curveX!!, curveY!!, curveZ!!))
|
||||
|
||||
successText(access, "MultiLerpVec3f", id, context)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(CommandManager.literal("Null")
|
||||
.executes { context ->
|
||||
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||
|
||||
updateParam(id, access, ParamClasses.LerpVal.Null)
|
||||
|
||||
successText(access, "Null", id, context)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fun forceFieldArg(access: KProperty1<EmitterParams,ParamClasses.ForceFieldArray>,
|
||||
configArg: LiteralArgumentBuilder<ServerCommandSource>
|
||||
) : LiteralArgumentBuilder<ServerCommandSource>
|
||||
{
|
||||
return configArg
|
||||
.then(CommandManager.literal("Add")
|
||||
.then(CommandManager.argument("X", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Y", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Z", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.literal("Sphere")
|
||||
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Min Force", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Max Force", FloatArgumentType.floatArg())
|
||||
.executes { context ->
|
||||
forceFieldAddArg(context, access, "Sphere")
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(CommandManager.literal("Cube")
|
||||
.then(CommandManager.argument("Size X", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Size Y", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Size Z", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Dir X", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Dir Y", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Dir Z", FloatArgumentType.floatArg())
|
||||
.then(CommandManager.argument("Force", FloatArgumentType.floatArg())
|
||||
.executes { context ->
|
||||
forceFieldAddArg(context, access, "Cube")
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
.then(CommandManager.literal("Remove")
|
||||
.then(CommandManager.argument("Index", IntegerArgumentType.integer())
|
||||
.executes { context ->
|
||||
val index = IntegerArgumentType.getInteger(context, "Index")
|
||||
forceFieldRemoveArg(context, access, index)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
.executes { context ->
|
||||
forceFieldRemoveArg(context, access, -1)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun forceFieldAddArg(context: CommandContext<ServerCommandSource>,
|
||||
access: KProperty1<EmitterParams, ParamClasses.ForceFieldArray>,
|
||||
shape: String
|
||||
) {
|
||||
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")
|
||||
|
||||
|
||||
val forceFields = getEmitterDataById(id)?.forceFields
|
||||
var forceField: ForceField? = null
|
||||
|
||||
if (shape == "Sphere") {
|
||||
val radius = FloatArgumentType.getFloat(context, "Radius")
|
||||
val minForce = FloatArgumentType.getFloat(context, "Min Force")
|
||||
val maxForce = FloatArgumentType.getFloat(context, "Max Force")
|
||||
|
||||
forceField = ForceField(
|
||||
Vector3f(x, y, z),
|
||||
ForceFieldShape.Sphere(radius, Pair(minForce, maxForce))
|
||||
)
|
||||
}
|
||||
|
||||
if (forceFields != null && forceField != null) {
|
||||
forceFields.array.toMutableList().apply { add(forceField) }.toTypedArray()
|
||||
updateParam(id, access, forceFields)
|
||||
successText(access, "++ForceField", id, context)
|
||||
}
|
||||
else {
|
||||
negativeFeedback("Failed to update param \"forceFields\"! The Emitter ID is most likely invalid!", context)
|
||||
}
|
||||
}
|
||||
|
||||
fun forceFieldRemoveArg(context: CommandContext<ServerCommandSource>,
|
||||
access: KProperty1<EmitterParams, ParamClasses.ForceFieldArray>,
|
||||
index: Int
|
||||
) {
|
||||
val id = StringArgumentType.getString(context, "Emitter ID")
|
||||
|
||||
val forceFields = getEmitterDataById(id)?.forceFields
|
||||
|
||||
if (index == -1 && forceFields != null) {
|
||||
forceFields.array.toMutableList().apply { removeLast() }.toTypedArray()
|
||||
updateParam(id, access, forceFields)
|
||||
}
|
||||
else if (forceFields != null) {
|
||||
forceFields.array.toMutableList().apply { removeAt(index.coerceIn(0, forceFields.array.lastIndex)) }.toTypedArray()
|
||||
updateParam(id, access, forceFields)
|
||||
}
|
||||
|
||||
successText(access, "--item at $index", id, context)
|
||||
}
|
||||
@@ -22,7 +22,7 @@ data class EmitterParams (
|
||||
var initScale: ParamClasses.PairVec3f,
|
||||
var transformWithVel: ParamClasses.TransformWithVel,
|
||||
// velocity
|
||||
var forceFields: Array<ForceField>,
|
||||
var forceFields: ParamClasses.ForceFieldArray,
|
||||
var constVel: Vector3f,
|
||||
var drag: Float,
|
||||
var minVel: Float,
|
||||
@@ -49,11 +49,11 @@ data class EmitterParams (
|
||||
initCenterVel = ParamClasses.PairFloat(0.4f, 0.5f),
|
||||
initScale = ParamClasses.PairVec3f.Uniform(0.5f, 1.5f),
|
||||
transformWithVel = ParamClasses.TransformWithVel.None,
|
||||
forceFields = emptyArray(),
|
||||
forceFields = ParamClasses.ForceFieldArray(emptyArray()),
|
||||
constVel = Vector3f(0.0f, 0.0f, 0.0f),
|
||||
drag = 0.075f,
|
||||
minVel = 0.0f,
|
||||
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
||||
offsetCurve = ParamClasses.LerpVal.Null,
|
||||
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt),
|
||||
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 2.5f, LerpCurves.Linear),
|
||||
modelCurve = ParamClasses.StringCurve(
|
||||
@@ -83,11 +83,11 @@ data class EmitterParams (
|
||||
initCenterVel = ParamClasses.PairFloat(1.5f, 1.5f),
|
||||
initScale = ParamClasses.PairVec3f.Uniform(2.0f, 2.0f),
|
||||
transformWithVel = ParamClasses.TransformWithVel.ScaleAndRot(0.75f),
|
||||
forceFields = emptyArray(),
|
||||
forceFields = ParamClasses.ForceFieldArray(emptyArray()),
|
||||
constVel = Vector3f(0.0f, -0.05f, 0.0f),
|
||||
drag = 0.075f,
|
||||
minVel = 0.0f,
|
||||
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
||||
offsetCurve = ParamClasses.LerpVal.Null,
|
||||
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Linear),
|
||||
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.0f, LerpCurves.Linear),
|
||||
modelCurve = ParamClasses.StringCurve(
|
||||
@@ -117,15 +117,16 @@ data class EmitterParams (
|
||||
initCenterVel = ParamClasses.PairFloat(-1.5f, -1.5f),
|
||||
initScale = ParamClasses.PairVec3f.Uniform(10.0f, 15.0f),
|
||||
transformWithVel = ParamClasses.TransformWithVel.None,
|
||||
forceFields = arrayOf(ForceField(
|
||||
"MUSHROOM_HEAD",
|
||||
Vector3f(0.0f, 75.0f, 0.0f),
|
||||
ForceFieldShape.Sphere(15.0f, Pair(0.1f, 0.2f))
|
||||
)),
|
||||
forceFields = ParamClasses.ForceFieldArray(
|
||||
arrayOf(ForceField(
|
||||
Vector3f(0.0f, 75.0f, 0.0f),
|
||||
ForceFieldShape.Sphere(15.0f, Pair(0.1f, 0.2f))
|
||||
))
|
||||
),
|
||||
constVel = Vector3f(0.0f, 0.001f, 0.0f),
|
||||
drag = 0.075f,
|
||||
minVel = 0.0f,
|
||||
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
||||
offsetCurve = ParamClasses.LerpVal.Null,
|
||||
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Linear),
|
||||
scaleCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 1.5f, LerpCurves.Linear),
|
||||
modelCurve = ParamClasses.StringCurve(
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.bytedice.bde_particles.particles
|
||||
import org.joml.Vector3f
|
||||
|
||||
data class ForceField (
|
||||
val name: String = "DEFAULT",
|
||||
val pos: Vector3f = Vector3f(0.0f, 5.0f, 0.0f),
|
||||
val shape: ForceFieldShape = ForceFieldShape.Sphere()
|
||||
val pos: Vector3f,
|
||||
val shape: ForceFieldShape
|
||||
)
|
||||
@@ -94,7 +94,7 @@ class ParamClasses {
|
||||
return com.bytedice.bde_particles.lerp(from, to, curve.function(t))
|
||||
}
|
||||
}
|
||||
data object NoLerpVec3f : LerpVal()
|
||||
data object Null : LerpVal()
|
||||
|
||||
fun lerpToVector3f(t: Float) : Vector3f {
|
||||
when (this) {
|
||||
@@ -104,7 +104,7 @@ class ParamClasses {
|
||||
val x = this.lerp(t)
|
||||
return Vector3f(x, x, x)
|
||||
}
|
||||
is NoLerpVec3f -> return Vector3f(1.0f, 1.0f, 1.0f)
|
||||
is Null -> return Vector3f(1.0f, 1.0f, 1.0f)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,4 +162,7 @@ class ParamClasses {
|
||||
) {
|
||||
fun lerp(t: Float) : String { return lerpArray(array as Array<Any>, t, curve) as String }
|
||||
}
|
||||
data class ForceFieldArray (
|
||||
val array: Array<ForceField>
|
||||
)
|
||||
}
|
||||
@@ -157,7 +157,7 @@ class Particle(
|
||||
pos = newPos
|
||||
|
||||
|
||||
for (forceField in emitterParams.forceFields) {
|
||||
for (forceField in emitterParams.forceFields.array) {
|
||||
if (forceField.shape is ForceFieldShape.Sphere) { vel.add(sphereSdfVel(forceField)) }
|
||||
else if (forceField.shape is ForceFieldShape.Cube) { vel.add(cubeSdfVel(forceField)) }
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ fun addToRegister(id: String, params: EmitterParams) : Pair<String, Boolean> {
|
||||
|
||||
val newModels: MutableList<String> = mutableListOf()
|
||||
|
||||
for (model in params.modelCurve.first) {
|
||||
for (model in params.modelCurve.array) {
|
||||
val modelModIdRegex = ".*:".toRegex()
|
||||
if (modelModIdRegex.containsMatchIn(model)) { break }
|
||||
else {
|
||||
@@ -35,7 +35,7 @@ fun addToRegister(id: String, params: EmitterParams) : Pair<String, Boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
params.modelCurve = Pair(newModels.toTypedArray(), params.modelCurve.second)
|
||||
params.modelCurve = ParamClasses.StringCurve(newModels.toTypedArray(), params.modelCurve.curve)
|
||||
|
||||
idRegister[id] = params
|
||||
println("BPS - Registered Emitter ID \"$newId\".")
|
||||
|
||||
@@ -118,12 +118,12 @@ sealed class SpawningShape() {
|
||||
|
||||
sealed class ForceFieldShape {
|
||||
data class Sphere(
|
||||
val radius: Float = 3.0f,
|
||||
val force: Pair<Float, Float> = Pair(0.0f, 0.02f),
|
||||
val radius: Float,
|
||||
val force: Pair<Float, Float>,
|
||||
) : ForceFieldShape()
|
||||
data class Cube(
|
||||
val size: Vector3f = Vector3f(1.0f, 1.0f, 1.0f),
|
||||
val dir: Vector3f = Vector3f(0.0f, 1.0f, 0.0f),
|
||||
val force: Float = 0.02f
|
||||
val size: Vector3f,
|
||||
val dir: Vector3f,
|
||||
val force: Float
|
||||
) : ForceFieldShape()
|
||||
}
|
||||
Reference in New Issue
Block a user