You're breathtaking!
This commit is contained in:
9
Source/Engine/Main/Android/android_native_app_glue.h
Normal file
9
Source/Engine/Main/Android/android_native_app_glue.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
|
||||
#include <../../../../../../../sources/android/native_app_glue/android_native_app_glue.h>
|
||||
|
||||
#endif
|
||||
16
Source/Engine/Main/Android/main.cpp
Normal file
16
Source/Engine/Main/Android/main.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
|
||||
#include "Engine/Engine/Engine.h"
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include <../../../../../../../sources/android/native_app_glue/android_native_app_glue.h>
|
||||
#include <../../../../../../../sources/android/native_app_glue/android_native_app_glue.c>
|
||||
|
||||
void android_main(android_app* app)
|
||||
{
|
||||
AndroidPlatform::PreInit(app);
|
||||
Engine::Main(TEXT(""));
|
||||
}
|
||||
|
||||
#endif
|
||||
24
Source/Engine/Main/Linux/main.cpp
Normal file
24
Source/Engine/Main/Linux/main.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
|
||||
#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
|
||||
75
Source/Engine/Main/Main.Build.cs
Normal file
75
Source/Engine/Main/Main.Build.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Flax.Build;
|
||||
using Flax.Build.NativeCpp;
|
||||
|
||||
/// <summary>
|
||||
/// Application startup module.
|
||||
/// </summary>
|
||||
public class Main : EngineModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void Setup(BuildOptions options)
|
||||
{
|
||||
base.Setup(options);
|
||||
|
||||
// Use source folder per platform group
|
||||
options.SourcePaths.Clear();
|
||||
switch (options.Platform.Target)
|
||||
{
|
||||
case TargetPlatform.Windows:
|
||||
options.SourcePaths.Add(Path.Combine(FolderPath, "Windows"));
|
||||
|
||||
// Visual Leak Detector (https://kinddragon.github.io/vld/)
|
||||
/*{
|
||||
var vldPath = @"C:\Program Files (x86)\Visual Leak Detector";
|
||||
var vldBinaries = options.Toolchain.Architecture == TargetArchitecture.x64 ? "Win64" : "Win32";
|
||||
var vldBinariesPostfix = options.Toolchain.Architecture == TargetArchitecture.x64 ? "x64" : "x86";
|
||||
options.PrivateDefinitions.Add("USE_VLD_MEM_LEAKS_CHECK");
|
||||
options.PrivateDefinitions.Add("VLD_FORCE_ENABLE");
|
||||
options.PrivateIncludePaths.Add(Path.Combine(vldPath, "include"));
|
||||
options.OutputFiles.Add(Path.Combine(vldPath, "lib", vldBinaries, "vld.lib"));
|
||||
options.DependencyFiles.Add(Path.Combine(vldPath, "bin", vldBinaries, "vld_" + vldBinariesPostfix + ".dll"));
|
||||
options.DependencyFiles.Add(Path.Combine(vldPath, "bin", vldBinaries, "vld_" + vldBinariesPostfix + ".pdb"));
|
||||
options.DependencyFiles.Add(Path.Combine(vldPath, "bin", vldBinaries, "dbghelp.dll"));
|
||||
options.DependencyFiles.Add(Path.Combine(vldPath, "bin", vldBinaries, "Microsoft.DTfW.DHL.manifest"));
|
||||
}*/
|
||||
|
||||
// Visual Studio memory leaks detection
|
||||
/*{
|
||||
options.PrivateDefinitions.Add("USE_VS_MEM_LEAKS_CHECK");
|
||||
}*/
|
||||
|
||||
break;
|
||||
case TargetPlatform.XboxOne:
|
||||
case TargetPlatform.UWP:
|
||||
options.SourcePaths.Add(Path.Combine(FolderPath, "UWP"));
|
||||
|
||||
// Use Visual C++ component extensions C++/CX for UWP
|
||||
options.CompileEnv.WinRTComponentExtensions = true;
|
||||
options.CompileEnv.GenerateDocumentation = true;
|
||||
|
||||
break;
|
||||
case TargetPlatform.Linux:
|
||||
options.SourcePaths.Add(Path.Combine(FolderPath, "Linux"));
|
||||
break;
|
||||
case TargetPlatform.PS4:
|
||||
options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "PS4", "Engine", "Main"));
|
||||
break;
|
||||
case TargetPlatform.XboxScarlett:
|
||||
options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "XboxScarlett", "Engine", "Main"));
|
||||
break;
|
||||
case TargetPlatform.Android:
|
||||
options.SourcePaths.Add(Path.Combine(FolderPath, "Android"));
|
||||
break;
|
||||
default: throw new InvalidPlatformException(options.Platform.Target);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void GetFilesToDeploy(List<string> files)
|
||||
{
|
||||
}
|
||||
}
|
||||
443
Source/Engine/Main/UWP/main.cpp
Normal file
443
Source/Engine/Main/UWP/main.cpp
Normal file
@@ -0,0 +1,443 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if PLATFORM_UWP
|
||||
|
||||
// @formatter:off
|
||||
|
||||
#include "main.h"
|
||||
#include <sal.h>
|
||||
|
||||
// Use better GPU
|
||||
extern "C" {
|
||||
_declspec(dllexport) unsigned int NvOptimusEnablement = 0x00000001;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||
}
|
||||
|
||||
using namespace Windows::ApplicationModel;
|
||||
using namespace Windows::ApplicationModel::Activation;
|
||||
using namespace Windows::ApplicationModel::Core;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Graphics::Display;
|
||||
using namespace Windows::UI;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Input;
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
using namespace Windows::Devices::Input;
|
||||
using namespace Windows::Gaming::Input;
|
||||
using namespace Windows::System;
|
||||
using namespace Platform;
|
||||
using namespace FlaxEngine;
|
||||
|
||||
Game::Game()
|
||||
{
|
||||
PlatformImpl::Init();
|
||||
}
|
||||
|
||||
void Game::Initialize(CoreApplicationView^ applicationView)
|
||||
{
|
||||
applicationView->Activated += ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &Game::OnActivated);
|
||||
CoreApplication::Suspending += ref new EventHandler<SuspendingEventArgs^>(this, &Game::OnSuspending);
|
||||
CoreApplication::Resuming += ref new EventHandler<Platform::Object^>(this, &Game::OnResuming);
|
||||
}
|
||||
|
||||
void Game::SetWindow(Windows::UI::Core::CoreWindow^ window)
|
||||
{
|
||||
PlatformImpl::InitWindow(window);
|
||||
|
||||
PointerVisualizationSettings^ visualizationSettings = PointerVisualizationSettings::GetForCurrentView();
|
||||
visualizationSettings->IsContactFeedbackEnabled = false;
|
||||
visualizationSettings->IsBarrelButtonFeedbackEnabled = false;
|
||||
}
|
||||
|
||||
void Game::Run()
|
||||
{
|
||||
RunUWP();
|
||||
}
|
||||
|
||||
void Game::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
|
||||
{
|
||||
CoreWindow^ window = CoreWindow::GetForCurrentThread();
|
||||
window->Activate();
|
||||
}
|
||||
|
||||
void Game::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
|
||||
{
|
||||
/*
|
||||
// Save app state asynchronously after requesting a deferral. Holding a deferral
|
||||
// indicates that the application is busy performing suspending operations. Be
|
||||
// aware that a deferral may not be held indefinitely. After about five seconds,
|
||||
// the app will be forced to exit.
|
||||
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
|
||||
|
||||
create_task([this, deferral]()
|
||||
{
|
||||
m_deviceResources->Trim();
|
||||
|
||||
m_main->Suspend();
|
||||
|
||||
deferral->Complete();
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
void Game::OnResuming(Platform::Object^ sender, Platform::Object^ args)
|
||||
{
|
||||
// Restore any data or state that was unloaded on suspend. By default, data
|
||||
// and state are persisted when resuming from suspend. Note that this event
|
||||
// does not occur if the app was previously terminated.
|
||||
// TODO: m_main->Resume();
|
||||
}
|
||||
|
||||
PlatformImpl MainPlatform;
|
||||
WindowImpl MainWindow;
|
||||
|
||||
void WindowEvents::Register(WindowImpl* win)
|
||||
{
|
||||
_win = win;
|
||||
|
||||
auto window = win->Window;
|
||||
|
||||
window->Activated += ref new TypedEventHandler<CoreWindow^, WindowActivatedEventArgs^>(this, &WindowEvents::OnActivationChanged);
|
||||
window->SizeChanged += ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &WindowEvents::OnSizeChanged);
|
||||
window->Closed += ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &WindowEvents::OnClosed);
|
||||
window->VisibilityChanged += ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &WindowEvents::OnVisibilityChanged);
|
||||
window->PointerPressed += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &WindowEvents::OnPointerPressed);
|
||||
window->PointerMoved += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &WindowEvents::OnPointerMoved);
|
||||
window->PointerWheelChanged += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &WindowEvents::OnPointerWheelChanged);
|
||||
window->PointerReleased += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &WindowEvents::OnPointerReleased);
|
||||
window->PointerExited += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &WindowEvents::OnPointerExited);
|
||||
window->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &WindowEvents::OnKeyDown);
|
||||
window->KeyUp += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &WindowEvents::OnKeyUp);
|
||||
window->CharacterReceived += ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &WindowEvents::OnCharacterReceived);
|
||||
|
||||
MouseDevice::GetForCurrentView()->MouseMoved += ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &WindowEvents::OnMouseMoved);
|
||||
|
||||
DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
|
||||
currentDisplayInformation->DpiChanged += ref new TypedEventHandler<DisplayInformation^, Platform::Object^>(this, &WindowEvents::OnDisplayDpiChanged);
|
||||
currentDisplayInformation->OrientationChanged += ref new TypedEventHandler<DisplayInformation^, Object^>(this, &WindowEvents::OnOrientationChanged);
|
||||
currentDisplayInformation->StereoEnabledChanged += ref new TypedEventHandler<DisplayInformation^, Platform::Object^>(this, &WindowEvents::OnStereoEnabledChanged);
|
||||
DisplayInformation::DisplayContentsInvalidated += ref new TypedEventHandler<DisplayInformation^, Platform::Object^>(this, &WindowEvents::OnDisplayContentsInvalidated);
|
||||
|
||||
// Detect gamepad connection and disconnection events
|
||||
Gamepad::GamepadAdded += ref new EventHandler<Gamepad^>(this, &WindowEvents::OnGamepadAdded);
|
||||
Gamepad::GamepadRemoved += ref new EventHandler<Gamepad^>(this, &WindowEvents::OnGamepadRemoved);
|
||||
}
|
||||
|
||||
void WindowEvents::OnActivationChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowActivatedEventArgs^ args)
|
||||
{
|
||||
bool hasFocus;
|
||||
if (args->WindowActivationState == Windows::UI::Core::CoreWindowActivationState::Deactivated)
|
||||
hasFocus = false;
|
||||
else if (args->WindowActivationState == Windows::UI::Core::CoreWindowActivationState::CodeActivated
|
||||
|| args->WindowActivationState == Windows::UI::Core::CoreWindowActivationState::PointerActivated)
|
||||
hasFocus = true;
|
||||
|
||||
if (_win->FocusChanged)
|
||||
_win->FocusChanged(hasFocus, _win->UserData);
|
||||
}
|
||||
|
||||
void WindowEvents::OnSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args)
|
||||
{
|
||||
if (_win->SizeChanged)
|
||||
_win->SizeChanged(args->Size.Width, args->Size.Height, _win->UserData);
|
||||
}
|
||||
|
||||
void WindowEvents::OnClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args)
|
||||
{
|
||||
if (_win->Closed)
|
||||
_win->Closed(_win->UserData);
|
||||
}
|
||||
|
||||
void WindowEvents::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args)
|
||||
{
|
||||
if (_win->VisibilityChanged)
|
||||
_win->VisibilityChanged(args->Visible, _win->UserData);
|
||||
}
|
||||
|
||||
void WindowEvents::OnStereoEnabledChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args)
|
||||
{
|
||||
//m_deviceResources->UpdateStereoState();
|
||||
//m_main->CreateWindowSizeDependentResources();
|
||||
}
|
||||
|
||||
void WindowEvents::OnDisplayDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args)
|
||||
{
|
||||
if (_win->DpiChanged)
|
||||
_win->DpiChanged(sender->LogicalDpi, _win->UserData);
|
||||
}
|
||||
|
||||
void WindowEvents::OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args)
|
||||
{
|
||||
//m_deviceResources->SetCurrentOrientation(sender->CurrentOrientation);
|
||||
//m_main->CreateWindowSizeDependentResources();
|
||||
}
|
||||
|
||||
void WindowEvents::OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args)
|
||||
{
|
||||
//m_deviceResources->ValidateDevice();
|
||||
}
|
||||
|
||||
void WindowEvents::OnGamepadAdded(Object^ sender, Gamepad^ gamepad)
|
||||
{
|
||||
//_win->GamepadsChanged = true;
|
||||
}
|
||||
|
||||
void WindowEvents::OnGamepadRemoved(Object^ sender, Gamepad^ gamepad)
|
||||
{
|
||||
//_win->GamepadsChanged = true;
|
||||
}
|
||||
|
||||
void GetPointerData(UWPWindowImpl::PointerData & data, PointerEventArgs^ args)
|
||||
{
|
||||
PointerPoint^ point = args->CurrentPoint;
|
||||
Point pointerPosition = point->Position;
|
||||
PointerPointProperties^ pointProperties = point->Properties;
|
||||
auto pointerDevice = point->PointerDevice;
|
||||
auto pointerDeviceType = pointerDevice->PointerDeviceType;
|
||||
|
||||
data.PointerId = point->PointerId;
|
||||
data.PositionX = pointerPosition.X;
|
||||
data.PositionY = pointerPosition.Y;
|
||||
data.MouseWheelDelta = pointProperties->MouseWheelDelta;
|
||||
data.IsLeftButtonPressed = pointProperties->IsLeftButtonPressed;
|
||||
data.IsMiddleButtonPressed = pointProperties->IsMiddleButtonPressed;
|
||||
data.IsRightButtonPressed = pointProperties->IsRightButtonPressed;
|
||||
data.IsXButton1Pressed = pointProperties->IsXButton1Pressed;
|
||||
data.IsXButton2Pressed = pointProperties->IsXButton2Pressed;
|
||||
|
||||
data.IsMouse = pointerDeviceType == PointerDeviceType::Mouse;
|
||||
data.IsPen = pointerDeviceType == PointerDeviceType::Pen;
|
||||
data.IsTouch = pointerDeviceType == PointerDeviceType::Touch;
|
||||
|
||||
args->Handled = true;
|
||||
}
|
||||
|
||||
void WindowEvents::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
if (_win->PointerPressed)
|
||||
{
|
||||
UWPWindowImpl::PointerData data;
|
||||
GetPointerData(data, args);
|
||||
_win->PointerPressed(&data, _win->UserData);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEvents::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
if (_win->PointerMoved)
|
||||
{
|
||||
UWPWindowImpl::PointerData data;
|
||||
GetPointerData(data, args);
|
||||
_win->PointerMoved(&data, _win->UserData);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEvents::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
if (_win->PointerWheelChanged)
|
||||
{
|
||||
UWPWindowImpl::PointerData data;
|
||||
GetPointerData(data, args);
|
||||
_win->PointerWheelChanged(&data, _win->UserData);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEvents::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
if (_win->PointerReleased)
|
||||
{
|
||||
UWPWindowImpl::PointerData data;
|
||||
GetPointerData(data, args);
|
||||
_win->PointerReleased(&data, _win->UserData);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEvents::OnPointerExited(CoreWindow^ sender, PointerEventArgs^ args)
|
||||
{
|
||||
if (_win->PointerExited)
|
||||
{
|
||||
UWPWindowImpl::PointerData data;
|
||||
GetPointerData(data, args);
|
||||
_win->PointerExited(&data, _win->UserData);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEvents::OnKeyDown(CoreWindow^ sender, KeyEventArgs^ args)
|
||||
{
|
||||
if (_win->KeyDown)
|
||||
{
|
||||
_win->KeyDown((int)args->VirtualKey, _win->UserData);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEvents::OnKeyUp(CoreWindow^ sender, KeyEventArgs^ args)
|
||||
{
|
||||
if (_win->KeyUp)
|
||||
{
|
||||
_win->KeyUp((int)args->VirtualKey, _win->UserData);
|
||||
args->Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEvents::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ args)
|
||||
{
|
||||
if (_win->CharacterReceived)
|
||||
{
|
||||
_win->CharacterReceived(args->KeyCode, _win->UserData);
|
||||
args->Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEvents::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
|
||||
{
|
||||
if (_win->MouseMoved)
|
||||
{
|
||||
Point point = _win->Window->PointerPosition;
|
||||
_win->MouseMoved(point.X, point.Y, _win->UserData);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowImpl::Init(CoreWindow^ window)
|
||||
{
|
||||
Window = window;
|
||||
Events = ref new WindowEvents();
|
||||
|
||||
window->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
|
||||
|
||||
PointerVisualizationSettings^ visualizationSettings = PointerVisualizationSettings::GetForCurrentView();
|
||||
visualizationSettings->IsContactFeedbackEnabled = false;
|
||||
visualizationSettings->IsBarrelButtonFeedbackEnabled = false;
|
||||
|
||||
Events->Register(this);
|
||||
}
|
||||
|
||||
void WindowImpl::SetGamepadVibration(const int index, UWPGamepadStateVibration& vibration)
|
||||
{
|
||||
auto gamepads = Gamepad::Gamepads;
|
||||
if (index >= (int)gamepads->Size)
|
||||
return;
|
||||
auto gamepad = gamepads->GetAt(index);
|
||||
|
||||
GamepadVibration gamepadVibration;
|
||||
gamepadVibration.LeftMotor = vibration.LeftLarge;
|
||||
gamepadVibration.RightMotor = vibration.RightLarge;
|
||||
gamepadVibration.LeftTrigger = vibration.LeftSmall;
|
||||
gamepadVibration.RightTrigger = vibration.RightSmall;
|
||||
gamepad->Vibration = gamepadVibration;
|
||||
}
|
||||
|
||||
void WindowImpl::GetGamepadState(const int index, UWPGamepadState& state)
|
||||
{
|
||||
auto gamepads = Gamepad::Gamepads;
|
||||
if (index >= (int)gamepads->Size)
|
||||
return;
|
||||
auto gamepad = gamepads->GetAt(index);
|
||||
|
||||
GamepadReading reading = gamepad->GetCurrentReading();
|
||||
|
||||
state.Buttons = (int)reading.Buttons;
|
||||
state.LeftThumbstickX = (float)reading.LeftThumbstickX;
|
||||
state.LeftThumbstickY = (float)reading.LeftThumbstickY;
|
||||
state.RightThumbstickX = (float)reading.RightThumbstickX;
|
||||
state.RightThumbstickY = (float)reading.RightThumbstickY;
|
||||
state.LeftTrigger = (float)reading.LeftTrigger;
|
||||
state.RightTrigger = (float)reading.LeftTrigger;
|
||||
}
|
||||
|
||||
void PlatformImpl::Init()
|
||||
{
|
||||
// Register UWP platform implementation for the FlaxEngine API
|
||||
CUWPPlatform = &MainPlatform;
|
||||
}
|
||||
|
||||
void PlatformImpl::InitWindow(Windows::UI::Core::CoreWindow^ window)
|
||||
{
|
||||
MainWindow.Init(window);
|
||||
}
|
||||
|
||||
UWPWindowImpl* PlatformImpl::GetMainWindowImpl()
|
||||
{
|
||||
return &MainWindow;
|
||||
}
|
||||
|
||||
void PlatformImpl::Tick()
|
||||
{
|
||||
CoreWindow^ window = CoreWindow::GetForCurrentThread();
|
||||
window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
|
||||
}
|
||||
|
||||
int PlatformImpl::GetDpi()
|
||||
{
|
||||
auto currentDisplayInformation = Windows::Graphics::Display::DisplayInformation::GetForCurrentView();
|
||||
return (int)currentDisplayInformation->LogicalDpi;
|
||||
}
|
||||
|
||||
int PlatformImpl::GetSpecialFolderPath(const SpecialFolder type, wchar_t* buffer, int bufferLength)
|
||||
{
|
||||
String^ path = nullptr;
|
||||
switch (type)
|
||||
{
|
||||
case SpecialFolder::Desktop:
|
||||
path = Windows::Storage::KnownFolders::DocumentsLibrary->Path + "/../Desktop";
|
||||
break;
|
||||
case SpecialFolder::Documents:
|
||||
path = Windows::Storage::KnownFolders::DocumentsLibrary->Path;
|
||||
break;
|
||||
case SpecialFolder::Pictures:
|
||||
path = Windows::Storage::KnownFolders::PicturesLibrary->Path;
|
||||
break;
|
||||
case SpecialFolder::AppData:
|
||||
path = Windows::Storage::ApplicationData::Current->RoamingFolder->Path;
|
||||
break;
|
||||
case SpecialFolder::LocalAppData:
|
||||
path = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
|
||||
break;
|
||||
case SpecialFolder::ProgramData:
|
||||
break;
|
||||
//case SpecialFolder::Temporary: path = Windows::Storage::ApplicationData::Current->TemporaryFolder->Path; break;
|
||||
case SpecialFolder::Temporary:
|
||||
path = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
|
||||
break;
|
||||
}
|
||||
|
||||
if (path != nullptr)
|
||||
{
|
||||
int length = path->Length();
|
||||
if (length >= bufferLength)
|
||||
length = bufferLength - 1;
|
||||
const wchar_t* data = path->Data();
|
||||
for (int i = 0; i<length; i++)
|
||||
buffer[i] = data[i];
|
||||
buffer[length] = 0;
|
||||
return length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PlatformImpl::GetDisplaySize(float* width, float* height)
|
||||
{
|
||||
auto bounds = ApplicationView::GetForCurrentView()->VisibleBounds;
|
||||
auto scaleFactor = DisplayInformation::GetForCurrentView()->RawPixelsPerViewPixel;
|
||||
*width = (float)(bounds.Width * scaleFactor);
|
||||
*height = (float)(bounds.Height * scaleFactor);
|
||||
}
|
||||
|
||||
UWPPlatformImpl::DialogResult PlatformImpl::ShowMessageDialog(UWPWindowImpl* window, const wchar_t* text, const wchar_t* caption, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||
{
|
||||
Platform::String^ content = ref new Platform::String(text);
|
||||
Platform::String^ title = ref new Platform::String(caption);
|
||||
Windows::UI::Popups::MessageDialog^ msg = ref new Windows::UI::Popups::MessageDialog(content, title);
|
||||
|
||||
// TODO: implement buttons
|
||||
// TODO: gather result
|
||||
|
||||
msg->ShowAsync();
|
||||
|
||||
return DialogResult::OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
266
Source/Engine/Main/UWP/main.h
Normal file
266
Source/Engine/Main/UWP/main.h
Normal file
@@ -0,0 +1,266 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PLATFORM_UWP
|
||||
|
||||
#include "Engine/Platform/UWP/UWPPlatformImpl.h"
|
||||
|
||||
// @formatter:off
|
||||
|
||||
class WindowImpl;
|
||||
|
||||
namespace FlaxEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// The helper bridge interface to initialize and run a game.
|
||||
/// </summary>
|
||||
public ref class Game sealed
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Game"/> class.
|
||||
/// </summary>
|
||||
Game();
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// A method for app view initialization, which is called when an app object is launched.
|
||||
/// </summary>
|
||||
/// <param name="applicationView">The default view provided by the app object. You can use this instance in your implementation to obtain the CoreWindow created by the app object, and register callbacks for the Activated event.</param>
|
||||
void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
|
||||
|
||||
/// <summary>
|
||||
/// A method that sets the current window for the game rendering output.
|
||||
/// </summary>
|
||||
/// <param name="window">The current window for the app object.</param>
|
||||
void SetWindow(Windows::UI::Core::CoreWindow^ window);
|
||||
|
||||
/// <summary>
|
||||
/// A method that starts the game.
|
||||
/// </summary>
|
||||
void Run();
|
||||
|
||||
private:
|
||||
|
||||
// Application lifecycle event handlers
|
||||
void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
|
||||
void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args);
|
||||
void OnResuming(Platform::Object^ sender, Platform::Object^ args);
|
||||
};
|
||||
}
|
||||
|
||||
namespace FlaxEngine
|
||||
{
|
||||
private ref class WindowEvents sealed
|
||||
{
|
||||
friend WindowImpl;
|
||||
|
||||
private:
|
||||
|
||||
WindowImpl* _win;
|
||||
|
||||
private:
|
||||
|
||||
void Register(WindowImpl* win);
|
||||
|
||||
private:
|
||||
|
||||
void OnActivationChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowActivatedEventArgs^ args);
|
||||
void OnSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
|
||||
void OnClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
|
||||
void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
|
||||
void OnStereoEnabledChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
void OnDisplayDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerExited(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
void OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args);
|
||||
void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouseDevice, Windows::Devices::Input::MouseEventArgs^ args);
|
||||
void OnGamepadAdded(Platform::Object^ sender, Windows::Gaming::Input::Gamepad^ gamepad);
|
||||
void OnGamepadRemoved(Platform::Object^ sender, Windows::Gaming::Input::Gamepad^ gamepad);
|
||||
};
|
||||
}
|
||||
|
||||
class WindowImpl : public UWPWindowImpl
|
||||
{
|
||||
public:
|
||||
|
||||
//Platform::Agile<Windows::UI::Core::CoreWindow> Window
|
||||
Windows::UI::Core::CoreWindow^ Window;
|
||||
FlaxEngine::WindowEvents^ Events;
|
||||
|
||||
public:
|
||||
|
||||
void Init(Windows::UI::Core::CoreWindow^ window);
|
||||
|
||||
public:
|
||||
|
||||
// [UWPWindowImpl]
|
||||
void* GetHandle() const override
|
||||
{
|
||||
//return (void*)reinterpret_cast<IUnknown*>(Window.Get());
|
||||
//return (void*)reinterpret_cast<IUnknown*>(Window);
|
||||
return reinterpret_cast<void*>(Window);
|
||||
}
|
||||
|
||||
void SetMousePosition(float x, float y) override
|
||||
{
|
||||
Window->PointerPosition = Windows::Foundation::Point(x, y);
|
||||
}
|
||||
|
||||
void GetMousePosition(float* x, float* y) override
|
||||
{
|
||||
Windows::Foundation::Point point = Window->PointerPosition;
|
||||
*x = point.X;
|
||||
*y = point.Y;
|
||||
}
|
||||
|
||||
void SetCursor(CursorType type) override
|
||||
{
|
||||
auto window = Windows::UI::Core::CoreWindow::GetForCurrentThread();
|
||||
if (window == nullptr)
|
||||
return;
|
||||
if (type == CursorType::Hidden)
|
||||
{
|
||||
// TODO: use custom cursor with empty image, when PointerCursor is null mouse events are not passed to the window events
|
||||
window->PointerCursor = ref new Windows::UI::Core::CoreCursor(Windows::UI::Core::CoreCursorType::Arrow, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Windows::UI::Core::CoreCursorType uwpType;
|
||||
switch (type)
|
||||
{
|
||||
case CursorType::Cross:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::Cross;
|
||||
break;
|
||||
case CursorType::Hand:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::Hand;
|
||||
break;
|
||||
case CursorType::Help:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::Help;
|
||||
break;
|
||||
case CursorType::IBeam:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::IBeam;
|
||||
break;
|
||||
case CursorType::No:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::UniversalNo;
|
||||
break;
|
||||
case CursorType::Wait:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::Wait;
|
||||
break;
|
||||
case CursorType::SizeAll:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::SizeAll;
|
||||
break;
|
||||
case CursorType::SizeNESW:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::SizeNortheastSouthwest;
|
||||
break;
|
||||
case CursorType::SizeNS:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::SizeNorthSouth;
|
||||
break;
|
||||
case CursorType::SizeNWSE:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::SizeNorthwestSoutheast;
|
||||
break;
|
||||
case CursorType::SizeWE:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::SizeWestEast;
|
||||
break;
|
||||
default:
|
||||
uwpType = Windows::UI::Core::CoreCursorType::Arrow;
|
||||
break;
|
||||
}
|
||||
window->PointerCursor = ref new Windows::UI::Core::CoreCursor(uwpType, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GetBounds(float* x, float* y, float* width, float* height) override
|
||||
{
|
||||
auto bounds = Window->Bounds;
|
||||
*x = bounds.X;
|
||||
*y = bounds.Y;
|
||||
*width = bounds.Width;
|
||||
*height = bounds.Height;
|
||||
}
|
||||
|
||||
void GetDpi(float* dpi) override
|
||||
{
|
||||
auto currentDisplayInformation = Windows::Graphics::Display::DisplayInformation::GetForCurrentView();
|
||||
*dpi = currentDisplayInformation->LogicalDpi;
|
||||
}
|
||||
|
||||
void GetTitle(wchar_t* buffer, int bufferLength) override
|
||||
{
|
||||
auto appView = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
|
||||
auto title = appView->Title;
|
||||
|
||||
if (title)
|
||||
{
|
||||
int length = title->Length();
|
||||
if (length >= bufferLength)
|
||||
length = bufferLength - 1;
|
||||
const wchar_t* data = title->Data();
|
||||
for (int i = 0; i < length; i++)
|
||||
buffer[i] = data[i];
|
||||
buffer[length] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SetTitle(const wchar_t* title) override
|
||||
{
|
||||
auto appView = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
|
||||
appView->Title = ref new Platform::String(title);
|
||||
}
|
||||
|
||||
int GetGamepadsCount()
|
||||
{
|
||||
return Windows::Gaming::Input::Gamepad::Gamepads->Size;
|
||||
}
|
||||
|
||||
void SetGamepadVibration(const int index, UWPGamepadStateVibration& vibration) override;
|
||||
void GetGamepadState(const int index, UWPGamepadState& state) override;
|
||||
|
||||
void Activate() override
|
||||
{
|
||||
Window->Activate();
|
||||
}
|
||||
|
||||
void Close() override
|
||||
{
|
||||
Window->Close();
|
||||
}
|
||||
};
|
||||
|
||||
class PlatformImpl : public UWPPlatformImpl
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Registers platform.
|
||||
/// </summary>
|
||||
static void Init();
|
||||
|
||||
static void InitWindow(Windows::UI::Core::CoreWindow^ window);
|
||||
|
||||
public:
|
||||
|
||||
// [UWPPlatformImpl]
|
||||
UWPWindowImpl* GetMainWindowImpl() override;
|
||||
void Tick() override;
|
||||
int GetDpi() override;
|
||||
int GetSpecialFolderPath(const SpecialFolder type, wchar_t* buffer, int bufferLength) override;
|
||||
void GetDisplaySize(float* width, float* height) override;
|
||||
DialogResult ShowMessageDialog(UWPWindowImpl* window, const wchar_t* text, const wchar_t* caption, MessageBoxButtons buttons, MessageBoxIcon icon) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
54
Source/Engine/Main/Windows/main.cpp
Normal file
54
Source/Engine/Main/Windows/main.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
#ifdef USE_VLD_MEM_LEAKS_CHECK
|
||||
#include <vld.h>
|
||||
#endif
|
||||
#ifdef USE_VS_MEM_LEAKS_CHECK
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "Engine/Engine/Engine.h"
|
||||
#include "Engine/Platform/Win32/IncludeWindowsHeaders.h"
|
||||
|
||||
// Favor the high performance NVIDIA GPU if there are multiple GPUs
|
||||
extern "C" {
|
||||
_declspec(dllexport) uint32 NvOptimusEnablement = 0x00000001;
|
||||
}
|
||||
|
||||
// Favor the high performance AMD GPU if there are multiple GPUs
|
||||
extern "C" {
|
||||
__declspec(dllexport) int32 AmdPowerXpressRequestHighPerformance = 1;
|
||||
}
|
||||
|
||||
extern LONG CALLBACK SehExceptionHandler(EXCEPTION_POINTERS* ep);
|
||||
|
||||
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
#ifdef USE_VS_MEM_LEAKS_CHECK
|
||||
// Memory leaks detect inside VS
|
||||
int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||
flag |= _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF;
|
||||
_CrtSetDbgFlag(flag);
|
||||
#endif
|
||||
|
||||
#ifdef USE_VLD_MEM_LEAKS_CHECK
|
||||
VLDGlobalEnable();
|
||||
#endif
|
||||
|
||||
Platform::PreInit(hInstance);
|
||||
__try
|
||||
{
|
||||
return Engine::Main(lpCmdLine);
|
||||
}
|
||||
__except (SehExceptionHandler(GetExceptionInformation()))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user