Generalize selection boxes
authorPerttu Ahola <celeron55@gmail.com>
Sun, 13 Nov 2011 10:31:05 +0000 (12:31 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Tue, 29 Nov 2011 17:13:41 +0000 (19:13 +0200)
src/content_mapnode.cpp
src/game.cpp
src/mapnode_contentfeatures.h

index a365f2ae982466a1695c945aad200bece2be9303..0ba59fcbb8b91f0d4fc819a9364f2f131b279163 100644 (file)
@@ -335,6 +335,7 @@ void content_mapnode_init()
        f->solidness = 0; // drawn separately, makes no faces
        f->air_equivalent = true; // grass grows underneath
        f->walkable = false;
+       f->selection_box.type = NODEBOX_FIXED;
        setDirtLikeDiggingProperties(f->digging_properties, 0.75);
 
        i = CONTENT_LADDER;
@@ -350,6 +351,7 @@ void content_mapnode_init()
        f->air_equivalent = true;
        f->walkable = false;
        f->climbable = true;
+       f->selection_box.type = NODEBOX_WALLMOUNTED;
        setWoodLikeDiggingProperties(f->digging_properties, 0.5);
 
        // Deprecated
@@ -606,6 +608,13 @@ void content_mapnode_init()
        f->air_equivalent = true;
        f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
        f->light_source = LIGHT_MAX-1;
+       f->selection_box.type = NODEBOX_WALLMOUNTED;
+       f->selection_box.wall_top = core::aabbox3d<f32>(
+                       -BS/10, BS/2-BS/3.333*2, -BS/10, BS/10, BS/2, BS/10);
+       f->selection_box.wall_bottom = core::aabbox3d<f32>(
+                       -BS/10, -BS/2, -BS/10, BS/10, -BS/2+BS/3.333*2, BS/10);
+       f->selection_box.wall_side = core::aabbox3d<f32>(
+                       -BS/2, -BS/3.333, -BS/10, -BS/2+BS/3.333, BS/3.333, BS/10);
        f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
        
        i = CONTENT_SIGN_WALL;
@@ -623,6 +632,7 @@ void content_mapnode_init()
        if(f->initial_metadata == NULL)
                f->initial_metadata = new SignNodeMetadata("Some sign");
        f->digging_properties.set("", DiggingProperties(true, 0.5, 0));
+       f->selection_box.type = NODEBOX_WALLMOUNTED;
        
        i = CONTENT_CHEST;
        f = &content_features(i);
index d7efbeae9fbaf616d19113ee48820f5463cd79bd..30bd1bcf7fce04ea9a59a6c491ed5b2cc18b0724 100644 (file)
@@ -43,7 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gettext.h"
 #include "log.h"
 #include "filesys.h"
-// Needed for some special cases for CONTENT_TORCH and CONTENT_SIGN_WALL
+// Needed for writing to signs (CONTENT_SIGN_WALL)
 // TODO: A generic way for handling such should be created
 #include "content_mapnode.h"
 // Needed for sign text input
@@ -343,43 +343,15 @@ void getPointedNode(Client *client, v3f player_position,
                        v3s16(-1,0,0), // left
                };
                
-               /*
-                       Meta-objects
-               */
-               if(n.getContent() == CONTENT_TORCH)
+               ContentFeatures &f = content_features(n);
+               
+               if(f.selection_box.type == NODEBOX_FIXED)
                {
-                       v3s16 dir = unpackDir(n.param2);
-                       v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
-                       dir_f *= BS/2 - BS/6 - BS/20;
-                       v3f cpf = npf + dir_f;
-                       f32 distance = (cpf - camera_position).getLength();
+                       f32 distance = (npf - camera_position).getLength();
 
-                       core::aabbox3d<f32> box;
-                       
-                       // bottom
-                       if(dir == v3s16(0,-1,0))
-                       {
-                               box = core::aabbox3d<f32>(
-                                       npf - v3f(BS/6, BS/2, BS/6),
-                                       npf + v3f(BS/6, -BS/2+BS/3*2, BS/6)
-                               );
-                       }
-                       // top
-                       else if(dir == v3s16(0,1,0))
-                       {
-                               box = core::aabbox3d<f32>(
-                                       npf - v3f(BS/6, -BS/2+BS/3*2, BS/6),
-                                       npf + v3f(BS/6, BS/2, BS/6)
-                               );
-                       }
-                       // side
-                       else
-                       {
-                               box = core::aabbox3d<f32>(
-                                       cpf - v3f(BS/6, BS/3, BS/6),
-                                       cpf + v3f(BS/6, BS/3, BS/6)
-                               );
-                       }
+                       core::aabbox3d<f32> box = f.selection_box.fixed;
+                       box.MinEdge += npf;
+                       box.MaxEdge += npf;
 
                        if(distance < mindistance)
                        {
@@ -393,7 +365,7 @@ void getPointedNode(Client *client, v3f player_position,
                                }
                        }
                }
-               else if(n.getContent() == CONTENT_SIGN_WALL)
+               else if(f.selection_box.type == NODEBOX_WALLMOUNTED)
                {
                        v3s16 dir = unpackDir(n.param2);
                        v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
@@ -401,122 +373,43 @@ void getPointedNode(Client *client, v3f player_position,
                        v3f cpf = npf + dir_f;
                        f32 distance = (cpf - camera_position).getLength();
 
-                       v3f vertices[4] =
-                       {
-                               v3f(BS*0.42,-BS*0.35,-BS*0.4),
-                               v3f(BS*0.49, BS*0.35, BS*0.4),
-                       };
-
-                       for(s32 i=0; i<2; i++)
-                       {
-                               if(dir == v3s16(1,0,0))
-                                       vertices[i].rotateXZBy(0);
-                               if(dir == v3s16(-1,0,0))
-                                       vertices[i].rotateXZBy(180);
-                               if(dir == v3s16(0,0,1))
-                                       vertices[i].rotateXZBy(90);
-                               if(dir == v3s16(0,0,-1))
-                                       vertices[i].rotateXZBy(-90);
-                               if(dir == v3s16(0,-1,0))
-                                       vertices[i].rotateXYBy(-90);
-                               if(dir == v3s16(0,1,0))
-                                       vertices[i].rotateXYBy(90);
-
-                               vertices[i] += npf;
-                       }
-
                        core::aabbox3d<f32> box;
-
-                       box = core::aabbox3d<f32>(vertices[0]);
-                       box.addInternalPoint(vertices[1]);
-
-                       if(distance < mindistance)
-                       {
-                               if(box.intersectsWithLine(shootline))
-                               {
-                                       nodefound = true;
-                                       nodepos = np;
-                                       neighbourpos = np;
-                                       mindistance = distance;
-                                       nodehilightbox = box;
-                               }
+                       
+                       // top
+                       if(dir == v3s16(0,1,0)){
+                               box = f.selection_box.wall_top;
                        }
-               }
-
-               else if(n.getContent() == CONTENT_LADDER)
-               {
-                       v3s16 dir = unpackDir(n.param2);
-                       v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
-                       dir_f *= BS/2 - BS/6 - BS/20;
-                       v3f cpf = npf + dir_f;
-                       f32 distance = (cpf - camera_position).getLength();
-
-                       v3f vertices[4] =
-                       {
-                               v3f(BS*0.42,-BS/2,-BS/2),
-                               v3f(BS*0.49, BS/2, BS/2),
-                       };
-
-                       for(s32 i=0; i<2; i++)
-                       {
-                               if(dir == v3s16(1,0,0))
-                                       vertices[i].rotateXZBy(0);
-                               if(dir == v3s16(-1,0,0))
-                                       vertices[i].rotateXZBy(180);
-                               if(dir == v3s16(0,0,1))
-                                       vertices[i].rotateXZBy(90);
-                               if(dir == v3s16(0,0,-1))
-                                       vertices[i].rotateXZBy(-90);
-                               if(dir == v3s16(0,-1,0))
-                                       vertices[i].rotateXYBy(-90);
-                               if(dir == v3s16(0,1,0))
-                                       vertices[i].rotateXYBy(90);
-
-                               vertices[i] += npf;
+                       // bottom
+                       else if(dir == v3s16(0,-1,0)){
+                               box = f.selection_box.wall_bottom;
                        }
+                       // side
+                       else{
+                               v3f vertices[2] =
+                               {
+                                       f.selection_box.wall_side.MinEdge,
+                                       f.selection_box.wall_side.MaxEdge
+                               };
 
-                       core::aabbox3d<f32> box;
-
-                       box = core::aabbox3d<f32>(vertices[0]);
-                       box.addInternalPoint(vertices[1]);
-
-                       if(distance < mindistance)
-                       {
-                               if(box.intersectsWithLine(shootline))
+                               for(s32 i=0; i<2; i++)
                                {
-                                       nodefound = true;
-                                       nodepos = np;
-                                       neighbourpos = np;
-                                       mindistance = distance;
-                                       nodehilightbox = box;
+                                       if(dir == v3s16(-1,0,0))
+                                               vertices[i].rotateXZBy(0);
+                                       if(dir == v3s16(1,0,0))
+                                               vertices[i].rotateXZBy(180);
+                                       if(dir == v3s16(0,0,-1))
+                                               vertices[i].rotateXZBy(90);
+                                       if(dir == v3s16(0,0,1))
+                                               vertices[i].rotateXZBy(-90);
                                }
-                       }
-               }
-               else if(n.getContent() == CONTENT_RAIL)
-               {
-                       v3s16 dir = unpackDir(n.param0);
-                       v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
-                       dir_f *= BS/2 - BS/6 - BS/20;
-                       v3f cpf = npf + dir_f;
-                       f32 distance = (cpf - camera_position).getLength();
 
-                       float d = (float)BS/16;
-                       v3f vertices[4] =
-                       {
-                               v3f(BS/2, -BS/2+d, -BS/2),
-                               v3f(-BS/2, -BS/2, BS/2),
-                       };
-
-                       for(s32 i=0; i<2; i++)
-                       {
-                               vertices[i] += npf;
+                               box = core::aabbox3d<f32>(vertices[0]);
+                               box.addInternalPoint(vertices[1]);
                        }
 
-                       core::aabbox3d<f32> box;
-
-                       box = core::aabbox3d<f32>(vertices[0]);
-                       box.addInternalPoint(vertices[1]);
-
+                       box.MinEdge += npf;
+                       box.MaxEdge += npf;
+                       
                        if(distance < mindistance)
                        {
                                if(box.intersectsWithLine(shootline))
@@ -529,10 +422,7 @@ void getPointedNode(Client *client, v3f player_position,
                                }
                        }
                }
-               /*
-                       Regular blocks
-               */
-               else
+               else // NODEBOX_REGULAR
                {
                        for(u16 i=0; i<6; i++)
                        {
index b60fc8d8bac16b73ce3fd07aaea05a7fd88b7375..7dd9df13b6ea951e498d5cadac63e47b4a2715ee 100644 (file)
@@ -57,6 +57,35 @@ enum LiquidType
        LIQUID_SOURCE
 };
 
+enum NodeBoxType
+{
+       NODEBOX_REGULAR, // Regular block; allows buildable_to
+       NODEBOX_FIXED, // Static separately defined box
+       NODEBOX_WALLMOUNTED, // Box for wall_mounted nodes; (top, bottom, side)
+};
+
+struct NodeBox
+{
+       enum NodeBoxType type;
+       // NODEBOX_REGULAR (no parameters)
+       // NODEBOX_FIXED
+       core::aabbox3d<f32> fixed;
+       // NODEBOX_WALLMOUNTED
+       core::aabbox3d<f32> wall_top;
+       core::aabbox3d<f32> wall_bottom;
+       core::aabbox3d<f32> wall_side; // being at the -X side
+
+       NodeBox():
+               type(NODEBOX_REGULAR),
+               // default is rail-like
+               fixed(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2),
+               // default is sign/ladder-like
+               wall_top(-BS/2, BS/2-BS/16., -BS/2, BS/2, BS/2, BS/2),
+               wall_bottom(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2),
+               wall_side(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2)
+       {}
+};
+
 struct MapNode;
 class NodeMetadata;
 
@@ -149,6 +178,8 @@ struct ContentFeatures
        DiggingPropertiesList digging_properties;
 
        u32 damage_per_second;
+
+       NodeBox selection_box;
        
        // NOTE: Move relevant properties to here from elsewhere
 
@@ -186,6 +217,7 @@ struct ContentFeatures
                light_source = 0;
                digging_properties.clear();
                damage_per_second = 0;
+               selection_box = NodeBox();
        }
 
        ContentFeatures()