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; }
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); }
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; } }
/// <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(); } } }
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(); }
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}"); } }
private void OnDestroy() { compiledSystem?.Dispose(); compiledSystem = null; }
private void OnDisable() { compiledSystem?.Dispose(); compiledSystem = null; }