Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: cb23ae366d31146bf85b403f6149419b
m_Address: SDKParticleSystem
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d08e60223593f4abe8863c64316f3476
m_Address: FlipLinearToGammaMaterial.mat
m_ReadOnly: 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ public static ComponentsContainer Create()
.Add(SDKComponentBuilder<PBTriggerArea>.Create(ComponentID.TRIGGER_AREA).AsProtobufComponent())
.Add(SDKComponentBuilder<PBTriggerAreaResult>.Create(ComponentID.TRIGGER_AREA_RESULT).AsProtobufResult())
.Add(SDKComponentBuilder<PBAvatarLocomotionSettings>.Create(ComponentID.AVATAR_LOCOMOTION_SETTINGS).AsProtobufComponent())
.Add(SDKComponentBuilder<PBParticleSystem>.Create(ComponentID.PARTICLE_SYSTEM).AsProtobufComponent())
.Add(SDKComponentBuilder<PBPhysicsCombinedImpulse>.Create(ComponentID.PHYSICS_COMBINED_IMPULSE).AsProtobufComponent())
.Add(SDKComponentBuilder<PBPhysicsCombinedForce>.Create(ComponentID.PHYSICS_COMBINED_FORCE).AsProtobufComponent());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ public UniTask InitializeAsync(StaticSettings settings, CancellationToken ct)
new InputModifierPlugin(globalWorld, container.PlayerEntity, container.SceneRestrictionBusController),
new MainCameraPlugin(componentsContainer.ComponentPoolsRegistry, container.assetsProvisioner, container.CacheCleaner, exposedGlobalDataContainer.ExposedCameraData, container.SceneRestrictionBusController, globalWorld),
new LightSourcePlugin(componentsContainer.ComponentPoolsRegistry, container.assetsProvisioner, container.CacheCleaner, container.CharacterContainer.CharacterObject, globalWorld, appArgs.HasDebugFlag()),
new ParticleSystemPlugin(componentsContainer.ComponentPoolsRegistry, container.assetsProvisioner, container.CacheCleaner, container.DebugContainerBuilder),
new PrimaryPointerInfoPlugin(globalWorld),
promisesAnalyticsPlugin,
new SkyboxTimePlugin(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ public partial class PBTriggerArea : IDirtyMarker
public bool IsDirty { get; set; }
}

public partial class PBParticleSystem : IDirtyMarker
{
public bool IsDirty { get; set; }
}

