Example #1
0
        protected void CreatePropLookup(DungeonPropDataAsset PropAsset, PropBySocketTypeByTheme_t PropBySocketTypeByTheme)
        {
            if (PropAsset == null || PropBySocketTypeByTheme.ContainsKey(PropAsset))
            {
                // Lookup for this theme has already been built
                return;
            }

            PropBySocketType_t PropBySocketType = new PropBySocketType_t();

            PropBySocketTypeByTheme.Add(PropAsset, PropBySocketType);

            foreach (PropTypeData Prop in PropAsset.Props)
            {
                if (!PropBySocketType.ContainsKey(Prop.AttachToSocket))
                {
                    PropBySocketType.Add(Prop.AttachToSocket, new List <PropTypeData>());
                }
                PropBySocketType[Prop.AttachToSocket].Add(Prop);
            }
        }
Example #2
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);
            }
        }
Example #3
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]);
        }
Example #4
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();
            }
        }