Browse Source

Atomic C# Work (Native Events with strong typing, Object lifetimes, cleanups) (+23 squashed commits)
Squashed commits:
[8c5e720] Object lifetime and event handling improvements
[ae7acba] Fixing issue with slider widgets not getting events, register audio subsystem
[e84617d] Improved event enum handling, allow subclasses when getting event instance parms, fix case of events being called "EventEvent" if they contain event in name,
[9b714e8] Fix issue with C# enum binding values
[d59358c] Binding ValueAnimation::SetKeyframe, adding Color/Vector3 to ScriptVariant, adding some Colors
[5f2445f] Adding ScriptVariant
[c941573] Add generic version of unsubscribe from event
[68ebd71] Camera Clip/Reflection plane bindings
[b7af143] Fix a couple binding issues exposed by Navigation subsystem, CrowdManager bindings
[51a7605] Adding Controls, physics world ray cast,
[eeb75fd] Add log levels
[04f7289] Skeletons and Bones for C# (WIP)
[6ad1086] Adding NavigationMesh::FindPath to C#
[c9e9024] C# Raycasting support
[684853a] Use name from class which is guaranteed to have proper case
[fe7ebb4] Exposing some light control structures
[b62b64b] Working on feature examples
[24c735b] Support for more event parameter types
[e466b5d] Native event cleanup (simplify native events by mirroring native sides lack of sender info when receiving)
[0eb4ca6] More work on typed native events
[bcd3161] More WIP on scripted events
[49ae163] Adding basic event params to C# bindings
[d1777ca] Working on exposing native events to script (typesafe)

Josh Engebretson 9 years ago
parent
commit
304ab275ef
94 changed files with 3533 additions and 538 deletions
  1. 5 0
      Script/AtomicNET/AtomicNET/Application/PlayerApp.cs
  2. 75 51
      Script/AtomicNET/AtomicNET/Core/AObject.cs
  3. 3 2
      Script/AtomicNET/AtomicNET/Core/AtomicNET.cs
  4. 86 52
      Script/AtomicNET/AtomicNET/Core/NativeCore.cs
  5. 111 1
      Script/AtomicNET/AtomicNET/Core/NativeEvents.cs
  6. 9 0
      Script/AtomicNET/AtomicNET/Core/RefCounted.cs
  7. 150 0
      Script/AtomicNET/AtomicNET/Core/Structs.cs
  8. 20 0
      Script/AtomicNET/AtomicNET/Core/VariantMap.cs
  9. 33 0
      Script/AtomicNET/AtomicNET/Graphics/AnimatedModel.cs
  10. 86 0
      Script/AtomicNET/AtomicNET/Graphics/Camera.cs
  11. 114 0
      Script/AtomicNET/AtomicNET/Graphics/Light.cs
  12. 109 0
      Script/AtomicNET/AtomicNET/Graphics/Octree.cs
  13. 32 0
      Script/AtomicNET/AtomicNET/Graphics/RenderPath.cs
  14. 154 0
      Script/AtomicNET/AtomicNET/Graphics/Skeleton.cs
  15. 28 0
      Script/AtomicNET/AtomicNET/IO/Log.cs
  16. 110 0
      Script/AtomicNET/AtomicNET/Input/Controls.cs
  17. 116 4
      Script/AtomicNET/AtomicNET/Math/BoundingBox.cs
  18. 11 7
      Script/AtomicNET/AtomicNET/Math/Color.cs
  19. 58 30
      Script/AtomicNET/AtomicNET/Math/Matrix3x4.cs
  20. 47 0
      Script/AtomicNET/AtomicNET/Navigation/CrowdManager.cs
  21. 58 0
      Script/AtomicNET/AtomicNET/Navigation/NavigationMesh.cs
  22. 31 0
      Script/AtomicNET/AtomicNET/Physics/PhysicsWorld.cs
  23. 5 0
      Script/AtomicNET/AtomicNET/Resource/ResourceCache.cs
  24. 7 0
      Script/AtomicNET/AtomicNET/Scene/CSComponent.cs
  25. 18 183
      Script/AtomicNET/AtomicNET/Scene/CSComponentCore.cs
  26. 15 0
      Script/AtomicNET/AtomicNET/Scene/Component.cs
  27. 24 1
      Script/AtomicNET/AtomicNET/Scene/Node.cs
  28. 304 0
      Script/AtomicNET/AtomicNET/Scene/Scene.cs
  29. 22 0
      Script/AtomicNET/AtomicNET/Scene/ValueAnimation.cs
  30. 42 0
      Script/AtomicNET/AtomicNET/Script/ScriptVariant.cs
  31. 7 4
      Script/AtomicNET/AtomicNET/Script/ScriptVariantMap.cs
  32. 52 0
      Script/AtomicNET/AtomicNET/UI/UIWidget.cs
  33. 5 0
      Script/Packages/Atomic/Core.json
  34. 1 1
      Script/Packages/Atomic/Navigation.json
  35. 1 1
      Script/Packages/Atomic/Script.json
  36. 14 0
      Source/Atomic/Container/RefCounted.cpp
  37. 7 0
      Source/Atomic/Container/RefCounted.h
  38. 1 1
      Source/Atomic/Environment/ProcSky.cpp
  39. 1 1
      Source/Atomic/Navigation/CrowdAgent.h
  40. 5 5
      Source/Atomic/Navigation/Obstacle.h
  41. 22 0
      Source/Atomic/Script/ScriptComponent.cpp
  42. 22 0
      Source/Atomic/Script/ScriptComponent.h
  43. 22 0
      Source/Atomic/Script/ScriptComponentFile.cpp
  44. 22 0
      Source/Atomic/Script/ScriptComponentFile.h
  45. 22 0
      Source/Atomic/Script/ScriptPhysics.cpp
  46. 22 0
      Source/Atomic/Script/ScriptPhysics.h
  47. 22 0
      Source/Atomic/Script/ScriptSystem.cpp
  48. 22 0
      Source/Atomic/Script/ScriptSystem.h
  49. 22 0
      Source/Atomic/Script/ScriptVariant.cpp
  50. 72 0
      Source/Atomic/Script/ScriptVariant.h
  51. 22 0
      Source/Atomic/Script/ScriptVariantMap.cpp
  52. 26 0
      Source/Atomic/Script/ScriptVariantMap.h
  53. 22 0
      Source/Atomic/Script/ScriptVector.cpp
  54. 21 0
      Source/Atomic/Script/ScriptVector.h
  55. 13 8
      Source/Atomic/UI/UI.cpp
  56. 7 7
      Source/Atomic/UI/UIEditField.h
  57. 1 1
      Source/Atomic/UI/UIEvents.h
  58. 13 13
      Source/Atomic/UI/UILayout.h
  59. 3 3
      Source/Atomic/UI/UIMessageWindow.h
  60. 4 4
      Source/Atomic/UI/UIPreferredSize.h
  61. 10 10
      Source/Atomic/UI/UIScrollContainer.h
  62. 5 10
      Source/Atomic/UI/UIWidget.cpp
  63. 47 42
      Source/Atomic/UI/UIWidget.h
  64. 7 6
      Source/Atomic/UI/UIWindow.h
  65. 416 6
      Source/AtomicNET/NETNative/NETCInterop.cpp
  66. 17 2
      Source/AtomicNET/NETNative/NETCore.cpp
  67. 5 0
      Source/AtomicNET/NETNative/NETCore.h
  68. 1 1
      Source/AtomicNET/NETNative/NETEventDispatcher.cpp
  69. 1 1
      Source/AtomicNET/NETScript/NETScriptEvents.h
  70. 1 1
      Source/ThirdParty/TurboBadger/tb_widgets_common.cpp
  71. 5 5
      Source/ToolCore/JSBind/CSharp/CSFunctionWriter.cpp
  72. 137 1
      Source/ToolCore/JSBind/CSharp/CSModuleWriter.cpp
  73. 1 1
      Source/ToolCore/JSBind/CSharp/CSModuleWriter.h
  74. 1 1
      Source/ToolCore/JSBind/CSharp/CSPackageWriter.cpp
  75. 2 2
      Source/ToolCore/JSBind/CSharp/CSTypeHelper.cpp
  76. 21 4
      Source/ToolCore/JSBind/JSBClass.cpp
  77. 2 0
      Source/ToolCore/JSBind/JSBClass.h
  78. 1 1
      Source/ToolCore/JSBind/JSBDoc.cpp
  79. 203 0
      Source/ToolCore/JSBind/JSBEvent.cpp
  80. 83 0
      Source/ToolCore/JSBind/JSBEvent.h
  81. 1 1
      Source/ToolCore/JSBind/JSBFunction.cpp
  82. 26 13
      Source/ToolCore/JSBind/JSBFunction.h
  83. 6 6
      Source/ToolCore/JSBind/JSBHaxe.cpp
  84. 4 4
      Source/ToolCore/JSBind/JSBHaxe.h
  85. 2 0
      Source/ToolCore/JSBind/JSBHeader.h
  86. 4 0
      Source/ToolCore/JSBind/JSBHeaderVisitor.h
  87. 83 32
      Source/ToolCore/JSBind/JSBModule.cpp
  88. 14 0
      Source/ToolCore/JSBind/JSBModule.h
  89. 31 0
      Source/ToolCore/JSBind/JSBPackage.cpp
  90. 7 1
      Source/ToolCore/JSBind/JSBPackage.h
  91. 1 1
      Source/ToolCore/JSBind/JSBPreprocessVisitor.h
  92. 1 1
      Source/ToolCore/JSBind/JSBTypeScript.cpp
  93. 1 1
      Source/ToolCore/JSBind/JavaScript/JSClassWriter.cpp
  94. 7 4
      Source/ToolCore/JSBind/JavaScript/JSFunctionWriter.cpp

+ 5 - 0
Script/AtomicNET/AtomicNET/Application/PlayerApp.cs

@@ -12,13 +12,18 @@ namespace AtomicEngine
         static protected void RegisterSubsystems()
         {
             // TODO: Refactor these registrations
+
+            AtomicNET.RegisterSubsystem("Engine");
+
             AtomicNET.RegisterSubsystem("FileSystem");
 
             AtomicNET.RegisterSubsystem("Graphics");
             AtomicNET.RegisterSubsystem("Player");
 
+            AtomicNET.RegisterSubsystem("Audio");
             AtomicNET.RegisterSubsystem("Input");
             AtomicNET.RegisterSubsystem("Renderer");
+            AtomicNET.RegisterSubsystem("UI");
 
             AtomicNET.RegisterSubsystem("ResourceCache");
             AtomicNET.Cache = AtomicNET.GetSubsystem<ResourceCache>();

+ 75 - 51
Script/AtomicNET/AtomicNET/Core/AObject.cs

@@ -20,34 +20,59 @@ namespace AtomicEngine
         }
         private Dictionary<uint, EventDelegate> eventHandlers;
 
-        private Dictionary<SenderEventKey, SenderEventDelegate> SenderEventHandlers
+        private Dictionary<uint, NativeEventDelegate> NativeEventHandlers
         {
             get
             {
-                if (senderEventHandlers == null)
+                if (nativeHandlers == null)
                 {
-                    SenderEventKeyComparer comparer = SenderEventKeyComparer.Default;
-                    senderEventHandlers = new Dictionary<SenderEventKey, SenderEventDelegate>(comparer);
+                    nativeHandlers = new Dictionary<uint, NativeEventDelegate>();
                 }
-                return senderEventHandlers;
+                return nativeHandlers;
             }
         }
-        private Dictionary<SenderEventKey, SenderEventDelegate> senderEventHandlers;
+        private Dictionary<uint, NativeEventDelegate> nativeHandlers;
 
         public static T GetSubsystem<T>() where T : AObject
         {
             return AtomicNET.GetSubsystem<T>();
         }
 
-        internal void HandleEvent(uint eventType, ScriptVariantMap eventData)
+        public void UnsubscribeFromAllEvents()
         {
-            eventHandlers[eventType](eventType, eventData);
+            if (eventHandlers != null)
+                eventHandlers.Clear();
+
+            if(nativeHandlers != null)
+                nativeHandlers.Clear();
+
+            NativeCore.UnsubscribeFromAllEvents(this);
+            csi_Atomic_AObject_UnsubscribeFromAllEvents(nativeInstance);
         }
 
-        internal void HandleEvent(AObject sender, uint eventType, ScriptVariantMap eventData)
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_AObject_UnsubscribeFromAllEvents(IntPtr self);
+
+        internal void HandleEvent(uint eventType, ScriptVariantMap eventData, NativeEventData nativeEventData)
         {
-            var key = new SenderEventKey(eventType, sender.nativeInstance);
-            senderEventHandlers[key](sender, eventType, eventData);
+            NativeEventDelegate nativeDelegate;
+
+            if (NativeEventHandlers.TryGetValue(eventType, out nativeDelegate))
+            {
+                nativeDelegate(nativeEventData);
+                return;
+            }
+            
+            EventDelegate eventDelegate;
+
+            if (EventHandlers.TryGetValue(eventType, out eventDelegate))
+            {
+                eventDelegate(eventType, eventData);
+                return;
+            }
+          
+            // Reaching here should be a warning, possibly an error
+
         }
 
         public void SubscribeToEvent(uint eventType, EventDelegate eventDelegate)
@@ -66,80 +91,79 @@ namespace AtomicEngine
         {
             NativeCore.UnsubscribeFromEvent(this, eventType);
             EventHandlers.Remove(eventType);
+            NativeEventHandlers.Remove(eventType);
         }
 
-        public void SubscribeToEvent(AObject sender, uint eventType, SenderEventDelegate eventDelegate)
+        public void SubscribeToEvent(AObject sender, uint eventType, EventDelegate eventDelegate)
         {
             if (sender == null)
             {
                 throw new InvalidOperationException("AObject.SubscribeToEvent - trying to subscribe to events from a null object");
             }
 
+            // Move this
             NETCore.RegisterNETEventType(eventType);
-            var key = new SenderEventKey(eventType, sender.nativeInstance);
-            SenderEventHandlers[key] = eventDelegate;
             NativeCore.SubscribeToEvent(this, sender, eventType);
         }
 
-        public void SubscribeToEvent(AObject sender, string eventType, SenderEventDelegate eventDelegate)
+        public void SubscribeToEvent(AObject sender, string eventType, EventDelegate eventDelegate)
         {
             SubscribeToEvent(sender, AtomicNET.StringToStringHash(eventType), eventDelegate);
         }
 
-        public void UnsubscribeFromEvent(AObject sender, uint eventType)
-        {
-            NativeCore.UnsubscribeFromEvent(this, sender, eventType);
-            var key = new SenderEventKey(eventType, sender.nativeInstance);
-            SenderEventHandlers.Remove(key);
-        }
+        // Native events
 
-        public void SendEvent(string eventType, ScriptVariantMap eventData = null)
+
+        public void UnsubscribeFromEvent<T>() where T : NativeEventData
         {
+            uint eventType = NativeEvents.GetEventID<T>();
+            UnsubscribeFromEvent(eventType);
+        }
 
-            csi_Atomic_AObject_SendEvent(this.nativeInstance, eventType, eventData == null ? IntPtr.Zero : eventData.nativeInstance);
 
+        public void SubscribeToEvent<T>(NativeEventDelegate<T> eventDelegate) where T : NativeEventData
+        {
+            SubscribeToEvent<T>(null, eventDelegate);
         }
 
-        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
-        private static extern void csi_Atomic_AObject_SendEvent(IntPtr self, string eventType, IntPtr variantMap);
-
-        private struct SenderEventKey
+        public void SubscribeToEvent<T>(AObject sender, NativeEventDelegate<T> eventDelegate) where T : NativeEventData
         {
-            public readonly uint EventType;
-            public readonly IntPtr Sender; 
+            uint eventType = NativeEvents.GetEventID<T>();
 
-            public SenderEventKey(uint eventType, IntPtr sender)
+            if (eventType == 0)
             {
-                EventType = eventType;
-                Sender = sender;
+                throw new InvalidOperationException("AObject.SubscribeToEvent<T>(EventDelegate<T> eventDelegate) - Unknown native event id");
             }
-        }
 
-        // Use a comparer to avoid boxing on struct .Equals override
-        private class SenderEventKeyComparer : IEqualityComparer<SenderEventKey>
-        {
-            public static readonly SenderEventKeyComparer Default = new SenderEventKeyComparer();
+            // Move this
+            NETCore.RegisterNETEventType(eventType);
 
-            private SenderEventKeyComparer() { }
+            NativeEventHandlers[eventType] = (eventData) =>
+            {
+                eventDelegate((T)eventData);
+            };
 
-            public bool Equals(SenderEventKey lhs, SenderEventKey rhs)
+            if (sender != null)
             {
-                return (lhs.EventType == rhs.EventType &&
-                    lhs.Sender == rhs.Sender);
+                NativeCore.SubscribeToEvent(this, sender, eventType);
             }
-
-            public int GetHashCode(SenderEventKey key)
+            else
             {
-                // Based on http://stackoverflow.com/a/263416/156328
-                unchecked
-                {
-                    int hash = 17;
-                    hash = hash * 23 + key.EventType.GetHashCode();
-                    hash = hash * 23 + key.Sender.GetHashCode();
-                    return hash;
-                }
+                NativeCore.SubscribeToEvent(this, eventType);
             }
+           
         }
+
+        public void SendEvent(string eventType, ScriptVariantMap eventData = null)
+        {
+
+            csi_Atomic_AObject_SendEvent(this.nativeInstance, eventType, eventData == null ? IntPtr.Zero : eventData.nativeInstance);
+
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_AObject_SendEvent(IntPtr self, string eventType, IntPtr variantMap);
+
     }
 
 }

+ 3 - 2
Script/AtomicNET/AtomicNET/Core/AtomicNET.cs

@@ -49,6 +49,7 @@ namespace AtomicEngine
         // static members so they don't get GC'd
         private static EventDispatchDelegate eventDispatchDelegate = NativeCore.EventDispatch;
         private static UpdateDispatchDelegate updateDispatchDelegate = NativeCore.UpdateDispatch;
+        private static RefCountedDeletedDelegate refCountedDeletedDelegate = NativeCore.RefCountedDeleted;
 
         public static void Initialize()
         {
@@ -81,7 +82,7 @@ namespace AtomicEngine
 
             PlayerModule.Initialize();
 
-            IntPtr coreptr = csi_Atomic_NETCore_Initialize(eventDispatchDelegate, updateDispatchDelegate);
+            IntPtr coreptr = csi_Atomic_NETCore_Initialize(eventDispatchDelegate, updateDispatchDelegate, refCountedDeletedDelegate);
 
             NETCore core = (coreptr == IntPtr.Zero ? null : NativeCore.WrapNative<NETCore>(coreptr));
 
@@ -102,7 +103,7 @@ namespace AtomicEngine
         }
 
         [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
-        private static extern IntPtr csi_Atomic_NETCore_Initialize(EventDispatchDelegate eventDispatch, UpdateDispatchDelegate updateDispatch);
+        private static extern IntPtr csi_Atomic_NETCore_Initialize(EventDispatchDelegate eventDispatch, UpdateDispatchDelegate updateDispatch, RefCountedDeletedDelegate refCountedDeleted);
 
         private static Context context;
         private static Dictionary<Type, AObject> subSystems = new Dictionary<Type, AObject>();

+ 86 - 52
Script/AtomicNET/AtomicNET/Core/NativeCore.cs

@@ -18,6 +18,9 @@ namespace AtomicEngine
     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
     public delegate void UpdateDispatchDelegate(float timeStep);
 
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    public delegate void RefCountedDeletedDelegate(IntPtr refCounted);
+
     public class NativeType
     {
 
@@ -72,36 +75,10 @@ namespace AtomicEngine
                 throw new InvalidOperationException("NativeCore.SubscribeToEvent - unable to find native receiver instance");
             }
 
-            RefCounted refcounted;
-            if (!w.TryGetTarget(out refcounted))
-            {
-                throw new InvalidOperationException("NativeCore.SubscribeToEvent - attempting to subscribe a GC'd AObject");
-            }
-
-            IntPtr nativeSender = IntPtr.Zero;
-            if (sender != null)
-            {
-                nativeSender = sender.nativeInstance;
-                if (!nativeLookup.TryGetValue(sender.nativeInstance, out w))
-                {
-                    throw new InvalidOperationException("NativeCore.SubscribeToEvent - unable to find native sender instance");
-                }
-
-                if (!w.TryGetTarget(out refcounted))
-                {
-                    throw new InvalidOperationException("NativeCore.SubscribeToEvent - attempting to subscribe to a GC'd AObject");
-                }
-            }
-
-            eventReceivers.Add(new EventSubscription(receiver, nativeSender));
+            eventReceivers.Add(new EventSubscription(receiver, sender));
         }
 
         static internal void UnsubscribeFromEvent(AObject receiver, uint eventType)
-        {
-            UnsubscribeFromEvent(receiver, null, eventType);
-        }
-
-        static internal void UnsubscribeFromEvent(AObject receiver, RefCounted sender, uint eventType)
         {
             List<EventSubscription> eventReceivers;
             if (!eventReceiverLookup.TryGetValue(eventType, out eventReceivers))
@@ -113,8 +90,7 @@ namespace AtomicEngine
                 if (!er.Receiver.TryGetTarget(out obj))
                     continue; // GC'd
 
-                if (obj == receiver &&
-                    (sender == null || er.Sender == sender.nativeInstance))
+                if (obj == receiver)
                 {
                     eventReceivers.Remove(er);
                     return;
@@ -122,6 +98,36 @@ namespace AtomicEngine
             }
         }
 
+        static internal void UnsubscribeFromAllEvents(AObject receiver)
+        {
+            // TODO: Optimize
+
+            AObject obj;
+
+            foreach (var subList in eventReceiverLookup.Values)
+            {                
+                subList.RemoveAll(item => item.Receiver.TryGetTarget(out obj) && obj == receiver);
+            }
+
+        }
+
+        static internal void RemoveEventSender(IntPtr sender)
+        {
+            //TODO: OPTIMIZE
+
+            if (sender == IntPtr.Zero)
+                return;         
+            
+            foreach (var subList in eventReceiverLookup.Values)
+            {
+                var len = subList.Count;
+
+                subList.RemoveAll(item => item.Sender == sender);
+
+                //TODO: The events are still in the receiver lookup tables!
+            }
+        }
+
         static ScriptVariantMap[] svm;
         static int svmDepth = 0;
         const int svmMax = 256;
@@ -147,6 +153,13 @@ namespace AtomicEngine
             if (expireDelta > 2.0f)
             {
                 expireDelta = 0.0f;
+    
+                
+                // TODO: tune GC    
+                GC.Collect();
+                GC.WaitForPendingFinalizers();
+                GC.Collect();
+
                 ExpireNatives();
             }
         }
@@ -165,20 +178,10 @@ namespace AtomicEngine
 
             }
 
