void BuildAndroid::RunADBInstall()
{
    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
    ToolPrefs* prefs = tenv->GetToolPrefs();
    SubprocessSystem* subs = GetSubsystem<SubprocessSystem>();
    String adbCommand = platformAndroid_->GetADBCommand();

    Vector<String> args;

    if ( prefs->GetReleaseCheck() > 2 ) // install release apk
        args = String("install -r ./bin/Atomic-release.apk").Split(' ');
    else
        args = String("install -r ./bin/Atomic-debug.apk").Split(' ');

    currentBuildPhase_ = ADBInstall;
    Subprocess* subprocess = subs->Launch(adbCommand, args, buildPath_);
    if (!subprocess)
    {
        FailBuild("APK Device Installation operation did not launch successfully.");
        return;
    }

    VariantMap buildOutput;
    buildOutput[BuildOutput::P_TEXT] = "\n\n<color #D4FB79>Installing on Android Device</color>\n\n";
    SendEvent(E_BUILDOUTPUT, buildOutput);

    SubscribeToEvent(subprocess, E_SUBPROCESSCOMPLETE, ATOMIC_HANDLER(BuildAndroid, HandleRunADBInstallComplete));
    SubscribeToEvent(subprocess, E_SUBPROCESSOUTPUT, ATOMIC_HANDLER(BuildBase, HandleSubprocessOutputEvent));

}
bool AndroidProjectGenerator::GenerateLocalProperties()
{
    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
    ToolPrefs* prefs = tenv->GetToolPrefs();
    String sdkPath = prefs->GetAndroidSDKPath();

    if (!sdkPath.Length())
    {
        errorText_ = "Invalid Android SDK Path";
        return false;
    }

    String props;
    props.AppendWithFormat("sdk.dir=%s", sdkPath.CString());

    File file(context_, buildPath_ + "/local.properties", FILE_WRITE);

    if (!file.IsOpen())
        return false;

    file.Write(props.CString(), props.Length());

    return true;

}
Beispiel #3
0
void PlayCmd::Run()
{
    LOGINFOF("Playing project");

    ToolSystem* tsystem = GetSubsystem<ToolSystem>();
    ToolEnvironment* env = GetSubsystem<ToolCore::ToolEnvironment>();
    Project* project = tsystem->GetProject();
    const String& editorBinary = env->GetEditorBinary();

    Vector<String> paths;
    paths.Push(env->GetCoreDataDir());
    paths.Push(env->GetPlayerDataDir());
    paths.Push(project->GetResourcePath());

    // fixme: this is for loading from cache
    paths.Push(project->GetProjectPath());
    paths.Push(project->GetProjectPath() + "Cache");

    String resourcePaths;
    resourcePaths.Join(paths, "!");

    Vector<String> vargs;

    String args = ToString("--player --project \"%s\"", AddTrailingSlash(project->GetProjectPath()).CString());

    vargs = args.Split(' ');
    //vargs.Insert(0, "--player");

    // TODO: use IPC (maybe before this set log location/access the log and output it, we need access to errors)
    LaunchPlayerProcess(editorBinary, vargs, "");

    Finished();

}
    void AtomicGlowApp::Setup()
    {
        IPCClientApp::Setup();

        // AtomicGlow is always headless
        engineParameters_["Headless"] = true;

        FileSystem* filesystem = GetSubsystem<FileSystem>();
        engineParameters_.InsertNew("LogName", filesystem->GetAppPreferencesDir("AtomicEditor", "Logs") + "AtomicGlow.log");

        ToolSystem* tsystem = new ToolSystem(context_);
        context_->RegisterSubsystem(tsystem);

        ToolEnvironment* env = new ToolEnvironment(context_);
        context_->RegisterSubsystem(env);

        String projectPath;

        for (unsigned i = 0; i < arguments_.Size(); ++i)
        {
            if (arguments_[i].Length() > 1)
            {
                String argument = arguments_[i].ToLower();
                String value = i + 1 < arguments_.Size() ? arguments_[i + 1] : String::EMPTY;

                if (argument == "--project" && value.Length())
                {
                    if (GetExtension(value) == ".atomic")
                    {
                        value = GetPath(value);
                    }

                    if (filesystem->DirExists(value))
                    {

                    }
                    else
                    {
                        ErrorExit(ToString("%s project path does not exist", value.CString()));
                    }

                    projectPath = AddTrailingSlash(value);

                }
            }
        }

        if (!env->Initialize())
        {

			ErrorExit("Unable to initialize tool environment from %s");

            return;
        }

        engineParameters_["ResourcePrefixPaths"] = env->GetRootSourceDir() + "/Resources/";
        engineParameters_["ResourcePaths"] = ToString("CoreData;EditorData;%sResources;%sCache", projectPath.CString(), projectPath.CString());


    }
