Add Mac platform
This commit is contained in:
@@ -42,6 +42,7 @@ namespace FlaxEditor.Content.Create
|
|||||||
SwitchPlatformSettings,
|
SwitchPlatformSettings,
|
||||||
[EditorDisplay(null, "PS5 Platform Settings")]
|
[EditorDisplay(null, "PS5 Platform Settings")]
|
||||||
PS5PlatformSettings,
|
PS5PlatformSettings,
|
||||||
|
MacPlatformSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Type[] _types =
|
private static readonly Type[] _types =
|
||||||
@@ -66,6 +67,7 @@ namespace FlaxEditor.Content.Create
|
|||||||
typeof(AndroidPlatformSettings),
|
typeof(AndroidPlatformSettings),
|
||||||
TypeUtils.GetManagedType(GameSettings.SwitchPlatformSettingsTypename),
|
TypeUtils.GetManagedType(GameSettings.SwitchPlatformSettingsTypename),
|
||||||
TypeUtils.GetManagedType(GameSettings.PS5PlatformSettingsTypename),
|
TypeUtils.GetManagedType(GameSettings.PS5PlatformSettingsTypename),
|
||||||
|
typeof(MacPlatformSettings),
|
||||||
};
|
};
|
||||||
|
|
||||||
internal class Options
|
internal class Options
|
||||||
@@ -236,6 +238,11 @@ namespace FlaxEditor.Content.Create
|
|||||||
return false;
|
return false;
|
||||||
instance.PS5Platform = asset;
|
instance.PS5Platform = asset;
|
||||||
break;
|
break;
|
||||||
|
case SettingsTypes.MacPlatformSettings:
|
||||||
|
if (instance.MacPlatform != null)
|
||||||
|
return false;
|
||||||
|
instance.MacPlatform = asset;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,12 @@ API_ENUM() enum class BuildPlatform
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_ENUM(Attributes="EditorDisplay(null, \"PlayStation 5\")")
|
API_ENUM(Attributes="EditorDisplay(null, \"PlayStation 5\")")
|
||||||
PS5 = 11,
|
PS5 = 11,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MacOS (x86-64 Intel)
|
||||||
|
/// </summary>
|
||||||
|
API_ENUM(Attributes="EditorDisplay(null, \"Mac x64\")")
|
||||||
|
MacOSx64 = 12,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FLAXENGINE_API const Char* ToString(const BuildPlatform platform);
|
extern FLAXENGINE_API const Char* ToString(const BuildPlatform platform);
|
||||||
|
|||||||
@@ -58,6 +58,10 @@
|
|||||||
#if PLATFORM_TOOLS_SWITCH
|
#if PLATFORM_TOOLS_SWITCH
|
||||||
#include "Platforms/Switch/Editor/PlatformTools/SwitchPlatformTools.h"
|
#include "Platforms/Switch/Editor/PlatformTools/SwitchPlatformTools.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if PLATFORM_TOOLS_MAC
|
||||||
|
#include "Platform/Mac/MacPlatformTools.h"
|
||||||
|
#include "Engine/Platform/Mac/MacPlatformSettings.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace GameCookerImpl
|
namespace GameCookerImpl
|
||||||
{
|
{
|
||||||
@@ -129,6 +133,8 @@ const Char* ToString(const BuildPlatform platform)
|
|||||||
return TEXT("Switch");
|
return TEXT("Switch");
|
||||||
case BuildPlatform::PS5:
|
case BuildPlatform::PS5:
|
||||||
return TEXT("PlayStation 5");
|
return TEXT("PlayStation 5");
|
||||||
|
case BuildPlatform::MacOSx64:
|
||||||
|
return TEXT("Mac x64");
|
||||||
default:
|
default:
|
||||||
return TEXT("?");
|
return TEXT("?");
|
||||||
}
|
}
|
||||||
@@ -325,6 +331,11 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
|
|||||||
case BuildPlatform::PS5:
|
case BuildPlatform::PS5:
|
||||||
result = New<PS5PlatformTools>();
|
result = New<PS5PlatformTools>();
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#if PLATFORM_TOOLS_MAC
|
||||||
|
case BuildPlatform::MacOSx64:
|
||||||
|
result = New<MacPlatformTools>(ArchitectureType::x64);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Tools.Add(platform, result);
|
Tools.Add(platform, result);
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ namespace FlaxEditor
|
|||||||
case BuildPlatform.AndroidARM64: return PlatformType.Android;
|
case BuildPlatform.AndroidARM64: return PlatformType.Android;
|
||||||
case BuildPlatform.XboxScarlett: return PlatformType.XboxScarlett;
|
case BuildPlatform.XboxScarlett: return PlatformType.XboxScarlett;
|
||||||
case BuildPlatform.Switch: return PlatformType.Switch;
|
case BuildPlatform.Switch: return PlatformType.Switch;
|
||||||
|
case BuildPlatform.MacOSx64: return PlatformType.Mac;
|
||||||
default: throw new ArgumentOutOfRangeException(nameof(buildPlatform), buildPlatform, null);
|
default: throw new ArgumentOutOfRangeException(nameof(buildPlatform), buildPlatform, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,6 +186,10 @@ bool CompileScriptsStep::Perform(CookingData& data)
|
|||||||
platform = TEXT("PS5");
|
platform = TEXT("PS5");
|
||||||
architecture = TEXT("x64");
|
architecture = TEXT("x64");
|
||||||
break;
|
break;
|
||||||
|
case BuildPlatform::MacOSx64:
|
||||||
|
platform = TEXT("Mac");
|
||||||
|
architecture = TEXT("x64");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(Error, "Unknown or unsupported build platform.");
|
LOG(Error, "Unknown or unsupported build platform.");
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -61,8 +61,16 @@ public class Editor : EditorModule
|
|||||||
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "XboxScarlett", "PLATFORM_TOOLS_XBOX_SCARLETT", "PLATFORM_TOOLS_GDK");
|
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "XboxScarlett", "PLATFORM_TOOLS_XBOX_SCARLETT", "PLATFORM_TOOLS_GDK");
|
||||||
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Android", "PLATFORM_TOOLS_ANDROID");
|
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Android", "PLATFORM_TOOLS_ANDROID");
|
||||||
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Switch", "PLATFORM_TOOLS_SWITCH");
|
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Switch", "PLATFORM_TOOLS_SWITCH");
|
||||||
|
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Linux", "PLATFORM_TOOLS_LINUX");
|
||||||
|
}
|
||||||
|
else if (options.Platform.Target == TargetPlatform.Linux)
|
||||||
|
{
|
||||||
|
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Linux", "PLATFORM_TOOLS_LINUX");
|
||||||
|
}
|
||||||
|
else if (options.Platform.Target == TargetPlatform.Mac)
|
||||||
|
{
|
||||||
|
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Mac", "PLATFORM_TOOLS_MAC");
|
||||||
}
|
}
|
||||||
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Linux", "PLATFORM_TOOLS_LINUX");
|
|
||||||
|
|
||||||
// Visual Studio integration
|
// Visual Studio integration
|
||||||
if (options.Platform.Target == TargetPlatform.Windows && Flax.Build.Platform.BuildTargetPlatform == TargetPlatform.Windows)
|
if (options.Platform.Target == TargetPlatform.Windows && Flax.Build.Platform.BuildTargetPlatform == TargetPlatform.Windows)
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ namespace FlaxEditor.GUI
|
|||||||
new PlatformData(PlatformType.Android, icons.AndroidIcon128, "Android"),
|
new PlatformData(PlatformType.Android, icons.AndroidIcon128, "Android"),
|
||||||
new PlatformData(PlatformType.Switch, icons.SwitchIcon128, "Switch"),
|
new PlatformData(PlatformType.Switch, icons.SwitchIcon128, "Switch"),
|
||||||
new PlatformData(PlatformType.PS5, icons.PS5Icon128, "PlayStation 5"),
|
new PlatformData(PlatformType.PS5, icons.PS5Icon128, "PlayStation 5"),
|
||||||
|
new PlatformData(PlatformType.Mac, icons.Flax64, "Mac"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const float IconSize = 64.0f;
|
const float IconSize = 64.0f;
|
||||||
|
|||||||
@@ -945,6 +945,7 @@ namespace FlaxEditor.Modules
|
|||||||
Proxy.Add(new SettingsProxy(typeof(UWPPlatformSettings), Editor.Instance.Icons.UWPSettings128));
|
Proxy.Add(new SettingsProxy(typeof(UWPPlatformSettings), Editor.Instance.Icons.UWPSettings128));
|
||||||
Proxy.Add(new SettingsProxy(typeof(LinuxPlatformSettings), Editor.Instance.Icons.LinuxSettings128));
|
Proxy.Add(new SettingsProxy(typeof(LinuxPlatformSettings), Editor.Instance.Icons.LinuxSettings128));
|
||||||
Proxy.Add(new SettingsProxy(typeof(AndroidPlatformSettings), Editor.Instance.Icons.AndroidSettings128));
|
Proxy.Add(new SettingsProxy(typeof(AndroidPlatformSettings), Editor.Instance.Icons.AndroidSettings128));
|
||||||
|
Proxy.Add(new SettingsProxy(typeof(MacPlatformSettings), Editor.Instance.Icons.Document128));
|
||||||
|
|
||||||
var typePS4PlatformSettings = TypeUtils.GetManagedType(GameSettings.PS4PlatformSettingsTypename);
|
var typePS4PlatformSettings = TypeUtils.GetManagedType(GameSettings.PS4PlatformSettingsTypename);
|
||||||
if (typePS4PlatformSettings != null)
|
if (typePS4PlatformSettings != null)
|
||||||
|
|||||||
@@ -1342,13 +1342,13 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
},
|
},
|
||||||
new NodeArchetype
|
new NodeArchetype
|
||||||
{
|
{
|
||||||
TypeID = 17,
|
TypeID = 18,
|
||||||
Title = "Platform Switch",
|
Title = "Platform Switch",
|
||||||
Description = "Gets the input value based on the runtime-platform type",
|
Description = "Gets the input value based on the runtime-platform type",
|
||||||
Flags = NodeFlags.AllGraphs,
|
Flags = NodeFlags.AllGraphs,
|
||||||
Size = new Vector2(220, 200),
|
Size = new Vector2(220, 200),
|
||||||
ConnectionsHints = ConnectionsHint.Value,
|
ConnectionsHints = ConnectionsHint.Value,
|
||||||
IndependentBoxes = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
|
IndependentBoxes = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 },
|
||||||
DependentBoxes = new[] { 0 },
|
DependentBoxes = new[] { 0 },
|
||||||
Elements = new[]
|
Elements = new[]
|
||||||
{
|
{
|
||||||
@@ -1363,6 +1363,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
NodeElementArchetype.Factory.Input(7, "Android", true, null, 8),
|
NodeElementArchetype.Factory.Input(7, "Android", true, null, 8),
|
||||||
NodeElementArchetype.Factory.Input(8, "Switch", true, null, 9),
|
NodeElementArchetype.Factory.Input(8, "Switch", true, null, 9),
|
||||||
NodeElementArchetype.Factory.Input(9, "PlayStation 5", true, null, 10),
|
NodeElementArchetype.Factory.Input(9, "PlayStation 5", true, null, 10),
|
||||||
|
NodeElementArchetype.Factory.Input(10, "Mac", true, null, 11),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new NodeArchetype
|
new NodeArchetype
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ namespace FlaxEditor.Windows
|
|||||||
{ PlatformType.Android, new Android() },
|
{ PlatformType.Android, new Android() },
|
||||||
{ PlatformType.Switch, new Switch() },
|
{ PlatformType.Switch, new Switch() },
|
||||||
{ PlatformType.PS5, new PS5() },
|
{ PlatformType.PS5, new PS5() },
|
||||||
|
{ PlatformType.Mac, new Mac() },
|
||||||
};
|
};
|
||||||
|
|
||||||
public BuildTabProxy(GameCookerWindow win, PlatformSelector platformSelector)
|
public BuildTabProxy(GameCookerWindow win, PlatformSelector platformSelector)
|
||||||
@@ -61,6 +62,7 @@ namespace FlaxEditor.Windows
|
|||||||
PerPlatformOptions[PlatformType.Android].Init("Output/Android", "Android");
|
PerPlatformOptions[PlatformType.Android].Init("Output/Android", "Android");
|
||||||
PerPlatformOptions[PlatformType.Switch].Init("Output/Switch", "Switch");
|
PerPlatformOptions[PlatformType.Switch].Init("Output/Switch", "Switch");
|
||||||
PerPlatformOptions[PlatformType.PS5].Init("Output/PS5", "PS5");
|
PerPlatformOptions[PlatformType.PS5].Init("Output/PS5", "PS5");
|
||||||
|
PerPlatformOptions[PlatformType.Mac].Init("Output/Mac", "Mac");
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Platform
|
abstract class Platform
|
||||||
@@ -102,7 +104,15 @@ namespace FlaxEditor.Windows
|
|||||||
|
|
||||||
// Check if can build on that platform
|
// Check if can build on that platform
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
IsSupported = true;
|
switch (BuildPlatform)
|
||||||
|
{
|
||||||
|
case BuildPlatform.MacOSx64:
|
||||||
|
IsSupported = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
IsSupported = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
#elif PLATFORM_LINUX
|
#elif PLATFORM_LINUX
|
||||||
switch (BuildPlatform)
|
switch (BuildPlatform)
|
||||||
{
|
{
|
||||||
@@ -202,6 +212,11 @@ namespace FlaxEditor.Windows
|
|||||||
protected override BuildPlatform BuildPlatform => BuildPlatform.PS5;
|
protected override BuildPlatform BuildPlatform => BuildPlatform.PS5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Mac : Platform
|
||||||
|
{
|
||||||
|
protected override BuildPlatform BuildPlatform => BuildPlatform.MacOSx64;
|
||||||
|
}
|
||||||
|
|
||||||
class Editor : CustomEditor
|
class Editor : CustomEditor
|
||||||
{
|
{
|
||||||
private PlatformType _platform;
|
private PlatformType _platform;
|
||||||
@@ -249,6 +264,9 @@ namespace FlaxEditor.Windows
|
|||||||
case PlatformType.PS5:
|
case PlatformType.PS5:
|
||||||
name = "PlayStation 5";
|
name = "PlayStation 5";
|
||||||
break;
|
break;
|
||||||
|
case PlatformType.Mac:
|
||||||
|
name = "Mac";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
name = CustomEditorsUtil.GetPropertyNameUI(_platform.ToString());
|
name = CustomEditorsUtil.GetPropertyNameUI(_platform.ToString());
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ public class Audio : EngineModule
|
|||||||
options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "PS5", "Engine", "Audio"));
|
options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "PS5", "Engine", "Audio"));
|
||||||
options.CompileEnv.PreprocessorDefinitions.Add("AUDIO_API_PS5");
|
options.CompileEnv.PreprocessorDefinitions.Add("AUDIO_API_PS5");
|
||||||
break;
|
break;
|
||||||
|
case TargetPlatform.Mac:
|
||||||
|
useNone = true; // TODO: Audio support on Mac
|
||||||
|
break;
|
||||||
default: throw new InvalidPlatformException(options.Platform.Target);
|
default: throw new InvalidPlatformException(options.Platform.Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ IMPLEMENT_SETTINGS_GETTER(XboxScarlettPlatformSettings, XboxScarlettPlatform);
|
|||||||
IMPLEMENT_SETTINGS_GETTER(AndroidPlatformSettings, AndroidPlatform);
|
IMPLEMENT_SETTINGS_GETTER(AndroidPlatformSettings, AndroidPlatform);
|
||||||
#elif PLATFORM_SWITCH
|
#elif PLATFORM_SWITCH
|
||||||
IMPLEMENT_SETTINGS_GETTER(SwitchPlatformSettings, SwitchPlatform);
|
IMPLEMENT_SETTINGS_GETTER(SwitchPlatformSettings, SwitchPlatform);
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
IMPLEMENT_SETTINGS_GETTER(MacPlatformSettings, MacPlatform);
|
||||||
#else
|
#else
|
||||||
#error Unknown platform
|
#error Unknown platform
|
||||||
#endif
|
#endif
|
||||||
@@ -226,6 +228,7 @@ void GameSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* mo
|
|||||||
DESERIALIZE(AndroidPlatform);
|
DESERIALIZE(AndroidPlatform);
|
||||||
DESERIALIZE(SwitchPlatform);
|
DESERIALIZE(SwitchPlatform);
|
||||||
DESERIALIZE(PS5Platform);
|
DESERIALIZE(PS5Platform);
|
||||||
|
DESERIALIZE(MacPlatform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayersAndTagsSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
void LayersAndTagsSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||||
|
|||||||
@@ -177,6 +177,14 @@ namespace FlaxEditor.Content.Settings
|
|||||||
public JsonAsset PS5Platform;
|
public JsonAsset PS5Platform;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if FLAX_EDITOR || PLATFORM_MAC
|
||||||
|
/// <summary>
|
||||||
|
/// Reference to <see cref="MacPlatformSettings"/> asset. Used to apply configuration on Mac platform.
|
||||||
|
/// </summary>
|
||||||
|
[EditorOrder(2090), EditorDisplay("Platform Settings", "Mac"), AssetReference(typeof(MacPlatformSettings), true), Tooltip("Reference to Mac Platform Settings asset")]
|
||||||
|
public JsonAsset MacPlatform;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the absolute path to the game settings asset file.
|
/// Gets the absolute path to the game settings asset file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -295,6 +303,10 @@ namespace FlaxEditor.Content.Settings
|
|||||||
if (type.FullName == PS5PlatformSettingsTypename)
|
if (type.FullName == PS5PlatformSettingsTypename)
|
||||||
return LoadAsset(gameSettings.PS5Platform, PS5PlatformSettingsTypename) as T;
|
return LoadAsset(gameSettings.PS5Platform, PS5PlatformSettingsTypename) as T;
|
||||||
#endif
|
#endif
|
||||||
|
#if FLAX_EDITOR || PLATFORM_MAC
|
||||||
|
if (type == typeof(MacPlatformSettings))
|
||||||
|
return LoadAsset<MacPlatformSettings>(gameSettings.MacPlatform) as T;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (gameSettings.CustomSettings != null)
|
if (gameSettings.CustomSettings != null)
|
||||||
{
|
{
|
||||||
@@ -391,6 +403,8 @@ namespace FlaxEditor.Content.Settings
|
|||||||
return SaveAsset(gameSettings, ref gameSettings.PS5Platform, obj);
|
return SaveAsset(gameSettings, ref gameSettings.PS5Platform, obj);
|
||||||
if (type == typeof(AudioSettings))
|
if (type == typeof(AudioSettings))
|
||||||
return SaveAsset(gameSettings, ref gameSettings.Audio, obj);
|
return SaveAsset(gameSettings, ref gameSettings.Audio, obj);
|
||||||
|
if (type == typeof(MacPlatformSettings))
|
||||||
|
return SaveAsset(gameSettings, ref gameSettings.MacPlatform, obj);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ public:
|
|||||||
Guid AndroidPlatform;
|
Guid AndroidPlatform;
|
||||||
Guid SwitchPlatform;
|
Guid SwitchPlatform;
|
||||||
Guid PS5Platform;
|
Guid PS5Platform;
|
||||||
|
Guid MacPlatform;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -32,3 +32,6 @@
|
|||||||
#if PLATFORM_PS5
|
#if PLATFORM_PS5
|
||||||
#include "Platforms/PS5/Engine/Platform/PS5PlatformSettings.h"
|
#include "Platforms/PS5/Engine/Platform/PS5PlatformSettings.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
#include "Engine/Platform/Mac/MacPlatformSettings.h"
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
#include "Android/AndroidGame.h"
|
#include "Android/AndroidGame.h"
|
||||||
#elif PLATFORM_SWITCH
|
#elif PLATFORM_SWITCH
|
||||||
#include "Platforms/Switch/Engine/Engine/SwitchGame.h"
|
#include "Platforms/Switch/Engine/Engine/SwitchGame.h"
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
#include "Mac/MacGame.h"
|
||||||
#else
|
#else
|
||||||
#error Missing Game implementation!
|
#error Missing Game implementation!
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
19
Source/Engine/Engine/Mac/MacGame.h
Normal file
19
Source/Engine/Engine/Mac/MacGame.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC && !USE_EDITOR
|
||||||
|
|
||||||
|
#include "../Base/GameBase.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The game class implementation for Mac platform.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="Game" />
|
||||||
|
class MacGame : public GameBase
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef MacGame Game;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -81,6 +81,9 @@ public class Graphics : EngineModule
|
|||||||
case TargetPlatform.Switch:
|
case TargetPlatform.Switch:
|
||||||
options.PrivateDependencies.Add("GraphicsDeviceVulkan");
|
options.PrivateDependencies.Add("GraphicsDeviceVulkan");
|
||||||
break;
|
break;
|
||||||
|
case TargetPlatform.Mac:
|
||||||
|
options.PrivateDependencies.Add("GraphicsDeviceNull"); // TODO: Graphics support on Mac
|
||||||
|
break;
|
||||||
default: throw new InvalidPlatformException(options.Platform.Target);
|
default: throw new InvalidPlatformException(options.Platform.Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
24
Source/Engine/Main/Mac/main.cpp
Normal file
24
Source/Engine/Main/Mac/main.cpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "Engine/Engine/Engine.h"
|
||||||
|
#include "Engine/Core/Types/StringBuilder.h"
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
// Join the arguments
|
||||||
|
StringBuilder args;
|
||||||
|
for (int i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
args.Append(argv[i]);
|
||||||
|
|
||||||
|
if (i + 1 != argc)
|
||||||
|
args.Append(TEXT(' '));
|
||||||
|
}
|
||||||
|
args.Append(TEXT('\0'));
|
||||||
|
|
||||||
|
return Engine::Main(*args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -72,6 +72,9 @@ public class Main : EngineModule
|
|||||||
case TargetPlatform.Switch:
|
case TargetPlatform.Switch:
|
||||||
options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "Main"));
|
options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "Main"));
|
||||||
break;
|
break;
|
||||||
|
case TargetPlatform.Mac:
|
||||||
|
options.SourcePaths.Add(Path.Combine(FolderPath, "Mac"));
|
||||||
|
break;
|
||||||
default: throw new InvalidPlatformException(options.Platform.Target);
|
default: throw new InvalidPlatformException(options.Platform.Target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -614,6 +614,8 @@ const Char* ToString(PlatformType type)
|
|||||||
return TEXT("Switch");
|
return TEXT("Switch");
|
||||||
case PlatformType::PS5:
|
case PlatformType::PS5:
|
||||||
return TEXT("PlayStation 5");
|
return TEXT("PlayStation 5");
|
||||||
|
case PlatformType::Mac:
|
||||||
|
return TEXT("Mac");
|
||||||
default:
|
default:
|
||||||
return TEXT("");
|
return TEXT("");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS || PLATFORM_UWP || PLATFORM_XBOX_ONE || PLATFORM_XBOX_SCARLETT
|
||||||
#include "Win32/Win32CriticalSection.h"
|
#include "Win32/Win32CriticalSection.h"
|
||||||
#elif PLATFORM_UWP
|
#elif PLATFORM_LINUX || PLATFORM_ANDROID || PLATFORM_PS4 || PLATFORM_PS5
|
||||||
#include "Win32/Win32CriticalSection.h"
|
|
||||||
#elif PLATFORM_LINUX
|
|
||||||
#include "Unix/UnixCriticalSection.h"
|
|
||||||
#elif PLATFORM_PS4
|
|
||||||
#include "Unix/UnixCriticalSection.h"
|
|
||||||
#elif PLATFORM_PS5
|
|
||||||
#include "Unix/UnixCriticalSection.h"
|
|
||||||
#elif PLATFORM_XBOX_ONE
|
|
||||||
#include "Win32/Win32CriticalSection.h"
|
|
||||||
#elif PLATFORM_XBOX_SCARLETT
|
|
||||||
#include "Win32/Win32CriticalSection.h"
|
|
||||||
#elif PLATFORM_ANDROID
|
|
||||||
#include "Unix/UnixCriticalSection.h"
|
#include "Unix/UnixCriticalSection.h"
|
||||||
#elif PLATFORM_SWITCH
|
#elif PLATFORM_SWITCH
|
||||||
#include "Platforms/Switch/Engine/Platform/SwitchCriticalSection.h"
|
#include "Platforms/Switch/Engine/Platform/SwitchCriticalSection.h"
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ API_ENUM() enum class PlatformType
|
|||||||
/// Running on PlayStation 5.
|
/// Running on PlayStation 5.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
PS5 = 9,
|
PS5 = 9,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Running on Mac.
|
||||||
|
/// </summary>
|
||||||
|
Mac = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -120,9 +125,6 @@ API_ENUM() enum class ArchitectureType
|
|||||||
#if !defined(PLATFORM_MAC)
|
#if !defined(PLATFORM_MAC)
|
||||||
#define PLATFORM_MAC 0
|
#define PLATFORM_MAC 0
|
||||||
#endif
|
#endif
|
||||||
#if !defined(PLATFORM_OSX)
|
|
||||||
#define PLATFORM_OSX 0
|
|
||||||
#endif
|
|
||||||
#if !defined(PLATFORM_IOS)
|
#if !defined(PLATFORM_IOS)
|
||||||
#define PLATFORM_IOS 0
|
#define PLATFORM_IOS 0
|
||||||
#endif
|
#endif
|
||||||
@@ -148,6 +150,8 @@ API_ENUM() enum class ArchitectureType
|
|||||||
#include "Android/AndroidDefines.h"
|
#include "Android/AndroidDefines.h"
|
||||||
#elif PLATFORM_SWITCH
|
#elif PLATFORM_SWITCH
|
||||||
#include "Platforms/Switch/Engine/Platform/SwitchDefines.h"
|
#include "Platforms/Switch/Engine/Platform/SwitchDefines.h"
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
#include "Mac/MacDefines.h"
|
||||||
#else
|
#else
|
||||||
#error Missing Defines implementation!
|
#error Missing Defines implementation!
|
||||||
#endif
|
#endif
|
||||||
@@ -189,7 +193,7 @@ API_ENUM() enum class ArchitectureType
|
|||||||
#define PLATFORM_WINDOWS_FAMILY (PLATFORM_WINDOWS || PLATFORM_UWP || PLATFORM_XBOX_ONE || PLATFORM_XBOX_SCARLETT)
|
#define PLATFORM_WINDOWS_FAMILY (PLATFORM_WINDOWS || PLATFORM_UWP || PLATFORM_XBOX_ONE || PLATFORM_XBOX_SCARLETT)
|
||||||
#define PLATFORM_MICROSOFT_FAMILY (PLATFORM_WINDOWS_FAMILY)
|
#define PLATFORM_MICROSOFT_FAMILY (PLATFORM_WINDOWS_FAMILY)
|
||||||
#define PLATFORM_UNIX_FAMILY (PLATFORM_LINUX || PLATFORM_ANDROID || PLATFORM_PS4 || PLATFORM_PS5)
|
#define PLATFORM_UNIX_FAMILY (PLATFORM_LINUX || PLATFORM_ANDROID || PLATFORM_PS4 || PLATFORM_PS5)
|
||||||
#define PLATFORM_APPLE_FAMILY (PLATFORM_IOS || PLATFORM_OSX)
|
#define PLATFORM_APPLE_FAMILY (PLATFORM_MAC || PLATFORM_IOS)
|
||||||
|
|
||||||
// SIMD defines
|
// SIMD defines
|
||||||
#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) || defined(__SSE2__)
|
#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) || defined(__SSE2__)
|
||||||
|
|||||||
@@ -2,24 +2,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS || PLATFORM_UWP || PLATFORM_XBOX_ONE || PLATFORM_XBOX_SCARLETT
|
||||||
#include "Win32/Win32File.h"
|
#include "Win32/Win32File.h"
|
||||||
#elif PLATFORM_UWP
|
#elif PLATFORM_LINUX || PLATFORM_PS4 || PLATFORM_PS5
|
||||||
#include "Win32/Win32File.h"
|
|
||||||
#elif PLATFORM_LINUX
|
|
||||||
#include "Unix/UnixFile.h"
|
#include "Unix/UnixFile.h"
|
||||||
#elif PLATFORM_PS4
|
|
||||||
#include "Unix/UnixFile.h"
|
|
||||||
#elif PLATFORM_PS5
|
|
||||||
#include "Unix/UnixFile.h"
|
|
||||||
#elif PLATFORM_XBOX_ONE
|
|
||||||
#include "Win32/Win32File.h"
|
|
||||||
#elif PLATFORM_XBOX_SCARLETT
|
|
||||||
#include "Win32/Win32File.h"
|
|
||||||
#elif PLATFORM_ANDROID
|
#elif PLATFORM_ANDROID
|
||||||
#include "Android/AndroidFile.h"
|
#include "Android/AndroidFile.h"
|
||||||
#elif PLATFORM_SWITCH
|
#elif PLATFORM_SWITCH
|
||||||
#include "Platforms/Switch/Engine/Platform/SwitchFile.h"
|
#include "Platforms/Switch/Engine/Platform/SwitchFile.h"
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
#include "Mac/MacFile.h"
|
||||||
#else
|
#else
|
||||||
#error Missing File implementation!
|
#error Missing File implementation!
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#include "Android/AndroidFileSystem.h"
|
#include "Android/AndroidFileSystem.h"
|
||||||
#elif PLATFORM_SWITCH
|
#elif PLATFORM_SWITCH
|
||||||
#include "Platforms/Switch/Engine/Platform/SwitchFileSystem.h"
|
#include "Platforms/Switch/Engine/Platform/SwitchFileSystem.h"
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
#include "Mac/MacFileSystem.h"
|
||||||
#else
|
#else
|
||||||
#error Missing File System implementation!
|
#error Missing File System implementation!
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
91
Source/Engine/Platform/Mac/MacConditionVariable.h
Normal file
91
Source/Engine/Platform/Mac/MacConditionVariable.h
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "MacCriticalSection.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mac implementation of a condition variables. Condition variables are synchronization primitives that enable threads to wait until a particular condition occurs. Condition variables enable threads to atomically release a lock and enter the sleeping state.
|
||||||
|
/// </summary>
|
||||||
|
class FLAXENGINE_API MacConditionVariable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
pthread_cond_t _cond;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
MacConditionVariable(const MacConditionVariable&);
|
||||||
|
MacConditionVariable& operator=(const MacConditionVariable&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MacConditionVariable"/> class.
|
||||||
|
/// </summary>
|
||||||
|
MacConditionVariable()
|
||||||
|
{
|
||||||
|
pthread_cond_init(&_cond, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalizes an instance of the <see cref="MacConditionVariable"/> class.
|
||||||
|
/// </summary>
|
||||||
|
~MacConditionVariable()
|
||||||
|
{
|
||||||
|
pthread_cond_destroy(&_cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Blocks the current thread execution until the condition variable is woken up.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lock">The critical section locked by the current thread.</param>
|
||||||
|
void Wait(const MacCriticalSection& lock)
|
||||||
|
{
|
||||||
|
pthread_cond_wait(&_cond, lock._mutexPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Blocks the current thread execution until the condition variable is woken up or after the specified timeout duration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lock">The critical section locked by the current thread.</param>
|
||||||
|
/// <param name="timeout">The time-out interval, in milliseconds. If the time-out interval elapses, the function re-acquires the critical section and returns zero. If timeout is zero, the function tests the states of the specified objects and returns immediately. If timeout is INFINITE, the function's time-out interval never elapses.</param>
|
||||||
|
/// <returns>If the function succeeds, the return value is true, otherwise, if the function fails or the time-out interval elapses, the return value is false.</returns>
|
||||||
|
bool Wait(const MacCriticalSection& lock, const int32 timeout)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
ts.tv_sec = time(NULL) + timeout / 1000;
|
||||||
|
ts.tv_nsec = tv.tv_usec * 1000 + 1000 * 1000 * (timeout % 1000);
|
||||||
|
ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
|
||||||
|
ts.tv_nsec %= (1000 * 1000 * 1000);
|
||||||
|
|
||||||
|
return pthread_cond_timedwait(&_cond, lock._mutexPtr, &ts) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies one waiting thread.
|
||||||
|
/// </summary>
|
||||||
|
void NotifyOne()
|
||||||
|
{
|
||||||
|
pthread_cond_signal(&_cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies all waiting threads.
|
||||||
|
/// </summary>
|
||||||
|
void NotifyAll()
|
||||||
|
{
|
||||||
|
pthread_cond_broadcast(&_cond);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
92
Source/Engine/Platform/Mac/MacCriticalSection.h
Normal file
92
Source/Engine/Platform/Mac/MacCriticalSection.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "Engine/Platform/Platform.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
class MacConditionVariable;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mac implementation of a critical section.
|
||||||
|
/// </summary>
|
||||||
|
class FLAXENGINE_API MacCriticalSection
|
||||||
|
{
|
||||||
|
friend MacConditionVariable;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
pthread_mutex_t _mutex;
|
||||||
|
pthread_mutex_t* _mutexPtr;
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
pthread_t _owningThreadId;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
MacCriticalSection(const MacCriticalSection&);
|
||||||
|
MacCriticalSection& operator=(const MacCriticalSection&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MacCriticalSection"/> class.
|
||||||
|
/// </summary>
|
||||||
|
MacCriticalSection()
|
||||||
|
{
|
||||||
|
pthread_mutexattr_t attributes;
|
||||||
|
pthread_mutexattr_init(&attributes);
|
||||||
|
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
pthread_mutex_init(&_mutex, &attributes);
|
||||||
|
pthread_mutexattr_destroy(&attributes);
|
||||||
|
_mutexPtr = &_mutex;
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
_owningThreadId = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalizes an instance of the <see cref="MacCriticalSection"/> class.
|
||||||
|
/// </summary>
|
||||||
|
~MacCriticalSection()
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy(&_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Locks the critical section.
|
||||||
|
/// </summary>
|
||||||
|
void Lock() const
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(_mutexPtr);
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
((MacCriticalSection*)this)->_owningThreadId = pthread_self();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to enter a critical section without blocking. If the call is successful, the calling thread takes ownership of the critical section.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if calling thread took ownership of the critical section.</returns>
|
||||||
|
bool TryLock() const
|
||||||
|
{
|
||||||
|
return pthread_mutex_trylock(_mutexPtr) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the lock on the critical section.
|
||||||
|
/// </summary>
|
||||||
|
void Unlock() const
|
||||||
|
{
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
((MacCriticalSection*)this)->_owningThreadId = 0;
|
||||||
|
#endif
|
||||||
|
pthread_mutex_unlock(_mutexPtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
19
Source/Engine/Platform/Mac/MacDefines.h
Normal file
19
Source/Engine/Platform/Mac/MacDefines.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
// Platform description
|
||||||
|
#define PLATFORM_64BITS 1
|
||||||
|
#define PLATFORM_ARCH_X64 1
|
||||||
|
#define PLATFORM_ARCH ArchitectureType::x64
|
||||||
|
#define PLATFORM_TYPE PlatformType::Mac
|
||||||
|
#define PLATFORM_DESKTOP 1
|
||||||
|
#define PLATFORM_CACHE_LINE_SIZE 128
|
||||||
|
#define PLATFORM_HAS_HEADLESS_MODE 1
|
||||||
|
#define PLATFORM_DEBUG_BREAK __builtin_trap()
|
||||||
|
#define PLATFORM_LINE_TERMINATOR "\n"
|
||||||
|
#define PLATFORM_TEXT_IS_CHAR16 1
|
||||||
|
|
||||||
|
#endif
|
||||||
156
Source/Engine/Platform/Mac/MacFile.cpp
Normal file
156
Source/Engine/Platform/Mac/MacFile.cpp
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "../File.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
|
#include "Engine/Core/Types/String.h"
|
||||||
|
#include "Engine/Core/Types/DateTime.h"
|
||||||
|
#include "Engine/Core/Types/TimeSpan.h"
|
||||||
|
#include "Engine/Utilities/StringConverter.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <cerrno>
|
||||||
|
|
||||||
|
MacFile::MacFile(int32 handle)
|
||||||
|
: _handle(handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MacFile::~MacFile()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
MacFile* MacFile::Open(const StringView& path, FileMode mode, FileAccess access, FileShare share)
|
||||||
|
{
|
||||||
|
int flags = O_CLOEXEC;
|
||||||
|
switch (access)
|
||||||
|
{
|
||||||
|
case FileAccess::Read:
|
||||||
|
flags |= O_RDONLY;
|
||||||
|
break;
|
||||||
|
case FileAccess::Write:
|
||||||
|
flags |= O_WRONLY;
|
||||||
|
break;
|
||||||
|
case FileAccess::ReadWrite:
|
||||||
|
flags |= O_RDWR;
|
||||||
|
break;
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case FileMode::CreateAlways:
|
||||||
|
flags |= O_CREAT | O_TRUNC;
|
||||||
|
break;
|
||||||
|
case FileMode::CreateNew:
|
||||||
|
flags |= O_CREAT | O_EXCL;
|
||||||
|
break;
|
||||||
|
case FileMode::OpenAlways:
|
||||||
|
break;
|
||||||
|
case FileMode::OpenExisting:
|
||||||
|
break;
|
||||||
|
case FileMode::TruncateExisting:
|
||||||
|
flags |= O_TRUNC;
|
||||||
|
break;
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
mode_t omode = S_IRUSR | S_IWUSR;
|
||||||
|
if ((uint32)share & (uint32)FileShare::Delete)
|
||||||
|
omode |= 0;
|
||||||
|
if ((uint32)share & (uint32)FileShare::Read)
|
||||||
|
omode |= (mode_t)(S_IRGRP | S_IROTH);
|
||||||
|
if ((uint32)share & (uint32)FileShare::Write)
|
||||||
|
omode |= (mode_t)(S_IWGRP | S_IWOTH);
|
||||||
|
if ((uint32)share & (uint32)FileShare::Delete)
|
||||||
|
omode |= 0;
|
||||||
|
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
auto handle = open(pathANSI.Get(), flags, omode);
|
||||||
|
if (handle == -1)
|
||||||
|
{
|
||||||
|
LOG_Mac_LAST_ERROR;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return New<MacFile>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFile::Read(void* buffer, uint32 bytesToRead, uint32* bytesRead)
|
||||||
|
{
|
||||||
|
const ssize_t tmp = read(_handle, buffer, bytesToRead);
|
||||||
|
if (tmp != -1)
|
||||||
|
{
|
||||||
|
if (bytesRead)
|
||||||
|
*bytesRead = tmp;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bytesRead)
|
||||||
|
*bytesRead = 0;
|
||||||
|
LOG_Mac_LAST_ERROR;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFile::Write(const void* buffer, uint32 bytesToWrite, uint32* bytesWritten)
|
||||||
|
{
|
||||||
|
const ssize_t tmp = write(_handle, buffer, bytesToWrite);
|
||||||
|
if (tmp != -1)
|
||||||
|
{
|
||||||
|
if (bytesWritten)
|
||||||
|
*bytesWritten = tmp;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bytesWritten)
|
||||||
|
*bytesWritten = 0;
|
||||||
|
LOG_Mac_LAST_ERROR;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacFile::Close()
|
||||||
|
{
|
||||||
|
if (_handle != -1)
|
||||||
|
{
|
||||||
|
close(_handle);
|
||||||
|
_handle = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 MacFile::GetSize() const
|
||||||
|
{
|
||||||
|
struct stat fileInfo;
|
||||||
|
fstat(_handle, &fileInfo);
|
||||||
|
return fileInfo.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime MacFile::GetLastWriteTime() const
|
||||||
|
{
|
||||||
|
struct stat fileInfo;
|
||||||
|
if (fstat(_handle, &fileInfo) == -1)
|
||||||
|
{
|
||||||
|
return DateTime::MinValue();
|
||||||
|
}
|
||||||
|
const TimeSpan timeSinceEpoch(0, 0, fileInfo.st_mtime);
|
||||||
|
const DateTime MacEpoch(1970, 1, 1);
|
||||||
|
return MacEpoch + timeSinceEpoch;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 MacFile::GetPosition() const
|
||||||
|
{
|
||||||
|
return lseek(_handle, 0, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacFile::SetPosition(uint32 seek)
|
||||||
|
{
|
||||||
|
lseek(_handle, seek, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFile::IsOpened() const
|
||||||
|
{
|
||||||
|
return _handle != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
56
Source/Engine/Platform/Mac/MacFile.h
Normal file
56
Source/Engine/Platform/Mac/MacFile.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "Engine/Platform/Base/FileBase.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mac platform file object implementation.
|
||||||
|
/// </summary>
|
||||||
|
class MacFile : public FileBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int32 _handle;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MacFile"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handle">The handle.</param>
|
||||||
|
MacFile(int32 handle);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalizes an instance of the <see cref="MacFile"/> class.
|
||||||
|
/// </summary>
|
||||||
|
~MacFile();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates or opens a file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The name of the file to be created or opened.</param>
|
||||||
|
/// <param name="mode">An action to take on a file that exists or does not exist.</param>
|
||||||
|
/// <param name="access">The requested access to the file.</param>
|
||||||
|
/// <param name="share">The requested sharing mode of the file.</param>
|
||||||
|
/// <returns>Opened file handle or null if cannot.</returns>
|
||||||
|
static MacFile* Open(const StringView& path, FileMode mode, FileAccess access = FileAccess::ReadWrite, FileShare share = FileShare::None);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// [FileBase]
|
||||||
|
bool Read(void* buffer, uint32 bytesToRead, uint32* bytesRead = nullptr) override;
|
||||||
|
bool Write(const void* buffer, uint32 bytesToWrite, uint32* bytesWritten = nullptr) override;
|
||||||
|
void Close() override;
|
||||||
|
uint32 GetSize() const override;
|
||||||
|
DateTime GetLastWriteTime() const override;
|
||||||
|
uint32 GetPosition() const override;
|
||||||
|
void SetPosition(uint32 seek) override;
|
||||||
|
bool IsOpened() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
523
Source/Engine/Platform/Mac/MacFileSystem.cpp
Normal file
523
Source/Engine/Platform/Mac/MacFileSystem.cpp
Normal file
@@ -0,0 +1,523 @@
|
|||||||
|
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "MacFileSystem.h"
|
||||||
|
#include "Engine/Platform/File.h"
|
||||||
|
#include "Engine/Core/Types/String.h"
|
||||||
|
#include "Engine/Core/Types/StringView.h"
|
||||||
|
#include "Engine/Core/Types/TimeSpan.h"
|
||||||
|
#include "Engine/Core/Math/Math.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
|
#include "Engine/Utilities/StringConverter.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/sendfile.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
const DateTime UnixEpoch(1970, 1, 1);
|
||||||
|
|
||||||
|
bool MacFileSystem::CreateDirectory(const StringView& path)
|
||||||
|
{
|
||||||
|
const StringAsANSI<> pathAnsi(*path, path.Length());
|
||||||
|
|
||||||
|
// Skip if already exists
|
||||||
|
struct stat fileInfo;
|
||||||
|
if (stat(pathAnsi.Get(), &fileInfo) != -1 && S_ISDIR(fileInfo.st_mode))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively do it all again for the parent directory, if any
|
||||||
|
const int32 slashIndex = path.FindLast('/');
|
||||||
|
if (slashIndex > 1)
|
||||||
|
{
|
||||||
|
if (CreateDirectory(path.Substring(0, slashIndex)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the last directory on the path (the recursive calls will have taken care of the parent directories by now)
|
||||||
|
return mkdir(pathAnsi.Get(), 0755) != 0 && errno != EEXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeletePathTree(const char* path)
|
||||||
|
{
|
||||||
|
size_t pathLength;
|
||||||
|
DIR* dir;
|
||||||
|
struct stat statPath, statEntry;
|
||||||
|
struct dirent* entry;
|
||||||
|
|
||||||
|
// Stat for the path
|
||||||
|
stat(path, &statPath);
|
||||||
|
|
||||||
|
// If path does not exists or is not dir - exit with status -1
|
||||||
|
if (S_ISDIR(statPath.st_mode) == 0)
|
||||||
|
{
|
||||||
|
// Is not directory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not possible to read the directory for this user
|
||||||
|
if ((dir = opendir(path)) == NULL)
|
||||||
|
{
|
||||||
|
// Cannot open directory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The length of the path
|
||||||
|
pathLength = strlen(path);
|
||||||
|
|
||||||
|
// Iteration through entries in the directory
|
||||||
|
while ((entry = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
// Skip entries "." and ".."
|
||||||
|
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Determinate a full path of an entry
|
||||||
|
char full_path[256];
|
||||||
|
ASSERT(pathLength + strlen(entry->d_name) < ARRAY_COUNT(full_path));
|
||||||
|
strcpy(full_path, path);
|
||||||
|
strcat(full_path, "/");
|
||||||
|
strcat(full_path, entry->d_name);
|
||||||
|
|
||||||
|
// Stat for the entry
|
||||||
|
stat(full_path, &statEntry);
|
||||||
|
|
||||||
|
// Recursively remove a nested directory
|
||||||
|
if (S_ISDIR(statEntry.st_mode) != 0)
|
||||||
|
{
|
||||||
|
if (DeletePathTree(full_path))
|
||||||
|
return true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a file object
|
||||||
|
if (unlink(full_path) != 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the devastated directory and close the object of it
|
||||||
|
if (rmdir(path) != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::DeleteDirectory(const String& path, bool deleteContents)
|
||||||
|
{
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
if (deleteContents)
|
||||||
|
return DeletePathTree(pathANSI.Get());
|
||||||
|
return rmdir(pathANSI.Get()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::DirectoryExists(const StringView& path)
|
||||||
|
{
|
||||||
|
struct stat fileInfo;
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
if (stat(pathANSI.Get(), &fileInfo) != -1)
|
||||||
|
{
|
||||||
|
return S_ISDIR(fileInfo.st_mode);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::DirectoryGetFiles(Array<String>& results, const String& path, const Char* searchPattern, DirectorySearchOption option)
|
||||||
|
{
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
const StringAsANSI<> searchPatternANSI(searchPattern);
|
||||||
|
|
||||||
|
// Check if use only top directory
|
||||||
|
if (option == DirectorySearchOption::TopDirectoryOnly)
|
||||||
|
return getFilesFromDirectoryTop(results, pathANSI.Get(), searchPatternANSI.Get());
|
||||||
|
return getFilesFromDirectoryAll(results, pathANSI.Get(), searchPatternANSI.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::GetChildDirectories(Array<String>& results, const String& directory)
|
||||||
|
{
|
||||||
|
size_t pathLength;
|
||||||
|
DIR* dir;
|
||||||
|
struct stat statPath, statEntry;
|
||||||
|
struct dirent* entry;
|
||||||
|
const StringAsANSI<> pathANSI(*directory, directory.Length());
|
||||||
|
const char* path = pathANSI.Get();
|
||||||
|
|
||||||
|
// Stat for the path
|
||||||
|
stat(path, &statPath);
|
||||||
|
|
||||||
|
// If path does not exists or is not dir - exit with status -1
|
||||||
|
if (S_ISDIR(statPath.st_mode) == 0)
|
||||||
|
{
|
||||||
|
// Is not directory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not possible to read the directory for this user
|
||||||
|
if ((dir = opendir(path)) == NULL)
|
||||||
|
{
|
||||||
|
// Cannot open directory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The length of the path
|
||||||
|
pathLength = strlen(path);
|
||||||
|
|
||||||
|
// Iteration through entries in the directory
|
||||||
|
while ((entry = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
// Skip entries "." and ".."
|
||||||
|
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Determinate a full path of an entry
|
||||||
|
char full_path[256];
|
||||||
|
ASSERT(pathLength + strlen(entry->d_name) < ARRAY_COUNT(full_path));
|
||||||
|
strcpy(full_path, path);
|
||||||
|
strcat(full_path, "/");
|
||||||
|
strcat(full_path, entry->d_name);
|
||||||
|
|
||||||
|
// Stat for the entry
|
||||||
|
stat(full_path, &statEntry);
|
||||||
|
|
||||||
|
// Check for directory
|
||||||
|
if (S_ISDIR(statEntry.st_mode) != 0)
|
||||||
|
{
|
||||||
|
// Add directory
|
||||||
|
results.Add(String(full_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::FileExists(const StringView& path)
|
||||||
|
{
|
||||||
|
struct stat fileInfo;
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
if (stat(pathANSI.Get(), &fileInfo) != -1)
|
||||||
|
{
|
||||||
|
return S_ISREG(fileInfo.st_mode);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::DeleteFile(const StringView& path)
|
||||||
|
{
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
return unlink(pathANSI.Get()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 MacFileSystem::GetFileSize(const StringView& path)
|
||||||
|
{
|
||||||
|
struct stat fileInfo;
|
||||||
|
fileInfo.st_size = -1;
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
if (stat(pathANSI.Get(), &fileInfo) != -1)
|
||||||
|
{
|
||||||
|
// Check for directories
|
||||||
|
if (S_ISDIR(fileInfo.st_mode))
|
||||||
|
{
|
||||||
|
fileInfo.st_size = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileInfo.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::IsReadOnly(const StringView& path)
|
||||||
|
{
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
if (access(pathANSI.Get(), W_OK) == -1)
|
||||||
|
{
|
||||||
|
return errno == EACCES;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::SetReadOnly(const StringView& path, bool isReadOnly)
|
||||||
|
{
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
struct stat fileInfo;
|
||||||
|
if (stat(pathANSI.Get(), &fileInfo) != -1)
|
||||||
|
{
|
||||||
|
if (isReadOnly)
|
||||||
|
{
|
||||||
|
fileInfo.st_mode &= ~S_IWUSR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileInfo.st_mode |= S_IWUSR;
|
||||||
|
}
|
||||||
|
return chmod(pathANSI.Get(), fileInfo.st_mode) == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::MoveFile(const StringView& dst, const StringView& src, bool overwrite)
|
||||||
|
{
|
||||||
|
if (!overwrite && FileExists(dst))
|
||||||
|
{
|
||||||
|
// Already exists
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overwrite)
|
||||||
|
{
|
||||||
|
unlink(StringAsANSI<>(*dst, dst.Length()).Get());
|
||||||
|
}
|
||||||
|
if (rename(StringAsANSI<>(*src, src.Length()).Get(), StringAsANSI<>(*dst, dst.Length()).Get()) != 0)
|
||||||
|
{
|
||||||
|
if (errno == EXDEV)
|
||||||
|
{
|
||||||
|
if (!CopyFile(dst, src))
|
||||||
|
{
|
||||||
|
unlink(StringAsANSI<>(*src, src.Length()).Get());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::CopyFile(const StringView& dst, const StringView& src)
|
||||||
|
{
|
||||||
|
const StringAsANSI<> srcANSI(*src, src.Length());
|
||||||
|
const StringAsANSI<> dstANSI(*dst, dst.Length());
|
||||||
|
|
||||||
|
int srcFile, dstFile;
|
||||||
|
char buffer[4096];
|
||||||
|
ssize_t readSize;
|
||||||
|
int cachedError;
|
||||||
|
|
||||||
|
srcFile = open(srcANSI.Get(), O_RDONLY);
|
||||||
|
if (srcFile < 0)
|
||||||
|
return true;
|
||||||
|
dstFile = open(dstANSI.Get(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||||
|
if (dstFile < 0)
|
||||||
|
goto out_error;
|
||||||
|
|
||||||
|
// first try the kernel method
|
||||||
|
struct stat statBuf;
|
||||||
|
fstat(srcFile, &statBuf);
|
||||||
|
readSize = 1;
|
||||||
|
while (readSize > 0)
|
||||||
|
{
|
||||||
|
readSize = sendfile(dstFile, srcFile, 0, statBuf.st_size);
|
||||||
|
}
|
||||||
|
// sendfile could fail for example if the input file is not nmap'able
|
||||||
|
// in this case we fall back to the read/write loop
|
||||||
|
if (readSize < 0)
|
||||||
|
{
|
||||||
|
while (readSize = read(srcFile, buffer, sizeof(buffer)), readSize > 0)
|
||||||
|
{
|
||||||
|
char* ptr = buffer;
|
||||||
|
ssize_t writeSize;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
writeSize = write(dstFile, ptr, readSize);
|
||||||
|
if (writeSize >= 0)
|
||||||
|
{
|
||||||
|
readSize -= writeSize;
|
||||||
|
ptr += writeSize;
|
||||||
|
}
|
||||||
|
else if (errno != EINTR)
|
||||||
|
{
|
||||||
|
goto out_error;
|
||||||
|
}
|
||||||
|
} while (readSize > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readSize == 0)
|
||||||
|
{
|
||||||
|
if (close(dstFile) < 0)
|
||||||
|
{
|
||||||
|
dstFile = -1;
|
||||||
|
goto out_error;
|
||||||
|
}
|
||||||
|
close(srcFile);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_error:
|
||||||
|
cachedError = errno;
|
||||||
|
close(srcFile);
|
||||||
|
if (dstFile >= 0)
|
||||||
|
close(dstFile);
|
||||||
|
errno = cachedError;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::getFilesFromDirectoryTop(Array<String>& results, const char* path, const char* searchPattern)
|
||||||
|
{
|
||||||
|
size_t pathLength;
|
||||||
|
struct stat statPath, statEntry;
|
||||||
|
struct dirent* entry;
|
||||||
|
|
||||||
|
// Stat for the path
|
||||||
|
stat(path, &statPath);
|
||||||
|
|
||||||
|
// If path does not exists or is not dir - exit with status -1
|
||||||
|
if (S_ISDIR(statPath.st_mode) == 0)
|
||||||
|
{
|
||||||
|
// Is not directory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not possible to read the directory for this user
|
||||||
|
DIR* dir = opendir(path);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
// Cannot open directory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The length of the path
|
||||||
|
pathLength = strlen(path);
|
||||||
|
|
||||||
|
// Iteration through entries in the directory
|
||||||
|
while ((entry = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
// Skip entries "." and ".."
|
||||||
|
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Determinate a full path of an entry
|
||||||
|
char fullPath[256];
|
||||||
|
ASSERT(pathLength + strlen(entry->d_name) < ARRAY_COUNT(fullPath));
|
||||||
|
strcpy(fullPath, path);
|
||||||
|
strcat(fullPath, "/");
|
||||||
|
strcat(fullPath, entry->d_name);
|
||||||
|
|
||||||
|
// Stat for the entry
|
||||||
|
stat(fullPath, &statEntry);
|
||||||
|
|
||||||
|
// Check for file
|
||||||
|
if (S_ISREG(statEntry.st_mode) != 0)
|
||||||
|
{
|
||||||
|
// Validate with filter
|
||||||
|
const int32 fullPathLength = StringUtils::Length(fullPath);
|
||||||
|
const int32 searchPatternLength = StringUtils::Length(searchPattern);
|
||||||
|
if (searchPatternLength == 0 || StringUtils::Compare(searchPattern, "*") == 0)
|
||||||
|
{
|
||||||
|
// All files
|
||||||
|
}
|
||||||
|
else if (searchPattern[0] == '*' && searchPatternLength < fullPathLength && StringUtils::Compare(fullPath + fullPathLength - searchPatternLength + 1, searchPattern + 1, searchPatternLength - 1) == 0)
|
||||||
|
{
|
||||||
|
// Path ending
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: implement all cases in a generic way
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add file
|
||||||
|
results.Add(String(fullPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacFileSystem::getFilesFromDirectoryAll(Array<String>& results, const char* path, const char* searchPattern)
|
||||||
|
{
|
||||||
|
// Find all files in this directory
|
||||||
|
getFilesFromDirectoryTop(results, path, searchPattern);
|
||||||
|
|
||||||
|
size_t pathLength;
|
||||||
|
DIR* dir;
|
||||||
|
struct stat statPath, statEntry;
|
||||||
|
struct dirent* entry;
|
||||||
|
|
||||||
|
// Stat for the path
|
||||||
|
stat(path, &statPath);
|
||||||
|
|
||||||
|
// If path does not exists or is not dir - exit with status -1
|
||||||
|
if (S_ISDIR(statPath.st_mode) == 0)
|
||||||
|
{
|
||||||
|
// Is not directory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not possible to read the directory for this user
|
||||||
|
if ((dir = opendir(path)) == NULL)
|
||||||
|
{
|
||||||
|
// Cannot open directory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The length of the path
|
||||||
|
pathLength = strlen(path);
|
||||||
|
|
||||||
|
// Iteration through entries in the directory
|
||||||
|
while ((entry = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
// Skip entries "." and ".."
|
||||||
|
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Determinate a full path of an entry
|
||||||
|
char full_path[256];
|
||||||
|
ASSERT(pathLength + strlen(entry->d_name) < ARRAY_COUNT(full_path));
|
||||||
|
strcpy(full_path, path);
|
||||||
|
strcat(full_path, "/");
|
||||||
|
strcat(full_path, entry->d_name);
|
||||||
|
|
||||||
|
// Stat for the entry
|
||||||
|
stat(full_path, &statEntry);
|
||||||
|
|
||||||
|
// Check for directory
|
||||||
|
if (S_ISDIR(statEntry.st_mode) != 0)
|
||||||
|
{
|
||||||
|
if (getFilesFromDirectoryAll(results, full_path, searchPattern))
|
||||||
|
{
|
||||||
|
closedir(dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime MacFileSystem::GetFileLastEditTime(const StringView& path)
|
||||||
|
{
|
||||||
|
struct stat fileInfo;
|
||||||
|
const StringAsANSI<> pathANSI(*path, path.Length());
|
||||||
|
if (stat(pathANSI.Get(), &fileInfo) == -1)
|
||||||
|
{
|
||||||
|
return DateTime::MinValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TimeSpan timeSinceEpoch(0, 0, fileInfo.st_mtime);
|
||||||
|
return UnixEpoch + timeSinceEpoch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacFileSystem::GetSpecialFolderPath(const SpecialFolder type, String& result)
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacFileSystem::GetSpecialFolderPath");
|
||||||
|
return; // TODO: filesystem on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
52
Source/Engine/Platform/Mac/MacFileSystem.h
Normal file
52
Source/Engine/Platform/Mac/MacFileSystem.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "Engine/Platform/Base/FileSystemBase.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mac platform implementation of filesystem service.
|
||||||
|
/// </summary>
|
||||||
|
class FLAXENGINE_API MacFileSystem : public FileSystemBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// [FileSystemBase]
|
||||||
|
static bool CreateDirectory(const StringView& path);
|
||||||
|
static bool DeleteDirectory(const String& path, bool deleteContents = true);
|
||||||
|
static bool DirectoryExists(const StringView& path);
|
||||||
|
static bool DirectoryGetFiles(Array<String, HeapAllocation>& results, const String& path, const Char* searchPattern, DirectorySearchOption option = DirectorySearchOption::AllDirectories);
|
||||||
|
static bool GetChildDirectories(Array<String, HeapAllocation>& results, const String& directory);
|
||||||
|
static bool FileExists(const StringView& path);
|
||||||
|
static bool DeleteFile(const StringView& path);
|
||||||
|
static uint64 GetFileSize(const StringView& path);
|
||||||
|
static bool IsReadOnly(const StringView& path);
|
||||||
|
static bool SetReadOnly(const StringView& path, bool isReadOnly);
|
||||||
|
static bool MoveFile(const StringView& dst, const StringView& src, bool overwrite = false);
|
||||||
|
static bool CopyFile(const StringView& dst, const StringView& src);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets last time when file has been modified (in UTC).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The file path to check.</param>
|
||||||
|
/// <returns>The last write time or DateTime::MinValue() if cannot get data.</returns>
|
||||||
|
static DateTime GetFileLastEditTime(const StringView& path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the special folder path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The folder type.</param>
|
||||||
|
/// <param name="result">The result full path.</param>
|
||||||
|
static void GetSpecialFolderPath(const SpecialFolder type, String& result);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static bool getFilesFromDirectoryTop(Array<String, HeapAllocation>& results, const char* path, const char* searchPattern);
|
||||||
|
static bool getFilesFromDirectoryAll(Array<String, HeapAllocation>& results, const char* path, const char* searchPattern);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
7
Source/Engine/Platform/Mac/MacNetwork.cpp
Normal file
7
Source/Engine/Platform/Mac/MacNetwork.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
// TODO: networking on Mac
|
||||||
|
|
||||||
|
#endif
|
||||||
27
Source/Engine/Platform/Mac/MacNetwork.h
Normal file
27
Source/Engine/Platform/Mac/MacNetwork.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "Engine/Platform/Base/NetworkBase.h"
|
||||||
|
|
||||||
|
class FLAXENGINE_API MacNetwork : public NetworkBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// [NetworkBase]
|
||||||
|
static bool CreateSocket(NetworkSocket& socket, NetworkProtocol proto, NetworkIPVersion ipv);
|
||||||
|
static bool DestroySocket(NetworkSocket& socket);
|
||||||
|
static bool SetSocketOption(NetworkSocket& socket, NetworkSocketOption option, int32 value);
|
||||||
|
static bool GetSocketOption(NetworkSocket& socket, NetworkSocketOption option, int32& value);
|
||||||
|
static bool ConnectSocket(NetworkSocket& socket, NetworkEndPoint& endPoint);
|
||||||
|
static bool BindSocket(NetworkSocket& socket, NetworkEndPoint& endPoint);
|
||||||
|
static bool Listen(NetworkSocket& socket, uint16 queueSize);
|
||||||
|
static bool Accept(NetworkSocket& serverSocket, NetworkSocket& newSocket, NetworkEndPoint& newEndPoint);
|
||||||
|
static int32 WriteSocket(NetworkSocket socket, byte* data, uint32 length, NetworkEndPoint* endPoint = nullptr);
|
||||||
|
static int32 ReadSocket(NetworkSocket socket, byte* buffer, uint32 bufferSize, NetworkEndPoint* endPoint = nullptr);
|
||||||
|
static bool CreateEndPoint(const String& address, const String& port, NetworkIPVersion ipv, NetworkEndPoint& endPoint, bool bindable = true);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
357
Source/Engine/Platform/Mac/MacPlatform.cpp
Normal file
357
Source/Engine/Platform/Mac/MacPlatform.cpp
Normal file
@@ -0,0 +1,357 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "MacPlatform.h"
|
||||||
|
#include "MacWindow.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
|
#include "Engine/Core/Types/Guid.h"
|
||||||
|
#include "Engine/Core/Types/String.h"
|
||||||
|
#include "Engine/Core/Collections/HashFunctions.h"
|
||||||
|
#include "Engine/Core/Collections/Array.h"
|
||||||
|
#include "Engine/Core/Collections/Dictionary.h"
|
||||||
|
#include "Engine/Core/Collections/HashFunctions.h"
|
||||||
|
#include "Engine/Core/Math/Math.h"
|
||||||
|
#include "Engine/Core/Math/Rectangle.h"
|
||||||
|
#include "Engine/Core/Math/Color32.h"
|
||||||
|
#include "Engine/Platform/CPUInfo.h"
|
||||||
|
#include "Engine/Platform/MemoryStats.h"
|
||||||
|
#include "Engine/Platform/StringUtils.h"
|
||||||
|
#include "Engine/Platform/MessageBox.h"
|
||||||
|
#include "Engine/Platform/WindowsManager.h"
|
||||||
|
#include "Engine/Platform/Clipboard.h"
|
||||||
|
#include "Engine/Platform/IGuiData.h"
|
||||||
|
#include "Engine/Platform/Base/PlatformUtils.h"
|
||||||
|
#include "Engine/Utilities/StringConverter.h"
|
||||||
|
#include "Engine/Threading/Threading.h"
|
||||||
|
#include "Engine/Engine/Engine.h"
|
||||||
|
#include "Engine/Engine/CommandLine.h"
|
||||||
|
#include "Engine/Input/Input.h"
|
||||||
|
#include "Engine/Input/Mouse.h"
|
||||||
|
#include "Engine/Input/Keyboard.h"
|
||||||
|
|
||||||
|
CPUInfo MacCpu;
|
||||||
|
Guid DeviceId;
|
||||||
|
String UserLocale, ComputerName;
|
||||||
|
byte MacAddress[6];
|
||||||
|
|
||||||
|
DialogResult MessageBox::Show(Window* parent, const StringView& text, const StringView& caption, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||||
|
{
|
||||||
|
if (CommandLine::Options.Headless)
|
||||||
|
return DialogResult::None;
|
||||||
|
todo;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MacKeyboard : public Keyboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MacKeyboard()
|
||||||
|
: Keyboard()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacMouse : public Mouse
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MacMouse()
|
||||||
|
: Mouse()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// [Mouse]
|
||||||
|
void SetMousePosition(const Vector2& newPosition) final override
|
||||||
|
{
|
||||||
|
MacPlatform::SetMousePosition(newPosition);
|
||||||
|
|
||||||
|
OnMouseMoved(newPosition);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool MacPlatform::Is64BitPlatform()
|
||||||
|
{
|
||||||
|
return PLATFORM_64BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPUInfo MacPlatform::GetCPUInfo()
|
||||||
|
{
|
||||||
|
return MacCpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 MacPlatform::GetCacheLineSize()
|
||||||
|
{
|
||||||
|
return MacCpu.CacheLineSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStats MacPlatform::GetMemoryStats()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetMemoryStats");
|
||||||
|
return MemoryStats(); // TODO: platform stats on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessMemoryStats MacPlatform::GetProcessMemoryStats()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetProcessMemoryStats");
|
||||||
|
return ProcessMemoryStats(); // TODO: platform stats on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 MacPlatform::GetCurrentThreadID()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetCurrentThreadID");
|
||||||
|
return 0; // TODO: threading on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::SetThreadPriority(ThreadPriority priority)
|
||||||
|
{
|
||||||
|
// TODO: impl this
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::SetThreadAffinityMask(uint64 affinityMask)
|
||||||
|
{
|
||||||
|
// TODO: impl this
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::Sleep(int32 milliseconds)
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::Sleep");
|
||||||
|
return; // TODO: clock on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
double MacPlatform::GetTimeSeconds()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetTimeSeconds");
|
||||||
|
return 0.0; // TODO: clock on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 MacPlatform::GetTimeCycles()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetTimeCycles");
|
||||||
|
return 0; // TODO: clock on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 MacPlatform::GetClockFrequency()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetClockFrequency");
|
||||||
|
return 0; // TODO: clock on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::GetSystemTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& minute, int32& second, int32& millisecond)
|
||||||
|
{
|
||||||
|
// Query for calendar time
|
||||||
|
struct timeval time;
|
||||||
|
gettimeofday(&time, nullptr);
|
||||||
|
|
||||||
|
// Convert to local time
|
||||||
|
struct tm localTime;
|
||||||
|
localtime_r(&time.tv_sec, &localTime);
|
||||||
|
|
||||||
|
// Extract time
|
||||||
|
year = localTime.tm_year + 1900;
|
||||||
|
month = localTime.tm_mon + 1;
|
||||||
|
dayOfWeek = localTime.tm_wday;
|
||||||
|
day = localTime.tm_mday;
|
||||||
|
hour = localTime.tm_hour;
|
||||||
|
minute = localTime.tm_min;
|
||||||
|
second = localTime.tm_sec;
|
||||||
|
millisecond = time.tv_usec / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::GetUTCTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& minute, int32& second, int32& millisecond)
|
||||||
|
{
|
||||||
|
// Get the calendar time
|
||||||
|
struct timeval time;
|
||||||
|
gettimeofday(&time, nullptr);
|
||||||
|
|
||||||
|
// Convert to UTC time
|
||||||
|
struct tm localTime;
|
||||||
|
gmtime_r(&time.tv_sec, &localTime);
|
||||||
|
|
||||||
|
// Extract time
|
||||||
|
year = localTime.tm_year + 1900;
|
||||||
|
month = localTime.tm_mon + 1;
|
||||||
|
dayOfWeek = localTime.tm_wday;
|
||||||
|
day = localTime.tm_mday;
|
||||||
|
hour = localTime.tm_hour;
|
||||||
|
minute = localTime.tm_min;
|
||||||
|
second = localTime.tm_sec;
|
||||||
|
millisecond = time.tv_usec / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacPlatform::Init()
|
||||||
|
{
|
||||||
|
if (PlatformBase::Init())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// TODO: get MacCpu
|
||||||
|
|
||||||
|
// TODO: get MacAddress
|
||||||
|
// TODO: get DeviceId
|
||||||
|
|
||||||
|
// TODO: get username
|
||||||
|
OnPlatformUserAdd(New<User>(TEXT("User")));
|
||||||
|
|
||||||
|
// TODO: get UserLocale
|
||||||
|
// TODO: get ComputerName
|
||||||
|
|
||||||
|
Input::Mouse = Impl::Mouse = New<MacMouse>();
|
||||||
|
Input::Keyboard = Impl::Keyboard = New<MacKeyboard>();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::BeforeRun()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::Tick()
|
||||||
|
{
|
||||||
|
// TODO: app events
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::BeforeExit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::Exit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 MacPlatform::GetDpi()
|
||||||
|
{
|
||||||
|
return todo;
|
||||||
|
}
|
||||||
|
|
||||||
|
String MacPlatform::GetUserLocaleName()
|
||||||
|
{
|
||||||
|
return UserLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
String MacPlatform::GetComputerName()
|
||||||
|
{
|
||||||
|
return ComputerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacPlatform::GetHasFocus()
|
||||||
|
{
|
||||||
|
// Check if any window is focused
|
||||||
|
ScopeLock lock(WindowsManager::WindowsLocker);
|
||||||
|
for (auto window : WindowsManager::Windows)
|
||||||
|
{
|
||||||
|
if (window->IsFocused())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to true if has no windows open
|
||||||
|
return WindowsManager::Windows.IsEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacPlatform::CanOpenUrl(const StringView& url)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::OpenUrl(const StringView& url)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 MacPlatform::GetMousePosition()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetMousePosition");
|
||||||
|
return Vector2(0, 0); // TODO: mouse on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::SetMousePosition(const Vector2& pos)
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::SetMousePosition");
|
||||||
|
// TODO: mouse on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 MacPlatform::GetDesktopSize()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetDesktopSize");
|
||||||
|
return Vector2(0, 0); // TODO: desktop size on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle MacPlatform::GetMonitorBounds(const Vector2& screenPos)
|
||||||
|
{
|
||||||
|
// TODO: do it in a proper way
|
||||||
|
return Rectangle(Vector2::Zero, GetDesktopSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle MacPlatform::GetVirtualDesktopBounds()
|
||||||
|
{
|
||||||
|
// TODO: do it in a proper way
|
||||||
|
return Rectangle(Vector2::Zero, GetDesktopSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
String MacPlatform::GetMainDirectory()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetMainDirectory");
|
||||||
|
return TEXT("/"); // TODO: GetMainDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
String MacPlatform::GetExecutableFilePath()
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetExecutableFilePath");
|
||||||
|
return TEXT("/"); // TODO: GetMainDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
Guid MacPlatform::GetUniqueDeviceId()
|
||||||
|
{
|
||||||
|
return DeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
String MacPlatform::GetWorkingDirectory()
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
getcwd(buffer, ARRAY_COUNT(buffer));
|
||||||
|
return String(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacPlatform::SetWorkingDirectory(const String& path)
|
||||||
|
{
|
||||||
|
return chdir(StringAsANSI<>(*path).Get()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window* MacPlatform::CreateWindow(const CreateWindowSettings& settings)
|
||||||
|
{
|
||||||
|
return New<MacWindow>(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacPlatform::GetEnvironmentVariable(const String& name, String& value)
|
||||||
|
{
|
||||||
|
char* env = getenv(StringAsANSI<>(*name).Get());
|
||||||
|
if (env)
|
||||||
|
{
|
||||||
|
value = String(env);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacPlatform::SetEnvironmentVariable(const String& name, const String& value)
|
||||||
|
{
|
||||||
|
return setenv(StringAsANSI<>(*name).Get(), StringAsANSI<>(*value).Get(), true) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MacPlatform::LoadLibrary(const Char* filename)
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::LoadLibrary");
|
||||||
|
return nullptr; // TODO: dynamic libs on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacPlatform::FreeLibrary(void* handle)
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::FreeLibrary");
|
||||||
|
return; // TODO: dynamic libs on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MacPlatform::GetProcAddress(void* handle, const char* symbol)
|
||||||
|
{
|
||||||
|
MISSING_CODE("MacPlatform::GetProcAddress");
|
||||||
|
return nullptr; // TODO: dynamic libs on Mac
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
112
Source/Engine/Platform/Mac/MacPlatform.h
Normal file
112
Source/Engine/Platform/Mac/MacPlatform.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "../Base/PlatformBase.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Mac platform implementation and application management utilities.
|
||||||
|
/// </summary>
|
||||||
|
class FLAXENGINE_API MacPlatform : public UnixPlatform
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// [UnixPlatform]
|
||||||
|
FORCE_INLINE static void MemoryBarrier()
|
||||||
|
{
|
||||||
|
__sync_synchronize();
|
||||||
|
}
|
||||||
|
FORCE_INLINE static int64 InterlockedExchange(int64 volatile* dst, int64 exchange)
|
||||||
|
{
|
||||||
|
return __sync_lock_test_and_set(dst, exchange);
|
||||||
|
}
|
||||||
|
FORCE_INLINE static int32 InterlockedCompareExchange(int32 volatile* dst, int32 exchange, int32 comperand)
|
||||||
|
{
|
||||||
|
return __sync_val_compare_and_swap(dst, comperand, exchange);
|
||||||
|
}
|
||||||
|
FORCE_INLINE static int64 InterlockedCompareExchange(int64 volatile* dst, int64 exchange, int64 comperand)
|
||||||
|
{
|
||||||
|
return __sync_val_compare_and_swap(dst, comperand, exchange);
|
||||||
|
}
|
||||||
|
FORCE_INLINE static int64 InterlockedIncrement(int64 volatile* dst)
|
||||||
|
{
|
||||||
|
return __sync_add_and_fetch(dst, 1);
|
||||||
|
}
|
||||||
|
FORCE_INLINE static int64 InterlockedDecrement(int64 volatile* dst)
|
||||||
|
{
|
||||||
|
return __sync_sub_and_fetch(dst, 1);
|
||||||
|
}
|
||||||
|
FORCE_INLINE static int64 InterlockedAdd(int64 volatile* dst, int64 value)
|
||||||
|
{
|
||||||
|
return __sync_fetch_and_add(dst, value);
|
||||||
|
}
|
||||||
|
FORCE_INLINE static int32 AtomicRead(int32 volatile* dst)
|
||||||
|
{
|
||||||
|
int32 result;
|
||||||
|
__atomic_load(dst, &result, __ATOMIC_SEQ_CST);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
FORCE_INLINE static int64 AtomicRead(int64 volatile* dst)
|
||||||
|
{
|
||||||
|
int64 result;
|
||||||
|
__atomic_load(dst, &result, __ATOMIC_SEQ_CST);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
FORCE_INLINE static void AtomicStore(int32 volatile* dst, int32 value)
|
||||||
|
{
|
||||||
|
__atomic_store(dst, &value, __ATOMIC_SEQ_CST);
|
||||||
|
}
|
||||||
|
FORCE_INLINE static void AtomicStore(int64 volatile* dst, int64 value)
|
||||||
|
{
|
||||||
|
__atomic_store(dst, &value, __ATOMIC_SEQ_CST);
|
||||||
|
}
|
||||||
|
FORCE_INLINE static void Prefetch(void const* ptr)
|
||||||
|
{
|
||||||
|
__builtin_prefetch(static_cast<char const*>(ptr));
|
||||||
|
}
|
||||||
|
static bool Is64BitPlatform();
|
||||||
|
static CPUInfo GetCPUInfo();
|
||||||
|
static int32 GetCacheLineSize();
|
||||||
|
static MemoryStats GetMemoryStats();
|
||||||
|
static ProcessMemoryStats GetProcessMemoryStats();
|
||||||
|
static uint64 GetCurrentThreadID();
|
||||||
|
static void SetThreadPriority(ThreadPriority priority);
|
||||||
|
static void SetThreadAffinityMask(uint64 affinityMask);
|
||||||
|
static void Sleep(int32 milliseconds);
|
||||||
|
static double GetTimeSeconds();
|
||||||
|
static uint64 GetTimeCycles();
|
||||||
|
static uint64 GetClockFrequency();
|
||||||
|
static void GetSystemTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& minute, int32& second, int32& millisecond);
|
||||||
|
static void GetUTCTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& minute, int32& second, int32& millisecond);
|
||||||
|
static bool Init();
|
||||||
|
static void BeforeRun();
|
||||||
|
static void Tick();
|
||||||
|
static void BeforeExit();
|
||||||
|
static void Exit();
|
||||||
|
static int32 GetDpi();
|
||||||
|
static String GetUserLocaleName();
|
||||||
|
static String GetComputerName();
|
||||||
|
static bool GetHasFocus();
|
||||||
|
static bool CanOpenUrl(const StringView& url);
|
||||||
|
static void OpenUrl(const StringView& url);
|
||||||
|
static Vector2 GetMousePosition();
|
||||||
|
static void SetMousePosition(const Vector2& pos);
|
||||||
|
static Rectangle GetMonitorBounds(const Vector2& screenPos);
|
||||||
|
static Vector2 GetDesktopSize();
|
||||||
|
static Rectangle GetVirtualDesktopBounds();
|
||||||
|
static String GetMainDirectory();
|
||||||
|
static String GetExecutableFilePath();
|
||||||
|
static Guid GetUniqueDeviceId();
|
||||||
|
static String GetWorkingDirectory();
|
||||||
|
static bool SetWorkingDirectory(const String& path);
|
||||||
|
static Window* CreateWindow(const CreateWindowSettings& settings);
|
||||||
|
static bool GetEnvironmentVariable(const String& name, String& value);
|
||||||
|
static bool SetEnvironmentVariable(const String& name, const String& value);
|
||||||
|
static void* LoadLibrary(const Char* filename);
|
||||||
|
static void FreeLibrary(void* handle);
|
||||||
|
static void* GetProcAddress(void* handle, const char* symbol);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
31
Source/Engine/Platform/Mac/MacPlatformSettings.h
Normal file
31
Source/Engine/Platform/Mac/MacPlatformSettings.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC || USE_EDITOR
|
||||||
|
|
||||||
|
#include "Engine/Core/Config/PlatformSettingsBase.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mac platform settings.
|
||||||
|
/// </summary>
|
||||||
|
API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API MacPlatformSettings : public SettingsBase
|
||||||
|
{
|
||||||
|
DECLARE_SCRIPTING_TYPE_MINIMAL(MacPlatformSettings);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.
|
||||||
|
/// </summary>
|
||||||
|
static MacPlatformSettings* Get();
|
||||||
|
|
||||||
|
// [SettingsBase]
|
||||||
|
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
typedef MacPlatformSettings PlatformSettings;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
277
Source/Engine/Platform/Mac/MacStringUtils.cpp
Normal file
277
Source/Engine/Platform/Mac/MacStringUtils.cpp
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "Engine/Platform/StringUtils.h"
|
||||||
|
#include <wctype.h>
|
||||||
|
#include <cctype>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
bool StringUtils::IsUpper(char c)
|
||||||
|
{
|
||||||
|
return isupper(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsLower(char c)
|
||||||
|
{
|
||||||
|
return islower(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsAlpha(char c)
|
||||||
|
{
|
||||||
|
return iswalpha(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsPunct(char c)
|
||||||
|
{
|
||||||
|
return ispunct(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsAlnum(char c)
|
||||||
|
{
|
||||||
|
return isalnum(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsDigit(char c)
|
||||||
|
{
|
||||||
|
return isdigit(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsHexDigit(char c)
|
||||||
|
{
|
||||||
|
return isxdigit(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsWhitespace(char c)
|
||||||
|
{
|
||||||
|
return isspace(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char StringUtils::ToUpper(char c)
|
||||||
|
{
|
||||||
|
return toupper(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
char StringUtils::ToLower(char c)
|
||||||
|
{
|
||||||
|
return tolower(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsUpper(Char c)
|
||||||
|
{
|
||||||
|
return iswupper(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsLower(Char c)
|
||||||
|
{
|
||||||
|
return iswlower(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsAlpha(Char c)
|
||||||
|
{
|
||||||
|
return iswalpha(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsPunct(Char c)
|
||||||
|
{
|
||||||
|
return iswpunct(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsAlnum(Char c)
|
||||||
|
{
|
||||||
|
return iswalnum(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsDigit(Char c)
|
||||||
|
{
|
||||||
|
return iswdigit(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsHexDigit(Char c)
|
||||||
|
{
|
||||||
|
return iswxdigit(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringUtils::IsWhitespace(Char c)
|
||||||
|
{
|
||||||
|
return iswspace(c) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Char StringUtils::ToUpper(Char c)
|
||||||
|
{
|
||||||
|
return towupper(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
Char StringUtils::ToLower(Char c)
|
||||||
|
{
|
||||||
|
return towlower(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::Compare(const Char* str1, const Char* str2)
|
||||||
|
{
|
||||||
|
Char c1, c2;
|
||||||
|
int32 i;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c1 = *str1++;
|
||||||
|
c2 = *str2++;
|
||||||
|
i = (int32)c1 - (int32)c2;
|
||||||
|
} while (i == 0 && c1 && c2);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::Compare(const Char* str1, const Char* str2, int32 maxCount)
|
||||||
|
{
|
||||||
|
Char c1, c2;
|
||||||
|
int32 i;
|
||||||
|
if (maxCount == 0)
|
||||||
|
return 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c1 = *str1++;
|
||||||
|
c2 = *str2++;
|
||||||
|
i = (int32)c1 - (int32)c2;
|
||||||
|
maxCount--;
|
||||||
|
} while (i == 0 && c1 && c2 && maxCount);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::CompareIgnoreCase(const Char* str1, const Char* str2)
|
||||||
|
{
|
||||||
|
Char c1, c2;
|
||||||
|
int32 i;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c1 = ToLower(*str1++);
|
||||||
|
c2 = ToLower(*str2++);
|
||||||
|
i = (int32)c1 - (int32)c2;
|
||||||
|
} while (i == 0 && c1 && c2);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::CompareIgnoreCase(const Char* str1, const Char* str2, int32 maxCount)
|
||||||
|
{
|
||||||
|
Char c1, c2;
|
||||||
|
int32 i;
|
||||||
|
if (maxCount == 0)
|
||||||
|
return 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c1 = ToLower(*str1++);
|
||||||
|
c2 = ToLower(*str2++);
|
||||||
|
i = (int32)c1 - (int32)c2;
|
||||||
|
maxCount--;
|
||||||
|
} while (i == 0 && c1 && c2 && maxCount);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::Length(const Char* str)
|
||||||
|
{
|
||||||
|
if (!str)
|
||||||
|
return 0;
|
||||||
|
const Char* ptr = str;
|
||||||
|
for (; *ptr; ++ptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return ptr - str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::Length(const char* str)
|
||||||
|
{
|
||||||
|
if (!str)
|
||||||
|
return 0;
|
||||||
|
return static_cast<int32>(strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::Compare(const char* str1, const char* str2)
|
||||||
|
{
|
||||||
|
return strcmp(str1, str2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::Compare(const char* str1, const char* str2, int32 maxCount)
|
||||||
|
{
|
||||||
|
return strncmp(str1, str2, maxCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::CompareIgnoreCase(const char* str1, const char* str2)
|
||||||
|
{
|
||||||
|
return strcasecmp(str1, str2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 StringUtils::CompareIgnoreCase(const char* str1, const char* str2, int32 maxCount)
|
||||||
|
{
|
||||||
|
return strncasecmp(str1, str2, maxCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
Char* StringUtils::Copy(Char* dst, const Char* src)
|
||||||
|
{
|
||||||
|
Char* q = dst;
|
||||||
|
const Char* p = src;
|
||||||
|
Char ch;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*q++ = ch = *p++;
|
||||||
|
} while (ch);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
Char* StringUtils::Copy(Char* dst, const Char* src, int32 count)
|
||||||
|
{
|
||||||
|
Char* q = dst;
|
||||||
|
const Char* p = src;
|
||||||
|
char ch;
|
||||||
|
while (count)
|
||||||
|
{
|
||||||
|
count--;
|
||||||
|
*q++ = ch = *p++;
|
||||||
|
if (!ch)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*q = 0;
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Char* StringUtils::Find(const Char* str, const Char* toFind)
|
||||||
|
{
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
const Char* start = str;
|
||||||
|
const Char* sub = toFind;
|
||||||
|
|
||||||
|
// If first character of sub string match, check for whole string
|
||||||
|
while (*str && *sub && *str == *sub)
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
sub++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If complete substring match, return starting address
|
||||||
|
if (!*sub)
|
||||||
|
return (Char*)start;
|
||||||
|
|
||||||
|
// Increment main string
|
||||||
|
str = start + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No matches
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* StringUtils::Find(const char* str, const char* toFind)
|
||||||
|
{
|
||||||
|
return strstr(str, toFind);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringUtils::ConvertANSI2UTF16(const char* from, Char* to, int32 len)
|
||||||
|
{
|
||||||
|
todo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringUtils::ConvertUTF162ANSI(const Char* from, char* to, int32 len)
|
||||||
|
{
|
||||||
|
todo;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
23
Source/Engine/Platform/Mac/MacThread.cpp
Normal file
23
Source/Engine/Platform/Mac/MacThread.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "MacThread.h"
|
||||||
|
#include "Engine/Threading/IRunnable.h"
|
||||||
|
#include "Engine/Threading/ThreadRegistry.h"
|
||||||
|
|
||||||
|
MacThread::MacThread(IRunnable* runnable, const String& name, ThreadPriority priority)
|
||||||
|
: ThreadBase(runnable, name, priority)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MacThread::~MacThread()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MacThread* Create(IRunnable* runnable, const String& name, ThreadPriority priority = ThreadPriority::Normal, uint32 stackSize = 0)
|
||||||
|
{
|
||||||
|
// TODO: imp this
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
31
Source/Engine/Platform/Mac/MacThread.h
Normal file
31
Source/Engine/Platform/Mac/MacThread.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "../Base/ThreadBase.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Thread object for Mac platform.
|
||||||
|
/// </summary>
|
||||||
|
class MacThread : public ThreadBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
MacThread(IRunnable* runnable, const String& name, ThreadPriority priority);
|
||||||
|
~MacThread();
|
||||||
|
static MacThread* Create(IRunnable* runnable, const String& name, ThreadPriority priority = ThreadPriority::Normal, uint32 stackSize = 0);
|
||||||
|
|
||||||
|
// [ThreadBase]
|
||||||
|
void Join() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// [ThreadBase]
|
||||||
|
void ClearHandleInternal();
|
||||||
|
void SetPriorityInternal(ThreadPriority priority);
|
||||||
|
void KillInternal(bool waitForJoin);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
103
Source/Engine/Platform/Mac/MacWindow.cpp
Normal file
103
Source/Engine/Platform/Mac/MacWindow.cpp
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "../Window.h"
|
||||||
|
|
||||||
|
MacWindow::MacWindow(const CreateWindowSettings& settings)
|
||||||
|
: WindowBase(settings)
|
||||||
|
{
|
||||||
|
int32 x = Math::TruncToInt(settings.Position.X);
|
||||||
|
int32 y = Math::TruncToInt(settings.Position.Y);
|
||||||
|
int32 clientWidth = Math::TruncToInt(settings.Size.X);
|
||||||
|
int32 clientHeight = Math::TruncToInt(settings.Size.Y);
|
||||||
|
int32 windowWidth = clientWidth;
|
||||||
|
int32 windowHeight = clientHeight;
|
||||||
|
_clientSize = Vector2((float)clientWidth, (float)clientHeight);
|
||||||
|
|
||||||
|
// TODO: setup window
|
||||||
|
}
|
||||||
|
|
||||||
|
MacWindow::~MacWindow()
|
||||||
|
{
|
||||||
|
// TODO: close window
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MacWindow::GetNativePtr() const
|
||||||
|
{
|
||||||
|
// TODO: return window handle
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacWindow::Show()
|
||||||
|
{
|
||||||
|
if (!_visible)
|
||||||
|
{
|
||||||
|
InitSwapChain();
|
||||||
|
if (_showAfterFirstPaint)
|
||||||
|
{
|
||||||
|
if (RenderTask)
|
||||||
|
RenderTask->Enabled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show
|
||||||
|
// TODO: show window
|
||||||
|
_focused = true;
|
||||||
|
|
||||||
|
// Base
|
||||||
|
WindowBase::Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacWindow::Hide()
|
||||||
|
{
|
||||||
|
if (_visible)
|
||||||
|
{
|
||||||
|
// Hide
|
||||||
|
// TODO: hide window
|
||||||
|
|
||||||
|
// Base
|
||||||
|
WindowBase::Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacWindow::Minimize()
|
||||||
|
{
|
||||||
|
// TODO: Minimize
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacWindow::Maximize()
|
||||||
|
{
|
||||||
|
// TODO: Maximize
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacWindow::Restore()
|
||||||
|
{
|
||||||
|
// TODO: Restore
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacWindow::IsClosed() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacWindow::IsForegroundWindow() const
|
||||||
|
{
|
||||||
|
return Platform::GetHasFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacWindow::SetIsFullscreen(bool isFullscreen)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacWindow::GetScreenInfo(int32& x, int32& y, int32& width, int32& height) const
|
||||||
|
{
|
||||||
|
// TODO: proper screen info
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
width = (int32)_clientSize.X;
|
||||||
|
height = (int32)_clientSize.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
38
Source/Engine/Platform/Mac/MacWindow.h
Normal file
38
Source/Engine/Platform/Mac/MacWindow.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_MAC
|
||||||
|
|
||||||
|
#include "Engine/Platform/Base/WindowBase.h"
|
||||||
|
#include "Engine/Platform/Platform.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation of the window class for Mac platform.
|
||||||
|
/// </summary>
|
||||||
|
class MacWindow : public WindowBase
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Vector2 _clientSize;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MacWindow(const CreateWindowSettings& settings);
|
||||||
|
~MacWindow();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// [Window]
|
||||||
|
void* GetNativePtr() const override;
|
||||||
|
void Show() override;
|
||||||
|
void Hide() override;
|
||||||
|
void Minimize() override;
|
||||||
|
void Maximize() override;
|
||||||
|
void Restore() override;
|
||||||
|
bool IsClosed() const override;
|
||||||
|
bool IsForegroundWindow() const override;
|
||||||
|
void SetIsFullscreen(bool isFullscreen) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,24 +2,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS || PLATFORM_UWP || PLATFORM_XBOX_ONE || PLATFORM_XBOX_SCARLETT
|
||||||
#include "Win32/Win32Network.h"
|
#include "Win32/Win32Network.h"
|
||||||
#elif PLATFORM_UWP
|
#elif PLATFORM_LINUX || PLATFORM_ANDROID
|
||||||
#include "Win32/Win32Network.h"
|
|
||||||
#elif PLATFORM_LINUX
|
|
||||||
#include "Unix/UnixNetwork.h"
|
#include "Unix/UnixNetwork.h"
|
||||||
#elif PLATFORM_PS4
|
#elif PLATFORM_PS4
|
||||||
#include "Platforms/PS4/Engine/Platform/PS4Network.h"
|
#include "Platforms/PS4/Engine/Platform/PS4Network.h"
|
||||||
#elif PLATFORM_PS5
|
#elif PLATFORM_PS5
|
||||||
#include "Platforms/PS5/Engine/Platform/PS5Network.h"
|
#include "Platforms/PS5/Engine/Platform/PS5Network.h"
|
||||||
#elif PLATFORM_XBOX_ONE
|
|
||||||
#include "Win32/Win32Network.h"
|
|
||||||
#elif PLATFORM_XBOX_SCARLETT
|
|
||||||
#include "Win32/Win32Network.h"
|
|
||||||
#elif PLATFORM_ANDROID
|
|
||||||
#include "Unix/UnixNetwork.h"
|
|
||||||
#elif PLATFORM_SWITCH
|
#elif PLATFORM_SWITCH
|
||||||
#include "Platforms/Switch/Engine/Platform/SwitchNetwork.h"
|
#include "Platforms/Switch/Engine/Platform/SwitchNetwork.h"
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
#include "Mac/MacNetwork.h"
|
||||||
#else
|
#else
|
||||||
#error Missing Network implementation!
|
#error Missing Network implementation!
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ public class Platform : EngineModule
|
|||||||
case TargetPlatform.Switch:
|
case TargetPlatform.Switch:
|
||||||
options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "Platform"));
|
options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "Platform"));
|
||||||
break;
|
break;
|
||||||
|
case TargetPlatform.Mac:
|
||||||
|
options.SourcePaths.Add(Path.Combine(FolderPath, "Mac"));
|
||||||
|
break;
|
||||||
default: throw new InvalidPlatformException(options.Platform.Target);
|
default: throw new InvalidPlatformException(options.Platform.Target);
|
||||||
}
|
}
|
||||||
if (options.Target.IsEditor)
|
if (options.Target.IsEditor)
|
||||||
@@ -87,6 +90,7 @@ public class Platform : EngineModule
|
|||||||
options.SourceFiles.Add(Path.Combine(FolderPath, "Linux", "LinuxPlatformSettings.h"));
|
options.SourceFiles.Add(Path.Combine(FolderPath, "Linux", "LinuxPlatformSettings.h"));
|
||||||
options.SourceFiles.Add(Path.Combine(FolderPath, "Android", "AndroidPlatformSettings.h"));
|
options.SourceFiles.Add(Path.Combine(FolderPath, "Android", "AndroidPlatformSettings.h"));
|
||||||
options.SourceFiles.Add(Path.Combine(FolderPath, "GDK", "GDKPlatformSettings.h"));
|
options.SourceFiles.Add(Path.Combine(FolderPath, "GDK", "GDKPlatformSettings.h"));
|
||||||
|
options.SourceFiles.Add(Path.Combine(FolderPath, "Mac", "MacPlatformSettings.h"));
|
||||||
AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "XboxOne", "Engine", "Platform", "XboxOnePlatformSettings.h"));
|
AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "XboxOne", "Engine", "Platform", "XboxOnePlatformSettings.h"));
|
||||||
AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "XboxScarlett", "Engine", "Platform", "XboxScarlettPlatformSettings.h"));
|
AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "XboxScarlett", "Engine", "Platform", "XboxScarlettPlatformSettings.h"));
|
||||||
AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "PS4", "Engine", "Platform", "PS4PlatformSettings.h"));
|
AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "PS4", "Engine", "Platform", "PS4PlatformSettings.h"));
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
#include "Android/AndroidPlatform.h"
|
#include "Android/AndroidPlatform.h"
|
||||||
#elif PLATFORM_SWITCH
|
#elif PLATFORM_SWITCH
|
||||||
#include "Platforms/Switch/Engine/Platform/SwitchPlatform.h"
|
#include "Platforms/Switch/Engine/Platform/SwitchPlatform.h"
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
#include "Mac/MacPlatform.h"
|
||||||
#else
|
#else
|
||||||
#error Missing Platform implementation!
|
#error Missing Platform implementation!
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS || PLATFORM_UWP || PLATFORM_XBOX_ONE || PLATFORM_XBOX_SCARLETT
|
||||||
#include "Win32/Win32Thread.h"
|
|
||||||
#elif PLATFORM_UWP
|
|
||||||
#include "Win32/Win32Thread.h"
|
#include "Win32/Win32Thread.h"
|
||||||
#elif PLATFORM_LINUX
|
#elif PLATFORM_LINUX
|
||||||
#include "Linux/LinuxThread.h"
|
#include "Linux/LinuxThread.h"
|
||||||
@@ -12,14 +10,12 @@
|
|||||||
#include "Platforms/PS4/Engine/Platform/PS4Thread.h"
|
#include "Platforms/PS4/Engine/Platform/PS4Thread.h"
|
||||||
#elif PLATFORM_PS5
|
#elif PLATFORM_PS5
|
||||||
#include "Platforms/PS5/Engine/Platform/PS5Thread.h"
|
#include "Platforms/PS5/Engine/Platform/PS5Thread.h"
|
||||||
#elif PLATFORM_XBOX_ONE
|
|
||||||
#include "Win32/Win32Thread.h"
|
|
||||||
#elif PLATFORM_XBOX_SCARLETT
|
|
||||||
#include "Win32/Win32Thread.h"
|
|
||||||
#elif PLATFORM_ANDROID
|
#elif PLATFORM_ANDROID
|
||||||
#include "Android/AndroidThread.h"
|
#include "Android/AndroidThread.h"
|
||||||
#elif PLATFORM_SWITCH
|
#elif PLATFORM_SWITCH
|
||||||
#include "Platforms/Switch/Engine/Platform/SwitchThread.h"
|
#include "Platforms/Switch/Engine/Platform/SwitchThread.h"
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
#include "Mac/MacThread.h"
|
||||||
#else
|
#else
|
||||||
#error Missing Thread implementation!
|
#error Missing Thread implementation!
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -147,8 +147,8 @@ class Win32Thread;
|
|||||||
typedef Win32Thread Thread;
|
typedef Win32Thread Thread;
|
||||||
class GDKWindow;
|
class GDKWindow;
|
||||||
typedef GDKWindow Window;
|
typedef GDKWindow Window;
|
||||||
class NetworkBase;
|
class Win32Network;
|
||||||
typedef NetworkBase Network;
|
typedef Win32Network Network;
|
||||||
class GDKUser;
|
class GDKUser;
|
||||||
typedef GDKUser User;
|
typedef GDKUser User;
|
||||||
|
|
||||||
@@ -172,8 +172,8 @@ class Win32Thread;
|
|||||||
typedef Win32Thread Thread;
|
typedef Win32Thread Thread;
|
||||||
class GDKWindow;
|
class GDKWindow;
|
||||||
typedef GDKWindow Window;
|
typedef GDKWindow Window;
|
||||||
class NetworkBase;
|
class Win32Network;
|
||||||
typedef NetworkBase Network;
|
typedef Win32Network Network;
|
||||||
class GDKUser;
|
class GDKUser;
|
||||||
typedef GDKUser User;
|
typedef GDKUser User;
|
||||||
|
|
||||||
@@ -227,6 +227,31 @@ typedef SwitchNetwork Network;
|
|||||||
class UserBase;
|
class UserBase;
|
||||||
typedef UserBase User;
|
typedef UserBase User;
|
||||||
|
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
|
||||||
|
class ClipboardBase;
|
||||||
|
typedef ClipboardBase Clipboard;
|
||||||
|
class MacCriticalSection;
|
||||||
|
typedef MacCriticalSection CriticalSection;
|
||||||
|
class MacConditionVariable;
|
||||||
|
typedef MacConditionVariable ConditionVariable;
|
||||||
|
class MacFileSystem;
|
||||||
|
typedef MacFileSystem FileSystem;
|
||||||
|
class FileSystemWatcherBase;
|
||||||
|
typedef FileSystemWatcherBase FileSystemWatcher;
|
||||||
|
class MacFile;
|
||||||
|
typedef MacFile File;
|
||||||
|
class MacPlatform;
|
||||||
|
typedef MacPlatform Platform;
|
||||||
|
class MacThread;
|
||||||
|
typedef MacThread Thread;
|
||||||
|
class MacWindow;
|
||||||
|
typedef MacWindow Window;
|
||||||
|
class MacNetwork;
|
||||||
|
typedef MacNetwork Network;
|
||||||
|
class UserBase;
|
||||||
|
typedef UserBase User;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#error Missing Types implementation!
|
#error Missing Types implementation!
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#include "Platforms/Switch/Engine/Platform/SwitchWindow.h"
|
#include "Platforms/Switch/Engine/Platform/SwitchWindow.h"
|
||||||
#elif PLATFORM_PS5
|
#elif PLATFORM_PS5
|
||||||
#include "Platforms/PS5/Engine/Platform/PS5Window.h"
|
#include "Platforms/PS5/Engine/Platform/PS5Window.h"
|
||||||
|
#elif PLATFORM_MAC
|
||||||
|
#include "Mac/MacWindow.h"
|
||||||
#else
|
#else
|
||||||
#error Missing Window implementation!
|
#error Missing Window implementation!
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class TextureTool : EngineModule
|
|||||||
case TargetPlatform.PS5:
|
case TargetPlatform.PS5:
|
||||||
case TargetPlatform.Android:
|
case TargetPlatform.Android:
|
||||||
case TargetPlatform.Switch:
|
case TargetPlatform.Switch:
|
||||||
|
case TargetPlatform.Mac:
|
||||||
useStb = true;
|
useStb = true;
|
||||||
break;
|
break;
|
||||||
default: throw new InvalidPlatformException(options.Platform.Target);
|
default: throw new InvalidPlatformException(options.Platform.Target);
|
||||||
|
|||||||
@@ -769,6 +769,7 @@ void ShaderGenerator::ProcessGroupTools(Box* box, Node* node, Value& value)
|
|||||||
PLATFORM_CASE(8, "PLATFORM_ANDROID");
|
PLATFORM_CASE(8, "PLATFORM_ANDROID");
|
||||||
PLATFORM_CASE(9, "PLATFORM_SWITCH");
|
PLATFORM_CASE(9, "PLATFORM_SWITCH");
|
||||||
PLATFORM_CASE(10, "PLATFORM_PS5");
|
PLATFORM_CASE(10, "PLATFORM_PS5");
|
||||||
|
PLATFORM_CASE(11, "PLATFORM_MAC");
|
||||||
#undef PLATFORM_CASE
|
#undef PLATFORM_CASE
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -917,6 +917,9 @@ void VisjectExecutor::ProcessGroupTools(Box* box, Node* node, Value& value)
|
|||||||
case PlatformType::PS5:
|
case PlatformType::PS5:
|
||||||
boxId = 10;
|
boxId = 10;
|
||||||
break;
|
break;
|
||||||
|
case PlatformType::Mac:
|
||||||
|
boxId = 11;
|
||||||
|
break;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
value = tryGetValue(node->GetBox(node->GetBox(boxId)->HasConnection() ? boxId : 1), Value::Zero);
|
value = tryGetValue(node->GetBox(node->GetBox(boxId)->HasConnection() ? boxId : 1), Value::Zero);
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ namespace Flax.Build
|
|||||||
case TargetPlatform.XboxScarlett: return "PLATFORM_XBOX_SCARLETT";
|
case TargetPlatform.XboxScarlett: return "PLATFORM_XBOX_SCARLETT";
|
||||||
case TargetPlatform.Android: return "PLATFORM_ANDROID";
|
case TargetPlatform.Android: return "PLATFORM_ANDROID";
|
||||||
case TargetPlatform.Switch: return "PLATFORM_SWITCH";
|
case TargetPlatform.Switch: return "PLATFORM_SWITCH";
|
||||||
|
case TargetPlatform.Mac: return "PLATFORM_MAC";
|
||||||
default: throw new InvalidPlatformException(platform);
|
default: throw new InvalidPlatformException(platform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace Flax.Build
|
|||||||
case PlatformID.Win32Windows:
|
case PlatformID.Win32Windows:
|
||||||
case PlatformID.WinCE: return TargetPlatform.Windows;
|
case PlatformID.WinCE: return TargetPlatform.Windows;
|
||||||
case PlatformID.Unix: return TargetPlatform.Linux;
|
case PlatformID.Unix: return TargetPlatform.Linux;
|
||||||
|
case PlatformID.MacOSX: return TargetPlatform.Mac;
|
||||||
default: throw new NotImplementedException(string.Format("Unsupported build platform {0}.", platformId));
|
default: throw new NotImplementedException(string.Format("Unsupported build platform {0}.", platformId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,6 +243,7 @@ namespace Flax.Build
|
|||||||
case TargetPlatform.PS5: return targetArchitecture == TargetArchitecture.x64;
|
case TargetPlatform.PS5: return targetArchitecture == TargetArchitecture.x64;
|
||||||
case TargetPlatform.Android: return targetArchitecture == TargetArchitecture.ARM64;
|
case TargetPlatform.Android: return targetArchitecture == TargetArchitecture.ARM64;
|
||||||
case TargetPlatform.Switch: return targetArchitecture == TargetArchitecture.ARM64;
|
case TargetPlatform.Switch: return targetArchitecture == TargetArchitecture.ARM64;
|
||||||
|
case TargetPlatform.Mac: return targetArchitecture == TargetArchitecture.x64;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ namespace Flax.Build
|
|||||||
/// Running on PlayStation 5.
|
/// Running on PlayStation 5.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
PS5 = 9,
|
PS5 = 9,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Running on Mac.
|
||||||
|
/// </summary>
|
||||||
|
Mac = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ namespace Flax.Deps
|
|||||||
case TargetPlatform.Linux:
|
case TargetPlatform.Linux:
|
||||||
case TargetPlatform.PS4:
|
case TargetPlatform.PS4:
|
||||||
case TargetPlatform.PS5:
|
case TargetPlatform.PS5:
|
||||||
|
case TargetPlatform.Mac:
|
||||||
{
|
{
|
||||||
cmdLine = "CMakeLists.txt";
|
cmdLine = "CMakeLists.txt";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
<Compile Include="Platforms\Linux\*.cs" />
|
<Compile Include="Platforms\Linux\*.cs" />
|
||||||
<Compile Include="..\..\Platforms\PS4\Flax.Build\*.cs" />
|
<Compile Include="..\..\Platforms\PS4\Flax.Build\*.cs" />
|
||||||
<Compile Include="..\..\Platforms\PS5\Flax.Build\*.cs" />
|
<Compile Include="..\..\Platforms\PS5\Flax.Build\*.cs" />
|
||||||
|
<Compile Include="Platforms\Mac\*.cs" />
|
||||||
<Compile Include="Platforms\Unix\*.cs" />
|
<Compile Include="Platforms\Unix\*.cs" />
|
||||||
<Compile Include="Platforms\UWP\*.cs" />
|
<Compile Include="Platforms\UWP\*.cs" />
|
||||||
<Compile Include="Platforms\Windows\*.cs" />
|
<Compile Include="Platforms\Windows\*.cs" />
|
||||||
@@ -160,6 +161,7 @@
|
|||||||
<Compile Include="Projects\VisualStudio\VisualStudioProject.cs" />
|
<Compile Include="Projects\VisualStudio\VisualStudioProject.cs" />
|
||||||
<Compile Include="Projects\VisualStudio\VisualStudioProjectGenerator.cs" />
|
<Compile Include="Projects\VisualStudio\VisualStudioProjectGenerator.cs" />
|
||||||
<Compile Include="Projects\VisualStudio\VisualStudioVersion.cs" />
|
<Compile Include="Projects\VisualStudio\VisualStudioVersion.cs" />
|
||||||
|
<Compile Include="Projects\XCode.cs" />
|
||||||
<Compile Include="Utilities\StringWriterWithEncoding.cs" />
|
<Compile Include="Utilities\StringWriterWithEncoding.cs" />
|
||||||
<Compile Include="Utilities\Tokenizer.cs" />
|
<Compile Include="Utilities\Tokenizer.cs" />
|
||||||
<Compile Include="Utilities\TwoWayEnumerator.cs" />
|
<Compile Include="Utilities\TwoWayEnumerator.cs" />
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ namespace Flax.Build
|
|||||||
TargetPlatform.XboxScarlett,
|
TargetPlatform.XboxScarlett,
|
||||||
TargetPlatform.Android,
|
TargetPlatform.Android,
|
||||||
TargetPlatform.Switch,
|
TargetPlatform.Switch,
|
||||||
|
TargetPlatform.Mac,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
60
Source/Tools/Flax.Build/Platforms/Mac/MacPlatform.cs
Normal file
60
Source/Tools/Flax.Build/Platforms/Mac/MacPlatform.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using Flax.Build.Projects;
|
||||||
|
|
||||||
|
namespace Flax.Build.Platforms
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The build platform for all Mac systems.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="Platform" />
|
||||||
|
public sealed class MacPlatform : Platform
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override TargetPlatform Target => TargetPlatform.Mac;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool HasRequiredSDKsInstalled { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool HasSharedLibrarySupport => true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ExecutableFileExtension => string.Empty;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string SharedLibraryFileExtension => ".dylib";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string StaticLibraryFileExtension => ".a";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ProgramDatabaseFileExtension => ".dSYM";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string SharedLibraryFilePrefix => string.Empty;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string StaticLibraryFilePrefix => "lib";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override ProjectFormat DefaultProjectFormat => ProjectFormat.XCode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Flax.Build.Platforms.MacPlatform"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public MacPlatform()
|
||||||
|
{
|
||||||
|
if (Platform.BuildTargetPlatform != TargetPlatform.Mac)
|
||||||
|
return;
|
||||||
|
|
||||||
|
throw new System.NotImplementedException("TODO: detect MacSDK installation");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override Toolchain CreateToolchain(TargetArchitecture architecture)
|
||||||
|
{
|
||||||
|
return new MacToolchain(this, architecture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs
Normal file
58
Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Flax.Build.Graph;
|
||||||
|
using Flax.Build.NativeCpp;
|
||||||
|
|
||||||
|
namespace Flax.Build.Platforms
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The build toolchain for all Mac systems.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="Toolchain" />
|
||||||
|
public sealed class MacToolchain : Toolchain
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MacToolchain"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="platform">The platform.</param>
|
||||||
|
/// <param name="architecture">The target architecture.</param>
|
||||||
|
public MacToolchain(MacPlatform platform, TargetArchitecture architecture)
|
||||||
|
: base(platform, architecture)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string DllExport => "__attribute__((__visibility__(\\\"default\\\")))";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string DllImport => "";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void LogInfo()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("TODO: MacToolchain.LogInfo");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void SetupEnvironment(BuildOptions options)
|
||||||
|
{
|
||||||
|
base.SetupEnvironment(options);
|
||||||
|
|
||||||
|
options.CompileEnv.PreprocessorDefinitions.Add("PLATFORM_MAC");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override CompileOutput CompileCppFiles(TaskGraph graph, BuildOptions options, List<string> sourceFiles, string outputPath)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("TODO: MacToolchain.CompileCppFiles");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void LinkFiles(TaskGraph graph, BuildOptions options, string outputFilePath)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("TODO: MacToolchain.LinkFiles");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,5 +41,10 @@ namespace Flax.Build.Projects
|
|||||||
/// Visual Studio Code.
|
/// Visual Studio Code.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
VisualStudioCode,
|
VisualStudioCode,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// XCode.
|
||||||
|
/// </summary>
|
||||||
|
XCode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ namespace Flax.Build.Projects
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ProjectFormat.VisualStudioCode: return new VisualStudioCodeProjectGenerator();
|
case ProjectFormat.VisualStudioCode: return new VisualStudioCodeProjectGenerator();
|
||||||
|
case ProjectFormat.XCode: return new XCodeProjectGenerator();
|
||||||
case ProjectFormat.Custom:
|
case ProjectFormat.Custom:
|
||||||
if (CustomProjectTypes.TryGetValue(Configuration.ProjectFormatCustom, out var factory))
|
if (CustomProjectTypes.TryGetValue(Configuration.ProjectFormatCustom, out var factory))
|
||||||
return factory(type);
|
return factory(type);
|
||||||
|
|||||||
49
Source/Tools/Flax.Build/Projects/XCode.cs
Normal file
49
Source/Tools/Flax.Build/Projects/XCode.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Flax.Build.Projects
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Project generator for XCode.
|
||||||
|
/// </summary>
|
||||||
|
public class XCodeProjectGenerator : ProjectGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="XCodeProjectGenerator"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public XCodeProjectGenerator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ProjectFileExtension => "xcodeproj";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string SolutionFileExtension => string.Empty;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override TargetType? Type => null;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Project CreateProject()
|
||||||
|
{
|
||||||
|
return new Project
|
||||||
|
{
|
||||||
|
Generator = this,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void GenerateProject(Project project)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("TODO: XCode");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void GenerateSolution(Solution solution)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("TODO: XCode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user