Selaa lähdekoodia

Working on C#

Josh Engebretson 10 vuotta sitten
vanhempi
sitoutus
ef60a2402f

+ 28 - 15
Build/AtomicSharp/AtomicEngine.cs

@@ -98,20 +98,21 @@ namespace AtomicEngine
 	{
 		public const string LIBNAME = "/Users/josh/Dev/atomic/AtomicGameEngineSharp-build/Source/AtomicSharp/AtomicSharp";
 	}
-
-	public partial class Node
-	{
-		public T AddComponent<T> () where T:Component, new()
+		
+	public partial class RefCounted
+	{		
+		public RefCounted()
 		{
-			T component = new T ();
-			AddComponent( component, 0, CreateMode.REPLICATED);
-			return component;
+			// if we're not a native type, we need to not be kept alive
+			// as we need to save managed state, native types don't 
+			// save local state
+			if (!NativeCore.GetNativeType (this.GetType ())) {
+
+				handle = GCHandle.Alloc (this);
+			}
+		
 		}
-//		/new MyComponent (), 0, CreateMode.REPLICATED
-	}
 
-	public partial class RefCounted
-	{
 		protected RefCounted (IntPtr native)
 		{
 			nativeInstance = native;
@@ -130,19 +131,31 @@ namespace AtomicEngine
 		}
 
 		[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
-		public static extern IntPtr csb_RefCounted_GetClassID (IntPtr self);	
+		public static extern IntPtr csb_RefCounted_GetClassID (IntPtr self);
+
+		GCHandle handle;
 
 	}
 
+	public partial class AObject
+	{
+	}
+		
 	public partial class Node : Animatable
 	{
 		public T GetComponent<T> (bool recursive  = false) where T:Component
 		{
 			return (T) GetComponent (typeof(T).Name, recursive);
 		}
-		
-	}
-
 
+		public T AddComponent<T> () where T:Component, new()
+		{
+			T component = new T ();
+			AddComponent( component, 0, CreateMode.REPLICATED);
+			return component;
+		}
 
+		
+	}
+		
 }

+ 3 - 3
Build/AtomicSharp/AtomicInterop.cs

