]> git.lizzy.rs Git - minetest.git/blob - src/client/particles.h
Add keybind to swap items between hands
[minetest.git] / src / client / particles.h
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #pragma once
21
22 #include <iostream>
23 #include "irrlichttypes_extrabloated.h"
24 #include "client/tile.h"
25 #include "localplayer.h"
26 #include "../particles.h"
27
28 struct ClientEvent;
29 class ParticleManager;
30 class ClientEnvironment;
31 struct MapNode;
32 struct ContentFeatures;
33
34 struct ClientTexture
35 {
36         /* per-spawner structure used to store the ParticleTexture structs
37          * that spawned particles will refer to through ClientTexRef */
38         ParticleTexture tex;
39         video::ITexture *ref = nullptr;
40
41         ClientTexture() = default;
42         ClientTexture(const ServerParticleTexture& p, ITextureSource *t):
43                         tex(p),
44                         ref(t->getTextureForMesh(p.string)) {};
45 };
46
47 struct ClientTexRef
48 {
49         /* per-particle structure used to avoid massively duplicating the
50          * fairly large ParticleTexture struct */
51         ParticleTexture* tex = nullptr;
52         video::ITexture* ref = nullptr;
53         ClientTexRef() = default;
54
55         /* constructor used by particles spawned from a spawner */
56         ClientTexRef(ClientTexture& t):
57                         tex(&t.tex), ref(t.ref) {};
58
59         /* constructor used for node particles */
60         ClientTexRef(decltype(ref) tp): ref(tp) {};
61 };
62
63 class ParticleSpawner;
64
65 class Particle : public scene::ISceneNode
66 {
67 public:
68         Particle(
69                 IGameDef *gamedef,
70                 LocalPlayer *player,
71                 ClientEnvironment *env,
72                 const ParticleParameters &p,
73                 const ClientTexRef &texture,
74                 v2f texpos,
75                 v2f texsize,
76                 video::SColor color
77         );
78         ~Particle();
79
80         virtual const aabb3f &getBoundingBox() const
81         {
82                 return m_box;
83         }
84
85         virtual u32 getMaterialCount() const
86         {
87                 return 1;
88         }
89
90         virtual video::SMaterial& getMaterial(u32 i)
91         {
92                 return m_material;
93         }
94
95         virtual void OnRegisterSceneNode();
96         virtual void render();
97
98         void step(float dtime);
99
100         bool get_expired ()
101         { return m_expiration < m_time; }
102
103         ParticleSpawner *m_parent;
104
105 private:
106         void updateLight();
107         void updateVertices();
108         void setVertexAlpha(float a);
109
110         video::S3DVertex m_vertices[4];
111         float m_time = 0.0f;
112         float m_expiration;
113
114         ClientEnvironment *m_env;
115         IGameDef *m_gamedef;
116         aabb3f m_box;
117         aabb3f m_collisionbox;
118         ClientTexRef m_texture;
119         video::SMaterial m_material;
120         v2f m_texpos;
121         v2f m_texsize;
122         v3f m_pos;
123         v3f m_velocity;
124         v3f m_acceleration;
125         v3f m_drag;
126         ParticleParamTypes::v3fRange m_jitter;
127         ParticleParamTypes::f32Range m_bounce;
128         LocalPlayer *m_player;
129         float m_size;
130
131         //! Color without lighting
132         video::SColor m_base_color;
133         //! Final rendered color
134         video::SColor m_color;
135         bool m_collisiondetection;
136         bool m_collision_removal;
137         bool m_object_collision;
138         bool m_vertical;
139         v3s16 m_camera_offset;
140         struct TileAnimationParams m_animation;
141         float m_animation_time = 0.0f;
142         int m_animation_frame = 0;
143         u8 m_glow;
144         float m_alpha = 0.0f;
145 };
146
147 class ParticleSpawner
148 {
149 public:
150         ParticleSpawner(IGameDef *gamedef,
151                 LocalPlayer *player,
152                 const ParticleSpawnerParameters &p,
153                 u16 attached_id,
154                 std::unique_ptr<ClientTexture[]> &texpool,
155                 size_t texcount,
156                 ParticleManager* p_manager);
157
158         void step(float dtime, ClientEnvironment *env);
159
160         size_t m_active;
161
162         bool getExpired() const
163         { return m_dying || (p.amount <= 0 && p.time != 0); }
164         void setDying() { m_dying = true; }
165
166 private:
167         void spawnParticle(ClientEnvironment *env, float radius,
168                 const core::matrix4 *attached_absolute_pos_rot_matrix);
169
170         ParticleManager *m_particlemanager;
171         float m_time;
172         bool m_dying;
173         IGameDef *m_gamedef;
174         LocalPlayer *m_player;
175         ParticleSpawnerParameters p;
176         std::unique_ptr<ClientTexture[]> m_texpool;
177         size_t m_texcount;
178         std::vector<float> m_spawntimes;
179         u16 m_attached_id;
180 };
181
182 /**
183  * Class doing particle as well as their spawners handling
184  */
185 class ParticleManager
186 {
187 friend class ParticleSpawner;
188 public:
189         ParticleManager(ClientEnvironment* env);
190         ~ParticleManager();
191
192         void step (float dtime);
193
194         void handleParticleEvent(ClientEvent *event, Client *client,
195                         LocalPlayer *player);
196
197         void addDiggingParticles(IGameDef *gamedef, LocalPlayer *player, v3s16 pos,
198                 const MapNode &n, const ContentFeatures &f);
199
200         void addNodeParticle(IGameDef *gamedef, LocalPlayer *player, v3s16 pos,
201                 const MapNode &n, const ContentFeatures &f);
202
203         void reserveParticleSpace(size_t max_estimate);
204
205         /**
206          * This function is only used by client particle spawners
207          *
208          * We don't need to check the particle spawner list because client ID will
209          * never overlap (u64)
210          * @return new id
211          */
212         u64 generateSpawnerId()
213         {
214                 return m_next_particle_spawner_id++;
215         }
216
217 protected:
218         static bool getNodeParticleParams(const MapNode &n, const ContentFeatures &f,
219                 ParticleParameters &p, video::ITexture **texture, v2f &texpos,
220                 v2f &texsize, video::SColor *color, u8 tilenum = 0);
221
222         void addParticle(Particle* toadd);
223
224 private:
225         void addParticleSpawner(u64 id, ParticleSpawner *toadd);
226         void deleteParticleSpawner(u64 id);
227
228         void stepParticles(float dtime);
229         void stepSpawners(float dtime);
230
231         void clearAll();
232
233         std::vector<Particle*> m_particles;
234         std::unordered_map<u64, ParticleSpawner*> m_particle_spawners;
235         // Start the particle spawner ids generated from here after u32_max. lower values are
236         // for server sent spawners.
237         u64 m_next_particle_spawner_id = U32_MAX + 1;
238
239         ClientEnvironment* m_env;
240         std::mutex m_particle_list_lock;
241         std::mutex m_spawner_list_lock;
242 };