Browse Source

Adding support deploying managed applications

Josh Engebretson 9 years ago
parent
commit
4364f07f7e

+ 22 - 0
Script/AtomicNET/AtomicIPCPlayer/Program.cs

@@ -0,0 +1,22 @@
+
+using AtomicEngine;
+
+public class Program
+{
+    public static void Main(string[] args)
+    {               
+        // Create the Application
+        var app = NETIPCPlayerApp.Create(args);
+
+        // Managed code in charge of main loop
+        while (app.RunFrame())
+        {
+
+        }
+
+        // Shut 'er down
+        app.Shutdown();
+    }
+}
+
+

+ 37 - 0
Script/AtomicNET/AtomicNET/Application/NETAtomicPlayer.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Reflection;
+
+
+namespace AtomicEngine
+{
+    public partial class NETAtomicPlayer : PlayerApp
+    {
+
+        /// <summary>
+        ///  AtomicPlayer for NET deployments
+        /// </summary>
+        /// <param name="args"></param>
+        /// <param name="headless"></param>
+        /// <returns></returns>
+        public static NETAtomicPlayer Create(string[] args, bool headless = false)
+        {
+            DeployedApp = true;
+
+            // Initialize AtomicNET
+            AtomicNET.Initialize();
+
+            var app = CreateInternal();
+
+            app.Initialize();
+
+            RegisterSubsystems();
+
+            ExecuteAtomicMain(args);
+
+            return app;
+        }
+
+
+    }
+
+}

+ 8 - 57
Script/AtomicNET/AtomicNET/Application/NETIPCPlayerApp.cs

@@ -1,55 +1,16 @@
 using System;
 using System.Reflection;
 
