// Parse the sentence, load symbol implementations and find the next module to execute. // One module is executed at a time, and an internal pointer is adjusted to for the next iteration. public bool ProcessNextModule(Module previous, Sentence sentence, SerializableDictionary <char, GameObject> implementation, RuleSet rules, ParameterBundle bundle, bool baked) { if (dead) { return(false); } Profiler.BeginSample("LSystem.Module.ProcessNextModule"); GameObject module; char symbol = '\0'; do { if (!sentence.HasNext()) { sentence = rules.NextGeneration(sentence); if (!bundle.Set("Sentence", sentence)) { Debug.LogError("Cannot set 'Sentence' parameter in GetAndExecuteModule", gameObject); } int generation; int iterations; if (bundle.Get("Generation", out generation)) { generation++; if (bundle.Get("Iterations", out iterations)) { if (generation > iterations) { //Max iterations reached. return(false); } } if (!bundle.Set("Generation", generation)) { Debug.LogError("Cannot set 'Generation' parameter in GetAndExecuteModule", gameObject); } } else { Debug.LogError("Cannot get 'Generation' parameter in GetAndExecuteModule", gameObject); } } symbol = sentence.Next(); if (symbol == '\0') { return(false); //Sentence is empty! Caused if rules do not generate anything from previous } } while (!implementation.TryGetValue(symbol, out module)); KeyValuePair <GameObject, Sentence> newPair = new KeyValuePair <GameObject, Sentence>(module, sentence); Profiler.EndSample(); ExecuteModule(previous, newPair, bundle, symbol, baked); return(true); }
/// <summary> /// Merge multiple ParameterBundles into one. Note that parameters with the same key will override each other and parameters with the same key but different value will be ignored /// </summary> /// <param name="bundles"></param> /// <returns></returns> public static ParameterBundle Merge(List <ParameterBundle> bundles) { ParameterBundle merged = new ParameterBundle(); foreach (ParameterBundle bundle in bundles) { foreach (KeyValuePair <string, object> pair in bundle.parameters) { if (!merged.Set(pair.Key, pair.Value)) { merged.Put(pair.Key, pair.Value); } } } return(merged); }
// Encapsulates common functionality between Bake and Execute. protected void AnyExecute(ParameterBundle bundle) { //try get relevant prams. bool fatal = false; Sentence sentence; CharGameObjectDict implementations; RuleSet rules; if (!GetCoreParameters(bundle, out sentence, out implementations, out rules)) { fatal = true; } // Perform rotation on transform based. // Note that many rotations are not easily possible with this method. Needs to be improved. Quaternion rotation; if (bundle.Get("Rotation", out rotation)) { //apply pitch yaw and roll to the rotation rotation = rotation * Quaternion.Euler(new Vector3(Random.Range(eulerAnglesMin.x, eulerAnglesMax.x), Random.Range(eulerAnglesMin.y, eulerAnglesMax.y), Random.Range(eulerAnglesMin.z, eulerAnglesMax.z))); bundle.Set("Rotation", rotation); } else { Debug.LogWarning("Default parameter 'Rotation' missing. Skipping Rotation", gameObject); } if (!fatal) { //Call next module if (baked) { BakeNextModule(transform, sentence, implementations, rules, bundle); } else { EnqueueProcessNextModule(transform, sentence, implementations, rules, bundle); } } Destroy(gameObject); //once rotation and next module clled we can destroy the object. }