Example #1
0
        public DuplicateBrick(LayerBrick layer, List <Layer.LayerItem> bricksToDuplicate, bool needToAddOffset)
            : base(bricksToDuplicate, needToAddOffset, Budget.Budget.Instance.ShouldUseBudgetLimitation)
        {
            // init the layer
            mBrickLayer = layer;

            // elagate the list according to the budget limit
            mWereItemsTrimmed = trimItemListWithBudgetLimitation();

            // get bricks for the notification from the trimmed list
            mBricksForNotification = Layer.sFilterListToGetOnlyBricksInLibrary(mItems);

            // remove the group that were added to the item list for brick notification purpose
            // they are added at the end, so find the first one and erase the end
            if (Budget.Budget.Instance.ShouldUseBudgetLimitation)
            {
                for (int i = 0; i < mItems.Count; ++i)
                {
                    if (mItems[i].IsAGroup)
                    {
                        mItems.RemoveRange(i, mItems.Count - i);
                        break;
                    }
                }
            }

            // try to get a part number (which can be the name of a group)
            Layer.LayerItem topItem = Layer.sGetTopItemFromList(mItems);
            if (topItem != null)
            {
                mPartNumber = topItem.PartNumber;
            }
        }
        public DuplicateBrick(LayerBrick layer, List<Layer.LayerItem> bricksToDuplicate, bool needToAddOffset)
            : base(bricksToDuplicate, needToAddOffset, Budget.Budget.Instance.ShouldUseBudgetLimitation)
        {
            // init the layer
            mBrickLayer = layer;

            // elagate the list according to the budget limit
            mWereItemsTrimmed = trimItemListWithBudgetLimitation();

            // get bricks for the notification from the trimmed list
            mBricksForNotification = Layer.sFilterListToGetOnlyBricksInLibrary(mItems);

            // remove the group that were added to the item list for brick notification purpose
            // they are added at the end, so find the first one and erase the end
            if (Budget.Budget.Instance.ShouldUseBudgetLimitation)
                for (int i = 0; i < mItems.Count; ++i)
                    if (mItems[i].IsAGroup)
                    {
                        mItems.RemoveRange(i, mItems.Count - i);
                        break;
                    }

            // try to get a part number (which can be the name of a group)
            Layer.LayerItem topItem = Layer.sGetTopItemFromList(mItems);
            if (topItem != null)
                mPartNumber = topItem.PartNumber;
        }
        /// <summary>
        /// this method should be called when a brick is added
        /// </summary>
        public void addBrickNotification(LayerBrick layer, Layer.LayerItem brickOrGroup, bool isDueToRegroup)
        {
            // do nothing if the window is not visible
            // because we rebuild everything when it becomes visible
            if (!this.Visible)
                return;

            // get the group entry associated with this layer
            GroupEntry currentGroupEntry = getGroupEntryFromLayer(layer, true);

            // add the specified brick
            addBrick(brickOrGroup, currentGroupEntry);

            // if the specified brick is group, add also the sub items in the list
            if (brickOrGroup.IsAGroup)
                foreach (Layer.LayerItem item in (brickOrGroup as Layer.Group).Items)
                    if (item.PartNumber != string.Empty) // item can be a brick or another named group, but we should not add unnamed group
                    {
                        if (isDueToRegroup)
                        {
                            if (!BrickLibrary.Instance.isListedInLibrary(item.PartNumber))
                                this.removeBrickNotification(layer, item, false); // don't use true otherwise it's an infinite loop
                        }
                        else
                        {
                            if (BrickLibrary.Instance.isListedInLibrary(item.PartNumber))
                                this.addBrickNotification(layer, item, false); // anyway isDueToRegroup is false
                        }
                    }
        }
Example #4
0
        /// <summary>
        /// Get the percentage of usage for the specified layer, according to the current budget.
        /// This method will iterate on all the bricks present on the specified layer and will
        /// sum all the budget of those bricks. Then it will compute a percentage between the
        /// total count of the budgeted bricks on this layer, and the total budget count computed.
        /// </summary>
        /// <param name="layer">The layer in which you want to know the brick usage</param>
        /// <param name="totalBudgetForTheLayer">this out parameter will contains the total budget count for the parts used on the layer</param>
        /// <returns>the brick usage percentage on the specified layer</returns>
        public float getUsagePercentageForLayer(LayerBrick layer, out int totalBudgetForTheLayer)
        {
            float result = 0;

            totalBudgetForTheLayer = 0;
            // try to get the specified layer and iterate on all its values
            Dictionary <string, int> layeredCount = null;

            if (mCountPerLayer.TryGetValue(layer, out layeredCount))
            {
                int totalCount = 0;
                // itearate on all the pair on the specified layer
                foreach (KeyValuePair <string, int> brickCount in layeredCount)
                {
                    // check if the current brick has a budget, otherwise ignore it
                    int budget = 0;
                    if (mBudget.TryGetValue(brickCount.Key, out budget))
                    {
                        // increase the count and budget
                        totalCount             += brickCount.Value;
                        totalBudgetForTheLayer += budget;
                    }
                }
                // compute the result (if budget is not null to avoid division by zero)
                if (totalBudgetForTheLayer > 0)
                {
                    result = (float)(totalCount * 100) / (float)totalBudgetForTheLayer;
                }
            }
            return(result);
        }
Example #5
0
        private void buttonOk_Click(object sender, EventArgs e)
        {
            // create a copy of the edited layer to hold the old data
            LayerBrick oldLayerData = new LayerBrick();

            oldLayerData.CopyOptionsFrom(mEditedLayer);

            // create a new layer to store the new data
            LayerBrick newLayerData = new LayerBrick();

            // name and visibility
            newLayerData.Name    = this.nameTextBox.Text;
            newLayerData.Visible = this.isVisibleCheckBox.Checked;

            //transparency
            newLayerData.Transparency = (int)(this.alphaNumericUpDown.Value);

            // hull
            newLayerData.DisplayHulls  = this.displayHullCheckBox.Checked;
            newLayerData.PenToDrawHull = new Pen(mHullColor, (int)hullThicknessNumericUpDown.Value);

            // brick elevation
            newLayerData.DisplayBrickElevation = this.displayBrickElevationCheckBox.Checked;

            // do a change option action
            ActionManager.Instance.doAction(new ChangeLayerOption(mEditedLayer, oldLayerData, newLayerData));
        }
Example #6
0
        private string mPartNumber     = string.Empty; //if the list contains only one brick or one group, this is the name of this specific brick or group

        public DeleteBrick(LayerBrick layer, List <Layer.LayerItem> bricksToDelete)
        {
            mBrickLayer            = layer;
            mBrickIndex            = new List <int>(bricksToDelete.Count);
            mBricksForNotification = Layer.sFilterListToGetOnlyBricksInLibrary(bricksToDelete);
            // copy the list, because the pointer may change (specially if it is the selection)
            mBricks = new List <Layer.LayerItem>(bricksToDelete.Count);
            foreach (Layer.LayerItem obj in bricksToDelete)
            {
                mBricks.Add(obj);
            }

            // try to get a part number (which can be the name of a group)
            Layer.LayerItem topItem = Layer.sGetTopItemFromList(mBricks);
            if (topItem != null)
            {
                if (topItem.IsAGroup)
                {
                    mPartNumber = (topItem as Layer.Group).PartNumber;
                }
                else
                {
                    mPartNumber = (topItem as LayerBrick.Brick).PartNumber;
                }
            }
        }
