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);
                    }
                }
            }
        }
Exemple #2
0
        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(),
            });
        }
Exemple #4
0
        /// <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;
            }
        }