void BuildBase::GetDefaultResourcePaths(Vector<String>& paths)
{
    paths.Clear();

    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();

    paths.Push(AddTrailingSlash(tenv->GetCoreDataDir()));
    paths.Push(AddTrailingSlash(tenv->GetPlayerDataDir()));
}
bool EditorMode::PlayProject(String addArgs, bool debug)
{
    ToolEnvironment* env = GetSubsystem<ToolEnvironment>();
    ToolSystem* tsystem = GetSubsystem<ToolSystem>();

    const String& editorBinary = env->GetEditorBinary();

    Project* project = tsystem->GetProject();

    if (!project)
        return false;

    Vector<String> paths;
    paths.Push(env->GetCoreDataDir());
    paths.Push(env->GetPlayerDataDir());
    paths.Push(project->GetResourcePath());

    // fixme: this is for loading from cache
    paths.Push(project->GetProjectPath());
    paths.Push(project->GetProjectPath() + "Cache");

    String resourcePaths;
    resourcePaths.Join(paths, "!");

    Vector<String> vargs;

    String args = ToString("--player --project \"%s\"", AddTrailingSlash(project->GetProjectPath()).CString());

    vargs = args.Split(' ');

    if (debug)
        vargs.Insert(0, "--debug");

    if (addArgs.Length() > 0)
        vargs.Insert(0, addArgs.Split(' '));

    String dump;
    dump.Join(vargs, " ");
    LOGINFOF("Launching Broker %s %s", editorBinary.CString(), dump.CString());

    IPC* ipc = GetSubsystem<IPC>();
    playerBroker_ = ipc->SpawnWorker(editorBinary, vargs);

    if (playerBroker_)
    {
        SubscribeToEvent(playerBroker_, E_IPCJSERROR, HANDLER(EditorMode, HandleIPCJSError));
        SubscribeToEvent(playerBroker_, E_IPCWORKEREXIT, HANDLER(EditorMode, HandleIPCWorkerExit));
        SubscribeToEvent(playerBroker_, E_IPCWORKERLOG, HANDLER(EditorMode, HandleIPCWorkerLog));
    }

    return playerBroker_.NotNull();

}
bool AndroidProjectGenerator::GenerateLocalProperties( )
{
    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
    ToolPrefs* prefs = tenv->GetToolPrefs();
    String sdkPath = prefs->GetAndroidSDKPath();

    if (!sdkPath.Length())
    {
        errorText_ = "Invalid Android SDK Path, select the path in Build Settings.";
        return false;
    }

    String props;
    props.AppendWithFormat("sdk.dir=%s", sdkPath.CString());

    File file(context_, buildPath_ + "/local.properties", FILE_WRITE);

    if (!file.IsOpen())
    {
        errorText_ = "Project generator unable to open file " + buildPath_ + "/local.properties ";
        return false;
    }
    
    file.Write(props.CString(), props.Length());


    if ( prefs->GetReleaseCheck() > 2 ) // if release index is set ...
    {
        FileSystem* fileSystem = GetSubsystem<FileSystem>();
        String Reldir = prefs->GetReleasePath();
        if (!fileSystem->DirExists(Reldir))
        {
            errorText_ = "Invalid Release Path, select the path in Build Settings.";
            return false;
        }
        
        String antname = Reldir + "/ant.properties";
        if ( !fileSystem->FileExists ( antname) ) 
        {
            errorText_ = "The file ant.properties not found in " + Reldir + ", unable to generate Release APK.";
            return false;
        }

        if ( !buildBase_->BuildCopyFile ( antname, buildPath_ + "/ant.properties" ))
            return false;

    }
    return true;

}
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)
{
    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();

    buildPath_ = AddTrailingSlash(buildPath) + GetBuildSubfolder();

    BuildLog("Starting Windows Deployment");

    Initialize();

    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";

    if (!BuildCreateDirectory(buildPath_))
        return;

    if (!BuildCreateDirectory(buildPath_ + "/AtomicPlayer_Resources"))
        return;

    String resourcePackagePath = buildPath_ + "/AtomicPlayer_Resources/AtomicResources" + PAK_EXTENSION;
    GenerateResourcePackage(resourcePackagePath);
    if (buildFailed_)
        return;
   
    if (!BuildCopyFile(playerBinary, buildPath_ + "/AtomicPlayer.exe"))
        return;

    if (!BuildCopyFile(d3d9dll, buildPath_ + "/D3DCompiler_47.dll"))
        return;

    BuildAtomicNET();

    BuildLog("Windows Deployment Complete");

    buildSystem->BuildComplete(PLATFORMID_WINDOWS, buildPath_);

}
bool AndroidProjectGenerator::CopyDebugGdbserver()
{
    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
    ToolPrefs* prefs = tenv->GetToolPrefs();

    // include gdbserver in APK
    if ( prefs->GetReleaseCheck() == 1 || prefs->GetReleaseCheck() == 2 ) 
    {
        String ndkPath = prefs->GetNdkPath();    
        if (ndkPath.Empty())
        {
            errorText_ = "NDK path not entered, this is required to add gdbserver to APK";
            return false;
        }

        FileSystem* fileSystem = GetSubsystem<FileSystem>();
        if (!fileSystem->DirExists(ndkPath))
        {
            errorText_ = "Invalid NDK Path, can not add gdbserver to APK.";
            return false;
        }

        // copy gdbserver file
        String gsstring = ndkPath + "/prebuilt/android-arm/gdbserver/gdbserver";  // assume arm type abi
        String destDir = buildPath_ + "/libs/armeabi-v7a"; // assume armeabi-v7a abi type
        if ( !fileSystem->FileExists (gsstring) )
        {
            errorText_ = "gdbserver not found as " + gsstring;
            return false;
        }
        
        if ( prefs->GetReleaseCheck() == 1 ) // Debug Source with gdbserver
        {
            if ( !buildBase_->BuildCopyFile ( gsstring, destDir + "/gdbserver"))
                return false;
        } 
        else if ( prefs->GetReleaseCheck() == 2 ) // Debug Source with libgdbserver.so
        {
            if ( !buildBase_->BuildCopyFile ( gsstring, destDir + "/libgdbserver.so"))
                return false;
        } 
    }
    return true;
}
JSResourceEditor ::JSResourceEditor(Context* context, const String &fullpath, UITabContainer *container) :
    ResourceEditor(context, fullpath, container)
{

    TBLayout* layout = new TBLayout();
    layout->SetLayoutSize(LAYOUT_SIZE_GRAVITY);
    layout->SetGravity(WIDGET_GRAVITY_ALL);
    layout->SetLayoutDistribution(LAYOUT_DISTRIBUTION_GRAVITY);

    rootContentWidget_->GetInternalWidget()->AddChild(layout);

    TBContainer* c = new TBContainer();
    c->SetGravity(WIDGET_GRAVITY_ALL);

    layout->AddChild(c);

    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
    String codeEditorDir = tenv->GetToolDataDir();
    codeEditorDir += "CodeEditor/Editor.html";

#ifdef ATOMIC_PLATFORM_OSX
    String url = "file://" + codeEditorDir;
#else
    String url = "file:///" + codeEditorDir;
#endif

    webView_ = new UIWebView(context_, url);
    webClient_ = webView_->GetWebClient();
    messageHandler_ = new WebMessageHandler(context_);
    webClient_->AddMessageHandler(messageHandler_);

    webView_->GetWebTexture2D()->SetClearColor(Color(.23f, .23f, .23f, 1));

    SubscribeToEvent(webClient_, E_WEBVIEWLOADEND, HANDLER(JSResourceEditor, HandleWebViewLoadEnd));
    SubscribeToEvent(messageHandler_, E_WEBMESSAGE, HANDLER(JSResourceEditor, HandleWebMessage));

    SubscribeToEvent(E_RENAMERESOURCENOTIFICATION, HANDLER(JSResourceEditor, HandleRenameResourceNotification));
    SubscribeToEvent(E_DELETERESOURCENOTIFICATION, HANDLER(JSResourceEditor, HandleDeleteResourceNotification));
    SubscribeToEvent(E_PROJECTUNLOADEDNOTIFICATION, HANDLER(JSResourceEditor, HandleProjectUnloadedNotification));

    c->AddChild(webView_->GetInternalWidget());

}
void AEEditorApp::Setup()
{
    context_->SetEditorContext(true);

    AEEditorCommon::Setup();

    ToolEnvironment* env = GetSubsystem<ToolEnvironment>();

    engineParameters_["WindowTitle"] = "AtomicEditor";
    engineParameters_["WindowResizable"] = true;
    engineParameters_["FullScreen"] = false;
    engineParameters_["LogLevel"] = LOG_DEBUG;

    FileSystem* filesystem = GetSubsystem<FileSystem>();
    engineParameters_["LogName"] = filesystem->GetAppPreferencesDir("AtomicEditor", "Logs") + "AtomicEditor.log";

#ifdef ATOMIC_PLATFORM_OSX
    engineParameters_["WindowIcon"] = "Images/AtomicLogo32.png";
#endif

#ifdef ATOMIC_DEV_BUILD
    engineParameters_["ResourcePrefixPath"] = "";
    String resourcePaths = env->GetCoreDataDir() + ";" + env->GetEditorDataDir();
    // for dev builds, add the compile editor scripts from artifacts
    resourcePaths += ";" + env->GetRootSourceDir() + "Artifacts/Build/Resources/EditorData/";
    engineParameters_["ResourcePaths"] = resourcePaths;
#else

#ifdef ATOMIC_PLATFORM_OSX
    engineParameters_["ResourcePrefixPath"] = "../Resources";

#else
    engineParameters_["ResourcePrefixPath"] = filesystem->GetProgramDir() + "Resources";
#endif

    engineParameters_["ResourcePaths"] = "CoreData;EditorData";

#endif // ATOMIC_DEV_BUILD

    ReadPreferences();

}
void AEEditorApp::Setup()
{
    context_->SetEditorContext(true);

    ToolEnvironment* env = new ToolEnvironment(context_);
    context_->RegisterSubsystem(env);

    ToolSystem* system = new ToolSystem(context_);
    context_->RegisterSubsystem(system);

#ifdef ATOMIC_DEV_BUILD

    if (!env->InitFromJSON())
    {
        ErrorExit(ToString("Unable to initialize tool environment from %s", env->GetDevConfigFilename().CString()));
        return;
    }
#else

    env->InitFromPackage();

#endif

    engineParameters_["WindowTitle"] = "AtomicEditor";
    engineParameters_["WindowResizable"] = true;
    engineParameters_["FullScreen"] = false;
    engineParameters_["LogLevel"] = LOG_DEBUG;

    FileSystem* filesystem = GetSubsystem<FileSystem>();
    engineParameters_["LogName"] = filesystem->GetAppPreferencesDir("AtomicEditor", "Logs") + "AtomicEditor.log";

#ifdef ATOMIC_PLATFORM_OSX
    engineParameters_["WindowIcon"] = "Images/AtomicLogo32.png";
#endif

#ifdef ATOMIC_DEV_BUILD
    engineParameters_["ResourcePrefixPath"] = "";
    String ScriptPath = env->GetRootSourceDir() + "Script";
    String resourcePaths = env->GetCoreDataDir() + ";" +  env->GetEditorDataDir() + ";" + ScriptPath;
    engineParameters_["ResourcePaths"] = resourcePaths;
#else

#ifdef ATOMIC_PLATFORM_OSX
    engineParameters_["ResourcePrefixPath"] = "../Resources";
    
#else
	engineParameters_["ResourcePrefixPath"] = filesystem->GetProgramDir() + "Resources";
#endif

	engineParameters_["ResourcePaths"] = "CoreData;EditorData;Script";

#endif // ATOMIC_DEV_BUILD


}
void AtomicTool::Start()
{
    // Subscribe to events
    SubscribeToEvent(E_COMMANDERROR, HANDLER(AtomicTool, HandleCommandError));
    SubscribeToEvent(E_COMMANDFINISHED, HANDLER(AtomicTool, HandleCommandFinished));

    SubscribeToEvent(E_LICENSE_EULAREQUIRED, HANDLER(AtomicTool, HandleLicenseEulaRequired));
    SubscribeToEvent(E_LICENSE_ACTIVATIONREQUIRED, HANDLER(AtomicTool, HandleLicenseActivationRequired));
    SubscribeToEvent(E_LICENSE_ERROR, HANDLER(AtomicTool, HandleLicenseError));
    SubscribeToEvent(E_LICENSE_SUCCESS, HANDLER(AtomicTool, HandleLicenseSuccess));

    const Vector<String>& arguments = GetArguments();

    ToolSystem* tsystem = new ToolSystem(context_);
    context_->RegisterSubsystem(tsystem);

    ToolEnvironment* env = new ToolEnvironment(context_);
    context_->RegisterSubsystem(env);

//#ifdef ATOMIC_DEV_BUILD

    if (!env->InitFromJSON())
    {
        ErrorExit(ToString("Unable to initialize tool environment from %s", env->GetDevConfigFilename().CString()));
        return;
    }

    if (!cliDataPath_.Length())
    {
        cliDataPath_ = env->GetRootSourceDir() + "/Resources/";
    }

//#endif

    tsystem->SetCLI();
    tsystem->SetDataPath(cliDataPath_);


    if (activationKey_.Length())
    {
        DoActivation();
        return;
    } else if (deactivate_)
    {
        DoDeactivation();
        return;
    }

    BuildSystem* buildSystem = GetSubsystem<BuildSystem>();

    SharedPtr<CommandParser> parser(new CommandParser(context_));

    SharedPtr<Command> cmd(parser->Parse(arguments));
    if (!cmd)
    {
        String error = "No command found";

        if (parser->GetErrorMessage().Length())
            error = parser->GetErrorMessage();

        ErrorExit(error);
        return;
    }

    if (cmd->RequiresProjectLoad())
    {
        FileSystem* fileSystem = GetSubsystem<FileSystem>();

        String projectDirectory = fileSystem->GetCurrentDir();

        Vector<String> projectFiles;
        fileSystem->ScanDir(projectFiles, projectDirectory, "*.atomic", SCAN_FILES, false);
        if (!projectFiles.Size())
        {
            ErrorExit(ToString("No .atomic project file in %s", projectDirectory.CString()));
            return;
        }
        else if (projectFiles.Size() > 1)
        {
            ErrorExit(ToString("Multiple .atomic project files found in %s", projectDirectory.CString()));
            return;
        }

        String projectFile = projectDirectory + "/" + projectFiles[0];

        if (!tsystem->LoadProject(projectFile))
        {
            //ErrorExit(ToString("Failed to load project: %s", projectFile.CString()));
            //return;
        }

        // Set the build path
        String buildFolder = projectDirectory + "/" + "Build";
        buildSystem->SetBuildPath(buildFolder);

        if (!fileSystem->DirExists(buildFolder))
        {
            fileSystem->CreateDir(buildFolder);

            if (!fileSystem->DirExists(buildFolder))
            {
                ErrorExit(ToString("Failed to create build folder: %s", buildFolder.CString()));
                return;
            }
        }

    }

    command_ = cmd;

    // BEGIN LICENSE MANAGEMENT
    if (cmd->RequiresLicenseValidation())
    {
        GetSubsystem<LicenseSystem>()->Initialize();
    }
    else
    {
        if (command_.Null())
        {
            GetSubsystem<Engine>()->Exit();
            return;
        }

        command_->Run();
    }
    // END LICENSE MANAGEMENT

}
void BuildWindows::BuildAtomicNET()
{
    // AtomicNET

    FileSystem* fileSystem = GetSubsystem<FileSystem>();
    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
    ToolSystem* tsystem = GetSubsystem<ToolSystem>();
    Project* project = tsystem->GetProject();
    String projectResources = project->GetResourcePath();

    String assembliesPath = projectResources + "Assemblies/";

    // if no assemblies path, no need to install AtomicNET
    if (!fileSystem->DirExists(assembliesPath))
        return;

    Vector<String> results;
    fileSystem->ScanDir(results, assembliesPath, "*.dll", SCAN_FILES, true);

    // if no assembiles in Assemblies path, no need to install AtomicNET
    if (!results.Size())
        return;

    BuildLog("Building AtomicNET");

    fileSystem->CreateDir(buildPath_ + "/AtomicPlayer_Resources/AtomicNET");
    fileSystem->CreateDir(buildPath_ + "/AtomicPlayer_Resources/AtomicNET/Atomic");
    fileSystem->CreateDir(buildPath_ + "/AtomicPlayer_Resources/AtomicNET/Atomic/Assemblies");

    fileSystem->CopyDir(tenv->GetNETCoreCLRAbsPath(), buildPath_ + "/AtomicPlayer_Resources/AtomicNET/CoreCLR");
    fileSystem->CopyDir(tenv->GetNETTPAPaths(), buildPath_ + "/AtomicPlayer_Resources/AtomicNET/Atomic/TPA");

    // Atomic Assemblies

    const String& assemblyLoadPaths = tenv->GetNETAssemblyLoadPaths();
    Vector<String> paths = assemblyLoadPaths.Split(';');

    for (unsigned i = 0; i < paths.Size(); i++)
    {
        Vector<String> loadResults;
        fileSystem->ScanDir(loadResults, paths[i], "*.dll", SCAN_FILES, true);

        for (unsigned j = 0; j < loadResults.Size(); j++)
        {
            String pathName, fileName, ext;
            SplitPath(loadResults[j], pathName, fileName, ext);

            if (fileName != "AtomicNETEngine")
                continue;

            fileSystem->Copy(paths[i] + "/" + loadResults[j], ToString("%s/AtomicPlayer_Resources/AtomicNET/Atomic/Assemblies/%s.dll", buildPath_.CString(), fileName.CString()));
        }

    }

    // Project assemblied
    for (unsigned i = 0; i < results.Size(); i++)
    {
        String pathName, fileName, ext;
        SplitPath(results[i], pathName, fileName, ext);
        fileSystem->Copy(assembliesPath + results[i], ToString("%s/AtomicPlayer_Resources/AtomicNET/Atomic/Assemblies/%s.dll", buildPath_.CString(), fileName.CString()));
    }



}
    void NETBuildSystem::HandleToolUpdate(StringHash eventType, VariantMap& eventData)
    {
        if (curBuild_.Null() && !builds_.Size())
            return;

        if (curBuild_.Null())
        {
            // kick off a new build

            curBuild_ = builds_.Front();
            builds_.PopFront();


            FileSystem* fileSystem = GetSubsystem<FileSystem>();

            // Ensure solution still exists
            if (!fileSystem->FileExists(curBuild_->solutionPath_))
            {
                CurrentBuildError(ToString("Solution does not exist(%s)", curBuild_->solutionPath_.CString()));
                return;
            }

            String solutionPath = curBuild_->solutionPath_;

            String ext = GetExtension(solutionPath);

            bool requiresNuGet = true;

            if (ext == ".sln")
            {
                // TODO: handle projects that require nuget
                requiresNuGet = false;

                if (!fileSystem->FileExists(solutionPath))
                {
                    CurrentBuildError(ToString("Generated solution does not exist (%s : %s)", curBuild_->solutionPath_.CString(), solutionPath.CString()));
                    return;
                }

            }
            else if (ext == ".json")
            {
                SharedPtr<NETProjectGen> gen(new NETProjectGen(context_));

                gen->SetSupportedPlatforms(curBuild_->platforms_);
                gen->SetRewriteSolution(true);

                if (!gen->LoadJSONProject(solutionPath))
                {
                    CurrentBuildError(ToString("Error loading project (%s)", solutionPath.CString()));
                    return;
                }

                if (!gen->Generate())
                {
                    CurrentBuildError(ToString("Error generating project (%s)", solutionPath.CString()));
                    return;
                }

                solutionPath = gen->GetSolution()->GetOutputFilename();
                requiresNuGet = gen->GetRequiresNuGet();

                if (!fileSystem->FileExists(solutionPath))
                {
                    CurrentBuildError(ToString("Generated solution does not exist (%s : %s)", curBuild_->solutionPath_.CString(), solutionPath.CString()));
                    return;
                }

            }

            ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
            const String& nugetBinary = tenv->GetAtomicNETNuGetBinary();

            if (requiresNuGet && !fileSystem->FileExists(nugetBinary))
            {
                CurrentBuildError(ToString("NuGet binary is missing (%s)", nugetBinary.CString()));
                return;
            }

            StringVector stringVector;
            String platforms;
            StringVector processedPlatforms;
            String configs;

            for (unsigned i = 0; i < curBuild_->configurations_.Size(); i++)
            {
                stringVector.Push(ToString("/p:Configuration=%s", curBuild_->configurations_[i].CString()));
            }

            configs = String::Joined(stringVector, " ");
            stringVector.Clear();

            for (unsigned i = 0; i < curBuild_->platforms_.Size(); i++)
            {
                // map platform
                String platform = curBuild_->platforms_[i];

                if (platform == "windows" || platform == "macosx" || platform == "linux")
                {
                    ATOMIC_LOGINFOF("Platform \"%s\" mapped to \"desktop\"", platform.CString());
                    platform = "desktop";
                }

                if (processedPlatforms.Contains(platform))
                {
                    ATOMIC_LOGWARNINGF("Platform \"%s\" is duplicated, skipping", platform.CString());
                    continue;
                }

                processedPlatforms.Push(platform);

                if (platform == "desktop" || platform == "android")
                {
                    platform = "\"Any CPU\"";
                }
                else if (platform == "ios")
                {

                    platform = "\"Any CPU\"";
                    // TODO
                    // platform = "iPhone";
                }
                else
                {
                    ATOMIC_LOGERRORF("Unknown platform: %s, skipping", platform.CString());
                    continue;
                }

                platform = ToString("/p:Platform=%s", platform.CString());

                if (stringVector.Contains(platform))
                {
                    // This can happen when specifying Desktop + Android for example
                    continue;
                }

                stringVector.Push(platform);
            }

            platforms = String::Joined(stringVector, " ");
            stringVector.Clear();

            Vector<String> args;

#ifdef ATOMIC_PLATFORM_WINDOWS

            String cmdToolsPath = Poco::Environment::get("VS140COMNTOOLS", "").c_str();

            if (!cmdToolsPath.Length())
            {
                CurrentBuildError("VS140COMNTOOLS environment variable not found, cannot proceed");
                return;
            }

            if (!cmdToolsPath.EndsWith("\\"))
            {
                cmdToolsPath += "\\";
            }

            String msbuildcmd = ToString("%sVsMSBuildCmd.bat", cmdToolsPath.CString());

            String cmd = "cmd";

            args.Push("/A");
            args.Push("/C");

            // vcvars bat
            String compile = ToString("\"\"%s\" ", msbuildcmd.CString());

            if (requiresNuGet)
            {
                compile += ToString("&& \"%s\" restore \"%s\" ", nugetBinary.CString(), solutionPath.CString());
            }

            compile += ToString("&& msbuild \"%s\" %s %s", solutionPath.CString(), platforms.CString(), configs.CString());

            if (curBuild_->targets_.Size()) {

                StringVector targets;

                for (unsigned i = 0; i < curBuild_->targets_.Size(); i++)
                {
                    const char* tname = curBuild_->targets_[i].CString();
                    targets.Push(ToString("/t:\"%s:Rebuild\"", tname));
                }

                compile += " " + String::Joined(targets, " ");

            }

            // close out quote
            compile += "\"";

            args.Push(compile);

#else

            String compile;

            String cmd = "bash";
            args.Push("-c");

            String xbuildBinary = tenv->GetMonoExecutableDir() + "xbuild";

            if (requiresNuGet)
            {
#ifdef ATOMIC_PLATFORM_OSX
                compile += ToString("\"%s\" restore \"%s\" && ", nugetBinary.CString(), solutionPath.CString());
#else
                compile += ToString("mono \"%s\" restore \"%s\" && ", nugetBinary.CString(), solutionPath.CString());
#endif
            }

            compile += ToString("\"%s\" \"%s\" %s %s", xbuildBinary.CString(), solutionPath.CString(), platforms.CString(), configs.CString());

            if (curBuild_->targets_.Size()) {

                StringVector targets;

                for (unsigned i = 0; i < curBuild_->targets_.Size(); i++)
                {
                    const char* tname = curBuild_->targets_[i].CString();
                    targets.Push(ToString("%s:Rebuild", tname));
                }

                compile += " /target:\"" + String::Joined(targets, ";") + "\"";

            }

            args.Push(compile);

#endif

            curBuild_->allArgs_.Join(args, " ");

            SubprocessSystem* subs = GetSubsystem<SubprocessSystem>();
            Subprocess* subprocess = nullptr;

            ATOMIC_LOGINFOF("%s : %s", cmd.CString(), curBuild_->allArgs_.CString());

            try
            {
                subprocess = subs->Launch(cmd, args, "");
            }
            catch (Poco::SystemException)
            {
                subprocess = nullptr;
            }

            if (!subprocess)
            {
                CurrentBuildError(ToString("NETCompile::Compile - Unable to launch MSBuild subprocess\n%s", curBuild_->allArgs_.CString()));
                return;
            }

            VariantMap buildBeginEventData;
            buildBeginEventData[NETBuildBegin::P_BUILD] = curBuild_;
            SendEvent(E_NETBUILDBEGIN, buildBeginEventData);

            SubscribeToEvent(subprocess, E_SUBPROCESSCOMPLETE, ATOMIC_HANDLER(NETBuildSystem, HandleCompileProcessComplete));
            SubscribeToEvent(subprocess, E_SUBPROCESSOUTPUT, ATOMIC_HANDLER(NETBuildSystem, HandleSubprocessOutput));

            curBuild_->status_ = NETBUILD_BUILDING;

        }

    }