Example #7
0
 public AddBrick(LayerBrick layer, Layer.LayerItem brickOrGroup)
 {
     mBrickLayer   = layer;
     mBrickOrGroup = brickOrGroup;
     // after setting the brick or group, call the init brick list function
     initBrickList();
 }
 public void addAllBrickConnections(LayerBrick.Brick brick)
 {
     // add its connection points to the free list
     if (brick.HasConnectionPoint)
         foreach (LayerBrick.Brick.ConnectionPoint connection in brick.ConnectionPoints)
             mFreeConnections[connection.Type].Add(connection);
 }
        private int mNextPreferedActiveConnectionIndex = 0; // the prefered active connection index according to the brick library

        #endregion Fields

        #region Constructors

        public AddConnectBrick(LayerBrick layer, string partNumber, int wantedConnexion)
        {
            mBrickLayer = layer;
            mBrick = new LayerBrick.Brick(partNumber);
            LayerBrick.Brick selectedBrick = layer.getConnectableBrick();

            if (selectedBrick != null)
            {
                // check if the selected brick has connection point
                if (selectedBrick.HasConnectionPoint && mBrick.HasConnectionPoint)
                {
                    // choose the best active connection point for the brick
                    setBestConnectionPointIndex(selectedBrick, mBrick, wantedConnexion);

                    // 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, mBrick.ActiveConnectionPointIndex);

                    // then rotate the brick to connect
                    mBrick.Orientation = sGetOrientationOfConnectedBrick(selectedBrick, mBrick);
                    // the place the brick to add at the correct position
                    mBrick.ActiveConnectionPosition = selectedBrick.ActiveConnectionPosition;
                }
                else
                {
                    PointF position = selectedBrick.Position;
                    position.X += selectedBrick.DisplayArea.Width;
                    mBrick.Position = position;
                }

                // set the index of the brick in the list just after the selected brick
                mBrickIndex = layer.BrickList.IndexOf(selectedBrick) + 1;
            }
        }
Example #10
0
 public AddBrick(LayerBrick layer, Layer.LayerItem brickOrGroup)
 {
     mBrickLayer = layer;
     mBrickOrGroup = brickOrGroup;
     // after setting the brick or group, call the init brick list function
     initBrickList();
 }
 public AttachRulerToBrick(LayerRuler.RulerItem rulerItem, LayerBrick.Brick brick)
 {
     // compute the attach offset in local coordinate
     PointF attachOffset = RulerAttachementSet.Anchor.sComputeLocalOffsetFromLayerItem(brick, rulerItem.CurrentControlPoint);
     // create a new Anchor
     mAnchor = new RulerAttachementSet.Anchor(rulerItem, rulerItem.CurrentControlPointIndex, attachOffset);
     mBrick = brick;
 }
Example #12
0
        private void SelectAllButton_Click(object sender, EventArgs e)
        {
            // get the search part
            string searchingPartNumber = this.FindComboBox.SelectedItem as string;
            // the new list of object to select
            List <Layer.LayerItem> objectToSelect = new List <Layer.LayerItem>();

            // get the current selected layer because we will need it (normally it is never null)
            Layer selectedLayer = Map.Instance.SelectedLayer;

            if (selectedLayer != null)
            {
                // check if the selection must be performed in the current selection
                // or in a new layer
                if (this.inCurrentSelectionRadioButton.Checked)
                {
                    // sub select in current selection, iterate on the selection
                    int nbSelectedItems = selectedLayer.SelectedObjects.Count;
                    for (int i = 0; i < nbSelectedItems; ++i)
                    {
                        Layer.LayerItem currentItem       = selectedLayer.SelectedObjects[i];
                        string          currentPartNumber = (currentItem as LayerBrick.Brick).PartNumber;
                        if (currentPartNumber.Equals(searchingPartNumber))
                        {
                            objectToSelect.Add(currentItem);
                        }
                    }
                }
                else if (this.LayerCheckedListBox.CheckedItems.Count == 1)
                {
                    // find in which layer the selection should be done
                    LayerBrick layerToSelect = mBrickOnlyLayerList[this.LayerCheckedListBox.CheckedIndices[0]];
                    // First we need to select the target layer if not already selected
                    if (selectedLayer != layerToSelect)
                    {
                        Actions.ActionManager.Instance.doAction(new Actions.Layers.SelectLayer(layerToSelect));
                        // important to update the new selected layer for the rest of the code
                        selectedLayer = layerToSelect;
                    }
                    // then iterate on all the bricks of the selected layer to find the one we search
                    foreach (LayerBrick.Brick brick in layerToSelect.BrickList)
                    {
                        if (brick.PartNumber.Equals(searchingPartNumber))
                        {
                            objectToSelect.Add(brick);
                        }
                    }
                }
            }

            // select the new objects
            selectedLayer.clearSelection();
            selectedLayer.addObjectInSelection(objectToSelect);

            // close the window
            this.Close();
        }
Example #13
0
        private void replaceOneItem(LayerBrick layer, Layer.LayerItem itemToRemove, Layer.LayerItem itemToAdd)
        {
            // memorise the brick index order and the group of the old brick
            int oldItemIndex = -1;

            Layer.Group oldItemGroup = itemToRemove.Group;

            // first remove the item from its group, in case it belongs to a group
            // (so that later if someone ask all item of this group, it won't get this limbo item)
            if (itemToRemove.Group != null)
            {
                itemToRemove.Group.removeItem(itemToRemove);
            }

            // check if the item to remove is a group or a simple brick
            if (itemToRemove.IsAGroup)
            {
                List <Layer.LayerItem> bricksToRemove = (itemToRemove as Layer.Group).getAllLeafItems();
                foreach (Layer.LayerItem item in bricksToRemove)
                {
                    oldItemIndex = layer.removeBrick(item as LayerBrick.Brick);
                }
                // we alsways take the last index to be sure we don't keep an index bigger than the brick list
                // after removing all the parts of the group
            }
            else
            {
                oldItemIndex = layer.removeBrick(itemToRemove as LayerBrick.Brick);
            }

            // check if the item to add is a group or a simple brick
            if (itemToAdd.IsAGroup)
            {
                List <Layer.LayerItem> bricksToAdd = (itemToAdd as Layer.Group).getAllLeafItems();
                // since we will add all the brick at the same index, iterating in the normal order
                // the insertion order will be reversed. So we reverse the list to make the insertion in correct order
                bricksToAdd.Reverse();
                foreach (Layer.LayerItem item in bricksToAdd)
                {
                    layer.addBrick(item as LayerBrick.Brick, oldItemIndex);
                }
            }
            else
            {
                layer.addBrick(itemToAdd as LayerBrick.Brick, oldItemIndex);
            }

            // then once the item has been added to the layer, add it also to the group if the old item had a group
            if (oldItemGroup != null)
            {
                oldItemGroup.addItem(itemToAdd);
            }

            // notify the part list view (after actually adding and deleting the bricks because the total map size need to be recomputed)
            MainForm.Instance.NotifyPartListForBrickRemoved(layer, itemToRemove, false);
            MainForm.Instance.NotifyPartListForBrickAdded(layer, itemToAdd, false);
        }
Example #14
0
        /// <summary>
        /// The constructor should be called before starting to update the flex chain,
        /// because the action save the initial state of the bricks in the constructor
        /// This constructor Create a flex chain from a set of brick given a starting brick. From the best connection point
        /// of this starting brick go through all the linked connection points while the brick only have
        /// two connections. If the brick has only one or more than 2 connection (like a joint or crossing)
        /// we stop the chain.
        /// </summary>
        /// <param name="layer">The layer on which the flex move is performed</param>
        /// <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>
        public FlexMove(LayerBrick layer, List <Layer.LayerItem> trackList, LayerBrick.Brick grabbedTrack, PointF mouseCoordInStud)
        {
            // first we check if we can create a valid flex chain
            mIsValid = false;
            // check that the grabbed part is a part has 1 or 2 connection points (no more no less)
            if (!grabbedTrack.HasConnectionPoint || grabbedTrack.ConnectionPoints.Count > 2)
            {
                return;
            }

            // if the grabbed part is not in the list, it failed
            if (!trackList.Contains(grabbedTrack))
            {
                return;
            }

            // declare a variable for the starting connection, we will pass it to the flex creation
            // this variable can stay null, in that case the middle of the grabbed part will be used instead
            LayerBrick.Brick.ConnectionPoint startConnection = null;

            // declare a variable to know from which connection to start the flex chain
            if (grabbedTrack.ConnectionPoints.Count == 1)
            {
                // if there's only one connection, if must be a flexible one, and
                // the starting connection will be the brick itself
                // and the only connection will be the second one from which starting the chain
                if (BrickLibrary.Instance.getConnexionHingeAngle(grabbedTrack.ConnectionPoints[0].Type) == 0.0f)
                {
                    return;
                }
            }
            else
            {
                // try to find the starting connection point, if the result is null, the flex chain cannot be created
                startConnection = findStartingConnectionPoint(trackList, grabbedTrack, mouseCoordInStud);
                if (startConnection == null)
                {
                    return;
                }
            }

            // if we pass all the tests, the flex move is valid
            mIsValid = true;

            // init other data member
            mBrickLayer = layer;
            //create the edition data
            ceateFlexChain(trackList, grabbedTrack, startConnection);
            // and save the action data
            recordState(ref mInitState);

            // also save the current selection, because we will only select the flex brick for visual feedback
            // Do not save directly the list object because we will modified the selection
            mSelectedBricksBeforeFlexMove = new List <Layer.LayerItem>(layer.SelectedObjects);
            // now clear the slection and select only the bricks in the flex chain
            layer.unsafeSetSelection(mBricksInTheFlexChain);
        }
