Пример #1
0
        public void Build(IDungeonSceneObjectInstantiator objectInstantiator)
        {
            NotifyPreBuild();

            Initialize();
            dungeonModel.ResetModel();

            dungeonBuilder.BuildDungeon(config, dungeonModel);
            markers = dungeonBuilder.PropSockets;

            NotifyPostLayoutBuild();

            if (dungeonBuilder.IsThemingSupported())
            {
                ReapplyTheme(objectInstantiator);
            }
            else
            {
                dungeonBuilder.BuildNonThemedDungeon(sceneProvider, objectInstantiator);
            }

            // Build the navigation
            var navigation = GetComponent <DungeonRuntimeNavigation>();

            if (navigation != null)
            {
                navigation.BuildNavMesh();
            }

            NotifyPostBuild();
        }
Пример #2
0
        /// <summary>
        /// Runs the theming engine over the existing layout to rebuild the game objects from the theme file.
        /// The layout is not built in this stage
        /// </summary>
        public void ReapplyTheme(IDungeonSceneObjectInstantiator objectInstantiator)
        {
            // Emit markers defined by this builder
            dungeonBuilder.EmitMarkers();

            // Emit markers defined by the users (by attaching implementation of DungeonMarkerEmitter behaviors)
            dungeonBuilder.EmitCustomMarkers();

            NotifyMarkersEmitted(dungeonBuilder.PropSockets);

            var themes = GetThemeAssets();

            sceneProvider.OnDungeonBuildStart();

            dungeonBuilder.ApplyTheme(themes, sceneProvider, objectInstantiator);

            sceneProvider.OnDungeonBuildStop();
        }
Пример #3
0
 // This is called by the builders that do not support theming
 public virtual void BuildNonThemedDungeon(DungeonSceneProvider sceneProvider, IDungeonSceneObjectInstantiator objectInstantiator)
 {
 }
Пример #4
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);
            }
        }
Пример #5
0
        public override GameObject AddSprite(SpritePropTypeData spriteProp, Matrix4x4 transform, IDungeonSceneObjectInstantiator objectInstantiator)
        {
            if (spriteProp == null)
            {
                return(null);
            }
            string NodeId = spriteProp.NodeId;

            if (spriteProp.sprite == null)
            {
                return(null);
            }

            FlipSpriteTransform(ref transform, spriteProp.sprite);

            GameObject item = null;

            // Try to reuse an object from the pool
            if (pooledObjects.ContainsKey(NodeId) && pooledObjects [NodeId].Count > 0)
            {
                item = pooledObjects [NodeId].Dequeue();
                SetTransform(item.transform, transform);
            }
            else
            {
                // Pool is exhausted for this object
                item = BuildSpriteObject(spriteProp, transform, NodeId);
            }
            item.isStatic = spriteProp.IsStaticObject;

            return(item);
        }
Пример #6
0
        public override GameObject AddGameObjectFromArray(GameObjectArrayPropTypeData gameObjectArrayProp, int index, Matrix4x4 transform, IDungeonSceneObjectInstantiator objectInstantiator)
        {
            if (gameObjectArrayProp == null)
            {
                return(null);
            }
            string NodeId = gameObjectArrayProp.NodeId + "_" + index.ToString();

            // If we are in 2D mode, then flip the YZ axis
            {
                var mode2D = false;
                if (config != null)
                {
                    mode2D = config.Mode2D;
                }
                if (mode2D)
                {
                    var position = Matrix.GetTranslation(ref transform);
                    FlipSpritePosition(ref position);
                    Matrix.SetTranslation(ref transform, position);
                }
            }

            GameObject item = null;

            // Try to reuse an object from the pool
            if (pooledObjects.ContainsKey(NodeId) && pooledObjects [NodeId].Count > 0)
            {
                item = pooledObjects [NodeId].Dequeue();
                SetTransform(item.transform, transform);
            }
            else
            {
                // Pool is exhausted for this object
                item = BuildGameObjectFromArray(gameObjectArrayProp, index, transform, objectInstantiator);
            }

            item.isStatic = gameObjectArrayProp.IsStaticObject;
            if (gameObjectArrayProp.IsStaticObject)
            {
                RecursivelySetStatic(item.transform);
            }

            return(item);
        }
Пример #7
0
 protected GameObject BuildGameObject(GameObjectPropTypeData gameObjectProp, Matrix4x4 transform, IDungeonSceneObjectInstantiator objectInstantiator)
 {
     return(BuildGameObject(gameObjectProp.Template, gameObjectProp.NodeId, gameObjectProp.affectsNavigation, transform, objectInstantiator));
 }
