private static HeightRender LoadRender(Stream stream) { byte[] buffer = new byte[4]; stream.Read(buffer, 0, sizeof(int)); int width = BitConverter.ToInt32(buffer, 0); stream.Read(buffer, 0, sizeof(int)); int height = BitConverter.ToInt32(buffer, 0); stream.Read(buffer, 0, sizeof(bool)); bool clamp = BitConverter.ToBoolean(buffer, 0); stream.Read(buffer, 0, sizeof(float)); float clampMin = BitConverter.ToSingle(buffer, 0); stream.Read(buffer, 0, sizeof(float)); float clampMax = BitConverter.ToSingle(buffer, 0); stream.Read(buffer, 0, sizeof(bool)); bool wrapX = BitConverter.ToBoolean(buffer, 0); stream.Read(buffer, 0, sizeof(bool)); bool wrapY = BitConverter.ToBoolean(buffer, 0); HeightRender render = new HeightRender(width, height, clamp, clampMin, clampMax, wrapX, wrapY); for (int i = 0; i < render.HeightField.Data.Length; i++) { stream.Read(buffer, 0, sizeof(float)); render.HeightField.Data[i] = BitConverter.ToSingle(buffer, 0); } return(render); }
public RenderDialog(string renderName, Form owner) { Owner = owner; if (renderName != null && renderName.Length > 0) { CenterToParent(); InitializeComponent(); Text = "Render - " + renderName; if (Document.ContainsRender(this.renderName = renderName) && (render = Document.GetRender(renderName)) != null) { widthBox.Value = render.HeightField.Width; widthBox.Enabled = false; heightBox.Value = render.HeightField.Height; heightBox.Enabled = false; clampBox.Checked = render.HeightField.Clamp; clampMinBox.Value = (decimal)render.HeightField.ClampMin; clampMaxBox.Value = (decimal)render.HeightField.ClampMax; wrapXBox.Checked = render.HeightField.WrapX; wrapYBox.Checked = render.HeightField.WrapY; } else { widthBox.Enabled = true; heightBox.Enabled = true; } } else { throw new Exception("The supplied name was empty or null."); } }
private void compileButton_Click(object sender, EventArgs e) { script.Source = scriptBox.Text; HeightRender.Effect effect; string errors; switch (HeightRender.CompileEffect(script, out effect, out errors)) { case HeightRender.EffectCompileResult.WrongApplySignature: MessageBox.Show("The method signature for the \"Apply\" function should be:\n\nPhoton Apply(int x, int y, Photon color, HeightField heightField)", "Script Error"); break; case HeightRender.EffectCompileResult.MissingApplyFunction: MessageBox.Show("The \"Apply\" function is missing from your script.", "Script Error"); break; case HeightRender.EffectCompileResult.SyntaxError: MessageBox.Show("There was a compilation error in your script:\r\n" + errors, "Script Error"); break; case HeightRender.EffectCompileResult.Success: Document.SetEffect(effectName, effect, script); break; } }
public RenderDialog(string renderName) { CenterToParent(); InitializeComponent(); Text = "Render - " + renderName; if (Document.ContainsRender(this.renderName = renderName)) { render = Document.GetRender(renderName); widthBox.Value = render.HeightField.Width; widthBox.Enabled = false; heightBox.Value = render.HeightField.Height; heightBox.Enabled = false; clampBox.Checked = render.HeightField.Clamp; clampMinBox.Value = (decimal)render.HeightField.ClampMin; clampMaxBox.Value = (decimal)render.HeightField.ClampMax; wrapXBox.Checked = render.HeightField.WrapX; wrapYBox.Checked = render.HeightField.WrapY; } else { widthBox.Enabled = true; heightBox.Enabled = true; } }
private void compileButton_Click(object sender, EventArgs e) { script.Source = scriptBox.Text; HeightRender.Generator generator; string errors; switch (HeightRender.CompileGenerator(script, out generator, out errors)) { case HeightRender.GeneratorCompileResult.WrongGenerateSignature: MessageBox.Show("The method signature for the \"Generate\" function should be:\n\nfloat Generate(int x, int y, HeightField heightField)", "Script Error"); break; case HeightRender.GeneratorCompileResult.MissingGenerateFunction: MessageBox.Show("The \"Generate\" function is missing from your script.", "Script Error"); break; case HeightRender.GeneratorCompileResult.SyntaxError: MessageBox.Show("There was a compilation error in your script:\r\n" + errors, "Script Error"); break; case HeightRender.GeneratorCompileResult.Success: Document.SetGenerator(generatorName, generator, script); break; } }
private void Document_RenderSet(string name, HeightRender render) { renderNameBox.Items.Clear(); foreach (string s in Document.RenderNames) { renderNameBox.Items.Add(s); } }
private void Document_RenderSet(string name, HeightRender render) { selectedRenderBox.Items.Clear(); foreach (string s in Document.RenderNames) { selectedRenderBox.Items.Add(s); } selectedRenderBox.SelectedItem = Document.SelectedRender; }
private void Document_RenderRemoved(string name, HeightRender render) { renderNameBox.Items.Clear(); selectedRenderBox.Items.Clear(); foreach (string s in Document.RenderNames) { renderNameBox.Items.Add(s); selectedRenderBox.Items.Add(s); } selectedRenderBox.Text = Document.SelectedRenderName; }
private static void SaveRender(Stream stream, HeightRender render) { stream.Write(BitConverter.GetBytes(render.HeightField.Width), 0, sizeof(int)); stream.Write(BitConverter.GetBytes(render.HeightField.Height), 0, sizeof(int)); stream.Write(BitConverter.GetBytes(render.HeightField.Clamp), 0, sizeof(bool)); stream.Write(BitConverter.GetBytes(render.HeightField.ClampMin), 0, sizeof(float)); stream.Write(BitConverter.GetBytes(render.HeightField.ClampMax), 0, sizeof(float)); stream.Write(BitConverter.GetBytes(render.HeightField.WrapX), 0, sizeof(bool)); stream.Write(BitConverter.GetBytes(render.HeightField.WrapY), 0, sizeof(bool)); for (int i = 0; i < render.HeightField.Data.Length; i++) { stream.Write(BitConverter.GetBytes(render.HeightField.Data[i]), 0, sizeof(float)); } }
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); } }
//Setting public static bool SetRender(string name, HeightRender render) { if (name != null && name.Length > 0) { renders[name] = render; if (renderSet != null) { renderSet(name, render); } return(true); } else { return(false); } }
private static GeneratorScript LoadGenerator(Stream stream) { CSScript script = new CSScript(); script.Source = LoadText(stream); HeightRender.Generator generator; string errors; HeightRender.CompileGenerator(script, out generator, out errors); GeneratorScript gs = new GeneratorScript() { generator = generator, script = script }; return(gs); }
private static EffectScript LoadEffect(Stream stream) { CSScript script = new CSScript(); script.Source = LoadText(stream); HeightRender.Effect effect; string errors; HeightRender.CompileEffect(script, out effect, out errors); EffectScript es = new EffectScript() { effect = effect, script = script }; return(es); }
//Loading public static IOEvaluation Load(string path) { Clear(); if (File.Exists(path)) { FileStream stream = null; try { stream = new FileStream(path, FileMode.Open); } catch { return(IOEvaluation.CannotOpenStream); } try { IOBlockIdentifier block; string blockName; byte[] blockBuff = new byte[sizeof(int)]; stream.Read(blockBuff, 0, sizeof(int)); block = (IOBlockIdentifier)BitConverter.ToInt32(blockBuff, 0); if (block == IOBlockIdentifier.FileBegin) { do { if (stream.Position < stream.Length) { stream.Read(blockBuff, 0, sizeof(int)); block = (IOBlockIdentifier)BitConverter.ToInt32(blockBuff, 0); switch (block) { case IOBlockIdentifier.FileEnd: break; case IOBlockIdentifier.Brush: blockName = LoadText(stream); BrushScript bs = LoadBrush(stream); SetBrush(blockName, bs.brush, bs.script); break; case IOBlockIdentifier.Effect: blockName = LoadText(stream); EffectScript es = LoadEffect(stream); SetEffect(blockName, es.effect, es.script); break; case IOBlockIdentifier.Gradient: blockName = LoadText(stream); PhotonGradient gradient = LoadGradient(stream); SetGradient(blockName, gradient); break; case IOBlockIdentifier.Render: blockName = LoadText(stream); HeightRender render = LoadRender(stream); SetRender(blockName, render); break; case IOBlockIdentifier.Generator: blockName = LoadText(stream); GeneratorScript gs = LoadGenerator(stream); SetGenerator(blockName, gs.generator, gs.script); break; default: throw new Exception("Encountered a block that couldn't be identified."); } } else { throw new Exception("The end of the file was reached before the appropriate 'End of File' flag was found."); } }while (block != IOBlockIdentifier.FileEnd); //Path and Callback associatedPath = path; if (loaded != null) { loaded(path); } return(IOEvaluation.Success); } else { return(IOEvaluation.ConversionError); } } catch { Clear(); return(IOEvaluation.ConversionError); } finally { stream.Close(); } } else { associatedPath = path; return(IOEvaluation.FileDoesNotExist); } }
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; }
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; }
//Loading public static bool Load(string path) { Clear(); if (File.Exists(path)) { FileStream stream = new FileStream(path, FileMode.Open); try { byte[] countBuf = new byte[4]; int count; //Load Renders stream.Read(countBuf, 0, sizeof(int)); count = BitConverter.ToInt32(countBuf, 0); for (int i = 0; i < count; i++) { string name = LoadText(stream); HeightRender render = LoadRender(stream); SetRender(name, render); } //Load Gradients stream.Read(countBuf, 0, sizeof(int)); count = BitConverter.ToInt32(countBuf, 0); for (int i = 0; i < count; i++) { string name = LoadText(stream); PhotonGradient gradient = LoadGradient(stream); SetGradient(name, gradient); } //Load Effects stream.Read(countBuf, 0, sizeof(int)); count = BitConverter.ToInt32(countBuf, 0); for (int i = 0; i < count; i++) { string name = LoadText(stream); EffectScript es = LoadEffect(stream); SetEffect(name, es.effect, es.script); } //Load Brushes stream.Read(countBuf, 0, sizeof(int)); count = BitConverter.ToInt32(countBuf, 0); for (int i = 0; i < count; i++) { string name = LoadText(stream); BrushScript bs = LoadBrush(stream); SetBrush(name, bs.brush, bs.script); } //Path and Callback associatedPath = path; if (loaded != null) { loaded(path); } return(true); } catch { associatedPath = null; return(false); } finally { stream.Close(); } } else { associatedPath = path; return(false); } }