Example #15
0
        private void replace(bool newByOld)
        {
            // iterate on all the layers
            for (int i = 0; i < mBrickLayerList.Count; ++i)
            {
                // get the layer and the list of brick pair to replace
                LayerBrick       currentLayer    = mBrickLayerList[i];
                List <BrickPair> currentPairList = mBrickPairList[i];

                // clear the selection (we will select the replaced brick for updating the connectivity)
                currentLayer.clearSelection();

                if (currentPairList.Count > 0)
                {
                    // iterate on all the brick pair
                    foreach (BrickPair brickPair in currentPairList)
                    {
                        // get the old and new brick
                        Layer.LayerItem oldOne = brickPair.mOldBrick;
                        Layer.LayerItem newOne = brickPair.mNewBrick;
                        // reverse them if needed
                        if (newByOld)
                        {
                            oldOne = brickPair.mNewBrick;
                            newOne = brickPair.mOldBrick;
                        }
                        // replace the old brick with the new one in the current layer
                        replaceOneItem(currentLayer, oldOne, newOne);
                        // add the brick in the selection for updating connectivity later
                        currentLayer.addObjectInSelection(newOne);
                    }

                    // update the connectivity of the whole layer after replacement
                    currentLayer.updateFullBrickConnectivityForSelectedBricksOnly();
                    // clear the selection again (it was only use for fast connectivity update)
                    currentLayer.clearSelection();
                }

                // If the current layer is the one which has the selection
                // reselect all the new brick
                if (currentLayer == mLayerWhereToSelectTheReplacedBricks)
                {
                    foreach (BrickPair brickPair in mReplacedBricksToSelect)
                    {
                        if (newByOld)
                        {
                            currentLayer.addObjectInSelection(brickPair.mOldBrick);
                        }
                        else
                        {
                            currentLayer.addObjectInSelection(brickPair.mNewBrick);
                        }
                    }
                }
            }
        }
Example #16
0
        private string mPartNumber = string.Empty;         //if the list contains only one brick or one group, this is the name of this specific brick or group

        public MoveBrick(LayerBrick layer, List <Layer.LayerItem> bricks, PointF move)
            : base(layer, bricks, move)
        {
            // try to get a part number (which can be the name of a group)
            Layer.LayerItem topItem = Layer.sGetTopItemFromList(mItems);
            if (topItem != null)
            {
                mPartNumber = topItem.PartNumber;                 // part number is virtual, works both for part and group
            }
        }
Example #17
0
 public AddBrick(LayerBrick layer, string partNumber)
 {
     mBrickLayer = layer;
     if (BrickLibrary.Instance.isAGroup(partNumber))
         mBrickOrGroup = new Layer.Group(partNumber);
     else
         mBrickOrGroup = new LayerBrick.Brick(partNumber);
     // after setting the brick or group, call the init brick list function
     initBrickList();
 }
 public static void check(LayerBrick.Brick startingBrick)
 {
     // check that the specified brick is an electric brick, else do nothing
     if (startingBrick.ElectricCircuitIndexList != null)
     {
         // increment the time stamp
         incrementTimeStamp();
         // call the main method
         checkFromOneBrick(startingBrick);
     }
 }
        public static void check(LayerBrick brickLayer)
        {
            // increment the time stamp
            incrementTimeStamp();

            // check for every brick if not already at the time stamp
            foreach (LayerBrick.Brick brick in brickLayer.BrickList)
                if (brick.ElectricCircuitIndexList != null)
                    if (Math.Abs(brick.ConnectionPoints[0].Polarity) != sTimeStamp)
                        checkFromOneBrick(brick);
        }
Example #20
0
        /// <summary>
        /// Get the total number of bricks present in the specified layer of the current map
        /// </summary>
        /// <param name="layer">The layer in which you want to know the count</param>
        /// <param name="onlyBudgetedParts">if true only the budgeted parts will be counted, otherwise all the parts on the layer</param>
        /// <returns>the number of bricks in the specified layer of the map which could be 0</returns>
        public int getTotalCountForLayer(LayerBrick layer, bool onlyBudgetedParts)
        {
            int result = 0;
            // try to get the specified layer and iterate on all its values
            Dictionary <string, int> layeredCount = null;

            if (mCountPerLayer.TryGetValue(layer, out layeredCount))
            {
                result = getCountInDictionary(layeredCount, onlyBudgetedParts);
            }
            return(result);
        }
Example #21
0
        /// <summary>
        /// Add a new single part 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 part, 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 part to add</param>
        /// <param name="wantedConnexion">The connection index of the part to add that should be used to connect to the selected item, or -1 if you don't care.</param>
        public AddConnectBrick(LayerBrick layer, Layer.LayerItem selectedItem, string partNumber, int wantedConnexion)
        {
            // the selected item should not be null
            System.Diagnostics.Debug.Assert(selectedItem != null);

            mBrickLayer = layer;
            mBrick      = new LayerBrick.Brick(partNumber);
            LayerBrick.Brick selectedBrick = layer.getConnectableBrick();
            bool             hasAGoodConnectionBeenFound = false;

            // check if the selected brick and the brick to add have connection points, and if we can find a good connection match
            // The selected brick can be null if there's no connection in the single group connected in the layer
            if ((selectedBrick != null) && selectedBrick.HasConnectionPoint && mBrick.HasConnectionPoint)
            {
                // choose the best active connection point for the brick
                hasAGoodConnectionBeenFound = setBestConnectionPointIndex(selectedBrick, mBrick, wantedConnexion);
            }

            // check if we found a good connection, continue to set the position of the brick to add relative to the connection
            if (hasAGoodConnectionBeenFound)
            {
                // then rotate the brick to connect
                mBrick.Orientation = sGetOrientationOfConnectedBrick(selectedBrick, mBrick);
                // the place the brick to add at the correct position
                mBrick.ActiveConnectionPosition = selectedBrick.ActiveConnectionPosition;
            }
            else
            {
                // and just compute the position to the right of the selected item
                PointF position = selectedItem.Position;
                position.X     += selectedItem.DisplayArea.Width;
                mBrick.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 brick in the list just after the selected brick
            if (selectedBrick != null)
            {
                mBrickIndex = layer.BrickList.IndexOf(selectedBrick) + 1;
            }
        }
Example #22
0
        private List <int> mBrickIndex         = null; // this list of index is for the redo, to add each text at the same place

        public AddBrick(LayerBrick layer, string partNumber)
        {
            mBrickLayer = layer;
            if (BrickLibrary.Instance.isAGroup(partNumber))
            {
                mBrickOrGroup = new Layer.Group(partNumber);
            }
            else
            {
                mBrickOrGroup = new LayerBrick.Brick(partNumber);
            }
            // after setting the brick or group, call the init brick list function
            initBrickList();
        }
Example #23
0
        public override void undo()
        {
            LayerBrick brickLayer = mLayer as LayerBrick;

            // reselect the items of the action, cause after we will update the connectivity of the selection
            // and do it before calling the base class cause the base class will update the selection rectangle
            brickLayer.selectOnlyThisObject(mItems);
            // call the base class
            base.undo();
            // update the brick connectivity
            brickLayer.updateBrickConnectivityOfSelection(false);
            // notify the main form for the brick move
            MainForm.Instance.NotifyForPartMoved();
        }
        private int mNextPreferedActiveConnectionIndex = 0; // the prefered active connection index according to the brick library

        #endregion Fields

        #region Constructors

        public AddConnectGroup(LayerBrick layer, string partNumber, int wantedConnexion)
        {
            // save the layer and construct the group
            mBrickLayer = layer;
            mGroup = new Layer.Group(partNumber);
            LayerBrick.Brick selectedBrick = layer.getConnectableBrick();

            // get the flat list of bricks from the hierarchical group
            mBricksInTheGroup = mGroup.getAllLeafItems();

            // check if we can attach the group to the unique selected object
            if (selectedBrick != null)
            {
                // find the brick of the group that will be connected to the selected brick
                LayerBrick.Brick brickToConnect = null;
                if (selectedBrick.HasConnectionPoint)
                    brickToConnect = findBrickToConnectAdnSetBestConnectionPointIndex(selectedBrick, ref wantedConnexion);

                // check if the selected brick has connection point
                if (brickToConnect != null && brickToConnect.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, brickToConnect);
                    newOrientation -= brickToConnect.Orientation;
                    // Rotate all the bricks of the group first before translating
                    RotateBrickOnPivotBrick rotateBricksAction = new RotateBrickOnPivotBrick(layer, mBricksInTheGroup, newOrientation, brickToConnect);
                    rotateBricksAction.MustUpdateBrickConnectivity = false;
                    rotateBricksAction.redo();

                    // compute the translation to add to all the bricks
                    PointF translation = new PointF(selectedBrick.ActiveConnectionPosition.X - brickToConnect.ActiveConnectionPosition.X,
                                                    selectedBrick.ActiveConnectionPosition.Y - brickToConnect.ActiveConnectionPosition.Y);
                    mGroup.translate(translation);
                }
                else
                {
                    PointF position = selectedBrick.Position;
                    position.X += selectedBrick.DisplayArea.Width;
                    mGroup.Position = position;
                }

                // set the index of the brick in the list just after the selected brick
                mInsertIndex = layer.BrickList.IndexOf(selectedBrick) + 1;
            }
        }
