Added configurable selectionbox width. Min width = 1, Max = 5
[oweals/minetest.git] / src / particles.cpp
index 1d814f6191513676f76af074f93d82cb947c3d2e..5a3056c324dc1242815b4a9e0030a8c1479c2378 100644 (file)
@@ -57,12 +57,16 @@ Particle::Particle(
        float expirationtime,
        float size,
        bool collisiondetection,
        float expirationtime,
        float size,
        bool collisiondetection,
-       AtlasPointer ap
+       bool vertical,
+       video::ITexture *texture,
+       v2f texpos,
+       v2f texsize
 ):
        scene::ISceneNode(smgr->getRootSceneNode(), smgr)
 {
        // Misc
        m_gamedef = gamedef;
 ):
        scene::ISceneNode(smgr->getRootSceneNode(), smgr)
 {
        // Misc
        m_gamedef = gamedef;
+       m_env = &env;
 
        // Texture
        m_material.setFlag(video::EMF_LIGHTING, false);
 
        // Texture
        m_material.setFlag(video::EMF_LIGHTING, false);
@@ -70,8 +74,9 @@ Particle::Particle(
        m_material.setFlag(video::EMF_BILINEAR_FILTER, false);
        m_material.setFlag(video::EMF_FOG_ENABLE, true);
        m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
        m_material.setFlag(video::EMF_BILINEAR_FILTER, false);
        m_material.setFlag(video::EMF_FOG_ENABLE, true);
        m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
-       m_material.setTexture(0, ap.atlas);
-       m_ap = ap;
+       m_material.setTexture(0, texture);
+       m_texpos = texpos;
+       m_texsize = texsize;
 
 
        // Particle related
 
 
        // Particle related
@@ -83,6 +88,7 @@ Particle::Particle(
        m_player = player;
        m_size = size;
        m_collisiondetection = collisiondetection;
        m_player = player;
        m_size = size;
        m_collisiondetection = collisiondetection;
+       m_vertical = vertical;
 
        // Irrlicht stuff
        m_collisionbox = core::aabbox3d<f32>
 
        // Irrlicht stuff
        m_collisionbox = core::aabbox3d<f32>
@@ -90,7 +96,7 @@ Particle::Particle(
        this->setAutomaticCulling(scene::EAC_OFF);
 
        // Init lighting
        this->setAutomaticCulling(scene::EAC_OFF);
 
        // Init lighting
-       updateLight(env);
+       updateLight();
 
        // Init model
        updateVertices();
 
        // Init model
        updateVertices();
@@ -129,7 +135,7 @@ void Particle::render()
                        scene::EPT_TRIANGLES, video::EIT_16BIT);
 }
 
                        scene::EPT_TRIANGLES, video::EIT_16BIT);
 }
 
-void Particle::step(float dtime, ClientEnvironment &env)
+void Particle::step(float dtime)
 {
        m_time += dtime;
        if (m_collisiondetection)
 {
        m_time += dtime;
        if (m_collisiondetection)
@@ -138,7 +144,7 @@ void Particle::step(float dtime, ClientEnvironment &env)
                v3f p_pos = m_pos*BS;
                v3f p_velocity = m_velocity*BS;
                v3f p_acceleration = m_acceleration*BS;
                v3f p_pos = m_pos*BS;
                v3f p_velocity = m_velocity*BS;
                v3f p_acceleration = m_acceleration*BS;
-               collisionMoveSimple(&env, m_gamedef,
+               collisionMoveSimple(m_env, m_gamedef,
                        BS*0.5, box,
                        0, dtime,
                        p_pos, p_velocity, p_acceleration);
                        BS*0.5, box,
                        0, dtime,
                        p_pos, p_velocity, p_acceleration);
@@ -153,13 +159,13 @@ void Particle::step(float dtime, ClientEnvironment &env)
        }
 
        // Update lighting
        }
 
        // Update lighting
-       updateLight(env);
+       updateLight();
 
        // Update model
        updateVertices();
 }
 
 
        // Update model
        updateVertices();
 }
 
