Send KEY_END when (re)creating a text input
[oweals/minetest.git] / src / mapblockobject.cpp
index 779fe3fa71d0257c208c20d00082f880039e4259..071a14b0cdb3b497d586f057fb6a1503377b0f20 100644 (file)
@@ -17,10 +17,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
+// This file contains the DEPRECATED MapBlockObject system
+
 #include "mapblockobject.h"
 #include "mapblock.h"
-// Only for ::getNodeBox, TODO: Get rid of this
+// For object wrapping
 #include "map.h"
+#include "inventory.h"
+#include "utility.h"
+#include "mapblock.h"
 
 /*
        MapBlockObject
@@ -33,7 +38,7 @@ v3f MapBlockObject::getAbsolutePos()
                return m_pos;
        
        // getPosRelative gets nodepos relative to map origin
-       v3f blockpos = intToFloat(m_block->getPosRelative());
+       v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
        return blockpos + m_pos;
 }
 
@@ -53,13 +58,13 @@ v3f MovingObject::getAbsoluteShowPos()
                return m_pos;
        
        // getPosRelative gets nodepos relative to map origin
-       v3f blockpos = intToFloat(m_block->getPosRelative());
+       v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
        return blockpos + m_showpos;
 }
 
 void MovingObject::move(float dtime, v3f acceleration)
 {
-       DSTACK("%s: typeid=%i, pos=(%f,%f,%f), speed=(%f,%f,%f)"
+       DSTACKF("%s: typeid=%i, pos=(%f,%f,%f), speed=(%f,%f,%f)"
                        ", dtime=%f, acc=(%f,%f,%f)",
                        __FUNCTION_NAME,
                        getTypeId(),
@@ -69,7 +74,7 @@ void MovingObject::move(float dtime, v3f acceleration)
                        acceleration.X, acceleration.Y, acceleration.Z
                        );
        
-       v3s16 oldpos_i = floatToInt(m_pos);
+       v3s16 oldpos_i = floatToInt(m_pos, BS);
        
        if(m_block->isValidPosition(oldpos_i) == false)
        {
@@ -135,7 +140,7 @@ void MovingObject::move(float dtime, v3f acceleration)
                        Collision detection
                */
                
-               v3s16 pos_i = floatToInt(position);
+               v3s16 pos_i = floatToInt(position, BS);
                
                // The loop length is limited to the object moving a distance
                f32 d = (float)BS * 0.15;
@@ -156,8 +161,8 @@ void MovingObject::move(float dtime, v3f acceleration)
                for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
                {
                        try{
-                               if(content_walkable(m_block->getNodeParent(v3s16(x,y,z)).d)
-                                               == false)
+                               MapNode n = m_block->getNodeParent(v3s16(x,y,z));
+                               if(content_features(n).walkable == false)
                                        continue;
                        }
                        catch(InvalidPositionException &e)
@@ -166,8 +171,7 @@ void MovingObject::move(float dtime, v3f acceleration)
                                // walking over map borders
                        }
 
-                       core::aabbox3d<f32> nodebox = Map::getNodeBox(
-                                       v3s16(x,y,z));
+                       core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
                        
                        // See if the object is touching ground
                        if(
@@ -280,8 +284,9 @@ void RatObject::addToScene(scene::ISceneManager *smgr)
        buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
        buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
        buf->getMaterial().setTexture
-                       (0, driver->getTexture("../data/rat.png"));
+                       (0, driver->getTexture(getTexturePath("rat.png").c_str()));
        buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
+       buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
        buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
        // Add to mesh
        mesh->addMeshBuffer(buf);
@@ -292,6 +297,162 @@ void RatObject::addToScene(scene::ISceneManager *smgr)
 }
 #endif
 
