diff options
Diffstat (limited to 'platform')
48 files changed, 593 insertions, 1289 deletions
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 6d021ad33a..4194e129ef 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -220,6 +220,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String name; String description; int api_level; + bool usb; }; struct APKExportData { @@ -246,17 +247,20 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String devices; List<String> args; args.push_back("devices"); + args.push_back("-l"); int ec; OS::get_singleton()->execute(adb, args, true, NULL, &devices, &ec); Vector<String> ds = devices.split("\n"); Vector<String> ldevices; + Vector<bool> ldevices_usbconnection; for (int i = 1; i < ds.size(); i++) { String d = ds[i]; - int dpos = d.find("device"); + int dpos = d.find(" device "); if (dpos == -1) continue; + ldevices_usbconnection.push_back(d.find(" usb:") != -1); d = d.substr(0, dpos).strip_edges(); ldevices.push_back(d); } @@ -287,6 +291,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { Device d; d.id = ldevices[i]; + d.usb = ldevices_usbconnection[i]; for (int j = 0; j < ea->devices.size(); j++) { if (ea->devices[j].id == ldevices[i]) { d.description = ea->devices[j].description; @@ -341,9 +346,17 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } else if (p.begins_with("ro.opengles.version=")) { uint32_t opengl = p.get_slice("=", 1).to_int(); d.description += "OpenGL: " + itos(opengl >> 16) + "." + itos((opengl >> 8) & 0xFF) + "." + itos((opengl)&0xFF) + "\n"; + } else if (p.begins_with("ro.boot.serialno=")) { + d.description += "Serial: " + p.get_slice("=", 1).strip_edges() + "\n"; } } + if (d.usb) { + d.description += "Connection: USB\n"; + } else { + d.description += "Connection: " + d.id + "\n"; + } + d.name = vendor + " " + device; if (device == String()) continue; } @@ -1415,7 +1428,9 @@ public: } const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT); - const bool use_reverse = devices[p_device].api_level >= 21; + const bool use_reverse = devices[p_device].api_level >= 21 && devices[p_device].usb; + // Note: Reverse can still fail if device is connected by both usb and network + // Ideally we'd know for sure whether adb reverse would work before we build the APK if (use_reverse) p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST; @@ -1520,7 +1535,7 @@ public: } } else { - static const char *const msg = "--- Device API < 21; debugging over Wi-Fi ---"; + static const char *const msg = "--- Device API < 21 or no USB connection; debugging over Wi-Fi ---"; EditorNode::get_singleton()->get_log()->add_message(msg, EditorLog::MSG_TYPE_EDITOR); print_line(String(msg).to_upper()); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java index 2c4a444e5a..21df5a91b0 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* PermissionsUtil.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + package org.godotengine.godot.utils; import android.Manifest; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index defee8f1f1..9068b76cfb 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -175,9 +175,6 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int input = memnew(InputDefault); input->set_fallback_mapping(godot_java->get_input_fallback_mapping()); - ///@TODO implement a subclass for Android and instantiate that instead - camera_server = memnew(CameraServer); - //power_manager = memnew(PowerAndroid); return OK; @@ -196,8 +193,6 @@ void OS_Android::delete_main_loop() { void OS_Android::finalize() { - memdelete(camera_server); - memdelete(input); } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index a290c0cedd..16b5c8c3a3 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -39,7 +39,6 @@ #include "main/input_default.h" //#include "power_android.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual/rasterizer.h" class GodotJavaWrapper; @@ -79,8 +78,6 @@ private: VisualServer *visual_server; - CameraServer *camera_server; - mutable String data_dir_cache; //AudioDriverAndroid audio_driver_android; diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index 9c07535c85..438b50053f 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -133,8 +133,6 @@ Error OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p window->Show(); visual_server->init(); - camera_server = memnew(CameraServer); - AudioDriverManager::initialize(p_audio_driver); return OK; @@ -150,8 +148,6 @@ void OS_Haiku::finalize() { visual_server->finish(); memdelete(visual_server); - memdelete(camera_server); - memdelete(input); #if defined(OPENGL_ENABLED) diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h index 70d78a1978..e1d4cf8d87 100644 --- a/platform/haiku/os_haiku.h +++ b/platform/haiku/os_haiku.h @@ -38,7 +38,6 @@ #include "haiku_direct_window.h" #include "main/input_default.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual_server.h" class OS_Haiku : public OS_Unix { @@ -50,7 +49,6 @@ private: VisualServer *visual_server; VideoMode current_video_mode; int video_driver_index; - CameraServer *camera_server; #ifdef MEDIA_KIT_ENABLED AudioDriverMediaKit driver_media_kit; diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index 85ba56165b..fa1b124561 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -14,7 +14,6 @@ iphone_lib = [ 'in_app_store.mm', 'icloud.mm', 'ios.mm', - 'camera_ios.mm', ] env_ios = env.Clone() diff --git a/platform/iphone/camera_ios.h b/platform/iphone/camera_ios.h deleted file mode 100644 index ceabdba6a3..0000000000 --- a/platform/iphone/camera_ios.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************/ -/* camera_ios.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CAMERAIOS_H -#define CAMERAIOS_H - -#include "servers/camera_server.h" - -class CameraIOS : public CameraServer { -private: -public: - CameraIOS(); - ~CameraIOS(); - - void update_feeds(); -}; - -#endif /* CAMERAIOS_H */
\ No newline at end of file diff --git a/platform/iphone/camera_ios.mm b/platform/iphone/camera_ios.mm deleted file mode 100644 index ff84df66ff..0000000000 --- a/platform/iphone/camera_ios.mm +++ /dev/null @@ -1,436 +0,0 @@ -/*************************************************************************/ -/* camera_ios.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -///@TODO this is a near duplicate of CameraOSX, we should find a way to combine those to minimise code duplication!!!! -// If you fix something here, make sure you fix it there as wel! - -#include "camera_ios.h" -#include "servers/camera/camera_feed.h" - -#import <AVFoundation/AVFoundation.h> -#import <UIKit/UIKit.h> - -////////////////////////////////////////////////////////////////////////// -// MyCaptureSession - This is a little helper class so we can capture our frames - -@interface MyCaptureSession : AVCaptureSession <AVCaptureVideoDataOutputSampleBufferDelegate> { - Ref<CameraFeed> feed; - size_t width[2]; - size_t height[2]; - PoolVector<uint8_t> img_data[2]; - - AVCaptureDeviceInput *input; - AVCaptureVideoDataOutput *output; -} - -@end - -@implementation MyCaptureSession - -- (id)initForFeed:(Ref<CameraFeed>)p_feed andDevice:(AVCaptureDevice *)p_device { - if (self = [super init]) { - NSError *error; - feed = p_feed; - width[0] = 0; - height[0] = 0; - width[1] = 0; - height[1] = 0; - - // prepare our device - [p_device lockForConfiguration:&error]; - - [p_device setFocusMode:AVCaptureFocusModeLocked]; - [p_device setExposureMode:AVCaptureExposureModeLocked]; - [p_device setWhiteBalanceMode:AVCaptureWhiteBalanceModeLocked]; - - [p_device unlockForConfiguration]; - - [self beginConfiguration]; - - // setup our capture - self.sessionPreset = AVCaptureSessionPreset1280x720; - - input = [AVCaptureDeviceInput deviceInputWithDevice:p_device error:&error]; - if (!input) { - print_line("Couldn't get input device for camera"); - } else { - [self addInput:input]; - } - - output = [AVCaptureVideoDataOutput new]; - if (!output) { - print_line("Couldn't get output device for camera"); - } else { - NSDictionary *settings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) }; - output.videoSettings = settings; - - // discard if the data output queue is blocked (as we process the still image) - [output setAlwaysDiscardsLateVideoFrames:YES]; - - // now set ourselves as the delegate to receive new frames. Note that we're doing this on the main thread at the moment, we may need to change this.. - [output setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; - - [self addOutput:output]; - } - - [self commitConfiguration]; - - // kick off our session.. - [self startRunning]; - }; - return self; -} - -- (void)cleanup { - // stop running - [self stopRunning]; - - // cleanup - [self beginConfiguration]; - - if (input) { - [self removeInput:input]; - // don't release this - input = nil; - } - - if (output) { - [self removeOutput:output]; - [output setSampleBufferDelegate:nil queue:NULL]; - [output release]; - output = nil; - } - - [self commitConfiguration]; -} - -- (void)dealloc { - // bye bye - [super dealloc]; -} - -- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { - // This gets called every time our camera has a new image for us to process. - // May need to investigate in a way to throttle this if we get more images then we're rendering frames.. - - // For now, version 1, we're just doing the bare minimum to make this work... - - CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); - // int width = CVPixelBufferGetWidth(pixelBuffer); - // int height = CVPixelBufferGetHeight(pixelBuffer); - - // It says that we need to lock this on the documentation pages but it's not in the samples - // need to lock our base address so we can access our pixel buffers, better safe then sorry? - CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); - - // get our buffers - unsigned char *dataY = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0); - unsigned char *dataCbCr = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1); - if (dataY == NULL) { - print_line("Couldn't access Y pixel buffer data"); - } else if (dataCbCr == NULL) { - print_line("Couldn't access CbCr pixel buffer data"); - } else { - UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; - Ref<Image> img[2]; - - { - // do Y - int new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0); - int new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0); - int _bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0); - - if ((width[0] != new_width) || (height[0] != new_height)) { - // printf("Camera Y plane %i, %i - %i\n", new_width, new_height, bytes_per_row); - - width[0] = new_width; - height[0] = new_height; - img_data[0].resize(new_width * new_height); - } - - PoolVector<uint8_t>::Write w = img_data[0].write(); - memcpy(w.ptr(), dataY, new_width * new_height); - - img[0].instance(); - img[0]->create(new_width, new_height, 0, Image::FORMAT_R8, img_data[0]); - } - - { - // do CbCr - int new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 1); - int new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1); - int bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1); - - if ((width[1] != new_width) || (height[1] != new_height)) { - // printf("Camera CbCr plane %i, %i - %i\n", new_width, new_height, bytes_per_row); - - width[1] = new_width; - height[1] = new_height; - img_data[1].resize(2 * new_width * new_height); - } - - PoolVector<uint8_t>::Write w = img_data[1].write(); - memcpy(w.ptr(), dataCbCr, 2 * new_width * new_height); - - ///TODO GLES2 doesn't support FORMAT_RG8, need to do some form of conversion - img[1].instance(); - img[1]->create(new_width, new_height, 0, Image::FORMAT_RG8, img_data[1]); - } - - // set our texture... - feed->set_YCbCr_imgs(img[0], img[1]); - - // update our matrix to match the orientation, note, before changing anything - // here, be aware that the project orientation settings must match your xcode - // settings or this will go wrong! - Transform2D display_transform; - switch (orientation) { - case UIInterfaceOrientationPortrait: { - display_transform = Transform2D(0.0, -1.0, -1.0, 0.0, 1.0, 1.0); - } break; - case UIInterfaceOrientationLandscapeRight: { - display_transform = Transform2D(1.0, 0.0, 0.0, -1.0, 0.0, 1.0); - } break; - case UIInterfaceOrientationLandscapeLeft: { - display_transform = Transform2D(-1.0, 0.0, 0.0, 1.0, 1.0, 0.0); - } break; - default: { - display_transform = Transform2D(0.0, 1.0, 1.0, 0.0, 0.0, 0.0); - } break; - } - - //TODO: this is correct for the camera on the back, I have a feeling this needs to be inversed for the camera on the front! - feed->set_transform(display_transform); - } - - // and unlock - CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); -} - -@end - -////////////////////////////////////////////////////////////////////////// -// CameraFeedIOS - Subclass for camera feeds in iOS - -class CameraFeedIOS : public CameraFeed { -private: - AVCaptureDevice *device; - MyCaptureSession *capture_session; - -public: - bool get_is_arkit() const; - AVCaptureDevice *get_device() const; - - CameraFeedIOS(); - ~CameraFeedIOS(); - - void set_device(AVCaptureDevice *p_device); - - bool activate_feed(); - void deactivate_feed(); -}; - -AVCaptureDevice *CameraFeedIOS::get_device() const { - return device; -}; - -CameraFeedIOS::CameraFeedIOS() { - capture_session = NULL; - device = NULL; - transform = Transform2D(1.0, 0.0, 0.0, 1.0, 0.0, 0.0); /* should re-orientate this based on device orientation */ -}; - -void CameraFeedIOS::set_device(AVCaptureDevice *p_device) { - device = p_device; - [device retain]; - - // get some info - NSString *device_name = p_device.localizedName; - name = device_name.UTF8String; - position = CameraFeed::FEED_UNSPECIFIED; - if ([p_device position] == AVCaptureDevicePositionBack) { - position = CameraFeed::FEED_BACK; - } else if ([p_device position] == AVCaptureDevicePositionFront) { - position = CameraFeed::FEED_FRONT; - }; -}; - -CameraFeedIOS::~CameraFeedIOS() { - if (capture_session != NULL) { - [capture_session release]; - capture_session = NULL; - }; - - if (device != NULL) { - [device release]; - device = NULL; - }; -}; - -bool CameraFeedIOS::activate_feed() { - if (capture_session) { - // already recording! - } else { - // start camera capture - capture_session = [[MyCaptureSession alloc] initForFeed:this andDevice:device]; - }; - - return true; -}; - -void CameraFeedIOS::deactivate_feed() { - // end camera capture if we have one - if (capture_session) { - [capture_session cleanup]; - [capture_session release]; - capture_session = NULL; - }; -}; - -////////////////////////////////////////////////////////////////////////// -// MyDeviceNotifications - This is a little helper class gets notifications -// when devices are connected/disconnected - -@interface MyDeviceNotifications : NSObject { - CameraIOS *camera_server; -} - -@end - -@implementation MyDeviceNotifications - -- (void)devices_changed:(NSNotification *)notification { - camera_server->update_feeds(); -} - -- (id)initForServer:(CameraIOS *)p_server { - if (self = [super init]) { - camera_server = p_server; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(devices_changed:) name:AVCaptureDeviceWasConnectedNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(devices_changed:) name:AVCaptureDeviceWasDisconnectedNotification object:nil]; - }; - return self; -} - -- (void)dealloc { - // remove notifications - [[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureDeviceWasConnectedNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureDeviceWasDisconnectedNotification object:nil]; - - [super dealloc]; -} - -@end - -MyDeviceNotifications *device_notifications = nil; - -////////////////////////////////////////////////////////////////////////// -// CameraIOS - Subclass for our camera server on iPhone - -void CameraIOS::update_feeds() { - // this way of doing things is deprecated but still works, - // rewrite to using AVCaptureDeviceDiscoverySession - - AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:[NSArray arrayWithObjects:AVCaptureDeviceTypeBuiltInTelephotoCamera, AVCaptureDeviceTypeBuiltInDualCamera, AVCaptureDeviceTypeBuiltInTrueDepthCamera, AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; - - // remove devices that are gone.. - for (int i = feeds.size() - 1; i >= 0; i--) { - Ref<CameraFeedIOS> feed(feeds[i]); - - if (feed.is_null()) { - // feed not managed by us - } else if (![session.devices containsObject:feed->get_device()]) { - // remove it from our array, this will also destroy it ;) - remove_feed(feed); - }; - }; - - // add new devices.. - for (AVCaptureDevice *device in session.devices) { - bool found = false; - - for (int i = 0; i < feeds.size() && !found; i++) { - Ref<CameraFeedIOS> feed(feeds[i]); - - if (feed.is_null()) { - // feed not managed by us - } else if (feed->get_device() == device) { - found = true; - }; - }; - - if (!found) { - Ref<CameraFeedIOS> newfeed; - newfeed.instance(); - newfeed->set_device(device); - add_feed(newfeed); - }; - }; -}; - -CameraIOS::CameraIOS() { - // check if we have our usage description - NSString *usage_desc = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSCameraUsageDescription"]; - if (usage_desc == NULL) { - // don't initialise if we don't get anything - print_line("No NSCameraUsageDescription key in pList, no access to cameras."); - return; - } else if (usage_desc.length == 0) { - // don't initialise if we don't get anything - print_line("Empty NSCameraUsageDescription key in pList, no access to cameras."); - return; - } - - // now we'll request access. - // If this is the first time the user will be prompted with the string (iOS will read it). - // Once a decision is made it is returned. If the user wants to change it later on they - // need to go into setting. - print_line("Requesting Camera permissions"); - - [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo - completionHandler:^(BOOL granted) { - if (granted) { - print_line("Access to cameras granted!"); - - // Find available cameras we have at this time - update_feeds(); - - // should only have one of these.... - device_notifications = [[MyDeviceNotifications alloc] initForServer:this]; - } else { - print_line("No access to cameras!"); - } - }]; -}; - -CameraIOS::~CameraIOS() { - [device_notifications release]; -}; diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index baae13c53d..4f4439bc60 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -63,6 +63,10 @@ class EditorExportPlatformIOS : public EditorExportPlatform { String architectures; String linker_flags; String cpp_code; + String modules_buildfile; + String modules_fileref; + String modules_buildphase; + String modules_buildgrp; }; struct ExportArchitecture { @@ -178,6 +182,7 @@ public: return list; } virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); + virtual void add_module_code(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &p_name, const String &p_fid, const String &p_gid); virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const; @@ -214,7 +219,7 @@ void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> Vector<EditorExportPlatformIOS::ExportArchitecture> EditorExportPlatformIOS::_get_supported_architectures() { Vector<ExportArchitecture> archs; - archs.push_back(ExportArchitecture("armv7", true)); + archs.push_back(ExportArchitecture("armv7", false)); // Disabled by default, not included in official templates. archs.push_back(ExportArchitecture("arm64", true)); return archs; } @@ -263,11 +268,16 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/arkit"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/camera"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/game_center"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/in_app_purchases"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/push_notifications"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_files_app"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), "")); @@ -311,6 +321,14 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ for (int i = 0; i < lines.size(); i++) { if (lines[i].find("$binary") != -1) { strnew += lines[i].replace("$binary", p_config.binary_name) + "\n"; + } else if (lines[i].find("$modules_buildfile") != -1) { + strnew += lines[i].replace("$modules_buildfile", p_config.modules_buildfile) + "\n"; + } else if (lines[i].find("$modules_fileref") != -1) { + strnew += lines[i].replace("$modules_fileref", p_config.modules_fileref) + "\n"; + } else if (lines[i].find("$modules_buildphase") != -1) { + strnew += lines[i].replace("$modules_buildphase", p_config.modules_buildphase) + "\n"; + } else if (lines[i].find("$modules_buildgrp") != -1) { + strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n"; } else if (lines[i].find("$name") != -1) { strnew += lines[i].replace("$name", p_config.pkg_name) + "\n"; } else if (lines[i].find("$info") != -1) { @@ -349,6 +367,10 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n"; } else if (lines[i].find("$cpp_code") != -1) { strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n"; + } else if (lines[i].find("$docs_in_place") != -1) { + strnew += lines[i].replace("$docs_in_place", ((bool)p_preset->get("user_data/accessible_from_files_app")) ? "<true/>" : "<false/>") + "\n"; + } else if (lines[i].find("$docs_sharing") != -1) { + strnew += lines[i].replace("$docs_sharing", ((bool)p_preset->get("user_data/accessible_from_itunes_sharing")) ? "<true/>" : "<false/>") + "\n"; } else if (lines[i].find("$access_wifi") != -1) { bool is_on = p_preset->get("capabilities/access_wifi"); strnew += lines[i].replace("$access_wifi", is_on ? "1" : "0") + "\n"; @@ -837,6 +859,22 @@ Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<Edit return enabled_archs; } +void EditorExportPlatformIOS::add_module_code(const Ref<EditorExportPreset> &p_preset, EditorExportPlatformIOS::IOSConfigData &p_config_data, const String &p_name, const String &p_fid, const String &p_gid) { + if ((bool)p_preset->get("capabilities/" + p_name)) { + //add module static library + print_line("ADDING MODULE: " + p_name); + + p_config_data.modules_buildfile += p_gid + " /* libgodot_" + p_name + "_module.a in Frameworks */ = {isa = PBXBuildFile; fileRef = " + p_fid + " /* libgodot_" + p_name + "_module.a */; };\n\t\t"; + p_config_data.modules_fileref += p_fid + " /* libgodot_" + p_name + "_module.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot_" + p_name + "_module ; path = \"libgodot_" + p_name + "_module.a\"; sourceTree = \"<group>\"; };\n\t\t"; + p_config_data.modules_buildphase += p_gid + " /* libgodot_" + p_name + "_module.a */,\n\t\t\t\t"; + p_config_data.modules_buildgrp += p_fid + " /* libgodot_" + p_name + "_module.a */,\n\t\t\t\t"; + } else { + //add stub function for disabled module + p_config_data.cpp_code += "void register_" + p_name + "_types() { /*stub*/ };\n"; + p_config_data.cpp_code += "void unregister_" + p_name + "_types() { /*stub*/ };\n"; + } +} + Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); @@ -934,7 +972,11 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p _get_additional_plist_content(), String(" ").join(_get_preset_architectures(p_preset)), _get_linker_flags(), - _get_cpp_code() + _get_cpp_code(), + "", + "", + "", + "" }; DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir); @@ -949,6 +991,10 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p return ERR_CANT_OPEN; } + add_module_code(p_preset, config_data, "arkit", "F9B95E6E2391205500AF0000", "F9C95E812391205C00BF0000"); + add_module_code(p_preset, config_data, "camera", "F9B95E6E2391205500AF0001", "F9C95E812391205C00BF0001"); + + //export rest of the files int ret = unzGoToFirstFile(src_pkg_zip); Vector<uint8_t> project_file_data; while (ret == UNZ_OK) { @@ -988,6 +1034,20 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p is_execute = true; #endif file = "godot_ios.a"; + } else if (file.begins_with("libgodot_arkit")) { + if ((bool)p_preset->get("capabilities/arkit") && file.ends_with(String(p_debug ? "debug" : "release") + ".fat.a")) { + file = "libgodot_arkit_module.a"; + } else { + ret = unzGoToNextFile(src_pkg_zip); + continue; //ignore! + } + } else if (file.begins_with("libgodot_camera")) { + if ((bool)p_preset->get("capabilities/camera") && file.ends_with(String(p_debug ? "debug" : "release") + ".fat.a")) { + file = "libgodot_camera_module.a"; + } else { + ret = unzGoToNextFile(src_pkg_zip); + continue; //ignore! + } } if (file == project_file) { project_file_data = data; diff --git a/platform/iphone/gl_view.h b/platform/iphone/gl_view.h index 4fb721f159..e3c9d212f0 100644 --- a/platform/iphone/gl_view.h +++ b/platform/iphone/gl_view.h @@ -79,8 +79,6 @@ @property(strong, nonatomic) AVPlayer *avPlayer; @property(strong, nonatomic) AVPlayerLayer *avPlayerLayer; -// Old videoplayer properties -@property(strong, nonatomic) MPMoviePlayerController *moviePlayerController; @property(strong, nonatomic) UIWindow *backgroundWindow; @property(nonatomic) UITextAutocorrectionType autocorrectionType; diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm index dfca2e3dd7..4e6b8e1ada 100644 --- a/platform/iphone/gl_view.mm +++ b/platform/iphone/gl_view.mm @@ -340,6 +340,7 @@ static void clear_touches() { [EAGLContext setCurrentContext:context]; [self destroyFramebuffer]; [self createFramebuffer]; + [self drawView]; } - (BOOL)createFramebuffer { @@ -455,23 +456,23 @@ static void clear_touches() { // Updates the OpenGL view when the timer fires - (void)drawView { + + if (!active) { + printf("draw view not active!\n"); + return; + }; if (useCADisplayLink) { // Pause the CADisplayLink to avoid recursion [displayLink setPaused:YES]; // Process all input events - while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource) + while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, TRUE) == kCFRunLoopRunHandledSource) ; // We are good to go, resume the CADisplayLink [displayLink setPaused:NO]; } - if (!active) { - printf("draw view not active!\n"); - return; - }; - // Make sure that you are drawing to the current context [EAGLContext setCurrentContext:context]; @@ -729,40 +730,4 @@ static void clear_touches() { _stop_video(); } -/* -- (void)moviePlayBackDidFinish:(NSNotification*)notification { - - - NSNumber* reason = [[notification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey]; - switch ([reason intValue]) { - case MPMovieFinishReasonPlaybackEnded: - //NSLog(@"Playback Ended"); - break; - case MPMovieFinishReasonPlaybackError: - //NSLog(@"Playback Error"); - video_found_error = true; - break; - case MPMovieFinishReasonUserExited: - //NSLog(@"User Exited"); - video_found_error = true; - break; - default: - //NSLog(@"Unsupported reason!"); - break; - } - - MPMoviePlayerController *player = [notification object]; - - [[NSNotificationCenter defaultCenter] - removeObserver:self - name:MPMoviePlayerPlaybackDidFinishNotification - object:player]; - - [_instance.moviePlayerController stop]; - [_instance.moviePlayerController.view removeFromSuperview]; - - video_playing = false; -} -*/ - @end diff --git a/platform/iphone/godot_iphone.cpp b/platform/iphone/godot_iphone.cpp index db93db5021..992da2818b 100644 --- a/platform/iphone/godot_iphone.cpp +++ b/platform/iphone/godot_iphone.cpp @@ -47,7 +47,7 @@ int iphone_main(int, int, int, char **, String); int iphone_main(int width, int height, int argc, char **argv, String data_dir) { - int len = strlen(argv[0]); + size_t len = strlen(argv[0]); while (len--) { if (argv[0][len] == '/') break; diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm index 490e84c571..8eef430621 100644 --- a/platform/iphone/in_app_store.mm +++ b/platform/iphone/in_app_store.mm @@ -92,7 +92,7 @@ void InAppStore::_bind_methods() { PoolStringArray localized_prices; PoolStringArray currency_codes; - for (int i = 0; i < [products count]; i++) { + for (NSUInteger i = 0; i < [products count]; i++) { SKProduct *product = [products objectAtIndex:i]; diff --git a/platform/iphone/ios.h b/platform/iphone/ios.h index 91c4725b35..ef45fc7ac3 100644 --- a/platform/iphone/ios.h +++ b/platform/iphone/ios.h @@ -42,6 +42,7 @@ class iOS : public Object { public: static void alert(const char *p_alert, const char *p_title); + String get_model() const; String get_rate_url(int p_app_id) const; iOS(); diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm index 686422ceb2..6e986df493 100644 --- a/platform/iphone/ios.mm +++ b/platform/iphone/ios.mm @@ -29,6 +29,7 @@ /*************************************************************************/ #include "ios.h" +#include <sys/sysctl.h> #import <UIKit/UIKit.h> @@ -42,6 +43,21 @@ void iOS::alert(const char *p_alert, const char *p_title) { [alert show]; } +String iOS::get_model() const { + // [[UIDevice currentDevice] model] only returns "iPad" or "iPhone". + size_t size; + sysctlbyname("hw.machine", NULL, &size, NULL, 0); + char *model = (char *)malloc(size); + if (model == NULL) { + return ""; + } + sysctlbyname("hw.machine", model, &size, NULL, 0); + NSString *platform = [NSString stringWithCString:model encoding:NSUTF8StringEncoding]; + free(model); + const char *str = [platform UTF8String]; + return String(str != NULL ? str : ""); +} + String iOS::get_rate_url(int p_app_id) const { String templ = "itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APP_ID"; String templ_iOS7 = "itms-apps://itunes.apple.com/app/idAPP_ID"; diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 353078c51c..8984ed1d7b 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -47,8 +47,6 @@ #include "semaphore_iphone.h" -#include "ios.h" - #include <dlfcn.h> int OSIPhone::get_video_driver_count() const { @@ -166,8 +164,6 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p input = memnew(InputDefault); - camera_server = memnew(CameraIOS); - #ifdef GAME_CENTER_ENABLED game_center = memnew(GameCenter); Engine::get_singleton()->add_singleton(Engine::Singleton("GameCenter", game_center)); @@ -184,7 +180,8 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p Engine::get_singleton()->add_singleton(Engine::Singleton("ICloud", icloud)); //icloud->connect(); #endif - Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", memnew(iOS))); + ios = memnew(iOS); + Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", ios)); return OK; }; @@ -362,11 +359,6 @@ void OSIPhone::finalize() { if (main_loop) // should not happen? memdelete(main_loop); - if (camera_server) { - memdelete(camera_server); - camera_server = NULL; - } - visual_server->finish(); memdelete(visual_server); // memdelete(rasterizer); @@ -507,6 +499,15 @@ String OSIPhone::get_name() const { return "iOS"; }; +String OSIPhone::get_model_name() const { + + String model = ios->get_model(); + if (model != "") + return model; + + return OS_Unix::get_model_name(); +} + Size2 OSIPhone::get_window_size() const { return Vector2(video_mode.width, video_mode.height); diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 804ba0b1af..1f49062cfc 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -37,10 +37,10 @@ #include "drivers/coreaudio/audio_driver_coreaudio.h" #include "drivers/unix/os_unix.h" -#include "camera_ios.h" #include "game_center.h" #include "icloud.h" #include "in_app_store.h" +#include "ios.h" #include "main/input_default.h" #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" @@ -61,8 +61,6 @@ private: AudioDriverCoreAudio audio_driver; - CameraServer *camera_server; - #ifdef GAME_CENTER_ENABLED GameCenter *game_center; #endif @@ -72,6 +70,7 @@ private: #ifdef ICLOUD_ENABLED ICloud *icloud; #endif + iOS *ios; MainLoop *main_loop; @@ -178,6 +177,7 @@ public: void set_data_dir(String p_dir); virtual String get_name() const; + virtual String get_model_name() const; Error shell_open(String p_uri); diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index a0d6ac9214..7bf3e1bc1d 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -24,6 +24,7 @@ def get_opts(): def get_flags(): return [ ('tools', False), + ('builtin_pcre2_with_jit', False), # Disabling the mbedtls module reduces file size. # The module has little use due to the limited networking functionality # in this platform. For the available networking methods, the browser @@ -82,10 +83,7 @@ def configure(env): env['CXX'] = 'em++' env['LINK'] = 'emcc' - # Emscripten's ar has issues with duplicate file names, so use cc. - env['AR'] = 'emcc' - env['ARFLAGS'] = '-o' - # emranlib is a noop, so it's safe to use with AR=emcc. + env['AR'] = 'emar' env['RANLIB'] = 'emranlib' # Use TempFileMunge since some AR invocations are too long for cmd.exe. @@ -127,8 +125,19 @@ def configure(env): ## Link flags + # We use IDBFS in javascript_main.cpp. Since Emscripten 1.39.1 it needs to + # be linked explicitly. + env.Append(LIBS=['idbfs.js']) + env.Append(LINKFLAGS=['-s', 'BINARYEN=1']) + # This needs to be defined for Emscripten using 'fastcomp' (default pre-1.39.0) + # and undefined if using 'upstream'. And to make things simple, earlier + # Emscripten versions didn't include 'fastcomp' in their path, so we check + # against the presence of 'upstream' to conditionally add the flag. + if not "upstream" in em_config['EMSCRIPTEN_ROOT']: + env.Append(LINKFLAGS=['-s', 'BINARYEN_TRAP_MODE=\'clamp\'']) + # Allow increasing memory buffer size during runtime. This is efficient # when using WebAssembly (in comparison to asm.js) and works well for # us since we don't know requirements at compile-time. diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp index e6e933811f..1f3f2ed53c 100644 --- a/platform/javascript/http_client_javascript.cpp +++ b/platform/javascript/http_client_javascript.cpp @@ -211,6 +211,10 @@ void HTTPClient::set_read_chunk_size(int p_size) { read_limit = p_size; } +int HTTPClient::get_read_chunk_size() const { + return read_limit; +} + Error HTTPClient::poll() { switch (status) { diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index b0661cb4dd..61919bb24a 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -837,7 +837,7 @@ void OS_JavaScript::set_clipboard(const String &p_text) { var text = UTF8ToString($0); if (!navigator.clipboard || !navigator.clipboard.writeText) return 1; - navigator.clipboard.writeText(text).catch(e => { + navigator.clipboard.writeText(text).catch(function(e) { // Setting OS clipboard is only possible from an input callback. console.error("Setting OS clipboard is only possible from an input callback for the HTML5 plafrom. Exception:", e); }); @@ -970,8 +970,6 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, VisualServer *visual_server = memnew(VisualServerRaster()); input = memnew(InputDefault); - camera_server = memnew(CameraServer); - EMSCRIPTEN_RESULT result; #define EM_CHECK(ev) \ if (result != EMSCRIPTEN_RESULT_SUCCESS) \ @@ -1106,7 +1104,6 @@ void OS_JavaScript::delete_main_loop() { void OS_JavaScript::finalize() { - memdelete(camera_server); memdelete(input); } diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 10676c49f7..7c97e302e9 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -35,7 +35,6 @@ #include "drivers/unix/os_unix.h" #include "main/input_default.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual/rasterizer.h" #include <emscripten/html5.h> @@ -67,8 +66,6 @@ class OS_JavaScript : public OS_Unix { int64_t sync_wait_time; int64_t last_sync_check_time; - CameraServer *camera_server; - static EM_BOOL fullscreen_change_callback(int p_event_type, const EmscriptenFullscreenChangeEvent *p_event, void *p_user_data); static EM_BOOL keydown_callback(int p_event_type, const EmscriptenKeyboardEvent *p_event, void *p_user_data); diff --git a/platform/osx/SCsub b/platform/osx/SCsub index 9620863b96..e15b4339a7 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -13,7 +13,6 @@ files = [ 'dir_access_osx.mm', 'joypad_osx.cpp', 'power_osx.cpp', - 'camera_osx.mm', ] prog = env.add_program('#bin/godot', files) diff --git a/platform/osx/camera_osx.h b/platform/osx/camera_osx.h deleted file mode 100644 index 80ca3759ba..0000000000 --- a/platform/osx/camera_osx.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************/ -/* camera_osx.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CAMERAOSX_H -#define CAMERAOSX_H - -///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimise code duplication!!!! -// If you fix something here, make sure you fix it there as wel! - -#include "servers/camera_server.h" - -class CameraOSX : public CameraServer { -public: - CameraOSX(); - ~CameraOSX(); - - void update_feeds(); -}; - -#endif /* CAMERAOSX_H */
\ No newline at end of file diff --git a/platform/osx/camera_osx.mm b/platform/osx/camera_osx.mm deleted file mode 100644 index f13cf76beb..0000000000 --- a/platform/osx/camera_osx.mm +++ /dev/null @@ -1,362 +0,0 @@ -/*************************************************************************/ -/* camera_osx.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimise code duplication!!!! -// If you fix something here, make sure you fix it there as wel! - -#include "camera_osx.h" -#include "servers/camera/camera_feed.h" -#import <AVFoundation/AVFoundation.h> - -////////////////////////////////////////////////////////////////////////// -// MyCaptureSession - This is a little helper class so we can capture our frames - -@interface MyCaptureSession : AVCaptureSession <AVCaptureVideoDataOutputSampleBufferDelegate> { - Ref<CameraFeed> feed; - size_t width[2]; - size_t height[2]; - PoolVector<uint8_t> img_data[2]; - - AVCaptureDeviceInput *input; - AVCaptureVideoDataOutput *output; -} - -@end - -@implementation MyCaptureSession - -- (id)initForFeed:(Ref<CameraFeed>)p_feed andDevice:(AVCaptureDevice *)p_device { - if (self = [super init]) { - NSError *error; - feed = p_feed; - width[0] = 0; - height[0] = 0; - width[1] = 0; - height[1] = 0; - - [self beginConfiguration]; - - input = [AVCaptureDeviceInput deviceInputWithDevice:p_device error:&error]; - if (!input) { - print_line("Couldn't get input device for camera"); - } else { - [self addInput:input]; - } - - output = [AVCaptureVideoDataOutput new]; - if (!output) { - print_line("Couldn't get output device for camera"); - } else { - NSDictionary *settings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) }; - output.videoSettings = settings; - - // discard if the data output queue is blocked (as we process the still image) - [output setAlwaysDiscardsLateVideoFrames:YES]; - - // now set ourselves as the delegate to receive new frames. - [output setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; - - // this takes ownership - [self addOutput:output]; - } - - [self commitConfiguration]; - - // kick off our session.. - [self startRunning]; - }; - return self; -} - -- (void)cleanup { - // stop running - [self stopRunning]; - - // cleanup - [self beginConfiguration]; - - // remove input - if (input) { - [self removeInput:input]; - // don't release this - input = NULL; - } - - // free up our output - if (output) { - [self removeOutput:output]; - [output setSampleBufferDelegate:nil queue:NULL]; - [output release]; - output = NULL; - } - - [self commitConfiguration]; -} - -- (void)dealloc { - // bye bye - [super dealloc]; -} - -- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { - // This gets called every time our camera has a new image for us to process. - // May need to investigate in a way to throttle this if we get more images then we're rendering frames.. - - // For now, version 1, we're just doing the bare minimum to make this work... - CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); - // int _width = CVPixelBufferGetWidth(pixelBuffer); - // int _height = CVPixelBufferGetHeight(pixelBuffer); - - // It says that we need to lock this on the documentation pages but it's not in the samples - // need to lock our base address so we can access our pixel buffers, better safe then sorry? - CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); - - // get our buffers - unsigned char *dataY = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0); - unsigned char *dataCbCr = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1); - if (dataY == NULL) { - print_line("Couldn't access Y pixel buffer data"); - } else if (dataCbCr == NULL) { - print_line("Couldn't access CbCr pixel buffer data"); - } else { - Ref<Image> img[2]; - - { - // do Y - int new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0); - int new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0); - - if ((width[0] != new_width) || (height[0] != new_height)) { - width[0] = new_width; - height[0] = new_height; - img_data[0].resize(new_width * new_height); - } - - PoolVector<uint8_t>::Write w = img_data[0].write(); - memcpy(w.ptr(), dataY, new_width * new_height); - - img[0].instance(); - img[0]->create(new_width, new_height, 0, Image::FORMAT_R8, img_data[0]); - } - - { - // do CbCr - int new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 1); - int new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1); - - if ((width[1] != new_width) || (height[1] != new_height)) { - width[1] = new_width; - height[1] = new_height; - img_data[1].resize(2 * new_width * new_height); - } - - PoolVector<uint8_t>::Write w = img_data[1].write(); - memcpy(w.ptr(), dataCbCr, 2 * new_width * new_height); - - ///TODO GLES2 doesn't support FORMAT_RG8, need to do some form of conversion - img[1].instance(); - img[1]->create(new_width, new_height, 0, Image::FORMAT_RG8, img_data[1]); - } - - // set our texture... - feed->set_YCbCr_imgs(img[0], img[1]); - } - - // and unlock - CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); -} - -@end - -////////////////////////////////////////////////////////////////////////// -// CameraFeedOSX - Subclass for camera feeds in OSX - -class CameraFeedOSX : public CameraFeed { -private: - AVCaptureDevice *device; - MyCaptureSession *capture_session; - -public: - AVCaptureDevice *get_device() const; - - CameraFeedOSX(); - ~CameraFeedOSX(); - - void set_device(AVCaptureDevice *p_device); - - bool activate_feed(); - void deactivate_feed(); -}; - -AVCaptureDevice *CameraFeedOSX::get_device() const { - return device; -}; - -CameraFeedOSX::CameraFeedOSX() { - device = NULL; - capture_session = NULL; -}; - -void CameraFeedOSX::set_device(AVCaptureDevice *p_device) { - device = p_device; - [device retain]; - - // get some info - NSString *device_name = p_device.localizedName; - name = device_name.UTF8String; - position = CameraFeed::FEED_UNSPECIFIED; - if ([p_device position] == AVCaptureDevicePositionBack) { - position = CameraFeed::FEED_BACK; - } else if ([p_device position] == AVCaptureDevicePositionFront) { - position = CameraFeed::FEED_FRONT; - }; -}; - -CameraFeedOSX::~CameraFeedOSX() { - if (capture_session != NULL) { - [capture_session release]; - capture_session = NULL; - }; - - if (device != NULL) { - [device release]; - device = NULL; - }; -}; - -bool CameraFeedOSX::activate_feed() { - if (capture_session) { - // already recording! - } else { - // start camera capture - capture_session = [[MyCaptureSession alloc] initForFeed:this andDevice:device]; - }; - - return true; -}; - -void CameraFeedOSX::deactivate_feed() { - // end camera capture if we have one - if (capture_session) { - [capture_session cleanup]; - [capture_session release]; - capture_session = NULL; - }; -}; - -////////////////////////////////////////////////////////////////////////// -// MyDeviceNotifications - This is a little helper class gets notifications -// when devices are connected/disconnected - -@interface MyDeviceNotifications : NSObject { - CameraOSX *camera_server; -} - -@end - -@implementation MyDeviceNotifications - -- (void)devices_changed:(NSNotification *)notification { - camera_server->update_feeds(); -} - -- (id)initForServer:(CameraOSX *)p_server { - if (self = [super init]) { - camera_server = p_server; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(devices_changed:) name:AVCaptureDeviceWasConnectedNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(devices_changed:) name:AVCaptureDeviceWasDisconnectedNotification object:nil]; - }; - return self; -} - -- (void)dealloc { - // remove notifications - [[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureDeviceWasConnectedNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureDeviceWasDisconnectedNotification object:nil]; - - [super dealloc]; -} - -@end - -MyDeviceNotifications *device_notifications = nil; - -////////////////////////////////////////////////////////////////////////// -// CameraOSX - Subclass for our camera server on OSX - -void CameraOSX::update_feeds() { - NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; - - // remove devices that are gone.. - for (int i = feeds.size() - 1; i >= 0; i--) { - Ref<CameraFeedOSX> feed = (Ref<CameraFeedOSX>)feeds[i]; - - if (![devices containsObject:feed->get_device()]) { - // remove it from our array, this will also destroy it ;) - remove_feed(feed); - }; - }; - - // add new devices.. - for (AVCaptureDevice *device in devices) { - bool found = false; - for (int i = 0; i < feeds.size() && !found; i++) { - Ref<CameraFeedOSX> feed = (Ref<CameraFeedOSX>)feeds[i]; - if (feed->get_device() == device) { - found = true; - }; - }; - - if (!found) { - Ref<CameraFeedOSX> newfeed; - newfeed.instance(); - newfeed->set_device(device); - - // assume display camera so inverse - Transform2D transform = Transform2D(-1.0, 0.0, 0.0, -1.0, 1.0, 1.0); - newfeed->set_transform(transform); - - add_feed(newfeed); - }; - }; -}; - -CameraOSX::CameraOSX() { - // Find available cameras we have at this time - update_feeds(); - - // should only have one of these.... - device_notifications = [[MyDeviceNotifications alloc] initForServer:this]; -}; - -CameraOSX::~CameraOSX() { - [device_notifications release]; -}; diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm index e19fdf1b9f..015859b3c0 100644 --- a/platform/osx/crash_handler_osx.mm +++ b/platform/osx/crash_handler_osx.mm @@ -95,7 +95,7 @@ static void handle_crash(int sig) { if (strings) { void *load_addr = (void *)load_address(); - for (int i = 1; i < size; i++) { + for (size_t i = 1; i < size; i++) { char fname[1024]; Dl_info info; @@ -142,7 +142,7 @@ static void handle_crash(int sig) { } } - fprintf(stderr, "[%d] %ls\n", i, output.c_str()); + fprintf(stderr, "[%zu] %ls\n", i, output.c_str()); } free(strings); diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 881ed05025..7882253e7a 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -91,6 +91,9 @@ def configure(env): env['RANLIB'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-ranlib" env['AS'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-as" env.Append(CPPDEFINES=['__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define + else: + env['CC'] = 'clang' + env['CXX'] = 'clang++' detect_darwin_sdk_path('osx', env) env.Append(CCFLAGS=['-isysroot', '$MACOS_SDK_PATH']) diff --git a/platform/osx/joypad_osx.cpp b/platform/osx/joypad_osx.cpp index fa124dac11..4edf347f61 100644 --- a/platform/osx/joypad_osx.cpp +++ b/platform/osx/joypad_osx.cpp @@ -578,7 +578,7 @@ JoypadOSX::JoypadOSX() { const size_t n_elements = sizeof(vals) / sizeof(vals[0]); CFArrayRef array = okay ? CFArrayCreate(kCFAllocatorDefault, vals, n_elements, &kCFTypeArrayCallBacks) : NULL; - for (int i = 0; i < n_elements; i++) { + for (size_t i = 0; i < n_elements; i++) { if (vals[i]) { CFRelease((CFTypeRef)vals[i]); } diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index f1f37e24d2..78e1aa6c0a 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -31,7 +31,8 @@ #ifndef OS_OSX_H #define OS_OSX_H -#include "camera_osx.h" +#define BitMap _QDBitMap // Suppress deprecated QuickDraw definition. + #include "core/os/input.h" #include "crash_handler_osx.h" #include "drivers/coreaudio/audio_driver_coreaudio.h" @@ -50,6 +51,7 @@ #include <ApplicationServices/ApplicationServices.h> #include <CoreVideo/CoreVideo.h> +#undef BitMap #undef CursorShape class OS_OSX : public OS_Unix { @@ -71,8 +73,6 @@ public: //Rasterizer *rasterizer; VisualServer *visual_server; - CameraServer *camera_server; - List<String> args; MainLoop *main_loop; @@ -110,9 +110,6 @@ public: NSOpenGLContext *context; bool layered_window; - bool waiting_for_vsync; - NSCondition *vsync_condition; - CVDisplayLinkRef displayLink; CursorShape cursor_shape; NSCursor *cursors[CURSOR_MAX]; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 51ae264cf7..122e8274b9 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -115,21 +115,6 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto return Vector2(mouse_x, mouse_y); } -// DisplayLinkCallback is called from our DisplayLink OS thread informing us right before -// a screen update is required. We can use it to work around the broken vsync. -static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) { - OS_OSX *os = (OS_OSX *)displayLinkContext; - - // Set flag so we know we can output our next frame and signal our conditional lock - // if we're not doing vsync this will be ignored - [os->vsync_condition lock]; - os->waiting_for_vsync = false; - [os->vsync_condition signal]; - [os->vsync_condition unlock]; - - return kCVReturnSuccess; -} - @interface GodotApplication : NSApplication @end @@ -355,12 +340,8 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt //Update context if (OS_OSX::singleton->main_loop) { - [OS_OSX::singleton->context update]; - - //Force window resize ??? - NSRect frame = [OS_OSX::singleton->window_object frame]; - [OS_OSX::singleton->window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, 1, 1) display:YES]; - [OS_OSX::singleton->window_object setFrame:frame display:YES]; + //Force window resize event + [self windowDidResize:notification]; } } } @@ -620,7 +601,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType]; Vector<String> files; - for (int i = 0; i < filenames.count; i++) { + for (NSUInteger i = 0; i < filenames.count; i++) { NSString *ns = [filenames objectAtIndex:i]; char *utfs = strdup([ns UTF8String]); String ret; @@ -709,6 +690,11 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { const CGFloat backingScaleFactor = [[event window] backingScaleFactor]; const Vector2 pos = get_mouse_pos([event locationInWindow], backingScaleFactor); mm->set_position(pos); + mm->set_pressure([event pressure]); + if ([event subtype] == NSTabletPointEventSubtype) { + const NSPoint p = [event tilt]; + mm->set_tilt(Vector2(p.x, p.y)); + } mm->set_global_position(pos); mm->set_speed(OS_OSX::singleton->input->get_last_mouse_speed()); Vector2 relativeMotion = Vector2(); @@ -1502,7 +1488,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a [window_object setContentView:window_view]; [window_object setDelegate:window_delegate]; [window_object setAcceptsMouseMovedEvents:YES]; - [window_object center]; + [(NSWindow *)window_object center]; [window_object setRestorable:NO]; @@ -1576,15 +1562,6 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a [context makeCurrentContext]; - // setup our display link, this will inform us when a refresh is needed - CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); - CVDisplayLinkSetOutputCallback(displayLink, &DisplayLinkCallback, this); - CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, context.CGLContextObj, pixelFormat.CGLPixelFormatObj); - CVDisplayLinkStart(displayLink); - - // initialise a conditional lock object - vsync_condition = [[NSCondition alloc] init]; - set_use_vsync(p_desired.use_vsync); [NSApp activateIgnoringOtherApps:YES]; @@ -1651,8 +1628,6 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a visual_server->init(); AudioDriverManager::initialize(p_audio_driver); - camera_server = memnew(CameraOSX); - input = memnew(InputDefault); joypad_osx = memnew(JoypadOSX); @@ -1677,21 +1652,11 @@ void OS_OSX::finalize() { midi_driver.close(); #endif - if (displayLink) { - CVDisplayLinkRelease(displayLink); - } - [vsync_condition release]; - CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL); CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL); delete_main_loop(); - if (camera_server) { - memdelete(camera_server); - camera_server = NULL; - } - memdelete(joypad_osx); memdelete(input); @@ -2248,23 +2213,11 @@ Error OS_OSX::shell_open(String p_uri) { } String OS_OSX::get_locale() const { - NSString *locale_code = [[NSLocale currentLocale] localeIdentifier]; + NSString *locale_code = [[NSLocale preferredLanguages] objectAtIndex:0]; return [locale_code UTF8String]; } void OS_OSX::swap_buffers() { - if (is_vsync_enabled()) { - // Wait until our DisplayLink callback unsets our flag... - [vsync_condition lock]; - while (waiting_for_vsync) - [vsync_condition wait]; - - // Make sure we wait again next frame around - waiting_for_vsync = true; - - [vsync_condition unlock]; - } - [context flushBuffer]; } @@ -2338,12 +2291,12 @@ void OS_OSX::set_current_screen(int p_screen) { }; Point2 OS_OSX::get_native_screen_position(int p_screen) const { - if (p_screen == -1) { + if (p_screen < 0) { p_screen = get_current_screen(); } NSArray *screenArray = [NSScreen screens]; - if (p_screen < [screenArray count]) { + if ((NSUInteger)p_screen < [screenArray count]) { float display_scale = _display_scale([screenArray objectAtIndex:p_screen]); NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; // Return the top-left corner of the screen, for OS X the y starts at the bottom @@ -2362,12 +2315,12 @@ Point2 OS_OSX::get_screen_position(int p_screen) const { } int OS_OSX::get_screen_dpi(int p_screen) const { - if (p_screen == -1) { + if (p_screen < 0) { p_screen = get_current_screen(); } NSArray *screenArray = [NSScreen screens]; - if (p_screen < [screenArray count]) { + if ((NSUInteger)p_screen < [screenArray count]) { float displayScale = _display_scale([screenArray objectAtIndex:p_screen]); NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription]; NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue]; @@ -2381,12 +2334,12 @@ int OS_OSX::get_screen_dpi(int p_screen) const { } Size2 OS_OSX::get_screen_size(int p_screen) const { - if (p_screen == -1) { + if (p_screen < 0) { p_screen = get_current_screen(); } NSArray *screenArray = [NSScreen screens]; - if (p_screen < [screenArray count]) { + if ((NSUInteger)p_screen < [screenArray count]) { float displayScale = _display_scale([screenArray objectAtIndex:p_screen]); // Note: Use frame to get the whole screen size NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; @@ -3004,20 +2957,11 @@ Error OS_OSX::move_to_trash(const String &p_path) { } void OS_OSX::_set_use_vsync(bool p_enable) { - // CGLCPSwapInterval broke in OSX 10.14 and it seems Apple is not interested in fixing - // it as OpenGL is now deprecated and Metal solves this differently. - // Following SDLs example we're working around this using DisplayLink - // When vsync is enabled we set a flag "waiting_for_vsync" to true. - // This flag is set to false when DisplayLink informs us our display is about to refresh. - - /* CGLContextObj ctx = CGLGetCurrentContext(); + CGLContextObj ctx = CGLGetCurrentContext(); if (ctx) { GLint swapInterval = p_enable ? 1 : 0; CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval); - }*/ - - ///TODO Maybe pause/unpause display link? - waiting_for_vsync = p_enable; + } } OS_OSX *OS_OSX::singleton = NULL; diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 87dc6421ac..12e53054bc 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -88,8 +88,6 @@ Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int visual_server = memnew(VisualServerRaster); visual_server->init(); - camera_server = memnew(CameraServer); - AudioDriverManager::initialize(p_audio_driver); input = memnew(InputDefault); @@ -119,8 +117,6 @@ void OS_Server::finalize() { memdelete(input); - memdelete(camera_server); - memdelete(power_manager); ResourceLoader::remove_resource_format_loader(resource_loader_dummy); diff --git a/platform/server/os_server.h b/platform/server/os_server.h index b8119288ff..6d975ca7e0 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -71,7 +71,6 @@ class OS_Server : public OS_Unix { #endif CrashHandler crash_handler; - CameraServer *camera_server; int video_driver_index; diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py index 7da93eafae..000bd18e7d 100644 --- a/platform/uwp/detect.py +++ b/platform/uwp/detect.py @@ -34,6 +34,7 @@ def get_flags(): return [ ('tools', False), ('xaudio2', True), + ('builtin_pcre2_with_jit', False), ] diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index fefad3584b..be78e4db20 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -517,7 +517,7 @@ Error AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t int total_out_before = strm.total_out; int err = deflate(&strm, Z_FULL_FLUSH); - ERR_FAIL_COND_V(err >= 0, ERR_BUG); // Negative means bug + ERR_FAIL_COND_V(err < 0, ERR_BUG); // Negative means bug bh.compressed_size = strm.total_out - total_out_before; @@ -1144,11 +1144,21 @@ public: return valid; } + if (!_valid_resource_name(p_preset->get("package/short_name"))) { + valid = false; + err += TTR("Invalid package short name.") + "\n"; + } + if (!_valid_resource_name(p_preset->get("package/unique_name"))) { valid = false; err += TTR("Invalid package unique name.") + "\n"; } + if (!_valid_resource_name(p_preset->get("package/publisher_display_name"))) { + valid = false; + err += TTR("Invalid package publisher display name.") + "\n"; + } + if (!_valid_guid(p_preset->get("identity/product_guid"))) { valid = false; err += TTR("Invalid product GUID.") + "\n"; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 60f2290355..eb0ae96111 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -303,9 +303,6 @@ Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_a visual_server->init(); - ///@TODO implement a subclass for UWP and instantiate that instead - camera_server = memnew(CameraServer); - input = memnew(InputDefault); joypad = ref new JoypadUWP(input); @@ -404,8 +401,6 @@ void OS_UWP::finalize() { memdelete(input); - memdelete(camera_server); - joypad = nullptr; } diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 370cab6a9b..adca7d18cc 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -41,7 +41,6 @@ #include "main/input_default.h" #include "power_uwp.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" @@ -93,8 +92,6 @@ private: VisualServer *visual_server; int pressrc; - CameraServer *camera_server; - ContextEGL_UWP *gl_context; Windows::UI::Core::CoreWindow ^ window; diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 8426ccbb89..892d734734 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -8,7 +8,6 @@ import platform_windows_builders common_win = [ "godot_windows.cpp", - "camera_win.cpp", "context_gl_windows.cpp", "crash_handler_windows.cpp", "os_windows.cpp", diff --git a/platform/windows/camera_win.cpp b/platform/windows/camera_win.cpp deleted file mode 100644 index 10787d0d0a..0000000000 --- a/platform/windows/camera_win.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/*************************************************************************/ -/* camera_win.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "camera_win.h" - -///@TODO sorry guys, I got about 80% through implementing this using DirectShow only -// to find out Microsoft deprecated half the API and its replacement is as confusing -// as they could make it. Joey suggested looking into libuvc which offers a more direct -// route to webcams over USB and this is very promising but it wouldn't compile on -// windows for me...I've gutted the classes I implemented DirectShow in just to have -// a skeleton for someone to work on, mail me for more details or if you want a copy.... - -////////////////////////////////////////////////////////////////////////// -// CameraFeedWindows - Subclass for our camera feed on windows - -/// @TODO need to implement this - -class CameraFeedWindows : public CameraFeed { -private: -protected: -public: - CameraFeedWindows(); - virtual ~CameraFeedWindows(); - - bool activate_feed(); - void deactivate_feed(); -}; - -CameraFeedWindows::CameraFeedWindows(){ - ///@TODO implement this, should store information about our available camera -}; - -CameraFeedWindows::~CameraFeedWindows() { - // make sure we stop recording if we are! - if (is_active()) { - deactivate_feed(); - }; - - ///@TODO free up anything used by this -}; - -bool CameraFeedWindows::activate_feed() { - ///@TODO this should activate our camera and start the process of capturing frames - - return true; -}; - -///@TODO we should probably have a callback method here that is being called by the -// camera API which provides frames and call back into the CameraServer to update our texture - -void CameraFeedWindows::deactivate_feed(){ - ///@TODO this should deactivate our camera and stop the process of capturing frames -}; - -////////////////////////////////////////////////////////////////////////// -// CameraWindows - Subclass for our camera server on windows - -void CameraWindows::add_active_cameras(){ - ///@TODO scan through any active cameras and create CameraFeedWindows objects for them -}; - -CameraWindows::CameraWindows() { - // Find cameras active right now - add_active_cameras(); - - // need to add something that will react to devices being connected/removed... -}; - -CameraWindows::~CameraWindows(){ - -}; diff --git a/platform/windows/camera_win.h b/platform/windows/camera_win.h deleted file mode 100644 index 22ce9aa43f..0000000000 --- a/platform/windows/camera_win.h +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************/ -/* camera_win.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CAMERAWIN_H -#define CAMERAWIN_H - -#include "servers/camera/camera_feed.h" -#include "servers/camera_server.h" - -class CameraWindows : public CameraServer { -private: - void add_active_cameras(); - -public: - CameraWindows(); - ~CameraWindows(); -}; - -#endif /* CAMERAWIN_H */ diff --git a/platform/windows/context_gl_windows.cpp b/platform/windows/context_gl_windows.cpp index e715999378..34a5698394 100644 --- a/platform/windows/context_gl_windows.cpp +++ b/platform/windows/context_gl_windows.cpp @@ -34,6 +34,8 @@ #include "context_gl_windows.h" +#include <dwmapi.h> + #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_FLAGS_ARB 0x2094 @@ -63,16 +65,52 @@ int ContextGL_Windows::get_window_height() { return OS::get_singleton()->get_video_mode().height; } +bool ContextGL_Windows::should_vsync_via_compositor() { + + if (OS::get_singleton()->is_window_fullscreen() || !OS::get_singleton()->is_vsync_via_compositor_enabled()) { + return false; + } + + // Note: All Windows versions supported by Godot have a compositor. + // It can be disabled on earlier Windows versions. + BOOL dwm_enabled; + + if (SUCCEEDED(DwmIsCompositionEnabled(&dwm_enabled))) { + return dwm_enabled; + } + + return false; +} + void ContextGL_Windows::swap_buffers() { SwapBuffers(hDC); + + if (use_vsync) { + bool vsync_via_compositor_now = should_vsync_via_compositor(); + + if (vsync_via_compositor_now) { + DwmFlush(); + } + + if (vsync_via_compositor_now != vsync_via_compositor) { + // The previous frame had a different operating mode than this + // frame. Set the 'vsync_via_compositor' member variable and the + // OpenGL swap interval to their proper values. + set_use_vsync(true); + } + } } void ContextGL_Windows::set_use_vsync(bool p_use) { + vsync_via_compositor = p_use && should_vsync_via_compositor(); + if (wglSwapIntervalEXT) { - wglSwapIntervalEXT(p_use ? 1 : 0); + int swap_interval = (p_use && !vsync_via_compositor) ? 1 : 0; + wglSwapIntervalEXT(swap_interval); } + use_vsync = p_use; } @@ -177,6 +215,7 @@ ContextGL_Windows::ContextGL_Windows(HWND hwnd, bool p_opengl_3_context) { opengl_3_context = p_opengl_3_context; hWnd = hwnd; use_vsync = false; + vsync_via_compositor = false; } ContextGL_Windows::~ContextGL_Windows() { diff --git a/platform/windows/context_gl_windows.h b/platform/windows/context_gl_windows.h index d23fba50e1..e65ea1928f 100644 --- a/platform/windows/context_gl_windows.h +++ b/platform/windows/context_gl_windows.h @@ -50,9 +50,12 @@ class ContextGL_Windows { HWND hWnd; bool opengl_3_context; bool use_vsync; + bool vsync_via_compositor; PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; + static bool should_vsync_via_compositor(); + public: void release_current(); diff --git a/platform/windows/detect.py b/platform/windows/detect.py index f4390a9882..b37a21f37f 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -221,7 +221,8 @@ def configure_msvc(env, manual_msvc_config): LIBS = ['winmm', 'opengl32', 'dsound', 'kernel32', 'ole32', 'oleaut32', 'user32', 'gdi32', 'IPHLPAPI', 'Shlwapi', 'wsock32', 'Ws2_32', - 'shell32', 'advapi32', 'dinput8', 'dxguid', 'imm32', 'bcrypt','Avrt'] + 'shell32', 'advapi32', 'dinput8', 'dxguid', 'imm32', 'bcrypt','Avrt', + 'dwmapi'] env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS]) if manual_msvc_config: @@ -348,9 +349,9 @@ def configure_mingw(env): env.Append(CCFLAGS=['-mwindows']) env.Append(CPPDEFINES=['WINDOWS_ENABLED', 'OPENGL_ENABLED', 'WASAPI_ENABLED', 'WINMIDI_ENABLED']) env.Append(CPPDEFINES=[('WINVER', env['target_win_version']), ('_WIN32_WINNT', env['target_win_version'])]) - env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt', 'avrt', 'uuid']) + env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt', 'avrt', 'uuid', 'dwmapi']) - env.Append(CPPDEFINES=['MINGW_ENABLED']) + env.Append(CPPDEFINES=['MINGW_ENABLED', ('MINGW_HAS_SECURE_API', 1)]) # resrc env.Append(BUILDERS={'RES': env.Builder(action=build_res_file, suffix='.o', src_suffix='.rc')}) diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index 3abb05b494..858453ddfd 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -39,6 +39,7 @@ static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, class EditorExportPlatformWindows : public EditorExportPlatformPC { + void _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path); Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path); public: @@ -62,15 +63,50 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> return err; } + _rcedit_add_data(p_preset, p_path); + + if (p_preset->get("codesign/enable") && err == OK) { + err = _code_sign(p_preset, p_path); + } + + return err; +} + +void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { + EditorExportPlatformPC::get_export_options(r_options); + + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false)); +#ifdef WINDOWS_ENABLED + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0)); +#endif + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/description"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::POOL_STRING_ARRAY, "codesign/custom_options"), PoolStringArray())); + + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), "")); +} + +void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path) { String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); if (rcedit_path == String()) { - return OK; + return; } if (!FileAccess::exists(rcedit_path)) { - ERR_PRINTS("Could not find rcedit executable at " + rcedit_path + ", aborting."); - return ERR_FILE_NOT_FOUND; + ERR_PRINTS("Could not find rcedit executable at " + rcedit_path + ", no icon or app information data will be included."); + return; } #ifndef WINDOWS_ENABLED @@ -78,8 +114,8 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> String wine_path = EditorSettings::get_singleton()->get("export/windows/wine"); if (wine_path != String() && !FileAccess::exists(wine_path)) { - ERR_PRINTS("Could not find wine executable at " + wine_path + ", aborting."); - return ERR_FILE_NOT_FOUND; + ERR_PRINTS("Could not find wine executable at " + wine_path + ", no icon or app information data will be included."); + return; } if (wine_path == String()) { @@ -144,37 +180,6 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> args.push_front(rcedit_path); OS::get_singleton()->execute(wine_path, args, true); #endif - - if (p_preset->get("codesign/enable") && err == OK) { - err = _code_sign(p_preset, p_path); - } - - return err; -} - -void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { - EditorExportPlatformPC::get_export_options(r_options); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false)); -#ifdef WINDOWS_ENABLED - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0)); -#endif - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/description"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::POOL_STRING_ARRAY, "codesign/custom_options"), PoolStringArray())); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/trademarks"), "")); } Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) { diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis index 55c83c3f3c..593557cc69 100644 --- a/platform/windows/godot.natvis +++ b/platform/windows/godot.natvis @@ -143,4 +143,12 @@ <Item Name="alpha">a</Item> </Expand> </Type> + + <Type Name="Node" Inheritable="false"> + <Expand> + <Item Name="Object">(Object*)this</Item> + <Item Name="class_name">(StringName*)(((char*)this) + sizeof(Object))</Item> + <Item Name="data">(Node::Data*)(((char*)this) + sizeof(Object) + sizeof(StringName))</Item> + </Expand> + </Type> </AutoVisualizer> diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 81b8d08b3d..f749134f3c 100644..100755 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -70,6 +70,10 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; #define WM_TOUCH 576 #endif +#ifndef WM_POINTERUPDATE +#define WM_POINTERUPDATE 0x0245 +#endif + typedef struct { int count; int screen; @@ -192,6 +196,9 @@ BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) { } } +GetPointerTypePtr OS_Windows::win8p_GetPointerType = NULL; +GetPointerPenInfoPtr OS_Windows::win8p_GetPointerPenInfo = NULL; + void OS_Windows::initialize_debugging() { SetConsoleCtrlHandler(HandlerRoutine, TRUE); @@ -288,15 +295,16 @@ void OS_Windows::_drag_event(float p_x, float p_y, int idx) { if (curr->get() == Vector2(p_x, p_y)) return; - curr->get() = Vector2(p_x, p_y); - Ref<InputEventScreenDrag> event; event.instance(); event->set_index(idx); event->set_position(Vector2(p_x, p_y)); + event->set_relative(Vector2(p_x, p_y) - curr->get()); if (main_loop) input->accumulate_input_event(event); + + curr->get() = Vector2(p_x, p_y); }; LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -480,6 +488,119 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } delete[] lpb; } break; + case WM_POINTERUPDATE: { + if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) { + break; + } + + if (!win8p_GetPointerType || !win8p_GetPointerPenInfo) { + break; + } + + uint32_t pointer_id = LOWORD(wParam); + POINTER_INPUT_TYPE pointer_type = PT_POINTER; + if (!win8p_GetPointerType(pointer_id, &pointer_type)) { + break; + } + + if (pointer_type != PT_PEN) { + break; + } + + POINTER_PEN_INFO pen_info; + if (!win8p_GetPointerPenInfo(pointer_id, &pen_info)) { + break; + } + + if (input->is_emulating_mouse_from_touch()) { + // Universal translation enabled; ignore OS translation + LPARAM extra = GetMessageExtraInfo(); + if (IsTouchEvent(extra)) { + break; + } + } + + if (outside) { + //mouse enter + + if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED) + main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); + + CursorShape c = cursor_shape; + cursor_shape = CURSOR_MAX; + set_cursor_shape(c); + outside = false; + + //Once-Off notification, must call again.... + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + } + + // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode. + if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) + break; + + Ref<InputEventMouseMotion> mm; + mm.instance(); + + mm->set_pressure(pen_info.pressure ? (float)pen_info.pressure / 1024 : 0); + mm->set_tilt(Vector2(pen_info.tiltX ? (float)pen_info.tiltX / 90 : 0, pen_info.tiltY ? (float)pen_info.tiltY / 90 : 0)); + + mm->set_control((wParam & MK_CONTROL) != 0); + mm->set_shift((wParam & MK_SHIFT) != 0); + mm->set_alt(alt_mem); + + mm->set_button_mask(last_button_state); + + POINT coords; //client coords + coords.x = GET_X_LPARAM(lParam); + coords.y = GET_Y_LPARAM(lParam); + + ScreenToClient(hWnd, &coords); + + mm->set_position(Vector2(coords.x, coords.y)); + mm->set_global_position(Vector2(coords.x, coords.y)); + + if (mouse_mode == MOUSE_MODE_CAPTURED) { + + Point2i c(video_mode.width / 2, video_mode.height / 2); + old_x = c.x; + old_y = c.y; + + if (mm->get_position() == c) { + center = c; + return 0; + } + + Point2i ncenter = mm->get_position(); + center = ncenter; + POINT pos = { (int)c.x, (int)c.y }; + ClientToScreen(hWnd, &pos); + SetCursorPos(pos.x, pos.y); + } + + input->set_mouse_position(mm->get_position()); + mm->set_speed(input->get_last_mouse_speed()); + + if (old_invalid) { + + old_x = mm->get_position().x; + old_y = mm->get_position().y; + old_invalid = false; + } + + mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); + old_x = mm->get_position().x; + old_y = mm->get_position().y; + if (window_has_focus && main_loop) + input->parse_input_event(mm); + + return 0; //Pointer event handled return 0 to avoid duplicate WM_MOUSEMOVE event + } break; case WM_MOUSEMOVE: { if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) { break; @@ -1359,6 +1480,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int video_driver_index = p_video_driver; gl_context->set_use_vsync(video_mode.use_vsync); + set_vsync_via_compositor(video_mode.vsync_via_compositor); #endif visual_server = memnew(VisualServerRaster); @@ -1373,8 +1495,6 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int power_manager = memnew(PowerWindows); - camera_server = memnew(CameraWindows); - AudioDriverManager::initialize(p_audio_driver); TRACKMOUSEEVENT tme; @@ -1528,7 +1648,6 @@ void OS_Windows::finalize() { memdelete(joypad); memdelete(input); - memdelete(camera_server); touch_state.clear(); cursors_cache.clear(); @@ -1875,6 +1994,8 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) { if (p_enabled) { + was_maximized = maximized; + if (pre_fs_valid) { GetWindowRect(hWnd, &pre_fs_rect); } @@ -1904,7 +2025,7 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) { rect.bottom = video_mode.height; } - _update_window_style(false); + _update_window_style(false, was_maximized); MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); @@ -2086,12 +2207,16 @@ bool OS_Windows::get_borderless_window() { return video_mode.borderless_window; } -void OS_Windows::_update_window_style(bool repaint) { +void OS_Windows::_update_window_style(bool p_repaint, bool p_maximized) { if (video_mode.fullscreen || video_mode.borderless_window) { SetWindowLongPtr(hWnd, GWL_STYLE, WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE); } else { if (video_mode.resizable) { - SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE); + if (p_maximized) { + SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE); + } else { + SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE); + } } else { SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_VISIBLE); } @@ -2099,7 +2224,7 @@ void OS_Windows::_update_window_style(bool repaint) { SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); - if (repaint) { + if (p_repaint) { RECT rect; GetWindowRect(hWnd, &rect); MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); @@ -2861,7 +2986,7 @@ void OS_Windows::move_window_to_foreground() { Error OS_Windows::shell_open(String p_uri) { - ShellExecuteW(NULL, L"open", p_uri.c_str(), NULL, NULL, SW_SHOWNORMAL); + ShellExecuteW(NULL, NULL, p_uri.c_str(), NULL, NULL, SW_SHOWNORMAL); return OK; } @@ -3246,8 +3371,16 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { control_mem = false; meta_mem = false; minimized = false; + was_maximized = false; console_visible = IsWindowVisible(GetConsoleWindow()); + //Note: Functions for pen input, available on Windows 8+ + HMODULE user32_lib = LoadLibraryW(L"user32.dll"); + if (user32_lib) { + win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType"); + win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo"); + } + hInstance = _hInstance; pressrc = 0; old_invalid = true; diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 915d025e3b..28fec27216 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -31,7 +31,6 @@ #ifndef OS_WINDOWS_H #define OS_WINDOWS_H -#include "camera_win.h" #include "context_gl_windows.h" #include "core/os/input.h" #include "core/os/os.h" @@ -56,6 +55,71 @@ #include <windows.h> #include <windowsx.h> +#ifndef POINTER_STRUCTURES + +#define POINTER_STRUCTURES + +typedef DWORD POINTER_INPUT_TYPE; +typedef UINT32 POINTER_FLAGS; +typedef UINT32 PEN_FLAGS; +typedef UINT32 PEN_MASK; + +enum tagPOINTER_INPUT_TYPE { + PT_POINTER = 0x00000001, + PT_TOUCH = 0x00000002, + PT_PEN = 0x00000003, + PT_MOUSE = 0x00000004, + PT_TOUCHPAD = 0x00000005 +}; + +typedef enum tagPOINTER_BUTTON_CHANGE_TYPE { + POINTER_CHANGE_NONE, + POINTER_CHANGE_FIRSTBUTTON_DOWN, + POINTER_CHANGE_FIRSTBUTTON_UP, + POINTER_CHANGE_SECONDBUTTON_DOWN, + POINTER_CHANGE_SECONDBUTTON_UP, + POINTER_CHANGE_THIRDBUTTON_DOWN, + POINTER_CHANGE_THIRDBUTTON_UP, + POINTER_CHANGE_FOURTHBUTTON_DOWN, + POINTER_CHANGE_FOURTHBUTTON_UP, + POINTER_CHANGE_FIFTHBUTTON_DOWN, + POINTER_CHANGE_FIFTHBUTTON_UP, +} POINTER_BUTTON_CHANGE_TYPE; + +typedef struct tagPOINTER_INFO { + POINTER_INPUT_TYPE pointerType; + UINT32 pointerId; + UINT32 frameId; + POINTER_FLAGS pointerFlags; + HANDLE sourceDevice; + HWND hwndTarget; + POINT ptPixelLocation; + POINT ptHimetricLocation; + POINT ptPixelLocationRaw; + POINT ptHimetricLocationRaw; + DWORD dwTime; + UINT32 historyCount; + INT32 InputData; + DWORD dwKeyStates; + UINT64 PerformanceCount; + POINTER_BUTTON_CHANGE_TYPE ButtonChangeType; +} POINTER_INFO; + +typedef struct tagPOINTER_PEN_INFO { + POINTER_INFO pointerInfo; + PEN_FLAGS penFlags; + PEN_MASK penMask; + UINT32 pressure; + UINT32 rotation; + INT32 tiltX; + INT32 tiltY; +} POINTER_PEN_INFO; + +#endif + +typedef BOOL(WINAPI *GetPointerTypePtr)(uint32_t p_id, POINTER_INPUT_TYPE *p_type); +typedef BOOL(WINAPI *GetPointerPenInfoPtr)(uint32_t p_id, POINTER_PEN_INFO *p_pen_info); + typedef struct { BYTE bWidth; // Width, in pixels, of the image BYTE bHeight; // Height, in pixels, of the image @@ -77,11 +141,16 @@ typedef struct { class JoypadWindows; class OS_Windows : public OS { + static GetPointerTypePtr win8p_GetPointerType; + static GetPointerPenInfoPtr win8p_GetPointerPenInfo; + enum { KEY_EVENT_BUFFER_SIZE = 512 }; +#ifdef STDOUT_FILE FILE *stdo; +#endif struct KeyEvent { @@ -105,9 +174,7 @@ class OS_Windows : public OS { ContextGL_Windows *gl_context; #endif VisualServer *visual_server; - CameraWindows *camera_server; int pressrc; - HDC hDC; // Private GDI Device Context HINSTANCE hInstance; // Holds The Instance Of The Application HWND hWnd; Point2 last_pos; @@ -175,7 +242,7 @@ class OS_Windows : public OS { void _drag_event(float p_x, float p_y, int idx); void _touch_event(bool p_pressed, float p_x, float p_y, int idx); - void _update_window_style(bool repaint = true); + void _update_window_style(bool p_repaint = true, bool p_maximized = false); void _set_mouse_mode_impl(MouseMode p_mode); @@ -208,6 +275,7 @@ protected: bool minimized; bool borderless; bool console_visible; + bool was_maximized; public: LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 694aea7462..39d5c0e84e 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -83,6 +83,12 @@ #define XINPUT_CLIENT_VERSION_MAJOR 2 #define XINPUT_CLIENT_VERSION_MINOR 2 +#define VALUATOR_ABSX 0 +#define VALUATOR_ABSY 1 +#define VALUATOR_PRESSURE 2 +#define VALUATOR_TILTX 3 +#define VALUATOR_TILTY 4 + static const double abs_resolution_mult = 10000.0; static const double abs_resolution_range_mult = 10.0; @@ -590,9 +596,6 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a AudioDriverManager::initialize(p_audio_driver); - ///@TODO implement a subclass for Linux and instantiate that instead - camera_server = memnew(CameraServer); - input = memnew(InputDefault); window_has_focus = true; // Set focus to true at init @@ -665,6 +668,15 @@ bool OS_X11::refresh_device_info() { int range_min_y = 0; int range_max_x = 0; int range_max_y = 0; + int pressure_resolution = 0; + int pressure_min = 0; + int pressure_max = 0; + int tilt_resolution_x = 0; + int tilt_resolution_y = 0; + int tilt_range_min_x = 0; + int tilt_range_min_y = 0; + int tilt_range_max_x = 0; + int tilt_range_max_y = 0; for (int j = 0; j < dev->num_classes; j++) { #ifdef TOUCH_ENABLED if (dev->classes[j]->type == XITouchClass && ((XITouchClassInfo *)dev->classes[j])->mode == XIDirectTouch) { @@ -674,16 +686,28 @@ bool OS_X11::refresh_device_info() { if (dev->classes[j]->type == XIValuatorClass) { XIValuatorClassInfo *class_info = (XIValuatorClassInfo *)dev->classes[j]; - if (class_info->number == 0 && class_info->mode == XIModeAbsolute) { + if (class_info->number == VALUATOR_ABSX && class_info->mode == XIModeAbsolute) { resolution_x = class_info->resolution; range_min_x = class_info->min; range_max_x = class_info->max; absolute_mode = true; - } else if (class_info->number == 1 && class_info->mode == XIModeAbsolute) { + } else if (class_info->number == VALUATOR_ABSY && class_info->mode == XIModeAbsolute) { resolution_y = class_info->resolution; range_min_y = class_info->min; range_max_y = class_info->max; absolute_mode = true; + } else if (class_info->number == VALUATOR_PRESSURE && class_info->mode == XIModeAbsolute) { + pressure_resolution = class_info->resolution; + pressure_min = class_info->min; + pressure_max = class_info->max; + } else if (class_info->number == VALUATOR_TILTX && class_info->mode == XIModeAbsolute) { + tilt_resolution_x = class_info->resolution; + tilt_range_min_x = class_info->min; + tilt_range_max_x = class_info->max; + } else if (class_info->number == VALUATOR_TILTY && class_info->mode == XIModeAbsolute) { + tilt_resolution_y = class_info->resolution; + tilt_range_min_y = class_info->min; + tilt_range_max_y = class_info->max; } } } @@ -703,6 +727,18 @@ bool OS_X11::refresh_device_info() { xi.absolute_devices[dev->deviceid] = Vector2(abs_resolution_mult / resolution_x, abs_resolution_mult / resolution_y); print_verbose("XInput: Absolute pointing device: " + String(dev->name)); } + + if (pressure_resolution <= 0) { + pressure_resolution = (pressure_max - pressure_min); + } + if (tilt_resolution_x <= 0) { + tilt_resolution_x = (tilt_range_max_x - tilt_range_min_x); + } + if (tilt_resolution_y <= 0) { + tilt_resolution_y = (tilt_range_max_y - tilt_range_min_y); + } + xi.pressure = 0; + xi.pen_devices[dev->deviceid] = Vector3(pressure_resolution, tilt_resolution_x, tilt_resolution_y); } XIFreeDeviceInfo(info); @@ -793,8 +829,6 @@ void OS_X11::finalize() { memdelete(input); - memdelete(camera_server); - cursors_cache.clear(); visual_server->finish(); memdelete(visual_server); @@ -1827,6 +1861,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { input->accumulate_input_event(k); } + memfree(utf8string); return; } memfree(utf8string); @@ -2095,14 +2130,39 @@ void OS_X11::process_xevents() { double rel_x = 0.0; double rel_y = 0.0; + double pressure = 0.0; + double tilt_x = 0.0; + double tilt_y = 0.0; - if (XIMaskIsSet(raw_event->valuators.mask, 0)) { + if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_ABSX)) { rel_x = *values; values++; } - if (XIMaskIsSet(raw_event->valuators.mask, 1)) { + if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_ABSY)) { rel_y = *values; + values++; + } + + if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_PRESSURE)) { + pressure = *values; + values++; + } + + if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTX)) { + tilt_x = *values; + values++; + } + + if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTY)) { + tilt_y = *values; + } + + Map<int, Vector3>::Element *pen_info = xi.pen_devices.find(device_id); + if (pen_info) { + Vector3 mult = pen_info->value(); + if (mult.x != 0.0) xi.pressure = pressure / mult.x; + if ((mult.y != 0.0) && (mult.z != 0.0)) xi.tilt = Vector2(tilt_x / mult.y, tilt_y / mult.z); } // https://bugs.freedesktop.org/show_bug.cgi?id=71609 @@ -2417,6 +2477,9 @@ void OS_X11::process_xevents() { Ref<InputEventMouseMotion> mm; mm.instance(); + mm->set_pressure(xi.pressure); + mm->set_tilt(xi.tilt); + // Make the absolute position integral so it doesn't look _too_ weird :) Point2i posi(pos); diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index e6c2effacf..d02160fab7 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -42,7 +42,6 @@ #include "main/input_default.h" #include "power_x11.h" #include "servers/audio_server.h" -#include "servers/camera_server.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" //#include "servers/visual/visual_server_wrap_mt.h" @@ -131,9 +130,12 @@ class OS_X11 : public OS_Unix { int opcode; Vector<int> touch_devices; Map<int, Vector2> absolute_devices; + Map<int, Vector3> pen_devices; XIEventMask all_event_mask; XIEventMask all_master_event_mask; Map<int, Vector2> state; + double pressure; + Vector2 tilt; Vector2 mouse_pos_to_filter; Vector2 relative_motion; Vector2 raw_pos; @@ -147,8 +149,6 @@ class OS_X11 : public OS_Unix { void get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state); void flush_mouse_motion(); - CameraServer *camera_server; - MouseMode mouse_mode; Point2i center; |