-void Particle::updateLight(ClientEnvironment &env)
+void Particle::updateLight()
 {
        u8 light = 0;
        try{
 {
        u8 light = 0;
        try{
@@ -168,11 +174,11 @@ void Particle::updateLight(ClientEnvironment &env)
                        floor(m_pos.Y+0.5),
                        floor(m_pos.Z+0.5)
                );
                        floor(m_pos.Y+0.5),
                        floor(m_pos.Z+0.5)
                );
-               MapNode n = env.getClientMap().getNode(p);
-               light = n.getLightBlend(env.getDayNightRatio(), m_gamedef->ndef());
+               MapNode n = m_env->getClientMap().getNode(p);
+               light = n.getLightBlend(m_env->getDayNightRatio(), m_gamedef->ndef());
        }
        catch(InvalidPositionException &e){
        }
        catch(InvalidPositionException &e){
-               light = blend_light(env.getDayNightRatio(), LIGHT_SUN, 0);
+               light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0);
        }
        m_light = decode_light(light);
 }
        }
        m_light = decode_light(light);
 }
@@ -180,31 +186,41 @@ void Particle::updateLight(ClientEnvironment &env)
 void Particle::updateVertices()
 {
        video::SColor c(255, m_light, m_light, m_light);
 void Particle::updateVertices()
 {
        video::SColor c(255, m_light, m_light, m_light);
+       f32 tx0 = m_texpos.X;
+       f32 tx1 = m_texpos.X + m_texsize.X;
+       f32 ty0 = m_texpos.Y;
+       f32 ty1 = m_texpos.Y + m_texsize.Y;
+
        m_vertices[0] = video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0,
        m_vertices[0] = video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0,
-                       c, m_ap.x0(), m_ap.y1());
+                       c, tx0, ty1);
        m_vertices[1] = video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0,
        m_vertices[1] = video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0,
-                       c, m_ap.x1(), m_ap.y1());
+                       c, tx1, ty1);
        m_vertices[2] = video::S3DVertex(m_size/2,m_size/2,0, 0,0,0,
        m_vertices[2] = video::S3DVertex(m_size/2,m_size/2,0, 0,0,0,
-                       c, m_ap.x1(), m_ap.y0());
+                       c, tx1, ty0);
        m_vertices[3] = video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0,
        m_vertices[3] = video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0,
-                       c ,m_ap.x0(), m_ap.y0());
+                       c, tx0, ty0);
 
 
+       v3s16 camera_offset = m_env->getCameraOffset();
        for(u16 i=0; i<4; i++)
        {
        for(u16 i=0; i<4; i++)
        {
-               m_vertices[i].Pos.rotateYZBy(m_player->getPitch());
-               m_vertices[i].Pos.rotateXZBy(m_player->getYaw());
+               if (m_vertical) {
+                       v3f ppos = m_player->getPosition()/BS;
+                       m_vertices[i].Pos.rotateXZBy(atan2(ppos.Z-m_pos.Z, ppos.X-m_pos.X)/core::DEGTORAD+90);
+               } else {
+                       m_vertices[i].Pos.rotateYZBy(m_player->getPitch());
+                       m_vertices[i].Pos.rotateXZBy(m_player->getYaw());
+               }
                m_box.addInternalPoint(m_vertices[i].Pos);
                m_box.addInternalPoint(m_vertices[i].Pos);
-               m_vertices[i].Pos += m_pos*BS;
+               m_vertices[i].Pos += m_pos*BS - intToFloat(camera_offset, BS);
        }
 }
 
        }
 }
 
-
 /*
        Helpers
 */
 
 
 /*
        Helpers
 */
 
 
-void allparticles_step (float dtime, ClientEnvironment &env)
+void allparticles_step (float dtime)
 {
        for(std::vector<Particle*>::iterator i = all_particles.begin();
                        i != all_particles.end();)
 {
        for(std::vector<Particle*>::iterator i = all_particles.begin();
                        i != all_particles.end();)
@@ -213,11 +229,11 @@ void allparticles_step (float dtime, ClientEnvironment &env)
                {
                        (*i)->remove();
                        delete *i;
                {
                        (*i)->remove();
                        delete *i;
-                       all_particles.erase(i);
+                       i = all_particles.erase(i);
                }
                else
                {
                }
                else
                {
-                       (*i)->step(dtime, env);
+                       (*i)->step(dtime);
                        i++;
                }
        }
                        i++;
                }
        }
