void BuildTreeInternal(PWNode node, BiomeSwitchNode currentNode, int depth, BiomeSwitchNode parent = null) { if (node == null) { return; } //TODO: anchor to multiple PWNodeBiomeSwitch management if (node.GetType() == typeof(PWNodeBiomeSwitch)) { PWNodeBiomeSwitch bSwitch = node as PWNodeBiomeSwitch; int outputLinksCount = bSwitch.GetLinks().Count; int childIndex = 0; List <PWNode> outputNodeList = new List <PWNode>(); Debug.Log("encountered switch: " + bSwitch.switchMode); currentNode.SetChildCount(outputLinksCount); switch (bSwitch.switchMode) { case BiomeSwitchMode.Water: int?terrestrialAnchorId = node.GetAnchorId(PWAnchorType.Output, 0); int?aquaticAnchorId = node.GetAnchorId(PWAnchorType.Output, 1); if (terrestrialAnchorId != null) { var nodes = node.GetNodesAttachedToAnchor(terrestrialAnchorId.Value); outputNodeList.AddRange(nodes); // Debug.Log("terrestrialNodes: " + nodes[0].nodeId); for (int i = 0; i < nodes.Count; i++) { currentNode.GetChildAt(childIndex++).SetSwitchValue(false, bSwitch.switchMode, "terrestrial", Color.black); } biomeCoverage[BiomeSwitchMode.Water] += 0.5f; } //get all nodes on the first anchor: if (aquaticAnchorId != null) { var nodes = node.GetNodesAttachedToAnchor(aquaticAnchorId.Value); // Debug.Log("aquaticNodes: " + nodes[0].nodeId); outputNodeList.AddRange(nodes); for (int i = 0; i < nodes.Count; i++) { currentNode.GetChildAt(childIndex++).SetSwitchValue(true, bSwitch.switchMode, "aquatic", Color.blue); } biomeCoverage[BiomeSwitchMode.Water] += 0.5f; } break; default: // Debug.Log("swicth data count for node " + node.nodeId + ": " + bSwitch.switchDatas.Count); for (int anchorIndex = 0; anchorIndex < bSwitch.switchDatas.Count; anchorIndex++) { int?anchorId = node.GetAnchorId(PWAnchorType.Output, anchorIndex); var sData = bSwitch.switchDatas[anchorIndex]; if (anchorId == null) { continue; } var attachedNodesToAnchor = node.GetNodesAttachedToAnchor(anchorId.Value); outputNodeList.AddRange(attachedNodesToAnchor); // if (attachedNodesToAnchor.Count == 0) // Debug.LogWarning("nothing attached to the biome switch output " + anchorIndex); foreach (var attachedNode in attachedNodesToAnchor) { var child = currentNode.GetChildAt(childIndex++); child.SetSwitchValue(sData.min, sData.max, bSwitch.switchMode, sData.name, sData.color); } biomeCoverage[bSwitch.switchMode] += (sData.max - sData.min) / (sData.absoluteMax - sData.absoluteMin); } break; } childIndex = 0; foreach (var outNode in outputNodeList) { if (bSwitch.switchMode == BiomeSwitchMode.Water) { Debug.Log("water switch mode output type: " + currentNode.GetChildAt(childIndex) + " [" + childIndex + "] -> " + outNode); } BuildTreeInternal(outNode, currentNode.GetChildAt(childIndex, true), depth + 1, currentNode); Type outNodeType = outNode.GetType(); if (outNodeType == typeof(PWNodeBiomeSwitch) || outNodeType == typeof(PWNodeBiomeBinder)) { childIndex++; } } } else if (node.GetType() == typeof(PWNodeBiomeBinder)) { PWNodeBiomeBinder binder = node as PWNodeBiomeBinder; string biomeName = currentNode.biomeName; if (String.IsNullOrEmpty(biomeName)) { Debug.LogWarning("Biome name null or empty for biomeBinder: " + binder); return; } //Biome binder detected, assign the biome to the current Node: currentNode.biome = binder.outputBiome; // Debug.Log("current node: " + currentNode + ", preview color: " + currentNode.previewColor); //set the color of the biome in the binder binder.outputBiome.previewColor = currentNode.previewColor; Debug.Log("set biome " + currentNode.biome + " in node " + currentNode); //set the biome ID and name: currentNode.biome.name = biomeName; currentNode.biome.id = biomeIdCount++; //store the biome in dictionaries for fast access biomePerId[currentNode.biome.id] = currentNode.biome; biomePerName[biomeName] = currentNode.biome; } else { foreach (var outNode in node.GetOutputNodes()) { BuildTreeInternal(outNode, currentNode, depth++, parent); } } return; }
public bool BuildGraph(BiomeData biomeData) { ResetGraph(); PWNode rootNode = biomeData.biomeSwitchGraphStartPoint; Stack <PWNode> biomeNodes = new Stack <PWNode>(); biomeNodes.Push(rootNode); BiomeSwitchCell currentCell = null; //fill param range dictionary (used to compute weights) FillParamRange(biomeData); while (biomeNodes.Count > 0) { PWNode currentNode = biomeNodes.Pop(); Type nodeType = currentNode.GetType(); if (nodeType == typeof(PWNodeBiome)) { //get all precedent switch data in the order of the tree (start from rootNode) var precedentSwitchDatas = GetPrecedentSwitchDatas(currentNode, rootNode); var biomeNode = currentNode as PWNodeBiome; var lastSwitch = precedentSwitchDatas.Last(); currentCell = new BiomeSwitchCell(); //Set cell and partial biome remaining empty params currentCell.name = biomeNode.outputBiome.name = lastSwitch.name; currentCell.id = biomeNode.outputBiome.id = biomeIdCount++; currentCell.color = biomeNode.outputBiome.previewColor = lastSwitch.color; currentCell.weight = currentCell.GetWeight(paramRanges); //add the partial biome to utility dictionary accessors: partialBiomePerName[currentCell.name] = biomeNode.outputBiome; partialBiomePerId[currentCell.id] = biomeNode.outputBiome; //load all access condition for this biome switch foreach (var sd in precedentSwitchDatas) { int index = biomeData.GetBiomeIndex(sd.samplerName); var param = currentCell.switchParams.switchParams[index]; param.enabled = true; param.min = sd.min; param.max = sd.max; biomeCoverage[index] += (sd.max - sd.min) / (sd.absoluteMax - sd.absoluteMin); } } else if (nodeType == typeof(PWNodeBiomeBlender)) { if (currentCell == null) { throw new Exception("[PWBiomeSwitchGraph] idk what happened but this is really bad"); } //if the flow reaches the biomeblender everything is OK and add the current cell to the graph cells.Add(currentCell); continue; } foreach (var outputNode in currentNode.GetOutputNodes()) { biomeNodes.Push(outputNode); } } //Generate links between all linkable nodes BuildLinks(); rootCell = cells.First(); if (!CheckValid()) { return(false); } isBuilt = true; return(true); }