internal override ITileConstraint GetTileConstraint(AdjacentModel model) { if (hasPathColors) { var colorSet = new HashSet <int>(pathColors); var pathTilesSet = new HashSet <TesseraTile>(pathTiles); var generator = GetComponent <TesseraGenerator>(); TesseraGeneratorHelper.SetupModelFromTiles(generator.tiles, out var allTiles, out var internalAdjacencies, out var tilesByFaceDir); // All internal connections are valid exits var internalDirs = internalAdjacencies .Concat(internalAdjacencies.Select(t => (t.Item2, t.Item1, DirectionSet.Cartesian3d.Inverse(t.Item3)))) .Where(x => !hasPathTiles || pathTilesSet.Contains(((ModelTile)x.Item1.Value).Tile)) .ToLookup(x => x.Item1, x => x.Item3); // Extneral connections are valid exits only if the color in the center of the face matches var externalDirs = tilesByFaceDir .SelectMany(kv => kv.Value.Select(t => new { FaceDir = kv.Key, FaceDetails = t.Item1, Tile = t.Item2 })) .Where(x => !hasPathTiles || pathTilesSet.Contains(((ModelTile)x.Tile.Value).Tile)) .Where(x => colorSet.Contains(x.FaceDetails.center)) .ToLookup(x => x.Tile, x => x.FaceDir.ToDirection()); var exits = internalDirs.Select(x => x.Key).Union(externalDirs.Select(x => x.Key)) .ToDictionary(x => x, x => (ISet <Direction>) new HashSet <Direction>(internalDirs[x].Concat(externalDirs[x]))); return(new DeBroglie.Constraints.EdgedPathConstraint(exits)); } else if (hasPathTiles) { var actualPathTiles = new HashSet <Tile>(GetModelTiles(pathTiles).Select(x => new Tile(x))); return(new DeBroglie.Constraints.PathConstraint(actualPathTiles)); } else { throw new Exception("One of hasColors or hasPathTiles must be set for PathConstraints"); } }
public void StartGeneration() { if (running) { return; } if (started) { StopGeneration(); } tileOutput?.ClearTiles(); var generator = GetComponent <TesseraGenerator>(); helper = generator.CreateTesseraGeneratorHelper(); helper.Setup(); // TODO: Should be *all tiles* to start with lastTiles = helper.Propagator.ToValueSets <ModelTile>(); lastStepTime = GetTime(); tileOutput = generator.GetComponent <ITesseraTileOutput>() ?? new UpdatableInstantiateOutput(transform); if (!tileOutput.SupportsIncremental) { throw new Exception($"Output {tileOutput} does not support animations"); } supportsCubes = generator.GetComponent <ITesseraTileOutput>() == null; hasObject = new bool[helper.Propagator.Topology.IndexCount]; cubesByIndex = new GameObject[helper.Propagator.Topology.IndexCount]; started = true; ResumeGeneration(); }
internal TesseraGeneratorHelper CreateTesseraGeneratorHelper(TesseraGenerateOptions options = null) { options = options ?? new TesseraGenerateOptions(); var progress = options.progress; var seed = options.seed == 0 ? UnityEngine.Random.Range(int.MinValue, int.MaxValue) : options.seed; var xororng = new XoRoRNG(seed); Validate(); TesseraGeneratorHelper.SetupModelFromTiles(tiles, out var allTiles, out var internalAdjacencies, out var tilesByFaceDir); var model = new AdjacentModel(DirectionSet.Cartesian3d); foreach (var(tile, frequency) in allTiles) { model.SetFrequency(tile, frequency); } foreach (var(tile1, tile2, d) in internalAdjacencies) { model.AddAdjacency(tile1, tile2, d); } // Generate adjacencies AddAdjacency(palette, model, Direction.XPlus, tilesByFaceDir[FaceDir.Right], tilesByFaceDir[FaceDir.Left]); AddAdjacency(palette, model, Direction.YPlus, tilesByFaceDir[FaceDir.Up], tilesByFaceDir[FaceDir.Down]); AddAdjacency(palette, model, Direction.ZPlus, tilesByFaceDir[FaceDir.Forward], tilesByFaceDir[FaceDir.Back]); var initialConstraints = searchInitialConstraints ? GetInitialConstraints() : this.initialConstraints; var constraints = GetTileConstraints(model); var actualSkyBox = skyBox == null ? null : new TesseraInitialConstraint { faceDetails = skyBox.faceDetails, offsets = skyBox.offsets, }; return(new TesseraGeneratorHelper( palette, model, allTiles, initialConstraints, constraints, tilesByFaceDir, size, backtrack, actualSkyBox, progress, null, xororng, options.cancellationToken)); }