Example #25
0
        /// <summary>
        /// The constructor should be called before starting to update the flex chain,
        /// because the action save the initial state of the bricks in the constructor
        /// This constructor Create a flex chain from a set of brick given a starting brick. From the best connection point
        /// of this starting brick go through all the linked connection points while the brick only have
        /// two connections. If the brick has only one or more than 2 connection (like a joint or crossing)
        /// we stop the chain.
        /// </summary>
        /// <param name="layer">The layer on which the flex move is performed</param>
        /// <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>
        public FlexMove(LayerBrick layer, List<Layer.LayerItem> trackList, LayerBrick.Brick grabbedTrack, PointF mouseCoordInStud)
        {
            // first we check if we can create a valid flex chain
            mIsValid = false;
            // check that the grabbed part is a part has 1 or 2 connection points (no more no less)
            if (!grabbedTrack.HasConnectionPoint || grabbedTrack.ConnectionPoints.Count > 2)
                return;

            // if the grabbed part is not in the list, it failed
            if (!trackList.Contains(grabbedTrack))
                return;

            // declare a variable for the starting connection, we will pass it to the flex creation
            // this variable can stay null, in that case the middle of the grabbed part will be used instead
            LayerBrick.Brick.ConnectionPoint startConnection = null;

            // declare a variable to know from which connection to start the flex chain
            if (grabbedTrack.ConnectionPoints.Count == 1)
            {
                // if there's only one connection, if must be a flexible one, and
                // the starting connection will be the brick itself
                // and the only connection will be the second one from which starting the chain
                if (BrickLibrary.Instance.getConnexionHingeAngle(grabbedTrack.ConnectionPoints[0].Type) == 0.0f)
                    return;
            }
            else
            {
                // try to find the starting connection point, if the result is null, the flex chain cannot be created
                startConnection = findStartingConnectionPoint(trackList, grabbedTrack, mouseCoordInStud);
                if (startConnection == null)
                    return;
            }

            // if we pass all the tests, the flex move is valid
            mIsValid = true;

            // init other data member
            mBrickLayer = layer;
            //create the edition data
            ceateFlexChain(trackList, grabbedTrack, startConnection);
            // and save the action data
            recordState(ref mInitState);

            // also save the current selection, because we will only select the flex brick for visual feedback
            // Do not save directly the list object because we will modified the selection
            mSelectedBricksBeforeFlexMove = new List<Layer.LayerItem>(layer.SelectedObjects);
            // now clear the slection and select only the bricks in the flex chain
            layer.unsafeSetSelection(mBricksInTheFlexChain);
        }
        public static void check(LayerBrick brickLayer)
        {
            // increment the time stamp
            incrementTimeStamp();

            // check for every brick if not already at the time stamp
            foreach (LayerBrick.Brick brick in brickLayer.BrickList)
            {
                if (brick.ElectricCircuitIndexList != null)
                {
                    if (Math.Abs(brick.ConnectionPoints[0].Polarity) != sTimeStamp)
                    {
                        checkFromOneBrick(brick);
                    }
                }
            }
        }
Example #27
0
        /// <summary>
        /// Call this method when you want to notify the budget counter that a new brick has been added
        /// </summary>
        /// <param name="layer">The layer on which the brick is added</param>
        /// <param name="brick">the brick that was added</param>
        /// <param name="isDueToRegroup">tells if the brick is a group that was regrouped by an undo</param>
        public void addBrickNotification(LayerBrick layer, Layer.LayerItem brickOrGroup, bool isDueToRegroup)
        {
            string partID = brickOrGroup.PartNumber;

            if (partID != string.Empty)
            {
                // get the current count in the count dictionary
                int currentCount = 0;
                mCount.TryGetValue(partID, out currentCount);
                // and update the value in the global dictionnary
                mCount.Remove(partID);
                mCount.Add(partID, currentCount + 1);

                // also update in the layered dictionary
                Dictionary <string, int> layeredCount = null;
                if (mCountPerLayer.TryGetValue(layer, out layeredCount))
                {
                    int currentCountInLayer = 0;
                    layeredCount.TryGetValue(partID, out currentCountInLayer);
                    layeredCount.Remove(partID);
                    layeredCount.Add(partID, currentCountInLayer + 1);
                }
                else
                {
                    // this is a new layer (this layer didn't exist before), so add the layer and also the count
                    layeredCount = new Dictionary <string, int>();
                    layeredCount.Add(partID, 1);
                    mCountPerLayer.Add(layer, layeredCount);
                }
            }
            // add also all the named children if the brick is a group
            // (unless it is a regroup in that case the children are already counted)
            if (!isDueToRegroup)
            {
                Layer.Group group = brickOrGroup as Layer.Group;
                if (group != null)
                {
                    foreach (Layer.LayerItem item in group.Items)
                    {
                        addBrickNotification(layer, item, isDueToRegroup);
                    }
                }
            }
        }
Example #28
0
        /// <summary>
        /// Call this method when you want to notify the budget counter that a brick has been removed
        /// </summary>
        /// <param name="layer">The layer on which the brick is removed</param>
        /// <param name="brick">the brick that was removed</param>
        /// <param name="isDueToUngroup">tell if the brick is a group that is ungrouped</param>
        public void removeBrickNotification(LayerBrick layer, Layer.LayerItem brickOrGroup, bool isDueToUngroup)
        {
            string partID = brickOrGroup.PartNumber;

            if (partID != string.Empty)
            {
                // get the current count
                int currentCount = 0;
                mCount.TryGetValue(partID, out currentCount);
                if (currentCount > 0)
                {
                    // update the value
                    mCount.Remove(partID);
                    mCount.Add(partID, currentCount - 1);
                }

                // also update in the layered dictionary
                Dictionary <string, int> layeredCount = null;
                if (mCountPerLayer.TryGetValue(layer, out layeredCount))
                {
                    int currentCountInLayer = 0;
                    layeredCount.TryGetValue(partID, out currentCountInLayer);
                    if (currentCountInLayer > 0)
                    {
                        layeredCount.Remove(partID);
                        layeredCount.Add(partID, currentCountInLayer - 1);
                    }
                }
                // if the layer doesn't exist, we have nothing to remove
            }
            // remove also all the named children if the brick is a group
            // (unless it is a ungroup in that case we leave the children and just remove the one we ungrouped)
            if (!isDueToUngroup)
            {
                Layer.Group group = brickOrGroup as Layer.Group;
                if (group != null)
                {
                    foreach (Layer.LayerItem item in group.Items)
                    {
                        removeBrickNotification(layer, item, isDueToUngroup);
                    }
                }
            }
        }
        private List <BriCkAndIndex> mBrickIndex = null;        // this list of index is for the redo, to add each text at the same place

        public ChangeBrickElevation(LayerBrick layer, List <LayerBrick.Brick> bricksToEdit, float newElevation)
        {
            // save the item list to edit and the other parameters
            mLayer        = layer;
            mBricksToEdit = bricksToEdit;
            mNewElevation = newElevation;
            // and memorise the elevation of all the bricks and also its original index (for the undo)
            mOldElevationForEachBrick = new List <float>(bricksToEdit.Count);
            mBrickIndex = new List <BriCkAndIndex>(bricksToEdit.Count);
            foreach (LayerBrick.Brick brick in bricksToEdit)
            {
                mOldElevationForEachBrick.Add(brick.Altitude);
                mBrickIndex.Add(new BriCkAndIndex()
                {
                    mBrick = brick, mIndex = mLayer.BrickList.IndexOf(brick)
                });
            }
            // sort the brick index list
            mBrickIndex.Sort((x, y) => x.mIndex - y.mIndex);
        }