+/*
+       ItemObject
+*/
+#ifndef SERVER
+void ItemObject::addToScene(scene::ISceneManager *smgr)
+{
+       if(m_node != NULL)
+               return;
+       
+       //video::IVideoDriver* driver = smgr->getVideoDriver();
+       
+       // Get image of item for showing
+       video::ITexture *texture = getItemImage();
+
+       /*
+               Create a mesh
+       */
+
+       scene::SMesh *mesh = new scene::SMesh();
+       {
+       scene::IMeshBuffer *buf = new scene::SMeshBuffer();
+       video::SColor c(255,255,255,255);
+       video::S3DVertex vertices[4] =
+       {
+               /*video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
+               video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
+               video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
+               video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),*/
+               video::S3DVertex(BS/3,-BS/2,0, 0,0,0, c, 0,1),
+               video::S3DVertex(-BS/3,-BS/2,0, 0,0,0, c, 1,1),
+               video::S3DVertex(-BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 1,0),
+               video::S3DVertex(BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 0,0),
+       };
+       u16 indices[] = {0,1,2,2,3,0};
+       buf->append(vertices, 4, indices, 6);
+       // Set material
+       buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
+       buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
+       buf->getMaterial().setTexture(0, texture);
+       buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
+       buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
+       buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+       // Add to mesh
+       mesh->addMeshBuffer(buf);
+       buf->drop();
+       }
+       m_node = smgr->addMeshSceneNode(mesh, NULL);
+       // Set it to use the materials of the meshbuffers directly.
+       // This is needed for changing the texture in the future
+       ((scene::IMeshSceneNode*)m_node)->setReadOnlyMaterials(true);
+       mesh->drop();
+
+       updateSceneNode();
+}
+
+video::ITexture * ItemObject::getItemImage()
+{
+       /*
+               Create an inventory item to see what is its image
+       */
+       video::ITexture *texture = NULL;
+       InventoryItem *item = createInventoryItem();
+       if(item)
+               texture = item->getImage();
+       if(item)
+               delete item;
+       return texture;
+}
+
+#endif
+
+InventoryItem * ItemObject::createInventoryItem()
+{
+       try{
+               std::istringstream is(m_itemstring, std::ios_base::binary);
+               InventoryItem *item = InventoryItem::deSerialize(is);
+               dstream<<__FUNCTION_NAME<<": m_itemstring=\""
+                               <<m_itemstring<<"\" -> item="<<item
+                               <<std::endl;
+               return item;
+       }
+       catch(SerializationError &e)
+       {
+               dstream<<__FUNCTION_NAME<<": serialization error: "
+                               <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
+               return NULL;
+       }
+}
+
+/*
+       PlayerObject
+*/
+#ifndef SERVER
+void PlayerObject::addToScene(scene::ISceneManager *smgr)
+{
+       if(m_node != NULL)
+               return;
+       
+       video::IVideoDriver* driver = smgr->getVideoDriver();
+
+       // Attach a simple mesh to the player for showing an image
+       scene::SMesh *mesh = new scene::SMesh();
+       { // Front
+       scene::IMeshBuffer *buf = new scene::SMeshBuffer();
+       video::SColor c(255,255,255,255);
+       video::S3DVertex vertices[4] =
+       {
+               video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
+               video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
+               video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
+               video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
+       };
+       u16 indices[] = {0,1,2,2,3,0};
+       buf->append(vertices, 4, indices, 6);
+       // Set material
+       buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
+       //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
+       buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str()));
+       buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
+       buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
+       //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
+       buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+       // Add to mesh
+       mesh->addMeshBuffer(buf);
+       buf->drop();
+       }
+       { // Back
+       scene::IMeshBuffer *buf = new scene::SMeshBuffer();
+       video::SColor c(255,255,255,255);
+       video::S3DVertex vertices[4] =
+       {
+               video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
+               video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
+               video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
+               video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
+       };
+       u16 indices[] = {0,1,2,2,3,0};
+       buf->append(vertices, 4, indices, 6);
+       // Set material
+       buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
+       //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
+       buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str()));
+       buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
+       buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
+       buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+       // Add to mesh
+       mesh->addMeshBuffer(buf);
+       buf->drop();
+       }
+       
+       m_node = smgr->addMeshSceneNode(mesh, NULL);
+       mesh->drop();
+       updateNodePos();
+}
+#endif
+
 /*
        MapBlockObjectList
 */
@@ -412,6 +573,10 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
                        {
                                obj = new RatObject(m_block, id, pos);
                        }
