[NUI] Call base.Dispose(type) at derived class's Dispose.
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / ParticleSystem / ParticleSource.cs
1 /*
2  * Copyright(c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 using System;
19 using System.ComponentModel;
20
21 namespace Tizen.NUI.ParticleSystem
22 {
23     using Tizen.NUI.BaseComponents;
24
25     /// <summary>
26     /// ParticleSourceInterface provides callbacks in order to define
27     /// how new particles are emitted.
28     /// </summary>
29     [EditorBrowsable(EditorBrowsableState.Never)]
30     public class ParticleSourceInterface
31     {
32         /// <summary>
33         /// Constructor
34         /// </summary>
35         [EditorBrowsable(EditorBrowsableState.Never)]
36         public ParticleSourceInterface()
37         {
38         }
39
40         /// <summary>
41         /// Second constructor
42         /// </summary>
43         /// <remarks>
44         /// Second constructor should be overriden by the implementation.
45         /// It allows passing variable number of arguments for processing.
46         /// It is called immediately following the class constructor.
47         /// </remarks>
48         /// <param name="list">List of arguments</param>
49         [EditorBrowsable(EditorBrowsableState.Never)]
50         public virtual void Construct(params object[] list)
51         {
52         }
53
54         /// <summary>
55         /// Updates the ParticleSource.
56         /// </summary>
57         /// <remarks>
58         /// This callback is responsible for spawning new particles. To spawn new particle,
59         /// emitter.NewParticle() must be call. Number of particles to emit is given as 'count'.
60         ///
61         /// This callback runs on the Update thread! It should avoid using NUI objects.
62         /// 
63         /// </remarks>
64         /// <param name="emitterProxy">Proxy to the ParticleEmitter object</param>
65         /// <param name="count">Number of particles emitter expects to be spawned during call</param>
66         /// <returns>Number of spawned particles</returns>
67         [EditorBrowsable(EditorBrowsableState.Never)]
68         public virtual uint Update(ParticleEmitterProxy emitterProxy, uint count)
69         {
70             return 0;
71         }
72
73         /// <summary>
74         /// Initializes ParticleSource  
75         /// </summary>
76         /// <remarks>
77         /// This callback should be overriden in order to initialise the ParticleSource.
78         /// It is called after ParticleEmitter.SetSource() and runs on the Event thread.
79         /// It is the only place where ParticleSource may use NUI objects.
80         /// </remarks>
81         [EditorBrowsable(EditorBrowsableState.Never)]
82         public virtual void Init()
83         {
84             
85         }
86
87         /// <summary>
88         /// ParticleEmitter proxy that can be accessed by the user implementation
89         /// </summary>
90         [EditorBrowsable(EditorBrowsableState.Never)]
91         public ParticleEmitterProxy Emitter;
92     }
93     
94     /// <summary>
95     /// Class represents the particle source
96     /// </summary>
97     /// <remarks>
98     /// ParticleSource is responsible for emission of particles.
99     /// It calls the implementation of <see cref="ParticleSourceInterface"/> class.
100     /// The callback runs on update thread.
101     /// </remarks>
102     /// <typeparam name="T">Class of interface that derives from <see cref="ParticleSourceInterface"/></typeparam>
103     [EditorBrowsable(EditorBrowsableState.Never)]
104     public partial class ParticleSource<T> : BaseHandle where T : ParticleSourceInterface, new()
105     {
106         // static cache for sources (binding between native side and interfaces)
107         private static ParticleInterfaceRegister<ParticleSourceInterface> gSourceInterfaceRegister = new ParticleInterfaceRegister<ParticleSourceInterface>();
108
109         /// <summary>
110         /// Dispose.
111         /// </summary>
112         [EditorBrowsable(EditorBrowsableState.Never)]
113         protected override void Dispose(DisposeTypes type)
114         {
115             if (Disposed)
116             {
117                 return;
118             }
119
120             if (HasBody())
121             {
122                 gSourceInterfaceRegister.Remove(mInterface);
123             }
124             base.Dispose(type);
125         }
126         
127         /// <summary>
128         /// Invoker for ParticleSourceInterface.Init()
129         /// </summary>
130         /// <remarks>
131         /// Function is called from the native side
132         /// </remarks>
133         /// <param name="cPtr">Native pointer of ParticleSource base object</param>
134         [EditorBrowsable(EditorBrowsableState.Never)]
135         static void OnInitInvoker(IntPtr cPtr)
136         {
137             // This function runs on Event thread
138             T source = gSourceInterfaceRegister.Get(cPtr) as T;
139             source?.Init();
140         }
141         
142         /// <summary>
143         /// Invoker for ParticleSourceInterface.Update()
144         /// </summary>
145         /// <remarks>
146         /// Function is called from the native side
147         /// </remarks>
148         /// <param name="cPtr">Native pointer of ParticleSource base object</param>
149         /// <param name="count">Number of particles to emit</param>
150         /// <returns>Number of emitted particles</returns>
151         [EditorBrowsable(EditorBrowsableState.Never)]
152         static uint OnUpdateInvoker(IntPtr cPtr, uint count)
153         {
154             T source = gSourceInterfaceRegister.Get(cPtr) as T;
155             var retval= source?.Update(source.Emitter, count);
156             return retval.HasValue ? retval.Value : 0;
157         }
158         
159         internal ParticleSource(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
160         {
161         }
162
163         /// <summary>
164         /// Constructor of ParticleSource
165         /// </summary>
166         /// <remarks>
167         /// ParticleSource is a generic type that will call back into the given ParticleSourceInterface
168         /// instance.
169         /// The instance of T (derived from ParticleSourceInterface) is created internally and own by the
170         /// ParticleSource.
171         /// The constructor takes variable number of arguments which is processed when called ParticleSourceInterface.Construct()
172         /// </remarks>
173         [EditorBrowsable(EditorBrowsableState.Never)]
174         public ParticleSource(params object[] list) : this(Interop.ParticleSource.New( mOnInitInvoker, mOnUpdateInvoker, out gRefObjectPtr ), true)
175         {
176             // Create interface on the C# side (no direct connection with C++)
177             mInterface = new T();
178             mInterface.Construct(list);
179             
180             // Register interface using base ptr
181             gSourceInterfaceRegister.Register(gRefObjectPtr, mInterface);
182             
183             // Initialise native side for this interface
184             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
185         }
186         
187         /// <summary>
188         /// Returns associated source callback interface
189         /// </summary>
190         /// <returns>Source callback interface</returns>
191         [EditorBrowsable(EditorBrowsableState.Never)]
192         private T GetCallbackInterface()
193         {
194             return mInterface as T;
195         }
196
197         /// <summary>
198         /// Returns associated source callback interface
199         /// </summary>
200         /// <returns>Source callback interface</returns>
201         [EditorBrowsable(EditorBrowsableState.Never)]
202         public T Callback => GetCallbackInterface();
203
204         internal void SetEmitter(ParticleEmitter emitter)
205         {
206             mInterface.Emitter = new ParticleEmitterProxy(emitter);
207         }
208         
209         // private fields
210         private static Interop.ParticleSource.ParticleSourceInitInvokerType mOnInitInvoker = OnInitInvoker;
211         private static Interop.ParticleSource.ParticleSourceUpdateInvokerType mOnUpdateInvoker = OnUpdateInvoker;
212         private ParticleSourceInterface mInterface = null;
213         private static IntPtr gRefObjectPtr;
214     }
215 }