Ejemplo n.º 1
0
 private void Redo()
 {
     if (redoQueue.Count > 0)
     {
         BrushAction redoAction = redoQueue.Dequeue();
         //Set all of the values in the affected area to what they were before the undo action took place.
         HeightRender render   = Document.SelectedRender;
         BrushAction  opposite = new BrushAction(redoAction.Selection, redoAction.Data);
         for (int x = redoAction.Selection.Left; x < redoAction.Selection.Right; x++)
         {
             for (int y = redoAction.Selection.Top; y < redoAction.Selection.Bottom; y++)
             {
                 float oldSample;
                 if (render.HeightField.TryGetHeight(x, y, out oldSample))
                 {
                     int i = (y - redoAction.Selection.Top) * redoAction.Selection.Width + (x - redoAction.Selection.Left);
                     render.HeightField[x, y] = redoAction.Data[i];
                     opposite.Data[i]         = oldSample;
                 }
             }
         }
         PhotonGradient gradient = Document.SelectedGradient;
         IEnumerable <HeightRender.Effect> effects;
         if (paintEffectsBox.Checked)
         {
             effects = Document.SelectedEffects;
         }
         else
         {
             effects = null;                 //Don't worry about effects if we're not painting with them.
         }
         //Update each section of the selection when wrapping has been accounted for.
         foreach (FieldSelection fs in redoAction.Selection.SubSelectionsOf(render.HeightField))
         {
             //Omit any parts that have a width or height of zero.
             if (!fs.IsEmpty)
             {
                 //Update the corresponding part of the render.
                 render.UpdateArea(fs.Left, fs.Top, fs.Width, fs.Height, gradient, effects);
                 //Invalidate the corresponding part of the image panel so that it redraws itself in realtime.
                 Point start = Numerics.ToPoint(renderArea.ImageToClient(new Vector2(fs.Left, fs.Top)));
                 Point end   = Numerics.ToPoint(renderArea.ImageToClient(new Vector2(fs.Right, fs.Bottom)));
                 renderArea.Invalidate(new Rectangle(Numerics.Max(start.X, 0), Numerics.Max(start.Y, 0), Numerics.Max(end.X, 0), Numerics.Max(end.Y, 0)));
             }
         }
         undoQueue.Enqueue(opposite);
     }
 }