Example #30
0
        private string mPartNumber = string.Empty; //if the list contains only one brick or one group, this is the name of this specific brick or group

        #endregion Fields

        #region Constructors

        public DeleteBrick(LayerBrick layer, List<Layer.LayerItem> bricksToDelete)
        {
            mBrickLayer = layer;
            mBrickIndex = new List<int>(bricksToDelete.Count);
            mBricksForNotification = Layer.sFilterListToGetOnlyBricksInLibrary(bricksToDelete);
            // copy the list, because the pointer may change (specially if it is the selection)
            mBricks = new List<Layer.LayerItem>(bricksToDelete.Count);
            foreach (Layer.LayerItem obj in bricksToDelete)
                mBricks.Add(obj);

            // try to get a part number (which can be the name of a group)
            Layer.LayerItem topItem = Layer.sGetTopItemFromList(mBricks);
            if (topItem != null)
            {
                if (topItem.IsAGroup)
                    mPartNumber = (topItem as Layer.Group).PartNumber;
                else
                    mPartNumber = (topItem as LayerBrick.Brick).PartNumber;
            }
        }
Example #31
0
 public LayerBrickOptionForm(LayerBrick layer)
 {
     InitializeComponent();
     // save the reference on the layer that we are editing
     mEditedLayer = layer;
     // update the controls with the data of the gridLayer
     // name and visibility
     this.nameTextBox.Text          = layer.Name;
     this.isVisibleCheckBox.Checked = layer.Visible;
     // transparency
     this.alphaNumericUpDown.Value = layer.Transparency;
     this.alphaTrackBar.Value      = layer.Transparency;
     // the display hull settings
     this.displayHullCheckBox.Checked = layer.DisplayHulls;
     updateHullColor(layer.PenToDrawHull.Color);
     hullThicknessNumericUpDown.Value = (int)layer.PenToDrawHull.Width;
     // call the checkchange to force the enable of the hull color option
     displayHullCheckBox_CheckedChanged(this, null);
     // brick elevation
     this.displayBrickElevationCheckBox.Checked = layer.DisplayBrickElevation;
 }
Example #32
0
        /// <summary>
        /// Recount all the bricks in the current Map.
        /// </summary>
        public void recountAllBricks()
        {
            // clear the count of all the bricks
            mCount.Clear();
            mCountPerLayer.Clear();

            // iterate on all the brick of all the brick layers,
            foreach (Layer layer in Map.Instance.LayerList)
            {
                LayerBrick brickLayer = layer as LayerBrick;
                if (brickLayer != null)
                {
                    // add a layered count for this current layer
                    Dictionary <string, int> layeredCount = new Dictionary <string, int>();
                    mCountPerLayer.Add(brickLayer, layeredCount);

                    // now iterate on all the brick of the current layer
                    foreach (Layer.LayerItem item in brickLayer.LibraryBrickList)
                    {
                        // get the part id
                        string partID = item.PartNumber;

                        // get the current global count
                        int currentCount = 0;
                        mCount.TryGetValue(partID, out currentCount);
                        // update the value
                        mCount.Remove(partID);
                        mCount.Add(partID, currentCount + 1);

                        // also count the brick on the layered count
                        int currentCountInLayer = 0;
                        layeredCount.TryGetValue(partID, out currentCountInLayer);
                        // update the value
                        layeredCount.Remove(partID);
                        layeredCount.Add(partID, currentCountInLayer + 1);
                    }
                }
            }
        }
        /// <summary>
        /// Try to find the best connection index that should be used for the brickToAttach when we attach it
        /// to the current active connection point of the fixedBrick, and set it.
        /// </summary>
        /// <param name="fixedBrick">The brick that doesn't move neither change its connection point</param>
        /// <param name="brickToAttach">The brick for which computing the best connection point</param>
        /// <param name="wantedConnexion">The prefered connection index if possible</param>
        private void setBestConnectionPointIndex(LayerBrick.Brick fixedBrick, LayerBrick.Brick brickToAttach, int wantedConnexion)
        {
            // get the type of the active connexion of the selected brick
            int fixedConnexionType = fixedBrick.ActiveConnectionPoint.Type;

            // 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.ActiveConnectionPointIndex = wantedConnexion;
                // check that the wanted connection type is the same as the selected brick
                isActiveConnectionPointChosen = (brickToAttach.ActiveConnectionPoint.Type == fixedConnexionType) &&
                                                brickToAttach.ActiveConnectionPoint.IsFree;
            }
            else if (fixedBrick.PartNumber == brickToAttach.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
                brickToAttach.ActiveConnectionPointIndex = BrickLibrary.Instance.getConnectionNextPreferedIndex(fixedBrick.PartNumber, fixedBrick.ActiveConnectionPointIndex);
                // check that the connection type is the same
                isActiveConnectionPointChosen = (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)
                for (int i = 0; i < brickToAttach.ConnectionPoints.Count; ++i)
                    if ((brickToAttach.ConnectionPoints[i].Type == fixedConnexionType) &&
                        brickToAttach.ConnectionPoints[i].IsFree)
                    {
                        brickToAttach.ActiveConnectionPointIndex = i;
                        break;
                    }
        }
 /// <summary>
 /// Compute and return the angle that should take the brickToAttach if it is connected to the
 /// fixedBrick with both the specified connection point.
 /// </summary>
 /// <param name="fixedBrick">The brick on the map that doesn't move</param>
 /// <param name="connectionIndexForFixedBrick">the fixed brick's connection index that you want to use to compute the orientaion</param>
 /// <param name="brickToAttach">The brick to add for which we should compute the angle</param>
 /// <param name="connectionIndexForBrickToAttach">the attached brick's connection index that you want to use to compute the orientaion</param>
 /// <returns>The absolute orientation that should have the brick to attach to be correctly connected to the fixed brick (in degree)</returns>
 public static float sGetOrientationOfConnectedBrick(LayerBrick.Brick fixedBrick, int connectionIndexForFixedBrick, LayerBrick.Brick brickToAttach, int connectionIndexForBrickToAttach)
 {
     // compute the rotation
     float newOrientation = fixedBrick.Orientation +
                             BrickLibrary.Instance.getConnectionAngleDifference(fixedBrick.PartNumber,
                                         connectionIndexForFixedBrick,
                                         brickToAttach.PartNumber,
                                         connectionIndexForBrickToAttach);
     // clamp the orientation between 0 and 360
     if (newOrientation >= 360.0f)
         newOrientation -= 360.0f;
     if (newOrientation < 0.0f)
         newOrientation += 360.0f;
     // return the value
     return newOrientation;
 }
Example #35
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;
            }
        }
Example #36
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);
 }
 public void add(LayerBrick.Brick.ConnectionPoint connection)
 {
     mFreeConnections[connection.Type].Add(connection);
 }
 public void remove(LayerBrick.Brick.ConnectionPoint connection)
 {
     mFreeConnections[connection.Type].Remove(connection);
 }
Example #39
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;
            }
        }
