Example #1
0
        private void drawArrow(PseudoButton sourceButton, PseudoButton destinationButton, Boolean successArrow)
        {
            Line line = new Line();

            line.Visibility      = System.Windows.Visibility.Visible;
            line.StrokeThickness = 2;

            //var x1 = GetRight(currentButton.button);
            line.X1 = sourceButton.left + sourceButton.button.ActualWidth;
            line.X2 = destinationButton.left;
            line.Y1 = sourceButton.top + sourceButton.button.ActualHeight / 2;
            line.Y2 = destinationButton.top + destinationButton.button.ActualHeight / 2;
            Children.Add(line);
            //Arrowhead:
            var    arrowheadlength = 7;
            Point  source          = new Point(line.X1, line.Y1);
            Point  destination     = new Point(line.X2, line.Y2);
            Matrix rotatorone      = new Matrix();
            Vector backvect        = (source - destination);

            backvect.Normalize();
            backvect = backvect * arrowheadlength;
            rotatorone.Rotate(45);
            Line arrowlineone = new Line();

            arrowlineone.X1 = line.X2;
            arrowlineone.Y1 = line.Y2;
            Point arrowlineoneend = new Point(line.X2, line.Y2) + backvect * rotatorone;

            arrowlineone.X2 = arrowlineoneend.X;
            arrowlineone.Y2 = arrowlineoneend.Y;
            Line arrowlinetwo = new Line();

            arrowlinetwo.X1 = line.X2;
            arrowlinetwo.Y1 = line.Y2;
            Matrix rotatortwo = new Matrix();

            rotatortwo.Rotate(-45);
            Point arrowlinetwoend = new Point(line.X2, line.Y2) + backvect * rotatortwo;

            arrowlinetwo.X2 = arrowlinetwoend.X;
            arrowlinetwo.Y2 = arrowlinetwoend.Y;

            arrowlineone.Visibility      = System.Windows.Visibility.Visible;
            arrowlineone.StrokeThickness = 2;
            arrowlinetwo.Visibility      = System.Windows.Visibility.Visible;
            arrowlinetwo.StrokeThickness = 2;
            if (line.X1 < line.X2)
            {
                if (successArrow)
                {
                    line.Stroke         = System.Windows.Media.Brushes.Black;
                    arrowlineone.Stroke = System.Windows.Media.Brushes.Black;
                    arrowlinetwo.Stroke = System.Windows.Media.Brushes.Black;
                }
                else
                {
                    line.Stroke         = System.Windows.Media.Brushes.Red;
                    arrowlineone.Stroke = System.Windows.Media.Brushes.Red;
                    arrowlinetwo.Stroke = System.Windows.Media.Brushes.Red;
                }
            }
            else
            {
                if (successArrow)
                {
                    line.Stroke         = System.Windows.Media.Brushes.DarkGray;
                    arrowlineone.Stroke = System.Windows.Media.Brushes.DarkGray;
                    arrowlinetwo.Stroke = System.Windows.Media.Brushes.DarkGray;
                }
                else
                {
                    line.Stroke         = System.Windows.Media.Brushes.PaleVioletRed;
                    arrowlineone.Stroke = System.Windows.Media.Brushes.PaleVioletRed;
                    arrowlinetwo.Stroke = System.Windows.Media.Brushes.PaleVioletRed;
                }
            }
            Children.Add(arrowlineone);
            Children.Add(arrowlinetwo);
            SetZIndex(line, 0);
        }