Пример #8
0
 /// <summary>
 /// Request the creation of a sprite object
 /// </summary>
 /// <param name="spriteProp">The sprite game object template reference</param>
 /// <param name="transform">The transform of the prop</param>
 public virtual GameObject AddSprite(SpritePropTypeData spriteProp, Matrix4x4 transform, IDungeonSceneObjectInstantiator objectInstantiator)
 {
     return(null);
 }
Пример #9
0
 /// <summary>
 /// Requests the creation of a game object from the provided list
 /// </summary>
 /// <returns>The game object from array.</returns>
 /// <param name="gameObjectArrayProp">Game object array property.</param>
 /// <param name="index">Index.</param>
 /// <param name="transform">Transform.</param>
 public virtual GameObject AddGameObjectFromArray(GameObjectArrayPropTypeData gameObjectArrayProp, int index, Matrix4x4 transform, IDungeonSceneObjectInstantiator objectInstantiator)
 {
     return(null);
 }
Пример #10
0
        protected GameObject BuildGameObject(GameObject template, string nodeId, bool affectsNavigation, Matrix4x4 transform, IDungeonSceneObjectInstantiator objectInstantiator)
        {
            Matrix.DecomposeMatrix(ref transform, out _position, out _rotation, out _scale);

            var    MeshTemplate = template;
            string NodeId       = nodeId;

            var gameObj = objectInstantiator.Instantiate(MeshTemplate, _position, _rotation, _scale);

            /*
             * var gameObj = Instantiate(MeshTemplate) as GameObject;
             * gameObj.transform.position = _position;
             * gameObj.transform.rotation = _rotation;
             * gameObj.transform.localScale = _scale;
             */

            if (itemParent != null)
            {
                gameObj.transform.parent = itemParent.transform;
            }

            var data = gameObj.AddComponent <DungeonSceneProviderData> ();

            data.NodeId            = NodeId;
            data.dungeon           = dungeon;
            data.affectsNavigation = affectsNavigation;

            return(gameObj);
        }
Пример #11
0
        protected GameObject BuildGameObjectFromArray(GameObjectArrayPropTypeData gameObjectArrayProp, int index, Matrix4x4 transform, IDungeonSceneObjectInstantiator objectInstantiator)
        {
            if (index < 0 || index >= gameObjectArrayProp.Templates.Length)
            {
                // Invalid index
                return(null);
            }
            GameObject template = gameObjectArrayProp.Templates[index];

            return(BuildGameObject(template, gameObjectArrayProp.NodeId, gameObjectArrayProp.affectsNavigation, transform, objectInstantiator));
        }