-
 namespace AtomicEngine
 {
-    public partial class PlayerApp : AppBase
-    {
-        protected static void ExecuteAtomicMain(string[] args)
-        {
-            var file = AtomicNET.Cache.GetFile("AtomicProject.dll");
-
-            if (file == null)
-                return;
-
-            Assembly assembly = Assembly.LoadFrom(file.FullPath);
-
-            if (assembly == null)
-                return;
-
-            Type atomicMainType = null;
-            Type[] assemblyTypes = assembly.GetTypes();
-
-            for (int j = 0; j < assemblyTypes.Length; j++)
-            {
-                if (assemblyTypes[j].Name == "AtomicMain")
-                {
-                    atomicMainType = assemblyTypes[j];
-                    break;
-                }
-            }
-
-            if (atomicMainType == null)
-                return;
-
-            Type[] mainParms = new Type[1] { typeof(string[]) };
-
-            var method = atomicMainType.GetMethod("Main", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, mainParms, null);
-
-            if (method == null)
-                return;
-
-            Object[] parms = new Object[1] { args };
-            method.Invoke(null, parms);
-
-        }
-
-    }
-
     public partial class NETIPCPlayerApp : IPCPlayerApp
     {
-
+        /// <summary>
+        ///  IPC Player App used with the Atomic Editor
+        /// </summary>
+        /// <param name="args"></param>
+        /// <param name="headless"></param>
+        /// <returns></returns>
         public static NETIPCPlayerApp Create(string[] args, bool headless = false)
         {
             // Initialize AtomicNET
@@ -59,18 +20,8 @@ namespace AtomicEngine
 
             app.Initialize();
 
-            // TODO: Refactor these registrations
-            AtomicNET.RegisterSubsystem("FileSystem");
-
-            AtomicNET.RegisterSubsystem("Graphics");
-            AtomicNET.RegisterSubsystem("Player");
-
-            AtomicNET.RegisterSubsystem("Input");
-            AtomicNET.RegisterSubsystem("Renderer");
-
-            AtomicNET.RegisterSubsystem("ResourceCache");
-            AtomicNET.Cache = AtomicNET.GetSubsystem<ResourceCache>();
-
+            RegisterSubsystems();
+            
             ExecuteAtomicMain(args);
 
             return app;

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

@@ -0,0 +1,77 @@
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace AtomicEngine
+{
+
+
+    public partial class PlayerApp : AppBase
+    {
+        public static bool DeployedApp = false;
+
+        static protected void RegisterSubsystems()
+        {
+            // TODO: Refactor these registrations
+            AtomicNET.RegisterSubsystem("FileSystem");
+
+            AtomicNET.RegisterSubsystem("Graphics");
+            AtomicNET.RegisterSubsystem("Player");
+
+            AtomicNET.RegisterSubsystem("Input");
+            AtomicNET.RegisterSubsystem("Renderer");
+
+            AtomicNET.RegisterSubsystem("ResourceCache");
+            AtomicNET.Cache = AtomicNET.GetSubsystem<ResourceCache>();
+        }
+
+        protected static void ExecuteAtomicMain(string[] args)
+        {
+            String projectAssemblyPath;
+
+            if (!DeployedApp)
+            {
+                var file = AtomicNET.Cache.GetFile("AtomicProject.dll");
+                projectAssemblyPath = file.FullPath;
+            }
+            else
+            {
+                projectAssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/AtomicProject.dll";
+            }
+               
+            Assembly assembly = Assembly.LoadFrom(projectAssemblyPath);
+
+            if (assembly == null)
+                return;
+
+            Type atomicMainType = null;
+            Type[] assemblyTypes = assembly.GetTypes();
+
+            for (int j = 0; j < assemblyTypes.Length; j++)
+            {
+                if (assemblyTypes[j].Name == "AtomicMain")
+                {
+                    atomicMainType = assemblyTypes[j];
+                    break;
+                }
+            }
+
+            if (atomicMainType == null)
+                return;
+
+            Type[] mainParms = new Type[1] { typeof(string[]) };
+
+            var method = atomicMainType.GetMethod("Main", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, mainParms, null);
+
+            if (method == null)
+                return;
+
+            Object[] parms = new Object[1] { args };
+            method.Invoke(null, parms);
+
+        }
+
+    }
+
+
+}

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

@@ -1,4 +1,5 @@
 using System;
+using System.IO;
 using System.Collections.Generic;
 using System.Reflection;
 using System.Linq;
@@ -247,6 +248,12 @@ namespace AtomicEngine
                 componentCache[assemblyPath] = assemblyTypes = new Dictionary<string, CSComponentInfo>();
             }
 
+            // HACK!
+            if (PlayerApp.DeployedApp)
+            {
+                assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/AtomicProject.dll";
+            }
+
             Assembly assembly = Assembly.LoadFrom(assemblyPath);
 
             Type[] types = assembly.GetTypes();

+ 23 - 5
Script/AtomicNET/AtomicNETProject.json

@@ -64,10 +64,10 @@
       ]
     },
     {
-      "name": "AtomicPlayer",
+      "name": "AtomicIPCPlayer",
       "outputType" : "Exe",
-      "rootNamespace" : "AtomicPlayer",
-      "assemblyName" : "AtomicPlayer",
+      "rootNamespace" : "AtomicIPCPlayer",
+      "assemblyName" : "AtomicIPCPlayer",
       "assemblyOutputPath" : "..\\..\\",
       "references" : [
         "System",
@@ -77,8 +77,26 @@
         "AtomicNET"
       ],
       "sources" : [
-        "$ATOMIC_ROOT$/Script/AtomicNET/AtomicPlayer/"
+        "$ATOMIC_ROOT$/Script/AtomicNET/AtomicIPCPlayer/"
       ]
-    }
+  },
+  {
+    "name": "AtomicPlayer",
+    "outputType" : "Exe",
+    "rootNamespace" : "AtomicPlayer",
+    "assemblyName" : "AtomicPlayer",
+    "assemblyOutputPath" : "..\\..\\",
+    "references" : [
+      "System",
+      "System.Core" ,
+      "System.Xml.Linq",
+      "System.XML",
+      "AtomicNET"
+    ],
+    "sources" : [
+      "$ATOMIC_ROOT$/Script/AtomicNET/AtomicPlayer/"
+    ]
+  }
+
   ]
 }

+ 2 - 4
Script/AtomicNET/AtomicPlayer/Program.cs

