internal IEnumerable <ModelTile> GetModelTiles(IEnumerable <TesseraTile> tiles) { var rg = new RotationGroup(4, true); foreach (var tile in tiles) { if (tile == null) { continue; } foreach (var rot in rg) { if (!tile.rotatable && rot.RotateCw != 0) { continue; } if (!tile.reflectable && rot.ReflectX) { continue; } foreach (var offset in tile.offsets) { var modelTile = new ModelTile(tile, rot, offset); yield return(modelTile); } } } }
internal TesseraTileInstance GetTesseraTileInstance(int x, int y, int z, ModelTile modelTile) { var rot = modelTile.Rotation; var tile = modelTile.Tile; var p = new Vector3Int(x, y, z); var localRotation = Quaternion.Euler(0, -rot.RotateCw, 0); var localPosition = GetLocalPosition(p) - GeometryUtils.Rotate(rot, tile.center + Vector3.Scale(tileSize, modelTile.Offset)); var localScale = rot.ReflectX ? new Vector3(-1, 1, 1) : new Vector3(1, 1, 1); var worldPosition = gameObject.transform.TransformPoint(localPosition); var worldRotation = gameObject.transform.rotation * localRotation; var worldScale = (gameObject.transform.localToWorldMatrix * Matrix4x4.TRS(localPosition, localRotation, localScale)).lossyScale; var newParent = gameObject.transform; var cells = tile.offsets.Select(offset => p + GeometryUtils.Rotate(rot, offset - modelTile.Offset)).ToArray(); return(new TesseraTileInstance { Tile = tile, Position = worldPosition, Rotation = worldRotation, LossyScale = worldScale, LocalPosition = localPosition, LocalRotation = localRotation, LocalScale = localScale, #pragma warning disable CS0618 // Type or member is obsolete IntPosition = new Vector3Int(x, y, z), #pragma warning restore CS0618 // Type or member is obsolete Cells = cells, }); }
internal override ITileConstraint GetTileConstraint(AdjacentModel model) { var actualSymmetricTilesX = new HashSet <TesseraTile>(hasSymmetricTiles ? symmetricTilesX : GetSymmetricTilesX()); var actualSymmetricTilesZ = new HashSet <TesseraTile>(hasSymmetricTiles ? symmetricTilesZ : GetSymmetricTilesZ()); // TODO: Not working in demo // TODO: Symmetric definition doesn't work with rotated tiles! var trb = new TileRotationBuilder(4, true, TileRotationTreatment.Missing); foreach (var tile in model.Tiles) { var modelTile = (ModelTile)tile.Value; if ((modelTile.Rotation.RotateCw % 180 == 0 ? actualSymmetricTilesX : actualSymmetricTilesZ).Contains(modelTile.Tile)) { var r = new Rotation(0, true); var bounds = modelTile.Tile.GetBounds(); var modelTile2 = new ModelTile { Tile = modelTile.Tile, Offset = modelTile.Offset, Rotation = modelTile.Rotation, }; trb.Add(tile, r, new Tile(modelTile2)); } else if (modelTile.Tile.reflectable) { var r = new Rotation(0, true); var modelTile2 = new ModelTile { Tile = modelTile.Tile, Offset = modelTile.Offset, Rotation = modelTile.Rotation * r, }; trb.Add(tile, r, new Tile(modelTile2)); } } return(new DeBroglie.Constraints.MirrorXConstraint { TileRotation = trb.Build(), }); }
/// <summary> /// Asynchronously runs the generation process described in the class docs, for use with StartCoroutine. /// </summary> /// <remarks>The default instantiation is still synchronous, so this can still cause frame glitches unless you override onCreate.</remarks> /// <param name="onCreate"></param> public IEnumerator StartGenerate(TesseraGenerateOptions options = null) { options = options ?? new TesseraGenerateOptions(); var coregenerator = CreateTesseraGeneratorHelper(options); for (var r = 0; r < retries; r++) { TilePropagator propagator; TilePropagator Run() { coregenerator.SetupAndRun(); return(coregenerator.Propagator); } if (options.multithreaded) { var runTask = Task.Run(Run, options.cancellationToken); while (!runTask.IsCompleted) { yield return(null); } options.cancellationToken.ThrowIfCancellationRequested(); propagator = runTask.Result; } else { propagator = Run(); } var status = propagator.Status; var contradictionTile = new ModelTile { }; var result = propagator.ToValueArray <ModelTile?>(contradiction: contradictionTile); if (status == DeBroglie.Resolution.Contradiction) { if (r < retries - 1) { continue; } } var completion = new TesseraCompletion(); completion.retries = r; completion.backtrackCount = propagator.BacktrackCount; completion.success = status == DeBroglie.Resolution.Decided; completion.tileInstances = GetTesseraTileInstances(result).ToList(); completion.contradictionLocation = completion.success ? null : GetContradictionLocation(result); if (options.onComplete != null) { options.onComplete(completion); } else { HandleComplete(options, completion); } yield return(completion); // Exit retries break; } }