Example #40
0
 public RotateBrickOnPivotBrick(LayerBrick layer, List <Layer.LayerItem> bricks, float angle, LayerBrick.Brick pivotBrick)
     : base(layer, bricks, angle)
 {
     mPivotBrick = pivotBrick;
 }
Example #41
0
        public FindForm()
        {
            InitializeComponent();
            // get the selected layer because we will need it
            Layer selectedLayer = Map.Instance.SelectedLayer;

            // determines which radio button should be selected
            bool isSelectionEmpty = (selectedLayer.SelectedObjects.Count == 0);

            this.inCurrentSelectionRadioButton.Checked = !isSelectionEmpty;
            this.inCurrentSelectionRadioButton.Enabled = !isSelectionEmpty;
            this.inLayerRadioButton.Checked            = isSelectionEmpty;
            inLayerRadioButton_CheckedChanged(this.inLayerRadioButton, null);

            // fill the layer list (in reverse order)
            for (int i = Map.Instance.LayerList.Count - 1; i >= 0; --i)
            {
                Layer layer = Map.Instance.LayerList[i];
                if (layer is LayerBrick)
                {
                    // add a check box item and the corresponding layer reference in a private list
                    this.LayerCheckedListBox.Items.Add(layer.Name, layer == selectedLayer);
                    mBrickOnlyLayerList.Add(layer as LayerBrick);
                }
            }

            // construct the list of parts from the selection (if it is a valid selection)
            LayerBrick selectedBrickLayer = selectedLayer as LayerBrick;

            if ((selectedBrickLayer != null) && (selectedLayer.SelectedObjects.Count > 0))
            {
                // collapse all the selection in a dictionnary with unique instance of each part
                // and a counter of each different part in the selection
                Dictionary <string, int> collaspedList = new Dictionary <string, int>();
                foreach (Layer.LayerItem item in selectedLayer.SelectedObjects)
                {
                    // add the item
                    addPartToBuildingDictionnary(ref collaspedList, item.PartNumber);
                    // and also add its named parents
                    List <Layer.LayerItem> namedParents = item.NamedParents;
                    foreach (Layer.LayerItem parent in namedParents)
                    {
                        addPartToBuildingDictionnary(ref collaspedList, parent.PartNumber);
                    }
                }
                // construct the list by expanding the dictionnary
                // and at the same time find the best part (the one which higher occurence)
                int j         = 0;
                int bestScore = 0;
                mSelectionPartList = new string[collaspedList.Count];
                foreach (KeyValuePair <string, int> keyValue in collaspedList)
                {
                    mSelectionPartList[j++] = keyValue.Key;
                    if (keyValue.Value > bestScore)
                    {
                        bestScore = keyValue.Value;
                        mBestPartToFindInSelection = keyValue.Key;
                    }
                }
            }

            // fill the find and replace combo box
            if (mSelectionPartList != null)
            {
                this.FindComboBox.Items.AddRange(mSelectionPartList);
            }
            else
            {
                this.FindComboBox.Items.AddRange(mLibraryPartList);
            }
            this.ReplaceComboBox.Items.AddRange(mLibraryPartList);
            setBestSelectedItemForFindComboBox();

            // update the check all button according to the number of layer checked
            // the function to update the status of the button will be called by the event handler
            LayerCheckedListBox_SelectedIndexChanged(null, null);
        }
 /// <summary>
 /// Call this function when you want to attach the current control point to the specified brick.
 /// Be sure to choose the correct current point before calling this function.
 /// </summary>
 /// <param name="index">the index of the control point to attach</param>
 /// <param name="brick">the brick to which the current control point will be attached</param>
 public override void attachControlPointToBrick(int index, LayerBrick.Brick brick)
 {
     mControlPoint[index].mAttachedBrick = brick;
 }
 /// <summary>
 /// Call this function when you want to attach the current control point to the specified brick.
 /// Be sure to choose the correct current point before calling this function
 /// </summary>
 /// <param name="index">the index of the control point to attach</param>
 /// <param name="brick">the brick to which the current control point will be attached</param>
 public abstract void attachControlPointToBrick(int index, LayerBrick.Brick brick);
Example #44
0
        /// <summary>
        /// Try to reach the specify target position with this chain
        /// </summary>
        /// <param name="targetInWorldStudCoord">the target position in world stud coord</param>
        /// <param name="targetConnection">If the end of the flex chain need to be connected to a connection, this parameter indicates which one, otherwise it is null</param>
        public void reachTarget(PointF targetInWorldStudCoord, LayerBrick.Brick.ConnectionPoint targetConnection)
        {
            // save the primary target
            mPrimaryTarget = targetInWorldStudCoord;

            // check if we need to compute a second target position
            mUseTwoTargets = (targetConnection != null);
            if (mUseTwoTargets)
            {
                // rotate the second target vector according to the orientation of the snapped connection
                PointF[] translation = { mLastBoneVector };
                Matrix rotation = new Matrix();
                rotation.Rotate(targetConnection.mMyBrick.Orientation + targetConnection.Angle + 180);
                rotation.TransformVectors(translation);

                // translate the target with the rotated vector for the second target
                mSecondaryTarget.X = targetInWorldStudCoord.X + translation[0].X;
                mSecondaryTarget.Y = targetInWorldStudCoord.Y + translation[0].Y;
            }

            // reset the status flag
            mCurrentUpdateStatus = IKSolver.CCDResult.Processing;

            // and call the update method
            update();
        }
Example #45
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);
        }
Example #46
0
        public ReplaceBrick(List <LayerBrick> layerList, string partNumberToReplace, string newPartNumber, bool replaceInSelectionOnly)
        {
            // store the list of layer for which this action apply and create a list of the same size for the bricks
            mBrickLayerList      = layerList;
            mPartNumberToReplace = partNumberToReplace;
            mBrickPairList       = new List <List <BrickPair> >(layerList.Count);
            // use a counter of brick replaced, to avoid exceeding the budget
            int replacedBrickCount = 0;

            // iterate on all the layers
            foreach (LayerBrick layer in layerList)
            {
                // memorize the layer that has the selected bricks
                if (layer.SelectedObjects.Count > 0)
                {
                    mLayerWhereToSelectTheReplacedBricks = layer;
                }
                // add the list of brick pair (that can stay empty if no brick is found in that layer)
                List <BrickPair> currentPairList = new List <BrickPair>();
                mBrickPairList.Add(currentPairList);
                // compute the list of bricks on which we should iterate
                List <Layer.LayerItem> itemsToReplace = null;
                if (replaceInSelectionOnly)
                {
                    itemsToReplace = computeListOfItemToReplace(layer.SelectedObjects);
                }
                else
                {
                    itemsToReplace = computeListOfItemToReplace(layer.BrickList);
                }
                // iterate on all the bricks of the layer or on the selection to find the brick to replace
                foreach (Layer.LayerItem item in itemsToReplace)
                {
                    // increase the count of brick to replace
                    replacedBrickCount++;
                    // then check if we can add the brick
                    if (Budget.Budget.Instance.canAddBrick(newPartNumber, replacedBrickCount, true))
                    {
                        // create the new item
                        Layer.LayerItem newItem = createReplacementBrick(item, newPartNumber);
                        // create the pair and add it to the list
                        BrickPair brickPair = new BrickPair(item, newItem);
                        currentPairList.Add(brickPair);
                        // check if we also need to add this pair to the list of brick to reselect
                        if (layer.SelectedObjects.Contains(item))
                        {
                            mReplacedBricksToSelect.Add(brickPair);
                        }
                    }
                    else
                    {
                        // beep if we reach the limit
                        Map.Instance.giveFeedbackForNotAddingBrick(Map.BrickAddability.YES_AND_NO_REPLACEMENT_LIMITED_BY_BUDGET);
                        // no need to continue if we cannot add more bricks, so stop the iteration
                        mIsLimitedByBudget = true;
                        break;
                    }
                }
                // stop iterating on the layer if we reach the limit
                if (mIsLimitedByBudget)
                {
                    break;
                }
            }
        }
 /// <summary>
 /// Compute and return the angle that should take the brickToAttach if it is connected to the
 /// fixedBrick with both their respective active connection point.
 /// </summary>
 /// <param name="fixedBrick">The brick on the map that doesn't move</param>
 /// <param name="brickToAttach">The brick to add for which we should compute the angle</param>
 /// <returns>The absolute orientation that should have the brick to attach to be correctly connected to the fixed brick (in degree)</returns>
 public static float sGetOrientationOfConnectedBrick(LayerBrick.Brick fixedBrick, LayerBrick.Brick brickToAttach)
 {
     return sGetOrientationOfConnectedBrick(fixedBrick, fixedBrick.ActiveConnectionPointIndex, brickToAttach, brickToAttach.ActiveConnectionPointIndex);
 }
