예제 #1
0
        protected void ProcessMarkerOverrideVolumes()
        {
            var dungeon = GetComponent <Dungeon>();
            // Process the theme override volumes
            var replacementVolumes = GameObject.FindObjectsOfType <MarkerReplaceVolume>();

            foreach (var replacementVolume in replacementVolumes)
            {
                if (replacementVolume.dungeon == dungeon)
                {
                    // Fill up the prop sockets with the defined mesh data
                    for (int i = 0; i < propSockets.Count; i++)
                    {
                        PropSocket socket         = propSockets[i];
                        var        socketPosition = Matrix.GetTranslation(ref socket.Transform);
                        if (replacementVolume.GetBounds().Contains(socketPosition))
                        {
                            foreach (var replacementEntry in replacementVolume.replacements)
                            {
                                if (socket.SocketType == replacementEntry.fromMarker)
                                {
                                    socket.SocketType = replacementEntry.toMarker;
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #2
0
        public static void DrawMarker(PropSocket marker, Color color)
        {
            var start = Matrix.GetTranslation(ref marker.Transform);
            var end   = start + new Vector3(0, 0.2f, 0);

            Debug.DrawLine(start, end, color);
        }
예제 #3
0
        public override void Remove(PropSocket marker)
        {
            base.Remove(marker);

            var partitionCoord = GetBucketCoord(marker);

            if (buckets.ContainsKey(partitionCoord))
            {
                buckets[partitionCoord].Remove(marker);
            }
        }
예제 #4
0
        public override void Add(PropSocket marker)
        {
            base.Add(marker);

            var partitionCoord = GetBucketCoord(marker);

            if (!buckets.ContainsKey(partitionCoord))
            {
                buckets.Add(partitionCoord, new List <PropSocket>());
            }
            buckets[partitionCoord].Add(marker);
        }
예제 #5
0
 void RecursivelyTagMarkerForDeletion(PropSocket marker, HashSet <int> visited)
 {
     visited.Add(marker.Id);
     marker.markForDeletion = true;
     foreach (var childMarker in marker.childMarkers)
     {
         if (!visited.Contains(childMarker.Id))
         {
             RecursivelyTagMarkerForDeletion(childMarker, visited);
         }
     }
 }
예제 #6
0
        protected void EmitMarker(List <PropSocket> pPropSockets, string SocketType, Matrix4x4 transform, IntVector gridPosition, int cellId)
        {
            PropSocket socket = new PropSocket();

            socket.Id           = ++_SocketIdCounter;
            socket.IsConsumed   = false;
            socket.SocketType   = SocketType;
            socket.Transform    = transform;
            socket.gridPosition = gridPosition;
            socket.cellId       = cellId;
            pPropSockets.Add(socket);
        }
예제 #7
0
        public PropSocket EmitMarker(string SocketType, Matrix4x4 transform, IntVector gridPosition, int cellId)
        {
            PropSocket socket = new PropSocket();

            socket.Id           = ++_SocketIdCounter;
            socket.IsConsumed   = false;
            socket.SocketType   = SocketType;
            socket.Transform    = transform;
            socket.gridPosition = gridPosition;
            socket.cellId       = cellId;
            PropSockets.Add(socket);
            return(socket);
        }
예제 #8
0
        protected virtual bool ProcessSpatialConstraint(SpatialConstraintProcessor constraintProcessor, SpatialConstraintAsset constraint, PropSocket socket, out Matrix4x4 OutOffset, out PropSocket[] outMarkersToRemove)
        {
            if (constraintProcessor == null)
            {
                OutOffset          = Matrix4x4.identity;
                outMarkersToRemove = new PropSocket[0];
                return(false);
            }
            var context = new SpatialConstraintProcessorContext();

            context.constraintAsset = constraint;
            context.marker          = socket;
            context.model           = model;
            context.config          = config;
            context.builder         = this;
            context.levelMarkers    = propSockets;
            return(constraintProcessor.ProcessSpatialConstraint(context, out OutOffset, out outMarkersToRemove));
        }
예제 #9
0
 /// <summary>
 /// Implementations should override this and determine if the node should be selected (inserted into the scene)
 /// </summary>
 /// <param name="socket">The marker data-structure</param>
 /// <param name="propTransform">The combined transform of the visual node that invoked this rule</param>
 /// <param name="model">The dungeon model</param>
 /// <param name="random">The random stream used by the builder. User this random stream for any randomness for consistancy</param>
 /// <returns></returns>
 public virtual bool CanSelect(PropSocket socket, Matrix4x4 propTransform, DungeonModel model, System.Random random)
 {
     return(true);
 }
예제 #10
0
        IntVector2 GetBucketCoord(PropSocket marker)
        {
            var position = Matrix.GetTranslation(ref marker.Transform);

            return(GetBucketCoord(position.x, position.z));
        }
예제 #11
0
 /// <summary>
 /// Implement this method to provide a transform based on your logic.
 /// </summary>
 /// <param name="socket">The marker data structure</param>
 /// <param name="model">The dungeon model</param>
 /// <param name="propTransform">The combined transform of the visual node that invoked this rule</param>
 /// <param name="random">The random stream used by the builder. User this random stream for any randomness for consistancy</param>
 /// <param name="outPosition">Set your position offset here</param>
 /// <param name="outRotation">Set your rotation offset here</param>
 /// <param name="outScale">Set your scale offset here</param>
 public virtual void GetTransform(PropSocket socket, DungeonModel model, Matrix4x4 propTransform, System.Random random, out Vector3 outPosition, out Quaternion outRotation, out Vector3 outScale)
 {
     outPosition = Vector3.zero;
     outRotation = Quaternion.identity;
     outScale    = Vector3.one;
 }
예제 #12
0
        public virtual void ApplyTheme(List <DungeonPropDataAsset> Themes, DungeonSceneProvider SceneProvider,
                                       IDungeonSceneObjectInstantiator objectInstantiator)
        {
            var instanceCache       = new InstanceCache();
            var constraintProcessor = GetComponent <SpatialConstraintProcessor>();

            PropBySocketTypeByTheme_t PropBySocketTypeByTheme = new PropBySocketTypeByTheme_t();

            foreach (DungeonPropDataAsset Theme in Themes)
            {
                CreatePropLookup(Theme, PropBySocketTypeByTheme);
            }

            // Collect all the theme override volumes and prepare their theme lookup
            var overrideVolumes = new List <ThemeOverrideVolume>();
            Dictionary <Graph, DungeonPropDataAsset> GraphToThemeMapping = new Dictionary <Graph, DungeonPropDataAsset>();

            var dungeon = GetComponent <Dungeon>();

            // Process the theme override volumes
            var themeOverrides = GameObject.FindObjectsOfType <ThemeOverrideVolume>();

            foreach (var volume in themeOverrides)
            {
                if (volume.dungeon != dungeon)
                {
                    continue;
                }

                overrideVolumes.Add(volume);
                var graph = volume.overrideTheme;
                if (graph != null && !GraphToThemeMapping.ContainsKey(graph))
                {
                    DungeonPropDataAsset theme = new DungeonPropDataAsset();
                    theme.BuildFromGraph(volume.overrideTheme);
                    GraphToThemeMapping.Add(volume.overrideTheme, theme);

                    CreatePropLookup(theme, PropBySocketTypeByTheme);
                }
            }

            var srandom = new PMRandom(config.Seed);

            var nodesExecutionContext = new NodeListExecutionContext();

            nodesExecutionContext.instanceCache       = instanceCache;
            nodesExecutionContext.constraintProcessor = constraintProcessor;
            nodesExecutionContext.srandom             = srandom;
            nodesExecutionContext.SceneProvider       = SceneProvider;
            nodesExecutionContext.objectInstantiator  = objectInstantiator;

            var spawnDataList = new List <NodeSpawnData>();

            var delayedExecutionList = new Queue <NodeListExecutionData>();

            // Fill up the prop sockets with the defined mesh data
            for (int i = 0; i < PropSockets.Count; i++)
            {
                PropSocket socket = PropSockets[i];
                if (!socket.markForDeletion)
                {
                    DungeonPropDataAsset themeToUse = GetBestMatchedTheme(Themes, socket, PropBySocketTypeByTheme); // PropAsset;

                    // Check if this socket resides within a override volume
                    {
                        var socketPosition = Matrix.GetTranslation(ref socket.Transform);
                        foreach (var volume in overrideVolumes)
                        {
                            if (volume.GetBounds().Contains(socketPosition))
                            {
                                var graph = volume.overrideTheme;
                                if (graph != null && GraphToThemeMapping.ContainsKey(graph))
                                {
                                    themeToUse = GraphToThemeMapping[volume.overrideTheme];
                                    break;
                                }
                            }
                        }
                    }

                    if (themeToUse != null)
                    {
                        PropBySocketType_t PropBySocketType = PropBySocketTypeByTheme[themeToUse];
                        if (PropBySocketType.ContainsKey(socket.SocketType))
                        {
                            var data = new NodeListExecutionData();
                            data.socket       = socket;
                            data.nodeDataList = PropBySocketType[socket.SocketType];

                            if (ShouldDelayExecution(data.nodeDataList))
                            {
                                delayedExecutionList.Enqueue(data);
                            }
                            else
                            {
                                ExecuteNodesUnderMarker(data, nodesExecutionContext, spawnDataList);
                            }
                        }
                    }
                }

                // We execute the delayed node list (that have spatial constraints) at the very end of the list
                // Each execution of the delayed node however, can add more items to this list
                bool isLastIndex = (i == PropSockets.Count - 1);
                while (isLastIndex && delayedExecutionList.Count > 0)
                {
                    var data = delayedExecutionList.Dequeue();
                    if (!data.socket.markForDeletion)
                    {
                        ExecuteNodesUnderMarker(data, nodesExecutionContext, spawnDataList);
                    }

                    isLastIndex = (i == PropSockets.Count - 1);
                }
            }

            RecursivelyTagMarkersForDeletion();

            // Spawn the items
            foreach (var spawnData in spawnDataList)
            {
                if (spawnData.socket.markForDeletion)
                {
                    continue;
                }

                SpawnNodeItem(spawnData, nodesExecutionContext);
            }
        }
예제 #13
0
        // Picks a theme from the list that has a definition for the defined socket
        protected DungeonPropDataAsset GetBestMatchedTheme(List <DungeonPropDataAsset> Themes, PropSocket socket, PropBySocketTypeByTheme_t PropBySocketTypeByTheme)
        {
            var ValidThemes = new List <DungeonPropDataAsset>();

            foreach (DungeonPropDataAsset Theme in Themes)
            {
                if (PropBySocketTypeByTheme.ContainsKey(Theme))
                {
                    PropBySocketType_t PropBySocketType = PropBySocketTypeByTheme[Theme];
                    if (PropBySocketType.Count > 0)
                    {
                        if (PropBySocketType.ContainsKey(socket.SocketType) && PropBySocketType[socket.SocketType].Count > 0)
                        {
                            ValidThemes.Add(Theme);
                        }
                    }
                }
            }
            if (ValidThemes.Count == 0)
            {
                return(null);
            }

            int index = Mathf.FloorToInt(random.GetNextUniformFloat() * ValidThemes.Count) % ValidThemes.Count;

            return(ValidThemes[index]);
        }
예제 #14
0
        public virtual void ApplyTheme(List <DungeonPropDataAsset> Themes, DungeonSceneProvider SceneProvider)
        {
            var instanceCache       = new InstanceCache();
            var constraintProcessor = GetComponent <SpatialConstraintProcessor>();

            if (constraintProcessor != null)
            {
                constraintProcessor.Initialize(model, propSockets);
            }

            PropBySocketTypeByTheme_t PropBySocketTypeByTheme = new PropBySocketTypeByTheme_t();

            foreach (DungeonPropDataAsset Theme in Themes)
            {
                CreatePropLookup(Theme, PropBySocketTypeByTheme);
            }

            // Collect all the theme override volumes and prepare their theme lookup
            var overrideVolumes = new List <ThemeOverrideVolume>();
            Dictionary <Graph, DungeonPropDataAsset> GraphToThemeMapping = new Dictionary <Graph, DungeonPropDataAsset>();

            var dungeon = GetComponent <Dungeon>();

            // Process the theme override volumes
            var themeOverrides = GameObject.FindObjectsOfType <ThemeOverrideVolume>();

            foreach (var themeOverride in themeOverrides)
            {
                if (themeOverride.dungeon != dungeon)
                {
                    continue;
                }

                overrideVolumes.Add(themeOverride);
                var graph = themeOverride.overrideTheme;
                if (graph != null && !GraphToThemeMapping.ContainsKey(graph))
                {
                    DungeonPropDataAsset theme = new DungeonPropDataAsset();
                    theme.BuildFromGraph(themeOverride.overrideTheme);
                    GraphToThemeMapping.Add(themeOverride.overrideTheme, theme);

                    CreatePropLookup(theme, PropBySocketTypeByTheme);
                }
            }

            var srandom = new PMRandom(config.Seed);

            // Fill up the prop sockets with the defined mesh data
            for (int i = 0; i < PropSockets.Count; i++)
            {
                PropSocket socket = PropSockets[i];

                DungeonPropDataAsset ThemeToUse = GetBestMatchedTheme(Themes, socket, PropBySocketTypeByTheme); // PropAsset;

                // Check if this socket resides within a override volume
                {
                    var socketPosition = Matrix.GetTranslation(ref socket.Transform);
                    foreach (var volume in overrideVolumes)
                    {
                        if (volume.GetBounds().Contains(socketPosition))
                        {
                            var graph = volume.overrideTheme;
                            if (graph != null && GraphToThemeMapping.ContainsKey(graph))
                            {
                                ThemeToUse = GraphToThemeMapping[volume.overrideTheme];
                                break;
                            }
                        }
                    }
                }

                if (ThemeToUse == null)
                {
                    continue;
                }

                PropBySocketType_t PropBySocketType = PropBySocketTypeByTheme[ThemeToUse];

                if (PropBySocketType.ContainsKey(socket.SocketType))
                {
                    List <PropTypeData> props = PropBySocketType[socket.SocketType];
                    foreach (PropTypeData prop in props)
                    {
                        bool      insertMesh = false;
                        Matrix4x4 transform  = socket.Transform * prop.Offset;

                        if (prop.UseSelectionRule && prop.SelectorRuleClassName != null)
                        {
                            var selectorRule = instanceCache.GetInstance(prop.SelectorRuleClassName) as SelectorRule;
                            if (selectorRule != null)
                            {
                                // Run the selection rule logic to determine if we need to insert this mesh in the scene
                                insertMesh = selectorRule.CanSelect(socket, transform, model, random.UniformRandom);
                            }
                        }
                        else
                        {
                            // Perform probability based selection logic
                            float probability = srandom.GetNextUniformFloat();
                            insertMesh = (probability < prop.Affinity);
                        }

                        if (insertMesh && prop.useSpatialConstraint && prop.spatialConstraint != null)
                        {
                            Matrix4x4 spatialOffset;
                            if (!ProcessSpatialConstraint(constraintProcessor, prop.spatialConstraint, socket, out spatialOffset))
                            {
                                // Fails spatial constraint
                                insertMesh = false;
                            }
                            else
                            {
                                // Apply the offset
                                var markerOffset = socket.Transform;
                                if (prop.spatialConstraint != null && !prop.spatialConstraint.applyMarkerRotation)
                                {
                                    var markerPosition = Matrix.GetTranslation(ref markerOffset);
                                    var markerScale    = Matrix.GetScale(ref markerOffset);
                                    markerOffset = Matrix4x4.TRS(markerPosition, Quaternion.identity, markerScale);
                                }
                                transform = markerOffset * spatialOffset * prop.Offset;
                            }
                        }

                        if (insertMesh)
                        {
                            // Attach this prop to the socket
                            // Apply transformation logic, if specified
                            if (prop.UseTransformRule && prop.TransformRuleClassName != null && prop.TransformRuleClassName.Length > 0)
                            {
                                var transformer = instanceCache.GetInstance(prop.TransformRuleClassName) as TransformationRule;
                                if (transformer != null)
                                {
                                    Vector3    _position, _scale;
                                    Quaternion _rotation;
                                    transformer.GetTransform(socket, model, transform, random.UniformRandom, out _position, out _rotation, out _scale);
                                    var offset = Matrix4x4.TRS(_position, _rotation, _scale);
                                    transform = transform * offset;
                                }
                            }

                            if (prop is GameObjectPropTypeData)
                            {
                                var gameObjectProp = prop as GameObjectPropTypeData;
                                SceneProvider.AddGameObject(gameObjectProp, transform);
                            }
                            else if (prop is GameObjectArrayPropTypeData)
                            {
                                var gameObjectArrayProp = prop as GameObjectArrayPropTypeData;
                                int count = gameObjectArrayProp.Templates.Length;
                                int index = Mathf.FloorToInt(random.GetNextUniformFloat() * count) % count;
                                SceneProvider.AddGameObjectFromArray(gameObjectArrayProp, index, transform);
                            }
                            else if (prop is SpritePropTypeData)
                            {
                                var spriteProp = prop as SpritePropTypeData;
                                SceneProvider.AddSprite(spriteProp, transform);
                            }
                            // TODO: Handle light creation


                            // Add child sockets if any
                            foreach (PropChildSocketData ChildSocket in prop.ChildSockets)
                            {
                                Matrix4x4 childTransform = transform * ChildSocket.Offset;
                                EmitMarker(ChildSocket.SocketType, childTransform, socket.gridPosition, socket.cellId);
                            }

                            if (prop.ConsumeOnAttach)
                            {
                                // Attach no more on this socket
                                break;
                            }
                        }
                    }
                }
            }

            if (constraintProcessor != null)
            {
                constraintProcessor.Cleanup();
            }
        }
예제 #15
0
        protected virtual bool ProcessSpatialConstraint(SpatialConstraintProcessor constraintProcessor, SpatialConstraint constraint, PropSocket socket, out Matrix4x4 OutOffset)
        {
            if (constraintProcessor == null)
            {
                OutOffset = Matrix4x4.identity;
                return(false);
            }

            return(constraintProcessor.ProcessSpatialConstraint(constraint, socket, model, propSockets, out OutOffset));
        }