@@ -4,9 +4,9 @@ using AtomicEngine;
 public class Program
 {
     public static void Main(string[] args)
-    {               
+    {
         // Create the Application
-        var app = NETIPCPlayerApp.Create(args);
+        var app = NETAtomicPlayer.Create(args);
 
         // Managed code in charge of main loop
         while (app.RunFrame())
@@ -18,5 +18,3 @@ public class Program
         app.Shutdown();
     }
 }
-
-

+ 0 - 27
Script/AtomicNET/AtomicPlayer/project.json

@@ -1,27 +0,0 @@
-{
-  "version": "1.0.0-*",
-  "buildOptions": {
-    "emitEntryPoint": true, 
-    "allowUnsafe": true
-  },
-  "dependencies": {
-    "AtomicNETCore": {
-      "target": "project"
-    },
-    "AtomicNET": {
-      "target": "project"
-    },        
-    "Microsoft.NETCore.App": {      
-      "version": "1.0.0-rc2-3002702"
-    }
-  },
-  "runtimes": {                                                     
-      "osx.10.11-x64": {}                                               
-  },    
-  "frameworks": {
-    "netcoreapp1.0": {
-      "imports": "dnxcore50"
-    }
-  }
-}
-

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

@@ -1,5 +1,5 @@
 {
 	"name" : "AtomicNETNative",
 	"sources" : ["Source/AtomicNET/NETNative"],
-	"classes" : ["NETCore", "NETIPCPlayerApp", "NETServiceApplication"]
+	"classes" : ["NETCore", "NETIPCPlayerApp", "NETServiceApplication", "NETAtomicPlayer"]
 }

+ 1 - 1
Source/AtomicEditor/EditorMode/AEEditorMode.cpp

@@ -143,7 +143,7 @@ bool EditorMode::PlayProject(String addArgs, bool debug)
     if (fileSystem->FileExists(project->GetResourcePath() + "AtomicProject.dll"))
     {
         managed = true;
-        playerBinary = env->GetAtomicNETManagedPlayerBinary();
+        playerBinary = env->GetAtomicNETManagedIPCPlayerBinary();
     }
 
 

+ 131 - 0
Source/AtomicNET/NETNative/NETAtomicPlayer.cpp

@@ -0,0 +1,131 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include <Atomic/Engine/Engine.h>
+#include <Atomic/Engine/EngineConfig.h>
+#include <Atomic/IO/FileSystem.h>
+
+#include "NETCore.h"
+#include <AtomicNET/NETScript/NETScript.h>
+
+#include "NETAtomicPlayer.h"
+
+#ifdef ATOMIC_PLATFORM_OSX
+#include <unistd.h>
+#endif
+
+#ifdef ATOMIC_PLATFORM_WINDOWS
+#include <stdio.h>
+#endif
+
+namespace Atomic
+{
+
+    NETAtomicPlayer::NETAtomicPlayer(Context* context) :
+        PlayerApp(context)
+    {
+
+#ifdef WIN32
+        ParseArguments(GetCommandLineW());
+#else
+        #warning Implement Argument Parsing
+#endif
+        arguments_ = GetArguments();
+
+    }
+
+    void NETAtomicPlayer::Setup()
+    {
+        PlayerApp::Setup();
+    }
+
+    int NETAtomicPlayer::Initialize()
+    {
+        Setup();
+
+        // Read the engine configuration
+        ReadEngineConfig();
+
+        RegisterNETScriptLibrary(context_);
+
+        if (exitCode_)
+            return exitCode_;
+
+        if (!engine_->Initialize(engineParameters_))
+        {
+            ErrorExit();
+            return exitCode_;
+        }
+
+        Start();
+
+        if (exitCode_)
+            return exitCode_;
+
+        return 0;
+    }
+
+    bool NETAtomicPlayer::RunFrame()
+    {
+        engine_->RunFrame();
+
+        if (engine_->IsExiting())
+        {
+            return false;
+        }
+
+        return true;
+
+    }
+
+    void NETAtomicPlayer::Shutdown()
+    {
+        Stop();
+    }
+
+    void NETAtomicPlayer::Stop()
+    {
+        PlayerApp::Stop();
+    }
+
+    NETAtomicPlayer* NETAtomicPlayer::CreateInternal()
+    {
+        return new NETAtomicPlayer(NETCore::GetContext());
+    }
+
+    void NETAtomicPlayer::ReadEngineConfig()
+    {
+        FileSystem* fileSystem = GetSubsystem<FileSystem>();
+        String filename = fileSystem->GetProgramDir() + "Settings/Engine.json";
+
+        if (!fileSystem->FileExists(filename))
+            return;
+
+        if (EngineConfig::LoadFromFile(context_, filename))
+        {
+            EngineConfig::ApplyConfig(engineParameters_, true);
+        }
+    }
+
+
+}

+ 59 - 0
Source/AtomicNET/NETNative/NETAtomicPlayer.h

@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include <AtomicApp/Player/PlayerApp.h>
+
+namespace Atomic
+{
+
+    class NETAtomicPlayer : public PlayerApp
+    {
+        OBJECT(NETAtomicPlayer)
+
+    public:
+
+        static NETAtomicPlayer* CreateInternal();
+
+        int Initialize();
+
+        bool RunFrame();
+
+        void Shutdown();
+
+    private:
+
+        /// Construct.
+        NETAtomicPlayer(Context* context);
+
+        /// Setup before engine initialization.
+        virtual void Setup();
+        /// Cleanup after the main loop.
+        virtual void Stop();
+
+        void ReadEngineConfig();
+
+    };
+
+}

+ 93 - 12
Source/ToolCore/Build/BuildWindows.cpp

@@ -21,6 +21,7 @@
 //
 
 #include <Atomic/Core/StringUtils.h>
+#include <Atomic/IO/Log.h>
 #include <Atomic/IO/FileSystem.h>
 #include <Atomic/Resource/ResourceCache.h>
 
@@ -90,9 +91,90 @@ bool BuildWindows::CheckIncludeResourceFile(const String& resourceDir, const Str
     return BuildBase::CheckIncludeResourceFile(resourceDir, fileName);
 }
 
+void BuildWindows::BuildManaged(const String& buildPath)
+{
+    BuildLog("Building Managed Application");
+
+    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+    ToolSystem* toolSystem = GetSubsystem<ToolSystem>();
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+    Project* project = toolSystem->GetProject();
+    
+    StringVector results;
+    StringVector filtered;
+    fileSystem->ScanDir(results, tenv->GetAtomicNETCoreAssemblyDir(), "", SCAN_FILES, false);
+
+    StringVector filterList;
+
+    filterList.Push("AtomicIPCPlayer");
+    filterList.Push(".pdb");
+    filterList.Push("System.Collections.Immutable");
+    filterList.Push("System.Reflection.Metadata");
+    filterList.Push("ComponentTest");
+    filterList.Push("AtomicNETService");
+
+    StringVector::Iterator itr = results.Begin();
+    while (itr != results.End())
+    {
+        unsigned i;
+        for (i = 0; i < filterList.Size(); i++)
+        {
+            if (itr->Contains(filterList[i]))
+                break;
+        }
+
+        if (i == filterList.Size())
+            filtered.Push(*itr);
+
+        itr++;
+    }
+
+    String playerBinary = tenv->GetAtomicNETManagedPlayerBinary();
+   
+    if (!BuildCopyFile(playerBinary, buildPath_ + "/AtomicPlayer.exe"))
+        return;
+
+    for (unsigned i = 0; i < filtered.Size(); i++)
+    {
+        String filename = filtered[i];
+
+        if (!BuildCopyFile(tenv->GetAtomicNETCoreAssemblyDir() + filename, buildPath_ + "/" + filename))
+            return;
+
+    }
+    if (!BuildCopyFile(project->GetResourcePath() + "/AtomicProject.dll", buildPath_ + "/AtomicProject.dll"));
+        return;
+
+   
+  
+}
+
+void BuildWindows::BuildNative(const String& buildPath)
+{
+    BuildLog("Building Native Application");
+
+    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+
+    String playerBinary = tenv->GetPlayerBinary();
+
+    String d3d9dll = GetPath(playerBinary) + "/D3DCompiler_47.dll";
+
+    if (!BuildCopyFile(playerBinary, buildPath_ + "/AtomicPlayer.exe"))
+        return;
+
+    if (!BuildCopyFile(d3d9dll, buildPath_ + "/D3DCompiler_47.dll"))
+        return;
+
+}
+
+
 void BuildWindows::Build(const String& buildPath)
 {
+    BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
     ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+    ToolSystem* tsystem = GetSubsystem<ToolSystem>();
+    Project* project = tsystem->GetProject();
 
     buildPath_ = AddTrailingSlash(buildPath) + GetBuildSubfolder();
 
@@ -103,13 +185,7 @@ void BuildWindows::Build(const String& buildPath)
     if (!BuildClean(buildPath_))
         return;
 
-    BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
-
-    FileSystem* fileSystem = GetSubsystem<FileSystem>();
-
-    String rootSourceDir = tenv->GetRootSourceDir();
-    String playerBinary = tenv->GetPlayerBinary();
-    String d3d9dll = GetPath(playerBinary) + "/D3DCompiler_47.dll";
+    String rootSourceDir = tenv->GetRootSourceDir();        
 
     if (!BuildCreateDirectory(buildPath_))
         return;
@@ -133,12 +209,17 @@ void BuildWindows::Build(const String& buildPath)
             return;
     }
 
-    if (!BuildCopyFile(playerBinary, buildPath_ + "/AtomicPlayer.exe"))
-        return;
-
-    if (!BuildCopyFile(d3d9dll, buildPath_ + "/D3DCompiler_47.dll"))
-        return;
+    // TODO: Set project as managed and don't key off AtomicProject.dll
 
+    if (fileSystem->FileExists(project->GetResourcePath() + "/AtomicProject.dll"))
+    {
+        BuildManaged(buildPath);
+    }
+    else
+    {
+        BuildNative(buildPath);
+    }
+    
     BuildLog("Windows Deployment Complete");
 
     buildSystem->BuildComplete(PLATFORMID_WINDOWS, buildPath_);

+ 3 - 0
Source/ToolCore/Build/BuildWindows.h

@@ -49,6 +49,9 @@ protected:
 
 private:
 
+    void BuildNative(const String& buildPath);
+    void BuildManaged(const String& buildPath);
+
 };
 
 }