void BuildAndroid::RunAntDebug()
{
    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
    SubprocessSystem* subs = GetSubsystem<SubprocessSystem>();
    ToolPrefs* tprefs = tenv->GetToolPrefs();

    Poco::Process::Env env;

    String buildApk = "debug";  // the default

    if ( tprefs->GetReleaseCheck() > 2 ) // create release apk
        buildApk = "release";


#ifdef ATOMIC_PLATFORM_OSX
    String antCommand = tprefs->GetAntPath();
    Vector<String> args;
    args.Push(buildApk);
#endif
#ifdef ATOMIC_PLATFORM_WINDOWS
    // C:\ProgramData\Oracle\Java\javapath;
    Vector<String> args;
    String antCommand = "cmd";
    String antPath = tprefs->GetAntPath() + "/ant.bat";
    env["JAVA_HOME"] = tprefs->GetJDKRootPath().CString();
    // ant is a batch file on windows, so have to run with cmd /c
    args.Push("/c");
    args.Push("\"" + antPath + "\"");
    args.Push(buildApk);
#endif
#ifdef ATOMIC_PLATFORM_LINUX 

    String antCommand = tprefs->GetAntPath();
    if ( antCommand.Empty() ) // user didnt fill it out, use installed one
    {
        antCommand = "/usr/bin/ant"; // system default if installed
    }
    else
    {
        antCommand.Append("/ant"); 
    }
    FileSystem* fileSystem = GetSubsystem<FileSystem>();
    if ( !fileSystem->FileExists ( antCommand) ) 
    {
        FailBuild("The ant program can not be found, check the Ant Path in Build Settings.");
    }
    Vector<String> args;
    args.Push(buildApk);
#endif

    currentBuildPhase_ = AntBuildDebug;
    Subprocess* subprocess = subs->Launch(antCommand, args, buildPath_, env);

    if (!subprocess)
    {
        FailBuild("The ant build operation did not launch successfully.");
        return;
    }

    VariantMap buildOutput;
    buildOutput[BuildOutput::P_TEXT] = "<color #D4FB79>Starting Android " + buildApk + " Deployment</color>\n\n";
    SendEvent(E_BUILDOUTPUT, buildOutput);

    SubscribeToEvent(subprocess, E_SUBPROCESSCOMPLETE, ATOMIC_HANDLER(BuildAndroid, HandleAntDebugComplete));
    SubscribeToEvent(subprocess, E_SUBPROCESSOUTPUT, ATOMIC_HANDLER(BuildBase, HandleSubprocessOutputEvent));

}
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);

    if (!resourcesOnly_)
        buildPath_ += GetBuildSubfolder();

    BuildLog("Starting Windows Deployment");

    Initialize();

    if (!resourcesOnly_ && !BuildClean(buildPath_))
        return;

    String rootSourceDir = tenv->GetRootSourceDir();

    if (!BuildCreateDirectory(buildPath_))
        return;

    if (!resourcesOnly_ && !BuildCreateDirectory(buildPath_ + "/AtomicPlayer_Resources"))
        return;

    String resourcePackagePath = buildPath_ + "/AtomicPlayer_Resources/AtomicResources" + PAK_EXTENSION;

    if (resourcesOnly_)
    {
        resourcePackagePath = buildPath_ + "/AtomicResources" + PAK_EXTENSION;
    }

    GenerateResourcePackage(resourcePackagePath);

    if (buildFailed_)
        return;

    if (resourcesOnly_)
        return;

    if (!BuildCreateDirectory(buildPath_ + "/Settings"))
        return;

    String engineJSON(GetSettingsDirectory() + "/Engine.json");

    if (fileSystem->FileExists(engineJSON))
    {
        if (!BuildCopyFile(engineJSON, buildPath_ + "/Settings/Engine.json"))
            return;
    }

    // TODO: Set project as managed and don't key off project assembly

    if (fileSystem->FileExists(project->GetResourcePath() + project->GetProjectSettings()->GetName() + ".dll"))
    {
        if (!BuildManaged(buildPath))
            return;
    }
    else
    {
        BuildNative(buildPath);
    }

    BuildLog("Windows Deployment Complete");

    buildSystem->BuildComplete(PLATFORMID_WINDOWS, buildPath_);

}
bool EditorMode::PlayProject(String addArgs, bool debug)
{
    FileSystem* fileSystem = GetSubsystem<FileSystem>();
    ToolSystem* tsystem = GetSubsystem<ToolSystem>();
    Project* project = tsystem->GetProject();

    if (!project)
        return false;

    ToolEnvironment* env = GetSubsystem<ToolEnvironment>();

    String playerBinary = env->GetEditorBinary();

    // TODO: We need to configure project as managed
    bool managed = false;
    if (fileSystem->FileExists(project->GetResourcePath() + "AtomicProject.dll"))
    {
        managed = true;
        playerBinary = env->GetAtomicNETManagedIPCPlayerBinary();
    }


    Vector<String> paths;
    paths.Push(env->GetCoreDataDir());
    paths.Push(env->GetPlayerDataDir());
    paths.Push(project->GetResourcePath());

    // fixme: this is for loading from cache
    paths.Push(project->GetProjectPath());
    paths.Push(project->GetProjectPath() + "Cache");

    String resourcePaths;
    resourcePaths.Join(paths, "!");

    Vector<String> vargs;

    String args = ToString("--player --project \"%s\"", AddTrailingSlash(project->GetProjectPath()).CString());

    vargs = args.Split(' ');

    if (managed)
    {            
        vargs.Insert(0, ToString("\"%s\"", (fileSystem->GetProgramDir() + "Resources/").CString()));        
        vargs.Insert(0, "--resourcePrefix");
    }

    if (debug)
        vargs.Insert(0, "--debug");

    if (addArgs.Length() > 0)
        vargs.Insert(0, addArgs.Split(' '));

    String dump;
    dump.Join(vargs, " ");
    ATOMIC_LOGINFOF("Launching Broker %s %s", playerBinary.CString(), dump.CString());

    IPC* ipc = GetSubsystem<IPC>();
    playerBroker_ = ipc->SpawnWorker(playerBinary, vargs);

    if (playerBroker_)
    {
        SubscribeToEvent(playerBroker_, E_IPCWORKERSTART, ATOMIC_HANDLER(EditorMode, HandleIPCWorkerStarted));

        SubscribeToEvent(E_IPCPLAYERPAUSERESUMEREQUEST, ATOMIC_HANDLER(EditorMode, HandleIPCPlayerPauseResumeRequest));
        SubscribeToEvent(E_IPCPLAYERUPDATESPAUSEDRESUMED, ATOMIC_HANDLER(EditorMode, HandleIPCPlayerUpdatesPausedResumed));
        SubscribeToEvent(E_IPCPLAYERPAUSESTEPREQUEST, ATOMIC_HANDLER(EditorMode, HandleIPCPlayerPauseStepRequest));
        SubscribeToEvent(E_IPCPLAYEREXITREQUEST, ATOMIC_HANDLER(EditorMode, HandleIPCPlayerExitRequest));
    

        SubscribeToEvent(playerBroker_, E_IPCJSERROR, ATOMIC_HANDLER(EditorMode, HandleIPCJSError));
        SubscribeToEvent(playerBroker_, E_IPCWORKEREXIT, ATOMIC_HANDLER(EditorMode, HandleIPCWorkerExit));
        SubscribeToEvent(playerBroker_, E_IPCWORKERLOG, ATOMIC_HANDLER(EditorMode, HandleIPCWorkerLog));
    }

    return playerBroker_.NotNull();

}
void BuildAndroid::Build(const String& buildPath)
{
    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
    ToolSystem* tsystem = GetSubsystem<ToolSystem>();
    Project* project = tsystem->GetProject();

    buildPath_ = AddTrailingSlash(buildPath) + GetBuildSubfolder();

    Initialize();
 
    if (!BuildClean(buildPath_))
        return;

    //generate manifest file
    String manifest;
    for (unsigned i = 0; i < resourceEntries_.Size(); i++)
    {
        BuildResourceEntry* entry = resourceEntries_[i];
        manifest += entry->packagePath_;
        if ( i != resourceEntries_.Size() - 1)
            manifest += ";";
    }

    String buildSourceDir = tenv->GetToolDataDir();

    String androidProject = buildSourceDir + "Deployment/Android";

    // Copy the base android project
    FileSystem* fileSystem = GetSubsystem<FileSystem>();
    if( !BuildCopyDir(androidProject, buildPath_))
        return;

    Vector<String> defaultResourcePaths;
    GetDefaultResourcePaths(defaultResourcePaths);
    String projectResources = project->GetResourcePath();

    for (unsigned i = 0; i < defaultResourcePaths.Size(); i++)
    {
        if ( !BuildCopyDir(defaultResourcePaths[i], buildPath_ + "/assets/" + GetFileName(RemoveTrailingSlash(defaultResourcePaths[i]))))
            return;
    }

    if( !BuildCopyDir(project->GetProjectPath() + "Cache/", buildPath_ + "/assets/Cache"))
        return;
    if( !BuildCopyDir(projectResources, buildPath_ + "/assets/AtomicResources"))
        return;

    // write the manifest
    SharedPtr<File> mfile(new File(context_, buildPath_ + "/assets/AtomicManifest", FILE_WRITE));
    mfile->WriteString(manifest);
    mfile->Close();

    //check for Deployment/Android/libs/armeabi-v7a/libAtomicPlayer.so
    if ( !fileSystem->FileExists(androidProject + "/libs/armeabi-v7a/libAtomicPlayer.so")  )
    {
        FailBuild( "The file libAtomicPlayer.so is not found. This is required for APK generation." );
        return;
    }

    AndroidProjectGenerator gen(context_, this);
    gen.SetBuildPath(buildPath_);

    if (!gen.Generate())
    {
        FailBuild(gen.GetErrorText());
        return;
    }

    RunAntDebug();

}