@@ -248,19 +264,19 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
 {
        // Texture
        u8 texid = myrand_range(0,5);
 {
        // Texture
        u8 texid = myrand_range(0,5);
-       AtlasPointer ap = tiles[texid].texture;
-       float size = rand()%64/512.;
-       float visual_size = BS*size;
-       float texsize = size*2;
+       video::ITexture *texture = tiles[texid].texture;
 
 
-       float x1 = ap.x1();
-       float y1 = ap.y1();
+       // Only use first frame of animated texture
+       f32 ymax = 1;
+       if(tiles[texid].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
+               ymax /= tiles[texid].animation_frame_count;
 
 
-       ap.size.X = (ap.x1() - ap.x0()) * texsize;
-       ap.size.Y = (ap.x1() - ap.x0()) * texsize;
-
-       ap.pos.X = ap.x0() + (x1 - ap.x0()) * ((rand()%64)/64.-texsize);
-       ap.pos.Y = ap.y0() + (y1 - ap.y0()) * ((rand()%64)/64.-texsize);
+       float size = rand()%64/512.;
+       float visual_size = BS*size;
+       v2f texsize(size*2, ymax*size*2);
+       v2f texpos;
+       texpos.X = ((rand()%64)/64.-texsize.X);
+       texpos.Y = ymax*((rand()%64)/64.-texsize.Y);
 
        // Physics
        v3f velocity(   (rand()%100/50.-1)/1.5,
 
        // Physics
        v3f velocity(   (rand()%100/50.-1)/1.5,
@@ -285,7 +301,10 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
                rand()%100/100., // expiration time
                visual_size,
                true,
                rand()%100/100., // expiration time
                visual_size,
                true,
-               ap);
+               false,
+               texture,
+               texpos,
+               texsize);
 }
 
 /*
 }
 
 /*
@@ -296,7 +315,7 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
        u16 amount, float time,
        v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
        float minexptime, float maxexptime, float minsize, float maxsize,
        u16 amount, float time,
        v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
        float minexptime, float maxexptime, float minsize, float maxsize,
-       bool collisiondetection, AtlasPointer ap, u32 id)
+       bool collisiondetection, bool vertical, video::ITexture *texture, u32 id)
 {
        m_gamedef = gamedef;
        m_smgr = smgr;
 {
        m_gamedef = gamedef;
        m_smgr = smgr;
@@ -314,7 +333,8 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
        m_minsize = minsize;
        m_maxsize = maxsize;
        m_collisiondetection = collisiondetection;
        m_minsize = minsize;
        m_maxsize = maxsize;
        m_collisiondetection = collisiondetection;
-       m_ap = ap;
+       m_vertical = vertical;
+       m_texture = texture;
        m_time = 0;
 
        for (u16 i = 0; i<=m_amount; i++)
        m_time = 0;
 
        for (u16 i = 0; i<=m_amount; i++)
@@ -362,8 +382,11 @@ void ParticleSpawner::step(float dtime, ClientEnvironment &env)
                                        exptime,
                                        size,
                                        m_collisiondetection,
                                        exptime,
                                        size,
                                        m_collisiondetection,
-                                       m_ap);
-                               m_spawntimes.erase(i);
+                                       m_vertical,
+                                       m_texture,
+                                       v2f(0.0, 0.0),
+                                       v2f(1.0, 1.0));
+                               i = m_spawntimes.erase(i);
                        }
                        else
                        {
                        }
                        else
                        {
@@ -398,7 +421,10 @@ void ParticleSpawner::step(float dtime, ClientEnvironment &env)
                                        exptime,
                                        size,
                                        m_collisiondetection,
                                        exptime,
                                        size,
                                        m_collisiondetection,
-                                       m_ap);
+                                       m_vertical,
+                                       m_texture,
+                                       v2f(0.0, 0.0),
+                                       v2f(1.0, 1.0));
                        }
                }
        }
                        }
                }
        }
@@ -448,6 +474,6 @@ void clear_particles ()
        {
                (*i)->remove();
                delete *i;
        {
                (*i)->remove();
                delete *i;
-               all_particles.erase(i);
-       }       
+               i = all_particles.erase(i);
+       }
 }
 }