Exemplo n.º 1
0
        /// <summary>
        /// Resolves a template by either loading it from a file or by picking a sub-template from the current context.
        /// Logs a warning and returns null if the specified template could not be resolved.
        /// </summary>
        private MapTemplate ResolveTemplate(string mapPath, string templateName, InstantiationContext context)
        {
            if (mapPath != null)
            {
                Logger.Verbose($"Resolving map template '{mapPath}'.");

                // We support both absolute and relative paths. Relative paths are relative to the map that a template is being inserted into.
                if (!Path.IsPathRooted(mapPath))
                {
                    mapPath = Path.Combine(context.CurrentWorkingDirectory, mapPath);
                }

                try
                {
                    // TODO: If no extension is specified, use a certain preferential order (.rmf, .map, ...)? ...
                    return(GetMapTemplate(mapPath, context.Globals));
                }
                catch (Exception ex)
                {
                    Logger.Warning($"Failed to load map template '{mapPath}':", ex);
                    return(null);
                }
            }
            else if (templateName != null)
            {
                Logger.Verbose($"Resolving sub-template '{templateName}'.");

                // We'll look for sub-templates in the closest parent context whose template has been loaded from a map file.
                // If there are multiple matches, we'll pick one at random. If there are no matches, we'll fall through and return null.
                var matchingSubTemplates = context.SubTemplates
                                           .Where(subTemplate => context.EvaluateInterpolatedString(subTemplate.Name) == templateName)
                                           .Select(subTemplate => new {
                    SubTemplate = subTemplate,
                    Weight      = double.TryParse(context.EvaluateInterpolatedString(subTemplate.SelectionWeightExpression), NumberStyles.Float, CultureInfo.InvariantCulture, out var weight) ? weight : 0
                })
Exemplo n.º 2
0
        // TODO: If 'angles' and 'scale' are missing, that could cause issues...? But what if we always insert them,
        //       could that also be problematic in different situations?
        /// <summary>
        /// Creates a copy of this entity. The copy is scaled, rotated and translated,
        /// and by default any expressions in its properties will be evaluated.
        /// If it contains 'angles' and 'scale' properties, then these will be updated according to how the entity has been transformed.
        /// Ignores VIS-group and group relationships.
        /// </summary>
        public static Entity Copy(this Entity entity, InstantiationContext context, bool applyTransform = true, bool evaluateExpressions = true)
        {
            var transform = applyTransform ? context.Transform : Transform.Identity;
            var copy      = new Entity(entity.Brushes.Select(brush => brush.Copy(transform)));

            if (evaluateExpressions)
            {
                foreach (var kv in entity.Properties)
                {
                    copy.Properties[context.EvaluateInterpolatedString(kv.Key)] = context.EvaluateInterpolatedString(kv.Value);
                }

                UpdateSpawnFlags(copy);
            }
            else
            {
                foreach (var kv in entity.Properties)
                {
                    copy.Properties[kv.Key] = kv.Value;
                }
            }

            if (applyTransform)
            {
                // TODO: Also check whether maybe the angles/scale keys do exist, but contain invalid values!
                if (copy.Angles is Angles angles)
                {
                    copy.Angles = (angles.ToMatrix() * context.Transform.Rotation).ToAngles();
                }

                if (copy.Scale is double scale)
                {
                    copy.Scale = scale * context.Transform.Scale;
                }

                if (copy.IsPointBased)
                {
                    copy.Origin = ApplyTransform(copy.Origin, context.Transform);
                }
            }

            return(copy);
        }