Example #48
0
 public BrickTransform(LayerBrick.Brick brick, PointF position, float orientation)
 {
     mBrick = brick;
     mPosition = position;
     mOrientation = orientation;
 }
 /// <summary>
 /// Call this function when you want to attach the current control point to the specified brick.
 /// Be sure to choose the correct current point before calling this function
 /// </summary>
 /// <param name="index">useless for circular ruler</param>
 /// <param name="brick">the brick to which the current control point will be attached</param>
 public override void attachControlPointToBrick(int index, LayerBrick.Brick brick)
 {
     // the circular ruler only have one attach
     mAttachedBrick = brick;
 }
Example #50
0
        private void ReplaceButton_Click(object sender, EventArgs e)
        {
            List <LayerBrick> layers = null;

            // check if the selection must be performed in the current selection
            // or in several layers
            if (this.inCurrentSelectionRadioButton.Checked)
            {
                // only one layer is selected
                layers = new List <LayerBrick>(1);

                // get the current selected layer because we will need it (normally it is never null)
                LayerBrick selectedLayer = (Map.Instance.SelectedLayer) as LayerBrick;
                if (selectedLayer != null)
                {
                    layers.Add(selectedLayer);
                }
            }
            else
            {
                layers = new List <LayerBrick>(this.LayerCheckedListBox.CheckedIndices.Count);
                foreach (int index in this.LayerCheckedListBox.CheckedIndices)
                {
                    layers.Add(mBrickOnlyLayerList[index]);
                }
            }

            // get the search and replace part number
            string searchingPartNumber   = this.FindComboBox.SelectedItem as string;
            string replacementPartNumber = this.ReplaceComboBox.SelectedItem as string;

            // create the action
            Actions.Bricks.ReplaceBrick replaceAction = new Actions.Bricks.ReplaceBrick(layers, searchingPartNumber, replacementPartNumber, this.inCurrentSelectionRadioButton.Checked);
            // check if there was a budget limitation and if the user cancel the action
            bool canDoTheAction = true;

            if (Settings.Default.DisplayWarningMessageForBrickNotReplacedDueToBudgetLimitation && replaceAction.IsLimitedByBudget)
            {
                // if some brick cannot be replaced, display a warning message
                // use a local variable to get the value of the checkbox, by default we don't suggest the user to hide it
                bool dontDisplayMessageAgain = false;

                // display the warning message
                DialogResult result = ForgetableMessageBox.Show(BlueBrick.MainForm.Instance, Properties.Resources.ErrorMsgSomeBrickWereNotReplacedDueToBudgetLimitation,
                                                                Properties.Resources.ErrorMsgTitleWarning, MessageBoxButtons.YesNo,
                                                                MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, ref dontDisplayMessageAgain);

                // set back the checkbox value in the settings (don't save the settings now, it will be done when exiting the application)
                Properties.Settings.Default.DisplayWarningMessageForBrickNotReplacedDueToBudgetLimitation = !dontDisplayMessageAgain;

                // change the action flag depending of the answer of the user
                canDoTheAction = (result == DialogResult.Yes);
            }
            // do the action if we should
            if (canDoTheAction)
            {
                Actions.ActionManager.Instance.doAction(replaceAction);
            }

            // close the window
            this.Close();
        }
Example #51
0
        /// <summary>
        /// Create a flex chain from a set of brick given a starting brick. From the free connection point
        /// of this starting brick go through all the linked connection points while the brick only have
        /// two connections. If the brick has only one or more than 2 connection (like a joint or crossing)
        /// we stop the chain.
        /// </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="currentFirstConnection">The first connection from which to start, which can be null and belongs to the grabbed track</param>
        public void ceateFlexChain(List<Layer.LayerItem> trackList, LayerBrick.Brick grabbedTrack, LayerBrick.Brick.ConnectionPoint currentFirstConnection)
        {
            // init all the arrays
            int boneCount = trackList.Count;
            mBoneList = new List<IKSolver.Bone_2D_CCD>(boneCount);
            mFlexChainList = new List<ChainLink>(boneCount * 2);
            mBricksInTheFlexChain = new List<Layer.LayerItem>(boneCount);

            // start to iterate from the grabbed track
            LayerBrick.Brick currentBrick = grabbedTrack;
            ChainLink hingedLink = null;
            addNewBone(currentFirstConnection, grabbedTrack, 0.0);
            // continue to iterate until we reach the end (no current brick) or the end of the selection
            // and continue only if the chain is made with track that exclusively has 2 connections to make a chain
            // (or one for the first iteration).
            while ((currentBrick != null) && trackList.Contains(currentBrick) &&
                    ((currentFirstConnection == null) || (currentBrick.ConnectionPoints.Count == 2)))
            {
                // get the other connection on the current brick
                int secondIndex = (currentBrick.ConnectionPoints[0] == currentFirstConnection) ? 1 : 0;
                LayerBrick.Brick.ConnectionPoint currentSecondConnection = currentBrick.ConnectionPoints[secondIndex];
                LayerBrick.Brick nextBrick = currentSecondConnection.ConnectedBrick;
                LayerBrick.Brick.ConnectionPoint nextFirstConnection = currentSecondConnection.ConnectionLink;

                // add the two connections of the brick
                ChainLink link = new ChainLink(nextFirstConnection, currentSecondConnection);
                mFlexChainList.Insert(0, link);

                // check if the connection can rotate (if it is an hinge)
                float hingeAngle = BrickLibrary.Instance.getConnexionHingeAngle(currentSecondConnection.Type);
                if (hingeAngle != 0.0f)
                {
                    // advance the hinge conncetion
                    hingedLink = link;
                    // add the link in the list
                    addNewBone(currentSecondConnection, currentBrick, hingeAngle);
                    // compute the current angle between the hinge connection and set it to the current bone
                    // to do that we use the current angle between the connected brick and remove the static angle between them
                    // to only get the flexible angle.
                    float angleInDegree = 0.0f;
                    if (nextBrick != null)
                        angleInDegree = simplifyAngle(nextBrick.Orientation - currentBrick.Orientation - link.mAngleBetween);
                    mBoneList[0].localAngleInRad = angleInDegree * (Math.PI / 180);

                    // save the initial static cumulative orientation: start with the orientation of the root brick
                    // if the hinge is connected to a brick, otherwise, if the hinge is free (connected to the world)
                    // use the orientation of the hinge brick.
                    // we set the value several time in the loop, in order to set it with the brick directly
                    // connected to the last hinge in the chain
                    if (nextBrick != null)
                        mInitialStaticCumulativeOrientation = -nextBrick.Orientation;
                    else
                        mInitialStaticCumulativeOrientation = -currentBrick.Orientation;
                }

                // advance to the next link
                currentBrick = nextBrick;
                currentFirstConnection = nextFirstConnection;

                // check if the track is not a loop, otherwise we will have an infinite loop.
                // but don't add the test in the while because the first iteration must pass
                if (currentBrick == grabbedTrack)
                    break;
            }

            // store the root hinge connection index (the last hinge found is the flexible root)
            if (hingedLink != null)
                mRootHingedLinkIndex = mFlexChainList.IndexOf(hingedLink);

            // compute the last bone vector if there is enough bones
            if (mBoneList.Count > 2)
            {
                int lastIndex = mBoneList.Count - 1;
                int beforeLastIndex = lastIndex - 1;
                mLastBoneVector = new PointF((float)(mBoneList[beforeLastIndex].worldX - mBoneList[lastIndex].worldX),
                                            (float)(mBoneList[beforeLastIndex].worldY - mBoneList[lastIndex].worldY));
                // rotate the vector such as to compute it for a null angle
                // but if the last bone doesn't have connection, it can never snap, so the last bone will never be used
                if (mBoneList[lastIndex].connectionPoint != null)
                {
                    PointF[] translation = { mLastBoneVector };
                    Matrix rotation = new Matrix();
                    rotation.Rotate(mBoneList[lastIndex].connectionPoint.mMyBrick.Orientation);
                    rotation.TransformVectors(translation);
                    mLastBoneVector = translation[0];
                }
            }

            // add the current brick in the list of bricks, by not going further than the root brick
            LayerBrick.Brick.ConnectionPoint rootConnection = mFlexChainList[mRootHingedLinkIndex].mFirstConnection;
            if (rootConnection.mMyBrick != null)
                mBricksInTheFlexChain.Add(rootConnection.mMyBrick);
            for (int i = mRootHingedLinkIndex; i < mFlexChainList.Count; ++i)
                mBricksInTheFlexChain.Add(mFlexChainList[i].mSecondConnection.mMyBrick);
        }
