public void SetZone( int idx, IDZone zone ) { zones[idx] = zone; }
public virtual void ReadFrom( BinaryReader reader, int size ) { zones = new IDZone[size]; for ( int i=0; i<size; ++i ) { zones[i] = new IDZone( reader ); } }
public ushort this[int x] { get { return LookupZone( x ).ID; } set { x = Lightmap.BaseNormalizeX( x ); // I think this is the longest set { } implementation I've ever written... :) ~ Inferis // Transform x coordinate into a zoneindex int index = LookupZoneIndex( x ); if ( index < 0 ) throw new ArgumentOutOfRangeException(); // Skip if we're trying to put the same value IDZone zone = zones[index]; if ( zone.ID == value ) return; // Find the length out int length = index+1 < zones.Length ? (zones[index+1].X - zone.X) : (Lightmap.BaseWidth - zone.X); IDZone[] list; if ( length == 1 ) { // Special case. We don't have to bother about resizing the zone, but we might have to join surrounding zones if they contain the same values. zone.ID = value; bool leftOk = (index > 0 && zones[index-1].ID == value); bool rightOk = (index+1 < zones.Length && zones[index+1].ID == value); if ( leftOk && !rightOk ) { // Left equals us, but not the right... Just remove this block (it is joined with the left, left.X remains valid). list = new IDZone[zones.Length-1]; Array.Copy( zones, 0, list, 0, index ); Array.Copy( zones, index+1, list, index, zones.Length-index-1 ); zones = list; } else if ( !leftOk && rightOk ) { // Right equals us, but not the left... Keep this block, and remove the right (as our X remains valid) list = new IDZone[zones.Length-1]; Array.Copy( zones, 0, list, 0, index+1 ); Array.Copy( zones, index+2, list, index+1, zones.Length-index-2 ); zones = list; } else if ( leftOk && rightOk ) { // Both left and right equal us. Move all three into one block (keep left, as it's X remains valid) list = new IDZone[zones.Length-2]; Array.Copy( zones, 0, list, 0, index ); Array.Copy( zones, index+2, list, index, zones.Length-index-2 ); zones = list; } else { // None of the blocks beside us are equal. Simplest case, just change the value! zones[index].ID = value; } return; } // Okay, our zone is longer than 1 pixel. Is it... // ... At the start of this zone? if ( x == zone.X ) { // Yes, check if previous zone exists and if it has the same value... if ( index == 0 || zones[index-1].ID != value ) { // Nope, create a new zonelist in a temporary array, and place the new zone at the correct place list = new IDZone[zones.Length+1]; Array.Copy( zones, 0, list, 0, index ); list[index] = new IDZone( x, value ); Array.Copy( zones, index, list, index+1, zones.Length-index ); // Assign new array zones = list; // Move index ++index; } // Then, shorten this zone zones[index].X += 1; return; } // Not at the start, maybe at the end? if ( x == zone.X+length-1 ) { // Yeps, check if next zone exists and if it has the same value if ( index+1 < zones.Length && zones[index+1].ID == value ) { // Yes... Lengthen zones[index+1].X -= 1; } else { // Nope, create a new zonelist in a temporary array, and place the new zone at the correct place list = new IDZone[zones.Length+1]; if ( index+1 == zones.Length ) { // We're at the end, just copy the list and add the proc behind zones.CopyTo( list, 0 ); } else { Array.Copy( zones, 0, list, 0, index+1 ); Array.Copy( zones, index+1, list, index+2, zones.Length-index-1 ); // Assign new array } list[index+1] = new IDZone( x, value ); zones = list; } return; } // So, somewhere in the middle. Split the zone in three. IDZone left = new IDZone( zone.X, zone.ID ); IDZone right = new IDZone( x+1, zone.ID ); zone = new IDZone( x, value ); list = new IDZone[zones.Length+2]; Array.Copy( zones, 0, list, 0, index ); list[index] = left; list[index+1] = zone; list[index+2] = right; Array.Copy( zones, index+1, list, index+3, zones.Length-index-1 ); zones = list; } }
public void ImportBitmapBuffer( int[] buffer, int bufstart, int bufwidth, int left, int right ) { ArrayList newZones = new ArrayList( bufwidth/8 ); bufwidth += bufstart; IDZone currentZone = new IDZone( left, buffer[bufstart] ); for ( int bx = bufstart+1, px = left+1; bx<bufwidth; ++bx, ++px ) { if ( buffer[bx] != currentZone.ID ) { // ID changes, so add this zone and start a new one newZones.Add( currentZone ); currentZone = new IDZone( px, buffer[bx] ); } } // Add last zone newZones.Add( currentZone ); int leftindex = LookupZoneIndex( left ); int rightindex = LookupZoneIndex( right ); //System.Diagnostics.Debug.Assert( leftindex <= rightindex, "invalid left/right index" ); if ( zones[rightindex].ID == ((IDZone)newZones[newZones.Count-1]).ID ) { // If the last new zone equals the original right zone, we can safely drop the original right zone. // That means that rightindex is included in the "to be removed" area. ++rightindex; } else if ( leftindex < rightindex ) { // Otherwise, we'll have to adjust the X value of that original right zone, and shift // rightindex one to the left. zones[rightindex].X = (short)right; } else { newZones.Add( new IDZone( right, zones[rightindex].ID ) ); ++rightindex; } if ( zones[leftindex].ID == ((IDZone)newZones[0]).ID ) { // If the first new zone equals the original left zone, we'll need to adjust the first zone. IDZone tmp = ((IDZone)newZones[0]); tmp.X = zones[leftindex].X; newZones[0] = tmp; } else { // Otherwise, we start at the next zone, but only if the previous zone is different. if ( leftindex > 0 && zones[leftindex-1].ID == ((IDZone)newZones[0]).ID ) { newZones.RemoveAt( 0 ); } else if ( zones[leftindex].X != ((IDZone)newZones[0]).X ) { ++leftindex; } } // leftindex and rightindex now define the bounds of the zones we need to get rid of int nzi = 0; for ( int zi=leftindex; zi<rightindex; ++zi ) { if ( nzi < newZones.Count ) { // we have new zones left, copy one over zones[zi] = (IDZone)newZones[nzi++]; } else { // no more new zones left, shift the rest of the bunch to the left for ( int shift=0; shift < zones.Length-rightindex; ++shift ) { zones[zi+shift] = zones[rightindex+shift]; } // Resize the array IDZone[] zones2 = new IDZone[zi+zones.Length-rightindex]; Array.Copy( zones, 0, zones2, 0, zones2.Length ); zones = zones2; break; } } if ( nzi < newZones.Count ) { // We still need to copy some IDZone[] zones2 = new IDZone[zones.Length+newZones.Count-nzi]; Array.Copy( zones, 0, zones2, 0, rightindex ); Array.Copy( zones, rightindex, zones2, rightindex+newZones.Count-nzi, zones.Length-rightindex ); while ( nzi < newZones.Count ) { zones2[rightindex++] = (IDZone)newZones[nzi++]; } zones = zones2; } }
public Scanline( ushort zero, IDZone[] zones ) { this.zones = new IDZone[zones.Length]; Array.Copy( zones, 0, this.zones, 0, zones.Length ); zeroId = zero; }