--- /dev/null
+/*
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using global::System.Runtime.InteropServices;
+
+namespace Tizen.NUI.ParticleSystem
+{
+ internal static partial class Interop
+ {
+ internal static partial class Particle
+ {
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Particle_ReadFloat")]
+ internal static extern float ReadFloat(global::System.Runtime.InteropServices.HandleRef jarg1, uint streamIndex, uint particleIndex);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Particle_ReadVector2")]
+ internal static extern global::System.IntPtr ReadVector2(global::System.Runtime.InteropServices.HandleRef jarg1, uint streamIndex, uint particleIndex);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Particle_ReadVector3")]
+ internal static extern global::System.IntPtr ReadVector3(global::System.Runtime.InteropServices.HandleRef jarg1, uint streamIndex, uint particleIndex);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Particle_ReadVector4")]
+ internal static extern global::System.IntPtr ReadVector4(global::System.Runtime.InteropServices.HandleRef jarg1, uint streamIndex, uint particleIndex);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Particle_WriteFloat")]
+ internal static extern void WriteFloat(global::System.Runtime.InteropServices.HandleRef jarg1, uint streamIndex, uint particleIndex, float value);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Particle_WriteVector2")]
+ internal static extern void WriteVector2(global::System.Runtime.InteropServices.HandleRef jarg1, uint streamIndex, uint particleIndex, HandleRef value);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Particle_WriteVector3")]
+ internal static extern void WriteVector3(global::System.Runtime.InteropServices.HandleRef jarg1, uint streamIndex, uint particleIndex, HandleRef value);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Particle_WriteVector4")]
+ internal static extern void WriteVector4(global::System.Runtime.InteropServices.HandleRef jarg1, uint streamIndex, uint particleIndex, HandleRef value);
+ }
+ }
+}
+
--- /dev/null
+/*
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using global::System.Runtime.InteropServices;
+
+namespace Tizen.NUI.ParticleSystem
+{
+ internal static partial class Interop
+ {
+ internal static partial class ParticleEmitter
+ {
+ [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_New_SWIG_0")]
+ internal static extern global::System.IntPtr New(HandleRef view);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_delete_ParticleEmitter")]
+ internal static extern void DeleteParticleEmitter(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_Assign")]
+ internal static extern global::System.IntPtr Assign(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_DownCast")]
+ internal static extern global::System.IntPtr DownCast(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_SetSource")]
+ internal static extern void SetSource(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_SetDomain")]
+ internal static extern void SetDomain(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_SetRenderer")]
+ internal static extern void SetRenderer(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_AddModifier")]
+ internal static extern void AddModifier(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_SetParticleCount")]
+ internal static extern void SetParticleCount(global::System.Runtime.InteropServices.HandleRef jarg1, uint count);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetParticleCount")]
+ internal static extern uint GetParticleCount(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_SetEmissionRate")]
+ internal static extern void SetEmissionRate(global::System.Runtime.InteropServices.HandleRef jarg1, uint count);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_SetInitialParticleCount")]
+ internal static extern void SetInitialParticleCount(global::System.Runtime.InteropServices.HandleRef jarg1, uint count);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_SetActiveParticlesLimit")]
+ internal static extern void SetActiveParticlesLimit(global::System.Runtime.InteropServices.HandleRef jarg1, uint count);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetActiveParticlesLimit")]
+ internal static extern uint GetActiveParticlesLimit(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_Start")]
+ internal static extern void Start(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_Stop")]
+ internal static extern void Stop(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_RemoveModifierAt")]
+ internal static extern void RemoveModifierAt(global::System.Runtime.InteropServices.HandleRef jarg1, uint index);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetModifierAt")]
+ internal static extern global::System.IntPtr GetModifierAt(global::System.Runtime.InteropServices.HandleRef jarg1, uint index);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetParticleList")]
+ internal static extern global::System.IntPtr GetParticleList(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetSource")]
+ internal static extern global::System.IntPtr GetSource(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetDomain")]
+ internal static extern global::System.IntPtr GetDomain(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetRenderer")]
+ internal static extern global::System.IntPtr GetRenderer(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetEmissionRate")]
+ internal static extern uint GetEmissionRate(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetInitialParticleCount")]
+ internal static extern uint GetInitialParticleCount(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_GetActiveParticleLimit")]
+ internal static extern uint GetActiveParticleLimit(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ // ParticleRenderer
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleRenderer_SetTexture")]
+ internal static extern void SetTexture(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleRenderer_SetBlendingMode")]
+ internal static extern void SetBlendingMode(global::System.Runtime.InteropServices.HandleRef jarg1, ParticleBlendingMode mode);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleRenderer_GetBlendingMode")]
+ internal static extern int GetBlendingMode(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleEmitter_NewParticle")]
+ internal static extern int NewParticle(global::System.IntPtr emitter, float lifetime);
+
+ // ParticleList
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleList_AddLocalStream")]
+ internal unsafe static extern uint AddLocalStream(global::System.Runtime.InteropServices.HandleRef jarg1, uint streamType, void* defaultValue, uint typeSize );
+
+ [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleList_GetDefaultStreamIndex")]
+ internal unsafe static extern int GetDefaultStreamIndex(global::System.Runtime.InteropServices.HandleRef jarg1, uint builtInStream );
+
+ }
+ }
+}
+
--- /dev/null
+/*
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using global::System.Runtime.InteropServices;
+using System.Reflection;
+using System;
+
+namespace Tizen.NUI.ParticleSystem
+{
+ internal static partial class Interop
+ {
+ internal static partial class ParticleModifier
+ {
+ internal delegate void ParticleModifierUpdateInvokerType(IntPtr ptr, IntPtr particleListPtr, uint first, uint count);
+
+ [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleModifier_New_SWIG_0")]
+ public static extern global::System.IntPtr New(ParticleModifierUpdateInvokerType updateInvoker, out IntPtr basePtr);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using global::System.Runtime.InteropServices;
+using System.Reflection;
+using System;
+
+namespace Tizen.NUI.ParticleSystem
+{
+ internal static partial class Interop
+ {
+ internal static partial class ParticleSource
+ {
+ internal delegate void ParticleSourceInitInvokerType(IntPtr ptr);
+ internal delegate uint ParticleSourceUpdateInvokerType(IntPtr ptr, uint count);
+
+ [DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_ParticleSource_New_SWIG_0")]
+ internal static extern global::System.IntPtr New(ParticleSourceInitInvokerType initInvoker, ParticleSourceUpdateInvokerType updateInvoker, out IntPtr refObject);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System;
+using System.Runtime.InteropServices;
+using global::System.Runtime.InteropServices;
+using System.ComponentModel;
+using System.Reflection;
+
+namespace Tizen.NUI.ParticleSystem
+{
+ using Tizen.NUI.BaseComponents;
+
+ /// <summary>
+ /// Declares types of default streams
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public enum ParticleStream
+ {
+ Position = 1 << 0, // Vector3, Position of particle
+ Rotation = 1 << 1, // Vector4, Rotation of particle (quaternion)
+ Scale = 1 << 2, // Vector3, Scale of particle
+ Size = 1 << 3, // Vector3, size of particle
+ Color = 1 << 4, // Vector4/Color - Color of particle, (RGBA)
+ Opacity = 1 << 5, // float, opacity (0.0-1.0)
+ Velocity = 1 << 6, // Vector3, vector of velocity
+ Lifetime = 1 << 7, // float, remaining lifetime
+ Lifetime_Base = 1 << 8, // float, initial lifetime
+ }
+
+ /// <summary>
+ /// Particle class provides interface to particle data streams
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class Particle
+ {
+ /// <summary>
+ /// StreamView provides functionality allowing particle
+ /// data manipulation (read/write).
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class StreamView
+ {
+ internal StreamView(HandleRef list, uint particleIndex, uint streamIndex)
+ {
+ mParticleIndex = particleIndex;
+ mStreamIndex = (int)streamIndex;
+ mEmitterRef = list;
+ }
+
+ internal StreamView(HandleRef list, uint particleIndex, ParticleStream builtInStream)
+ {
+ mEmitterRef = list;
+ mParticleIndex = particleIndex;
+ mStreamIndex = Interop.ParticleEmitter.GetDefaultStreamIndex(mEmitterRef, (uint)(builtInStream));
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ private struct Value
+ {
+ internal float valueFloat;
+ internal Vector2 valueVector2;
+ internal Vector3 valueVector3;
+ internal Vector4 valueVector4;
+ }
+
+ internal StreamView(float f)
+ {
+ value.valueFloat = f;
+ type = typeof(float);
+ }
+
+ internal StreamView(Vector2 f)
+ {
+ value.valueVector2 = f;
+ type = typeof(Vector2);
+ }
+
+ internal StreamView(Vector3 f)
+ {
+ value.valueVector3 = f;
+ type = typeof(Vector3);
+ }
+
+ internal StreamView(Vector4 f)
+ {
+ value.valueVector4 = f;
+ type = typeof(Vector4);
+ }
+
+ /// <summary>
+ /// Conversion operator to float value
+ /// </summary>
+ /// <param name="sv">StreamView object</param>
+ /// <returns>Converted value</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static implicit operator float(StreamView sv)
+ {
+ var ret = sv.mStreamIndex >= 0 ? Interop.Particle.ReadFloat(sv.mEmitterRef, (uint)sv.mStreamIndex, sv.mParticleIndex) : 0.0f;
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+
+ /// <summary>
+ /// Conversion operator to Vector2 value
+ /// </summary>
+ /// <param name="sv">StreamView object</param>
+ /// <returns>Converted value</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static implicit operator Vector2(StreamView sv) {
+ var ret = sv.mStreamIndex >= 0 ? new Vector2(Interop.Particle.ReadVector2(sv.mEmitterRef, (uint)sv.mStreamIndex, sv.mParticleIndex), true) : Vector2.Zero;
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+
+ /// <summary>
+ /// Conversion operator to Vector3 value
+ /// </summary>
+ /// <param name="sv">StreamView object</param>
+ /// <returns>Converted value</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static implicit operator Vector3(StreamView sv) {
+ var ret = sv.mStreamIndex >= 0 ? new Vector3(Interop.Particle.ReadVector3(sv.mEmitterRef, (uint)sv.mStreamIndex, sv.mParticleIndex), true) : Vector3.Zero;
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+
+ /// <summary>
+ /// Conversion operator to Vecto4 value
+ /// </summary>
+ /// <param name="sv">StreamView object</param>
+ /// <returns>Converted value</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static implicit operator Vector4(StreamView sv) {
+
+ var ret = sv.mStreamIndex >= 0 ? new Vector4(Interop.Particle.ReadVector4(sv.mEmitterRef, (uint)sv.mStreamIndex, sv.mParticleIndex), true) : Vector4.Zero;
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+
+ private int mStreamIndex;
+ private uint mParticleIndex;
+ private HandleRef mEmitterRef;
+ private Value value;
+ private System.Type type;
+ }
+
+ /// <summary>
+ /// Create an initialized Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal Particle(HandleRef emitter, uint index)
+ {
+ mIndex = index;
+ mEmitterRef = emitter;
+ }
+
+ /// <summary>
+ /// Returns value from specified data stream (default/custom)
+ /// </summary>
+ /// <param name="streamIndex">Index of stream to get value from</param>
+ /// <returns>StreamView object</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public StreamView GetStreamValue(uint streamIndex)
+ {
+ return new StreamView(mEmitterRef, mIndex, streamIndex);
+ }
+
+ /// <summary>
+ /// Returns value from specified default streamIndex
+ /// </summary>
+ /// <param name="streamIndex">Index of stream to get value from</param>
+ /// <returns>StreamView object</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public StreamView GetStreamValue(ParticleStream streamIndex)
+ {
+ return new StreamView(mEmitterRef, mIndex, streamIndex);
+ }
+
+ /// <summary>
+ /// Sets value on the specified data stream
+ /// </summary>
+ /// <param name="value">Value to set</param>
+ /// <param name="streamIndex">Index of stream to get value from</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetStreamValue(float value, uint streamIndex)
+ {
+ Interop.Particle.WriteFloat(mEmitterRef, streamIndex, mIndex, value);
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Sets value on the specified data stream
+ /// </summary>
+ /// <param name="value">Value to set</param>
+ /// <param name="streamIndex">Index of stream to get value from</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetStreamValue(Vector2 value, uint streamIndex)
+ {
+ Interop.Particle.WriteVector2(mEmitterRef, streamIndex, mIndex, value.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Sets value on the specified data stream
+ /// </summary>
+ /// <param name="value">Value to set</param>
+ /// <param name="streamIndex">Index of stream to get value from</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetStreamValue(Vector3 value, uint streamIndex)
+ {
+ Interop.Particle.WriteVector3(mEmitterRef, streamIndex, mIndex, value.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Sets value on the specified data stream
+ /// </summary>
+ /// <param name="value">Value to set</param>
+ /// <param name="streamIndex">Index of stream to get value from</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetStreamValue(Vector4 value, uint streamIndex)
+ {
+ Interop.Particle.WriteVector4(mEmitterRef, streamIndex, mIndex, value.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Sets value on the specified data stream
+ /// </summary>
+ /// <param name="value">Value to set</param>
+ /// <param name="particleStream">Stream to get value from</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetStreamValue(float value, ParticleStream particleStream)
+ {
+ uint streamIndex = (uint)(Interop.ParticleEmitter.GetDefaultStreamIndex(mEmitterRef, (uint)(particleStream)));
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+
+ Interop.Particle.WriteFloat(mEmitterRef, streamIndex, mIndex, value);
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Sets value on the specified data stream
+ /// </summary>
+ /// <param name="value">Value to set</param>
+ /// <param name="particleStream">Stream to get value from</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetStreamValue(Vector2 value, ParticleStream particleStream)
+ {
+ uint streamIndex = (uint)(Interop.ParticleEmitter.GetDefaultStreamIndex(mEmitterRef, (uint)(particleStream)));
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+
+ Interop.Particle.WriteVector2(mEmitterRef, streamIndex, mIndex, value.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Sets value on the specified data stream
+ /// </summary>
+ /// <param name="value">Value to set</param>
+ /// <param name="particleStream">Stream to get value from</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetStreamValue(Vector3 value, ParticleStream particleStream)
+ {
+ uint streamIndex = (uint)(Interop.ParticleEmitter.GetDefaultStreamIndex(mEmitterRef, (uint)(particleStream)));
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+
+ Interop.Particle.WriteVector3(mEmitterRef, streamIndex, mIndex, value.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Sets value on the specified data stream
+ /// </summary>
+ /// <param name="value">Value to set</param>
+ /// <param name="particleStream">Stream to get value from</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetStreamValue(Vector4 value, ParticleStream particleStream)
+ {
+ uint streamIndex = (uint)(Interop.ParticleEmitter.GetDefaultStreamIndex(mEmitterRef, (uint)(particleStream)));
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+
+ Interop.Particle.WriteVector4(mEmitterRef, streamIndex, mIndex, value.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending)
+ throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+
+ /// <summary>
+ /// Returns index of one of default streams.
+ /// </summary>
+ /// <param name="streamBit">Stream to get index</param>
+ /// <returns>Index of stream within emitter</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ private uint GetStreamIndex(ParticleStream streamBit)
+ {
+ uint streamIndex = (uint)(Interop.ParticleEmitter.GetDefaultStreamIndex(mEmitterRef, (uint)(streamBit)));
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return streamIndex;
+ }
+
+ /// <summary>
+ /// Position of the Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Vector3 Position
+ {
+ get
+ {
+ var streamIndex = GetStreamIndex(ParticleStream.Position);
+ var ret = new Vector3(Interop.Particle.ReadVector3(mEmitterRef, (uint)streamIndex, mIndex), true);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+ set
+ {
+ SetStreamValue( value, ParticleStream.Position);
+ }
+ }
+
+ /// <summary>
+ /// Color of the Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Vector4 Color
+ {
+ get
+ {
+ var streamIndex = GetStreamIndex(ParticleStream.Color);
+ var ret = new Vector4(Interop.Particle.ReadVector4(mEmitterRef, (uint)streamIndex, mIndex), true);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+ set
+ {
+ SetStreamValue( value, ParticleStream.Color);
+ }
+ }
+
+ /// <summary>
+ /// Velocity of the Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Vector3 Velocity
+ {
+ get
+ {
+ var streamIndex = GetStreamIndex(ParticleStream.Velocity);
+ var ret = new Vector3(Interop.Particle.ReadVector3(mEmitterRef, (uint)streamIndex, mIndex), true);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+ set
+ {
+ SetStreamValue( value, ParticleStream.Velocity);
+ }
+ }
+
+ /// <summary>
+ /// Scale of the Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Vector3 Scale
+ {
+ get
+ {
+ var streamIndex = GetStreamIndex(ParticleStream.Scale);
+ var ret = new Vector3(Interop.Particle.ReadVector3(mEmitterRef, (uint)streamIndex, mIndex), true);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+ set
+ {
+ SetStreamValue( value, ParticleStream.Scale);
+ }
+ }
+
+ /// <summary>
+ /// Rotation of the Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Vector4 Rotation
+ {
+ get
+ {
+ var streamIndex = GetStreamIndex(ParticleStream.Rotation);
+ var ret = new Vector4(Interop.Particle.ReadVector4(mEmitterRef, (uint)streamIndex, mIndex), true);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+ set
+ {
+ SetStreamValue( value, ParticleStream.Rotation);
+ }
+ }
+
+ /// <summary>
+ /// Opacity of the Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public float Opacity
+ {
+ get
+ {
+ var streamIndex = GetStreamIndex(ParticleStream.Opacity);
+ var ret = Interop.Particle.ReadFloat(mEmitterRef, (uint)streamIndex, mIndex);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+ set
+ {
+ SetStreamValue( value, ParticleStream.Opacity);
+ }
+ }
+
+ /// <summary>
+ /// Lifetime of the Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public float Lifetime
+ {
+ get
+ {
+ var streamIndex = GetStreamIndex(ParticleStream.Lifetime);
+ var ret = Interop.Particle.ReadFloat(mEmitterRef, (uint)streamIndex, mIndex);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+ set
+ {
+ SetStreamValue( value, ParticleStream.Lifetime);
+ }
+ }
+
+ /// <summary>
+ /// Initial lifetime of the Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public float LifetimeBase
+ {
+ get
+ {
+ var streamIndex = GetStreamIndex(ParticleStream.Lifetime_Base);
+ var ret = Interop.Particle.ReadFloat(mEmitterRef, (uint)streamIndex, mIndex);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+ set
+ {
+ SetStreamValue( value, ParticleStream.Lifetime_Base);
+ }
+ }
+
+ /// <summary>
+ /// Index of the Particle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal uint Index
+ {
+ get => mIndex;
+ set
+ {
+ mIndex = value;
+ }
+ }
+
+ private uint mIndex;
+ private readonly HandleRef mEmitterRef;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.ComponentModel;
+
+namespace Tizen.NUI.ParticleSystem
+{
+ using Tizen.NUI.BaseComponents;
+
+ /// <summary>
+ /// Enum defining blending options when rendering the particles.
+ /// </summary>
+ public enum ParticleBlendingMode
+ {
+ Additive = 0,
+ Screen = 1,
+ Default = Additive
+ }
+
+ /// <summary>
+ /// Internal class defining data types stored in the data streams
+ /// </summary>
+ internal enum StreamType
+ {
+ Float = 0,
+ FloatVector2 = 1,
+ FloatVector3 = 2,
+ FloatVector4 = 3,
+ Integer = 4,
+ IntVector2 = 5,
+ IntVector3 = 6,
+ IntVector4 = 7,
+ }
+
+ /// <summary>
+ /// Class ParticleEmitter creates a single emitter attached to a specified
+ /// View. ParticleEmitter is responsible for spawning and updating particles.
+ ///
+ /// Emitter must contain:
+ /// ParticleSource - responsible for spawning new particles
+ /// ParticleModifier(s) - responsible for updating particles in the system
+ ///
+ /// ParticleSource and ParticleModifier callback interfaces should not be accessing
+ /// Event side (NUI) objects. Both callbacks are executed on Update thread.
+ /// </summary>
+ public class ParticleEmitter : BaseHandle
+ {
+ internal ParticleEmitter(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
+ {
+ }
+
+ /// <summary>
+ /// Create an initialized ParticleEmitter.
+ /// </summary>
+ /// <param name="view">View to attach the particle emitter.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleEmitter(View view) : this(Interop.ParticleEmitter.New(view.SwigCPtr), true)
+ {
+ mProxy = new ParticleEmitterProxy(this);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Copy constructor.
+ /// </summary>
+ /// <param name="particleEmitter">Source object to copy.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleEmitter( ParticleEmitter particleEmitter) : this(Interop. ParticleEmitter.New( ParticleEmitter.getCPtr(particleEmitter)), true)
+ {
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Assignment operator.
+ /// </summary>
+ /// <param name="particleEmitter">Source object to be assigned.</param>
+ /// <returns>Reference to this.</returns>
+ internal ParticleEmitter Assign( ParticleEmitter particleEmitter)
+ {
+ ParticleEmitter ret = new ParticleEmitter(Interop.ParticleEmitter.Assign(SwigCPtr, ParticleEmitter.getCPtr(particleEmitter)), false);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return ret;
+ }
+
+ /// <summary>
+ /// Raises the window to the top of the window stack.
+ /// </summary>
+ /// <param name="particleEmitter">Source object to copy.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetSource<T>(ParticleSource<T> source) where T : ParticleSourceInterface, new()
+ {
+ // update interface
+ source.SetEmitter(this);
+
+ // Set native source
+ Interop.ParticleEmitter.SetSource(SwigCPtr, source.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Maximum particle count
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint ParticleCount
+ {
+ get
+ {
+ var value = Interop.ParticleEmitter.GetParticleCount(SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+
+ return value;
+ }
+ set
+ {
+ Interop.ParticleEmitter.SetParticleCount(SwigCPtr, value);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+ }
+
+ /// <summary>
+ /// Rate of emission per second
+ /// </summary>
+ /// <remarks>
+ /// EmissionRate defines number of particles emitted per second.
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint EmissionRate
+ {
+ get
+ {
+ var value = Interop.ParticleEmitter.GetEmissionRate(SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return value;
+ }
+ set
+ {
+ Interop.ParticleEmitter.SetEmissionRate(SwigCPtr, value);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+ }
+
+ /// <summary>
+ /// Initial particle count
+ /// </summary>
+ /// <remarks>
+ /// Initial number of particles to be emitted immediately after emitter starts. It allows
+ /// initial burst emission. By default it's set to 0.
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint InitialParticleCount
+ {
+ get
+ {
+ var value = Interop.ParticleEmitter.GetInitialParticleCount(SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return value;
+ }
+ set
+ {
+ Interop.ParticleEmitter.SetInitialParticleCount(SwigCPtr, value);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+ }
+
+ /// <summary>
+ /// Limit of active particles in the system
+ /// </summary>
+ /// <remarks>
+ /// Active particles in the system can be limited without changing <see cref="ParticleCount"/>.
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint ActiveParticleLimit
+ {
+ get{
+ var value = Interop.ParticleEmitter.GetActiveParticlesLimit(SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return value;
+ }
+ set
+ {
+ Interop.ParticleEmitter.SetActiveParticlesLimit(SwigCPtr, value);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ }
+
+ /// <summary>
+ /// Gets/sets blending mode for particle renderer
+ /// </summary>
+ /// <remarks>
+ /// Currently two blending modes are supported: Additive and Screen (advanced blending mode).
+ /// <see cref="ParticleBlendingMode"/>
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleBlendingMode RendererBlendingMode
+ {
+ get
+ {
+ var value = Interop.ParticleEmitter.GetBlendingMode(SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return (ParticleBlendingMode)value;
+ }
+ set
+ {
+ Interop.ParticleEmitter.SetBlendingMode(SwigCPtr, value);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+ }
+
+ /// <summary>
+ /// Gets/sets texture to be used by the renderer
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Texture RendererTexture
+ {
+ set
+ {
+ Interop.ParticleEmitter.SetTexture(SwigCPtr, value.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+ }
+
+ /// <summary>
+ /// Adds ParticleModifier to the stack
+ /// </summary>
+ /// <remarks>
+ /// ParticleEmitter implements a stack of modifiers which are responsible for
+ /// updating particles in the system. The stack is processed such as result of
+ /// previous modifier is an input for next modifier.
+ /// </remarks>
+ /// <param name="modifier">Valid modifier object</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void AddModifier<T>(ParticleModifier<T> modifier) where T : ParticleModifierInterface, new()
+ {
+ // update interface
+ modifier.SetEmitter(this);
+
+ Interop.ParticleEmitter.AddModifier(SwigCPtr, modifier.SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Returns associated ParticleSource object
+ /// </summary>
+ /// <returns>Valid ParticleSource object or null</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleSource<T> GetSource<T>() where T : ParticleSourceInterface, new()
+ {
+ IntPtr cPtr = Interop.ParticleEmitter.GetSource(SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ ParticleSource<T> ret = (cPtr == IntPtr.Zero) ? null : Registry.GetManagedBaseHandleFromNativePtr(cPtr) as ParticleSource<T>;
+ return ret;
+ }
+
+ /// <summary>
+ /// Returns modifier at specified index
+ /// </summary>
+ /// <param name="index">Index within modifier stack</param>
+ /// <returns>Valid ParticleModifier object or null</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleModifier<ParticleModifierInterface> GetModifierAt(uint index)
+ {
+ IntPtr cPtr = Interop.ParticleEmitter.GetModifierAt(SwigCPtr, index);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ ParticleModifier<ParticleModifierInterface> ret = (cPtr == IntPtr.Zero) ? null : Registry.GetManagedBaseHandleFromNativePtr(cPtr) as ParticleModifier<ParticleModifierInterface>;
+ return ret;
+ }
+
+ /// <summary>
+ /// Starts emission of particles.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void Start()
+ {
+ Interop.ParticleEmitter.Start(SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Stops emission of particles.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void Stop()
+ {
+ Interop.ParticleEmitter.Stop(SwigCPtr);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Adds local (not used by shader) data stream to the particle emitter
+ /// </summary>
+ /// <remarks>
+ /// Adds new stream of float type.
+ /// </remarks>
+ /// <param name="defaultValue">Default value to fill the stream with</param>
+ /// <returns>Index of newly created data stream</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public unsafe uint AddLocalStreamFloat(float defaultValue)
+ {
+ var result = Interop.ParticleEmitter.AddLocalStream(SwigCPtr, (uint)StreamType.Float, &defaultValue, sizeof(float));
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return result;
+ }
+
+ /// <summary>
+ /// Adds local (not used by shader) data stream to the particle emitter
+ /// </summary>
+ /// <remarks>
+ /// Adds new stream of Vector2 type.
+ /// </remarks>
+ /// <param name="defaultValue">Default value to fill the stream with</param>
+ /// <returns>Index of newly created data stream</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public unsafe uint AddLocalStreamVector2(Vector2 defaultValue)
+ {
+ var result = Interop.ParticleEmitter.AddLocalStream(SwigCPtr, (uint)StreamType.FloatVector2, (void*)defaultValue.SwigCPtr.Handle, sizeof(float)*2);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return result;
+ }
+
+ /// <summary>
+ /// Adds local (not used by shader) data stream to the particle emitter
+ /// </summary>
+ /// <remarks>
+ /// Adds new stream of Vector3 type.
+ /// </remarks>
+ /// <param name="defaultValue">Default value to fill the stream with</param>
+ /// <returns>Index of newly created data stream</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public unsafe uint AddLocalStreamVector3(Vector3 defaultValue)
+ {
+ var result = Interop.ParticleEmitter.AddLocalStream(SwigCPtr, (uint)StreamType.FloatVector3, (void*)defaultValue.SwigCPtr.Handle, sizeof(float)*3);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return result;
+ }
+
+ /// <summary>
+ /// Adds local (not used by shader) data stream to the particle emitter
+ /// </summary>
+ /// <remarks>
+ /// Adds new stream of Vector4 type.
+ /// </remarks>
+ /// <param name="defaultValue">Default value to fill the stream with</param>
+ /// <returns>Index of newly created data stream</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public unsafe uint AddLocalStreamVector4(Vector4 defaultValue)
+ {
+ var result = Interop.ParticleEmitter.AddLocalStream(SwigCPtr, (uint)StreamType.FloatVector4, (void*)defaultValue.SwigCPtr.Handle, sizeof(float)*4);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ return result;
+ }
+
+ // Internal proxy object to be used on the update thread
+ internal ParticleEmitterProxy EmitterProxy => mProxy;
+ private ParticleEmitterProxy mProxy = null;
+ }
+
+ /// <summary>
+ /// This class provides functionality that can be used inside the Source/Modifier callbacks.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class ParticleEmitterProxy
+ {
+ internal ParticleEmitterProxy(ParticleEmitter emitter)
+ {
+ mEmitterBasePtr = emitter.SwigCPtr.Handle;
+ mEmitter = emitter;
+ }
+
+ /// <summary>
+ /// Creates new particle
+ /// </summary>
+ /// <remarks>
+ /// Function may fail and return null if current number of particles exceeds limits of emitter.
+ /// Particle is valid only inside the callback and must not be stored and used anywhere else. Otherwise
+ /// the behaviour is undefined.
+ /// </remarks>
+ /// <param name="lifetime">Lifetime of the particle in seconds</param>
+ /// <returns>New Particle object or null</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Particle NewParticle( float lifetime )
+ {
+ var result = Interop.ParticleEmitter.NewParticle(mEmitterBasePtr, lifetime);
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ if (result >= 0)
+ {
+ // TODO: new particles should be coming form cached queue
+ return new Particle(mEmitter.SwigCPtr, (uint)result);
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Acquires list of Particles of specified length
+ /// </summary>
+ /// <remarks>
+ /// The function should be use internally only. Native side passes list of indices of particles (int[]).
+ /// Before calling the callback the indices must be marshalled and converted into the Particle objects.
+ ///
+ /// Internal Particle cache is used to speed up acquiring new Particle.
+ /// </remarks>
+ /// <param name="nativePtr">Native pointer to the list of indices (int32)</param>
+ /// <param name="count">Number of elements</param>
+ /// <returns>List of Particle objects</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal List<Particle> AcquireParticleList(IntPtr nativePtr, uint count)
+ {
+ // Populate enough particles into cache
+ while(mParticleCache.Count < count)
+ {
+ mParticleCache.Push(new Particle(mEmitter.SwigCPtr, 0));
+ }
+
+ List<Particle> retval = new List<Particle>();
+ for (var i = 0; i < count; ++i)
+ {
+ var particleIndex = Marshal.ReadInt32(nativePtr, i * 4);
+ Particle p = mParticleCache.Pop();
+ p.Index = (uint)particleIndex;
+ retval.Add(p);
+ }
+
+ return retval;
+ }
+
+ /// <summary>
+ /// Releases list of Particles back into the pool
+ /// </summary>
+ /// <remarks>
+ /// Acquired particles come from internal pool and must be returned so then they can
+ /// be recycled.
+ /// </remarks>
+ /// <param name="particles">List of particles to be returned</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal void ReleaseParticleList(List<Particle> particles)
+ {
+ // return particles back into the pull
+ for(var i = 0; i < particles.Count; ++i)
+ {
+ mParticleCache.Push(particles[i]);
+ }
+
+ // clear the list (probably not needed?)
+ particles.Clear();
+ }
+
+ /// <summary>
+ /// Adds local particle data stream of float values
+ /// </summary>
+ /// <param name="defaultValue">Default value</param>
+ /// <returns>Index of new stream</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint AddLocalStreamFloat(float defaultValue)
+ {
+ return mEmitter.AddLocalStreamFloat(defaultValue);
+ }
+
+ /// <summary>
+ /// Adds local particle data stream of Vector2 values
+ /// </summary>
+ /// <param name="defaultValue">Default value</param>
+ /// <returns>Index of new stream</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint AddLocalStreamVector2(Vector2 defaultValue)
+ {
+ return mEmitter.AddLocalStreamVector2(defaultValue);
+ }
+
+ /// <summary>
+ /// Adds local particle data stream of Vector3 values
+ /// </summary>
+ /// <param name="defaultValue">Default value</param>
+ /// <returns>Index of new stream</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint AddLocalStreamVector3(Vector3 defaultValue)
+ {
+ return mEmitter.AddLocalStreamVector3(defaultValue);
+ }
+
+ /// <summary>
+ /// Adds local particle data stream of Vector4 values
+ /// </summary>
+ /// <param name="defaultValue">Default value</param>
+ /// <returns>Index of new stream</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint AddLocalStreamVector4(Vector4 defaultValue)
+ {
+ return mEmitter.AddLocalStreamVector4(defaultValue);
+ }
+
+ // Stack of cached particles
+ private Stack<Particle> mParticleCache = new Stack<Particle>();
+
+ private IntPtr mEmitterBasePtr;
+ private ParticleEmitter mEmitter;
+
+ }
+
+ /// <summary>
+ /// Register binding Source/Modifier interface to the pointer of a native counterpart
+ /// </summary>
+ /// <typeparam name="T">Class type of objects to be stored in the register</typeparam>
+ internal class ParticleInterfaceRegister<T> where T : class
+ {
+ internal void Register(IntPtr cPtr, T iface)
+ {
+ lock (mBasePtr)
+ {
+ mBasePtr.Add(cPtr);
+ mInterfaces.Add(iface);
+ }
+ }
+
+ internal bool Remove(IntPtr cPtr)
+ {
+ lock (mBasePtr)
+ {
+ var result = mBasePtr.FindIndex(0, x => x == cPtr);
+ if (result >= 0)
+ {
+ mBasePtr.RemoveAt(result);
+ mInterfaces.RemoveAt(result);
+ }
+
+ return result >= 0;
+ }
+ }
+
+ internal bool Remove(T iface)
+ {
+ lock (mBasePtr)
+ {
+ var result = mInterfaces.FindIndex(0, x => x.Equals(iface));
+ if (result >= 0)
+ {
+ mBasePtr.RemoveAt(result);
+ mInterfaces.RemoveAt(result);
+ }
+
+ return result >= 0;
+ }
+ }
+
+ internal T Get(IntPtr cPtr)
+ {
+ var result = mBasePtr.FindIndex(0, x => x == cPtr );
+ if (result >= 0)
+ {
+ return mInterfaces[result];
+ }
+
+ return null;
+ }
+
+ private List<IntPtr> mBasePtr = new List<IntPtr>();
+ private List<T> mInterfaces = new List<T>();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System.Reflection;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Tizen.NUI.ParticleSystem
+{
+ /// <summary>
+ /// ParticleModifierInterface provides callbacks in order to define
+ /// how particles in the system should be modified
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class ParticleModifierInterface
+ {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleModifierInterface()
+ {
+ }
+
+ /// <summary>
+ /// Second constructor
+ /// </summary>
+ /// <remarks>
+ /// Second constructor should be overriden by the implementation.
+ /// It allows passing variable number of arguments for processing.
+ /// It is called immediately following the class constructor.
+ /// </remarks>
+ /// <param name="list">List of arguments</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual void Construct(params object[] list)
+ {
+ }
+
+ /// <summary>
+ /// Updates the ParticleModifier.
+ /// </summary>
+ /// <remarks>
+ /// This callback is responsible for updating particles in the system.
+ ///
+ /// This callback runs on the Update thread! It should avoid using NUI objects.
+ ///
+ /// </remarks>
+ /// <param name="emitterProxy">Proxy to the ParticleEmitter object</param>
+ /// <param name="particleList">List of particles to be updated by the modifier</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual void Update(ParticleEmitterProxy emitterProxy, List<Particle> particleList)
+ {
+ }
+
+ /// <summary>
+ /// ParticleEmitter proxy that can be accessed by the user implementation
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleEmitterProxy Emitter;
+ }
+
+
+ /// <summary>
+ /// Class represents particle modifier
+ /// </summary>
+ /// <remarks>
+ /// ParticleModifier modifies existing particles in the system.
+ /// Modifiers can be stacked (more than one can be added to the ParticleEmitter).
+ /// Output of one modifier becomes input for next modifier.
+ ///
+ /// Modifier calls into the implementation of <see cref="ParticleModifierInterface"> class.
+ ///
+ /// </remarks>
+ /// <typeparam name="T">Class of interface that derives from <see cref="ParticleModifierInterface"/></typeparam>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public partial class ParticleModifier<T> : BaseHandle where T : ParticleModifierInterface, new()
+ {
+ // static cache for modifiers (binding between native side and interfaces)
+ static ParticleInterfaceRegister<ParticleModifierInterface> gModifierInterfaceRegister = new ParticleInterfaceRegister<ParticleModifierInterface>();
+
+ /// <summary>
+ /// Destructor
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ ~ParticleModifier()
+ {
+ gModifierInterfaceRegister.Remove(mInterface);
+ }
+
+ /// <summary>
+ /// Invoker for ParticleModifierInterface.Update()
+ /// </summary>
+ /// <param name="cPtr">Native pointer of ParticleModifier base object</param>
+ /// <param name="listPtr">C-style array of integers</param>
+ /// <param name="first">First particle to be modified (now always 0)</param>
+ /// <param name="count">Number of particles to be modified</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ static void OnUpdateInvoker(IntPtr cPtr, IntPtr listPtr, uint first, uint count)
+ {
+ if (count > 0)
+ {
+ T modifier = (cPtr == IntPtr.Zero) ? null : gModifierInterfaceRegister.Get(cPtr) as T;
+ var list = modifier?.Emitter.AcquireParticleList(listPtr, count);
+ modifier?.Update(modifier.Emitter, list);
+ modifier?.Emitter.ReleaseParticleList(list);
+ }
+ }
+
+
+ internal ParticleModifier(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
+ {
+ }
+
+
+ /// <summary>
+ /// Constructor of ParticleModifier
+ /// </summary>
+ /// <remarks>
+ /// ParticleModifier is a generic type that will call back into the given ParticleModifierInterface
+ /// instance.
+ /// The instance of T (derived from ParticleModifierInterface) is created internally and own by the
+ /// ParticleModifier.
+ /// The constructor takes variable number of arguments which is processed when called ParticleModifierInterface.Construct()
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleModifier(params object[] list) : this(Interop.ParticleModifier.New(mOnUpdateInvoker, out gRefObjectPtr), true)
+ {
+ // Create interface on the C# side (no direct connection with C++)
+ mInterface = new T();
+ mInterface.Construct(list);
+
+ // Register interface using base ptr
+ gModifierInterfaceRegister.Register(gRefObjectPtr, mInterface);
+
+ // Initialise native side for this interface
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal void SetEmitter(ParticleEmitter emitter)
+ {
+ mInterface.Emitter = new ParticleEmitterProxy(emitter);
+ }
+
+ private static Interop.ParticleModifier.ParticleModifierUpdateInvokerType mOnUpdateInvoker = OnUpdateInvoker;
+ private ParticleModifierInterface mInterface = null;
+ private static IntPtr gRefObjectPtr;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.ComponentModel;
+
+namespace Tizen.NUI.ParticleSystem
+{
+ using Tizen.NUI.BaseComponents;
+
+ /// <summary>
+ /// ParticleSourceInterface provides callbacks in order to define
+ /// how new particles are emitted.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class ParticleSourceInterface
+ {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleSourceInterface()
+ {
+ }
+
+ /// <summary>
+ /// Second constructor
+ /// </summary>
+ /// <remarks>
+ /// Second constructor should be overriden by the implementation.
+ /// It allows passing variable number of arguments for processing.
+ /// It is called immediately following the class constructor.
+ /// </remarks>
+ /// <param name="list">List of arguments</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual void Construct(params object[] list)
+ {
+ }
+
+ /// <summary>
+ /// Updates the ParticleSource.
+ /// </summary>
+ /// <remarks>
+ /// This callback is responsible for spawning new particles. To spawn new particle,
+ /// emitter.NewParticle() must be call. Number of particles to emit is given as 'count'.
+ ///
+ /// This callback runs on the Update thread! It should avoid using NUI objects.
+ ///
+ /// </remarks>
+ /// <param name="emitterProxy">Proxy to the ParticleEmitter object</param>
+ /// <param name="count">Number of particles emitter expects to be spawned during call</param>
+ /// <returns>Number of spawned particles</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual uint Update(ParticleEmitterProxy emitterProxy, uint count)
+ {
+ return 0;
+ }
+
+ /// <summary>
+ /// Initializes ParticleSource
+ /// </summary>
+ /// <remarks>
+ /// This callback should be overriden in order to initialise the ParticleSource.
+ /// It is called after ParticleEmitter.SetSource() and runs on the Event thread.
+ /// It is the only place where ParticleSource may use NUI objects.
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual void Init()
+ {
+
+ }
+
+ /// <summary>
+ /// ParticleEmitter proxy that can be accessed by the user implementation
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleEmitterProxy Emitter;
+ }
+
+ /// <summary>
+ /// Class represents the particle source
+ /// </summary>
+ /// <remarks>
+ /// ParticleSource is responsible for emission of particles.
+ /// It calls the implementation of <see cref="ParticleSourceInterface"/> class.
+ /// The callback runs on update thread.
+ /// </remarks>
+ /// <typeparam name="T">Class of interface that derives from <see cref="ParticleSourceInterface"/></typeparam>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public partial class ParticleSource<T> : BaseHandle where T : ParticleSourceInterface, new()
+ {
+ // static cache for sources (binding between native side and interfaces)
+ private static ParticleInterfaceRegister<ParticleSourceInterface> gSourceInterfaceRegister = new ParticleInterfaceRegister<ParticleSourceInterface>();
+
+ /// <summary>
+ /// Destructor
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ ~ParticleSource()
+ {
+ gSourceInterfaceRegister.Remove(mInterface);
+ }
+
+ /// <summary>
+ /// Invoker for ParticleSourceInterface.Init()
+ /// </summary>
+ /// <remarks>
+ /// Function is called from the native side
+ /// </remarks>
+ /// <param name="cPtr">Native pointer of ParticleSource base object</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ static void OnInitInvoker(IntPtr cPtr)
+ {
+ // This function runs on Event thread
+ T source = gSourceInterfaceRegister.Get(cPtr) as T;
+ source?.Init();
+ }
+
+ /// <summary>
+ /// Invoker for ParticleSourceInterface.Update()
+ /// </summary>
+ /// <remarks>
+ /// Function is called from the native side
+ /// </remarks>
+ /// <param name="cPtr">Native pointer of ParticleSource base object</param>
+ /// <param name="count">Number of particles to emit</param>
+ /// <returns>Number of emitted particles</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ static uint OnUpdateInvoker(IntPtr cPtr, uint count)
+ {
+ T source = gSourceInterfaceRegister.Get(cPtr) as T;
+ var retval= source?.Update(source.Emitter, count);
+ return retval.HasValue ? retval.Value : 0;
+ }
+
+ internal ParticleSource(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
+ {
+ }
+
+ /// <summary>
+ /// Constructor of ParticleSource
+ /// </summary>
+ /// <remarks>
+ /// ParticleSource is a generic type that will call back into the given ParticleSourceInterface
+ /// instance.
+ /// The instance of T (derived from ParticleSourceInterface) is created internally and own by the
+ /// ParticleSource.
+ /// The constructor takes variable number of arguments which is processed when called ParticleSourceInterface.Construct()
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ParticleSource(params object[] list) : this(Interop.ParticleSource.New( mOnInitInvoker, mOnUpdateInvoker, out gRefObjectPtr ), true)
+ {
+ // Create interface on the C# side (no direct connection with C++)
+ mInterface = new T();
+ mInterface.Construct(list);
+
+ // Register interface using base ptr
+ gSourceInterfaceRegister.Register(gRefObjectPtr, mInterface);
+
+ // Initialise native side for this interface
+ if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+ }
+
+ /// <summary>
+ /// Returns associated source callback interface
+ /// </summary>
+ /// <returns>Source callback interface</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ private T GetCallbackInterface()
+ {
+ return mInterface as T;
+ }
+
+ /// <summary>
+ /// Returns associated source callback interface
+ /// </summary>
+ /// <returns>Source callback interface</returns>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public T Callback => GetCallbackInterface();
+
+ internal void SetEmitter(ParticleEmitter emitter)
+ {
+ mInterface.Emitter = new ParticleEmitterProxy(emitter);
+ }
+
+ // private fields
+ private static Interop.ParticleSource.ParticleSourceInitInvokerType mOnInitInvoker = OnInitInvoker;
+ private static Interop.ParticleSource.ParticleSourceUpdateInvokerType mOnUpdateInvoker = OnUpdateInvoker;
+ private ParticleSourceInterface mInterface = null;
+ private static IntPtr gRefObjectPtr;
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Tizen.NUI.ParticleSystem;
+
+namespace Tizen.NUI.ParticleSystem.Sample
+{
+ // SparkleEffectSource spawns particle from the middle of the
+ // window.
+ class SparkleEffectSource : ParticleSourceInterface
+ {
+ public override void Construct(params object[] list)
+ {
+ base.Construct(list);
+ mRadius = new Vector2(list[0] as Vector2);
+ }
+
+ public override uint Update(ParticleEmitterProxy emitterProxy, uint count)
+ {
+ if(mStreamBasePos == 0 || mStreamBaseAngle == 0) // streams must exist
+ {
+ return 0u;
+ }
+
+ while(count > 0)
+ {
+ // Create new particle (lifetime 5 seconds of each)
+ var particle = emitterProxy.NewParticle(5.0f);
+ if(particle == null)
+ {
+ return 0u;
+ }
+
+ UpdateParticle(ref particle);
+
+ count--;
+ }
+ return 0;
+ }
+
+ public override void Init()
+ {
+ // Add local stream of Vector3 type
+ mStreamBasePos = Emitter.AddLocalStreamVector3(Vector3.Zero);
+
+ // Add local stream of float type
+ mStreamBaseAngle = Emitter.AddLocalStreamFloat(0.0f);
+ }
+
+ void UpdateParticle(ref Particle p)
+ {
+ float posRadians = ((mRandom.Next() % 360) * (float)Math.PI) / 180.0f;
+ p.Position = new Vector3(mRadius.X * (float)Math.Sin(posRadians), mRadius.Y * (float)Math.Cos(posRadians), 0.0f);
+ p.SetStreamValue(p.Position, mStreamBasePos);
+ p.Color = Vector4.One;
+ p.SetStreamValue(mAngle, mStreamBaseAngle);
+ mAngle = ((mAngle+5)%360);
+ float rad = ((mRandom.Next() % 360) * (float)Math.PI) / 180.0f;
+ float speed = ((mRandom.Next() % 5) + 5);
+ p.Velocity = new Vector3((float)Math.Sin(rad) * speed, (float)Math.Cos(rad) * speed, 0);
+
+ // Random initial scale
+ float initialScale = (float)(mRandom.Next() % 32) + 32;
+ p.Scale = new Vector3(initialScale, initialScale, 1.0f);
+ }
+
+ private static float mAngle = 0;
+ private Random mRandom = new Random();
+ public uint mStreamBasePos = 0;
+ public uint mStreamBaseAngle = 0;
+ private Vector2 mRadius;
+ }
+
+ // SparkleEffectModifier spawns particle from the middle of the
+ // window.
+ class SparkleEffectModifier : ParticleModifierInterface
+ {
+ public override void Construct(params object[] list)
+ {
+ base.Construct(list);
+ mSource = list[0] as SparkleEffectSource;
+ }
+
+ public override void Update(ParticleEmitterProxy proxy, List<Particle> particles)
+ {
+ if (particles.Count == 0)
+ {
+ return;
+ }
+
+ if (mStreamBasePos == 0)
+ {
+ mStreamBasePos = mSource.mStreamBasePos;
+ }
+
+ if (mStreamBaseAngle == 0)
+ {
+ mStreamBaseAngle = mSource.mStreamBaseAngle;
+ }
+
+ if (mStreamBasePos == 0)
+ {
+ return;
+ }
+
+ for (uint i = 0; i < particles.Count; ++i)
+ {
+ var p = particles[(int)i];
+
+ float angle = p.GetStreamValue(mStreamBaseAngle);
+ Vector3 basePos = p.GetStreamValue(mStreamBaseAngle);
+ float radians = (float)((angle * Math.PI)/180.0f);
+ float lifetime = p.Lifetime;
+ Vector3 pos = p.Position;
+ var vel = p.Velocity;
+ p.Position = new Vector3(pos.X + vel.X * (float)Math.Cos(radians),pos.Y + vel.Y * (float)Math.Sin(radians),
+ pos.Z);
+
+ p.Velocity = (vel * 0.990f);
+ float normalizedTime = (lifetime / p.LifetimeBase);
+
+ var color = new Vector4( 1, 1, 1, normalizedTime);
+ p.Color = color;
+ p.Scale = new Vector3(64.0f*(normalizedTime * normalizedTime * normalizedTime * normalizedTime), 64.0f*(normalizedTime * normalizedTime * normalizedTime * normalizedTime), 1.0f);
+
+ }
+ }
+
+ private uint mStreamBasePos = 0;
+ private uint mStreamBaseAngle = 0;
+ private SparkleEffectSource mSource;
+
+ }
+
+ class ParticleSystemSample : NUIApplication
+ {
+ static string IMAGE_DIR = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "image/";
+
+ private Window mWindow;
+
+ private ParticleEmitter mEmitter;
+ private ParticleSource<SparkleEffectSource> mSource;
+ private ParticleModifier<SparkleEffectModifier> mModifier;
+
+ public void Activate()
+ {
+ mWindow = Window.Instance;
+ mWindow.BackgroundColor = Color.Black;
+
+ var view = new View();
+ view.BackgroundColor = Color.Wheat;
+ view.Size = new Size(1, 1);
+ view.PivotPoint = new Position(0, 0);
+ view.Position2D = new Position2D(mWindow.Size.Width/2, mWindow.Size.Height/2);
+ mWindow.Add(view);
+ // Attach emitter to view
+ mEmitter = new ParticleEmitter(view)
+ {
+ ParticleCount = 10000,
+ EmissionRate = 500,
+ InitialParticleCount = 0,
+ RendererBlendingMode = ParticleBlendingMode.Screen
+ };
+
+ mSource = new ParticleSource<SparkleEffectSource>(new Vector2(50, 50));
+ mModifier = new ParticleModifier<SparkleEffectModifier>(mSource.Callback);
+
+ mEmitter.SetSource(mSource);
+ mEmitter.AddModifier(mModifier);
+
+ // Load texture
+ var pixelBuffer = ImageLoader.LoadImageFromFile(IMAGE_DIR + "/blue-part2.png");
+ Texture tex = new Texture(TextureType.TEXTURE_2D, PixelFormat.RGBA8888, pixelBuffer.GetWidth(),
+ pixelBuffer.GetHeight());
+ tex.Upload(pixelBuffer.CreatePixelData());
+
+ mEmitter.RendererTexture = tex;
+ mEmitter.Start();
+ }
+
+ protected override void OnCreate()
+ {
+ // Up call to the Base class first
+ base.OnCreate();
+ Activate();
+ }
+
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread] // Forces app to use one thread to access NUI
+ static void Main(string[] args)
+ {
+ ParticleSystemSample example = new ParticleSystemSample();
+ example.Run(args);
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net6.0</TargetFramework>
+ </PropertyGroup>
+
+ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="../../src/Tizen/Tizen.csproj" />
+ <ProjectReference Include="../../src/Tizen.NUI/Tizen.NUI.csproj" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Update="res\image\*.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <PropertyGroup>
+ <NeedInjection>True</NeedInjection>
+ </PropertyGroup>
+</Project>