@@ -6,11 +6,11 @@ namespace AtomicEngine
 	internal static class AtomicInterop
 	{
 		[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
-		delegate void CSComponentCreateDelegate (string name, IntPtr nativeCSComponent);
+		delegate IntPtr CSComponentCreateDelegate (string name);
 
-		static void CSComponentCreate(string name, IntPtr nativeCSComponent)
+		static IntPtr CSComponentCreate(string name)
 		{
-			ComponentCore.CreateCSComponent (name, nativeCSComponent);
+			return ComponentCore.CreateCSComponent (name);
 		}
 
 		[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]

+ 4 - 4
Build/AtomicSharp/AtomicSharpTest/Program.cs

@@ -3,20 +3,20 @@ using System;
 using AtomicEngine;
 using AtomicPlayer;
 
-class MyComponent : CSComponent
+class Spinner : CSComponent
 {
 	public float Speed = 1.0f;
 
 	override public void Start()
 	{
-		Console.Write ("I Started!");
-
+		
 	}
 
 	override public void Update(float timeStep)
 	{
 		Node.Yaw (timeStep * 75 * Speed, TransformSpace.TS_LOCAL);
 	}
+
 }
 	
 class MyGame
@@ -37,7 +37,7 @@ class MyGame
 		var name = zone.Node.Name;
 
 		var chestNode = scene.GetChild ("Chest", true);
-		var c = chestNode.AddComponent <MyComponent> ();
+		var c = chestNode.AddComponent <Spinner> ();
 		c.Speed = 10.0f;
 
 		zone.SetAmbientColor( new Color(1, 0, 0) );

+ 24 - 16
Build/AtomicSharp/CSComponent.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Runtime.InteropServices;
 
 namespace AtomicEngine
@@ -9,20 +10,8 @@ namespace AtomicEngine
 
 		public CSComponent ()
 		{	
-			// component being created native side
-			if (ComponentCore.CurrentCSComponentNativeInstance != IntPtr.Zero) {
-
-				nativeInstance = ComponentCore.CurrentCSComponentNativeInstance;
-				NativeCore.RegisterNative (nativeInstance, this);
-				ComponentCore.CurrentCSComponentNativeInstance = IntPtr.Zero;
-				
-			} else {
-				
-				nativeInstance = NativeCore.RegisterNative (csb_Atomic_CSComponent_Constructor(), this);	
-				ComponentCore.RegisterCSComponent (this);
-			
-			}
-
+			nativeInstance = NativeCore.RegisterNative (csb_Atomic_CSComponent_Constructor(), this);	
+			ComponentCore.RegisterCSComponent (this);
 		}
 
 		virtual public void Start()
@@ -33,13 +22,32 @@ namespace AtomicEngine
 		virtual public void Update(float timeStep)
 		{
 			
+		}
+			
+		public void SendEvent(string eventType, Dictionary<string, object> eventData = null)
+		{
+
 		}
 
-		public void SetManagedID(uint id)
+		// function would be a C# method, and all classes other than component and uiwidget are sealed
+		// so basically, not having inheritance means no local state for native classes
+		// allowing inheritance, neans need to GCHandle the object as can have local state
+		// and can't regenerate it, comes down to components and UI?
+		public void SubscribeToEvent(AObject sender, string eventType, object function)
 		{
-			csb_Atomic_CSComponent_SetManagedID (nativeInstance, id);
+
 		}
 
+		public void SubscribeToEvent(string eventType, object function)
+		{
+
+		}
+
+		void handleEvent(string eventType, Dictionary<uint, object> eventData)
+		{
+
+		}
+			
 		[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
 		private static extern IntPtr csb_Atomic_CSComponent_Constructor();
 

+ 8 - 19
Build/AtomicSharp/ComponentCore.cs

@@ -19,19 +19,15 @@ namespace AtomicEngine
 	{
 		static Dictionary<String, Type> componentTypes = new Dictionary<String, Type>();
 
-		static Dictionary<uint, GCHandle> liveComponents = new Dictionary<uint, GCHandle>();
-
-		static uint idGen = 1;
+		static Dictionary<uint, CSComponent> liveComponents = new Dictionary<uint, CSComponent>();
 
 		public static IntPtr CurrentCSComponentNativeInstance = default(IntPtr);
 
 		public static void CallComponentMethod(uint componentID, CSComponentMethod method, float value)
 		{
-			GCHandle handle;
-
-			if (liveComponents.TryGetValue (componentID, out handle)) {
+			CSComponent component;
 
-				var component = (CSComponent)handle.Target;
+			if (liveComponents.TryGetValue (componentID, out component)) {
 
 				switch (method) {
 
@@ -50,34 +46,27 @@ namespace AtomicEngine
 
 		public static void RegisterCSComponent(CSComponent component)
 		{
-			// keep the instance from being GC'd as it may be referenced solely in native code 
-			// attached to a node
-			GCHandle handle = GCHandle.Alloc (component);
-
 			// register
-			liveComponents [idGen] = handle;
-			component.SetManagedID (idGen);
-			idGen++;
+			liveComponents [component.RefID] = component;
 		}
 
 		// native create CSComponent
-		public static void CreateCSComponent(string name, IntPtr nativeCSComponent) 
+		public static IntPtr CreateCSComponent(string name) 
 		{
 			Type type;
 
 			if (componentTypes.TryGetValue (name, out type)) {
 
 				// create an instance of the component type
-				CurrentCSComponentNativeInstance = nativeCSComponent;
 				var component = (CSComponent) Activator.CreateInstance(type);
-				CurrentCSComponentNativeInstance = IntPtr.Zero;
-
 				RegisterCSComponent (component);
 
+				return component.nativeInstance;
 
-			
 			}
 
+			return IntPtr.Zero;
+
 		}
 
 		static void RegisterComponentType(Type componentType)

+ 22 - 0
Build/AtomicSharp/NativeCore.cs

@@ -3,6 +3,15 @@ using System.Collections.Generic;
 
 namespace AtomicEngine
 {
+	// Want to be able to inherit from CSComponent, ScriptObject, and the various UI classes
+	// This means that the managed side needs to be kept alive as will have object state
+	// and we might get these back from native code in a variety of ways
+
+	// a inherited instance must have a GCHandle to keep it alive
+	// it must also at some point along constructor chain create the backing native
+
+	// can we detect a native class?  
+
 	static class NativeCore
 	{
 		// given an existing instance classID, construct the managed instance, with downcast support (ask for Component, get StaticModel for example)
@@ -10,6 +19,18 @@ namespace AtomicEngine
 
 		public static Dictionary<IntPtr, WeakReference> nativeLookup = new Dictionary<IntPtr, WeakReference> ();
 
+		private static Dictionary<Type, Type> nativeTypes = new Dictionary<Type, Type> ();
+
+		public static bool GetNativeType (Type type)
+		{
+			return nativeTypes.ContainsKey (type);
+		}
+			
+		public static void RegisterNativeType (Type type)
+		{
+			nativeTypes.Add (type, type);		
+		}
+
 		public static IntPtr RegisterNative (IntPtr native, RefCounted r)
 		{
 			var w = new WeakReference (r);
@@ -67,6 +88,7 @@ namespace AtomicEngine
 			IntPtr classID = RefCounted.csb_RefCounted_GetClassID (native);
 
 			// and store, with downcast support for instance Component -> StaticModel
+			// we never want to hit this path for scripted natives
 			w = new WeakReference (nativeClassIDToManagedConstructor[classID](native));
 			NativeCore.nativeLookup [native] = w;
 

+ 10 - 0
Source/Atomic/Container/RefCounted.cpp

@@ -29,10 +29,17 @@
 namespace Atomic
 {
 
+// ATOMIC BEGIN
+unsigned RefCounted::refIDCounter_ = 1;
+// ATOMIC END
+
 RefCounted::RefCounted() :
     refCount_(new RefCount()),
     jsHeapPtr_(0)
 {
+    refID_ = refIDCounter_++;
+    refLookup_[refID_] = this;
+
     // Hold a weak ref to self to avoid possible double delete of the refcount
     (refCount_->weakRefs_)++;
 }
@@ -63,7 +70,10 @@ void RefCounted::ReleaseRef()
     assert(refCount_->refs_ > 0);
     (refCount_->refs_)--;
     if (!refCount_->refs_)
+    {
+        refLookup_.Erase(refID_);
         delete this;
+    }
 }
 
 int RefCounted::Refs() const

+ 13 - 0
Source/Atomic/Container/RefCounted.h

@@ -22,6 +22,8 @@
 
 #pragma once
 
+#include "HashMap.h"
+
 namespace Atomic
 {
 
@@ -88,9 +90,12 @@ public:
     virtual ClassID GetClassID() const  = 0;
     static ClassID GetClassIDStatic() { static const int typeID = 0; return (ClassID) &typeID; }
 
+    inline unsigned GetRefID() const { return refID_; }
+
     /// JavaScript VM, heap object which can be pushed directly on stack without any lookups
     inline void* JSGetHeapPtr() const { return jsHeapPtr_; }
     inline void  JSSetHeapPtr(void* heapptr) { jsHeapPtr_ = heapptr; }
+
     // ATOMIC END
 
 private:
@@ -102,8 +107,16 @@ private:
     /// Pointer to the reference count structure.
     RefCount* refCount_;
 
+    // ATOMIC BEGIN
+
+    HashMap<unsigned, RefCounted*> refLookup_;
+    unsigned refID_;
+    static unsigned refIDCounter_;
+
     void* jsHeapPtr_;
 
+    // ATOMIC END
+
 
 };
 

+ 1 - 2
Source/Atomic/Core/Context.cpp

@@ -54,8 +54,7 @@ void RemoveNamedAttribute(HashMap<StringHash, Vector<AttributeInfo> >& attribute
 
 Context::Context() :
     eventHandler_(0),
-    editorContext_(false),
-    globalEventListener_(0)
+    editorContext_(false)
 {
 #ifdef ANDROID
     // Always reset the random seed on Android, as the Urho3D library might not be unloaded between runs

+ 13 - 4
Source/Atomic/Core/Context.h

@@ -159,7 +159,8 @@ public:
     // ATOMIC BEGIN
 
     // hook for listening into events
-    void SetGlobalEventListener(GlobalEventListener* listener) { globalEventListener_ = listener; }
+    void AddGlobalEventListener(GlobalEventListener* listener) { globalEventListeners_.Push(listener); }
+    void RemoveGlobalEventListener(GlobalEventListener* listener) { globalEventListeners_.Erase(globalEventListeners_.Find(listener)); }
 
     /// Get whether an Editor Context
     void SetEditorContext(bool editor) { editorContext_ = editor; }
@@ -181,10 +182,18 @@ private:
     void SetEventHandler(EventHandler* handler) { eventHandler_ = handler; }
 
     /// Begin event send.
-    void BeginSendEvent(Object* sender, StringHash eventType, VariantMap& eventData) { if (globalEventListener_) globalEventListener_->BeginSendEvent(this, sender, eventType, eventData); eventSenders_.Push(sender); }
+    void BeginSendEvent(Object* sender, StringHash eventType, VariantMap& eventData) {
+        for (unsigned i = 0; i < globalEventListeners_.Size(); i++)
+            globalEventListeners_[i]->BeginSendEvent(this, sender, eventType, eventData);
+        eventSenders_.Push(sender);
+    }
 
     /// End event send. Clean up event receivers removed in the meanwhile.
-    void EndSendEvent(Object* sender, StringHash eventType, VariantMap& eventData) { if (globalEventListener_) globalEventListener_->EndSendEvent(this, sender, eventType, eventData); eventSenders_.Pop(); }
+    void EndSendEvent(Object* sender, StringHash eventType, VariantMap& eventData) {
+        for (unsigned i = 0; i < globalEventListeners_.Size(); i++)
+            globalEventListeners_[i]->EndSendEvent(this, sender, eventType, eventData);
+        eventSenders_.Pop();
+    }
 
     /// Object factories.
     HashMap<StringHash, SharedPtr<ObjectFactory> > factories_;
@@ -208,7 +217,7 @@ private:
     HashMap<String, Vector<StringHash> > objectCategories_;
 
     // ATOMIC BEGIN
-    GlobalEventListener* globalEventListener_;
+    PODVector<GlobalEventListener*> globalEventListeners_;
     bool editorContext_;
     // ATOMIC END
 };

+ 4 - 3
Source/AtomicJS/Javascript/JSVM.cpp

@@ -57,14 +57,15 @@ JSVM::JSVM(Context* context) :
 
     metrics_ = new JSMetrics(context, this);
 
-    context_->RegisterSubsystem(new JSEventDispatcher(context_));
-    context_->SetGlobalEventListener(context_->GetSubsystem<JSEventDispatcher>());
+    SharedPtr<JSEventDispatcher> dispatcher(new JSEventDispatcher(context_));
+    context_->RegisterSubsystem(dispatcher);
+    context_->AddGlobalEventListener(dispatcher);
 
 }
 
 JSVM::~JSVM()
 {
-    context_->SetGlobalEventListener(0);
+    context_->RemoveGlobalEventListener(context_->GetSubsystem<JSEventDispatcher>());
     context_->RemoveSubsystem(JSEventDispatcher::GetTypeStatic());
 
     duk_destroy_heap(ctx_);

+ 3 - 12
Source/AtomicSharp/AtomicSharpAPI.cpp

@@ -26,17 +26,17 @@ using namespace Atomic;
 extern "C"
 {
 
-typedef void (*CSComponentCreatePtr)(const char* csComponentTypeName, CSComponent* instance);
+typedef CSComponent* (*CSComponentCreatePtr)(const char* csComponentTypeName);
 CSComponentCreatePtr _CSComponentCreate = 0;
 ATOMIC_EXPORT_API void csb_AtomicEngine_AtomicInterop_Set_CSComponentCreate(CSComponentCreatePtr method)
 {
     _CSComponentCreate = method;
 }
 
-void CSComponentCreate(String name, CSComponent* instance)
+CSComponent* CSComponentCreate(String name)
 {
     assert(_CSComponentCreate);
-    _CSComponentCreate(name.CString(), instance);
+    return _CSComponentCreate(name.CString());
 }
 
 
@@ -60,15 +60,6 @@ ATOMIC_EXPORT_API RefCounted* csb_Atomic_CSComponent_Constructor()
    return new CSComponent(AtomicSharp::GetContext());
 }
 
-ATOMIC_EXPORT_API void csb_Atomic_CSComponent_SetManagedID(CSComponent* self, unsigned id)
-{
-   if (!self)
-       return;
-
-    self->SetManagedID(id);
-}
-
-
 ATOMIC_EXPORT_API ClassID csb_RefCounted_GetClassID(RefCounted* refCounted)
 {
     if (!refCounted)

+ 1 - 1
Source/AtomicSharp/AtomicSharpAPI.h

@@ -21,7 +21,7 @@ namespace Atomic
 extern "C"
 {
 
-void CSComponentCreate(String name, CSComponent* instance);
+CSComponent* CSComponentCreate(String name);
 
 void CSComponentCallMethod(unsigned id, CSComponentMethod methodID, float value = 0.0f);
 

+ 4 - 9
Source/AtomicSharp/CSComponent.cpp

@@ -87,11 +87,7 @@ public:
 
         if (managedClass.Length())
         {
-            CSComponent* csc = new CSComponent(context_);
-            CSComponentCreate(managedClass, csc);
-            assert(csc->managedID_);
-            ptr = csc;
-
+            ptr = CSComponentCreate(managedClass);
         }
 
         if (ptr.Null())
@@ -112,8 +108,7 @@ CSComponent::CSComponent(Context* context) :
     destroyed_(false),
     scriptClassInstance_(false),
     delayedStartCalled_(false),
-    loading_(false),
-    managedID_(0)
+    loading_(false)
 {
 
 }
@@ -149,10 +144,10 @@ void CSComponent::ApplyAttributes()
 
 void CSComponent::CallScriptMethod(CSComponentMethod method, float value)
 {
-    if (!managedID_ || destroyed_ || !node_ || !node_->GetScene())
+    if (destroyed_ || !node_ || !node_->GetScene())
         return;
 
-    CSComponentCallMethod(managedID_, method, value);
+    CSComponentCallMethod(GetRefID(), method, value);
 
 }
 

+ 0 - 3
Source/AtomicSharp/CSComponent.h

@@ -79,7 +79,6 @@ public:
     bool IsDelayedStartCalled() const { return delayedStartCalled_; }
 
     void SetDestroyed() { destroyed_ = true; }
-    void SetManagedID(unsigned id) { managedID_ = id; }
 
 protected:
     /// Handle scene node being assigned at creation.
@@ -133,8 +132,6 @@ private:
 
     bool loading_;
 
-    unsigned managedID_;
-
 };
 
 }

+ 87 - 0
Source/AtomicSharp/CSEventHelper.cpp

@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <Atomic/UI/UIEvents.h>
+#include "CSEventHelper.h"
+
+namespace Atomic
+{
+
+
+CSEventDispatcher::CSEventDispatcher(Context* context) :
+    Object(context)
+{
+
+}
+
+CSEventDispatcher::~CSEventDispatcher()
+{
+}
+
+void CSEventDispatcher::BeginSendEvent(Context* context, Object* sender, StringHash eventType, VariantMap& eventData)
+{
+}
+
+void CSEventDispatcher::EndSendEvent(Context* context, Object* sender, StringHash eventType, VariantMap& eventData)
+{
+    if (!csEvents_.Contains(eventType))
+        return;
+
+}
+
+CSEventHelper::CSEventHelper(Context* context, Object* object) :
+    Object(context),
+    object_(object)
+
+{
+
+}
+
+CSEventHelper::~CSEventHelper()
+{
+
+}
+
+void CSEventHelper::AddEventHandler(StringHash eventType)
+{
+    GetSubsystem<CSEventDispatcher>()->RegisterCSEvent(eventType);
+
+    // subscribe using object, so unsubscribing from object and not the event helper works
+    object_->SubscribeToEvent(eventType, HANDLER(CSEventHelper, HandleEvent));
+}
+
+void CSEventHelper::AddEventHandler(Object* sender, StringHash eventType)
+{
+    GetSubsystem<CSEventDispatcher>()->RegisterCSEvent(eventType);
+
+    // subscribe using object, so unsubscribing from object and not the event helper works
+    object_->SubscribeToEvent(sender, eventType, HANDLER(CSEventHelper, HandleEvent));
+}
+
+void CSEventHelper::HandleEvent(StringHash eventType, VariantMap& eventData)
+{
+    if (object_.Null())
+        return;
+}
+
+
+}

+ 74 - 0
Source/AtomicSharp/CSEventHelper.h

@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+#include <Atomic/Core/Context.h>
+
+namespace Atomic
+{
+
+class ATOMIC_API CSEventDispatcher : public Object, public GlobalEventListener
+{
+    OBJECT(CSEventDispatcher);
+
+public:
+    /// Construct.
+    CSEventDispatcher(Context* context);
+    /// Destruct.
+    virtual ~CSEventDispatcher();
+
+    void RegisterCSEvent(StringHash hash) { csEvents_[hash] = true; }
+
+private:
+
+    void BeginSendEvent(Context* context, Object* sender, StringHash eventType, VariantMap& eventData);
+    void EndSendEvent(Context* context, Object* sender, StringHash eventType, VariantMap& eventData);
+
+    HashMap<StringHash, bool> csEvents_;
+
+};
+
+class ATOMIC_API CSEventHelper : public Object
+{
+    OBJECT(CSEventHelper);
+
+public:
+    /// Construct.
+    CSEventHelper(Context* context, Object* object);
+    /// Destruct.
+    virtual ~CSEventHelper();
+
+    void AddEventHandler(StringHash eventType);
+    void AddEventHandler(Object* sender, StringHash eventType);
+
+private:
+
+    void HandleEvent(StringHash eventType, VariantMap& eventData);
+
+    WeakPtr<Object> object_;
+
+};
+
+
+}

+ 0 - 1
Source/ToolCore/JSBind/CSharp/CSClassWriter.cpp

@@ -64,7 +64,6 @@ void CSClassWriter::GenerateNativeSource(String& sourceOut)
     sourceOut += source;
 }
 
-
 void CSClassWriter::WriteManagedProperties(String& sourceOut)
 {
     String source;

+ 12 - 8
Source/ToolCore/JSBind/CSharp/CSFunctionWriter.cpp

@@ -465,17 +465,17 @@ void CSFunctionWriter::WriteManagedConstructor(String& source)
     JSBClass* klass = function_->GetClass();
     JSBPackage* package = klass->GetPackage();
 
+    if (klass->GetName() == "RefCounted")
+        return;
+
     // wrapping constructor
 
     String line;
 
-    if (klass->GetName() != "RefCounted")
-    {
-        line = ToString("public %s (IntPtr native) : base (native)\n", klass->GetName().CString());
-        source += IndentLine(line);
-        source += IndentLine("{\n");
-        source += IndentLine("}\n\n");
-    }
+    line = ToString("public %s (IntPtr native) : base (native)\n", klass->GetName().CString());
+    source += IndentLine(line);
+    source += IndentLine("{\n");
+    source += IndentLine("}\n\n");
 
     String sig;
     GenManagedFunctionParameters(sig);
@@ -488,7 +488,11 @@ void CSFunctionWriter::WriteManagedConstructor(String& source)
 
     Indent();
 
-    source += IndentLine(ToString("if (typeof(%s) == this.GetType())\n", klass->GetName().CString()));
+    line = ToString("if (typeof(%s) == this.GetType()", klass->GetName().CString());
+    line += ToString(" || (this.GetType().BaseType == typeof(%s) && !NativeCore.GetNativeType(this.GetType())))\n", klass->GetName().CString());
+
+    source += IndentLine(line);
+
     source += IndentLine("{\n");
 
     Indent();

+ 3 - 0
Source/ToolCore/JSBind/CSharp/CSModuleWriter.cpp

@@ -316,6 +316,9 @@ void CSModuleWriter::GenerateManagedModuleClass(String& sourceOut)
         if (klass->IsNumberArray() || klass->IsAbstract())
             continue;
 
+        line = ToString("NativeCore.RegisterNativeType(typeof(%s));\n", klass->GetName().CString());
+
+        source += IndentLine(line);
 
         line = ToString("NativeCore.nativeClassIDToManagedConstructor [ %s.csb_%s_%s_GetClassIDStatic ()] = (IntPtr x) => {\n",
                         klass->GetName().CString(), package->GetName().CString(), klass->GetName().CString());