public void InitializePostDeserialize(LSystemBehavior handleOwner)
        {
            if (useSharedSystem)
            {
                this.systemObject.OnCachedSystemUpdated += OnSharedSystemRecompiled;
            }
            if (GlobalLSystemCoordinator.instance == null)
            {
                throw new Exception("No global l system coordinator singleton object. A single GlobalLSystemCoordinator must be present");
            }

            var lastHandle = globalResourceHandle;

            globalResourceHandle = GlobalLSystemCoordinator.instance.GetManagedResourceHandleFromSavedData(lastHandle, handleOwner);

            if (!useSharedSystem)
            {
                var newSystem = systemObject.CompileWithParameters(compiledGlobalCompiletimeReplacements);
                if (lSystemPendingCompletable != null)
                {
                    lSystemPendingCompletable.Cancel();
                }
                compiledSystem?.Dispose();
                compiledSystem = newSystem;
            }

            if (globalResourceHandle.uniqueIdOriginPoint != lastHandle.uniqueIdOriginPoint)
            {
                Debug.Log("global handle was changed when loading from save");
                // the unique ID origin point changed. therefore, the l-system must step again to update the IDs based on the serialized LastState
                //  this could be done faster with a simple ID update
                StepSystemAsync(runtimeParameters, repeatLast: true);
            }
        }
        /// <summary>
        /// Optionally Set to a different L-system, and reset the state and the current runtime parameters
        /// </summary>
        private void ResetState(
            LSystemState <float> newState,
            LSystemStepper newSystem)
        {
            if (lSystemPendingCompletable != null)
            {
                lSystemPendingCompletable.Cancel();
            }
            lastState?.currentSymbols.Dispose();
            lastState = null;
            currentState?.currentSymbols.Dispose();
            currentState = null;

            totalSteps        = 0;
            lastUpdateChanged = true;
            currentState      = newState;

            runtimeParameters = systemObject.GetRuntimeParameters();

            if (newSystem != null)
            {
                SetNewCompiledSystem(newSystem);
            }

            // clear out the next state handle. if an update is pending, just abort it.

            OnSystemStateUpdated?.Invoke();
        }
 private void SetNewCompiledSystem(LSystemStepper newSystem)
 {
     if (!useSharedSystem)
     {
         compiledSystem?.Dispose();
     }
     compiledSystem = newSystem;
 }
예제 #4
0
        public LSystemStepper CompileSystem(Dictionary <string, string> globalCompileTimeOverrides = null)
        {
            UnityEngine.Profiling.Profiler.BeginSample("L System compilation");

            var openSymbol  = GetSymbol(originFile, '[');
            var closeSymbol = GetSymbol(originFile, ']');

            var allReplacementDirectives = GetCompileTimeReplacementsWithOverrides(globalCompileTimeOverrides);

            var compiledRules = CompileAllRules(
                allReplacementDirectives,
                out var nativeRuleData,
                openSymbol, closeSymbol);

            var includedByFile = allFiles.data
                                 .Select(x => new HashSet <int>(x.GetAllIncludedContextualSymbols()))
                                 .ToArray();

            var customSymbols = new CustomRuleSymbols();

            customSymbols.branchOpenSymbol  = openSymbol;
            customSymbols.branchCloseSymbol = closeSymbol;

            foreach (var file in allFiles.data)
            {
                file.SetCustomRuleSymbols(ref customSymbols);
            }
            if (allReplacementDirectives.TryGetValue("diffusionStepsPerStep", out var defineValue))
            {
                if (!int.TryParse(defineValue, out var stepsPerStep))
                {
                    throw new LinkException(LinkExceptionType.BAD_GLOBAL_PARAMETER, $"global parameter 'diffusionStepsPerStep' is defined, but is not an integer. this parameter must be an integer: '{defineValue}'");
                }
                customSymbols.diffusionStepsPerStep = stepsPerStep;
            }
            customSymbols.independentDiffusionUpdate = false;
            customSymbols.diffusionConstantRuntimeGlobalMultiplier = 1f;
            if (allReplacementDirectives.TryGetValue("independentDiffusionStep", out defineValue))
            {
                if (!bool.TryParse(defineValue, out var stepsIndependent))
                {
                    throw new LinkException(LinkExceptionType.BAD_GLOBAL_PARAMETER, $"global parameter 'independentDiffusionStep' is defined, but is not a boolean. this parameter must be either 'true' or 'false': '{defineValue}'");
                }
                customSymbols.independentDiffusionUpdate = stepsIndependent;
            }

            var result = new LSystemStepper(
                compiledRules,
                nativeRuleData,
                customSymbols,
                expectedGlobalParameters: allGlobalRuntimeParams.Count,
                includedContextualCharactersByRuleIndex: includedByFile
                );

            UnityEngine.Profiling.Profiler.EndSample();
            return(result);
        }
예제 #5
0
        public void LoadFromFilePath(string filePath)
        {
            if (!string.IsNullOrWhiteSpace(filePath))
            {
                var linker = new FileLinker(new FileSystemFileProvider());
                linkedFiles = linker.LinkFiles(filePath);

                // compile the system right away and throw it out to catch any compile-time errors
                this.CompileToCached();
                compiledSystem?.Dispose();
                compiledSystem = null;
            }
        }