Example #52
0
 private void MapPanel_DragDrop(object sender, DragEventArgs e)
 {
     if (mCurrentPartDrop != null)
     {
         // we have finished a dragndrop, remove the temporary part
         if (mBrickLayerThatReceivePartDrop != null)
         {
             mBrickLayerThatReceivePartDrop.removeTemporaryPartDrop(mCurrentPartDrop);
             mBrickLayerThatReceivePartDrop = null;
         }
         // and add the real new part
         Map.Instance.addBrick(mCurrentPartDrop);
         // reset the dropping part number here and there
         mCurrentPartDrop = null;
         (this.TopLevelControl as MainForm).resetDraggingPartNumberInPartLib();
         // refresh the view
         updateView();
         // and give the focus to the map panel such as if the user use the wheel to zoom
         // just after after the drop, the zoom is performed instead of the part lib scrolling
         this.Focus();
     }
     else
     {
         // if it is not a string, call the drag enter of the main app
         (this.TopLevelControl as MainForm).MainForm_DragDrop(sender, e);
     }
 }
Example #53
0
 private void addNewBone(LayerBrick.Brick.ConnectionPoint connection, LayerBrick.Brick brick, double maxAngleInDeg)
 {
     IKSolver.Bone_2D_CCD newBone = new IKSolver.Bone_2D_CCD();
     newBone.maxAbsoluteAngleInRad = maxAngleInDeg * (Math.PI / 180);
     if (connection != null)
     {
         newBone.worldX = connection.PositionInStudWorldCoord.X;
         newBone.worldY = -connection.PositionInStudWorldCoord.Y; // BlueBrick use an indirect coord sys, and the IKSolver a direct one
     }
     else
     {
         newBone.worldX = brick.Center.X;
         newBone.worldY = -brick.Center.Y; // BlueBrick use an indirect coord sys, and the IKSolver a direct one
     }
     newBone.connectionPoint = connection;
     mBoneList.Insert(0, newBone);
 }
Example #54
0
        private void MapPanel_DragEnter(object sender, DragEventArgs e)
        {
            // if the number of click is null, that means it can be a dragndrop from another view, such as the part lib
            // check if we need to search the image dropped, or if we already have it
            if (mCurrentPartDrop == null)
            {
                // by default do not accept the drop
                e.Effect = DragDropEffects.None;

                // ask the main window if one part was selected in the part lib
                // because the getData from the event doesn't work well under mono, normally it should be: e.Data.GetData(DataFormats.SystemString) as string
                string partDropNumber = (this.TopLevelControl as MainForm).getDraggingPartNumberInPartLib();

                // check if we can add it
                Map.BrickAddability canAdd = Map.Instance.canAddBrick(partDropNumber);
                if (canAdd == Map.BrickAddability.YES)
                {
                    mBrickLayerThatReceivePartDrop = Map.Instance.SelectedLayer as LayerBrick;
                    if (partDropNumber != null && mBrickLayerThatReceivePartDrop != null)
                    {
                        if (BrickLibrary.Instance.isAGroup(partDropNumber))
                            mCurrentPartDrop = new Layer.Group(partDropNumber);
                        else
                            mCurrentPartDrop = new LayerBrick.Brick(partDropNumber);
                        mBrickLayerThatReceivePartDrop.addTemporaryPartDrop(mCurrentPartDrop);
                        // set the effect in order to get the drop event
                        e.Effect = DragDropEffects.Copy;
                    }
                }
                else
                    Map.Instance.giveFeedbackForNotAddingBrick(canAdd);
            }

            // check again if we are not dragging a part, maybe we drag a file
            if (mCurrentPartDrop == null)
                (this.TopLevelControl as MainForm).MainForm_DragEnter(sender, e);
        }
Example #55
0
 /// <summary>
 /// read and set the two parameter to follow a chain of brick until we found a flexible part. This function only
 /// advance the search for one step (one link).
 /// </summary>
 /// <param name="connectionLead">the current connection point, from which we need to find the next one</param>
 /// <param name="isConnectionLeadingToFlexiblePart">a flag to tell if a flexible brick is found</param>
 private void followConnectionToFindFlexiblePart(ref LayerBrick.Brick.ConnectionPoint connectionLead, ref bool isConnectionLeadingToFlexiblePart)
 {
     if (connectionLead != null)
     {
         // set the flag if not already true
         isConnectionLeadingToFlexiblePart |= (BrickLibrary.Instance.getConnexionHingeAngle(connectionLead.Type) != 0.0f);
         // if we found a flexible part, stop following the path
         if (isConnectionLeadingToFlexiblePart)
         {
             connectionLead = null; // stop following this path
         }
         else
         {
             // jump to the attach brick accross the link (which may be null, in such case, the search will stop)
             connectionLead = connectionLead.ConnectionLink;
             // if there's a brick connected, check if it is a 2 connections brick and take the other
             if (connectionLead != null)
             {
                 // get the list of connection point for the first leading brick
                 List<LayerBrick.Brick.ConnectionPoint> connectionList = connectionLead.mMyBrick.ConnectionPoints;
                 if (connectionList.Count == 2)
                 {
                     // check the next connections and set it
                     int otherIndex = (connectionList[0] == connectionLead) ? 1 : 0;
                     connectionLead = connectionList[otherIndex];
                 }
                 else
                 {
                     // if it is a 0, 1 or 3 or more connections brick type, stop the search
                     connectionLead = null;
                 }
             }
         }
     }
 }
Example #56
0
 private void MapPanel_DragLeave(object sender, EventArgs e)
 {
     // if the user leave the panel while is was dropping a part,
     // just cancel the drop
     if (mCurrentPartDrop != null)
     {
         // remove and destroy the part
         if (mBrickLayerThatReceivePartDrop != null)
         {
             mBrickLayerThatReceivePartDrop.removeTemporaryPartDrop(mCurrentPartDrop);
             mBrickLayerThatReceivePartDrop = null;
         }
         mCurrentPartDrop = null;
         // update the view
         updateView();
     }
 }
Example #57
0
 public ChainLink(LayerBrick.Brick.ConnectionPoint firstConnection, LayerBrick.Brick.ConnectionPoint secondConnection)
 {
     mFirstConnection = firstConnection;
     mSecondConnection = secondConnection;
     if (firstConnection != null)
     {
         int firstIndex = firstConnection.mMyBrick.ConnectionPoints.IndexOf(firstConnection);
         int secondIndex = secondConnection.mMyBrick.ConnectionPoints.IndexOf(secondConnection);
         mAngleBetween = BrickLibrary.Instance.getConnectionAngleDifference(secondConnection.mMyBrick.PartNumber, secondIndex,
                                                                         firstConnection.mMyBrick.PartNumber, firstIndex);
     }
     else
     {
         // if the first connection point is null, create a dummy connection point in the world,
         // at the position of the second connection and not attached to a brick.
         // The angle between is in that case of course null
         mFirstConnection = new LayerBrick.Brick.ConnectionPoint(secondConnection.PositionInStudWorldCoord);
     }
 }
Example #58
0
 public RotateBrick(LayerBrick layer, List <Layer.LayerItem> bricks, int rotateSteps)
     : this(layer, bricks, rotateSteps, false)
 {
 }
Example #59
0
 public RotateBrick(LayerBrick layer, List <Layer.LayerItem> bricks, float angle, bool forceKeepLastCenter)
 {
     commonConstructor(layer, bricks, angle, forceKeepLastCenter);
 }
Example #60
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);
        }