Пример #1
0
        void ExecuteNodesUnderMarker(NodeListExecutionData data, NodeListExecutionContext context, List <NodeSpawnData> spawnDataList)
        {
            var socket       = data.socket;
            var nodeDataList = data.nodeDataList;

            foreach (PropTypeData nodeData in nodeDataList)
            {
                bool      insertMesh = false;
                Matrix4x4 transform  = socket.Transform * nodeData.Offset;

                if (nodeData.UseSelectionRule && nodeData.SelectorRuleClassName != null)
                {
                    var selectorRule = context.instanceCache.GetInstance(nodeData.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 = context.srandom.GetNextUniformFloat();
                    insertMesh = (probability < nodeData.Affinity);
                }

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

                        foreach (var markerToRemove in markersToRemove)
                        {
                            markerToRemove.markForDeletion = true;
                        }
                    }
                }

                if (insertMesh)
                {
                    // Attach this prop to the socket
                    // Apply transformation logic, if specified
                    if (nodeData.UseTransformRule && nodeData.TransformRuleClassName != null && nodeData.TransformRuleClassName.Length > 0)
                    {
                        var transformer = context.instanceCache.GetInstance(nodeData.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;
                        }
                    }

                    // Create a spawn request
                    var spawnData = new NodeSpawnData();
                    spawnData.nodeData  = nodeData;
                    spawnData.transform = transform;
                    spawnData.socket    = socket;
                    spawnDataList.Add(spawnData);

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

                    if (nodeData.ConsumeOnAttach)
                    {
                        // Attach no more on this socket
                        break;
                    }
                }
            }
        }
Пример #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);
            }
        }