예제 #6
0
        /// <summary>
        /// Compile this L-system into the <see cref="compiledSystem"/> property
        /// </summary>
        /// <param name="globalCompileTimeOverrides">overrides to the compile time directives. Will only be applied if the Key matches an already defined compile time parameter</param>
        public void CompileToCached(Dictionary <string, string> globalCompileTimeOverrides = null, bool silent = false)
        {
            var newSystem = CompileSystem(globalCompileTimeOverrides);

            if (newSystem != null)
            {
                compiledSystem?.Dispose();
                compiledSystem = newSystem;

                if (!silent)
                {
                    OnCachedSystemUpdated?.Invoke();
                }
            }
        }
예제 #7
0
    public void RandomNumTest()
    {
        var indexCount = 100;
        var seedCount  = 100;

        var perfectDistribution = Enumerable.Range(0, 100).Select(x => x / 100d).StdDev(out var mean);

        var indexes   = Enumerable.Range(1, indexCount).Select(x => (uint)x);
        var randomGen = new System.Random(UnityEngine.Random.Range(0, int.MaxValue));
        var seeds     = Enumerable.Repeat(0, seedCount).Select((x) =>
        {
            return((uint)randomGen.Next(int.MinValue, int.MaxValue));
        });
        var randomByIndexesThenBySeed = indexes.Select(x =>
        {
            return(seeds.Select(seed =>
            {
                var r = LSystemStepper.RandomFromIndexAndSeed(x, seed);
                return r.NextUInt();
            }).ToArray());
        }).ToArray();

        var statsAcrossIndexes = Enumerable.Range(0, indexCount)
                                 .Select(index => randomByIndexesThenBySeed[index]
                                         .GetStats()
                                         ).ToArray().GetMetaStats();
        var statsAcrossSeeds = Enumerable.Range(0, seedCount)
                               .Select(index => randomByIndexesThenBySeed
                                       .Select(x => x[index])
                                       .ToList()
                                       .GetStats()
                                       ).ToArray().GetMetaStats();

        UnityEngine.Debug.Log($"perfect stdDev:{perfectDistribution:P1}");
        UnityEngine.Debug.Log($"stats across indexes:\n{statsAcrossIndexes}");
        UnityEngine.Debug.Log($"stats across seeds:\n{statsAcrossSeeds}");

        // ensure even distribution across seeds, and across indexes within seeds
        Assert.AreEqual(0, statsAcrossIndexes.minStats.MeanRel, 0.02);
        Assert.AreEqual(1, statsAcrossIndexes.maxStats.MeanRel, 0.02);
        Assert.AreEqual(0, statsAcrossIndexes.stdDevStats.StdDevRel, 0.02);
        Assert.AreEqual(perfectDistribution, statsAcrossIndexes.stdDevStats.MeanRel, 0.02);

        Assert.AreEqual(0, statsAcrossSeeds.minStats.MeanRel, 0.02);
        Assert.AreEqual(1, statsAcrossSeeds.maxStats.MeanRel, 0.02);
        Assert.AreEqual(0, statsAcrossSeeds.stdDevStats.StdDevRel, 0.02);
        Assert.AreEqual(perfectDistribution, statsAcrossSeeds.stdDevStats.MeanRel, 0.02);
    }
        public void Dispose()
        {
            if (useSharedSystem)
            {
                systemObject.OnCachedSystemUpdated -= OnSharedSystemRecompiled;
            }
            else
            {
                compiledSystem?.Dispose();
                compiledSystem = null;
            }
            lSystemPendingCompletable?.Cancel();
            lastState?.currentSymbols.Dispose();
            lastState = null;

            currentState?.currentSymbols.Dispose();
            currentState = null;

            globalResourceHandle.Dispose();
        }
예제 #9
0
    private void AssertStochasticResults(LSystemStepper system, string axiom, string[] expectedResults, float[] globalParams = null)
    {
        var resultSet     = new HashSet <string>();
        var attemptSeeder = new Unity.Mathematics.Random((uint)axiom.GetHashCode());
        var attempts      = expectedResults.Length * 10;

        for (int attempt = 1; attempt < attempts; attempt++)
        {
            LSystemState <float> state = new DefaultLSystemState(axiom, attemptSeeder.NextUInt());
            state = system.StepSystem(state, globalParams);
            resultSet.Add(state.currentSymbols.Data.ToString());
            state.currentSymbols.Dispose();
        }
        Assert.AreEqual(expectedResults.Length, resultSet.Count);
        for (int i = 0; i < expectedResults.Length; i++)
        {
            var expected = expectedResults[i];
            Assert.IsTrue(resultSet.Contains(expected), $"Generated states should contain stochastic result {expected}");
        }
    }
예제 #10
0
 private void OnDestroy()
 {
     compiledSystem?.Dispose();
     compiledSystem = null;
 }
예제 #11
0
 private void OnDisable()
 {
     compiledSystem?.Dispose();
     compiledSystem = null;
 }