GridPos Grid::positionOfPiece(Piece* piece) const { auto it = _piecePositions.find(piece); if (it != _piecePositions.end()) { return (*it).second; } return GridPos(0,0); }
void DataGridContentProvider::NotifySelectCell(vint row, vint column) { currentCell=GridPos(row, column); dataGrid->NotifySelectedCellChanged(); if(listViewItemStyleProvider) { GuiListControl::IItemStyleController* selectedStyleController=0; GuiListControl::IItemArranger* arranger=dataGrid->GetArranger(); if(arranger) { selectedStyleController=arranger->GetVisibleStyle(row); } vint count=listViewItemStyleProvider->GetCreatedItemStyles().Count(); for(vint i=0;i<count;i++) { GuiListControl::IItemStyleController* itemStyleController=listViewItemStyleProvider->GetCreatedItemStyles().Get(i); ItemContent* itemContent=listViewItemStyleProvider->GetItemContent<ItemContent>(itemStyleController); if(itemContent) { if(itemStyleController==selectedStyleController) { itemContent->NotifySelectCell(column); } else { itemContent->NotifySelectCell(-1); } } } } }
bool DataGridContentProvider::SetSelectedCell(const GridPos& value, bool openEditor) { if(currentCell!=value) { if(value==GridPos(-1, -1)) { CloseEditor(false); return true; } else if(0<=value.row && value.row<dataProvider->GetRowCount() && 0<=value.column && value.column<dataProvider->GetColumnCount()) { IDataEditorFactory* editorFactory=openEditor?dataProvider->GetCellDataEditorFactory(value.row, value.column):0; OpenEditor(value.row, value.column, editorFactory); return true; } return false; } return true; }
void DataGridContentProvider::CloseEditor(bool forOpenNewEditor) { if(currentEditorRequestingSaveData) { NotifyCloseEditor(); } else { if(currentCell!=GridPos(-1, -1)) { if(currentEditor) { NotifyCloseEditor(); currentEditor=0; } if(!forOpenNewEditor) { NotifySelectCell(-1, -1); } } } }
GridPos GridPos::operator+(const GridPos& p) const { return GridPos(q + p.q, r + p.r); }
GridPos GridPos::operator-(const GridPos& p) const { return GridPos(q - p.q, r - p.r); }
/* Core code contributed by Kevin Behilo, 2/20/04. * * Possible TODO: add code to soften and blend shadow edges * (see aliasing comments in source). * * Definite TODO: the whole thing can be sped up by precalculating the * surface normals once. In fact that should be placed in a separate Shading * Context, so that it could be re-used for quickly re-shading multiple times. */ void vtHeightFieldGrid3d::ShadowCastDib(vtBitmapBase *pBM, const FPoint3 &light_dir, float fLightFactor, float fAmbient, bool progress_callback(int)) const { const IPoint2 bitmap_size = pBM->GetSize(); // Compute area that we will sample for shading, bounded by the texel // centers, which are 1/2 texel in from the grid extents. const DPoint2 texel_size(m_EarthExtents.Width() / bitmap_size.x, m_EarthExtents.Height() / bitmap_size.y); DRECT texel_area = m_EarthExtents; texel_area.Grow(-texel_size.x/2, -texel_size.y/2); const DPoint2 texel_base(texel_area.left, texel_area.bottom); const bool b8bit = (pBM->GetDepth() == 8); // These values are hardcoded here but could be exposed in the GUI const float sun = 0.7f; // If we have light that's pointing UP, rather than down at the terrain, // then it's only going to take a really long time to produce a // completely dark terrain. We can catch this case up front. if (light_dir.y > 0) { for (int i = 0; i < bitmap_size.x; i++) { for (int j = 0; j < bitmap_size.y; j++) { if (b8bit) pBM->ScalePixel8(i, j, fAmbient); else pBM->ScalePixel24(i, j, fAmbient); } } return; } // Create array to hold flags LightMap lightmap(bitmap_size.x, bitmap_size.y); // This factor is used when applying shading to non-shadowed areas to // try and keep the "contrast" down to a min. (still get "patches" of // dark/light spots though). // It is initialized to 1.0, because in case there are no shadows at all // (such as at noon) we still need a reasonable value. float darkest_shadow = 1.0; // For the vector used to cast shadows, we need it in grid coordinates, // which are (Column,Row) where Row is north. But the direction passed // in uses OpenGL coordinates where Z is south. So flip Z. FPoint3 grid_light_dir = light_dir; grid_light_dir.z = -grid_light_dir.z; // Scale the light vector such that the X or Z component (whichever is // larger) is 1. This is will serve as our direction vector in grid // coordinates, when drawing a line across the grid to cast the shadow. // // Code adapted from aaron_torpy: // http://www.geocities.com/aaron_torpy/algorithms.htm // float f, HScale; if ( fabs(grid_light_dir.x) > fabs(grid_light_dir.z) ) { HScale = m_fStep.x; f = fabs(light_dir.x); } else { HScale = m_fStep.y; f = fabs(light_dir.z); } grid_light_dir /= f; int i_init, i_final, i_incr; int j_init, j_final, j_incr; if (grid_light_dir.x > 0) { i_init=0; i_final=bitmap_size.x; i_incr=1; } else { i_init=bitmap_size.x-1; i_final=-1; i_incr=-1; } if (grid_light_dir.z > 0) { j_init=0; j_final=bitmap_size.y; j_incr=1; } else { j_init=bitmap_size.y-1; j_final=-1; j_incr=-1; } // First pass: find each point that it is in shadow. DPoint2 pos; float shadowheight, elevation; FPoint3 normal; FPoint3 p3; int x, z; float shade; for (int j = j_init; j != j_final; j += j_incr) { if (progress_callback != NULL && (j%20) == 0) progress_callback(abs(j-j_init) * 100 / bitmap_size.y); for (int i = i_init; i != i_final; i += i_incr) { pos = GridPos(texel_base, texel_size, i, j); FindAltitudeOnEarth(pos, shadowheight, true); if (shadowheight == INVALID_ELEVATION) { // set a flag so we won't visit this one again lightmap.Set(i, j, 1); continue; } bool Under_Out = false; for (int k = 1; Under_Out == false; k++) { x = (int) (i + grid_light_dir.x*k + 0.5f); z = (int) (j + grid_light_dir.z*k + 0.5f); shadowheight += grid_light_dir.y * HScale; if ((x<0) || (x>bitmap_size.x-1) || (z<0) || (z>bitmap_size.y-1)) { Under_Out = true; // Out of the grid break; } pos = GridPos(texel_base, texel_size, x, z); FindAltitudeOnEarth(pos, elevation, true); // skip holes in the grid if (elevation == INVALID_ELEVATION) continue; if (elevation > shadowheight) { if (k>1) Under_Out = true; // Under the terrain break; } // Combine color and shading. // Only do shadow if we have not shaded this i,j before. if (lightmap.Get(x,z) < 1) { // 3D elevation query to get slope m_LocalCS.EarthToLocal(pos, p3.x, p3.z); FindAltitudeAtPoint(p3, p3.y, true, 0, &normal); //***************************************** // Here the Sun(r, g, b) = 0 because we are in the shade // therefore I(r, g, b) = Amb(r, g, b) * (0.5*N[z] + 0.5) // shade = sun*normal.Dot(-light_direction) + fAmbient * (0.5f*normal.y + 0.5f); shade = fAmbient * (0.5f*normal.y + 0.5f); //***************************************** //***************************************** if (darkest_shadow > shade) darkest_shadow = shade; // Rather than doing the shading at this point we may want to // simply save the value into the LightMap array. Then apply // some anti-aliasing or edge softening algorithm to the LightMap. // Once that's done, apply the whole LightMap to the DIB. if (b8bit) pBM->ScalePixel8(x, bitmap_size.y-1-z, shade); else pBM->ScalePixel24(x, bitmap_size.y-1-z, shade); // set a flag to show that this texel has been shaded. // (or set to value of the shading - see comment above) lightmap.Set(x, z, lightmap.Get(x, z)+1); } } } //for i } //for j // For dot-product lighting, we use the normal 3D vector, only inverted // so that we can compare it to the upward-pointing ground normals. const FPoint3 inv_light_dir = -light_dir; // Second pass. Now we are going to loop through the LightMap and apply // the full lighting formula to each texel that has not been shaded yet. for (int j = 0; j < bitmap_size.y; j++) { if (progress_callback != NULL && (j%20) == 0) progress_callback(j * 100 / bitmap_size.y); for (int i = 0; i < bitmap_size.x; i++) { if (lightmap.Get(i, j) > 0) continue; pos = GridPos(texel_base, texel_size, i, j); // 2D elevation query to check for holes in the grid FindAltitudeOnEarth(pos, elevation, true); if (elevation == INVALID_ELEVATION) continue; // 3D elevation query to get slope m_LocalCS.EarthToLocal(pos, p3.x, p3.z); FindAltitudeAtPoint(p3, p3.y, true, 0, &normal); //***************************************** //***************************************** //shade formula based on: //http://www.geocities.com/aaron_torpy/algorithms.htm#calc_intensity // The Amb value was arbitrarily chosen // Need to experiment more to determine the best value // Perhaps calculating Sun(r, g, b) and Amb(r, g, b) for a // given time of day (e.g. warmer colors close to sunset) // or give control to user since textures will differ // I(r, g, b) = Sun(r, g, b) * scalarprod(N, v) + Amb(r, g, b) * (0.5*N[z] + 0.5) shade = sun * normal.Dot(inv_light_dir); // It's a reasonable assuption that an angle of 45 degrees is // sufficient to fully illuminate the ground. shade /= .7071f; // Now add ambient component shade += fAmbient * (0.5f*normal.y + 0.5f); // Maybe clipping values can be exposed to the user as well. // Clip - don't shade down below lowest ambient level if (shade < darkest_shadow) shade = darkest_shadow; else if (shade > 1.2f) shade = 1.2f; // Push the value of 'shade' toward 1.0 by the fLightFactor factor. // This means that fLightFactor=0 means no lighting, 1 means full lighting. float diff = 1 - shade; diff = diff * (1 - fLightFactor); shade += diff; // Rather than doing the shading at this point we may want to // simply save the value into the LightMap array. Then apply // some anti-aliasing or edge softening algorithm to the LightMap. // Once that's done, apply the whole LightMap to the DIB. // LightMap[I][J]= shade; // set to value of the shading - see comment above) if (b8bit) pBM->ScalePixel8(i, bitmap_size.y-1-j, shade); else pBM->ScalePixel24(i, bitmap_size.y-1-j, shade); } } // Possible TODO: Apply edge softening algorithm (?) }
/*! * @return the position below this position * * \sa left(), right(), up() */ inline GridPos down() { return GridPos(row()+1, column()); }
/*! * @return the position above this position * * \sa left(), right(), down() */ inline GridPos up() { return GridPos(row()-1, column()); }
/*! * @return the position to the right of this position * * \sa left(), up(), down() */ inline GridPos right() { return GridPos(row(), column()+1); }
/*! * @return the position to the left of this position * * \sa right(), up(), down() */ inline GridPos left() { return GridPos(row(), column()-1); }