mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-19 08:18:05 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into nut
This commit is contained in:
commit
32399997b1
35 changed files with 493 additions and 221 deletions
|
@ -25,7 +25,6 @@ OriginalDesktop.Desktop {
|
|||
|
||||
Action {
|
||||
text: "Open Browser"
|
||||
shortcut: "Ctrl+B"
|
||||
onTriggered: {
|
||||
console.log("Open browser");
|
||||
browserBuilder.createObject(desktop);
|
||||
|
|
|
@ -49,7 +49,10 @@ Item {
|
|||
}
|
||||
|
||||
function pushSource(path) {
|
||||
d.push(Qt.resolvedUrl("../../" + path));
|
||||
// Workaround issue https://bugreports.qt.io/browse/QTBUG-75516 in Qt 5.12.3
|
||||
// by creating the manually, instead of letting StackView do it for us.
|
||||
var item = Qt.createComponent(Qt.resolvedUrl("../../" + path));
|
||||
d.push(item);
|
||||
if (d.currentItem.sendToScript !== undefined) {
|
||||
d.currentItem.sendToScript.connect(tabletMenu.sendToScript);
|
||||
}
|
||||
|
|
|
@ -867,7 +867,11 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<ScriptCache>();
|
||||
DependencyManager::set<SoundCache>();
|
||||
DependencyManager::set<SoundCacheScriptingInterface>();
|
||||
|
||||
#ifdef HAVE_DDE
|
||||
DependencyManager::set<DdeFaceTracker>();
|
||||
#endif
|
||||
|
||||
DependencyManager::set<EyeTracker>();
|
||||
DependencyManager::set<AudioClient>();
|
||||
DependencyManager::set<AudioScope>();
|
||||
|
@ -2759,7 +2763,6 @@ void Application::cleanupBeforeQuit() {
|
|||
// this must happen after QML, as there are unexplained audio crashes originating in qtwebengine
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "stop");
|
||||
DependencyManager::destroy<AudioClient>();
|
||||
DependencyManager::destroy<AudioInjectorManager>();
|
||||
DependencyManager::destroy<AudioScriptingInterface>();
|
||||
|
||||
// The PointerManager must be destroyed before the PickManager because when a Pointer is deleted,
|
||||
|
@ -2819,6 +2822,7 @@ Application::~Application() {
|
|||
|
||||
DependencyManager::destroy<SoundCacheScriptingInterface>();
|
||||
|
||||
DependencyManager::destroy<AudioInjectorManager>();
|
||||
DependencyManager::destroy<AvatarManager>();
|
||||
DependencyManager::destroy<AnimationCacheScriptingInterface>();
|
||||
DependencyManager::destroy<AnimationCache>();
|
||||
|
@ -3324,7 +3328,9 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
|||
surfaceContext->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
|
||||
|
||||
surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
||||
#ifdef HAVE_DDE
|
||||
surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||
#endif
|
||||
surfaceContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());
|
||||
surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
||||
surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
|
@ -4303,10 +4309,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
break;
|
||||
|
||||
case Qt::Key_B:
|
||||
if (isMeta) {
|
||||
auto offscreenUi = getOffscreenUI();
|
||||
offscreenUi->load("Browser.qml");
|
||||
} else if (isOption) {
|
||||
if (isOption) {
|
||||
controller::InputRecorder* inputRecorder = controller::InputRecorder::getInstance();
|
||||
inputRecorder->stopPlayback();
|
||||
}
|
||||
|
@ -4345,12 +4348,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_N:
|
||||
if (!isOption && !isShifted && isMeta) {
|
||||
DependencyManager::get<NodeList>()->toggleIgnoreRadius();
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_S:
|
||||
if (isShifted && isMeta && !isOption) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::SuppressShortTimings);
|
||||
|
@ -5174,9 +5171,15 @@ ivec2 Application::getMouse() const {
|
|||
}
|
||||
|
||||
FaceTracker* Application::getActiveFaceTracker() {
|
||||
#ifdef HAVE_DDE
|
||||
auto dde = DependencyManager::get<DdeFaceTracker>();
|
||||
|
||||
return dde->isActive() ? static_cast<FaceTracker*>(dde.data()) : nullptr;
|
||||
if (dde && dde->isActive()) {
|
||||
return static_cast<FaceTracker*>(dde.data());
|
||||
}
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FaceTracker* Application::getSelectedFaceTracker() {
|
||||
|
@ -7010,7 +7013,10 @@ void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const {
|
|||
// feature. However, we still use this to reset face trackers, eye trackers, audio and to optionally re-load the avatar
|
||||
// rig and animations from scratch.
|
||||
void Application::resetSensors(bool andReload) {
|
||||
#ifdef HAVE_DDE
|
||||
DependencyManager::get<DdeFaceTracker>()->reset();
|
||||
#endif
|
||||
|
||||
DependencyManager::get<EyeTracker>()->reset();
|
||||
_overlayConductor.centerUI();
|
||||
getActiveDisplayPlugin()->resetSensors();
|
||||
|
@ -7214,7 +7220,7 @@ void Application::nodeKilled(SharedNodePointer node) {
|
|||
_octreeProcessor.nodeKilled(node);
|
||||
|
||||
_entityEditSender.nodeKilled(node);
|
||||
|
||||
|
||||
if (node->getType() == NodeType::AudioMixer) {
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "audioMixerKilled");
|
||||
} else if (node->getType() == NodeType::EntityServer) {
|
||||
|
@ -7402,8 +7408,10 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
scriptEngine->registerGlobalObject("AccountServices", AccountServicesScriptingInterface::getInstance());
|
||||
qScriptRegisterMetaType(scriptEngine.data(), DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue);
|
||||
|
||||
#ifdef HAVE_DDE
|
||||
scriptEngine->registerGlobalObject("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||
|
||||
#endif
|
||||
|
||||
scriptEngine->registerGlobalObject("AvatarManager", DependencyManager::get<AvatarManager>().data());
|
||||
|
||||
scriptEngine->registerGlobalObject("LODManager", DependencyManager::get<LODManager>().data());
|
||||
|
|
|
@ -4947,35 +4947,55 @@ void MyAvatar::setWalkSpeed(float value) {
|
|||
}
|
||||
|
||||
void MyAvatar::setWalkBackwardSpeed(float value) {
|
||||
bool changed = true;
|
||||
float prevVal;
|
||||
switch (_controlSchemeIndex) {
|
||||
case LocomotionControlsMode::CONTROLS_DEFAULT:
|
||||
prevVal = _defaultWalkBackwardSpeed.get();
|
||||
_defaultWalkBackwardSpeed.set(value);
|
||||
break;
|
||||
case LocomotionControlsMode::CONTROLS_ANALOG:
|
||||
prevVal = _analogWalkBackwardSpeed.get();
|
||||
_analogWalkBackwardSpeed.set(value);
|
||||
break;
|
||||
case LocomotionControlsMode::CONTROLS_ANALOG_PLUS:
|
||||
prevVal = _analogPlusWalkBackwardSpeed.get();
|
||||
_analogPlusWalkBackwardSpeed.set(value);
|
||||
break;
|
||||
default:
|
||||
changed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (changed && prevVal != value) {
|
||||
emit walkBackwardSpeedChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::setSprintSpeed(float value) {
|
||||
bool changed = true;
|
||||
float prevVal;
|
||||
switch (_controlSchemeIndex) {
|
||||
case LocomotionControlsMode::CONTROLS_DEFAULT:
|
||||
prevVal = _defaultSprintSpeed.get();
|
||||
_defaultSprintSpeed.set(value);
|
||||
break;
|
||||
case LocomotionControlsMode::CONTROLS_ANALOG:
|
||||
prevVal = _analogSprintSpeed.get();
|
||||
_analogSprintSpeed.set(value);
|
||||
break;
|
||||
case LocomotionControlsMode::CONTROLS_ANALOG_PLUS:
|
||||
prevVal = _analogPlusSprintSpeed.get();
|
||||
_analogPlusSprintSpeed.set(value);
|
||||
break;
|
||||
default:
|
||||
changed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (changed && prevVal != value) {
|
||||
emit analogPlusSprintSpeedChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
float MyAvatar::getSprintSpeed() const {
|
||||
|
@ -5013,9 +5033,12 @@ float MyAvatar::getAnalogSprintSpeed() const {
|
|||
}
|
||||
|
||||
void MyAvatar::setAnalogPlusWalkSpeed(float value) {
|
||||
_analogPlusWalkSpeed.set(value);
|
||||
// Sprint speed for Analog Plus should be double walk speed.
|
||||
_analogPlusSprintSpeed.set(value * 2.0f);
|
||||
if (_analogPlusWalkSpeed.get() != value) {
|
||||
_analogPlusWalkSpeed.set(value);
|
||||
emit analogPlusWalkSpeedChanged(value);
|
||||
// Sprint speed for Analog Plus should be double walk speed.
|
||||
_analogPlusSprintSpeed.set(value * 2.0f);
|
||||
}
|
||||
}
|
||||
|
||||
float MyAvatar::getAnalogPlusWalkSpeed() const {
|
||||
|
@ -5023,7 +5046,10 @@ float MyAvatar::getAnalogPlusWalkSpeed() const {
|
|||
}
|
||||
|
||||
void MyAvatar::setAnalogPlusSprintSpeed(float value) {
|
||||
_analogPlusSprintSpeed.set(value);
|
||||
if (_analogPlusSprintSpeed.get() != value) {
|
||||
_analogPlusSprintSpeed.set(value);
|
||||
emit analogPlusSprintSpeedChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
float MyAvatar::getAnalogPlusSprintSpeed() const {
|
||||
|
|
|
@ -370,10 +370,10 @@ class MyAvatar : public Avatar {
|
|||
Q_PROPERTY(QUuid SELF_ID READ getSelfID CONSTANT)
|
||||
|
||||
Q_PROPERTY(float walkSpeed READ getWalkSpeed WRITE setWalkSpeed);
|
||||
Q_PROPERTY(float analogPlusWalkSpeed READ getAnalogPlusWalkSpeed WRITE setAnalogPlusWalkSpeed);
|
||||
Q_PROPERTY(float analogPlusSprintSpeed READ getAnalogPlusSprintSpeed WRITE setAnalogPlusSprintSpeed);
|
||||
Q_PROPERTY(float walkBackwardSpeed READ getWalkBackwardSpeed WRITE setWalkBackwardSpeed);
|
||||
Q_PROPERTY(float sprintSpeed READ getSprintSpeed WRITE setSprintSpeed);
|
||||
Q_PROPERTY(float analogPlusWalkSpeed READ getAnalogPlusWalkSpeed WRITE setAnalogPlusWalkSpeed NOTIFY analogPlusWalkSpeedChanged);
|
||||
Q_PROPERTY(float analogPlusSprintSpeed READ getAnalogPlusSprintSpeed WRITE setAnalogPlusSprintSpeed NOTIFY analogPlusSprintSpeedChanged);
|
||||
Q_PROPERTY(float walkBackwardSpeed READ getWalkBackwardSpeed WRITE setWalkBackwardSpeed NOTIFY walkBackwardSpeedChanged);
|
||||
Q_PROPERTY(float sprintSpeed READ getSprintSpeed WRITE setSprintSpeed NOTIFY sprintSpeedChanged);
|
||||
Q_PROPERTY(bool isInSittingState READ getIsInSittingState WRITE setIsInSittingState);
|
||||
Q_PROPERTY(MyAvatar::SitStandModelType userRecenterModel READ getUserRecenterModel WRITE setUserRecenterModel);
|
||||
Q_PROPERTY(bool isSitStandStateLocked READ getIsSitStandStateLocked WRITE setIsSitStandStateLocked);
|
||||
|
@ -2161,6 +2161,38 @@ signals:
|
|||
*/
|
||||
void audioListenerModeChanged();
|
||||
|
||||
/**jsdoc
|
||||
* Notifies when the analogPlusWalkSpeed value is changed.
|
||||
* @function MyAvatar.analogPlusWalkSpeedChanged
|
||||
* @param {float} value - the new avatar walk speed
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void analogPlusWalkSpeedChanged(float value);
|
||||
|
||||
/**jsdoc
|
||||
* Notifies when the analogPlusSprintSpeed value is changed.
|
||||
* @function MyAvatar.analogPlusSprintSpeedChanged
|
||||
* @param {float} value - the new avatar sprint speed
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void analogPlusSprintSpeedChanged(float value);
|
||||
|
||||
/**jsdoc
|
||||
* Notifies when the sprintSpeed value is changed.
|
||||
* @function MyAvatar.sprintSpeedChanged
|
||||
* @param {float} value - the new avatar sprint speed
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void sprintSpeedChanged(float value);
|
||||
|
||||
/**jsdoc
|
||||
* Notifies when the walkBackwardSpeed value is changed.
|
||||
* @function MyAvatar.walkBackwardSpeedChanged
|
||||
* @param {float} value - the new avatar walk backward speed
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void walkBackwardSpeedChanged(float value);
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.transformChanged
|
||||
* @returns {Signal}
|
||||
|
|
|
@ -219,7 +219,7 @@ bool OtherAvatar::isInPhysicsSimulation() const {
|
|||
}
|
||||
|
||||
bool OtherAvatar::shouldBeInPhysicsSimulation() const {
|
||||
return !isDead() && _workloadRegion < workload::Region::R3;
|
||||
return !isDead() && _workloadRegion <= workload::Region::R3;
|
||||
}
|
||||
|
||||
bool OtherAvatar::needsPhysicsUpdate() const {
|
||||
|
|
|
@ -14,8 +14,9 @@
|
|||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
//Disabling dde due to random crashes with closing the socket on macos. all the accompanying code is wrapped with the ifdef HAVE_DDE. uncomment the define below to enable
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_OSX)
|
||||
#define HAVE_DDE
|
||||
//#define HAVE_DDE
|
||||
#endif
|
||||
|
||||
#include <QProcess>
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
|
||||
class AudioInputDeviceList : public AudioDeviceList {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool peakValuesAvailable READ peakValuesAvailable)
|
||||
Q_PROPERTY(bool peakValuesAvailable READ peakValuesAvailable CONSTANT)
|
||||
Q_PROPERTY(bool peakValuesEnabled READ peakValuesEnabled WRITE setPeakValuesEnabled NOTIFY peakValuesEnabledChanged)
|
||||
|
||||
public:
|
||||
|
|
|
@ -111,7 +111,7 @@ void setupPreferences() {
|
|||
auto setter = [](bool value) { qApp->setSettingConstrainToolbarPosition(value); };
|
||||
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Constrain Toolbar Position to Horizontal Center", getter, setter));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
auto getter = []()->bool { return qApp->getAwayStateWhenFocusLostInVREnabled(); };
|
||||
auto setter = [](bool value) { qApp->setAwayStateWhenFocusLostInVREnabled(value); };
|
||||
|
@ -231,7 +231,7 @@ void setupPreferences() {
|
|||
"installation and system details, and crash events. By allowing High Fidelity to collect "
|
||||
"this information you are helping to improve the product. ", getter, setter));
|
||||
}
|
||||
|
||||
|
||||
static const QString AVATAR_TUNING { "Avatar Tuning" };
|
||||
{
|
||||
auto getter = [myAvatar]()->QString { return myAvatar->getDominantHand(); };
|
||||
|
@ -247,8 +247,8 @@ void setupPreferences() {
|
|||
preference->setStep(0.05f);
|
||||
preference->setDecimals(2);
|
||||
preferences->addPreference(preference);
|
||||
|
||||
// When the Interface is first loaded, this section setupPreferences(); is loaded -
|
||||
|
||||
// When the Interface is first loaded, this section setupPreferences(); is loaded -
|
||||
// causing the myAvatar->getDomainMinScale() and myAvatar->getDomainMaxScale() to get set to incorrect values
|
||||
// which can't be changed across domain switches. Having these values loaded up when you load the Dialog each time
|
||||
// is a way around this, therefore they're not specified here but in the QML.
|
||||
|
@ -271,10 +271,14 @@ void setupPreferences() {
|
|||
|
||||
static const QString FACE_TRACKING{ "Face Tracking" };
|
||||
{
|
||||
#ifdef HAVE_DDE
|
||||
auto getter = []()->float { return DependencyManager::get<DdeFaceTracker>()->getEyeClosingThreshold(); };
|
||||
auto setter = [](float value) { DependencyManager::get<DdeFaceTracker>()->setEyeClosingThreshold(value); };
|
||||
preferences->addPreference(new SliderPreference(FACE_TRACKING, "Eye Closing Threshold", getter, setter));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
auto getter = []()->float { return FaceTracker::getEyeDeflection(); };
|
||||
auto setter = [](float value) { FaceTracker::setEyeDeflection(value); };
|
||||
|
@ -307,14 +311,14 @@ void setupPreferences() {
|
|||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [myAvatar]() -> bool { return myAvatar->hoverWhenUnsupported(); };
|
||||
auto getter = [myAvatar]()->bool { return myAvatar->hoverWhenUnsupported(); };
|
||||
auto setter = [myAvatar](bool value) { myAvatar->setHoverWhenUnsupported(value); };
|
||||
auto preference = new CheckPreference(VR_MOVEMENT, "Hover When Unsupported", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [myAvatar]()->int { return myAvatar->getMovementReference(); };
|
||||
auto setter = [myAvatar](int value) { myAvatar->setMovementReference(value); };
|
||||
auto setter = [myAvatar](int value) { myAvatar->setMovementReference(value); };
|
||||
//auto preference = new CheckPreference(VR_MOVEMENT, "Hand-Relative Movement", getter, setter);
|
||||
auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Movement Direction", getter, setter);
|
||||
QStringList items;
|
||||
|
@ -520,6 +524,5 @@ void setupPreferences() {
|
|||
preference->setStep(10);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ typedef enum LoginErrorTypes
|
|||
- (BOOL) loginShouldSetErrorState;
|
||||
- (void) displayErrorPage;
|
||||
- (void) showLoginScreen;
|
||||
- (NSString*) getLauncherPath;
|
||||
- (ProcessState) currentProccessState;
|
||||
- (void) setCurrentProcessState:(ProcessState) aProcessState;
|
||||
- (void) setLoginErrorState:(LoginError) aLoginError;
|
||||
|
|
|
@ -73,6 +73,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
return filePath;
|
||||
}
|
||||
|
||||
- (NSString*) getLauncherPath
|
||||
{
|
||||
return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Contents/MacOS/"];
|
||||
}
|
||||
|
||||
- (void) extractZipFileAtDestination:(NSString *)destination :(NSString*)file
|
||||
{
|
||||
NSTask* task = [[NSTask alloc] init];
|
||||
|
@ -174,7 +179,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
|
||||
- (NSString*) getAppPath
|
||||
{
|
||||
return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Contents/MacOS/"];
|
||||
return [self getDownloadPathForContentAndScripts];
|
||||
}
|
||||
|
||||
- (BOOL) loginShouldSetErrorState
|
||||
|
@ -317,7 +322,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
|
||||
- (void) launchInterface
|
||||
{
|
||||
NSString* launcherPath = [[self getAppPath] stringByAppendingString:@"HQ Launcher"];
|
||||
NSString* launcherPath = [[self getLauncherPath] stringByAppendingString:@"HQ Launcher"];
|
||||
|
||||
[[Settings sharedSettings] setLauncherPath:launcherPath];
|
||||
[[Settings sharedSettings] save];
|
||||
|
@ -351,8 +356,6 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
}
|
||||
[workspace launchApplicationAtURL:url options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:&error];
|
||||
|
||||
//NSLog(@"arguments %@", [NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments]);
|
||||
|
||||
[NSApp terminate:self];
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,10 @@ CLauncherDlg::CLauncherDlg(CWnd* pParent)
|
|||
EnableD2DSupport();
|
||||
}
|
||||
|
||||
CLauncherDlg::~CLauncherDlg() {
|
||||
theApp._manager.closeLog();
|
||||
}
|
||||
|
||||
void CLauncherDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
DDX_Control(pDX, IDC_BUTTON_NEXT, m_btnNext);
|
||||
|
@ -154,25 +158,54 @@ HCURSOR CLauncherDlg::OnQueryDragIcon()
|
|||
}
|
||||
|
||||
void CLauncherDlg::startProcess() {
|
||||
if (theApp._manager.needsUpdate()) {
|
||||
setDrawDialog(DrawStep::DrawProcessUpdate);
|
||||
} else {
|
||||
setDrawDialog(DrawStep::DrawProcessSetup);
|
||||
}
|
||||
|
||||
CString installDir;
|
||||
theApp._manager.getAndCreatePaths(LauncherManager::PathType::Interface_Directory, installDir);
|
||||
CString interfaceExe = installDir += "\\interface.exe";
|
||||
if (!theApp._manager.isLoggedIn()) {
|
||||
theApp._manager.downloadContent();
|
||||
} else {
|
||||
theApp._manager.downloadApplication();
|
||||
}
|
||||
if (theApp._manager.needsUpdate()) {
|
||||
theApp._manager.addToLog(_T("Starting Process Update"));
|
||||
setDrawDialog(DrawStep::DrawProcessUpdate);
|
||||
} else {
|
||||
theApp._manager.addToLog(_T("Starting Process Setup"));
|
||||
setDrawDialog(DrawStep::DrawProcessSetup);
|
||||
}
|
||||
theApp._manager.addToLog(_T("Deleting directories before install"));
|
||||
|
||||
CString installDir;
|
||||
theApp._manager.getAndCreatePaths(LauncherManager::PathType::Interface_Directory, installDir);
|
||||
CString downloadDir;
|
||||
theApp._manager.getAndCreatePaths(LauncherManager::PathType::Download_Directory, downloadDir);
|
||||
|
||||
LauncherUtils::deleteDirectoriesOnThread(installDir, downloadDir, [&](int error) {
|
||||
LauncherUtils::DeleteDirError deleteError = (LauncherUtils::DeleteDirError)error;
|
||||
switch(error) {
|
||||
case LauncherUtils::DeleteDirError::NoErrorDeleting:
|
||||
theApp._manager.addToLog(_T("Install directory deleted."));
|
||||
theApp._manager.addToLog(_T("Downloads directory deleted."));
|
||||
if (!theApp._manager.isLoggedIn()) {
|
||||
theApp._manager.addToLog(_T("Downloading Content"));
|
||||
theApp._manager.downloadContent();
|
||||
} else {
|
||||
theApp._manager.addToLog(_T("Downloading App"));
|
||||
theApp._manager.downloadApplication();
|
||||
}
|
||||
break;
|
||||
case LauncherUtils::DeleteDirError::ErrorDeletingBothDirs:
|
||||
theApp._manager.addToLog(_T("Error deleting directories."));
|
||||
break;
|
||||
case LauncherUtils::DeleteDirError::ErrorDeletingApplicationDir:
|
||||
theApp._manager.addToLog(_T("Error deleting application directory."));
|
||||
break;
|
||||
case LauncherUtils::DeleteDirError::ErrorDeletingDownloadsDir:
|
||||
theApp._manager.addToLog(_T("Error deleting downloads directory."));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
BOOL CLauncherDlg::getHQInfo(const CString& orgname) {
|
||||
CString hash;
|
||||
LauncherUtils::hMac256(orgname, LAUNCHER_HMAC_SECRET, hash);
|
||||
CString lowerOrgName = orgname;
|
||||
lowerOrgName.MakeLower();
|
||||
LauncherUtils::hMac256(lowerOrgName, LAUNCHER_HMAC_SECRET, hash);
|
||||
return theApp._manager.readOrganizationJSON(hash) == LauncherUtils::ResponseError::NoError;
|
||||
}
|
||||
|
||||
|
@ -181,33 +214,44 @@ afx_msg void CLauncherDlg::OnTroubleClicked() {
|
|||
}
|
||||
|
||||
afx_msg void CLauncherDlg::OnNextClicked() {
|
||||
if (_drawStep != DrawStep::DrawChoose) {
|
||||
CString token;
|
||||
CString username, password, orgname;
|
||||
m_orgname.GetWindowTextW(orgname);
|
||||
m_username.GetWindowTextW(username);
|
||||
m_password.GetWindowTextW(password);
|
||||
LauncherUtils::ResponseError error;
|
||||
if (orgname.GetLength() > 0 && username.GetLength() > 0 && password.GetLength() > 0) {
|
||||
if (getHQInfo(orgname)) {
|
||||
error = theApp._manager.getAccessTokenForCredentials(username, password);
|
||||
if (error == LauncherUtils::ResponseError::NoError) {
|
||||
setDrawDialog(DrawStep::DrawChoose);
|
||||
} else if (error == LauncherUtils::ResponseError::BadCredentials) {
|
||||
setDrawDialog(DrawStep::DrawLoginErrorCred);
|
||||
} else {
|
||||
MessageBox(L"Error Reading or retreaving response.", L"Network Error", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
} else {
|
||||
setDrawDialog(DrawStep::DrawLoginErrorOrg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CString displayName;
|
||||
m_username.GetWindowTextW(displayName);
|
||||
theApp._manager.setDisplayName(displayName);
|
||||
startProcess();
|
||||
}
|
||||
if (_drawStep != DrawStep::DrawChoose) {
|
||||
CString token;
|
||||
CString username, password, orgname;
|
||||
m_orgname.GetWindowTextW(orgname);
|
||||
m_username.GetWindowTextW(username);
|
||||
m_password.GetWindowTextW(password);
|
||||
|
||||
username = LauncherUtils::urlEncodeString(username);
|
||||
password = LauncherUtils::urlEncodeString(password);
|
||||
LauncherUtils::ResponseError error;
|
||||
if (orgname.GetLength() > 0 && username.GetLength() > 0 && password.GetLength() > 0) {
|
||||
theApp._manager.addToLog(_T("Trying to get organization data"));
|
||||
if (getHQInfo(orgname)) {
|
||||
theApp._manager.addToLog(_T("Organization data received."));
|
||||
theApp._manager.addToLog(_T("Trying to log in with credentials"));
|
||||
error = theApp._manager.getAccessTokenForCredentials(username, password);
|
||||
if (error == LauncherUtils::ResponseError::NoError) {
|
||||
theApp._manager.addToLog(_T("Logged in correctly."));
|
||||
setDrawDialog(DrawStep::DrawChoose);
|
||||
} else if (error == LauncherUtils::ResponseError::BadCredentials) {
|
||||
theApp._manager.addToLog(_T("Bad credentials. Try again"));
|
||||
setDrawDialog(DrawStep::DrawLoginErrorCred);
|
||||
} else {
|
||||
theApp._manager.addToLog(_T("Error Reading or retrieving response."));
|
||||
MessageBox(L"Error Reading or retrieving response.", L"Network Error", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
} else {
|
||||
theApp._manager.addToLog(_T("Organization name does not exist."));
|
||||
setDrawDialog(DrawStep::DrawLoginErrorOrg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CString displayName;
|
||||
m_username.GetWindowTextW(displayName);
|
||||
theApp._manager.setDisplayName(displayName);
|
||||
theApp._manager.addToLog(_T("Setting display name: " + displayName));
|
||||
startProcess();
|
||||
}
|
||||
}
|
||||
|
||||
void CLauncherDlg::drawBackground(CHwndRenderTarget* pRenderTarget) {
|
||||
|
@ -534,11 +578,13 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
|
|||
}
|
||||
if (_showSplash) {
|
||||
if (_splashStep == 0){
|
||||
if (theApp._manager.needsUninstall()) {
|
||||
setDrawDialog(DrawStep::DrawProcessUninstall);
|
||||
} else {
|
||||
setDrawDialog(DrawStep::DrawLogo);
|
||||
}
|
||||
if (theApp._manager.needsUninstall()) {
|
||||
theApp._manager.addToLog(_T("Waiting to uninstall"));
|
||||
setDrawDialog(DrawStep::DrawProcessUninstall);
|
||||
} else {
|
||||
theApp._manager.addToLog(_T("Start splash screen"));
|
||||
setDrawDialog(DrawStep::DrawLogo);
|
||||
}
|
||||
} else if (_splashStep > 100) {
|
||||
_showSplash = false;
|
||||
if (theApp._manager.shouldShutDown()) {
|
||||
|
@ -551,6 +597,7 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
|
|||
theApp._manager.uninstallApplication();
|
||||
exit(0);
|
||||
} else {
|
||||
theApp._manager.addToLog(_T("Starting login"));
|
||||
setDrawDialog(DrawStep::DrawLoginLogin);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
};
|
||||
|
||||
CLauncherDlg(CWnd* pParent = nullptr);
|
||||
~CLauncherDlg();
|
||||
virtual BOOL PreTranslateMessage(MSG* pMsg);
|
||||
|
||||
void setDrawDialog(DrawStep step, BOOL isUpdate = FALSE);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <time.h>
|
||||
#include <fstream>
|
||||
|
||||
#include "LauncherManager.h"
|
||||
|
@ -24,19 +25,57 @@ LauncherManager::~LauncherManager()
|
|||
}
|
||||
|
||||
void LauncherManager::init() {
|
||||
getMostRecentBuild(_latestApplicationURL, _latestVersion);
|
||||
CString currentVersion;
|
||||
if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) {
|
||||
if (_latestVersion.Compare(currentVersion) == 0) {
|
||||
launchApplication();
|
||||
_shouldShutdown = TRUE;
|
||||
} else {
|
||||
_shouldUpdate = TRUE;
|
||||
}
|
||||
}
|
||||
initLog();
|
||||
addToLog(_T("Getting most recent build"));
|
||||
getMostRecentBuild(_latestApplicationURL, _latestVersion);
|
||||
addToLog(_T("Latest version: ") + _latestVersion);
|
||||
CString currentVersion;
|
||||
if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) {
|
||||
addToLog(_T("Installed version: ") + currentVersion);
|
||||
if (_latestVersion.Compare(currentVersion) == 0) {
|
||||
addToLog(_T("Already running most recent build. Launching interface.exe"));
|
||||
launchApplication();
|
||||
_shouldShutdown = TRUE;
|
||||
} else {
|
||||
addToLog(_T("New build found. Updating"));
|
||||
_shouldUpdate = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LauncherManager::initLog() {
|
||||
CString logPath;
|
||||
auto result = getAndCreatePaths(PathType::Launcher_Directory, logPath);
|
||||
if (result) {
|
||||
logPath += _T("log.txt");
|
||||
return result = _logFile.Open(logPath, CFile::modeCreate | CFile::modeReadWrite);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LauncherManager::addToLog(const CString& line) {
|
||||
if (_logFile.m_hFile != CStdioFile::hFileNull) {
|
||||
char buff[100];
|
||||
time_t now = time(0);
|
||||
tm ltm;
|
||||
localtime_s(<m, &now);
|
||||
|
||||
strftime(buff, 100, "%Y-%m-%d %H:%M:%S", <m);
|
||||
CString timeStr = CString(buff);
|
||||
_logFile.WriteString(timeStr + _T(" ") + line + _T("\n"));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void LauncherManager::closeLog() {
|
||||
if (_logFile.m_hFile != CStdioFile::hFileNull) {
|
||||
_logFile.Close();
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LauncherManager::installLauncher() {
|
||||
addToLog(_T("Installing Launcher."));
|
||||
CString appPath;
|
||||
BOOL result = getAndCreatePaths(PathType::Running_Path, appPath);
|
||||
if (!result) {
|
||||
|
@ -60,6 +99,7 @@ BOOL LauncherManager::installLauncher() {
|
|||
CopyFile(appPath, instalationPath, FALSE);
|
||||
}
|
||||
} else if (_shouldUninstall) {
|
||||
addToLog(_T("Launching uninstall mode."));
|
||||
CString tempPath;
|
||||
if (getAndCreatePaths(PathType::Temp_Directory, tempPath)) {
|
||||
tempPath += _T("\\HQ_uninstaller_tmp.exe");
|
||||
|
@ -73,6 +113,7 @@ BOOL LauncherManager::installLauncher() {
|
|||
|
||||
BOOL LauncherManager::createShortcuts() {
|
||||
CString desktopLnkPath;
|
||||
addToLog(_T("Creating shortcuts."));
|
||||
getAndCreatePaths(PathType::Desktop_Directory, desktopLnkPath);
|
||||
desktopLnkPath += _T("\\HQ Launcher.lnk");
|
||||
CString installDir;
|
||||
|
@ -100,6 +141,7 @@ BOOL LauncherManager::createShortcuts() {
|
|||
|
||||
BOOL LauncherManager::deleteShortcuts() {
|
||||
CString desktopLnkPath;
|
||||
addToLog(_T("Deleting shortcuts."));
|
||||
getAndCreatePaths(PathType::Desktop_Directory, desktopLnkPath);
|
||||
desktopLnkPath += _T("\\HQ Launcher.lnk");
|
||||
BOOL success = LauncherUtils::deleteFileOrDirectory(desktopLnkPath);
|
||||
|
@ -353,13 +395,17 @@ BOOL LauncherManager::uninstallApplication() {
|
|||
|
||||
void LauncherManager::onZipExtracted(ZipType type, int size) {
|
||||
if (type == ZipType::ZipContent) {
|
||||
addToLog(_T("Downloading application."));
|
||||
downloadApplication();
|
||||
} else if (type == ZipType::ZipApplication) {
|
||||
createShortcuts();
|
||||
CString versionPath;
|
||||
getAndCreatePaths(LauncherManager::PathType::Launcher_Directory, versionPath);
|
||||
createConfigJSON();
|
||||
addToLog(_T("Creating config.json"));
|
||||
createConfigJSON();
|
||||
addToLog(_T("Launching application."));
|
||||
launchApplication(_tokensJSON);
|
||||
addToLog(_T("Creating registry keys."));
|
||||
createApplicationRegistryKeys(size);
|
||||
_shouldShutdown = TRUE;
|
||||
}
|
||||
|
@ -377,8 +423,10 @@ BOOL LauncherManager::extractApplication() {
|
|||
|
||||
void LauncherManager::onFileDownloaded(DownloadType type) {
|
||||
if (type == DownloadType::DownloadContent) {
|
||||
addToLog(_T("Installing content."));
|
||||
installContent();
|
||||
} else if (type == DownloadType::DownloadApplication) {
|
||||
addToLog(_T("Installing application."));
|
||||
extractApplication();
|
||||
}
|
||||
}
|
||||
|
@ -412,6 +460,7 @@ BOOL LauncherManager::downloadFile(DownloadType type, const CString& url, CStrin
|
|||
}
|
||||
|
||||
BOOL LauncherManager::downloadContent() {
|
||||
addToLog(_T("Downloading content."));
|
||||
CString contentURL = getContentURL();
|
||||
return downloadFile(DownloadType::DownloadContent, contentURL, _contentZipPath);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,9 @@ public:
|
|||
LauncherManager();
|
||||
~LauncherManager();
|
||||
void init();
|
||||
BOOL initLog();
|
||||
BOOL addToLog(const CString& line);
|
||||
void closeLog();
|
||||
BOOL getAndCreatePaths(PathType type, CString& outPath);
|
||||
BOOL getInstalledVersion(const CString& path, CString& version);
|
||||
BOOL isApplicationInstalled(CString& version, CString& domain,
|
||||
|
@ -105,5 +108,6 @@ private:
|
|||
BOOL _shouldUpdate{ FALSE };
|
||||
BOOL _shouldUninstall{ FALSE };
|
||||
BOOL _shouldShutdown{ FALSE };
|
||||
CStdioFile _logFile;
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,24 @@
|
|||
|
||||
#include "LauncherUtils.h"
|
||||
|
||||
CString LauncherUtils::urlEncodeString(const CString& url) {
|
||||
std::map<CString, CString> specialCharsMap = { { _T("$"), _T("%24") }, { _T(" "), _T("%20") }, { _T("#"), _T("%23") },
|
||||
{ _T("@"), _T("%40") }, { _T("`"), _T("%60") }, { _T("&"), _T("%26") },
|
||||
{ _T("/"), _T("%2F") }, { _T(":"), _T("%3A") }, { _T(";"), _T("%3B") },
|
||||
{ _T("<"), _T("%3C") }, { _T(">"), _T("%3E") }, { _T("="), _T("%3D") },
|
||||
{ _T("?"), _T("%3F") }, { _T("["), _T("%5B") }, { _T("\\"), _T("%5C") },
|
||||
{ _T("]"), _T("%5D") }, { _T("^"), _T("%5E") }, { _T("{"), _T("%7B") },
|
||||
{ _T("|"), _T("%7C") }, { _T("}"), _T("%7D") }, { _T("~"), _T("%7E") },
|
||||
{ _T("“"), _T("%22") }, { _T("‘"), _T("%27") }, { _T("+"), _T("%2B") },
|
||||
{ _T(","), _T("%2C") } };
|
||||
CString stringOut = url;
|
||||
stringOut.Replace(_T("%"), _T("%25"));
|
||||
for (auto& itr = specialCharsMap.begin(); itr != specialCharsMap.end(); itr++) {
|
||||
stringOut.Replace(itr->first, itr->second);
|
||||
}
|
||||
return stringOut;
|
||||
}
|
||||
|
||||
BOOL LauncherUtils::IsProcessRunning(const wchar_t *processName) {
|
||||
bool exists = false;
|
||||
PROCESSENTRY32 entry;
|
||||
|
@ -374,6 +392,19 @@ DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DWORD WINAPI LauncherUtils::deleteDirectoriesThread(LPVOID lpParameter) {
|
||||
DeleteThreadData& data = *((DeleteThreadData*)lpParameter);
|
||||
DeleteDirError error = DeleteDirError::NoErrorDeleting;
|
||||
if (!LauncherUtils::deleteFileOrDirectory(data._applicationDir)) {
|
||||
error = DeleteDirError::ErrorDeletingApplicationDir;
|
||||
}
|
||||
if (!LauncherUtils::deleteFileOrDirectory(data._downloadsDir)) {
|
||||
error = error == NoError ? DeleteDirError::ErrorDeletingDownloadsDir : DeleteDirError::ErrorDeletingBothDirs;
|
||||
}
|
||||
data.callback(error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL LauncherUtils::unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, std::function<void(int, int)> callback) {
|
||||
DWORD myThreadID;
|
||||
UnzipThreadData* unzipThreadData = new UnzipThreadData();
|
||||
|
@ -402,4 +433,20 @@ BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CSt
|
|||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LauncherUtils::deleteDirectoriesOnThread(const CString& applicationDir,
|
||||
const CString& downloadsDir,
|
||||
std::function<void(int)> callback) {
|
||||
DWORD myThreadID;
|
||||
DeleteThreadData* deleteThreadData = new DeleteThreadData();
|
||||
deleteThreadData->_applicationDir = applicationDir;
|
||||
deleteThreadData->_downloadsDir = downloadsDir;
|
||||
deleteThreadData->setCallback(callback);
|
||||
HANDLE myHandle = CreateThread(0, 0, deleteDirectoriesThread, deleteThreadData, 0, &myThreadID);
|
||||
if (myHandle) {
|
||||
CloseHandle(myHandle);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,13 @@ public:
|
|||
NoError
|
||||
};
|
||||
|
||||
enum DeleteDirError {
|
||||
NoErrorDeleting = 0,
|
||||
ErrorDeletingApplicationDir,
|
||||
ErrorDeletingDownloadsDir,
|
||||
ErrorDeletingBothDirs
|
||||
};
|
||||
|
||||
struct DownloadThreadData {
|
||||
int _type;
|
||||
CString _url;
|
||||
|
@ -52,6 +59,13 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct DeleteThreadData {
|
||||
CString _applicationDir;
|
||||
CString _downloadsDir;
|
||||
std::function<void(int)> callback;
|
||||
void setCallback(std::function<void(int)> fn) { callback = std::bind(fn, std::placeholders::_1); }
|
||||
};
|
||||
|
||||
static BOOL parseJSON(const CString& jsonTxt, Json::Value& jsonObject);
|
||||
static ResponseError makeHTTPCall(const CString& callerName, const CString& mainUrl,
|
||||
const CString& dirUrl, const CString& contentType,
|
||||
|
@ -69,9 +83,14 @@ public:
|
|||
static BOOL deleteRegistryKey(const CString& registryPath);
|
||||
static BOOL unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, std::function<void(int, int)> callback);
|
||||
static BOOL downloadFileOnThread(int type, const CString& url, const CString& file, std::function<void(int)> callback);
|
||||
static BOOL deleteDirectoriesOnThread(const CString& applicationDir,
|
||||
const CString& downloadsDir,
|
||||
std::function<void(int)> callback);
|
||||
static CString urlEncodeString(const CString& url);
|
||||
|
||||
private:
|
||||
// Threads
|
||||
static DWORD WINAPI unzipThread(LPVOID lpParameter);
|
||||
static DWORD WINAPI downloadThread(LPVOID lpParameter);
|
||||
static DWORD WINAPI deleteDirectoriesThread(LPVOID lpParameter);
|
||||
};
|
|
@ -170,9 +170,9 @@ public:
|
|||
glFinish();
|
||||
}
|
||||
currentPlugin = newPlugin;
|
||||
_newPluginQueue.pop();
|
||||
_condition.notify_one();
|
||||
}
|
||||
_newPluginQueue.pop();
|
||||
_condition.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -257,7 +257,7 @@ ShapeKey MaterialEntityRenderer::getShapeKey() {
|
|||
|
||||
bool isTranslucent = drawMaterialKey.isTranslucent();
|
||||
bool hasTangents = drawMaterialKey.isNormalMap();
|
||||
bool hasLightmap = drawMaterialKey.isLightmapMap();
|
||||
bool hasLightmap = drawMaterialKey.isLightMap();
|
||||
bool isUnlit = drawMaterialKey.isUnlit();
|
||||
|
||||
ShapeKey::Builder builder;
|
||||
|
@ -270,7 +270,7 @@ ShapeKey MaterialEntityRenderer::getShapeKey() {
|
|||
builder.withTangents();
|
||||
}
|
||||
if (hasLightmap) {
|
||||
builder.withLightmap();
|
||||
builder.withLightMap();
|
||||
}
|
||||
if (isUnlit) {
|
||||
builder.withUnlit();
|
||||
|
|
|
@ -197,7 +197,7 @@ ShapeKey ShapeEntityRenderer::getShapeKey() {
|
|||
|
||||
bool isTranslucent = drawMaterialKey.isTranslucent();
|
||||
bool hasTangents = drawMaterialKey.isNormalMap();
|
||||
bool hasLightmap = drawMaterialKey.isLightmapMap();
|
||||
bool hasLightmap = drawMaterialKey.isLightMap();
|
||||
bool isUnlit = drawMaterialKey.isUnlit();
|
||||
|
||||
ShapeKey::Builder builder;
|
||||
|
@ -210,7 +210,7 @@ ShapeKey ShapeEntityRenderer::getShapeKey() {
|
|||
builder.withTangents();
|
||||
}
|
||||
if (hasLightmap) {
|
||||
builder.withLightmap();
|
||||
builder.withLightMap();
|
||||
}
|
||||
if (isUnlit) {
|
||||
builder.withUnlit();
|
||||
|
|
|
@ -88,7 +88,7 @@ private:
|
|||
// emissive, albedo
|
||||
// urls to textures:
|
||||
// emissiveMap, albedoMap (set opacityMap = albedoMap for transparency), metallicMap or specularMap, roughnessMap or glossMap,
|
||||
// normalMap or bumpMap, occlusionMap, lightmapMap (broken, FIXME), scatteringMap (only works if normal mapped)
|
||||
// normalMap or bumpMap, occlusionMap, lightMap (broken, FIXME), scatteringMap (only works if normal mapped)
|
||||
QString _materialURL;
|
||||
// Type of material. "uv" or "projected".
|
||||
MaterialMappingMode _materialMappingMode { UV };
|
||||
|
|
|
@ -841,7 +841,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
parents[child] = nodecount;
|
||||
}
|
||||
sortedNodes.push_back(nodecount);
|
||||
nodecount++;
|
||||
++nodecount;
|
||||
}
|
||||
|
||||
|
||||
|
@ -857,7 +857,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
_file.nodes[nodecount].transforms.push_back(getModelTransform(parentNode));
|
||||
parentIndex = parents[parentIndex];
|
||||
}
|
||||
nodecount++;
|
||||
++nodecount;
|
||||
}
|
||||
|
||||
|
||||
|
@ -871,7 +871,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
int parentIndex = parents[currentNode];
|
||||
if (parentIndex == -1 || hasBeenSorted[parentIndex]) {
|
||||
hasBeenSorted[currentNode] = true;
|
||||
i++;
|
||||
++i;
|
||||
} else {
|
||||
int j = i + 1; // index of node to be sorted
|
||||
while (j < numNodes) {
|
||||
|
@ -882,10 +882,10 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
hasBeenSorted[nextNode] = true;
|
||||
sortedNodes[i] = nextNode;
|
||||
sortedNodes[j] = currentNode;
|
||||
i++;
|
||||
++i;
|
||||
currentNode = sortedNodes[i];
|
||||
}
|
||||
j++;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -894,7 +894,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
// Build map from original to new indices
|
||||
QVector<int> originalToNewNodeIndexMap;
|
||||
originalToNewNodeIndexMap.fill(-1, numNodes);
|
||||
for (int i = 0; i < numNodes; i++) {
|
||||
for (int i = 0; i < numNodes; ++i) {
|
||||
originalToNewNodeIndexMap[sortedNodes[i]] = i;
|
||||
}
|
||||
|
||||
|
@ -903,6 +903,8 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
HFMJoint joint;
|
||||
joint.distanceToParent = 0;
|
||||
hfmModel.jointIndices["x"] = numNodes;
|
||||
QVector<glm::mat4> globalTransforms;
|
||||
globalTransforms.resize(numNodes);
|
||||
|
||||
for (int nodeIndex : sortedNodes) {
|
||||
auto& node = _file.nodes[nodeIndex];
|
||||
|
@ -917,6 +919,13 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
glm::vec3 scale = extractScale(joint.transform);
|
||||
joint.postTransform = glm::scale(glm::mat4(), scale);
|
||||
|
||||
joint.parentIndex = parents[nodeIndex];
|
||||
globalTransforms[nodeIndex] = joint.transform;
|
||||
if (joint.parentIndex != -1) {
|
||||
globalTransforms[nodeIndex] = globalTransforms[joint.parentIndex] * globalTransforms[nodeIndex];
|
||||
joint.parentIndex = originalToNewNodeIndexMap[joint.parentIndex];
|
||||
}
|
||||
|
||||
joint.name = node.name;
|
||||
joint.isSkeletonJoint = false;
|
||||
hfmModel.joints.push_back(joint);
|
||||
|
@ -924,20 +933,30 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
hfmModel.shapeVertices.resize(hfmModel.joints.size());
|
||||
|
||||
|
||||
// get offset transform from mapping
|
||||
float unitScaleFactor = 1.0f;
|
||||
float offsetScale = mapping.value("scale", 1.0f).toFloat() * unitScaleFactor;
|
||||
glm::quat offsetRotation = glm::quat(glm::radians(glm::vec3(mapping.value("rx").toFloat(), mapping.value("ry").toFloat(), mapping.value("rz").toFloat())));
|
||||
hfmModel.offset = glm::translate(glm::mat4(), glm::vec3(mapping.value("tx").toFloat(), mapping.value("ty").toFloat(), mapping.value("tz").toFloat())) *
|
||||
glm::mat4_cast(offsetRotation) * glm::scale(glm::mat4(), glm::vec3(offsetScale, offsetScale, offsetScale));
|
||||
|
||||
|
||||
// Build skeleton
|
||||
std::vector<glm::mat4> jointInverseBindTransforms;
|
||||
std::vector<glm::mat4> globalBindTransforms;
|
||||
jointInverseBindTransforms.resize(numNodes);
|
||||
globalBindTransforms.resize(numNodes);
|
||||
|
||||
hfmModel.hasSkeletonJoints = !_file.skins.isEmpty();
|
||||
if (hfmModel.hasSkeletonJoints) {
|
||||
hfmModel.hasSkeletonJoints = true;
|
||||
std::vector<std::vector<float>> inverseBindValues;
|
||||
getSkinInverseBindMatrices(inverseBindValues);
|
||||
|
||||
for (int jointIndex = 0; jointIndex < numNodes; jointIndex++) {
|
||||
for (int jointIndex = 0; jointIndex < numNodes; ++jointIndex) {
|
||||
int nodeIndex = sortedNodes[jointIndex];
|
||||
auto joint = hfmModel.joints[jointIndex];
|
||||
|
||||
for (int s = 0; s < _file.skins.size(); s++) {
|
||||
for (int s = 0; s < _file.skins.size(); ++s) {
|
||||
const auto& skin = _file.skins[s];
|
||||
int matrixIndex = skin.joints.indexOf(nodeIndex);
|
||||
joint.isSkeletonJoint = skin.joints.contains(nodeIndex);
|
||||
|
@ -954,6 +973,10 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
} else {
|
||||
jointInverseBindTransforms[jointIndex] = glm::mat4();
|
||||
}
|
||||
globalBindTransforms[jointIndex] = jointInverseBindTransforms[jointIndex];
|
||||
if (joint.parentIndex != -1) {
|
||||
globalBindTransforms[jointIndex] = globalBindTransforms[joint.parentIndex] * globalBindTransforms[jointIndex];
|
||||
}
|
||||
glm::vec3 bindTranslation = extractTranslation(hfmModel.offset * glm::inverse(jointInverseBindTransforms[jointIndex]));
|
||||
hfmModel.bindExtents.addPoint(bindTranslation);
|
||||
}
|
||||
|
@ -962,13 +985,13 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
}
|
||||
|
||||
|
||||
//Build materials
|
||||
// Build materials
|
||||
QVector<QString> materialIDs;
|
||||
QString unknown = "Default";
|
||||
int ukcount = 0;
|
||||
foreach(auto material, _file.materials) {
|
||||
if (!material.defined["name"]) {
|
||||
QString name = unknown + QString::number(ukcount++);
|
||||
QString name = unknown + QString::number(++ukcount);
|
||||
material.name = name;
|
||||
material.defined.insert("name", true);
|
||||
}
|
||||
|
@ -977,7 +1000,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
materialIDs.push_back(mid);
|
||||
}
|
||||
|
||||
for (int i = 0; i < materialIDs.size(); i++) {
|
||||
for (int i = 0; i < materialIDs.size(); ++i) {
|
||||
QString& matid = materialIDs[i];
|
||||
hfmModel.materials[matid] = HFMMaterial();
|
||||
HFMMaterial& hfmMaterial = hfmModel.materials[matid];
|
||||
|
@ -989,6 +1012,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
|
||||
// Build meshes
|
||||
nodecount = 0;
|
||||
hfmModel.meshExtents.reset();
|
||||
for (int nodeIndex : sortedNodes) {
|
||||
auto& node = _file.nodes[nodeIndex];
|
||||
|
||||
|
@ -1003,7 +1027,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
cluster.inverseBindTransform = Transform(cluster.inverseBindMatrix);
|
||||
mesh.clusters.append(cluster);
|
||||
} else { // skinned model
|
||||
for (int j = 0; j < numNodes; j++) {
|
||||
for (int j = 0; j < numNodes; ++j) {
|
||||
HFMCluster cluster;
|
||||
cluster.jointIndex = j;
|
||||
cluster.inverseBindMatrix = jointInverseBindTransforms[j];
|
||||
|
@ -1300,7 +1324,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
}
|
||||
|
||||
QVector<int> validatedIndices;
|
||||
for (int n = 0; n < indices.count(); n++) {
|
||||
for (int n = 0; n < indices.count(); ++n) {
|
||||
if (indices[n] < partVerticesCount) {
|
||||
validatedIndices.push_back(indices[n] + prevMeshVerticesCount);
|
||||
} else {
|
||||
|
@ -1332,7 +1356,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
}
|
||||
} else {
|
||||
if (meshAttributes.contains("TANGENT")) {
|
||||
for (int i = 0; i < partVerticesCount; i++) {
|
||||
for (int i = 0; i < partVerticesCount; ++i) {
|
||||
mesh.tangents.push_back(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
|
@ -1344,7 +1368,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
}
|
||||
} else {
|
||||
if (meshAttributes.contains("TEXCOORD_0")) {
|
||||
for (int i = 0; i < partVerticesCount; i++) {
|
||||
for (int i = 0; i < partVerticesCount; ++i) {
|
||||
mesh.texCoords.push_back(glm::vec2(0.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
|
@ -1356,7 +1380,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
}
|
||||
} else {
|
||||
if (meshAttributes.contains("TEXCOORD_1")) {
|
||||
for (int i = 0; i < partVerticesCount; i++) {
|
||||
for (int i = 0; i < partVerticesCount; ++i) {
|
||||
mesh.texCoords1.push_back(glm::vec2(0.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
|
@ -1368,7 +1392,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
}
|
||||
} else {
|
||||
if (meshAttributes.contains("COLOR_0")) {
|
||||
for (int i = 0; i < partVerticesCount; i++) {
|
||||
for (int i = 0; i < partVerticesCount; ++i) {
|
||||
mesh.colors.push_back(glm::vec3(1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
|
@ -1398,8 +1422,8 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
}
|
||||
} else {
|
||||
if (meshAttributes.contains("JOINTS_0")) {
|
||||
for (int i = 0; i < partVerticesCount; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int i = 0; i < partVerticesCount; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
clusterJoints.push_back(0);
|
||||
}
|
||||
}
|
||||
|
@ -1430,9 +1454,9 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
}
|
||||
} else {
|
||||
if (meshAttributes.contains("WEIGHTS_0")) {
|
||||
for (int i = 0; i < partVerticesCount; i++) {
|
||||
for (int i = 0; i < partVerticesCount; ++i) {
|
||||
clusterWeights.push_back(1.0f);
|
||||
for (int j = 1; j < 4; j++) {
|
||||
for (int j = 1; j < 4; ++j) {
|
||||
clusterWeights.push_back(0.0f);
|
||||
}
|
||||
}
|
||||
|
@ -1448,12 +1472,12 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
int numVertices = mesh.vertices.size() - prevMeshVerticesCount;
|
||||
|
||||
// Append new cluster indices and weights for this mesh part
|
||||
for (int i = 0; i < numVertices * WEIGHTS_PER_VERTEX; i++) {
|
||||
for (int i = 0; i < numVertices * WEIGHTS_PER_VERTEX; ++i) {
|
||||
mesh.clusterIndices.push_back(mesh.clusters.size() - 1);
|
||||
mesh.clusterWeights.push_back(0);
|
||||
}
|
||||
|
||||
for (int c = 0; c < clusterJoints.size(); c++) {
|
||||
for (int c = 0; c < clusterJoints.size(); ++c) {
|
||||
mesh.clusterIndices[prevMeshClusterIndexCount + c] =
|
||||
originalToNewNodeIndexMap[_file.skins[node.skin].joints[clusterJoints[c]]];
|
||||
}
|
||||
|
@ -1474,6 +1498,20 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
} else {
|
||||
mesh.clusterWeights[prevMeshClusterWeightCount + j] = (uint16_t)((float)(UINT16_MAX) + ALMOST_HALF);
|
||||
}
|
||||
for (int clusterIndex = 0; clusterIndex < mesh.clusters.size() - 1; ++clusterIndex) {
|
||||
ShapeVertices& points = hfmModel.shapeVertices.at(clusterIndex);
|
||||
glm::vec3 globalMeshScale = extractScale(globalTransforms[nodeIndex]);
|
||||
const glm::mat4 meshToJoint = glm::scale(glm::mat4(), globalMeshScale) * jointInverseBindTransforms[clusterIndex];
|
||||
|
||||
const float EXPANSION_WEIGHT_THRESHOLD = 0.25f;
|
||||
if (mesh.clusterWeights[j] >= EXPANSION_WEIGHT_THRESHOLD) {
|
||||
// TODO: fix transformed vertices being pushed back
|
||||
auto& vertex = mesh.vertices[i];
|
||||
const glm::mat4 vertexTransform = meshToJoint * (glm::translate(glm::mat4(), vertex));
|
||||
glm::vec3 transformedVertex = hfmModel.joints[clusterIndex].translation * (extractTranslation(vertexTransform));
|
||||
points.push_back(transformedVertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1484,7 +1522,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
|
||||
// populate the texture coordinates if they don't exist
|
||||
if (mesh.texCoords.size() == 0 && !hfmModel.hasSkeletonJoints) {
|
||||
for (int i = 0; i < part.triangleIndices.size(); i++) { mesh.texCoords.push_back(glm::vec2(0.0, 1.0)); }
|
||||
for (int i = 0; i < part.triangleIndices.size(); ++i) { mesh.texCoords.push_back(glm::vec2(0.0, 1.0)); }
|
||||
}
|
||||
|
||||
// Build morph targets (blend shapes)
|
||||
|
@ -1495,7 +1533,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
hifi::VariantHash blendshapeMappings = mapping.value("bs").toHash();
|
||||
QMultiHash<QString, WeightedIndex> blendshapeIndices;
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
for (int i = 0;; ++i) {
|
||||
hifi::ByteArray blendshapeName = FACESHIFT_BLENDSHAPES[i];
|
||||
if (blendshapeName.isEmpty()) {
|
||||
break;
|
||||
|
@ -1515,7 +1553,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
auto names = _file.meshes[node.mesh].extras.targetNames;
|
||||
QVector<double> weights = _file.meshes[node.mesh].weights;
|
||||
|
||||
for (int weightedIndex = 0; weightedIndex < values.size(); weightedIndex++) {
|
||||
for (int weightedIndex = 0; weightedIndex < values.size(); ++weightedIndex) {
|
||||
float weight = 0.1f;
|
||||
int indexFromMapping = weightedIndex;
|
||||
int targetIndex = weightedIndex;
|
||||
|
@ -1556,32 +1594,17 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
} else {
|
||||
blendshape.vertices[count] = blendshape.vertices[count] + vertices[i];
|
||||
blendshape.normals[count] = blendshape.normals[count] + normals[i];
|
||||
count++;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int clusterIndex = 0; clusterIndex < mesh.clusters.size() - 1; clusterIndex++) {
|
||||
ShapeVertices& points = hfmModel.shapeVertices.at(clusterIndex);
|
||||
for (glm::vec3 vertex : mesh.vertices) {
|
||||
points.push_back(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
mesh.meshExtents.reset();
|
||||
foreach(const glm::vec3& vertex, mesh.vertices) {
|
||||
mesh.meshExtents.addPoint(vertex);
|
||||
hfmModel.meshExtents.addPoint(vertex);
|
||||
}
|
||||
|
||||
mesh.meshIndex = hfmModel.meshes.size();
|
||||
}
|
||||
|
||||
mesh.meshExtents.reset();
|
||||
foreach(const glm::vec3& vertex, mesh.vertices) {
|
||||
mesh.meshExtents.addPoint(vertex);
|
||||
hfmModel.meshExtents.addPoint(vertex);
|
||||
glm::vec3 transformedVertex = glm::vec3(globalTransforms[nodeIndex] * glm::vec4(vertex, 1.0f));
|
||||
mesh.meshExtents.addPoint(transformedVertex);
|
||||
hfmModel.meshExtents.addPoint(transformedVertex);
|
||||
}
|
||||
}
|
||||
|
||||
// Add epsilon to mesh extents to compensate for planar meshes
|
||||
|
@ -1592,7 +1615,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash&
|
|||
|
||||
mesh.meshIndex = hfmModel.meshes.size();
|
||||
}
|
||||
nodecount++;
|
||||
++nodecount;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1839,8 +1862,8 @@ bool GLTFSerializer::readArray(const hifi::ByteArray& bin, int byteOffset, int c
|
|||
blobstream.unsetDevice();
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (int j = 0; j < bufferCount; j++) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
for (int j = 0; j < bufferCount; ++j) {
|
||||
if (!blobstream.atEnd()) {
|
||||
T value;
|
||||
blobstream >> value;
|
||||
|
@ -1893,7 +1916,7 @@ bool GLTFSerializer::addArrayFromAccessor(GLTFAccessor& accessor, QVector<T>& ou
|
|||
success = addArrayOfType(buffer.blob, bufferview.byteOffset + accBoffset, accessor.count, outarray, accessor.type,
|
||||
accessor.componentType);
|
||||
} else {
|
||||
for (int i = 0; i < accessor.count; i++) {
|
||||
for (int i = 0; i < accessor.count; ++i) {
|
||||
T value;
|
||||
memset(&value, 0, sizeof(T)); // Make sure the dummy array is initalised to zero.
|
||||
outarray.push_back(value);
|
||||
|
@ -1924,10 +1947,10 @@ bool GLTFSerializer::addArrayFromAccessor(GLTFAccessor& accessor, QVector<T>& ou
|
|||
accessor.sparse.count, out_sparse_values_array, accessor.type, accessor.componentType);
|
||||
|
||||
if (success) {
|
||||
for (int i = 0; i < accessor.sparse.count; i++) {
|
||||
for (int i = 0; i < accessor.sparse.count; ++i) {
|
||||
if ((i * 3) + 2 < out_sparse_values_array.size()) {
|
||||
if ((out_sparse_indices_array[i] * 3) + 2 < outarray.length()) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
outarray[(out_sparse_indices_array[i] * 3) + j] = out_sparse_values_array[(i * 3) + j];
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace scriptable {
|
|||
* @property {string} normalMap
|
||||
* @property {string} bumpMap
|
||||
* @property {string} occlusionMap
|
||||
* @property {string} lightmapMap
|
||||
* @property {string} lightMap
|
||||
* @property {string} scatteringMap
|
||||
* @property {Mat4|string} texCoordTransform0
|
||||
* @property {Mat4|string} texCoordTransform1
|
||||
|
@ -91,7 +91,7 @@ namespace scriptable {
|
|||
QString normalMap;
|
||||
QString bumpMap;
|
||||
QString occlusionMap;
|
||||
QString lightmapMap;
|
||||
QString lightMap;
|
||||
QString scatteringMap;
|
||||
std::array<glm::mat4, graphics::Material::NUM_TEXCOORD_TRANSFORMS> texCoordTransforms;
|
||||
|
||||
|
|
|
@ -430,10 +430,10 @@ namespace scriptable {
|
|||
obj.setProperty("occlusionMap", material.occlusionMap);
|
||||
}
|
||||
|
||||
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::LIGHTMAP_MAP_BIT)) {
|
||||
obj.setProperty("lightmapMap", FALLTHROUGH);
|
||||
} else if (!material.lightmapMap.isEmpty()) {
|
||||
obj.setProperty("lightmapMap", material.lightmapMap);
|
||||
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::LIGHT_MAP_BIT)) {
|
||||
obj.setProperty("lightMap", FALLTHROUGH);
|
||||
} else if (!material.lightMap.isEmpty()) {
|
||||
obj.setProperty("lightMap", material.lightMap);
|
||||
}
|
||||
|
||||
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_MAP_BIT)) {
|
||||
|
|
|
@ -39,7 +39,7 @@ scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const
|
|||
normalMap = material.normalMap;
|
||||
bumpMap = material.bumpMap;
|
||||
occlusionMap = material.occlusionMap;
|
||||
lightmapMap = material.lightmapMap;
|
||||
lightMap = material.lightMap;
|
||||
scatteringMap = material.scatteringMap;
|
||||
|
||||
defaultFallthrough = material.defaultFallthrough;
|
||||
|
@ -110,9 +110,9 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint
|
|||
occlusionMap = map->getTextureSource()->getUrl().toString();
|
||||
}
|
||||
|
||||
map = material->getTextureMap(graphics::Material::MapChannel::LIGHTMAP_MAP);
|
||||
map = material->getTextureMap(graphics::Material::MapChannel::LIGHT_MAP);
|
||||
if (map && map->getTextureSource()) {
|
||||
lightmapMap = map->getTextureSource()->getUrl().toString();
|
||||
lightMap = map->getTextureSource()->getUrl().toString();
|
||||
}
|
||||
|
||||
map = material->getTextureMap(graphics::Material::MapChannel::SCATTERING_MAP);
|
||||
|
|
|
@ -129,7 +129,7 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur
|
|||
_texcoordTransforms[1] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4());
|
||||
}
|
||||
|
||||
if (channel == MaterialKey::LIGHTMAP_MAP) {
|
||||
if (channel == MaterialKey::LIGHT_MAP) {
|
||||
// update the texcoord1 with lightmap
|
||||
_texcoordTransforms[1] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4());
|
||||
_lightmapParams = (textureMap ? glm::vec2(textureMap->getLightmapOffsetScale()) : glm::vec2(0.0, 1.0));
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
ROUGHNESS_MAP_BIT,
|
||||
NORMAL_MAP_BIT,
|
||||
OCCLUSION_MAP_BIT,
|
||||
LIGHTMAP_MAP_BIT,
|
||||
LIGHT_MAP_BIT,
|
||||
SCATTERING_MAP_BIT,
|
||||
|
||||
NUM_FLAGS,
|
||||
|
@ -67,7 +67,7 @@ public:
|
|||
ROUGHNESS_MAP,
|
||||
NORMAL_MAP,
|
||||
OCCLUSION_MAP,
|
||||
LIGHTMAP_MAP,
|
||||
LIGHT_MAP,
|
||||
SCATTERING_MAP,
|
||||
|
||||
NUM_MAP_CHANNELS,
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
|
||||
Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); }
|
||||
Builder& withOcclusionMap() { _flags.set(OCCLUSION_MAP_BIT); return (*this); }
|
||||
Builder& withLightmapMap() { _flags.set(LIGHTMAP_MAP_BIT); return (*this); }
|
||||
Builder& withLightMap() { _flags.set(LIGHT_MAP_BIT); return (*this); }
|
||||
Builder& withScatteringMap() { _flags.set(SCATTERING_MAP_BIT); return (*this); }
|
||||
|
||||
// Convenient standard keys that we will keep on using all over the place
|
||||
|
@ -157,8 +157,8 @@ public:
|
|||
void setOcclusionMap(bool value) { _flags.set(OCCLUSION_MAP_BIT, value); }
|
||||
bool isOcclusionMap() const { return _flags[OCCLUSION_MAP_BIT]; }
|
||||
|
||||
void setLightmapMap(bool value) { _flags.set(LIGHTMAP_MAP_BIT, value); }
|
||||
bool isLightmapMap() const { return _flags[LIGHTMAP_MAP_BIT]; }
|
||||
void setLightMap(bool value) { _flags.set(LIGHT_MAP_BIT, value); }
|
||||
bool isLightMap() const { return _flags[LIGHT_MAP_BIT]; }
|
||||
|
||||
void setScattering(bool value) { _flags.set(SCATTERING_VAL_BIT, value); }
|
||||
bool isScattering() const { return _flags[SCATTERING_VAL_BIT]; }
|
||||
|
@ -235,8 +235,8 @@ public:
|
|||
Builder& withoutOcclusionMap() { _value.reset(MaterialKey::OCCLUSION_MAP_BIT); _mask.set(MaterialKey::OCCLUSION_MAP_BIT); return (*this); }
|
||||
Builder& withOcclusionMap() { _value.set(MaterialKey::OCCLUSION_MAP_BIT); _mask.set(MaterialKey::OCCLUSION_MAP_BIT); return (*this); }
|
||||
|
||||
Builder& withoutLightmapMap() { _value.reset(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
|
||||
Builder& withLightmapMap() { _value.set(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); }
|
||||
Builder& withoutLightMap() { _value.reset(MaterialKey::LIGHT_MAP_BIT); _mask.set(MaterialKey::LIGHT_MAP_BIT); return (*this); }
|
||||
Builder& withLightMap() { _value.set(MaterialKey::LIGHT_MAP_BIT); _mask.set(MaterialKey::LIGHT_MAP_BIT); return (*this); }
|
||||
|
||||
Builder& withoutScattering() { _value.reset(MaterialKey::SCATTERING_VAL_BIT); _mask.set(MaterialKey::SCATTERING_VAL_BIT); return (*this); }
|
||||
Builder& withScattering() { _value.set(MaterialKey::SCATTERING_VAL_BIT); _mask.set(MaterialKey::SCATTERING_VAL_BIT); return (*this); }
|
||||
|
|
|
@ -178,7 +178,7 @@ float fetchScatteringMap(vec2 uv) {
|
|||
float <$occlusion$> = mix(1.0, fetchOcclusionMap(<$texcoord1$>), float((<$matKey$> & OCCLUSION_MAP_BIT) != 0));
|
||||
<@endif@>
|
||||
<@if lightmap@>
|
||||
vec3 <$lightmap$> = fetchLightmapMap(<$texcoord1$>);
|
||||
vec3 <$lightmap$> = fetchLightMap(<$texcoord1$>);
|
||||
<@endif@>
|
||||
<@endfunc@>
|
||||
|
||||
|
@ -189,7 +189,7 @@ float fetchScatteringMap(vec2 uv) {
|
|||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP) uniform sampler2D emissiveMap;
|
||||
vec3 fetchLightmapMap(vec2 uv) {
|
||||
vec3 fetchLightMap(vec2 uv) {
|
||||
vec2 lightmapParams = getTexMapArray()._lightmapParams;
|
||||
return (vec3(lightmapParams.x) + lightmapParams.y * texture(emissiveMap, uv).rgb);
|
||||
}
|
||||
|
|
|
@ -362,9 +362,9 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
|||
if (value.isString()) {
|
||||
auto valueString = value.toString();
|
||||
if (valueString == FALLTHROUGH) {
|
||||
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::LIGHTMAP_MAP_BIT);
|
||||
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::LIGHT_MAP_BIT);
|
||||
} else {
|
||||
material->setLightmapMap(baseUrl.resolved(valueString));
|
||||
material->setLightMap(baseUrl.resolved(valueString));
|
||||
}
|
||||
}
|
||||
} else if (key == "texCoordTransform0") {
|
||||
|
@ -567,12 +567,12 @@ void NetworkMaterial::setScatteringMap(const QUrl& url) {
|
|||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setLightmapMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||
void NetworkMaterial::setLightMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHT_MAP);
|
||||
if (map) {
|
||||
//map->setTextureTransform(_lightmapTransform);
|
||||
//map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||
setTextureMap(MapChannel::LIGHTMAP_MAP, map);
|
||||
setTextureMap(MapChannel::LIGHT_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -640,14 +640,14 @@ NetworkMaterial::NetworkMaterial(const HFMMaterial& material, const QUrl& textur
|
|||
}
|
||||
|
||||
if (!material.lightmapTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHT_MAP);
|
||||
if (map) {
|
||||
_lightmapTransform = material.lightmapTexture.transform;
|
||||
_lightmapParams = material.lightmapParams;
|
||||
map->setTextureTransform(_lightmapTransform);
|
||||
map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||
}
|
||||
setTextureMap(MapChannel::LIGHTMAP_MAP, map);
|
||||
setTextureMap(MapChannel::LIGHT_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -660,7 +660,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) {
|
|||
const auto& metallicName = getTextureName(MapChannel::METALLIC_MAP);
|
||||
const auto& occlusionName = getTextureName(MapChannel::OCCLUSION_MAP);
|
||||
const auto& emissiveName = getTextureName(MapChannel::EMISSIVE_MAP);
|
||||
const auto& lightmapName = getTextureName(MapChannel::LIGHTMAP_MAP);
|
||||
const auto& lightmapName = getTextureName(MapChannel::LIGHT_MAP);
|
||||
const auto& scatteringName = getTextureName(MapChannel::SCATTERING_MAP);
|
||||
|
||||
if (!albedoName.isEmpty()) {
|
||||
|
@ -715,12 +715,12 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) {
|
|||
|
||||
if (!lightmapName.isEmpty()) {
|
||||
auto url = textureMap.contains(lightmapName) ? textureMap[lightmapName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHT_MAP);
|
||||
if (map) {
|
||||
map->setTextureTransform(_lightmapTransform);
|
||||
map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||
}
|
||||
setTextureMap(MapChannel::LIGHTMAP_MAP, map);
|
||||
setTextureMap(MapChannel::LIGHT_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
void setOcclusionMap(const QUrl& url);
|
||||
void setEmissiveMap(const QUrl& url);
|
||||
void setScatteringMap(const QUrl& url);
|
||||
void setLightmapMap(const QUrl& url);
|
||||
void setLightMap(const QUrl& url);
|
||||
|
||||
bool isMissingTexture();
|
||||
void checkResetOpacityMap();
|
||||
|
|
|
@ -115,8 +115,8 @@ ShapeKey MeshPartPayload::getShapeKey() const {
|
|||
if (drawMaterialKey.isNormalMap()) {
|
||||
builder.withTangents();
|
||||
}
|
||||
if (drawMaterialKey.isLightmapMap()) {
|
||||
builder.withLightmap();
|
||||
if (drawMaterialKey.isLightMap()) {
|
||||
builder.withLightMap();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr
|
|||
|
||||
bool isTranslucent = drawMaterialKey.isTranslucent();
|
||||
bool hasTangents = drawMaterialKey.isNormalMap() && _hasTangents;
|
||||
bool hasLightmap = drawMaterialKey.isLightmapMap();
|
||||
bool hasLightmap = drawMaterialKey.isLightMap();
|
||||
bool isUnlit = drawMaterialKey.isUnlit();
|
||||
|
||||
bool isDeformed = _isBlendShaped || _isSkinned;
|
||||
|
@ -374,7 +374,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr
|
|||
builder.withTangents();
|
||||
}
|
||||
if (hasLightmap) {
|
||||
builder.withLightmap();
|
||||
builder.withLightMap();
|
||||
}
|
||||
if (isUnlit) {
|
||||
builder.withUnlit();
|
||||
|
|
|
@ -107,7 +107,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
|
|||
model_translucent_normal_map, nullptr, nullptr);
|
||||
addPipeline(
|
||||
// FIXME: Ignore lightmap for translucents meshpart
|
||||
Key::Builder().withMaterial().withTranslucent().withLightmap(),
|
||||
Key::Builder().withMaterial().withTranslucent().withLightMap(),
|
||||
model_translucent, nullptr, nullptr);
|
||||
// Same thing but with Fade on
|
||||
addPipeline(
|
||||
|
@ -127,21 +127,21 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
|
|||
model_translucent_normal_map_fade, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
// FIXME: Ignore lightmap for translucents meshpart
|
||||
Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(),
|
||||
Key::Builder().withMaterial().withTranslucent().withLightMap().withFade(),
|
||||
model_translucent_fade, batchSetter, itemSetter);
|
||||
// Lightmapped
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap(),
|
||||
Key::Builder().withMaterial().withLightMap(),
|
||||
model_lightmap, nullptr, nullptr);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withTangents(),
|
||||
Key::Builder().withMaterial().withLightMap().withTangents(),
|
||||
model_lightmap_normal_map, nullptr, nullptr);
|
||||
// Same thing but with Fade on
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withFade(),
|
||||
Key::Builder().withMaterial().withLightMap().withFade(),
|
||||
model_lightmap_fade, batchSetter, itemSetter);
|
||||
addPipeline(
|
||||
Key::Builder().withMaterial().withLightmap().withTangents().withFade(),
|
||||
Key::Builder().withMaterial().withLightMap().withTangents().withFade(),
|
||||
model_lightmap_normal_map_fade, batchSetter, itemSetter);
|
||||
|
||||
// matrix palette skinned
|
||||
|
@ -228,10 +228,10 @@ void initForwardPipelines(ShapePlumber& plumber) {
|
|||
|
||||
// Opaques
|
||||
addPipeline(Key::Builder().withMaterial(), program::forward_model);
|
||||
addPipeline(Key::Builder().withMaterial().withLightmap(), program::forward_model_lightmap);
|
||||
addPipeline(Key::Builder().withMaterial().withLightMap(), program::forward_model_lightmap);
|
||||
addPipeline(Key::Builder().withMaterial().withUnlit(), program::forward_model_unlit);
|
||||
addPipeline(Key::Builder().withMaterial().withTangents(), program::forward_model_normal_map);
|
||||
addPipeline(Key::Builder().withMaterial().withTangents().withLightmap(), program::forward_model_normal_map_lightmap);
|
||||
addPipeline(Key::Builder().withMaterial().withTangents().withLightMap(), program::forward_model_normal_map_lightmap);
|
||||
|
||||
// Deformed Opaques
|
||||
addPipeline(Key::Builder().withMaterial().withDeformed(), program::forward_deformed_model);
|
||||
|
@ -581,7 +581,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
break;
|
||||
case graphics::MaterialKey::EMISSIVE_MAP_BIT:
|
||||
// Lightmap takes precendence over emissive map for legacy reasons
|
||||
if (materialKey.isEmissiveMap() && !materialKey.isLightmapMap()) {
|
||||
if (materialKey.isEmissiveMap() && !materialKey.isLightMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP);
|
||||
if (itr != textureMaps.end()) {
|
||||
if (itr->second->isDefined()) {
|
||||
|
@ -595,14 +595,14 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
forceDefault = true;
|
||||
}
|
||||
schemaKey.setEmissiveMap(true);
|
||||
} else if (materialKey.isLightmapMap()) {
|
||||
} else if (materialKey.isLightMap()) {
|
||||
// We'll set this later when we check the lightmap
|
||||
wasSet = true;
|
||||
}
|
||||
break;
|
||||
case graphics::MaterialKey::LIGHTMAP_MAP_BIT:
|
||||
if (materialKey.isLightmapMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::LIGHTMAP_MAP);
|
||||
case graphics::MaterialKey::LIGHT_MAP_BIT:
|
||||
if (materialKey.isLightMap()) {
|
||||
auto itr = textureMaps.find(graphics::MaterialKey::LIGHT_MAP);
|
||||
if (itr != textureMaps.end()) {
|
||||
if (itr->second->isDefined()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView());
|
||||
|
@ -614,7 +614,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
} else {
|
||||
forceDefault = true;
|
||||
}
|
||||
schemaKey.setLightmapMap(true);
|
||||
schemaKey.setLightMap(true);
|
||||
}
|
||||
break;
|
||||
case graphics::Material::TEXCOORDTRANSFORM0:
|
||||
|
@ -712,12 +712,12 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
}
|
||||
break;
|
||||
case graphics::MaterialKey::EMISSIVE_MAP_BIT:
|
||||
if (schemaKey.isEmissiveMap() && !schemaKey.isLightmapMap()) {
|
||||
if (schemaKey.isEmissiveMap() && !schemaKey.isLightMap()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getGrayTexture());
|
||||
}
|
||||
break;
|
||||
case graphics::MaterialKey::LIGHTMAP_MAP_BIT:
|
||||
if (schemaKey.isLightmapMap()) {
|
||||
case graphics::MaterialKey::LIGHT_MAP_BIT:
|
||||
if (schemaKey.isLightMap()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getBlackTexture());
|
||||
}
|
||||
break;
|
||||
|
@ -765,7 +765,7 @@ bool RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu:
|
|||
batch.setResourceTextureTable(multiMaterial.getTextureTable());
|
||||
} else {
|
||||
if (renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) {
|
||||
if (key.isLightmapMap()) {
|
||||
if (key.isLightMap()) {
|
||||
defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getBlackTexture());
|
||||
} else if (key.isEmissiveMap()) {
|
||||
defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getGrayTexture());
|
||||
|
|
|
@ -558,14 +558,20 @@ void Scene::removeItemTransition(ItemID itemId) {
|
|||
auto& item = _items[itemId];
|
||||
TransitionStage::Index transitionId = item.getTransitionId();
|
||||
if (!render::TransitionStage::isIndexInvalid(transitionId)) {
|
||||
auto finishedOperators = _transitionFinishedOperatorMap[transitionId];
|
||||
for (auto finishedOperator : finishedOperators) {
|
||||
if (finishedOperator) {
|
||||
finishedOperator();
|
||||
const auto& transition = transitionStage->getTransition(transitionId);
|
||||
const auto transitionOwner = transition.itemId;
|
||||
if (transitionOwner == itemId) {
|
||||
// No more items will be using this transition. Clean it up.
|
||||
auto finishedOperators = _transitionFinishedOperatorMap[transitionId];
|
||||
for (auto finishedOperator : finishedOperators) {
|
||||
if (finishedOperator) {
|
||||
finishedOperator();
|
||||
}
|
||||
}
|
||||
_transitionFinishedOperatorMap.erase(transitionId);
|
||||
transitionStage->removeTransition(transitionId);
|
||||
}
|
||||
_transitionFinishedOperatorMap.erase(transitionId);
|
||||
transitionStage->removeTransition(transitionId);
|
||||
|
||||
setItemTransition(itemId, render::TransitionStage::INVALID_INDEX);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
|
||||
Builder& withMaterial() { _flags.set(MATERIAL); return (*this); }
|
||||
Builder& withTranslucent() { _flags.set(TRANSLUCENT); return (*this); }
|
||||
Builder& withLightmap() { _flags.set(LIGHTMAP); return (*this); }
|
||||
Builder& withLightMap() { _flags.set(LIGHTMAP); return (*this); }
|
||||
Builder& withTangents() { _flags.set(TANGENTS); return (*this); }
|
||||
Builder& withUnlit() { _flags.set(UNLIT); return (*this); }
|
||||
Builder& withDeformed() { _flags.set(DEFORMED); return (*this); }
|
||||
|
@ -116,8 +116,8 @@ public:
|
|||
Builder& withTranslucent() { _flags.set(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); }
|
||||
Builder& withOpaque() { _flags.reset(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); }
|
||||
|
||||
Builder& withLightmap() { _flags.set(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); }
|
||||
Builder& withoutLightmap() { _flags.reset(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); }
|
||||
Builder& withLightMap() { _flags.set(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); }
|
||||
Builder& withoutLightMap() { _flags.reset(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); }
|
||||
|
||||
Builder& withTangents() { _flags.set(TANGENTS); _mask.set(TANGENTS); return (*this); }
|
||||
Builder& withoutTangents() { _flags.reset(TANGENTS); _mask.set(TANGENTS); return (*this); }
|
||||
|
@ -160,7 +160,7 @@ public:
|
|||
};
|
||||
|
||||
bool useMaterial() const { return _flags[MATERIAL]; }
|
||||
bool hasLightmap() const { return _flags[LIGHTMAP]; }
|
||||
bool hasLightMap() const { return _flags[LIGHTMAP]; }
|
||||
bool hasTangents() const { return _flags[TANGENTS]; }
|
||||
bool isUnlit() const { return _flags[UNLIT]; }
|
||||
bool isTranslucent() const { return _flags[TRANSLUCENT]; }
|
||||
|
@ -199,7 +199,7 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) {
|
|||
} else {
|
||||
debug << "[ShapeKey:"
|
||||
<< "useMaterial:" << key.useMaterial()
|
||||
<< "hasLightmap:" << key.hasLightmap()
|
||||
<< "hasLightmap:" << key.hasLightMap()
|
||||
<< "hasTangents:" << key.hasTangents()
|
||||
<< "isUnlit:" << key.isUnlit()
|
||||
<< "isTranslucent:" << key.isTranslucent()
|
||||
|
|
|
@ -38,7 +38,7 @@ class Camera : public QObject {
|
|||
|
||||
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
|
||||
Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation)
|
||||
Q_PROPERTY(QString mode READ getModeString WRITE setModeString)
|
||||
Q_PROPERTY(QString mode READ getModeString WRITE setModeString NOTIFY modeUpdated)
|
||||
Q_PROPERTY(QVariantMap frustum READ getViewFrustum CONSTANT)
|
||||
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue