Exemple #1
0
        public override InstanceState GetState()
        {
            BuildingState state = new BuildingState();

            state.instance = this;
            state.info     = info;

            state.position      = buildingBuffer[id.Building].m_position;
            state.angle         = buildingBuffer[id.Building].m_angle;
            state.terrainHeight = TerrainManager.instance.SampleOriginalRawHeightSmooth(state.position);
            state.flags         = buildingBuffer[id.Building].m_flags;
            state.length        = buildingBuffer[id.Building].Length;

            List <InstanceState> subStates = new List <InstanceState>();

            foreach (Instance instance in subInstances)
            {
                if (instance != null && instance.isValid)
                {
                    subStates.Add(instance.GetState());
                }
            }

            if (subStates.Count > 0)
            {
                state.subStates = subStates.ToArray();
            }

            return(state);
        }
Exemple #2
0
        public override void RenderCloneGeometry(InstanceState instanceState, ref Matrix4x4 matrix4x, Vector3 deltaPosition, float deltaAngle, Vector3 center, bool followTerrain, RenderManager.CameraInfo cameraInfo, Color toolColor)
        {
            BuildingState state = instanceState as BuildingState;

            BuildingInfo buildingInfo = state.info as BuildingInfo;
            Color        color        = GetColor(state.instance.id.Building, buildingInfo);

            Vector3 newPosition = matrix4x.MultiplyPoint(state.position - center);

            newPosition.y = state.position.y + deltaPosition.y;

            if (followTerrain)
            {
                newPosition.y = newPosition.y - state.terrainHeight + TerrainManager.instance.SampleOriginalRawHeightSmooth(newPosition);
            }

            float newAngle = state.angle + deltaAngle;

            buildingInfo.m_buildingAI.RenderBuildGeometry(cameraInfo, newPosition, newAngle, 0);
            BuildingTool.RenderGeometry(cameraInfo, buildingInfo, state.length, newPosition, newAngle, false, color);
            if (buildingInfo.m_subBuildings != null && buildingInfo.m_subBuildings.Length != 0)
            {
                Matrix4x4 subMatrix4x = default(Matrix4x4);
                subMatrix4x.SetTRS(newPosition, Quaternion.AngleAxis(newAngle * Mathf.Rad2Deg, Vector3.down), Vector3.one);
                for (int i = 0; i < buildingInfo.m_subBuildings.Length; i++)
                {
                    BuildingInfo buildingInfo2 = buildingInfo.m_subBuildings[i].m_buildingInfo;
                    Vector3      position      = subMatrix4x.MultiplyPoint(buildingInfo.m_subBuildings[i].m_position);
                    float        angle         = buildingInfo.m_subBuildings[i].m_angle * 0.0174532924f + newAngle;
                    buildingInfo2.m_buildingAI.RenderBuildGeometry(cameraInfo, position, angle, 0);
                    BuildingTool.RenderGeometry(cameraInfo, buildingInfo2, 0, position, angle, true, color);
                }
            }
        }
Exemple #3
0
        // Constructor for FindIt object
        public CloneActionFindIt(PrefabInfo prefab)
        {
            m_oldSelection = selection;
            m_states.Clear();

            Vector3       position = MoveItTool.RaycastMouseLocation();
            InstanceState state    = new InstanceState();

            if (prefab is BuildingInfo)
            {
                state = new BuildingState
                {
                    isSubInstance = false,
                    isHidden      = false,
                    flags         = Building.Flags.Completed
                };
                state.Info.Prefab = prefab;
                InstanceID id = new InstanceID
                {
                    Building = 1,
                    Type     = InstanceType.Building
                };
                state.instance = new MoveableBuilding(id);
            }
            else if (prefab is PropInfo)
            {
                state = new PropState
                {
                    fixedHeight = false,
                    single      = false,
                };
                state.Info.Prefab = prefab;
                InstanceID id = new InstanceID
                {
                    Prop = 1,
                    Type = InstanceType.Prop
                };
                state.instance = new MoveableProp(id);
            }
            else if (prefab is TreeInfo)
            {
                state = new TreeState
                {
                    fixedHeight = false,
                    single      = false,
                };
                state.Info.Prefab = prefab;
                InstanceID id = new InstanceID
                {
                    Tree = 1,
                    Type = InstanceType.Tree
                };
                state.instance = new MoveableTree(id);
            }

            state.position      = position;
            state.terrainHeight = position.y;
            m_states.Add(state);
            center = position;
        }
Exemple #4
0
        // For Deletion Undo
        public override Instance Clone(InstanceState instanceState, Dictionary <ushort, ushort> clonedNodes)
        {
            BuildingState state = instanceState as BuildingState;

            MoveableBuilding cloneInstance = null;
            BuildingInfo     info          = state.Info.Prefab as BuildingInfo;

            if (BuildingManager.instance.CreateBuilding(out ushort clone, ref SimulationManager.instance.m_randomizer,
                                                        info, state.position, state.angle,
                                                        state.length, SimulationManager.instance.m_currentBuildIndex))
            {
                SimulationManager.instance.m_currentBuildIndex++;

                InstanceID cloneID = default;
                cloneID.Building = clone;
                cloneInstance    = new MoveableBuilding(cloneID);

                buildingBuffer[clone].m_flags = state.flags;

                if (info.m_subBuildings != null && info.m_subBuildings.Length != 0)
                {
                    Matrix4x4 subMatrix4x = default;
                    subMatrix4x.SetTRS(state.position, Quaternion.AngleAxis(state.angle * Mathf.Rad2Deg, Vector3.down), Vector3.one);
                    for (int i = 0; i < info.m_subBuildings.Length; i++)
                    {
                        BuildingInfo subInfo     = info.m_subBuildings[i].m_buildingInfo;
                        Vector3      subPosition = subMatrix4x.MultiplyPoint(info.m_subBuildings[i].m_position);
                        float        subAngle    = info.m_subBuildings[i].m_angle * 0.0174532924f + state.angle;

                        if (BuildingManager.instance.CreateBuilding(out ushort subClone, ref SimulationManager.instance.m_randomizer,
                                                                    subInfo, subPosition, subAngle, 0, SimulationManager.instance.m_currentBuildIndex))
                        {
                            SimulationManager.instance.m_currentBuildIndex++;
                            if (info.m_subBuildings[i].m_fixedHeight)
                            {
                                buildingBuffer[subClone].m_flags = buildingBuffer[subClone].m_flags | Building.Flags.FixedHeight;
                            }
                        }
                        if (clone != 0 && subClone != 0)
                        {
                            buildingBuffer[clone].m_subBuilding       = subClone;
                            buildingBuffer[subClone].m_parentBuilding = clone;
                            buildingBuffer[subClone].m_flags          = buildingBuffer[subClone].m_flags | Building.Flags.Untouchable;
                            clone = subClone;
                        }
                    }
                }
                cloneInstance.ResetSubInstances();
            }

            return(cloneInstance);
        }
Exemple #5
0
        public override void ReplaceInstance(Instance instance)
        {
            base.ReplaceInstance(instance);

            MoveableNode node = instance as MoveableNode;

            if (pillarState != null)
            {
                pillarState.instance = node.Pillar;
                if (pillarState.instance == null)
                {
                    pillarState = null;
                }
            }
        }
Exemple #6
0
        public override InstanceState SaveToState(bool integrate = true)
        {
            BuildingState state = new BuildingState
            {
                instance        = this,
                Info            = Info,
                position        = buildingBuffer[id.Building].m_position,
                angle           = buildingBuffer[id.Building].m_angle,
                flags           = buildingBuffer[id.Building].m_flags,
                length          = buildingBuffer[id.Building].Length,
                isSubInstance   = isSubInstance,
                isHidden        = isHidden,
                isCustomContent = Info.Prefab.m_isCustomContent
            };

            state.terrainHeight = TerrainManager.instance.SampleOriginalRawHeightSmooth(state.position);

            List <InstanceState> subStates = new List <InstanceState>();

            foreach (Instance subInstance in subInstances)
            {
                if (subInstance != null && subInstance.isValid)
                {
                    if (subInstance.id.Building > 0)
                    {
                        subStates.Add(((MoveableBuilding)subInstance).SaveToState());
                    }
                    else
                    {
                        subStates.Add(subInstance.SaveToState());
                    }
                }
            }

            if (subStates.Count > 0)
            {
                state.subStates = subStates.ToArray();
            }

            state.SaveIntegrations(integrate);

            return(state);
        }
Exemple #7
0
        public InstanceState GetBuildingState(int depth)
        {
            BuildingState state = new BuildingState
            {
                instance = this,
                Info     = Info,
                position = buildingBuffer[id.Building].m_position,
                angle    = buildingBuffer[id.Building].m_angle,
                flags    = buildingBuffer[id.Building].m_flags,
                length   = buildingBuffer[id.Building].Length
            };

            state.terrainHeight = TerrainManager.instance.SampleOriginalRawHeightSmooth(state.position);

            List <InstanceState> subStates = new List <InstanceState>();

            foreach (Instance subInstance in subInstances)
            {
                if (subInstance != null && subInstance.isValid)
                {
                    if (subInstance.id.Building > 0)
                    {
                        if (depth < 1)
                        {
                            subStates.Add(((MoveableBuilding)subInstance).GetBuildingState(depth + 1));
                        }
                    }
                    else
                    {
                        subStates.Add(subInstance.GetState());
                    }
                }
            }

            if (subStates.Count > 0)
            {
                state.subStates = subStates.ToArray();
            }

            return(state);
        }
Exemple #8
0
        public override void Transform(InstanceState instanceState, ref Matrix4x4 matrix4x, float deltaHeight, float deltaAngle, Vector3 center, bool followTerrain)
        {
            BuildingState state = instanceState as BuildingState;

            Vector3 newPosition = matrix4x.MultiplyPoint(state.position - center);

            newPosition.y = state.position.y + deltaHeight;

            float terrainHeight = TerrainManager.instance.SampleOriginalRawHeightSmooth(newPosition);

            if (followTerrain)
            {
                newPosition.y = newPosition.y + terrainHeight - state.terrainHeight;
            }

            // TODO: when should the flag be set?
            if (Mathf.Abs(terrainHeight - newPosition.y) > 0.01f)
            {
                AddFixedHeightFlag(id.Building);
            }
            else
            {
                RemoveFixedHeightFlag(id.Building);
            }

            Move(newPosition, state.angle + deltaAngle);

            if (state.subStates != null)
            {
                foreach (InstanceState subState in state.subStates)
                {
                    Vector3 subPosition = subState.position - center;
                    subPosition   = matrix4x.MultiplyPoint(subPosition);
                    subPosition.y = subState.position.y - state.position.y + newPosition.y;

                    subState.instance.Move(subPosition, subState.angle + deltaAngle);
                }
            }
        }
        public override void RenderCloneOverlay(InstanceState instanceState, ref Matrix4x4 matrix4x, Vector3 deltaPosition, float deltaAngle, Vector3 center, bool followTerrain, RenderManager.CameraInfo cameraInfo, Color toolColor)
        {
            if (MoveItTool.m_isLowSensitivity && MoveItTool.hideSelectorsOnLowSensitivity)
            {
                return;
            }

            BuildingState state = instanceState as BuildingState;

            BuildingInfo buildingInfo = state.Info.Prefab as BuildingInfo;

            Vector3 newPosition = matrix4x.MultiplyPoint(state.position - center);

            newPosition.y = state.position.y + deltaPosition.y;

            if (followTerrain)
            {
                newPosition.y = newPosition.y - state.terrainHeight + TerrainManager.instance.SampleOriginalRawHeightSmooth(newPosition);
            }

            float newAngle = state.angle + deltaAngle;

            buildingInfo.m_buildingAI.RenderBuildOverlay(cameraInfo, toolColor, newPosition, newAngle, default);
            BuildingTool.RenderOverlay(cameraInfo, buildingInfo, state.length, newPosition, newAngle, toolColor, false);
            if (buildingInfo.m_subBuildings != null && buildingInfo.m_subBuildings.Length != 0)
            {
                Matrix4x4 subMatrix4x = default;
                subMatrix4x.SetTRS(newPosition, Quaternion.AngleAxis(newAngle * Mathf.Rad2Deg, Vector3.down), Vector3.one);
                for (int i = 0; i < buildingInfo.m_subBuildings.Length; i++)
                {
                    BuildingInfo buildingInfo2 = buildingInfo.m_subBuildings[i].m_buildingInfo;
                    Vector3      position      = subMatrix4x.MultiplyPoint(buildingInfo.m_subBuildings[i].m_position);
                    float        angle         = buildingInfo.m_subBuildings[i].m_angle * 0.0174532924f + newAngle;
                    buildingInfo2.m_buildingAI.RenderBuildOverlay(cameraInfo, toolColor, position, angle, default);
                    BuildingTool.RenderOverlay(cameraInfo, buildingInfo2, 0, position, angle, toolColor, true);
                }
            }
        }
Exemple #10
0
        public override Instance Clone(InstanceState instanceState, ref Matrix4x4 matrix4x, float deltaHeight, float deltaAngle, Vector3 center, bool followTerrain, Dictionary <ushort, ushort> clonedNodes)
        {
            BuildingState state = instanceState as BuildingState;

            Vector3 newPosition = matrix4x.MultiplyPoint(state.position - center);

            newPosition.y = state.position.y + deltaHeight;

            float terrainHeight = TerrainManager.instance.SampleOriginalRawHeightSmooth(newPosition);

            if (followTerrain)
            {
                newPosition.y = newPosition.y + terrainHeight - state.terrainHeight;
            }
            MoveableBuilding cloneInstance = null;
            BuildingInfo     info          = state.info as BuildingInfo;

            float newAngle = state.angle + deltaAngle;

            if (BuildingManager.instance.CreateBuilding(out ushort clone, ref SimulationManager.instance.m_randomizer,
                                                        info, newPosition, newAngle,
                                                        state.length, SimulationManager.instance.m_currentBuildIndex))
            {
                SimulationManager.instance.m_currentBuildIndex++;

                InstanceID cloneID = default(InstanceID);
                cloneID.Building = clone;
                cloneInstance    = new MoveableBuilding(cloneID);

                if ((state.flags & Building.Flags.Completed) != Building.Flags.None)
                {
                    buildingBuffer[clone].m_flags = buildingBuffer[clone].m_flags | Building.Flags.Completed;
                }
                if ((state.flags & Building.Flags.FixedHeight) != Building.Flags.None)
                {
                    buildingBuffer[clone].m_flags = buildingBuffer[clone].m_flags | Building.Flags.FixedHeight;
                }

                // TODO: when should the flag be set?
                if (Mathf.Abs(terrainHeight - newPosition.y) > 0.01f)
                {
                    AddFixedHeightFlag(clone);
                }
                else
                {
                    RemoveFixedHeightFlag(clone);
                }

                if (info.m_subBuildings != null && info.m_subBuildings.Length != 0)
                {
                    Matrix4x4 subMatrix4x = default(Matrix4x4);
                    subMatrix4x.SetTRS(newPosition, Quaternion.AngleAxis(newAngle * Mathf.Rad2Deg, Vector3.down), Vector3.one);
                    for (int i = 0; i < info.m_subBuildings.Length; i++)
                    {
                        BuildingInfo subInfo     = info.m_subBuildings[i].m_buildingInfo;
                        Vector3      subPosition = subMatrix4x.MultiplyPoint(info.m_subBuildings[i].m_position);
                        float        subAngle    = info.m_subBuildings[i].m_angle * 0.0174532924f + newAngle;

                        if (BuildingManager.instance.CreateBuilding(out ushort subClone, ref SimulationManager.instance.m_randomizer,
                                                                    subInfo, subPosition, subAngle, 0, SimulationManager.instance.m_currentBuildIndex))
                        {
                            SimulationManager.instance.m_currentBuildIndex++;
                            if (info.m_subBuildings[i].m_fixedHeight)
                            {
                                buildingBuffer[subClone].m_flags = buildingBuffer[subClone].m_flags | Building.Flags.FixedHeight;
                            }
                        }
                        if (clone != 0 && subClone != 0)
                        {
                            buildingBuffer[clone].m_subBuilding       = subClone;
                            buildingBuffer[subClone].m_parentBuilding = clone;
                            buildingBuffer[subClone].m_flags          = buildingBuffer[subClone].m_flags | Building.Flags.Untouchable;
                            clone = subClone;
                        }
                    }
                }
            }

            return(cloneInstance);
        }
Exemple #11
0
        protected HashSet <InstanceState> ProcessPillars(HashSet <InstanceState> states, bool makeClone)
        {
            if (!MoveItTool.advancedPillarControl)
            {
                return(states);
            }

            HashSet <ushort> nodesWithAttachments = new HashSet <ushort>();

            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();
            foreach (InstanceState instanceState in states)
            {
                if (instanceState is NodeState ns && ((NetNode)(ns.instance.data)).m_building > 0 &&
                    ((buildingBuffer[((NetNode)(ns.instance.data)).m_building].m_flags & Building.Flags.Hidden) != Building.Flags.Hidden))
                {
                    nodesWithAttachments.Add(ns.instance.id.NetNode);
                    //Debug.Log($"Node {ns.instance.id.NetNode} found");
                }
            }
            HashSet <InstanceState> newStates = new HashSet <InstanceState>(states);

            foreach (InstanceState instanceState in states)
            {
                ushort buildingId = instanceState.instance.id.Building;
                if (instanceState is BuildingState originalState && MoveItTool.m_pillarMap.ContainsKey(buildingId) && MoveItTool.m_pillarMap[buildingId] > 0)
                {
                    ushort nodeId = MoveItTool.m_pillarMap[buildingId];
                    if (nodesWithAttachments.Contains(nodeId)) // The node is also selected
                    {
                        //Debug.Log($"Pillar {buildingId} for selected node {nodeId}");
                        continue;
                    }
                    MoveableBuilding original = (MoveableBuilding)instanceState.instance;
                    buildingBuffer[buildingId].m_flags |= Building.Flags.Hidden;
                    selection.Remove(original);
                    newStates.Remove(originalState);
                    BuildingState cloneState = null;
                    if (makeClone)
                    {
                        MoveableBuilding clone = original.Duplicate();
                        selection.Add(clone);
                        cloneState = (BuildingState)clone.SaveToState();
                        newStates.Add(cloneState);
                        Debug.Log($"Pillar {buildingId} for node {nodeId} duplicated to {clone.id.Building}");
                    }
                    else
                    {
                        Debug.Log($"Pillar {buildingId} for node {nodeId} hidden");
                    }
                    pillarsOriginalToClone.Add(originalState, cloneState);
                    original.isHidden = true;
                }
            }
            if (pillarsOriginalToClone.Count > 0)
            {
                MoveItTool.UpdatePillarMap();
            }
            states = newStates;
            watch.Stop();
            Debug.Log($"Pillars handled in {watch.ElapsedMilliseconds} ms\nSelected nodes:{nodesWithAttachments.Count}, total selection:{states.Count}, dups mapped:{pillarsOriginalToClone.Count}");
            PillarsProcessed = true;

            return(states);
        }
        public void UndoImplementation(bool reset = false)
        {
            if (m_states == null)
            {
                return;
            }

            Dictionary <Instance, Instance> toReplace   = new Dictionary <Instance, Instance>();
            Dictionary <ushort, ushort>     clonedNodes = new Dictionary <ushort, ushort>();

            Building[] buildingBuffer = BuildingManager.instance.m_buildings.m_buffer;

            // Recreate nodes
            foreach (InstanceState state in m_states)
            {
                if (state.instance.id.Type == InstanceType.NetNode)
                {
                    Instance clone = state.instance.Clone(state, null);
                    toReplace.Add(state.instance, clone);
                    clonedNodes.Add(state.instance.id.NetNode, clone.id.NetNode);
                    ActionQueue.instance.UpdateNodeIdInStateHistory(state.instance.id.NetNode, clone.id.NetNode);
                }
            }

            // Recreate everything except nodes and segments
            foreach (InstanceState state in m_states)
            {
                if (state.instance.id.Type == InstanceType.NetNode)
                {
                    continue;
                }
                if (state.instance.id.Type == InstanceType.NetSegment)
                {
                    continue;
                }
                if (state is ProcState)
                {
                    continue;
                }

                Instance clone = state.instance.Clone(state, clonedNodes);
                toReplace.Add(state.instance, clone);

                if (state.instance.id.Type == InstanceType.Prop)
                {
                    PropManager.instance.m_props.m_buffer[clone.id.Prop].FixedHeight = ((PropState)state).fixedHeight;
                }
                else if (state.instance.id.Type == InstanceType.Building)
                {
                    // Add attached nodes to the clonedNode list so other segments reconnect
                    BuildingState buildingState = state as BuildingState;
                    List <ushort> origNodeIds   = new List <ushort>();

                    MoveableBuilding cb          = clone as MoveableBuilding;
                    ushort           cloneNodeId = ((Building)cb.data).m_netNode;

                    if (reset)
                    {
                        ushort cloneId = cb.id.Building;

                        buildingBuffer[cloneId].m_flags = buildingBuffer[cloneId].m_flags & ~Building.Flags.BurnedDown;
                        buildingBuffer[cloneId].m_flags = buildingBuffer[cloneId].m_flags & ~Building.Flags.Collapsed;
                        buildingBuffer[cloneId].m_flags = buildingBuffer[cloneId].m_flags & ~Building.Flags.Abandoned;
                        buildingBuffer[cloneId].m_flags = buildingBuffer[cloneId].m_flags | Building.Flags.Active;
                        Thread.Sleep(50);
                    }

                    if (cloneNodeId != 0)
                    {
                        int c = 0;
                        foreach (InstanceState i in buildingState.subStates)
                        {
                            if (i is NodeState ns)
                            {
                                InstanceID instanceID = default;
                                instanceID.RawData = ns.id;
                                origNodeIds.Insert(c++, instanceID.NetNode);
                            }
                        }

                        c = 0;
                        while (cloneNodeId != 0)
                        {
                            ushort origNodeId = origNodeIds[c];

                            NetNode clonedAttachedNode = Singleton <NetManager> .instance.m_nodes.m_buffer[cloneNodeId];
                            if (clonedAttachedNode.Info.GetAI() is TransportLineAI)
                            {
                                cloneNodeId = clonedAttachedNode.m_nextBuildingNode;
                                continue;
                            }

                            if (clonedNodes.ContainsKey(origNodeId))
                            {
                                Debug.Log($"Node #{origNodeId} is already in clone list!");
                            }

                            clonedNodes.Add(origNodeId, cloneNodeId);

                            cloneNodeId = clonedAttachedNode.m_nextBuildingNode;

                            if (++c > 32768)
                            {
                                CODebugBase <LogChannel> .Error(LogChannel.Core, "Nodes: Invalid list detected!\n" + Environment.StackTrace);

                                break;
                            }
                        }
                    }
                }
            }

            // Recreate segments
            foreach (InstanceState state in m_states)
            {
                if (state is SegmentState segmentState)
                {
                    if (!clonedNodes.ContainsKey(segmentState.startNodeId))
                    {
                        InstanceID instanceID = InstanceID.Empty;
                        instanceID.NetNode = segmentState.startNodeId;

                        // Don't clone if node is missing
                        if (!((Instance)instanceID).isValid)
                        {
                            continue;
                        }

                        clonedNodes.Add(segmentState.startNodeId, segmentState.startNodeId);
                    }

                    if (!clonedNodes.ContainsKey(segmentState.endNodeId))
                    {
                        InstanceID instanceID = InstanceID.Empty;
                        instanceID.NetNode = segmentState.endNodeId;

                        // Don't clone if node is missing
                        if (!((Instance)instanceID).isValid)
                        {
                            continue;
                        }

                        clonedNodes.Add(segmentState.endNodeId, segmentState.endNodeId);
                    }

                    Instance clone = state.instance.Clone(state, clonedNodes);
                    toReplace.Add(state.instance, clone);
                    MoveItTool.NS.SetSegmentModifiers(clone.id.NetSegment, segmentState);
                }
            }

            if (replaceInstances)
            {
                ReplaceInstances(toReplace);
                ActionQueue.instance.ReplaceInstancesBackward(toReplace);

                selection = new HashSet <Instance>();
                foreach (Instance i in m_oldSelection)
                {
                    if (i is MoveableProc)
                    {
                        continue;
                    }
                    selection.Add(i);
                }
                MoveItTool.m_debugPanel.UpdatePanel();
            }
        }
        public void UndoImplementation(bool reset = false)
        {
            if (m_states == null)
            {
                return;
            }

            Dictionary <Instance, Instance> toReplace   = new Dictionary <Instance, Instance>();
            Dictionary <ushort, ushort>     clonedNodes = new Dictionary <ushort, ushort>();

            var stateToClone           = new Dictionary <InstanceState, Instance>();
            var InstanceID_origToClone = new Dictionary <InstanceID, InstanceID>();

            Building[] buildingBuffer = BuildingManager.instance.m_buildings.m_buffer;

            // Recreate nodes
            foreach (InstanceState state in m_states)
            {
                try
                {
                    if (state.instance.id.Type == InstanceType.NetNode)
                    {
                        Instance clone = state.instance.Clone(state, null);
                        toReplace.Add(state.instance, clone);
                        stateToClone.Add(state, clone);
                        InstanceID_origToClone.Add(state.instance.id, clone.id);
                        clonedNodes.Add(state.instance.id.NetNode, clone.id.NetNode);
                        ActionQueue.instance.UpdateNodeIdInStateHistory(state.instance.id.NetNode, clone.id.NetNode);
                    }
                }
                catch (Exception e)
                {
                    Debug.Log($"Undo Bulldoze failed on {(state is InstanceState ? state.prefabName : "unknown")}\n{e}");
                }
            }

            // Recreate everything except nodes and segments
            foreach (InstanceState state in m_states)
            {
                try
                {
                    if (state.instance.id.Type == InstanceType.NetNode)
                    {
                        continue;
                    }
                    if (state.instance.id.Type == InstanceType.NetSegment)
                    {
                        continue;
                    }
                    if (state is ProcState)
                    {
                        continue;
                    }

                    Instance clone = state.instance.Clone(state, clonedNodes);
                    toReplace.Add(state.instance, clone);
                    stateToClone.Add(state, clone);
                    InstanceID_origToClone.Add(state.instance.id, clone.id);

                    if (state.instance.id.Type == InstanceType.Prop)
                    {
                        PropManager.instance.m_props.m_buffer[clone.id.Prop].FixedHeight = ((PropState)state).fixedHeight;
                    }
                    else if (state.instance.id.Type == InstanceType.Building)
                    {
                        // Add attached nodes to the clonedNode list so other segments reconnect
                        BuildingState buildingState = state as BuildingState;
                        List <ushort> origNodeIds   = new List <ushort>();

                        MoveableBuilding cb          = clone as MoveableBuilding;
                        ushort           cloneNodeId = ((Building)cb.data).m_netNode;

                        if (reset)
                        {
                            ushort cloneId = cb.id.Building;

                            buildingBuffer[cloneId].m_flags = buildingBuffer[cloneId].m_flags & ~Building.Flags.BurnedDown;
                            buildingBuffer[cloneId].m_flags = buildingBuffer[cloneId].m_flags & ~Building.Flags.Collapsed;
                            buildingBuffer[cloneId].m_flags = buildingBuffer[cloneId].m_flags & ~Building.Flags.Abandoned;
                            buildingBuffer[cloneId].m_flags = buildingBuffer[cloneId].m_flags | Building.Flags.Active;
                            Thread.Sleep(50);
                        }

                        if (cloneNodeId != 0)
                        {
                            int c = 0;
                            foreach (InstanceState i in buildingState.subStates)
                            {
                                if (i is NodeState ns)
                                {
                                    InstanceID instanceID = default;
                                    instanceID.RawData = ns.id;
                                    origNodeIds.Insert(c++, instanceID.NetNode);
                                }
                            }

                            c = 0;
                            while (cloneNodeId != 0)
                            {
                                ushort origNodeId = origNodeIds[c];

                                NetNode clonedAttachedNode = Singleton <NetManager> .instance.m_nodes.m_buffer[cloneNodeId];
                                if (clonedAttachedNode.Info.GetAI() is TransportLineAI)
                                {
                                    cloneNodeId = clonedAttachedNode.m_nextBuildingNode;
                                    continue;
                                }

                                if (clonedNodes.ContainsKey(origNodeId))
                                {
                                    Debug.Log($"Node #{origNodeId} is already in clone list!");
                                }

                                clonedNodes.Add(origNodeId, cloneNodeId);

                                cloneNodeId = clonedAttachedNode.m_nextBuildingNode;

                                if (++c > 32768)
                                {
                                    CODebugBase <LogChannel> .Error(LogChannel.Core, "Nodes: Invalid list detected!\n" + Environment.StackTrace);

                                    break;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.Log($"Undo Bulldoze failed on {(state is InstanceState ? state.prefabName : "unknown")}\n{e}");
                }
            }

            // Recreate segments
            foreach (InstanceState state in m_states)
            {
                try
                {
                    if (state is SegmentState segmentState)
                    {
                        if (!clonedNodes.ContainsKey(segmentState.startNodeId))
                        {
                            InstanceID instanceID = InstanceID.Empty;
                            instanceID.NetNode = segmentState.startNodeId;

                            // Don't clone if node is missing
                            if (!((Instance)instanceID).isValid)
                            {
                                continue;
                            }

                            clonedNodes.Add(segmentState.startNodeId, segmentState.startNodeId);
                        }

                        if (!clonedNodes.ContainsKey(segmentState.endNodeId))
                        {
                            InstanceID instanceID = InstanceID.Empty;
                            instanceID.NetNode = segmentState.endNodeId;

                            // Don't clone if node is missing
                            if (!((Instance)instanceID).isValid)
                            {
                                continue;
                            }

                            clonedNodes.Add(segmentState.endNodeId, segmentState.endNodeId);
                        }

                        Instance clone = state.instance.Clone(state, clonedNodes);
                        toReplace.Add(state.instance, clone);
                        stateToClone.Add(state, clone);
                        InstanceID_origToClone.Add(state.instance.id, clone.id);
                        MoveItTool.NS.SetSegmentModifiers(clone.id.NetSegment, segmentState);
                    }
                }
                catch (Exception e)
                {
                    Debug.Log($"Undo Bulldoze failed on {(state is InstanceState ? state.prefabName : "unknown")}\n{e}");
                }
            }

            // clone integrations.
            foreach (var item in stateToClone)
            {
                foreach (var data in item.Key.IntegrationData)
                {
                    try
                    {
                        data.Key.Paste(item.Value.id, data.Value, InstanceID_origToClone);
                    }
                    catch (Exception e)
                    {
                        InstanceID sourceInstanceID = item.Key.instance.id;
                        InstanceID targetInstanceID = item.Value.id;
                        Debug.LogError($"integration {data.Key} Failed to paste from " +
                                       $"{sourceInstanceID.Type}:{sourceInstanceID.Index} to {targetInstanceID.Type}:{targetInstanceID.Index}");
                        DebugUtils.LogException(e);
                    }
                }
            }

            if (replaceInstances)
            {
                ReplaceInstances(toReplace);
                ActionQueue.instance.ReplaceInstancesBackward(toReplace);

                selection = new HashSet <Instance>();
                foreach (Instance i in m_oldSelection)
                {
                    if (i is MoveableProc)
                    {
                        continue;
                    }
                    selection.Add(i);
                }
                MoveItTool.m_debugPanel.UpdatePanel();
            }

            // Does not check MoveItTool.advancedPillarControl, because even if disabled now advancedPillarControl may have been active earlier in action queue
            foreach (KeyValuePair <BuildingState, BuildingState> pillarClone in pillarsOriginalToClone)
            {
                BuildingState originalState = pillarClone.Key;
                originalState.instance.isHidden = false;
                buildingBuffer[originalState.instance.id.Building].m_flags &= ~Building.Flags.Hidden;
                selection.Add(originalState.instance);
                m_states.Add(originalState);
            }
            if (pillarsOriginalToClone.Count > 0)
            {
                MoveItTool.UpdatePillarMap();
            }
        }
Exemple #14
0
        public override void Transform(InstanceState instanceState, ref Matrix4x4 matrix4x, float deltaHeight, float deltaAngle, Vector3 center, bool followTerrain)
        {
            BuildingState state = instanceState as BuildingState;

            Vector3 newPosition = matrix4x.MultiplyPoint(state.position - center);

            newPosition.y = state.position.y + deltaHeight;

            float terrainHeight = TerrainManager.instance.SampleOriginalRawHeightSmooth(newPosition);
            bool  isFixed       = GetFixedHeightFlag(id.Building);

            if (!isFixed)
            {
                AddFixedHeightFlag(id.Building);
            }

            if (followTerrain)
            {
                newPosition.y = newPosition.y + terrainHeight - state.terrainHeight;
            }

            AddFixedHeightFlag(id.Building);
            Move(newPosition, state.angle + deltaAngle);

            Matrix4x4 matrixSub = default;

            matrixSub.SetTRS(Vector3.zero, Quaternion.AngleAxis(deltaAngle * Mathf.Rad2Deg, Vector3.down), Vector3.one);

            if (state.subStates != null)
            {
                foreach (InstanceState subState in state.subStates)
                {
                    Vector3 subOffset   = (subState.position - center) - (state.position - center);
                    Vector3 subPosition = TransformPosition + matrixSub.MultiplyPoint(subOffset);

                    subPosition.y = subState.position.y - state.position.y + newPosition.y;

                    subState.instance.Move(subPosition, subState.angle + deltaAngle);
                    if (subState.instance is MoveableNode mn)
                    {
                        if (mn.Pillar != null)
                        {
                            mn.Pillar.Move(subPosition, subState.angle + deltaAngle);
                        }
                    }

                    if (subState is BuildingState bs)
                    {
                        if (bs.subStates != null)
                        {
                            foreach (InstanceState subSubState in bs.subStates)
                            {
                                Vector3 subSubOffset   = (subSubState.position - center) - (state.position - center);
                                Vector3 subSubPosition = TransformPosition + matrixSub.MultiplyPoint(subSubOffset);

                                subSubPosition.y = subSubState.position.y - state.position.y + newPosition.y;

                                subSubState.instance.Move(subSubPosition, subSubState.angle + deltaAngle);
                                if (subSubState.instance is MoveableNode mn2)
                                {
                                    if (mn2.Pillar != null)
                                    {
                                        mn2.Pillar.Move(subSubPosition, subSubState.angle + deltaAngle);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (!isFixed && Mathf.Abs(terrainHeight - newPosition.y) < 0.01f)
            {
                RemoveFixedHeightFlag(id.Building);
            }
        }
        public override void Undo()
        {
            if (m_states == null)
            {
                return;
            }

            Dictionary <Instance, Instance> toReplace   = new Dictionary <Instance, Instance>();
            Dictionary <ushort, ushort>     clonedNodes = new Dictionary <ushort, ushort>();

            // Recreate nodes
            foreach (InstanceState state in m_states)
            {
                if (state.instance.id.Type == InstanceType.NetNode)
                {
                    Instance clone = state.instance.Clone(state, null);
                    toReplace.Add(state.instance, clone);
                    clonedNodes.Add(state.instance.id.NetNode, clone.id.NetNode);
                    ActionQueue.instance.UpdateNodeIdInStateHistory(state.instance.id.NetNode, clone.id.NetNode);
                    //Debug.Log($"Cloned N:{state.instance.id.NetNode}->{clone.id.NetNode}");
                }
            }

            // Recreate everything except nodes and segments
            foreach (InstanceState state in m_states)
            {
                if (state.instance.id.Type == InstanceType.NetNode)
                {
                    continue;
                }
                if (state.instance.id.Type == InstanceType.NetSegment)
                {
                    continue;
                }

                Instance clone = state.instance.Clone(state, clonedNodes);
                toReplace.Add(state.instance, clone);

                // Add attached nodes to the clonedNode list so other segments reconnect
                if (state.instance.id.Type == InstanceType.Building)
                {
                    BuildingState buildingState = state as BuildingState;
                    List <ushort> origNodeIds   = new List <ushort>();

                    MoveableBuilding cb          = clone as MoveableBuilding;
                    ushort           cloneNodeId = ((Building)cb.data).m_netNode;

                    if (cloneNodeId != 0)
                    {
                        int    c    = 0;
                        string msg2 = "Original attached nodes:";
                        foreach (InstanceState i in buildingState.subStates)
                        {
                            if (i is NodeState ns)
                            {
                                InstanceID instanceID = default(InstanceID);
                                instanceID.RawData = ns.id;
                                //msg2 += $"\n{c} - Attached node #{instanceID.NetNode}: {ns.Info.Name}";
                                origNodeIds.Insert(c++, instanceID.NetNode);
                            }
                        }
                        //Debug.Log(msg2);

                        c    = 0;
                        msg2 = "";
                        while (cloneNodeId != 0)
                        {
                            ushort origNodeId = origNodeIds[c];

                            NetNode clonedAttachedNode = NetManager.instance.m_nodes.m_buffer[cloneNodeId];
                            if (clonedAttachedNode.Info.GetAI() is TransportLineAI)
                            {
                                cloneNodeId = clonedAttachedNode.m_nextBuildingNode;
                                continue;
                            }

                            if (clonedNodes.ContainsKey(origNodeId))
                            {
                                Debug.Log($"Node #{origNodeId} is already in clone list!");
                            }

                            clonedNodes.Add(origNodeId, cloneNodeId);

                            msg2       += $"\n{c} - {origNodeId} -> {cloneNodeId} {clonedAttachedNode.Info.GetAI()}";
                            cloneNodeId = clonedAttachedNode.m_nextBuildingNode;

                            if (++c > 32768)
                            {
                                CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                                break;
                            }
                        }
                        Debug.Log(msg2);
                    }
                }
            }

            //string msg = "Cloned Nodes:\n";
            //foreach (KeyValuePair<ushort, ushort> kvp in clonedNodes)
            //{
            //    msg += $"{kvp.Key} => {kvp.Value}\n";
            //}
            //Debug.Log(msg);

            // Recreate segments
            foreach (InstanceState state in m_states)
            {
                if (state.instance.id.Type == InstanceType.NetSegment)
                {
                    SegmentState segState = state as SegmentState;

                    if (!clonedNodes.ContainsKey(segState.startNode))
                    {
                        InstanceID instanceID = InstanceID.Empty;
                        instanceID.NetNode = segState.startNode;

                        // Don't clone if node is missing
                        if (!((Instance)instanceID).isValid)
                        {
                            continue;
                        }

                        clonedNodes.Add(segState.startNode, segState.startNode);
                    }

                    if (!clonedNodes.ContainsKey(segState.endNode))
                    {
                        InstanceID instanceID = InstanceID.Empty;
                        instanceID.NetNode = segState.endNode;

                        // Don't clone if node is missing
                        if (!((Instance)instanceID).isValid)
                        {
                            continue;
                        }

                        clonedNodes.Add(segState.endNode, segState.endNode);
                    }

                    Instance clone = state.instance.Clone(state, clonedNodes);
                    toReplace.Add(state.instance, clone);
                }
            }

            if (replaceInstances)
            {
                ReplaceInstances(toReplace);
                ActionQueue.instance.ReplaceInstancesBackward(toReplace);

                selection = m_oldSelection;
            }
        }