From 9c6c4a264d4b01a11f7f175da890d7dcd5dffdd8 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Tue, 23 Jul 2019 13:52:16 -0700 Subject: [PATCH 01/20] inital work --- launchers/darwin/CMakeLists.txt | 6 +++++- launchers/darwin/src/updater/main.m | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 launchers/darwin/src/updater/main.m diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index 177a7722e5..6114c656d2 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -47,6 +47,9 @@ set(src_files nib/ProcessScreen.xib nib/DisplayNameScreen.xib) +set(updater_src_files + src/updater/main.m) + set(APP_NAME "HQ Launcher") set(CMAKE_C_FLAGS "-x objective-c") @@ -72,6 +75,7 @@ endfunction() set_packaging_parameters() add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${src_files}) +add_executable("updater" ${updater_src_files}) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME} MACOSX_BUNDLE_BUNDLE_NAME ${APP_NAME}) set_from_env(LAUNCHER_HMAC_SECRET LAUNCHER_HMAC_SECRET "") @@ -103,7 +107,7 @@ add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD ${CMAKE_SOURCE_DIR}/images "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${APP_NAME}.app/Contents/Resources/") install( - TARGETS HQLauncher + TARGETS HQLauncher updater BUNDLE DESTINATION "." COMPONENT applications ) diff --git a/launchers/darwin/src/updater/main.m b/launchers/darwin/src/updater/main.m new file mode 100644 index 0000000000..cef16f1530 --- /dev/null +++ b/launchers/darwin/src/updater/main.m @@ -0,0 +1,4 @@ +int main(int argc, const char* argv[]) +{ + NSLog(@"Hello World"); +} From 7ed13a2ba2f42942a6c85226bfeb5fb08b7176b8 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Tue, 23 Jul 2019 16:56:09 -0700 Subject: [PATCH 02/20] auto-updater --- launchers/darwin/CMakeLists.txt | 10 ++- launchers/darwin/src/DownloadLauncher.h | 8 ++ launchers/darwin/src/DownloadLauncher.m | 74 +++++++++++++++++++ launchers/darwin/src/LatestBuildRequest.m | 12 ++- launchers/darwin/src/Launcher.h | 5 +- launchers/darwin/src/Launcher.m | 52 ++++++++----- .../darwin/src/LauncherCommandlineArgs.h | 8 ++ .../darwin/src/LauncherCommandlineArgs.m | 30 ++++++++ launchers/darwin/src/main.mm | 1 + launchers/darwin/src/updater/main.m | 37 +++++++++- 10 files changed, 214 insertions(+), 23 deletions(-) create mode 100644 launchers/darwin/src/DownloadLauncher.h create mode 100644 launchers/darwin/src/DownloadLauncher.m create mode 100644 launchers/darwin/src/LauncherCommandlineArgs.h create mode 100644 launchers/darwin/src/LauncherCommandlineArgs.m diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index 6114c656d2..fe7f4298ce 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -20,6 +20,8 @@ set(src_files src/DownloadInterface.m src/DownloadDomainContent.h src/DownloadDomainContent.m + src/DownloadLauncher.h + src/DownloadLauncher.m src/DownloadScripts.h src/DownloadScripts.m src/CredentialsRequest.h @@ -34,6 +36,8 @@ set(src_files src/Interface.m src/ErrorViewController.h src/ErrorViewController.m + src/LauncherCommandlineArgs.h + src/LauncherCommandlineArgs.m src/Settings.h src/Settings.m src/LaunchInterface.h @@ -106,8 +110,12 @@ add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/images "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${APP_NAME}.app/Contents/Resources/") +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND updater + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/updater" "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${APP_NAME}.app/Contents/Resources/") + install( - TARGETS HQLauncher updater + TARGETS HQLauncher BUNDLE DESTINATION "." COMPONENT applications ) diff --git a/launchers/darwin/src/DownloadLauncher.h b/launchers/darwin/src/DownloadLauncher.h new file mode 100644 index 0000000000..2f97910cd8 --- /dev/null +++ b/launchers/darwin/src/DownloadLauncher.h @@ -0,0 +1,8 @@ +#import + +@interface DownloadLauncher : NSObject { +} + +- (void) downloadLauncher:(NSString*) launcherUrl; + +@end diff --git a/launchers/darwin/src/DownloadLauncher.m b/launchers/darwin/src/DownloadLauncher.m new file mode 100644 index 0000000000..d2538c897b --- /dev/null +++ b/launchers/darwin/src/DownloadLauncher.m @@ -0,0 +1,74 @@ +#import "DownloadLauncher.h" +#import "Launcher.h" + + +@implementation DownloadLauncher + +- (void) downloadLauncher:(NSString *)launcherUrl +{ + NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:launcherUrl] + cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:60.0]; + + NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; + NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]]; + NSURLSessionDownloadTask *downloadTask = [defaultSession downloadTaskWithRequest:request]; + [downloadTask resume]; +} + +-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { + CGFloat prog = (float)totalBytesWritten/totalBytesExpectedToWrite; + NSLog(@"Launcher downloaded %f", (100.0*prog)); + +} + +-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { + // unused in this example +} + +-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { + NSLog(@"Did finish downloading to url"); + NSError *error = nil; + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *destinationFileName = downloadTask.originalRequest.URL.lastPathComponent; + NSString* finalFilePath = [[[Launcher sharedLauncher] getDownloadPathForContentAndScripts] stringByAppendingPathComponent:destinationFileName]; + NSURL *destinationURL = [NSURL URLWithString: [finalFilePath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]] relativeToURL: [NSURL URLWithString:@"file://"]]; + NSLog(@"desintation %@", destinationURL); + if([fileManager fileExistsAtPath:[destinationURL path]]) + { + [fileManager removeItemAtURL:destinationURL error:nil]; + } + + NSLog(@"location: %@", location.path); + NSLog(@"destination: %@", destinationURL); + BOOL success = [fileManager moveItemAtURL:location toURL:destinationURL error:&error]; + + + NSLog(success ? @"TRUE" : @"FALSE"); + Launcher* sharedLauncher = [Launcher sharedLauncher]; + + if (error) { + NSLog(@"Download Launcher: failed to move file to destintation -> error: %@", error); + [sharedLauncher displayErrorPage]; + return; + } + NSLog(@"extracting domain content file"); + BOOL extractionSuccessful = [sharedLauncher extractZipFileAtDestination:[sharedLauncher getDownloadPathForContentAndScripts] :[[sharedLauncher getDownloadPathForContentAndScripts] stringByAppendingString:destinationFileName]]; + + if (!extractionSuccessful) { + [sharedLauncher displayErrorPage]; + return; + } + NSLog(@"finished extracting content file"); + + + [[Launcher sharedLauncher] runAutoupdater]; +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { + NSLog(@"completed; error: %@", error); + if (error) { + [[Launcher sharedLauncher] displayErrorPage]; + } +} +@end diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index deb6d9795b..a2650a194f 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -58,9 +58,11 @@ NSFileManager* fileManager = [NSFileManager defaultManager]; NSArray *values = [json valueForKey:@"results"]; + NSDictionary *launcherValues = [json valueForKey:@"launcher"]; NSDictionary *value = [values objectAtIndex:0]; - + NSString* launcherVersion = [launcherValues valueForKey:@"version"]; + NSString* launcherUrl = [[launcherValues valueForKey:@"mac"] valueForKey:@"url"]; NSString* buildNumber = [value valueForKey:@"latest_version"]; NSDictionary* installers = [value objectForKey:@"installers"]; NSDictionary* macInstallerObject = [installers objectForKey:@"mac"]; @@ -71,16 +73,22 @@ dispatch_async(dispatch_get_main_queue(), ^{ NSInteger currentVersion = [self getCurrentVersion]; + NSInteger currentLauncherVersion = atoi(LAUNCHER_BUILD_VERSION); + NSLog(@"Latest Build Request -> current launcher version %ld", currentLauncherVersion); + NSLog(@"Latest Build Request -> latest launcher version %ld", launcherVersion.integerValue); + NSLog(@"Latest Build Request -> launcher url %@", launcherUrl); NSLog(@"Latest Build Request -> does build directory exist: %@", appDirectoryExist ? @"TRUE" : @"FALSE"); NSLog(@"Latest Build Request -> current version: %ld", currentVersion); NSLog(@"Latest Build Request -> latest version: %ld", buildNumber.integerValue); NSLog(@"Latest Build Request -> mac url: %@", macInstallerUrl); BOOL latestVersionAvailable = (currentVersion != buildNumber.integerValue); + BOOL latestLauncherVersionAvailable = (currentLauncherVersion != launcherVersion.integerValue); [[Settings sharedSettings] buildVersion:buildNumber.integerValue]; BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist); NSLog(@"Latest Build Request -> SHOULD DOWNLOAD: %@", shouldDownloadInterface ? @"TRUE" : @"FALSE"); - [sharedLauncher shouldDownloadLatestBuild:shouldDownloadInterface :macInstallerUrl]; + [sharedLauncher shouldDownloadLatestBuild:shouldDownloadInterface :macInstallerUrl + :latestLauncherVersionAvailable :launcherUrl]; }); }]; diff --git a/launchers/darwin/src/Launcher.h b/launchers/darwin/src/Launcher.h index de67850bfe..d20f58dee7 100644 --- a/launchers/darwin/src/Launcher.h +++ b/launchers/darwin/src/Launcher.h @@ -2,6 +2,7 @@ #import "DownloadInterface.h" #import "CredentialsRequest.h" #import "DownloadDomainContent.h" +#import "DownloadLauncher.h" #import "LatestBuildRequest.h" #import "OrganizationRequest.h" #import "DownloadScripts.h" @@ -44,6 +45,7 @@ struct LatestBuildInfo { @property (nonatomic, retain) DownloadInterface* downloadInterface; @property (nonatomic, retain) CredentialsRequest* credentialsRequest; @property (nonatomic, retain) DownloadDomainContent* downloadDomainContent; +@property (nonatomic, retain) DownloadLauncher* downloadLauncher; @property (nonatomic, retain) DownloadScripts* downloadScripts; @property (nonatomic, retain) LatestBuildRequest* latestBuildRequest; @property (nonatomic, retain) OrganizationRequest* organizationRequest; @@ -74,11 +76,12 @@ struct LatestBuildInfo { - (void) showLoginScreen; - (void) restart; - (NSString*) getLauncherPath; +- (void) runAutoupdater; - (ProcessState) currentProccessState; - (void) setCurrentProcessState:(ProcessState) aProcessState; - (void) setLoginErrorState:(LoginError) aLoginError; - (LoginError) getLoginErrorState; -- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl; +- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl :(BOOL) newLauncherAvailable :(NSString*) launcherUrl; - (void) interfaceFinishedDownloading; - (NSString*) getDownloadPathForContentAndScripts; - (void) launchInterface; diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index 1a84e9143d..38027d6fd3 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -3,6 +3,7 @@ #import "SplashScreen.h" #import "LoginScreen.h" #import "DisplayNameScreen.h" +#import "LauncherCommandlineArgs.h" #import "ProcessScreen.h" #import "ErrorViewController.h" #import "Settings.h" @@ -32,6 +33,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; self.username = [[NSString alloc] initWithString:@"Default Property Value"]; self.downloadInterface = [DownloadInterface alloc]; self.downloadDomainContent = [DownloadDomainContent alloc]; + self.downloadLauncher = [DownloadLauncher alloc]; self.credentialsRequest = [CredentialsRequest alloc]; self.latestBuildRequest = [LatestBuildRequest alloc]; self.organizationRequest = [OrganizationRequest alloc]; @@ -362,28 +364,44 @@ static BOOL const DELETE_ZIP_FILES = TRUE; [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: loginScreen]; } -- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl +- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl :(BOOL) newLauncherAvailable :(NSString*) launcherUrl { - self.shouldDownloadInterface = shouldDownload; - self.interfaceDownloadUrl = downloadUrl; - self.latestBuildRequestFinished = TRUE; - if ([self isLoadedIn]) { - Launcher* sharedLauncher = [Launcher sharedLauncher]; - [sharedLauncher setCurrentProcessState:CHECKING_UPDATE]; - if (shouldDownload) { - ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; - [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; - [self startUpdateProgressIndicatorTimer]; - [self.downloadInterface downloadInterface: downloadUrl]; - return; - } - [self interfaceFinishedDownloading]; + NSDictionary* launcherArguments = [LauncherCommandlineArgs arguments]; + if (newLauncherAvailable && ![launcherArguments valueForKey: @"--noUpdate"]) { + [self.downloadLauncher downloadLauncher: launcherUrl]; } else { - [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; - [self showLoginScreen]; + self.shouldDownloadInterface = shouldDownload; + self.interfaceDownloadUrl = downloadUrl; + self.latestBuildRequestFinished = TRUE; + if ([self isLoadedIn]) { + Launcher* sharedLauncher = [Launcher sharedLauncher]; + [sharedLauncher setCurrentProcessState:CHECKING_UPDATE]; + if (shouldDownload) { + ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; + [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; + [self startUpdateProgressIndicatorTimer]; + [self.downloadInterface downloadInterface: downloadUrl]; + return; + } + [self interfaceFinishedDownloading]; + } else { + [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; + [self showLoginScreen]; + } } } +-(void)runAutoupdater +{ + NSTask* task = [[NSTask alloc] init]; + NSString* newLauncher = [[[Launcher sharedLauncher] getDownloadPathForContentAndScripts] stringByAppendingPathComponent: @"HQ Launcher.app"]; + task.launchPath = [newLauncher stringByAppendingString:@"/Contents/Resources/updater"]; + task.arguments = @[[[NSBundle mainBundle] bundlePath], newLauncher]; + [task launch]; + + [NSApp terminate:self]; +} + -(void)onSplashScreenTimerFinished:(NSTimer *)timer { [self.latestBuildRequest requestLatestBuildInfo]; diff --git a/launchers/darwin/src/LauncherCommandlineArgs.h b/launchers/darwin/src/LauncherCommandlineArgs.h new file mode 100644 index 0000000000..c348e50987 --- /dev/null +++ b/launchers/darwin/src/LauncherCommandlineArgs.h @@ -0,0 +1,8 @@ +#import +#import + +@interface LauncherCommandlineArgs : NSObject { +} ++(NSDictionary*) arguments; +@end + diff --git a/launchers/darwin/src/LauncherCommandlineArgs.m b/launchers/darwin/src/LauncherCommandlineArgs.m new file mode 100644 index 0000000000..0c53da2b71 --- /dev/null +++ b/launchers/darwin/src/LauncherCommandlineArgs.m @@ -0,0 +1,30 @@ +#import "LauncherCommandlineArgs.h" + +@implementation LauncherCommandlineArgs ++(NSDictionary*) arguments +{ + + NSArray* arguments = [[NSProcessInfo processInfo] arguments]; + if (arguments.count < 2) + { + return nil; + } + + NSMutableDictionary* argsDict = [[NSMutableDictionary alloc] init]; + NSMutableArray* args = [arguments mutableCopy]; + + for (NSString* arg in args) + { + if ([arg rangeOfString:@"="].location != NSNotFound && [arg rangeOfString:@"--"].location != NSNotFound) { + NSArray* components = [arg componentsSeparatedByString:@"="]; + NSString* key = [components objectAtIndex:0]; + NSString* value = [components objectAtIndex:1]; + [argsDict setObject:value forKey:key]; + } else if ([arg rangeOfString:@"--"].location != NSNotFound) { + [argsDict setObject:@TRUE forKey:arg]; + } + } + NSLog(@"AGS: %@", argsDict); + return argsDict; +} +@end diff --git a/launchers/darwin/src/main.mm b/launchers/darwin/src/main.mm index b6555aad87..8651ffe3ff 100644 --- a/launchers/darwin/src/main.mm +++ b/launchers/darwin/src/main.mm @@ -1,5 +1,6 @@ #import "Launcher.h" #import "Settings.h" +#import "LauncherCommandlineArgs.h" void redirectLogToDocuments() { diff --git a/launchers/darwin/src/updater/main.m b/launchers/darwin/src/updater/main.m index cef16f1530..31b333c5d9 100644 --- a/launchers/darwin/src/updater/main.m +++ b/launchers/darwin/src/updater/main.m @@ -1,4 +1,37 @@ -int main(int argc, const char* argv[]) +#import +#import + +@interface UpdaterHelper : NSObject ++(NSURL*) NSStringToNSURL: (NSString*) path; +@end + +@implementation UpdaterHelper ++(NSURL*) NSStringToNSURL: (NSString*) path { - NSLog(@"Hello World"); + return [NSURL URLWithString: [path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]] relativeToURL: [NSURL URLWithString:@"file://"]]; +} +@end + +int main(int argc, char const* argv[]) +{ + if (argc < 3) + { + NSLog(@"Error: wrong number of arguments"); + return 0; + } + + for (int index = 0; index < argc; index++) { + NSLog(@"argv at index %d = %s", index, argv[index]); + } + NSString* oldLauncher = [NSString stringWithUTF8String:argv[1]]; + NSString* newLauncher = [NSString stringWithUTF8String:argv[2]]; + NSFileManager* fileManager = [NSFileManager defaultManager]; + [fileManager removeItemAtURL:[UpdaterHelper NSStringToNSURL:oldLauncher] error:nil]; + [fileManager moveItemAtURL: [UpdaterHelper NSStringToNSURL: newLauncher] toURL: [UpdaterHelper NSStringToNSURL:oldLauncher] error:nil]; + NSWorkspace* workspace = [NSWorkspace sharedWorkspace]; + NSURL* applicationURL = [UpdaterHelper NSStringToNSURL: [oldLauncher stringByAppendingString: @"/Contents/MacOS/HQ Launcher"]]; + NSArray* arguments =@[]; + NSLog(@"Launcher agruments: %@", arguments); + [workspace launchApplicationAtURL:applicationURL options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:nil]; + return 0; } From 078ca7edea471c40befd4323a1a7dae3f1b642c9 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Tue, 30 Jul 2019 09:59:45 -0700 Subject: [PATCH 03/20] supporting text effects + fonts on text entities --- interface/src/ui/overlays/QmlOverlay.cpp | 10 +- interface/src/ui/overlays/QmlOverlay.h | 6 +- interface/src/ui/overlays/TextOverlay.cpp | 15 +- .../src/avatars-renderer/Avatar.cpp | 28 +-- .../src/RenderableEntityItem.cpp | 23 +++ .../src/RenderableEntityItem.h | 1 + .../src/RenderableTextEntityItem.cpp | 73 +++++-- .../src/RenderableTextEntityItem.h | 5 + .../entities/src/EntityItemProperties.cpp | 67 ++++++ libraries/entities/src/EntityItemProperties.h | 6 + libraries/entities/src/EntityPropertyFlags.h | 4 + libraries/entities/src/TextEntityItem.cpp | 77 ++++++- libraries/entities/src/TextEntityItem.h | 19 ++ libraries/networking/src/udt/PacketHeaders.h | 1 + libraries/octree/src/OctreePacketData.h | 2 + libraries/render-utils/src/TextRenderer3D.cpp | 55 ++--- libraries/render-utils/src/TextRenderer3D.h | 40 ++-- libraries/render-utils/src/sdf_text3D.slf | 28 +-- libraries/render-utils/src/sdf_text3D.slh | 66 ++++-- libraries/render-utils/src/sdf_text3D.slv | 17 +- libraries/render-utils/src/text/EffectType.h | 15 -- libraries/render-utils/src/text/Font.cpp | 194 +++++++++++------- libraries/render-utils/src/text/Font.h | 55 +++-- .../render-utils/src/text/FontFamilies.h | 31 --- libraries/render-utils/src/text/Glyph.cpp | 1 + libraries/shared/src/FontFamilies.h | 17 ++ libraries/shared/src/TextEffect.cpp | 26 +++ libraries/shared/src/TextEffect.h | 42 ++++ 28 files changed, 622 insertions(+), 302 deletions(-) delete mode 100644 libraries/render-utils/src/text/EffectType.h delete mode 100644 libraries/render-utils/src/text/FontFamilies.h create mode 100644 libraries/shared/src/FontFamilies.h create mode 100644 libraries/shared/src/TextEffect.cpp create mode 100644 libraries/shared/src/TextEffect.h diff --git a/interface/src/ui/overlays/QmlOverlay.cpp b/interface/src/ui/overlays/QmlOverlay.cpp index f301a23d49..2afb29bb91 100644 --- a/interface/src/ui/overlays/QmlOverlay.cpp +++ b/interface/src/ui/overlays/QmlOverlay.cpp @@ -9,18 +9,10 @@ #include "QmlOverlay.h" #include +#include #include -#include -#include #include -#include -#include -#include -#include - -#include "Application.h" -#include "text/FontFamilies.h" QmlOverlay::QmlOverlay(const QUrl& url) { buildQmlElement(url); diff --git a/interface/src/ui/overlays/QmlOverlay.h b/interface/src/ui/overlays/QmlOverlay.h index 32badde28b..0d3c0982c3 100644 --- a/interface/src/ui/overlays/QmlOverlay.h +++ b/interface/src/ui/overlays/QmlOverlay.h @@ -9,10 +9,6 @@ #ifndef hifi_QmlOverlay_h #define hifi_QmlOverlay_h -#include -#include - -#include #include "Overlay2D.h" class QQuickItem; @@ -33,7 +29,7 @@ private: Q_INVOKABLE void buildQmlElement(const QUrl& url); protected: - QQuickItem* _qmlElement{ nullptr }; + QQuickItem* _qmlElement { nullptr }; }; #endif // hifi_QmlOverlay_h diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 2f4353dae8..6760c918d3 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -11,18 +11,9 @@ #include "TextOverlay.h" #include +#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Application.h" -#include "text/FontFamilies.h" +#include "FontFamilies.h" QString const TextOverlay::TYPE = "text"; QUrl const TextOverlay::URL(QString("hifi/overlays/TextOverlay.qml")); @@ -44,7 +35,7 @@ QSizeF TextOverlay::textSize(const QString& text) const { ++lines; } } - QFont font(SANS_FONT_FAMILY); + QFont font(ROBOTO_FONT_FAMILY); font.setPixelSize(18); QFontMetrics fm(font); QSizeF result = QSizeF(fm.width(text), 18 * lines); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 5af98100dc..a7e4a0ae9f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -598,26 +598,6 @@ void Avatar::measureMotionDerivatives(float deltaTime) { } } -enum TextRendererType { - CHAT, - DISPLAYNAME -}; - -static TextRenderer3D* textRenderer(TextRendererType type) { - static TextRenderer3D* chatRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, -1, - false, SHADOW_EFFECT); - static TextRenderer3D* displayNameRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY); - - switch(type) { - case CHAT: - return chatRenderer; - case DISPLAYNAME: - return displayNameRenderer; - } - - return displayNameRenderer; -} - void Avatar::metaBlendshapeOperator(render::ItemID renderItemID, int blendshapeNumber, const QVector& blendshapeOffsets, const QVector& blendedMeshSizes, const render::ItemIDs& subItemIDs) { render::Transaction transaction; @@ -1050,7 +1030,6 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const || (glm::dot(view.getDirection(), getDisplayNamePosition() - view.getPosition()) <= CLIP_DISTANCE)) { return; } - auto renderer = textRenderer(DISPLAYNAME); // optionally render timing stats for this avatar with the display name QString renderedDisplayName = _displayName; @@ -1065,7 +1044,8 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const } // Compute display name extent/position offset - const glm::vec2 extent = renderer->computeExtent(renderedDisplayName); + static TextRenderer3D* displayNameRenderer = TextRenderer3D::getInstance(ROBOTO_FONT_FAMILY); + const glm::vec2 extent = displayNameRenderer->computeExtent(renderedDisplayName); if (!glm::any(glm::isCompNull(extent, EPSILON))) { const QRect nameDynamicRect = QRect(0, 0, (int)extent.x, (int)extent.y); const int text_x = -nameDynamicRect.width() / 2; @@ -1104,11 +1084,11 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const QByteArray nameUTF8 = renderedDisplayName.toLocal8Bit(); // Render text slightly in front to avoid z-fighting - textTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_IN_FRONT * renderer->getFontSize())); + textTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_IN_FRONT * displayNameRenderer->getFontSize())); batch.setModelTransform(textTransform); { PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderText"); - renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor, glm::vec2(-1.0f), true, forward); + displayNameRenderer->draw(batch, text_x, -text_y, glm::vec2(-1.0f), nameUTF8.data(), textColor, true, forward); } } } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 11e369b532..5ebb0e2fd0 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -483,3 +483,26 @@ glm::vec4 EntityRenderer::calculatePulseColor(const glm::vec4& color, const Puls return result; } + +glm::vec3 EntityRenderer::calculatePulseColor(const glm::vec3& color, const PulsePropertyGroup& pulseProperties, quint64 start) { + if (pulseProperties.getPeriod() == 0.0f || (pulseProperties.getColorMode() == PulseMode::NONE && pulseProperties.getAlphaMode() == PulseMode::NONE)) { + return color; + } + + float t = ((float)(usecTimestampNow() - start)) / ((float)USECS_PER_SECOND); + float pulse = 0.5f * (cosf(t * (2.0f * (float)M_PI) / pulseProperties.getPeriod()) + 1.0f) * (pulseProperties.getMax() - pulseProperties.getMin()) + pulseProperties.getMin(); + float outPulse = (1.0f - pulse); + + glm::vec3 result = color; + if (pulseProperties.getColorMode() == PulseMode::IN_PHASE) { + result.r *= pulse; + result.g *= pulse; + result.b *= pulse; + } else if (pulseProperties.getColorMode() == PulseMode::OUT_PHASE) { + result.r *= outPulse; + result.g *= outPulse; + result.b *= outPulse; + } + + return result; +} diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 1db4cfdf53..7f06547cdc 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -61,6 +61,7 @@ public: virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); } static glm::vec4 calculatePulseColor(const glm::vec4& color, const PulsePropertyGroup& pulseProperties, quint64 start); + static glm::vec3 calculatePulseColor(const glm::vec3& color, const PulsePropertyGroup& pulseProperties, quint64 start); virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; virtual Item::Bound getBound() override; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 0ead1de71a..d8099df0fe 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -30,7 +30,7 @@ const float LINE_SCALE_RATIO = 1.2f; TextEntityRenderer::TextEntityRenderer(const EntityItemPointer& entity) : Parent(entity), - _textRenderer(TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f)) { + _textRenderer(TextRenderer3D::getInstance(ROBOTO_FONT_FAMILY)) { auto geometryCache = DependencyManager::get(); if (geometryCache) { _geometryID = geometryCache->allocateID(); @@ -96,7 +96,6 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint if (_text != entity->getText()) { return true; } - if (_lineHeight != entity->getLineHeight()) { return true; } @@ -104,15 +103,12 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint if (_textColor != toGlm(entity->getTextColor())) { return true; } - if (_textAlpha != entity->getTextAlpha()) { return true; } - if (_backgroundColor != toGlm(entity->getBackgroundColor())) { return true; } - if (_backgroundAlpha != entity->getBackgroundAlpha()) { return true; } @@ -128,15 +124,12 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint if (_leftMargin != entity->getLeftMargin()) { return true; } - if (_rightMargin != entity->getRightMargin()) { return true; } - if (_topMargin != entity->getTopMargin()) { return true; } - if (_bottomMargin != entity->getBottomMargin()) { return true; } @@ -145,6 +138,20 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint return true; } + if (_font != entity->getFont()) { + return true; + } + + if (_effect != entity->getTextEffect()) { + return true; + } + if (_effectColor != toGlm(entity->getTextEffectColor())) { + return true; + } + if (_effectThickness != entity->getTextEffectThickness()) { + return true; + } + if (_pulseProperties != entity->getPulseProperties()) { return true; } @@ -179,6 +186,10 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe _topMargin = entity->getTopMargin(); _bottomMargin = entity->getBottomMargin(); _unlit = entity->getUnlit(); + _font = entity->getFont(); + _effect = entity->getTextEffect(); + _effectColor = toGlm(entity->getTextEffectColor()); + _effectThickness = entity->getTextEffectThickness(); updateTextRenderItem(); }); } @@ -282,7 +293,22 @@ ItemKey entities::TextPayload::getKey() const { auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); if (renderable) { auto textRenderable = std::static_pointer_cast(renderable); - return ItemKey::Builder(textRenderable->getKey()).withoutMetaCullGroup().withSubMetaCulled(); + + // Similar to RenderableEntityItem::getKey() + ItemKey::Builder builder = ItemKey::Builder().withTypeShape().withTypeMeta().withTagBits(textRenderable->getTagMask()).withLayer(textRenderable->getHifiRenderLayer()); + builder.withSubMetaCulled(); + + if (textRenderable->isTextTransparent()) { + builder.withTransparent(); + } else if (textRenderable->_canCastShadow) { + builder.withShadowCaster(); + } + + if (!textRenderable->_visible) { + builder.withInvisible(); + } + + return builder; } } return ItemKey::Builder::opaqueShape(); @@ -342,27 +368,40 @@ void entities::TextPayload::render(RenderArgs* args) { } auto textRenderable = std::static_pointer_cast(renderable); - glm::vec4 textColor; Transform modelTransform; - BillboardMode billboardMode; - float lineHeight, leftMargin, rightMargin, topMargin, bottomMargin; - QString text; glm::vec3 dimensions; + BillboardMode billboardMode; + + QString text; + glm::vec4 textColor; + QString font; + TextEffect effect; + glm::vec3 effectColor; + float effectThickness; + float lineHeight, leftMargin, rightMargin, topMargin, bottomMargin; bool forward; textRenderable->withReadLock([&] { modelTransform = textRenderable->_renderTransform; + dimensions = textRenderable->_dimensions; billboardMode = textRenderable->_billboardMode; + + text = textRenderable->_text; + font = textRenderable->_font; + effect = textRenderable->_effect; + effectThickness = textRenderable->_effectThickness; + lineHeight = textRenderable->_lineHeight; leftMargin = textRenderable->_leftMargin; rightMargin = textRenderable->_rightMargin; topMargin = textRenderable->_topMargin; bottomMargin = textRenderable->_bottomMargin; - text = textRenderable->_text; - dimensions = textRenderable->_dimensions; float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f; textColor = glm::vec4(textRenderable->_textColor, fadeRatio * textRenderable->_textAlpha); textColor = EntityRenderer::calculatePulseColor(textColor, textRenderable->_pulseProperties, textRenderable->_created); + + effectColor = EntityRenderer::calculatePulseColor(textRenderable->_effectColor, textRenderable->_pulseProperties, textRenderable->_created); + forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; }); @@ -378,7 +417,9 @@ void entities::TextPayload::render(RenderArgs* args) { batch.setModelTransform(modelTransform); glm::vec2 bounds = glm::vec2(dimensions.x - (leftMargin + rightMargin), dimensions.y - (topMargin + bottomMargin)); - textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, text, textColor, bounds / scale, textRenderable->_unlit, forward); + textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, bounds / scale, scale, + text, font, textColor, effectColor, effectThickness, effect, + textRenderable->_unlit, forward); } namespace render { diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index c62851a876..63cf3e6e9e 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -67,6 +67,11 @@ private: BillboardMode _billboardMode; glm::vec3 _dimensions; + QString _font { "" }; + TextEffect _effect { TextEffect::NO_EFFECT }; + glm::vec3 _effectColor { 0 }; + float _effectThickness { 0.0f }; + int _geometryID { 0 }; std::shared_ptr _textPayload; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index b89788040f..42ce276aca 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -299,6 +299,24 @@ void EntityItemProperties::setAvatarPriorityFromString(const QString& mode) { } } +inline void addTextEffect(QHash& lookup, TextEffect effect) { lookup[TextEffectHelpers::getNameForTextEffect(effect)] = effect; } +const QHash stringToTextEffectLookup = [] { + QHash toReturn; + addTextEffect(toReturn, TextEffect::NO_EFFECT); + addTextEffect(toReturn, TextEffect::OUTLINE_EFFECT); + addTextEffect(toReturn, TextEffect::OUTLINE_WITH_FILL_EFFECT); + addTextEffect(toReturn, TextEffect::SHADOW_EFFECT); + return toReturn; +}(); +QString EntityItemProperties::getTextEffectAsString() const { return TextEffectHelpers::getNameForTextEffect(_textEffect); } +void EntityItemProperties::setTextEffectFromString(const QString& effect) { + auto textEffectItr = stringToTextEffectLookup.find(effect.toLower()); + if (textEffectItr != stringToTextEffectLookup.end()) { + _textEffect = textEffectItr.value(); + _textEffectChanged = true; + } +} + QString getCollisionGroupAsString(uint16_t group) { switch (group) { case USER_COLLISION_GROUP_DYNAMIC: @@ -528,6 +546,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_TOP_MARGIN, topMargin); CHECK_PROPERTY_CHANGE(PROP_BOTTOM_MARGIN, bottomMargin); CHECK_PROPERTY_CHANGE(PROP_UNLIT, unlit); + CHECK_PROPERTY_CHANGE(PROP_FONT, font); + CHECK_PROPERTY_CHANGE(PROP_TEXT_EFFECT, textEffect); + CHECK_PROPERTY_CHANGE(PROP_TEXT_EFFECT_COLOR, textEffectColor); + CHECK_PROPERTY_CHANGE(PROP_TEXT_EFFECT_THICKNESS, textEffectThickness); // Zone changedProperties += _keyLight.getChangedProperties(); @@ -1287,6 +1309,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} bottomMargin=0.0 - The bottom margin, in meters. * @property {boolean} unlit=false - true if the entity should be unaffected by lighting. Otherwise, the text * is lit by the keylight and local lights. + * @property {string} font="" - The text is rendered with this font. Can be one of the following: CourierInconsolata, Roboto, Timeless, or a path to a .sdff file. + * @property {TextEffect} textEffect="none" - The effect that is applied to the text. + * @property {Color} textEffectColor=255,255,255 - The color of the effect. + * @property {number} textEffectThickness=0.2 - The magnitude of the text effect, range 0.00.5. * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. * @property {boolean} faceCamera - true if billboardMode is "yaw", false * if it isn't. Setting this property to false sets the billboardMode to "none". @@ -1727,6 +1754,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TOP_MARGIN, topMargin); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_BOTTOM_MARGIN, bottomMargin); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_UNLIT, unlit); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FONT, font); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_TEXT_EFFECT, textEffect, getTextEffectAsString()); + COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_TEXT_EFFECT_COLOR, textEffectColor, u8vec3Color); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXT_EFFECT_THICKNESS, textEffectThickness); } // Zones only @@ -2103,6 +2134,10 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(topMargin, float, setTopMargin); COPY_PROPERTY_FROM_QSCRIPTVALUE(bottomMargin, float, setBottomMargin); COPY_PROPERTY_FROM_QSCRIPTVALUE(unlit, bool, setUnlit); + COPY_PROPERTY_FROM_QSCRIPTVALUE(font, QString, setFont); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(textEffect, TextEffect); + COPY_PROPERTY_FROM_QSCRIPTVALUE(textEffectColor, u8vec3Color, setTextEffectColor); + COPY_PROPERTY_FROM_QSCRIPTVALUE(textEffectThickness, float, setTextEffectThickness); // Zone _keyLight.copyFromScriptValue(object, _defaultSettings); @@ -2387,6 +2422,10 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(topMargin); COPY_PROPERTY_IF_CHANGED(bottomMargin); COPY_PROPERTY_IF_CHANGED(unlit); + COPY_PROPERTY_IF_CHANGED(font); + COPY_PROPERTY_IF_CHANGED(textEffect); + COPY_PROPERTY_IF_CHANGED(textEffectColor); + COPY_PROPERTY_IF_CHANGED(textEffectThickness); // Zone _keyLight.merge(other._keyLight); @@ -2746,6 +2785,10 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_TOP_MARGIN, TopMargin, topMargin, float); ADD_PROPERTY_TO_MAP(PROP_BOTTOM_MARGIN, BottomMargin, bottomMargin, float); ADD_PROPERTY_TO_MAP(PROP_UNLIT, Unlit, unlit, bool); + ADD_PROPERTY_TO_MAP(PROP_FONT, Font, font, QString); + ADD_PROPERTY_TO_MAP(PROP_TEXT_EFFECT, TextEffect, textEffect, TextEffect); + ADD_PROPERTY_TO_MAP(PROP_TEXT_EFFECT_COLOR, TextEffectColor, textEffectColor, u8vec3Color); + ADD_PROPERTY_TO_MAP_WITH_RANGE(PROP_TEXT_EFFECT_THICKNESS, TextEffectThickness, textEffectThickness, float, 0.0, 0.5); // Zone { // Keylight @@ -3178,6 +3221,10 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_TOP_MARGIN, properties.getTopMargin()); APPEND_ENTITY_PROPERTY(PROP_BOTTOM_MARGIN, properties.getBottomMargin()); APPEND_ENTITY_PROPERTY(PROP_UNLIT, properties.getUnlit()); + APPEND_ENTITY_PROPERTY(PROP_FONT, properties.getFont()); + APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT, (uint32_t)properties.getTextEffect()); + APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_COLOR, properties.getTextEffectColor()); + APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, properties.getTextEffectThickness()); } if (properties.getType() == EntityTypes::Zone) { @@ -3657,6 +3704,10 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TOP_MARGIN, float, setTopMargin); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BOTTOM_MARGIN, float, setBottomMargin); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_UNLIT, bool, setUnlit); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FONT, QString, setFont); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_EFFECT, TextEffect, setTextEffect); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_EFFECT_COLOR, u8vec3Color, setTextEffectColor); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_EFFECT_THICKNESS, float, setTextEffectThickness); } if (properties.getType() == EntityTypes::Zone) { @@ -4050,6 +4101,10 @@ void EntityItemProperties::markAllChanged() { _topMarginChanged = true; _bottomMarginChanged = true; _unlitChanged = true; + _fontChanged = true; + _textEffectChanged = true; + _textEffectColorChanged = true; + _textEffectThicknessChanged = true; // Zone _keyLight.markAllChanged(); @@ -4642,6 +4697,18 @@ QList EntityItemProperties::listChangedProperties() { if (unlitChanged()) { out += "unlit"; } + if (fontChanged()) { + out += "font"; + } + if (textEffectChanged()) { + out += "textEffect"; + } + if (textEffectColorChanged()) { + out += "textEffectColor"; + } + if (textEffectThicknessChanged()) { + out += "textEffectThickness"; + } // Zone getKeyLight().listChangedProperties(out); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 456ee3cdec..63d8183899 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -32,6 +32,7 @@ #include #include #include +#include "FontFamilies.h" #include "EntityItemID.h" #include "EntityItemPropertiesDefaults.h" @@ -64,6 +65,7 @@ #include "PrimitiveMode.h" #include "WebInputMode.h" #include "GizmoType.h" +#include "TextEffect.h" const quint64 UNKNOWN_CREATED_TIME = 0; @@ -315,6 +317,10 @@ public: DEFINE_PROPERTY_REF(PROP_TOP_MARGIN, TopMargin, topMargin, float, TextEntityItem::DEFAULT_MARGIN); DEFINE_PROPERTY_REF(PROP_BOTTOM_MARGIN, BottomMargin, bottomMargin, float, TextEntityItem::DEFAULT_MARGIN); DEFINE_PROPERTY_REF(PROP_UNLIT, Unlit, unlit, bool, false); + DEFINE_PROPERTY_REF(PROP_FONT, Font, font, QString, ROBOTO_FONT_FAMILY); + DEFINE_PROPERTY_REF_ENUM(PROP_TEXT_EFFECT, TextEffect, textEffect, TextEffect, TextEffect::NO_EFFECT); + DEFINE_PROPERTY_REF(PROP_TEXT_EFFECT_COLOR, TextEffectColor, textEffectColor, u8vec3Color, TextEntityItem::DEFAULT_TEXT_COLOR); + DEFINE_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, TextEffectThickness, textEffectThickness, float, TextEntityItem::DEFAULT_TEXT_EFFECT_THICKNESS); // Zone DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 8d3833f364..d5af337a7d 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -244,6 +244,10 @@ enum EntityPropertyList { PROP_TOP_MARGIN = PROP_DERIVED_8, PROP_BOTTOM_MARGIN = PROP_DERIVED_9, PROP_UNLIT = PROP_DERIVED_10, + PROP_FONT = PROP_DERIVED_11, + PROP_TEXT_EFFECT = PROP_DERIVED_12, + PROP_TEXT_EFFECT_COLOR = PROP_DERIVED_13, + PROP_TEXT_EFFECT_THICKNESS = PROP_DERIVED_14, // Zone // Keylight diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 08200084f4..d237071a17 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -29,6 +29,7 @@ const glm::u8vec3 TextEntityItem::DEFAULT_TEXT_COLOR = { 255, 255, 255 }; const float TextEntityItem::DEFAULT_TEXT_ALPHA = 1.0f; const glm::u8vec3 TextEntityItem::DEFAULT_BACKGROUND_COLOR = { 0, 0, 0}; const float TextEntityItem::DEFAULT_MARGIN = 0.0f; +const float TextEntityItem::DEFAULT_TEXT_EFFECT_THICKNESS = 0.2f; EntityItemPointer TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity(new TextEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); @@ -65,6 +66,10 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de COPY_ENTITY_PROPERTY_TO_PROPERTIES(topMargin, getTopMargin); COPY_ENTITY_PROPERTY_TO_PROPERTIES(bottomMargin, getBottomMargin); COPY_ENTITY_PROPERTY_TO_PROPERTIES(unlit, getUnlit); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(font, getFont); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(textEffect, getTextEffect); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(textEffectColor, getTextEffectColor); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(textEffectThickness, getTextEffectThickness); return properties; } @@ -89,6 +94,10 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(topMargin, setTopMargin); SET_ENTITY_PROPERTY_FROM_PROPERTIES(bottomMargin, setBottomMargin); SET_ENTITY_PROPERTY_FROM_PROPERTIES(unlit, setUnlit); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(font, setFont); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(textEffect, setTextEffect); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(textEffectColor, setTextEffectColor); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(textEffectThickness, setTextEffectThickness); if (somethingChanged) { bool wantDebug = false; @@ -132,6 +141,10 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_TOP_MARGIN, float, setTopMargin); READ_ENTITY_PROPERTY(PROP_BOTTOM_MARGIN, float, setBottomMargin); READ_ENTITY_PROPERTY(PROP_UNLIT, bool, setUnlit); + READ_ENTITY_PROPERTY(PROP_FONT, QString, setFont); + READ_ENTITY_PROPERTY(PROP_TEXT_EFFECT, TextEffect, setTextEffect); + READ_ENTITY_PROPERTY(PROP_TEXT_EFFECT_COLOR, glm::u8vec3, setTextEffectColor); + READ_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, float, setTextEffectThickness); return bytesRead; } @@ -153,6 +166,10 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p requestedProperties += PROP_TOP_MARGIN; requestedProperties += PROP_BOTTOM_MARGIN; requestedProperties += PROP_UNLIT; + requestedProperties += PROP_FONT; + requestedProperties += PROP_TEXT_EFFECT; + requestedProperties += PROP_TEXT_EFFECT_COLOR; + requestedProperties += PROP_TEXT_EFFECT_THICKNESS; return requestedProperties; } @@ -184,6 +201,10 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_TOP_MARGIN, getTopMargin()); APPEND_ENTITY_PROPERTY(PROP_BOTTOM_MARGIN, getBottomMargin()); APPEND_ENTITY_PROPERTY(PROP_UNLIT, getUnlit()); + APPEND_ENTITY_PROPERTY(PROP_FONT, getFont()); + APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT, (uint32_t)getTextEffect()); + APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_COLOR, getTextEffectColor()); + APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, getTextEffectThickness()); } glm::vec3 TextEntityItem::getRaycastDimensions() const { @@ -255,12 +276,10 @@ void TextEntityItem::setText(const QString& value) { }); } -QString TextEntityItem::getText() const { - QString result; - withReadLock([&] { - result = _text; +QString TextEntityItem::getText() const { + return resultWithReadLock([&] { + return _text; }); - return result; } void TextEntityItem::setLineHeight(float value) { @@ -399,6 +418,54 @@ bool TextEntityItem::getUnlit() const { }); } +void TextEntityItem::setFont(const QString& value) { + withWriteLock([&] { + _font = value; + }); +} + +QString TextEntityItem::getFont() const { + return resultWithReadLock([&] { + return _font; + }); +} + +void TextEntityItem::setTextEffect(TextEffect value) { + withWriteLock([&] { + _effect = value; + }); +} + +TextEffect TextEntityItem::getTextEffect() const { + return resultWithReadLock([&] { + return _effect; + }); +} + +void TextEntityItem::setTextEffectColor(const glm::u8vec3& value) { + withWriteLock([&] { + _effectColor = value; + }); +} + +glm::u8vec3 TextEntityItem::getTextEffectColor() const { + return resultWithReadLock([&] { + return _effectColor; + }); +} + +void TextEntityItem::setTextEffectThickness(float value) { + withWriteLock([&] { + _effectThickness = value; + }); +} + +float TextEntityItem::getTextEffectThickness() const { + return resultWithReadLock([&] { + return _effectThickness; + }); +} + PulsePropertyGroup TextEntityItem::getPulseProperties() const { return resultWithReadLock([&] { return _pulseProperties; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index a962482cde..5e3f6d7c02 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -15,6 +15,7 @@ #include "EntityItem.h" #include "PulsePropertyGroup.h" +#include "TextEffect.h" class TextEntityItem : public EntityItem { public: @@ -100,6 +101,19 @@ public: bool getUnlit() const; void setUnlit(bool value); + void setFont(const QString& value); + QString getFont() const; + + TextEffect getTextEffect() const; + void setTextEffect(TextEffect value); + + glm::u8vec3 getTextEffectColor() const; + void setTextEffectColor(const glm::u8vec3& value); + + static const float DEFAULT_TEXT_EFFECT_THICKNESS; + float getTextEffectThickness() const; + void setTextEffectThickness(float value); + PulsePropertyGroup getPulseProperties() const; private: @@ -117,6 +131,11 @@ private: float _topMargin; float _bottomMargin; bool _unlit; + + QString _font; + TextEffect _effect; + glm::u8vec3 _effectColor; + float _effectThickness; }; #endif // hifi_TextEntityItem_h diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 2d184fe592..dc1c79e0eb 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -273,6 +273,7 @@ enum class EntityVersion : PacketVersion { PrivateUserData, TextUnlit, ShadowBiasAndDistance, + TextEntityFonts, // Add new versions above here NUM_PACKET_TYPE, diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index a2fe886810..46e5de9bda 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -40,6 +40,7 @@ #include "WebInputMode.h" #include "PulseMode.h" #include "GizmoType.h" +#include "TextEffect.h" #include "OctreeConstants.h" #include "OctreeElement.h" @@ -273,6 +274,7 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, WebInputMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, PulseMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, GizmoType& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } + static int unpackDataFromBytes(const unsigned char* dataBytes, TextEffect& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result); static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result); static int unpackDataFromBytes(const unsigned char* dataBytes, glm::u8vec3& result); diff --git a/libraries/render-utils/src/TextRenderer3D.cpp b/libraries/render-utils/src/TextRenderer3D.cpp index 8c514df91d..264ff409a6 100644 --- a/libraries/render-utils/src/TextRenderer3D.cpp +++ b/libraries/render-utils/src/TextRenderer3D.cpp @@ -10,45 +10,19 @@ // #include "TextRenderer3D.h" -#include -#include - -#include -#include -#include -#include - -#include #include "text/Font.h" -#include "GLMHelpers.h" -#include "MatrixStack.h" -#include "RenderUtilsLogging.h" - -#include "GeometryCache.h" - -const float TextRenderer3D::DEFAULT_POINT_SIZE = 12; - -TextRenderer3D* TextRenderer3D::getInstance(const char* family, float pointSize, - bool bold, bool italic, EffectType effect, int effectThickness) { - return new TextRenderer3D(family, pointSize, false, italic, effect, effectThickness); +TextRenderer3D* TextRenderer3D::getInstance(const char* family) { + return new TextRenderer3D(family); } -TextRenderer3D::TextRenderer3D(const char* family, float pointSize, int weight, bool italic, - EffectType effect, int effectThickness) : - _effectType(effect), - _effectThickness(effectThickness), +TextRenderer3D::TextRenderer3D(const char* family) : + _family(family), _font(Font::load(family)) { if (!_font) { qWarning() << "Unable to load font with family " << family; - _font = Font::load("Courier"); - } - if (1 != _effectThickness) { - qWarning() << "Effect thickness not currently supported"; - } - if (NO_EFFECT != _effectType && OUTLINE_EFFECT != _effectType) { - qWarning() << "Effect type not currently supported"; + _font = Font::load(ROBOTO_FONT_FAMILY); } } @@ -66,12 +40,21 @@ float TextRenderer3D::getFontSize() const { return 0.0f; } -void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color, - const glm::vec2& bounds, bool unlit, bool forward) { - // The font does all the OpenGL work +void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, + const QString& str, const glm::vec4& color, bool unlit, bool forward) { if (_font) { - _color = color; - _font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, unlit, forward); + _font->drawString(batch, _drawInfo, str, color, glm::vec3(0.0f), 0, TextEffect::NO_EFFECT, { x, y }, bounds, 1.0f, unlit, forward); } } +void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, float scale, + const QString& str, const QString& font, const glm::vec4& color, const glm::vec3& effectColor, + float effectThickness, TextEffect effect, bool unlit, bool forward) { + if (font != _family) { + _family = font; + _font = Font::load(_family); + } + if (_font) { + _font->drawString(batch, _drawInfo, str, color, effectColor, effectThickness, effect, { x, y }, bounds, scale, unlit, forward); + } +} \ No newline at end of file diff --git a/libraries/render-utils/src/TextRenderer3D.h b/libraries/render-utils/src/TextRenderer3D.h index 8118aa883c..3a88ed555c 100644 --- a/libraries/render-utils/src/TextRenderer3D.h +++ b/libraries/render-utils/src/TextRenderer3D.h @@ -14,48 +14,32 @@ #include #include -#include -#include - -namespace gpu { -class Batch; -} -class Font; #include "text/Font.h" -#include "text/EffectType.h" -#include "text/FontFamilies.h" +#include "TextEffect.h" +#include "FontFamilies.h" -// TextRenderer3D is actually a fairly thin wrapper around a Font class -// defined in the cpp file. class TextRenderer3D { public: - static const float DEFAULT_POINT_SIZE; - - static TextRenderer3D* getInstance(const char* family, float pointSize = DEFAULT_POINT_SIZE, - bool bold = false, bool italic = false, EffectType effect = NO_EFFECT, int effectThickness = 1); + static TextRenderer3D* getInstance(const char* family); glm::vec2 computeExtent(const QString& str) const; float getFontSize() const; // Pixel size - void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color, - const glm::vec2& bounds, bool unlit, bool forward); + void draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, + const QString& str, const glm::vec4& color, bool unlit, bool forward); + void draw(gpu::Batch& batch, float x, float y, const glm::vec2& bounds, float scale, + const QString& str, const QString& font, const glm::vec4& color, const glm::vec3& effectColor, + float effectThickness, TextEffect effect, bool unlit, bool forward); private: - TextRenderer3D(const char* family, float pointSize, int weight = -1, bool italic = false, - EffectType effect = NO_EFFECT, int effectThickness = 1); + TextRenderer3D(const char* family); - // the type of effect to apply - const EffectType _effectType; + QString _family; - // the thickness of the effect - const int _effectThickness; - - // text color - glm::vec4 _color; - Font::DrawInfo _drawInfo; std::shared_ptr _font; + Font::DrawInfo _drawInfo; + }; - #endif // hifi_TextRenderer3D_h diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index ac064e5c8f..c5bed1ecab 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -36,29 +36,29 @@ layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES; <@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw +layout(location=RENDER_UTILS_ATTR_FADE1) flat in vec4 _glyphBounds; // we're reusing the fade texcoord locations here void main() { - float alpha = evalSDFSuperSampled(_texCoord0); + vec4 color = evalSDFSuperSampled(_texCoord0, _glyphBounds); <@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> - alpha *= _color.a; - if (alpha <= 0.0) { + color.a *= params.color.a; + if (color.a <= 0.0) { discard; } <@endif@> <@if HIFI_USE_UNLIT@> <@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> - _fragColor0 = vec4(_color.rgb * isUnlitEnabled(), alpha); + _fragColor0 = vec4(color.rgb * isUnlitEnabled(), color.a); <@else@> packDeferredFragmentUnlit( normalize(_normalWS), - alpha, - _color.rgb); + color.a, + color.rgb); <@endif@> <@else@> <@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> @@ -72,12 +72,12 @@ void main() { DEFAULT_OCCLUSION, fragPosition, normalize(_normalWS), - _color.rgb, + color.rgb, DEFAULT_FRESNEL, DEFAULT_METALLIC, DEFAULT_EMISSIVE, - DEFAULT_ROUGHNESS, alpha), - alpha); + DEFAULT_ROUGHNESS, color.a), + color.a); <@else@> _fragColor0 = vec4(evalSkyboxGlobalColor( cam._viewInverse, @@ -85,17 +85,17 @@ void main() { DEFAULT_OCCLUSION, fragPosition, normalize(_normalWS), - _color.rgb, + color.rgb, DEFAULT_FRESNEL, DEFAULT_METALLIC, DEFAULT_ROUGHNESS), - alpha); + color.a); <@endif@> <@else@> packDeferredFragment( normalize(_normalWS), - alpha, - _color.rgb, + color.a, + color.rgb, DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, diff --git a/libraries/render-utils/src/sdf_text3D.slh b/libraries/render-utils/src/sdf_text3D.slh index 3297596efd..76ace99182 100644 --- a/libraries/render-utils/src/sdf_text3D.slh +++ b/libraries/render-utils/src/sdf_text3D.slh @@ -14,11 +14,16 @@ <@if not SDF_TEXT3D_SLH@> <@def SDF_TEXT3D_SLH@> -LAYOUT(binding=0) uniform sampler2D Font; +LAYOUT(binding=0) uniform sampler2D fontTexture; struct TextParams { vec4 color; - vec4 outline; + + vec3 effectColor; + float effectThickness; + + int effect; + vec3 spare; }; LAYOUT(binding=0) uniform textParamsBuffer { @@ -29,32 +34,57 @@ LAYOUT(binding=0) uniform textParamsBuffer { #define TAA_TEXTURE_LOD_BIAS -3.0 -const float interiorCutoff = 0.8; -const float outlineExpansion = 0.2; +const float interiorCutoff = 0.5; const float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS); -float evalSDF(vec2 texCoord) { - // retrieve signed distance - float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g; - sdf = mix(sdf, mix(sdf + outlineExpansion, 1.0 - sdf, float(sdf > interiorCutoff)), float(params.outline.x > 0.0)); +vec4 evalSDF(vec2 texCoord, vec4 glyphBounds) { + vec3 color = params.color.rgb; + float sdf = textureLod(fontTexture, texCoord, TAA_TEXTURE_LOD_BIAS).g; - // Rely on TAA for anti-aliasing - return step(0.5, sdf); + // Outline + if (params.effect == 1 || params.effect == 2) { + float outline = float(sdf < interiorCutoff); + color = mix(color, params.effectColor, outline); + + // with or without fill + sdf = mix(sdf, 0.0, float(params.effect == 1) * (1.0 - outline)); + + const float EPSILON = 0.00001; + sdf += mix(0.0, params.effectThickness - EPSILON, outline); + } else if (params.effect == 3) { // Shadow + // don't sample from outside of our glyph bounds + sdf *= mix(1.0, 0.0, float(clamp(texCoord, glyphBounds.xy, glyphBounds.xy + glyphBounds.zw) != texCoord)); + + if (sdf < interiorCutoff) { + color = params.effectColor; + const float DOUBLE_MAX_OFFSET_PIXELS = 20.0; // must match value in Font.cpp + // FIXME: TAA_TEXTURE_LOD_BIAS doesn't have any effect because we're only generating one mip, so here we need to use 0, but it should + // really match the LOD that we use in the textureLod call below + vec2 textureOffset = vec2(params.effectThickness * DOUBLE_MAX_OFFSET_PIXELS) / vec2(textureSize(fontTexture, 0/*int(TAA_TEXTURE_LOD_BIAS)*/)); + vec2 shadowTexCoords = texCoord - textureOffset; + sdf = textureLod(fontTexture, shadowTexCoords, TAA_TEXTURE_LOD_BIAS).g; + + // don't sample from outside of our glyph bounds + sdf *= mix(1.0, 0.0, float(clamp(shadowTexCoords, glyphBounds.xy, glyphBounds.xy + glyphBounds.zw) != shadowTexCoords)); + } + } + + return vec4(color, sdf); } -float evalSDFSuperSampled(vec2 texCoord) { +vec4 evalSDFSuperSampled(vec2 texCoord, vec4 glyphBounds) { vec2 dxTexCoord = dFdx(texCoord) * 0.5 * taaBias; vec2 dyTexCoord = dFdy(texCoord) * 0.5 * taaBias; // Perform 4x supersampling for anisotropic filtering - float a; - a = evalSDF(texCoord); - a += evalSDF(texCoord + dxTexCoord); - a += evalSDF(texCoord + dyTexCoord); - a += evalSDF(texCoord + dxTexCoord + dyTexCoord); - a *= 0.25; + vec4 color; + color = evalSDF(texCoord, glyphBounds); + color += evalSDF(texCoord + dxTexCoord, glyphBounds); + color += evalSDF(texCoord + dyTexCoord, glyphBounds); + color += evalSDF(texCoord + dxTexCoord + dyTexCoord, glyphBounds); + color *= 0.25; - return a; + return vec4(color.rgb, step(interiorCutoff, color.a)); } <@endfunc@> diff --git a/libraries/render-utils/src/sdf_text3D.slv b/libraries/render-utils/src/sdf_text3D.slv index 731cbc2cad..a6cb43f038 100644 --- a/libraries/render-utils/src/sdf_text3D.slv +++ b/libraries/render-utils/src/sdf_text3D.slv @@ -23,19 +23,28 @@ layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; <@endif@> layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS; -layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; +layout(location=RENDER_UTILS_ATTR_FADE1) flat out vec4 _glyphBounds; // we're reusing the fade texcoord locations here void main() { _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); - _color = color_sRGBAToLinear(params.color); + _glyphBounds = inTexCoord1; + + vec4 position = inPosition; + // if we're in shadow mode, we need to move each subsequent quad slightly forward so it doesn't z-fight + // with the shadows of the letters before it + if (params.effect == 3) { // Shadow + const int VERTICES_PER_QUAD = 4; // must match value in Font.cpp + const float EPSILON = 0.001; + position.z += floor(gl_VertexID / VERTICES_PER_QUAD) * EPSILON; + } TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> + <$transformModelToEyeAndClipPos(cam, obj, position, _positionES, gl_Position)$> <@else@> - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToClipPos(cam, obj, position, gl_Position)$> <@endif@> const vec3 normal = vec3(0, 0, 1); diff --git a/libraries/render-utils/src/text/EffectType.h b/libraries/render-utils/src/text/EffectType.h deleted file mode 100644 index 63ec820036..0000000000 --- a/libraries/render-utils/src/text/EffectType.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/07/16 -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#pragma once -#ifndef hifi_EffectType_h -#define hifi_EffectType_h - -enum EffectType { NO_EFFECT, SHADOW_EFFECT, OUTLINE_EFFECT }; - -#endif diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index eee6a7daea..f9ca9d4cae 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -2,6 +2,7 @@ #include #include +#include #include @@ -13,6 +14,8 @@ #include "FontFamilies.h" #include "../StencilMaskPass.h" +#include "NetworkAccessManager.h" + static std::mutex fontMutex; std::map, gpu::PipelinePointer> Font::_pipelines; @@ -21,67 +24,90 @@ gpu::Stream::FormatPointer Font::_format; struct TextureVertex { glm::vec2 pos; glm::vec2 tex; + glm::vec4 bounds; TextureVertex() {} - TextureVertex(const glm::vec2& pos, const glm::vec2& tex) : pos(pos), tex(tex) {} + TextureVertex(const glm::vec2& pos, const glm::vec2& tex, const glm::vec4& bounds) : pos(pos), tex(tex), bounds(bounds) {} }; -static const int NUMBER_OF_INDICES_PER_QUAD = 6; // 1 quad = 2 triangles -static const int VERTICES_PER_QUAD = 4; // 1 quad = 4 vertices +static const int NUMBER_OF_INDICES_PER_QUAD = 6; // 1 quad = 2 triangles +static const int VERTICES_PER_QUAD = 4; // 1 quad = 4 vertices (must match value in sdf_text3D.slv) +const float DOUBLE_MAX_OFFSET_PIXELS = 20.0f; // must match value in sdf_text3D.slh struct QuadBuilder { TextureVertex vertices[VERTICES_PER_QUAD]; - QuadBuilder(const glm::vec2& min, const glm::vec2& size, - const glm::vec2& texMin, const glm::vec2& texSize) { + QuadBuilder(const Glyph& glyph, const glm::vec2& offset, float scale, bool enlargeForShadows) { + glm::vec2 min = offset + glm::vec2(glyph.offset.x, glyph.offset.y - glyph.size.y); + glm::vec2 size = glyph.size; + glm::vec2 texMin = glyph.texOffset; + glm::vec2 texSize = glyph.texSize; + + // We need the pre-adjustment bounds for clamping + glm::vec4 bounds = glm::vec4(texMin, texSize); + if (enlargeForShadows) { + glm::vec2 imageSize = glyph.size / glyph.texSize; + glm::vec2 sizeDelta = 0.5f * DOUBLE_MAX_OFFSET_PIXELS * scale * imageSize; + glm::vec2 oldSize = size; + size += sizeDelta; + min.y -= sizeDelta.y; + + texSize = texSize * (size / oldSize); + } + // min = bottomLeft vertices[0] = TextureVertex(min, - texMin + glm::vec2(0.0f, texSize.y)); + texMin + glm::vec2(0.0f, texSize.y), bounds); vertices[1] = TextureVertex(min + glm::vec2(size.x, 0.0f), - texMin + texSize); + texMin + texSize, bounds); vertices[2] = TextureVertex(min + glm::vec2(0.0f, size.y), - texMin); + texMin, bounds); vertices[3] = TextureVertex(min + size, - texMin + glm::vec2(texSize.x, 0.0f)); + texMin + glm::vec2(texSize.x, 0.0f), bounds); } - QuadBuilder(const Glyph& glyph, const glm::vec2& offset) : - QuadBuilder(offset + glm::vec2(glyph.offset.x, glyph.offset.y - glyph.size.y), glyph.size, - glyph.texOffset, glyph.texSize) {} }; - - -static QHash LOADED_FONTS; - Font::Pointer Font::load(QIODevice& fontFile) { Pointer font = std::make_shared(); font->read(fontFile); return font; } +static QHash LOADED_FONTS; + Font::Pointer Font::load(const QString& family) { std::lock_guard lock(fontMutex); if (!LOADED_FONTS.contains(family)) { - - static const QString SDFF_COURIER_PRIME_FILENAME{ ":/CourierPrime.sdff" }; - static const QString SDFF_INCONSOLATA_MEDIUM_FILENAME{ ":/InconsolataMedium.sdff" }; - static const QString SDFF_ROBOTO_FILENAME{ ":/Roboto.sdff" }; - static const QString SDFF_TIMELESS_FILENAME{ ":/Timeless.sdff" }; - QString loadFilename; - if (family == MONO_FONT_FAMILY) { - loadFilename = SDFF_COURIER_PRIME_FILENAME; + if (family == ROBOTO_FONT_FAMILY) { + loadFilename = ":/Roboto.sdff"; } else if (family == INCONSOLATA_FONT_FAMILY) { - loadFilename = SDFF_INCONSOLATA_MEDIUM_FILENAME; - } else if (family == SANS_FONT_FAMILY) { - loadFilename = SDFF_ROBOTO_FILENAME; + loadFilename = ":/InconsolataMedium.sdff"; + } else if (family == COURIER_FONT_FAMILY) { + loadFilename = ":/CourierPrime.sdff"; + } else if (family == TIMELESS_FONT_FAMILY) { + loadFilename = ":/Timeless.sdff"; + } else if (family.startsWith("http")) { + auto loadingFont = std::make_shared(); + loadingFont->setLoaded(false); + LOADED_FONTS[family] = loadingFont; + + auto& networkAccessManager = NetworkAccessManager::getInstance(); + + QNetworkRequest networkRequest; + networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + networkRequest.setUrl(family); + + auto networkReply = networkAccessManager.get(networkRequest); + connect(networkReply, &QNetworkReply::finished, loadingFont.get(), &Font::handleFontNetworkReply); + } else if (!LOADED_FONTS.contains(ROBOTO_FONT_FAMILY)) { + // Unrecognized font and we haven't loaded Roboto yet + loadFilename = ":/Roboto.sdff"; } else { - if (!LOADED_FONTS.contains(SERIF_FONT_FAMILY)) { - loadFilename = SDFF_TIMELESS_FILENAME; - } else { - LOADED_FONTS[family] = LOADED_FONTS[SERIF_FONT_FAMILY]; - } + // Unrecognized font but we've already loaded Roboto + LOADED_FONTS[family] = LOADED_FONTS[ROBOTO_FONT_FAMILY]; } if (!loadFilename.isEmpty()) { @@ -96,14 +122,24 @@ Font::Pointer Font::load(const QString& family) { return LOADED_FONTS[family]; } -Font::Font() { - static bool fontResourceInitComplete = false; - if (!fontResourceInitComplete) { - Q_INIT_RESOURCE(fonts); - fontResourceInitComplete = true; +void Font::handleFontNetworkReply() { + auto requestReply = qobject_cast(sender()); + + if (requestReply->error() == QNetworkReply::NoError) { + setLoaded(true); + read(*requestReply); + } else { + qDebug() << "Error downloading " << requestReply->url() << " - " << requestReply->errorString(); } } +Font::Font() { + static std::once_flag once; + std::call_once(once, []{ + Q_INIT_RESOURCE(fonts); + }); +} + // NERD RAGE: why doesn't QHash have a 'const T & operator[] const' member const Glyph& Font::getGlyph(const QChar& c) const { if (!_glyphs.contains(c)) { @@ -139,7 +175,7 @@ glm::vec2 Font::computeTokenExtent(const QString& token) const { glm::vec2 Font::computeExtent(const QString& str) const { glm::vec2 extent = glm::vec2(0.0f, 0.0f); - QStringList lines{ splitLines(str) }; + QStringList lines = splitLines(str); if (!lines.empty()) { for(const auto& line : lines) { glm::vec2 tokenExtent = computeTokenExtent(line); @@ -154,7 +190,9 @@ void Font::read(QIODevice& in) { uint8_t header[4]; readStream(in, header); if (memcmp(header, "SDFF", 4)) { - qFatal("Bad SDFF file"); + qDebug() << "Bad SDFF file"; + _loaded = false; + return; } uint16_t version; @@ -191,7 +229,9 @@ void Font::read(QIODevice& in) { // read image data QImage image; if (!image.loadFromData(in.readAll(), "PNG")) { - qFatal("Failed to read SDFF image"); + qDebug() << "Failed to read SDFF image"; + _loaded = false; + return; } _glyphs.clear(); @@ -212,6 +252,9 @@ void Font::read(QIODevice& in) { formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::BGRA); } + // FIXME: We're forcing this to use only one mip, and then manually doing anisotropic filtering in the shader, + // and also calling textureLod. Shouldn't this just use anisotropic filtering and auto-generate mips? + // We should also use smoothstep for anti-aliasing, as explained here: https://github.com/libgdx/libgdx/wiki/Distance-field-fonts _texture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR)); _texture->setStoredMipFormat(formatMip); @@ -244,20 +287,21 @@ void Font::setupGPU() { } // Sanity checks - static const int OFFSET = offsetof(TextureVertex, tex); - assert(OFFSET == sizeof(glm::vec2)); - assert(sizeof(glm::vec2) == 2 * sizeof(float)); - assert(sizeof(TextureVertex) == 2 * sizeof(glm::vec2)); + static const int TEX_COORD_OFFSET = offsetof(TextureVertex, tex); + static const int TEX_BOUNDS_OFFSET = offsetof(TextureVertex, bounds); + assert(TEX_COORD_OFFSET == sizeof(glm::vec2)); + assert(sizeof(TextureVertex) == 2 * sizeof(glm::vec2) + sizeof(glm::vec4)); assert(sizeof(QuadBuilder) == 4 * sizeof(TextureVertex)); // Setup rendering structures _format = std::make_shared(); _format->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); - _format->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), OFFSET); + _format->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), TEX_COORD_OFFSET); + _format->setAttribute(gpu::Stream::TEXCOORD1, 0, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW), TEX_BOUNDS_OFFSET); } } -void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds) { +void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds, float scale, bool enlargeForShadows) { drawInfo.verticesBuffer = std::make_shared(); drawInfo.indicesBuffer = std::make_shared(); drawInfo.indexCount = 0; @@ -267,6 +311,8 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm drawInfo.bounds = bounds; drawInfo.origin = origin; + float enlargedBoundsX = bounds.x - 0.5f * DOUBLE_MAX_OFFSET_PIXELS * float(enlargeForShadows); + // Top left of text glm::vec2 advance = origin; foreach(const QString& token, tokenizeForWrapping(str)) { @@ -274,7 +320,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm bool forceNewLine = false; // Handle wrapping - if (!isNewLine && (bounds.x != -1) && (advance.x + computeExtent(token).x > origin.x + bounds.x)) { + if (!isNewLine && (bounds.x != -1) && (advance.x + computeExtent(token).x > origin.x + enlargedBoundsX)) { // We are out of the x bound, force new line forceNewLine = true; } @@ -285,7 +331,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm if (isNewLine) { // No need to draw anything, go directly to next token continue; - } else if (computeExtent(token).x > bounds.x) { + } else if (computeExtent(token).x > enlargedBoundsX) { // token will never fit, stop drawing break; } @@ -301,10 +347,10 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm auto glyph = _glyphs[c]; quint16 verticesOffset = numVertices; - QuadBuilder qd(glyph, advance - glm::vec2(0.0f, _ascent)); + QuadBuilder qd(glyph, advance - glm::vec2(0.0f, _ascent), scale, enlargeForShadows); drawInfo.verticesBuffer->append(qd); - numVertices += 4; - + numVertices += VERTICES_PER_QUAD; + // Sam's recommended triangle slices // Triangle tri1 = { v0, v1, v3 }; // Triangle tri2 = { v1, v2, v3 }; @@ -331,7 +377,6 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm indices[5] = verticesOffset + 3; drawInfo.indicesBuffer->append(sizeof(indices), (const gpu::Byte*)indices); drawInfo.indexCount += NUMBER_OF_INDICES_PER_QUAD; - // Advance by glyph size advance.x += glyph.d; @@ -344,38 +389,49 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm } void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString& str, const glm::vec4& color, - EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool unlit, bool forward) { - if (str == "") { + const glm::vec3& effectColor, float effectThickness, TextEffect effect, + const glm::vec2& origin, const glm::vec2& bounds, float scale, bool unlit, bool forward) { + if (!_loaded || str == "") { return; } - if (str != drawInfo.string || bounds != drawInfo.bounds || origin != drawInfo.origin) { - buildVertices(drawInfo, str, origin, bounds); + int textEffect = (int)effect; + const int SHADOW_EFFECT = (int)TextEffect::SHADOW_EFFECT; + + // If we're switching to or from shadow effect mode, we need to rebuild the vertices + if (str != drawInfo.string || bounds != drawInfo.bounds || origin != drawInfo.origin || + (drawInfo.params.effect != textEffect && (textEffect == SHADOW_EFFECT || drawInfo.params.effect == SHADOW_EFFECT)) || + (textEffect == SHADOW_EFFECT && scale != _scale)) { + _scale = scale; + buildVertices(drawInfo, str, origin, bounds, scale, textEffect == SHADOW_EFFECT); } setupGPU(); - struct GpuDrawParams { - glm::vec4 color; - glm::vec4 outline; - }; - - if (!drawInfo.paramsBuffer || drawInfo.params.color != color || drawInfo.params.effect != effectType) { + if (!drawInfo.paramsBuffer || drawInfo.params.color != color || drawInfo.params.effectColor != effectColor || + drawInfo.params.effectThickness != effectThickness || drawInfo.params.effect != textEffect) { drawInfo.params.color = color; - drawInfo.params.effect = effectType; - GpuDrawParams gpuDrawParams; + drawInfo.params.effectColor = effectColor; + drawInfo.params.effectThickness = effectThickness; + drawInfo.params.effect = textEffect; + + // need the gamma corrected color here + DrawParams gpuDrawParams; gpuDrawParams.color = ColorUtils::sRGBToLinearVec4(drawInfo.params.color); - gpuDrawParams.outline.x = (drawInfo.params.effect == OUTLINE_EFFECT) ? 1 : 0; - drawInfo.paramsBuffer = std::make_shared(sizeof(GpuDrawParams), nullptr); - drawInfo.paramsBuffer->setSubData(0, sizeof(GpuDrawParams), (const gpu::Byte*)&gpuDrawParams); + gpuDrawParams.effectColor = ColorUtils::sRGBToLinearVec3(drawInfo.params.effectColor); + gpuDrawParams.effectThickness = drawInfo.params.effectThickness; + gpuDrawParams.effect = drawInfo.params.effect; + if (!drawInfo.paramsBuffer) { + drawInfo.paramsBuffer = std::make_shared(sizeof(DrawParams), nullptr); + } + drawInfo.paramsBuffer->setSubData(0, sizeof(DrawParams), (const gpu::Byte*)&gpuDrawParams); } - // need the gamma corrected color here batch.setPipeline(_pipelines[std::make_tuple(color.a < 1.0f, unlit, forward)]); batch.setInputFormat(_format); batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride); batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture); - batch.setUniformBuffer(0, drawInfo.paramsBuffer, 0, sizeof(GpuDrawParams)); + batch.setUniformBuffer(0, drawInfo.paramsBuffer, 0, sizeof(DrawParams)); batch.setIndexBuffer(gpu::UINT16, drawInfo.indicesBuffer, 0); batch.drawIndexed(gpu::TRIANGLES, drawInfo.indexCount, 0); } diff --git a/libraries/render-utils/src/text/Font.h b/libraries/render-utils/src/text/Font.h index be1e890e3d..c75f0f746f 100644 --- a/libraries/render-utils/src/text/Font.h +++ b/libraries/render-utils/src/text/Font.h @@ -10,12 +10,16 @@ #ifndef hifi_Font_h #define hifi_Font_h +#include + #include "Glyph.h" -#include "EffectType.h" +#include "TextEffect.h" #include #include -class Font { +class Font : public QObject { + Q_OBJECT + public: using Pointer = std::shared_ptr; @@ -24,14 +28,23 @@ public: void read(QIODevice& path); struct DrawParams { - vec4 color{ -1 }; - EffectType effect; + vec4 color { 0 }; + + vec3 effectColor { 0 }; + float effectThickness { 0 }; + + int effect { 0 }; + +#if defined(__clang__) + __attribute__((unused)) +#endif + vec3 _spare; }; struct DrawInfo { - gpu::BufferPointer verticesBuffer; - gpu::BufferPointer indicesBuffer; - gpu::BufferPointer paramsBuffer; + gpu::BufferPointer verticesBuffer { nullptr }; + gpu::BufferPointer indicesBuffer { nullptr }; + gpu::BufferPointer paramsBuffer { nullptr }; uint32_t indexCount; QString string; @@ -44,12 +57,18 @@ public: float getFontSize() const { return _fontSize; } // Render string to batch - void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str, - const glm::vec4& color, EffectType effectType, - const glm::vec2& origin, const glm::vec2& bound, bool unlit, bool forward); + void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str, const glm::vec4& color, + const glm::vec3& effectColor, float effectThickness, TextEffect effect, + const glm::vec2& origin, const glm::vec2& bound, float scale, bool unlit, bool forward); static Pointer load(const QString& family); + bool isLoaded() const { return _loaded; } + void setLoaded(bool loaded) { _loaded = loaded; } + +public slots: + void handleFontNetworkReply(); + private: static Pointer load(QIODevice& fontFile); QStringList tokenizeForWrapping(const QString& str) const; @@ -57,7 +76,7 @@ private: glm::vec2 computeTokenExtent(const QString& str) const; const Glyph& getGlyph(const QChar& c) const; - void buildVertices(DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds); + void buildVertices(DrawInfo& drawInfo, const QString& str, const glm::vec2& origin, const glm::vec2& bounds, float scale, bool enlargeForShadows); void setupGPU(); @@ -70,11 +89,15 @@ private: // Font characteristics QString _family; - float _fontSize = 0.0f; - float _leading = 0.0f; - float _ascent = 0.0f; - float _descent = 0.0f; - float _spaceWidth = 0.0f; + float _fontSize { 0.0f }; + float _leading { 0.0f }; + float _ascent { 0.0f }; + float _descent { 0.0f }; + float _spaceWidth { 0.0f }; + + float _scale { 0.0f }; + + bool _loaded { true }; gpu::TexturePointer _texture; gpu::BufferStreamPointer _stream; diff --git a/libraries/render-utils/src/text/FontFamilies.h b/libraries/render-utils/src/text/FontFamilies.h deleted file mode 100644 index 3c4186f5c4..0000000000 --- a/libraries/render-utils/src/text/FontFamilies.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/07/16 -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#pragma once -#ifndef hifi_FontFamilies_h -#define hifi_FontFamilies_h - -// the standard sans serif font family -#define SANS_FONT_FAMILY "Helvetica" - -// the standard sans serif font family -#define SERIF_FONT_FAMILY "Timeless" - -// the standard mono font family -#define MONO_FONT_FAMILY "Courier" - -// the Inconsolata font family -#ifdef Q_OS_WIN -#define INCONSOLATA_FONT_FAMILY "Fixedsys" -#define INCONSOLATA_FONT_WEIGHT QFont::Normal -#else -#define INCONSOLATA_FONT_FAMILY "Inconsolata" -#define INCONSOLATA_FONT_WEIGHT QFont::Bold -#endif - -#endif diff --git a/libraries/render-utils/src/text/Glyph.cpp b/libraries/render-utils/src/text/Glyph.cpp index 0354b1057c..ee3656bc00 100644 --- a/libraries/render-utils/src/text/Glyph.cpp +++ b/libraries/render-utils/src/text/Glyph.cpp @@ -18,5 +18,6 @@ void Glyph::read(QIODevice& in) { readStream(in, size); readStream(in, offset); readStream(in, d); + // texSize is divided by the image size later texSize = size; } diff --git a/libraries/shared/src/FontFamilies.h b/libraries/shared/src/FontFamilies.h new file mode 100644 index 0000000000..ba7af3ae7b --- /dev/null +++ b/libraries/shared/src/FontFamilies.h @@ -0,0 +1,17 @@ +// +// Created by Bradley Austin Davis on 2015/07/16 +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_FontFamilies_h +#define hifi_FontFamilies_h + +#define ROBOTO_FONT_FAMILY "Roboto" +#define COURIER_FONT_FAMILY "Courier" +#define INCONSOLATA_FONT_FAMILY "Inconsolata" +#define TIMELESS_FONT_FAMILY "Timeless" + +#endif // hifi_FontFamilies_h diff --git a/libraries/shared/src/TextEffect.cpp b/libraries/shared/src/TextEffect.cpp new file mode 100644 index 0000000000..27ed1caa59 --- /dev/null +++ b/libraries/shared/src/TextEffect.cpp @@ -0,0 +1,26 @@ +// +// Created by Sam Gondelman on 7/21/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "TextEffect.h" + +const char* textEffectNames[] = { + "none", + "outline", + "outline fill", + "shadow" +}; + +static const size_t TEXT_EFFECT_NAMES = (sizeof(textEffectNames) / sizeof(textEffectNames[0])); + +QString TextEffectHelpers::getNameForTextEffect(TextEffect effect) { + if (((int)effect <= 0) || ((int)effect >= (int)TEXT_EFFECT_NAMES)) { + effect = (TextEffect)0; + } + + return textEffectNames[(int)effect]; +} \ No newline at end of file diff --git a/libraries/shared/src/TextEffect.h b/libraries/shared/src/TextEffect.h new file mode 100644 index 0000000000..91bd5ec60c --- /dev/null +++ b/libraries/shared/src/TextEffect.h @@ -0,0 +1,42 @@ +// +// Created by Bradley Austin Davis on 2015/07/16 +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_TextEffect_h +#define hifi_TextEffect_h + +#include "QString" + +/**jsdoc + *

A {@link Entities.EntityProperties-Text|Text} entity may use one of the following effects:

+ * + * + * + * + * + * + * + * + * + * + *
ValueDescription
"none"No effect.
"outline"An outline effect.
"outlineFill"An outline effect, with fill.
"shadow"A shadow effect.
+ * @typedef {string} Entities.TextEffect + */ + +enum class TextEffect { + NO_EFFECT = 0, + OUTLINE_EFFECT, + OUTLINE_WITH_FILL_EFFECT, + SHADOW_EFFECT +}; + +class TextEffectHelpers { +public: + static QString getNameForTextEffect(TextEffect effect); +}; + +#endif // hifi_TextEffect_h \ No newline at end of file From f07352ab2c4d7e0bd60fbda9aba71f7b58bb3221 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 31 Jul 2019 13:39:52 -0700 Subject: [PATCH 04/20] add MaterialCache to oven's DependencyManager --- tools/oven/src/Oven.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/oven/src/Oven.cpp b/tools/oven/src/Oven.cpp index a680dd1f89..d7e0cec67b 100644 --- a/tools/oven/src/Oven.cpp +++ b/tools/oven/src/Oven.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ Oven::Oven() { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); MaterialBaker::setNextOvenWorkerThreadOperator([] { return Oven::instance().getNextWorkerThread(); From bfe42215aac68cc290ceeefa19168d4bd1e20b6d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 1 Aug 2019 14:29:03 -0700 Subject: [PATCH 05/20] DEV-279: Add rendering API information to the platform JSON object --- interface/src/Application.cpp | 3 + libraries/gl/src/gl/GLHelpers.cpp | 43 ++++++--- libraries/gl/src/gl/GLHelpers.h | 22 ++++- libraries/gl/src/gl/GLWindow.cpp | 14 ++- libraries/gl/src/gl/OffscreenGLCanvas.cpp | 8 +- .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 12 ++- libraries/platform/CMakeLists.txt | 4 +- .../platform/src/platform/PlatformKeys.h | 38 ++++++++ .../src/platform/backend/MACOSPlatform.cpp | 5 ++ .../src/platform/backend/MACOSPlatform.h | 1 + .../src/platform/backend/Platform.cpp | 39 ++++++++ .../src/platform/backend/PlatformInstance.cpp | 90 +++++++++++++++++++ .../src/platform/backend/PlatformInstance.h | 2 + .../src/platform/backend/WINPlatform.cpp | 6 ++ .../src/platform/backend/WINPlatform.h | 1 + 15 files changed, 254 insertions(+), 34 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a7cd45ae37..fd56795e12 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2996,6 +2996,9 @@ void Application::initializeGL() { qCWarning(interfaceapp, "Unable to make window context current"); } + // Populate the global OpenGL context based on the information for the primary window GL context + gl::ContextInfo::get(true); + #if !defined(DISABLE_QML) QStringList chromiumFlags; // HACK: re-expose mic and camera to prevent crash on domain-change in chromium's media::FakeAudioInputStream::ReadAudioFromSource() diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index c9f17b686d..2555ac61fc 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -148,6 +148,33 @@ static bool setupPixelFormatSimple(HDC hdc) { #endif + +const gl::ContextInfo& gl::ContextInfo::get(bool init) { + static gl::ContextInfo INSTANCE; + if (init) { + static std::once_flag once; + std::call_once(once, [&] { + INSTANCE.init(); + }); + } + return INSTANCE; +} + +gl::ContextInfo& gl::ContextInfo::init() { + if (glGetString) { + version = (const char*)glGetString(GL_VERSION); + shadingLanguageVersion = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + vendor = (const char*)glGetString(GL_VENDOR); + renderer = (const char*)glGetString(GL_RENDERER); + GLint n = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &n); + for (GLint i = 0; i < n; ++i) { + extensions.emplace_back((const char*)glGetStringi(GL_EXTENSIONS, i)); + } + } + return *this; +} + uint16_t gl::getAvailableVersion() { static uint8_t major = 0, minor = 0; static std::once_flag once; @@ -277,20 +304,16 @@ int glVersionToInteger(QString glVersion) { return (majorNumber << 16) | minorNumber; } -QJsonObject getGLContextData() { +const QJsonObject& getGLContextData() { static QJsonObject result; static std::once_flag once; std::call_once(once, [] { - QString glVersion = QString((const char*)glGetString(GL_VERSION)); - QString glslVersion = QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - QString glVendor = QString((const char*) glGetString(GL_VENDOR)); - QString glRenderer = QString((const char*)glGetString(GL_RENDERER)); - + auto contextInfo = gl::ContextInfo::get(); result = QJsonObject { - { "version", glVersion }, - { "sl_version", glslVersion }, - { "vendor", glVendor }, - { "renderer", glRenderer }, + { "version", contextInfo.version.c_str() }, + { "sl_version", contextInfo.shadingLanguageVersion.c_str() }, + { "vendor", contextInfo.vendor.c_str() }, + { "renderer", contextInfo.renderer.c_str() }, }; }); return result; diff --git a/libraries/gl/src/gl/GLHelpers.h b/libraries/gl/src/gl/GLHelpers.h index c09f9d4963..5090153bab 100644 --- a/libraries/gl/src/gl/GLHelpers.h +++ b/libraries/gl/src/gl/GLHelpers.h @@ -29,7 +29,7 @@ class QGLFormat; size_t evalGLFormatSwapchainPixelSize(const QSurfaceFormat& format); const QSurfaceFormat& getDefaultOpenGLSurfaceFormat(); -QJsonObject getGLContextData(); +const QJsonObject& getGLContextData(); int glVersionToInteger(QString glVersion); bool isRenderThread(); @@ -39,6 +39,26 @@ bool isRenderThread(); #define GL_GET_MAJOR_VERSION(glversion) ((glversion & 0xFF00) >> 8) namespace gl { + struct ContextInfo { + std::string version; + std::string shadingLanguageVersion; + std::string vendor; + std::string renderer; + std::vector extensions; + + ContextInfo& init(); + operator bool() const { return !version.empty(); } + + static const ContextInfo& get(bool init = false); + }; + +#define LOG_GL_CONTEXT_INFO(category, contextInfo) \ + qCDebug(category) << "GL Version: " << contextInfo.version.c_str(); \ + qCDebug(category) << "GL Shader Language Version: " << contextInfo.shadingLanguageVersion.c_str(); \ + qCDebug(category) << "GL Vendor: " << contextInfo.vendor.c_str(); \ + qCDebug(category) << "GL Renderer: " << contextInfo.renderer.c_str(); + + void globalLock(); void globalRelease(bool finish = true); diff --git a/libraries/gl/src/gl/GLWindow.cpp b/libraries/gl/src/gl/GLWindow.cpp index 7930e050de..19f8428d0a 100644 --- a/libraries/gl/src/gl/GLWindow.cpp +++ b/libraries/gl/src/gl/GLWindow.cpp @@ -33,14 +33,12 @@ GLWindow::~GLWindow() { bool GLWindow::makeCurrent() { bool makeCurrentResult = _context->makeCurrent(); Q_ASSERT(makeCurrentResult); - - std::call_once(_reportOnce, []{ - qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); - qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(glLogging) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR)); - qCDebug(glLogging) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER)); - }); - + + if (makeCurrentResult) { + std::call_once(_reportOnce, []{ + LOG_GL_CONTEXT_INFO(glLogging, gl::ContextInfo().init()); + }); + } return makeCurrentResult; } diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp index 69b41da821..c5b8baa6d4 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp +++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp @@ -73,13 +73,9 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) { bool OffscreenGLCanvas::makeCurrent() { bool result = _context->makeCurrent(_offscreenSurface); - if (glGetString) { + if (result) { std::call_once(_reportOnce, [] { - qCDebug(glLogging) << "GL Version: " << QString((const char*)glGetString(GL_VERSION)); - qCDebug(glLogging) << "GL Shader Language Version: " - << QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(glLogging) << "GL Vendor: " << QString((const char*)glGetString(GL_VENDOR)); - qCDebug(glLogging) << "GL Renderer: " << QString((const char*)glGetString(GL_RENDERER)); + LOG_GL_CONTEXT_INFO(glLogging, gl::ContextInfo().init()); }); } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index fef458f536..3e5043003b 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -117,9 +117,10 @@ void GLBackend::init() { static std::once_flag once; std::call_once(once, [] { - - QString vendor{ (const char*)glGetString(GL_VENDOR) }; - QString renderer{ (const char*)glGetString(GL_RENDERER) }; + ::gl::ContextInfo contextInfo; + contextInfo.init(); + QString vendor { contextInfo.vendor.c_str() }; + QString renderer { contextInfo.renderer.c_str() }; // Textures GL_GET_INTEGER(MAX_TEXTURE_IMAGE_UNITS); @@ -131,10 +132,7 @@ void GLBackend::init() { GL_GET_INTEGER(MAX_UNIFORM_BLOCK_SIZE); GL_GET_INTEGER(UNIFORM_BUFFER_OFFSET_ALIGNMENT); - qCDebug(gpugllogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); - qCDebug(gpugllogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(gpugllogging) << "GL Vendor: " << vendor; - qCDebug(gpugllogging) << "GL Renderer: " << renderer; + LOG_GL_CONTEXT_INFO(gpugllogging, contextInfo); GPUIdent* gpu = GPUIdent::getInstance(vendor, renderer); // From here on, GPUIdent::getInstance()->getMumble() should efficiently give the same answers. qCDebug(gpugllogging) << "GPU:"; diff --git a/libraries/platform/CMakeLists.txt b/libraries/platform/CMakeLists.txt index f0dce500f4..0d984f9684 100644 --- a/libraries/platform/CMakeLists.txt +++ b/libraries/platform/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME platform) setup_hifi_library() -link_hifi_libraries(shared) +link_hifi_libraries(shared gl) GroupSources("src") target_json() @@ -15,4 +15,4 @@ if (APPLE) elseif(WIN32) target_link_libraries(${TARGET_NAME} Iphlpapi.lib) -endif () \ No newline at end of file +endif() \ No newline at end of file diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index 5008a4f6ce..02c6a6021d 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -34,6 +34,43 @@ namespace platform { namespace keys{ extern const char* displays; extern const char* isMaster; } + namespace renderingApis { + extern const char* apiOpenGL; + extern const char* apiVulkan; + extern const char* apiDirect3D11; + extern const char* apiDirect3D12; + extern const char* apiMetal; + namespace gl { + extern const char* version; + extern const char* shadingLanguageVersion; + extern const char* vendor; + extern const char* renderer; + extern const char* extensions; + } + namespace vk { + extern const char* version; + extern const char* devices; + namespace device { + extern const char* apiVersion; + extern const char* driverVersion; + extern const char* deviceType; + extern const char* vendor; + extern const char* name; + extern const char* formats; + extern const char* extensions; + extern const char* queues; + extern const char* heaps; + namespace heap { + extern const char* flags; + extern const char* size; + } + namespace queue { + extern const char* flags; + extern const char* count; + } + } + } + } namespace nic { extern const char* mac; extern const char* name; @@ -78,6 +115,7 @@ namespace platform { namespace keys{ // Keys for categories used in json returned by getAll() extern const char* CPUS; extern const char* GPUS; + extern const char* RENDERING_APIS; extern const char* DISPLAYS; extern const char* NICS; extern const char* MEMORY; diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index 66c9cd2c5d..8b37cd36b5 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -322,3 +322,8 @@ void MACOSInstance::enumerateComputer(){ } +void MACOSInstance::enumerateRenderingApis() { + Instance::enumerateRenderingApis(); + + // TODO imeplement Metal query +} diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.h b/libraries/platform/src/platform/backend/MACOSPlatform.h index f249dad001..464d2ced5e 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.h +++ b/libraries/platform/src/platform/backend/MACOSPlatform.h @@ -19,6 +19,7 @@ namespace platform { void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; + void enumerateRenderingApis() override; }; } // namespace platform diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index 17d9d8019e..d15ce34776 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -35,6 +35,44 @@ namespace platform { namespace keys { const char* displays = "displays"; const char* isMaster = "isMaster"; } + namespace renderingApis { + const char* apiOpenGL = "OpenGL"; + const char* apiVulkan = "Vulkan"; + const char* apiDirect3D11 = "D3D11"; + const char* apiDirect3D12 = "D3D12"; + const char* apiMetal = "Metal"; + + namespace gl { + const char* version = "version"; + const char* shadingLanguageVersion = "shadingLanguageVersion"; + const char* vendor = "vendor"; + const char* renderer = "renderer"; + const char* extensions = "extensions"; + } + namespace vk { + const char* version = "version"; + const char* devices = "devices"; + namespace device { + const char* apiVersion = "apiVersion"; + const char* driverVersion = "driverVersion"; + const char* deviceType = "deviceType"; + const char* vendor = "vendor"; + const char* name = "name"; + const char* formats = "formats"; + const char* extensions = "extensions"; + const char* heaps = "heaps"; + namespace heap { + const char* flags = "flags"; + const char* size = "size"; + } + const char* queues = "queues"; + namespace queue { + const char* flags = "flags"; + const char* count = "count"; + } + } + } + } namespace nic { const char* mac = "mac"; const char* name = "name"; @@ -78,6 +116,7 @@ namespace platform { namespace keys { const char* CPUS = "cpus"; const char* GPUS = "gpus"; + const char* RENDERING_APIS = "renderingApis"; const char* DISPLAYS = "displays"; const char* NICS = "nics"; const char* MEMORY = "memory"; diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index d4cadba3b7..0ac11f9f0f 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -10,9 +10,18 @@ #include "PlatformInstance.h" #include +#include #include "../PlatformKeys.h" #include "../Profiler.h" +// For testing the vulkan dump +//#define HAVE_VULKAN 1 +//#pragma comment(lib, "C:\\VulkanSDK\\1.1.101.0\\Lib\\vulkan-1.lib") + +#ifdef HAVE_VULKAN +#include +#endif + using namespace platform; bool Instance::enumeratePlatform() { @@ -30,6 +39,7 @@ bool Instance::enumeratePlatform() { enumerateCpus(); enumerateGpusAndDisplays(); enumerateNics(); + enumerateRenderingApis(); // eval the master index for each platform scopes updateMasterIndices(); @@ -105,6 +115,72 @@ void Instance::enumerateNics() { } } +#if defined(HAVE_VULKAN) +static std::string vkVersionToString(uint32_t version) { + return QString("%1.%2.%3").arg(VK_VERSION_MAJOR(version)).arg(VK_VERSION_MINOR(version)).arg(VK_VERSION_PATCH(version)).toStdString(); +} +#endif + + +void Instance::enumerateRenderingApis() { + // OpenGL rendering API is supported on all platforms + { + auto& glContextInfo = gl::ContextInfo::get(); + json gl; + gl[keys::renderingApis::gl::version] = glContextInfo.version; + gl[keys::renderingApis::gl::vendor] = glContextInfo.vendor; + gl[keys::renderingApis::gl::renderer] = glContextInfo.renderer; + gl[keys::renderingApis::gl::shadingLanguageVersion] = glContextInfo.shadingLanguageVersion; + gl[keys::renderingApis::gl::extensions] = glContextInfo.extensions; + _renderingApis[keys::renderingApis::apiOpenGL] = gl; + } + +#if defined(HAVE_VULKAN) + // Vulkan rendering API is supported on all platforms (sort of) + { + try { + vk::ApplicationInfo appInfo{ "Interface", 1, "Luci", 1, VK_API_VERSION_1_1 }; + auto instancePtr = vk::createInstanceUnique({ {}, &appInfo }); + if (instancePtr) { + json vkinfo; + const auto& vkinstance = *instancePtr; + vkinfo[keys::renderingApis::vk::version] = vkVersionToString(VK_API_VERSION_1_1); + for (const auto& physicalDevice : vkinstance.enumeratePhysicalDevices()) { + json vkdevice; + auto properties = physicalDevice.getProperties(); + vkdevice[keys::renderingApis::vk::device::driverVersion] = vkVersionToString(properties.driverVersion); + vkdevice[keys::renderingApis::vk::device::apiVersion] = vkVersionToString(properties.apiVersion); + vkdevice[keys::renderingApis::vk::device::deviceType] = vk::to_string(properties.deviceType); + vkdevice[keys::renderingApis::vk::device::vendor] = properties.vendorID; + vkdevice[keys::renderingApis::vk::device::name] = properties.deviceName; + for (const auto& extensionProperties : physicalDevice.enumerateDeviceExtensionProperties()) { + vkdevice[keys::renderingApis::vk::device::extensions].push_back(extensionProperties.extensionName); + } + + for (const auto& queueFamilyProperties : physicalDevice.getQueueFamilyProperties()) { + json vkqueuefamily; + vkqueuefamily[keys::renderingApis::vk::device::queue::flags] = vk::to_string(queueFamilyProperties.queueFlags); + vkqueuefamily[keys::renderingApis::vk::device::queue::count] = queueFamilyProperties.queueCount; + vkdevice[keys::renderingApis::vk::device::queues].push_back(vkqueuefamily); + } + auto memoryProperties = physicalDevice.getMemoryProperties(); + for (uint32_t heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; ++heapIndex) { + json vkmemoryheap; + const auto& heap = memoryProperties.memoryHeaps[heapIndex]; + vkmemoryheap[keys::renderingApis::vk::device::heap::flags] = vk::to_string(heap.flags); + vkmemoryheap[keys::renderingApis::vk::device::heap::size] = heap.size; + vkdevice[keys::renderingApis::vk::device::heaps].push_back(vkmemoryheap); + } + vkinfo[keys::renderingApis::vk::devices].push_back(vkdevice); + } + _renderingApis[keys::renderingApis::apiVulkan] = vkinfo; + } + } catch (const std::runtime_error&) { + } + } +#endif +} + json Instance::getCPU(int index) { assert(index <(int) _cpus.size()); @@ -167,6 +243,18 @@ json Instance::listAllKeys() { keys::gpu::driver, keys::gpu::displays, + keys::renderingApis::apiOpenGL, + keys::renderingApis::apiVulkan, + keys::renderingApis::apiMetal, + keys::renderingApis::apiDirect3D11, + keys::renderingApis::apiDirect3D12, + + keys::renderingApis::gl::version, + keys::renderingApis::gl::shadingLanguageVersion, + keys::renderingApis::gl::vendor, + keys::renderingApis::gl::renderer, + keys::renderingApis::gl::extensions, + keys::display::boundsLeft, keys::display::boundsRight, keys::display::boundsTop, @@ -188,6 +276,7 @@ json Instance::listAllKeys() { keys::CPUS, keys::GPUS, + keys::RENDERING_APIS, keys::DISPLAYS, keys::MEMORY, keys::COMPUTER, @@ -219,6 +308,7 @@ json Instance::getAll() { all[keys::MEMORY] = _memory; all[keys::CPUS] = _cpus; all[keys::GPUS] = _gpus; + all[keys::RENDERING_APIS] = _renderingApis; all[keys::DISPLAYS] = _displays; all[keys::NICS] = _nics; diff --git a/libraries/platform/src/platform/backend/PlatformInstance.h b/libraries/platform/src/platform/backend/PlatformInstance.h index 069124853e..7078c31d90 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.h +++ b/libraries/platform/src/platform/backend/PlatformInstance.h @@ -44,6 +44,7 @@ public: void virtual enumerateNics(); void virtual enumerateMemory() = 0; void virtual enumerateComputer()=0; + virtual void enumerateRenderingApis(); virtual ~Instance(); @@ -57,6 +58,7 @@ protected: std::vector _gpus; std::vector _displays; std::vector _nics; + json _renderingApis; json _memory; json _computer; diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index e528618fe1..e0585aa14b 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -251,3 +251,9 @@ void WINInstance::enumerateNics() { } #endif } + +void WINInstance::enumerateRenderingApis() { + Instance::enumerateRenderingApis(); + + // TODO imeplement D3D 11/12 queries +} diff --git a/libraries/platform/src/platform/backend/WINPlatform.h b/libraries/platform/src/platform/backend/WINPlatform.h index cc56ebfbbc..0a92efb948 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.h +++ b/libraries/platform/src/platform/backend/WINPlatform.h @@ -20,6 +20,7 @@ namespace platform { void enumerateMemory() override; void enumerateComputer () override; void enumerateNics() override; + void enumerateRenderingApis() override; }; } // namespace platform From f1dee1e7f83036a0274f0d8dbb09a878da769dfe Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Aug 2019 14:50:21 -0700 Subject: [PATCH 06/20] fix uninitialized variables --- libraries/entities/src/EntityScriptingInterface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 0442756300..ca9108852f 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -78,7 +78,7 @@ public: bool accurate { true }; QUuid entityID; float distance { 0.0f }; - BoxFace face; + BoxFace face { UNKNOWN_FACE }; glm::vec3 intersection; glm::vec3 surfaceNormal; QVariantMap extraInfo; @@ -94,7 +94,7 @@ public: QUuid entityID; float distance { 0.0f }; float parabolicDistance { 0.0f }; - BoxFace face; + BoxFace face { UNKNOWN_FACE }; glm::vec3 intersection; glm::vec3 surfaceNormal; QVariantMap extraInfo; From 06ad461c32a92e75f2bdf0669b9c271d727a4d95 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 1 Aug 2019 16:57:54 -0700 Subject: [PATCH 07/20] PR feedback --- interface/src/Application.cpp | 21 +++--- libraries/gl/src/gl/GLHelpers.cpp | 15 ----- libraries/gl/src/gl/GLHelpers.h | 1 - .../platform/src/platform/PlatformKeys.h | 8 +-- .../src/platform/backend/Platform.cpp | 7 +- .../src/platform/backend/PlatformInstance.cpp | 64 +++++++++---------- .../src/platform/backend/PlatformInstance.h | 2 +- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 14 +++- 8 files changed, 67 insertions(+), 65 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fd56795e12..8789fcde1c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1659,7 +1659,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. static const QString TESTER = "HIFI_TESTER"; auto gpuIdent = GPUIdent::getInstance(); - auto glContextData = getGLContextData(); + auto glContextData = gl::ContextInfo::get(); QJsonObject properties = { { "version", applicationVersion() }, { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) || isTester }, @@ -1676,11 +1676,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo { "gpu_name", gpuIdent->getName() }, { "gpu_driver", gpuIdent->getDriver() }, { "gpu_memory", static_cast(gpuIdent->getMemory()) }, - { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, - { "gl_version", glContextData["version"] }, - { "gl_vender", glContextData["vendor"] }, - { "gl_sl_version", glContextData["sl_version"] }, - { "gl_renderer", glContextData["renderer"] }, + { "gl_version_int", glVersionToInteger(glContextData.version.c_str()) }, + { "gl_version", glContextData.version.c_str() }, + { "gl_vender", glContextData.vendor.c_str() }, + { "gl_sl_version", glContextData.shadingLanguageVersion.c_str() }, + { "gl_renderer", glContextData.renderer.c_str() }, { "ideal_thread_count", QThread::idealThreadCount() } }; auto macVersion = QSysInfo::macVersion(); @@ -2282,8 +2282,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); - auto glInfo = getGLContextData(); - properties["gl_info"] = glInfo; + auto contextInfo = gl::ContextInfo::get(); + properties["gl_info"] = QJsonObject{ + { "version", contextInfo.version.c_str() }, + { "sl_version", contextInfo.shadingLanguageVersion.c_str() }, + { "vendor", contextInfo.vendor.c_str() }, + { "renderer", contextInfo.renderer.c_str() }, + }; properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemSize()); properties["gpu_free_memory"] = (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemSize()); properties["gpu_frame_time"] = (float)(qApp->getGPUContext()->getFrameTimerGPUAverage()); diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index 2555ac61fc..b2c98e91d3 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -304,21 +304,6 @@ int glVersionToInteger(QString glVersion) { return (majorNumber << 16) | minorNumber; } -const QJsonObject& getGLContextData() { - static QJsonObject result; - static std::once_flag once; - std::call_once(once, [] { - auto contextInfo = gl::ContextInfo::get(); - result = QJsonObject { - { "version", contextInfo.version.c_str() }, - { "sl_version", contextInfo.shadingLanguageVersion.c_str() }, - { "vendor", contextInfo.vendor.c_str() }, - { "renderer", contextInfo.renderer.c_str() }, - }; - }); - return result; -} - QThread* RENDER_THREAD = nullptr; bool isRenderThread() { diff --git a/libraries/gl/src/gl/GLHelpers.h b/libraries/gl/src/gl/GLHelpers.h index 5090153bab..05687b2a8a 100644 --- a/libraries/gl/src/gl/GLHelpers.h +++ b/libraries/gl/src/gl/GLHelpers.h @@ -29,7 +29,6 @@ class QGLFormat; size_t evalGLFormatSwapchainPixelSize(const QSurfaceFormat& format); const QSurfaceFormat& getDefaultOpenGLSurfaceFormat(); -const QJsonObject& getGLContextData(); int glVersionToInteger(QString glVersion); bool isRenderThread(); diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index 02c6a6021d..9bd9d47890 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -34,21 +34,21 @@ namespace platform { namespace keys{ extern const char* displays; extern const char* isMaster; } - namespace renderingApis { + namespace graphicsAPI { + extern const char* name; + extern const char* version; extern const char* apiOpenGL; extern const char* apiVulkan; extern const char* apiDirect3D11; extern const char* apiDirect3D12; extern const char* apiMetal; namespace gl { - extern const char* version; extern const char* shadingLanguageVersion; extern const char* vendor; extern const char* renderer; extern const char* extensions; } namespace vk { - extern const char* version; extern const char* devices; namespace device { extern const char* apiVersion; @@ -115,7 +115,7 @@ namespace platform { namespace keys{ // Keys for categories used in json returned by getAll() extern const char* CPUS; extern const char* GPUS; - extern const char* RENDERING_APIS; + extern const char* GRAPHICS_APIS; extern const char* DISPLAYS; extern const char* NICS; extern const char* MEMORY; diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index d15ce34776..dd40de04f1 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -35,7 +35,10 @@ namespace platform { namespace keys { const char* displays = "displays"; const char* isMaster = "isMaster"; } - namespace renderingApis { + namespace graphicsAPI { + const char* name = "name"; + const char* version = "version"; + const char* apiOpenGL = "OpenGL"; const char* apiVulkan = "Vulkan"; const char* apiDirect3D11 = "D3D11"; @@ -116,7 +119,7 @@ namespace platform { namespace keys { const char* CPUS = "cpus"; const char* GPUS = "gpus"; - const char* RENDERING_APIS = "renderingApis"; + const char* GRAPHICS_APIS = "graphicsAPIS"; const char* DISPLAYS = "displays"; const char* NICS = "nics"; const char* MEMORY = "memory"; diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index 0ac11f9f0f..faea24289a 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -127,12 +127,13 @@ void Instance::enumerateRenderingApis() { { auto& glContextInfo = gl::ContextInfo::get(); json gl; - gl[keys::renderingApis::gl::version] = glContextInfo.version; - gl[keys::renderingApis::gl::vendor] = glContextInfo.vendor; - gl[keys::renderingApis::gl::renderer] = glContextInfo.renderer; - gl[keys::renderingApis::gl::shadingLanguageVersion] = glContextInfo.shadingLanguageVersion; - gl[keys::renderingApis::gl::extensions] = glContextInfo.extensions; - _renderingApis[keys::renderingApis::apiOpenGL] = gl; + gl[keys::graphicsAPI::name] = keys::graphicsAPI::apiOpenGL; + gl[keys::graphicsAPI::version] = glContextInfo.version; + gl[keys::graphicsAPI::gl::vendor] = glContextInfo.vendor; + gl[keys::graphicsAPI::gl::renderer] = glContextInfo.renderer; + gl[keys::graphicsAPI::gl::shadingLanguageVersion] = glContextInfo.shadingLanguageVersion; + gl[keys::graphicsAPI::gl::extensions] = glContextInfo.extensions; + _graphicsApis.push_back(gl); } #if defined(HAVE_VULKAN) @@ -144,36 +145,37 @@ void Instance::enumerateRenderingApis() { if (instancePtr) { json vkinfo; const auto& vkinstance = *instancePtr; - vkinfo[keys::renderingApis::vk::version] = vkVersionToString(VK_API_VERSION_1_1); + vkinfo[keys::graphicsAPI::name] = keys::graphicsAPI::apiVulkan; + vkinfo[keys::graphicsAPI::version] = vkVersionToString(VK_API_VERSION_1_1); for (const auto& physicalDevice : vkinstance.enumeratePhysicalDevices()) { json vkdevice; auto properties = physicalDevice.getProperties(); - vkdevice[keys::renderingApis::vk::device::driverVersion] = vkVersionToString(properties.driverVersion); - vkdevice[keys::renderingApis::vk::device::apiVersion] = vkVersionToString(properties.apiVersion); - vkdevice[keys::renderingApis::vk::device::deviceType] = vk::to_string(properties.deviceType); - vkdevice[keys::renderingApis::vk::device::vendor] = properties.vendorID; - vkdevice[keys::renderingApis::vk::device::name] = properties.deviceName; + vkdevice[keys::graphicsAPI::vk::device::driverVersion] = vkVersionToString(properties.driverVersion); + vkdevice[keys::graphicsAPI::vk::device::apiVersion] = vkVersionToString(properties.apiVersion); + vkdevice[keys::graphicsAPI::vk::device::deviceType] = vk::to_string(properties.deviceType); + vkdevice[keys::graphicsAPI::vk::device::vendor] = properties.vendorID; + vkdevice[keys::graphicsAPI::vk::device::name] = properties.deviceName; for (const auto& extensionProperties : physicalDevice.enumerateDeviceExtensionProperties()) { - vkdevice[keys::renderingApis::vk::device::extensions].push_back(extensionProperties.extensionName); + vkdevice[keys::graphicsAPI::vk::device::extensions].push_back(extensionProperties.extensionName); } for (const auto& queueFamilyProperties : physicalDevice.getQueueFamilyProperties()) { json vkqueuefamily; - vkqueuefamily[keys::renderingApis::vk::device::queue::flags] = vk::to_string(queueFamilyProperties.queueFlags); - vkqueuefamily[keys::renderingApis::vk::device::queue::count] = queueFamilyProperties.queueCount; - vkdevice[keys::renderingApis::vk::device::queues].push_back(vkqueuefamily); + vkqueuefamily[keys::graphicsAPI::vk::device::queue::flags] = vk::to_string(queueFamilyProperties.queueFlags); + vkqueuefamily[keys::graphicsAPI::vk::device::queue::count] = queueFamilyProperties.queueCount; + vkdevice[keys::graphicsAPI::vk::device::queues].push_back(vkqueuefamily); } auto memoryProperties = physicalDevice.getMemoryProperties(); for (uint32_t heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; ++heapIndex) { json vkmemoryheap; const auto& heap = memoryProperties.memoryHeaps[heapIndex]; - vkmemoryheap[keys::renderingApis::vk::device::heap::flags] = vk::to_string(heap.flags); - vkmemoryheap[keys::renderingApis::vk::device::heap::size] = heap.size; - vkdevice[keys::renderingApis::vk::device::heaps].push_back(vkmemoryheap); + vkmemoryheap[keys::graphicsAPI::vk::device::heap::flags] = vk::to_string(heap.flags); + vkmemoryheap[keys::graphicsAPI::vk::device::heap::size] = heap.size; + vkdevice[keys::graphicsAPI::vk::device::heaps].push_back(vkmemoryheap); } - vkinfo[keys::renderingApis::vk::devices].push_back(vkdevice); + vkinfo[keys::graphicsAPI::vk::devices].push_back(vkdevice); } - _renderingApis[keys::renderingApis::apiVulkan] = vkinfo; + _graphicsApis.push_back(vkinfo); } } catch (const std::runtime_error&) { } @@ -243,17 +245,13 @@ json Instance::listAllKeys() { keys::gpu::driver, keys::gpu::displays, - keys::renderingApis::apiOpenGL, - keys::renderingApis::apiVulkan, - keys::renderingApis::apiMetal, - keys::renderingApis::apiDirect3D11, - keys::renderingApis::apiDirect3D12, + keys::graphicsAPI::version, + keys::graphicsAPI::name, - keys::renderingApis::gl::version, - keys::renderingApis::gl::shadingLanguageVersion, - keys::renderingApis::gl::vendor, - keys::renderingApis::gl::renderer, - keys::renderingApis::gl::extensions, + keys::graphicsAPI::gl::shadingLanguageVersion, + keys::graphicsAPI::gl::vendor, + keys::graphicsAPI::gl::renderer, + keys::graphicsAPI::gl::extensions, keys::display::boundsLeft, keys::display::boundsRight, @@ -276,7 +274,7 @@ json Instance::listAllKeys() { keys::CPUS, keys::GPUS, - keys::RENDERING_APIS, + keys::GRAPHICS_APIS, keys::DISPLAYS, keys::MEMORY, keys::COMPUTER, @@ -308,7 +306,7 @@ json Instance::getAll() { all[keys::MEMORY] = _memory; all[keys::CPUS] = _cpus; all[keys::GPUS] = _gpus; - all[keys::RENDERING_APIS] = _renderingApis; + all[keys::GRAPHICS_APIS] = _graphicsApis; all[keys::DISPLAYS] = _displays; all[keys::NICS] = _nics; diff --git a/libraries/platform/src/platform/backend/PlatformInstance.h b/libraries/platform/src/platform/backend/PlatformInstance.h index 7078c31d90..7cb419ceca 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.h +++ b/libraries/platform/src/platform/backend/PlatformInstance.h @@ -58,7 +58,7 @@ protected: std::vector _gpus; std::vector _displays; std::vector _nics; - json _renderingApis; + json _graphicsApis; json _memory; json _computer; diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 34cac90a05..35fb92a086 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -264,7 +264,19 @@ void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) { } auto rootContext = engine->rootContext(); - rootContext->setContextProperty("GL", ::getGLContextData()); + + static QJsonObject QML_GL_INFO; + static std::once_flag once_gl_info; + std::call_once(once_gl_info, [] { + const auto& contextInfo = gl::ContextInfo::get(); + QML_GL_INFO = QJsonObject { + { "version", contextInfo.version.c_str() }, + { "sl_version", contextInfo.shadingLanguageVersion.c_str() }, + { "vendor", contextInfo.vendor.c_str() }, + { "renderer", contextInfo.renderer.c_str() }, + }; + }); + rootContext->setContextProperty("GL", QML_GL_INFO); rootContext->setContextProperty("urlHandler", new UrlHandler(rootContext)); rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath())); rootContext->setContextProperty("ApplicationInterface", qApp); From c85b0572e592a988b710e23b28b33a08dcec30c8 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 1 Aug 2019 17:17:47 -0700 Subject: [PATCH 08/20] fixing function name --- libraries/platform/src/platform/backend/MACOSPlatform.cpp | 4 ++-- libraries/platform/src/platform/backend/MACOSPlatform.h | 2 +- libraries/platform/src/platform/backend/PlatformInstance.cpp | 4 ++-- libraries/platform/src/platform/backend/PlatformInstance.h | 2 +- libraries/platform/src/platform/backend/WINPlatform.cpp | 4 ++-- libraries/platform/src/platform/backend/WINPlatform.h | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index 8b37cd36b5..5a7b40f71b 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -322,8 +322,8 @@ void MACOSInstance::enumerateComputer(){ } -void MACOSInstance::enumerateRenderingApis() { - Instance::enumerateRenderingApis(); +void MACOSInstance::enumerateGraphicsApis() { + Instance::enumerateGraphicsApis(); // TODO imeplement Metal query } diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.h b/libraries/platform/src/platform/backend/MACOSPlatform.h index 464d2ced5e..87c16972ec 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.h +++ b/libraries/platform/src/platform/backend/MACOSPlatform.h @@ -19,7 +19,7 @@ namespace platform { void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; - void enumerateRenderingApis() override; + void enumerateGraphicsApis() override; }; } // namespace platform diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index faea24289a..d73abf5286 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -39,7 +39,7 @@ bool Instance::enumeratePlatform() { enumerateCpus(); enumerateGpusAndDisplays(); enumerateNics(); - enumerateRenderingApis(); + enumerateGraphicsApis(); // eval the master index for each platform scopes updateMasterIndices(); @@ -122,7 +122,7 @@ static std::string vkVersionToString(uint32_t version) { #endif -void Instance::enumerateRenderingApis() { +void Instance::enumerateGraphicsApis() { // OpenGL rendering API is supported on all platforms { auto& glContextInfo = gl::ContextInfo::get(); diff --git a/libraries/platform/src/platform/backend/PlatformInstance.h b/libraries/platform/src/platform/backend/PlatformInstance.h index 7cb419ceca..2b263c21ef 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.h +++ b/libraries/platform/src/platform/backend/PlatformInstance.h @@ -44,7 +44,7 @@ public: void virtual enumerateNics(); void virtual enumerateMemory() = 0; void virtual enumerateComputer()=0; - virtual void enumerateRenderingApis(); + virtual void enumerateGraphicsApis(); virtual ~Instance(); diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index e0585aa14b..8c0bb1b9aa 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -252,8 +252,8 @@ void WINInstance::enumerateNics() { #endif } -void WINInstance::enumerateRenderingApis() { - Instance::enumerateRenderingApis(); +void WINInstance::enumerateGraphicsApis() { + Instance::enumerateGraphicsApis(); // TODO imeplement D3D 11/12 queries } diff --git a/libraries/platform/src/platform/backend/WINPlatform.h b/libraries/platform/src/platform/backend/WINPlatform.h index 0a92efb948..dd29d696dc 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.h +++ b/libraries/platform/src/platform/backend/WINPlatform.h @@ -20,7 +20,7 @@ namespace platform { void enumerateMemory() override; void enumerateComputer () override; void enumerateNics() override; - void enumerateRenderingApis() override; + void enumerateGraphicsApis() override; }; } // namespace platform From 8878731826b8fa9174d02d03c735a27935a77ede Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 1 Aug 2019 17:44:42 -0700 Subject: [PATCH 09/20] Fixing unused vars --- libraries/platform/src/platform/backend/Platform.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index dd40de04f1..4bc6f3219f 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -46,14 +46,12 @@ namespace platform { namespace keys { const char* apiMetal = "Metal"; namespace gl { - const char* version = "version"; const char* shadingLanguageVersion = "shadingLanguageVersion"; const char* vendor = "vendor"; const char* renderer = "renderer"; const char* extensions = "extensions"; } namespace vk { - const char* version = "version"; const char* devices = "devices"; namespace device { const char* apiVersion = "apiVersion"; From 029a494beb9228fa2e9f35363f7fee40deb9a0a0 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Thu, 1 Aug 2019 14:53:02 -0700 Subject: [PATCH 10/20] try to fix android shader build error --- libraries/render-utils/src/sdf_text3D.slv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/sdf_text3D.slv b/libraries/render-utils/src/sdf_text3D.slv index a6cb43f038..9ac3b871f9 100644 --- a/libraries/render-utils/src/sdf_text3D.slv +++ b/libraries/render-utils/src/sdf_text3D.slv @@ -36,7 +36,7 @@ void main() { if (params.effect == 3) { // Shadow const int VERTICES_PER_QUAD = 4; // must match value in Font.cpp const float EPSILON = 0.001; - position.z += floor(gl_VertexID / VERTICES_PER_QUAD) * EPSILON; + position.z += float(gl_VertexID / VERTICES_PER_QUAD) * EPSILON; } TransformCamera cam = getTransformCamera(); From 437d0ea92807dd14f409e9ac8f5f33ebcfd68755 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 2 Aug 2019 06:46:34 -0700 Subject: [PATCH 11/20] Save and restore the audio gain settings --- interface/src/scripting/Audio.cpp | 10 ++++++++++ interface/src/scripting/Audio.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index f674b533a7..f5569a19b2 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -213,6 +213,11 @@ void Audio::setPTTHMD(bool enabled) { } void Audio::saveData() { + _avatarGainSetting.set(getAvatarGain()); + _injectorGainSetting.set(getInjectorGain()); + _localInjectorGainSetting.set(getLocalInjectorGain()); + _systemInjectorGainSetting.set(getSystemInjectorGain()); + _mutedDesktopSetting.set(getMutedDesktop()); _mutedHMDSetting.set(getMutedHMD()); _pttDesktopSetting.set(getPTTDesktop()); @@ -220,6 +225,11 @@ void Audio::saveData() { } void Audio::loadData() { + setAvatarGain(_avatarGainSetting.get()); + setInjectorGain(_injectorGainSetting.get()); + setLocalInjectorGain(_localInjectorGainSetting.get()); + setSystemInjectorGain(_systemInjectorGainSetting.get()); + setMutedDesktop(_mutedDesktopSetting.get()); setMutedHMD(_mutedHMDSetting.get()); setPTTDesktop(_pttDesktopSetting.get()); diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index d2d1ee36c9..5baeee4176 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -521,6 +521,10 @@ private: bool _settingsLoaded { false }; float _inputVolume { 1.0f }; float _inputLevel { 0.0f }; + Setting::Handle _avatarGainSetting { QStringList { Audio::AUDIO, "AvatarGain" }, 0.0f }; + Setting::Handle _injectorGainSetting { QStringList { Audio::AUDIO, "InjectorGain" }, 0.0f }; + Setting::Handle _localInjectorGainSetting { QStringList { Audio::AUDIO, "LocalInjectorGain" }, 0.0f }; + Setting::Handle _systemInjectorGainSetting { QStringList { Audio::AUDIO, "SystemInjectorGain" }, 0.0f }; float _localInjectorGain { 0.0f }; // in dB float _systemInjectorGain { 0.0f }; // in dB float _pttOutputGainDesktop { 0.0f }; // in dB From 0b97f2bbc04706a4d897e31067b3f21ecb365e10 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 2 Aug 2019 07:14:43 -0700 Subject: [PATCH 12/20] Track the desired audio-mixer gains when not connected --- libraries/networking/src/NodeList.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 306e0155d3..63a36bc97b 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -1143,6 +1143,10 @@ void NodeList::maybeSendIgnoreSetToNode(SharedNodePointer newNode) { } void NodeList::setAvatarGain(const QUuid& nodeID, float gain) { + if (nodeID.isNull()) { + _avatarGain = gain; + } + // cannot set gain of yourself if (getSessionUUID() != nodeID) { auto audioMixer = soloNodeOfType(NodeType::AudioMixer); @@ -1160,7 +1164,6 @@ void NodeList::setAvatarGain(const QUuid& nodeID, float gain) { qCDebug(networking) << "Sending Set MASTER Avatar Gain packet with Gain:" << gain; sendPacket(std::move(setAvatarGainPacket), *audioMixer); - _avatarGain = gain; } else { qCDebug(networking) << "Sending Set Avatar Gain packet with UUID:" << uuidStringWithoutCurlyBraces(nodeID) << "Gain:" << gain; @@ -1192,6 +1195,8 @@ float NodeList::getAvatarGain(const QUuid& nodeID) { } void NodeList::setInjectorGain(float gain) { + _injectorGain = gain; + auto audioMixer = soloNodeOfType(NodeType::AudioMixer); if (audioMixer) { // setup the packet @@ -1203,7 +1208,6 @@ void NodeList::setInjectorGain(float gain) { qCDebug(networking) << "Sending Set Injector Gain packet with Gain:" << gain; sendPacket(std::move(setInjectorGainPacket), *audioMixer); - _injectorGain = gain; } else { qWarning() << "Couldn't find audio mixer to send set gain request"; From 020fd20169e7fce95d22d68abc67d0ebb8caa2f6 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 2 Aug 2019 09:01:08 -0700 Subject: [PATCH 13/20] Fixing caplitalizatoin --- libraries/platform/src/platform/backend/Platform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index 4bc6f3219f..c3abcce5f1 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -117,7 +117,7 @@ namespace platform { namespace keys { const char* CPUS = "cpus"; const char* GPUS = "gpus"; - const char* GRAPHICS_APIS = "graphicsAPIS"; + const char* GRAPHICS_APIS = "graphicsAPIs"; const char* DISPLAYS = "displays"; const char* NICS = "nics"; const char* MEMORY = "memory"; From d05f1ac87f38e195ce8c956a1c1a624efcd42662 Mon Sep 17 00:00:00 2001 From: amerhifi Date: Fri, 2 Aug 2019 11:23:33 -0700 Subject: [PATCH 14/20] adding ability to reload defaultOverrdie script without saving to settings: --- libraries/script-engine/src/ScriptEngines.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index da698c6e4e..96d4b79594 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -401,13 +401,14 @@ void ScriptEngines::stopAllScripts(bool restart) { continue; } + bool isOverrideScript = it.key().toString().compare(this->_defaultScriptsOverride.toString()); // queue user scripts if restarting - if (restart && scriptEngine->isUserLoaded()) { + if (restart && (scriptEngine->isUserLoaded() || isOverrideScript)) { _isReloading = true; ScriptEngine::Type type = scriptEngine->getType(); - connect(scriptEngine.data(), &ScriptEngine::finished, this, [this, type] (QString scriptName) { - reloadScript(scriptName, true)->setType(type); + connect(scriptEngine.data(), &ScriptEngine::finished, this, [this, type, isOverrideScript](QString scriptName) { + reloadScript(scriptName, !isOverrideScript)->setType(type); }); } From 0ee9de7ed823219b28afaaa64f86450076a847fe Mon Sep 17 00:00:00 2001 From: amerhifi Date: Fri, 2 Aug 2019 11:24:21 -0700 Subject: [PATCH 15/20] lambda space --- libraries/script-engine/src/ScriptEngines.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 96d4b79594..381377c9f4 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -407,7 +407,7 @@ void ScriptEngines::stopAllScripts(bool restart) { _isReloading = true; ScriptEngine::Type type = scriptEngine->getType(); - connect(scriptEngine.data(), &ScriptEngine::finished, this, [this, type, isOverrideScript](QString scriptName) { + connect(scriptEngine.data(), &ScriptEngine::finished, this, [this, type, isOverrideScript] (QString scriptName) { reloadScript(scriptName, !isOverrideScript)->setType(type); }); } From b9106b9adeedfd10a902a3817e64f3a766445f88 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Fri, 2 Aug 2019 11:26:41 -0700 Subject: [PATCH 16/20] making requested changes --- launchers/darwin/src/DownloadLauncher.m | 28 ++++++++----------- launchers/darwin/src/LatestBuildRequest.m | 20 ++++++------- .../darwin/src/LauncherCommandlineArgs.m | 3 +- launchers/darwin/src/updater/main.m | 10 +++---- 4 files changed, 26 insertions(+), 35 deletions(-) diff --git a/launchers/darwin/src/DownloadLauncher.m b/launchers/darwin/src/DownloadLauncher.m index d2538c897b..e7d293be43 100644 --- a/launchers/darwin/src/DownloadLauncher.m +++ b/launchers/darwin/src/DownloadLauncher.m @@ -4,8 +4,7 @@ @implementation DownloadLauncher -- (void) downloadLauncher:(NSString *)launcherUrl -{ +- (void) downloadLauncher:(NSString*)launcherUrl { NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:launcherUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; @@ -22,20 +21,15 @@ } --(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { - // unused in this example -} - --(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { +-(void)URLSession:(NSURLSession*)session downloadTask:(NSURLSessionDownloadTask*)downloadTask didFinishDownloadingToURL:(NSURL*)location { NSLog(@"Did finish downloading to url"); - NSError *error = nil; - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *destinationFileName = downloadTask.originalRequest.URL.lastPathComponent; + NSError* error = nil; + NSFileManager* fileManager = [NSFileManager defaultManager]; + NSString* destinationFileName = downloadTask.originalRequest.URL.lastPathComponent; NSString* finalFilePath = [[[Launcher sharedLauncher] getDownloadPathForContentAndScripts] stringByAppendingPathComponent:destinationFileName]; NSURL *destinationURL = [NSURL URLWithString: [finalFilePath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]] relativeToURL: [NSURL URLWithString:@"file://"]]; NSLog(@"desintation %@", destinationURL); - if([fileManager fileExistsAtPath:[destinationURL path]]) - { + if([fileManager fileExistsAtPath:[destinationURL path]]) { [fileManager removeItemAtURL:destinationURL error:nil]; } @@ -51,21 +45,21 @@ NSLog(@"Download Launcher: failed to move file to destintation -> error: %@", error); [sharedLauncher displayErrorPage]; return; - } - NSLog(@"extracting domain content file"); - BOOL extractionSuccessful = [sharedLauncher extractZipFileAtDestination:[sharedLauncher getDownloadPathForContentAndScripts] :[[sharedLauncher getDownloadPathForContentAndScripts] stringByAppendingString:destinationFileName]]; + } + NSLog(@"extracting Launcher file"); + BOOL extractionSuccessful = [sharedLauncher extractZipFileAtDestination:[sharedLauncher getDownloadPathForContentAndScripts] :[[sharedLauncher getDownloadPathForContentAndScripts] stringByAppendingString:@"HQ Launcher.zip"]]; if (!extractionSuccessful) { [sharedLauncher displayErrorPage]; return; } - NSLog(@"finished extracting content file"); + NSLog(@"finished extracting Launcher file"); [[Launcher sharedLauncher] runAutoupdater]; } -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { +- (void)URLSession:(NSURLSession*)session task:(NSURLSessionTask*)task didCompleteWithError:(NSError*)error { NSLog(@"completed; error: %@", error); if (error) { [[Launcher sharedLauncher] displayErrorPage]; diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index a2650a194f..a663200089 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -9,8 +9,8 @@ NSInteger currentVersion; @try { NSString* interfaceAppPath = [[Launcher.sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]; - NSError * error = nil; - Interface * interface = [[Interface alloc] initWith:interfaceAppPath]; + NSError* error = nil; + Interface* interface = [[Interface alloc] initWith:interfaceAppPath]; currentVersion = [interface getVersion:&error]; if (currentVersion == 0 && error != nil) { NSLog(@"can't get version from interface, falling back to settings: %@", error); @@ -24,17 +24,17 @@ } - (void) requestLatestBuildInfo { - NSMutableURLRequest *request = [NSMutableURLRequest new]; + NSMutableURLRequest* request = [NSMutableURLRequest new]; [request setURL:[NSURL URLWithString:@"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"]]; [request setHTTPMethod:@"GET"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; // We're using an ephermeral session here to ensure the tags api response is never cached. - NSURLSession * session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration]; + NSURLSession* session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration]; NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSLog(@"Latest Build Request error: %@", error); NSLog(@"Latest Build Request Data: %@", data); - NSHTTPURLResponse *ne = (NSHTTPURLResponse *)response; + NSHTTPURLResponse* ne = (NSHTTPURLResponse *)response; NSLog(@"Latest Build Request Response: %ld", [ne statusCode]); Launcher* sharedLauncher = [Launcher sharedLauncher]; @@ -47,9 +47,9 @@ NSMutableData* webData = [NSMutableData data]; [webData appendData:data]; NSString* jsonString = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[data length] encoding:NSUTF8StringEncoding]; - NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"Latest Build Request -> json string: %@", jsonString); - NSError *jsonError = nil; + NSError* jsonError = nil; id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError]; if (jsonError) { @@ -57,9 +57,9 @@ } NSFileManager* fileManager = [NSFileManager defaultManager]; - NSArray *values = [json valueForKey:@"results"]; - NSDictionary *launcherValues = [json valueForKey:@"launcher"]; - NSDictionary *value = [values objectAtIndex:0]; + NSArray* values = [json valueForKey:@"results"]; + NSDictionary* launcherValues = [json valueForKey:@"launcher"]; + NSDictionary* value = [values objectAtIndex:0]; NSString* launcherVersion = [launcherValues valueForKey:@"version"]; NSString* launcherUrl = [[launcherValues valueForKey:@"mac"] valueForKey:@"url"]; diff --git a/launchers/darwin/src/LauncherCommandlineArgs.m b/launchers/darwin/src/LauncherCommandlineArgs.m index 0c53da2b71..4229c91205 100644 --- a/launchers/darwin/src/LauncherCommandlineArgs.m +++ b/launchers/darwin/src/LauncherCommandlineArgs.m @@ -1,8 +1,7 @@ #import "LauncherCommandlineArgs.h" @implementation LauncherCommandlineArgs -+(NSDictionary*) arguments -{ ++(NSDictionary*) arguments { NSArray* arguments = [[NSProcessInfo processInfo] arguments]; if (arguments.count < 2) diff --git a/launchers/darwin/src/updater/main.m b/launchers/darwin/src/updater/main.m index 31b333c5d9..7c7ace6f70 100644 --- a/launchers/darwin/src/updater/main.m +++ b/launchers/darwin/src/updater/main.m @@ -12,10 +12,8 @@ } @end -int main(int argc, char const* argv[]) -{ - if (argc < 3) - { +int main(int argc, char const* argv[]) { + if (argc < 3) { NSLog(@"Error: wrong number of arguments"); return 0; } @@ -25,9 +23,9 @@ int main(int argc, char const* argv[]) } NSString* oldLauncher = [NSString stringWithUTF8String:argv[1]]; NSString* newLauncher = [NSString stringWithUTF8String:argv[2]]; + NSURL* destinationUrl = [UpdaterHelper NSStringToNSURL:newLauncher]; NSFileManager* fileManager = [NSFileManager defaultManager]; - [fileManager removeItemAtURL:[UpdaterHelper NSStringToNSURL:oldLauncher] error:nil]; - [fileManager moveItemAtURL: [UpdaterHelper NSStringToNSURL: newLauncher] toURL: [UpdaterHelper NSStringToNSURL:oldLauncher] error:nil]; + [fileManager replaceItemAtURL:[UpdaterHelper NSStringToNSURL:oldLauncher] withItemAtURL:[UpdaterHelper NSStringToNSURL:newLauncher] backupItemName:nil options:NSFileManagerItemReplacementUsingNewMetadataOnly resultingItemURL:&destinationUrl error:nil]; NSWorkspace* workspace = [NSWorkspace sharedWorkspace]; NSURL* applicationURL = [UpdaterHelper NSStringToNSURL: [oldLauncher stringByAppendingString: @"/Contents/MacOS/HQ Launcher"]]; NSArray* arguments =@[]; From ebe7581f62178a333c4ce498c22d9858ee5a3d29 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 2 Aug 2019 11:39:54 -0700 Subject: [PATCH 17/20] check for Win7 before using SHCore.dll API --- .../platform/src/platform/backend/WINPlatform.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index 8c0bb1b9aa..2958374451 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -27,7 +27,6 @@ #include #pragma comment(lib, "dxgi.lib") #include -#pragma comment(lib, "Shcore.lib") #endif @@ -118,10 +117,19 @@ void WINInstance::enumerateGpusAndDisplays() { // Grab the dpi info for the monitor UINT dpiX{ 0 }; UINT dpiY{ 0 }; - GetDpiForMonitor(outputDesc.Monitor, MDT_RAW_DPI, &dpiX, &dpiY); UINT dpiXScaled{ 0 }; UINT dpiYScaled{ 0 }; - GetDpiForMonitor(outputDesc.Monitor, MDT_EFFECTIVE_DPI, &dpiXScaled, &dpiYScaled); + + // SHCore.dll is not available prior to Windows 8.1 + HMODULE SHCoreDLL = LoadLibraryW(L"SHCore.dll"); + if (SHCoreDLL) { + auto _GetDpiForMonitor = reinterpret_cast(GetProcAddress(SHCoreDLL, "GetDpiForMonitor")); + if (_GetDpiForMonitor) { + _GetDpiForMonitor(outputDesc.Monitor, MDT_RAW_DPI, &dpiX, &dpiY); + _GetDpiForMonitor(outputDesc.Monitor, MDT_EFFECTIVE_DPI, &dpiXScaled, &dpiYScaled); + } + FreeLibrary(SHCoreDLL); + } // Current display mode DEVMODEW devMode; From a37ef7d80ea1f22e4cb7f01e7a883040b631747a Mon Sep 17 00:00:00 2001 From: amerhifi Date: Fri, 2 Aug 2019 13:00:43 -0700 Subject: [PATCH 18/20] adding default script location setting for defaultscriptoverride runs. Prevents the second interface run to have no ui --- libraries/script-engine/src/ScriptEngines.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 381377c9f4..69455294d6 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -352,6 +352,7 @@ void ScriptEngines::saveScripts() { // the scripts that the user expects to be there when launched without the // --scripts override. if (_defaultScriptsLocationOverridden) { + runningScriptsHandle.set(QVariantList{ DEFAULT_SCRIPTS_LOCATION }); return; } From 34bc71fba95b8ebaa51c896ab80930717d33f1fc Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 5 Aug 2019 15:12:29 -0400 Subject: [PATCH 19/20] Fix BUGZ-1131: Add Shield icon back to HUD for Metaverse users --- interface/src/ui/AvatarInputs.cpp | 1 + interface/src/ui/AvatarInputs.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/AvatarInputs.cpp b/interface/src/ui/AvatarInputs.cpp index b9a1fc441f..a6bc7cf84f 100644 --- a/interface/src/ui/AvatarInputs.cpp +++ b/interface/src/ui/AvatarInputs.cpp @@ -32,6 +32,7 @@ AvatarInputs* AvatarInputs::getInstance() { AvatarInputs::AvatarInputs(QObject* parent) : QObject(parent) { _showAudioTools = showAudioToolsSetting.get(); + _showBubbleTools = showBubbleToolsSetting.get(); auto nodeList = DependencyManager::get(); auto usersScriptingInterface = DependencyManager::get(); connect(nodeList.data(), &NodeList::ignoreRadiusEnabledChanged, this, &AvatarInputs::ignoreRadiusEnabledChanged); diff --git a/interface/src/ui/AvatarInputs.h b/interface/src/ui/AvatarInputs.h index 9e7d231dd2..dca39fd433 100644 --- a/interface/src/ui/AvatarInputs.h +++ b/interface/src/ui/AvatarInputs.h @@ -194,8 +194,8 @@ private: void onAvatarEnteredIgnoreRadius(); void onAvatarLeftIgnoreRadius(); float _trailingAudioLoudness{ 0 }; - bool _showAudioTools { false }; - bool _showBubbleTools{ false }; + bool _showAudioTools { true }; + bool _showBubbleTools{ true }; }; #endif // hifi_AvatarInputs_h From 86adc6099b4ed8b6791666fe16be96d7d8f7123a Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 5 Aug 2019 12:14:45 -0700 Subject: [PATCH 20/20] Attempt audio device format with native sample rate and channels forced to 2/1 before failing --- libraries/audio-client/src/AudioClient.cpp | 27 +++++++++++++++------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index c16e297c28..09b8b495f3 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -597,11 +597,17 @@ bool AudioClient::getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QStr // attempt to use the native sample rate and channel count -bool nativeFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, - QAudioFormat& audioFormat) { +bool nativeFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, QAudioFormat& audioFormat) { audioFormat = audioDevice.preferredFormat(); + // converting to/from this rate must produce an integral number of samples + if ((audioFormat.sampleRate() <= 0) || + (audioFormat.sampleRate() * AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL % AudioConstants::SAMPLE_RATE != 0)) { + qCWarning(audioclient) << "The native sample rate [" << audioFormat.sampleRate() << "] is not supported."; + return false; + } + audioFormat.setCodec("audio/pcm"); audioFormat.setSampleSize(16); audioFormat.setSampleType(QAudioFormat::SignedInt); @@ -609,12 +615,17 @@ bool nativeFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, if (!audioDevice.isFormatSupported(audioFormat)) { qCWarning(audioclient) << "The native format is" << audioFormat << "but isFormatSupported() failed."; - return false; - } - // converting to/from this rate must produce an integral number of samples - if (audioFormat.sampleRate() * AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL % AudioConstants::SAMPLE_RATE != 0) { - qCWarning(audioclient) << "The native sample rate [" << audioFormat.sampleRate() << "] is not supported."; - return false; + + // attempt the native sample rate, with channels forced to 2 + audioFormat.setChannelCount(2); + if (!audioDevice.isFormatSupported(audioFormat)) { + + // attempt the native sample rate, with channels forced to 1 + audioFormat.setChannelCount(1); + if (!audioDevice.isFormatSupported(audioFormat)) { + return false; + } + } } return true; }