using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Foundations.Testbed { public partial class GUI : Form { public class SimulationState : Foundations.ISimulationState { public int Value { get; set; } public void CopyFrom(SimulationState other) { Value = other.Value; } public string Serialize() { return Value.ToString(); } public void Deserialize(string serializedState) { Value = int.Parse(serializedState); } } public class RenderState { public int Value { get; set; } } public GUI() { _main = new Foundations.Main(Simulate, PrepareRender, Render); InitializeComponent(); _main.SimulationLoop.Paused.OnChanged += UpdateSimPlayButton; _main.RenderLoop.Paused.OnChanged += UpdateRenderPlayButton; _main.DrawLoop.Paused.OnChanged += UpdateDrawCallbackPlayButton; _simWorkloadHeavy.OnChanged += UpdateSimWorkloadButton; _renderWorkloadHeavy.OnChanged += UpdateRenderWorkloadButton; _drawWorkloadHeavy.OnChanged += UpdateDrawWorkloadButton; _main.FrameLocked.OnChanged += UpdateFrameLockedCheckbox; _main.PulseChangeEvents(); _simWorkloadHeavy.PulseChangeEvent(); _renderWorkloadHeavy.PulseChangeEvent(); _drawWorkloadHeavy.PulseChangeEvent(); timer.Start(); } /// /// Sends the action off to be invoked on the GUI thread if necessary, otherwise executes immediately. /// private void MaybeInvoke(Action action) { if (InvokeRequired) { this.BeginInvoke(action); } else { action(); } } private void UpdateSimPlayButton(bool paused) { MaybeInvoke(() => this.playButton.Text = paused ? "Paused" : "Playing"); } private void UpdateRenderPlayButton(bool paused) { MaybeInvoke(() => this.renderPlayButton.Text = paused ? "Paused" : "Playing"); } private void UpdateDrawCallbackPlayButton(bool enabled) { MaybeInvoke(() => this.idlePlayButton.Text = enabled ? "Paused" : "Playing"); } private void UpdateSimWorkloadButton(bool enabled) { MaybeInvoke(() => this.simWorkloadButton.Text = enabled ? "Heavy" : "Light"); } private void UpdateRenderWorkloadButton(bool enabled) { MaybeInvoke(() => this.renderWorkloadButton.Text = enabled ? "Heavy" : "Light"); } private void UpdateDrawWorkloadButton(bool enabled) { MaybeInvoke(() => this.drawWorkloadButton.Text = enabled ? "Heavy" : "Light"); } private void UpdateFrameLockedCheckbox(bool frameLocked) { MaybeInvoke(() => frameLockedCheckbox.Checked = frameLocked); } /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } if (_main != null) { _main.Dispose(); _main = null; } base.Dispose(disposing); } private ThreadsafeBool _simWorkloadHeavy = new ThreadsafeBool(); private void Simulate(SimulationState state) { if (_simWorkloadHeavy) { System.Threading.Thread.Sleep(millisecondsTimeout: 1000); } ++state.Value; } private ThreadsafeBool _renderWorkloadHeavy = new ThreadsafeBool(); private RenderState PrepareRender(SimulationState state) { if (_renderWorkloadHeavy) { System.Threading.Thread.Sleep(millisecondsTimeout: 1000); } return new RenderState { Value = state.Value, }; } private ThreadsafeBool _drawWorkloadHeavy = new ThreadsafeBool(); private void Render(RenderState state) { if (_drawWorkloadHeavy) { System.Threading.Thread.Sleep(millisecondsTimeout: 1000); } renderingLabel.Text = "Current count: " + state.Value; } private Foundations.Main _main; private void playButton_Click(object sender, EventArgs e) { _main.SimulationLoop.Paused.Toggle(); } private void stepButton_Click(object sender, EventArgs e) { _main.SimulationLoop.SingleStep(); } private void simCrashButton_Click(object sender, EventArgs e) { _main.SimulationLoop.ForceCrash(); } private void renderCrashButton_Click(object sender, EventArgs e) { _main.RenderLoop.ForceCrash(); } private void idleCrashButton_Click(object sender, EventArgs e) { _main.DrawLoop.ForceCrash(); } private void uiCrashButton_Click(object sender, EventArgs e) { throw new Exception("Poop"); } private void renderPlayButton_Click(object sender, EventArgs e) { _main.RenderLoop.Paused.Toggle(); } private void renderStepButton_Click(object sender, EventArgs e) { _main.RenderLoop.SingleStep(); } private void timer_Tick(object sender, EventArgs e) { simCycleTimesLabel.Text = (_main.SimulationLoop.WeightedCycleTimes * 1000000).ToString("0.00") + " ns/cyc"; renderCycleTimesLabel.Text = (_main.RenderLoop.WeightedCycleTimes * 1000000).ToString("0.00") + " ns/cyc"; uiCycleTimesLabel.Text = (_main.DrawLoop.WeightedCycleTimes * 1000000).ToString("0.00") + " ns/cyc"; } private void frameLockedCheckbox_CheckedChanged(object sender, EventArgs e) { _main.FrameLocked.Toggle(); } private void idlePlayButton_Click(object sender, EventArgs e) { _main.DrawLoop.Paused.Toggle(); } private void simWorkloadButton_Click(object sender, EventArgs e) { _simWorkloadHeavy.Toggle(); } private void renderWorkloadButton_Click(object sender, EventArgs e) { _renderWorkloadHeavy.Toggle(); } private void drawWorkloadButton_Click(object sender, EventArgs e) { _drawWorkloadHeavy.Toggle(); } private async void modifiersCrashButton_Click(object sender, EventArgs e) { await _main.EnqueueModifier(state => { throw new InvalidOperationException("Test modifier crash."); }); } private async void queriesCrashButton_Click(object sender, EventArgs e) { Func callback = state => { throw new InvalidOperationException("Test modifier crash."); }; await _main.QuerySimulation(callback); } } }