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 class Particle : public scene::ISceneNode 35 { 36 public: 37 Particle( 38 IGameDef* gamedef, 39 LocalPlayer *player, 40 ClientEnvironment *env, 41 const ParticleParameters &p, 42 video::ITexture *texture, 43 v2f texpos, 44 v2f texsize, 45 video::SColor color 46 ); 47 ~Particle() = default; 48 getBoundingBox()49 virtual const aabb3f &getBoundingBox() const 50 { 51 return m_box; 52 } 53 getMaterialCount()54 virtual u32 getMaterialCount() const 55 { 56 return 1; 57 } 58 getMaterial(u32 i)59 virtual video::SMaterial& getMaterial(u32 i) 60 { 61 return m_material; 62 } 63 64 virtual void OnRegisterSceneNode(); 65 virtual void render(); 66 67 void step(float dtime); 68 get_expired()69 bool get_expired () 70 { return m_expiration < m_time; } 71 72 private: 73 void updateLight(); 74 void updateVertices(); 75 76 video::S3DVertex m_vertices[4]; 77 float m_time = 0.0f; 78 float m_expiration; 79 80 ClientEnvironment *m_env; 81 IGameDef *m_gamedef; 82 aabb3f m_box; 83 aabb3f m_collisionbox; 84 video::SMaterial m_material; 85 v2f m_texpos; 86 v2f m_texsize; 87 v3f m_pos; 88 v3f m_velocity; 89 v3f m_acceleration; 90 LocalPlayer *m_player; 91 float m_size; 92 //! Color without lighting 93 video::SColor m_base_color; 94 //! Final rendered color 95 video::SColor m_color; 96 bool m_collisiondetection; 97 bool m_collision_removal; 98 bool m_object_collision; 99 bool m_vertical; 100 v3s16 m_camera_offset; 101 struct TileAnimationParams m_animation; 102 float m_animation_time = 0.0f; 103 int m_animation_frame = 0; 104 u8 m_glow; 105 }; 106 107 class ParticleSpawner 108 { 109 public: 110 ParticleSpawner(IGameDef* gamedef, 111 LocalPlayer *player, 112 const ParticleSpawnerParameters &p, 113 u16 attached_id, 114 video::ITexture *texture, 115 ParticleManager* p_manager); 116 117 ~ParticleSpawner() = default; 118 119 void step(float dtime, ClientEnvironment *env); 120 get_expired()121 bool get_expired () 122 { return p.amount <= 0 && p.time != 0; } 123 124 private: 125 void spawnParticle(ClientEnvironment *env, float radius, 126 const core::matrix4 *attached_absolute_pos_rot_matrix); 127 128 ParticleManager *m_particlemanager; 129 float m_time; 130 IGameDef *m_gamedef; 131 LocalPlayer *m_player; 132 ParticleSpawnerParameters p; 133 video::ITexture *m_texture; 134 std::vector<float> m_spawntimes; 135 u16 m_attached_id; 136 }; 137 138 /** 139 * Class doing particle as well as their spawners handling 140 */ 141 class ParticleManager 142 { 143 friend class ParticleSpawner; 144 public: 145 ParticleManager(ClientEnvironment* env); 146 ~ParticleManager(); 147 148 void step (float dtime); 149 150 void handleParticleEvent(ClientEvent *event, Client *client, 151 LocalPlayer *player); 152 153 void addDiggingParticles(IGameDef *gamedef, LocalPlayer *player, v3s16 pos, 154 const MapNode &n, const ContentFeatures &f); 155 156 void addNodeParticle(IGameDef *gamedef, LocalPlayer *player, v3s16 pos, 157 const MapNode &n, const ContentFeatures &f); 158 159 /** 160 * This function is only used by client particle spawners 161 * 162 * We don't need to check the particle spawner list because client ID will 163 * never overlap (u64) 164 * @return new id 165 */ generateSpawnerId()166 u64 generateSpawnerId() 167 { 168 return m_next_particle_spawner_id++; 169 } 170 171 protected: 172 static bool getNodeParticleParams(const MapNode &n, const ContentFeatures &f, 173 ParticleParameters &p, video::ITexture **texture, v2f &texpos, 174 v2f &texsize, video::SColor *color, u8 tilenum = 0); 175 176 void addParticle(Particle* toadd); 177 178 private: 179 void addParticleSpawner(u64 id, ParticleSpawner *toadd); 180 void deleteParticleSpawner(u64 id); 181 182 void stepParticles(float dtime); 183 void stepSpawners(float dtime); 184 185 void clearAll(); 186 187 std::vector<Particle*> m_particles; 188 std::unordered_map<u64, ParticleSpawner*> m_particle_spawners; 189 // Start the particle spawner ids generated from here after u32_max. lower values are 190 // for server sent spawners. 191 u64 m_next_particle_spawner_id = U32_MAX + 1; 192 193 ClientEnvironment* m_env; 194 std::mutex m_particle_list_lock; 195 std::mutex m_spawner_list_lock; 196 }; 197