Ejemplo n.º 1
0
        /// <summary>
        /// This function try different strategy to find the best connection point to use on the specified grabbed part
        /// to start the flex chain. It is assumed that the grab part only have two connection, then:
        /// 1) if one connection is flexible and not the other, return this one,
        /// 2) else if one connection leads to a flexible connection and not the other, return this one
        /// 3) else if one connection is connected to a brick part of the track list and not the other, return this one,
        /// 4) else if both connections are or lead to a flexible one, return the connection closest to the mouse click
        /// 5) else if no connection are or lead to a flexible one, return null (no flexible chain can be created)
        /// </summary>
        /// <param name="trackList">A set of track hopefully connected together, and hopefully containing flex track</param>
        /// <param name="grabbedTrack">The part which will try to reach the target. It should be part of the list.</param>
        /// <param name="mouseCoordInStud">the coordinate of the mouse in stud coord</param>
        /// <returns>The best connection point of the grabbed part or null</returns>
        private LayerBrick.Brick.ConnectionPoint findStartingConnectionPoint(List <Layer.LayerItem> trackList, LayerBrick.Brick grabbedTrack, PointF mouseCoordInStud)
        {
            // try to find the best first connection point which will be the end target of the flex.
            LayerBrick.Brick.ConnectionPoint grabbedFirstConnection  = grabbedTrack.ConnectionPoints[0];
            LayerBrick.Brick.ConnectionPoint grabbedSecondConnection = grabbedTrack.ConnectionPoints[1];
            // by preference choose the not flexible connection on the grabbed part
            float firstHingeAngle  = BrickLibrary.Instance.getConnexionHingeAngle(grabbedFirstConnection.Type);
            float secondHingeAngle = BrickLibrary.Instance.getConnexionHingeAngle(grabbedSecondConnection.Type);

            if (firstHingeAngle != 0.0f && secondHingeAngle == 0.0f)
            {
                return(grabbedSecondConnection);
            }
            else if (firstHingeAngle == 0.0f && secondHingeAngle != 0.0f)
            {
                return(grabbedFirstConnection);
            }
            else if (firstHingeAngle == 0.0f && secondHingeAngle == 0.0f)
            {
                // neither connection are flexibles on the grab part, so we choose the connection that
                // do not lead to a flexible part (and the other connection does)
                bool firstConnectionLeadToFlexiblePart  = false;
                bool secondConnectionLeadToFlexiblePart = false;
                LayerBrick.Brick.ConnectionPoint firstConnectionLead  = grabbedFirstConnection;
                LayerBrick.Brick.ConnectionPoint secondConnectionLead = grabbedSecondConnection;
                // use a clone of the track list because we will remove the tested track to avoid infinite loop
                // in case of a close track chain
                List <Layer.LayerItem> remaingTrackToTestList = new List <Layer.LayerItem>(trackList);
                while ((!firstConnectionLeadToFlexiblePart || !secondConnectionLeadToFlexiblePart) &&
                       (firstConnectionLead != null || secondConnectionLead != null))
                {
                    // check if the leading bricks are in the trask list otherwise stop to follow the lead
                    LayerBrick.Brick firstBrickLead  = (firstConnectionLead != null) ? firstConnectionLead.mMyBrick : null;
                    LayerBrick.Brick secondBrickLead = (secondConnectionLead != null) ? secondConnectionLead.mMyBrick : null;
                    if (!remaingTrackToTestList.Contains(firstBrickLead))
                    {
                        firstConnectionLead = null;
                    }
                    if (!remaingTrackToTestList.Contains(secondBrickLead))
                    {
                        secondConnectionLead = null;
                    }
                    // remove those check brick from the list. Do it after and not in the if because first and second brick
                    // may be the same and flexible, so it could be unfair to the second test
                    remaingTrackToTestList.Remove(firstBrickLead);
                    remaingTrackToTestList.Remove(secondBrickLead);
                    // set the flag and follow the lead for the two leads
                    followConnectionToFindFlexiblePart(ref firstConnectionLead, ref firstConnectionLeadToFlexiblePart);
                    followConnectionToFindFlexiblePart(ref secondConnectionLead, ref secondConnectionLeadToFlexiblePart);
                }
                // either the loop is finished because we found flexible part on both side, or because we
                // finished to explore the two paths. Check if we have only one side leading to a flexible part
                // and choose the other one, otherwise go to the default method
                if (firstConnectionLeadToFlexiblePart && !secondConnectionLeadToFlexiblePart)
                {
                    return(grabbedSecondConnection);
                }
                else if (!firstConnectionLeadToFlexiblePart && secondConnectionLeadToFlexiblePart)
                {
                    return(grabbedFirstConnection);
                }
                else if (!firstConnectionLeadToFlexiblePart && !secondConnectionLeadToFlexiblePart)
                {
                    return(null);                    // neither connection lead to a flexible part
                }
            }

            // both connection of the grab part are flexibles, or both side of the grab part
            // lead to a flexible part, so we choose the connection which neighboor is not in the list
            bool isGrabbedFirstNeighborInList  = trackList.Contains(grabbedFirstConnection.ConnectedBrick);
            bool isGrabbedSecondNeighborInList = trackList.Contains(grabbedSecondConnection.ConnectedBrick);

            if (isGrabbedFirstNeighborInList && !isGrabbedSecondNeighborInList)
            {
                return(grabbedSecondConnection);
            }
            else if (!isGrabbedFirstNeighborInList && isGrabbedSecondNeighborInList)
            {
                return(grabbedFirstConnection);
            }
            else
            {
                // both or neither neighboor are in the list, so we choose the closest connection to the mouse
                PointF distToFirstConnection        = new PointF(grabbedFirstConnection.PositionInStudWorldCoord.X - mouseCoordInStud.X, grabbedFirstConnection.PositionInStudWorldCoord.Y - mouseCoordInStud.Y);
                PointF distToSecondConnection       = new PointF(grabbedSecondConnection.PositionInStudWorldCoord.X - mouseCoordInStud.X, grabbedSecondConnection.PositionInStudWorldCoord.Y - mouseCoordInStud.Y);
                float  squareDistToFirstConnection  = (distToFirstConnection.X * distToFirstConnection.X) + (distToFirstConnection.Y * distToFirstConnection.Y);
                float  squareDistToSecondConnection = (distToSecondConnection.X * distToSecondConnection.X) + (distToSecondConnection.Y * distToSecondConnection.Y);
                if (squareDistToFirstConnection < squareDistToSecondConnection)
                {
                    return(grabbedFirstConnection);
                }
                else
                {
                    return(grabbedSecondConnection);
                }
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// construct a new node
 /// </summary>
 /// <param name="brick">the brick corresponding to this node</param>
 public AStarNode(LayerBrick.Brick brick)
 {
     mBrick = brick;
 }
Ejemplo n.º 3
0
 public RulerAttachementSet(LayerBrick.Brick owner)
 {
     mOwnerBrick = owner;
 }
Ejemplo n.º 4
0
        /// <summary>
        /// This function check all the electric circuit connected to the specified brick, starting from
        /// the specified brick. The startingBrick must have an ElectricCircuitIndexList not null.
        /// </summary>
        /// <param name="startingBrick">The brick to start from.</param>
        private static void checkFromOneBrick(LayerBrick.Brick startingBrick)
        {
            // the list of all the shortcut found
            List <LayerBrick.Brick.ConnectionPoint> shortcuts = new List <LayerBrick.Brick.ConnectionPoint>();

            // clear the list and add the first node
            mBricksToExplore.Clear();
            mBricksToExplore.Add(startingBrick);
            // init the first connection of the starting brick with the new timestamp
            LayerBrick.Brick.ConnectionPoint firstConnection = startingBrick.ConnectionPoints[startingBrick.ElectricCircuitIndexList[0].mIndex1];
            firstConnection.Polarity = sTimeStamp;
            // if the first connection is connected to another brick, also add this brick in the list
            if (firstConnection.ConnectionLink != null)
            {
                firstConnection.ConnectionLink.Polarity = (short)(-sTimeStamp);
                mBricksToExplore.Add(firstConnection.ConnectedBrick);
            }

            //explore while the list is not empty
            while (mBricksToExplore.Count > 0)
            {
                // pop the first node of the list
                LayerBrick.Brick brick = mBricksToExplore[0];
                mBricksToExplore.RemoveAt(0);

                // declare a boolean variable to check if during the exploration of all the circuits of the
                // brick, one was ignore. If yes and later we transfert electricity on the brick, we will
                // have to re-explore the brick for checking again the ignored circuits
                bool needToReexploreTheBrick = false;

                // iterate on all the brick connection
                if (brick.ElectricCircuitIndexList != null)
                {
                    foreach (BrickLibrary.Brick.ElectricCircuit circuit in brick.ElectricCircuitIndexList)
                    {
                        // get the connection point of the current circuit inside the brick
                        LayerBrick.Brick.ConnectionPoint start = brick.ConnectionPoints[circuit.mIndex1];
                        LayerBrick.Brick.ConnectionPoint end   = brick.ConnectionPoints[circuit.mIndex2];

                        // check wich one has the incoming electricity, if it's not the start,
                        // swap the two connections point in order to have only one algorithm in the following
                        // after this swap, normally we should have the start +/-timestamp
                        if (Math.Abs(end.Polarity) == sTimeStamp)
                        {
                            LayerBrick.Brick.ConnectionPoint swap = start;
                            start = end;
                            end   = swap;
                        }

                        // transfert the time stamp from the start to the end
                        if (Math.Abs(start.Polarity) == sTimeStamp)
                        {
                            // check if we have a shortcut in the current circuit.
                            // If the end is already set with the same polarity than the start, we have a shortcut
                            if (end.Polarity == start.Polarity)
                            {
                                // shortcut!!
                                shortcuts.Add(start);
                            }
                            // else if no shorcut check if we didn't already transfer the electricity to the end
                            else if (end.Polarity != -start.Polarity)
                            {
                                // the end connection was not explored yet, so we will set its timestamp and push
                                // his neighbor for future exploration.

                                // transfert the electricity to the end
                                end.Polarity = (short)(-start.Polarity);

                                // for complex part that has several circuit in it, if we transfert electricity
                                // in a circuit, this circuit may also be linked to a previous one already iterated.
                                // This is the case of the rail jonction point. The circuit 0 is for example the
                                // straight line, whereas circuit 1, is the curved derivation. If the current comes
                                // from circuit 1, then the circuit 0 was already ignored and must be re-tested.
                                // So we reinsert the part if some circuit werz ignored on this part
                                if (needToReexploreTheBrick)
                                {
                                    mBricksToExplore.Insert(0, brick);
                                    needToReexploreTheBrick = false;
                                }

                                // add the neighbor if any
                                LayerBrick.Brick.ConnectionPoint connectionLink = end.ConnectionLink;
                                if (connectionLink != null)
                                {
                                    // check if we have a shortcut
                                    if (connectionLink.Polarity == end.Polarity)
                                    {
                                        // shortcut!!
                                        shortcuts.Add(end);
                                    }
                                    // if no shortcut, check if we have to to explore the connection
                                    else if (connectionLink.Polarity != -end.Polarity)
                                    {
                                        // transfert the polarity to the linked connection
                                        connectionLink.Polarity = (short)(-end.Polarity);
                                        // and add the new brick in the list for furture exploration
                                        mBricksToExplore.Add(end.ConnectedBrick);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // no electric current in this circuit. This may be the case with a part
                            // with different independant circuit.
                            // Maybe the circuits are linked, maybe they are independant, anyway, we
                            // check the flag to tell that the brick need to be re-explored
                            needToReexploreTheBrick = true;
                        }
                    }
                }
            }

            // set the polarity to 0 for all the connection where we found the shortcuts
            foreach (LayerBrick.Brick.ConnectionPoint connection in shortcuts)
            {
                connection.HasElectricShortcut = true;
            }
        }
Ejemplo n.º 5
0
        public static List <Layer.LayerItem> findPath(LayerBrick.Brick startBrick, LayerBrick.Brick goalBrick)
        {
            List <Layer.LayerItem> result = new List <Layer.LayerItem>();

            // init some variables
            sOpenList.Clear();
            sCloseList.Clear();

            // create the first node with the starting brick
            AStarNode currentNode = new AStarNode(startBrick);

            currentNode.ComputeParameters(goalBrick);

            // start of the loop
            while (currentNode != null)
            {
                // get the refernce of the current brick
                LayerBrick.Brick currentBrick = currentNode.mBrick;

                // check if we reached the goal
                if (currentBrick == goalBrick)
                {
                    // the goal is reached, put all the bricks in the result list
                    for (AStarNode node = currentNode; node != null; node = node.mParentNode)
                    {
                        result.Add(node.mBrick);
                    }
                    // reverse the list to have the path from start to goal
                    result.Reverse();
                    return(result);
                }

                // now iterate on all the connexion point of the current brick
                List <LayerBrick.Brick.ConnectionPoint> connexionList = currentBrick.ConnectionPoints;
                if (connexionList != null)
                {
                    foreach (LayerBrick.Brick.ConnectionPoint connexion in connexionList)
                    {
                        // check if the connexion is free, or if there is a brick connected to it
                        LayerBrick.Brick neighborBrick = connexion.ConnectedBrick;
                        if (neighborBrick == null)
                        {
                            continue;
                        }

                        // we found a valid connexion, create a new node for this new potential brick to explore
                        AStarNode potentialNewNeighborNode = new AStarNode(neighborBrick);
                        potentialNewNeighborNode.mParentNode = currentNode;
                        potentialNewNeighborNode.ComputeParameters(goalBrick);

                        // try to search the neighbor brick in the close list
                        AStarNode neighborNode = sCloseList.Find(neighborBrick);
                        if (neighborNode != null)
                        {
                            // we found this brick in the close list, that means this brick was already explored,
                            // but we need to check if we found a shorter way, by checking the f values
                            // so we check if the node stay where it is
                            if (neighborNode.f <= potentialNewNeighborNode.f)
                            {
                                continue;                                 // that's fine the previous exploration was the shorter way
                            }
                            // else we found a shorter way
                            // so we remove the node from the close list (cause we will add it in open)
                            sCloseList.Remove(neighborNode);
                        }
                        else
                        {
                            // the neighbor brick is not in the close list so now we check if it is in open list
                            neighborNode = sOpenList.Find(neighborBrick);
                            if (neighborNode != null)
                            {
                                // the brick is already in the open list but we check if we have found a shorter way
                                // by checking the f values.
                                if (neighborNode.f <= potentialNewNeighborNode.f)
                                {
                                    continue;                                     // that's fine the new way we found is not shorter
                                }
                                // else that mean the new way is shorter
                                // so we remove the node from the open list (cause we will add the better one)
                                sOpenList.Remove(neighborNode);
                            }
                        }

                        // If we reach this point, that means the potential new node is valid and
                        // must be added in the open list
                        sOpenList.Add(potentialNewNeighborNode);
                    }
                }

                // the current node is finished to be expored, so add it in the close list
                sCloseList.Add(currentNode);

                // get the next node to explore
                if (sOpenList.Count > 0)
                {
                    currentNode = sOpenList[0];
                    sOpenList.RemoveAt(0);
                }
                else
                {
                    currentNode = null;
                }
            }

            // the open list is empty and we didn't find the goal brick, so the search failed.
            return(result);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Write a list of prefered connections. The list is computed as follow:
        /// First we get all the free connections in the whole group, then we split that
        /// list into sub-list per connection type, and then for each sub-list we create
        /// a loop of next connection preferences.
        /// For example if the group contains 4 track and 3 road connections, and the
        /// two track parts are connected, then we have only 2 free track connections
        /// and 3 free road connection. We will generate a first cycle for the track
        /// and a second cycle for the road.
        /// </summary>
        /// <param name="xmlWriter">The xmlWritter where to write the list</param>
        /// <param name="group">The group for which we are writting the list</param>
        private void writeGroupConnectionPreferenceList(XmlWriter xmlWriter, Layer.Group group)
        {
            // get all the bricks in a flat list (removing intermediate group)
            List <Layer.LayerItem> allBricks = group.getAllLeafItems();

            // if the group doesn't contains brick, just early exit
            if ((allBricks.Count == 0) || !(allBricks[0] is LayerBrick.Brick))
            {
                return;
            }

            // declare a dictionary of list of connections, to store all the connections separated by connection type (which is the key of the dictionnary)
            Dictionary <int, List <ConnectionAndIndex> > connectionsPerType = new Dictionary <int, List <ConnectionAndIndex> >();
            // declare a global counter to count the connection index inside the group
            int connectionCounter = 0;

            // now, iterate on all the connections of all the bricks, and create separated list of free connection
            foreach (Layer.LayerItem item in allBricks)
            {
                LayerBrick.Brick brick = item as LayerBrick.Brick;
                if (brick.HasConnectionPoint)
                {
                    foreach (LayerBrick.Brick.ConnectionPoint connection in brick.ConnectionPoints)
                    {
                        if (connection.IsFree)
                        {
                            // we found a free connection, check if the list for its type was already added in the dictionary
                            if (!connectionsPerType.ContainsKey(connection.Type))
                            {
                                connectionsPerType.Add(connection.Type, new List <ConnectionAndIndex>());
                            }
                            // now get the list corresponding to the type
                            List <ConnectionAndIndex> freeConnectionList = connectionsPerType[connection.Type];
                            // then add the connection in the list
                            freeConnectionList.Add(new ConnectionAndIndex(connection, connectionCounter));
                        }

                        // increase the connection counter, no matter if the current connection is free or not
                        connectionCounter++;
                    }
                }
            }

            // check if we found something
            if (connectionsPerType.Count > 0)
            {
                // write the header of the list
                xmlWriter.WriteStartElement("GroupConnectionPreferenceList");

                // now iterate on the dictionary, and for each list, create a cycle
                foreach (KeyValuePair <int, List <ConnectionAndIndex> > connectionsOfOneType in connectionsPerType)
                {
                    for (int i = 0; i < connectionsOfOneType.Value.Count; ++i)
                    {
                        // get the current and the next connection
                        ConnectionAndIndex currentConnection = connectionsOfOneType.Value[i];
                        ConnectionAndIndex nextConnection    = (i == connectionsOfOneType.Value.Count - 1) ? connectionsOfOneType.Value[0] : connectionsOfOneType.Value[i + 1];
                        // write the current prefered link
                        xmlWriter.WriteStartElement("nextIndex");
                        xmlWriter.WriteAttributeString("from", currentConnection.mIndexInTheGroup.ToString());
                        xmlWriter.WriteValue(nextConnection.mIndexInTheGroup);
                        xmlWriter.WriteEndElement();                         // nextIndex
                    }
                }

                xmlWriter.WriteEndElement();                 // GroupConnectionPreferenceList
            }
        }
Ejemplo n.º 7
0
 public RotateAndMoveBrick(LayerBrick layer, List <Layer.LayerItem> bricks, float angle, LayerBrick.Brick pivotBrick, PointF move)
     : base(layer, bricks, angle, pivotBrick)
 {
     this.MustUpdateBrickConnectivity = false;             // the connectivity will be updated by the move action
     mMoveAction = new MoveBrick(layer, bricks, move);
 }
Ejemplo n.º 8
0
        private int mNextPreferedActiveConnectionIndex = 0; // the prefered active connection index according to the brick library

        /// <summary>
        /// Add a new named group which has the specified partNumber on the specifier layer, and connected it to
        /// the specified selectedItem (part or group) using the specified wanted connection for that new part.
        /// </summary>
        /// <param name="layer">The layer on which to add the group, and in which the selectedItem is selected</param>
        /// <param name="selectedItem">The single selected item (this can be a single part or a single group). This parameter cannot be null.</param>
        /// <param name="partNumber">The number of the named group to add</param>
        /// <param name="wantedConnexion">The connection index of the group to add that should be used to connect to the selected item, or -1 if you don't care.</param>
        public AddConnectGroup(LayerBrick layer, Layer.LayerItem selectedItem, string partNumber, int wantedConnexion)
        {
            // the selected item should not be null
            System.Diagnostics.Debug.Assert(selectedItem != null);

            // save the layer and construct the group
            mBrickLayer = layer;
            mGroup      = new Layer.Group(partNumber);
            // get the flat list of bricks from the hierarchical group
            mBricksInTheGroup = mGroup.getAllLeafItems();

            // get the connectable brick among the selection, and also the selected item (in case the selected item is a single group without connections points)
            LayerBrick.Brick selectedBrick = layer.getConnectableBrick();
            LayerBrick.Brick brickToConnectInAddedGroup = null;

            // check if we can attach the group to the unique selected object
            if ((selectedBrick != null) && selectedBrick.HasConnectionPoint)
            {
                // find the brick of the group that will be connected to the selected brick
                brickToConnectInAddedGroup = findBrickToConnectAndSetBestConnectionPointIndex(selectedItem, ref wantedConnexion);
            }

            // check if the brick to connect is valid and has connection point
            if ((brickToConnectInAddedGroup != null) && brickToConnectInAddedGroup.HasConnectionPoint)
            {
                // after setting the active connection point index from which this brick will be attached,
                // get the prefered index from the library
                mNextPreferedActiveConnectionIndex = BrickLibrary.Instance.getConnectionNextPreferedIndex(partNumber, wantedConnexion);

                // Compute the orientation of the bricks
                float newOrientation = AddConnectBrick.sGetOrientationOfConnectedBrick(selectedBrick, brickToConnectInAddedGroup);
                newOrientation -= brickToConnectInAddedGroup.Orientation;
                // Rotate all the bricks of the group first before translating
                RotateBrickOnPivotBrick rotateBricksAction = new RotateBrickOnPivotBrick(layer, mBricksInTheGroup, newOrientation, brickToConnectInAddedGroup);
                rotateBricksAction.MustUpdateBrickConnectivity = false;
                rotateBricksAction.redo();

                // compute the translation to add to all the bricks
                PointF translation = new PointF(selectedBrick.ActiveConnectionPosition.X - brickToConnectInAddedGroup.ActiveConnectionPosition.X,
                                                selectedBrick.ActiveConnectionPosition.Y - brickToConnectInAddedGroup.ActiveConnectionPosition.Y);
                mGroup.translate(translation);
            }
            else
            {
                // and just compute the position to the right of the selected item
                PointF position = selectedItem.Position;
                position.X     += selectedItem.DisplayArea.Width;
                mGroup.Position = position;

                // the reassing the selected brick with the first brick of the group if the selected item is a group
                // so that the brick index can correctly be set
                if (selectedItem.IsAGroup)
                {
                    selectedBrick = (selectedItem as Layer.Group).getAllLeafItems()[0] as LayerBrick.Brick;
                }
                else
                {
                    selectedBrick = selectedItem as LayerBrick.Brick;
                }
            }

            // set the index of the group in the list just after the selected brick
            if (selectedBrick != null)
            {
                mInsertIndex = layer.BrickList.IndexOf(selectedBrick) + 1;
            }
        }
Ejemplo n.º 9
0
        private LayerBrick.Brick findBrickToConnectAndSetBestConnectionPointIndex(Layer.LayerItem fixedItem, ref int wantedConnexion)
        {
            // the brick that will be used to attach the group
            LayerBrick.Brick brickToAttach = null;
            int originalWantedConnexion    = wantedConnexion;          // memorize the original wanted connection in case we need to reset it

            // get the type of the active connexion of the selected brick
            Layer.Group fixedGroup         = fixedItem as Layer.Group;
            int         fixedConnexionType = (fixedGroup != null) ? fixedGroup.ActiveConnectionPoint.Type : (fixedItem as LayerBrick.Brick).ActiveConnectionPoint.Type;

            // first connect all the connection inside the group. Normally the connection of the bricks of the group
            // are done directly on the layer, afer that the brick has been added. But here we need to connect the bricks
            // inisde the group, in order to check the free remaining connections
            LayerBrick.updateBrickConnectivityForASpareSetOfBrickAmongThemselve(mBricksInTheGroup);

            // try to give the correct connexion point, either the specified wanted one, or if
            // we add the same brick do a special case
            bool isActiveConnectionPointChosen = false;

            if (wantedConnexion >= 0)
            {
                // set the active connexion point with the wanted one
                brickToAttach = setActiveConnectionIndex(wantedConnexion);
                // check that the wanted connection type is the same as the selected brick
                isActiveConnectionPointChosen = (brickToAttach != null) &&
                                                (brickToAttach.ActiveConnectionPoint.Type == fixedConnexionType) &&
                                                brickToAttach.ActiveConnectionPoint.IsFree;
            }
            else if ((fixedGroup != null) && (fixedGroup.PartNumber == mGroup.PartNumber))
            {
                // check if the new added brick is the same kind of the selected one, if so,
                // then we choose the previous connection point, but check if it is the same type
                wantedConnexion = BrickLibrary.Instance.getConnectionNextPreferedIndex(fixedGroup.PartNumber, fixedGroup.ActiveConnectionIndex);
                brickToAttach   = setActiveConnectionIndex(wantedConnexion);
                // check that the connection type is the same
                isActiveConnectionPointChosen = (brickToAttach != null) &&
                                                (brickToAttach.ActiveConnectionPoint.Type == fixedConnexionType) &&
                                                brickToAttach.ActiveConnectionPoint.IsFree;
            }

            // if we didn't find any valid active connexion point, set the active connection
            // with the first connexion of the same type that we can find (if the brick as any connection point)
            if (!isActiveConnectionPointChosen)
            {
                wantedConnexion = 0;
                foreach (Layer.LayerItem item in mBricksInTheGroup)
                {
                    LayerBrick.Brick brick = item as LayerBrick.Brick;
                    if (brick.HasConnectionPoint)
                    {
                        for (int i = 0; i < brick.ConnectionPoints.Count; ++i)
                        {
                            if ((brick.ConnectionPoints[i].Type == fixedConnexionType) &&
                                brick.ConnectionPoints[i].IsFree)
                            {
                                brick.ActiveConnectionPointIndex = i;
                                brickToAttach = brick;
                                isActiveConnectionPointChosen = true;
                                break;
                            }
                            // increase the connection count
                            ++wantedConnexion;
                        }
                    }
                    // break again if we found it
                    if (isActiveConnectionPointChosen)
                    {
                        break;
                    }
                }
            }

            // if we still didn't find a compatible brick, reset the wanted connection that we have modified
            if (!isActiveConnectionPointChosen)
            {
                wantedConnexion = originalWantedConnexion;
            }

            // finally return the brick selected for the attachement
            return(brickToAttach);
        }
Ejemplo n.º 10
0
        public RotateBrick(LayerBrick layer, List <Layer.LayerItem> bricks, int rotateSteps, bool forceKeepLastCenter)
        {
            // compute the default rotation angle, used if no bricks in the list is connected to something else
            float angle = MapData.Layer.CurrentRotationStep * rotateSteps;

            // now check if we can find any brick in the list which is connected to another
            // brick not in the list: in that case we don't care about the rotation step,
            // we rotate the group of brick such as it can connect with its next connexion point.
            // we do this first because maybe it will invalidate the flag sLastCenterIsValid

            // first we gather all the free connections or those linked with bricks outside of the list of brick
            FreeConnectionSet externalConnectionSet  = new FreeConnectionSet();            // all the connection connected to external bricks
            FreeConnectionSet availableConnectionSet = new FreeConnectionSet();            // all the possible connections that can be used to link to one external brick

            foreach (Layer.LayerItem item in bricks)
            {
                LayerBrick.Brick brick = item as LayerBrick.Brick;
                if (brick.HasConnectionPoint)
                {
                    foreach (LayerBrick.Brick.ConnectionPoint connection in brick.ConnectionPoints)
                    {
                        if (connection.IsFree)
                        {
                            availableConnectionSet.add(connection);
                        }
                        else if (!bricks.Contains(connection.ConnectionLink.mMyBrick))
                        {
                            availableConnectionSet.add(connection);
                            externalConnectionSet.add(connection);
                        }
                    }
                }
            }

            // get the biggest group of external connection among all the available types, and also get its type
            int chosenConnexionType = BrickLibrary.ConnectionType.DEFAULT;
            List <LayerBrick.Brick.ConnectionPoint> externalConnectionList = externalConnectionSet.getBiggestList(out chosenConnexionType);

            // check if there is any external connection on which we should rotate
            if (externalConnectionList.Count > 0)
            {
                // in that case we don't use the static center
                sLastCenterIsValid = false;

                // for now, without a lot of imagination, take the first connection of the list
                mOldConnectionPoint = externalConnectionList[0];

                // store the connection position
                mConnexionPosition = mOldConnectionPoint.PositionInStudWorldCoord;

                // get the fixed brick, the external brick on the other side of the chosen connection
                LayerBrick.Brick fixedBrick   = mOldConnectionPoint.ConnectedBrick;
                int fixedBrickConnectionIndex = mOldConnectionPoint.ConnectionLink.Index;

                // get the same list but for available connections
                List <LayerBrick.Brick.ConnectionPoint> availableConnectionList = availableConnectionSet.getListForType(chosenConnexionType);

                // check in which direction and how many connection we should jump
                bool rotateCW = (rotateSteps < 0);
                int  nbSteps  = Math.Abs(rotateSteps);

                // get the index of the chosen connection in the available connection list
                int index = availableConnectionList.IndexOf(mOldConnectionPoint);
                // start from it then count forward or backward a certain number of connections
                // depending on the number of steps and the rotation direction
                if (rotateCW)
                {
                    index -= (nbSteps % availableConnectionList.Count);
                    if (index < 0)
                    {
                        index += availableConnectionList.Count;
                    }
                }
                else
                {
                    index += (nbSteps % availableConnectionList.Count);
                    if (index >= availableConnectionList.Count)
                    {
                        index -= availableConnectionList.Count;
                    }
                }
                // finally get the new connection from the chosen index
                mNewConnectionPoint = availableConnectionList[index];

                // compute the angle to rotate
                LayerBrick.Brick newConnectedBrick = mNewConnectionPoint.mMyBrick;
                angle = AddConnectBrick.sGetOrientationOfConnectedBrick(fixedBrick, fixedBrickConnectionIndex,
                                                                        newConnectedBrick, mNewConnectionPoint.Index) - newConnectedBrick.Orientation;
            }

            // then call the normal constructor
            commonConstructor(layer, bricks, angle, forceKeepLastCenter);
        }