Browse Source

Working on C# components

Josh Engebretson 10 years ago
parent
commit
556216bc05

+ 0 - 139
Build/AtomicNET/AtomicNETEngine/AtomicNET.cs

@@ -80,145 +80,6 @@ public partial class RefCounted
 
 }
 
-static class NativeCore
-{
-  [DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
-  private static extern void csb_AtomicEngine_ReleaseRef (IntPtr refCounted);
-
-  // given an existing instance classID, construct the managed instance, with downcast support (ask for Component, get StaticModel for example)
-  public static Dictionary<IntPtr, Func<IntPtr, RefCounted>> nativeClassIDToManagedConstructor = new Dictionary<IntPtr, Func<IntPtr, RefCounted>>();
-
-  // weak references here, hold a ref native side
-  public static Dictionary<IntPtr, WeakReference> nativeLookup = new Dictionary<IntPtr, WeakReference> ();
-
-  // native engine types, instances of these types can be trivially recreated managed side
-  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 void ReleaseExpiredNativeReferences()
-  {
-    List<IntPtr> released = null;
-
-    foreach(KeyValuePair<IntPtr, WeakReference> entry in nativeLookup)
-    {
-
-      if (entry.Value.Target == null || !entry.Value.IsAlive)
-      {
-        if (released == null)
-          released = new List<IntPtr> ();
-
-        released.Add (entry.Key);
-      }
-
-    }
-
-    if (released == null)
-      return;
-
-    foreach (IntPtr native in released) {
-      nativeLookup.Remove (native);
-      csb_AtomicEngine_ReleaseRef(native);
-      //Console.WriteLine("Released: " + test);
-    }
-
-  }
-
-  static IntPtr test = IntPtr.Zero;
-
-  // called by native code
-  public static void NETUpdate (float timeStep)
-  {
-
-    GC.Collect();
-    GC.WaitForPendingFinalizers();
-    GC.Collect();
-    ReleaseExpiredNativeReferences();
-
-    ComponentCore.Update(timeStep);
-
-  }
-
-  // called by native code for every refcounted deleted
-  public static void RefCountedDeleted (IntPtr native)
-  {
-    // native side deleted, immediate remove, if we have a script reference still this is an error
-
-    WeakReference w;
-
-    if (nativeLookup.TryGetValue (native, out w)) {
-
-        if ( w != null && w.IsAlive) {
-          throw new System.InvalidOperationException("Native Refcounted was deleted with live managed instance");
-        }
-    }
-
-    nativeLookup.Remove(native);
-  }
-
-  // register a newly created native
-  public static IntPtr RegisterNative (IntPtr native, RefCounted r)
-  {
-    r.nativeInstance = native;
-
-    var w = new WeakReference (r);
-    NativeCore.nativeLookup [native] = w;
-    // keep native side alive
-    r.AddRef();
-
-    return native;
-  }
-
-  // wraps an existing native instance, with downcast support
-  public static T WrapNative<T> (IntPtr native) where T:RefCounted
-  {
-    if (native == IntPtr.Zero)
-      return null;
-
-    WeakReference w;
-
-    // first see if we're already available
-    if (nativeLookup.TryGetValue (native, out w)) {
-
-      if (w.IsAlive) {
-
-        // we're alive!
-        return (T)w.Target;
-
-      } else {
-
-        // we were seen before, but have since been GC'd, remove!
-        nativeLookup.Remove (native);
-        csb_AtomicEngine_ReleaseRef(native);
-      }
-    }
-
-    IntPtr classID = RefCounted.csb_Atomic_RefCounted_GetClassID (native);
-
-    // and store, with downcast support for instance Component -> StaticModel
-    // we never want to hit this path for script inherited natives
-
-    RefCounted r = nativeClassIDToManagedConstructor[classID](native);
-    w = new WeakReference (r);
-    NativeCore.nativeLookup [native] = w;
-
-    // store a ref, so native side will not be released while we still have a reference in managed code
-    r.AddRef();
-
-    return (T) r;
-
-  }
-
-}
-
 public class InspectorAttribute : Attribute
 {
   public InspectorAttribute(string DefaultValue = "")

+ 103 - 0
Build/AtomicNET/AtomicNETEngine/ComponentCore.cs

@@ -3,6 +3,7 @@ using System.Reflection;
 using System.Collections.Generic;
 using System.Runtime.Loader;
 using System.Runtime.InteropServices;
+using System.Linq;
 
 namespace AtomicEngine
 {
@@ -11,27 +12,118 @@ namespace AtomicEngine
 public partial class CSComponent : ScriptComponent
 {
 
+  public void StartInternal()
+  {
+    ApplyFieldValues();
+    Start();
+  }
+
+  public virtual void Start()
+  {
+
+  }
+
+
   public virtual void Update(float timeStep)
   {
 
   }
 
+
+
 }
 
 public static class ComponentCore
 {
 
+  static List<CSComponent> startQueue = new List<CSComponent>();
+
   // holds a reference
   static Dictionary<IntPtr, CSComponent> liveComponents = new Dictionary<IntPtr, CSComponent>();
 
   public static void Update (float timeStep)
   {
+
+      List<CSComponent> _startQueue = new List<CSComponent>(startQueue);
+      startQueue.Clear();
+
+      foreach (var c in _startQueue)
+      {
+        c.StartInternal();
+      }
+
       foreach (var c in liveComponents.Values)
       {
             c.Update(timeStep);
       }
   }
 
+  // This will need to be optimized
+  public static void CSComponentApplyFields(IntPtr componentPtr, IntPtr fieldMapPtr)
+  {
+    NETVariantMap fieldMap = NativeCore.WrapNative<NETVariantMap>(fieldMapPtr);;
+    CSComponent component = NativeCore.WrapNative<CSComponent>(componentPtr);;
+
+    if (fieldMap == null || component == null)
+        return;
+
+    FieldInfo[] fields = componentClassFields[component.GetType()];
+
+    foreach (var field in fields)
+    {
+        if (fieldMap.Contains(field.Name))
+        {
+          //Console.WriteLine("Applying: {0} {1}", field.Name, field.FieldType.Name);
+
+          var fieldType = field.FieldType;
+
+          if (fieldType.IsEnum)
+          {
+              field.SetValue(component, fieldMap.GetInt(field.Name));
+              continue;
+          }
+
+          switch (Type.GetTypeCode(fieldType))
+          {
+            case TypeCode.Boolean:
+                field.SetValue(component, fieldMap.GetBool(field.Name));
+                break;
+
+              case TypeCode.Int32:
+                  field.SetValue(component, fieldMap.GetInt(field.Name));
+                  break;
+
+              case TypeCode.Single:
+                  field.SetValue(component, fieldMap.GetFloat(field.Name));
+                  break;
+
+              case TypeCode.String:
+                  field.SetValue(component, fieldMap.GetString(field.Name));
+                  break;
+
+              default:
+
+                  if (fieldType == typeof(Vector3))
+                  {
+                    field.SetValue(component, fieldMap.GetVector3(field.Name));
+                  }
+                  else if (fieldType == typeof(Quaternion))
+                  {
+                    field.SetValue(component, fieldMap.GetQuaternion(field.Name));
+                  }
+                  else if (fieldType.IsSubclassOf(typeof(RefCounted)))
+                  {
+                      field.SetValue(component, fieldMap.GetPtr(field.Name));
+                  }
+
+                  break;
+          }
+        }
+    }
+  }
+
+  static Dictionary<Type, FieldInfo[] > componentClassFields = new Dictionary<Type, FieldInfo[]>();
+
   public static IntPtr CSComponentCreate(string assemblyName, string classTypeName)
   {
 
@@ -43,6 +135,17 @@ public static class ComponentCore
 
     var component = (CSComponent) Activator.CreateInstance(type);
 
+    if (!componentClassFields.ContainsKey(type))
+    {
+      var fields = type.GetFields()
+          .Where(field => field.IsDefined(typeof(InspectorAttribute), true));
+
+      componentClassFields[type] = fields.ToArray<FieldInfo>();
+
+    }
+
+    startQueue.Add(component);
+
     liveComponents[component.nativeInstance] = component;
 
     return component.nativeInstance;

+ 147 - 0
Build/AtomicNET/AtomicNETEngine/NativeCore.cs

@@ -0,0 +1,147 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+namespace AtomicEngine
+{
+
+  static class NativeCore
+  {
+    [DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+    private static extern void csb_AtomicEngine_ReleaseRef (IntPtr refCounted);
+
+    // given an existing instance classID, construct the managed instance, with downcast support (ask for Component, get StaticModel for example)
+    public static Dictionary<IntPtr, Func<IntPtr, RefCounted>> nativeClassIDToManagedConstructor = new Dictionary<IntPtr, Func<IntPtr, RefCounted>>();
+
+    // weak references here, hold a ref native side
+    public static Dictionary<IntPtr, WeakReference> nativeLookup = new Dictionary<IntPtr, WeakReference> ();
+
+    // native engine types, instances of these types can be trivially recreated managed side
+    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 void ReleaseExpiredNativeReferences()
+    {
+      List<IntPtr> released = null;
+
+      foreach(KeyValuePair<IntPtr, WeakReference> entry in nativeLookup)
+      {
+
+        if (entry.Value.Target == null || !entry.Value.IsAlive)
+        {
+          if (released == null)
+            released = new List<IntPtr> ();
+
+          released.Add (entry.Key);
+        }
+
+      }
+
+      if (released == null)
+        return;
+
+      foreach (IntPtr native in released) {
+        nativeLookup.Remove (native);
+        csb_AtomicEngine_ReleaseRef(native);
+        //Console.WriteLine("Released: " + test);
+      }
+
+    }
+
+    static IntPtr test = IntPtr.Zero;
+
+    // called by native code
+    public static void NETUpdate (float timeStep)
+    {
+
+      GC.Collect();
+      GC.WaitForPendingFinalizers();
+      GC.Collect();
+      ReleaseExpiredNativeReferences();
+
+      ComponentCore.Update(timeStep);
+
+    }
+
+    // called by native code for every refcounted deleted
+    public static void RefCountedDeleted (IntPtr native)
+    {
+      // native side deleted, immediate remove, if we have a script reference still this is an error
+
+      WeakReference w;
+
+      if (nativeLookup.TryGetValue (native, out w)) {
+
+          if ( w != null && w.IsAlive) {
+            throw new System.InvalidOperationException("Native Refcounted was deleted with live managed instance");
+          }
+      }
+
+      nativeLookup.Remove(native);
+    }
+
+    // register a newly created native
+    public static IntPtr RegisterNative (IntPtr native, RefCounted r)
+    {
+      r.nativeInstance = native;
+
+      var w = new WeakReference (r);
+      NativeCore.nativeLookup [native] = w;
+      // keep native side alive
+      r.AddRef();
+
+      return native;
+    }
+
+    // wraps an existing native instance, with downcast support
+    public static T WrapNative<T> (IntPtr native) where T:RefCounted
+    {
+      if (native == IntPtr.Zero)
+        return null;
+
+      WeakReference w;
+
+      // first see if we're already available
+      if (nativeLookup.TryGetValue (native, out w)) {
+
+        if (w.IsAlive) {
+
+          // we're alive!
+          return (T)w.Target;
+
+        } else {
+
+          // we were seen before, but have since been GC'd, remove!
+          nativeLookup.Remove (native);
+          csb_AtomicEngine_ReleaseRef(native);
+        }
+      }
+
+      IntPtr classID = RefCounted.csb_Atomic_RefCounted_GetClassID (native);
+
+      // and store, with downcast support for instance Component -> StaticModel
+      // we never want to hit this path for script inherited natives
+
+      RefCounted r = nativeClassIDToManagedConstructor[classID](native);
+      w = new WeakReference (r);
+      NativeCore.nativeLookup [native] = w;
+
+      // store a ref, so native side will not be released while we still have a reference in managed code
+      r.AddRef();
+
+      return (T) r;
+
+    }
+
+  }
+
+}

+ 1 - 0
Build/AtomicNET/build.sh

@@ -6,6 +6,7 @@ mcs /out:/Users/josh/Desktop/OSX.x64.Debug/AtomicNETBootstrap.dll /nostdlib /noc
 
 mcs /out:/Users/josh/Desktop/AtomicNETEngine.dll /nostdlib /noconfig /t:library /w:0 /lib:/Users/josh/Desktop/OSX.x64.Debug \
 /r:System.Console.dll /r:System.Runtime.dll /r:System.IO.dll /r:System.IO.FileSystem.dll /r:mscorlib.dll \
+/r:System.Linq.dll \
 /Users/josh/Dev/atomic/AtomicGameEngine/Build/Source/Generated/MACOSX/CSharp/Packages/Atomic/Managed/*.cs \
 /Users/josh/Dev/atomic/AtomicGameEngine/Build/Source/Generated/MACOSX/CSharp/Packages/AtomicNET/Managed/*.cs \
 /Users/josh/Dev/atomic/AtomicGameEngine/Build/Source/Generated/MACOSX/CSharp/Packages/AtomicPlayer/Managed/*.cs \

+ 1 - 1
Script/Packages/AtomicNET/AtomicNET.json

@@ -1,6 +1,6 @@
 {
 	"name" : "AtomicNET",
 	"sources" : ["Source/AtomicNET/NETCore"],
-	"classes" : ["NETCore", "NETManaged", "NETAssemblyFile", "CSScriptObject", "CSComponent"]
+	"classes" : ["NETCore", "NETManaged", "NETAssemblyFile", "NETVariantMap", "CSScriptObject", "CSComponent"]
 
 }

+ 1 - 1
Source/Atomic/Script/ScriptComponentFile.cpp

@@ -25,7 +25,7 @@ void ScriptComponentFile::RegisterObject(Context* context)
 
 void ScriptComponentFile::AddEnum(const String& enumName, const EnumInfo& enumInfo, const String& classname)
 {
-    EnumMap enums = classEnums_[classname];
+    EnumMap& enums = classEnums_[classname];
     Vector<EnumInfo>& enumValues = enums[enumName];
     enumValues.Push(enumInfo);
 }

+ 8 - 8
Source/AtomicJS/Javascript/JSSceneSerializable.cpp

@@ -211,15 +211,15 @@ static int Serializable_GetAttribute(duk_context* ctx)
         {
             const String& componentClassName = jsc->GetComponentClassName();
 
-            const HashMap<String, VariantType>& fields = file->GetFields(componentClassName);
+            const FieldMap& fields = file->GetFields(componentClassName);
 
             if (fields.Contains(name))
             {
-                VariantMap& values = jsc->GetFieldValues();
+                const VariantMap& values = jsc->GetFieldValues();
 
-                if (values.Contains(name))
+                if (Variant* vptr = values[name])
                 {
-                    js_push_variant(ctx,  values[name]);
+                    js_push_variant(ctx,  *vptr);
                     return 1;
                 }
                 else
@@ -257,8 +257,8 @@ static const String& GetResourceRefClassName(Context* context, const ResourceRef
 }
 
 static void GetDynamicAttributes(duk_context* ctx, unsigned& count, const VariantMap& defaultFieldValues,
-                                 const HashMap<String, VariantType>& fields,
-                                 const HashMap<String, Vector<EnumInfo>>& enums)
+                                 const FieldMap& fields,
+                                 const EnumMap& enums)
 {
     if (fields.Size())
     {
@@ -423,8 +423,8 @@ static int Serializable_GetAttributes(duk_context* ctx)
 
             const String& className = jsc->GetComponentClassName();
             const VariantMap& defaultFieldValues = file->GetDefaultFieldValues(className);
-            const HashMap<String, VariantType>& fields =  file->GetFields(className);
-            const HashMap<String, Vector<EnumInfo>>& enums = file->GetEnums(className);
+            const FieldMap& fields =  file->GetFields(className);
+            const EnumMap& enums = file->GetEnums(className);
 
             GetDynamicAttributes(ctx, count, defaultFieldValues, fields, enums);
         }

+ 11 - 194
Source/AtomicNET/NETCore/CSComponent.cpp

@@ -33,8 +33,10 @@
 #include <Atomic/Scene/Scene.h>
 #include <Atomic/Scene/SceneEvents.h>
 
+#include "NETVariant.h"
+#include "NETManaged.h"
 #include "CSComponent.h"
-//#include "AtomicSharpAPI.h"
+
 
 namespace Atomic
 {
@@ -120,15 +122,7 @@ public:
 
 
 CSComponent::CSComponent(Context* context) :
-    ScriptComponent(context),
-    updateEventMask_(USE_UPDATE | USE_POSTUPDATE | USE_FIXEDUPDATE | USE_FIXEDPOSTUPDATE),
-    currentEventMask_(0),
-    instanceInitialized_(false),
-    started_(false),
-    destroyed_(false),
-    scriptClassInstance_(false),
-    delayedStartCalled_(false),
-    loading_(false)
+    ScriptComponent(context)
 {
 
 }
@@ -153,69 +147,24 @@ void CSComponent::RegisterObject(Context* context)
 
 void CSComponent::OnSetEnabled()
 {
-    UpdateEventSubscription();
-}
-
-void CSComponent::SetUpdateEventMask(unsigned char mask)
-{
-    if (updateEventMask_ != mask)
-    {
-        updateEventMask_ = mask;
-        UpdateEventSubscription();
-    }
 }
 
 void CSComponent::ApplyAttributes()
 {
 }
 
-void CSComponent::CallScriptMethod(CSComponentMethod method, float value)
+void CSComponent::ApplyFieldValues()
 {
-    if (destroyed_ || !node_ || !node_->GetScene())
+    if (!fieldValues_.Size())
         return;
 
-    // Change to callback
-    //CSComponentCallMethod(GetRefID(), method, value);
-
-}
-
-void CSComponent::Start()
-{
-    CallScriptMethod(CSComponentMethod_Start);
-}
-
-void CSComponent::DelayedStart()
-{
-    CallScriptMethod(CSComponentMethod_DelayedStart);
-}
-
-void CSComponent::Update(float timeStep)
-{
-    //if (!instanceInitialized_)
-    //    InitInstance();
+    SharedPtr<NETVariantMap> vmap(new NETVariantMap());
+    vmap->CopySourceVariantMap(fieldValues_);
 
-    if (!started_)
-    {
-        started_ = true;
-        Start();
-    }
-
-    CallScriptMethod(CSComponentMethod_Update, timeStep);
-}
-
-void CSComponent::PostUpdate(float timeStep)
-{
-    CallScriptMethod(CSComponentMethod_PostUpdate, timeStep);
-}
+    NETManaged* managed = GetSubsystem<NETManaged>();
 
-void CSComponent::FixedUpdate(float timeStep)
-{
-    CallScriptMethod(CSComponentMethod_FixedUpdate, timeStep);
-}
+    managed->CSComponentApplyFields(this, vmap);
 
-void CSComponent::FixedPostUpdate(float timeStep)
-{
-    CallScriptMethod(CSComponentMethod_PostFixedUpdate, timeStep);
 }
 
 void CSComponent::OnNodeSet(Node* node)
@@ -228,155 +177,23 @@ void CSComponent::OnNodeSet(Node* node)
     {
         // We are being detached from a node: execute user-defined stop function and prepare for destruction
         //UpdateReferences(true);
-        Stop();
+        //Stop();
     }
 }
 
 void CSComponent::OnSceneSet(Scene* scene)
 {
-    if (scene)
-        UpdateEventSubscription();
-    else
-    {
-        UnsubscribeFromEvent(E_SCENEUPDATE);
-        UnsubscribeFromEvent(E_SCENEPOSTUPDATE);
-#ifdef ATOMIC_PHYSICS
-        UnsubscribeFromEvent(E_PHYSICSPRESTEP);
-        UnsubscribeFromEvent(E_PHYSICSPOSTSTEP);
-#endif
-        currentEventMask_ = 0;
-    }
 }
 
-void CSComponent::UpdateEventSubscription()
-{
-    Scene* scene = GetScene();
-    if (!scene)
-        return;
-
-    bool enabled = IsEnabledEffective();
-
-    bool needUpdate = enabled && ((updateEventMask_ & USE_UPDATE) || !delayedStartCalled_);
-    if (needUpdate && !(currentEventMask_ & USE_UPDATE))
-    {
-        SubscribeToEvent(scene, E_SCENEUPDATE, HANDLER(CSComponent, HandleSceneUpdate));
-        currentEventMask_ |= USE_UPDATE;
-    }
-    else if (!needUpdate && (currentEventMask_ & USE_UPDATE))
-    {
-        UnsubscribeFromEvent(scene, E_SCENEUPDATE);
-        currentEventMask_ &= ~USE_UPDATE;
-    }
-
-    bool needPostUpdate = enabled && (updateEventMask_ & USE_POSTUPDATE);
-    if (needPostUpdate && !(currentEventMask_ & USE_POSTUPDATE))
-    {
-        SubscribeToEvent(scene, E_SCENEPOSTUPDATE, HANDLER(CSComponent, HandleScenePostUpdate));
-        currentEventMask_ |= USE_POSTUPDATE;
-    }
-    else if (!needUpdate && (currentEventMask_ & USE_POSTUPDATE))
-    {
-        UnsubscribeFromEvent(scene, E_SCENEPOSTUPDATE);
-        currentEventMask_ &= ~USE_POSTUPDATE;
-    }
-
-#ifdef ATOMIC_PHYSICS
-    PhysicsWorld* world = scene->GetComponent<PhysicsWorld>();
-    if (!world)
-        return;
-
-    bool needFixedUpdate = enabled && (updateEventMask_ & USE_FIXEDUPDATE);
-    if (needFixedUpdate && !(currentEventMask_ & USE_FIXEDUPDATE))
-    {
-        SubscribeToEvent(world, E_PHYSICSPRESTEP, HANDLER(CSComponent, HandlePhysicsPreStep));
-        currentEventMask_ |= USE_FIXEDUPDATE;
-    }
-    else if (!needFixedUpdate && (currentEventMask_ & USE_FIXEDUPDATE))
-    {
-        UnsubscribeFromEvent(world, E_PHYSICSPRESTEP);
-        currentEventMask_ &= ~USE_FIXEDUPDATE;
-    }
-
-    bool needFixedPostUpdate = enabled && (updateEventMask_ & USE_FIXEDPOSTUPDATE);
-    if (needFixedPostUpdate && !(currentEventMask_ & USE_FIXEDPOSTUPDATE))
-    {
-        SubscribeToEvent(world, E_PHYSICSPOSTSTEP, HANDLER(CSComponent, HandlePhysicsPostStep));
-        currentEventMask_ |= USE_FIXEDPOSTUPDATE;
-    }
-    else if (!needFixedPostUpdate && (currentEventMask_ & USE_FIXEDPOSTUPDATE))
-    {
-        UnsubscribeFromEvent(world, E_PHYSICSPOSTSTEP);
-        currentEventMask_ &= ~USE_FIXEDPOSTUPDATE;
-    }
-#endif
-}
-
-void CSComponent::HandleSceneUpdate(StringHash eventType, VariantMap& eventData)
-{
-    using namespace SceneUpdate;
-
-    assert(!destroyed_);
-
-    // Execute user-defined delayed start function before first update
-    if (!delayedStartCalled_)
-    {
-        DelayedStart();
-        delayedStartCalled_ = true;
-
-        // If did not need actual update events, unsubscribe now
-        if (!(updateEventMask_ & USE_UPDATE))
-        {
-            UnsubscribeFromEvent(GetScene(), E_SCENEUPDATE);
-            currentEventMask_ &= ~USE_UPDATE;
-            return;
-        }
-    }
-
-    // Then execute user-defined update function
-    Update(eventData[P_TIMESTEP].GetFloat());
-}
-
-void CSComponent::HandleScenePostUpdate(StringHash eventType, VariantMap& eventData)
-{
-    using namespace ScenePostUpdate;
-
-    // Execute user-defined post-update function
-    PostUpdate(eventData[P_TIMESTEP].GetFloat());
-}
-
-#ifdef ATOMIC_PHYSICS
-void CSComponent::HandlePhysicsPreStep(StringHash eventType, VariantMap& eventData)
-{
-    using namespace PhysicsPreStep;
-
-    // Execute user-defined fixed update function
-    FixedUpdate(eventData[P_TIMESTEP].GetFloat());
-}
-
-void CSComponent::HandlePhysicsPostStep(StringHash eventType, VariantMap& eventData)
-{
-    using namespace PhysicsPostStep;
-
-    // Execute user-defined fixed post-update function
-    FixedPostUpdate(eventData[P_TIMESTEP].GetFloat());
-}
-#endif
-
 bool CSComponent::Load(Deserializer& source, bool setInstanceDefault)
 {
-    loading_ = true;
     bool success = Component::Load(source, setInstanceDefault);
-    loading_ = false;
-
     return success;
 }
 
 bool CSComponent::LoadXML(const XMLElement& source, bool setInstanceDefault)
 {
-    loading_ = true;
     bool success = Component::LoadXML(source, setInstanceDefault);
-    loading_ = false;
-
     return success;
 }
 

+ 1 - 56
Source/AtomicNET/NETCore/CSComponent.h

@@ -73,20 +73,10 @@ public:
     /// Handle enabled/disabled state change. Changes update event subscription.
     virtual void OnSetEnabled();
 
-    /// Set what update events should be subscribed to. Use this for optimization: by default all are in use. Note that this is not an attribute and is not saved or network-serialized, therefore it should always be called eg. in the subclass constructor.
-    void SetUpdateEventMask(unsigned char mask);
-
+    void ApplyFieldValues();
     VariantMap& GetFieldValues() { return fieldValues_; }
 
-    /// Return what update events are subscribed to.    
-    unsigned char GetUpdateEventMask() const { return updateEventMask_; }
-    /// Return whether the DelayedStart() function has been called.
-    bool IsDelayedStartCalled() const { return delayedStartCalled_; }
-
-    void SetDestroyed() { destroyed_ = true; }
-
     void SetComponentClassName(const String& name) { componentClassName_ = name; }
-
     const String& GetComponentClassName() const { return componentClassName_; }
 
     virtual ScriptComponentFile* GetComponentFile() { return assemblyFile_; }
@@ -104,54 +94,9 @@ protected:
     virtual void OnSceneSet(Scene* scene);
 
 private:
-    /// Subscribe/unsubscribe to update events based on current enabled state and update event mask.
-    void UpdateEventSubscription();
-    /// Handle scene update event.
-    void HandleSceneUpdate(StringHash eventType, VariantMap& eventData);
-    /// Handle scene post-update event.
-    void HandleScenePostUpdate(StringHash eventType, VariantMap& eventData);
-#ifdef ATOMIC_PHYSICS
-    /// Handle physics pre-step event.
-    void HandlePhysicsPreStep(StringHash eventType, VariantMap& eventData);
-    /// Handle physics post-step event.
-    void HandlePhysicsPostStep(StringHash eventType, VariantMap& eventData);
-#endif
-
-    void CallScriptMethod(CSComponentMethod method, float value = 0.0f);
-
-    /// Called when the component is added to a scene node. Other components may not yet exist.
-    virtual void Start();
-    /// Called before the first update. At this point all other components of the node should exist. Will also be called if update events are not wanted; in that case the event is immediately unsubscribed afterward.
-    virtual void DelayedStart();
-    /// Called when the component is detached from a scene node, usually on destruction. Note that you will no longer have access to the node and scene at that point.
-    virtual void Stop() {}
-    /// Called on scene update, variable timestep.
-    virtual void Update(float timeStep);
-    /// Called on scene post-update, variable timestep.
-    virtual void PostUpdate(float timeStep);
-    /// Called on physics update, fixed timestep.
-    virtual void FixedUpdate(float timeStep);
-    /// Called on physics post-update, fixed timestep.
-    virtual void FixedPostUpdate(float timeStep);
-
-    /// Requested event subscription mask.
-    unsigned char updateEventMask_;
-    /// Current event subscription mask.
-    unsigned char currentEventMask_;
-
-    bool instanceInitialized_;
-    bool started_;
-    bool destroyed_;
-    bool scriptClassInstance_;
-
-    /// Flag for delayed start.
-    bool delayedStartCalled_;
-
-    bool loading_;
 
     String componentClassName_;
     SharedPtr<NETAssemblyFile> assemblyFile_;
-    VariantMap fieldValues_;
 
 };
 

+ 3 - 3
Source/AtomicNET/NETCore/NETAssemblyFile.cpp

@@ -98,13 +98,13 @@ bool NETAssemblyFile::ParseComponentClassJSON(const JSONValue& json)
             String fieldName = jfield.Get("name").GetString();
             String defaultValue = jfield.Get("defaultValue").GetString();
 
-            if (isEnum && assemblyEnums_.Contains(typeName) && !enumsAdded.Contains(typeName))
+            if (isEnum && assemblyEnums_.Contains(typeName) && !enumsAdded.Contains(fieldName))
             {
                 varType = VAR_INT;
-                enumsAdded.Push(typeName);
+                enumsAdded.Push(fieldName);
                 const Vector<EnumInfo>& einfos = assemblyEnums_[typeName];
                 for (unsigned i = 0; i < einfos.Size(); i++)
-                    AddEnum(typeName, einfos[i], className);
+                    AddEnum(/*typeName*/fieldName, einfos[i], className);
             }
 
             if (varType == VAR_NONE && typeMap_.Contains(typeName))

+ 1 - 0
Source/AtomicNET/NETCore/NETAssemblyFile.h

@@ -33,6 +33,7 @@ namespace Atomic
 {
 
 class CSComponent;
+class NETVariantMap;
 
 // At runtime we need to load the assembly, in the editor we use metadata
 /// NET Assembly resource.

+ 11 - 20
Source/AtomicNET/NETCore/NETManaged.cpp

@@ -18,6 +18,7 @@ namespace Atomic
 NETManaged::NETManaged(Context* context) :
     Object(context),
     CSComponentCreate_(0),
+    CSComponentApplyFields_(0),
     CSComponentCallMethod_(0),
     CSBeginSendEvent_(0),
     NETUpdate_(0)
@@ -34,16 +35,12 @@ bool NETManaged::Initialize()
 {
     NETCore* core = GetSubsystem<NETCore>();
     core->CreateDelegate("AtomicNETEngine", "AtomicEngine.ComponentCore", "CSComponentCreate", (void**) &CSComponentCreate_);
+    core->CreateDelegate("AtomicNETEngine", "AtomicEngine.ComponentCore", "CSComponentApplyFields", (void**) &CSComponentApplyFields_);
     core->CreateDelegate("AtomicNETEngine", "AtomicEngine.NativeCore", "NETUpdate", (void**) &NETUpdate_);
 
     return true;
 }
 
-void NETManaged::SetNETUpdate(NETUpdateFunctionPtr ptr)
-{
-    NETUpdate_ = ptr;
-}
-
 void NETManaged::NETUpdate(float timeStep)
 {
     if (!NETUpdate_)
@@ -61,6 +58,15 @@ CSComponent* NETManaged::CSComponentCreate(const String& assemblyName, const Str
 
 }
 
+void NETManaged::CSComponentApplyFields(CSComponent* component, NETVariantMap* fieldMapPtr)
+{
+    if (!CSComponentApplyFields_ || !component || !fieldMapPtr)
+        return;
+
+    CSComponentApplyFields_(component, fieldMapPtr);
+
+}
+
 void NETManaged::CSComponentCallMethod(unsigned id, CSComponentMethod methodID, float value)
 {
     if (!CSComponentCallMethod_)
@@ -79,20 +85,5 @@ void NETManaged::CSBeginSendEvent(unsigned senderRefID, unsigned eventType, Vari
 
 }
 
-void NETManaged::SetCSComponentCreate(CSComponentCreateFunctionPtr ptr)
-{
-    CSComponentCreate_ = ptr;
-}
-
-void NETManaged::SetCSComponentCallMethod(CSComponentCallMethodFunctionPtr ptr)
-{
-    CSComponentCallMethod_ = ptr;
-}
-
-void NETManaged::SetCSBeginSendEvent(CSBeginSendEventFunctionPtr ptr)
-{
-    CSBeginSendEvent_ = ptr;
-}
-
 }
 

+ 7 - 6
Source/AtomicNET/NETCore/NETManaged.h

@@ -31,10 +31,13 @@ namespace Atomic
 {
 
 class NETCore;
+class NETVariantMap;
 
 typedef void (*NETUpdateFunctionPtr)(float timeStep);
 
 typedef CSComponent* (*CSComponentCreateFunctionPtr)(const char* assemblyName, const char* csComponentTypeName);
+typedef void (*CSComponentApplyFieldsPtr)(CSComponent* componentPtr, NETVariantMap* fieldMapPtr);
+
 typedef void (*CSComponentCallMethodFunctionPtr)(unsigned id, CSComponentMethod method, float value);
 typedef void (*CSBeginSendEventFunctionPtr)(unsigned senderRefID, unsigned eventType, VariantMap* eventData);
 
@@ -50,21 +53,19 @@ public:
 
     bool Initialize();
 
-    void SetNETUpdate(NETUpdateFunctionPtr ptr);
-
-    void SetCSComponentCreate(CSComponentCreateFunctionPtr ptr);
-    void SetCSComponentCallMethod(CSComponentCallMethodFunctionPtr ptr);
-    void SetCSBeginSendEvent(CSBeginSendEventFunctionPtr ptr);
-
     void NETUpdate(float timeStep);
 
     CSComponent* CSComponentCreate(const String& assemblyName, const String& componentName);
+    void CSComponentApplyFields(CSComponent* component, NETVariantMap* fieldMapPtr);
+
+
     void CSComponentCallMethod(unsigned id, CSComponentMethod methodID, float value = 0.0f);
     void CSBeginSendEvent(unsigned senderRefID, unsigned eventType, VariantMap* eventData);
 
 private:
 
     CSComponentCreateFunctionPtr CSComponentCreate_;
+    CSComponentApplyFieldsPtr CSComponentApplyFields_;
     CSComponentCallMethodFunctionPtr CSComponentCallMethod_;
     CSBeginSendEventFunctionPtr CSBeginSendEvent_;
     NETUpdateFunctionPtr NETUpdate_;

+ 10 - 0
Source/AtomicNET/NETCore/NETVariant.cpp

@@ -0,0 +1,10 @@
+
+#include "NETVariant.h"
+
+
+namespace Atomic
+{
+
+
+
+}

+ 130 - 0
Source/AtomicNET/NETCore/NETVariant.h

@@ -0,0 +1,130 @@
+
+#pragma once
+
+#include <Atomic/Core/Variant.h>
+
+namespace Atomic
+{
+
+/// Wraps a VariantMap as a RefCounted so we can easily send it to managed code
+/// For perfomance sensitive code, specialized marshaling should be used instead (for example physics event data)
+class NETVariantMap : public RefCounted
+{
+    REFCOUNTED(NETVariantMap)
+
+public:
+
+    NETVariantMap() : RefCounted()
+    {
+
+    }
+
+    virtual ~NETVariantMap()
+    {
+
+    }
+
+    bool GetBool(StringHash key) const
+    {
+        Variant* variant = vmap_[key];
+
+        if (!variant)
+            return 0;
+
+        return variant->GetBool();
+
+    }
+
+    int GetInt(StringHash key) const
+    {
+        Variant* variant = vmap_[key];
+
+        if (!variant)
+            return 0;
+
+        return variant->GetInt();
+
+    }
+
+    float GetFloat(StringHash key) const
+    {
+        Variant* variant = vmap_[key];
+
+        if (!variant)
+            return 0;
+
+        return variant->GetFloat();
+
+    }
+
+    const Vector3& GetVector3(StringHash key) const
+    {
+        Variant* variant = vmap_[key];
+
+        if (!variant)
+            return Vector3::ZERO;
+
+        return variant->GetVector3();
+
+    }
+
+    const Quaternion& GetQuaternion(StringHash key) const
+    {
+        Variant* variant = vmap_[key];
+
+        if (!variant)
+            return Quaternion::IDENTITY;
+
+        return variant->GetQuaternion();
+
+    }
+
+
+    RefCounted* GetPtr(StringHash key) const
+    {
+        Variant* variant = vmap_[key];
+
+        if (!variant)
+            return 0;
+
+        return variant->GetPtr();
+
+    }
+
+    const String& GetString(StringHash key) const
+    {
+        Variant* variant = vmap_[key];
+
+        if (!variant)
+            return String::EMPTY;
+
+        return variant->GetString();
+
+    }
+
+    VariantType GetVariantType(StringHash key) const
+    {
+        Variant* variant = vmap_[key];
+
+        if (!variant)
+            return VAR_NONE;
+
+        return variant->GetType();
+    }
+
+
+    bool Contains(StringHash key) const
+    {
+        return vmap_.Contains(key);
+    }
+
+
+    void CopySourceVariantMap(const VariantMap src) { vmap_ = src; }
+
+private:
+
+    VariantMap vmap_;
+
+};
+
+}

+ 1 - 1
Source/AtomicNET/NETJS/CMakeLists.txt

@@ -3,7 +3,7 @@ include_directories (${CMAKE_SOURCE_DIR}/Source/ThirdParty)
 file (GLOB_RECURSE SOURCE_FILES *.cpp *.h)
 
 # Create the JSBind files ahead of time, so they are picked up with glob
-set (JSFILES JSPackageAtomicNET.cpp;JSPackageAtomicNET.cpp)
+set (JSFILES JSPackageAtomicNET.cpp;JSModuleAtomicNET.cpp)
 
 foreach(JSFILE ${JSFILES})