示例#1
0
        ModuleBuildNode BuildLayoutRecursive(ModuleGrowthNode GrowthNode, List <Bounds> OccupiedBounds,
                                             int DepthFromStart, int DesiredDepth, bool bMainBranch, bool bForceIgnoreEndModule, SnapLayoutBuildState RecursiveState)
        {
            if (RecursiveState.NumTries >= snapConfig.MaxProcessingPower)
            {
                return(null);
            }
            RecursiveState.NumTries++;

            if (DepthFromStart > DesiredDepth)
            {
                return(null);
            }

            ModuleGrowthNode Top = GrowthNode;

            // Pick a door from this module to extend
            int             BestValidMainBranchDifference = int.MaxValue;
            ModuleBuildNode BestBuildNode = null;

            int SnapModuleListLength = RecursiveState.ModuleInfoList.Count;

            int[] ShuffledIndices = MathUtils.GetShuffledIndices(SnapModuleListLength, random);
            for (int si = 0; si < ShuffledIndices.Length; si++)
            {
                int Index = ShuffledIndices[si];

                ModuleInfo Module = RecursiveState.ModuleInfoList[Index];

                var AttachmentConfig = new SnapAttachmentConfiguration();
                if (!FindAttachmentConfiguration(Module, Top.IncomingModule, ref Top.ModuleTransform, Top.IncomingModuleDoorIndex, OccupiedBounds, ref AttachmentConfig))
                {
                    continue;
                }

                var BuildNode = new ModuleBuildNode();
                BuildNode.AttachmentConfig  = AttachmentConfig;
                BuildNode.IncomingDoorIndex = Top.IncomingModuleDoorIndex;
                BuildNode.Module            = Module;

                if (DepthFromStart == DesiredDepth)
                {
                    // This has to be the leaf node
                    return(BuildNode);
                }

                if (BestBuildNode == null)
                {
                    BestBuildNode = BuildNode;
                }

                // We found a valid module. Use this
                OccupiedBounds.Add(AttachmentConfig.AttachedModuleWorldBounds);

                int AttachmentDoorIndex = AttachmentConfig.AttachedModuleDoorIndex;

                // Extend from this door further
                for (int ExtensionDoorIndex = 0; ExtensionDoorIndex < Module.ConnectionTransforms.Length; ExtensionDoorIndex++)
                {
                    if (ExtensionDoorIndex == AttachmentDoorIndex && Top.IncomingModuleDoorIndex != -1)
                    {
                        // Don't want to extend from the door we came in through
                        continue;
                    }

                    int ModuleCountContribution = 1;

                    // Grow this branch further
                    var NextNode = new ModuleGrowthNode();
                    NextNode.IncomingModuleDoorIndex = ExtensionDoorIndex;
                    NextNode.ModuleTransform         = AttachmentConfig.AttachedModuleTransform;
                    NextNode.IncomingModule          = Module;
                    ModuleBuildNode ExtensionNode = BuildLayoutRecursive(NextNode, OccupiedBounds, DepthFromStart + ModuleCountContribution, DesiredDepth,
                                                                         bMainBranch, false, RecursiveState);

                    if (ExtensionNode != null)
                    {
                        int BranchLength            = DepthFromStart + ExtensionNode.DepthFromLeaf;
                        int ValidDistanceDifference = Mathf.Abs(BranchLength - DesiredDepth);
                        if (ValidDistanceDifference < BestValidMainBranchDifference || RecursiveState.bFoundBestBuild)
                        {
                            BestValidMainBranchDifference = ValidDistanceDifference;
                            BuildNode.Extensions.Clear();
                            ExtensionNode.Parent = BuildNode;
                            BuildNode.Extensions.Add(ExtensionNode);
                            BuildNode.DepthFromLeaf = Mathf.Max(BuildNode.DepthFromLeaf, ExtensionNode.DepthFromLeaf + ModuleCountContribution);

                            BestBuildNode = BuildNode;
                        }

                        if (BranchLength >= DesiredDepth)
                        {
                            // We found a branch with the desired length
                            RecursiveState.bFoundBestBuild = true;
                        }

                        if (RecursiveState.bFoundBestBuild)
                        {
                            break;
                        }
                    }
                }

                // Remove it since we move out
                OccupiedBounds.Remove(AttachmentConfig.AttachedModuleWorldBounds);

                if (RecursiveState.bFoundBestBuild)
                {
                    break;
                }
            }

            return(BestBuildNode);
        }
示例#2
0
        // This is called by the builders that do not support theming
        public override void BuildNonThemedDungeon(DungeonSceneProvider sceneProvider)
        {
            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 <SnapModule>();
                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);

                    // Register this in the model
                    var snapModule        = new SnapModule();
                    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);
        }