Archived
1
Fork 0
This repository has been archived on 2025-04-12. You can view files and clone it, but cannot push or open issues or pull requests.
prism/platforms/uikit/ViewController.mm.in

428 lines
12 KiB
Text
Raw Normal View History

#define VK_USE_PLATFORM_METAL_EXT
2022-02-18 14:36:38 -05:00
#import "QuartzCore/QuartzCore.hpp"
2022-08-15 11:09:43 -04:00
#include <GameController/GameController.h>
#include <MetalKit/MetalKit.h>
2020-08-11 12:07:21 -04:00
#import <UIKit/UIKit.h>
#include <@APP_INCLUDE@>
2022-08-15 11:09:43 -04:00
#include <engine.hpp>
2020-08-11 12:07:21 -04:00
#ifdef ENABLE_VULKAN
2022-08-15 11:09:43 -04:00
#ifdef PLATFORM_IOS
#define VK_USE_PLATFORM_IOS_MVK
#else
#define VK_USE_PLATFORM_TVOS_MVK
#endif
#include "gfx_vulkan.hpp"
#endif
#ifdef ENABLE_METAL
2022-08-15 11:09:43 -04:00
#include "gfx_metal.hpp"
#endif
#include "gfx_dummy.hpp"
2022-08-15 11:09:43 -04:00
@APP_CLASS@ * app = nullptr;
GFX* gfx_interface = nullptr;
2020-08-11 12:07:21 -04:00
int maxFPS = 60;
std::array<bool, 8> inputKeys;
float rightX = 0.0f, rightY = 0.0f;
float leftX = 0.0f, leftY = 0.0f;
#ifdef ENABLE_METAL
void* create_metal_surface(platform::window_ptr window, void* surface_creation_info);
void* get_next_metal_drawable(platform::window_ptr window);
#endif
#ifdef ENABLE_VULKAN
void* create_vulkan_surface(platform::window_ptr window, void* surface_creation_info);
#endif
2020-08-11 12:07:21 -04:00
@interface GameView : UIView
@end
@implementation GameView
2022-08-15 11:09:43 -04:00
+ (Class)layerClass {
2020-08-11 12:07:21 -04:00
return [CAMetalLayer class];
}
- (void)draw {
engine->update(1.0f / (float)maxFPS);
engine->begin_frame(1.0f / (float)maxFPS);
2022-02-18 14:36:38 -05:00
engine->render((void*)1);
engine->end_frame();
2020-08-11 12:07:21 -04:00
}
2022-08-15 11:09:43 -04:00
- (void)controllerConnected {
2020-08-11 12:07:21 -04:00
GCController* controller = [GCController controllers][0];
2022-08-15 11:09:43 -04:00
[[controller extendedGamepad]
setValueChangedHandler:^(GCExtendedGamepad* _Nonnull gamepad, GCControllerElement* _Nonnull element) {
const auto& handle_element = [element](int index, GCControllerElement* e) {
if (element == e)
inputKeys[index] = [(GCControllerButtonInput*)e value] == 1.0f;
};
handle_element(0, [[controller extendedGamepad] buttonA]);
handle_element(1, [[controller extendedGamepad] buttonB]);
handle_element(2, [[controller extendedGamepad] buttonX]);
handle_element(3, [[controller extendedGamepad] buttonY]);
if (element == [[controller extendedGamepad] dpad]) {
inputKeys[4] = [[[[controller extendedGamepad] dpad] up] value] == 1.0f;
inputKeys[5] = [[[[controller extendedGamepad] dpad] down] value] == 1.0f;
inputKeys[6] = [[[[controller extendedGamepad] dpad] left] value] == 1.0f;
inputKeys[7] = [[[[controller extendedGamepad] dpad] right] value] == 1.0f;
}
if (element == [[controller extendedGamepad] leftThumbstick]) {
leftX = [[[[controller extendedGamepad] leftThumbstick] xAxis] value];
leftY = [[[[controller extendedGamepad] leftThumbstick] yAxis] value];
}
if (element == [[controller extendedGamepad] rightThumbstick]) {
rightX = [[[[controller extendedGamepad] rightThumbstick] xAxis] value];
rightY = [[[[controller extendedGamepad] rightThumbstick] yAxis] value];
}
}];
2020-08-11 12:07:21 -04:00
}
@end
@interface GameViewController : UIViewController
@end
float mouse_x = 0.0f, mouse_y = 0.0f;
bool mouse_down = false;
2022-08-15 11:09:43 -04:00
@interface GameViewController () {
2020-08-11 12:07:21 -04:00
GameView* view;
}
2022-08-15 11:09:43 -04:00
2020-08-11 12:07:21 -04:00
@end
@implementation GameViewController
2022-08-15 11:09:43 -04:00
- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event {
2020-08-11 12:07:21 -04:00
UITouch* touch = [touches anyObject];
2022-08-15 11:09:43 -04:00
CGPoint touchPoint = [touch locationInView:self.view];
2020-08-11 12:07:21 -04:00
mouse_x = touchPoint.x;
mouse_y = touchPoint.y;
2022-08-15 11:09:43 -04:00
2020-08-11 12:07:21 -04:00
mouse_down = true;
engine->process_mouse_down(0, {static_cast<int32_t>(touchPoint.x), static_cast<int32_t>(touchPoint.y)});
}
2022-08-15 11:09:43 -04:00
- (void)touchesEnded:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event {
2020-08-11 12:07:21 -04:00
UITouch* touch = [touches anyObject];
2022-08-15 11:09:43 -04:00
CGPoint touchPoint = [touch locationInView:self.view];
2020-08-11 12:07:21 -04:00
mouse_x = touchPoint.x;
mouse_y = touchPoint.y;
2022-08-15 11:09:43 -04:00
2020-08-11 12:07:21 -04:00
mouse_down = false;
}
2022-08-15 11:09:43 -04:00
- (void)touchesMoved:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event {
2020-08-11 12:07:21 -04:00
UITouch* touch = [touches anyObject];
2022-08-15 11:09:43 -04:00
CGPoint touchPoint = [touch locationInView:self.view];
2020-08-11 12:07:21 -04:00
mouse_x = touchPoint.x;
mouse_y = touchPoint.y;
}
int width, height;
int drawable_width, drawable_height;
2022-02-18 14:36:38 -05:00
CAMetalLayer* layer;
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
template<class GFXBackend> void try_initialize() {
if (gfx_interface == nullptr) {
auto backend = new GFXBackend();
const bool supported = backend->is_supported() && platform::supports_context(backend->required_context());
2022-08-15 11:09:43 -04:00
if (!supported) {
prism::log("Failed to initialize GFX backend... trying next...");
} else {
gfx_interface = backend;
platform::initialize_context(gfx_interface->required_context());
}
}
}
2020-08-11 12:07:21 -04:00
- (void)viewDidLoad {
[super viewDidLoad];
view = (GameView*)self.view;
view.userInteractionEnabled = true;
2022-02-18 14:36:38 -05:00
layer = (CAMetalLayer*)view.layer;
2020-08-11 12:07:21 -04:00
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:view selector:@selector(draw)];
2022-02-18 14:36:38 -05:00
displayLink.preferredFramesPerSecond = [UIScreen mainScreen].maximumFramesPerSecond;
maxFPS = [UIScreen mainScreen].maximumFramesPerSecond;
2020-08-11 12:07:21 -04:00
[displayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSDefaultRunLoopMode];
2022-08-15 11:09:43 -04:00
2020-08-11 12:07:21 -04:00
width = [view frame].size.width;
height = [view frame].size.height;
2022-08-15 11:09:43 -04:00
2020-08-11 12:07:21 -04:00
drawable_width = [view frame].size.width * [view contentScaleFactor];
drawable_height = [view frame].size.height * [view contentScaleFactor];
2022-08-15 11:09:43 -04:00
2022-02-12 20:24:54 -05:00
engine = new prism::engine(0, nullptr);
2022-08-15 11:09:43 -04:00
#ifdef ENABLE_METAL
try_initialize<GFXMetal>();
#endif
2022-08-15 11:09:43 -04:00
#ifdef ENABLE_VULKAN
try_initialize<GFXVulkan>();
#endif
try_initialize<GFXDummy>();
GFXCreateInfo info = {};
2022-08-15 11:09:43 -04:00
if (gfx_interface->initialize(info)) {
engine->set_gfx(gfx_interface);
} else {
return -1;
}
2020-08-11 12:07:21 -04:00
app = new @APP_CLASS@();
app_main(engine);
engine->set_app(app);
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
engine->add_window(
(void*)CFBridgingRetain([view layer]), (void*)1, {static_cast<uint32_t>(width), static_cast<uint32_t>(height)});
2020-08-11 12:07:21 -04:00
app->initialize_render();
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
2022-08-15 11:09:43 -04:00
[nc addObserver:view selector:@selector(controllerConnected) name:GCControllerDidConnectNotification object:nil];
2020-08-11 12:07:21 -04:00
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
2022-08-15 11:09:43 -04:00
- (bool)prefersStatusBarHidden {
2020-08-11 12:07:21 -04:00
return YES;
}
@end
bool platform::supports_context(GFXContext context) {
#ifdef ENABLE_DX12
2022-08-15 11:09:43 -04:00
if (context == GFXContext::DirectX)
return true;
#endif
#ifdef ENABLE_VULKAN
2022-08-15 11:09:43 -04:00
if (context == GFXContext::Vulkan)
return true;
#endif
#ifdef ENABLE_METAL
2022-08-15 11:09:43 -04:00
if (context == GFXContext::Metal)
return true;
#endif
2022-08-15 11:09:43 -04:00
if (context == GFXContext::None)
return true;
return false;
}
2022-08-15 11:09:43 -04:00
void platform::initialize_context(const GFXContext context) {}
void* platform::get_context_information() {
#ifdef ENABLE_VULKAN
2022-08-15 11:09:43 -04:00
if (gfx_interface->required_context() == GFXContext::Vulkan) {
auto info = new vulkan_information();
info->surface_extensions = {VK_EXT_METAL_SURFACE_EXTENSION_NAME};
return (void*)info;
}
#endif
return nullptr;
}
void* platform::create_surface(window_ptr window, void* surface_creation_info) {
#ifdef ENABLE_VULKAN
2022-08-15 11:09:43 -04:00
if (gfx_interface->required_context() == GFXContext::Vulkan) {
return create_vulkan_surface(window, surface_creation_info);
}
#endif
#ifdef ENABLE_METAL
2022-08-15 11:09:43 -04:00
if (gfx_interface->required_context() == GFXContext::Metal) {
return create_metal_surface(window, surface_creation_info);
}
#endif
return nullptr;
}
void* platform::get_next_image(window_ptr window) {
#ifdef ENABLE_METAL
2022-08-15 11:09:43 -04:00
if (gfx_interface->required_context() == GFXContext::Metal) {
return get_next_metal_drawable(window);
}
#endif
return nullptr;
}
2022-08-15 11:09:43 -04:00
void platform::capture_mouse(const bool capture) {}
2020-08-11 12:07:21 -04:00
2022-02-12 20:24:54 -05:00
// TODO: unimplemented
PlatformTheme platform::get_theme() {
return PlatformTheme::Light;
}
void platform::begin_text_input() {
2022-08-15 11:09:43 -04:00
// TODO: stub
2022-02-12 20:24:54 -05:00
}
void platform::end_text_input() {
2022-08-15 11:09:43 -04:00
// TODO: stub
2022-02-12 20:24:54 -05:00
}
void* create_vulkan_surface(platform::window_ptr index, void* surface_creation_info) {
auto vulkan_surface_info = (vulkan_surface_creation_info*)surface_creation_info;
VkMetalSurfaceCreateInfoEXT surfaceInfo = {};
2022-02-12 20:52:10 -05:00
surfaceInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
surfaceInfo.pNext = 0;
surfaceInfo.flags = 0;
2022-02-18 14:36:38 -05:00
surfaceInfo.pLayer = layer;
2022-02-12 20:52:10 -05:00
auto vk_surface = new vulkan_surface();
vkCreateMetalSurfaceEXT((VkInstance)vulkan_surface_info->instance, &surfaceInfo, nullptr, &vk_surface->surface);
2022-02-12 20:52:10 -05:00
return vk_surface;
2022-02-18 14:36:38 -05:00
}
void* create_metal_surface(platform::window_ptr window, void* surface_creation_info) {
auto metal_surface_info = (metal_surface_creation_info*)surface_creation_info;
layer.device = (__bridge id<MTLDevice>)metal_surface_info->device;
2022-02-18 14:36:38 -05:00
layer.allowsNextDrawableTimeout = true;
auto return_surface = new metal_surface();
return_surface->format = static_cast<MTL::PixelFormat>(layer.pixelFormat);
return return_surface;
2022-02-18 14:36:38 -05:00
}
void* get_next_metal_drawable(platform::window_ptr window) {
auto drawable = (__bridge CA::MetalDrawable*)[layer nextDrawable];
drawable->retain();
return drawable;
2022-02-12 20:24:54 -05:00
}
bool platform::is_main_window(platform::window_ptr index) {
return true;
}
2022-08-15 11:09:43 -04:00
void platform::show_window(const platform::window_ptr index) {}
2022-02-12 20:24:54 -05:00
bool platform::supports_feature(const PlatformFeature feature) {
return false;
}
prism::Offset platform::get_cursor_position() {
2020-08-11 12:07:21 -04:00
return {static_cast<int32_t>(mouse_x), static_cast<int32_t>(mouse_y)};
}
std::tuple<float, float> platform::get_right_stick_position() {
return {rightX, rightY};
}
std::tuple<float, float> platform::get_left_stick_position() {
return {leftX, leftY};
}
bool platform::get_key_down(InputButton key) {
2022-08-15 11:09:43 -04:00
if (key == InputButton::ButtonA)
2020-08-11 12:07:21 -04:00
return inputKeys[0];
2022-08-15 11:09:43 -04:00
if (key == InputButton::ButtonB)
2020-08-11 12:07:21 -04:00
return inputKeys[1];
2022-08-15 11:09:43 -04:00
if (key == InputButton::ButtonX)
2020-08-11 12:07:21 -04:00
return inputKeys[2];
2022-08-15 11:09:43 -04:00
if (key == InputButton::ButtonY)
2020-08-11 12:07:21 -04:00
return inputKeys[3];
2022-08-15 11:09:43 -04:00
if (key == InputButton::DPadUp)
2020-08-11 12:07:21 -04:00
return inputKeys[4];
2022-08-15 11:09:43 -04:00
if (key == InputButton::DPadDown)
2020-08-11 12:07:21 -04:00
return inputKeys[5];
2022-08-15 11:09:43 -04:00
if (key == InputButton::DPadLeft)
2020-08-11 12:07:21 -04:00
return inputKeys[6];
2022-08-15 11:09:43 -04:00
if (key == InputButton::DPadRight)
2020-08-11 12:07:21 -04:00
return inputKeys[7];
2022-08-15 11:09:43 -04:00
return false;
2020-08-11 12:07:21 -04:00
}
2022-08-15 11:09:43 -04:00
platform::window_ptr
platform::open_window(const std::string_view title, const prism::Rectangle rect, const WindowFlags flags) {
return (void*)1;
2020-08-11 12:07:21 -04:00
}
2022-08-15 11:09:43 -04:00
void platform::set_window_title(const platform::window_ptr index, const std::string_view title) {}
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
bool platform::is_window_focused(const platform::window_ptr index) {}
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
void platform::set_window_focused(const platform::window_ptr index) {}
2020-08-11 12:07:21 -04:00
2022-02-12 20:24:54 -05:00
prism::Extent platform::get_window_size(const platform::window_ptr index) {
2020-08-11 12:07:21 -04:00
return {static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
}
2022-02-12 20:24:54 -05:00
prism::Extent platform::get_window_drawable_size(const platform::window_ptr index) {
2020-08-11 12:07:21 -04:00
return {static_cast<uint32_t>(drawable_width), static_cast<uint32_t>(drawable_height)};
}
2022-08-15 11:09:43 -04:00
prism::Offset platform::get_window_position(const platform::window_ptr index) {}
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
void platform::set_window_size(const platform::window_ptr index, const prism::Extent extent) {}
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
void platform::set_window_position(const platform::window_ptr index, const prism::Offset offset) {}
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
void platform::close_window(const platform::window_ptr index) {}
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
int platform::get_keycode(const InputButton button) {}
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
prism::Rectangle platform::get_monitor_resolution() {}
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
prism::Rectangle platform::get_monitor_work_area() {}
2020-08-11 12:07:21 -04:00
2022-08-15 11:09:43 -04:00
prism::Offset platform::get_screen_cursor_position() {}
2020-08-11 12:07:21 -04:00
bool platform::get_mouse_button_down(const int index) {
return mouse_down;
}
float platform::get_monitor_dpi() {
return 2.0f;
}
2022-08-15 11:09:43 -04:00
std::tuple<float, float> platform::get_wheel_delta() {}
2020-08-11 12:07:21 -04:00
const char* platform::get_name() {
return "iOS";
}