Merge pull request #11347 from Atlante45/feat/auto-bake

Finalize auto baking UI
This commit is contained in:
Stephen Birarda 2017-09-13 16:05:38 -07:00 committed by GitHub
commit 7b36105793
16 changed files with 1601 additions and 104 deletions

View file

@ -83,7 +83,8 @@ void BakeAssetTask::run() {
if (baker->hasErrors()) {
qDebug() << "Failed to bake: " << _assetHash << _assetPath << baker->getErrors();
emit bakeFailed(_assetHash, _assetPath);
auto errors = baker->getErrors().join('\n'); // Join error list into a single string for convenience
emit bakeFailed(_assetHash, _assetPath, errors);
} else {
auto vectorOutputFiles = QVector<QString>::fromStdVector(baker->getOutputFiles());
qDebug() << "Finished baking: " << _assetHash << _assetPath << vectorOutputFiles;
@ -112,19 +113,19 @@ QString AssetServer::getPathToAssetHash(const AssetHash& assetHash) {
return _filesDirectory.absoluteFilePath(assetHash);
}
BakingStatus AssetServer::getAssetStatus(const AssetPath& path, const AssetHash& hash) {
std::pair<BakingStatus, QString> AssetServer::getAssetStatus(const AssetPath& path, const AssetHash& hash) {
auto it = _pendingBakes.find(hash);
if (it != _pendingBakes.end()) {
return (*it)->isBaking() ? Baking : Pending;
return { (*it)->isBaking() ? Baking : Pending, "" };
}
if (path.startsWith(HIDDEN_BAKED_CONTENT_FOLDER)) {
return Baked;
return { Baked, "" };
}
auto dotIndex = path.lastIndexOf(".");
if (dotIndex == -1) {
return Irrelevant;
return { Irrelevant, "" };
}
auto extension = path.mid(dotIndex + 1);
@ -136,28 +137,28 @@ BakingStatus AssetServer::getAssetStatus(const AssetPath& path, const AssetHash&
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit()) && hasMetaFile(hash)) {
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
} else {
return Irrelevant;
return { Irrelevant, "" };
}
auto bakedPath = HIDDEN_BAKED_CONTENT_FOLDER + hash + "/" + bakedFilename;
auto jt = _fileMappings.find(bakedPath);
if (jt != _fileMappings.end()) {
if (jt->second == hash) {
bool loaded;
AssetMeta meta;
std::tie(loaded, meta) = readMetaFile(hash);
if (loaded && meta.failedLastBake) {
return Error;
}
return NotBaked;
return { NotBaked, "" };
} else {
return Baked;
return { Baked, "" };
}
} else {
bool loaded;
AssetMeta meta;
std::tie(loaded, meta) = readMetaFile(hash);
if (loaded && meta.failedLastBake) {
return { Error, meta.lastBakeErrors };
}
}
return Pending;
return { Pending, "" };
}
void AssetServer::bakeAssets() {
@ -564,7 +565,14 @@ void AssetServer::handleGetAllMappingOperation(ReceivedMessage& message, SharedN
auto hash = it->second;
replyPacket.writeString(mapping);
replyPacket.write(QByteArray::fromHex(hash.toUtf8()));
replyPacket.writePrimitive(getAssetStatus(mapping, hash));
BakingStatus status;
QString lastBakeErrors;
std::tie(status, lastBakeErrors) = getAssetStatus(mapping, hash);
replyPacket.writePrimitive(status);
if (status == Error) {
replyPacket.writeString(lastBakeErrors);
}
}
}
@ -1146,8 +1154,8 @@ QString getBakeMapping(const AssetHash& hash, const QString& relativeFilePath) {
return HIDDEN_BAKED_CONTENT_FOLDER + hash + "/" + relativeFilePath;
}
void AssetServer::handleFailedBake(QString originalAssetHash, QString assetPath) {
qDebug() << "Failed: " << originalAssetHash << assetPath;
void AssetServer::handleFailedBake(QString originalAssetHash, QString assetPath, QString errors) {
qDebug() << "Failed: " << originalAssetHash << assetPath << errors;
bool loaded;
AssetMeta meta;
@ -1155,8 +1163,11 @@ void AssetServer::handleFailedBake(QString originalAssetHash, QString assetPath)
std::tie(loaded, meta) = readMetaFile(originalAssetHash);
meta.failedLastBake = true;
meta.lastBakeErrors = errors;
writeMetaFile(originalAssetHash, meta);
_pendingBakes.remove(originalAssetHash);
}
void AssetServer::handleCompletedBake(QString originalAssetHash, QString originalAssetPath, QVector<QString> bakedFilePaths) {
@ -1239,6 +1250,7 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina
static const QString BAKE_VERSION_KEY = "bake_version";
static const QString APP_VERSION_KEY = "app_version";
static const QString FAILED_LAST_BAKE_KEY = "failed_last_bake";
static const QString LAST_BAKE_ERRORS_KEY = "last_bake_errors";
std::pair<bool, AssetMeta> AssetServer::readMetaFile(AssetHash hash) {
auto metaFilePath = HIDDEN_BAKED_CONTENT_FOLDER + hash + "/" + "meta.json";
@ -1265,15 +1277,18 @@ std::pair<bool, AssetMeta> AssetServer::readMetaFile(AssetHash hash) {
auto bakeVersion = root[BAKE_VERSION_KEY].toInt(-1);
auto appVersion = root[APP_VERSION_KEY].toInt(-1);
auto failedLastBake = root[FAILED_LAST_BAKE_KEY];
auto lastBakeErrors = root[LAST_BAKE_ERRORS_KEY];
if (bakeVersion != -1
&& appVersion != -1
&& failedLastBake.isBool()) {
&& failedLastBake.isBool()
&& lastBakeErrors.isString()) {
AssetMeta meta;
meta.bakeVersion = bakeVersion;
meta.applicationVersion = appVersion;
meta.failedLastBake = failedLastBake.toBool();
meta.lastBakeErrors = lastBakeErrors.toString();
return { true, meta };
} else {
@ -1292,6 +1307,7 @@ bool AssetServer::writeMetaFile(AssetHash originalAssetHash, const AssetMeta& me
metaFileObject[BAKE_VERSION_KEY] = meta.bakeVersion;
metaFileObject[APP_VERSION_KEY] = meta.applicationVersion;
metaFileObject[FAILED_LAST_BAKE_KEY] = meta.failedLastBake;
metaFileObject[LAST_BAKE_ERRORS_KEY] = meta.lastBakeErrors;
QJsonDocument metaFileDoc;
metaFileDoc.setObject(metaFileObject);

View file

@ -19,7 +19,6 @@
#include <ThreadedAssignment.h>
#include "AssetUtils.h"
#include "AutoBaker.h"
#include "ReceivedMessage.h"
@ -41,7 +40,7 @@ public:
signals:
void bakeComplete(QString assetHash, QString assetPath, QVector<QString> outputFiles);
void bakeFailed(QString assetHash, QString assetPath);
void bakeFailed(QString assetHash, QString assetPath, QString errors);
private:
std::atomic<bool> _isBaking { false };
@ -57,6 +56,7 @@ struct AssetMeta {
int bakeVersion { 0 };
int applicationVersion { 0 };
bool failedLastBake { false };
QString lastBakeErrors;
};
class AssetServer : public ThreadedAssignment {
@ -109,7 +109,7 @@ private:
QString getPathToAssetHash(const AssetHash& assetHash);
BakingStatus getAssetStatus(const AssetPath& path, const AssetHash& hash);
std::pair<BakingStatus, QString> getAssetStatus(const AssetPath& path, const AssetHash& hash);
void bakeAssets();
void maybeBake(const AssetPath& path, const AssetHash& hash);
@ -120,7 +120,7 @@ private:
/// Move baked content for asset to baked directory and update baked status
void handleCompletedBake(QString originalAssetHash, QString assetPath, QVector<QString> bakedFilePaths);
void handleFailedBake(QString originalAssetHash, QString assetPath);
void handleFailedBake(QString originalAssetHash, QString assetPath, QString errors);
/// Create meta file to describe baked content for original asset
std::pair<bool, AssetMeta> readMetaFile(AssetHash hash);

View file

@ -1,37 +0,0 @@
//
// AutoBaker.cpp
// assignment-client/src/assets
//
// Created by Clement Brisset on 8/9/17
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AutoBaker.h"
#include <shared/Algorithms.h>
using namespace alg;
void AutoBaker::addPendingBake(AssetHash hash) {
_pendingBakes.push_back(hash);
// Maybe start baking it right away
}
bool AutoBaker::assetNeedsBaking(AssetPath path, AssetHash hash) {
return path.endsWith(".fbx");
}
BakingStatus AutoBaker::getAssetStatus(AssetHash hash) {
if (find(_pendingBakes, hash) != std::end(_pendingBakes)) {
return Pending;
}
if (find(_currentlyBaking, hash) != std::end(_currentlyBaking)) {
return Baking;
}
return NotBaked;
}

View file

@ -1,32 +0,0 @@
//
// AutoBaker.h
// assignment-client/src/assets
//
// Created by Clement Brisset on 8/9/17
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AutoBaker_h
#define hifi_AutoBaker_h
#include <vector>
#include "AssetUtils.h"
class AutoBaker {
public:
void addPendingBake(AssetHash hash);
bool assetNeedsBaking(AssetPath path, AssetHash hash);
BakingStatus getAssetStatus(AssetHash hash);
private:
std::vector<AssetHash> _pendingBakes;
std::vector<AssetHash> _currentlyBaking;
};
#endif /* hifi_AutoBaker_h */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,421 @@
@charset "UTF-8";
@font-face {
font-family: "hifi-glyphs";
src:url("fonts/hifi-glyphs.eot");
src:url("fonts/hifi-glyphs.eot?#iefix") format("embedded-opentype"),
url("fonts/hifi-glyphs.woff") format("woff"),
url("fonts/hifi-glyphs.ttf") format("truetype"),
url("fonts/hifi-glyphs.svg#hifi-glyphs") format("svg");
font-weight: normal;
font-style: normal;
}
[data-icon]:before {
font-family: "hifi-glyphs" !important;
content: attr(data-icon);
font-style: normal !important;
font-weight: normal !important;
font-variant: normal !important;
text-transform: none !important;
speak: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
[class^="icon-"]:before,
[class*=" icon-"]:before {
font-family: "hifi-glyphs" !important;
font-style: normal !important;
font-weight: normal !important;
font-variant: normal !important;
text-transform: none !important;
speak: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-hmd:before {
content: "\62";
}
.icon-2d-screen:before {
content: "\63";
}
.icon-keyboard:before {
content: "\64";
}
.icon-hand-controllers:before {
content: "\65";
}
.icon-headphones-mic:before {
content: "\66";
}
.icon-gamepad:before {
content: "\67";
}
.icon-headphones:before {
content: "\68";
}
.icon-mic:before {
content: "\69";
}
.icon-upload:before {
content: "\6a";
}
.icon-script:before {
content: "\6b";
}
.icon-text:before {
content: "\6c";
}
.icon-cube:before {
content: "\6d";
}
.icon-sphere:before {
content: "\6e";
}
.icon-zone:before {
content: "\6f";
}
.icon-light:before {
content: "\70";
}
.icon-web:before {
content: "\71";
}
.icon-web-2:before {
content: "\72";
}
.icon-edit:before {
content: "\73";
}
.icon-market:before {
content: "\74";
}
.icon-directory:before {
content: "\75";
}
.icon-menu:before {
content: "\76";
}
.icon-close:before {
content: "\77";
}
.icon-close-inverted:before {
content: "\78";
}
.icon-pin:before {
content: "\79";
}
.icon-pin-inverted:before {
content: "\7a";
}
.icon-resize-handle:before {
content: "\41";
}
.icon-diclosure-expand:before {
content: "\42";
}
.icon-reload-small:before {
content: "\61";
}
.icon-close-small:before {
content: "\43";
}
.icon-backward:before {
content: "\45";
}
.icon-reload:before {
content: "\46";
}
.icon-minimize:before {
content: "\49";
}
.icon-maximize:before {
content: "\4a";
}
.icon-maximize-inverted:before {
content: "\4b";
}
.icon-disclosure-button-expand:before {
content: "\4c";
}
.icon-disclosure-button-collapse:before {
content: "\4d";
}
.icon-script-stop:before {
content: "\4e";
}
.icon-script-reload:before {
content: "\4f";
}
.icon-script-run:before {
content: "\50";
}
.icon-script-new:before {
content: "\51";
}
.icon-hifi-forum:before {
content: "\32";
}
.icon-hifi-logo-small:before {
content: "\53";
}
.icon-avatar-1:before {
content: "\54";
}
.icon-placemark:before {
content: "\55";
}
.icon-box:before {
content: "\56";
}
.icon-community:before {
content: "\30";
}
.icon-grab-handle:before {
content: "\58";
}
.icon-search:before {
content: "\59";
}
.icon-disclosure-collapse:before {
content: "\5a";
}
.icon-script-upload:before {
content: "\52";
}
.icon-code:before {
content: "\57";
}
.icon-avatar:before {
content: "\3c";
}
.icon-arrows-h:before {
content: "\3a";
}
.icon-arrows-v:before {
content: "\3b";
}
.icon-arrows:before {
content: "\60";
}
.icon-compress:before {
content: "\21";
}
.icon-expand:before {
content: "\22";
}
.icon-placemark-1:before {
content: "\23";
}
.icon-circle:before {
content: "\24";
}
.icon-hand-pointer:before {
content: "\39";
}
.icon-plus-square-o:before {
content: "\25";
}
.icon-square:before {
content: "\27";
}
.icon-align-center:before {
content: "\38";
}
.icon-align-justify:before {
content: "\29";
}
.icon-align-left:before {
content: "\2a";
}
.icon-align-right:before {
content: "\5e";
}
.icon-bars:before {
content: "\37";
}
.icon-circle-slash:before {
content: "\2c";
}
.icon-sync:before {
content: "\28";
}
.icon-key:before {
content: "\2d";
}
.icon-link:before {
content: "\2e";
}
.icon-location:before {
content: "\2f";
}
.icon-carat-r:before {
content: "\33";
}
.icon-carat-l:before {
content: "\34";
}
.icon-folder-lg:before {
content: "\3e";
}
.icon-folder-sm:before {
content: "\3f";
}
.icon-level-up:before {
content: "\31";
}
.icon-info:before {
content: "\5b";
}
.icon-question:before {
content: "\5d";
}
.icon-alert:before {
content: "\2b";
}
.icon-home:before {
content: "\5f";
}
.icon-error:before {
content: "\3d";
}
.icon-settings:before {
content: "\40";
}
.icon-trash:before {
content: "\7b";
}
.icon-object-group:before {
content: "\e000";
}
.icon-cm:before {
content: "\7d";
}
.icon-msvg:before {
content: "\7e";
}
.icon-deg:before {
content: "\5c";
}
.icon-px:before {
content: "\7c";
}
.icon-m-sq:before {
content: "\e001";
}
.icon-m-cubed:before {
content: "\e002";
}
.icon-acceleration:before {
content: "\e003";
}
.icon-particles:before {
content: "\e004";
}
.icon-voxels:before {
content: "\e005";
}
.icon-lock:before {
content: "\e006";
}
.icon-visible:before {
content: "\e007";
}
.icon-model:before {
content: "\e008";
}
.icon-forward:before {
content: "\44";
}
.icon-avatar-2:before {
content: "\e009";
}
.icon-arrow-dn:before {
content: "\35";
}
.icon-arrow-up:before {
content: "\36";
}
.icon-time:before {
content: "\e00a";
}
.icon-transparency:before {
content: "\e00b";
}
.icon-unmuted:before {
content: "\47";
}
.icon-user:before {
content: "\e00c";
}
.icon-edit-pencil:before {
content: "\e00d";
}
.icon-muted:before {
content: "\48";
}
.icon-vol-0:before {
content: "\e00e";
}
.icon-vol-1:before {
content: "\e00f";
}
.icon-vol-2:before {
content: "\e010";
}
.icon-vol-3:before {
content: "\e011";
}
.icon-vol-4:before {
content: "\e012";
}
.icon-vol-x-0:before {
content: "\e013";
}
.icon-vol-x-1:before {
content: "\e014";
}
.icon-vol-x-2:before {
content: "\e015";
}
.icon-vol-x-3:before {
content: "\e016";
}
.icon-vol-x-4:before {
content: "\e017";
}
.icon-share-ext:before {
content: "\e018";
}
.icon-ellipsis:before {
content: "\e019";
}
.icon-check:before {
content: "\e01a";
}
.icon-sliders:before {
content: "\26";
}
.icon-polyline:before {
content: "\e01b";
}
.icon-source:before {
content: "\e01c";
}
.icon-playback-play:before {
content: "\e01d";
}
.icon-stop-square:before {
content: "\e01e";
}
.icon-avatar-t-pose:before {
content: "\e01f";
}
.icon-check-2-01:before {
content: "\e020";
}

View file

@ -561,7 +561,7 @@ ScrollingWindow {
case "Not Baked":
return hifi.glyphs.circleSlash;
case "Baked":
return hifi.glyphs.placemark;
return hifi.glyphs.check_2_01;
case "Error":
return hifi.glyphs.alert;
default:
@ -606,6 +606,14 @@ ScrollingWindow {
elide: Text.ElideRight
horizontalAlignment: TextInput.AlignHCenter
HifiControls.ToolTip {
anchors.fill: parent
visible: styleData.value === "Error"
toolTip: assetProxyModel.data(styleData.index, 0x106)
}
}
}
Component {
@ -651,7 +659,7 @@ ScrollingWindow {
}
onAccepted: {
if (acceptableInput && styleData.selected) {
if (!modifyEl(selection.currentIndex, text)) {
if (!treeView.modifyEl(treeView.selection.currentIndex, text)) {
text = styleData.value;
}
unfocusHelper.forceActiveFocus();

View file

@ -0,0 +1,51 @@
//
// ToolTip.qml
//
// Created by Clement on 9/12/17
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
Item {
property string toolTip
property bool showToolTip: false
Rectangle {
id: toolTipRectangle
anchors.right: parent.right
width: toolTipText.width + 4
height: toolTipText.height + 4
opacity: (toolTip != "" && showToolTip) ? 1 : 0
color: "#ffffaa"
border.color: "#0a0a0a"
Text {
id: toolTipText
text: toolTip
color: "black"
anchors.centerIn: parent
}
Behavior on opacity {
PropertyAnimation {
easing.type: Easing.InOutQuad
duration: 250
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
onEntered: showTimer.start()
onExited: { showToolTip = false; showTimer.stop(); }
hoverEnabled: true
}
Timer {
id: showTimer
interval: 250
onTriggered: { showToolTip = true; }
}
}

View file

@ -225,11 +225,4 @@ TreeView {
onClicked: {
selectionModel.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect);
}
onActivated: {
var path = scriptsModel.data(index, 0x100)
if (path) {
loadScript(path)
}
}
}

View file

@ -375,6 +375,13 @@ ScrollingWindow {
TableViewColumn {
role: "display";
}
onActivated: {
var path = scriptsModel.data(index, 0x100)
if (path) {
loadScript(path)
}
}
}
HifiControls.VerticalSpacer {

View file

@ -426,6 +426,13 @@ Rectangle {
}
}
}
onActivated: {
var path = scriptsModel.data(index, 0x100)
if (path) {
loadScript(path)
}
}
}
Item {

View file

@ -338,5 +338,6 @@ Item {
readonly property string stop_square: "\ue01e"
readonly property string avatarTPose: "\ue01f"
readonly property string lock: "\ue006"
readonly property string check_2_01: "\ue020"
}
}

View file

@ -261,6 +261,7 @@ void AssetMappingModel::refresh() {
// update status
auto statusString = isFolder ? "--" : bakingStatusToString(mapping.second.status);
lastItem->setData(statusString, Qt::UserRole + 5);
lastItem->setData(mapping.second.bakingErrors, Qt::UserRole + 6);
}
Q_ASSERT(fullPath == path);

View file

@ -66,6 +66,7 @@ enum BakingStatus {
struct MappingInfo {
AssetHash hash;
BakingStatus status;
QString bakingErrors;
};
using AssetMapping = std::map<AssetPath, MappingInfo>;

View file

@ -137,8 +137,12 @@ void GetAllMappingsRequest::doStart() {
auto path = message->readString();
auto hash = message->read(SHA256_HASH_LENGTH).toHex();
BakingStatus status;
QString lastBakeErrors;
message->readPrimitive(&status);
_mappings[path] = { hash, status };
if (status == BakingStatus::Error) {
lastBakeErrors = message->readString();
}
_mappings[path] = { hash, status, lastBakeErrors };
}
}
emit finished(this);