+                       else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM)
+                       {
+                               obj = new ItemObject(m_block, id, pos);
+                       }
                        else
                        {
                                // This is fatal because we cannot know the length
@@ -449,7 +614,7 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
                {
                        u8 light = LIGHT_MAX;
                        try{
-                               v3s16 relpos_i = floatToInt(obj->m_pos);
+                               v3s16 relpos_i = floatToInt(obj->m_pos, BS);
                                MapNode n = m_block->getNodeParent(relpos_i);
                                light = n.getLightBlend(daynight_ratio);
                        }
@@ -591,7 +756,7 @@ void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
        core::map<s16, bool> ids_to_delete;
 
        {
-               DSTACK("%s: stepping objects", __FUNCTION_NAME);
+               DSTACKF("%s: stepping objects", __FUNCTION_NAME);
 
                for(core::map<s16, MapBlockObject*>::Iterator
                                i = m_objects.getIterator();
@@ -599,7 +764,7 @@ void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
                {
                        MapBlockObject *obj = i.getNode()->getValue();
                        
-                       DSTACK("%s: stepping object type %i", __FUNCTION_NAME,
+                       DSTACKF("%s: stepping object type %i", __FUNCTION_NAME,
                                        obj->getTypeId());
 
                        if(server)
@@ -607,7 +772,7 @@ void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
                                // Update light
                                u8 light = LIGHT_MAX;
                                try{
-                                       v3s16 relpos_i = floatToInt(obj->m_pos);
+                                       v3s16 relpos_i = floatToInt(obj->m_pos, BS);
                                        MapNode n = m_block->getNodeParent(relpos_i);
                                        light = n.getLightBlend(daynight_ratio);
                                }
@@ -627,7 +792,7 @@ void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
        }
 
        {
-               DSTACK("%s: deleting objects", __FUNCTION_NAME);
+               DSTACKF("%s: deleting objects", __FUNCTION_NAME);
 
                // Delete objects in delete queue
                for(core::map<s16, bool>::Iterator
@@ -651,7 +816,7 @@ void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
                return;
        
        {
-               DSTACK("%s: object wrap loop", __FUNCTION_NAME);
+               DSTACKF("%s: object wrap loop", __FUNCTION_NAME);
 
                for(core::map<s16, MapBlockObject*>::Iterator
                                i = m_objects.getIterator();
@@ -659,7 +824,7 @@ void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
                {
                        MapBlockObject *obj = i.getNode()->getValue();
 
-                       v3s16 pos_i = floatToInt(obj->m_pos);
+                       v3s16 pos_i = floatToInt(obj->m_pos, BS);
 
                        if(m_block->isValidPosition(pos_i))
                        {
@@ -692,21 +857,12 @@ bool MapBlockObjectList::wrapObject(MapBlockObject *object)
        assert(m_objects.find(object->m_id) != NULL);
        assert(m_objects[object->m_id] == object);
 
-       NodeContainer *parentcontainer = m_block->getParent();
-       // This will only work if the parent is the map
-       if(parentcontainer->nodeContainerId() != NODECONTAINER_ID_MAP)
-       {
-               dstream<<"WARNING: Wrapping object not possible: "
-                               "MapBlock's parent is not map"<<std::endl;
-               return true;
-       }
-       // OK, we have the map!
-       Map *map = (Map*)parentcontainer;
+       Map *map = m_block->getParent();
        
        // Calculate blockpos on map
        v3s16 oldblock_pos_i_on_map = m_block->getPosRelative();
        v3f pos_f_on_oldblock = object->m_pos;
-       v3s16 pos_i_on_oldblock = floatToInt(pos_f_on_oldblock);
+       v3s16 pos_i_on_oldblock = floatToInt(pos_f_on_oldblock, BS);
        v3s16 pos_i_on_map = pos_i_on_oldblock + oldblock_pos_i_on_map;
        v3s16 pos_blocks_on_map = getNodeBlockPos(pos_i_on_map);
 
@@ -740,9 +896,9 @@ bool MapBlockObjectList::wrapObject(MapBlockObject *object)
        }
        
        // Calculate position on new block
-       v3f oldblock_pos_f_on_map = intToFloat(oldblock_pos_i_on_map);
+       v3f oldblock_pos_f_on_map = intToFloat(oldblock_pos_i_on_map, BS);
        v3s16 newblock_pos_i_on_map = newblock->getPosRelative();
-       v3f newblock_pos_f_on_map = intToFloat(newblock_pos_i_on_map);
+       v3f newblock_pos_f_on_map = intToFloat(newblock_pos_i_on_map, BS);
        v3f pos_f_on_newblock = pos_f_on_oldblock
                        - newblock_pos_f_on_map + oldblock_pos_f_on_map;