Source

SharpHammer / SharpHammer / engine.cs

using System;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace SharpHammer
{
	public class Engine : DisposableBase
	{
		Scene _activeScene = null;
		Camera _activeCamera = null;
		RenderForm _frm = null;
		bool _pause = false;
		Stopwatch _sw = new Stopwatch();

		public event UpdateHandler OnUpdate;
		public event ActivateHandler OnActivate;
		public event ResizeHandler OnResize;

		public Engine(string title, Config cfg)
			: this(title, cfg, IntPtr.Zero)
		{

		}

		public Engine(string title, Config cfg, IntPtr hwnd)
		{
			int r;
			if (hwnd == IntPtr.Zero) {
				_frm = new RenderForm();
				hwnd = _frm.Handle;
			}
			r = NativeCalls.app_init(title, cfg._params, hwnd);

			if (NativeCalls.IS_FAIL(r))
				throw new Exception("Failed to initialize app.");
			r = NativeCalls.eng_init(cfg._params);
			if (NativeCalls.IS_FAIL(r))
				throw new Exception("Failed to initialize engine.");

			if (_frm != null) {
				_frm.Text = title;
				int w = (int)NativeCalls.app_get_wndwidth();
				int h = (int)NativeCalls.app_get_wndheight();
				_frm.ClientSize = new System.Drawing.Size(w, h);
			}
		}

		public void Run()
		{
			NativeCalls.gfx_set_gridcallback();
			if (_frm != null) {
				_frm.Resize = onResize;
				_frm.Update = onUpdate;
				System.Windows.Forms.Application.Run(_frm);
			} else {
				//Application.Idle += Application_Idle;
			}
		}

		//void Application_Idle(object sender, EventArgs e)
		//{
		//	while (AppStillIdle) {
		//		onUpdate();
		//	}
		//}

		public bool IsAppStillIdle
		{
			get { return Engine.AppStillIdle; }
		}

		public void Update()
		{
			onUpdate();
		}

		public void SetViewSize(int w, int h)
		{
			NativeCalls.cam_set_viewsize(ref ActiveCamera._cam, (float)w, (float)h);
			NativeCalls.app_resize_window(IntPtr.Zero, (UInt32)w, (UInt32)h);
		}

		void onUpdate()
		{			
			_sw.Stop();
			//_sw.
			_sw.Start();
			NativeCalls.input_update();
			if (OnUpdate != null)
				OnUpdate();
			NativeCalls.eng_update();
		}

		void onResize()
		{
			SetViewSize(_frm.ClientSize.Width, _frm.ClientSize.Height);
		}

		protected override void OnDisposeManaged()
		{
			if (_frm != null) {
				_frm.Close();
				_frm.Dispose();
			}
			if (_activeScene != null)
				_activeScene.Dispose();
		}

		protected override void OnDisposeUnmanaged()
		{
			NativeCalls.eng_release();
			NativeCalls.app_release();
		}

		#region Properties
		public Scene ActiveScene
		{
			get { return _activeScene; }
			set
			{
				_activeScene = value;
				NativeCalls.scn_setactive(value._sceneID);
			}
		}

		public Camera ActiveCamera
		{
			get { return _activeCamera; }
			set
			{
				_activeCamera = value;
				NativeCalls.scn_setcam(ref _activeCamera._cam);
			}
		}

		public bool Pause
		{
			get { return _pause; }
			set
			{
				_pause = value;
				if (_pause)
					NativeCalls.eng_pause();
				else
					NativeCalls.eng_resume();
			}
		}
		#endregion

		#region FastLoop
		static bool AppStillIdle
		{
			get
			{
				Message msg;
				return !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
			}
		}

		[System.Security.SuppressUnmanagedCodeSecurity]
		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		[return: MarshalAs(UnmanagedType.Bool)]
		private static extern bool PeekMessage(out Message msg, IntPtr hWnd,
			uint messageFilterMin, uint messageFilterMax, uint flags);

		[StructLayout(LayoutKind.Sequential)]
		struct Message
		{
			public IntPtr hWnd;
			public uint msg;
			public IntPtr wParam;
			public IntPtr lParam;
			public uint time;
			public System.Drawing.Point p;
		}
		#endregion

		#region RenderForm
		private class RenderForm : Form
		{
			public Action Update = null;
			public Action Resize = null;

			public RenderForm()
			{
				this.SuspendLayout();
				this.ClientSize = new System.Drawing.Size(400, 300);
				this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
				this.MaximizeBox = false;
				this.MinimizeBox = false;
				this.Name = "RenderForm";
				this.Text = "RenderForm";
				this.ResumeLayout(false);

				Application.Idle += Application_Idle;
			}

			void Application_Idle(object sender, EventArgs e)
			{
				while (AppStillIdle) {
					if (Update != null)
						Update();
				}	
			}

			protected override void OnResize(EventArgs e)
			{ 
				if (Resize != null)
					Resize(); 
			}

			protected override void OnPaint(PaintEventArgs e)
			{ }

			protected override void OnPaintBackground(PaintEventArgs e)
			{ }
		}
		#endregion

	}

	#region Delegates
	public delegate void UpdateHandler();
	public delegate void ResizeHandler(int width, int height);
	public delegate void ActivateHandler(bool active);
	#endregion
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.