From 2ef1c6458abf8f56b0da4a3c07d6bc33fbf7a221 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 15 Aug 2019 14:53:30 -0700 Subject: [PATCH 01/21] Fix joint indexing when duplicated joint on skeleton --- .../src/model-baker/PrepareJointsTask.cpp | 55 +++++++------------ 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp b/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp index 6bf25ff769..bf3aea4c92 100644 --- a/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp +++ b/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp @@ -71,14 +71,7 @@ void PrepareJointsTask::run(const baker::BakeContextPointer& context, const Inpu auto& jointRotationOffsets = output.edit1(); auto& jointIndices = output.edit2(); - bool newJointRot = false; - static const QString JOINT_ROTATION_OFFSET2_FIELD = "jointRotationOffset2"; QVariantHash fstHashMap = mapping; - if (fstHashMap.contains(JOINT_ROTATION_OFFSET2_FIELD)) { - newJointRot = true; - } else { - newJointRot = false; - } // Get joint renames auto jointNameMapping = getJointNameMapping(mapping); @@ -87,11 +80,27 @@ void PrepareJointsTask::run(const baker::BakeContextPointer& context, const Inpu jointsOut.push_back(jointIn); auto& jointOut = jointsOut.back(); - if (!newJointRot) { - auto jointNameMapKey = jointNameMapping.key(jointIn.name); - if (jointNameMapping.contains(jointNameMapKey)) { - jointOut.name = jointNameMapKey; - } + auto jointNameMapKey = jointNameMapping.key(jointIn.name); + if (jointNameMapping.contains(jointNameMapKey)) { + jointOut.name = jointNameMapKey; + } + + // Make sure that joint name is unique + if (jointIndices.contains(jointOut.name)) { + // The joint name is duplicated. Most likely a mesh joint. + auto duplicatedJointData = jointIndices.find(jointOut.name); + int duplicatedJointIndex = duplicatedJointData.value(); + auto& duplicatedJoint = jointsOut[duplicatedJointIndex]; + QString existJointName = jointOut.name; + qCDebug(model_baker) << "Joint already exist. Renaming joint: " << existJointName; + // One of the joints could be a mesh joint. Locate it and change its name. + if (!jointOut.isSkeletonJoint) { + jointOut.name = existJointName + "_mesh"; + } else { + duplicatedJoint.name = existJointName + "_mesh"; + jointIndices.remove(jointOut.name); + jointIndices.insert(duplicatedJoint.name, duplicatedJointIndex); + } } jointIndices.insert(jointOut.name, (int)jointsOut.size()); } @@ -107,27 +116,5 @@ void PrepareJointsTask::run(const baker::BakeContextPointer& context, const Inpu qCDebug(model_baker) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; } } - - if (newJointRot) { - for (auto& jointOut : jointsOut) { - auto jointNameMapKey = jointNameMapping.key(jointOut.name); - int mappedIndex = jointIndices.value(jointOut.name); - if (jointNameMapping.contains(jointNameMapKey)) { - // delete and replace with hifi name - jointIndices.remove(jointOut.name); - jointOut.name = jointNameMapKey; - jointIndices.insert(jointOut.name, mappedIndex); - } else { - // nothing mapped to this fbx joint name - if (jointNameMapping.contains(jointOut.name)) { - // but the name is in the list of hifi names is mapped to a different joint - int extraIndex = jointIndices.value(jointOut.name); - jointIndices.remove(jointOut.name); - jointOut.name = ""; - jointIndices.insert(jointOut.name, extraIndex); - } - } - } - } } } From 260ee5958597bf8ac7563a8b644c1f91aad6b14a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 15 Aug 2019 16:57:17 -0700 Subject: [PATCH 02/21] Make sure joint names are unique --- .../src/model-baker/PrepareJointsTask.cpp | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp b/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp index bf3aea4c92..a62294d2f6 100644 --- a/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp +++ b/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp @@ -64,6 +64,9 @@ void PrepareJointsTask::run(const baker::BakeContextPointer& context, const Inpu const auto& jointsIn = input.get0(); auto& jointsOut = output.edit0(); + const QString APPEND_DUPLICATE_JOINT = "_joint"; + const QString APPEND_DUPLICATE_MESH = "_mesh"; + if (_passthrough) { jointsOut = jointsIn; } else { @@ -87,17 +90,29 @@ void PrepareJointsTask::run(const baker::BakeContextPointer& context, const Inpu // Make sure that joint name is unique if (jointIndices.contains(jointOut.name)) { - // The joint name is duplicated. Most likely a mesh joint. - auto duplicatedJointData = jointIndices.find(jointOut.name); - int duplicatedJointIndex = duplicatedJointData.value(); + int duplicatedJointIndex = jointIndices.find(jointOut.name).value(); auto& duplicatedJoint = jointsOut[duplicatedJointIndex]; + bool areBothJoints = jointOut.isSkeletonJoint && duplicatedJoint.isSkeletonJoint; QString existJointName = jointOut.name; - qCDebug(model_baker) << "Joint already exist. Renaming joint: " << existJointName; - // One of the joints could be a mesh joint. Locate it and change its name. - if (!jointOut.isSkeletonJoint) { - jointOut.name = existJointName + "_mesh"; + QString appendName; + if (areBothJoints) { + appendName = APPEND_DUPLICATE_JOINT; + qCWarning(model_baker) << "Duplicated skeleton joints found: " << existJointName; } else { - duplicatedJoint.name = existJointName + "_mesh"; + appendName = APPEND_DUPLICATE_MESH; + qCDebug(model_baker) << "Duplicated joints found. Renaming the mesh joint: " << existJointName; + } + QString newName = existJointName + appendName; + // Make sure the new name is unique + int duplicateIndex = 0; + while (jointIndices.contains(newName)) { + newName = existJointName + appendName + QString::number(++duplicateIndex); + } + // Find and rename the mesh joint + if (!jointOut.isSkeletonJoint) { + jointOut.name = newName; + } else { + duplicatedJoint.name = newName; jointIndices.remove(jointOut.name); jointIndices.insert(duplicatedJoint.name, duplicatedJointIndex); } From 1e65908e439c66655fd2515becb4d0b11fd601ea Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 8 Aug 2019 16:25:52 -0700 Subject: [PATCH 03/21] Add build tags to Mac launcher --- launchers/darwin/src/LatestBuildRequest.m | 41 +------ launchers/darwin/src/Launcher.h | 11 +- launchers/darwin/src/Launcher.m | 121 ++++++++++++++++----- launchers/darwin/src/OrganizationRequest.m | 6 + launchers/darwin/src/Settings.h | 3 + launchers/darwin/src/Settings.m | 21 +++- 6 files changed, 132 insertions(+), 71 deletions(-) diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index a663200089..bd59341644 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -1,28 +1,9 @@ #import "LatestBuildRequest.h" #import "Launcher.h" #import "Settings.h" -#import "Interface.h" @implementation LatestBuildRequest -- (NSInteger) getCurrentVersion { - NSInteger currentVersion; - @try { - NSString* interfaceAppPath = [[Launcher.sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]; - 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); - currentVersion = [Settings.sharedSettings latestBuildVersion]; - } - } @catch (NSException *exception) { - NSLog(@"an exception was thrown: %@", exception); - currentVersion = [Settings.sharedSettings latestBuildVersion]; - } - return currentVersion; -} - - (void) requestLatestBuildInfo { NSMutableURLRequest* request = [NSMutableURLRequest new]; [request setURL:[NSURL URLWithString:@"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"]]; @@ -59,36 +40,26 @@ NSFileManager* fileManager = [NSFileManager defaultManager]; NSArray* values = [json valueForKey:@"results"]; NSDictionary* launcherValues = [json valueForKey:@"launcher"]; - NSDictionary* value = [values objectAtIndex:0]; + + NSString* defaultBuildTag = [json valueForKey:@"default_tag"]; 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"]; - NSString* macInstallerUrl = [macInstallerObject valueForKey:@"zip_url"]; BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]]; 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 - :latestLauncherVersionAvailable :launcherUrl]; + [sharedLauncher shouldDownloadLatestBuild:values + :defaultBuildTag + :latestLauncherVersionAvailable + :launcherUrl]; }); }]; diff --git a/launchers/darwin/src/Launcher.h b/launchers/darwin/src/Launcher.h index d20f58dee7..b6f89fac49 100644 --- a/launchers/darwin/src/Launcher.h +++ b/launchers/darwin/src/Launcher.h @@ -55,6 +55,8 @@ struct LatestBuildInfo { @property (nonatomic) BOOL waitingForInterfaceToTerminate; @property (nonatomic) BOOL shouldDownloadInterface; @property (nonatomic) BOOL latestBuildRequestFinished; +@property (nonatomic, assign) NSArray* latestBuilds; +@property (nonatomic, assign) NSString* defaultBuildTag; @property (nonatomic, assign) NSTimer* updateProgressIndicatorTimer; @property (nonatomic, assign, readwrite) ProcessState processState; @property (nonatomic, assign, readwrite) LoginError loginError; @@ -70,6 +72,7 @@ struct LatestBuildInfo { - (void) domainContentDownloadFinished; - (void) domainScriptsDownloadFinished; - (void) setDomainURLInfo:(NSString*) aDomainURL :(NSString*) aDomainContentUrl :(NSString*) aDomainScriptsUrl; +- (void) setOrganizationBuildTag:(NSString*) organizationBuildTag; - (void) organizationRequestFinished:(BOOL) aOriginzationAccepted; - (BOOL) loginShouldSetErrorState; - (void) displayErrorPage; @@ -81,7 +84,9 @@ struct LatestBuildInfo { - (void) setCurrentProcessState:(ProcessState) aProcessState; - (void) setLoginErrorState:(LoginError) aLoginError; - (LoginError) getLoginErrorState; -- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl :(BOOL) newLauncherAvailable :(NSString*) launcherUrl; +- (void) updateLatestBuildInfo; +- (void) shouldDownloadLatestBuild:(NSArray*) latestBuilds :(NSString*) defaultBuildTag :(BOOL) newLauncherAvailable :(NSString*) launcherUrl; +- (void) tryDownloadLatestBuild:(BOOL)progressScreenAlreadyDisplayed; - (void) interfaceFinishedDownloading; - (NSString*) getDownloadPathForContentAndScripts; - (void) launchInterface; @@ -97,11 +102,9 @@ struct LatestBuildInfo { - (NSString*) getDownloadFilename; - (void) startUpdateProgressIndicatorTimer; - (void) endUpdateProgressIndicatorTimer; -- (BOOL) isLoadedIn; +- (BOOL) isLoggedIn; - (NSString*) getAppPath; - (void) updateProgressIndicator; -- (void) setLatestBuildInfo:(struct LatestBuildInfo) latestBuildInfo; -- (struct LatestBuildInfo) getLatestBuildInfo; + (id) sharedLauncher; @end diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index 8fb501db55..111359370e 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -8,6 +8,7 @@ #import "ErrorViewController.h" #import "Settings.h" #import "NSTask+NSTaskExecveAdditions.h" +#import "Interface.h" @interface Launcher () @@ -241,7 +242,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; return self.waitingForInterfaceToTerminate; } -- (BOOL) isLoadedIn +- (BOOL) isLoggedIn { return [[Settings sharedSettings] isLoggedIn]; } @@ -255,6 +256,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE; [[Settings sharedSettings] setDomainUrl:aDomainURL]; } +- (void) setOrganizationBuildTag:(NSString*) organizationBuildTag; +{ + [[Settings sharedSettings] setOrganizationBuildTag:organizationBuildTag]; +} + - (NSString*) getAppPath { return [self getDownloadPathForContentAndScripts]; @@ -275,13 +281,27 @@ static BOOL const DELETE_ZIP_FILES = TRUE; self.displayName = aDiplayName; } +- (NSInteger) getCurrentVersion { + NSInteger currentVersion; + @try { + NSString* interfaceAppPath = [[self getAppPath] stringByAppendingString:@"interface.app"]; + 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); + currentVersion = [Settings.sharedSettings latestBuildVersion]; + } + } @catch (NSException *exception) { + NSLog(@"an exception was thrown: %@", exception); + currentVersion = [Settings.sharedSettings latestBuildVersion]; + } + return currentVersion; +} + - (void) domainContentDownloadFinished { - if (self.shouldDownloadInterface) { - [self.downloadInterface downloadInterface: self.interfaceDownloadUrl]; - return; - } - [self interfaceFinishedDownloading]; + [self tryDownloadLatestBuild:TRUE]; } - (void) domainScriptsDownloadFinished @@ -337,6 +357,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; { self.credentialsAccepted = aOriginzationAccepted; if (aOriginzationAccepted) { + [self updateLatestBuildInfo]; [self.credentialsRequest confirmCredentials:self.username : self.password]; } else { LoginScreen* loginScreen = [[LoginScreen alloc] initWithNibName:@"LoginScreen" bundle:nil]; @@ -349,42 +370,26 @@ static BOOL const DELETE_ZIP_FILES = TRUE; return YES; } -- (struct LatestBuildInfo) getLatestBuildInfo -{ - return self.buildInfo; -} - -- (void) setLatestBuildInfo:(struct LatestBuildInfo) latestBuildInfo -{ - self.buildInfo = latestBuildInfo; -} - -(void) showLoginScreen { LoginScreen* loginScreen = [[LoginScreen alloc] initWithNibName:@"LoginScreen" bundle:nil]; [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: loginScreen]; } -- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl :(BOOL) newLauncherAvailable :(NSString*) launcherUrl +- (void) shouldDownloadLatestBuild:(NSArray*) latestBuilds :(NSString*) defaultBuildTag :(BOOL) newLauncherAvailable :(NSString*) launcherUrl { + self.latestBuilds = [[NSArray alloc] initWithArray:latestBuilds copyItems:true]; + self.defaultBuildTag = defaultBuildTag; + + [self updateLatestBuildInfo]; + NSDictionary* launcherArguments = [LauncherCommandlineArgs arguments]; if (newLauncherAvailable && ![launcherArguments valueForKey: @"--noUpdate"]) { [self.downloadLauncher downloadLauncher: launcherUrl]; } else { - 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]; + if ([self isLoggedIn]) { + [self tryDownloadLatestBuild:FALSE]; } else { [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; [self showLoginScreen]; @@ -392,6 +397,62 @@ static BOOL const DELETE_ZIP_FILES = TRUE; } } +// The latest builds are always retrieved on application start because they contain not only +// the latest interface builds, but also the latest launcher builds, which are required to know if +// we need to self-update first. The interface builds are categorized by build tag, and we may +// not know at application start which build tag we should be using. There are 2 scenarios where +// we call this function to determine our build tag and the correct build: +// +// 1. If we are logged in, we will have our build tag and can immediately get the correct build +// after receiving the builds. +// 2. If we are not logged in, we need to wait until we have logged in and received the org +// metadata for the user. The latest build info also needs to be updated _before_ downloading +// the content set cache because the progress bar value depends on it. +// +- (void) updateLatestBuildInfo { + NSLog(@"Updating latest build info"); + + NSInteger currentVersion = [self getCurrentVersion]; + Launcher* sharedLauncher = [Launcher sharedLauncher]; + [sharedLauncher setCurrentProcessState:CHECKING_UPDATE]; + BOOL newVersionAvailable = false; + NSString* url = @""; + NSString* buildTag = [[Settings sharedSettings] organizationBuildTag]; + if ([buildTag length] == 0) { + buildTag = self.defaultBuildTag; + } + + for (NSDictionary* build in self.latestBuilds) { + NSString* name = [build valueForKey:@"name"]; + if ([name isEqual:buildTag]) { + url = [[[build objectForKey:@"installers"] objectForKey:@"mac"] valueForKey:@"zip_url"]; + NSString* latestVersion = [build valueForKey:@"latest_version"]; + newVersionAvailable = currentVersion != latestVersion.integerValue; + break; + } + } + + self.shouldDownloadInterface = newVersionAvailable; + self.interfaceDownloadUrl = url; + + NSLog(@"Updating latest build info %@ %@", (self.shouldDownloadInterface ? @"Yes" : @"No"), self.interfaceDownloadUrl); +} + +- (void) tryDownloadLatestBuild:(BOOL)progressScreenAlreadyDisplayed +{ + if (self.shouldDownloadInterface) { + if (!progressScreenAlreadyDisplayed) { + ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil]; + [[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen]; + [self startUpdateProgressIndicatorTimer]; + } + [self.downloadInterface downloadInterface: self.interfaceDownloadUrl]; + return; + } + + [self interfaceFinishedDownloading]; +} + -(void)runAutoupdater { NSTask* task = [[NSTask alloc] init]; diff --git a/launchers/darwin/src/OrganizationRequest.m b/launchers/darwin/src/OrganizationRequest.m index 1aaed2ce51..d8db0d19c3 100644 --- a/launchers/darwin/src/OrganizationRequest.m +++ b/launchers/darwin/src/OrganizationRequest.m @@ -2,6 +2,7 @@ #include #include #import "Launcher.h" +#import "Settings.h" static NSString* const organizationURL = @"https://orgs.highfidelity.com/organizations/"; @@ -75,11 +76,16 @@ static NSString* const organizationURL = @"https://orgs.highfidelity.com/organiz } NSString* domainURL = [json valueForKey:@"domain"]; NSString* contentSetURL = [json valueForKey:@"content_set_url"]; + NSString* buildTag = [json valueForKey:@"build_tag"]; + if (buildTag == nil) { + buildTag = @""; + } if (domainURL != nil && contentSetURL != nil) { NSLog(@"Organization: getting org file successful"); [sharedLauncher setDomainURLInfo:[json valueForKey:@"domain"] :[json valueForKey:@"content_set_url"] :nil]; [sharedLauncher setLoginErrorState: NONE]; + [[Settings sharedSettings] setOrganizationBuildTag:buildTag]; [sharedLauncher organizationRequestFinished:TRUE]; } else { NSLog(@"Organization: Either domainURL: %@ or contentSetURL: %@ json entries are invalid", domainURL, contentSetURL); diff --git a/launchers/darwin/src/Settings.h b/launchers/darwin/src/Settings.h index 6a036ca1b1..57225f6f52 100644 --- a/launchers/darwin/src/Settings.h +++ b/launchers/darwin/src/Settings.h @@ -7,6 +7,7 @@ @property (nonatomic, assign) BOOL loggedIn; @property (nonatomic, assign) NSString* domain; @property (nonatomic, assign) NSString* launcher; +@property (nonatomic, assign) NSString* _organizationBuildTag; - (NSInteger) latestBuildVersion; - (BOOL) isLoggedIn; - (void) login:(BOOL)aLoggedIn; @@ -15,6 +16,8 @@ - (NSString*) getLaucnherPath; - (void) setDomainUrl:(NSString*) aDomainUrl; - (NSString*) getDomainUrl; +- (void) setOrganizationBuildTag:(NSString*) aOrganizationBuildTag; +- (NSString*) organizationBuildTag; - (void) save; + (id) sharedSettings; @end diff --git a/launchers/darwin/src/Settings.m b/launchers/darwin/src/Settings.m index 407f869af9..cb9abe18b8 100644 --- a/launchers/darwin/src/Settings.m +++ b/launchers/darwin/src/Settings.m @@ -32,13 +32,18 @@ NSError * err; NSData *data =[jsonString dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary * json; - if(data!=nil){ + if (data != nil) { json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&err]; self.loggedIn = [[json valueForKey:@"loggedIn"] boolValue]; self.build = [[json valueForKey:@"build_version"] integerValue]; self.launcher = [json valueForKey:@"luancherPath"]; self.domain = [json valueForKey:@"domain"]; + self.organizationBuildTag = [json valueForKey:@"organizationBuildTag"]; + if ([self.organizationBuildTag length] == 0) { + self.organizationBuildTag = @""; + } + return; } } @@ -53,7 +58,9 @@ [NSString stringWithFormat:@"%ld", self.build], @"build_version", self.loggedIn ? @"TRUE" : @"FALSE", @"loggedIn", self.domain, @"domain", - self.launcher, @"launcherPath", nil]; + self.launcher, @"launcherPath", + self.organizationBuildTag, @"organizationBuildTag", + nil]; NSError * err; NSData * jsonData = [NSJSONSerialization dataWithJSONObject:json options:0 error:&err]; NSString * jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; @@ -114,6 +121,16 @@ return self.domain; } +- (void) setOrganizationBuildTag:(NSString*) aOrganizationBuildTag +{ + self._organizationBuildTag = aOrganizationBuildTag; +} + +- (NSString*) organizationBuildTag +{ + return self._organizationBuildTag; +} + - (NSString*) getLaucnherPath { return self.launcher; From 322ba3ad557b4802f84ba3b4d669d7447325e568 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 15 Aug 2019 16:19:23 -0700 Subject: [PATCH 04/21] Add env variable to adjust builds URL in mac launcher --- launchers/darwin/src/LatestBuildRequest.m | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index bd59341644..4d858d8be6 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -5,8 +5,16 @@ @implementation LatestBuildRequest - (void) requestLatestBuildInfo { + NSString* buildsURL = [[[NSProcessInfo processInfo] environment] objectForKey:@"HQ_LAUNCHER_BUILDS_URL"]; + + if ([buildsURL length] == 0) { + buildsURL = @"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"; + } + + NSLog(@"Making request for builds to: %@", buildsURL); + NSMutableURLRequest* request = [NSMutableURLRequest new]; - [request setURL:[NSURL URLWithString:@"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"]]; + [request setURL:[NSURL URLWithString:buildsURL]]; [request setHTTPMethod:@"GET"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; From 8642f2aaf83486a4d95e6ba12b83c9746de3db56 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 15 Aug 2019 16:20:18 -0700 Subject: [PATCH 05/21] Fix mac launcher not handling networking failures when requesting builds --- launchers/darwin/src/LatestBuildRequest.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index 4d858d8be6..6fde16689c 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -27,7 +27,7 @@ NSLog(@"Latest Build Request Response: %ld", [ne statusCode]); Launcher* sharedLauncher = [Launcher sharedLauncher]; - if ([ne statusCode] == 500) { + if (error || [ne statusCode] == 500) { dispatch_async(dispatch_get_main_queue(), ^{ [sharedLauncher displayErrorPage]; }); From 5ae6a323aceb6d6f6e9b216ca137e0a398112edc Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 19 Aug 2019 09:58:22 -0700 Subject: [PATCH 06/21] Cleanup macos launcher download spam --- launchers/darwin/src/DownloadInterface.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/launchers/darwin/src/DownloadInterface.m b/launchers/darwin/src/DownloadInterface.m index f0bdb645da..234d807d9f 100644 --- a/launchers/darwin/src/DownloadInterface.m +++ b/launchers/darwin/src/DownloadInterface.m @@ -21,7 +21,10 @@ -(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(@"interface downloaded %d%%", (int)(100.0*prog)); + + if ((int)(100.0 * prog) != (int)self.progressPercentage) { + NSLog(@"interface downloaded %d%%", (int)(100.0*prog)); + } self.progressPercentage = (100.0 * prog); [[Launcher sharedLauncher] updateProgressIndicator]; From 5916fb42ac0cd3161dd50d2224c2464fd5585a15 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 19 Aug 2019 09:59:16 -0700 Subject: [PATCH 07/21] Fix mac launcher not correctly reading interface version The logic to convert the interface output assumed that the output would be null terminated, but it was not. --- launchers/darwin/src/Interface.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/launchers/darwin/src/Interface.m b/launchers/darwin/src/Interface.m index d02b66b581..8dc5d00806 100644 --- a/launchers/darwin/src/Interface.m +++ b/launchers/darwin/src/Interface.m @@ -33,10 +33,11 @@ return 0; } - NSFileHandle * fh = [standardOut fileHandleForReading]; - NSData * data = [fh readDataToEndOfFile]; - NSString * output = [NSString stringWithUTF8String:[data bytes]]; - if (output == nil) { + NSFileHandle* fh = [standardOut fileHandleForReading]; + NSData* data = [fh readDataToEndOfFile]; + + NSString* output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (output == nil || [output length] == 0) { NSDictionary * userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@"Couldn't start interface", nil) }; From 73c120b15464b800ee49d1cf0f7deca63b1e6950 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 19 Aug 2019 10:00:29 -0700 Subject: [PATCH 08/21] Add mac launcher logging around latest build --- launchers/darwin/src/Launcher.m | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index 111359370e..f88005f733 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -413,6 +413,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE; NSLog(@"Updating latest build info"); NSInteger currentVersion = [self getCurrentVersion]; + NSInteger latestVersion = 0; Launcher* sharedLauncher = [Launcher sharedLauncher]; [sharedLauncher setCurrentProcessState:CHECKING_UPDATE]; BOOL newVersionAvailable = false; @@ -424,10 +425,13 @@ static BOOL const DELETE_ZIP_FILES = TRUE; for (NSDictionary* build in self.latestBuilds) { NSString* name = [build valueForKey:@"name"]; + NSLog(@"Checking %@", name); if ([name isEqual:buildTag]) { url = [[[build objectForKey:@"installers"] objectForKey:@"mac"] valueForKey:@"zip_url"]; - NSString* latestVersion = [build valueForKey:@"latest_version"]; - newVersionAvailable = currentVersion != latestVersion.integerValue; + NSString* thisLatestVersion = [build valueForKey:@"latest_version"]; + latestVersion = thisLatestVersion.integerValue; + newVersionAvailable = currentVersion != latestVersion; + NSLog(@"Using %@, %ld", name, latestVersion); break; } } @@ -435,7 +439,8 @@ static BOOL const DELETE_ZIP_FILES = TRUE; self.shouldDownloadInterface = newVersionAvailable; self.interfaceDownloadUrl = url; - NSLog(@"Updating latest build info %@ %@", (self.shouldDownloadInterface ? @"Yes" : @"No"), self.interfaceDownloadUrl); + NSLog(@"Updating latest build info, currentVersion=%ld, latestVersion=%ld, %@ %@", + currentVersion, latestVersion, (self.shouldDownloadInterface ? @"Yes" : @"No"), self.interfaceDownloadUrl); } - (void) tryDownloadLatestBuild:(BOOL)progressScreenAlreadyDisplayed From 81eaf157a69c7e18e991c2b220869455d76214ea Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 19 Aug 2019 17:06:46 -0700 Subject: [PATCH 09/21] tighter bounding box when rendering PolyLines --- .../src/RenderableEntityItem.h | 4 +-- .../src/RenderablePolyLineEntityItem.cpp | 14 ++++++++ .../src/RenderablePolyLineEntityItem.h | 2 ++ libraries/entities/src/PolyLineEntityItem.cpp | 35 ++++++++++++++++--- libraries/entities/src/PolyLineEntityItem.h | 8 +++-- 5 files changed, 53 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index c860b849b8..2697d30de4 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -101,7 +101,7 @@ protected: virtual void doRender(RenderArgs* args) = 0; virtual bool isFading() const { return _isFading; } - void updateModelTransformAndBound(); + virtual void updateModelTransformAndBound(); virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; } inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; } @@ -124,7 +124,6 @@ signals: protected: template std::shared_ptr asTypedEntity() { return std::static_pointer_cast(_entity); } - static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters); const Transform& getModelTransform() const; @@ -153,7 +152,6 @@ protected: quint64 _created; -private: // The base class relies on comparing the model transform to the entity transform in order // to trigger an update, so the member must not be visible to derived classes as a modifiable // transform diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 9d2ce6fa28..45e718e1d5 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -41,6 +41,20 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity) } } +void PolyLineEntityRenderer::updateModelTransformAndBound() { + bool success = false; + auto newModelTransform = _entity->getTransformToCenter(success); + if (success) { + _modelTransform = newModelTransform; + + auto lineEntity = std::static_pointer_cast(_entity); + AABox bound; + lineEntity->computeTightLocalBoundingBox(bound); + bound.transform(newModelTransform); + _bound = bound; + } +} + void PolyLineEntityRenderer::buildPipelines() { // FIXME: opaque pipelines diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 9139c260ea..97a45cef19 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -25,6 +25,8 @@ class PolyLineEntityRenderer : public TypedEntityRenderer { public: PolyLineEntityRenderer(const EntityItemPointer& entity); + void updateModelTransformAndBound() override; + // FIXME: shouldn't always be transparent: take into account texture and glow virtual bool isTransparent() const override { return true; } diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 645d2b39f8..fe14ba6925 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -14,6 +14,7 @@ #include #include +#include #include "EntitiesLogging.h" #include "EntityItemProperties.h" @@ -85,7 +86,7 @@ void PolyLineEntityItem::setLinePoints(const QVector& points) { _points = points; _pointsChanged = true; }); - computeAndUpdateDimensionsAndPosition(); + computeAndUpdateDimensions(); } void PolyLineEntityItem::setStrokeWidths(const QVector& strokeWidths) { @@ -93,7 +94,7 @@ void PolyLineEntityItem::setStrokeWidths(const QVector& strokeWidths) { _widths = strokeWidths; _widthsChanged = true; }); - computeAndUpdateDimensionsAndPosition(); + computeAndUpdateDimensions(); } void PolyLineEntityItem::setNormals(const QVector& normals) { @@ -110,7 +111,7 @@ void PolyLineEntityItem::setStrokeColors(const QVector& strokeColors) }); } -void PolyLineEntityItem::computeAndUpdateDimensionsAndPosition() { +void PolyLineEntityItem::computeAndUpdateDimensions() { QVector points; QVector widths; @@ -129,6 +130,32 @@ void PolyLineEntityItem::computeAndUpdateDimensionsAndPosition() { setScaledDimensions(2.0f * (maxHalfDim + maxWidth)); } +void PolyLineEntityItem::computeTightLocalBoundingBox(AABox& localBox) const { + QVector points; + QVector widths; + withReadLock([&] { + points = _points; + widths = _widths; + }); + + if (points.size() > 0) { + Extents extents; + float maxWidth = DEFAULT_LINE_WIDTH; + for (int i = 0; i < points.length(); i++) { + extents.addPoint(points[i]); + if (i < widths.size()) { + maxWidth = glm::max(maxWidth, widths[i]); + } + } + extents.addPoint(extents.minimum - maxWidth * Vectors::ONE); + extents.addPoint(extents.maximum + maxWidth * Vectors::ONE); + + localBox.setBox(extents.minimum, extents.maximum - extents.minimum); + } else { + localBox.setBox(glm::vec3(-0.5f * DEFAULT_LINE_WIDTH), glm::vec3(DEFAULT_LINE_WIDTH)); + } +} + int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, @@ -267,4 +294,4 @@ void PolyLineEntityItem::setFaceCamera(bool faceCamera) { _needsRenderUpdate = _faceCamera != faceCamera; _faceCamera = faceCamera; }); -} \ No newline at end of file +} diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index fc3b085cf1..e68666d75e 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -15,7 +15,7 @@ #include "EntityItem.h" class PolyLineEntityItem : public EntityItem { - public: +public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); PolyLineEntityItem(const EntityItemID& entityItemID); @@ -90,10 +90,12 @@ class PolyLineEntityItem : public EntityItem { BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } + void computeTightLocalBoundingBox(AABox& box) const; + virtual void debugDump() const override; private: - void computeAndUpdateDimensionsAndPosition(); - + void computeAndUpdateDimensions(); + protected: glm::u8vec3 _color; QVector _points; From 8957cc5b2be372aeb6327ba2716490280c768ee4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 22 Aug 2019 08:12:25 -0700 Subject: [PATCH 10/21] render opaque PolyLines with opaque pipepline --- .../src/RenderablePolyLineEntityItem.cpp | 41 +++++++++++++++---- .../src/RenderablePolyLineEntityItem.h | 3 +- .../src/entities-renderer/paintStroke.slp | 2 +- .../entities-renderer/src/paintStroke.slf | 6 ++- .../render-utils/src/DeferredBufferWrite.slh | 3 +- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 45e718e1d5..9a762b3b3a 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -55,23 +55,41 @@ void PolyLineEntityRenderer::updateModelTransformAndBound() { } } -void PolyLineEntityRenderer::buildPipelines() { - // FIXME: opaque pipelines +bool PolyLineEntityRenderer::isTransparent() const { + return _glow || (_textureLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()); +} +void PolyLineEntityRenderer::buildPipelines() { static const std::vector> keys = { { render::Args::DEFERRED, false }, { render::Args::DEFERRED, true }, { render::Args::FORWARD, false }, { render::Args::FORWARD, true }, }; for (auto& key : keys) { - gpu::ShaderPointer program = gpu::Shader::createProgram(key.first == render::Args::DEFERRED ? shader::entities_renderer::program::paintStroke : shader::entities_renderer::program::paintStroke_forward); + gpu::ShaderPointer program; + render::Args::RenderMethod renderMethod = key.first; + bool transparent = key.second; + + if (renderMethod == render::Args::DEFERRED) { + if (transparent) { + program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke_translucent); + } else { + program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke); + } + } else { // render::Args::FORWARD + program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke_forward); + } gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setCullMode(gpu::State::CullMode::CULL_NONE); - state->setDepthTest(true, !key.second, gpu::LESS_EQUAL); - PrepareStencil::testMask(*state); + state->setDepthTest(true, !transparent, gpu::LESS_EQUAL); + if (transparent) { + PrepareStencil::testMask(*state); + } else { + PrepareStencil::testMaskDrawShape(*state); + } - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + state->setBlendFunction(transparent, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); _pipelines[key] = gpu::Pipeline::create(program, state); @@ -79,11 +97,16 @@ void PolyLineEntityRenderer::buildPipelines() { } ItemKey PolyLineEntityRenderer::getKey() { - return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + return isTransparent() ? + ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()) : + ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } ShapeKey PolyLineEntityRenderer::getShapeKey() { - auto builder = ShapeKey::Builder().withOwnPipeline().withTranslucent().withoutCullFace(); + auto builder = ShapeKey::Builder().withOwnPipeline().withoutCullFace(); + if (isTransparent()) { + builder.withTranslucent(); + } if (_primitiveMode == PrimitiveMode::LINES) { builder.withWireframe(); } @@ -308,7 +331,7 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { buildPipelines(); } - batch.setPipeline(_pipelines[{args->_renderMethod, _glow}]); + batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]); batch.setModelTransform(transform); batch.setResourceTexture(0, texture); batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * numVertices), 0); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 97a45cef19..41b66c0e51 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -27,8 +27,7 @@ public: void updateModelTransformAndBound() override; - // FIXME: shouldn't always be transparent: take into account texture and glow - virtual bool isTransparent() const override { return true; } + virtual bool isTransparent() const override; protected: virtual bool needsRenderUpdate() const override; diff --git a/libraries/entities-renderer/src/entities-renderer/paintStroke.slp b/libraries/entities-renderer/src/entities-renderer/paintStroke.slp index e283f4edcb..acdda4dece 100644 --- a/libraries/entities-renderer/src/entities-renderer/paintStroke.slp +++ b/libraries/entities-renderer/src/entities-renderer/paintStroke.slp @@ -1 +1 @@ -DEFINES forward \ No newline at end of file +DEFINES translucent:f forward diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 4ae242655c..3d5cc190d0 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -34,7 +34,11 @@ void main(void) { texel.a *= mix(1.0, pow(1.0 - min(1.0, abs(_distanceFromCenter)), 10.0), _polylineData.faceCameraGlow.y); <@if not HIFI_USE_FORWARD@> - packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS); + <@if HIFI_USE_TRANSLUCENT@> + packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS); + <@else@> + packDeferredFragmentUnlit((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb); + <@endif@> <@else@> _fragColor0 = texel; <@endif@> diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index de4581d66e..de3d0a3087 100644 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -52,7 +52,8 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r } void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) { - if (alpha < 1.0) { + // to reduce texel flickering for floating point error we discard when alpha is "almost one" + if (alpha < 0.999999) { discard; } _fragColor0 = vec4(color, packUnlit()); From 4b1b61ae5be55e679f1ecaed4c434cc1c23f1d04 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 22 Aug 2019 13:16:32 -0700 Subject: [PATCH 11/21] Keep new offset rotation method and resolve duplicates at the end --- .../src/model-baker/PrepareJointsTask.cpp | 126 +++++++++++------- 1 file changed, 79 insertions(+), 47 deletions(-) diff --git a/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp b/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp index a62294d2f6..dd7dd1bde4 100644 --- a/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp +++ b/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp @@ -60,76 +60,108 @@ void PrepareJointsTask::configure(const Config& config) { _passthrough = config.passthrough; } + void PrepareJointsTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) { const auto& jointsIn = input.get0(); auto& jointsOut = output.edit0(); - - const QString APPEND_DUPLICATE_JOINT = "_joint"; - const QString APPEND_DUPLICATE_MESH = "_mesh"; - + std::vector jointNames; if (_passthrough) { jointsOut = jointsIn; } else { const auto& mapping = input.get1(); auto& jointRotationOffsets = output.edit1(); - auto& jointIndices = output.edit2(); + static const QString JOINT_ROTATION_OFFSET2_FIELD = "jointRotationOffset2"; QVariantHash fstHashMap = mapping; + bool newJointRot = fstHashMap.contains(JOINT_ROTATION_OFFSET2_FIELD); // Get joint renames - auto jointNameMapping = getJointNameMapping(mapping); + QMap jointNameMapping = getJointNameMapping(mapping); // Apply joint metadata from FST file mappings - for (const auto& jointIn : jointsIn) { + for (const hfm::Joint& jointIn : jointsIn) { jointsOut.push_back(jointIn); - auto& jointOut = jointsOut.back(); + hfm::Joint& jointOut = jointsOut.back(); - auto jointNameMapKey = jointNameMapping.key(jointIn.name); - if (jointNameMapping.contains(jointNameMapKey)) { - jointOut.name = jointNameMapKey; - } - - // Make sure that joint name is unique - if (jointIndices.contains(jointOut.name)) { - int duplicatedJointIndex = jointIndices.find(jointOut.name).value(); - auto& duplicatedJoint = jointsOut[duplicatedJointIndex]; - bool areBothJoints = jointOut.isSkeletonJoint && duplicatedJoint.isSkeletonJoint; - QString existJointName = jointOut.name; - QString appendName; - if (areBothJoints) { - appendName = APPEND_DUPLICATE_JOINT; - qCWarning(model_baker) << "Duplicated skeleton joints found: " << existJointName; - } else { - appendName = APPEND_DUPLICATE_MESH; - qCDebug(model_baker) << "Duplicated joints found. Renaming the mesh joint: " << existJointName; + if (!newJointRot) { + // Offset rotations are referenced by the new joint's names + // We need to assign new joint's names now, before the offsets are read. + QString jointNameMapKey = jointNameMapping.key(jointIn.name); + if (jointNameMapping.contains(jointNameMapKey)) { + jointOut.name = jointNameMapKey; } - QString newName = existJointName + appendName; - // Make sure the new name is unique - int duplicateIndex = 0; - while (jointIndices.contains(newName)) { - newName = existJointName + appendName + QString::number(++duplicateIndex); - } - // Find and rename the mesh joint - if (!jointOut.isSkeletonJoint) { - jointOut.name = newName; - } else { - duplicatedJoint.name = newName; - jointIndices.remove(jointOut.name); - jointIndices.insert(duplicatedJoint.name, duplicatedJointIndex); - } } - jointIndices.insert(jointOut.name, (int)jointsOut.size()); + jointNames.push_back(jointOut.name); } // Get joint rotation offsets from FST file mappings - auto offsets = getJointRotationOffsets(mapping); + QMap offsets = getJointRotationOffsets(mapping); for (auto itr = offsets.begin(); itr != offsets.end(); itr++) { QString jointName = itr.key(); - int jointIndex = jointIndices.value(jointName) - 1; - if (jointIndex >= 0) { - glm::quat rotationOffset = itr.value(); - jointRotationOffsets.insert(jointIndex, rotationOffset); - qCDebug(model_baker) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; + auto jointToOffset = std::find_if(jointsOut.begin(), jointsOut.end(), [jointName](const hfm::Joint& joint) { + return (joint.name == jointName && joint.isSkeletonJoint); + }); + if (jointToOffset != jointsOut.end()) { + // In case there are named duplicates we'll assign the offset rotation to the first skeleton joint that matches the name. + int jointIndex = (int)distance(jointsOut.begin(), jointToOffset); + if (jointIndex >= 0) { + glm::quat rotationOffset = itr.value(); + jointRotationOffsets.insert(jointIndex, rotationOffset); + qCDebug(model_baker) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; + break; + } } } + + if (newJointRot) { + // Offset rotations are referenced using the original joint's names + // We need to apply new names now, once we have read the offsets + for (size_t i = 0; i < jointsOut.size(); i++) { + hfm::Joint& jointOut = jointsOut[i]; + QString jointNameMapKey = jointNameMapping.key(jointOut.name); + if (jointNameMapping.contains(jointNameMapKey)) { + jointOut.name = jointNameMapKey; + jointNames[i] = jointNameMapKey; + } + } + } + + const QString APPEND_DUPLICATE_JOINT = "_joint"; + const QString APPEND_DUPLICATE_MESH = "_mesh"; + + // resolve duplicates and set jointIndices + auto& jointIndices = output.edit2(); + for (size_t i = 0; i < jointsOut.size(); i++) { + hfm::Joint& jointOut = jointsOut[i]; + if (jointIndices.contains(jointOut.name)) { + int duplicatedJointIndex = jointIndices[jointOut.name] - 1; + if (duplicatedJointIndex >= 0) { + auto& duplicatedJoint = jointsOut[duplicatedJointIndex]; + bool areBothJoints = jointOut.isSkeletonJoint && duplicatedJoint.isSkeletonJoint; + QString existJointName = jointOut.name; + QString appendName; + if (areBothJoints) { + appendName = APPEND_DUPLICATE_JOINT; + qCWarning(model_baker) << "Duplicated skeleton joints found: " << existJointName; + } else { + appendName = APPEND_DUPLICATE_MESH; + qCDebug(model_baker) << "Duplicated joints found. Renaming the mesh joint: " << existJointName; + } + QString newName = existJointName + appendName; + // Make sure the new name is unique + int duplicateIndex = 0; + while (jointIndices.contains(newName)) { + newName = existJointName + appendName + QString::number(++duplicateIndex); + } + // Find and rename the mesh joint + if (!jointOut.isSkeletonJoint) { + jointOut.name = newName; + } else { + jointIndices.remove(jointOut.name); + jointIndices.insert(newName, duplicatedJointIndex); + } + } + } + jointIndices.insert(jointOut.name, i + 1); + } } } From 6e96b800b64ecf3022942374d02d80c852ec20dc Mon Sep 17 00:00:00 2001 From: RebeccaStankus Date: Thu, 22 Aug 2019 13:22:45 -0700 Subject: [PATCH 12/21] Engine handles turning PTT off if unmuting --- interface/resources/qml/hifi/audio/Audio.qml | 9 --------- interface/src/scripting/Audio.cpp | 14 +++++++++++--- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 9db19e72e2..d3bf6aca0a 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -186,15 +186,6 @@ Rectangle { backgroundOnColor: "#E3E3E3"; checked: muted; onClicked: { - if (pushToTalk && !checked) { - // disable push to talk if unmuting - if (bar.currentIndex === 0) { - AudioScriptingInterface.pushToTalkDesktop = false; - } - else { - AudioScriptingInterface.pushToTalkHMD = false; - } - } if (bar.currentIndex === 0) { AudioScriptingInterface.mutedDesktop = checked; } diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index e3e6138744..8d9e57ad93 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -101,6 +101,10 @@ void Audio::setMutedDesktop(bool isMuted) { } } }); + if (!isMuted && _settingsLoaded) { + // Disable Push-To-Talk if muted is changed to false. Settings also need to be loaded. + setPTTDesktop(isMuted); + } if (changed) { if (!isHMD) { emit mutedChanged(isMuted); @@ -128,6 +132,10 @@ void Audio::setMutedHMD(bool isMuted) { } } }); + if (!isMuted && _settingsLoaded) { + // Disable Push-To-Talk if muted is changed to false. Settings also need to be loaded. + setPTTHMD(isMuted); + } if (changed) { if (isHMD) { emit mutedChanged(isMuted); @@ -187,9 +195,9 @@ void Audio::setPTTDesktop(bool enabled) { _pttDesktop = enabled; } }); - if (enabled || _settingsLoaded) { + if (enabled && _settingsLoaded) { // Set to default behavior (muted for Desktop) on Push-To-Talk disable or when enabled. Settings also need to be loaded. - setMutedDesktop(true); + setMutedDesktop(enabled); } if (changed) { emit pushToTalkChanged(enabled); @@ -211,7 +219,7 @@ void Audio::setPTTHMD(bool enabled) { _pttHMD = enabled; } }); - if (enabled || _settingsLoaded) { + if (enabled && _settingsLoaded) { // Set to default behavior (unmuted for HMD) on Push-To-Talk disable or muted for when PTT is enabled. setMutedHMD(enabled); } From 1eaba67f67adb009d8e78d54c0cdd55ebde53590 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 22 Aug 2019 15:07:12 -0700 Subject: [PATCH 13/21] Remove use of build version in mac launcher settings --- launchers/darwin/src/Launcher.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index f88005f733..9a70ddf0e7 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -289,12 +289,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE; 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); - currentVersion = [Settings.sharedSettings latestBuildVersion]; + NSLog(@"can't get version from interface: %@", error); } } @catch (NSException *exception) { - NSLog(@"an exception was thrown: %@", exception); - currentVersion = [Settings.sharedSettings latestBuildVersion]; + NSLog(@"an exception was thrown while getting current interface version: %@", exception); + currentVersion = 0; } return currentVersion; } From 7ffcee35dde68767e19838527a874b5db3b849ad Mon Sep 17 00:00:00 2001 From: ingerjm0 Date: Thu, 22 Aug 2019 15:37:34 -0700 Subject: [PATCH 14/21] Fix formatting in API docs (DOC-112, DOC-113, DOC-142, DOC-143) --- .../static/styles/jsdoc.css | 111 +++++------------- 1 file changed, 29 insertions(+), 82 deletions(-) diff --git a/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css b/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css index 2232491d04..a33cff15e4 100644 --- a/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css +++ b/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css @@ -40,9 +40,9 @@ body letter-spacing: 0.5px; } -#main p { - line-height: 24px; - margin-bottom: 24px; +p { + font-size: 0.95rem; + line-height: 20px; } section @@ -118,30 +118,17 @@ h5, .container-overview .subsection-title **************************** Table styles ************************** ********************************************************************/ -table -{ - width: 100%; - background-color: #fff; +table { border-collapse: collapse; - border-spacing: 0; - border: solid #d8e1d9 1px; - text-align: left; - overflow: auto; - font-size: 0.9rem; - line-height: 1.5; + border: solid #d8e1d9 1px; margin-bottom: 1.5rem; + width: 100% } -table > thead { +thead { border-color: #d8e1d9; - background: #d8e1d9; - font-weight: 400; -} - -table th, table td { - padding: 0.5rem; - border-left: 1px solid #d8e1d9; - font-size: .95em; + background:#d8e1d9; + text-align: left; } table tr { @@ -152,6 +139,23 @@ table tr:nth-child(even) { background-color: #f8f8f8; } +td { + border: solid #c7cccb 1px; +} + +article table thead tr th, article table tbody tr td, article table tbody tr td p { + font-size: .89rem; + line-height: 20px; +} + +article table thead tr th, article table tbody tr td { + padding: 0.5rem; +} + +article table tbody tr td ul li { + font-size: .89rem; +} + /******************************************************************* ****************************** Link styles ************************* ********************************************************************/ @@ -169,21 +173,15 @@ a, a:hover, a:active, a:visited { ********************************************************************/ article ul { - margin-bottom: 1.7em; + margin-bottom: 1em; } article li { font-size: .95rem; + line-height: 20px; padding-bottom: 5px; } -.readme ul { - font-size: 0.95rem; - line-height: 24px; - margin-bottom: 24px; - -} - /******************************************************************* ********************** Navigation sidebar styles ******************* ********************************************************************/ @@ -388,20 +386,16 @@ tt, code, kbd, samp { font-size: 0.9rem; } - - img { display: block; max-width: 100%; margin: auto; } -p, ul, ol, blockquote { +ul, ol, blockquote { margin-bottom: 1em; } - - .class-description { font-size: 130%; line-height: 140%; @@ -423,7 +417,6 @@ header { padding: 0px 4px; } - .apiLinks { display: block; @@ -529,7 +522,6 @@ header { .code-caption { font-style: italic; - font-size: 107%; margin: 0; } @@ -696,51 +688,6 @@ span.param-type, .params td .param-type, .param-type dd { z-index: 1; } -/******************************************************************** -**************************** Mobile styles ************************** -*********************************************************************/ - -@media only screen and (min-width: 320px) and (max-width: 680px) { - body { - overflow-x: hidden; - } - - nav { - background: #FFF; - width: 250px; - height: 100%; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: -250px; - z-index: 3; - padding: 0 10px; - transition: left 0.2s; - } - - .navicon-button { - display: inline-block; - position: fixed; - top: 1.5em; - right: 0; - z-index: 2; - } - - #main { - width: 100%; - min-width: 360px; - } - - #main section { - padding: 0; - } - - footer { - margin-left: 0; - } -} - /** Add a '#' to static members */ [data-type="member"] a::before { content: '#'; From 07d17343bf48d609defa07165a52bc6da476a025 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 23 Aug 2019 07:21:19 -0700 Subject: [PATCH 15/21] fix warnigns --- libraries/model-baker/src/model-baker/PrepareJointsTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp b/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp index dd7dd1bde4..cd27f8ba0b 100644 --- a/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp +++ b/libraries/model-baker/src/model-baker/PrepareJointsTask.cpp @@ -161,7 +161,7 @@ void PrepareJointsTask::run(const baker::BakeContextPointer& context, const Inpu } } } - jointIndices.insert(jointOut.name, i + 1); + jointIndices.insert(jointOut.name, (int)(i + 1)); } } } From 83bc5e3fd64ea96fc08aa3c3b21c706b39c4c321 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 31 Jul 2019 16:28:18 -0700 Subject: [PATCH 16/21] Add build tags to Windows launcher --- launchers/win32/LauncherManager.cpp | 92 ++++++++++++++++++++--------- launchers/win32/LauncherManager.h | 11 +++- 2 files changed, 73 insertions(+), 30 deletions(-) diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index 5e452b97b2..9aaae7c8ca 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -36,6 +36,7 @@ void LauncherManager::init(BOOL allowUpdate, ContinueActionOnStart continueActio } addToLog(_T("Launcher is running version: " + _launcherVersion)); addToLog(_T("Getting most recent builds")); + _isInstalled = isApplicationInstalled(_currentVersion, _domainURL, _contentURL, _loggedIn, _organizationBuildTag); getMostRecentBuilds(_latestLauncherURL, _latestLauncherVersion, _latestApplicationURL, _latestVersion); } @@ -260,14 +261,14 @@ BOOL LauncherManager::deleteShortcuts() { } BOOL LauncherManager::isApplicationInstalled(CString& version, CString& domain, - CString& content, bool& loggedIn) { + CString& content, bool& loggedIn, CString& organizationBuildTag) { CString applicationDir; getAndCreatePaths(PathType::Launcher_Directory, applicationDir); CString applicationPath = applicationDir + "interface\\interface.exe"; BOOL isInstalled = PathFileExistsW(applicationPath); BOOL configFileExist = PathFileExistsW(applicationDir + _T("interface\\config.json")); if (configFileExist) { - LauncherUtils::ResponseError status = readConfigJSON(version, domain, content, loggedIn); + LauncherUtils::ResponseError status = readConfigJSON(version, domain, content, loggedIn, organizationBuildTag); return isInstalled && status == LauncherUtils::ResponseError::NoError; } return FALSE; @@ -326,7 +327,6 @@ BOOL LauncherManager::getInstalledVersion(const CString& path, CString& version) return success; } - HWND LauncherManager::launchApplication() { CString installDir; LauncherManager::getAndCreatePaths(PathType::Interface_Directory, installDir); @@ -368,6 +368,7 @@ BOOL LauncherManager::createConfigJSON() { config["launcherPath"] = LauncherUtils::cStringToStd(applicationPath); config["version"] = LauncherUtils::cStringToStd(_latestVersion); config["domain"] = LauncherUtils::cStringToStd(_domainURL); + config["organizationBuildTag"] = LauncherUtils::cStringToStd(_organizationBuildTag); CString content; getAndCreatePaths(PathType::Content_Directory, content); config["content"] = LauncherUtils::cStringToStd(content); @@ -377,7 +378,7 @@ BOOL LauncherManager::createConfigJSON() { } LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, CString& domain, - CString& content, bool& loggedIn) { + CString& content, bool& loggedIn, CString& organizationBuildTag) { CString configPath; getAndCreatePaths(PathType::Interface_Directory, configPath); configPath += "\\config.json"; @@ -394,6 +395,13 @@ LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, C version = config["version"].asCString(); domain = config["domain"].asCString(); content = config["content"].asCString(); + + if (config["organizationBuildTag"].isString()) { + organizationBuildTag = config["organizationBuildTag"].asCString(); + } else { + organizationBuildTag = ""; + } + configFile.close(); return LauncherUtils::ResponseError::NoError; } @@ -401,6 +409,37 @@ LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, C return LauncherUtils::ResponseError::ParsingJSON; } +bool findBuildInResponse(const Json::Value& json, const CString& tag, CString& interfaceUrlOut, CString& interfaceVersionOut) { + if (json["results"].isArray()) { + auto& results = json["results"]; + int count = results.size(); + for (int i = 0; i < count; i++) { + if (results[i].isObject()) { + Json::Value result = results[i]; + if (result["name"].asCString() == tag) { + if (result["latest_version"].isInt()) { + std::string version = std::to_string(result["latest_version"].asInt()); + interfaceVersionOut = CString(version.c_str()); + } else { + return false; + } + if (result["installers"].isObject() && + result["installers"]["windows"].isObject() && + result["installers"]["windows"]["zip_url"].isString()) { + interfaceUrlOut = result["installers"]["windows"]["zip_url"].asCString(); + } else { + return false; + } + return true; + } + } + } + } + + return false; +} + + LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString& hash) { CString contentTypeJson = L"content-type:application/json"; CString response; @@ -417,6 +456,13 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString if (json["content_set_url"].isString() && json["domain"].isString()) { _contentURL = json["content_set_url"].asCString(); _domainURL = json["domain"].asCString(); + _organizationBuildTag = json.get("build_tag", "").asCString(); + auto buildTag = _organizationBuildTag.IsEmpty() ? _defaultBuildTag : _organizationBuildTag; + + if (!findBuildInResponse(_latestBuilds, buildTag, _latestApplicationURL, _latestVersion)) { + return LauncherUtils::ResponseError::ParsingJSON; + } + return LauncherUtils::ResponseError::NoError; } } @@ -429,7 +475,9 @@ void LauncherManager::getMostRecentBuilds(CString& launcherUrlOut, CString& laun std::function httpCallback = [&](CString response, int err) { LauncherUtils::ResponseError error = LauncherUtils::ResponseError(err); if (error == LauncherUtils::ResponseError::NoError) { - Json::Value json; + Json::Value& json = _latestBuilds; + _defaultBuildTag = json.get("default_tag", "hqlauncher").asCString(); + auto buildTag = _organizationBuildTag.IsEmpty() ? _defaultBuildTag : _organizationBuildTag; if (LauncherUtils::parseJSON(response, json)) { if (json["launcher"].isObject()) { if (json["launcher"]["windows"].isObject() && json["launcher"]["windows"]["url"].isString()) { @@ -440,24 +488,12 @@ void LauncherManager::getMostRecentBuilds(CString& launcherUrlOut, CString& laun launcherVersionOut = CString(version.c_str()); } } - int count = json["count"].isInt() ? json["count"].asInt() : 0; - if (count > 0 && json["results"].isArray()) { - for (int i = 0; i < count; i++) { - if (json["results"][i].isObject()) { - Json::Value result = json["results"][i]; - if (result["latest_version"].isInt()) { - std::string version = std::to_string(result["latest_version"].asInt()); - interfaceVersionOut = CString(version.c_str()); - } - if (result["installers"].isObject() && - result["installers"]["windows"].isObject() && - result["installers"]["windows"]["zip_url"].isString()) { - interfaceUrlOut = result["installers"]["windows"]["zip_url"].asCString(); - } - } - } + + if (launcherUrlOut.IsEmpty() || launcherVersionOut.IsEmpty()) { + error = LauncherUtils::ResponseError::ParsingJSON; } - if (launcherUrlOut.IsEmpty() || launcherVersionOut.IsEmpty() || interfaceUrlOut.IsEmpty() || interfaceVersionOut.IsEmpty()) { + + if (!findBuildInResponse(json, buildTag, _latestApplicationURL, _latestVersion)) { error = LauncherUtils::ResponseError::ParsingJSON; } } @@ -473,8 +509,8 @@ void LauncherManager::getMostRecentBuilds(CString& launcherUrlOut, CString& laun void LauncherManager::onMostRecentBuildsReceived(const CString& response, LauncherUtils::ResponseError error) { if (error == LauncherUtils::ResponseError::NoError) { addToLog(_T("Latest launcher version: ") + _latestLauncherVersion); - CString currentVersion; - BOOL isInstalled = (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn); + CString currentVersion = _currentVersion; + BOOL isInstalled = _isInstalled && _loggedIn; bool newInterfaceVersion = _latestVersion.Compare(currentVersion) != 0; bool newLauncherVersion = _latestLauncherVersion.Compare(_launcherVersion) != 0 && _updateLauncherAllowed; if (newLauncherVersion) { @@ -511,7 +547,7 @@ void LauncherManager::onMostRecentBuildsReceived(const CString& response, Launch _shouldWait = FALSE; } else { - _hasFailed = true; + setFailed(true); CString msg; msg.Format(_T("Getting most recent builds has failed with error: %d"), error); addToLog(msg); @@ -611,7 +647,7 @@ BOOL LauncherManager::extractApplication() { onZipExtracted((ProcessType)type, size); } else { addToLog(_T("Error decompressing application zip file.")); - _hasFailed = true; + setFailed(true); } }; std::function onProgress = [&](float progress) { @@ -688,7 +724,7 @@ BOOL LauncherManager::installContent() { } else { addToLog(_T("Error decompressing content zip file.")); - _hasFailed = true; + setFailed(_hasFailed); } }; std::function onProgress = [&](float progress) { @@ -728,7 +764,7 @@ BOOL LauncherManager::downloadFile(ProcessType type, const CString& url, CString } else { addToLog(_T("Error downloading application.")); } - _hasFailed = true; + setFailed(_hasFailed); } }; std::function onProgress = [&, type](float progress) { diff --git a/launchers/win32/LauncherManager.h b/launchers/win32/LauncherManager.h index d0c81ae75b..bba54fb10b 100644 --- a/launchers/win32/LauncherManager.h +++ b/launchers/win32/LauncherManager.h @@ -76,7 +76,7 @@ public: BOOL getAndCreatePaths(PathType type, CString& outPath); BOOL getInstalledVersion(const CString& path, CString& version); BOOL isApplicationInstalled(CString& version, CString& domain, - CString& content, bool& loggedIn); + CString& content, bool& loggedIn, CString& organizationBuildTag); LauncherUtils::ResponseError getAccessTokenForCredentials(const CString& username, const CString& password); void getMostRecentBuilds(CString& launcherUrlOut, CString& launcherVersionOut, @@ -84,7 +84,7 @@ public: CString& interfaceVersionOut); LauncherUtils::ResponseError readOrganizationJSON(const CString& hash); LauncherUtils::ResponseError readConfigJSON(CString& version, CString& domain, - CString& content, bool& loggedIn); + CString& content, bool& loggedIn, CString& organizationBuildTag); BOOL createConfigJSON(); BOOL createApplicationRegistryKeys(int size); BOOL deleteApplicationRegistryKeys(); @@ -139,10 +139,12 @@ public: private: ProcessType _currentProcess { ProcessType::DownloadApplication }; void onMostRecentBuildsReceived(const CString& response, LauncherUtils::ResponseError error); + CString _latestApplicationURL; CString _latestVersion; CString _latestLauncherURL; CString _latestLauncherVersion; + CString _contentURL; CString _domainURL; CString _version; @@ -152,6 +154,8 @@ private: CString _contentZipPath; CString _launcherVersion; CString _tempLauncherPath; + CString _currentVersion; + bool _isInstalled{ false }; bool _loggedIn { false }; bool _hasFailed { false }; BOOL _shouldUpdate { FALSE }; @@ -171,4 +175,7 @@ private: float _progressOffset { 0.0f }; float _progress { 0.0f }; CStdioFile _logFile; + Json::Value _latestBuilds; + CString _defaultBuildTag; + CString _organizationBuildTag; }; From da9163616a3225f272c573e0a997ac38bc83e024 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 23 Aug 2019 08:46:59 -0700 Subject: [PATCH 17/21] Don't allow reactions ref count got bellow 0 --- interface/src/avatar/MyAvatar.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index af49aa1e3c..a599ec926b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -5863,7 +5863,11 @@ bool MyAvatar::endReaction(QString reactionName) { int reactionIndex = beginEndReactionNameToIndex(reactionName); if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_BEGIN_END_REACTIONS) { std::lock_guard guard(_reactionLock); - _reactionEnabledRefCounts[reactionIndex]--; + if (_reactionEnabledRefCounts[reactionIndex] > 0) { + _reactionEnabledRefCounts[reactionIndex]--; + } else { + _reactionEnabledRefCounts[reactionIndex] = 0; + } return true; } return false; From da1b2e9ec8502ded8dff7c816a50dd16821ef1d3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Aug 2019 16:30:19 -0700 Subject: [PATCH 18/21] Add method for overriding builds API url in win32 launcher --- launchers/win32/LauncherManager.cpp | 27 ++++++++++++++++++++++++--- launchers/win32/LauncherUtils.cpp | 11 ++++++----- launchers/win32/LauncherUtils.h | 5 +++-- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index 9aaae7c8ca..bba23966a6 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -445,7 +445,7 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString CString response; CString url = _T("/organizations/") + hash + _T(".json"); LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(getHttpUserAgent(), - L"orgs.highfidelity.com", url, + true, L"orgs.highfidelity.com", url, contentTypeJson, CStringA(), response, false); if (error != LauncherUtils::ResponseError::NoError) { @@ -500,9 +500,29 @@ void LauncherManager::getMostRecentBuilds(CString& launcherUrlOut, CString& laun } onMostRecentBuildsReceived(response, error); }; + + bool useHTTPS{ true }; + + CString domainName; + if (domainName.GetEnvironmentVariable(L"HQ_LAUNCHER_BUILDS_DOMAIN")) { + addToLog(_T("Using overridden builds domain: ") + domainName); + useHTTPS = false; + } else { + domainName = L"thunder.highfidelity.com"; + } + + CString pathName; + if (pathName.GetEnvironmentVariable(L"HQ_LAUNCHER_BUILDS_PATH")) { + addToLog(_T("Using overridden builds path: ") + pathName); + useHTTPS = false; + } else { + pathName = L"/builds/api/tags/latest?format=json"; + } + LauncherUtils::httpCallOnThread(getHttpUserAgent(), - L"thunder.highfidelity.com", - L"/builds/api/tags/latest?format=json", + useHTTPS, + domainName, + pathName, contentTypeJson, CStringA(), false, httpCallback); } @@ -567,6 +587,7 @@ LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString contentTypeText = L"content-type:application/x-www-form-urlencoded"; CString response; LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(getHttpUserAgent(), + true, L"metaverse.highfidelity.com", L"/oauth/token", contentTypeText, post, diff --git a/launchers/win32/LauncherUtils.cpp b/launchers/win32/LauncherUtils.cpp index e0a85302f0..ef23073ca5 100644 --- a/launchers/win32/LauncherUtils.cpp +++ b/launchers/win32/LauncherUtils.cpp @@ -181,7 +181,7 @@ BOOL LauncherUtils::deleteRegistryKey(const CString& registryPath) { } LauncherUtils::ResponseError LauncherUtils::makeHTTPCall(const CString& callerName, - const CString& mainUrl, const CString& dirUrl, + bool useHTTPS, const CString& mainUrl, const CString& dirUrl, const CString& contentType, CStringA& postData, CString& response, bool isPost = false) { @@ -190,12 +190,12 @@ LauncherUtils::ResponseError LauncherUtils::makeHTTPCall(const CString& callerNa if (!hopen) { return ResponseError::Open; } - HINTERNET hconnect = WinHttpConnect(hopen, mainUrl, INTERNET_DEFAULT_HTTPS_PORT, 0); + HINTERNET hconnect = WinHttpConnect(hopen, mainUrl, useHTTPS ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0); if (!hconnect) { return ResponseError::Connect; } HINTERNET hrequest = WinHttpOpenRequest(hconnect, isPost ? L"POST" : L"GET", dirUrl, - NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); + NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, useHTTPS ? WINHTTP_FLAG_SECURE : 0); if (!hrequest) { return ResponseError::OpenRequest; } @@ -497,7 +497,7 @@ DWORD WINAPI LauncherUtils::deleteDirectoryThread(LPVOID lpParameter) { DWORD WINAPI LauncherUtils::httpThread(LPVOID lpParameter) { HttpThreadData& data = *((HttpThreadData*)lpParameter); CString response; - auto error = LauncherUtils::makeHTTPCall(data._callerName, data._mainUrl, data._dirUrl, + auto error = LauncherUtils::makeHTTPCall(data._callerName, data._useHTTPS, data._mainUrl, data._dirUrl, data._contentType, data._postData, response, data._isPost); data._callback(response, error); return 0; @@ -552,12 +552,13 @@ BOOL LauncherUtils::deleteDirectoryOnThread(const CString& dirPath, std::functio return FALSE; } -BOOL LauncherUtils::httpCallOnThread(const CString& callerName, const CString& mainUrl, const CString& dirUrl, +BOOL LauncherUtils::httpCallOnThread(const CString& callerName, bool useHTTPS, const CString& mainUrl, const CString& dirUrl, const CString& contentType, CStringA& postData, bool isPost, std::function callback) { DWORD myThreadID; HttpThreadData* httpThreadData = new HttpThreadData(); httpThreadData->_callerName = callerName; + httpThreadData->_useHTTPS = useHTTPS; httpThreadData->_mainUrl = mainUrl; httpThreadData->_dirUrl = dirUrl; httpThreadData->_contentType = contentType; diff --git a/launchers/win32/LauncherUtils.h b/launchers/win32/LauncherUtils.h index 32cd5031b4..6e4e2b6ad8 100644 --- a/launchers/win32/LauncherUtils.h +++ b/launchers/win32/LauncherUtils.h @@ -120,6 +120,7 @@ public: struct HttpThreadData { CString _callerName; + bool _useHTTPS; CString _mainUrl; CString _dirUrl; CString _contentType; @@ -137,7 +138,7 @@ public: }; static BOOL parseJSON(const CString& jsonTxt, Json::Value& jsonObject); - static ResponseError makeHTTPCall(const CString& callerName, const CString& mainUrl, + static ResponseError makeHTTPCall(const CString& callerName, bool useHTTPS, const CString& mainUrl, const CString& dirUrl, const CString& contentType, CStringA& postData, CString& response, bool isPost); static std::string cStringToStd(CString cstring); @@ -163,7 +164,7 @@ public: std::function callback, std::function progressCallback); static BOOL deleteDirectoryOnThread(const CString& dirPath, std::function callback); - static BOOL httpCallOnThread(const CString& callerName, const CString& mainUrl, const CString& dirUrl, + static BOOL httpCallOnThread(const CString& callerName, bool useHTTPS, const CString& mainUrl, const CString& dirUrl, const CString& contentType, CStringA& postData, bool isPost, std::function callback); From 328896b9edc6ce9c2dc811e92a214b1ffc30d330 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Aug 2019 16:32:30 -0700 Subject: [PATCH 19/21] Fix calls to setFailed in win32 launcher --- launchers/win32/LauncherManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index bba23966a6..ea9073763d 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -745,7 +745,7 @@ BOOL LauncherManager::installContent() { } else { addToLog(_T("Error decompressing content zip file.")); - setFailed(_hasFailed); + setFailed(true); } }; std::function onProgress = [&](float progress) { @@ -785,7 +785,7 @@ BOOL LauncherManager::downloadFile(ProcessType type, const CString& url, CString } else { addToLog(_T("Error downloading application.")); } - setFailed(_hasFailed); + setFailed(true); } }; std::function onProgress = [&, type](float progress) { From cf64492185bfdb577f415045e600e27b08a7ccbf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 16 Aug 2019 12:51:09 -0700 Subject: [PATCH 20/21] Fix default_tag in win32 launcher not working --- launchers/win32/LauncherManager.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index ea9073763d..991f7bd412 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -476,9 +476,11 @@ void LauncherManager::getMostRecentBuilds(CString& launcherUrlOut, CString& laun LauncherUtils::ResponseError error = LauncherUtils::ResponseError(err); if (error == LauncherUtils::ResponseError::NoError) { Json::Value& json = _latestBuilds; - _defaultBuildTag = json.get("default_tag", "hqlauncher").asCString(); - auto buildTag = _organizationBuildTag.IsEmpty() ? _defaultBuildTag : _organizationBuildTag; if (LauncherUtils::parseJSON(response, json)) { + _defaultBuildTag = json.get("default_tag", "").asCString(); + auto buildTag = _organizationBuildTag.IsEmpty() ? _defaultBuildTag : _organizationBuildTag; + addToLog(_T("Build tag is: ") + buildTag); + if (json["launcher"].isObject()) { if (json["launcher"]["windows"].isObject() && json["launcher"]["windows"]["url"].isString()) { launcherUrlOut = json["launcher"]["windows"]["url"].asCString(); @@ -494,6 +496,7 @@ void LauncherManager::getMostRecentBuilds(CString& launcherUrlOut, CString& laun } if (!findBuildInResponse(json, buildTag, _latestApplicationURL, _latestVersion)) { + addToLog(_T("Failed to find build")); error = LauncherUtils::ResponseError::ParsingJSON; } } From 19d85ba824232950dd3f0c34cd5e5c60a63ed91a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 23 Aug 2019 09:07:27 -0700 Subject: [PATCH 21/21] MyAvatar.endReaction return false when no reaction has been trigger previously --- interface/src/avatar/MyAvatar.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a599ec926b..089ff4c2bf 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -5865,10 +5865,11 @@ bool MyAvatar::endReaction(QString reactionName) { std::lock_guard guard(_reactionLock); if (_reactionEnabledRefCounts[reactionIndex] > 0) { _reactionEnabledRefCounts[reactionIndex]--; + return true; } else { _reactionEnabledRefCounts[reactionIndex] = 0; + return false; } - return true; } return false; }