Browse Source

Merge pull request #1077 from AtomicGameEngine/JME-ATOMIC-SCRIPTEVENTS

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

+ 6 - 0
Data/AtomicEditor/ExampleInfo/Examples.json

@@ -1,6 +1,12 @@
 {
 {
     "examples" : [
     "examples" : [
 
 
+        {
+            "name": "Feature Examples",
+            "desc" : "Multiple Feature Examples",
+            "screenshot" : "Example.png",
+            "folder" : "FeatureExamples"
+        },
         {
         {
             "name": "Basic2D",
             "name": "Basic2D",
             "desc" : "Basic2D Scene Example",
             "desc" : "Basic2D Scene Example",

+ 10 - 0
Script/AtomicEditor/ui/modal/ModalOps.ts

@@ -53,6 +53,16 @@ class ModalOps extends Atomic.ScriptObject {
 
 
         this.dimmer = new Atomic.UIDimmer();
         this.dimmer = new Atomic.UIDimmer();
 
 
+        this.subscribeToEvent("WindowClosed", (e) => {
+            if (e.window == this.opWindow)
+            {
+                this.opWindow = null;
+                if (this.dimmer.parent) {
+                    this.dimmer.parent.removeChild(this.dimmer, false);
+                }
+            }
+        });
+
     }
     }
 
 
     showCreateProject(projectTemplateDefinition: ProjectTemplates.ProjectTemplateDefinition) {
     showCreateProject(projectTemplateDefinition: ProjectTemplates.ProjectTemplateDefinition) {

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

@@ -12,13 +12,18 @@ namespace AtomicEngine
         static protected void RegisterSubsystems()
         static protected void RegisterSubsystems()
         {
         {
             // TODO: Refactor these registrations
             // TODO: Refactor these registrations
+
+            AtomicNET.RegisterSubsystem("Engine");
+
             AtomicNET.RegisterSubsystem("FileSystem");
             AtomicNET.RegisterSubsystem("FileSystem");
 
 
             AtomicNET.RegisterSubsystem("Graphics");
             AtomicNET.RegisterSubsystem("Graphics");
             AtomicNET.RegisterSubsystem("Player");
             AtomicNET.RegisterSubsystem("Player");
 
 
+            AtomicNET.RegisterSubsystem("Audio");
             AtomicNET.RegisterSubsystem("Input");
             AtomicNET.RegisterSubsystem("Input");
             AtomicNET.RegisterSubsystem("Renderer");
             AtomicNET.RegisterSubsystem("Renderer");
+            AtomicNET.RegisterSubsystem("UI");
 
 
             AtomicNET.RegisterSubsystem("ResourceCache");
             AtomicNET.RegisterSubsystem("ResourceCache");
             AtomicNET.Cache = AtomicNET.GetSubsystem<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<uint, EventDelegate> eventHandlers;
 
 
-        private Dictionary<SenderEventKey, SenderEventDelegate> SenderEventHandlers
+        private Dictionary<uint, NativeEventDelegate> NativeEventHandlers
         {
         {
             get
             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
         public static T GetSubsystem<T>() where T : AObject
         {
         {
             return AtomicNET.GetSubsystem<T>();
             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)
         public void SubscribeToEvent(uint eventType, EventDelegate eventDelegate)
@@ -66,80 +91,79 @@ namespace AtomicEngine
         {
         {
             NativeCore.UnsubscribeFromEvent(this, eventType);
             NativeCore.UnsubscribeFromEvent(this, eventType);
             EventHandlers.Remove(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)
             if (sender == null)
             {
             {
                 throw new InvalidOperationException("AObject.SubscribeToEvent - trying to subscribe to events from a null object");
                 throw new InvalidOperationException("AObject.SubscribeToEvent - trying to subscribe to events from a null object");
             }
             }
 
 
+            // Move this
             NETCore.RegisterNETEventType(eventType);
             NETCore.RegisterNETEventType(eventType);
-            var key = new SenderEventKey(eventType, sender.nativeInstance);
-            SenderEventHandlers[key] = eventDelegate;
             NativeCore.SubscribeToEvent(this, sender, eventType);
             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);
             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
         // static members so they don't get GC'd
         private static EventDispatchDelegate eventDispatchDelegate = NativeCore.EventDispatch;
         private static EventDispatchDelegate eventDispatchDelegate = NativeCore.EventDispatch;
         private static UpdateDispatchDelegate updateDispatchDelegate = NativeCore.UpdateDispatch;
         private static UpdateDispatchDelegate updateDispatchDelegate = NativeCore.UpdateDispatch;
+        private static RefCountedDeletedDelegate refCountedDeletedDelegate = NativeCore.RefCountedDeleted;
 
 
         public static void Initialize()
         public static void Initialize()
         {
         {
@@ -81,7 +82,7 @@ namespace AtomicEngine
 
 
             PlayerModule.Initialize();
             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));
             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)]
         [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 Context context;
         private static Dictionary<Type, AObject> subSystems = new Dictionary<Type, AObject>();
         private static Dictionary<Type, AObject> subSystems = new Dictionary<Type, AObject>();

+ 97 - 54
Script/AtomicNET/AtomicNET/Core/NativeCore.cs

@@ -18,6 +18,9 @@ namespace AtomicEngine
     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
     public delegate void UpdateDispatchDelegate(float timeStep);
     public delegate void UpdateDispatchDelegate(float timeStep);
 
 
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    public delegate void RefCountedDeletedDelegate(IntPtr refCounted);
+
     public class NativeType
     public class NativeType
     {
     {
 
 
@@ -72,36 +75,10 @@ namespace AtomicEngine
                 throw new InvalidOperationException("NativeCore.SubscribeToEvent - unable to find native receiver instance");
                 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)
         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;
             List<EventSubscription> eventReceivers;
             if (!eventReceiverLookup.TryGetValue(eventType, out eventReceivers))
             if (!eventReceiverLookup.TryGetValue(eventType, out eventReceivers))
@@ -113,8 +90,7 @@ namespace AtomicEngine
                 if (!er.Receiver.TryGetTarget(out obj))
                 if (!er.Receiver.TryGetTarget(out obj))
                     continue; // GC'd
                     continue; // GC'd
 
 
-                if (obj == receiver &&
-                    (sender == null || er.Sender == sender.nativeInstance))
+                if (obj == receiver)
                 {
                 {
                     eventReceivers.Remove(er);
                     eventReceivers.Remove(er);
                     return;
                     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 ScriptVariantMap[] svm;
         static int svmDepth = 0;
         static int svmDepth = 0;
         const int svmMax = 256;
         const int svmMax = 256;
@@ -138,15 +144,24 @@ namespace AtomicEngine
         static float expireDelta = 0.0f;
         static float expireDelta = 0.0f;
 
 
         // called ahead of E_UPDATE event
         // called ahead of E_UPDATE event
-#if ATOMIC_IOS
+        #if ATOMIC_IOS
         [MonoPInvokeCallback(typeof(UpdateDispatchDelegate))]
         [MonoPInvokeCallback(typeof(UpdateDispatchDelegate))]
-#endif
+        #endif
         public static void UpdateDispatch(float timeStep)
         public static void UpdateDispatch(float timeStep)
         {
         {
             expireDelta += timeStep;
             expireDelta += timeStep;
             if (expireDelta > 2.0f)
             if (expireDelta > 2.0f)
             {
             {
                 expireDelta = 0.0f;
                 expireDelta = 0.0f;
+
+
+                // TODO: tune GC
+                /*
+                GC.Collect();
+                GC.WaitForPendingFinalizers();
+                GC.Collect();
+                */
+
                 ExpireNatives();
                 ExpireNatives();
             }
             }
         }
         }
@@ -165,20 +180,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
             // iterate over copy of list so we can modify it while running
             ScriptVariantMap scriptMap = null;
             ScriptVariantMap scriptMap = null;
+            NativeEventData nativeEventData = null;
+
             AObject receiver;
             AObject receiver;
             foreach (EventSubscription er in eventReceivers.ToList())
             foreach (EventSubscription er in eventReceivers.ToList())
             {
             {
@@ -186,6 +191,9 @@ namespace AtomicEngine
                 if (!er.Receiver.TryGetTarget(out receiver))
                 if (!er.Receiver.TryGetTarget(out receiver))
                     continue;
                     continue;
 
 
+                if (er.Sender != IntPtr.Zero && er.Sender != sender)
+                    continue;
+
                 if (scriptMap == null)
                 if (scriptMap == null)
                 {
                 {
                     if (svmDepth == svmMax)
                     if (svmDepth == svmMax)
@@ -195,21 +203,23 @@ namespace AtomicEngine
 
 
                     scriptMap = svm[svmDepth++];
                     scriptMap = svm[svmDepth++];
                     scriptMap.CopyVariantMap(eventData);
                     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)
             if (scriptMap != null)
+            {
                 svmDepth--;
                 svmDepth--;
 
 
+                if (nativeEventData != null)
+                {
+                    NativeEvents.ReleaseNativeEventData(nativeEventData);
+                }
+            }
+
         }
         }
 
 
         static void ExpireNatives()
         static void ExpireNatives()
@@ -270,6 +280,16 @@ namespace AtomicEngine
 
 
         }
         }
 
 
+        // Called from RefCounted native destructor, refCounted is not valid for any operations here
+        #if ATOMIC_IOS
+        [MonoPInvokeCallback(typeof(RefCountedDeletedDelegate))]
+        #endif
+        public static void RefCountedDeleted(IntPtr refCounted)
+        {
+            nativeLookup.Remove(refCounted);
+            RemoveEventSender(refCounted);
+        }
+
         // register a newly created native
         // register a newly created native
         public static IntPtr RegisterNative(IntPtr native, RefCounted r)
         public static IntPtr RegisterNative(IntPtr native, RefCounted r)
         {
         {
@@ -284,6 +304,10 @@ namespace AtomicEngine
 
 
             nativeLookup[native] = new WeakReference<RefCounted>(r);
             nativeLookup[native] = new WeakReference<RefCounted>(r);
 
 
+            r.InstantiationType = InstantiationType.INSTANTIATION_NET;
+
+            r.PostNativeUpdate();
+
             return native;
             return native;
         }
         }
 
 
@@ -334,6 +358,10 @@ namespace AtomicEngine
                 throw new InvalidOperationException("NativeCore.WrapNative - Attempting to wrap unknown native class id");
                 throw new InvalidOperationException("NativeCore.WrapNative - Attempting to wrap unknown native class id");
             }
             }
 
 
+            // TODO: make CSComponent abstract and have general abstract logic here?
+            if (nativeType.Type == typeof(CSComponent))
+                return null;
+
             r = nativeType.managedConstructor(native);
             r = nativeType.managedConstructor(native);
 
 
             w = new WeakReference<RefCounted>(r);
             w = new WeakReference<RefCounted>(r);
@@ -342,6 +370,15 @@ namespace AtomicEngine
             // store a ref, so native side will not be released while we still have a reference in managed code
             // store a ref, so native side will not be released while we still have a reference in managed code
             r.AddRef();
             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;
             return (T)r;
         }
         }
 
 
@@ -439,10 +476,16 @@ namespace AtomicEngine
             public WeakReference<AObject> Receiver;
             public WeakReference<AObject> Receiver;
             public IntPtr Sender;
             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;
+using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 namespace AtomicEngine
 namespace AtomicEngine
 {
 {
     public delegate void EventDelegate(uint eventType, ScriptVariantMap eventData);
     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
     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
 namespace AtomicEngine
 {
 {
 
 
+    [ComVisible(true)]
     public partial class RefCounted
     public partial class RefCounted
     {
     {
 
 
@@ -16,6 +17,14 @@ namespace AtomicEngine
             nativeInstance = native;
             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)
         public static implicit operator IntPtr(RefCounted refCounted)
         {
         {
             if (refCounted == null)
             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
 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;
             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 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)
         public static Color operator *(Color value, float scale)
         {
         {
@@ -54,4 +58,4 @@ namespace AtomicEngine
         public float A;
         public float A;
 
 
     }
     }
-}
+}

+ 76 - 28
Script/AtomicNET/AtomicNET/Math/Matrix3x4.cs

@@ -4,44 +4,92 @@ using System.Runtime.InteropServices;
 namespace AtomicEngine
 namespace AtomicEngine
 {
 {
 
 
-    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+    [StructLayout(LayoutKind.Sequential)]
     public struct Matrix3x4
     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 public readonly Matrix3x4 IDENTITY = CreateIdentity();
 
 
         static Matrix3x4 CreateIdentity()
         static Matrix3x4 CreateIdentity()
         {
         {
             var m = new Matrix3x4();
             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;
+            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;
             return m;
-
         }
         }
 
 
-        float m00_;
-        float m01_;
-        float m02_;
-        float m03_;
-        float m10_;
-        float m11_;
-        float m12_;
-        float m13_;
-        float m20_;
-        float m21_;
-        float m22_;
-        float m23_;
+        public Matrix3x4 Inverse()
+        {
+            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);
 
 
+            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);
+
+    }
+
+}

+ 33 - 0
Script/AtomicNET/AtomicNET/Player/Player.cs

@@ -0,0 +1,33 @@
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+using AtomicEngine;
+
+namespace AtomicPlayer
+{
+    public partial class Player : AObject
+    {
+        static List<Scene> loadedScenes = new List<Scene>();
+
+        internal override void PostNativeUpdate()
+        {
+            SubscribeToEvent<PlayerSceneLoadBeginEvent>(e =>
+            {
+                loadedScenes.Add(e.Scene);
+            });
+
+            SubscribeToEvent<PlayerSceneLoadEndEvent>(e =>
+            {
+                if (!e.Success)
+                    loadedScenes.Remove(e.Scene);
+            });
+
+        }
+
+
+    }
+
+}
+

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

@@ -9,6 +9,11 @@ namespace AtomicEngine
             return (T) GetResource(typeof(T).Name, path);
             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;
             return GetType().Name;
         }
         }
 
 
+        public bool Started
+        {
+            get { return started; }
+        }
+
+        internal bool started = false;
+
     }
     }
 
 
 }
 }

+ 19 - 211
Script/AtomicNET/AtomicNET/Scene/CSComponentCore.cs

@@ -43,8 +43,11 @@ namespace AtomicEngine
             Type[] postUpdateParms = new Type[1] { typeof(float) };
             Type[] postUpdateParms = new Type[1] { typeof(float) };
             PostUpdateMethod = type.GetMethod("PostUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, postUpdateParms, null);
             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] { };
             Type[] startParms = new Type[0] { };
             StartMethod = type.GetMethod("Start", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, startParms, null);
             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 FieldInfo[] InspectorFields;
         public Type Type;
         public Type Type;
 
 
-        public MethodInfo FixedUpdateMethod = null;
-        public MethodInfo PostUpdateMethod = null;
-        public MethodInfo UpdateMethod = null;        
+        // Start method called once
         public MethodInfo StartMethod = null;
         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();
         ScriptVariantMap fieldMap = new ScriptVariantMap();
 
 
         public Dictionary<uint, FieldInfo> fieldLookup = new Dictionary<uint, FieldInfo>();
         public Dictionary<uint, FieldInfo> fieldLookup = new Dictionary<uint, FieldInfo>();
@@ -255,86 +144,12 @@ namespace AtomicEngine
 
 
     public class CSComponentCore : NETScriptObject
     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"];
-
-            IntPtr csnative = eventData.GetVoidPtr("NativeInstance");
-            IntPtr fieldValues = IntPtr.Zero;
-
-            if (eventData.Contains("FieldValues"))
-                fieldValues = eventData.GetVoidPtr("FieldValues");
-
-            CSComponentInfo csinfo;
-
-            if (!componentCache.TryGetValue(className, out csinfo))
-            {
-                return;
-            }
-
-            NativeCore.NativeContructorOverride = csnative;
-            var component = (CSComponent)Activator.CreateInstance(csinfo.Type);
-            NativeCore.VerifyNativeContructorOverrideConsumed();
-
-            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)")]
         [Obsolete("Method HandleComponentAssemblyReference is deprecated (loading component assemblies at runtime, will be changed to preload them)")]
         void HandleComponentAssemblyReference(uint eventType, ScriptVariantMap eventData)
         void HandleComponentAssemblyReference(uint eventType, ScriptVariantMap eventData)
         {
         {
-#if ATOMIC_DESKTOP || ATOMIC_MOBILE
             string assemblyPath = eventData["AssemblyPath"];
             string assemblyPath = eventData["AssemblyPath"];
             string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
             string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
-
-            Assembly assembly = Assembly.LoadFrom(assemblyPath);
-
-            ParseAssembly(assembly);
-#endif
+            Log.Info($"Component Assembly referenced {assemblyName} ");
         }
         }
 
 
         void ParseComponents()
         void ParseComponents()
@@ -382,23 +197,16 @@ namespace AtomicEngine
             instance.ParseComponents();
             instance.ParseComponents();
 
 
             instance.SubscribeToEvent("CSComponentAssemblyReference", instance.HandleComponentAssemblyReference);
             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);
 
 
         }
         }
 
 
         // type name -> CSComponentInfo lookup TODO: store with namespace to solve ambiguities
         // type name -> CSComponentInfo lookup TODO: store with namespace to solve ambiguities
-        Dictionary<string, CSComponentInfo> componentCache = new Dictionary<string, CSComponentInfo>();
+        internal static Dictionary<string, CSComponentInfo> componentCache = new Dictionary<string, CSComponentInfo>();
 
 
         [Obsolete("Member parsedAssemblies is temporarily required for runtime component assemblies loading")]
         [Obsolete("Member parsedAssemblies is temporarily required for runtime component assemblies loading")]
         Dictionary<Assembly, bool> parsedAssemblies = new Dictionary<Assembly, bool>();
         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;
         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 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
         public T CreateComponent<T>(CreateMode mode = CreateMode.REPLICATED, uint id = 0) where T : Component
         {
         {
             var type = typeof(T);
             var type = typeof(T);
@@ -16,7 +35,6 @@ namespace AtomicEngine
             if (type.GetTypeInfo().IsSubclassOf(typeof(CSComponent)))
             if (type.GetTypeInfo().IsSubclassOf(typeof(CSComponent)))
             {
             {
                 Component component = (Component)Activator.CreateInstance(type);
                 Component component = (Component)Activator.CreateInstance(type);
-                CSComponentCore.RegisterInstance((CSComponent)component);
                 AddComponent(component, id, mode);
                 AddComponent(component, id, mode);
                 return (T)component;
                 return (T)component;
             }
             }
@@ -24,6 +42,11 @@ namespace AtomicEngine
             return (T)CreateComponent(type.Name, mode, id);
             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)
         public void GetChildrenWithComponent<T>(Vector<Node> dest, bool recursive = false)
         {
         {

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

@@ -0,0 +1,345 @@
+using System;
+using System.Linq;
+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<CSComponentLoadEvent>(this, HandleCSComponentLoad);
+
+            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 started = new List<CSComponent>();
+
+                foreach (var csc in cscomponentStart.ToList())
+                {
+                    if (!csc.IsEnabled())
+                    {
+                        continue;
+                    }
+
+                    // mark as started whether or not a Start method exists
+                    csc.started = true;
+                    started.Add(csc);
+
+                    CSComponentInfo info;
+                    if (CSComponentCore.csinfoLookup.TryGetValue(csc.GetType(), out info))
+                    {
+                        if (info.StartMethod != null)
+                        {
+                            info.StartMethod.Invoke(csc, null);
+                        }
+                    }
+
+                }
+
+                foreach (var csc in started)
+                {
+                    cscomponentStart.Remove(csc);
+                }
+            }
+
+            // Handle Scene Update
+
+            Object[] args = new Object[1] { e.TimeStep };
+
+            foreach (var item in cscomponents.ToList())
+            {
+                var info = item.Key;
+
+                var UpdateMethod = info.UpdateMethod;
+
+                if (UpdateMethod == null)
+                    continue;
+
+                foreach (var csc in item.Value.ToList())
+                {
+                    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 HandleCSComponentLoad(CSComponentLoadEvent e)
+        {
+            var scriptMap = e.scriptMap;
+
+            // Get the NativeInstance as an IntPtr, otherwise we would be wrapping as a CSComponent
+            IntPtr csnative = scriptMap.GetVoidPtr("NativeInstance");
+
+            IntPtr fieldValues = IntPtr.Zero;
+            if (scriptMap.Contains("FieldValues"))
+                fieldValues = scriptMap.GetVoidPtr("FieldValues");
+
+            CSComponentInfo csinfo;
+
+            if (!CSComponentCore.componentCache.TryGetValue(e.ClassName, out csinfo))
+            {
+                return;
+            }
+
+            NativeCore.NativeContructorOverride = csnative;
+            var component = (CSComponent)Activator.CreateInstance(csinfo.Type);
+            NativeCore.VerifyNativeContructorOverrideConsumed();
+
+            if (fieldValues != IntPtr.Zero)
+                csinfo.ApplyFieldValues(component, fieldValues);
+
+            AddCSComponent(component);
+
+        }
+
+        void AddCSComponent(CSComponent csc)
+        {
+            CSComponentInfo info;
+
+            if (!CSComponentCore.csinfoLookup.TryGetValue(csc.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);
+
+        }
+
+        void HandleComponentAdded(ComponentAddedEvent e)
+        {
+            Component component;
+
+            try
+            {
+                // will throw if component isn't a known native
+                component = e.Component;
+            }
+            catch
+            {
+                return;
+            }
+            
+
+            // Check null (CSComponent) or other abstract component
+            if (component == null)
+            {                
+                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;
+                AddCSComponent(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;
+using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
+
 namespace AtomicEngine
 namespace AtomicEngine
 {
 {
     public partial class ScriptVariantMap : RefCounted
     public partial class ScriptVariantMap : RefCounted
@@ -26,11 +28,11 @@ namespace AtomicEngine
             if (value == null)
             if (value == null)
                 return 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)
         public IntPtr GetVoidPtr(string key)
@@ -42,5 +44,6 @@ namespace AtomicEngine
         private static extern IntPtr csi_Atomic_AtomicNET_ScriptVariantMap_GetVoidPtr(IntPtr self, string key);
         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" : {
 	"excludes" : {
 		"Object" : {
 		"Object" : {
 			"SendEvent" : ["StringHash"]
 			"SendEvent" : ["StringHash"]
+		},
+		"CSharp" : {
+			"Object" : {
+				"UnsubscribeFromAllEvents" : []
+			}
 		}
 		}
 	},
 	},
 	"overloads" : {
 	"overloads" : {

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

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

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

@@ -1,5 +1,5 @@
 {
 {
 	"name" : "Script",
 	"name" : "Script",
 	"sources" : ["Source/Atomic/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_;
         delete refCount_;
 
 
     refCount_ = 0;
     refCount_ = 0;
+
+    for (unsigned i = 0; i < refCountedDeletedFunctions_.Size(); i++)
+        refCountedDeletedFunctions_[i](this);
 }
 }
 
 
 void RefCounted::AddRef()
 void RefCounted::AddRef()
@@ -109,6 +112,7 @@ int RefCounted::WeakRefs() const
 // ATOMIC BEGIN
 // ATOMIC BEGIN
 
 
 PODVector<RefCountChangedFunction> RefCounted::refCountChangedFunctions_;
 PODVector<RefCountChangedFunction> RefCounted::refCountChangedFunctions_;
+PODVector<RefCountedDeletedFunction> RefCounted::refCountedDeletedFunctions_;
 
 
 void RefCounted::AddRefSilent()
 void RefCounted::AddRefSilent()
 {
 {
@@ -126,6 +130,16 @@ void RefCounted::RemoveRefCountChangedFunction(RefCountChangedFunction function)
     refCountChangedFunctions_.Remove(function);
     refCountChangedFunctions_.Remove(function);
 }
 }
 
 
+void RefCounted::AddRefCountedDeletedFunction(RefCountedDeletedFunction function)
+{
+    refCountedDeletedFunctions_.Push(function);
+}
+
+void RefCounted::RemoveRefCountedDeletedFunction(RefCountedDeletedFunction function)
+{
+    refCountedDeletedFunctions_.Remove(function);
+}
+
 // ATOMIC END
 // 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
 // function that is called when ref count goes to 1 or 2+, used for script object lifetime
 typedef void (*RefCountChangedFunction)(RefCounted*, int refCount);
 typedef void (*RefCountChangedFunction)(RefCounted*, int refCount);
 
 
+// function callback for when a RefCounted is deleted
+typedef void(*RefCountedDeletedFunction)(RefCounted*);
+
 typedef const void* ClassID;
 typedef const void* ClassID;
 
 
 /// Macro to be included in RefCounted derived classes for efficient RTTI
 /// Macro to be included in RefCounted derived classes for efficient RTTI
@@ -118,6 +121,9 @@ public:
     static void AddRefCountChangedFunction(RefCountChangedFunction function);
     static void AddRefCountChangedFunction(RefCountChangedFunction function);
     static void RemoveRefCountChangedFunction(RefCountChangedFunction function);
     static void RemoveRefCountChangedFunction(RefCountChangedFunction function);
 
 
+    static void AddRefCountedDeletedFunction(RefCountedDeletedFunction function);
+    static void RemoveRefCountedDeletedFunction(RefCountedDeletedFunction function);
+
 // ATOMIC END
 // ATOMIC END
 
 
 private:
 private:
@@ -135,6 +141,7 @@ private:
     void* jsHeapPtr_;
     void* jsHeapPtr_;
 
 
     static PODVector<RefCountChangedFunction> refCountChangedFunctions_;
     static PODVector<RefCountChangedFunction> refCountChangedFunctions_;
+    static PODVector<RefCountedDeletedFunction> refCountedDeletedFunctions_;
 
 
     // ATOMIC END
     // 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
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // 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.
     /// Handle enabled/disabled state change.
     virtual void OnSetEnabled();
     virtual void OnSetEnabled();
     /// Draw debug geometry.
     /// Draw debug geometry.
-    void DrawDebugGeometry(bool);
+    void DrawDebugGeometry(bool depthTest);
     /// Draw debug feelers.
     /// Draw debug feelers.
     virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
     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:
 public:
     /// Construct.
     /// Construct.
-    Obstacle(Context*);
+    Obstacle(Context* content);
     /// Destruct.
     /// Destruct.
     virtual ~Obstacle();
     virtual ~Obstacle();
 
 
     /// Register Obstacle with engine context.
     /// Register Obstacle with engine context.
-    static void RegisterObject(Context*);
+    static void RegisterObject(Context* context);
 
 
     /// Update the owning mesh when enabled status has changed.
     /// Update the owning mesh when enabled status has changed.
     virtual void OnSetEnabled();
     virtual void OnSetEnabled();
@@ -53,19 +53,19 @@ public:
     float GetHeight() const { return height_; }
     float GetHeight() const { return height_; }
 
 
     /// Set the height of this obstacle.
     /// Set the height of this obstacle.
-    void SetHeight(float);
+    void SetHeight(float height);
 
 
     /// Get the blocking radius of this obstacle.
     /// Get the blocking radius of this obstacle.
     float GetRadius() const { return radius_; }
     float GetRadius() const { return radius_; }
 
 
     /// Set the blocking radius of this obstacle.
     /// Set the blocking radius of this obstacle.
-    void SetRadius(float);
+    void SetRadius(float radius);
 
 
     /// Get the internal obstacle ID.
     /// Get the internal obstacle ID.
     unsigned GetObstacleID() const { return obstacleId_; }
     unsigned GetObstacleID() const { return obstacleId_; }
 
 
     /// Render debug information.
     /// Render debug information.
-    virtual void DrawDebugGeometry(DebugRenderer*, bool depthTest);
+    virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
     /// Simplified rendering of debug information for script usage.
     /// Simplified rendering of debug information for script usage.
     void DrawDebugGeometry(bool depthTest);
     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 "../Core/Context.h"
 #include "ScriptComponentFile.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
 #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"
 #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
 #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/IO/MemoryBuffer.h>
 #include <Atomic/Physics/PhysicsEvents.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
 #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 "ScriptSystem.h"
 #include "ScriptComponent.h"
 #include "ScriptComponent.h"
 #include "ScriptComponentFile.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/Context.h"
 #include "../Core/Object.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"
 #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
 #pragma once
 
 
@@ -155,6 +176,11 @@ public:
 
 
     }
     }
 
 
+    void SetBool(StringHash key, bool value)
+    {
+        vmap_[key] = value;
+    }
+
     void SetUInt(StringHash key, unsigned value)
     void SetUInt(StringHash key, unsigned value)
     {
     {
         vmap_[key] = 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"
 #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"
 #include "ScriptSystem.h"
 
 

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

@@ -141,10 +141,14 @@ UI::~UI()
         
         
         tb::TBWidgetsAnimationManager::Shutdown();
         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_;
         delete rootWidget_;
+        
         // leak
         // leak
         //delete TBUIRenderer::renderer_;
         //delete TBUIRenderer::renderer_;
+
         tb_core_shutdown();
         tb_core_shutdown();
     }
     }
 
 
@@ -595,6 +599,7 @@ bool UI::UnwrapWidget(tb::TBWidget* widget)
 {
 {
     if (widgetWrap_.Contains(widget))
     if (widgetWrap_.Contains(widget))
     {
     {
+        widget->SetDelegate(0);
         widgetWrap_.Erase(widget);
         widgetWrap_.Erase(widget);
         return true;
         return true;
     }
     }
@@ -609,29 +614,29 @@ void UI::PruneUnreachableWidgets()
 
 
     for (itr = widgetWrap_.Begin(); itr != widgetWrap_.End(); )
     for (itr = widgetWrap_.Begin(); itr != widgetWrap_.End(); )
     {
     {
-        if ((*itr).first_->GetParent() || (*itr).second_->JSGetHeapPtr())
+        if ((*itr).first_->GetParent() || (*itr).second_->Refs() > 1)
         {
         {
             itr++;
             itr++;
             continue;
             continue;
         }
         }
 
 
-        tb::TBWidget* toDelete = (*itr).first_;
-
         itr.GotoNext();
         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;
         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)
 void UI::WrapWidget(UIWidget* widget, tb::TBWidget* tbwidget)
 {
 {
     assert (!widgetWrap_.Contains(tbwidget));
     assert (!widgetWrap_.Contains(tbwidget));
-
     widgetWrap_[tbwidget] = widget;
     widgetWrap_[tbwidget] = widget;
-    widget->AddRef();
 }
 }
 
 
 UIWidget* UI::WrapWidget(tb::TBWidget* widget)
 UIWidget* UI::WrapWidget(tb::TBWidget* widget)
@@ -856,6 +861,17 @@ bool UI::OnWidgetDying(tb::TBWidget *widget)
     return false;
     return false;
 }
 }
 
 
+void UI::OnWindowClose(tb::TBWindow *window)
+{
+    if (widgetWrap_.Contains(window))
+    {
+        UIWidget* widget = widgetWrap_[window];
+        VariantMap eventData;
+        eventData[WindowClosed::P_WINDOW] = widget;
+        widget->SendEvent(E_WINDOWCLOSED, eventData);
+    }
+}
+
 void UI::OnWidgetFocusChanged(TBWidget *widget, bool focused)
 void UI::OnWidgetFocusChanged(TBWidget *widget, bool focused)
 {
 {
     if (widgetWrap_.Contains(widget))
     if (widgetWrap_.Contains(widget))

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

@@ -134,6 +134,7 @@ private:
     bool OnWidgetDying(tb::TBWidget *widget);    
     bool OnWidgetDying(tb::TBWidget *widget);    
     void OnWidgetFocusChanged(tb::TBWidget *widget, bool focused);
     void OnWidgetFocusChanged(tb::TBWidget *widget, bool focused);
     bool OnWidgetInvokeEvent(tb::TBWidget *widget, const tb::TBWidgetEvent &ev);
     bool OnWidgetInvokeEvent(tb::TBWidget *widget, const tb::TBWidgetEvent &ev);
+    void OnWindowClose(tb::TBWindow *window);
 
 
 
 
     tb::TBWidget* rootWidget_;
     tb::TBWidget* rootWidget_;

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

@@ -30,13 +30,13 @@ namespace Atomic
 {
 {
 
 
 enum UI_EDIT_TYPE {
 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
 class UIEditField : public UIWidget

+ 6 - 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_HANDLER, Handler);           // UIWidget pointer of widget's OnEvent we are in
     ATOMIC_PARAM(P_TARGET, Target);             // UIWidget pointer
     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_X, X);                       // int
     ATOMIC_PARAM(P_Y, Y);                       // int
     ATOMIC_PARAM(P_Y, Y);                       // int
     ATOMIC_PARAM(P_DELTAX, DeltaX);             // int
     ATOMIC_PARAM(P_DELTAX, DeltaX);             // int
@@ -109,6 +109,11 @@ ATOMIC_EVENT(E_UISHORTCUT, UIShortcut)
 
 
 }
 }
 
 
+ATOMIC_EVENT(E_WINDOWCLOSED, WindowClosed)
+{
+    ATOMIC_PARAM(P_WINDOW, Window);               // UIWindow
+}
+
 ATOMIC_EVENT(E_UIWIDGETFOCUSCHANGED, UIWidgetFocusChanged)
 ATOMIC_EVENT(E_UIWIDGETFOCUSCHANGED, UIWidgetFocusChanged)
 {
 {
     ATOMIC_PARAM(P_WIDGET, Widget);             // UIWidget pointer
     ATOMIC_PARAM(P_WIDGET, Widget);             // UIWidget pointer

+ 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
     /// Sizes depend on the gravity for each widget. (If the widget pulls
     /// towards both directions, it should grow to all available space)
     /// 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.
     /// 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
     /// 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,
 /// Specifies which width widgets in a AXIS_X layout should have,
@@ -51,12 +51,12 @@ enum UI_LAYOUT_SIZE
 enum UI_LAYOUT_DISTRIBUTION
 enum UI_LAYOUT_DISTRIBUTION
 {
 {
     ///< Size will be the preferred so each widget may be sized differently.
     ///< 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
     ///< 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
     ///< Sizes depend on the gravity for each widget. (If the widget pulls
     /// ///< towards both directions, it should grow to all available space)
     /// ///< 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,
 /// Specifies which y position widgets in a AXIS_X layout should have,
@@ -64,14 +64,14 @@ enum UI_LAYOUT_DISTRIBUTION
 enum UI_LAYOUT_POSITION
 enum UI_LAYOUT_POSITION
 {
 {
     ///< Position is centered
     ///< 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.
     ///< 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.
     ///< 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
     ///< Position depend on the gravity for each widget. (If the widget pulls
     /// ///< towards both directions, it will be centered)
     /// ///< 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
 /** Specifies how widgets should be moved horizontally in a AXIS_X
@@ -79,9 +79,9 @@ enum UI_LAYOUT_POSITION
     available. */
     available. */
 enum UI_LAYOUT_DISTRIBUTION_POSITION
 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
 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.
 /// Defines how the size in one axis depend on the other axis when a widgets size is affected by constraints.
 enum UI_SIZE_DEP {
 enum UI_SIZE_DEP {
     /// No dependency (Faster layout).
     /// 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.
     /// 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.
     /// 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.
     /// 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
 class UIPreferredSize : public RefCounted

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

@@ -30,16 +30,16 @@ namespace Atomic
 {
 {
 
 
 enum UI_SCROLL_MODE {
 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
 };
 };
 
 
 
 

+ 4 - 9
Source/Atomic/UI/UIWidget.cpp

@@ -191,9 +191,9 @@ void UIWidget::OnDelete()
 {
 {
     VariantMap eventData;
     VariantMap eventData;
     eventData[WidgetDeleted::P_WIDGET] = this;
     eventData[WidgetDeleted::P_WIDGET] = this;
-    SendEvent(E_WIDGETDELETED, eventData);
+    this->SendEvent(E_WIDGETDELETED, eventData);
 
 
-    UnsubscribeFromAllEvents();   
+    UnsubscribeFromAllEvents();
 
 
     if (widget_)
     if (widget_)
     {
     {
@@ -201,13 +201,8 @@ void UIWidget::OnDelete()
         UI* ui = GetSubsystem<UI>();
         UI* ui = GetSubsystem<UI>();
 
 
         if (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
 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.
 /// Defines widget visibility, used with UIWidget::SetVisibility.
 enum UI_WIDGET_VISIBILITY
 enum UI_WIDGET_VISIBILITY
 {
 {
     /// Visible (default)
     /// Visible (default)
-    UI_WIDGET_VISIBILITY_VISIBLE = tb:: WIDGET_VISIBILITY_VISIBLE,
+    UI_WIDGET_VISIBILITY_VISIBLE = 0, //tb::WIDGET_VISIBILITY_VISIBLE,
     /// Invisible, but layouted. Interaction disabled.
     /// 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.
     /// 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).
 /// TBWidget gravity (may be combined).
 /// Gravity gives hints about positioning and sizing preferences.
 /// Gravity gives hints about positioning and sizing preferences.
 enum UI_GRAVITY {
 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 {
 enum UI_EVENT_TYPE {
+
     /** Click event is what should be used to trig actions in almost all cases.
     /** 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
         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
         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). */
         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
     /** Long click event is sent when the pointer has been down for some time
         without moving much.
         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 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
         If any of those are handled, the CLICK event that would normally be
         invoked after the pending POINTER_UP will be suppressed. */
         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
     /** Invoked after changing text in a TBTextField, changing selected item
         in a TBSelectList etc. Invoking this event trigs synchronization with
         in a TBSelectList etc. Invoking this event trigs synchronization with
         connected TBWidgetValue and other widgets connected to it. */
         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.
     /** Invoked by the platform when a standard keyboard shortcut is pressed.
         It's called before InvokeKeyDown (EVENT_TYPE_KEY_DOWN) and if the event
         It's called before InvokeKeyDown (EVENT_TYPE_KEY_DOWN) and if the event
         is handled (returns true), the KeyDown is canceled.
         is handled (returns true), the KeyDown is canceled.
         The ref_id will be set to one of the following:
         The ref_id will be set to one of the following:
             "cut", "copy", "paste", "selectall", "undo", "redo", "new", "open", "save". */
             "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.
     /** 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
         It may be invoked automatically for a widget on long click, if nothing handles
         the long click event. */
         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
     /** Invoked by the platform when one or multiple files has been dropped on
         the widget. The event is guaranteed to be a TBWidgetEventFileDrop. */
         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 */
     /** 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. */
     /** 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. */
 /** Defines widget z level relative to another widget, used with TBWidget::AddChildRelative. */
 enum UI_WIDGET_Z_REL {
 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
 /// TB_TEXT_ALIGN specifies horizontal text alignment
 enum UI_TEXT_ALIGN
 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 {
 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 {
 enum UI_AXIS {
     ///< Horizontal layout
     ///< Horizontal layout
-    UI_AXIS_X = tb::AXIS_X,
+    UI_AXIS_X = 0,  // tb::AXIS_X,
     ///< Vertical layout
     ///< 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 {
 enum UI_WINDOW_SETTINGS {
+
     ///< Chrome less window without any other 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.
     ///< 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.
     ///< 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.
     ///< 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.
     ///< 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/Script/ScriptVariantMap.h>
 #include <Atomic/IPC/IPC.h>
 #include <Atomic/IPC/IPC.h>
 
 
 #include <Atomic/Graphics/VertexBuffer.h>
 #include <Atomic/Graphics/VertexBuffer.h>
 #include <Atomic/Graphics/Viewport.h>
 #include <Atomic/Graphics/Viewport.h>
 #include <Atomic/Graphics/Graphics.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"
 #include "NETCore.h"
@@ -29,6 +44,13 @@ namespace Atomic
 
 
     extern "C"
     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)
         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)
         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)
         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());
             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();
             Context* context = new Context();
 
 
@@ -73,6 +107,7 @@ namespace Atomic
             NETCoreDelegates delegates;
             NETCoreDelegates delegates;
             delegates.eventDispatch = eventDispatch;
             delegates.eventDispatch = eventDispatch;
             delegates.updateDispatch = updateDispatch;
             delegates.updateDispatch = updateDispatch;
+            delegates.refCountedDeleted = refCountedDeleted;
 
 
             NETCore* netCore = new NETCore(context, &delegates);
             NETCore* netCore = new NETCore(context, &delegates);
             context->RegisterSubsystem(netCore);
             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)
             if (!vb)
                 return nullptr;
                 return nullptr;
@@ -165,6 +200,381 @@ namespace Atomic
             graphics->SetShaderParameter(param, *matrix);
             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
 #ifdef ATOMIC_PLATFORM_IOS
         ATOMIC_EXPORT_API void SDL_IOS_Init(const char *resourceDir, const char *documentsDir)
         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/Math/MathDefs.h>
 #include <Atomic/Core/ProcessUtils.h>
 #include <Atomic/Core/ProcessUtils.h>
+#include <Atomic/IO/Log.h>
 #include <Atomic/Script/ScriptVariantMap.h>
 #include <Atomic/Script/ScriptVariantMap.h>
 
 
 #include "NETCore.h"
 #include "NETCore.h"
@@ -9,10 +10,10 @@
 namespace Atomic
 namespace Atomic
 {
 {
 
 
-
 SharedPtr<Context> NETCore::csContext_;
 SharedPtr<Context> NETCore::csContext_;
 NETCoreEventDispatchFunction NETCore::eventDispatch_ = nullptr;
 NETCoreEventDispatchFunction NETCore::eventDispatch_ = nullptr;
 NETCoreUpdateDispatchFunction NETCore::updateDispatch_ = nullptr;
 NETCoreUpdateDispatchFunction NETCore::updateDispatch_ = nullptr;
+NETCoreRefCountedDeletedFunction NETCore::refCountedDeleted_ = nullptr;
 
 
 NETCore::NETCore(Context* context, NETCoreDelegates* delegates) :
 NETCore::NETCore(Context* context, NETCoreDelegates* delegates) :
     Object(context)
     Object(context)
@@ -22,15 +23,29 @@ NETCore::NETCore(Context* context, NETCoreDelegates* delegates) :
 
 
     eventDispatch_ = delegates->eventDispatch;
     eventDispatch_ = delegates->eventDispatch;
     updateDispatch_ = delegates->updateDispatch;
     updateDispatch_ = delegates->updateDispatch;
+    refCountedDeleted_ = delegates->refCountedDeleted;
 
 
     NETEventDispatcher* dispatcher = new NETEventDispatcher(context_);
     NETEventDispatcher* dispatcher = new NETEventDispatcher(context_);
     context_->RegisterSubsystem(dispatcher);
     context_->RegisterSubsystem(dispatcher);
     context_->AddGlobalEventListener(dispatcher);
     context_->AddGlobalEventListener(dispatcher);
+
+    RefCounted::AddRefCountedDeletedFunction(OnRefCountedDeleted);
 }
 }
 
 
 NETCore::~NETCore()
 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)
 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 (*NETCoreEventDispatchFunction)(Object* refCounted, unsigned eventID, VariantMap* eventData);
 typedef void (*NETCoreUpdateDispatchFunction)(float timeStep);
 typedef void (*NETCoreUpdateDispatchFunction)(float timeStep);
+typedef void (*NETCoreRefCountedDeletedFunction)(RefCounted* refCounted);
 
 
 struct NETCoreDelegates
 struct NETCoreDelegates
 {
 {
     NETCoreEventDispatchFunction eventDispatch;
     NETCoreEventDispatchFunction eventDispatch;
     NETCoreUpdateDispatchFunction updateDispatch;
     NETCoreUpdateDispatchFunction updateDispatch;
+    NETCoreRefCountedDeletedFunction refCountedDeleted;
 };
 };
 
 
 class ATOMIC_API NETCore : public Object
 class ATOMIC_API NETCore : public Object
@@ -63,10 +65,13 @@ public:
 
 
 private:
 private:
 
 
+    static void OnRefCountedDeleted(RefCounted* ref);
+
     static SharedPtr<Context> csContext_;
     static SharedPtr<Context> csContext_;
 
 
     static NETCoreUpdateDispatchFunction updateDispatch_;
     static NETCoreUpdateDispatchFunction updateDispatch_;
     static NETCoreEventDispatchFunction eventDispatch_;
     static NETCoreEventDispatchFunction eventDispatch_;
+    static NETCoreRefCountedDeletedFunction refCountedDeleted_;
 
 
 };
 };
 
 

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

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

+ 2 - 10
Source/AtomicNET/NETScript/CSComponent.cpp

@@ -103,26 +103,18 @@ void CSComponent::SendLoadEvent()
     if (!componentClassName_.Length())
     if (!componentClassName_.Length())
         return;
         return;
 
 
-    // TODO: We need to factor out runtime loading of CSComponent assemblies
-    CSComponentAssembly*  assemblyFile = 0;
-
-#ifdef ATOMIC_PLATFORM_DESKTOP
-    assemblyFile = CSComponentAssembly::ResolveClassAssembly(componentClassName_);
-#endif
-
     using namespace CSComponentLoad;
     using namespace CSComponentLoad;
 
 
     VariantMap eventData;
     VariantMap eventData;
 
 
-    eventData[P_ASSEMBLYPATH] = assemblyFile ? GetFileName(assemblyFile->GetFullPath()) : String::EMPTY;
-
     eventData[P_CLASSNAME] = componentClassName_;
     eventData[P_CLASSNAME] = componentClassName_;
     eventData[P_NATIVEINSTANCE] = (void*) this;
     eventData[P_NATIVEINSTANCE] = (void*) this;
 
 
     if (!fieldValues_.Empty())
     if (!fieldValues_.Empty())
         eventData[P_FIELDVALUES] = (void*) &fieldValues_;
         eventData[P_FIELDVALUES] = (void*) &fieldValues_;
 
 
-    SendEvent(E_CSCOMPONENTLOAD, eventData);
+    if (node_ && node_->GetScene())
+        node_->GetScene()->SendEvent(E_CSCOMPONENTLOAD, eventData);
 
 
 }
 }
 
 

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

@@ -35,7 +35,6 @@ namespace Atomic
 
 
     ATOMIC_EVENT(E_CSCOMPONENTLOAD, CSComponentLoad)
     ATOMIC_EVENT(E_CSCOMPONENTLOAD, CSComponentLoad)
     {
     {
-        ATOMIC_PARAM(P_ASSEMBLYPATH, AssemblyPath); // String
         ATOMIC_PARAM(P_CLASSNAME, ClassName); // String
         ATOMIC_PARAM(P_CLASSNAME, ClassName); // String
         ATOMIC_PARAM(P_NATIVEINSTANCE, NativeInstance); // CSComponent as void*
         ATOMIC_PARAM(P_NATIVEINSTANCE, NativeInstance); // CSComponent as void*
         ATOMIC_PARAM(P_FIELDVALUES, FieldValues);  // VariantMap as void*
         ATOMIC_PARAM(P_FIELDVALUES, FieldValues);  // VariantMap as void*
@@ -43,7 +42,7 @@ namespace Atomic
 
 
     ATOMIC_EVENT(E_CSCOMPONENTASSEMBLYCHANGED, CSComponentAssemblyChanged)
     ATOMIC_EVENT(E_CSCOMPONENTASSEMBLYCHANGED, CSComponentAssemblyChanged)
     {
     {
-        ATOMIC_PARAM(P_RESOURCE, Resource); // resource*
+        ATOMIC_PARAM(P_RESOURCE, Resource); // Resource
         ATOMIC_PARAM(P_ASSEMBLYPATH, AssemblyPath); // String
         ATOMIC_PARAM(P_ASSEMBLYPATH, AssemblyPath); // String
     }
     }
 
 

+ 14 - 0
Source/AtomicPlayer/Player.cpp

@@ -28,6 +28,7 @@
 #include <Atomic/Graphics/Renderer.h>
 #include <Atomic/Graphics/Renderer.h>
 #include <Atomic/Graphics/Camera.h>
 #include <Atomic/Graphics/Camera.h>
 
 
+#include "PlayerEvents.h"
 #include "Player.h"
 #include "Player.h"
 
 
 namespace AtomicPlayer
 namespace AtomicPlayer
@@ -66,12 +67,25 @@ Scene* Player::LoadScene(const String& filename, Camera *camera)
 
 
     Scene* scene = new Scene(context_);
     Scene* scene = new Scene(context_);
 
 
+    VariantMap eventData;
+
+    eventData[PlayerSceneLoadBegin::P_SCENE] = scene;
+
+    scene->SendEvent(E_PLAYERSCENELOADBEGIN, eventData);
+
     if (!scene->LoadXML(*file))
     if (!scene->LoadXML(*file))
     {
     {
+        eventData[PlayerSceneLoadEnd::P_SCENE] = scene;
+        eventData[PlayerSceneLoadEnd::P_SUCCESS] = false;
+        scene->SendEvent(E_PLAYERSCENELOADEND, eventData);
         scene->ReleaseRef();
         scene->ReleaseRef();
         return 0;
         return 0;
     }
     }
 
 
+    eventData[PlayerSceneLoadEnd::P_SCENE] = scene;
+    eventData[PlayerSceneLoadEnd::P_SUCCESS] = true;
+    scene->SendEvent(E_PLAYERSCENELOADEND, eventData);
+
     if (currentScene_.Null())
     if (currentScene_.Null())
     {
     {
         currentScene_ = scene;
         currentScene_ = scene;

+ 42 - 0
Source/AtomicPlayer/PlayerEvents.h

@@ -0,0 +1,42 @@
+//
+// 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/Object.h>
+
+using namespace Atomic;
+
+namespace AtomicPlayer
+{
+    ATOMIC_EVENT(E_PLAYERSCENELOADBEGIN, PlayerSceneLoadBegin)
+    {
+        ATOMIC_PARAM(P_SCENE, Scene);        // Scene
+    }
+
+    ATOMIC_EVENT(E_PLAYERSCENELOADEND, PlayerSceneLoadEnd)
+    {
+        ATOMIC_PARAM(P_SCENE, Scene);       // Scene
+        ATOMIC_PARAM(P_SUCCESS, Success);   // bool
+    }
+
+}

+ 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)
                 ev.special_key == TB_KEY_RIGHT || ev.special_key == TB_KEY_DOWN)
             return true;
             return true;
     }
     }
-    return false;
+    return TBWidget::OnEvent(ev);
 }
 }
 
 
 void TBSlider::UpdateHandle()
 void TBSlider::UpdateHandle()

+ 13 - 0
Source/ThirdParty/TurboBadger/tb_widgets_listener.cpp

@@ -4,6 +4,7 @@
 // ================================================================================
 // ================================================================================
 
 
 #include "tb_widgets_listener.h"
 #include "tb_widgets_listener.h"
+#include "tb_window.h"
 
 
 namespace tb {
 namespace tb {
 
 
@@ -85,6 +86,18 @@ bool TBWidgetListener::InvokeWidgetInvokeEvent(TBWidget *widget, const TBWidgetE
     return handled;
     return handled;
 }
 }
 
 
+// ATOMIC BEGIN
+void TBWidgetListener::InvokeWindowClose(TBWindow *window)
+{
+    TBLinkListOf<TBWidgetListenerGlobalLink>::Iterator global_i = g_listeners.IterateForward();
+    TBLinkListOf<TBWidgetListener>::Iterator local_i = window->m_listeners.IterateForward();
+    while (TBWidgetListener *listener = local_i.GetAndStep())
+        listener->OnWindowClose(window);
+    while (TBWidgetListenerGlobalLink *link = global_i.GetAndStep())
+        static_cast<TBWidgetListener*>(link)->OnWindowClose(window);
+}
+// ATOMIC END
+
 // == TBWidgetSafePointer ===================================================================================
 // == TBWidgetSafePointer ===================================================================================
 
 
 void TBWidgetSafePointer::Set(TBWidget *widget)
 void TBWidgetSafePointer::Set(TBWidget *widget)

+ 10 - 0
Source/ThirdParty/TurboBadger/tb_widgets_listener.h

@@ -59,6 +59,11 @@ public:
         to intercept events before they are handled, and block it (by returning true).
         to intercept events before they are handled, and block it (by returning true).
         Note, if returning true, other global listeners will still also be notified. */
         Note, if returning true, other global listeners will still also be notified. */
     virtual bool OnWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev) { return false; }
     virtual bool OnWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev) { return false; }
+
+    // ATOMIC BEGIN
+    virtual void OnWindowClose(TBWindow *window) {}
+    // ATOMIC END
+
 private:
 private:
     friend class TBWidget;
     friend class TBWidget;
     friend class TBEditField;
     friend class TBEditField;
@@ -68,6 +73,11 @@ private:
     static void InvokeWidgetRemove(TBWidget *parent, TBWidget *child);
     static void InvokeWidgetRemove(TBWidget *parent, TBWidget *child);
     static void InvokeWidgetFocusChanged(TBWidget *widget, bool focused);
     static void InvokeWidgetFocusChanged(TBWidget *widget, bool focused);
     static bool InvokeWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev);
     static bool InvokeWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev);
+
+    // ATOMIC BEGIN
+    friend class TBWindow;
+    static void InvokeWindowClose(TBWindow *window);
+    // ATOMIC END
 };
 };
 
 
 /** TBWidgetSafePointer keeps a pointer to a widget that will be set to
 /** TBWidgetSafePointer keeps a pointer to a widget that will be set to

+ 3 - 0
Source/ThirdParty/TurboBadger/tb_window.cpp

@@ -64,6 +64,9 @@ void TBWindow::ResizeToFitContent(RESIZE_FIT fit)
 
 
 void TBWindow::Close()
 void TBWindow::Close()
 {
 {
+// ATOMIC BEGIN
+    TBWidgetListener::InvokeWindowClose(this);
+// ATOMIC END
     Die();
     Die();
 }
 }
 
 

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

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

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

@@ -29,6 +29,7 @@
 #include "../JSBEnum.h"
 #include "../JSBEnum.h"
 #include "../JSBClass.h"
 #include "../JSBClass.h"
 #include "../JSBFunction.h"
 #include "../JSBFunction.h"
+#include "../JSBEvent.h"
 
 
 #include "CSTypeHelper.h"
 #include "CSTypeHelper.h"
 #include "CSClassWriter.h"
 #include "CSClassWriter.h"
@@ -252,7 +253,9 @@ void CSModuleWriter::GenerateManagedEnumsAndConstants(String& source)
             // BodyType2D enum order is assigned in RigidBody2D.h in incorrect order
             // BodyType2D enum order is assigned in RigidBody2D.h in incorrect order
             if (jenum->GetName() == "BodyType2D")
             if (jenum->GetName() == "BodyType2D")
             {                 
             {                 
-                if (name == "BT_KINEMATIC")
+                if (name == "BT_STATIC")
+                    value = "0";
+                else if (name == "BT_KINEMATIC")
                     value = "1";
                     value = "1";
                 else if (name == "BT_DYNAMIC")
                 else if (name == "BT_DYNAMIC")
                     value = "2";
                     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)
 void CSModuleWriter::GenerateManagedModuleClass(String& sourceOut)
 {
 {
     Indent();
     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();
     Dedent();
 
 
     source += IndentLine("}\n");
     source += IndentLine("}\n");
@@ -471,6 +606,7 @@ void CSModuleWriter::GenerateManagedSource()
     source += "{\n";
     source += "{\n";
 
 
     GenerateManagedEnumsAndConstants(source);
     GenerateManagedEnumsAndConstants(source);
+    GenerateManagedNativeEvents(source);
     GenerateManagedModuleClass(source);
     GenerateManagedModuleClass(source);
     GenerateManagedClasses(source);
     GenerateManagedClasses(source);
 
 

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

@@ -53,7 +53,7 @@ private:
     void GenerateManagedModuleClass(String& sourceOut);
     void GenerateManagedModuleClass(String& sourceOut);
     void GenerateManagedClasses(String& source);
     void GenerateManagedClasses(String& source);
     void GenerateManagedEnumsAndConstants(String& source);
     void GenerateManagedEnumsAndConstants(String& source);
-
+    void GenerateManagedNativeEvents(String& sourceOut);
 
 
     void WriteIncludes(String& source);
     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();
     JSBClass* klass = function->GetClass();
 
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
 
     Vector<String> args;
     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();
     JSBClass* klass = function->GetClass();
 
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
 
     Vector<String> args;
     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++)
     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())
     if (name_ != function->GetName())
         return false;
         return false;
 
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
 
     if (types_.Size() != parameters.Size())
     if (types_.Size() != parameters.Size())
         return false;
         return false;
@@ -300,9 +300,26 @@ void JSBClass::Process()
 
 
         for (unsigned k = 0; k < excludes_.Size(); k++)
         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;
                 break;
             }
             }
 
 
@@ -323,7 +340,7 @@ void JSBClass::Process()
         // skip function if only one parameter of type Context, if not Constuctor
         // skip function if only one parameter of type Context, if not Constuctor
         if (!function->IsConstructor())
         if (!function->IsConstructor())
         {
         {
-            Vector<JSBFunctionType*>& parameters = function->GetParameters();
+            const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
 
             if (parameters.Size() == 1 && parameters.At(0)->type_->asClassType())
             if (parameters.Size() == 1 && parameters.At(0)->type_->asClassType())
             {
             {

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

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

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

@@ -85,7 +85,7 @@ String JSBDoc::GenFunctionDoc(JSBFunction* function)
 
 
     String params;
     String params;
 
 
-    Vector<JSBFunctionType*>& parameters = function->GetParameters();
+    const Vector<JSBFunctionType*>& parameters = function->GetParameters();
 
 
     for (unsigned i = 0; i < parameters.Size(); i++)
     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;
             return false;
     }
     }
 
 
-    Vector<JSBFunctionType*>& fparams = func->GetParameters();
+    const Vector<JSBFunctionType*>& fparams = func->GetParameters();
 
 
     if (parameters_.Size() != fparams.Size())
     if (parameters_.Size() != fparams.Size())
         return false;
         return false;

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

@@ -139,19 +139,19 @@ public:
 
 
     JSBFunction(JSBClass* klass);
     JSBFunction(JSBClass* klass);
 
 
-    const String& GetName() { return name_; }
+    const String& GetName() const { return name_; }
 
 
     bool Match(JSBFunction* func);
     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 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)
         if (skip_ || language == BINDINGLANGUAGE_ANY)
             return skip_;
             return skip_;
@@ -161,16 +161,16 @@ public:
 
 
     unsigned GetID() const { return id_; }
     unsigned GetID() const { return id_; }
 
 
-    JSBClass* GetClass() { return class_; }
+    JSBClass* GetClass() const { return class_; }
     const String& GetPropertyName() { return propertyName_; }
     const String& GetPropertyName() { return propertyName_; }
-    JSBFunctionType* GetReturnType() { return returnType_; }
+    JSBFunctionType* GetReturnType() const { return returnType_; }
 
 
     /// Get class return type or null
     /// Get class return type or null
     JSBClass* GetReturnClass();
     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 SetName(const String& name) { name_ = name; }
     void SetConstructor(bool value = true) { isConstructor_ = value; }
     void SetConstructor(bool value = true) { isConstructor_ = value; }
@@ -236,7 +236,7 @@ public:
 
 
     void Dump()
     void Dump()
     {
     {
-        String sig;
+        String sig = ToString("Function ID: %u - ", id_);
         if (!returnType_)
         if (!returnType_)
             sig += "void ";
             sig += "void ";
         else
         else
@@ -254,6 +254,19 @@ public:
         }
         }
         sig += ");";
         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());
         ATOMIC_LOGINFOF("      %s", sig.CString());
 
 
     }
     }

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

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

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

@@ -50,14 +50,14 @@ namespace ToolCore
 
 
         void End();
         void End();
 
 
-        void ExportFunction(JSBFunction* function);
+        void ExportFunction(const JSBFunction* function);
 
 
-        String GetScriptType(JSBFunctionType* ftype);
+        String GetScriptType(const JSBFunctionType* ftype);
         String GetPrimitiveType(JSBPrimitiveType* ptype);
         String GetPrimitiveType(JSBPrimitiveType* ptype);
 
 
         bool checkV(JSBClass* clazz, const String name, const String type);
         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 ExportEnums(JSBModule* moduleName);
         void ExportModuleConstants(JSBModule*  moduleName);
         void ExportModuleConstants(JSBModule*  moduleName);

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

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

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

@@ -324,6 +324,10 @@ public:
                 return NULL;
                 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);
         JSBFunctionType* ftype = new JSBFunctionType(jtype);
         ftype->isPointer_ = isPointer;
         ftype->isPointer_ = isPointer;
         ftype->isSharedPtr_ = isSharedPtr;
         ftype->isSharedPtr_ = isSharedPtr;

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

@@ -35,6 +35,7 @@
 #include "JSBEnum.h"
 #include "JSBEnum.h"
 #include "JSBModuleWriter.h"
 #include "JSBModuleWriter.h"
 #include "JSBType.h"
 #include "JSBType.h"
+#include "JSBEvent.h"
 
 
 #include "JavaScript/JSModuleWriter.h"
 #include "JavaScript/JSModuleWriter.h"
 #include "CSharp/CSModuleWriter.h"
 #include "CSharp/CSModuleWriter.h"
@@ -160,7 +161,7 @@ void JSBModule::ProcessOverloads()
 
 
                 if (!_sig.IsArray())
                 if (!_sig.IsArray())
                 {
                 {
-                    ErrorExit("Bad overload defintion");
+                    ErrorExit("Bad overload definition");
                 }
                 }
 
 
                 JSONArray sig = _sig.GetArray();
                 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()
 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)
 void JSBModule::RegisterEnum(JSBEnum* jenum)
 {
 {
     if (JSBPackage::GetClassAllPackages(jenum->GetName()))
     if (JSBPackage::GetClassAllPackages(jenum->GetName()))

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

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

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

@@ -26,6 +26,7 @@
 #include <Atomic/Resource/JSONFile.h>
 #include <Atomic/Resource/JSONFile.h>
 
 
 #include "JSBind.h"
 #include "JSBind.h"
+#include "JSBEvent.h"
 #include "JSBModule.h"
 #include "JSBModule.h"
 #include "JSBPackage.h"
 #include "JSBPackage.h"
 #include "JSBPackageWriter.h"
 #include "JSBPackageWriter.h"
@@ -77,6 +78,11 @@ void JSBPackage::ProcessModules()
         modules_[i]->PostProcessClasses();
         modules_[i]->PostProcessClasses();
     }
     }
 
 
+    for (unsigned i = 0; i < modules_.Size(); i++)
+    {
+        JSBEvent::ScanModuleEvents(modules_[i]);
+    }
+
 }
 }
 
 
 void JSBPackage::GenerateSource(JSBPackageWriter& packageWriter)
 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)
 JSBEnum* JSBPackage::GetEnum(const String& name)
 {
 {
     for (unsigned i = 0; i < modules_.Size(); i++)
     for (unsigned i = 0; i < modules_.Size(); i++)

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

@@ -32,7 +32,7 @@ namespace ToolCore
 class JSBModule;
 class JSBModule;
 class JSBClass;
 class JSBClass;
 class JSBEnum;
 class JSBEnum;
-
+class JSBEvent;
 class JSBPackageWriter;
 class JSBPackageWriter;
 
 
 class JSBPackage : public Object
 class JSBPackage : public Object
@@ -85,6 +85,12 @@ public:
 
 
     static bool ContainsConstantAllPackages(const String& constantName);
     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);
     void GenerateSource(JSBPackageWriter& packageWriter);
 
 
     /// Define guard for the package as a whole
     /// Define guard for the package as a whole

Some files were not shown because too many files changed in this diff