Example #2
0
        public void BuildFlowchart()
        {
            var gdv = DataContext as gameDataView;

            //Populate the flowchart view now.  First, clear all old controls, which should get rid of buttons from last time
            Children.Clear();//Kill the actual buttons and lines on the canvas
            questButtons.Clear();
            uuidToStepButton.Clear();
            MinWidth  = 10;
            MinHeight = 10; //They get expanded below, after placing the buttons.
            List <PseudoButton> notYetUsedStepButtons = new List <PseudoButton>();
            PseudoButton        startingButton        = null;

            foreach (gamedataObject questStepObj in gdv.selectedQuestStepsObservable)
            {
                if (questStepObj.uuid.Equals(""))
                {
                    continue;
                }
                PseudoButton stepButton = new PseudoButton();
                stepButton.associatedQuestStep = questStepObj;
                stepButton.button.Content      = questStepObj.name;
                questButtons.Add(stepButton);
                notYetUsedStepButtons.Add(stepButton);
                uuidToStepButton.Add(questStepObj.uuid, stepButton);
                if (questStepObj.uuid.Equals(gdv.gameData.firstStepID))
                {
                    startingButton = stepButton;
                }
                stepButton.button.Click += delegate(object sender, RoutedEventArgs e) {
                    ((gameDataView)DataContext).SelectedQuestStep = questStepObj;
                };
                Children.Add(stepButton.button);//Add the actual button to the canvas; placement is arbitrary right now but will be fixed up below
                SetZIndex(stepButton.button, 1);
            }

            //While creating a quest, we hit this...
            if (notYetUsedStepButtons.Count() == 0)
            {
                return;
            }

            //Creating a flowchart:  we form columns of these step buttons.
            //The first column consists of the button for the quests starting step.
            //Then, we loop over all the steps in the rightmost column, and for each of those, we look at the following steps; if they are already somewhere, this is a backward loop, if they are not anywhere yet, they go into the next column.
            //When we hit a point where everything in the last column either has no followon, or is a backloop, the next column is empty, so we can stop.
            //Then we loop over all the steps creating arrows
            List <List <PseudoButton> > columnsOfSteps = new List <List <PseudoButton> >();
            List <PseudoButton>         firstColumn    = new List <PseudoButton>();

            firstColumn.Add(startingButton);
            columnsOfSteps.Add(firstColumn);
            notYetUsedStepButtons.Remove(startingButton);
            bool lastColumnEmpty = false;
            int  column          = 0;

            while (!lastColumnEmpty)
            {
                List <PseudoButton> newColumn = new List <PseudoButton>();
                int currentRow = 0;
                List <PseudoButton> currentColumn = columnsOfSteps.Last();
                foreach (PseudoButton stepButton in currentColumn)
                {
                    stepButton.column = column;
                    stepButton.row    = currentRow;
                    currentRow++;
                    string stepUUID = stepButton.associatedQuestStep.uuid;

                    foreach (gamedataObject choiceObj in gdv.root.Items.Where <gamedataObject>(iter => [email protected]("QuestStepChoiceData") &&
                                                                                               iter.deleted.Equals("False") &&
                                                                                               iter.stepID.Equals(stepUUID)))
                    {
                        if (choiceObj.nextStep != null && choiceObj.nextStep.Count() > 0)
                        {
                            string       nextStepUUID   = choiceObj.nextStepID;
                            PseudoButton nextStepButton = null;
                            foreach (PseudoButton iterButton in notYetUsedStepButtons)
                            {
                                if (iterButton.associatedQuestStep.uuid.Equals(nextStepUUID))
                                {
                                    nextStepButton = iterButton;
                                    notYetUsedStepButtons.Remove(iterButton);
                                    break;
                                }
                            }
                            if (nextStepButton != null)
                            {
                                newColumn.Add(nextStepButton);
                            }
                            string       failStepUUID   = choiceObj.failStepID;
                            PseudoButton failStepButton = null;
                            foreach (PseudoButton iterButton in notYetUsedStepButtons)
                            {
                                if (iterButton.associatedQuestStep.uuid.Equals(failStepUUID))
                                {
                                    failStepButton = iterButton;
                                    notYetUsedStepButtons.Remove(iterButton);
                                    break;
                                }
                            }
                            if (failStepButton != null)
                            {
                                newColumn.Add(failStepButton);
                            }
                        }
                    }
                }
                if (newColumn.Count() == 0)
                {
                    lastColumnEmpty = true;
                }
                else
                {
                    columnsOfSteps.Add(newColumn);
                    column++;
                }
            }
            //Place un-reachable nodes so they don't overlap the actual root node; right now they're still at row 0 col 0:
            int unusedButtonRow = 1;

            foreach (PseudoButton unusedButton in notYetUsedStepButtons)
            {
                unusedButton.row = unusedButtonRow;
                unusedButtonRow++;
            }

            UpdateLayout();//This does the _internal_ layout on all of the buttons, which causes their widths to be set according to the text in them, which is needed below.

            //Now that all the buttons are set up, shuffle them around to the right locations and add lines.
            //Loop over all the buttons and figure out their widths, and from that, the column bounds, and from that, the bounds of each button.
            double[] columnWidths           = new double[questButtons.Count];
            double[] cumulativeColumnWidths = new double[questButtons.Count];
            foreach (PseudoButton currentButton in questButtons)
            {
                double textWidth = currentButton.button.ActualWidth;
                if (textWidth > columnWidths[currentButton.column])
                {
                    columnWidths[currentButton.column] = textWidth;
                }
            }
            double cumulativeWidth = 0;

            for (int i = 0; i < cumulativeColumnWidths.Length; i++)
            {
                cumulativeColumnWidths[i] = cumulativeWidth;
                cumulativeWidth           = cumulativeWidth + columnWidths[i] + 36;
            }
            //Now that we have valid column widths, set the location of the current button.
            foreach (PseudoButton currentButton in questButtons)
            {
                currentButton.top = 10 + 50 * (currentButton.row);
                SetTop(currentButton.button, currentButton.top);
                if (currentButton.top + currentButton.button.ActualHeight + 10 > MinHeight)
                {
                    MinHeight = currentButton.top + currentButton.button.ActualHeight + 10;
                }
                currentButton.left = 10 + cumulativeColumnWidths[currentButton.column];
                if (currentButton.left + currentButton.button.ActualWidth + 10 > MinWidth)
                {
                    MinWidth = currentButton.left + currentButton.button.ActualWidth + 10;
                }
                SetLeft(currentButton.button, currentButton.left);
            }
            foreach (PseudoButton currentButton in questButtons)
            {
                foreach (gamedataObject choiceObj in gdv.root.Items.Where <gamedataObject>(iter => [email protected]("QuestStepChoiceData") &&
                                                                                           iter.deleted.Equals("False") &&
                                                                                           iter.stepID.Equals(((gamedataObject)currentButton.associatedQuestStep).uuid)))
                {
                    string nextStepUUID = choiceObj.nextStepID;
                    if (nextStepUUID != null && nextStepUUID != "")
                    {
                        PseudoButton nextStepButton = null;
                        uuidToStepButton.TryGetValue(nextStepUUID, out nextStepButton);
                        if (nextStepButton != null)
                        {
                            drawArrow(currentButton, nextStepButton, true);
                        }
                    }
                    string failStepUUID = choiceObj.failStepID;
                    if (failStepUUID != null && failStepUUID != "")
                    {
                        PseudoButton nextStepButton = null;
                        uuidToStepButton.TryGetValue(failStepUUID, out nextStepButton);
                        if (nextStepButton != null)
                        {
                            drawArrow(currentButton, nextStepButton, false);
                        }
                    }
                }
            }
        }