Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Fix Particle System Editor #8098

Merged
merged 2 commits into from
Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/client-core/i18n/en/editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@
"particle-system": {
"name": "Particle System",
"description": "Particle emitter to create particles.",
"looping": "Looping",
"duration": "Duration",
"prewarm": "Prewarm",
"emitter-shape": "Emitter Shape",
"emission-bursts": "Emission Bursts",
"shape-mesh": "Emitter Shape Mesh",
Expand All @@ -383,6 +386,7 @@
"start-tile-index": "Starting Tile Index",
"mesh": "Particle Mesh",
"blending": "Blending",
"transparent": "Transparent",
"world-space": "Use World Space"
},
"clouds": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,47 +114,27 @@ const ParticleSystemNodeEditor: EditorComponentType = (props) => {

const onSetState = useCallback((state: State<any>) => {
return (value: any) => {
state.set(value)
state.set(JSON.parse(JSON.stringify(value)))
particleSystemState._refresh.set((particleSystem._refresh + 1) % 1000)
}
}, [])

const onSetStateParm = useCallback((state: State<any>) => {
return (field: keyof typeof state.value) => {
if (field === 'value') {
return (value: any) => {
const nuVals = JSON.parse(JSON.stringify(state.value))
nuVals.value = value
state.set(nuVals)
particleSystemState._refresh.set((particleSystem._refresh + 1) % 1000)
}
} else
return (value: any) => {
state[field].set(value)
particleSystemState._refresh.set((particleSystem._refresh + 1) % 1000)
}
const onAddBehavior = useCallback(() => {
const nuBehavior: ApplyForceBehaviorJSON = {
type: 'ApplyForce',
direction: [0, 1, 0],
magnitude: {
type: 'ConstantValue',
value: 1
}
}
particleSystemState.behaviorParameters.set([
...JSON.parse(JSON.stringify(particleSystem.behaviorParameters)),
nuBehavior
])
particleSystemState._refresh.set((particleSystem._refresh + 1) % 1000)
}, [])

const onAddBehavior = useCallback(
() => () => {
const nuBehavior: ApplyForceBehaviorJSON = {
type: 'ApplyForce',
direction: [0, 1, 0],
magnitude: {
type: 'ConstantValue',
value: 1
}
}
particleSystemState.behaviorParameters.set([
...JSON.parse(JSON.stringify(particleSystem.behaviorParameters)),
nuBehavior
])
particleSystemState._refresh.set((particleSystem._refresh + 1) % 1000)
},
[]
)

const onRemoveBehavior = useCallback(
(behavior: BehaviorJSON) => () => {
particleSystemState.behaviorParameters.set(
Expand Down Expand Up @@ -204,6 +184,10 @@ const ParticleSystemNodeEditor: EditorComponentType = (props) => {
<NumericInput value={particleSystem.systemParameters.duration} onChange={onSetSystemParm('duration')} />
</InputGroup>

<InputGroup name="Prewarm" label={t('editor:properties.particle-system.prewarm')}>
<BooleanInput value={particleSystem.systemParameters.prewarm} onChange={onSetSystemParm('prewarm')} />
</InputGroup>

<InputGroup name="Emitter Shape" label={t('editor:properties.particle-system.emitter-shape')}>
<SelectInput
value={particleSystem.systemParameters.shape.type}
Expand Down Expand Up @@ -427,7 +411,7 @@ const ParticleSystemNodeEditor: EditorComponentType = (props) => {
<BooleanInput value={particleSystem.systemParameters.worldSpace} onChange={onSetSystemParm('worldSpace')} />
</InputGroup>
<h4>Behaviors</h4>
<Button onClick={onAddBehavior()}>Add Behavior</Button>
<Button onClick={onAddBehavior}>Add Behavior</Button>
<PaginatedList
list={particleSystemState.behaviorParameters}
element={(behaviorState: State<BehaviorJSON>) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default function BehaviorInput({
const onChangeBehaviorType = useCallback(() => {
const onChangeType = onChange(scope.type)
return (type: typeof value.type) => {
const nuVals = BehaviorJSONDefaults[type]
const nuVals = JSON.parse(JSON.stringify(BehaviorJSONDefaults[type]))
scope.set(nuVals)
onChangeType(type)
}
Expand Down Expand Up @@ -469,8 +469,7 @@ export default function BehaviorInput({
Rotation3DOverLife: rotation3DOverLifeInput,
WidthOverLength: widthOverLength,
ChangeEmitDirection: changeEmitDirectionInput,
EmitSubParticleSystem: emitSubParticleSystemInput,
ApplySequences: applySequencesInput
EmitSubParticleSystem: emitSubParticleSystemInput
}

return (
Expand All @@ -479,7 +478,6 @@ export default function BehaviorInput({
<SelectInput
value={value.type}
options={[
{ label: 'Apply Sequences', value: 'ApplySequences' },
{ label: 'Apply Force', value: 'ApplyForce' },
{ label: 'Noise', value: 'Noise' },
{ label: 'Turbulence Field', value: 'TurbulenceField' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default function ValueGenerator({
const onChangeType = useCallback(() => {
const thisOnChange = onChange(scope.type)
return (type: typeof value.type) => {
scope.set(ValueGeneratorJSONDefaults[type])
scope.set(JSON.parse(JSON.stringify(ValueGeneratorJSONDefaults[type])))
thisOnChange(type)
}
}, [])
Expand Down
26 changes: 20 additions & 6 deletions packages/engine/src/scene/components/ParticleSystemComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,16 @@ Ethereal Engine. All Rights Reserved.
*/

import { useEffect } from 'react'
import { AdditiveBlending, BufferGeometry, Material, MeshBasicMaterial, Texture, Vector2, Vector3 } from 'three'
import {
AdditiveBlending,
BufferGeometry,
Material,
MeshBasicMaterial,
Object3D,
Texture,
Vector2,
Vector3
} from 'three'
import { Behavior, BehaviorFromJSON, ParticleSystem, ParticleSystemJSONParameters, RenderMode } from 'three.quarks'
import matches from 'ts-matches'

Expand Down Expand Up @@ -752,7 +761,7 @@ export const ParticleSystemComponent = defineComponent({
},
onRemove: (entity, component) => {
if (component.system.value) {
removeObjectFromGroup(entity, component.system.value.emitter)
removeObjectFromGroup(entity, component.system.value.emitter as unknown as Object3D)
component.system.get(NO_PROXY)?.dispose()
component.system.set(none)
}
Expand All @@ -767,13 +776,16 @@ export const ParticleSystemComponent = defineComponent({
const componentState = useComponent(entity, ParticleSystemComponent)
const component = componentState.value
const batchRenderer = getBatchRenderer()!

useEffect(() => {
if (component.system && component.system!.emitter.userData['_refresh'] === component._refresh) return
if (component.system) {
removeObjectFromGroup(entity, component.system.emitter)
const emitterAsObj3D = component.system.emitter as unknown as Object3D
if (emitterAsObj3D.userData['_refresh'] === component._refresh) return
removeObjectFromGroup(entity, emitterAsObj3D)
component.system.dispose()
componentState.system.set(none)
}

function initParticleSystem(systemParameters: ParticleSystemJSONParameters, metadata: ParticleSystemMetadata) {
const nuSystem = ParticleSystem.fromJSON(systemParameters, metadata, {})
batchRenderer.addSystem(nuSystem)
Expand All @@ -784,8 +796,10 @@ export const ParticleSystemComponent = defineComponent({
return behavior
})
)
nuSystem.emitter.userData['_refresh'] = component._refresh
addObjectToGroup(entity, nuSystem.emitter)

const emitterAsObj3D = nuSystem.emitter as unknown as Object3D
emitterAsObj3D.userData['_refresh'] = component._refresh
addObjectToGroup(entity, emitterAsObj3D)
componentState.system.set(nuSystem)
}

Expand Down