+ 2 - 2
Source/ToolCore/NETTools/NETProjectGen.cpp

@@ -442,9 +442,9 @@ namespace ToolCore
                     String startArguments;
 
 #ifdef ATOMIC_DEV_BUILD
-                    String playerBin = tenv->GetAtomicNETRootDir() + cfg + "/AtomicPlayer.exe";
+                    String playerBin = tenv->GetAtomicNETRootDir() + cfg + "/AtomicIPCPlayer.exe";
 #else
-                    String playerBin = tenv->GetAtomicNETRootDir() + "Release/AtomicPlayer.exe";
+                    String playerBin = tenv->GetAtomicNETRootDir() + "Release/AtomicIPCPlayer.exe";
 
                     startArguments += ToString("--resourcePrefix \"%s\" ", (fileSystem->GetProgramDir() + "Resources/").CString());
 

+ 2 - 0
Source/ToolCore/ToolEnvironment.cpp

@@ -81,6 +81,7 @@ bool ToolEnvironment::InitFromPackage()
     atomicNETRootDir_ = resourcesDir + "ToolData/AtomicNET/";
     atomicNETCoreAssemblyDir_ = atomicNETRootDir_ + "Release/";
     atomicNETManagedPlayerBinary_ = atomicNETCoreAssemblyDir_ + "AtomicPlayer.exe";