public partial class PBPointerLock : IDirtyMarker
{
public bool IsDirty { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public static class Categories
public static readonly WidgetName LOCOMOTION_HANDS_IK = "locomotion: hands ik".AsWidgetName();
public static readonly WidgetName QUALITY = "Quality".AsWidgetName();
public static readonly WidgetName RENDERING = "Rendering".AsWidgetName();
public static readonly WidgetName PARTICLES = "Particles".AsWidgetName();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ public static class ReportCategory

public const string LIGHT_SOURCE = nameof(LIGHT_SOURCE);

public const string PARTICLE_SYSTEM = nameof(PARTICLE_SYSTEM);

public const string ALWAYS = nameof(ALWAYS);

public const string GPU_INSTANCING = nameof(GPU_INSTANCING);
Expand Down
130 changes: 130 additions & 0 deletions Explorer/Assets/DCL/PluginSystem/World/ParticleSystemPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Arch.SystemGroups;
using Cysharp.Threading.Tasks;
using DCL.AssetsProvision;
using DCL.DebugUtilities;
using DCL.DebugUtilities.UIBindings;
using DCL.ECSComponents;
using DCL.Optimization.Pools;
using DCL.PluginSystem.World.Dependencies;
using DCL.ResourcesUnloading;
using DCL.SDKComponents.ParticleSystem.Systems;
using ECS.LifeCycle;
using ECS.LifeCycle.Systems;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Pool;
using Object = UnityEngine.Object;
using Utility;

namespace DCL.PluginSystem.World
{
public class ParticleSystemPlugin : IDCLWorldPlugin<ParticleSystemPlugin.ParticleSystemPluginSettings>
{
private readonly IComponentPoolsRegistry poolsRegistry;
private readonly IAssetsProvisioner assetsProvisioner;
private readonly CacheCleaner cacheCleaner;
private readonly IDebugContainerBuilder debugBuilder;

private IComponentPool<ParticleSystem>? particleSystemPool;
private IObjectPool<Material>? particleMaterialPool;
private ParticleSystemPluginSettings? pluginSettings;
private ElementBinding<string>? particleCountBinding;
private DebugWidgetVisibilityBinding? particlesVisibilityBinding;

public ParticleSystemPlugin(IComponentPoolsRegistry poolsRegistry, IAssetsProvisioner assetsProvisioner,
CacheCleaner cacheCleaner, IDebugContainerBuilder debugBuilder)
{
this.poolsRegistry = poolsRegistry;
this.assetsProvisioner = assetsProvisioner;
this.cacheCleaner = cacheCleaner;
this.debugBuilder = debugBuilder;
}

public void Dispose() { }

public void InjectToWorld(
ref ArchSystemsWorldBuilder<Arch.Core.World> builder,
in ECSWorldInstanceSharedDependencies sharedDependencies,
in PersistentEntities persistentEntities,
List<IFinalizeWorldSystem> finalizeWorldSystems,
List<ISceneIsCurrentListener> sceneIsCurrentListeners)
{
ResetDirtyFlagSystem<PBParticleSystem>.InjectToWorld(ref builder);

var lifecycleSystem = ParticleSystemLifecycleSystem.InjectToWorld(
ref builder,
sharedDependencies.SceneStateProvider,
particleSystemPool,
particleMaterialPool!);

ParticleSystemApplyPropertiesSystem.InjectToWorld(
ref builder,
sharedDependencies.SceneData,
sharedDependencies.ScenePartition,
particleMaterialPool!);

var playbackSystem = ParticleSystemPlaybackSystem.InjectToWorld(ref builder);
sceneIsCurrentListeners.Add(playbackSystem);

ParticleSystemBudgetSystem.InjectToWorld(ref builder, pluginSettings!, particleCountBinding!, particlesVisibilityBinding!);

finalizeWorldSystems.Add(lifecycleSystem);
}

public async UniTask InitializeAsync(ParticleSystemPluginSettings settings, CancellationToken ct)
{
ParticleSystem prefab = (await assetsProvisioner.ProvideMainAssetAsync(settings.ParticleSystemPrefab, ct)).Value
.GetComponent<ParticleSystem>();

particleSystemPool = poolsRegistry.AddGameObjectPool(
() => Object.Instantiate(prefab, Vector3.zero, quaternion.identity),
onRelease: OnPoolRelease);

cacheCleaner.Register(particleSystemPool);

pluginSettings = settings;

particleCountBinding = new ElementBinding<string>(string.Empty);
particlesVisibilityBinding = new DebugWidgetVisibilityBinding(true);

debugBuilder.TryAddWidget(IDebugContainerBuilder.Categories.PARTICLES)
?.SetVisibilityBinding(particlesVisibilityBinding)
.AddCustomMarker("Scene Particles:", particleCountBinding);

particleMaterialPool = new ObjectPool<Material>(
createFunc: () => new Material(settings.ParticleMaterial),
actionOnRelease: releasedMaterial => releasedMaterial.CopyPropertiesFromMaterial(settings.ParticleMaterial),
actionOnDestroy: UnityObjectUtils.SafeDestroy,
defaultCapacity: 64,
maxSize: 512);
}

private static void OnPoolRelease(ParticleSystem particleSystem)
{
particleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
particleSystem.transform.SetParent(null);
particleSystem.gameObject.SetActive(false);
}

[Serializable]
public class ParticleSystemPluginSettings : IDCLPluginSettings
{
[field: SerializeField]
public AssetReferenceGameObject ParticleSystemPrefab { get; private set; }

/// <summary>
/// Base material for particle rendering. Should point to same Material used in MaterialWorldPlugin.
/// Kept as a direct reference (not Addressable) to ensure shader variants are compiled.
/// </summary>
[field: SerializeField]
public Material ParticleMaterial { get; private set; }

[field: SerializeField]
public int MaxSceneParticles { get; private set; } = 1000;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ MonoBehaviour:
- rid: 3414978285727645698
- rid: 3414978285727645699
- rid: 6144113899072913497
- rid: 4938242198007709791
references:
version: 2
RefIds:
Expand Down Expand Up @@ -219,6 +220,17 @@ MonoBehaviour:
<FadeSpeed>k__BackingField: 1
<FlipMaterial>k__BackingField: {fileID: 2100000, guid: d08e60223593f4abe8863c64316f3476, type: 2}
VideoPrioritizationSettings: {fileID: 11400000, guid: 12f48d0297bd3f746b92a97878478086, type: 2}
- rid: 4938242198007709791
type: {class: ParticleSystemPlugin/ParticleSystemPluginSettings, ns: DCL.PluginSystem.World, asm: DCL.Plugins}
data:
<ParticleSystemPrefab>k__BackingField:
m_AssetGUID: cb23ae366d31146bf85b403f6149419b
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0
<ParticleMaterial>k__BackingField: {fileID: 2100000, guid: 3f2e1d0c4b5a6978abcdef0123456789, type: 2}
<MaxSceneParticles>k__BackingField: 1000
- rid: 6144113899072913497
type: {class: SkyboxTimePlugin/SkyboxTimeSettings, ns: DCL.SDKComponents.SkyboxTime, asm: DCL.Plugins}
data:
Expand Down
8 changes: 8 additions & 0 deletions Explorer/Assets/DCL/SDKComponents/ParticleSystem.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using DCL.ECSComponents;

namespace DCL.SDKComponents.ParticleSystem.Components
{
public static class PBParticleSystemDefaults
{
public static bool GetActive(this PBParticleSystem self) =>
!self.HasActive || self.Active;

public static float GetRate(this PBParticleSystem self) =>
self.HasRate ? self.Rate : 10f;

public static uint GetMaxParticles(this PBParticleSystem self) =>
self.HasMaxParticles ? self.MaxParticles : 1000;

public static float GetLifetime(this PBParticleSystem self) =>
self.HasLifetime ? self.Lifetime : 5f;

public static float GetGravity(this PBParticleSystem self) =>
self.HasGravity ? self.Gravity : 0f;

public static bool GetLoop(this PBParticleSystem self) =>
!self.HasLoop || self.Loop;

public static bool GetPrewarm(this PBParticleSystem self) =>
self.HasPrewarm && self.Prewarm;

public static bool GetFaceTravelDirection(this PBParticleSystem self) =>
self.HasFaceTravelDirection && self.FaceTravelDirection;

public static PBParticleSystem.Types.BlendMode GetBlendMode(this PBParticleSystem self) =>
self.HasBlendMode ? self.BlendMode : PBParticleSystem.Types.BlendMode.PsbAlpha;

public static PBParticleSystem.Types.SimulationSpace GetSimulationSpace(this PBParticleSystem self) =>
self.HasSimulationSpace ? self.SimulationSpace : PBParticleSystem.Types.SimulationSpace.PssLocal;

public static PBParticleSystem.Types.PlaybackState GetPlaybackState(this PBParticleSystem self) =>
self.HasPlaybackState ? self.PlaybackState : PBParticleSystem.Types.PlaybackState.PsPlaying;

// --- Shape sub-types ---

public static float GetRadius(this PBParticleSystem.Types.Sphere self) =>
self.HasRadius ? self.Radius : 1f;

public static float GetAngle(this PBParticleSystem.Types.Cone self) =>
self.HasAngle ? self.Angle : 25f;

public static float GetRadius(this PBParticleSystem.Types.Cone self) =>
self.HasRadius ? self.Radius : 1f;

// --- LimitVelocity ---

public static float GetDampen(this PBParticleSystem.Types.LimitVelocity self) =>
self.HasDampen ? self.Dampen : 1f;

// --- SpriteSheet ---

public static float GetFramesPerSecond(this PBParticleSystem.Types.SpriteSheetAnimation self) =>
self.HasFramesPerSecond ? self.FramesPerSecond : 30f;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Arch.Core;
using DCL.ECSComponents;
using ECS.StreamableLoading.Common;
using ECS.StreamableLoading.Textures;
using UnityEngine;

namespace DCL.SDKComponents.ParticleSystem
{
public struct ParticleSystemComponent
{
public readonly UnityEngine.ParticleSystem ParticleSystemInstance;
public readonly ParticleSystemRenderer Renderer;
public readonly GameObject HostGameObject;

public GetTextureIntention LoadingTextureIntention;
public AssetPromise<TextureData, GetTextureIntention>? TexturePromise;
public Material ParticleMaterial;

public uint LastRestartCount;

// Cached objects to avoid allocations on dirty updates
public Gradient CachedGradient;
public GradientColorKey[] CachedColorKeys;
public GradientAlphaKey[] CachedAlphaKeys;
public AnimationCurve CachedCurve;

// Blend mode tracking to skip redundant material operations
public PBParticleSystem.Types.BlendMode LastAppliedBlendMode;
public bool BlendModeInitialized;

public ParticleSystemComponent(UnityEngine.ParticleSystem instance, GameObject hostGameObject) : this()
{
ParticleSystemInstance = instance;
Renderer = instance.GetComponent<ParticleSystemRenderer>();
HostGameObject = hostGameObject;
}

public void CleanUpTexture(in World world)
{
LoadingTextureIntention = default(GetTextureIntention);

if (TexturePromise != null)
{
TexturePromise.Value.ForgetLoading(world);
TexturePromise = null;
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading