Selaa lähdekoodia

Merge branch 'master' of github.com:taylor001/crown

Daniele Bartolini 10 vuotta sitten
vanhempi
sitoutus
29aa6f3807

+ 14 - 0
.gitignore

@@ -3,3 +3,17 @@
 
 
 # Ignore Python stuff
 # Ignore Python stuff
 __pycache__
 __pycache__
+
+# Ignore C# stuff
+/tools/**/bin
+/tools/**/obj
+/tools/**/Obj
+/tools/**/TestResults
+/tools/**/test-results
+/tools/**/*.csproj.user
+/tools/**/*.suo
+/tools/**/*.cache
+/tools/**/*~
+/tools/**/*.swp
+/tools/**/*.userprefs
+/tools/**/*.pidb

+ 2 - 2
README.md

@@ -28,11 +28,11 @@ C++ API: http://taylor001.github.io/crown/doxygen/
 
 
 TCP/IP console with autocomplete and color-coded output highlighting.
 TCP/IP console with autocomplete and color-coded output highlighting.
 
 
-![console](https://raw.githubusercontent.com/taylor001/crown/master/shots/console.png)
+![console](https://raw.githubusercontent.com/taylor001/crown/master/docs/shots/console.png)
 
 
 [WIP] Node editor.
 [WIP] Node editor.
 
 
-![node-editor](https://raw.githubusercontent.com/taylor001/crown/master/shots/node-editor.png)
+![node-editor](https://raw.githubusercontent.com/taylor001/crown/master/docs/shots/node-editor.png)
 
 
 ##Dependencies
 ##Dependencies
 
 

+ 0 - 0
shots/console.png → docs/shots/console.png


+ 0 - 0
shots/node-editor.png → docs/shots/node-editor.png


+ 0 - 3
src/core/filesystem/disk_file.cpp

@@ -5,8 +5,6 @@
 
 
 #include "disk_file.h"
 #include "disk_file.h"
 #include "types.h"
 #include "types.h"
-#include "log.h"
-#include "math_utils.h"
 #include "memory.h"
 #include "memory.h"
 #include <algorithm>
 #include <algorithm>
 
 
@@ -163,4 +161,3 @@ bool DiskFile::can_seek() const
 }
 }
 
 
 } // namespace crown
 } // namespace crown
-

+ 16 - 16
src/core/thread/semaphore.h

@@ -29,9 +29,9 @@ struct Semaphore
 #endif
 #endif
 	{
 	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-		int result = pthread_cond_init(&m_cond, NULL);
-		CE_ASSERT(result == 0, "pthread_cond_init: errno = %d", result);
-		CE_UNUSED(result);
+		int err = pthread_cond_init(&_cond, NULL);
+		CE_ASSERT(err == 0, "pthread_cond_init: errno = %d", err);
+		CE_UNUSED(err);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
 		_handle = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
 		_handle = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
 		CE_ASSERT(_handle != NULL, "CreateSemaphore: GetLastError = %d", GetLastError());
 		CE_ASSERT(_handle != NULL, "CreateSemaphore: GetLastError = %d", GetLastError());
@@ -42,9 +42,9 @@ struct Semaphore
 	~Semaphore()
 	~Semaphore()
 	{
 	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-		int result = pthread_cond_destroy(&m_cond);
-		CE_ASSERT(result == 0, "pthread_cond_destroy: errno = %d", result);
-		CE_UNUSED(result);
+		int err = pthread_cond_destroy(&_cond);
+		CE_ASSERT(err == 0, "pthread_cond_destroy: errno = %d", err);
+		CE_UNUSED(err);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
 		BOOL err = CloseHandle(_handle);
 		BOOL err = CloseHandle(_handle);
 		CE_ASSERT(err != 0, "CloseHandle: GetLastError = %d", GetLastError());
 		CE_ASSERT(err != 0, "CloseHandle: GetLastError = %d", GetLastError());
@@ -59,9 +59,9 @@ struct Semaphore
 
 
 		for (uint32_t i = 0; i < count; ++i)
 		for (uint32_t i = 0; i < count; ++i)
 		{
 		{
-			int result = pthread_cond_signal(&m_cond);
-			CE_ASSERT(result == 0, "pthread_cond_signal: errno = %d", result);
-			CE_UNUSED(result);
+			int err = pthread_cond_signal(&_cond);
+			CE_ASSERT(err == 0, "pthread_cond_signal: errno = %d", err);
+			CE_UNUSED(err);
 		}
 		}
 
 
 		_count += count;
 		_count += count;
@@ -79,16 +79,16 @@ struct Semaphore
 
 
 		while (_count <= 0)
 		while (_count <= 0)
 		{
 		{
-			int result = pthread_cond_wait(&m_cond, &(_mutex._mutex));
-			CE_ASSERT(result == 0, "pthread_cond_wait: errno = %d", result);
-			CE_UNUSED(result);
+			int err = pthread_cond_wait(&_cond, &(_mutex._mutex));
+			CE_ASSERT(err == 0, "pthread_cond_wait: errno = %d", err);
+			CE_UNUSED(err);
 		}
 		}
 
 
 		_count--;
 		_count--;
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-		DWORD result = WaitForSingleObject(_handle, INFINITE);
-		CE_ASSERT(result == WAIT_OBJECT_0, "WaitForSingleObject: GetLastError = %d", GetLastError());
-		CE_UNUSED(result);
+		DWORD err = WaitForSingleObject(_handle, INFINITE);
+		CE_ASSERT(err == WAIT_OBJECT_0, "WaitForSingleObject: GetLastError = %d", GetLastError());
+		CE_UNUSED(err);
 #endif
 #endif
 	}
 	}
 
 
@@ -96,7 +96,7 @@ private:
 
 
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
 	Mutex _mutex;
 	Mutex _mutex;
-	pthread_cond_t m_cond;
+	pthread_cond_t _cond;
 	int32_t _count;
 	int32_t _count;
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
 	HANDLE _handle;
 	HANDLE _handle;

+ 5 - 4
src/device.cpp

@@ -13,6 +13,7 @@
 #include "material_manager.h"
 #include "material_manager.h"
 #include "memory.h"
 #include "memory.h"
 #include "os.h"
 #include "os.h"
+#include "resource_loader.h"
 #include "resource_manager.h"
 #include "resource_manager.h"
 #include "resource_package.h"
 #include "resource_package.h"
 #include "types.h"
 #include "types.h"
@@ -58,6 +59,7 @@ Device::Device(DeviceOptions& opts)
 	, _boot_script_id(uint64_t(0))
 	, _boot_script_id(uint64_t(0))
 	, _boot_package(NULL)
 	, _boot_package(NULL)
 	, _lua_environment(NULL)
 	, _lua_environment(NULL)
+	, _resource_loader(NULL)
 	, _resource_manager(NULL)
 	, _resource_manager(NULL)
 	, _input_manager(NULL)
 	, _input_manager(NULL)
 	, _worlds(default_allocator())
 	, _worlds(default_allocator())
@@ -82,9 +84,8 @@ void Device::init()
 	physics_globals::init();
 	physics_globals::init();
 	bgfx::init();
 	bgfx::init();
 
 
-	// Create resource manager
-	CE_LOGD("Creating resource manager...");
-	_resource_manager = CE_NEW(_allocator, ResourceManager)(*_bundle_filesystem);
+	_resource_loader = CE_NEW(_allocator, ResourceLoader)(*_bundle_filesystem);
+	_resource_manager = CE_NEW(_allocator, ResourceManager)(*_resource_loader);
 
 
 	CE_LOGD("Creating material manager...");
 	CE_LOGD("Creating material manager...");
 	material_manager::init();
 	material_manager::init();
@@ -128,8 +129,8 @@ void Device::shutdown()
 	debug_line::shutdown();
 	debug_line::shutdown();
 	material_manager::shutdown();
 	material_manager::shutdown();
 
 
-	CE_LOGD("Releasing resource manager...");
 	CE_DELETE(_allocator, _resource_manager);
 	CE_DELETE(_allocator, _resource_manager);
+	CE_DELETE(_allocator, _resource_loader);
 
 
 	bgfx::shutdown();
 	bgfx::shutdown();
 	physics_globals::shutdown();
 	physics_globals::shutdown();

+ 1 - 0
src/device.h

@@ -139,6 +139,7 @@ private:
 	ResourcePackage* _boot_package;
 	ResourcePackage* _boot_package;
 
 
 	LuaEnvironment* _lua_environment;
 	LuaEnvironment* _lua_environment;
+	ResourceLoader* _resource_loader;
 	ResourceManager* _resource_manager;
 	ResourceManager* _resource_manager;
 	InputManager* _input_manager;
 	InputManager* _input_manager;
 
 

+ 5 - 11
src/resource/resource_loader.cpp

@@ -15,9 +15,8 @@
 namespace crown
 namespace crown
 {
 {
 
 
-ResourceLoader::ResourceLoader(Filesystem& fs, Allocator& resource_heap)
+ResourceLoader::ResourceLoader(Filesystem& fs)
 	: _fs(fs)
 	: _fs(fs)
-	, _resource_heap(resource_heap)
 	, _requests(default_allocator())
 	, _requests(default_allocator())
 	, _loaded(default_allocator())
 	, _loaded(default_allocator())
 	, _exit(false)
 	, _exit(false)
@@ -31,9 +30,10 @@ ResourceLoader::~ResourceLoader()
 	_thread.stop();
 	_thread.stop();
 }
 }
 
 
-void ResourceLoader::load(StringId64 type, StringId64 name)
+void ResourceLoader::add_request(StringId64 type, StringId64 name, Allocator& a)
 {
 {
-	add_request(type, name);
+	ScopedMutex sm(_mutex);
+	queue::push_back(_requests, make_request(type, name, a));
 }
 }
 
 
 void ResourceLoader::flush()
 void ResourceLoader::flush()
@@ -41,12 +41,6 @@ void ResourceLoader::flush()
 	while (num_requests()) {}
 	while (num_requests()) {}
 }
 }
 
 
-void ResourceLoader::add_request(StringId64 type, StringId64 name)
-{
-	ScopedMutex sm(_mutex);
-	queue::push_back(_requests, make_request(type, name));
-}
-
 uint32_t ResourceLoader::num_requests()
 uint32_t ResourceLoader::num_requests()
 {
 {
 	ScopedMutex sm(_mutex);
 	ScopedMutex sm(_mutex);
@@ -97,7 +91,7 @@ int32_t ResourceLoader::run()
 		path::join(CROWN_DATA_DIRECTORY, name, path);
 		path::join(CROWN_DATA_DIRECTORY, name, path);
 
 
 		File* file = _fs.open(path.c_str(), FOM_READ);
 		File* file = _fs.open(path.c_str(), FOM_READ);
-		rd.data = resource_on_load(id.type, *file, _resource_heap);
+		rd.data = resource_on_load(id.type, *file, *id.allocator);
 		_fs.close(file);
 		_fs.close(file);
 
 
 		add_loaded(rd);
 		add_loaded(rd);

+ 12 - 13
src/resource/resource_loader.h

@@ -10,7 +10,6 @@
 #include "thread.h"
 #include "thread.h"
 #include "container_types.h"
 #include "container_types.h"
 #include "mutex.h"
 #include "mutex.h"
-#include "memory_types.h"
 #include "string_id.h"
 #include "string_id.h"
 
 
 namespace crown
 namespace crown
@@ -30,22 +29,20 @@ class ResourceLoader
 {
 {
 public:
 public:
 
 
-	/// Reads the resources data from the given @a fs using
-	/// @a resource_heap to allocate memory for them.
-	ResourceLoader(Filesystem& fs, Allocator& resource_heap);
+	ResourceLoader(Filesystem& fs);
 	~ResourceLoader();
 	~ResourceLoader();
 
 
-	/// Loads the @a resource in a background thread.
-	void load(StringId64 type, StringId64 name);
+	/// Adds a request for loading the resource @a type @a name.
+	void add_request(StringId64 type, StringId64 name, Allocator& a);
 
 
 	/// Blocks until all pending requests have been processed.
 	/// Blocks until all pending requests have been processed.
 	void flush();
 	void flush();
 
 
+	/// Returns all the resources that have been loaded.
 	void get_loaded(Array<ResourceData>& loaded);
 	void get_loaded(Array<ResourceData>& loaded);
 
 
 private:
 private:
 
 
-	void add_request(StringId64 type, StringId64 name);
 	uint32_t num_requests();
 	uint32_t num_requests();
 	void add_loaded(ResourceData data);
 	void add_loaded(ResourceData data);
 
 
@@ -54,8 +51,7 @@ private:
 
 
 	static int32_t thread_proc(void* thiz)
 	static int32_t thread_proc(void* thiz)
 	{
 	{
-		ResourceLoader* rl = (ResourceLoader*)thiz;
-		return rl->run();
+		return ((ResourceLoader*)thiz)->run();
 	}
 	}
 
 
 private:
 private:
@@ -64,17 +60,20 @@ private:
 	{
 	{
 		StringId64 type;
 		StringId64 type;
 		StringId64 name;
 		StringId64 name;
+		Allocator* allocator;
 	};
 	};
 
 
-	ResourceRequest make_request(StringId64 type, StringId64 name)
+	ResourceRequest make_request(StringId64 type, StringId64 name, Allocator& a)
 	{
 	{
-		ResourceRequest request = { type, name };
-		return request;
+		ResourceRequest rr;
+		rr.type = type;
+		rr.name = name;
+		rr.allocator = &a;
+		return rr;
 	}
 	}
 
 
 	Thread _thread;
 	Thread _thread;
 	Filesystem& _fs;
 	Filesystem& _fs;
-	Allocator& _resource_heap;
 
 
 	Queue<ResourceRequest> _requests;
 	Queue<ResourceRequest> _requests;
 	Queue<ResourceData> _loaded;
 	Queue<ResourceData> _loaded;

+ 6 - 5
src/resource/resource_manager.cpp

@@ -4,6 +4,7 @@
  */
  */
 
 
 #include "resource_manager.h"
 #include "resource_manager.h"
+#include "resource_loader.h"
 #include "resource_registry.h"
 #include "resource_registry.h"
 #include "temp_allocator.h"
 #include "temp_allocator.h"
 #include "sort_map.h"
 #include "sort_map.h"
@@ -14,9 +15,9 @@ namespace crown
 
 
 const ResourceManager::ResourceEntry ResourceManager::ResourceEntry::NOT_FOUND = { 0xffffffffu, NULL };
 const ResourceManager::ResourceEntry ResourceManager::ResourceEntry::NOT_FOUND = { 0xffffffffu, NULL };
 
 
-ResourceManager::ResourceManager(Filesystem& fs)
+ResourceManager::ResourceManager(ResourceLoader& rl)
 	: _resource_heap("resource", default_allocator())
 	: _resource_heap("resource", default_allocator())
-	, _loader(fs, _resource_heap)
+	, _loader(&rl)
 	, _rm(default_allocator())
 	, _rm(default_allocator())
 	, _autoload(false)
 	, _autoload(false)
 {
 {
@@ -41,7 +42,7 @@ void ResourceManager::load(StringId64 type, StringId64 name)
 
 
 	if (entry == ResourceEntry::NOT_FOUND)
 	if (entry == ResourceEntry::NOT_FOUND)
 	{
 	{
-		_loader.load(type, name);
+		_loader->add_request(type, name, _resource_heap);
 		return;
 		return;
 	}
 	}
 
 
@@ -111,7 +112,7 @@ void ResourceManager::enable_autoload(bool enable)
 
 
 void ResourceManager::flush()
 void ResourceManager::flush()
 {
 {
-	_loader.flush();
+	_loader->flush();
 	complete_requests();
 	complete_requests();
 }
 }
 
 
@@ -119,7 +120,7 @@ void ResourceManager::complete_requests()
 {
 {
 	TempAllocator1024 ta;
 	TempAllocator1024 ta;
 	Array<ResourceData> loaded(ta);
 	Array<ResourceData> loaded(ta);
-	_loader.get_loaded(loaded);
+	_loader->get_loaded(loaded);
 
 
 	for (uint32_t i = 0; i < array::size(loaded); i++)
 	for (uint32_t i = 0; i < array::size(loaded); i++)
 		complete_request(loaded[i].type, loaded[i].name, loaded[i].data);
 		complete_request(loaded[i].type, loaded[i].name, loaded[i].data);

+ 3 - 3
src/resource/resource_manager.h

@@ -7,8 +7,8 @@
 
 
 #include "types.h"
 #include "types.h"
 #include "container_types.h"
 #include "container_types.h"
+#include "resource_types.h"
 #include "proxy_allocator.h"
 #include "proxy_allocator.h"
-#include "resource_loader.h"
 #include "string_id.h"
 #include "string_id.h"
 
 
 namespace crown
 namespace crown
@@ -24,7 +24,7 @@ class ResourceManager
 public:
 public:
 
 
 	/// The resources will be loaded from @a fs.
 	/// The resources will be loaded from @a fs.
-	ResourceManager(Filesystem& fs);
+	ResourceManager(ResourceLoader& rl);
 	~ResourceManager();
 	~ResourceManager();
 
 
 	/// Loads the resource (@a type, @a name).
 	/// Loads the resource (@a type, @a name).
@@ -92,7 +92,7 @@ private:
 	typedef SortMap<ResourcePair, ResourceEntry> ResourceMap;
 	typedef SortMap<ResourcePair, ResourceEntry> ResourceMap;
 
 
 	ProxyAllocator _resource_heap;
 	ProxyAllocator _resource_heap;
-	ResourceLoader _loader;
+	ResourceLoader* _loader;
 	ResourceMap _rm;
 	ResourceMap _rm;
 	bool _autoload;
 	bool _autoload;
 };
 };

+ 1 - 0
src/resource/resource_types.h

@@ -50,6 +50,7 @@
 namespace crown
 namespace crown
 {
 {
 	class ResourceManager;
 	class ResourceManager;
+	class ResourceLoader;
 	struct ResourcePackage;
 	struct ResourcePackage;
 
 
 	struct FontResource;
 	struct FontResource;

+ 27 - 0
tools/core/Properties/AssemblyInfo.cs

@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle ("core")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("")]
+[assembly: AssemblyCopyright ("Copyright (c) 2012-2015 Daniele Bartolini and individual contributors. License: https://github.com/taylor001/crown/blob/master/LICENSE")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion ("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+

+ 46 - 0
tools/core/core.csproj

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{E591C9C0-C1CF-43F3-92C1-7E9F3B3602B9}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>core</RootNamespace>
+    <AssemblyName>core</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <PlatformTarget>x64</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <PlatformTarget>x64</PlatformTarget>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="json\JSON.cs" />
+    <Compile Include="json\SJSON.cs" />
+    <Compile Include="math\Vector2.cs" />
+    <Compile Include="math\Vector3.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Folder Include="json\" />
+    <Folder Include="math\" />
+  </ItemGroup>
+</Project>

+ 309 - 0
tools/core/json/JSON.cs

@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+/*
+ * Public Domain Niklas Frykholm
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Collections;
+
+namespace Crown
+{
+	/// <summary>
+	/// Provides functions for encoding and decoding files in the JSON format.
+	/// </summary>
+	public class JSON
+	{
+		/// <summary>
+		///  Encodes the hashtable t in the JSON format. The hash table can
+		///  contain, numbers, bools, strings, ArrayLists and Hashtables.
+		/// </summary>
+		public static string Encode(object t)
+		{
+			StringBuilder builder = new StringBuilder();
+			Write(t, builder, 0);
+			return builder.ToString();
+		}
+
+		/// <summary>
+		/// Decodes a JSON bytestream into a hash table with numbers, bools, strings,
+		/// ArrayLists and Hashtables.
+		/// </summary>
+		public static object Decode(byte[] sjson)
+		{
+			int index = 0;
+			return Parse(sjson, ref index);
+		}
+
+		/// <summary>
+		/// Convenience function for loading a file.
+		/// </summary>
+		public static Hashtable Load(string path)
+		{
+			System.IO.FileStream fs = System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read);
+			byte[] bytes = new byte[fs.Length];
+			fs.Read(bytes, 0, bytes.Length);
+			fs.Close();
+			return Decode(bytes) as Hashtable;
+		}
+
+		/// <summary>
+		/// Convenience function for saving a file.
+		/// </summary>
+		public static void Save(Hashtable h, string path)
+		{
+			string s = Encode(h);
+			System.IO.FileStream fs = System.IO.File.Open(path, System.IO.FileMode.Create);
+			byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s);
+			fs.Write(bytes, 0, bytes.Count());
+			fs.Close();
+		}
+
+		static void WriteNewLine(StringBuilder builder, int indentation)
+		{
+			builder.Append('\n');
+			for (int i = 0; i < indentation; ++i)
+				builder.Append('\t');
+		}
+
+		static void Write(object o, StringBuilder builder, int indentation)
+		{
+			if (o == null)
+				builder.Append("null");
+			else if (o is Boolean && (bool)o == false)
+				builder.Append("false");
+			else if (o is Boolean)
+				builder.Append("true");
+			else if (o is int)
+				builder.Append((int)o);
+			else if (o is float)
+				builder.Append((float)o);
+			else if (o is double)
+				builder.Append((double)o);
+			else if (o is string)
+				WriteString((String)o, builder);
+			else if (o is ArrayList)
+				WriteArray((ArrayList)o, builder, indentation);
+			else if (o is Hashtable)
+				WriteObject((Hashtable)o, builder, indentation);
+			else
+				throw new ArgumentException("Unknown object");
+		}
+
+		static void WriteString(String s, StringBuilder builder)
+		{
+			builder.Append('"');
+			for (int i = 0; i < s.Length; ++i)
+			{
+				Char c = s[i];
+				if (c == '"' || c == '\\')
+				{
+					builder.Append('\\');
+					builder.Append(c);
+				}
+				else if (c == '\n')
+				{
+					builder.Append('\\');
+					builder.Append('n');
+				}
+				else
+					builder.Append(c);
+			}
+			builder.Append('"');
+		}
+
+		static void WriteArray(ArrayList a, StringBuilder builder, int indentation)
+		{
+			bool write_comma = false;
+			builder.Append('[');
+			foreach (object item in a)
+			{
+				if (write_comma)
+					builder.Append(',');
+				WriteNewLine(builder, indentation + 1);
+				Write(item, builder, indentation + 1);
+				write_comma = true;
+
+			}
+			WriteNewLine(builder, indentation);
+			builder.Append(']');
+		}
+
+		static void WriteObject(Hashtable t, StringBuilder builder, int indentation)
+		{
+			builder.Append('{');
+			bool write_comma = false;
+			foreach (DictionaryEntry de in t)
+			{
+				if (write_comma)
+					builder.Append(", ");
+				WriteNewLine(builder, indentation);
+				Write(de.Key, builder, indentation);
+				builder.Append(" : ");
+				Write(de.Value, builder, indentation);
+				write_comma = true;
+
+			}
+			WriteNewLine(builder, indentation);
+			builder.Append('}');
+		}
+
+		static bool AtEnd(byte[] json, ref int index)
+		{
+			SkipWhitespace(json, ref index);
+			return (index >= json.Length);
+		}
+
+		static void SkipWhitespace(byte[] json, ref int index)
+		{
+			while (index < json.Length)
+			{
+				byte c = json[index];
+				if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == ',')
+					++index;
+				else
+					break;
+			}
+		}
+
+		static void Consume(byte[] json, ref int index, String consume)
+		{
+			SkipWhitespace(json, ref index);
+			for (int i = 0; i < consume.Length; ++i)
+			{
+				if (json[index] != consume[i])
+					throw new FormatException();
+				++index;
+			}
+		}
+
+		static object Parse(byte[] json, ref int index)
+		{
+			byte c = Next(json, ref index);
+
+			if (c == '{')
+				return ParseObject(json, ref index);
+			else if (c == '[')
+				return ParseArray(json, ref index);
+			else if (c == '"')
+				return ParseString(json, ref index);
+			else if (c == '-' || c >= '0' && c <= '9')
+				return ParseNumber(json, ref index);
+			else if (c == 't')
+			{
+				Consume(json, ref index, "true");
+				return true;
+			}
+			else if (c == 'f')
+			{
+				Consume(json, ref index, "false");
+				return false;
+			}
+			else if (c == 'n')
+			{
+				Consume(json, ref index, "null");
+				return null;
+			}
+			else
+				throw new FormatException();
+		}
+
+		static byte Next(byte[] json, ref int index)
+		{
+			SkipWhitespace(json, ref index);
+			return json[index];
+		}
+
+		static Hashtable ParseObject(byte[] json, ref int index)
+		{
+			Hashtable ht = new Hashtable();
+			Consume(json, ref index, "{");
+			SkipWhitespace(json, ref index);
+
+			while (Next(json, ref index) != '}')
+			{
+				String key = ParseString(json, ref index);
+				Consume(json, ref index, ":");
+				if (key.EndsWith("_binary"))
+					ht[key] = ParseBinary(json, ref index);
+				else
+					ht[key] = Parse(json, ref index);
+			}
+			Consume(json, ref index, "}");
+			return ht;
+		}
+
+		static ArrayList ParseArray(byte[] json, ref int index)
+		{
+			ArrayList a = new ArrayList();
+			Consume(json, ref index, "[");
+			while (Next(json, ref index) != ']')
+			{
+				object value = Parse(json, ref index);
+				a.Add(value);
+			}
+			Consume(json, ref index, "]");
+			return a;
+		}
+
+		static byte[] ParseBinary(byte[] json, ref int index)
+		{
+			List<byte> s = new List<byte>();
+
+			Consume(json, ref index, "\"");
+			while (true)
+			{
+				byte c = json[index];
+				++index;
+				if (c == '"')
+					break;
+				else if (c != '\\')
+					s.Add(c);
+				else
+				{
+					byte q = json[index];
+					++index;
+					if (q == '"' || q == '\\' || q == '/')
+						s.Add(q);
+					else if (q == 'b') s.Add((byte)'\b');
+					else if (q == 'f') s.Add((byte)'\f');
+					else if (q == 'n') s.Add((byte)'\n');
+					else if (q == 'r') s.Add((byte)'\r');
+					else if (q == 't') s.Add((byte)'\t');
+					else if (q == 'u')
+					{
+						throw new FormatException();
+					}
+					else
+					{
+						throw new FormatException();
+					}
+				}
+			}
+			return s.ToArray();
+		}
+
+		static String ParseString(byte[] json, ref int index)
+		{
+			return new UTF8Encoding().GetString(ParseBinary(json, ref index));
+		}
+
+		static Double ParseNumber(byte[] json, ref int index)
+		{
+			int end = index;
+			while ("0123456789+-.eE".IndexOf((char)json[end]) != -1)
+				++end;
+			byte[] num = new byte[end - index];
+			Array.Copy(json, index, num, 0, num.Length);
+			index = end;
+			String numstr = new UTF8Encoding().GetString(num);
+			return Double.Parse(numstr);
+		}
+	}
+}

+ 347 - 0
tools/core/json/SJSON.cs

@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+/*
+ * Public Domain Niklas Frykholm
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Collections;
+
+namespace Crown
+{
+	/// <summary>
+	/// Provides functions for encoding and decoding files in the simplified JSON format.
+	/// </summary>
+	public class SJSON
+	{
+		/// <summary>
+		///  Encodes the Hashtable t in the simplified JSON format. The Hashtable can
+		///  contain, numbers, bools, strings, ArrayLists and Hashtables.
+		/// </summary>
+		public static string Encode(Hashtable t)
+		{
+			StringBuilder builder = new StringBuilder();
+			WriteRootObject(t, builder);
+			return builder.ToString();
+		}
+
+		/// <summary>
+		/// Encodes the object o in the simplified JSON format (not as a root object).
+		/// </summary>
+		/// <returns></returns>
+		public static string EncodeObject(object o)
+		{
+			StringBuilder builder = new StringBuilder();
+			Write(o, builder, 0);
+			return builder.ToString();
+		}
+
+		/// <summary>
+		/// Decodes a SJSON bytestream into a Hashtable with numbers, bools, strings,
+		/// ArrayLists and Hashtables.
+		/// </summary>
+		public static Hashtable Decode(byte[] sjson)
+		{
+			int index = 0;
+			return ParseRootObject(sjson, ref index);
+		}
+
+		/// <summary>
+		/// Convenience function for loading a file.
+		/// </summary>
+		public static Hashtable Load(string path)
+		{
+			System.IO.FileStream fs = System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read);
+			byte[] bytes = new byte[fs.Length];
+			fs.Read(bytes, 0, bytes.Length);
+			fs.Close();
+			return Decode(bytes);
+		}
+
+		/// <summary>
+		/// Convenience function for saving a file.
+		/// </summary>
+		public static void Save(Hashtable h, string path)
+		{
+			string s = Encode(h);
+			System.IO.FileStream fs = System.IO.File.Open(path, System.IO.FileMode.Create);
+			byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s);
+			fs.Write(bytes, 0, bytes.Count());
+			fs.Close();
+		}
+
+		static void WriteRootObject(Hashtable t, StringBuilder builder)
+		{
+		   WriteObjectFields(t, builder, 0);
+		}
+
+		static void WriteObjectFields(Hashtable t, StringBuilder builder, int indentation)
+		{
+			List<string> keys = t.Keys.Cast<string>().ToList();
+			keys.Sort();
+			foreach (string key in keys) {
+				WriteNewLine(builder, indentation);
+				builder.Append(key);
+				builder.Append(" = ");
+				Write(t[key], builder, indentation);
+			}
+		}
+
+		static void WriteNewLine(StringBuilder builder, int indentation)
+		{
+			builder.Append('\n');
+			for (int i = 0; i < indentation; ++i)
+				builder.Append('\t');
+		}
+
+		static void Write(object o, StringBuilder builder, int indentation)
+		{
+			if (o == null)
+				builder.Append("null");
+			else if (o is Boolean && (bool)o == false)
+				builder.Append("false");
+			else if (o is Boolean)
+				builder.Append("true");
+			else if (o is byte)
+				builder.Append((byte)o);
+			else if (o is int)
+				builder.Append((int)o);
+			else if (o is float)
+				builder.Append((float)o);
+			else if (o is double)
+				builder.Append((double)o);
+			else if (o is string)
+				WriteString((String)o, builder);
+			else if (o is ArrayList)
+				WriteArray((ArrayList)o, builder, indentation);
+			else if (o is Hashtable)
+				WriteObject((Hashtable)o, builder, indentation);
+			else
+				throw new ArgumentException("Unknown object");
+		}
+
+		static void WriteString(String s, StringBuilder builder)
+		{
+			builder.Append('"');
+			for (int i=0; i<s.Length; ++i) {
+				Char c = s[i];
+				if (c == '"' || c == '\\')
+					builder.Append('\\');
+				builder.Append(c);
+			}
+			builder.Append('"');
+		}
+
+		static void WriteArray(ArrayList a, StringBuilder builder, int indentation)
+		{
+			builder.Append('[');
+			foreach (object item in a) {
+				WriteNewLine(builder, indentation+1);
+				Write(item, builder, indentation+1);
+			}
+			WriteNewLine(builder, indentation);
+			builder.Append(']');
+		}
+
+		static void WriteObject(Hashtable t, StringBuilder builder, int indentation)
+		{
+			builder.Append('{');
+			WriteObjectFields(t, builder, indentation+1);
+			WriteNewLine(builder, indentation);
+			builder.Append('}');
+		}
+
+		static Hashtable ParseRootObject(byte [] json, ref int index)
+		{
+			Hashtable ht = new Hashtable();
+			while (!AtEnd(json, ref index)) {
+				String key = ParseIdentifier(json, ref index);
+				Consume(json, ref index, "=");
+				object value = ParseValue(json, ref index);
+				ht[key] = value;
+			}
+			return ht;
+		}
+
+		static bool AtEnd(byte [] json, ref int index)
+		{
+			SkipWhitespace(json, ref index);
+			return (index >= json.Length);
+		}
+
+		static void SkipWhitespace(byte [] json, ref int index)
+		{
+			while (index < json.Length) {
+				byte c = json[index];
+				if (c == '/')
+					SkipComment(json, ref index);
+				else if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == ',')
+					++index;
+				else
+					break;
+			}
+		}
+
+		static void SkipComment(byte [] json, ref int index)
+		{
+			byte next = json[index + 1];
+			if (next == '/')
+			{
+				while (index + 1 < json.Length && json[index] != '\n')
+					++index;
+				++index;
+			}
+			else if (next == '*')
+			{
+				while (index + 2 < json.Length && (json[index] != '*' || json[index + 1] != '/'))
+					++index;
+				index += 2;
+			}
+			else
+				throw new FormatException();
+		}
+
+		static String ParseIdentifier(byte [] json, ref int index)
+		{
+			SkipWhitespace(json, ref index);
+
+			if (json[index] == '"')
+				return ParseString(json, ref index);
+
+			List<byte> s = new List<byte>();
+			while (true) {
+				byte c = json[index];
+				if (c == ' ' || c == '\t' || c == '\n' || c == '=')
+					break;
+				s.Add(c);
+				++index;
+			}
+			return new UTF8Encoding().GetString(s.ToArray());
+		}
+
+		static void Consume(byte [] json, ref int index, String consume)
+		{
+			SkipWhitespace(json, ref index);
+			for (int i=0; i<consume.Length; ++i) {
+				if (json[index] != consume[i])
+					throw new FormatException();
+				++index;
+			}
+		}
+
+		static object ParseValue(byte [] json, ref int index)
+		{
+			byte c = Next(json, ref index);
+
+			if (c == '{')
+				return ParseObject(json, ref index);
+			else if (c == '[')
+				return ParseArray(json, ref index);
+			else if (c == '"')
+				return ParseString(json, ref index);
+			else if (c == '-' || c >= '0' && c <= '9')
+				return ParseNumber(json, ref index);
+			else if (c == 't')
+			{
+				Consume(json, ref index, "true");
+				return true;
+			}
+			else if (c == 'f')
+			{
+				Consume(json, ref index, "false");
+				return false;
+			}
+			else if (c == 'n')
+			{
+				Consume(json, ref index, "null");
+				return null;
+			}
+			else
+				throw new FormatException();
+		}
+
+		static byte Next(byte [] json, ref int index)
+		{
+			SkipWhitespace(json, ref index);
+			return json[index];
+		}
+
+		static Hashtable ParseObject(byte [] json, ref int index)
+		{
+			Hashtable ht = new Hashtable();
+			Consume(json, ref index, "{");
+			SkipWhitespace(json, ref index);
+
+			while (Next(json, ref index) != '}') {
+				String key = ParseIdentifier(json, ref index);
+				Consume(json, ref index, "=");
+				object value = ParseValue(json, ref index);
+				ht[key] = value;
+			}
+			Consume(json, ref index, "}");
+			return ht;
+		}
+
+		static ArrayList ParseArray(byte [] json, ref int index)
+		{
+			ArrayList a = new ArrayList();
+			Consume(json, ref index, "[");
+			while (Next(json, ref index) != ']') {
+				object value = ParseValue(json, ref index);
+				a.Add(value);
+			}
+			Consume(json, ref index, "]");
+			return a;
+		}
+
+		static String ParseString(byte[] json, ref int index)
+		{
+			List<byte> s = new List<byte>();
+
+			Consume(json, ref index, "\"");
+			while (true) {
+				byte c = json[index];
+				++index;
+				if (c == '"')
+					break;
+				else if (c != '\\')
+					s.Add(c);
+				else {
+					byte q = json[index];
+					++index;
+					if (q == '"' || q == '\\' || q == '/')
+						s.Add(q);
+					else if (q == 'b') s.Add((byte)'\b');
+					else if (q == 'f') s.Add((byte)'\f');
+					else if (q == 'n') s.Add((byte)'\n');
+					else if (q == 'r') s.Add((byte)'\r');
+					else if (q == 't') s.Add((byte)'\t');
+					else if (q == 'u')  {
+						throw new FormatException();
+					} else {
+						throw new FormatException();
+					}
+				}
+			}
+			return new UTF8Encoding().GetString(s.ToArray());
+		}
+
+		static Double ParseNumber(byte[] json, ref int index)
+		{
+			int end = index;
+			while (end < json.Length && "0123456789+-.eE".IndexOf((char)json[end]) != -1)
+				++end;
+			byte[] num = new byte[end - index];
+			Array.Copy(json, index, num, 0, num.Length);
+			index = end;
+			String numstr = new UTF8Encoding().GetString(num);
+			return Double.Parse(numstr);
+		}
+	}
+}

+ 40 - 0
tools/core/math/Vector2.cs

@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+using System;
+
+namespace Crown
+{
+	public struct Vector2
+	{
+		public Vector2(float x, float y)
+		{
+			this.x = x;
+			this.y = y;
+		}
+
+		public static Vector2 operator+(Vector2 a, Vector2 b)
+		{
+			return new Vector2(a.x + b.x, a.y + b.y);
+		}
+
+		public static Vector2 operator-(Vector2 a, Vector2 b)
+		{
+			return new Vector2(a.x - b.x, a.y - b.y);
+		}
+
+		public static Vector2 operator*(Vector2 a, float k)
+		{
+			return new Vector2(a.x * k, a.y * k);
+		}
+
+		public static Vector2 operator*(float k, Vector2 a)
+		{
+			return a * k;
+		}
+
+		public float x, y;
+	}
+}

+ 41 - 0
tools/core/math/Vector3.cs

@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+using System;
+
+namespace Crown
+{
+	public struct Vector3
+	{
+		public Vector3(float x, float y, float z)
+		{
+			this.x = x;
+			this.y = y;
+			this.z = z;
+		}
+
+		public static Vector3 operator+(Vector3 a, Vector3 b)
+		{
+			return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
+		}
+
+		public static Vector3 operator-(Vector3 a, Vector3 b)
+		{
+			return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
+		}
+
+		public static Vector3 operator*(Vector3 a, float k)
+		{
+			return new Vector3(a.x * k, a.y * k, a.z * k);
+		}
+
+		public static Vector3 operator*(float k, Vector3 a)
+		{
+			return a * k;
+		}
+
+		public float x, y, z;
+	}
+}

+ 166 - 0
tools/tools.sln

@@ -0,0 +1,166 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "core", "core\core.csproj", "{E591C9C0-C1CF-43F3-92C1-7E9F3B3602B9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{E591C9C0-C1CF-43F3-92C1-7E9F3B3602B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{E591C9C0-C1CF-43F3-92C1-7E9F3B3602B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E591C9C0-C1CF-43F3-92C1-7E9F3B3602B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{E591C9C0-C1CF-43F3-92C1-7E9F3B3602B9}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		Policies = $0
+		$0.DotNetNamingPolicy = $1
+		$1.DirectoryNamespaceAssociation = None
+		$1.ResourceNamePolicy = FileFormatDefault
+		$0.TextStylePolicy = $2
+		$2.inheritsSet = null
+		$2.scope = text/x-csharp
+		$0.CSharpFormattingPolicy = $3
+		$3.AfterDelegateDeclarationParameterComma = True
+		$3.inheritsSet = Mono
+		$3.inheritsScope = text/x-csharp
+		$3.scope = text/x-csharp
+		$0.TextStylePolicy = $4
+		$4.FileWidth = 120
+		$4.TabsToSpaces = False
+		$4.inheritsSet = VisualStudio
+		$4.inheritsScope = text/plain
+		$4.scope = text/plain
+		$0.StandardHeader = $5
+		$5.Text = 
+		$5.IncludeInNewFiles = True
+		$0.NameConventionPolicy = $6
+		$6.Rules = $7
+		$7.NamingRule = $8
+		$8.Name = Namespaces
+		$8.AffectedEntity = Namespace
+		$8.VisibilityMask = VisibilityMask
+		$8.NamingStyle = PascalCase
+		$8.IncludeInstanceMembers = True
+		$8.IncludeStaticEntities = True
+		$7.NamingRule = $9
+		$9.Name = Types
+		$9.AffectedEntity = Class, Struct, Enum, Delegate
+		$9.VisibilityMask = Public
+		$9.NamingStyle = PascalCase
+		$9.IncludeInstanceMembers = True
+		$9.IncludeStaticEntities = True
+		$7.NamingRule = $10
+		$10.Name = Interfaces
+		$10.RequiredPrefixes = $11
+		$11.String = I
+		$10.AffectedEntity = Interface
+		$10.VisibilityMask = Public
+		$10.NamingStyle = PascalCase
+		$10.IncludeInstanceMembers = True
+		$10.IncludeStaticEntities = True
+		$7.NamingRule = $12
+		$12.Name = Attributes
+		$12.RequiredSuffixes = $13
+		$13.String = Attribute
+		$12.AffectedEntity = CustomAttributes
+		$12.VisibilityMask = Public
+		$12.NamingStyle = PascalCase
+		$12.IncludeInstanceMembers = True
+		$12.IncludeStaticEntities = True
+		$7.NamingRule = $14
+		$14.Name = Event Arguments
+		$14.RequiredSuffixes = $15
+		$15.String = EventArgs
+		$14.AffectedEntity = CustomEventArgs
+		$14.VisibilityMask = Public
+		$14.NamingStyle = PascalCase
+		$14.IncludeInstanceMembers = True
+		$14.IncludeStaticEntities = True
+		$7.NamingRule = $16
+		$16.Name = Exceptions
+		$16.RequiredSuffixes = $17
+		$17.String = Exception
+		$16.AffectedEntity = CustomExceptions
+		$16.VisibilityMask = VisibilityMask
+		$16.NamingStyle = PascalCase
+		$16.IncludeInstanceMembers = True
+		$16.IncludeStaticEntities = True
+		$7.NamingRule = $18
+		$18.Name = Methods
+		$18.AffectedEntity = Methods
+		$18.VisibilityMask = Protected, Public
+		$18.NamingStyle = PascalCase
+		$18.IncludeInstanceMembers = True
+		$18.IncludeStaticEntities = True
+		$7.NamingRule = $19
+		$19.Name = Static Readonly Fields
+		$19.AffectedEntity = ReadonlyField
+		$19.VisibilityMask = Protected, Public
+		$19.NamingStyle = PascalCase
+		$19.IncludeInstanceMembers = False
+		$19.IncludeStaticEntities = True
+		$7.NamingRule = $20
+		$20.Name = Fields
+		$20.AffectedEntity = Field
+		$20.VisibilityMask = Protected, Public
+		$20.NamingStyle = PascalCase
+		$20.IncludeInstanceMembers = True
+		$20.IncludeStaticEntities = True
+		$7.NamingRule = $21
+		$21.Name = ReadOnly Fields
+		$21.AffectedEntity = ReadonlyField
+		$21.VisibilityMask = Protected, Public
+		$21.NamingStyle = PascalCase
+		$21.IncludeInstanceMembers = True
+		$21.IncludeStaticEntities = False
+		$7.NamingRule = $22
+		$22.Name = Constant Fields
+		$22.AffectedEntity = ConstantField
+		$22.VisibilityMask = Protected, Public
+		$22.NamingStyle = PascalCase
+		$22.IncludeInstanceMembers = True
+		$22.IncludeStaticEntities = True
+		$7.NamingRule = $23
+		$23.Name = Properties
+		$23.AffectedEntity = Property
+		$23.VisibilityMask = Protected, Public
+		$23.NamingStyle = PascalCase
+		$23.IncludeInstanceMembers = True
+		$23.IncludeStaticEntities = True
+		$7.NamingRule = $24
+		$24.Name = Events
+		$24.AffectedEntity = Event
+		$24.VisibilityMask = Protected, Public
+		$24.NamingStyle = PascalCase
+		$24.IncludeInstanceMembers = True
+		$24.IncludeStaticEntities = True
+		$7.NamingRule = $25
+		$25.Name = Enum Members
+		$25.AffectedEntity = EnumMember
+		$25.VisibilityMask = VisibilityMask
+		$25.NamingStyle = PascalCase
+		$25.IncludeInstanceMembers = True
+		$25.IncludeStaticEntities = True
+		$7.NamingRule = $26
+		$26.Name = Parameters
+		$26.AffectedEntity = Parameter
+		$26.VisibilityMask = VisibilityMask
+		$26.NamingStyle = CamelCase
+		$26.IncludeInstanceMembers = True
+		$26.IncludeStaticEntities = True
+		$7.NamingRule = $27
+		$27.Name = Type Parameters
+		$27.RequiredPrefixes = $28
+		$28.String = T
+		$27.AffectedEntity = TypeParameter
+		$27.VisibilityMask = VisibilityMask
+		$27.NamingStyle = PascalCase
+		$27.IncludeInstanceMembers = True
+		$27.IncludeStaticEntities = True
+		$0.VersionControlPolicy = $29
+		$29.inheritsSet = Mono
+	EndGlobalSection
+EndGlobal