+    atomicNETManagedIPCPlayerBinary_ = atomicNETCoreAssemblyDir_ + "AtomicIPCPlayer.exe";
 
     return true;
 }
@@ -179,6 +180,7 @@ void ToolEnvironment::SetRootSourceDir(const String& sourceDir)
     atomicNETRootDir_ = rootSourceDir_ + "Artifacts/AtomicNET/";
     atomicNETCoreAssemblyDir_ = rootSourceDir_ + "Artifacts/AtomicNET/" + config + "/";
     atomicNETManagedPlayerBinary_ = atomicNETCoreAssemblyDir_ + "AtomicPlayer.exe";
+    atomicNETManagedIPCPlayerBinary_ = atomicNETCoreAssemblyDir_ + "AtomicIPCPlayer.exe";
 
 }
 

+ 2 - 0
Source/ToolCore/ToolEnvironment.h

@@ -85,6 +85,7 @@ public:
     const String& GetAtomicNETCoreAssemblyDir() { return atomicNETCoreAssemblyDir_; }
     const String& GetAtomicNETNuGetBinary() { return atomicNETNuGetBinary_; }
     const String& GetAtomicNETManagedPlayerBinary() { return atomicNETManagedPlayerBinary_; }
+    const String& GetAtomicNETManagedIPCPlayerBinary() { return atomicNETManagedIPCPlayerBinary_; }
 
 
     // OSX
@@ -145,6 +146,7 @@ private:
     String atomicNETCoreAssemblyDir_;
     String atomicNETNuGetBinary_;
     String atomicNETManagedPlayerBinary_;
+    String atomicNETManagedIPCPlayerBinary_;
 
     SharedPtr<ToolPrefs> toolPrefs_;
 };