-            AObject managedSender = null;
-            WeakReference<RefCounted> wr;
-            if (sender != IntPtr.Zero &&
-                nativeLookup.TryGetValue(sender, out wr))
-            {
-                RefCounted refCounted;
-                if (wr.TryGetTarget(out refCounted))
-                {
-                    managedSender = refCounted as AObject;
-                }
-            }
-
             // iterate over copy of list so we can modify it while running
             ScriptVariantMap scriptMap = null;
+            NativeEventData nativeEventData = null;
+
             AObject receiver;
             foreach (EventSubscription er in eventReceivers.ToList())
             {
@@ -186,6 +189,9 @@ namespace AtomicEngine
                 if (!er.Receiver.TryGetTarget(out receiver))
                     continue;
 
+                if (er.Sender != IntPtr.Zero && er.Sender != sender)
+                    continue;
+
                 if (scriptMap == null)
                 {
                     if (svmDepth == svmMax)
@@ -195,21 +201,23 @@ namespace AtomicEngine
 
                     scriptMap = svm[svmDepth++];
                     scriptMap.CopyVariantMap(eventData);
+                    nativeEventData = NativeEvents.GetNativeEventData(eventType, scriptMap);
+                    nativeEventData.sourceEventData = eventData;
                 }
 
-                if (managedSender != null && er.Sender == sender)
-                {
-                    receiver.HandleEvent(managedSender, eventType, scriptMap);
-                }
-                else if (er.Sender == IntPtr.Zero)
-                {
-                    receiver.HandleEvent(eventType, scriptMap);
-                }
+                receiver.HandleEvent(eventType, scriptMap, nativeEventData);
             }
 
             if (scriptMap != null)
+            {
                 svmDepth--;
 
+                if (nativeEventData != null)
+                {
+                    NativeEvents.ReleaseNativeEventData(nativeEventData);
+                }
+            }
+
         }
 
         static void ExpireNatives()
@@ -270,6 +278,13 @@ namespace AtomicEngine
 
         }
 
+        // Called from RefCounted native destructor, refCounted is not valid for any operations here
+        public static void RefCountedDeleted(IntPtr refCounted)
+        {
+            nativeLookup.Remove(refCounted);
+            RemoveEventSender(refCounted);
+        }
+
         // register a newly created native
         public static IntPtr RegisterNative(IntPtr native, RefCounted r)
         {
@@ -284,6 +299,10 @@ namespace AtomicEngine
 
             nativeLookup[native] = new WeakReference<RefCounted>(r);
 
+            r.InstantiationType = InstantiationType.INSTANTIATION_NET;
+
+            r.PostNativeUpdate();
+
             return native;
         }
 
@@ -342,6 +361,15 @@ namespace AtomicEngine
             // store a ref, so native side will not be released while we still have a reference in managed code
             r.AddRef();
 
+            // Note: r.InstantiationType may be INSTANTIATION_NET here is we were GC'd, native still had a reference, and we came back
+            if (r.InstantiationType == InstantiationType.INSTANTIATION_NET)
+            {
+                //Log.Warn($"Wrapped {r.GetType().Name} was originally instantiated in NET, changing to native, this is likely an error");
+                //r.InstantiationType = InstantiationType.INSTANTIATION_NATIVE;
+            }
+
+            r.PostNativeUpdate();
+
             return (T)r;
         }
 
@@ -439,10 +467,16 @@ namespace AtomicEngine
             public WeakReference<AObject> Receiver;
             public IntPtr Sender;
 
-            public EventSubscription(AObject obj, IntPtr source)
+            public EventSubscription(AObject receiver)
+            {
+                Receiver = new WeakReference<AObject>(receiver);
+                Sender = IntPtr.Zero;
+            }
+
+            public EventSubscription(AObject receiver, IntPtr sender)
             {
-                Receiver = new WeakReference<AObject>(obj);
-                Sender = source;
+                Receiver = new WeakReference<AObject>(receiver);
+                Sender = sender;
             }
         }
 

+ 111 - 1
Script/AtomicNET/AtomicNET/Core/NativeEvents.cs

@@ -1,11 +1,13 @@
 using System;
+using System.Collections.Generic;
 using System.Runtime.InteropServices;
 
 namespace AtomicEngine
 {
     public delegate void EventDelegate(uint eventType, ScriptVariantMap eventData);
 
-    public delegate void SenderEventDelegate(AObject sender, uint eventType, ScriptVariantMap eventData);
+    public delegate void NativeEventDelegate(NativeEventData eventData);
+    public delegate void NativeEventDelegate<T>(T eventData);
 
     public partial class ScriptVariantMap
     {
@@ -19,4 +21,112 @@ namespace AtomicEngine
 
     }
 
+    public class NativeEventData 
+    {
+        public ScriptVariantMap scriptMap;
+
+        public void Set(string name, bool value)
+        {
+            VariantMap.SetBool(sourceEventData, name, value);
+        }
+
+        // Variant Map
+        internal IntPtr sourceEventData;
+    }
+
+    public static partial class NativeEvents
+    {
+        class NativeEventDataCache
+        {
+            public NativeEventDataCache(Type type)
+            {
+                eventData = new NativeEventData[eventDataMax];
+
+                for (int i = 0; i < eventDataMax; i++)
+                    eventData[i] = (NativeEventData)Activator.CreateInstance(type);
+            }
+
+            public NativeEventData[] eventData;
+            public int eventDataDepth = 0;
+            public const int eventDataMax = 256;
+        }
+
+        public static uint GetEventID<T>() where T : NativeEventData
+        {
+            uint eventID;
+
+            if (eventIDLookup.TryGetValue(typeof(T), out eventID))
+            {
+                return eventID;
+            }
+
+            return 0;
+        }
+
+        public static void RegisterEventID<T>(string eventName) where T : NativeEventData
+        {
+            var eventID = AtomicNET.StringToStringHash(eventName);
+            var type = typeof(T);
+
+            eventIDLookup[type] = eventID;
+            typeLookup[eventID] = type;
+
+            // create event data cache
+            var cache = new NativeEventDataCache(type);
+            eventCache[type] = cache;
+            eventCacheByEventID[eventID] = cache;
+
+        }
+
+        public static NativeEventData GetNativeEventData(uint eventID, ScriptVariantMap eventMap)
+        {
+            NativeEventDataCache cache;
+
+            if (eventCacheByEventID.TryGetValue(eventID, out cache))
+            {
+                if (cache.eventDataDepth == NativeEventDataCache.eventDataMax)
+                {
+                    throw new InvalidOperationException("GetNativeEventData - max recursive event");
+                }
+
+                var eventData = cache.eventData[cache.eventDataDepth++];
+                eventData.scriptMap = eventMap;
+                return eventData;
+            }
+
+            return null;
+        }
+
+        public static void ReleaseNativeEventData(NativeEventData eventData)
+        {
+            Type dataType = eventData.GetType();
+            eventData.scriptMap = null;
+            eventData.sourceEventData = IntPtr.Zero;
+
+            NativeEventDataCache cache;
+
+            if (eventCache.TryGetValue(dataType, out cache))
+            {
+#if DEBUG
+                if (cache.eventData[cache.eventDataDepth - 1] != eventData)
+                {
+                    throw new InvalidOperationException("ReleaseNativeEventData - unexpected event data");
+                }    
+#endif                                
+                cache.eventDataDepth--;
+            }
+
+        }
+
+        // event cache
+        static Dictionary<Type, NativeEventDataCache> eventCache = new Dictionary<Type, NativeEventDataCache>();
+        static Dictionary<uint, NativeEventDataCache> eventCacheByEventID = new Dictionary<uint, NativeEventDataCache>();
+
+        // native event type -> native eventType hash id
+        static Dictionary<Type, uint> eventIDLookup = new Dictionary<Type, uint>();
+
+        // native eventType hash id -> NativeEvent type
+        static Dictionary<uint, Type> typeLookup = new Dictionary<uint, Type>();
+    }
+
 }

+ 9 - 0
Script/AtomicNET/AtomicNET/Core/RefCounted.cs

