private static Vector3D GetTemplateEntityOrigin(Entity templateEntity, EvaluationContext context) { if (!Enum.TryParse <TemplateAreaAnchor>(Evaluation.EvaluateInterpolatedString(templateEntity.GetStringProperty(Attributes.Anchor), context), out var anchor)) { anchor = TemplateAreaAnchor.OriginBrush; } if (anchor == TemplateAreaAnchor.OriginBrush) { if (templateEntity.GetOrigin() is Vector3D origin) { return(origin); } } // NOTE: The bottom anchor point is our default fallback for when there's no origin brush. switch (anchor) { default: case TemplateAreaAnchor.Bottom: return(new Vector3D(templateEntity.BoundingBox.Center.X, templateEntity.BoundingBox.Center.Y, templateEntity.BoundingBox.Min.Z)); case TemplateAreaAnchor.Center: return(templateEntity.BoundingBox.Center); case TemplateAreaAnchor.Top: return(new Vector3D(templateEntity.BoundingBox.Center.X, templateEntity.BoundingBox.Center.Y, templateEntity.BoundingBox.Max.Z)); } }
public InstantiationContext( MapTemplate template, ILogger logger, Transform transform = null, IDictionary <string, string> insertionEntityProperties = null, InstantiationContext parentContext = null, string workingDirectory = null, IDictionary <string, object> globals = null, int sequenceNumber = 0) { // Every context uses its own PRNG. Seeding is done automatically, but can be done explicitly // by adding a 'random_seed' attribute to the inserting entity (or to the map properties, for the root context). // NOTE: even with explicit seeding, a random value is always obtained from the parent context. // This ensures that switching between explicit and implicit seeding does not result in 'sibling' contexts // getting different seed values. var randomSeed = parentContext?._random.Next() ?? 0; if (insertionEntityProperties?.GetNumericProperty(Attributes.RandomSeed) is double seed) { randomSeed = (int)seed; } _random = new Random(randomSeed); _logger = logger; _insertionEntityProperties = insertionEntityProperties; _parentContext = parentContext; ID = GetRootContext()._nextID++; SequenceNumber = sequenceNumber; RecursionDepth = (parentContext?.RecursionDepth ?? -1) + 1; Template = template; CurrentWorkingDirectory = workingDirectory ?? Path.GetDirectoryName(GetNearestMapFileContext().Template.Name); SubTemplates = GetNearestMapFileContext().Template.SubTemplates; Transform = transform ?? Transform.Identity; Globals = globals ?? parentContext?.Globals ?? new Dictionary <string, object>(); var outerEvaluationContext = Evaluation.ContextFromProperties(insertionEntityProperties, ID, SequenceNumber, _random, Globals, _logger); var evaluatedTemplateProperties = template.Map.Properties.ToDictionary( kv => Evaluation.EvaluateInterpolatedString(kv.Key, outerEvaluationContext), kv => PropertyExtensions.ParseProperty(Evaluation.EvaluateInterpolatedString(kv.Value, outerEvaluationContext))); _evaluationContext = new EvaluationContext(evaluatedTemplateProperties, outerEvaluationContext); // Every instantiation is written to the same map, but with a different transform: OutputMap = parentContext?.OutputMap; if (OutputMap == null) { // Copy original map properties: OutputMap = new Map(); foreach (var kv in evaluatedTemplateProperties) { OutputMap.Properties[kv.Key] = Interpreter.Print(kv.Value); } } }
private void ApplyRewriteRule(Dictionary <string, string> entityProperties, RewriteDirective.Rule rule, EvaluationContext context) { var attributeName = Evaluation.EvaluateInterpolatedString(rule.Attribute, context); if (rule.DeleteAttribute) { entityProperties.Remove(attributeName); context.Bind(attributeName, null); } else { var value = Evaluation.EvaluateInterpolatedString(rule.NewValue, context); entityProperties[attributeName] = value; context.Bind(attributeName, value); } }
private void ApplyRewriteDirective(Dictionary <string, string> entityProperties, RewriteDirective rewriteDirective, int entityID, Random random, IDictionary <string, object> globals) { var context = Evaluation.ContextFromProperties(entityProperties, entityID, entityID, random, globals, Logger); NativeUtils.RegisterInstanceMethods(context, _directoryFunctions); foreach (var ruleGroup in rewriteDirective.RuleGroups) { if (!ruleGroup.HasCondition || Interpreter.IsTrue(PropertyExtensions.ParseProperty(Evaluation.EvaluateInterpolatedString(ruleGroup.Condition, context)))) { foreach (var rule in ruleGroup.Rules) { ApplyRewriteRule(entityProperties, rule, context); } } else if (ruleGroup.HasCondition) { foreach (var rule in ruleGroup.AlternateRules) { ApplyRewriteRule(entityProperties, rule, context); } } } }
/// <summary> /// Calls <see cref="Evaluation.EvaluateInterpolatedString(string, EvaluationContext)"/>, using this instance's evaluation context. /// </summary> public string EvaluateInterpolatedString(string interpolatedString) => Evaluation.EvaluateInterpolatedString(interpolatedString, _evaluationContext);