Пример #12
0
        // This is called by the builders that do not support theming
        public override void BuildNonThemedDungeon(DungeonSceneProvider sceneProvider, IDungeonSceneObjectInstantiator objectInstantiator)
        {
            random = new System.Random((int)config.Seed);
            propSockets.Clear();

            // We know that the dungeon prefab would have the appropriate config and models attached to it
            // Cast and save it for future reference
            snapConfig = config as SnapConfig;
            snapModel  = model as SnapModel;

            if (snapConfig == null)
            {
                Debug.LogError("No snap config script found in dungeon game object");
                return;
            }

            if (snapModel == null)
            {
                Debug.LogError("No snap model script found in dungeon game object");
                return;
            }

            // Generate the module info list
            var ModuleInfos = new List <ModuleInfo>();
            {
                var RegisteredModuleList = new List <GameObject>();
                RegisteredModuleList.AddRange(snapConfig.Modules);
                RegisteredModuleList.AddRange(snapConfig.StartModules);
                RegisteredModuleList.AddRange(snapConfig.EndModules);
                RegisteredModuleList.AddRange(snapConfig.BranchEndModules);
                var RegisteredModules = new HashSet <GameObject>(RegisteredModuleList);

                foreach (var RegisteredModule in RegisteredModules)
                {
                    var moduleInfo = GenerateModuleInfo(RegisteredModule);
                    ModuleInfos.Add(moduleInfo);
                }
            }

            var StartNode = new ModuleGrowthNode();

            StartNode.IncomingModuleDoorIndex = -1;
            StartNode.startNode       = true;
            StartNode.ModuleTransform = Matrix4x4.identity;

            var OccupiedBounds = new List <Bounds>();

            var LayoutBuildState = new SnapLayoutBuildState();

            LayoutBuildState.ModuleInfoList = ModuleInfos;

            // Build the main branch
            ModuleBuildNode BuildNode = BuildLayoutRecursive(StartNode, OccupiedBounds, 1, snapConfig.MainBranchSize, true, false, LayoutBuildState);

            // Build the side branches
            {
                var MainBranchNodes = new List <ModuleBuildNode>();

                // Grab the nodes in the main branch
                {
                    ModuleBuildNode BranchNode = BuildNode;
                    while (BranchNode != null)
                    {
                        BranchNode.bMainBranch = true;
                        MainBranchNodes.Add(BranchNode);

                        // Move forward
                        if (BranchNode.Extensions.Count == 0)
                        {
                            break;
                        }

                        BranchNode = BranchNode.Extensions[0];
                    }
                }

                // Iterate through the nodes in the main branch and start branching out
                for (int i = 0; i < MainBranchNodes.Count; i++)
                {
                    ModuleBuildNode BranchStartNode = MainBranchNodes[i];
                    ModuleBuildNode BranchNextNode  = i + 1 < MainBranchNodes.Count ? MainBranchNodes[i + 1] : null;

                    ModuleInfo BranchModule      = BranchStartNode.Module;
                    int        IncomingDoorIndex = BranchStartNode.IncomingDoorIndex;
                    int        OutgoingDoorIndex = BranchNextNode != null ? BranchNextNode.IncomingDoorIndex : -1;
                    int        NumDoors          = BranchModule.ConnectionTransforms.Length;
                    for (int DoorIndex = 0; DoorIndex < NumDoors; DoorIndex++)
                    {
                        if (DoorIndex == IncomingDoorIndex || DoorIndex == OutgoingDoorIndex)
                        {
                            // These doors are already extended
                            continue;
                        }

                        bool bGrowFromHere = (random.NextFloat() < snapConfig.SideBranchProbability);
                        if (!bGrowFromHere)
                        {
                            continue;
                        }

                        // TODO: Optimize me.  it recalculates the the bounds for the whole tree for every main branch node
                        OccupiedBounds.Clear();
                        CalculateOccupiedBounds(BuildNode, OccupiedBounds);

                        var BranchGrowNode = new ModuleGrowthNode();
                        BranchGrowNode.IncomingModuleDoorIndex = DoorIndex;
                        BranchGrowNode.IncomingModule          = BranchStartNode.Module;
                        BranchGrowNode.ModuleTransform         = BranchStartNode.AttachmentConfig.AttachedModuleTransform;

                        LayoutBuildState = new SnapLayoutBuildState();
                        LayoutBuildState.ModuleInfoList = ModuleInfos;
                        ModuleBuildNode BranchBuildNode = BuildLayoutRecursive(BranchGrowNode, OccupiedBounds, 1, snapConfig.SideBranchSize, false, false, LayoutBuildState);
                        if (BranchBuildNode != null)
                        {
                            // Make sure we don't end up with an undesirable leaf node
                            if (BranchBuildNode.Extensions.Count == 0 && BranchBuildNode.Module != null && snapConfig.SideBranchSize > 1)
                            {
                                continue;
                            }

                            BranchBuildNode.Parent = BranchStartNode;
                            BranchStartNode.Extensions.Add(BranchBuildNode);
                        }
                    }
                }
            }

            snapModel.ResetModel();


            sceneProvider.OnDungeonBuildStart();

            // Spawn the modules and register them in the model
            {
                var spawnedModuleList = new List <SnapModuleInstance>();
                TraverseTree(BuildNode, delegate(ModuleBuildNode Node)
                {
                    // Spawn a module at this location
                    ModuleInfo moduleInfo = Node.Module;

                    var templateInfo            = new GameObjectPropTypeData();
                    templateInfo.Template       = moduleInfo.ModuleTemplate;
                    templateInfo.NodeId         = moduleInfo.ModuleGuid.ToString();
                    templateInfo.Offset         = Matrix4x4.identity;
                    templateInfo.IsStaticObject = true;

                    Node.spawnedModule = sceneProvider.AddGameObject(templateInfo, Node.AttachmentConfig.AttachedModuleTransform, objectInstantiator);

                    // Register this in the model
                    var snapModule        = new SnapModuleInstance();
                    snapModule.InstanceID = Node.ModuleInstanceID;
                    spawnedModuleList.Add(snapModule);
                });
                snapModel.modules = spawnedModuleList.ToArray();
            }

            // Generate the list of connections
            {
                var connectionList = new List <SnapModuleConnection>();
                TraverseTree(BuildNode, delegate(ModuleBuildNode Node)
                {
                    if (Node.Parent != null)
                    {
                        var Connection = new SnapModuleConnection();
                        Connection.ModuleAInstanceID = Node.ModuleInstanceID;
                        Connection.DoorAIndex        = Node.AttachmentConfig.AttachedModuleDoorIndex;

                        Connection.ModuleBInstanceID = Node.Parent.ModuleInstanceID;
                        Connection.DoorBIndex        = Node.IncomingDoorIndex;

                        connectionList.Add(Connection);
                    }
                });
                snapModel.connections = connectionList.ToArray();
            }

            sceneProvider.OnDungeonBuildStop();

            FixupDoorStates(BuildNode);
        }