@@ -4,6 +4,7 @@ using System.Runtime.InteropServices;
 namespace AtomicEngine
 {
 
+    [ComVisible(true)]
     public partial class RefCounted
     {
 
@@ -16,6 +17,14 @@ namespace AtomicEngine
             nativeInstance = native;
         }
 
+        // This method may be called multiple times, called on instance after it is either registered as a new native created in C# (InstantiationType == InstantiationType.INSTANTIATION_NET)
+        // or a native which has been wrapped ((InstantiationType != InstantiationType.INSTANTIATION_NET)
+        // Note that RefCounted that get GC'd from script, can still live in native code, and get rewrapped 
+        internal virtual void PostNativeUpdate()
+        {
+
+        }
+
         public static implicit operator IntPtr(RefCounted refCounted)
         {
             if (refCounted == null)

+ 150 - 0
Script/AtomicNET/AtomicNET/Core/Structs.cs

@@ -0,0 +1,150 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    [StructLayout(LayoutKind.Sequential)]
+    public struct BiasParameters
+    {
+        public float ConstantBias;
+        public float SlopeScaleBias;
+        public float NormalOffset;
+
+        public BiasParameters(float constantBias, float slopeScaleBias, float normalOffset = 0.0f)
+        {
+            ConstantBias = constantBias;
+            SlopeScaleBias = slopeScaleBias;
+            NormalOffset = normalOffset;
+        }
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct CascadeParameters
+    {
+        public float Split1, Split2, Split3, Split4;
+        public float FadeStart;
+        public float BiasAutoAdjust;
+
+        public CascadeParameters(float split1, float split2, float split3, float split4, float fadeStart, float biasAutoAdjust = 1f)
+        {
+            Split1 = split1;
+            Split2 = split2;
+            Split3 = split3;
+            Split4 = split4;
+            FadeStart = fadeStart;
+            BiasAutoAdjust = biasAutoAdjust;
+        }
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct FocusParameters
+    {
+        public byte Focus;
+        public byte NonUniform;
+        public byte AutoSize;
+        public float Quantize;
+        public float MinView;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct Ray
+    {
+        public Vector3 Origin;
+        public Vector3 Direction;
+
+        public Ray(Vector3 origin, Vector3 direction)
+        {
+            Origin = origin;
+            Direction = Vector3.Normalize(direction);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (!(obj is Ray))
+                return false;
+
+            return (this == (Ray)obj);
+        }
+
+        public static bool operator ==(Ray left, Ray right)
+        {
+            return ((left.Origin == right.Origin) && (left.Direction == right.Direction));
+        }
+
+        public static bool operator !=(Ray left, Ray right)
+        {
+            return ((left.Origin != right.Origin) || (left.Direction != right.Direction));
+        }
+
+        public Vector3 Project(Vector3 point)
+        {
+            var offset = point - Origin;
+            return Origin + Vector3.Dot(offset, Direction) * Direction;
+        }
+
+        public override int GetHashCode()
+        {
+            return Origin.GetHashCode() + Direction.GetHashCode();
+        }
+
+        public float Distance(Vector3 point)
+        {
+            var projected = Project(point);
+            return (point - projected).Length;
+        }
+
+        public Vector3 ClosestPoint(Ray otherRay)
+        {
+            var p13 = Origin - otherRay.Origin;
+            var p43 = otherRay.Direction;
+            Vector3 p21 = Direction;
+
+            float d1343 = Vector3.Dot(p13, p43);
+            float d4321 = Vector3.Dot(p43, p21);
+            float d1321 = Vector3.Dot(p13, p21);
+            float d4343 = Vector3.Dot(p43, p43);
+            float d2121 = Vector3.Dot(p21, p21);
+
+            float d = d2121 * d4343 - d4321 * d4321;
+            if (Math.Abs(d) < float.Epsilon)
+                return Origin;
+            float n = d1343 * d4321 - d1321 * d4343;
+            float a = n / d;
+
+            return Origin + a * Direction;
+        }
+
+        public float HitDistance(Plane plane)
+        {
+            float d = Vector3.Dot(plane.Normal, Direction);
+            if (Math.Abs(d) >= float.Epsilon)
+            {
+                float t = -(Vector3.Dot(plane.Normal, Origin) + plane.D) / d;
+                if (t >= 0.0f)
+                    return t;
+                else
+                    return float.PositiveInfinity;
+            }
+            else
+                return float.PositiveInfinity;
+        }
+
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct WeakPtr
+    {
+        IntPtr ptr;
+        IntPtr refCountPtr;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct AtomicString
+    {
+        public uint Length;
+        public uint Capacity;
+        public IntPtr Buffer;
+    }
+
+}

+ 20 - 0
Script/AtomicNET/AtomicNET/Core/VariantMap.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+
+    internal static class VariantMap 
+    {
+
+        public static void SetBool(IntPtr vmap, string key, bool value)
+        {
+            csi_Atomic_VariantMap_SetBool(vmap, key, value);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern IntPtr csi_Atomic_VariantMap_SetBool(IntPtr vmap, string key, bool value);
+
+    }
+
+}

+ 33 - 0
Script/AtomicNET/AtomicNET/Graphics/AnimatedModel.cs

@@ -0,0 +1,33 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public partial class AnimatedModel : StaticModel
+    {
+
+        public Skeleton Skeleton
+        {
+            get
+            {
+                return GetSkeleton();
+            }
+        }
+
+        Skeleton GetSkeletonReturnValue;
+        public Skeleton GetSkeleton()
+        {
+            if (GetSkeletonReturnValue == null)
+                GetSkeletonReturnValue = new Skeleton(this, csi_Atomic_AnimatedModel_GetSkeleton(nativeInstance));
+
+            return GetSkeletonReturnValue;
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern IntPtr csi_Atomic_AnimatedModel_GetSkeleton(IntPtr self);
+
+    };
+
+}
+

+ 86 - 0
Script/AtomicNET/AtomicNET/Graphics/Camera.cs

@@ -0,0 +1,86 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public partial class Camera : Component
+    {
+       
+        /// Return ray corresponding to normalized screen coordinates (0 - 1), with origin on the near clip plane.
+        public Ray GetScreenRay(float x, float y)
+        {
+            csi_Atomic_Camera_GetScreenRay(nativeInstance, x, y, ref GetScreenRayReturnValue);
+            return GetScreenRayReturnValue;
+        }
+
+        public Plane ClipPlane
+        {
+            get
+            {
+                return GetClipPlane();
+            }
+            set
+            {
+                SetClipPlane(value);
+            }
+        }
+
+        public Plane ReflectionPlane
+        {
+            get
+            {
+                return GetReflectionPlane();
+            }
+            set
+            {
+                SetReflectionPlane(value);
+            }
+        }
+
+        public Plane GetClipPlane()
+        {
+            Plane plane = new Plane();
+            csi_Atomic_Camera_GetClipPlane(nativeInstance, ref plane);
+            return plane;
+        }
+
+        public Plane GetReflectionPlane()
+        {
+            Plane plane = new Plane();
+            csi_Atomic_Camera_GetReflectionPlane(nativeInstance, ref plane);
+            return plane;
+        }
+
+        public void SetClipPlane(Plane plane)
+        {
+            csi_Atomic_Camera_SetClipPlane(nativeInstance, ref plane);
+        }
+
+        public void SetReflectionPlane(Plane plane)
+        {
+            csi_Atomic_Camera_SetReflectionPlane(nativeInstance, ref plane);
+        }
+
+        private Ray GetScreenRayReturnValue = new Ray();
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Camera_GetScreenRay(IntPtr self, float x, float y, ref Ray retValue);
+
+        
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Camera_GetClipPlane(IntPtr self, ref Plane retValue);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Camera_GetReflectionPlane(IntPtr self, ref Plane retValue);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Camera_SetClipPlane(IntPtr self, ref Plane retValue);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Camera_SetReflectionPlane(IntPtr self, ref Plane retValue);
+
+
+    };
+
+}
+

+ 114 - 0
Script/AtomicNET/AtomicNET/Graphics/Light.cs

@@ -0,0 +1,114 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public partial class Light : Drawable
+    {
+
+        public BiasParameters ShadowBias
+        {
+            get
+            {
+                return GetShadowBias();
+            }
+            set
+            {
+                SetShadowBias(value);
+            }
+        }
+
+        public CascadeParameters ShadowCascade
+        {
+            get
+            {
+                return GetShadowCascade();
+            }
+            set
+            {
+                SetShadowCascade(value);
+            }
+        }
+
+        public FocusParameters ShadowFocus
+        {
+            get
+            {
+                return GetShadowFocus();
+            }
+            set
+            {
+                SetShadowFocus(value);
+            }
+        }
+
+        /// Set shadow depth bias parameters.
+        public void SetShadowBias(BiasParameters parameters)
+        {
+            csi_Atomic_Light_SetShadowBias(nativeInstance, ref parameters);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Light_SetShadowBias(IntPtr self, ref BiasParameters parameters);
+
+
+        /// Set directional light cascaded shadow parameters.
+        void SetShadowCascade(CascadeParameters parameters)
+        {
+            csi_Atomic_Light_SetShadowCascade(nativeInstance, ref parameters);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Light_SetShadowCascade(IntPtr self, ref CascadeParameters parameters);
+
+
+        /// Set shadow map focusing parameters.
+        void SetShadowFocus(FocusParameters parameters)
+        {
+            csi_Atomic_Light_SetShadowFocus(nativeInstance, ref parameters);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Light_SetShadowFocus(IntPtr self, ref FocusParameters parameters);
+
+
+        /// Set shadow depth bias parameters.
+
+        BiasParameters GetShadowBias()
+        {
+            BiasParameters biasParams = new BiasParameters();
+            csi_Atomic_Light_GetShadowBias(nativeInstance, ref biasParams);
+            return biasParams;
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Light_GetShadowBias(IntPtr self, ref BiasParameters retValue);
+
+        /// Set directional light cascaded shadow parameters.
+        CascadeParameters GetShadowCascade()
+        {
+            CascadeParameters cascadeParams = new CascadeParameters();
+            csi_Atomic_Light_GetShadowCascade(nativeInstance, ref cascadeParams);
+            return cascadeParams;
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Light_GetShadowCascade(IntPtr self, ref CascadeParameters retValue);
+
+        /// Set shadow map focusing parameters.
+        FocusParameters GetShadowFocus()
+        {
+            FocusParameters focusParams = new FocusParameters();
+            csi_Atomic_Light_GetShadowFocus(nativeInstance, ref focusParams);
+            return focusParams;
+
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_Light_GetShadowFocus(IntPtr self, ref FocusParameters retValue);
+
+    };
+
+}
+

+ 109 - 0
Script/AtomicNET/AtomicNET/Graphics/Octree.cs

@@ -0,0 +1,109 @@
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct RayQueryResult
+    {
+        public Vector3 Position;
+        public Vector3 Normal;
+        public Vector2 TextureUV;
+        public float Distance;
+
+        IntPtr drawablePtr;
+        IntPtr nodePtr;
+
+        // Optimize
+        public Drawable Drawable => NativeCore.WrapNative<Drawable>(drawablePtr);
+        public Node Node => NativeCore.WrapNative<Node>(nodePtr);
+
+        public uint SubObject;
+
+    }
+
+    public class RayOctreeQuery
+    {
+
+        /// Construct with ray and query parameters.
+        public RayOctreeQuery(Ray ray, RayQueryLevel level = RayQueryLevel.RAY_TRIANGLE, float maxDistance = Single.PositiveInfinity, uint drawableFlags = Constants.DRAWABLE_ANY, uint viewMask = Constants.DEFAULT_VIEWMASK)
+        {
+            this.Ray = ray;
+            this.Level = level;
+            this.MaxDistance = maxDistance;
+            this.DrawableFlags = drawableFlags;
+            this.ViewMask = viewMask;
+        }
+
+        public List<RayQueryResult> Results = new List<RayQueryResult>();
+
+        /// Ray.
+        public Ray Ray;
+
+        /// Drawable flags to include.
+        public uint DrawableFlags;
+        /// Drawable layers to include.
+        public uint ViewMask;
+
+        /// Maximum ray distance.
+        public float MaxDistance;
+
+        /// Raycast detail level.
+        public RayQueryLevel Level;
+
+    }
+
+    public partial class Octree : Component
+    {
+
+        /// Return the closest drawable object by a ray query.
+        public void RaycastSingle(RayOctreeQuery query)
+        {
+            Raycast(query, true);
+        }
+
+        public void Raycast(RayOctreeQuery query, bool single = false)
+        {
+
+            query.Results.Clear();
+
+            if (query.Ray == null)
+                return;
+
+            int count;
+            IntPtr resultVector;
+
+            var ptr = csi_Atomic_Octree_Raycast(nativeInstance, ref query.Ray, ref query.Level, query.MaxDistance, query.DrawableFlags, query.ViewMask, single, out resultVector, out count);
+
+            if (ptr == IntPtr.Zero)
+            {
+                return;
+            }
+                
+            int structSize = Marshal.SizeOf(typeof(RayQueryResult));
+
+            for (int i = 0; i < count; i++)
+            {
+                IntPtr data = new IntPtr(ptr.ToInt64() + structSize * i);
+                RayQueryResult item = (RayQueryResult)Marshal.PtrToStructure(data, typeof(RayQueryResult));
+                query.Results.Add(item);
+            }
+
+            csi_Atomic_Octree_Raycast_FreeResult(resultVector);
+
+        }
+
+        // Any resultVector returned here, must be freed with csi_Atomic_Octree_Raycast_FreeResult
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern IntPtr csi_Atomic_Octree_Raycast(IntPtr self, ref Ray ray, ref RayQueryLevel level, float maxDistance, uint drawableFlags, uint viewMask, bool single, out IntPtr resultVector, out int count);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern IntPtr csi_Atomic_Octree_Raycast_FreeResult(IntPtr resultVector);
+
+    };
+
+}
+

+ 32 - 0
Script/AtomicNET/AtomicNET/Graphics/RenderPath.cs

@@ -0,0 +1,32 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public partial class RenderPath : RefCounted
+    {
+
+        public void SetShaderParameter(string name, ScriptVariant variant)
+        {
+            csi_Atomic_RenderPath_SetShaderParameter(nativeInstance, name, variant.nativeInstance);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_RenderPath_SetShaderParameter(IntPtr self, string name, IntPtr variant);
+
+        public ScriptVariant GetShaderParameter(string name)
+        {
+            ScriptVariant variant = new ScriptVariant();
+            csi_Atomic_RenderPath_GetShaderParameter(nativeInstance, name, variant.nativeInstance);
+            return variant;
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        private static extern void csi_Atomic_RenderPath_GetShaderParameter(IntPtr self, string name, IntPtr variant);
+
+
+    };
+
+}
+

+ 154 - 0
Script/AtomicNET/AtomicNET/Graphics/Skeleton.cs

@@ -0,0 +1,154 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct NativeBone
+    {
+        public AtomicString Name;
+
+        public int NameHash;
+        public uint ParentIndex;
+        public Vector3 InitialPosition;
+        public Quaternion InitialRotation;
+        public Vector3 InitialScale;
+        public Matrix3x4 OffsetMatrix;
+
+        byte animated; //bool is not blittable.
+
+        public byte CollisionMask;
+        public float Radius;
+        public BoundingBox BoundingBox;
+
+        WeakPtr Node;
+
+        // Accessors
+        public bool Animated { get { return animated != 0; } set { animated = (byte)(value ? 1 : 0); } }
+    }
+
+    public unsafe class Bone
+    {
+        // Keeps object which holds bone alive
+        readonly object objRefHolder;
+        readonly NativeBone* b;
+
+        public Bone(object objHolder, NativeBone* bone)
+        {
+            this.objRefHolder = objHolder;
+            this.b = bone;
+        }
+
+        public AtomicString Name { get { return b->Name; } set { b->Name = value; } }
+
+        public int NameHash { get { return b->NameHash; } set { b->NameHash = value; } }
+        public uint ParentIndex { get { return b->ParentIndex; } set { b->ParentIndex = value; } }
+        public Vector3 InitialPosition { get { return b->InitialPosition; } set { b->InitialPosition = value; } }
+        public Quaternion InitialRotation { get { return b->InitialRotation; } set { b->InitialRotation = value; } }
+        public Vector3 InitialScale { get { return b->InitialScale; } set { b->InitialScale = value; } }
+        public Matrix3x4 OffsetMatrix { get { return b->OffsetMatrix; } set { b->OffsetMatrix = value; } }
+        public bool Animated { get { return b->Animated; } set { b->Animated = value; } }
+        public byte CollisionMask { get { return b->CollisionMask; } set { b->CollisionMask = value; } }
+        public float Radius { get { return b->Radius; } set { b->Radius = value; } }
+        public BoundingBox BoundingBox { get { return b->BoundingBox; } set { b->BoundingBox = value; } }
+    }
+
+    public unsafe class Skeleton
+    {
+        public Skeleton(RefCounted owner, IntPtr nativeSkeleton)
+        {
+            this.owner = owner;
+            this.nativeSkeleton = nativeSkeleton;
+        }
+
+        /// Define from another skeleton.
+        public void Define(Skeleton src)
+        {
+            csi_Atomic_Skeleton_Define(nativeSkeleton, src.nativeSkeleton);
+        }
+        /// Set root bone's index.
+        public void SetRootBoneIndex(uint index)
+        {
+            csi_Atomic_Skeleton_SetRootBoneIndex(nativeSkeleton, index);
+        }
+
+        /// Clear bones.
+        public void ClearBones()
+        {
+            csi_Atomic_Skeleton_ClearBones(nativeSkeleton);
+        }
+
+        /// Reset all animating bones to initial positions.
+        public void Reset()
+        {
+            csi_Atomic_Skeleton_Reset(nativeSkeleton);
+        }
+
+        /// Return number of bones.
+        public uint GetNumBones()
+        {
+            return csi_Atomic_Skeleton_GetNumBones(nativeSkeleton);
+        }
+
+        /// Return root bone.
+        public Bone GetRootBone()
+        {
+            NativeBone* nativeBone = csi_Atomic_Skeleton_GetRootBone(nativeSkeleton);
+            return new Bone(this, nativeBone);
+        }
+
+        /// Return bone by index.
+        public Bone GetBone(uint index)
+        {
+            NativeBone* nativeBone = csi_Atomic_Skeleton_GetBone_ByIndex(nativeSkeleton, index);
+            return new Bone(this, nativeBone);
+        }
+
+        /// Return bone by name.
+        public Bone GetBone(string boneName)
+        {
+            NativeBone* nativeBone = csi_Atomic_Skeleton_GetBone_ByName(nativeSkeleton, boneName);
+            return new Bone(this, nativeBone);
+        }
+
+        /// Reset all animating bones to initial positions without marking the nodes dirty. Requires the node dirtying to be performed later.
+        public void ResetSilent()
+        {
+            csi_Atomic_Skeleton_ResetSilent(nativeSkeleton);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void csi_Atomic_Skeleton_Define(IntPtr self, IntPtr other);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void csi_Atomic_Skeleton_SetRootBoneIndex(IntPtr self, uint index);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void csi_Atomic_Skeleton_Reset(IntPtr self);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void csi_Atomic_Skeleton_ResetSilent(IntPtr self);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void csi_Atomic_Skeleton_ClearBones(IntPtr self);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern uint csi_Atomic_Skeleton_GetNumBones(IntPtr self);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern NativeBone* csi_Atomic_Skeleton_GetRootBone(IntPtr self);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern NativeBone* csi_Atomic_Skeleton_GetBone_ByIndex(IntPtr self, uint index);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        internal static extern NativeBone* csi_Atomic_Skeleton_GetBone_ByName(IntPtr self, string name);
+
+        RefCounted owner;
+        IntPtr nativeSkeleton;
+
+    }
+
+}

+ 28 - 0
Script/AtomicNET/AtomicNET/IO/Log.cs

@@ -0,0 +1,28 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public partial class Log : AObject
+    {
+
+        public static void Warn(string message)
+        {
+            Log.Write(Constants.LOG_WARNING, message);
+        }
+
+        public static void Error(string message)
+        {
+            Log.Write(Constants.LOG_ERROR, message);
+        }
+
+        public static void Info(string message)
+        {
+            Log.Write(Constants.LOG_INFO, message);
+        }
+
+    };
+
+}
+

+ 110 - 0
Script/AtomicNET/AtomicNET/Input/Controls.cs

@@ -0,0 +1,110 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public partial class Controls
+    {
+        // If null, we own the unmanaged value
+        // This is not-null when this is created from a pointer to another object, so we use this to keep the other object alive.
+        Connection connection;
+        internal IntPtr handle;
+
+        internal Controls(Connection connection, IntPtr handle)
+        {
+            this.connection = connection;
+            this.handle = handle;
+        }
+
+        public Controls()
+        {
+            handle = csi_Atomic_Controls_Create();
+            connection = null;
+        }
+
+        static void ReleaseControl(IntPtr h)
+        {
+            csi_Atomic_Controls_Destroy(h);
+        }
+
+        ~Controls()
+        {
+            if (connection == null)
+            {
+                ReleaseControl(handle);
+                handle = IntPtr.Zero;
+            }
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        extern static void csi_Atomic_Controls_Destroy(IntPtr handle);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        extern static IntPtr csi_Atomic_Controls_Create();
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        extern static uint csi_Atomic_Controls_GetButtons(IntPtr handle);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        extern static void csi_Atomic_Controls_SetButtons(IntPtr handle, uint value);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        extern static float csi_Atomic_Controls_GetYaw(IntPtr handle);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        extern static void csi_Atomic_Controls_SetYaw(IntPtr handle, float yaw);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        extern static float csi_Atomic_Controls_GetPitch(IntPtr handle);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        extern static void csi_Atomic_Controls_SetPitch(IntPtr handle, float yaw);
+
+        public uint Buttons
+        {
+            get { return csi_Atomic_Controls_GetButtons(handle); }
+            set { csi_Atomic_Controls_SetButtons(handle, value); }
+        }
+
+        public float Yaw
+        {
+            get { return csi_Atomic_Controls_GetYaw(handle); }
+            set { csi_Atomic_Controls_SetYaw(handle, value); }
+        }
+
+        public float Pitch
+        {
+            get { return csi_Atomic_Controls_GetPitch(handle); }
+            set { csi_Atomic_Controls_SetPitch(handle, value); }
+        }
+
+        public bool IsPressed(uint button, ref Controls previousControls)
+        {
+            return ((Buttons & button) != 0) && ((previousControls.Buttons & button) != 0);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void csi_Atomic_Controls_Reset(IntPtr handle);
+
+        public void Reset()
+        {
+            csi_Atomic_Controls_Reset(handle);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void csi_Atomic_Controls_Set(IntPtr handle, uint buttons, bool down);
+
+        public void Set(uint buttons, bool down)
+        {
+            csi_Atomic_Controls_Set(handle, buttons, down);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern bool csi_Atomic_Controls_IsDown(IntPtr handle, uint button);
+
+        public bool IsDown(uint button)
+        {
+            return csi_Atomic_Controls_IsDown(handle, button);
+        }
+    }
+}

+ 116 - 4
Script/AtomicNET/AtomicNET/Math/BoundingBox.cs

@@ -4,10 +4,122 @@ using System.Runtime.InteropServices;
 namespace AtomicEngine
 {
 
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+    public struct BoundingBox
+    {
+        public Vector3 Min;
+        public float DummyMin;
+        public Vector3 Max;
+        public float DummyMax;
 
-[StructLayout (LayoutKind.Sequential, CharSet = CharSet.Ansi)]
-public struct BoundingBox
-{
-}
+        public BoundingBox(float min, float max)
+        {
+            DummyMax = 0;
+            DummyMin = 0;
+            Min = new Vector3(min, min, min);
+            Max = new Vector3(max, max, max);
+        }
+
+        public BoundingBox(Vector3 min, Vector3 max)
+        {
+            DummyMax = 0;
+            DummyMin = 0;
+            Min = min;
+            Max = max;
+        }
+
+        public void Merge(Vector3 point)
+        {
+            if (point.X < Min.X)
+                Min.X = point.X;
+            if (point.Y < Min.Y)
+                Min.Y = point.Y;
+            if (point.Z < Min.Z)
+                Min.Z = point.Z;
+            if (point.X > Max.X)
+                Max.X = point.X;
+            if (point.Y > Max.Y)
+                Max.Y = point.Y;
+            if (point.Z > Max.Z)
+                Max.Z = point.Z;
+        }
+
+        public void Merge(BoundingBox box)
+        {
+            if (box.Min.X < Min.X)
+                Min.X = box.Min.X;
+            if (box.Min.Y < Min.Y)
+                Min.Y = box.Min.Y;
+            if (box.Min.Z < Min.Z)
+                Min.Z = box.Min.Z;
+            if (box.Max.X > Max.X)
+                Max.X = box.Max.X;
+            if (box.Max.Y > Max.Y)
+                Max.Y = box.Max.Y;
+            if (box.Max.Z > Max.Z)
+                Max.Z = box.Max.Z;
+        }
+
+        public bool Defined()
+        {
+            return Min.X != float.PositiveInfinity;
+        }
+
+        public Vector3 Center
+        {
+            get
+            {
+                return (Max + Min) * 0.5f;
+            }
+        }
+
+        public Vector3 Size
+        {
+            get
+            {
+                return Max - Min;
+            }
+        }
+        public Vector3 HalfSize
+        {
+            get
+            {
+                return (Max - Min) * 0.5f;
+            }
+        }
+
+        public Intersection IsInside(Vector3 point)
+        {
+            if (point.X < Min.X || point.X > Max.X ||
+                point.Y < Min.Y || point.Y > Max.Y ||
+                point.Z < Min.Z || point.Z > Max.Z)
+                return Intersection.OUTSIDE;
+            return Intersection.INSIDE;
+        }
+
+        public Intersection IsInside(BoundingBox box)
+        {
+            if (box.Max.X < Min.X || box.Min.X > Max.X ||
+                box.Max.Y < Min.Y || box.Min.Y > Max.Y ||
+                box.Max.Z < Min.Z || box.Min.Z > Max.Z)
+                return Intersection.OUTSIDE;
+            else if (box.Min.X < Min.X || box.Max.X > Max.X ||
+                     box.Min.Y < Min.Y || box.Max.Y > Max.Y ||
+                     box.Min.Z < Min.Z || box.Max.Z > Max.Z)
+                return Intersection.INTERSECTS;
+            else
+                return Intersection.INSIDE;
+        }
+
+        public Intersection IsInsideFast(BoundingBox box)
+        {
+            if (box.Max.X < Min.X || box.Min.X > Max.X ||
+                box.Max.Y < Min.Y || box.Min.Y > Max.Y ||
+                box.Max.Z < Min.Z || box.Min.Z > Max.Z)
+                return Intersection.OUTSIDE;
+            else
+                return Intersection.INSIDE;
+        }
+    }
 
 }

+ 11 - 7
Script/AtomicNET/AtomicNET/Math/Color.cs

@@ -24,13 +24,17 @@ namespace AtomicEngine
             return (a << 24) | (b << 16) | (g << 8) | r;
         }
 
-
-        public static readonly Color White = new Color(1, 1, 1, 1);
-        public static readonly Color Red = new Color(1, 0, 0, 1);
-        public static readonly Color Blue = new Color(0, 1, 0, 1);
-        public static readonly Color Green = new Color(0, 0, 1, 1);
+        public static readonly Color White = new Color(1, 1, 1);
+        public static readonly Color Gray = new Color(0.5f, 0.5f, 0.5f);
+        public static readonly Color Black = new Color(0.0f, 0.0f, 0.0f);
+        public static readonly Color Red = new Color(1.0f, 0.0f, 0.0f);
+        public static readonly Color Green = new Color(0.0f, 1.0f, 0.0f);
+        public static readonly Color Blue = new Color(0.0f, 0.0f, 1.0f);
+        public static readonly Color Cyan = new Color(0.0f, 1.0f, 1.0f);
+        public static readonly Color Magenta = new Color(1.0f, 0.0f, 1.0f);
+        public static readonly Color Yellow = new Color(1.0f, 1.0f, 0.0f);
         public static readonly Color LightBlue = new Color(0.50f, 0.88f, 0.81f);
-        public static readonly Color Transparent = new Color(0, 0, 0, 0);
+        public static readonly Color Transparent = new Color(0.0f, 0.0f, 0.0f, 0.0f);
 
         public static Color operator *(Color value, float scale)
         {
@@ -54,4 +58,4 @@ namespace AtomicEngine
         public float A;
 
     }
-}
+}

+ 58 - 30
Script/AtomicNET/AtomicNET/Math/Matrix3x4.cs

@@ -4,43 +4,71 @@ using System.Runtime.InteropServices;
 namespace AtomicEngine
 {
 
-    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+    [StructLayout(LayoutKind.Sequential)]
     public struct Matrix3x4
     {
-        static public Matrix3x4 IDENTITY = CreateIdentity();
+        public float m00;
+        public float m01;
+        public float m02;
+        public float m03;
+        public float m10;
+        public float m11;
+        public float m12;
+        public float m13;
+        public float m20;
+        public float m21;
+        public float m22;
+        public float m23;
 
-        static Matrix3x4 CreateIdentity()
+        public Matrix3x4 Inverse()
         {
-            var m = new Matrix3x4();
-            m.m00_ = 1.0f;
-            m.m01_ = 0.0f;
-            m.m02_ = 0.0f;
-            m.m03_ = 0.0f;
-            m.m10_ = 0.0f;
-            m.m11_ = 1.0f;
-            m.m12_ = 0.0f;
-            m.m13_ = 0.0f;
-            m.m20_ = 0.0f;
-            m.m21_ = 0.0f;
-            m.m22_ = 1.0f;
-            m.m23_ = 0.0f;
-            return m;
+            float det = m00 * m11 * m22 +
+                m10 * m21 * m02 +
+                m20 * m01 * m12 -
+                m20 * m11 * m02 -
+                m10 * m01 * m22 -
+                m00 * m21 * m12;
 
-        }
+            float invDet = 1.0f / det;
+            Matrix3x4 ret;
+
+            ret.m00 = (m11 * m22 - m21 * m12) * invDet;
+            ret.m01 = -(m01 * m22 - m21 * m02) * invDet;
+            ret.m02 = (m01 * m12 - m11 * m02) * invDet;
+            ret.m03 = -(m03 * ret.m00 + m13 * ret.m01 + m23 * ret.m02);
+            ret.m10 = -(m10 * m22 - m20 * m12) * invDet;
+            ret.m11 = (m00 * m22 - m20 * m02) * invDet;
+            ret.m12 = -(m00 * m12 - m10 * m02) * invDet;
+            ret.m13 = -(m03 * ret.m10 + m13 * ret.m11 + m23 * ret.m12);
+            ret.m20 = (m10 * m21 - m20 * m11) * invDet;
+            ret.m21 = -(m00 * m21 - m20 * m01) * invDet;
+            ret.m22 = (m00 * m11 - m10 * m01) * invDet;
+            ret.m23 = -(m03 * ret.m20 + m13 * ret.m21 + m23 * ret.m22);
 
-        float m00_;
-        float m01_;
-        float m02_;
-        float m03_;
-        float m10_;
-        float m11_;
-        float m12_;
-        float m13_;
-        float m20_;
-        float m21_;
-        float m22_;
-        float m23_;
+            return ret;
+        }
 
+        public static Matrix4 operator *(Matrix4 left, Matrix3x4 rhs)
+        {
+            return new Matrix4(
+                left.M11 * rhs.m00 + left.M12 * rhs.m10 + left.M13 * rhs.m20,
+                left.M11 * rhs.m01 + left.M12 * rhs.m11 + left.M13 * rhs.m21,
+                left.M11 * rhs.m02 + left.M12 * rhs.m12 + left.M13 * rhs.m22,
+                left.M11 * rhs.m03 + left.M12 * rhs.m13 + left.M13 * rhs.m23 + left.M14,
+                left.M21 * rhs.m00 + left.M22 * rhs.m10 + left.M23 * rhs.m20,
+                left.M21 * rhs.m01 + left.M22 * rhs.m11 + left.M23 * rhs.m21,
+                left.M21 * rhs.m02 + left.M22 * rhs.m12 + left.M23 * rhs.m22,
+                left.M21 * rhs.m03 + left.M22 * rhs.m13 + left.M23 * rhs.m23 + left.M24,
+                left.M31 * rhs.m00 + left.M32 * rhs.m10 + left.M33 * rhs.m20,
+                left.M31 * rhs.m01 + left.M32 * rhs.m11 + left.M33 * rhs.m21,
+                left.M31 * rhs.m02 + left.M32 * rhs.m12 + left.M33 * rhs.m22,
+                left.M31 * rhs.m03 + left.M32 * rhs.m13 + left.M33 * rhs.m23 + left.M34,
+                left.M41 * rhs.m00 + left.M42 * rhs.m10 + left.M43 * rhs.m20,
+                left.M41 * rhs.m01 + left.M42 * rhs.m11 + left.M43 * rhs.m21,
+                left.M41 * rhs.m02 + left.M42 * rhs.m12 + left.M43 * rhs.m22,
+                left.M41 * rhs.m03 + left.M42 * rhs.m13 + left.M43 * rhs.m23 + left.M44
+            );
+        }
     }
 
 

+ 47 - 0
Script/AtomicNET/AtomicNET/Navigation/CrowdManager.cs

@@ -0,0 +1,47 @@
+
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    [StructLayout(LayoutKind.Sequential)]
+    public struct CrowdObstacleAvoidanceParams
+    {
+        public float VelBias;
+        public float WeightDesVel;
+        public float WeightCurVel;
+        public float WeightSide;
+        public float WeightToi;
+        public float HorizTime;
+        public byte GridSize;
+        public byte AdaptiveDivs;
+        public byte AdaptiveRings;
+        public byte AdaptiveDepth;
+    };
+
+    public partial class CrowdManager : Component
+    {
+        public CrowdObstacleAvoidanceParams GetObstacleAvoidanceParams(uint obstacleAvoidanceType)
+        {
+            CrowdObstacleAvoidanceParams parms = new CrowdObstacleAvoidanceParams();
+            csi_Atomic_CrowdManager_GetObstacleAvoidanceParams(nativeInstance, obstacleAvoidanceType, ref parms);
+            return parms;
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void csi_Atomic_CrowdManager_GetObstacleAvoidanceParams(IntPtr self,  uint obstacleAvoidanceType, ref CrowdObstacleAvoidanceParams parms);
+
+        public void SetObstacleAvoidanceParams(uint obstacleAvoidanceType, CrowdObstacleAvoidanceParams parms)
+        {
+            csi_Atomic_CrowdManager_SetObstacleAvoidanceParams(nativeInstance, obstacleAvoidanceType, ref parms);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern void csi_Atomic_CrowdManager_SetObstacleAvoidanceParams(IntPtr self, uint obstacleAvoidanceType, ref CrowdObstacleAvoidanceParams parms);
+
+
+    }
+
+}

+ 58 - 0
Script/AtomicNET/AtomicNET/Navigation/NavigationMesh.cs

@@ -0,0 +1,58 @@
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public partial class NavigationMesh : Component
+    {
+
+        public bool FindPath(List<Vector3> results, Vector3 start, Vector3 end)
+        {
+            return FindPath(results, start, end, Vector3.One);
+
+        }
+
+        public bool FindPath(List<Vector3> results, Vector3 start, Vector3 end, Vector3 extents)
+        {
+
+            results.Clear();
+
+            int count;
+            IntPtr resultVector;
+
+            var ptr = csi_Atomic_NavigationMesh_FindPath(nativeInstance, ref start, ref end, ref extents, out resultVector, out count);
+
+            if (ptr == IntPtr.Zero)
+            {
+                return false;
+            }
+
+            int structSize = Marshal.SizeOf(typeof(Vector3));
+
+            for (int i = 0; i < count; i++)
+            {
+                IntPtr data = new IntPtr(ptr.ToInt64() + structSize * i);
+                Vector3 v3 = (Vector3)Marshal.PtrToStructure(data, typeof(Vector3));
+                results.Add(v3);
+            }
+
+            csi_Atomic_NavigationMesh_FindPath_FreeResult(resultVector);
+
+            return true;
+
+        }
+
+        // Any resultVector returned here, must be freed with csi_Atomic_Octree_Raycast_FreeResult
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern IntPtr csi_Atomic_NavigationMesh_FindPath(IntPtr self, ref Vector3 start, ref Vector3 end, ref Vector3 extents, out IntPtr resultVector, out int count);
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern IntPtr csi_Atomic_NavigationMesh_FindPath_FreeResult(IntPtr resultVector);
+
+
+    };
+
+}
+

+ 31 - 0
Script/AtomicNET/AtomicNET/Physics/PhysicsWorld.cs

@@ -0,0 +1,31 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    [StructLayout(LayoutKind.Sequential)]
+    public struct PhysicsRaycastResult
+    {
+        public Vector3 Position;
+        public Vector3 Normal;
+        public float Distance;
+        public float HitFraction;
+
+        IntPtr bodyPtr;
+        public RigidBody Body => NativeCore.WrapNative<RigidBody>(bodyPtr);
+    }
+
+    public partial class PhysicsWorld : Component
+    {
+        public void RaycastSingle(ref PhysicsRaycastResult result, Ray ray, float maxDistance, uint collisionMask = uint.MaxValue)
+        {
+            csi_Atomic_PhysicsWorld_RaycastSingle(nativeInstance, ref ray, maxDistance, collisionMask, out result);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
+        internal static extern IntPtr csi_Atomic_PhysicsWorld_RaycastSingle(IntPtr self, ref Ray ray, float maxDistance, uint collisionMask, out PhysicsRaycastResult result);
+
+    }
+
+}

+ 5 - 0
Script/AtomicNET/AtomicNET/Resource/ResourceCache.cs

@@ -9,6 +9,11 @@ namespace AtomicEngine
             return (T) GetResource(typeof(T).Name, path);
         }
 
+        public T Get<T>(string path) where T : Resource
+        {
+            return (T)GetResource(typeof(T).Name, path);
+        }
+
     }
 
 }

+ 7 - 0
Script/AtomicNET/AtomicNET/Scene/CSComponent.cs

@@ -10,6 +10,13 @@ namespace AtomicEngine
             return GetType().Name;
         }
 
+        public bool Started
+        {
+            get { return started; }
+        }
+
+        internal bool started = false;
+
     }
 
 }

+ 18 - 183
Script/AtomicNET/AtomicNET/Scene/CSComponentCore.cs

@@ -43,8 +43,11 @@ namespace AtomicEngine
             Type[] postUpdateParms = new Type[1] { typeof(float) };
             PostUpdateMethod = type.GetMethod("PostUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, postUpdateParms, null);
 
-            Type[] fixedUpdateParms = new Type[1] { typeof(float) };
-            FixedUpdateMethod = type.GetMethod("FixedUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, fixedUpdateParms, null);
+            Type[] physicsPreStepParms = new Type[1] { typeof(float) };
+            PhysicsPreStepMethod = type.GetMethod("PhysicsPreStep", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, physicsPreStepParms, null);
+
+            Type[] physicsPostStepParms = new Type[1] { typeof(float) };
+            PhysicsPostStepMethod = type.GetMethod("PhysicsPostStep", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, physicsPostStepParms, null);
 
             Type[] startParms = new Type[0] { };
             StartMethod = type.GetMethod("Start", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, startParms, null);
@@ -118,136 +121,22 @@ namespace AtomicEngine
 
         }
 
-        public void RegisterInstance(CSComponent component)
-        {
-            Instances.Add(component);
-
-            if (StartMethod != null)
-            {
-                StartList.Add(component);
-            }
-
-        }
-
-        public void FixedUpdate(Object[] args)
-        {
-            if (FixedUpdateMethod == null)
-                return;
-
-            foreach (var instance in Instances)
-            { 
-                var node = instance.Node;
-
-                if (node != null && node.IsEnabled())
-                {
-
-                    if (node.Scene != null)
-                    {
-                        FixedUpdateMethod.Invoke(instance, args);
-                    }
-                }
-            }
-        }
-
-        public void PostUpdate(Object[] args)
-        {
-            if (PostUpdateMethod == null)
-                return;
-
-            foreach (var instance in Instances)
-            {
-                var node = instance.Node;
-
-                if (node != null && node.IsEnabled())
-                {
-
-                    if (node.Scene != null)
-                    {
-                        PostUpdateMethod.Invoke(instance, args);
-                    }
-                }
-            }
-        }
-
-
-        public void Update(Object[] args)
-        {
-            if (StartMethod != null)
-            {
-                foreach (var instance in StartList)
-                {
-                    var node = instance.Node;
-
-                    if (node != null && node.IsEnabled())
-                    {
-                        if (node.Scene != null)
-                        {
-                            StartMethod.Invoke(instance, null);
-                        }
-                    }
-
-                }
-
-                // TODO: need to handle delayed starts when node isn't enabled
-                StartList.Clear();
-
-            }
-
-            if (UpdateMethod != null)
-            {
-                foreach (var instance in Instances)
-                {
-                    bool remove = false;
-
-                    var node = instance.Node;
-
-                    // TODO: Ideally we want to remove disabled instances,
-                    // and re-add them when re-enabled
-                    if (node != null /*&& node.IsEnabled()*/)
-                    {
-
-                        if (node.Scene != null)
-                        {
-                            if (node.IsEnabled())
-                                UpdateMethod.Invoke(instance, args);
-                        }
-                        else
-                        {
-                            remove = true;
-                        }
-                    }
-                    else
-                    {
-                        remove = true;
-                    }
-
-                    if (remove)
-                        RemoveList.Add(instance);
-                }
-            }
-
-            foreach (var instance in RemoveList)
-            {
-                Instances.Remove(instance);                
-            }
-
-            RemoveList.Clear();
-        }
-
-        public List<CSComponent> Instances = new List<CSComponent>();
-        public List<CSComponent> StartList = new List<CSComponent>();
-
-        public List<CSComponent> RemoveList = new List<CSComponent>();
-
         public FieldInfo[] InspectorFields;
         public Type Type;
 
-        public MethodInfo FixedUpdateMethod = null;
-        public MethodInfo PostUpdateMethod = null;
-        public MethodInfo UpdateMethod = null;        
+        // Start method called once
         public MethodInfo StartMethod = null;
-        
 
+        // Update called first
+        public MethodInfo UpdateMethod = null;
+
+        // Physics steps if any
+        public MethodInfo PhysicsPreStepMethod = null;
+        public MethodInfo PhysicsPostStepMethod = null;
+
+        // Post Update
+        public MethodInfo PostUpdateMethod = null;
+                
         ScriptVariantMap fieldMap = new ScriptVariantMap();
 
         public Dictionary<uint, FieldInfo> fieldLookup = new Dictionary<uint, FieldInfo>();
@@ -256,46 +145,6 @@ namespace AtomicEngine
     public class CSComponentCore : NETScriptObject
     {
 
-        public static void RegisterInstance(CSComponent component)
-        {
-            instance.csinfoLookup[component.GetType()].RegisterInstance(component);
-        }
-
-        void HandleUpdate(uint eventType, ScriptVariantMap eventData)
-        {
-            Object[] args = new Object[1] { eventData.GetFloat("timestep") };
-
-            foreach (var csinfo in csinfoLookup.Values)
-            {
-                csinfo.Update(args);
-            }
-
-        }
-
-        void HandlePhysicsPreStep(uint eventType, ScriptVariantMap eventData)
-        {
-            // TODO: eventData also has a PhysicsWorld pointer, which could be factored in for multiworld support
-
-            Object[] args = new Object[1] { eventData.GetFloat("timestep") };
-
-            foreach (var csinfo in csinfoLookup.Values)
-            {
-                csinfo.FixedUpdate(args);
-            }
-
-        }
-
-        void HandlePostUpdate(uint eventType, ScriptVariantMap eventData)
-        {
-            Object[] args = new Object[1] { eventData.GetFloat("timestep") };
-
-            foreach (var csinfo in csinfoLookup.Values)
-            {
-                csinfo.PostUpdate(args);
-            }
-
-        }
-
         void HandleComponentLoad(uint eventType, ScriptVariantMap eventData)
         {
             var className = eventData["ClassName"];
@@ -319,22 +168,14 @@ namespace AtomicEngine
 
             if (fieldValues != IntPtr.Zero)
                 csinfo.ApplyFieldValues(component, fieldValues);
-
-            csinfo.RegisterInstance(component);
-
         }
 
         [Obsolete("Method HandleComponentAssemblyReference is deprecated (loading component assemblies at runtime, will be changed to preload them)")]
         void HandleComponentAssemblyReference(uint eventType, ScriptVariantMap eventData)
         {
-#if ATOMIC_DESKTOP || ATOMIC_MOBILE
             string assemblyPath = eventData["AssemblyPath"];
             string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
-
-            Assembly assembly = Assembly.LoadFrom(assemblyPath);
-
-            ParseAssembly(assembly);
-#endif
+            Log.Info($"Component Assembly referenced {assemblyName} ");
         }
 
         void ParseComponents()
@@ -383,12 +224,6 @@ namespace AtomicEngine
 
             instance.SubscribeToEvent("CSComponentAssemblyReference", instance.HandleComponentAssemblyReference);
             instance.SubscribeToEvent("CSComponentLoad", instance.HandleComponentLoad);
-            instance.SubscribeToEvent("Update", instance.HandleUpdate);
-
-            // PhysicsPreStep gets mapped to FixedUpdate
-            instance.SubscribeToEvent("PhysicsPreStep", instance.HandlePhysicsPreStep);
-
-            instance.SubscribeToEvent("PostUpdate", instance.HandlePostUpdate);
 
         }
 
@@ -398,7 +233,7 @@ namespace AtomicEngine
         [Obsolete("Member parsedAssemblies is temporarily required for runtime component assemblies loading")]
         Dictionary<Assembly, bool> parsedAssemblies = new Dictionary<Assembly, bool>();
 
-        Dictionary<Type, CSComponentInfo> csinfoLookup = new Dictionary<Type, CSComponentInfo>();
+        internal static Dictionary<Type, CSComponentInfo> csinfoLookup = new Dictionary<Type, CSComponentInfo>();
 
         static CSComponentCore instance;
     }

+ 15 - 0
Script/AtomicNET/AtomicNET/Scene/Component.cs

@@ -0,0 +1,15 @@
+using System;
+namespace AtomicEngine
+{
+
+    public partial class Component : Animatable
+    {
+
+        public T GetComponent<T>(bool recursive = false) where T : Component
+        {
+            return Node.GetComponent<T>(recursive);
+        }
+
+    }
+
+}

+ 24 - 1
Script/AtomicNET/AtomicNET/Scene/Node.cs

@@ -9,6 +9,25 @@ namespace AtomicEngine
     public partial class Node : Animatable
     {
 
+        public void RemoveComponent<T>() where T : Component
+        {
+            var type = typeof(T);
+
+            var name = type.Name;
+
+            // TODO: This doesn't allow removing of a specific component type derived from CSComponent
+            if (type.GetTypeInfo().IsSubclassOf(typeof(CSComponent)))
+            {
+                name = "CSComponent";
+
+                throw new InvalidOperationException("Node.RemoveComponent - Add functionality to remove specific CSComponent derived instances");
+            }
+
+            RemoveComponent(name);
+
+        }
+
+
         public T CreateComponent<T>(CreateMode mode = CreateMode.REPLICATED, uint id = 0) where T : Component
         {
             var type = typeof(T);
@@ -16,7 +35,6 @@ namespace AtomicEngine
             if (type.GetTypeInfo().IsSubclassOf(typeof(CSComponent)))
             {
                 Component component = (Component)Activator.CreateInstance(type);
-                CSComponentCore.RegisterInstance((CSComponent)component);
                 AddComponent(component, id, mode);
                 return (T)component;
             }
@@ -24,6 +42,11 @@ namespace AtomicEngine
             return (T)CreateComponent(type.Name, mode, id);
         }
 
+        public void AddComponent(Component component)
+        {
+            var type = component.GetType();
+            AddComponent(component, 0, CreateMode.REPLICATED);
+        }
 
         public void GetChildrenWithComponent<T>(Vector<Node> dest, bool recursive = false)
         {

+ 304 - 0
Script/AtomicNET/AtomicNET/Scene/Scene.cs

@@ -0,0 +1,304 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using static System.Reflection.IntrospectionExtensions;
+
+namespace AtomicEngine
+{
+    public partial class Scene : Node
+    {
+        internal override void PostNativeUpdate()
+        {    
+            SubscribeToEvent<NodeAddedEvent>(this, e =>
+            {
+                //Log.Info($"Node ADDED: {e.Node.Name}");
+
+            });
+
+            SubscribeToEvent<NodeRemovedEvent>(this, e =>
+            {
+                //Log.Info($"Node REMOVED: {e.Node.Name}");
+
+            });
+
+            SubscribeToEvent<ComponentAddedEvent>(this, HandleComponentAdded);
+            SubscribeToEvent<ComponentRemovedEvent>(this, HandleComponentRemoved);
+
+            // Update variable timestep logic
+            SubscribeToEvent<SceneUpdateEvent>(this, HandleSceneUpdate);
+
+            // Update scene subsystems. If a physics world is present, it will be updated, triggering fixed timestep logic updates
+            SubscribeToEvent<SceneSubsystemUpdateEvent>(this, HandleSceneSubsystemUpdate);
+
+            // Update transform smoothing
+            SubscribeToEvent<UpdateSmoothingEvent>(this, HandleUpdateSmoothing);
+
+            // Post-update variable timestep logic
+            SubscribeToEvent<ScenePostUpdateEvent>(this, HandleScenePostUpdate);
+
+        }
+
+        // Update variable timestep logic
+        void HandleSceneUpdate(SceneUpdateEvent e)
+        {            
+            // Handle Start
+            if (cscomponentStart.Count > 0)
+            {
+                var newList = new List<CSComponent>();
+                foreach (var csc in cscomponentStart)
+                {
+                    if (!csc.IsEnabled())
+                    {
+                        newList.Add(csc);
+                        continue;
+                    }
+
+                    // mark as started whether or not a Start method exists
+                    csc.started = true;
+
+                    CSComponentInfo info;
+                    if (CSComponentCore.csinfoLookup.TryGetValue(csc.GetType(), out info))
+                    {
+                        if (info.StartMethod != null)
+                        {
+                            info.StartMethod.Invoke(csc, null);
+                        }
+                    }
+
+                }
+
+                cscomponentStart = newList;
+            }
+
+            // Handle Scene Update
+
+            Object[] args = new Object[1] { e.TimeStep };
+
+            foreach (var item in cscomponents)
+            {
+                var info = item.Key;
+
+                var UpdateMethod = info.UpdateMethod;
+
+                if (UpdateMethod == null)
+                    continue;
+
+                foreach (var csc in item.Value)
+                {
+                    if (!csc.Started || !csc.IsEnabled())
+                        continue;
+
+                    UpdateMethod.Invoke(csc, args);
+                }
+                
+            }
+
+        }
+
+        // Update scene subsystems. If a physics world is present, it will be updated, triggering fixed timestep logic updates
+        void HandleSceneSubsystemUpdate(SceneSubsystemUpdateEvent e)
+        {
+        }
+
+        // Update transform smoothing
+        void HandleUpdateSmoothing(UpdateSmoothingEvent e)
+        {
+        }
+
+        // Post-update variable timestep logic
+        void HandleScenePostUpdate(ScenePostUpdateEvent e)
+        {
+            Object[] args = new Object[1] { e.TimeStep };
+
+            foreach (var item in cscomponents)
+            {
+                var info = item.Key;
+
+                var PostUpdateMethod = info.PostUpdateMethod;
+
+                if (PostUpdateMethod == null)
+                    continue;
+
+                foreach (var csc in item.Value)
+                {
+                    if (!csc.Started || !csc.IsEnabled())
+                        continue;
+
+                    PostUpdateMethod.Invoke(csc, args);
+                }
+
+            }
+
+        }
+
+        void HandlePhysicsPreStep(PhysicsPreStepEvent e)
+        {
+            Object[] args = new Object[1] { e.TimeStep };
+
+            foreach (var item in cscomponents)
+            {
+                var info = item.Key;
+
+                var PhysicsPreStepMethod = info.PhysicsPreStepMethod;
+
+                if (PhysicsPreStepMethod == null)
+                    continue;
+
+                foreach (var csc in item.Value)
+                {
+                    if (!csc.Started || !csc.IsEnabled())
+                        continue;
+
+                    PhysicsPreStepMethod.Invoke(csc, args);
+                }
+
+            }
+        }
+
+        void HandlePhysicsPostStep(PhysicsPostStepEvent e)
+        {
+            Object[] args = new Object[1] { e.TimeStep };
+
+            foreach (var item in cscomponents)
+            {
+                var info = item.Key;
+
+                var PhysicsPostStepMethod = info.PhysicsPostStepMethod;
+
+                if (PhysicsPostStepMethod == null)
+                    continue;
+
+                foreach (var csc in item.Value)
+                {
+                    if (!csc.Started || !csc.IsEnabled())
+                        continue;
+
+                    PhysicsPostStepMethod.Invoke(csc, args);
+                }
+
+            }
+        }
+
+        void HandleComponentRemoved(ComponentRemovedEvent e)
+        {
+            Component component;
+
+            try
+            {
+                // will throw if component isn't a known native
+                component = e.Component;
+            }
+            catch
+            {
+                return;
+            }
+
+            if (component.GetType() == typeof(PhysicsWorld) || component.GetType() == typeof(PhysicsWorld2D))
+            {
+                UnsubscribeFromEvent<PhysicsPreStepEvent>();
+                UnsubscribeFromEvent<PhysicsPostStepEvent>();
+            }
+
+            if (component.GetType().GetTypeInfo().IsSubclassOf(typeof(CSComponent)))
+            {
+                var csc = (CSComponent)component;
+
+                CSComponentInfo info;
+                if (!CSComponentCore.csinfoLookup.TryGetValue(csc.GetType(), out info))
+                {
+                    return;
+                }
+
+                cscomponentStart.Remove(csc);
+
+                List<CSComponent> cslist;
+
+                if (!cscomponents.TryGetValue(info, out cslist))
+                {
+                    return;
+                }
+
+                cslist.Remove(csc);
+
+            }
+
+        }
+
+        void HandleComponentAdded(ComponentAddedEvent e)
+        {
+            Component component;
+
+            try
+            {
+                // will throw if component isn't a known native
+                component = e.Component;
+            }
+            catch
+            {
+                return;
+            }
+            
+
+            if (component == null)
+            {
+                Log.Error("Scene.HandleComponentAdded - null component");
+                return;
+            }
+
+            // Log.Info($"Component {component.TypeName} ADDED From Node {e.Node.Name}");
+
+            if (component.GetType() == typeof(PhysicsWorld) || component.GetType() == typeof(PhysicsWorld2D))
+            {
+                SubscribeToEvent<PhysicsPreStepEvent>(component, HandlePhysicsPreStep);
+                SubscribeToEvent<PhysicsPostStepEvent>(component, HandlePhysicsPostStep);
+            }
+
+            // CSComponent
+            if (component.GetType().GetTypeInfo().IsSubclassOf(typeof(CSComponent)))
+            {
+                var csc = (CSComponent)component;
+
+                CSComponentInfo info;
+
+                if (!CSComponentCore.csinfoLookup.TryGetValue(component.GetType(), out info))
+                {
+                    Log.Error("Scene.HandleComponentAdded - unable to get CSComponentInfo");
+                    return;
+                }
+
+                List<CSComponent> cslist;
+
+                if (!cscomponents.TryGetValue(info, out cslist))
+                {
+                    cslist = cscomponents[info] = new List<CSComponent>();
+                }
+
+                if (cslist.Contains(csc))
+                {
+                    throw new InvalidOperationException("Scene.HandleComponentAdded - CSComponent already added to component list");
+                }
+
+                cslist.Add(csc);
+
+                if (cscomponentStart.Contains(csc))
+                {
+                    throw new InvalidOperationException("Scene.HandleComponentAdded CSComponent already added to start list");
+                }
+
+                if (csc.started)
+                {
+                    throw new InvalidOperationException("Scene.HandleComponentAdded CSComponent already started");
+                }
+
+                cscomponentStart.Add(csc);
+
+            }
+
+        }
+
+        Dictionary<CSComponentInfo, List<CSComponent>> cscomponents = new Dictionary<CSComponentInfo, List<CSComponent>>();
+        List<CSComponent> cscomponentStart = new List<CSComponent>();        
+
+    }
+
+}

+ 22 - 0
Script/AtomicNET/AtomicNET/Scene/ValueAnimation.cs

@@ -0,0 +1,22 @@
+
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public partial class ValueAnimation : Resource
+    {
+        public bool SetKeyFrame(float time, ScriptVariant variant)
+        {
+            return csi_Atomic_ValueAnimation_SetKeyFrame(nativeInstance, time, variant.nativeInstance);
+        }
+
+        [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+        [return: MarshalAs(UnmanagedType.I1)]
+        private static extern bool csi_Atomic_ValueAnimation_SetKeyFrame(IntPtr self, float time, IntPtr variant);
+
+    }
+
+}
+

+ 42 - 0
Script/AtomicNET/AtomicNET/Script/ScriptVariant.cs

@@ -0,0 +1,42 @@
+
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace AtomicEngine
+{
+    public partial class ScriptVariant : RefCounted
+    {
+        public ScriptVariant(Vector2 value) :this()
+        {
+            SetVector2(value);
+        }
+
+        public ScriptVariant(Vector3 value) : this()
+        {
+            SetVector3(value);
+        }
+
+        public ScriptVariant(Color value) : this()
+        {
+            SetColor(value);
+        }
+
+        public static implicit operator ScriptVariant(Vector2 value)  // Vector2
+        {
+            return new ScriptVariant(value);
+        }
+
+        public static implicit operator ScriptVariant(Vector3 value)  // Vector2
+        {
+            return new ScriptVariant(value);
+        }
+
+        public static implicit operator ScriptVariant(Color value)  // Vector2
+        {
+            return new ScriptVariant(value);
+        }
+    }
+
+}
+

+ 7 - 4
Script/AtomicNET/AtomicNET/Script/ScriptVariantMap.cs

@@ -1,8 +1,10 @@
 
 
 using System;
+using System.Reflection;
 using System.Runtime.InteropServices;
 
+
 namespace AtomicEngine
 {
     public partial class ScriptVariantMap : RefCounted
@@ -26,11 +28,11 @@ namespace AtomicEngine
             if (value == null)
                 return null;
 
-            // TODO: allow derived classes, throw error
-            if (value.GetType().Name != typeof(T).Name)
-                return null;
+            // TODO: warn on mismatch?
+            if (value.GetType() == typeof(T) || value.GetType().GetTypeInfo().IsSubclassOf(typeof(T)))
+                return (T) value;
 
-            return (T) value;            
+            return null;            
         }
 
         public IntPtr GetVoidPtr(string key)
@@ -42,5 +44,6 @@ namespace AtomicEngine
         private static extern IntPtr csi_Atomic_AtomicNET_ScriptVariantMap_GetVoidPtr(IntPtr self, string key);
 
     }
+
 }
 

+ 52 - 0
Script/AtomicNET/AtomicNET/UI/UIWidget.cs

@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using static System.Reflection.IntrospectionExtensions;
+
+namespace AtomicEngine
+{
+    public partial class WidgetEvent : NativeEventData
+    {
+        public bool Handled
+        {
+            get
+            {
+                return GetHandled();
+            }
+            set
+            {
+                SetHandled(value);
+            }
+        }
+
+        public bool GetHandled()
+        {
+            return scriptMap.GetBool("Handled");
+        }
+
+
+        public void SetHandled(bool handled = true)
+        {
+            scriptMap.SetBool("Handled", true); // this isn't great, though syncs up for future reads
+            // sets the native event data
+            Set("Handled", handled);
+        }
+    }
+
+    public partial class UIWidget : AObject
+    {
+        static Dictionary<IntPtr, UIWidget> widgets = new Dictionary<IntPtr, UIWidget>();
+
+        internal override void PostNativeUpdate()
+        {
+            widgets[nativeInstance] = this;
+
+            SubscribeToEvent<WidgetDeletedEvent>(this, e =>
+            {
+                widgets.Remove(nativeInstance);
+
+            });
+        }
+    }
+
+}

+ 5 - 0
Script/Packages/Atomic/Core.json

@@ -8,6 +8,11 @@
 	"excludes" : {
 		"Object" : {
 			"SendEvent" : ["StringHash"]
+		},
+		"CSharp" : {
+			"Object" : {
+				"UnsubscribeFromAllEvents" : []
+			}
 		}
 	},
 	"overloads" : {

+ 1 - 1
Script/Packages/Atomic/Navigation.json

@@ -3,7 +3,7 @@
 	"requires" : ["3D"],
 	"sources" : ["Source/Atomic/Navigation"],
 	"includes" : ["<Atomic/Scene/Node.h>"],
-	"classes" : ["Navigable", "NavigationMesh", "OffMeshConnection"],
+	"classes" : ["Navigable", "NavigationMesh", "DynamicNavigationMesh", "NavArea", "OffMeshConnection", "Obstacle", "CrowdAgent", "CrowdManager"],
 	"overloads" : {
 		"NavigationMesh" : {
 			"Build" : []

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

@@ -1,5 +1,5 @@
 {
 	"name" : "Script",
 	"sources" : ["Source/Atomic/Script"],
-	"classes" : ["ScriptVariantMap", "ScriptVector", "ScriptComponent", "ScriptComponentFile", "PhysicsContact", "PhysicsNodeCollision"]
+	"classes" : ["ScriptVariant", "ScriptVariantMap", "ScriptVector", "ScriptComponent", "ScriptComponentFile", "PhysicsContact", "PhysicsNodeCollision"]
 }

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

@@ -53,6 +53,9 @@ RefCounted::~RefCounted()
         delete refCount_;
 
     refCount_ = 0;
+
+    for (unsigned i = 0; i < refCountedDeletedFunctions_.Size(); i++)
+        refCountedDeletedFunctions_[i](this);
 }
 
 void RefCounted::AddRef()
@@ -109,6 +112,7 @@ int RefCounted::WeakRefs() const
 // ATOMIC BEGIN
 
 PODVector<RefCountChangedFunction> RefCounted::refCountChangedFunctions_;
+PODVector<RefCountedDeletedFunction> RefCounted::refCountedDeletedFunctions_;
 
 void RefCounted::AddRefSilent()
 {
@@ -126,6 +130,16 @@ void RefCounted::RemoveRefCountChangedFunction(RefCountChangedFunction function)
     refCountChangedFunctions_.Remove(function);
 }
 
+void RefCounted::AddRefCountedDeletedFunction(RefCountedDeletedFunction function)
+{
+    refCountedDeletedFunctions_.Push(function);
+}
+
+void RefCounted::RemoveRefCountedDeletedFunction(RefCountedDeletedFunction function)
+{
+    refCountedDeletedFunctions_.Remove(function);
+}
+
 // ATOMIC END
 
 }

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

@@ -43,6 +43,9 @@ class RefCounted;
 // function that is called when ref count goes to 1 or 2+, used for script object lifetime
 typedef void (*RefCountChangedFunction)(RefCounted*, int refCount);
 
+// function callback for when a RefCounted is deleted
+typedef void(*RefCountedDeletedFunction)(RefCounted*);
+
 typedef const void* ClassID;
 
 /// Macro to be included in RefCounted derived classes for efficient RTTI
@@ -118,6 +121,9 @@ public:
     static void AddRefCountChangedFunction(RefCountChangedFunction function);
     static void RemoveRefCountChangedFunction(RefCountChangedFunction function);
 
+    static void AddRefCountedDeletedFunction(RefCountedDeletedFunction function);
+    static void RemoveRefCountedDeletedFunction(RefCountedDeletedFunction function);
+
 // ATOMIC END
 
 private:
@@ -135,6 +141,7 @@ private:
     void* jsHeapPtr_;
 
     static PODVector<RefCountChangedFunction> refCountChangedFunctions_;
+    static PODVector<RefCountedDeletedFunction> refCountedDeletedFunctions_;
 
     // ATOMIC END
 

+ 1 - 1
Source/Atomic/Environment/ProcSky.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Copyright (c) 2014-2016, 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

+ 1 - 1
Source/Atomic/Navigation/CrowdAgent.h

@@ -89,7 +89,7 @@ public:
     /// Handle enabled/disabled state change.
     virtual void OnSetEnabled();
     /// Draw debug geometry.
-    void DrawDebugGeometry(bool);
+    void DrawDebugGeometry(bool depthTest);
     /// Draw debug feelers.
     virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
 

+ 5 - 5
Source/Atomic/Navigation/Obstacle.h

@@ -39,12 +39,12 @@ class ATOMIC_API Obstacle : public Component
 
 public:
     /// Construct.
-    Obstacle(Context*);
+    Obstacle(Context* content);
     /// Destruct.
     virtual ~Obstacle();
 
     /// Register Obstacle with engine context.
-    static void RegisterObject(Context*);
+    static void RegisterObject(Context* context);
 
     /// Update the owning mesh when enabled status has changed.
     virtual void OnSetEnabled();
@@ -53,19 +53,19 @@ public:
     float GetHeight() const { return height_; }
 
     /// Set the height of this obstacle.
-    void SetHeight(float);
+    void SetHeight(float height);
 
     /// Get the blocking radius of this obstacle.
     float GetRadius() const { return radius_; }
 
     /// Set the blocking radius of this obstacle.
-    void SetRadius(float);
+    void SetRadius(float radius);
 
     /// Get the internal obstacle ID.
     unsigned GetObstacleID() const { return obstacleId_; }
 
     /// Render debug information.
-    virtual void DrawDebugGeometry(DebugRenderer*, bool depthTest);
+    virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
     /// Simplified rendering of debug information for script usage.
     void DrawDebugGeometry(bool depthTest);
 

+ 22 - 0
Source/Atomic/Script/ScriptComponent.cpp

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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 "../Core/Context.h"
 #include "ScriptComponentFile.h"

+ 22 - 0
Source/Atomic/Script/ScriptComponent.h

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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
 

+ 22 - 0
Source/Atomic/Script/ScriptComponentFile.cpp

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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 "ScriptComponentFile.h"
 

+ 22 - 0
Source/Atomic/Script/ScriptComponentFile.h

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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
 

+ 22 - 0
Source/Atomic/Script/ScriptPhysics.cpp

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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/IO/MemoryBuffer.h>
 #include <Atomic/Physics/PhysicsEvents.h>

+ 22 - 0
Source/Atomic/Script/ScriptPhysics.h

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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
 

+ 22 - 0
Source/Atomic/Script/ScriptSystem.cpp

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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 "ScriptSystem.h"
 #include "ScriptComponent.h"
 #include "ScriptComponentFile.h"

+ 22 - 0
Source/Atomic/Script/ScriptSystem.h

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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 "../Core/Context.h"
 #include "../Core/Object.h"

+ 22 - 0
Source/Atomic/Script/ScriptVariant.cpp

@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2014-2016, 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.
+//
+

+ 72 - 0
Source/Atomic/Script/ScriptVariant.h

@@ -0,0 +1,72 @@
+//
+// Copyright (c) 2014-2016, 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/Variant.h>
+#include <Atomic/Resource/ResourceCache.h>
+
+#include "ScriptSystem.h"
+
+namespace Atomic
+{
+    /// Wraps a Variant as a RefCounted so we can easily send it to script code
+    /// For performance sensitive code, specialized marshaling should be used instead
+    class ScriptVariant : public RefCounted
+    {
+        ATOMIC_REFCOUNTED(ScriptVariant)
+
+    public:
+
+        ScriptVariant() : RefCounted()
+        {
+
+        }
+
+        virtual ~ScriptVariant()
+        {
+
+        }
+
+        const Variant& GetVariant() { return variant_; }
+
+        void SetVariant(const Variant& value) { variant_ = value; }
+
+        Vector2 GetVector2() { return variant_.GetVector2(); }
+
+        void SetVector2(const Vector2& value) { variant_ = value; }
+
+        Vector3 GetVector3() { return variant_.GetVector3(); }
+
+        void SetVector3(const Vector3& value) { variant_ = value; }
+
+        Color GetColor() { return variant_.GetColor(); }
+
+        void SetColor(const Color& value) { variant_ = value; }
+
+    private:
+
+        Variant variant_;
+
+    };
+
+}

+ 22 - 0
Source/Atomic/Script/ScriptVariantMap.cpp

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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 "ScriptVariantMap.h"
 

+ 26 - 0
Source/Atomic/Script/ScriptVariantMap.h

@@ -1,3 +1,24 @@
+//
+// Copyright (c) 2014-2016, 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
 
@@ -155,6 +176,11 @@ public:
 
     }
 
+    void SetBool(StringHash key, bool value)
+    {
+        vmap_[key] = value;
+    }
+
     void SetUInt(StringHash key, unsigned value)
     {
         vmap_[key] = value;

+ 22 - 0
Source/Atomic/Script/ScriptVector.cpp

@@ -1,3 +1,25 @@
+//
+// Copyright (c) 2014-2016, 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 "ScriptVector.h"
 

+ 21 - 0
Source/Atomic/Script/ScriptVector.h

@@ -1,3 +1,24 @@
+//
+// Copyright (c) 2014-2016, 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 "ScriptSystem.h"
 

+ 13 - 8
Source/Atomic/UI/UI.cpp

@@ -141,10 +141,14 @@ UI::~UI()
         
         tb::TBWidgetsAnimationManager::Shutdown();
 
-        widgetWrap_.Clear();
+        // The root widget can acquire a delegate if it is retrieved in script (via getting parent), clear it here
+        rootWidget_->SetDelegate(0);
+        widgetWrap_.Clear();    
         delete rootWidget_;
+        
         // leak
         //delete TBUIRenderer::renderer_;
+
         tb_core_shutdown();
     }
 
@@ -595,6 +599,7 @@ bool UI::UnwrapWidget(tb::TBWidget* widget)
 {
     if (widgetWrap_.Contains(widget))
     {
+        widget->SetDelegate(0);
         widgetWrap_.Erase(widget);
         return true;
     }
@@ -609,29 +614,29 @@ void UI::PruneUnreachableWidgets()
 
     for (itr = widgetWrap_.Begin(); itr != widgetWrap_.End(); )
     {
-        if ((*itr).first_->GetParent() || (*itr).second_->JSGetHeapPtr())
+        if ((*itr).first_->GetParent() || (*itr).second_->Refs() > 1)
         {
             itr++;
             continue;
         }
 
-        tb::TBWidget* toDelete = (*itr).first_;
-
         itr.GotoNext();
 
+        VariantMap eventData;
+        eventData[WidgetDeleted::P_WIDGET] = (UIWidget*) (*itr).second_;
+        (*itr).second_->SendEvent(E_WIDGETDELETED, eventData);
+
+        tb::TBWidget* toDelete = (*itr).first_;
+        UnwrapWidget(toDelete);
         delete toDelete;
 
-        // this will likely be flagged by valgrind as accessing invalid memory
-        assert(!widgetWrap_.Contains(toDelete));
     }
 }
 
 void UI::WrapWidget(UIWidget* widget, tb::TBWidget* tbwidget)
 {
     assert (!widgetWrap_.Contains(tbwidget));
-
     widgetWrap_[tbwidget] = widget;
-    widget->AddRef();
 }
 
 UIWidget* UI::WrapWidget(tb::TBWidget* widget)

+ 7 - 7
Source/Atomic/UI/UIEditField.h

@@ -30,13 +30,13 @@ namespace Atomic
 {
 
 enum UI_EDIT_TYPE {
-    UI_EDIT_TYPE_TEXT = tb::EDIT_TYPE_TEXT,
-    UI_EDIT_TYPE_SEARCH = tb::EDIT_TYPE_SEARCH,
-    UI_EDIT_TYPE_PASSWORD = tb::EDIT_TYPE_PASSWORD,
-    UI_EDIT_TYPE_EMAIL = tb::EDIT_TYPE_EMAIL,
-    UI_EDIT_TYPE_PHONE = tb::EDIT_TYPE_PHONE,
-    UI_EDIT_TYPE_URL = tb::EDIT_TYPE_URL,
-    UI_EDIT_TYPE_NUMBER = tb::EDIT_TYPE_NUMBER
+    UI_EDIT_TYPE_TEXT = 0, // tb::EDIT_TYPE_TEXT,
+    UI_EDIT_TYPE_SEARCH = 1, // tb::EDIT_TYPE_SEARCH,
+    UI_EDIT_TYPE_PASSWORD = 2, // tb::EDIT_TYPE_PASSWORD,
+    UI_EDIT_TYPE_EMAIL = 3, // tb::EDIT_TYPE_EMAIL,
+    UI_EDIT_TYPE_PHONE = 4, // tb::EDIT_TYPE_PHONE,
+    UI_EDIT_TYPE_URL = 5, // tb::EDIT_TYPE_URL,
+    UI_EDIT_TYPE_NUMBER = 6 // tb::EDIT_TYPE_NUMBER
 };
 
 class UIEditField : public UIWidget

+ 1 - 1
Source/Atomic/UI/UIEvents.h

@@ -37,7 +37,7 @@ ATOMIC_EVENT(E_WIDGETEVENT, WidgetEvent)
 {
     ATOMIC_PARAM(P_HANDLER, Handler);           // UIWidget pointer of widget's OnEvent we are in
     ATOMIC_PARAM(P_TARGET, Target);             // UIWidget pointer
-    ATOMIC_PARAM(P_TYPE, Type);                 // EVENT_TYPE enum
+    ATOMIC_PARAM(P_TYPE, Type);                 // enum UI_EVENT_TYPE
     ATOMIC_PARAM(P_X, X);                       // int
     ATOMIC_PARAM(P_Y, Y);                       // int
     ATOMIC_PARAM(P_DELTAX, DeltaX);             // int

+ 13 - 13
Source/Atomic/UI/UILayout.h

@@ -36,13 +36,13 @@ enum UI_LAYOUT_SIZE
 {
     /// Sizes depend on the gravity for each widget. (If the widget pulls
     /// towards both directions, it should grow to all available space)
-    UI_LAYOUT_SIZE_GRAVITY = tb::LAYOUT_SIZE_GRAVITY,
+    UI_LAYOUT_SIZE_GRAVITY = 0, // tb::LAYOUT_SIZE_GRAVITY,
 
     /// Size will be the preferred so each widget may be sized differently.
-    UI_LAYOUT_SIZE_PREFERRED = tb::LAYOUT_SIZE_PREFERRED,
+    UI_LAYOUT_SIZE_PREFERRED = 1, // tb::LAYOUT_SIZE_PREFERRED,
 
     /// Size should grow to all available space
-    UI_LAYOUT_SIZE_AVAILABLE = tb::LAYOUT_SIZE_AVAILABLE
+    UI_LAYOUT_SIZE_AVAILABLE = 2 // tb::LAYOUT_SIZE_AVAILABLE
 };
 
 /// Specifies which width widgets in a AXIS_X layout should have,
@@ -51,12 +51,12 @@ enum UI_LAYOUT_SIZE
 enum UI_LAYOUT_DISTRIBUTION
 {
     ///< Size will be the preferred so each widget may be sized differently.
-    UI_LAYOUT_DISTRIBUTION_PREFERRED = tb::LAYOUT_DISTRIBUTION_PREFERRED,
+    UI_LAYOUT_DISTRIBUTION_PREFERRED = 0, // tb::LAYOUT_DISTRIBUTION_PREFERRED,
     ///< Size should grow to all available space
-    UI_LAYOUT_DISTRIBUTION_AVAILABLE = tb::LAYOUT_DISTRIBUTION_AVAILABLE,
+    UI_LAYOUT_DISTRIBUTION_AVAILABLE = 1, // tb::LAYOUT_DISTRIBUTION_AVAILABLE,
     ///< Sizes depend on the gravity for each widget. (If the widget pulls
     /// ///< towards both directions, it should grow to all available space)
-    UI_LAYOUT_DISTRIBUTION_GRAVITY = tb::LAYOUT_DISTRIBUTION_GRAVITY
+    UI_LAYOUT_DISTRIBUTION_GRAVITY = 2 // tb::LAYOUT_DISTRIBUTION_GRAVITY
 };
 
 /// Specifies which y position widgets in a AXIS_X layout should have,
@@ -64,14 +64,14 @@ enum UI_LAYOUT_DISTRIBUTION
 enum UI_LAYOUT_POSITION
 {
     ///< Position is centered
-    UI_LAYOUT_POSITION_CENTER = tb::LAYOUT_POSITION_CENTER,
+    UI_LAYOUT_POSITION_CENTER = 0, // tb::LAYOUT_POSITION_CENTER,
     ///< Position is to the left for AXIS_Y layout and top for AXIS_X layout.
-    UI_LAYOUT_POSITION_LEFT_TOP = tb::LAYOUT_POSITION_LEFT_TOP,
+    UI_LAYOUT_POSITION_LEFT_TOP = 1, // tb::LAYOUT_POSITION_LEFT_TOP,
     ///< Position is to the right for AXIS_Y layout and bottom for AXIS_X layout.
-    UI_LAYOUT_POSITION_RIGHT_BOTTOM = tb::LAYOUT_POSITION_RIGHT_BOTTOM,
+    UI_LAYOUT_POSITION_RIGHT_BOTTOM = 2, // tb::LAYOUT_POSITION_RIGHT_BOTTOM,
     ///< Position depend on the gravity for each widget. (If the widget pulls
     /// ///< towards both directions, it will be centered)
-    UI_LAYOUT_POSITION_GRAVITY= tb::LAYOUT_POSITION_GRAVITY
+    UI_LAYOUT_POSITION_GRAVITY = 3 // tb::LAYOUT_POSITION_GRAVITY
 };
 
 /** Specifies how widgets should be moved horizontally in a AXIS_X
@@ -79,9 +79,9 @@ enum UI_LAYOUT_POSITION
     available. */
 enum UI_LAYOUT_DISTRIBUTION_POSITION
 {
-    UI_LAYOUT_DISTRIBUTION_POSITION_CENTER = tb::LAYOUT_DISTRIBUTION_POSITION_CENTER,
-    UI_LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP = tb::LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP,
-    UI_LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM = tb::LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM
+    UI_LAYOUT_DISTRIBUTION_POSITION_CENTER = 0, // tb::LAYOUT_DISTRIBUTION_POSITION_CENTER,
+    UI_LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP = 1, // tb::LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP,
+    UI_LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM = 2 //tb::LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM
 };
 
 

+ 3 - 3
Source/Atomic/UI/UIMessageWindow.h

@@ -31,9 +31,9 @@ namespace Atomic
 
 enum UI_MESSAGEWINDOW_SETTINGS
 {
-    UI_MESSAGEWINDOW_SETTINGS_OK = tb::TB_MSG_OK,
-    UI_MESSAGEWINDOW_SETTINGS_OK_CANCEL = tb::TB_MSG_OK_CANCEL,
-    UI_MESSAGEWINDOW_SETTINGS_YES_NO = tb::TB_MSG_YES_NO
+    UI_MESSAGEWINDOW_SETTINGS_OK = 1, // tb::TB_MSG_OK,
+    UI_MESSAGEWINDOW_SETTINGS_OK_CANCEL = 2, // tb::TB_MSG_OK_CANCEL,
+    UI_MESSAGEWINDOW_SETTINGS_YES_NO = 3 // tb::TB_MSG_YES_NO
 };
 
 

+ 4 - 4
Source/Atomic/UI/UIPreferredSize.h

@@ -36,13 +36,13 @@ namespace Atomic
 /// Defines how the size in one axis depend on the other axis when a widgets size is affected by constraints.
 enum UI_SIZE_DEP {
     /// No dependency (Faster layout).
-    UI_SIZE_DEP_NONE                        = tb::SIZE_DEP_NONE,
+    UI_SIZE_DEP_NONE                    = 0, // tb::SIZE_DEP_NONE,
     /// The width is dependant on the height. Additional layout pass may be required.
-    UI_SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT        = tb::SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT,
+    UI_SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT  = 1, // tb::SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT,
     /// The height is dependant on the width. Additional layout pass may be required.
-    UI_SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH        = tb::SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH,
+    UI_SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH  = 2, // tb::SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH,
     /// Both width and height are dependant on each other. Additional layout pass may be required.
-    UI_SIZE_DEP_BOTH                        =    tb::SIZE_DEP_BOTH
+    UI_SIZE_DEP_BOTH                    = 3 //  tb::SIZE_DEP_BOTH
 };
 
 class UIPreferredSize : public RefCounted

+ 10 - 10
Source/Atomic/UI/UIScrollContainer.h

@@ -30,16 +30,16 @@ namespace Atomic
 {
 
 enum UI_SCROLL_MODE {
-    ///< X and Y always            scroll-mode: xy
-    UI_SCROLL_MODE_X_Y = tb::SCROLL_MODE_X_Y,
-    ///< Y always (X never)        scroll-mode: y
-    UI_SCROLL_MODE_Y = tb::SCROLL_MODE_Y,
-    ///< Y auto (X never)        scroll-mode: y-auto
-    UI_SCROLL_MODE_Y_AUTO = tb::SCROLL_MODE_Y_AUTO,
-    ///< X auto, Y auto            scroll-mode: auto
-    UI_SCROLL_MODE_X_AUTO_Y_AUTO = tb::SCROLL_MODE_X_AUTO_Y_AUTO,
-    ///< X any Y never            scroll-mode: off
-    UI_SCROLL_MODE_OFF = tb::SCROLL_MODE_OFF
+    ///< X and Y always             scroll-mode: xy
+    UI_SCROLL_MODE_X_Y =            0, // tb::SCROLL_MODE_X_Y,
+    ///< Y always (X never)         scroll-mode: y
+    UI_SCROLL_MODE_Y =              1, // tb::SCROLL_MODE_Y,
+    ///< Y auto (X never)           scroll-mode: y-auto
+    UI_SCROLL_MODE_Y_AUTO =         2, // tb::SCROLL_MODE_Y_AUTO,
+    ///< X auto, Y auto             scroll-mode: auto
+    UI_SCROLL_MODE_X_AUTO_Y_AUTO =  3, // tb::SCROLL_MODE_X_AUTO_Y_AUTO,
+    ///< X any Y never              scroll-mode: off
+    UI_SCROLL_MODE_OFF =            4 // tb::SCROLL_MODE_OFF
 };
 
 

+ 5 - 10
Source/Atomic/UI/UIWidget.cpp

@@ -189,11 +189,11 @@ void UIWidget::ConvertEvent(UIWidget *handler, UIWidget* target, const tb::TBWid
 
 void UIWidget::OnDelete()
 {
+    UnsubscribeFromAllEvents();   
+
     VariantMap eventData;
     eventData[WidgetDeleted::P_WIDGET] = this;
-    SendEvent(E_WIDGETDELETED, eventData);
-
-    UnsubscribeFromAllEvents();   
+    this->SendEvent(E_WIDGETDELETED, eventData);
 
     if (widget_)
     {
@@ -201,13 +201,8 @@ void UIWidget::OnDelete()
         UI* ui = GetSubsystem<UI>();
 
         if (ui)
-        { 
-            if (ui->UnwrapWidget(widget_))
-            {
-                widget_ = 0;
-                ReleaseRef();
-                return;
-            }
+        {
+            ui->UnwrapWidget(widget_);
         }
     }
 

+ 47 - 42
Source/Atomic/UI/UIWidget.h

@@ -34,34 +34,39 @@
 namespace Atomic
 {
 
+// UI_WIDGET_* enums must match TurboBadger internal enum values, we assign directly to TB enum values
+// as C# script bindings need the values 
+// Note, this could be automated with a dumper util that compiles values in, however that is quite complicated
+
 /// Defines widget visibility, used with UIWidget::SetVisibility.
 enum UI_WIDGET_VISIBILITY
 {
     /// Visible (default)
-    UI_WIDGET_VISIBILITY_VISIBLE = tb:: WIDGET_VISIBILITY_VISIBLE,
+    UI_WIDGET_VISIBILITY_VISIBLE = 0, //tb::WIDGET_VISIBILITY_VISIBLE,
     /// Invisible, but layouted. Interaction disabled.
-    UI_WIDGET_VISIBILITY_INVISIBLE = tb::WIDGET_VISIBILITY_INVISIBLE,
+    UI_WIDGET_VISIBILITY_INVISIBLE = 1, //tb::WIDGET_VISIBILITY_INVISIBLE,
     /// Invisible and no layout. Interaction disabled.
-    UI_WIDGET_VISIBILITY_GONE = tb::WIDGET_VISIBILITY_GONE
+    UI_WIDGET_VISIBILITY_GONE = 2 //tb::WIDGET_VISIBILITY_GONE
 };
 
 /// TBWidget gravity (may be combined).
 /// Gravity gives hints about positioning and sizing preferences.
 enum UI_GRAVITY {
 
-    UI_GRAVITY_NONE = tb::WIDGET_GRAVITY_NONE,
-    UI_GRAVITY_LEFT = tb::WIDGET_GRAVITY_LEFT,
-    UI_GRAVITY_RIGHT = tb::WIDGET_GRAVITY_RIGHT,
-    UI_GRAVITY_TOP = tb::WIDGET_GRAVITY_TOP,
-    UI_GRAVITY_BOTTOM = tb::WIDGET_GRAVITY_BOTTOM,
+    UI_GRAVITY_NONE = 0,   // tb::WIDGET_GRAVITY_NONE,
+    UI_GRAVITY_LEFT = 1,   // tb::WIDGET_GRAVITY_LEFT,
+    UI_GRAVITY_RIGHT = 2,  // tb::WIDGET_GRAVITY_RIGHT,
+    UI_GRAVITY_TOP = 4,    // tb::WIDGET_GRAVITY_TOP,
+    UI_GRAVITY_BOTTOM = 8, // tb::WIDGET_GRAVITY_BOTTOM,
 
-    UI_GRAVITY_LEFT_RIGHT    = tb::WIDGET_GRAVITY_LEFT_RIGHT,
-    UI_GRAVITY_TOP_BOTTOM    = tb::WIDGET_GRAVITY_TOP_BOTTOM,
-    UI_GRAVITY_ALL            = tb::WIDGET_GRAVITY_ALL,
-    UI_GRAVITY_DEFAULT        = tb::WIDGET_GRAVITY_DEFAULT
+    UI_GRAVITY_LEFT_RIGHT    = 3 ,  // tb::WIDGET_GRAVITY_LEFT_RIGHT,
+    UI_GRAVITY_TOP_BOTTOM    = 12,  // tb::WIDGET_GRAVITY_TOP_BOTTOM,
+    UI_GRAVITY_ALL           = 15, // tb::WIDGET_GRAVITY_ALL,
+    UI_GRAVITY_DEFAULT       = 5   // tb::WIDGET_GRAVITY_DEFAULT
 };
 
 enum UI_EVENT_TYPE {
+
     /** Click event is what should be used to trig actions in almost all cases.
 
         It is invoked on a widget after POINTER_UP if the pointer is still inside
@@ -70,7 +75,7 @@ enum UI_EVENT_TYPE {
 
         If panning of scrollable widgets start while the pointer is down, CLICK
         won't be invoked when releasing the pointer (since that should stop panning). */
-    UI_EVENT_TYPE_CLICK = tb::EVENT_TYPE_CLICK,
+    UI_EVENT_TYPE_CLICK = 0, // tb::EVENT_TYPE_CLICK,
 
     /** Long click event is sent when the pointer has been down for some time
         without moving much.
@@ -79,76 +84,76 @@ enum UI_EVENT_TYPE {
         If this event isn't handled, the widget will invoke a CONTEXT_MENU event.
         If any of those are handled, the CLICK event that would normally be
         invoked after the pending POINTER_UP will be suppressed. */
-    UI_EVENT_TYPE_LONG_CLICK = tb::EVENT_TYPE_LONG_CLICK,
-    UI_EVENT_TYPE_POINTER_DOWN = tb::EVENT_TYPE_POINTER_DOWN,
-    UI_EVENT_TYPE_POINTER_UP = tb::EVENT_TYPE_POINTER_UP,
-    UI_EVENT_TYPE_POINTER_MOVE = tb::EVENT_TYPE_POINTER_MOVE,
-    UI_EVENT_TYPE_RIGHT_POINTER_DOWN = tb::EVENT_TYPE_RIGHT_POINTER_DOWN,
-    UI_EVENT_TYPE_RIGHT_POINTER_UP = tb::EVENT_TYPE_RIGHT_POINTER_UP,
-    UI_EVENT_TYPE_WHEEL = tb::EVENT_TYPE_WHEEL,
+    UI_EVENT_TYPE_LONG_CLICK = 1, // tb::EVENT_TYPE_LONG_CLICK,
+    UI_EVENT_TYPE_POINTER_DOWN = 2, // tb::EVENT_TYPE_POINTER_DOWN,
+    UI_EVENT_TYPE_POINTER_UP = 3, // tb::EVENT_TYPE_POINTER_UP,
+    UI_EVENT_TYPE_POINTER_MOVE = 4, // tb::EVENT_TYPE_POINTER_MOVE,
+    UI_EVENT_TYPE_RIGHT_POINTER_DOWN = 5, // tb::EVENT_TYPE_RIGHT_POINTER_DOWN,
+    UI_EVENT_TYPE_RIGHT_POINTER_UP = 6, // tb::EVENT_TYPE_RIGHT_POINTER_UP,
+    UI_EVENT_TYPE_WHEEL = 7, // tb::EVENT_TYPE_WHEEL,
 
     /** Invoked after changing text in a TBTextField, changing selected item
         in a TBSelectList etc. Invoking this event trigs synchronization with
         connected TBWidgetValue and other widgets connected to it. */
-    UI_EVENT_TYPE_CHANGED = tb::EVENT_TYPE_CHANGED,
-    UI_EVENT_TYPE_KEY_DOWN = tb::EVENT_TYPE_KEY_DOWN,
-    UI_EVENT_TYPE_KEY_UP = tb::EVENT_TYPE_KEY_UP,
+    UI_EVENT_TYPE_CHANGED = 8, // tb::EVENT_TYPE_CHANGED,
+    UI_EVENT_TYPE_KEY_DOWN = 9, // tb::EVENT_TYPE_KEY_DOWN,
+    UI_EVENT_TYPE_KEY_UP = 10, // tb::EVENT_TYPE_KEY_UP,
 
     /** Invoked by the platform when a standard keyboard shortcut is pressed.
         It's called before InvokeKeyDown (EVENT_TYPE_KEY_DOWN) and if the event
         is handled (returns true), the KeyDown is canceled.
         The ref_id will be set to one of the following:
             "cut", "copy", "paste", "selectall", "undo", "redo", "new", "open", "save". */
-    UI_EVENT_TYPE_SHORTCUT = tb::EVENT_TYPE_SHORTCUT,
+    UI_EVENT_TYPE_SHORTCUT = 11, // tb::EVENT_TYPE_SHORTCUT,
 
     /** Invoked when a context menu should be opened at the event x and y coordinates.
         It may be invoked automatically for a widget on long click, if nothing handles
         the long click event. */
-    UI_EVENT_TYPE_CONTEXT_MENU = tb::EVENT_TYPE_CONTEXT_MENU,
+    UI_EVENT_TYPE_CONTEXT_MENU = 12, // tb::EVENT_TYPE_CONTEXT_MENU,
 
     /** Invoked by the platform when one or multiple files has been dropped on
         the widget. The event is guaranteed to be a TBWidgetEventFileDrop. */
-    UI_EVENT_TYPE_FILE_DROP = tb::EVENT_TYPE_FILE_DROP,
+    UI_EVENT_TYPE_FILE_DROP = 13, // tb::EVENT_TYPE_FILE_DROP,
 
     /** Invoked by the platform when a tab container's tab changed */
-    UI_EVENT_TYPE_TAB_CHANGED = tb::EVENT_TYPE_TAB_CHANGED,
+    UI_EVENT_TYPE_TAB_CHANGED = 14, // tb::EVENT_TYPE_TAB_CHANGED,
 
     /** Custom event. Not used internally. ref_id may be used for additional type info. */
-    UI_EVENT_TYPE_CUSTOM = tb::EVENT_TYPE_CUSTOM
+    UI_EVENT_TYPE_CUSTOM = 15 // tb::EVENT_TYPE_CUSTOM
 };
 
 /** Defines widget z level relative to another widget, used with TBWidget::AddChildRelative. */
 enum UI_WIDGET_Z_REL {
-    UI_WIDGET_Z_REL_BEFORE = tb::WIDGET_Z_REL_BEFORE,        ///< Before the reference widget (visually behind reference).
-    UI_WIDGET_Z_REL_AFTER = tb::WIDGET_Z_REL_AFTER            ///< After the reference widget (visually above reference).
+    UI_WIDGET_Z_REL_BEFORE = 0, // tb::WIDGET_Z_REL_BEFORE,        ///< Before the reference widget (visually behind reference).
+    UI_WIDGET_Z_REL_AFTER = 1   // tb::WIDGET_Z_REL_AFTER            ///< After the reference widget (visually above reference).
 };
 
 /// TB_TEXT_ALIGN specifies horizontal text alignment
 enum UI_TEXT_ALIGN
 {
-    UI_TEXT_ALIGN_LEFT = tb::TB_TEXT_ALIGN_LEFT,
-    UI_TEXT_ALIGN_RIGHT = tb::TB_TEXT_ALIGN_RIGHT,
-    UI_TEXT_ALIGN_CENTER = tb::TB_TEXT_ALIGN_CENTER
+    UI_TEXT_ALIGN_LEFT = 0,     // tb::TB_TEXT_ALIGN_LEFT,
+    UI_TEXT_ALIGN_RIGHT = 1,    // tb::TB_TEXT_ALIGN_RIGHT,
+    UI_TEXT_ALIGN_CENTER = 2    // tb::TB_TEXT_ALIGN_CENTER
 };
 
 enum UI_WIDGET_STATE {
 
-    UI_WIDGET_STATE_NONE = tb::WIDGET_STATE_NONE,
-    UI_WIDGET_STATE_DISABLED = tb::WIDGET_STATE_DISABLED,
-    UI_WIDGET_STATE_FOCUSED = tb::WIDGET_STATE_FOCUSED,
-    UI_WIDGET_STATE_PRESSED = tb::WIDGET_STATE_PRESSED,
-    UI_WIDGET_STATE_SELECTED = tb::WIDGET_STATE_SELECTED,
-    UI_WIDGET_STATE_HOVERED = tb::WIDGET_STATE_HOVERED,
+    UI_WIDGET_STATE_NONE = 0,       // tb::WIDGET_STATE_NONE,
+    UI_WIDGET_STATE_DISABLED = 1,   // tb::WIDGET_STATE_DISABLED,
+    UI_WIDGET_STATE_FOCUSED = 2,    // tb::WIDGET_STATE_FOCUSED,
+    UI_WIDGET_STATE_PRESSED = 4,    // tb::WIDGET_STATE_PRESSED,
+    UI_WIDGET_STATE_SELECTED = 8,   // tb::WIDGET_STATE_SELECTED,
+    UI_WIDGET_STATE_HOVERED = 16,   // tb::WIDGET_STATE_HOVERED,
 
-    UI_WIDGET_STATE_ALL = tb::WIDGET_STATE_ALL
+    UI_WIDGET_STATE_ALL = 31        // tb::WIDGET_STATE_ALL
 
 };
 
 enum UI_AXIS {
     ///< Horizontal layout
-    UI_AXIS_X = tb::AXIS_X,
+    UI_AXIS_X = 0,  // tb::AXIS_X,
     ///< Vertical layout
-    UI_AXIS_Y = tb::AXIS_Y,
+    UI_AXIS_Y = 1   // tb::AXIS_Y,
 };
 
 

+ 7 - 6
Source/Atomic/UI/UIWindow.h

@@ -31,18 +31,19 @@ namespace Atomic
 
 
 enum UI_WINDOW_SETTINGS {
+
     ///< Chrome less window without any other settings.
-    UI_WINDOW_SETTINGS_NONE            = tb::WINDOW_SETTINGS_NONE,
+    UI_WINDOW_SETTINGS_NONE             = 0, // tb::WINDOW_SETTINGS_NONE,
     ///< Show a title bar that can also move the window.
-    UI_WINDOW_SETTINGS_TITLEBAR        = tb::WINDOW_SETTINGS_TITLEBAR,
+    UI_WINDOW_SETTINGS_TITLEBAR         = 1, // tb::WINDOW_SETTINGS_TITLEBAR,
     ///< Show a widget for resizing the window.
-    UI_WINDOW_SETTINGS_RESIZABLE    = tb::WINDOW_SETTINGS_RESIZABLE,
+    UI_WINDOW_SETTINGS_RESIZABLE        = 2, // tb::WINDOW_SETTINGS_RESIZABLE,
     ///< Show a widget for closing the window.
-    UI_WINDOW_SETTINGS_CLOSE_BUTTON    = tb::WINDOW_SETTINGS_CLOSE_BUTTON,
+    UI_WINDOW_SETTINGS_CLOSE_BUTTON     = 4, // tb::WINDOW_SETTINGS_CLOSE_BUTTON,
     ///< Can be activated and deactivate other windows.
-    UI_WINDOW_SETTINGS_CAN_ACTIVATE    = tb::WINDOW_SETTINGS_CAN_ACTIVATE,
+    UI_WINDOW_SETTINGS_CAN_ACTIVATE     = 8, // tb::WINDOW_SETTINGS_CAN_ACTIVATE,
 
-    UI_WINDOW_SETTINGS_DEFAULT = tb::WINDOW_SETTINGS_DEFAULT
+    UI_WINDOW_SETTINGS_DEFAULT          = 15 // tb::WINDOW_SETTINGS_DEFAULT
 };
 
 

+ 416 - 6
Source/AtomicNET/NETNative/NETCInterop.cpp

@@ -1,10 +1,25 @@
 
+#include <Atomic/Script/ScriptVariant.h>
 #include <Atomic/Script/ScriptVariantMap.h>
 #include <Atomic/IPC/IPC.h>
 
 #include <Atomic/Graphics/VertexBuffer.h>
 #include <Atomic/Graphics/Viewport.h>
 #include <Atomic/Graphics/Graphics.h>
+#include <Atomic/Graphics/RenderPath.h>
+#include <Atomic/Graphics/Camera.h>
+#include <Atomic/Graphics/Light.h>
+#include <Atomic/Graphics/Octree.h>
+#include <Atomic/Graphics/AnimatedModel.h>
+
+#include <Atomic/Navigation/NavigationMesh.h>
+#include <Atomic/Navigation/CrowdManager.h>
+
+#include <Atomic/Physics/PhysicsWorld.h>
+
+#include <Atomic/Scene/ValueAnimation.h>
+
+#include <Atomic/Input/Controls.h>
 
 
 #include "NETCore.h"
@@ -29,6 +44,13 @@ namespace Atomic
 
     extern "C"
     {
+        ATOMIC_EXPORT_API void csi_Atomic_VariantMap_SetBool(VariantMap* vmap, const char* key, bool value)
+        {
+            if (!vmap)
+                return;
+
+            (*vmap)[key] = value;
+        }
 
         ATOMIC_EXPORT_API ClassID csi_Atomic_RefCounted_GetClassID(RefCounted* refCounted)
         {
@@ -49,14 +71,17 @@ namespace Atomic
         ATOMIC_EXPORT_API const char* csi_Atomic_AObject_GetTypeName(Object* self)
         {
 
-           static String returnValue;
-           returnValue = self->GetTypeName();
-           return returnValue.CString();
+            static String returnValue;
+            returnValue = self->GetTypeName();
+            return returnValue.CString();
         }
 
         ATOMIC_EXPORT_API int csi_Atomic_RefCounted_Refs(RefCounted* self)
         {
-           return self->Refs();
+            if (!self)
+                return 0;
+
+            return self->Refs();
         }
 
 
@@ -65,7 +90,16 @@ namespace Atomic
             obj->SendEvent(eventType, vmap ? vmap->GetVariantMap() : obj->GetEventDataMap());
         }
 
-        ATOMIC_EXPORT_API ClassID csi_Atomic_NETCore_Initialize(NETCoreEventDispatchFunction eventDispatch, NETCoreUpdateDispatchFunction updateDispatch)
+        ATOMIC_EXPORT_API void csi_Atomic_AObject_UnsubscribeFromAllEvents(Object* obj)
+        {
+            if (!obj)
+                return;
+
+            obj->UnsubscribeFromAllEvents();
+        }
+
+
+        ATOMIC_EXPORT_API ClassID csi_Atomic_NETCore_Initialize(NETCoreEventDispatchFunction eventDispatch, NETCoreUpdateDispatchFunction updateDispatch, NETCoreRefCountedDeletedFunction refCountedDeleted)
         {
             Context* context = new Context();
 
@@ -73,6 +107,7 @@ namespace Atomic
             NETCoreDelegates delegates;
             delegates.eventDispatch = eventDispatch;
             delegates.updateDispatch = updateDispatch;
+            delegates.refCountedDeleted = refCountedDeleted;
 
             NETCore* netCore = new NETCore(context, &delegates);
             context->RegisterSubsystem(netCore);
@@ -148,7 +183,7 @@ namespace Atomic
 
         }
 
-        ATOMIC_EXPORT_API void* csi_Atomic_VertexBuffer_Lock(VertexBuffer* vb , unsigned start, unsigned count, bool discard)
+        ATOMIC_EXPORT_API void* csi_Atomic_VertexBuffer_Lock(VertexBuffer* vb, unsigned start, unsigned count, bool discard)
         {
             if (!vb)
                 return nullptr;
@@ -165,6 +200,381 @@ namespace Atomic
             graphics->SetShaderParameter(param, *matrix);
         }
 
+        // RenderPath
+
+        ATOMIC_EXPORT_API void csi_Atomic_RenderPath_SetShaderParameter(RenderPath* renderPath, const char* name, ScriptVariant* value)
+        {
+            if (!renderPath || !name || !value)
+                return;
+
+            Vector2 v2 = value->GetVariant().GetVector2();
+
+            renderPath->SetShaderParameter(name, value->GetVariant());
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_RenderPath_GetShaderParameter(RenderPath* renderPath, const char* name, ScriptVariant* value)
+        {
+            if (!renderPath || !name || !value)
+                return;
+
+            value->SetVariant(renderPath->GetShaderParameter(name));
+        }
+
+        // Light
+
+        ATOMIC_EXPORT_API void csi_Atomic_Light_SetShadowBias(Light* light, BiasParameters* parameters)
+        {
+            if (!parameters)
+                return;
+
+            light->SetShadowBias(*parameters);
+
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Light_GetShadowBias(Light* light, BiasParameters* parameters)
+        {
+            if (!parameters)
+                return;
+
+            *parameters = light->GetShadowBias();
+
+        }
+
+
+        ATOMIC_EXPORT_API void csi_Atomic_Light_SetShadowCascade(Light* light, CascadeParameters* parameters)
+        {
+            if (!parameters)
+                return;
+
+            light->SetShadowCascade(*parameters);
+
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Light_GetShadowCascade(Light* light, CascadeParameters* parameters)
+        {
+            if (!parameters)
+                return;
+
+            *parameters = light->GetShadowCascade();
+
+        }
+
+
+        ATOMIC_EXPORT_API void csi_Atomic_Light_SetShadowFocus(Light* light, FocusParameters* parameters)
+        {
+            if (!parameters)
+                return;
+
+            light->SetShadowFocus(*parameters);
+
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Light_GetShadowFocus(Light* light, FocusParameters* parameters)
+        {
+            if (!parameters)
+                return;
+
+            *parameters = light->GetShadowFocus();
+        }
+
+        // Camera
+
+        ATOMIC_EXPORT_API void csi_Atomic_Camera_GetScreenRay(Camera* camera, float x, float y, Ray* ray)
+        {
+            if (!camera || !ray)
+                return;
+
+            *ray = camera->GetScreenRay(x, y);
+        }
+
+
+        ATOMIC_EXPORT_API void csi_Atomic_Camera_SetClipPlane(Camera* camera, Plane* plane)
+        {
+            if (!camera || !plane)
+                return;
+
+            camera->SetClipPlane(*plane);
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Camera_GetClipPlane(Camera* camera, Plane* plane)
+        {
+            if (!camera || !plane)
+                return;
+
+            *plane = camera->GetClipPlane();
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Camera_SetReflectionPlane(Camera* camera, Plane* plane)
+        {
+            if (!camera || !plane)
+                return;
+
+            camera->SetReflectionPlane(*plane);
+        }
+
+
+        ATOMIC_EXPORT_API void csi_Atomic_Camera_GetReflectionPlane(Camera* camera, Plane* plane)
+        {
+            if (!camera || !plane)
+                return;
+
+            *plane = camera->GetReflectionPlane();
+        }
+
+        // Octree
+
+        ATOMIC_EXPORT_API void csi_Atomic_Octree_Raycast_FreeResult(PODVector<RayQueryResult>* resultVector)
+        {
+            delete resultVector;
+        }
+    
+
+        // Any result vector must be freed with csi_Atomic_Octree_Raycast_FreeResult
+        ATOMIC_EXPORT_API RayQueryResult* csi_Atomic_Octree_Raycast(Octree *octree, const Ray& ray, const RayQueryLevel& level, float maxDistance, unsigned int flags, unsigned int viewMask,
+            bool single, void** resultVector, int *count) 
+        {
+            PODVector<RayQueryResult>* results = new PODVector<RayQueryResult>();
+
+            *count = 0;
+            *resultVector = 0;
+
+            RayOctreeQuery query(*results, ray, level, maxDistance, flags, viewMask);
+            
+            if (single)
+                octree->RaycastSingle(query);
+            else
+                octree->Raycast(query);
+
+            if (results->Size() == 0)
+            {
+                delete results;
+                return NULL;
+            }
+
+            *count = results->Size();
+            *resultVector = results;
+            return &(*results)[0];
+        }
+
+        
+        // NavigationMesh
+
+        ATOMIC_EXPORT_API void csi_Atomic_NavigationMesh_FindPath_FreeResult(PODVector<Vector3>* resultVector)
+        {
+            delete resultVector;
+        }
+
+
+        // Any result vector must be freed with csi_Atomic_NavigationMesh_FindPath_FreeResult
+        ATOMIC_EXPORT_API Vector3* csi_Atomic_NavigationMesh_FindPath(NavigationMesh *navMesh, Vector3* start, Vector3* end, Vector3 *extents, void** resultVector, int *count)
+        {
+            PODVector<Vector3>* results = new PODVector<Vector3>();
+
+            navMesh->FindPath(*results, *start, *end, *extents);
+
+            *count = 0;
+            *resultVector = 0;
+
+            if (results->Size() == 0)
+            {
+                delete results;
+                return NULL;
+            }
+
+            *count = results->Size();
+            *resultVector = results;
+            return &(*results)[0];
+        }
+
+        // AnimatedModel
+
+        ATOMIC_EXPORT_API Skeleton* csi_Atomic_AnimatedModel_GetSkeleton(AnimatedModel *animatedModel)
+        {
+            if (!animatedModel)
+                return 0;
+
+            return &animatedModel->GetSkeleton();
+        }
+
+        // Skeleton
+
+        ATOMIC_EXPORT_API void csi_Atomic_Skeleton_SetRootBoneIndex(Skeleton *skeleton, unsigned index)
+        {
+            if (!skeleton)
+                return;
+
+            skeleton->SetRootBoneIndex(index);
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Skeleton_Define(Skeleton *skeleton, Skeleton *src)
+        {
+            if (!skeleton || !src)
+                return;
+
+            skeleton->Define(*src);
+        }
+
+
+        ATOMIC_EXPORT_API void csi_Atomic_Skeleton_Reset(Skeleton *skeleton)
+        {
+            if (!skeleton)
+                return;
+
+            skeleton->Reset();
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Skeleton_ResetSilent(Skeleton *skeleton)
+        {
+            if (!skeleton)
+                return;
+
+            skeleton->ResetSilent();
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Skeleton_ClearBones(Skeleton *skeleton)
+        {
+            if (!skeleton)
+                return;
+
+            skeleton->ClearBones();
+        }
+
+        ATOMIC_EXPORT_API Bone* csi_Atomic_Skeleton_GetRootBone(Skeleton *skeleton)
+        {
+            if (!skeleton)
+                return 0;
+
+            return skeleton->GetRootBone();
+        }
+
+
+        ATOMIC_EXPORT_API Bone* csi_Atomic_Skeleton_GetBone_ByIndex(Skeleton *skeleton, unsigned index)
+        {
+            if (!skeleton)
+                return 0;
+
+            if (index >= skeleton->GetNumBones())
+                return 0;
+
+            return skeleton->GetBone(index);            
+        }
+
+        ATOMIC_EXPORT_API Bone* csi_Atomic_Skeleton_GetBone_ByName(Skeleton *skeleton, const char* name)
+        {
+            if (!skeleton || !name || !strlen(name))
+                return 0;
+
+            return skeleton->GetBone(name);
+        }
+
+        ATOMIC_EXPORT_API unsigned csi_Atomic_Skeleton_GetNumBones(Skeleton *skeleton)
+        {
+            if (!skeleton)
+                return 0;
+
+            return skeleton->GetNumBones();
+        }
+
+        // PhysicsWorld
+
+        ATOMIC_EXPORT_API void csi_Atomic_PhysicsWorld_RaycastSingle(PhysicsWorld* world, Ray* ray, float maxDistance, unsigned collisionMask, PhysicsRaycastResult* result)
+        {
+            if (!world || !ray || !result)
+                return;
+
+            world->RaycastSingle(*result, *ray, maxDistance, collisionMask);
+
+        }
+
+        // Controls
+        
+        ATOMIC_EXPORT_API unsigned csi_Atomic_Controls_GetButtons(Controls *controls)
+        {
+            return controls->buttons_;
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Controls_SetButtons(Controls *controls, unsigned value)
+        {
+            controls->buttons_ = value;
+        }
+
+        ATOMIC_EXPORT_API float csi_Atomic_Controls_GetYaw(Controls *controls)
+        {
+            return controls->yaw_;
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Controls_SetYaw(Controls *controls, float value)
+        {
+            controls->yaw_ = value;
+        }
+
+        ATOMIC_EXPORT_API float csi_Atomic_Controls_GetPitch(Controls *controls)
+        {
+            return controls->pitch_;
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Controls_SetPitch(Controls *controls, float value)
+        {
+            controls->pitch_ = value;
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Controls_Reset(Controls *_target)
+        {
+            _target->Reset();
+        }
+
+        ATOMIC_EXPORT_API void csi_Atomic_Controls_Set(Controls *_target, unsigned int buttons, int down)
+        {
+            _target->Set(buttons, down);
+        }
+
+        ATOMIC_EXPORT_API int csi_Atomic_Controls_IsDown(Controls *_target, unsigned int button)
+        {
+            return _target->IsDown(button);
+        }
+
+        ATOMIC_EXPORT_API Controls*  csi_Atomic_Controls_Create()
+        {
+            return new Controls();
+        }
+
+        ATOMIC_EXPORT_API void  csi_Atomic_Controls_Destroy(Controls *controls)
+        {
+            if (!controls)
+                return;
+
+            delete controls;
+        }
+
+        // CrowdManager
+
+        ATOMIC_EXPORT_API void  csi_Atomic_CrowdManager_GetObstacleAvoidanceParams(CrowdManager *manager, unsigned obstacleAvoidanceType, CrowdObstacleAvoidanceParams* parms)
+        {
+            if (!manager || !parms)
+                return;
+
+            *parms = manager->GetObstacleAvoidanceParams(obstacleAvoidanceType);
+        }
+
+        ATOMIC_EXPORT_API void  csi_Atomic_CrowdManager_SetObstacleAvoidanceParams(CrowdManager *manager, unsigned obstacleAvoidanceType, CrowdObstacleAvoidanceParams* parms)
+        {
+            if (!manager || !parms)
+                return;
+
+            manager->SetObstacleAvoidanceParams(obstacleAvoidanceType, *parms);
+        }
+
+        // ValueAnimation
+
+        ATOMIC_EXPORT_API bool csi_Atomic_ValueAnimation_SetKeyFrame(ValueAnimation* self, float time, ScriptVariant* variant)
+        {
+            if (!self || !variant)
+                return false;
+
+            return self->SetKeyFrame(time, variant->GetVariant());
+        }
+
+
 #ifdef ATOMIC_PLATFORM_IOS
         ATOMIC_EXPORT_API void SDL_IOS_Init(const char *resourceDir, const char *documentsDir)
         {

+ 17 - 2
Source/AtomicNET/NETNative/NETCore.cpp

@@ -1,6 +1,7 @@
 
 #include <Atomic/Math/MathDefs.h>
 #include <Atomic/Core/ProcessUtils.h>
+#include <Atomic/IO/Log.h>
 #include <Atomic/Script/ScriptVariantMap.h>
 
 #include "NETCore.h"
@@ -9,10 +10,10 @@
 namespace Atomic
 {
 
-
 SharedPtr<Context> NETCore::csContext_;
 NETCoreEventDispatchFunction NETCore::eventDispatch_ = nullptr;
 NETCoreUpdateDispatchFunction NETCore::updateDispatch_ = nullptr;
+NETCoreRefCountedDeletedFunction NETCore::refCountedDeleted_ = nullptr;
 
 NETCore::NETCore(Context* context, NETCoreDelegates* delegates) :
     Object(context)
@@ -22,15 +23,29 @@ NETCore::NETCore(Context* context, NETCoreDelegates* delegates) :
 
     eventDispatch_ = delegates->eventDispatch;
     updateDispatch_ = delegates->updateDispatch;
+    refCountedDeleted_ = delegates->refCountedDeleted;
 
     NETEventDispatcher* dispatcher = new NETEventDispatcher(context_);
     context_->RegisterSubsystem(dispatcher);
     context_->AddGlobalEventListener(dispatcher);
+
+    RefCounted::AddRefCountedDeletedFunction(OnRefCountedDeleted);
 }
 
 NETCore::~NETCore()
 {
-    assert (!csContext_);
+    RefCounted::RemoveRefCountedDeletedFunction(OnRefCountedDeleted);
+    assert (!csContext_);    
+}
+
+void NETCore::OnRefCountedDeleted(RefCounted* ref)
+{
+    if (csContext_.Null())
+        return;
+
+    if (refCountedDeleted_)
+        refCountedDeleted_(ref);
+
 }
 
 void NETCore::RegisterNETEventType(unsigned eventType)

+ 5 - 0
Source/AtomicNET/NETNative/NETCore.h

@@ -30,11 +30,13 @@ namespace Atomic
 
 typedef void (*NETCoreEventDispatchFunction)(Object* refCounted, unsigned eventID, VariantMap* eventData);
 typedef void (*NETCoreUpdateDispatchFunction)(float timeStep);
+typedef void (*NETCoreRefCountedDeletedFunction)(RefCounted* refCounted);
 
 struct NETCoreDelegates
 {
     NETCoreEventDispatchFunction eventDispatch;
     NETCoreUpdateDispatchFunction updateDispatch;
+    NETCoreRefCountedDeletedFunction refCountedDeleted;
 };
 
 class ATOMIC_API NETCore : public Object
@@ -63,10 +65,13 @@ public:
 
 private:
 
+    static void OnRefCountedDeleted(RefCounted* ref);
+
     static SharedPtr<Context> csContext_;
 
     static NETCoreUpdateDispatchFunction updateDispatch_;
     static NETCoreEventDispatchFunction eventDispatch_;
+    static NETCoreRefCountedDeletedFunction refCountedDeleted_;
 
 };
 

+ 1 - 1
Source/AtomicNET/NETNative/NETEventDispatcher.cpp

@@ -55,7 +55,7 @@ namespace Atomic
 
         if (eventType == E_NODECOLLISION)
         {
-            VariantMap ncEventData;
+            VariantMap ncEventData = eventData;
 
             SharedPtr<PhysicsNodeCollision> nodeCollison(new PhysicsNodeCollision());
             nodeCollison->SetFromNodeCollisionEvent(eventData);

+ 1 - 1
Source/AtomicNET/NETScript/NETScriptEvents.h

@@ -43,7 +43,7 @@ namespace Atomic
 
     ATOMIC_EVENT(E_CSCOMPONENTASSEMBLYCHANGED, CSComponentAssemblyChanged)
     {
-        ATOMIC_PARAM(P_RESOURCE, Resource); // resource*
+        ATOMIC_PARAM(P_RESOURCE, Resource); // Resource
         ATOMIC_PARAM(P_ASSEMBLYPATH, AssemblyPath); // String
     }
 

+ 1 - 1
Source/ThirdParty/TurboBadger/tb_widgets_common.cpp

@@ -680,7 +680,7 @@ bool TBSlider::OnEvent(const TBWidgetEvent &ev)
                 ev.special_key == TB_KEY_RIGHT || ev.special_key == TB_KEY_DOWN)
             return true;
     }
-    return false;
+    return TBWidget::OnEvent(ev);
 }
 
 void TBSlider::UpdateHandle()

+ 5 - 5
Source/ToolCore/JSBind/CSharp/CSFunctionWriter.cpp

@@ -55,7 +55,7 @@ void CSFunctionWriter::GenNativeCallParameters(String& sig)
 {
     JSBClass* klass = function_->GetClass();
 
-    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
 
     Vector<String> args;
 
@@ -128,7 +128,7 @@ void CSFunctionWriter::WriteNativeFunction(String& source)
     // vector marshal
 
     bool hasVectorMarshal = false;
-    Vector<JSBFunctionType*>& fparams = function_->GetParameters();
+    const Vector<JSBFunctionType*>& fparams = function_->GetParameters();
 
     for (unsigned i = 0; i < fparams.Size(); i++)
     {
@@ -380,7 +380,7 @@ void CSFunctionWriter::WriteManagedPInvokeFunctionSignature(String& source)
     if (function_->IsConstructor())
         returnType = "IntPtr";
 
-    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
 
     Vector<String> args;
 
@@ -465,7 +465,7 @@ void CSFunctionWriter::WriteManagedPInvokeFunctionSignature(String& source)
 void CSFunctionWriter::GenManagedFunctionParameters(String& sig)
 {
     // generate args
-    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
 
     if (parameters.Size())
     {
@@ -595,7 +595,7 @@ void CSFunctionWriter::WriteManagedConstructor(String& source)
 void CSFunctionWriter::GenPInvokeCallParameters(String& sig)
 {
     // generate args
-    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
 
     if (parameters.Size())
     {

+ 137 - 1
Source/ToolCore/JSBind/CSharp/CSModuleWriter.cpp

@@ -29,6 +29,7 @@
 #include "../JSBEnum.h"
 #include "../JSBClass.h"
 #include "../JSBFunction.h"
+#include "../JSBEvent.h"
 
 #include "CSTypeHelper.h"
 #include "CSClassWriter.h"
@@ -252,7 +253,9 @@ void CSModuleWriter::GenerateManagedEnumsAndConstants(String& source)
             // BodyType2D enum order is assigned in RigidBody2D.h in incorrect order
             if (jenum->GetName() == "BodyType2D")
             {                 
-                if (name == "BT_KINEMATIC")
+                if (name == "BT_STATIC")
+                    value = "0";
+                else if (name == "BT_KINEMATIC")
                     value = "1";
                 else if (name == "BT_DYNAMIC")
                     value = "2";
@@ -385,6 +388,125 @@ void CSModuleWriter::GenerateManagedEnumsAndConstants(String& source)
 
 }
 
+void CSModuleWriter::GenerateManagedNativeEvents(String& sourceOut)
+{
+    Indent();
+
+    String source;
+
+    const Vector<SharedPtr<JSBEvent>>& events = module_->GetEvents();
+
+    for (unsigned i = 0; i < events.Size(); i++)
+    {
+        JSBEvent* event = events[i];
+
+        const String& eventID = event->GetEventID();
+
+        String line = ToString("public partial class %s : NativeEventData\n", event->GetScriptEventName().CString());
+
+        source += IndentLine(line);
+
+        source += IndentLine("{\n\n");
+
+        Indent();
+
+        // parameters
+
+        const Vector<JSBEvent::EventParam>& params = event->GetParameters();
+
+        for (unsigned j = 0; j < params.Size(); j++)
+        {
+            const JSBEvent::EventParam& p = params[j];
+
+            JSBClass* cls = JSBPackage::GetClassAllPackages(p.typeInfo_);
+
+            String typeName = p.typeInfo_;
+            String enumTypeName = p.enumTypeName_;
+
+            if (!cls)
+                typeName = typeName.ToLower();
+            else
+                typeName = cls->GetName();
+
+            if (typeName == "int" || typeName == "float" ||
+                typeName == "bool" || typeName == "string" || typeName == "enum" || cls)
+            {
+
+                bool isEnum = false;
+                if (typeName == "enum")
+                {   
+                    isEnum = true;
+                    if (enumTypeName.Length())
+                        typeName = enumTypeName;
+                    else
+                        typeName = "int";
+                }
+
+                line = "public " + typeName + " " + p.paramName_ + "\n";
+                source += IndentLine(line);
+                source += IndentLine("{\n");
+
+                Indent();
+
+                source += IndentLine("get\n");
+                source += IndentLine("{\n");
+
+                Indent();
+
+                line = "return ";
+
+                if (typeName == "int")
+                    line += "scriptMap.GetInt";
+                else if (isEnum)
+                {
+                    line += ToString("(%s) scriptMap.GetInt", typeName.CString());
+                }
+                else if (typeName == "float")
+                    line += "scriptMap.GetFloat";
+                else if (typeName == "bool")
+                    line += "scriptMap.GetBool";
+                else if (typeName == "string")
+                    line += "scriptMap.GetString";
+                else if (cls)
+                {
+                    if (typeName == "Vector3")
+                    {
+                        line += "scriptMap.Get" + typeName;
+                    }
+                    else
+                    {
+                        line += ToString("scriptMap.GetPtr<%s>", cls->GetName().CString());
+                    }
+                    
+                }
+
+                line += ToString("(\"%s\");\n", p.paramName_.CString());
+                source += IndentLine(line);
+
+                Dedent();
+
+                source += IndentLine("}\n");
+
+                Dedent();
+
+                source += IndentLine("}\n\n");
+
+            }
+
+        }
+
+        Dedent();
+
+        source += IndentLine("}\n\n");
+
+    }
+
+
+    sourceOut += source;
+
+    Dedent();
+}
+
 void CSModuleWriter::GenerateManagedModuleClass(String& sourceOut)
 {
     Indent();
@@ -436,6 +558,19 @@ void CSModuleWriter::GenerateManagedModuleClass(String& sourceOut)
 
     }
 
+    source += "\n";
+
+    // Native Events
+    const Vector<SharedPtr<JSBEvent>>& events = module_->GetEvents();
+
+    for (unsigned i = 0; i < events.Size(); i++)
+    {
+        JSBEvent* event = events[i];
+
+        line = ToString("NativeEvents.RegisterEventID<%s>(\"%s\");\n", event->GetScriptEventName().CString(), event->GetEventName().CString());
+        source += IndentLine(line);
+    }
+
     Dedent();
 
     source += IndentLine("}\n");
@@ -471,6 +606,7 @@ void CSModuleWriter::GenerateManagedSource()
     source += "{\n";
 
     GenerateManagedEnumsAndConstants(source);
+    GenerateManagedNativeEvents(source);
     GenerateManagedModuleClass(source);
     GenerateManagedClasses(source);
 

+ 1 - 1
Source/ToolCore/JSBind/CSharp/CSModuleWriter.h

@@ -53,7 +53,7 @@ private:
     void GenerateManagedModuleClass(String& sourceOut);
     void GenerateManagedClasses(String& source);
     void GenerateManagedEnumsAndConstants(String& source);
-
+    void GenerateManagedNativeEvents(String& sourceOut);
 
     void WriteIncludes(String& source);
 

+ 1 - 1
Source/ToolCore/JSBind/CSharp/CSPackageWriter.cpp

@@ -47,7 +47,7 @@ void CSPackageWriter::GenNativeFunctionSignature(JSBFunction* function, String&
 {
     JSBClass* klass = function->GetClass();
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
     Vector<String> args;
 

+ 2 - 2
Source/ToolCore/JSBind/CSharp/CSTypeHelper.cpp

@@ -31,7 +31,7 @@ void CSTypeHelper::GenNativeFunctionParameterSignature(JSBFunction* function, St
 {
     JSBClass* klass = function->GetClass();
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
     Vector<String> args;
 
@@ -398,7 +398,7 @@ bool CSTypeHelper::OmitFunction(JSBFunction* function)
         }
     }
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
     for (unsigned i = 0; i < parameters.Size(); i++)
     {

+ 21 - 4
Source/ToolCore/JSBind/JSBClass.cpp

@@ -65,7 +65,7 @@ bool JSBFunctionSignature::Match(JSBFunction* function)
     if (name_ != function->GetName())
         return false;
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
     if (types_.Size() != parameters.Size())
         return false;
@@ -300,9 +300,26 @@ void JSBClass::Process()
 
         for (unsigned k = 0; k < excludes_.Size(); k++)
         {
-            if (excludes_[k]->Match(functions_[j]))
+            JSBFunctionSignature* sig = excludes_[k];
+
+            if (sig->Match(functions_[j]))
             {
-                functions_[j]->SetSkip(true);
+                if (!sig->associatedBindings_.Size())
+                {
+                    functions_[j]->SetSkip(true);
+                }
+                else
+                {
+                    for (unsigned x = 0; x < sig->associatedBindings_.Size(); x++)
+                    {
+                        // This shouldn't happen
+                        if (sig->associatedBindings_[x] == BINDINGLANGUAGE_ANY)
+                            continue;
+
+                        functions_[j]->SetSkipLanguage(sig->associatedBindings_[x]);
+                    }
+                }
+
                 break;
             }
 
@@ -323,7 +340,7 @@ void JSBClass::Process()
         // skip function if only one parameter of type Context, if not Constuctor
         if (!function->IsConstructor())
         {
-            Vector<JSBFunctionType*>& parameters = function->GetParameters();
+            const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
             if (parameters.Size() == 1 && parameters.At(0)->type_->asClassType())
             {

+ 2 - 0
Source/ToolCore/JSBind/JSBClass.h

@@ -55,6 +55,8 @@ public:
     void Parse() ;
 
     bool parsed_;
+
+    PODVector<BindingLanguage> associatedBindings_;
 };
 
 class JSBProperty

+ 1 - 1
Source/ToolCore/JSBind/JSBDoc.cpp

@@ -85,7 +85,7 @@ String JSBDoc::GenFunctionDoc(JSBFunction* function)
 
     String params;
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
     for (unsigned i = 0; i < parameters.Size(); i++)
     {

+ 203 - 0
Source/ToolCore/JSBind/JSBEvent.cpp

@@ -0,0 +1,203 @@
+
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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/IO/Log.h>
+
+#include "JSBind.h"
+#include "JSBHeader.h"
+#include "JSBModule.h"
+#include "JSBPackage.h"
+#include "JSBEvent.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+JSBEvent::JSBEvent(Context* context, JSBModule* module, const String& eventID, const String& eventName) :
+    Object(context),
+    module_(module), 
+    header_(0),
+    eventID_(eventID),
+    eventName_(eventName)
+{
+
+}
+
+JSBEvent::~JSBEvent()
+{
+
+}
+
+JSBPackage* JSBEvent::GetPackage()
+{
+    return module_->GetPackage();
+}
+
+String JSBEvent::GetScriptEventName() const
+{
+    if (eventName_.EndsWith("Event"))
+        return eventName_;
+
+    return eventName_ + "Event";
+
+}
+
+bool JSBEvent::ScanModuleEvents(JSBModule* module)
+{
+    const Vector<SharedPtr<JSBHeader>>& headers = module->GetHeaders();
+
+    for (unsigned i = 0; i < headers.Size(); i++)
+    {
+        JSBHeader* header = headers.At(i);
+
+        String source = header->GetSource();
+
+        if (!source.Contains("ATOMIC_EVENT"))
+            continue;
+
+        StringVector lines = source.Split('\n');
+
+        SharedPtr<JSBEvent> curEvent;
+        String eventID;
+        String eventName;
+
+        for (unsigned j = 0; j < lines.Size(); j++)
+        {
+            String line = lines[j].Trimmed();
+            line.Replace("\r", "");
+
+            // Note: processes ATOMIC_EVENT decl in commented blocks
+            if (line.StartsWith("ATOMIC_EVENT"))
+            {
+                StringVector parts = line.Split('(');
+
+                if (parts.Size() != 2)
+                {
+                    ATOMIC_LOGWARNINGF("Unable to parse native event splitting '(' : %s : %s", header->GetFilePath().CString(), line.CString());
+                    continue;
+                }
+
+                parts = parts[1].Split(',');
+
+                if (parts.Size() != 2)
+                {
+                    ATOMIC_LOGWARNINGF("Unable to parse native even splitting ',' : %s : %s", header->GetFilePath().CString(), line.CString());
+                    continue;
+                }
+
+                eventID = parts[0].Trimmed();
+                eventName = parts[1].Trimmed();
+                eventName.Replace(")", "");
+
+                curEvent = new JSBEvent(module->GetContext(), module, eventID, eventName);
+            }            
+
+            if (line.Contains("}") && curEvent.NotNull())
+            {
+                module->RegisterEvent(curEvent);
+                curEvent = 0;
+            }
+
+            // ATOMIC_PARAM(P_TYPE, Type);                 // enum UI_EVENT_TYPE
+
+            if (line.StartsWith("ATOMIC_PARAM"))
+            {
+                if (curEvent.Null())
+                {
+                    ATOMIC_LOGWARNINGF("WARNING: Event param outside of current event: %s", line.CString());
+                    continue;
+                }
+
+                line.Replace("ATOMIC_PARAM", "");
+                line.Replace("(", "");
+                line.Replace(")", "");
+
+                StringVector parts = line.Split(';');
+
+                if (parts.Size() != 2)
+                {
+                    ATOMIC_LOGWARNINGF("Unable to parse native event param splitting ';' : %s : %s", header->GetFilePath().CString(), line.CString());
+                    continue;
+                }
+
+                String typeInfo;
+                String enumTypeName;
+
+                // comment contains type
+                if (parts[1].Contains("//"))
+                {
+                    String comment = parts[1];
+                    comment.Replace("//", "");
+                    comment = comment.Trimmed();
+                    StringVector typeVector = comment.Split(' ');
+                    if (typeVector.Size() > 0)
+                    {
+                        typeInfo = typeVector[0];
+
+                        if (typeInfo == "enum" && typeVector.Size() > 1)
+                        {
+                            if (JSBPackage::GetEnumAllPackages(typeVector[1]))
+                            {
+                                enumTypeName = typeVector[1];
+                            }
+                        }
+                    }
+                }
+
+                if (!typeInfo.Length())
+                {
+                    ATOMIC_LOGWARNINGF("Could not get type info for event param : %s : (%s) file: %s", 
+                        curEvent->GetEventID().CString(), line.CString(), header->GetFilePath().CString());
+                    continue;
+                }
+
+                // ID and Name parse
+                parts = parts[0].Split(',');
+
+                if (parts.Size() != 2)
+                {
+                    ATOMIC_LOGWARNINGF("Unable to parse native event param splitting ',' : %s : %s", header->GetFilePath().CString(), line.CString());
+                    continue;
+                }
+
+                typeInfo.Replace("*", "");
+
+                EventParam param;
+                param.paramID_ = parts[0].Trimmed();
+                param.paramName_ = parts[1].Trimmed();
+                param.typeInfo_ = typeInfo;
+                param.enumTypeName_ = enumTypeName;
+
+                curEvent->parameters_.Push(param);
+
+            }
+
+        }
+        
+    }
+
+    return true;
+}
+
+}

+ 83 - 0
Source/ToolCore/JSBind/JSBEvent.h

@@ -0,0 +1,83 @@
+//
+// Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
+//
+// 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>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+    class JSBPackage;
+    class JSBModule;
+    class JSBHeader;
+
+
+    class JSBEvent : public Object
+    {
+
+        ATOMIC_OBJECT(JSBEvent, Object)
+
+    public:
+
+        struct EventParam
+        {
+            String paramID_;
+            String paramName_;
+            String typeInfo_;
+            String enumTypeName_;
+        };
+
+        JSBEvent(Context* context, JSBModule* module, const String& eventID, const String& eventName);
+        virtual ~JSBEvent();
+
+        const String& GetEventID() const { return eventID_; }
+        const String& GetEventName() const { return eventName_; }
+        /// Generally this is the EventName + "Event"
+        String GetScriptEventName() const;
+        const Vector<EventParam>& GetParameters() const { return parameters_;  }
+
+
+        void SetHeader(JSBHeader* header) { header_ = header; }
+        JSBHeader* GetHeader() { return header_; }
+
+        JSBPackage* GetPackage();       
+
+        static bool ScanModuleEvents(JSBModule* module);
+
+
+    private:
+
+        SharedPtr<JSBModule> module_;
+        JSBHeader* header_;
+
+        String eventName_;
+        String eventID_;
+
+        Vector<EventParam> parameters_;
+
+    };
+
+
+}

+ 1 - 1
Source/ToolCore/JSBind/JSBFunction.cpp

@@ -104,7 +104,7 @@ bool JSBFunction::Match(JSBFunction* func)
             return false;
     }
 
-    Vector<JSBFunctionType*>& fparams = func->GetParameters();
+    const Vector<JSBFunctionType*>& fparams = func->GetParameters();
 
     if (parameters_.Size() != fparams.Size())
         return false;

+ 26 - 13
Source/ToolCore/JSBind/JSBFunction.h

@@ -139,19 +139,19 @@ public:
 
     JSBFunction(JSBClass* klass);
 
-    const String& GetName() { return name_; }
+    const String& GetName() const { return name_; }
 
     bool Match(JSBFunction* func);
 
-    bool IsConstructor() { return isConstructor_; }
-    bool IsDestructor() { return isDestructor_; }
-    bool IsSetter() { return isSetter_; }
-    bool IsGetter() { return isGetter_; }
+    bool IsConstructor() const { return isConstructor_; }
+    bool IsDestructor() const { return isDestructor_; }
+    bool IsSetter() const { return isSetter_; }
+    bool IsGetter() const { return isGetter_; }
     bool IsOverload() { return isOverload_; }
-    bool IsVirtual() { return isVirtual_; }
-    bool IsStatic() { return isStatic_; }
+    bool IsVirtual() const { return isVirtual_; }
+    bool IsStatic() const { return isStatic_; }
 
-    bool Skip(BindingLanguage language = BINDINGLANGUAGE_ANY)
+    bool Skip(BindingLanguage language = BINDINGLANGUAGE_ANY) const
     {
         if (skip_ || language == BINDINGLANGUAGE_ANY)
             return skip_;
@@ -161,16 +161,16 @@ public:
 
     unsigned GetID() const { return id_; }
 
-    JSBClass* GetClass() { return class_; }
+    JSBClass* GetClass() const { return class_; }
     const String& GetPropertyName() { return propertyName_; }
-    JSBFunctionType* GetReturnType() { return returnType_; }
+    JSBFunctionType* GetReturnType() const { return returnType_; }
 
     /// Get class return type or null
     JSBClass* GetReturnClass();
 
-    Vector<JSBFunctionType*>& GetParameters() { return parameters_; }
+    const Vector<JSBFunctionType*>& GetParameters() const { return parameters_; }
 
-    const String& GetDocString() { return docString_; }
+    const String& GetDocString() const { return docString_; }
 
     void SetName(const String& name) { name_ = name; }
     void SetConstructor(bool value = true) { isConstructor_ = value; }
@@ -236,7 +236,7 @@ public:
 
     void Dump()
     {
-        String sig;
+        String sig = ToString("Function ID: %u - ", id_);
         if (!returnType_)
             sig += "void ";
         else
@@ -254,6 +254,19 @@ public:
         }
         sig += ");";
 
+        String skipText;
+
+        if (GetSkipLanguage(BINDINGLANGUAGE_CSHARP))
+            skipText += "C#";
+
+        if (GetSkipLanguage(BINDINGLANGUAGE_JAVASCRIPT))
+            skipText += " JavaScript";
+
+        if (skipText.Length())
+        {
+            sig += ToString(" (Skipped: %s)", skipText.CString());
+        }
+
         ATOMIC_LOGINFOF("      %s", sig.CString());
 
     }

+ 6 - 6
Source/ToolCore/JSBind/JSBHaxe.cpp

@@ -34,7 +34,7 @@
 namespace ToolCore
 {
 
-    String JSBHaxe::GetScriptType(JSBFunctionType* ftype)
+    String JSBHaxe::GetScriptType(const JSBFunctionType* ftype)
     {
         String scriptType = "Dynamic";
 
@@ -114,11 +114,11 @@ namespace ToolCore
         source_ += "\n}\n";
     }
 
-    bool JSBHaxe::IsOverride(JSBFunction* function) {
+    bool JSBHaxe::IsOverride(const JSBFunction* function) {
         return findFunctionInBase(function) != NULL;
     }
 
-    JSBFunction* JSBHaxe::findFunctionInBase(JSBFunction* function) {
+    JSBFunction* JSBHaxe::findFunctionInBase(const JSBFunction* function) {
         PODVector<JSBClass*>& base = function->GetClass()->GetBaseClasses();
         for (unsigned j = 0; j < base.Size(); j++)
         {
@@ -142,7 +142,7 @@ namespace ToolCore
         return NULL;
     }
 
-    void JSBHaxe::ExportFunction(JSBFunction* function)
+    void JSBHaxe::ExportFunction(const JSBFunction* function)
     {
         //probably no need to check
         if (function->Skip())
@@ -165,7 +165,7 @@ namespace ToolCore
             //if (function->IsOverload())
             {
                 source_ += "    @:overload(function(";
-                Vector<JSBFunctionType*>& parameters = function->GetParameters();
+                const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
                 for (unsigned i = 0; i < parameters.Size(); i++)
                 {
@@ -202,7 +202,7 @@ namespace ToolCore
 
         source_ += scriptName + "(";
 
-        Vector<JSBFunctionType*>& parameters = function->GetParameters();
+        Vector<JSBFunctionType*> parameters = function->GetParameters();
 
         if (IsOverride(function))
             parameters = findFunctionInBase(function)->GetParameters();

+ 4 - 4
Source/ToolCore/JSBind/JSBHaxe.h

@@ -50,14 +50,14 @@ namespace ToolCore
 
         void End();
 
-        void ExportFunction(JSBFunction* function);
+        void ExportFunction(const JSBFunction* function);
 
-        String GetScriptType(JSBFunctionType* ftype);
+        String GetScriptType(const JSBFunctionType* ftype);
         String GetPrimitiveType(JSBPrimitiveType* ptype);
 
         bool checkV(JSBClass* clazz, const String name, const String type);
-        bool IsOverride(JSBFunction* function);
-        JSBFunction* findFunctionInBase(JSBFunction* function);
+        bool IsOverride(const JSBFunction* function);
+        JSBFunction* findFunctionInBase(const JSBFunction* function);
 
         void ExportEnums(JSBModule* moduleName);
         void ExportModuleConstants(JSBModule*  moduleName);

+ 2 - 0
Source/ToolCore/JSBind/JSBHeader.h

@@ -59,6 +59,8 @@ public:
     void VisitPreprocess();
     void VisitHeader();
 
+    const char* GetSource() const { return (const char*)data_.Get(); }
+
 private:
 
     CPlusPlus::TranslationUnit* translationUnit_;

+ 4 - 0
Source/ToolCore/JSBind/JSBHeaderVisitor.h

@@ -324,6 +324,10 @@ public:
                 return NULL;
         }
 
+        // We don't support pointers to Vector2/Vector3/etc which are generally out values 
+        if (isPointer && jtype->asClassType() && jtype->asClassType()->class_->IsNumberArray())
+            return NULL;
+
         JSBFunctionType* ftype = new JSBFunctionType(jtype);
         ftype->isPointer_ = isPointer;
         ftype->isSharedPtr_ = isSharedPtr;

+ 83 - 32
Source/ToolCore/JSBind/JSBModule.cpp

@@ -35,6 +35,7 @@
 #include "JSBEnum.h"
 #include "JSBModuleWriter.h"
 #include "JSBType.h"
+#include "JSBEvent.h"
 
 #include "JavaScript/JSModuleWriter.h"
 #include "CSharp/CSModuleWriter.h"
@@ -160,7 +161,7 @@ void JSBModule::ProcessOverloads()
 
                 if (!_sig.IsArray())
                 {
-                    ErrorExit("Bad overload defintion");
+                    ErrorExit("Bad overload definition");
                 }
 
                 JSONArray sig = _sig.GetArray();
@@ -179,56 +180,78 @@ void JSBModule::ProcessOverloads()
     }
 }
 
-void JSBModule::ProcessExcludes()
+void JSBModule::ProcessExcludes(const JSONValue& excludes, BindingLanguage language)
 {
-    // excludes
+    Vector<String> childNames = excludes.GetObject().Keys();
 
-    JSONValue root = moduleJSON_->GetRoot();
-
-    JSONValue excludes = root.Get("excludes");
-
-    if (excludes.IsObject())
+    for (unsigned j = 0; j < childNames.Size(); j++)
     {
-        Vector<String> childNames = excludes.GetObject().Keys();
+        String classname = childNames.At(j);
 
-        for (unsigned j = 0; j < childNames.Size(); j++)
+        if (classname == "CSharp")
         {
-            String classname = childNames.At(j);
+            JSONValue sharpexcludes = excludes.Get("CSharp");
 
-            JSBClass* klass = GetClass(classname);
-
-            if (!klass)
+            if (sharpexcludes.IsObject())
             {
-                ErrorExit("Bad exclude klass");
+                ProcessExcludes(sharpexcludes, BINDINGLANGUAGE_CSHARP);
             }
 
-            JSONValue classexcludes = excludes.Get(classname);
+            continue;
+        }
 
-            Vector<String> functionNames = classexcludes.GetObject().Keys();
+        JSBClass* klass = GetClass(classname);
 
-            for (unsigned k = 0; k < functionNames.Size(); k++)
-            {
-                JSONValue _sig = classexcludes.Get(functionNames[k]);
+        if (!klass)
+        {
+            ErrorExit("Bad exclude klass");
+        }
 
-                if (!_sig.IsArray())
-                {
-                    ErrorExit("Bad exclude defintion");
-                }
+        JSONValue classexcludes = excludes.Get(classname);
 
-                JSONArray sig = _sig.GetArray();
+        Vector<String> functionNames = classexcludes.GetObject().Keys();
 
-                Vector<String> values;
-                for (unsigned x = 0; x < sig.Size(); x++)
-                {
-                    values.Push(sig[x].GetString());
-                }
+        for (unsigned k = 0; k < functionNames.Size(); k++)
+        {
+            JSONValue _sig = classexcludes.Get(functionNames[k]);
+
+            if (!_sig.IsArray())
+            {
+                ErrorExit("Bad exclude defintion");
+            }
 
-                JSBFunctionSignature* fe = new JSBFunctionSignature(functionNames[k], values);
-                klass->AddFunctionExclude(fe);
+            JSONArray sig = _sig.GetArray();
 
+            Vector<String> values;
+            for (unsigned x = 0; x < sig.Size(); x++)
+            {
+                values.Push(sig[x].GetString());
             }
+
+            JSBFunctionSignature* fe = new JSBFunctionSignature(functionNames[k], values);
+            
+            if (language != BINDINGLANGUAGE_ANY)
+                fe->associatedBindings_.Push(language);
+            
+            klass->AddFunctionExclude(fe);
+
         }
     }
+
+}
+
+void JSBModule::ProcessExcludes()
+{
+    // excludes
+
+    JSONValue root = moduleJSON_->GetRoot();
+
+    JSONValue excludes = root.Get("excludes");
+
+    if (excludes.IsObject())
+    {
+        ProcessExcludes(excludes);
+    }
 }
 
 void JSBModule::ProcessClassExcludes()
@@ -396,6 +419,34 @@ void JSBModule::RegisterClass(String name)
     }
 }
 
+void JSBModule::RegisterEvent(JSBEvent* event)
+{
+    if (JSBPackage::GetEventAllPackages(event->GetEventID(), event->GetEventName()))
+    {
+        ErrorExit(ToString("Event collision: %s : %s", event->GetEventID().CString(), event->GetEventName().CString()));
+    }
+
+    events_.Push(SharedPtr<JSBEvent>(event));
+}
+
+JSBEvent* JSBModule::GetEvent(const String& eventID, const String& eventName)
+{
+    for (unsigned i = 0; i < events_.Size(); i++)
+    {
+        if (events_[i]->GetEventName() == eventName || events_[i]->GetEventID() == eventID)
+        {
+            return events_[i];
+        }
+    }
+
+    return 0;
+}
+
+const Vector<SharedPtr<JSBEvent>>& JSBModule::GetEvents()
+{    
+    return events_;
+}
+
 void JSBModule::RegisterEnum(JSBEnum* jenum)
 {
     if (JSBPackage::GetClassAllPackages(jenum->GetName()))

+ 14 - 0
Source/ToolCore/JSBind/JSBModule.h

@@ -23,6 +23,8 @@
 #pragma once
 
 #include <Atomic/Core/Object.h>
+#include <Atomic/Resource/JSONValue.h>
+#include "JSBindTypes.h"
 
 using namespace Atomic;
 
@@ -38,6 +40,7 @@ class JSBPackage;
 class JSBHeader;
 class JSBClass;
 class JSBEnum;
+class JSBEvent;
 class JSBPrimitiveType;
 
 class JSBModule : public Object
@@ -75,6 +78,11 @@ public:
     bool ContainsConstant(const String& constantName);
     void RegisterConstant(const String& constantName, const String& value, unsigned type, bool isUnsigned = false);
 
+    JSBEvent* GetEvent(const String& eventID, const String& eventName);
+    void RegisterEvent(JSBEvent* event);
+
+    const Vector<SharedPtr<JSBEvent>>& GetEvents();
+
     bool Requires(const String& requirement) { return requirements_.Contains(requirement); }
 
     bool Load(const String& jsonFilename);
@@ -94,9 +102,13 @@ public:
     /// Define guard for specific module code
     String GetClassDefineGuard(const String& name, const String& language = String::EMPTY) const;
 
+    /// Get the module's header files
+    const Vector<SharedPtr<JSBHeader>>& GetHeaders() const { return headers_; }
+
 private:
 
     void ProcessOverloads();
+    void ProcessExcludes(const JSONValue& excludes, BindingLanguage language = BINDINGLANGUAGE_ANY);
     void ProcessExcludes();
     void ProcessClassExcludes();
     void ProcessTypeScriptDecl();
@@ -122,6 +134,8 @@ private:
     HashMap<StringHash, SharedPtr<JSBClass> > classes_;
     HashMap<StringHash, SharedPtr<JSBEnum> > enums_;
 
+    Vector<SharedPtr<JSBEvent> > events_;
+
     HashMap<String, Constant> constants_;
 
     Vector<String> requirements_;

+ 31 - 0
Source/ToolCore/JSBind/JSBPackage.cpp

@@ -26,6 +26,7 @@
 #include <Atomic/Resource/JSONFile.h>
 
 #include "JSBind.h"
+#include "JSBEvent.h"
 #include "JSBModule.h"
 #include "JSBPackage.h"
 #include "JSBPackageWriter.h"
@@ -77,6 +78,11 @@ void JSBPackage::ProcessModules()
         modules_[i]->PostProcessClasses();
     }
 
+    for (unsigned i = 0; i < modules_.Size(); i++)
+    {
+        JSBEvent::ScanModuleEvents(modules_[i]);
+    }
+
 }
 
 void JSBPackage::GenerateSource(JSBPackageWriter& packageWriter)
@@ -110,6 +116,31 @@ JSBClass* JSBPackage::GetClassAllPackages(const String& name)
 
 }
 
+JSBEvent* JSBPackage::GetEvent(const String& eventID, const String& eventName)
+{
+    for (unsigned i = 0; i < modules_.Size(); i++)
+    {
+        JSBEvent* event = modules_[i]->GetEvent(eventID, eventName);
+
+        if (event)
+            return event;
+    }
+
+    return 0;
+}
+
+JSBEvent* JSBPackage::GetEventAllPackages(const String& eventID, const String& eventName)
+{
+    for (unsigned i = 0; i < allPackages_.Size(); i++)
+    {
+        JSBEvent* event = allPackages_[i]->GetEvent(eventID, eventName);
+        if (event)
+            return event;
+    }
+
+    return 0;
+}
+
 JSBEnum* JSBPackage::GetEnum(const String& name)
 {
     for (unsigned i = 0; i < modules_.Size(); i++)

+ 7 - 1
Source/ToolCore/JSBind/JSBPackage.h

@@ -32,7 +32,7 @@ namespace ToolCore
 class JSBModule;
 class JSBClass;
 class JSBEnum;
-
+class JSBEvent;
 class JSBPackageWriter;
 
 class JSBPackage : public Object
@@ -85,6 +85,12 @@ public:
 
     static bool ContainsConstantAllPackages(const String& constantName);
 
+    /// Get an event from this package, matches on either eventID or eventName
+    JSBEvent* GetEvent(const String& eventID, const String& eventName);
+
+    // get an event by name across all loaded packages
+    static JSBEvent* GetEventAllPackages(const String& eventID, const String& eventName);
+
     void GenerateSource(JSBPackageWriter& packageWriter);
 
     /// Define guard for the package as a whole

+ 1 - 1
Source/ToolCore/JSBind/JSBPreprocessVisitor.h

@@ -87,7 +87,7 @@ public:
                 }
             }
 
-            jenum->AddValue(name);
+            jenum->AddValue(name, value);
 
         }
 

+ 1 - 1
Source/ToolCore/JSBind/JSBTypeScript.cpp

@@ -134,7 +134,7 @@ void JSBTypeScript::ExportFunction(JSBFunction* function)
 
     source_ += scriptName + "(";
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
     for (unsigned i = 0; i < parameters.Size(); i++)
     {

+ 1 - 1
Source/ToolCore/JSBind/JavaScript/JSClassWriter.cpp

@@ -164,7 +164,7 @@ bool JSClassWriter::OmitFunction(JSBFunction* function)
     if (function->GetSkipLanguage(BINDINGLANGUAGE_JAVASCRIPT))
         return true;
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
     if (function->GetReturnType() && function->GetReturnType()->type_->asVectorType())
     {

+ 7 - 4
Source/ToolCore/JSBind/JavaScript/JSFunctionWriter.cpp

@@ -42,7 +42,7 @@ JSFunctionWriter::JSFunctionWriter(JSBFunction *function) : JSBFunctionWriter(fu
 void JSFunctionWriter::WriteParameterMarshal(String& source)
 {
     // generate args
-    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
 
     int cparam = 0;
     if (parameters.Size())
@@ -278,7 +278,7 @@ void JSFunctionWriter::WriteConstructor(String& source)
         String sparams;
         int cparam = 0;
 
-        Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+        const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
 
         for (unsigned i = 0; i < parameters.Size(); i++, cparam++)
         {
@@ -411,7 +411,10 @@ void JSFunctionWriter::WriteFunction(String& source)
             else if (klassType->class_->IsNumberArray())
             {
                 returnDeclared = true;
-                source.AppendWithFormat("const %s& retValue = ", klassType->class_->GetName().CString());
+                if (returnType->isReference_)
+                    source.AppendWithFormat("const %s& retValue = ", klassType->class_->GetName().CString());
+                else
+                    source.AppendWithFormat(" %s retValue = ", klassType->class_->GetName().CString());
             }
             else
             {
@@ -443,7 +446,7 @@ void JSFunctionWriter::WriteFunction(String& source)
         source.AppendWithFormat("native->%s(", function_->name_.CString());
     }
 
-    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function_->GetParameters();
 
     for (unsigned int i = 0; i < parameters.Size(); i++)
     {