/// <inheritdoc/> protected internal override void PrepareTileData(IBrushContext context, TileData tile, int variationIndex) { var tileSystem = context.TileSystem; // Find actual orientation of target tile. int actualOrientation = OrientationUtility.DetermineTileOrientation(tileSystem, context.Row, context.Column, context.Brush, tile.PaintedRotation); // Try to find nearest match, assume default scenario. int bestOrientation = this.FindClosestOrientationMask(actualOrientation); // Select tile for painting using tile brush. var orientation = this.FindOrientation(bestOrientation); if (orientation == null) { Debug.LogWarning(string.Format("Brush '{0}' orientation '{1}' not defined", this.name, OrientationUtility.NameFromMask(bestOrientation))); return; } int orientationVariationCount = orientation.VariationCount; // Randomize variation? if (variationIndex == RANDOM_VARIATION) { if (!tileSystem.BulkEditMode || tileSystem.IsEndingBulkEditMode) { variationIndex = orientation.PickRandomVariationIndex(); } } // Negative offset from variations of orientation. else if (variationIndex < 0) { variationIndex = Mathf.Max(0, orientationVariationCount + variationIndex); } // Ensure variation index is within bounds of orientation! int wrappedVariationIndex = variationIndex; if (wrappedVariationIndex >= orientationVariationCount) { wrappedVariationIndex = 0; } if (orientationVariationCount > 0) { // // Could re-insert following to 'fix' state of randomly selected tiles. // Note: Randomization is lost when erasing tiles from mass filled areas. // //// Persist wrapped variation when painting tile? //if (!system.BulkEditMode || system.IsEndingBulkEditMode) { // variationIndex = wrappedVariationIndex; //} // Fetch nested brush reference (if there is one). var nestedBrush = orientation.GetVariation(wrappedVariationIndex) as Brush; if (nestedBrush != null) { // Prepare tile data using nested brush. nestedBrush.PrepareTileData(context, tile, wrappedVariationIndex); } } tile.orientationMask = (byte)bestOrientation; tile.variationIndex = (byte)variationIndex; // Do not attempt automatic rotation where rotation has been manually specified. int rotation = tile.PaintedRotation + orientation.Rotation; if (rotation > 3) { rotation -= 4; } tile.Rotation = rotation; }
/// <inheritdoc/> protected internal override void CreateTile(IBrushContext context, TileData tile) { var orientation = this.FindOrientation(tile.orientationMask); if (orientation == null) { Debug.LogWarning(string.Format("Brush '{0}' orientation '{1}' not defined", this.name, OrientationUtility.NameFromMask(tile.orientationMask))); return; } if (orientation.VariationCount == 0) { Debug.LogWarning(string.Format("Brush '{0}' orientation '{1}' has no variations", this.name, OrientationUtility.NameFromMask(tile.orientationMask))); return; } // Note: Do not update variation index in tile data because this may be unintended! int variationIndex = (int)tile.variationIndex; if (variationIndex >= orientation.VariationCount) { variationIndex = 0; } var orientedVariation = orientation.GetVariation(variationIndex); // Orchestrate a "nested" brush? var nestedBrush = orientedVariation as Brush; if (nestedBrush != null) { // Force override flags with that of nested brush? // // Note: Naming a little backwards in this scenario, we want to preserve // flags from nested brush! // if (!this.forceOverrideFlags) { // Remove all user flags, solid flag and replace with flags from nested brush. tile.flags = (tile.flags & ~0x8FFFF) | nestedBrush.TileFlags; } nestedBrush.CreateTile(context, tile); nestedBrush.PostProcessTile(context, tile); return; } var variationPrefab = orientedVariation as GameObject; if (variationPrefab == null) { return; } // Actually create tile! tile.gameObject = InstantiatePrefabForTile(variationPrefab, tile, context.TileSystem); }
/// <summary> /// Finds mask of orientation that best matches the specified orientation mask. /// </summary> /// <param name="mask">Bit mask of tile orientation.</param> /// <returns> /// Bit mask of the closest available orientation. /// </returns> public int FindClosestOrientationMask(int mask) { // Is desired orientation available? if (this.FindOrientation(mask) != null) { return(mask); } // Find nearest match. int strongestConnections = 2; int weakConnections = 0; int strongestOrientation = this.defaultOrientationMask; int childOrientation, s, w; if (FallbackMode == Tile.FallbackMode.NextBest) { for (int i = 0; i < this.orientations.Length; ++i) { childOrientation = this.orientations[i].Mask; // If there are at least 3 strong connections... s = OrientationUtility.CountStrongConnections(mask, childOrientation); if (s > strongestConnections) { // Strong connections overule any previous weak connection matches! strongestConnections = s; weakConnections = OrientationUtility.CountWeakConnections(mask, childOrientation); strongestOrientation = childOrientation; } // If this connection is just as strong as the previous then we can determine // which one is better by looking at the weak connections. else if (s == strongestConnections) { // Choose the connection that has the most weak connections! w = OrientationUtility.CountWeakConnections(mask, childOrientation); if (w > weakConnections) { strongestOrientation = childOrientation; weakConnections = w; } } } } else if (FallbackMode == Tile.FallbackMode.UseDefault) { for (int i = 0; i < this.orientations.Length; ++i) { childOrientation = this.orientations[i].Mask; // When using default mode there must be exactly 4 strong connections! if (OrientationUtility.CountStrongConnections(mask, childOrientation) == 4) { w = OrientationUtility.CountWeakConnections(mask, childOrientation); // Has a strong connection been found for the first time? // Otherwise, choose the connection that has the most weak connections! if (strongestConnections == 2 || w > weakConnections) { strongestConnections = 4; weakConnections = w; strongestOrientation = childOrientation; } } } } else if (FallbackMode == Tile.FallbackMode.UseDefaultStrict) { for (int i = 0; i < this.orientations.Length; ++i) { childOrientation = this.orientations[i].Mask; // When using default mode there must be exactly 4 strong connections! if (OrientationUtility.CountStrongConnections(mask, childOrientation) == 4 && OrientationUtility.CountWeakConnections(mask, childOrientation) == 4) { strongestOrientation = childOrientation; } } } return(strongestOrientation); }