public override Instance Clone(InstanceState instanceState, Dictionary <ushort, ushort> clonedNodes) { SegmentState state = instanceState as SegmentState; Instance cloneInstance = null; ushort startNode = state.startNode; ushort endNode = state.endNode; // Nodes should exist startNode = clonedNodes[startNode]; endNode = clonedNodes[endNode]; if (netManager.CreateSegment(out ushort clone, ref SimulationManager.instance.m_randomizer, state.Info.Prefab as NetInfo, startNode, endNode, state.startDirection, state.endDirection, SimulationManager.instance.m_currentBuildIndex, SimulationManager.instance.m_currentBuildIndex, state.invert)) { SimulationManager.instance.m_currentBuildIndex++; InstanceID cloneID = default(InstanceID); cloneID.NetSegment = clone; cloneInstance = new MoveableSegment(cloneID); } return(cloneInstance); }
public override Instance Clone(InstanceState instanceState, ref Matrix4x4 matrix4x, float deltaHeight, float deltaAngle, Vector3 center, bool followTerrain, Dictionary <ushort, ushort> clonedNodes) { SegmentState state = instanceState as SegmentState; Vector3 newPosition = matrix4x.MultiplyPoint(state.position - center); Instance cloneInstance = null; ushort startNode = state.startNode; ushort endNode = state.endNode; // Nodes should exist startNode = clonedNodes[startNode]; endNode = clonedNodes[endNode]; Vector3 startDirection = newPosition - nodeBuffer[startNode].m_position; Vector3 endDirection = newPosition - nodeBuffer[endNode].m_position; startDirection.y = 0; endDirection.y = 0; startDirection.Normalize(); endDirection.Normalize(); if (netManager.CreateSegment(out ushort clone, ref SimulationManager.instance.m_randomizer, state.Info.Prefab as NetInfo, startNode, endNode, startDirection, endDirection, SimulationManager.instance.m_currentBuildIndex, SimulationManager.instance.m_currentBuildIndex, state.invert)) { SimulationManager.instance.m_currentBuildIndex++; InstanceID cloneID = default(InstanceID); cloneID.NetSegment = clone; cloneInstance = new MoveableSegment(cloneID); } return(cloneInstance); }
public override void Do() { if (MoveItTool.POProcessing > 0) { return; } MoveItTool.instance.m_lastInstance = null; m_clones = new HashSet <Instance>(); m_origToCloneUpdate = new Dictionary <Instance, Instance>(); m_nodeOrigToClone = new Dictionary <ushort, ushort>(); m_stateToClone = new Dictionary <InstanceState, Instance>(); m_InstanceID_origToClone = new Dictionary <InstanceID, InstanceID>(); matrix4x.SetTRS(center + moveDelta, Quaternion.AngleAxis(angleDelta * Mathf.Rad2Deg, Vector3.down), Vector3.one); // Clone nodes first foreach (InstanceState state in m_states) { if (state is NodeState) { Instance clone = state.instance.Clone(state, ref matrix4x, moveDelta.y, angleDelta, center, followTerrain, m_nodeOrigToClone, this); if (clone != null) { m_clones.Add(clone); m_stateToClone.Add(state, clone); m_InstanceID_origToClone.Add(state.instance.id, clone.id); m_origToCloneUpdate.Add(state.instance.id, clone.id); m_nodeOrigToClone.Add(state.instance.id.NetNode, clone.id.NetNode); } } } // Clone everything else except PO foreach (InstanceState state in m_states) { if (!(state is NodeState || state is ProcState)) { Instance clone = state.instance.Clone(state, ref matrix4x, moveDelta.y, angleDelta, center, followTerrain, m_nodeOrigToClone, this); if (clone == null) { Log.Debug($"Failed to clone {state}"); continue; } m_clones.Add(clone); m_stateToClone.Add(state, clone); m_InstanceID_origToClone.Add(state.instance.id, clone.id); m_origToCloneUpdate.Add(state.instance.id, clone.id); ; if (state is SegmentState segmentState) { MoveItTool.NS.SetSegmentModifiers(clone.id.NetSegment, segmentState); if (segmentState.LaneIDs != null) { // old version does not store lane ids var clonedLaneIds = MoveableSegment.GetLaneIds(clone.id.NetSegment); DebugUtils.AssertEq(clonedLaneIds.Count, segmentState.LaneIDs.Count, "clonedLaneIds.Count, segmentState.LaneIDs.Count"); for (int i = 0; i < clonedLaneIds.Count; ++i) { var lane0 = new InstanceID { NetLane = segmentState.LaneIDs[i] }; var lane = new InstanceID { NetLane = clonedLaneIds[i] }; // Log.Debug($"Mapping lane:{lane0.NetLane} to {lane.NetLane}"); m_InstanceID_origToClone.Add(lane0, lane); } } } } } // Clone PO foreach (InstanceState state in m_states) { if (state is ProcState) { _ = state.instance.Clone(state, ref matrix4x, moveDelta.y, angleDelta, center, followTerrain, m_nodeOrigToClone, this); } } if (m_origToClone != null) { Dictionary <Instance, Instance> toReplace = new Dictionary <Instance, Instance>(); foreach (Instance key in m_origToClone.Keys) { toReplace.Add(m_origToClone[key], m_origToCloneUpdate[key]); DebugUtils.Log("To replace: " + m_origToClone[key].id.RawData + " -> " + m_origToCloneUpdate[key].id.RawData); } ActionQueue.instance.ReplaceInstancesForward(toReplace); } m_origToClone = m_origToCloneUpdate; // Select clones selection = m_clones; MoveItTool.m_debugPanel.UpdatePanel(); UpdateArea(GetTotalBounds(false)); try { MoveItTool.UpdatePillarMap(); } catch (Exception e) { DebugUtils.Log("CloneActionBase.Do failed"); DebugUtils.LogException(e); } }
public BulldozeAction() { HashSet <Instance> newSelection = new HashSet <Instance>(selection); HashSet <Instance> extraNodes = new HashSet <Instance>(); HashSet <ushort> segments = new HashSet <ushort>(); // Segments to be removed NetManager netManager = Singleton <NetManager> .instance; // Add any segments whose node is selected foreach (Instance instance in selection) { if (instance.isValid) { if (instance.id.Type == InstanceType.NetSegment) { segments.Add(instance.id.NetSegment); } else if (instance.id.Type == InstanceType.NetNode) { for (int i = 0; i < 8; i++) { ushort segment = netManager.m_nodes.m_buffer[instance.id.NetNode].GetSegment(i); if (segment != 0) { InstanceID instanceID = default; instanceID.NetSegment = segment; if (selection.Contains(instanceID)) { continue; } newSelection.Add(new MoveableSegment(instanceID)); segments.Add(segment); } } } else if (instance.id.Type == InstanceType.Building) { Building building = (Building)((MoveableBuilding)instance).data; ushort nodeId = building.m_netNode; int c = 0; while (nodeId != 0) { NetNode node = netManager.m_nodes.m_buffer[nodeId]; if (node.m_building == 0 || node.Info.m_class.m_layer == ItemClass.Layer.WaterPipes) { // Exclude attached nodes with attached buildings (e.g. water buildings) for (int i = 0; i < 8; i++) { ushort segmentId = node.GetSegment(i); if (segmentId != 0 && MoveableSegment.isSegmentValid(segmentId) && ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Untouchable) == NetSegment.Flags.None)) { InstanceID instanceID = default; instanceID.NetSegment = segmentId; if (selection.Contains(instanceID)) { continue; } newSelection.Add(new MoveableSegment(instanceID)); segments.Add(segmentId); } } } nodeId = node.m_nextBuildingNode; if (++c > 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Nodes: Invalid list detected!\n" + Environment.StackTrace); break; } } } } } // Add any nodes whose segments are all selected foreach (Instance instance in newSelection) { if (instance.isValid) { if (instance.id.Type == InstanceType.NetSegment) { ushort segId = instance.id.NetSegment; ushort[] nodeIds = { netManager.m_segments.m_buffer[segId].m_startNode, netManager.m_segments.m_buffer[segId].m_endNode }; foreach (ushort id in nodeIds) { bool toDelete = true; NetNode node = netManager.m_nodes.m_buffer[id]; for (int i = 0; i < 8; i++) { if (node.GetSegment(i) != 0 && !segments.Contains(node.GetSegment(i))) { toDelete = false; break; } } if (toDelete) { if (node.Info.m_class.m_layer == ItemClass.Layer.WaterPipes) { foreach (Building b in BuildingManager.instance.m_buildings.m_buffer) { if (b.m_netNode == id) { toDelete = false; break; } } } } if (toDelete) { InstanceID instanceId = default; instanceId.NetNode = id; MoveableNode mn = new MoveableNode(instanceId); if (newSelection.Contains(mn)) { continue; } extraNodes.Add(mn); } } } } } // Sort segments by buildIndex HashSet <Instance> sorted = new HashSet <Instance>(); List <uint> indexes = new List <uint>(); foreach (Instance instance in newSelection) { if (instance.id.Type != InstanceType.NetSegment) { sorted.Add(instance); } else { uint bi = ((NetSegment)instance.data).m_buildIndex; if (!indexes.Contains(bi)) { indexes.Add(bi); } } } indexes.Sort(); foreach (uint i in indexes) { foreach (Instance instance in newSelection) { if (instance.id.Type == InstanceType.NetSegment) { if (((NetSegment)instance.data).m_buildIndex == i) { sorted.Add(instance); } } } } foreach (Instance instance in sorted) { m_states.Add(instance.SaveToState()); } foreach (Instance instance in extraNodes) { m_states.Add(instance.SaveToState()); } }
public override void Do() { if (MoveItTool.POProcessing > 0) { return; } MoveItTool.instance.m_lastInstance = null; m_clones = new HashSet <Instance>(); m_origToCloneUpdate = new Dictionary <Instance, Instance>(); m_nodeOrigToClone = new Dictionary <ushort, ushort>(); var stateToClone = new Dictionary <InstanceState, Instance>(); var InstanceID_origToClone = new Dictionary <InstanceID, InstanceID>(); matrix4x.SetTRS(center + moveDelta, Quaternion.AngleAxis(angleDelta * Mathf.Rad2Deg, Vector3.down), Vector3.one); // Clone nodes first foreach (InstanceState state in m_states) { if (state is NodeState) { Instance clone = state.instance.Clone(state, ref matrix4x, moveDelta.y, angleDelta, center, followTerrain, m_nodeOrigToClone, this); if (clone != null) { m_clones.Add(clone); stateToClone.Add(state, clone); InstanceID_origToClone.Add(state.instance.id, clone.id); m_origToCloneUpdate.Add(state.instance.id, clone.id); m_nodeOrigToClone.Add(state.instance.id.NetNode, clone.id.NetNode); } } } // Clone everything else except PO foreach (InstanceState state in m_states) { if (!(state is NodeState || state is ProcState)) { Instance clone = state.instance.Clone(state, ref matrix4x, moveDelta.y, angleDelta, center, followTerrain, m_nodeOrigToClone, this); if (clone == null) { Debug.Log($"Failed to clone {state}"); continue; } m_clones.Add(clone); stateToClone.Add(state, clone); InstanceID_origToClone.Add(state.instance.id, clone.id); m_origToCloneUpdate.Add(state.instance.id, clone.id); if (state is SegmentState segmentState) { MoveItTool.NS.SetSegmentModifiers(clone.id.NetSegment, segmentState); var clonedLaneIds = MoveableSegment.GetLaneIds(clone.id.NetSegment); DebugUtils.AssertEq(clonedLaneIds.Count, segmentState.LaneIDs.Count, "clonedLaneIds.Count, segmentState.LaneIDs.Count"); for (int i = 0; i < clonedLaneIds.Count; ++i) { var lane0 = new InstanceID { NetLane = segmentState.LaneIDs[i] }; var lane = new InstanceID { NetLane = clonedLaneIds[i] }; // Debug.Log($"Mapping lane:{lane0.NetLane} to {lane.NetLane}"); InstanceID_origToClone.Add(lane0, lane); } } } } // Clone NodeController after segments have been added. foreach (var item in stateToClone) { if (item.Key is NodeState nodeState) { Instance clone = item.Value; ushort nodeID = clone.id.NetNode; MoveItTool.NodeController.PasteNode(nodeID, nodeState); } } // Clone TMPE rules foreach (var state in m_states) { if (state is NodeState nodeState) { MoveItTool.TMPE.Paste(nodeState.TMPE_NodeRecord, InstanceID_origToClone); } else if (state is SegmentState segmentState) { MoveItTool.TMPE.Paste(segmentState.TMPE_SegmentRecord, InstanceID_origToClone); MoveItTool.TMPE.Paste(segmentState.TMPE_SegmentStartRecord, InstanceID_origToClone); MoveItTool.TMPE.Paste(segmentState.TMPE_SegmentEndRecord, InstanceID_origToClone); } } // Clone PO foreach (InstanceState state in m_states) { if (state is ProcState) { Instance clone = state.instance.Clone(state, ref matrix4x, moveDelta.y, angleDelta, center, followTerrain, m_nodeOrigToClone, this); } } if (m_origToClone != null) { Dictionary <Instance, Instance> toReplace = new Dictionary <Instance, Instance>(); foreach (Instance key in m_origToClone.Keys) { toReplace.Add(m_origToClone[key], m_origToCloneUpdate[key]); DebugUtils.Log("To replace: " + m_origToClone[key].id.RawData + " -> " + m_origToCloneUpdate[key].id.RawData); } ActionQueue.instance.ReplaceInstancesForward(toReplace); } m_origToClone = m_origToCloneUpdate; // Select clones selection = m_clones; MoveItTool.m_debugPanel.UpdatePanel(); UpdateArea(GetTotalBounds(false)); }
public BulldozeAction() { HashSet <Instance> newSelection = new HashSet <Instance>(selection); HashSet <Instance> extraNodes = new HashSet <Instance>(); HashSet <ushort> segments = new HashSet <ushort>(); // Segments to be removed //string msg = $"\nBasic Selection: {selection.Count}\n"; // Add any segments whose node is selected foreach (Instance instance in selection) { if (instance.isValid) { if (instance.id.Type == InstanceType.NetSegment) { segments.Add(instance.id.NetSegment); } else if (instance.id.Type == InstanceType.NetNode) { for (int i = 0; i < 8; i++) { ushort segment = NetManager.instance.m_nodes.m_buffer[instance.id.NetNode].GetSegment(i); if (segment != 0) { InstanceID instanceID = default(InstanceID); instanceID.NetSegment = segment; if (selection.Contains(instanceID)) { continue; } newSelection.Add(new MoveableSegment(instanceID)); segments.Add(segment); } } } else if (instance.id.Type == InstanceType.Building) { Building building = (Building)((MoveableBuilding)instance).data; ushort nodeId = building.m_netNode; int c = 0; while (nodeId != 0) { NetNode node = NetManager.instance.m_nodes.m_buffer[nodeId]; for (int i = 0; i < 8; i++) { ushort segmentId = node.GetSegment(i); if (segmentId != 0 && MoveableSegment.isSegmentValid(segmentId) && ((NetManager.instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Untouchable) == NetSegment.Flags.None)) { InstanceID instanceID = default(InstanceID); instanceID.NetSegment = segmentId; if (selection.Contains(instanceID)) { continue; } newSelection.Add(new MoveableSegment(instanceID)); segments.Add(segmentId); } } nodeId = node.m_nextBuildingNode; if (++c > 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } } //msg += $"Selection With Extra Segments: {newSelection.Count}\nTotal Segments: {segments.Count}\n"; // Add any nodes whose segments are all selected foreach (Instance instance in newSelection) { if (instance.isValid) { if (instance.id.Type == InstanceType.NetSegment) { ushort segId = instance.id.NetSegment; ushort[] nodeIds = { NetManager.instance.m_segments.m_buffer[segId].m_startNode, NetManager.instance.m_segments.m_buffer[segId].m_endNode }; foreach (ushort id in nodeIds) { bool toDelete = true; NetNode node = NetManager.instance.m_nodes.m_buffer[id]; for (int i = 0; i < 8; i++) { if (node.GetSegment(i) != 0 && !segments.Contains(node.GetSegment(i))) { toDelete = false; break; } } if (toDelete) { InstanceID instanceId = default(InstanceID); instanceId.NetNode = id; MoveableNode mn = new MoveableNode(instanceId); if (newSelection.Contains(mn)) { continue; } extraNodes.Add(mn); } } } } } foreach (Instance instance in newSelection) { m_states.Add(instance.GetState()); } foreach (Instance instance in extraNodes) { m_states.Add(instance.GetState()); } //Debug.Log(msg + $"Final Selection: {m_states.Count}"); }