From d12be67bcf24c66c66b2e5a4946250da40b4156b Mon Sep 17 00:00:00 2001 From: Caldfir Date: Fri, 20 Apr 2012 13:42:32 -0700 Subject: Added a second stage hidden block test for each block-hiding mode. --- MapLoading.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++------ UserInput.cpp | 2 +- commonTypes.h | 2 +- 3 files changed, 114 insertions(+), 15 deletions(-) diff --git a/MapLoading.cpp b/MapLoading.cpp index 228c05e..91e4117 100644 --- a/MapLoading.cpp +++ b/MapLoading.cpp @@ -34,6 +34,11 @@ inline bool IDisFloor(int in){ return isFloorTerrain( (tiletype::tiletype) in );; } +inline bool IDhasNoFloor(int in){ + //if not a custom type, do a lookup in dfHack's interface + return LowPassable( (tiletype::tiletype) in );; +} + //big look up table char rampblut[] = // generated by blutmaker.py @@ -132,9 +137,6 @@ bool isBlockOnVisibleEdgeOfSegment(WorldSegment* segment, Block* b) if(b->z == segment->z + segment->sizez - 2) return true; - if(!(segment->getBlock(b->x, b->y, b->z+1))) - return true; - if (DisplayedRotation == 0 && ( b->x == segment->x + segment->sizex - 2 @@ -179,8 +181,35 @@ bool isBlockOnVisibleEdgeOfSegment(WorldSegment* segment, Block* b) return false; } -bool areNeighborsVisible(t_designation designations[16][16],int x,int y) +bool areNeighborsVisible(WorldSegment* segment, Block* b) { + Block* temp; + + temp = segment->getBlock(b->x, b->y, b->z+1); + if(!temp || !(temp->designation.bits.hidden)) + return true; + + temp = segment->getBlock(b->x+1, b->y, b->z); + if(temp && !(temp->designation.bits.hidden)) + return true; + temp = segment->getBlock(b->x-1, b->y, b->z); + if(temp && !(temp->designation.bits.hidden)) + return true; + temp = segment->getBlock(b->x, b->y+1, b->z); + if(temp && !(temp->designation.bits.hidden)) + return true; + temp = segment->getBlock(b->x, b->y-1, b->z); + if(temp && !(temp->designation.bits.hidden)) + return true; +return false; +} + +bool areCellNeighborsVisible(t_designation designations[16][16],int x,int y) +{ + //don't do anything if this is the edge of the cell + if(x==0 || y==0 || x==15 || y==15) + return true; + //otherwise look at the neighbors and try to remove what we can if(designations[x-1][y-1].bits.hidden == false) return true; if(designations[x-1][y].bits.hidden == false) @@ -200,6 +229,35 @@ bool areNeighborsVisible(t_designation designations[16][16],int x,int y) return false; } +/** + * returns true iff the block is enclosed by other solid blocks, and is itself solid + */ +bool enclosed(WorldSegment* segment, Block* b) +{ + if(!IDisWall(b->tileType)) + return false; + + Block* temp; + temp = segment->getBlock(b->x, b->y, b->z+1); + if(!temp || IDhasNoFloor(temp->tileType)) + return false; + + temp = segment->getBlock(b->x+1, b->y, b->z); + if(temp && !IDisWall(temp->tileType)) + return false; + temp = segment->getBlock(b->x-1, b->y, b->z); + if(temp && !IDisWall(temp->tileType)) + return false; + temp = segment->getBlock(b->x, b->y+1, b->z); + if(temp && !IDisWall(temp->tileType)) + return false; + temp = segment->getBlock(b->x, b->y-1, b->z); + if(temp && !IDisWall(temp->tileType)) + return false; + + return true; +} + void ReadCellToSegment(DFHack::Core& DF, WorldSegment& segment, int CellX, int CellY, int CellZ, uint32_t BoundrySX, uint32_t BoundrySY, uint32_t BoundryEX, uint32_t BoundryEY, @@ -366,12 +424,14 @@ void ReadCellToSegment(DFHack::Core& DF, WorldSegment& segment, int CellX, int C isHidden &= !config.show_hidden_blocks; bool shouldBeIncluded = (!isOpenTerrain(b->tileType) || b->water.index || !trueBlock->designation[lx][ly].bits.outside) && !isHidden; - //include hidden blocks as shaded black - if(config.shade_hidden_blocks && isHidden && (isBlockOnVisibleEdgeOfSegment(&segment, b) || areNeighborsVisible(trueBlock->designation, lx, ly))) - { - b->building.info.type = (building_type::building_type) BUILDINGTYPE_BLACKBOX; - shouldBeIncluded= true; - } + //add back in blocks that are candidates for being shaded black (secondary check in beautify_Segment) + if( (!shouldBeIncluded) + && config.shade_hidden_blocks + && isHidden + && ( isBlockOnVisibleEdgeOfSegment(&segment, b) + || areCellNeighborsVisible(trueBlock->designation, lx, ly) + || (!segment.getBlock(b->x, b->y, b->z+1) ))) + shouldBeIncluded = true; if( shouldBeIncluded ) { @@ -837,20 +897,59 @@ WorldSegment* ReadMapSegment(int x, int y, int z, int sizex, int sizey, int size return segment; } +/** + * checks to see if the block is a potentially viewable hidden block + * if so, put the black mask block overtop + * if not, makes block not visible + */ +void mask_block(WorldSegment * segment, Block* b) +{ + //include hidden blocks as shaded black, make remaining invisible + if( b->designation.bits.hidden ) + { + if( isBlockOnVisibleEdgeOfSegment(segment, b) + || areNeighborsVisible(segment, b) ) + b->building.info.type = (building_type::building_type) BUILDINGTYPE_BLACKBOX; + else b->visible = false; + } +} + +/** + * checks to see if the block is a potentially viewable hidden block + * if not, makes block not visible + */ +void unhidden_block(WorldSegment * segment, Block* b) +{ + //make blocks that are impossible to see invisible + if( b->designation.bits.hidden + && (!isBlockOnVisibleEdgeOfSegment(segment, b)) + && (enclosed(segment, b)) ) + b->visible = false; +} + void beautify_Segment(WorldSegment * segment) { if(!segment) return; clock_t start_time = clock(); //do misc beautification + uint32_t numblocks = segment->getNumBlocks(); for(uint32_t i=0; i < numblocks; i++){ Block* b = segment->getBlock(i); - if(config.occlusion == 1) - occlude_block(b); - else if(config.occlusion == 2 && b->designation.bits.hidden) + //first check to see if this block is possible to be seen + if(config.shade_hidden_blocks && (!config.show_hidden_blocks)) + mask_block(segment, b); + else + unhidden_block(segment, b); + + if(!b->visible) + continue; + + //next see if the block is behind something + if(config.occlusion) occlude_block(b); if(!b->visible) diff --git a/UserInput.cpp b/UserInput.cpp index 55cb7ac..96c31fb 100644 --- a/UserInput.cpp +++ b/UserInput.cpp @@ -225,7 +225,7 @@ void doKeys(int Key) timeToReloadSegment = true; } if(Key == ALLEGRO_KEY_O){ - config.occlusion = (config.occlusion+1)%3; + config.occlusion = !config.occlusion; timeToReloadSegment = true; } if(Key == ALLEGRO_KEY_M){ diff --git a/commonTypes.h b/commonTypes.h index 3af3a5c..40c7c7f 100644 --- a/commonTypes.h +++ b/commonTypes.h @@ -196,7 +196,7 @@ typedef struct bool fog_of_war; - char occlusion; + bool occlusion; bool block_count; uint16_t bloodcutoff; -- cgit v1.2.1