Ejemplo n.º 2
0
        private void Application_Idle(object sender, EventArgs e)
        {
            Vector2 pointOnRenderArea = Numerics.ToVector(renderArea.PointToClient(Control.MousePosition));
            Vector2 pointOnRender     = renderArea.ClientToImage(pointOnRenderArea);

            if (renderArea.Focused && Document.SelectedRender != null)
            {
                #region Panning
                if (MouseButtons == MouseButtons.Middle)
                {
                    renderArea.ImageOffset += (pointOnRenderArea - lastPointOnRenderArea) / renderArea.ImageScale;
                }
                #endregion
                #region Brush
                HeightBrush activeBrush = null;
                if (MouseButtons == MouseButtons.Left)
                {
                    activeBrush = Document.LeftBrush;
                }
                else if (MouseButtons == MouseButtons.Right)
                {
                    activeBrush = Document.RightBrush;
                }

                if (activeBrush != null)
                {
                    HeightRender   render   = Document.SelectedRender;
                    PhotonGradient gradient = Document.SelectedGradient;
                    IEnumerable <HeightRender.Effect> effects;
                    if (paintEffectsBox.Checked)
                    {
                        effects = Document.SelectedEffects;
                    }
                    else
                    {
                        effects = null;
                    }
                    #region Process Steps
                    Vector2 brushDelta   = lastPointOnRender - pointOnRender;
                    float   strokeLength = (float)brushDelta.Length;
                    float   steps        = strokeLength / activeBrush.Precision + 1;
                    Vector2 brushStep    = brushDelta * (1.0f / steps);
                    for (int i = 0; i < steps; i++)
                    {
                        Vector2 brushPosition = pointOnRender + brushStep * i;
                        #region Process Brush Paint
                        try
                        {
                            FieldSelection brushArea;
                            activeBrush.Paint(render.HeightField, (int)brushPosition.X, (int)brushPosition.Y, strokeLength, out brushArea);
                            foreach (FieldSelection fs in brushArea.SubSelectionsOf(render.HeightField))
                            {
                                if (!fs.IsEmpty)
                                {
                                    render.UpdateArea(fs.Left, fs.Top, fs.Width, fs.Height, gradient, effects);
                                    Point start = Numerics.ToPoint(renderArea.ImageToClient(new Vector2(fs.Left, fs.Top)));
                                    Point end   = Numerics.ToPoint(renderArea.ImageToClient(new Vector2(fs.Right, fs.Bottom)));
                                    renderArea.Invalidate(new Rectangle(Numerics.Max(start.X, 0), Numerics.Max(start.Y, 0), Numerics.Max(end.X, 0), Numerics.Max(end.Y, 0)));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "There was a runtime error with your brush script.");
                        }
                        #endregion
                    }
                    #endregion
                }
                #endregion
            }

            lastPointOnRenderArea = pointOnRenderArea;
            lastPointOnRender     = pointOnRender;
        }
Ejemplo n.º 3
0
        private void Application_Idle(object sender, EventArgs e)
        {
            Vector2 pointOnRenderArea = Numerics.ToVector(renderArea.PointToClient(Control.MousePosition));
            Vector2 pointOnRender     = renderArea.ClientToImage(pointOnRenderArea);

            if (renderArea.Focused && Document.SelectedRender != null)
            {
                #region Undo
                if (undoing)
                {
                    Undo();
                }
                #endregion
                #region Redo
                if (redoing)
                {
                    Redo();
                }
                #endregion
                #region Panning
                if (MouseButtons == MouseButtons.Middle)
                {
                    renderArea.ImageOffset += (pointOnRenderArea - lastPointOnRenderArea) / renderArea.ImageScale;
                }
                #endregion
                #region Brush
                //Select the appropriate brush based on the active mouse buttons.
                HeightBrush activeBrush = null;
                if (MouseButtons == MouseButtons.Left)
                {
                    activeBrush = Document.LeftBrush;
                }
                else if (MouseButtons == MouseButtons.Right)
                {
                    activeBrush = Document.RightBrush;
                }
                //If a mouse button was in use; paint.
                if (activeBrush != null)
                {
                    HeightRender   render   = Document.SelectedRender;
                    PhotonGradient gradient = Document.SelectedGradient;
                    IEnumerable <HeightRender.Effect> effects;
                    if (paintEffectsBox.Checked)
                    {
                        effects = Document.SelectedEffects;
                    }
                    else
                    {
                        effects = null;                     //If we aren't painting with effects then we don't care about supplying them to the update.
                    }
                    #region Process Steps
                    //The brush stroke is broken up into steps that are each a given length (in pixels). The length is denoted by the brush precision.
                    Vector2 brushDelta   = lastPointOnRender - pointOnRender;
                    float   strokeLength = (float)brushDelta.Length;
                    float   steps        = strokeLength / activeBrush.Precision + 1;
                    Vector2 brushStep    = brushDelta * (1.0f / steps);
                    for (int i = (int)steps - 1; i >= 0; i--)                    //Work backwards so the undo and redo functionality makes sense.
                    {
                        //Calculate the current brush position, based on the starting point, the step vector and the current step index.
                        Vector2 brushPosition = pointOnRender + brushStep * i;
                        #region Process Brush Paint
                        try
                        {
                            //Perform the actual brush operation and capture the selected area it affects.
                            FieldSelection brushArea;
                            float[]        previousData;
                            activeBrush.Paint(render.HeightField, (int)brushPosition.X, (int)brushPosition.Y, strokeLength, out brushArea, out previousData);
                            //Add this paint event to the undo queue.
                            undoQueue.Enqueue(new BrushAction(brushArea, previousData));
                            redoQueue.Clear();
                            //Break up the brush area into multiple parts if they intersect the edges of the image.
                            foreach (FieldSelection fs in brushArea.SubSelectionsOf(render.HeightField))
                            {
                                //Omit any parts that have a width or height of zero.
                                if (!fs.IsEmpty)
                                {
                                    //Update the corresponding part of the render.
                                    render.UpdateArea(fs.Left, fs.Top, fs.Width, fs.Height, gradient, effects);
                                    //Invalidate the corresponding part of the image panel so that it redraws itself in realtime.
                                    Point start = Numerics.ToPoint(renderArea.ImageToClient(new Vector2(fs.Left, fs.Top)));
                                    Point end   = Numerics.ToPoint(renderArea.ImageToClient(new Vector2(fs.Right, fs.Bottom)));
                                    renderArea.Invalidate(new Rectangle(Numerics.Max(start.X, 0), Numerics.Max(start.Y, 0), Numerics.Max(end.X, 0), Numerics.Max(end.Y, 0)));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            //This usually happens when activeBrush.Paint is called, because it executes the user's brush script. Shows the script error message as a message box.
                            MessageBox.Show(ex.Message, "There was a runtime error with your brush script.");
                        }
                        #endregion
                    }
                    #endregion
                }
                #endregion
            }
            else
            {
                undoing = redoing = false;
            }

            lastPointOnRenderArea = pointOnRenderArea;
            lastPointOnRender     = pointOnRender;
        }