3
0
Fork 0
mirror of https://github.com/lubosz/overte.git synced 2025-04-27 05:15:34 +02:00

Merge branch 'mm_c8bef86' into android_places_goto

This commit is contained in:
Cristian Luis Duarte 2018-04-20 12:26:38 -03:00
commit 77caa4d402
119 changed files with 3930 additions and 1863 deletions
assignment-client/src/assets
interface
libraries

View file

@ -61,13 +61,13 @@ static const ScriptBakeVersion CURRENT_SCRIPT_BAKE_VERSION = (ScriptBakeVersion)
BakedAssetType assetTypeForExtension(const QString& extension) {
auto extensionLower = extension.toLower();
if (BAKEABLE_MODEL_EXTENSIONS.contains(extensionLower)) {
return Model;
return BakedAssetType::Model;
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extensionLower.toLocal8Bit())) {
return Texture;
return BakedAssetType::Texture;
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extensionLower)) {
return Script;
return BakedAssetType::Script;
}
return Undefined;
return BakedAssetType::Undefined;
}
BakedAssetType assetTypeForFilename(const QString& filename) {
@ -82,11 +82,11 @@ BakedAssetType assetTypeForFilename(const QString& filename) {
QString bakedFilenameForAssetType(BakedAssetType type) {
switch (type) {
case Model:
case BakedAssetType::Model:
return BAKED_MODEL_SIMPLE_NAME;
case Texture:
case BakedAssetType::Texture:
return BAKED_TEXTURE_SIMPLE_NAME;
case Script:
case BakedAssetType::Script:
return BAKED_SCRIPT_SIMPLE_NAME;
default:
return "";
@ -95,11 +95,11 @@ QString bakedFilenameForAssetType(BakedAssetType type) {
BakeVersion currentBakeVersionForAssetType(BakedAssetType type) {
switch (type) {
case Model:
case BakedAssetType::Model:
return (BakeVersion)CURRENT_MODEL_BAKE_VERSION;
case Texture:
case BakedAssetType::Texture:
return (BakeVersion)CURRENT_TEXTURE_BAKE_VERSION;
case Script:
case BakedAssetType::Script:
return (BakeVersion)CURRENT_SCRIPT_BAKE_VERSION;
default:
return 0;
@ -222,7 +222,7 @@ bool AssetServer::needsToBeBaked(const AssetUtils::AssetPath& path, const AssetU
BakedAssetType type = assetTypeForFilename(path);
if (type == Undefined) {
if (type == BakedAssetType::Undefined) {
return false;
}
@ -241,7 +241,7 @@ bool AssetServer::needsToBeBaked(const AssetUtils::AssetPath& path, const AssetU
AssetMeta meta;
std::tie(loaded, meta) = readMetaFile(assetHash);
if (type == Texture && !loaded) {
if (type == BakedAssetType::Texture && !loaded) {
return false;
}
@ -1546,7 +1546,7 @@ bool AssetServer::setBakingEnabled(const AssetUtils::AssetPathList& paths, bool
auto it = _fileMappings.find(path);
if (it != _fileMappings.end()) {
auto type = assetTypeForFilename(path);
if (type == Undefined) {
if (type == BakedAssetType::Undefined) {
continue;
}
QString bakedFilename = bakedFilenameForAssetType(type);

View file

@ -27,7 +27,7 @@ using BakeVersion = int;
static const BakeVersion INITIAL_BAKE_VERSION = 0;
static const BakeVersion NEEDS_BAKING_BAKE_VERSION = -1;
enum BakedAssetType : int {
enum class BakedAssetType : int {
Model = 0,
Texture,
Script,

View file

@ -25,7 +25,6 @@
<glyph glyph-name="web" unicode="&#113;" d="M438 390c0 8-6 15-14 15l-333 0c-8 0-15-7-15-15l0-298c0-8 7-14 15-14l333 0c8 0 14 6 14 14z m-219-8l172 0c8 0 15-7 15-16 0-9-7-16-15-16l-172 0c-8 0-15 7-15 16 0 9 7 16 15 16z m-47 1c9 0 16-7 16-16 0-10-7-17-16-17-10 0-17 7-17 17 0 9 7 16 17 16z m-51 0c9 0 17-7 17-16 0-10-8-17-17-17-9 0-17 7-17 17 0 9 8 16 17 16z m291-276l-308 0 0 219 308 0z m-250 84l-15 0-20 60 13 0 14-45 15 45 13 0 15-45 14 45 13 0-20-60-14 0-14 41z m137 25l-46 0c0-5 2-8 6-11 3-2 8-4 12-4 8 0 13 3 17 7l7-8c-6-6-14-9-25-9-8 0-15 2-21 8-6 5-9 13-9 22 0 9 3 17 9 22 6 6 13 9 21 9 8 0 15-3 21-8 6-5 8-11 8-20z m-46 9l34 0c0 5-2 9-5 12-3 3-7 4-11 4-5 0-9-1-13-4-3-3-5-7-5-12z m101 27c8 0 14-3 20-9 6-5 9-12 9-22 0-9-3-16-9-22-5-6-12-8-19-8-8 0-15 3-21 9l0-9-12 0 0 83 12 0 0-34c5 8 12 12 20 12z m-20-31c0-6 2-10 5-14 4-4 8-5 13-5 5 0 9 1 13 5 3 4 5 8 5 14 0 6-2 10-5 14-4 4-8 6-13 6-5 0-9-2-13-6-3-4-5-8-5-14z"/>
<glyph glyph-name="web-2" unicode="&#114;" d="M438 390c0 8-6 15-14 15l-333 0c-8 0-15-7-15-15l0-298c0-8 7-14 15-14l333 0c8 0 14 6 14 14z m-219-8l172 0c8 0 15-7 15-16 0-9-7-16-15-16l-172 0c-8 0-15 7-15 16 0 9 7 16 15 16z m-47 1c9 0 16-7 16-16 0-10-7-17-16-17-10 0-17 7-17 17 0 9 7 16 17 16z m-51 0c9 0 17-7 17-16 0-10-8-17-17-17-9 0-17 7-17 17 0 9 8 16 17 16z m291-276l-308 0 0 219 308 0z"/>
<glyph glyph-name="edit" unicode="&#115;" d="M196 214c-27-27-54-54-81-81-6 6-13 13-19 19 27 27 54 54 81 81l-22 21c-31-31-61-62-92-92-7-7-11-13-12-22-3-25-7-50-11-76 3 0 4 0 6 0 24 5 48 10 72 15 5 1 10 4 13 7 32 32 64 64 96 96z m126 207c10 10 21 21 33 32 4 4 10 4 14 0 19-19 38-38 57-57 4-5 4-10 0-15-11-11-22-22-34-33-23 24-46 48-70 73z m23-181c-5-1-8 0-11 3-8 8-15 15-23 23 18 18 37 37 55 55 2 2 4 4 4 4-24 25-47 49-71 74-2-2-3-4-5-6-18-18-37-37-55-55-34 34-67 67-101 101-2 2-5 5-8 7-18 14-42 12-57-5-15-17-14-42 2-58 50-51 101-101 151-151 17-16 33-33 50-49 2-3 3-5 2-8-2-8-4-15-4-23-4-48 27-90 73-102 20-5 39-4 58 4-1 2-3 3-5 4-14 14-28 28-42 42-10 11-11 26-2 36 8 8 16 16 24 24 11 10 24 10 35 0 2-1 4-4 6-6 15-14 29-28 43-42 0 0 1 0 2 1 1 8 3 16 4 24 7 69-59 123-125 103z m-243 162c-7 0-14 6-14 14 0 8 6 14 14 14 8 0 15-6 15-14 0-7-7-14-15-14z m198-46c6-6 13-12 19-19-13-13-26-26-39-39-7 6-13 12-20 19 14 13 27 26 40 39z"/>
<glyph glyph-name="market" unicode="&#116;" d="M88 370c3 0 7 0 10 0 6 0 11-1 15-2 9-2 16-8 20-16 3-5 4-10 6-15 2-6 3-13 5-19 3-10 5-19 8-27 2-6 3-13 5-19 3-7 5-15 7-23 3-9 6-19 9-30 0-2 1-4 1-6 2-8 5-17 9-24 3-7 8-12 13-15 6-3 13-5 22-6 2 0 5 0 7 0l21 0 57 0c25 0 50 0 75 0 12 0 25 0 37 0 1 0 1 0 2 0 6 0 13 0 17 2 5 3 7 9 9 16l3 10c0 0 0 0 0 0 0 2 1 3 1 3 5 20 11 40 17 60 1 4 2 9 4 13 2 8 4 16 7 24 2 7 4 16 0 22-3 4-9 5-14 5-6 0-188-2-284-4l-4 0-5 22c0 3-1 6-2 9 0 3-1 5-1 7-1 2-1 3-1 4-1 4-2 7-3 11-2 6-6 12-11 17-5 5-11 8-17 9-3 1-6 1-10 1-5 1-9 1-14 1-19 0-38 0-59 0-1 0-3 0-4 0-3 0-7 0-10-1-3 0-6-2-8-4-3-5-4-11-2-17 2-5 6-6 9-7 4-1 8-1 13-1 5 0 10 0 16 0l16 0c3 0 5 0 8 0z m353-78l-26-92-6-4-2 0c-2 0-21 0-55 0-50 0-118-1-125-1l-1-1 0 0c-6 0-12 2-16 6-4 4-6 10-8 16-3 12-6 25-10 39-1 4-2 8-3 12-2 4-3 8-4 13l-4 12z m-194-164c-9 0-15-2-20-7-5-5-8-11-8-20 0-8 3-16 8-21 5-5 13-8 20-8 17 0 30 12 30 28 0 8-3 15-9 20-5 6-12 8-21 8z m139 0c-9 0-16-2-21-6-5-6-8-13-8-21 0-9 3-16 8-21 5-6 12-8 21-8 16 0 29 13 29 29 0 8-3 14-8 20-5 5-13 7-21 7z"/>
<glyph glyph-name="directory" unicode="&#117;" d="M432 451l-99-38c-2 0-3-1-4-1-3 1-5 2-8 2l-116 38c-8 3-15 6-30-1l-91-35c-17-5-32-16-32-31l0-303c0-15 14-27 32-27l99 38c3 1 6 2 9 4 1-1 3-2 4-2 3-1 5-2 7-3 0 0 1 0 1-1 0 0 1 0 1 0l116-38 0 0c8-1 12-1 21 3l90 34c13 6 32 16 32 31l0 304c0 14-14 26-32 26z m-351-371c-1 0-1 1-1 2l0 303c0 2 5 6 14 9l1 0 1 1 89 34c1-1 0-1 0-2l0-303c0-1-3-4-16-10z m356 42c-1-2-5-5-17-11l-90-34c0 1-1 1-1 2l0 304c0 1 5 5 14 8l1 0 1 1 91 34c0 0 1-1 1-1z"/>
<glyph glyph-name="menu" unicode="&#118;" d="M257 22c-60 0-119 22-164 67-44 44-68 102-68 164 0 62 24 120 68 163 90 91 237 91 327 0 44-43 68-101 68-163 0-62-24-120-68-164-45-45-104-67-163-67z m0 431c-52 0-103-20-142-59-38-38-58-88-58-141 0-54 20-104 58-142 78-78 205-78 283 0 38 38 59 88 59 142 0 53-21 103-59 141-39 39-90 59-141 59z m101-133l-203 0c-8 0-15 7-15 15 0 8 7 15 15 15l203 0c8 0 14-7 14-15 0-8-6-15-14-15z m0-84l-203 0c-8 0-15 7-15 15 0 8 7 15 15 15l203 0c8 0 14-7 14-15 0-8-6-15-14-15z m0-81l-203 0c-8 0-15 7-15 15 0 8 7 14 15 14l203 0c8 0 14-6 14-14 0-8-6-15-14-15z"/>
<glyph glyph-name="close" unicode="&#119;" d="M258 19c-59 0-118 23-163 68-44 43-68 101-68 163 0 62 24 120 68 164 90 90 237 90 327 0 44-44 68-102 68-164 0-62-24-120-68-163-45-45-104-68-164-68z m0 431c-51 0-102-19-141-58-38-38-59-88-59-142 0-53 21-103 59-141 78-78 205-78 283 0 38 38 58 88 58 141 0 54-20 104-58 142-39 39-90 58-142 58z m25-200l67 67c7 7 7 18 0 25-7 7-18 7-25 0l-67-67-66 67c-7 7-18 7-25 0-7-7-7-18 0-25l66-67-66-66c-7-7-7-18 0-25 7-7 18-7 25 0l66 66 67-66c7-7 18-7 25 0 7 7 7 18 0 25z"/>
@ -145,4 +144,14 @@
<glyph glyph-name="rez" unicode="&#57381;" d="M373 321c-2 5-6 8-11 8l-49 8 55 61c4 4 5 9 3 14-2 5-7 8-12 8 0 0 0 0 0 0l-114-1c-5-1-10-4-12-9l-54-136c-1-4-1-8 1-11 2-4 6-6 9-7l38-5-54-136c-2-6 0-13 6-16 2-1 4-2 7-2 3 0 7 2 10 5l175 206c3 4 3 9 2 13z"/>
<glyph glyph-name="keyboard-collapse" unicode="&#57387;" d="M373 249l-26 0 0 25 26 0z m-35 0l-27 0 0 25 27 0z m-36 0l-27 0 0 25 27 0z m-36 0l-26 0 0 25 26 0z m-35 0l-27 0 0 25 27 0z m-36 0l-27 0 0 25 27 0z m-36 0l-26 0 0 25 26 0z m224-1l18 0c7 0 13 6 13 13 0 7-6 13-13 13l-18 0m-262 0l-17 0c-7 0-13-6-13-13 0-7 6-13 13-13l17 0m252 39l-31 0 0 25 31 0z m-42 0l-31 0 0 25 31 0z m-41 0l-32 0 0 25 32 0z m-42 0l-32 0 0 25 32 0z m-42 0l-32 0 0 25 32 0z m-41 0l-32 0 0 25 32 0z m218-1l18 0c7 0 13 6 13 13 0 8-6 14-13 14l-18 0m-262 0l-17 0c-7 0-13-6-13-14 0-7 6-13 13-13l17 0m288-124l-315 0c-33 0-59 28-59 61l0 76c0 34 26 61 59 61l315 0c33 0 59-27 59-61l0-76c1-33-26-61-59-61z m-315 172c-18 0-33-16-33-34l0-77c0-19 15-34 33-34l315 0c18 0 33 15 33 34l0 77c0 19-15 34-33 34z m248-99l32 0 0-25-32 0z m-41 0l31 0 0-25-31 0z m-42 0l31 0 0-25-31 0z m-43 0l32 0 0-25-32 0z m-42 0l32 0 0-25-32 0z m-41 0l31 0 0-25-31 0z m250-26l18 0c7 0 13 6 13 14 0 7-6 13-13 13l-18 0m-262 0l-17 0c-7 0-13-6-13-13 0-8 6-13 13-13l17 0m81-82l50-50 53 54-107 0"/>
<glyph glyph-name="image" unicode="&#57386;" d="M257 428c52 0 104 0 156 0 24 0 37-13 37-37 1-90 1-179 0-269 0-25-13-38-39-38-103 0-207 0-311 0-26 0-39 13-39 40 0 88 0 176 0 263 0 28 13 41 41 41 51 0 103 0 155 0z m167-263c0 7 0 10 0 14 0 69 0 138 0 206 0 17 0 17-17 17-101 0-202 0-303 0-16 0-17-1-17-17 0-58 0-115 0-173 0-3 0-7 0-12 8 3 14 6 19 9 17 8 30 7 44-6 5-5 10-10 15-15 5-7 11-8 19-4 40 21 81 41 121 61 19 10 31 8 46-7 9-9 18-18 27-27 15-15 29-29 46-46z m-328-54c7 0 11-1 15-1 98 0 197 0 296 0 6 0 14 2 16 6 5 7 0 14-6 20-27 26-54 53-80 80-8 9-15 9-26 4-67-35-135-68-203-102-3-2-6-4-12-7z m-8 26c21 10 40 20 63 31-8 7-14 12-20 17-2 2-7 3-10 3-30-9-36-17-34-48 0 0 0-1 1-3z m134 169c1-25-21-46-46-46-25-1-46 20-47 46 0 25 21 46 47 47 25 0 46-21 46-47z m-46 22c-12 0-22-9-22-21 0-13 9-22 21-23 13 0 23 9 23 22 0 13-10 22-22 22z"/>
<glyph glyph-name="environments" unicode="&#57388;" d="M256 454c-110 0-199-89-199-199 0-110 89-199 199-199 0 0 0 0 0 0l2-1 0 1c109 1 197 90 197 199 0 110-89 199-199 199z m114-204l0 0 0 5c0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 2l0 4 0 0c-1 22-4 43-10 63 21 5 36 11 46 15 15-26 24-56 24-87 0-30-8-59-23-85-8 4-23 11-47 16 6 21 9 42 10 64z m-19 102c-13 30-30 53-46 69 34-10 64-30 86-57-9-4-22-8-40-12z m-6-95c0-23-4-45-11-66-20 4-42 6-65 6l0 120c23 1 45 3 66 6 6-21 10-43 10-66z m-46-170c17 17 37 41 52 75 20-5 34-10 42-13-24-31-57-53-94-62z m-30 256l0 77c17-14 40-37 56-73-17-2-36-4-56-4z m0-248l0 77c20-1 39-3 56-5-16-35-40-59-56-72z m-83 252c17 35 40 59 56 73l0-77c-19 0-38 1-56 4z m-19-90c0 23 4 45 10 65 20-3 42-5 65-5l0-120c-23 0-45-1-65-4-6 20-10 42-10 64z m-47 106c22 28 52 48 86 58-15-16-33-39-46-70-18 4-31 8-40 12z m40-199c15-36 37-61 53-77-38 10-72 32-96 64 9 4 24 9 43 13z m82 8l0-77c-16 13-39 37-56 73 18 2 37 3 56 4z m-100 92l-1 0 0-4c0-1 0-1 0-2 0 0 0 0 0-1 0 0 0 0 0-1 0 0 0-1 0-1l0-5 1 0c0-21 4-42 10-62-23-5-39-10-49-15-14 25-21 53-21 82 0 30 8 60 23 86 10-4 25-10 47-14-6-20-10-41-10-63z"/>
<glyph glyph-name="wand" unicode="&#57389;" d="M438 107l-80 78c-5 5-12 7-18 6l-77 78c-5 5-14 5-19 0-5-5-6-14 0-19l77-79c0-6 2-12 7-17l80-78c5-4 10-6 15-6 6 0 12 2 16 6 8 9 8 22-1 31z m-185 209l-28 0 0 27c0 6-5 11-12 11-6 0-11-5-11-11l0-27-27 0c-6 0-11-5-11-12 0-6 5-11 11-11l27 0 0-28c0-6 5-11 11-11 7 0 12 5 12 11l0 28 28 0c6 0 11 5 11 11 0 7-5 12-11 12z m51-22c-6 0-10 4-10 10 0 5 4 10 10 10 15 0 31 0 45 0 6 0 10-5 10-10 0-6-4-10-10-10-14 0-30 0-45 0 0 0 0 0 0 0z m-184 0c0 0 0 0 0 0-12 0-26 0-40 0 0 0 0 0 0 0-5 0-10 4-10 10 0 5 5 10 10 10 14 0 28 0 41 0 5 0 10-5 10-10-1-6-5-10-11-10z m94-129c-5 0-10 4-10 9 0 14 0 26 0 40 0 5 5 9 10 9 0 0 0 0 0 0 6 0 10-5 10-10 0-13 0-25 0-38 0-6-4-10-10-10 0 0 0 0 0 0z m0 223c-5 0-10 4-10 9 0 14 0 26 0 40 0 5 5 9 10 9 6 0 10-5 10-10 0-13 0-25 0-38 0-6-4-10-10-10 0 0 0 0 0 0z m-68-26c-2 0-4 0-6 2-6 5-11 10-16 15-4 5-8 9-12 13-4 4-5 10-1 14 4 4 10 4 14 1 5-5 9-9 14-14 4-5 9-10 14-14 4-4 4-10 1-14-2-2-5-3-8-3z m-24-159c-3 0-5 1-7 3-4 3-4 10-1 14 5 5 9 10 14 14 5 4 9 8 12 12 4 4 10 5 14 1 4-4 5-10 1-14-4-5-9-10-13-14-5-4-9-8-13-12-2-2-4-4-7-4z m157 157c-3 0-5 1-6 2-5 3-6 10-2 14 4 6 10 11 15 16 5 4 10 8 13 12 3 5 10 6 14 2 4-3 5-9 2-14-5-6-10-10-15-15-5-4-10-8-13-13-2-2-5-4-8-4z"/>
<glyph glyph-name="market" unicode="&#116;" d="M428 332c-2 4-7 7-12 7-5 1-10 1-14 1-5 0-10 1-15 1-27 1-51 2-75 3-23 1-47 2-74 3-10 0-18 1-27 1-9 0-18 1-27 1l-1 0 0 1c-2 8-8 26-12 39-2 5-3 9-4 12-2 8-7 12-16 12l-48 0c-9 0-16-6-16-15 0-8 7-14 16-14l32 0c5 0 7-3 8-7l0 0c6-25 13-51 19-76 7-24 13-50 19-75 2-9 3-16 0-24-1-4-2-9-3-14-1-4-2-9-3-14-2-8-2-14 1-17 3-4 8-6 16-6l190 0c4 1 7 3 9 6 3 3 4 8 3 12-1 8-7 12-17 12l-170 0 1 1c0 1 1 4 1 6 2 7 5 17 4 20l0 1c1 6 5 10 12 10 8 0 16 0 24 0 43 2 87 3 128 5 8 1 12 4 15 10 8 15 29 65 36 86l0 0c3 4 3 8 0 12z m-45-224c0-16-13-30-29-30-16 0-29 13-29 30 0 15 13 30 29 30 16-1 29-15 29-30z m-177 1c0-16-14-29-29-29-16 0-29 14-29 29 0 17 13 30 29 30 16-1 29-14 29-30z"/>
<glyph glyph-name="wear" unicode="&#57390;" d="M451 180c3 1 5 4 6 7 1 3 1 7-1 10-2 3-4 5-8 6-3 1-6 1-10-1-6-4-13-5-19-6-3-1-6-1-7-1-1 0-1 0-1 0l-1 0-26 0 0 66c0 9-3 43-27 73-24 29-58 44-101 44-54 0-84-24-100-44-24-30-26-64-27-73l0-66-17 0c-2 0-4 0-8 1-8 1-17 3-27 7-7 3-14-1-17-7-2-7 1-14 8-17 14-6 27-8 33-9 3 0 6 0 8-1 1 0 1 0 2 0l299 0c1 0 2 0 3 0l0 0c2 1 6 1 10 2 6 1 18 3 28 9z m-295 80c0 15 6 39 20 58 18 22 45 34 80 34 35 0 62-12 80-34 15-19 21-43 22-58l0-6-202 0z m202-65l-202 0 0 33 202 0z"/>
<glyph glyph-name="certificate" unicode="&#57392;" d="M168 320l172 0c7 0 14 6 14 14 0 7-7 13-14 13l-172 0c-8 0-14-6-14-13 0-8 6-14 14-14z m0-55l63 0c7 0 13 6 13 13 0 8-6 13-13 13l-63 0c-8 0-14-5-14-13 0-7 6-13 14-13z m0-57l46 0c8 0 14 6 14 14 0 7-6 14-14 14l-46 0c-8 0-14-7-14-14 0-8 6-14 14-14z m-65 210l0-283 139 0c7 0 12 6 12 13 0 6-5 12-12 12l-114 0 0 233 256 0 0-83c0-7 6-12 13-12 6 0 12 5 12 12l0 108z m304-200c0 43-35 78-78 78-43 0-78-35-78-78 0-27 14-52 37-66l-3-69c0-5 2-9 6-11 5-3 10-2 13 1l27 20 26-21c2-2 5-3 8-3 2 0 4 0 5 1 4 2 7 7 7 12l-4 72c21 14 34 38 34 64z m-68-101c-4 4-10 4-14 1l-15-11 1 36c6-2 12-2 18-2 7 0 14 1 20 2l2-36z"/>
<glyph glyph-name="gift" unicode="&#57393;" d="M342 330c1 1 3 2 4 3 19 17 21 47 4 66-9 10-22 16-35 16-6 0-12-1-17-3-6 19-24 33-45 33-22 0-41-15-46-35-5 2-11 3-17 3-13 0-26-6-35-16-17-20-15-50 5-66 0 0 0 0 0-1l-82 0 0-84 27 0 0-166 298 0 0 166 27 0 0 84z m-45 50l0 1c1 1 2 2 4 3 5 5 10 6 14 6 6 0 12-3 16-8 4-4 6-9 5-15 0-6-3-11-7-15-2-2-3-3-4-3l0 0 0 0c-5-1-27-10-52-18 10 22 22 44 24 49z m-44 40c12 0 21-9 21-21 0-3 0-4 0-5l0 0 0 0c-2-5-11-24-21-48-10 23-19 42-21 47l0 1c0 1-1 3-1 5 0 12 10 21 22 21z m-79-40c4 5 10 8 16 8 4 0 9-1 14-5 2-2 3-3 4-4l0 0 0 0c2-5 11-23 22-47-24 7-44 13-49 15l-1 0c-1 1-2 2-4 3-9 8-10 21-2 30z m67-274l-110 0 0 140 110 0z m0 166l-137 0 0 32 137 0z m136-166l-111 0 0 140 111 0z m27 166l-138 0 0 32 138 0z"/>
<glyph glyph-name="update" unicode="&#57394;" d="M380 170c-7 0-13-6-13-13l0-12c0-5-4-9-9-9l-203 0c-5 0-9 4-9 9l0 114 33-27c6-4 14-4 19 2 4 5 4 13-2 18l-54 47c-3 2-5 3-8 3-4 0-7-1-9-3l-54-47c-6-5-6-13-1-18 4-6 13-6 18-1l32 26 0-114c0-19 16-35 35-35l203 0c19 0 35 16 35 35l0 12c0 7-6 13-13 13z m-248 153c7 0 13 5 13 13l0 12c0 5 4 8 9 8l203 0c5 0 9-4 9-8l0-115-33 27c-5 5-14 4-18-1-5-6-5-14 1-19l54-47c3-2 5-3 9-3 3 0 6 1 8 3l54 47c6 5 6 13 2 19-5 5-13 6-19 1l-32-27 0 115c0 19-16 34-35 34l-203 0c-19 0-35-15-35-34l0-12c0-8 6-13 13-13z"/>
<glyph glyph-name="uninstall" unicode="&#57395;" d="M83 227c-7 0-13-6-13-13l0-78c0-19 16-35 35-35l297 0c19 0 35 16 35 35l0 78c0 7-6 13-13 13-7 0-13-6-13-13l0-78c0-5-4-9-9-9l-297 0c-5 0-9 4-9 9l0 78c0 7-6 13-13 13z m191 47l50 50c5 5 5 14 0 19-5 5-13 5-19 0l-50-50-50 50c-5 5-13 5-19 0-5-5-5-14 0-19l50-50-50-50c-5-5-5-14 0-19 5-5 14-5 19 0l50 50 50-50c5-5 14-5 19 0 5 5 5 14 0 19z"/>
<glyph glyph-name="install" unicode="&#57391;" d="M83 227c-7 0-13-6-13-13l0-78c0-19 16-35 35-35l297 0c19 0 35 16 35 35l0 78c0 7-6 13-13 13-7 0-13-6-13-13l0-78c0-5-4-9-9-9l-297 0c-5 0-9 4-9 9l0 78c0 7-6 13-13 13z m170 171l0-155-33 27c-6 5-14 5-19-1-4-5-4-14 2-18l54-48c3-2 5-3 8-3 3 0 7 1 9 3l54 48c5 4 6 13 1 18-4 5-13 6-18 1l-32-27 0 154c0 8-6 13-13 13-7 0-13-5-13-12z"/>
<glyph glyph-name="ellipsis-vertical" unicode="&#57396;" d="M276 178c0-14-11-24-24-24-14 0-25 10-25 24 0 13 11 24 25 24 13 0 24-11 24-24z m0 78c0-14-11-24-24-24-14 0-25 10-25 24 0 13 11 24 25 24 13 0 24-11 24-24z m0 78c0-14-11-24-24-24-14 0-25 10-25 24 0 13 11 24 25 24 13 0 24-11 24-24z"/>
</font></defs></svg>

Before

(image error) Size: 78 KiB

After

(image error) Size: 83 KiB

View file

@ -12,7 +12,7 @@
<body>
<div class="container">
<h1>HiFi Glyphs</h1>
<p class="small">This font was created for use in<a href="http://highfidelity.io/">High Fidelity</a></p>
<p class="small">This font was created for use in <a href="http://highfidelity.io/">High Fidelity</a></p>
<h2>CSS mapping</h2>
<ul class="glyphs css-mapping">
<li>
@ -87,10 +87,6 @@
<div class="icon icon-edit"></div>
<input type="text" readonly="readonly" value="edit">
</li>
<li>
<div class="icon icon-market"></div>
<input type="text" readonly="readonly" value="market">
</li>
<li>
<div class="icon icon-directory"></div>
<input type="text" readonly="readonly" value="directory">
@ -567,6 +563,46 @@
<div class="icon icon-image"></div>
<input type="text" readonly="readonly" value="image">
</li>
<li>
<div class="icon icon-environments"></div>
<input type="text" readonly="readonly" value="environments">
</li>
<li>
<div class="icon icon-wand"></div>
<input type="text" readonly="readonly" value="wand">
</li>
<li>
<div class="icon icon-market"></div>
<input type="text" readonly="readonly" value="market">
</li>
<li>
<div class="icon icon-wear"></div>
<input type="text" readonly="readonly" value="wear">
</li>
<li>
<div class="icon icon-certificate"></div>
<input type="text" readonly="readonly" value="certificate">
</li>
<li>
<div class="icon icon-gift"></div>
<input type="text" readonly="readonly" value="gift">
</li>
<li>
<div class="icon icon-update"></div>
<input type="text" readonly="readonly" value="update">
</li>
<li>
<div class="icon icon-uninstall"></div>
<input type="text" readonly="readonly" value="uninstall">
</li>
<li>
<div class="icon icon-install"></div>
<input type="text" readonly="readonly" value="install">
</li>
<li>
<div class="icon icon-ellipsis-vertical"></div>
<input type="text" readonly="readonly" value="ellipsis-vertical">
</li>
</ul>
<h2>Character mapping</h2>
<ul class="glyphs character-mapping">
@ -642,10 +678,6 @@
<div data-icon="s" class="icon"></div>
<input type="text" readonly="readonly" value="s">
</li>
<li>
<div data-icon="t" class="icon"></div>
<input type="text" readonly="readonly" value="t">
</li>
<li>
<div data-icon="u" class="icon"></div>
<input type="text" readonly="readonly" value="u">
@ -1122,6 +1154,46 @@
<div data-icon="&#xe02a;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe02a;">
</li>
<li>
<div data-icon="&#xe02c;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe02c;">
</li>
<li>
<div data-icon="&#xe02d;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe02d;">
</li>
<li>
<div data-icon="t" class="icon"></div>
<input type="text" readonly="readonly" value="t">
</li>
<li>
<div data-icon="&#xe02e;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe02e;">
</li>
<li>
<div data-icon="&#xe030;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe030;">
</li>
<li>
<div data-icon="&#xe031;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe031;">
</li>
<li>
<div data-icon="&#xe032;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe032;">
</li>
<li>
<div data-icon="&#xe033;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe033;">
</li>
<li>
<div data-icon="&#xe02f;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe02f;">
</li>
<li>
<div data-icon="&#xe034;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe034;">
</li>
</ul>
</div>
<script>(function() {

View file

@ -92,9 +92,6 @@
.icon-edit:before {
content: "\73";
}
.icon-market:before {
content: "\74";
}
.icon-directory:before {
content: "\75";
}
@ -452,3 +449,33 @@
.icon-image:before {
content: "\e02a";
}
.icon-environments:before {
content: "\e02c";
}
.icon-wand:before {
content: "\e02d";
}
.icon-market:before {
content: "\74";
}
.icon-wear:before {
content: "\e02e";
}
.icon-certificate:before {
content: "\e030";
}
.icon-gift:before {
content: "\e031";
}
.icon-update:before {
content: "\e032";
}
.icon-uninstall:before {
content: "\e033";
}
.icon-install:before {
content: "\e02f";
}
.icon-ellipsis-vertical:before {
content: "\e034";
}

View file

@ -8,8 +8,9 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "../styles-uit"
import "../controls-uit" as HifiControls
@ -28,17 +29,11 @@ TextField {
property int roundedBorderRadius: 4
property bool error: false;
property bool hasClearButton: false;
property alias textColor: textField.color
property string leftPermanentGlyph: "";
property string centerPlaceholderGlyph: "";
placeholderText: textField.placeholderText
property bool rightAnchorSet: false;
anchors.onRightChanged: {
rightAnchorSet = true;
}
font.family: "Fira Sans"
font.pixelSize: hifi.fontSizes.textFieldInput
height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered.
@ -49,56 +44,42 @@ TextField {
// workaround for https://bugreports.qt.io/browse/QTBUG-49297
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Return:
case Qt.Key_Enter:
event.accepted = true;
case Qt.Key_Return:
case Qt.Key_Enter:
event.accepted = true;
// emit accepted signal manually
if (acceptableInput) {
accepted();
}
// emit accepted signal manually
if (acceptableInput) {
accepted();
}
}
}
Text {
id: placeholder
x: textField.leftPadding
y: textField.topPadding
width: textField.width - (textField.leftPadding + textField.rightPadding)
height: textField.height - (textField.topPadding + textField.bottomPadding)
text: textField.placeholderText
font: textField.font
color: textField.placeholderTextColor
verticalAlignment: textField.verticalAlignment
visible: !textField.length && !textField.preeditText && (!textField.activeFocus || textField.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
}
color: {
if (isLightColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
style: TextFieldStyle {
id: style;
textColor: {
if (isLightColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.lightGray
}
} else if (isFaintGrayColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.lightGray
}
} else {
hifi.colors.lightGray
}
} else if (isFaintGrayColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.lightGray
}
} else {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.lightGrayText
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.lightGrayText
}
}
}
}
background: Rectangle {
color: {
background: Rectangle {
color: {
if (isLightColorScheme) {
if (textField.activeFocus) {
hifi.colors.white
@ -119,22 +100,22 @@ TextField {
}
}
}
border.color: textField.error ? hifi.colors.redHighlight :
border.color: textField.error ? hifi.colors.redHighlight :
(textField.activeFocus ? hifi.colors.primaryHighlight : (hasDefocusedBorder ? (isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray) : color))
border.width: textField.activeFocus || hasRoundedBorder || textField.error ? 1 : 0
border.width: textField.activeFocus || hasRoundedBorder || textField.error ? 1 : 0
radius: isSearchField ? textField.height / 2 : (hasRoundedBorder ? roundedBorderRadius : 0)
HiFiGlyphs {
HiFiGlyphs {
text: textField.leftPermanentGlyph;
color: textColor;
size: hifi.fontSizes.textFieldSearchIcon;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
anchors.leftMargin: hifi.dimensions.textPadding - 2;
visible: text;
}
color: textColor;
size: hifi.fontSizes.textFieldSearchIcon;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
anchors.leftMargin: hifi.dimensions.textPadding - 2;
visible: text;
}
HiFiGlyphs {
HiFiGlyphs {
text: textField.centerPlaceholderGlyph;
color: textColor;
size: parent.height;
@ -144,57 +125,48 @@ TextField {
}
HiFiGlyphs {
text: hifi.glyphs.search
color: textColor
size: hifi.fontSizes.textFieldSearchIcon
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: hifi.dimensions.textPadding - 2
visible: isSearchField
}
text: hifi.glyphs.search
color: textColor
size: hifi.fontSizes.textFieldSearchIcon
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: hifi.dimensions.textPadding - 2
visible: isSearchField
}
HiFiGlyphs {
text: hifi.glyphs.error
color: textColor
size: 40
anchors.right: parent.right
anchors.rightMargin: hifi.dimensions.textPadding - 2
anchors.verticalCenter: parent.verticalCenter
visible: hasClearButton && textField.text !== "";
HiFiGlyphs {
text: hifi.glyphs.error
color: textColor
size: 40
anchors.right: parent.right
anchors.rightMargin: hifi.dimensions.textPadding - 2
anchors.verticalCenter: parent.verticalCenter
visible: hasClearButton && textField.text !== "";
MouseArea {
anchors.fill: parent;
onClicked: {
textField.text = "";
MouseArea {
anchors.fill: parent;
onClicked: {
textField.text = "";
}
}
}
}
placeholderTextColor: isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray
selectedTextColor: hifi.colors.black
selectionColor: hifi.colors.primaryHighlight
padding.left: hasRoundedBorder ? textField.height / 2 : ((isSearchField || textField.leftPermanentGlyph !== "") ? textField.height - 2 : 0) + hifi.dimensions.textPadding
padding.right: (hasClearButton ? textField.height - 2 : 0) + hifi.dimensions.textPadding
}
property color placeholderTextColor: isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray
selectedTextColor: hifi.colors.black
selectionColor: hifi.colors.primaryHighlight
leftPadding: hasRoundedBorder ? textField.height / 2 : ((isSearchField || textField.leftPermanentGlyph !== "") ? textField.height - 2 : 0) + hifi.dimensions.textPadding
rightPadding: (hasClearButton ? textField.height - 2 : 0) + hifi.dimensions.textPadding
HifiControls.Label {
id: textFieldLabel
text: textField.label
colorScheme: textField.colorScheme
anchors.left: parent.left
Binding on anchors.right {
when: rightAnchorSet
value: textField.right
}
Binding on wrapMode {
when: rightAnchorSet
value: Text.WordWrap
}
anchors.right: parent.right
anchors.bottom: parent.top
anchors.bottomMargin: 3
wrapMode: Text.WordWrap
visible: label != ""
}
}

View file

@ -257,9 +257,14 @@ Rectangle {
lightboxPopup.bodyImageSource = msg.securityImageSource;
lightboxPopup.bodyText = lightboxPopup.securityPicBodyText;
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "GO TO WALLET";
lightboxPopup.button2method = "sendToParent({method: 'checkout_openWallet'});";
lightboxPopup.button2method = function() {
lightboxPopup.visible = false;
sendToScript({method: 'checkout_openWallet'});
};
lightboxPopup.visible = true;
} else {
sendToScript(msg);
@ -623,10 +628,16 @@ Rectangle {
lightboxPopup.bodyText = "You will not be able to replace this domain's content with <b>" + root.itemName +
" </b>until the server owner gives you 'Replace Content' permissions.<br><br>Are you sure you want to purchase this content set?";
lightboxPopup.button1text = "CANCEL";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = "Commerce.buy('" + root.itemId + "', " + root.itemPrice + ");" +
"root.visible = false; buyButton.enabled = false; loading.visible = true;";
lightboxPopup.button2method = function() {
Commerce.buy(root.itemId, root.itemPrice);
lightboxPopup.visible = false;
buyButton.enabled = false;
loading.visible = true;
};
lightboxPopup.visible = true;
} else {
buyButton.enabled = false;
@ -771,19 +782,30 @@ Rectangle {
"<a href='https://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content'>" +
"click here to open info on your desktop browser.";
lightboxPopup.button1text = "CANCEL";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = "Commerce.replaceContentSet('" + root.itemHref + "', '" + root.certificateId + "');" +
"root.visible = false;rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start();" +
"UserActivityLogger.commerceEntityRezzed('" + root.itemId + "', 'checkout', '" + root.itemType + "');";
lightboxPopup.button2method = function() {
Commerce.replaceContentSet(root.itemHref);
lightboxPopup.visible = false;
rezzedNotifContainer.visible = true;
rezzedNotifContainerTimer.start();
UserActivityLogger.commerceEntityRezzed(root.itemId, 'checkout', root.itemType);
};
lightboxPopup.visible = true;
} else if (root.itemType === "avatar") {
lightboxPopup.titleText = "Change Avatar";
lightboxPopup.bodyText = "This will change your current avatar to " + root.itemName + " while retaining your wearables.";
lightboxPopup.button1text = "CANCEL";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + root.itemHref + "'); root.visible = false;";
lightboxPopup.button2method = function() {
MyAvatar.useFullAvatarURL(root.itemHref);
lightboxPopup.visible = false;
};
lightboxPopup.visible = true;
} else if (root.itemType === "app") {
if (root.isInstalled) {
@ -822,9 +844,14 @@ Rectangle {
lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.<br><br>" +
"Use the <b>GOTO app</b> to visit another domain or <b>go to your own sandbox.</b>";
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "OPEN GOTO";
lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});";
lightboxPopup.button2method = function() {
sendToScript({method: 'purchases_openGoTo'});
lightboxPopup.visible = false;
};
lightboxPopup.visible = true;
}
}
@ -918,7 +945,9 @@ Rectangle {
lightboxPopup.bodyText = 'Your item is marked "pending" while your purchase is being confirmed.<br><br>' +
'Confirmations usually take about 90 seconds.';
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
}
}

View file

@ -26,10 +26,10 @@ Rectangle {
property string bodyText;
property string button1color: hifi.buttons.noneBorderlessGray;
property string button1text;
property string button1method;
property string button2color: hifi.buttons.noneBorderless;
property var button1method;
property string button2color: hifi.buttons.blue;
property string button2text;
property string button2method;
property var button2method;
property string buttonLayout: "leftright";
readonly property string securityPicBodyText: "When you see your Security Pic, your actions and data are securely making use of your " +
@ -72,7 +72,7 @@ Rectangle {
anchors.right: parent.right;
anchors.rightMargin: 30;
height: paintedHeight;
color: hifi.colors.baseGray;
color: hifi.colors.black;
size: 24;
verticalAlignment: Text.AlignTop;
wrapMode: Text.WordWrap;
@ -104,7 +104,7 @@ Rectangle {
anchors.right: parent.right;
anchors.rightMargin: 30;
height: paintedHeight;
color: hifi.colors.baseGray;
color: hifi.colors.black;
size: 20;
verticalAlignment: Text.AlignTop;
wrapMode: Text.WordWrap;
@ -129,15 +129,15 @@ Rectangle {
colorScheme: hifi.colorSchemes.light;
anchors.top: root.buttonLayout === "leftright" ? parent.top : parent.top;
anchors.left: parent.left;
anchors.leftMargin: 10;
anchors.leftMargin: root.buttonLayout === "leftright" ? 30 : 10;
anchors.right: root.buttonLayout === "leftright" ? undefined : parent.right;
anchors.rightMargin: root.buttonLayout === "leftright" ? undefined : 10;
width: root.buttonLayout === "leftright" ? (root.button2text ? parent.width/2 - anchors.leftMargin*2 : parent.width - anchors.leftMargin * 2) :
(undefined);
height: 50;
height: 40;
text: root.button1text;
onClicked: {
eval(button1method);
button1method();
}
}
@ -152,12 +152,12 @@ Rectangle {
anchors.left: root.buttonLayout === "leftright" ? undefined : parent.left;
anchors.leftMargin: root.buttonLayout === "leftright" ? undefined : 10;
anchors.right: parent.right;
anchors.rightMargin: 10;
anchors.rightMargin: root.buttonLayout === "leftright" ? 30 : 10;
width: root.buttonLayout === "leftright" ? parent.width/2 - anchors.rightMargin*2 : undefined;
height: 50;
height: 40;
text: root.button2text;
onClicked: {
eval(button2method);
button2method();
}
}
}
@ -174,10 +174,10 @@ Rectangle {
root.bodyText = "";
root.button1color = hifi.buttons.noneBorderlessGray;
root.button1text = "";
root.button1method = "";
root.button2color = hifi.buttons.noneBorderless;
root.button1method = function() {};
root.button2color = hifi.buttons.blue;
root.button2text = "";
root.button2method = "";
root.button2method = function() {};
root.buttonLayout = "leftright";
}
//

View file

@ -1,6 +1,6 @@
//
// ConnectionItem.qml
// qml/hifi/commerce/wallet/sendMoney
// qml/hifi/commerce/common/sendAsset
//
// ConnectionItem
//
@ -113,7 +113,7 @@ Item {
text: "CHOOSE";
onClicked: {
var msg = { method: 'chooseConnection', userName: root.userName, profilePicUrl: root.profilePicUrl };
sendToSendMoney(msg);
sendToParent(msg);
}
}
}
@ -121,7 +121,7 @@ Item {
//
// FUNCTION DEFINITIONS START
//
signal sendToSendMoney(var msg);
signal sendToParent(var msg);
//
// FUNCTION DEFINITIONS END
//

View file

@ -1,6 +1,6 @@
//
// RecipientDisplay.qml
// qml/hifi/commerce/wallet/sendMoney
// qml/hifi/commerce/common/sendAsset
//
// RecipientDisplay
//
@ -18,7 +18,7 @@ import QtGraphicalEffects 1.0
import "../../../../styles-uit"
import "../../../../controls-uit" as HifiControlsUit
import "../../../../controls" as HifiControls
import "../../common" as HifiCommerceCommon
import "../" as HifiCommerceCommon
Item {
HifiConstants { id: hifi; }

View file

@ -13,7 +13,6 @@
import Hifi 1.0 as Hifi
import QtQuick 2.5
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "../../../styles-uit"
@ -22,14 +21,11 @@ import "../../../controls" as HifiControls
import "../wallet" as HifiWallet
import TabletScriptingInterface 1.0
// references XXX from root context
Item {
HifiConstants { id: hifi; }
id: root;
property string purchaseStatus;
property bool purchaseStatusChanged;
property string itemName;
property string itemId;
property string itemPreviewImageUrl;
@ -46,16 +42,18 @@ Item {
property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar];
property bool showConfirmation: false;
property bool hasPermissionToRezThis;
property bool permissionExplanationCardVisible;
property bool cardBackVisible;
property bool isInstalled;
property string wornEntityID;
property string upgradeUrl;
property string upgradeTitle;
property bool updateAvailable: root.upgradeUrl !== "" && !root.isShowingMyItems;
property bool isShowingMyItems;
property string originalStatusText;
property string originalStatusColor;
height: (root.upgradeUrl === "" || root.isShowingMyItems) ? 110 : 150;
height: 102;
width: parent.width;
Connections {
@ -99,16 +97,6 @@ Item {
}
}
onPurchaseStatusChangedChanged: {
if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") {
root.originalStatusText = statusText.text;
root.originalStatusColor = statusText.color;
statusText.text = "CONFIRMED!";
statusText.color = hifi.colors.blueAccent;
confirmedTimer.start();
}
}
onShowConfirmationChanged: {
if (root.showConfirmation) {
rezzedNotifContainer.visible = true;
@ -118,35 +106,307 @@ Item {
}
}
Timer {
id: confirmedTimer;
interval: 3000;
onTriggered: {
statusText.text = root.originalStatusText;
statusText.color = root.originalStatusColor;
root.purchaseStatusChanged = false;
Rectangle {
id: background;
z: 10;
color: Qt.rgba(0, 0, 0, 0.25);
anchors.fill: parent;
}
Flipable {
id: flipable;
z: 50;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: parent.top;
height: root.height - 2;
front: mainContainer;
back: Rectangle {
anchors.fill: parent;
color: hifi.colors.white;
Item {
id: closeContextMenuContainer;
anchors.right: parent.right;
anchors.rightMargin: 8;
anchors.top: parent.top;
anchors.topMargin: 8;
width: 30;
height: width;
HiFiGlyphs {
id: closeContextMenuGlyph;
text: hifi.glyphs.close;
anchors.fill: parent;
size: 26;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
color: hifi.colors.black;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
root.sendToPurchases({ method: 'flipCard', closeAll: true });
}
onEntered: {
closeContextMenuGlyph.text = hifi.glyphs.closeInverted;
}
onExited: {
closeContextMenuGlyph.text = hifi.glyphs.close;
}
}
}
Rectangle {
id: contextCard;
z: 2;
anchors.left: parent.left;
anchors.leftMargin: 30;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.right: closeContextMenuContainer.left;
anchors.rightMargin: 8;
color: hifi.colors.white;
Component {
id: contextCardButton;
Item {
property alias buttonGlyphText: buttonGlyph.text;
property alias buttonText: buttonText.text;
property string buttonColor: hifi.colors.black;
property string buttonColor_hover: hifi.colors.blueHighlight;
property alias enabled: buttonMouseArea.enabled;
property var buttonClicked;
HiFiGlyphs {
id: buttonGlyph;
anchors.top: parent.top;
anchors.topMargin: 4;
anchors.horizontalCenter: parent.horizontalCenter;
anchors.bottom: parent.verticalCenter;
width: parent.width;
size: 40;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
color: buttonMouseArea.enabled ? buttonColor : hifi.colors.lightGrayText;
}
RalewayRegular {
id: buttonText;
anchors.top: parent.verticalCenter;
anchors.topMargin: 4;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 12;
anchors.horizontalCenter: parent.horizontalCenter;
width: parent.width;
color: buttonMouseArea.enabled ? buttonColor : hifi.colors.lightGrayText;
size: 16;
wrapMode: Text.Wrap;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
}
MouseArea {
id: buttonMouseArea;
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
parent.buttonClicked();
}
onEntered: {
buttonGlyph.color = buttonColor_hover;
buttonText.color = buttonColor_hover;
}
onExited: {
buttonGlyph.color = buttonColor;
buttonText.color = buttonColor;
}
}
}
}
Loader {
id: giftButton;
visible: !root.isShowingMyItems;
sourceComponent: contextCardButton;
anchors.right: parent.right;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: 62;
onLoaded: {
item.enabled = (root.purchaseStatus === "confirmed");
item.buttonGlyphText = hifi.glyphs.gift;
item.buttonText = "Gift";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
sendToPurchases({
method: 'giftAsset',
itemName: root.itemName,
certId: root.certificateId,
itemType: root.itemType,
itemHref: root.itemHref,
isInstalled: root.isInstalled,
wornEntityID: root.wornEntityID,
effectImage: root.itemPreviewImageUrl
});
}
}
}
Loader {
id: marketplaceButton;
sourceComponent: contextCardButton;
anchors.right: giftButton.visible ? giftButton.left : parent.right;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: 100;
onLoaded: {
item.buttonGlyphText = hifi.glyphs.market;
item.buttonText = "View in Marketplace";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
sendToPurchases({method: 'purchases_itemInfoClicked', itemId: root.itemId});
}
}
}
Loader {
id: certificateButton;
sourceComponent: contextCardButton;
anchors.right: marketplaceButton.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: 100;
onLoaded: {
item.buttonGlyphText = hifi.glyphs.certificate;
item.buttonText = "View Certificate";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId});
}
}
}
Loader {
id: uninstallButton;
visible: root.isInstalled;
sourceComponent: contextCardButton;
anchors.right: certificateButton.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: 78;
onLoaded: {
item.buttonGlyphText = hifi.glyphs.uninstall;
item.buttonText = "Uninstall";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
Commerce.uninstallApp(root.itemHref);
}
}
}
Loader {
id: updateButton;
visible: root.updateAvailable;
sourceComponent: contextCardButton;
anchors.right: uninstallButton.visible ? uninstallButton.left : certificateButton.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: 84;
onLoaded: {
item.buttonGlyphText = hifi.glyphs.update;
item.buttonText = "Update";
item.buttonColor = "#E2334D";
item.buttonClicked = function() {
sendToPurchases({ method: 'flipCard', closeAll: true });
sendToPurchases({method: 'updateItemClicked', itemId: root.itemId, itemEdition: root.itemEdition, upgradeUrl: root.upgradeUrl});
}
}
}
}
Rectangle {
id: permissionExplanationCard;
z: 1;
anchors.left: parent.left;
anchors.leftMargin: 30;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.right: closeContextMenuContainer.left;
anchors.rightMargin: 8;
color: hifi.colors.white;
RalewayRegular {
id: permissionExplanationText;
anchors.fill: parent;
text: {
if (root.itemType === "contentSet") {
"You do not have 'Replace Content' permissions in this domain. <a href='#replaceContentPermission'>Learn more</a>";
} else if (root.itemType === "entity") {
"You do not have 'Rez Certified' permissions in this domain. <a href='#rezCertifiedPermission'>Learn more</a>";
} else {
"Hey! You're not supposed to see this. How is it even possible that you're here? Are you a developer???"
}
}
size: 16;
color: hifi.colors.baseGray;
wrapMode: Text.Wrap;
verticalAlignment: Text.AlignVCenter;
onLinkActivated: {
sendToPurchases({method: 'showPermissionsExplanation', itemType: root.itemType});
}
}
}
}
transform: Rotation {
id: rotation;
origin.x: flipable.width/2;
origin.y: flipable.height/2;
axis.x: 1;
axis.y: 0;
axis.z: 0;
angle: 0;
}
states: State {
name: "back";
PropertyChanges {
target: rotation;
angle: 180;
}
when: root.cardBackVisible;
}
transitions: Transition {
SmoothedAnimation {
target: rotation;
property: "angle";
velocity: 600;
}
}
}
Rectangle {
id: mainContainer;
z: 51;
// Style
color: hifi.colors.white;
// Size
anchors.left: parent.left;
anchors.leftMargin: 16;
anchors.right: parent.right;
anchors.rightMargin: 16;
anchors.verticalCenter: parent.verticalCenter;
height: root.height - 10;
// START "incorrect indentation to prevent insane diffs"
Item {
id: itemContainer;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.top: parent.top;
height: 100;
height: root.height - 2;
Image {
id: itemPreviewImage;
@ -154,8 +414,9 @@ Item {
anchors.left: parent.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: height;
width: height * 1.78;
fillMode: Image.PreserveAspectCrop;
mipmap: true;
MouseArea {
anchors.fill: parent;
@ -165,218 +426,53 @@ Item {
}
}
TextMetrics {
id: itemNameTextMetrics;
font: itemName.font;
text: itemName.text;
}
RalewaySemiBold {
RalewayRegular {
id: itemName;
anchors.top: itemPreviewImage.top;
anchors.top: parent.top;
anchors.topMargin: 4;
anchors.left: itemPreviewImage.right;
anchors.leftMargin: 8;
width: !noPermissionGlyph.visible ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin) :
Math.min(itemNameTextMetrics.tightBoundingRect.width + 2,
buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin - noPermissionGlyph.width + 2);
anchors.leftMargin: 10;
anchors.right: contextMenuButtonContainer.left;
anchors.rightMargin: 4;
height: paintedHeight;
// Text size
size: 24;
size: 20;
// Style
color: hifi.colors.blueAccent;
color: hifi.colors.black;
text: root.itemName;
elide: Text.ElideRight;
// Alignment
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
MouseArea {
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
sendToPurchases({method: 'purchases_itemInfoClicked', itemId: root.itemId});
}
onEntered: {
itemName.color = hifi.colors.blueHighlight;
}
onExited: {
itemName.color = hifi.colors.blueAccent;
}
}
}
HiFiGlyphs {
id: noPermissionGlyph;
visible: !root.hasPermissionToRezThis;
anchors.verticalCenter: itemName.verticalCenter;
anchors.left: itemName.right;
anchors.leftMargin: itemName.truncated ? -10 : -2;
text: hifi.glyphs.info;
// Size
size: 40;
width: 32;
// Style
color: hifi.colors.redAccent;
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
onEntered: {
noPermissionGlyph.color = hifi.colors.redHighlight;
}
onExited: {
noPermissionGlyph.color = hifi.colors.redAccent;
}
onClicked: {
root.sendToPurchases({ method: 'openPermissionExplanationCard' });
}
}
}
Rectangle {
id: permissionExplanationCard;
z: 995;
visible: root.permissionExplanationCardVisible;
anchors.fill: parent;
color: hifi.colors.white;
RalewayRegular {
id: permissionExplanationText;
text: {
if (root.itemType === "contentSet") {
"You do not have 'Replace Content' permissions in this domain. <a href='#replaceContentPermission'>Learn more</a>";
} else if (root.itemType === "entity") {
"You do not have 'Rez Certified' permissions in this domain. <a href='#rezCertifiedPermission'>Learn more</a>";
} else {
""
}
}
size: 16;
anchors.left: parent.left;
anchors.leftMargin: 30;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.right: permissionExplanationGlyph.left;
color: hifi.colors.baseGray;
wrapMode: Text.WordWrap;
verticalAlignment: Text.AlignVCenter;
onLinkActivated: {
sendToPurchases({method: 'showPermissionsExplanation', itemType: root.itemType});
}
}
// "Close" button
HiFiGlyphs {
id: permissionExplanationGlyph;
text: hifi.glyphs.close;
color: hifi.colors.baseGray;
size: 26;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.right: parent.right;
width: 77;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
onEntered: {
parent.text = hifi.glyphs.closeInverted;
}
onExited: {
parent.text = hifi.glyphs.close;
}
onClicked: {
root.sendToPurchases({ method: 'openPermissionExplanationCard', closeAll: true });
}
}
}
}
Item {
id: certificateContainer;
anchors.top: itemName.bottom;
anchors.topMargin: 4;
anchors.left: itemName.left;
anchors.right: buttonContainer.left;
anchors.rightMargin: 2;
height: 24;
HiFiGlyphs {
id: certificateIcon;
text: hifi.glyphs.scriptNew;
// Size
size: 30;
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
anchors.bottom: parent.bottom;
width: 32;
// Style
color: hifi.colors.black;
}
RalewayRegular {
id: viewCertificateText;
text: "VIEW CERTIFICATE";
size: 13;
anchors.left: certificateIcon.right;
anchors.leftMargin: 4;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.right: parent.right;
color: hifi.colors.black;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId});
}
onEntered: {
certificateIcon.color = hifi.colors.lightGray;
viewCertificateText.color = hifi.colors.lightGray;
}
onExited: {
certificateIcon.color = hifi.colors.black;
viewCertificateText.color = hifi.colors.black;
}
}
}
Item {
id: editionContainer;
RalewayRegular {
id: editionNumberText;
visible: root.displayedItemCount > 1 && !statusContainer.visible;
anchors.left: itemName.left;
anchors.top: certificateContainer.bottom;
anchors.topMargin: 8;
anchors.bottom: parent.bottom;
anchors.right: buttonContainer.left;
anchors.rightMargin: 2;
RalewayRegular {
anchors.left: parent.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: paintedWidth;
text: "#" + root.itemEdition;
size: 13;
color: hifi.colors.black;
verticalAlignment: Text.AlignTop;
}
anchors.right: itemName.right;
anchors.top: itemName.bottom;
anchors.topMargin: 4;
anchors.bottom: buttonContainer.top;
anchors.bottomMargin: 4;
width: itemName.width;
text: "Edition #" + root.itemEdition;
size: 13;
color: hifi.colors.black;
verticalAlignment: Text.AlignVCenter;
}
Item {
id: statusContainer;
visible: root.purchaseStatus === "pending" || root.purchaseStatus === "invalidated" || root.purchaseStatusChanged || root.numberSold > -1;
visible: root.purchaseStatus === "pending" || root.purchaseStatus === "invalidated" || root.numberSold > -1;
anchors.left: itemName.left;
anchors.top: certificateContainer.bottom;
anchors.topMargin: 8;
anchors.bottom: parent.bottom;
anchors.right: buttonContainer.left;
anchors.rightMargin: 2;
anchors.right: itemName.right;
anchors.top: itemName.bottom;
anchors.topMargin: 4;
anchors.bottom: buttonContainer.top;
anchors.bottomMargin: 4;
RalewaySemiBold {
RalewayRegular {
id: statusText;
anchors.left: parent.left;
anchors.top: parent.top;
@ -393,7 +489,7 @@ Item {
""
}
}
size: 18;
size: 13;
color: {
if (root.purchaseStatus === "pending") {
hifi.colors.blueAccent
@ -418,10 +514,10 @@ Item {
}
}
// Size
size: 36;
size: 34;
// Anchors
anchors.top: parent.top;
anchors.topMargin: -8;
anchors.topMargin: -10;
anchors.left: statusText.right;
anchors.bottom: parent.bottom;
// Style
@ -468,6 +564,50 @@ Item {
}
}
Item {
id: contextMenuButtonContainer;
anchors.right: parent.right;
anchors.rightMargin: 8;
anchors.top: parent.top;
anchors.topMargin: 8;
width: 30;
height: width;
Rectangle {
visible: root.updateAvailable;
anchors.fill: parent;
radius: height;
border.width: 1;
border.color: "#E2334D";
}
HiFiGlyphs {
id: contextMenuGlyph;
text: hifi.glyphs.verticalEllipsis;
anchors.fill: parent;
size: 46;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
color: root.updateAvailable ? "#E2334D" : hifi.colors.black;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
contextCard.z = 1;
permissionExplanationCard.z = 0;
root.sendToPurchases({ method: 'flipCard' });
}
onEntered: {
contextMenuGlyph.color = root.updateAvailable ? hifi.colors.redHighlight : hifi.colors.blueHighlight;
}
onExited: {
contextMenuGlyph.color = root.updateAvailable ? "#E2334D" : hifi.colors.black;
}
}
}
Rectangle {
id: rezzedNotifContainer;
z: 998;
@ -489,62 +629,22 @@ Item {
horizontalAlignment: Text.AlignHCenter;
}
Timer {
id: rezzedNotifContainerTimer;
interval: 2000;
onTriggered: rezzedNotifContainer.visible = false
}
}
Rectangle {
id: appButtonContainer;
color: hifi.colors.white;
z: 994;
visible: root.isInstalled;
anchors.fill: buttonContainer;
HifiControlsUit.Button {
id: openAppButton;
color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.light;
anchors.top: parent.top;
anchors.right: parent.right;
anchors.left: parent.left;
width: 92;
height: 44;
text: "OPEN"
onClicked: {
Commerce.openApp(root.itemHref);
}
}
HifiControlsUit.Button {
id: uninstallAppButton;
color: hifi.buttons.noneBorderless;
colorScheme: hifi.colorSchemes.light;
anchors.bottom: parent.bottom;
anchors.right: parent.right;
anchors.left: parent.left;
height: 44;
text: "UNINSTALL"
onClicked: {
Commerce.uninstallApp(root.itemHref);
}
Timer {
id: rezzedNotifContainerTimer;
interval: 2000;
onTriggered: rezzedNotifContainer.visible = false
}
}
Button {
id: buttonContainer;
property int color: hifi.buttons.blue;
property int colorScheme: hifi.colorSchemes.light;
anchors.top: parent.top;
anchors.topMargin: 4;
anchors.left: itemName.left;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 4;
anchors.right: parent.right;
anchors.rightMargin: 4;
width: height;
anchors.bottomMargin: 8;
width: 160;
height: 40;
enabled: root.hasPermissionToRezThis &&
root.purchaseStatus !== "invalidated" &&
MyAvatar.skeletonModelURL !== root.itemHref;
@ -568,8 +668,12 @@ Item {
} else if (root.itemType === "avatar") {
sendToPurchases({method: 'showChangeAvatarLightbox', itemName: root.itemName, itemHref: root.itemHref});
} else if (root.itemType === "app") {
// "Run" and "Uninstall" buttons are separate.
Commerce.installApp(root.itemHref);
if (root.isInstalled) {
Commerce.openApp(root.itemHref);
} else {
// "Run" and "Uninstall" buttons are separate.
Commerce.installApp(root.itemHref);
}
} else {
sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType});
root.showConfirmation = true;
@ -612,93 +716,76 @@ Item {
}
label: Item {
TextMetrics {
id: rezIconTextMetrics;
font: rezIcon.font;
text: rezIcon.text;
}
HiFiGlyphs {
id: rezIcon;
text: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)];
// Size
size: 60;
// Anchors
anchors.top: parent.top;
anchors.topMargin: 0;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.right: rezIconLabel.left;
anchors.rightMargin: 2;
anchors.verticalCenter: parent.verticalCenter;
size: 36;
horizontalAlignment: Text.AlignHCenter;
// Style
color: enabled ? hifi.buttons.textColor[control.color]
: hifi.buttons.disabledTextColor[control.colorScheme]
: hifi.buttons.disabledTextColor[control.colorScheme]
}
TextMetrics {
id: rezIconLabelTextMetrics;
font: rezIconLabel.font;
text: rezIconLabel.text;
}
RalewayBold {
id: rezIconLabel;
anchors.top: rezIcon.bottom;
anchors.topMargin: -4;
anchors.right: parent.right;
anchors.left: parent.left;
anchors.bottom: parent.bottom;
font.capitalization: Font.AllUppercase
color: enabled ? hifi.buttons.textColor[control.color]
: hifi.buttons.disabledTextColor[control.colorScheme]
text: root.isInstalled ? "OPEN" : (MyAvatar.skeletonModelURL === root.itemHref ? "CURRENT" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]);
anchors.verticalCenter: parent.verticalCenter;
width: rezIconLabelTextMetrics.width;
x: parent.width/2 - rezIconLabelTextMetrics.width/2 + rezIconTextMetrics.width/2;
size: 15;
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: MyAvatar.skeletonModelURL === root.itemHref ? "CURRENT" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)];
font.capitalization: Font.AllUppercase;
verticalAlignment: Text.AlignVCenter;
horizontalAlignment: Text.AlignHCenter;
color: enabled ? hifi.buttons.textColor[control.color]
: hifi.buttons.disabledTextColor[control.colorScheme]
}
}
}
}
}
// END "incorrect indentation to prevent insane diffs"
HiFiGlyphs {
id: noPermissionGlyph;
visible: !root.hasPermissionToRezThis;
anchors.verticalCenter: buttonContainer.verticalCenter;
anchors.left: buttonContainer.left;
anchors.right: buttonContainer.right;
anchors.rightMargin: -40;
text: hifi.glyphs.info;
// Size
size: 44;
// Style
color: hifi.colors.redAccent;
horizontalAlignment: Text.AlignRight;
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
Rectangle {
id: upgradeAvailableContainer;
visible: root.upgradeUrl !== "" && !root.isShowingMyItems;
anchors.top: itemContainer.bottom;
anchors.bottom: parent.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
color: "#B5EAFF";
RalewayRegular {
id: updateAvailableText;
text: "UPDATE AVAILABLE";
size: 13;
anchors.left: parent.left;
anchors.leftMargin: 12;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: paintedWidth;
color: hifi.colors.black;
verticalAlignment: Text.AlignVCenter;
}
RalewaySemiBold {
id: updateNowText;
text: "<font color='#0093C5'><a href='#'>Update this item now</a></font>";
size: 13;
anchors.left: updateAvailableText.right;
anchors.leftMargin: 16;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
width: paintedWidth;
color: hifi.colors.black;
verticalAlignment: Text.AlignVCenter;
onLinkActivated: {
sendToPurchases({method: 'updateItemClicked', itemId: root.itemId, itemEdition: root.itemEdition, upgradeUrl: root.upgradeUrl});
onEntered: {
noPermissionGlyph.color = hifi.colors.redHighlight;
}
onExited: {
noPermissionGlyph.color = hifi.colors.redAccent;
}
onClicked: {
contextCard.z = 0;
permissionExplanationCard.z = 1;
root.sendToPurchases({ method: 'flipCard' });
}
}
}
}
DropShadow {
anchors.fill: mainContainer;
horizontalOffset: 0;
verticalOffset: 4;
radius: 4.0;
samples: 9
color: Qt.rgba(0, 0, 0, 0.25);
source: mainContainer;
}
//
// FUNCTION DEFINITIONS START
//

View file

@ -19,6 +19,7 @@ import "../../../controls" as HifiControls
import "../wallet" as HifiWallet
import "../common" as HifiCommerceCommon
import "../inspectionCertificate" as HifiInspectionCertificate
import "../common/sendAsset" as HifiSendAsset
// references XXX from root context
@ -31,7 +32,6 @@ Rectangle {
property bool securityImageResultReceived: false;
property bool purchasesReceived: false;
property bool punctuationMode: false;
property bool pendingInventoryReply: true;
property bool isShowingMyItems: false;
property bool isDebuggingFirstUseTutorial: false;
property int pendingItemCount: 0;
@ -114,12 +114,6 @@ Rectangle {
purchasesContentsList.positionViewAtIndex(currentIndex, ListView.Beginning);
}
if (root.pendingInventoryReply && root.pendingItemCount > 0) {
inventoryTimer.start();
}
root.pendingInventoryReply = false;
}
onAvailableUpdatesResult: {
@ -142,7 +136,7 @@ Rectangle {
HifiInspectionCertificate.InspectionCertificate {
id: inspectionCertificate;
z: 999;
z: 998;
visible: false;
anchors.fill: parent;
@ -155,6 +149,7 @@ Rectangle {
HifiCommerceCommon.CommerceLightbox {
id: lightboxPopup;
z: 999;
visible: false;
anchors.fill: parent;
@ -169,12 +164,33 @@ Rectangle {
}
}
HifiSendAsset.SendAsset {
id: sendAsset;
z: 998;
visible: root.activeView === "giftAsset";
anchors.fill: parent;
parentAppTitleBarHeight: 70;
parentAppNavBarHeight: 0;
Connections {
onSendSignalToParent: {
if (msg.method === 'sendAssetHome_back' || msg.method === 'closeSendAsset') {
root.activeView = "purchasesMain";
Commerce.inventory();
Commerce.getAvailableUpdates();
} else {
sendToScript(msg);
}
}
}
}
//
// TITLE BAR START
//
HifiCommerceCommon.EmulatedMarketplaceHeader {
id: titleBarContainer;
z: 998;
z: 997;
visible: !needsLogIn.visible;
// Size
width: parent.width;
@ -191,9 +207,14 @@ Rectangle {
lightboxPopup.bodyImageSource = msg.securityImageSource;
lightboxPopup.bodyText = lightboxPopup.securityPicBodyText;
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "GO TO WALLET";
lightboxPopup.button2method = "sendToParent({method: 'purchases_openWallet'});";
lightboxPopup.button2method = function() {
sendToScript({method: 'purchases_openWallet'});
lightboxPopup.visible = false;
};
lightboxPopup.visible = true;
} else {
sendToScript(msg);
@ -308,7 +329,7 @@ Rectangle {
// FILTER BAR START
//
Item {
z: 997;
z: 996;
id: filterBarContainer;
// Size
height: 40;
@ -316,7 +337,7 @@ Rectangle {
anchors.left: parent.left;
anchors.leftMargin: 8;
anchors.right: parent.right;
anchors.rightMargin: 16;
anchors.rightMargin: 8;
anchors.top: parent.top;
anchors.topMargin: 4;
@ -341,6 +362,7 @@ Rectangle {
colorScheme: hifi.colorSchemes.faintGray;
anchors.top: parent.top;
anchors.right: parent.right;
anchors.rightMargin: 8;
anchors.left: myText.right;
anchors.leftMargin: 16;
textFieldHeight: 39;
@ -396,7 +418,7 @@ Rectangle {
//
HifiControlsUit.Separator {
z: 996;
z: 995;
id: separator;
colorScheme: 2;
anchors.left: parent.left;
@ -426,7 +448,6 @@ Rectangle {
snapMode: ListView.SnapToItem;
// Anchors
anchors.top: separator.bottom;
anchors.topMargin: 12;
anchors.left: parent.left;
anchors.bottom: updatesAvailableBanner.visible ? updatesAvailableBanner.top : parent.bottom;
width: parent.width;
@ -437,13 +458,13 @@ Rectangle {
itemHref: download_url;
certificateId: certificate_id;
purchaseStatus: status;
purchaseStatusChanged: statusChanged;
itemEdition: model.edition_number;
numberSold: model.number_sold;
limitedRun: model.limited_run;
displayedItemCount: model.displayedItemCount;
permissionExplanationCardVisible: model.permissionExplanationCardVisible;
cardBackVisible: model.cardBackVisible;
isInstalled: model.isInstalled;
wornEntityID: model.wornEntityID;
upgradeUrl: model.upgrade_url;
upgradeTitle: model.upgrade_title;
itemType: model.itemType;
@ -457,6 +478,11 @@ Rectangle {
sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId});
} else if (msg.method === "purchases_rezClicked") {
sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, itemType: itemType});
// Race condition - Wearable might not be rezzed by the time the "currently worn wearbles" model is created
if (itemType === "wearable") {
sendToScript({ method: 'purchases_updateWearables' });
}
} else if (msg.method === 'purchases_itemCertificateClicked') {
inspectionCertificate.visible = true;
inspectionCertificate.isLightbox = true;
@ -466,14 +492,18 @@ Rectangle {
lightboxPopup.bodyText = 'Your item is marked "invalidated" because this item has been suspended ' +
"from the Marketplace due to a claim against its author.";
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
} else if (msg.method === "showPendingLightbox") {
lightboxPopup.titleText = "Item Pending";
lightboxPopup.bodyText = 'Your item is marked "pending" while your purchase is being confirmed. ' +
"Usually, purchases take about 90 seconds to confirm.";
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
} else if (msg.method === "showReplaceContentLightbox") {
lightboxPopup.titleText = "Replace Content";
@ -483,17 +513,27 @@ Rectangle {
"<a href='https://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content'>" +
"click here to open info on your desktop browser.";
lightboxPopup.button1text = "CANCEL";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemHref + "', '" + msg.certID + "'); root.visible = false;";
lightboxPopup.button2method = function() {
Commerce.replaceContentSet(msg.itemHref, msg.certID);
lightboxPopup.visible = false;
};
lightboxPopup.visible = true;
} else if (msg.method === "showChangeAvatarLightbox") {
lightboxPopup.titleText = "Change Avatar";
lightboxPopup.bodyText = "This will change your current avatar to " + msg.itemName + " while retaining your wearables.";
lightboxPopup.button1text = "CANCEL";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + msg.itemHref + "'); root.visible = false;";
lightboxPopup.button2method = function() {
MyAvatar.useFullAvatarURL(msg.itemHref);
lightboxPopup.visible = false;
};
lightboxPopup.visible = true;
} else if (msg.method === "showPermissionsExplanation") {
if (msg.itemType === "entity") {
@ -501,27 +541,86 @@ Rectangle {
lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.<br><br>" +
"Use the <b>GOTO app</b> to visit another domain or <b>go to your own sandbox.</b>";
lightboxPopup.button2text = "OPEN GOTO";
lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});";
lightboxPopup.button2method = function() {
sendToScript({method: 'purchases_openGoTo'});
lightboxPopup.visible = false;
};
} else if (msg.itemType === "contentSet") {
lightboxPopup.titleText = "Replace Content Permission";
lightboxPopup.bodyText = "You do not have the permission 'Replace Content' in this <b>domain's server settings</b>. The domain owner " +
"must enable it for you before you can replace content sets in this domain.";
}
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
} else if (msg.method === "setFilterText") {
filterBar.text = msg.filterText;
} else if (msg.method === "openPermissionExplanationCard") {
} else if (msg.method === "flipCard") {
for (var i = 0; i < filteredPurchasesModel.count; i++) {
if (i !== index || msg.closeAll) {
filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", false);
filteredPurchasesModel.setProperty(i, "cardBackVisible", false);
} else {
filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", true);
filteredPurchasesModel.setProperty(i, "cardBackVisible", true);
}
}
} else if (msg.method === "updateItemClicked") {
sendToScript(msg);
} else if (msg.method === "giftAsset") {
sendAsset.assetName = msg.itemName;
sendAsset.assetCertID = msg.certId;
sendAsset.sendingPubliclyEffectImage = msg.effectImage;
if (msg.itemType === "avatar" && MyAvatar.skeletonModelURL === msg.itemHref) {
lightboxPopup.titleText = "Change Avatar to Default";
lightboxPopup.bodyText = "You are currently wearing the avatar that you are trying to gift.<br><br>" +
"If you proceed, your avatar will be changed to the default avatar.";
lightboxPopup.button1text = "CANCEL";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = function() {
MyAvatar.skeletonModelURL = '';
root.activeView = "giftAsset";
lightboxPopup.visible = false;
};
lightboxPopup.visible = true;
} else if (msg.itemType === "app" && msg.isInstalled) {
lightboxPopup.titleText = "Uninstall App";
lightboxPopup.bodyText = "You are currently using the app that you are trying to gift.<br><br>" +
"If you proceed, the app will be uninstalled.";
lightboxPopup.button1text = "CANCEL";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = function() {
Commerce.uninstallApp(msg.itemHref);
root.activeView = "giftAsset";
lightboxPopup.visible = false;
};
lightboxPopup.visible = true;
} else if (msg.itemType === "wearable" && msg.wornEntityID !== '') {
lightboxPopup.titleText = "Remove Wearable";
lightboxPopup.bodyText = "You are currently wearing the wearable that you are trying to send.<br><br>" +
"If you proceed, this wearable will be removed.";
lightboxPopup.button1text = "CANCEL";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.button2text = "CONFIRM";
lightboxPopup.button2method = function() {
Entities.deleteEntity(msg.wornEntityID);
filteredPurchasesModel.setProperty(index, 'wornEntityID', '');
root.activeView = "giftAsset";
lightboxPopup.visible = false;
};
lightboxPopup.visible = true;
} else {
root.activeView = "giftAsset";
}
}
}
}
@ -693,6 +792,7 @@ Rectangle {
HifiControlsUit.Keyboard {
id: keyboard;
z: 999;
raised: HMD.mounted && parent.keyboardRaised;
numeric: parent.punctuationMode;
anchors {
@ -702,26 +802,6 @@ Rectangle {
}
}
onVisibleChanged: {
if (!visible) {
inventoryTimer.stop();
}
}
Timer {
id: inventoryTimer;
interval: 4000; // Change this back to 90000 after demo
//interval: 90000;
onTriggered: {
if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) {
console.log("Refreshing Purchases...");
root.pendingInventoryReply = true;
Commerce.inventory();
Commerce.getAvailableUpdates();
}
}
}
//
// FUNCTION DEFINITIONS START
//
@ -833,10 +913,12 @@ Rectangle {
continue;
}
filteredPurchasesModel.append(tempPurchasesModel.get(i));
filteredPurchasesModel.setProperty(i, 'permissionExplanationCardVisible', false);
filteredPurchasesModel.setProperty(i, 'cardBackVisible', false);
filteredPurchasesModel.setProperty(i, 'isInstalled', ((root.installedApps).indexOf(currentId) > -1));
filteredPurchasesModel.setProperty(i, 'wornEntityID', '');
}
sendToScript({ method: 'purchases_updateWearables' });
populateDisplayedItemCounts();
sortByDate();
}
@ -863,6 +945,19 @@ Rectangle {
}
}
}
function updateCurrentlyWornWearables(wearables) {
for (var i = 0; i < filteredPurchasesModel.count; i++) {
for (var j = 0; j < wearables.length; j++) {
if (filteredPurchasesModel.get(i).itemType === "wearable" &&
wearables[j].entityCertID === filteredPurchasesModel.get(i).certificate_id &&
wearables[j].entityEdition.toString() === filteredPurchasesModel.get(i).edition_number) {
filteredPurchasesModel.setProperty(i, 'wornEntityID', wearables[j].entityID);
break;
}
}
}
}
//
// Function Name: fromScript()
@ -890,6 +985,16 @@ Rectangle {
case 'purchases_showMyItems':
root.isShowingMyItems = true;
break;
case 'updateConnections':
sendAsset.updateConnections(message.connections);
break;
case 'selectRecipient':
case 'updateSelectedRecipientUsername':
sendAsset.fromScript(message);
break;
case 'updateWearables':
updateCurrentlyWornWearables(message.wornWearables);
break;
default:
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
}

View file

@ -143,7 +143,9 @@ Item {
lightboxPopup.bodyImageSource = titleBarSecurityImage.source;
lightboxPopup.bodyText = lightboxPopup.securityPicBodyText;
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
}
}

View file

@ -42,18 +42,6 @@ Item {
}
}
}
// This will cause a bug -- if you bring up security image selection in HUD mode while
// in HMD while having HMD preview enabled, then move, then finish passphrase selection,
// HMD preview will stay off.
// TODO: Fix this unlikely bug
onVisibleChanged: {
if (visible) {
sendSignalToWallet({method: 'disableHmdPreview'});
} else {
sendSignalToWallet({method: 'maybeEnableHmdPreview'});
}
}
// Security Image
Item {

View file

@ -18,7 +18,7 @@ import "../../../styles-uit"
import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
import "../common" as HifiCommerceCommon
import "./sendMoney"
import "../common/sendAsset"
Rectangle {
HifiConstants { id: hifi; }
@ -160,7 +160,9 @@ Rectangle {
lightboxPopup.bodyImageSource = titleBarSecurityImage.source;
lightboxPopup.bodyText = lightboxPopup.securityPicBodyText;
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
}
}
@ -341,7 +343,7 @@ Rectangle {
}
}
SendMoney {
SendAsset {
id: sendMoney;
z: 997;
visible: root.activeView === "sendMoney";
@ -350,7 +352,7 @@ Rectangle {
parentAppNavBarHeight: tabButtonsContainer.height;
Connections {
onSendSignalToWallet: {
onSendSignalToParent: {
sendToScript(msg);
}
}
@ -405,7 +407,7 @@ Rectangle {
//
Item {
id: tabButtonsContainer;
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && root.activeView !== "securityImageChange" && sendMoney.currentActiveView !== "sendMoneyStep";
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && root.activeView !== "securityImageChange" && sendMoney.currentActiveView !== "sendAssetStep";
property int numTabs: 5;
// Size
width: root.width;

View file

@ -206,9 +206,14 @@ Item {
"This step cannot be undone.";
lightboxPopup.button1color = hifi.buttons.red;
lightboxPopup.button1text = "YES, CREATE NEW WALLET";
lightboxPopup.button1method = "root.visible = false;proceed(true);";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
proceed(true);
}
lightboxPopup.button2text = "CANCEL";
lightboxPopup.button2method = "root.visible = false;"
lightboxPopup.button2method = function() {
lightboxPopup.visible = false;
};
lightboxPopup.buttonLayout = "topbottom";
lightboxPopup.visible = true;
}
@ -241,7 +246,9 @@ Item {
"If you'd prefer to create a new wallet (not recommended - you will lose your money and past " +
"purchases), click 'Create New Wallet'.";
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
} else {
lightboxPopup.titleText = "You may have set up more than one wallet";
@ -251,7 +258,9 @@ Item {
"If you would prefer to use another wallet, click 'Locate Other Keys' to show us where " +
"you've stored the private keys for that wallet.";
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
}
}

View file

@ -76,7 +76,7 @@ Item {
UserActivityLogger.commerceWalletSetupProgress(timestamp, root.setupAttemptID,
Math.round((timestamp - root.startingTimestamp)/1000), currentStepNumber, root.setupStepNames[currentStepNumber - 1]);
if (root.activeView === "step_2" || root.activeView === "step_3") {
if (root.activeView === "step_3") {
sendSignalToWallet({method: 'disableHmdPreview'});
} else {
sendSignalToWallet({method: 'maybeEnableHmdPreview'});
@ -150,7 +150,9 @@ Item {
lightboxPopup.bodyImageSource = titleBarSecurityImage.source;
lightboxPopup.bodyText = lightboxPopup.securityPicBodyText;
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = "root.visible = false;"
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;
}
lightboxPopup.visible = true;
}
}

View file

@ -344,5 +344,10 @@ QtObject {
readonly property string wand: "\ue02d"
readonly property string hat: "\ue02e"
readonly property string install: "\ue02f"
readonly property string certificate: "\ue030"
readonly property string gift: "\ue031"
readonly property string update: "\ue032"
readonly property string uninstall: "\ue033"
readonly property string verticalEllipsis: "\ue034"
}
}

View file

@ -1,5 +1,5 @@
//
// DefaultFrame.qml
// Decoration.qml
//
// Created by Bradley Austin Davis on 12 Jan 2016
// Copyright 2016 High Fidelity, Inc.

View file

@ -2568,6 +2568,7 @@ void Application::initializeUi() {
QUrl{ "hifi/commerce/common/EmulatedMarketplaceHeader.qml" },
QUrl{ "hifi/commerce/common/FirstUseTutorial.qml" },
QUrl{ "hifi/commerce/common/SortableListModel.qml" },
QUrl{ "hifi/commerce/common/sendAsset/SendAsset.qml" },
QUrl{ "hifi/commerce/inspectionCertificate/InspectionCertificate.qml" },
QUrl{ "hifi/commerce/purchases/PurchasedItem.qml" },
QUrl{ "hifi/commerce/purchases/Purchases.qml" },
@ -2580,7 +2581,6 @@ void Application::initializeUi() {
QUrl{ "hifi/commerce/wallet/SecurityImageChange.qml" },
QUrl{ "hifi/commerce/wallet/SecurityImageModel.qml" },
QUrl{ "hifi/commerce/wallet/SecurityImageSelection.qml" },
QUrl{ "hifi/commerce/wallet/sendMoney/SendMoney.qml" },
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
@ -3157,6 +3157,10 @@ void Application::loadServerlessDomain(QUrl domainURL) {
tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0);
}
std::map<QString, QString> namedPaths = tmpTree->getNamedPaths();
nodeList->getDomainHandler().connectedToServerless(namedPaths);
_fullSceneReceivedCounter++;
}
@ -5920,6 +5924,9 @@ void Application::nodeActivated(SharedNodePointer node) {
}
getMyAvatar()->markIdentityDataChanged();
getMyAvatar()->resetLastSent();
// transmit a "sendAll" packet to the AvatarMixer we just connected to.
getMyAvatar()->sendAvatarDataPacket(true);
}
}

View file

@ -56,8 +56,8 @@ Handler(buy)
Handler(receiveAt)
Handler(balance)
Handler(inventory)
Handler(transferHfcToNode)
Handler(transferHfcToUsername)
Handler(transferAssetToNode)
Handler(transferAssetToUsername)
Handler(alreadyOwned)
Handler(availableUpdates)
Handler(updateItem)
@ -173,7 +173,8 @@ QString userLink(const QString& username, const QString& placename) {
QString transactionString(const QJsonObject& valueObject) {
int sentCerts = valueObject["sent_certs"].toInt();
int receivedCerts = valueObject["received_certs"].toInt();
int sent = valueObject["sent_money"].toInt();
int sentMoney = valueObject["sent_money"].toInt();
int receivedMoney = valueObject["received_money"].toInt();
int dateInteger = valueObject["created_at"].toInt();
QString message = valueObject["message"].toString();
QDateTime createdAt(QDateTime::fromSecsSinceEpoch(dateInteger, Qt::UTC));
@ -181,7 +182,7 @@ QString transactionString(const QJsonObject& valueObject) {
if (sentCerts <= 0 && receivedCerts <= 0 && !KNOWN_USERS.contains(valueObject["sender_name"].toString())) {
// this is an hfc transfer.
if (sent > 0) {
if (sentMoney > 0) {
QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString());
result += QString("Money sent to %1").arg(recipient);
} else {
@ -191,6 +192,18 @@ QString transactionString(const QJsonObject& valueObject) {
if (!message.isEmpty()) {
result += QString("<br>with memo: <i>\"%1\"</i>").arg(message);
}
} else if (sentMoney <= 0 && receivedMoney <= 0 && (sentCerts > 0 || receivedCerts > 0) && !KNOWN_USERS.contains(valueObject["sender_name"].toString())) {
// this is a non-HFC asset transfer.
if (sentCerts > 0) {
QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString());
result += QString("Gift sent to %1").arg(recipient);
} else {
QString sender = userLink(valueObject["sender_name"].toString(), valueObject["place_name"].toString());
result += QString("Gift from %1").arg(sender);
}
if (!message.isEmpty()) {
result += QString("<br>with memo: <i>\"%1\"</i>").arg(message);
}
} else {
result += valueObject["message"].toString();
}
@ -354,27 +367,41 @@ void Ledger::certificateInfo(const QString& certificateId) {
send(endpoint, "certificateInfoSuccess", "certificateInfoFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::None, request);
}
void Ledger::transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage) {
void Ledger::transferAssetToNode(const QString& hfc_key, const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage) {
QJsonObject transaction;
transaction["public_key"] = hfc_key;
transaction["node_id"] = nodeID;
transaction["quantity"] = amount;
transaction["message"] = optionalMessage;
transaction["place_name"] = DependencyManager::get<AddressManager>()->getPlaceName();
if (!certificateID.isEmpty()) {
transaction["certificate_id"] = certificateID;
}
QJsonDocument transactionDoc{ transaction };
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_node", "transferHfcToNodeSuccess", "transferHfcToNodeFailure");
if (certificateID.isEmpty()) {
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_node", "transferAssetToNodeSuccess", "transferAssetToNodeFailure");
} else {
signedSend("transaction", transactionString, hfc_key, "transfer_asset_to_node", "transferAssetToNodeSuccess", "transferAssetToNodeFailure");
}
}
void Ledger::transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage) {
void Ledger::transferAssetToUsername(const QString& hfc_key, const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage) {
QJsonObject transaction;
transaction["public_key"] = hfc_key;
transaction["username"] = username;
transaction["quantity"] = amount;
transaction["message"] = optionalMessage;
if (!certificateID.isEmpty()) {
transaction["certificate_id"] = certificateID;
}
QJsonDocument transactionDoc{ transaction };
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure");
if (certificateID.isEmpty()) {
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferAssetToUsernameSuccess", "transferAssetToUsernameFailure");
} else {
signedSend("transaction", transactionString, hfc_key, "transfer_asset_to_user", "transferAssetToUsernameSuccess", "transferAssetToUsernameFailure");
}
}
void Ledger::alreadyOwned(const QString& marketplaceId) {

View file

@ -33,8 +33,8 @@ public:
void account();
void updateLocation(const QString& asset_id, const QString& location, const bool& alsoUpdateSiblings = false, const bool controlledFailure = false);
void certificateInfo(const QString& certificateId);
void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage);
void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage);
void transferAssetToNode(const QString& hfc_key, const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage);
void transferAssetToUsername(const QString& hfc_key, const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage);
void alreadyOwned(const QString& marketplaceId);
void getAvailableUpdates(const QString& itemId = "");
void updateItem(const QString& hfc_key, const QString& certificate_id);
@ -56,8 +56,8 @@ signals:
void accountResult(QJsonObject result);
void locationUpdateResult(QJsonObject result);
void certificateInfoResult(QJsonObject result);
void transferHfcToNodeResult(QJsonObject result);
void transferHfcToUsernameResult(QJsonObject result);
void transferAssetToNodeResult(QJsonObject result);
void transferAssetToUsernameResult(QJsonObject result);
void alreadyOwnedResult(QJsonObject result);
void availableUpdatesResult(QJsonObject result);
void updateItemResult(QJsonObject result);
@ -81,10 +81,10 @@ public slots:
void updateLocationFailure(QNetworkReply& reply);
void certificateInfoSuccess(QNetworkReply& reply);
void certificateInfoFailure(QNetworkReply& reply);
void transferHfcToNodeSuccess(QNetworkReply& reply);
void transferHfcToNodeFailure(QNetworkReply& reply);
void transferHfcToUsernameSuccess(QNetworkReply& reply);
void transferHfcToUsernameFailure(QNetworkReply& reply);
void transferAssetToNodeSuccess(QNetworkReply& reply);
void transferAssetToNodeFailure(QNetworkReply& reply);
void transferAssetToUsernameSuccess(QNetworkReply& reply);
void transferAssetToUsernameFailure(QNetworkReply& reply);
void alreadyOwnedSuccess(QNetworkReply& reply);
void alreadyOwnedFailure(QNetworkReply& reply);
void availableUpdatesSuccess(QNetworkReply& reply);

View file

@ -36,8 +36,8 @@ QmlCommerce::QmlCommerce() {
connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult);
connect(ledger.data(), &Ledger::alreadyOwnedResult, this, &QmlCommerce::alreadyOwnedResult);
connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus);
connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult);
connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult);
connect(ledger.data(), &Ledger::transferAssetToNodeResult, this, &QmlCommerce::transferAssetToNodeResult);
connect(ledger.data(), &Ledger::transferAssetToUsernameResult, this, &QmlCommerce::transferAssetToUsernameResult);
connect(ledger.data(), &Ledger::availableUpdatesResult, this, &QmlCommerce::availableUpdatesResult);
connect(ledger.data(), &Ledger::updateItemResult, this, &QmlCommerce::updateItemResult);
@ -166,28 +166,28 @@ void QmlCommerce::certificateInfo(const QString& certificateId) {
ledger->certificateInfo(certificateId);
}
void QmlCommerce::transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage) {
void QmlCommerce::transferAssetToNode(const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage) {
auto ledger = DependencyManager::get<Ledger>();
auto wallet = DependencyManager::get<Wallet>();
QStringList keys = wallet->listPublicKeys();
if (keys.count() == 0) {
QJsonObject result{ { "status", "fail" },{ "message", "Uninitialized Wallet." } };
return emit buyResult(result);
return emit transferAssetToNodeResult(result);
}
QString key = keys[0];
ledger->transferHfcToNode(key, nodeID, amount, optionalMessage);
ledger->transferAssetToNode(key, nodeID, certificateID, amount, optionalMessage);
}
void QmlCommerce::transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage) {
void QmlCommerce::transferAssetToUsername(const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage) {
auto ledger = DependencyManager::get<Ledger>();
auto wallet = DependencyManager::get<Wallet>();
QStringList keys = wallet->listPublicKeys();
if (keys.count() == 0) {
QJsonObject result{ { "status", "fail" },{ "message", "Uninitialized Wallet." } };
return emit buyResult(result);
return emit transferAssetToUsernameResult(result);
}
QString key = keys[0];
ledger->transferHfcToUsername(key, username, amount, optionalMessage);
ledger->transferAssetToUsername(key, username, certificateID, amount, optionalMessage);
}
void QmlCommerce::replaceContentSet(const QString& itemHref, const QString& certificateID) {

View file

@ -48,8 +48,8 @@ signals:
void updateCertificateStatus(const QString& certID, uint certStatus);
void transferHfcToNodeResult(QJsonObject result);
void transferHfcToUsernameResult(QJsonObject result);
void transferAssetToNodeResult(QJsonObject result);
void transferAssetToUsernameResult(QJsonObject result);
void contentSetChanged(const QString& contentSetHref);
@ -81,8 +81,8 @@ protected:
Q_INVOKABLE void certificateInfo(const QString& certificateId);
Q_INVOKABLE void alreadyOwned(const QString& marketplaceId);
Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage);
Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage);
Q_INVOKABLE void transferAssetToNode(const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage);
Q_INVOKABLE void transferAssetToUsername(const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage);
Q_INVOKABLE void replaceContentSet(const QString& itemHref, const QString& certificateID);

View file

@ -13,8 +13,9 @@
#include "Ledger.h"
#include "Wallet.h"
#include "Application.h"
#include "ui/ImageProvider.h"
#include "ui/SecurityImageProvider.h"
#include "scripting/HMDScriptingInterface.h"
#include <ui/TabletScriptingInterface.h>
#include <PathUtils.h>
#include <OffscreenUi.h>
@ -566,7 +567,6 @@ bool Wallet::generateKeyPair() {
}
QStringList Wallet::listPublicKeys() {
qCInfo(commerce) << "Enumerating public keys.";
return _publicKeys;
}
@ -607,11 +607,17 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) {
}
void Wallet::updateImageProvider() {
// inform the image provider. Note it doesn't matter which one you inform, as the
// images are statics
auto engine = DependencyManager::get<OffscreenUi>()->getSurfaceContext()->engine();
auto imageProvider = reinterpret_cast<ImageProvider*>(engine->imageProvider(ImageProvider::PROVIDER_NAME));
imageProvider->setSecurityImage(_securityImage);
SecurityImageProvider* securityImageProvider;
// inform offscreenUI security image provider
QQmlEngine* engine = DependencyManager::get<OffscreenUi>()->getSurfaceContext()->engine();
securityImageProvider = reinterpret_cast<SecurityImageProvider*>(engine->imageProvider(SecurityImageProvider::PROVIDER_NAME));
securityImageProvider->setSecurityImage(_securityImage);
// inform tablet security image provider
QQmlEngine* tabletEngine = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system")->getTabletSurface()->getSurfaceContext()->engine();
securityImageProvider = reinterpret_cast<SecurityImageProvider*>(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME));
securityImageProvider->setSecurityImage(_securityImage);
}
void Wallet::chooseSecurityImage(const QString& filename) {
@ -651,6 +657,7 @@ bool Wallet::getSecurityImage() {
// if already decrypted, don't do it again
if (_securityImage) {
updateImageProvider();
emit securityImageResult(true);
return true;
}

View file

@ -24,6 +24,36 @@ class QScriptEngine;
#include <QReadWriteLock>
/**jsdoc
* The HMD API provides access to the HMD used in VR display mode.
*
* @namespace HMD
* @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise
* {@link Vec3(0)|Vec3.ZERO}. <em>Read-only.</em>
* @property {Quat} orientation - The orientation of the HMD if currently in VR display mode, otherwise
* {@link Quat(0)|Quat.IDENTITY}. <em>Read-only.</em>
* @property {boolean} active - <code>true</code> if the display mode is HMD, otherwise <code>false</code>. <em>Read-only.</em>
* @property {boolean} mounted - <code>true</code> if currently in VR display mode and the HMD is being worn, otherwise
* <code>false</code>. <em>Read-only.</em>
*
* @property {number} playerHeight - The real-world height of the user. <em>Read-only.</em> <em>Currently always returns a
* value of <code>1.755</code>.</em>
* @property {number} eyeHeight - The real-world height of the user's eyes. <em>Read-only.</em> <em>Currently always returns a
* value of <code>1.655</code>.</em>
* @property {number} ipd - The inter-pupillary distance (distance between eyes) of the user, used for rendering. Defaults to
* the human average of <code>0.064</code> unless set by the HMD. <em>Read-only.</em>
* @property {number} ipdScale=1.0 - A scale factor applied to the <code>ipd</code> property value.
*
* @property {boolean} showTablet - <code>true</code> if the tablet is being displayed, <code>false</code> otherwise.
* <em>Read-only.</em>
* @property {boolean} tabletContextualMode - <code>true</code> if the tablet has been opened in contextual mode, otherwise
* <code>false</code>. In contextual mode, the tablet has been opened at a specific world position and orientation rather
* than at a position and orientation relative to the user. <em>Read-only.</em>
* @property {Uuid} tabletID - The UUID of the tablet body model overlay.
* @property {Uuid} tabletScreenID - The UUID of the tablet's screen overlay.
* @property {Uuid} homeButtonID - The UUID of the tablet's "home" button overlay.
* @property {Uuid} homeButtonHighlightID - The UUID of the tablet's "home" button highlight overlay.
*/
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
Q_OBJECT
Q_PROPERTY(glm::vec3 position READ getPosition)
@ -37,26 +67,217 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID)
public:
/**jsdoc
* Calculate the intersection of a ray with the HUD overlay.
* @function HMD.calculateRayUICollisionPoint
* @param {Vec3} position - The origin of the ray.
* @param {Vec3} direction - The direction of the ray.
* @returns {Vec3} The point of intersection with the HUD overlay if it intersects, otherwise {@link Vec3(0)|Vec3.ZERO}.
* @example <caption>Draw a square on the HUD overlay in the direction you're looking.</caption>
* var hudIntersection = HMD.calculateRayUICollisionPoint(MyAvatar.getHeadPosition(),
* Quat.getForward(MyAvatar.headOrientation));
* var hudPoint = HMD.overlayFromWorldPoint(hudIntersection);
*
* var DIMENSIONS = { x: 50, y: 50 };
* var square = Overlays.addOverlay("rectangle", {
* x: hudPoint.x - DIMENSIONS.x / 2,
* y: hudPoint.y - DIMENSIONS.y / 2,
* width: DIMENSIONS.x,
* height: DIMENSIONS.y,
* color: { red: 255, green: 0, blue: 0 }
* });
*
* Script.scriptEnding.connect(function () {
* Overlays.deleteOverlay(square);
* });
*/
Q_INVOKABLE glm::vec3 calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction) const;
/**jsdoc
* Get the 2D HUD overlay coordinates of a 3D point on the HUD overlay.
* 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay.
* @function HMD.overlayFromWorldPoint
* @param {Vec3} position - The point on the HUD overlay in world coordinates.
* @returns {Vec2} The point on the HUD overlay in HUD coordinates.
* @example <caption>Draw a square on the HUD overlay in the direction you're looking.</caption>
* var hudIntersection = HMD.calculateRayUICollisionPoint(MyAvatar.getHeadPosition(),
* Quat.getForward(MyAvatar.headOrientation));
* var hudPoint = HMD.overlayFromWorldPoint(hudIntersection);
*
* var DIMENSIONS = { x: 50, y: 50 };
* var square = Overlays.addOverlay("rectangle", {
* x: hudPoint.x - DIMENSIONS.x / 2,
* y: hudPoint.y - DIMENSIONS.y / 2,
* width: DIMENSIONS.x,
* height: DIMENSIONS.y,
* color: { red: 255, green: 0, blue: 0 }
* });
*
* Script.scriptEnding.connect(function () {
* Overlays.deleteOverlay(square);
* });
*/
Q_INVOKABLE glm::vec2 overlayFromWorldPoint(const glm::vec3& position) const;
/**jsdoc
* Get the 3D world coordinates of a 2D point on the HUD overlay.
* 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay.
* @function HMD.worldPointFromOverlay
* @param {Vec2} coordinates - The point on the HUD overlay in HUD coordinates.
* @returns {Vec3} The point on the HUD overlay in world coordinates.
*/
Q_INVOKABLE glm::vec3 worldPointFromOverlay(const glm::vec2& overlay) const;
/**jsdoc
* Get the 2D point on the HUD overlay represented by given spherical coordinates.
* 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay.
* Spherical coordinates are polar coordinates in radians with <code>{ x: 0, y: 0 }</code> being the center of the HUD
* overlay.
* @function HMD.sphericalToOverlay
* @param {Vec2} sphericalPos - The point on the HUD overlay in spherical coordinates.
* @returns {Vec2} The point on the HUD overlay in HUD coordinates.
*/
Q_INVOKABLE glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const;
/**jsdoc
* Get the spherical coordinates of a 2D point on the HUD overlay.
* 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay.
* Spherical coordinates are polar coordinates in radians with <code>{ x: 0, y: 0 }</code> being the center of the HUD
* overlay.
* @function HMD.overlayToSpherical
* @param {Vec2} overlayPos - The point on the HUD overlay in HUD coordinates.
* @returns {Vec2} The point on the HUD overlay in spherical coordinates.
*/
Q_INVOKABLE glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const;
/**jsdoc
* Recenter the HMD HUD to the current HMD position and orientation.
* @function HMD.centerUI
*/
Q_INVOKABLE void centerUI();
/**jsdoc
* Get the name of the HMD audio input device.
* @function HMD.preferredAudioInput
* @returns {string} The name of the HMD audio input device if in HMD mode, otherwise an empty string.
*/
Q_INVOKABLE QString preferredAudioInput() const;
/**jsdoc
* Get the name of the HMD audio output device.
* @function HMD.preferredAudioOutput
* @returns {string} The name of the HMD audio output device if in HMD mode, otherwise an empty string.
*/
Q_INVOKABLE QString preferredAudioOutput() const;
/**jsdoc
* Check whether there is an HMD available.
* @function HMD.isHMDAvailable
* @param {string} [name=""] - The name of the HMD to check for, e.g., <code>"Oculus Rift"</code>. The name is the same as
* may be displayed in Interface's "Display" menu. If no name is specified then any HMD matches.
* @returns {boolean} <code>true</code> if an HMD of the specified <code>name</code> is available, otherwise
* <code>false</code>.
* @example <caption>Report on HMD availability.</caption>
* print("Is any HMD available: " + HMD.isHMDAvailable());
* print("Is an Oculus Rift HMD available: " + HMD.isHMDAvailable("Oculus Rift"));
* print("Is a Vive HMD available: " + HMD.isHMDAvailable("OpenVR (Vive)"));
*/
Q_INVOKABLE bool isHMDAvailable(const QString& name = "");
/**jsdoc
* Check whether there is an HMD head controller available.
* @function HMD.isHeadControllerAvailable
* @param {string} [name=""] - The name of the HMD head controller to check for, e.g., <code>"Oculus"</code>. If no name is
* specified then any HMD head controller matches.
* @returns {boolean} <code>true</code> if an HMD head controller of the specified <code>name</code> is available,
* otherwise <code>false</code>.
* @example <caption>Report HMD head controller availability.</caption>
* print("Is any HMD head controller available: " + HMD.isHeadControllerAvailable());
* print("Is an Oculus head controller available: " + HMD.isHeadControllerAvailable("Oculus"));
* print("Is a Vive head controller available: " + HMD.isHeadControllerAvailable("OpenVR"));
*/
Q_INVOKABLE bool isHeadControllerAvailable(const QString& name = "");
/**jsdoc
* Check whether there are HMD hand controllers available.
* @function HMD.isHandControllerAvailable
* @param {string} [name=""] - The name of the HMD hand controller to check for, e.g., <code>"Oculus"</code>. If no name is
* specified then any HMD hand controller matches.
* @returns {boolean} <code>true</code> if an HMD hand controller of the specified <code>name</code> is available,
* otherwise <code>false</code>.
* @example <caption>Report HMD hand controller availability.</caption>
* print("Are any HMD hand controllers available: " + HMD.isHandControllerAvailable());
* print("Are Oculus hand controllers available: " + HMD.isHandControllerAvailable("Oculus"));
* print("Are Vive hand controllers available: " + HMD.isHandControllerAvailable("OpenVR"));
*/
Q_INVOKABLE bool isHandControllerAvailable(const QString& name = "");
/**jsdoc
* Check whether there are specific HMD controllers available.
* @function HMD.isSubdeviceContainingNameAvailable
* @param {string} name - The name of the HMD controller to check for, e.g., <code>"OculusTouch"</code>.
* @returns {boolean} <code>true</code> if an HMD controller with a name containing the specified <code>name</code> is
* available, otherwise <code>false</code>.
* @example <caption>Report if particular Oculus controllers are available.</caption>
* print("Is an Oculus Touch controller available: " + HMD.isSubdeviceContainingNameAvailable("Touch"));
* print("Is an Oculus Remote controller available: " + HMD.isSubdeviceContainingNameAvailable("Remote"));
*/
Q_INVOKABLE bool isSubdeviceContainingNameAvailable(const QString& name);
/**jsdoc
* Signal that models of the HMD hand controllers being used should be displayed. The models are displayed at their actual,
* real-world locations.
* @function HMD.requestShowHandControllers
* @example <caption>Show your hand controllers for 10 seconds.</caption>
* HMD.requestShowHandControllers();
* Script.setTimeout(function () {
* HMD.requestHideHandControllers();
* }, 10000);
*/
Q_INVOKABLE void requestShowHandControllers();
/**jsdoc
* Signal that it is no longer necessary to display models of the HMD hand controllers being used. If no other scripts
* want the models displayed then they are no longer displayed.
* @function HMD.requestHideHandControllers
*/
Q_INVOKABLE void requestHideHandControllers();
/**jsdoc
* Check whether any script wants models of the HMD hand controllers displayed. Requests are made and canceled using
* {@link HMD.requestShowHandControllers|requestShowHandControllers} and
* {@link HMD.requestHideHandControllers|requestHideHandControllers}.
* @function HMD.shouldShowHandControllers
* @returns {boolean} <code>true</code> if any script is requesting that HMD hand controller models be displayed.
*/
Q_INVOKABLE bool shouldShowHandControllers() const;
/**jsdoc
* Causes the borders in HUD windows to be enlarged when the laser intersects them in HMD mode. By default, borders are not
* enlarged.
* @function HMD.activateHMDHandMouse
*/
Q_INVOKABLE void activateHMDHandMouse();
/**jsdoc
* Causes the border in HUD windows to no longer be enlarged when the laser intersects them in HMD mode. By default,
* borders are not enlarged.
* @function HMD.deactivateHMDHandMouse
*/
Q_INVOKABLE void deactivateHMDHandMouse();
/**jsdoc
* Suppress the activation of the HMD-provided keyboard, if any. Successful calls should be balanced with a call to
* {@link HMD.unspressKeyboard|unspressKeyboard} within a reasonable amount of time.
* @function HMD.suppressKeyboard
* @returns {boolean} <code>true</code> if the current HMD provides a keyboard and it was successfully suppressed (e.g., it
* isn't being displayed), otherwise <code>false</code>.
*/
/// Suppress the activation of any on-screen keyboard so that a script operation will
/// not be interrupted by a keyboard popup
/// Returns false if there is already an active keyboard displayed.
@ -65,21 +286,68 @@ public:
/// call to unsuppressKeyboard() within a reasonable amount of time
Q_INVOKABLE bool suppressKeyboard();
/**jsdoc
* Unsuppress the activation of the HMD-provided keyboard, if any.
* @function HMD.unsuppressKeyboard
*/
/// Enable the keyboard following a suppressKeyboard call
Q_INVOKABLE void unsuppressKeyboard();
/**jsdoc
* Check whether the HMD-provided keyboard, if any, is visible.
* @function HMD.isKeyboardVisible
* @returns {boolean} <code>true</code> if the current HMD provides a keyboard and it is visible, otherwise
* <code>false</code>.
*/
/// Query the display plugin to determine the current VR keyboard visibility
Q_INVOKABLE bool isKeyboardVisible();
// rotate the overlay UI sphere so that it is centered about the the current HMD position and orientation
Q_INVOKABLE void centerUI();
/**jsdoc
* Closes the tablet if it is open.
* @function HMD.closeTablet
*/
Q_INVOKABLE void closeTablet();
/**jsdoc
* Opens the tablet if the tablet is used in the current display mode and it isn't already showing, and sets the tablet to
* contextual mode if requested. In contextual mode, the page displayed on the tablet is wholly controlled by script (i.e.,
* the user cannot navigate to another).
* @function HMD.openTablet
* @param {boolean} [contextualMode=false] - If <code>true</code> then the tablet is opened at a specific position and
* orientation already set by the script, otherwise it opens at a position and orientation relative to the user. For
* contextual mode, set the world or local position and orientation of the <code>HMD.tabletID</code> overlay.
*/
Q_INVOKABLE void openTablet(bool contextualMode = false);
signals:
/**jsdoc
* Triggered when a request to show or hide models of the HMD hand controllers is made using
* {@link HMD.requestShowHandControllers|requestShowHandControllers} or
* {@link HMD.requestHideHandControllers|requestHideHandControllers}.
* @function HMD.shouldShowHandControllersChanged
* @returns {Signal}
* @example <caption>Report when showing of hand controllers changes.</caption>
* function onShouldShowHandControllersChanged() {
* print("Should show hand controllers: " + HMD.shouldShowHandControllers());
* }
* HMD.shouldShowHandControllersChanged.connect(onShouldShowHandControllersChanged);
*
* HMD.requestShowHandControllers();
* Script.setTimeout(function () {
* HMD.requestHideHandControllers();
* }, 10000);
*/
bool shouldShowHandControllersChanged();
/**jsdoc
* Triggered when the <code>HMD.mounted</code> property value changes.
* @function HMD.mountedChanged
* @returns {Signal}
* @example <caption>Report when there's a change in the HMD being worn.</caption>
* HMD.mountedChanged.connect(function () {
* print("Mounted changed. HMD is mounted: " + HMD.mounted);
* });
*/
void mountedChanged();
public:

View file

@ -58,6 +58,13 @@ void SkeletonModel::initJointStates() {
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset);
_rig.initJointStates(geometry, modelOffset);
{
// initialize _jointData with proper values for default joints
QVector<JointData> defaultJointData;
_rig.copyJointsIntoJointData(defaultJointData);
_owningAvatar->setRawJointData(defaultJointData);
}
// Determine the default eye position for avatar scale = 1.0
int headJointIndex = geometry.headJointIndex;
if (0 > headJointIndex || headJointIndex >= _rig.getJointStateCount()) {

View file

@ -559,7 +559,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
const JointData& last = lastSentJointData[i];
if (!data.rotationIsDefaultPose) {
if (sendAll || last.rotationIsDefaultPose || last.rotation != data.rotation) {
bool mustSend = sendAll || last.rotationIsDefaultPose;
if (mustSend || last.rotation != data.rotation) {
bool largeEnoughRotation = true;
if (cullSmallChanges) {
@ -568,7 +569,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
largeEnoughRotation = fabsf(glm::dot(last.rotation, data.rotation)) < minRotationDOT;
}
if (sendAll || !cullSmallChanges || largeEnoughRotation) {
if (mustSend || !cullSmallChanges || largeEnoughRotation) {
validity |= (1 << validityBit);
#ifdef WANT_DEBUG
rotationSentCount++;
@ -608,10 +609,12 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
float maxTranslationDimension = 0.0;
for (int i = 0; i < _jointData.size(); i++) {
const JointData& data = _jointData[i];
const JointData& last = lastSentJointData[i];
if (!data.translationIsDefaultPose) {
if (sendAll || lastSentJointData[i].translation != data.translation) {
if (sendAll || !cullSmallChanges || glm::distance(data.translation, lastSentJointData[i].translation) > minTranslation) {
bool mustSend = sendAll || last.translationIsDefaultPose;
if (mustSend || last.translation != data.translation) {
if (mustSend || !cullSmallChanges || glm::distance(data.translation, lastSentJointData[i].translation) > minTranslation) {
validity |= (1 << validityBit);
#ifdef WANT_DEBUG
translationSentCount++;
@ -669,6 +672,19 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
}
if (sentJointDataOut) {
// Mark default poses in lastSentJointData, so when they become non-default we send them.
for (int i = 0; i < _jointData.size(); i++) {
const JointData& data = _jointData[i];
JointData& local = localSentJointDataOut[i];
if (data.rotationIsDefaultPose) {
local.rotationIsDefaultPose = true;
}
if (data.translationIsDefaultPose) {
local.translationIsDefaultPose = true;
}
}
// Push new sent joint data to sentJointDataOut
sentJointDataOut->swap(localSentJointDataOut);
}
@ -1816,13 +1832,13 @@ void AvatarData::setJointMappingsFromNetworkReply() {
networkReply->deleteLater();
}
void AvatarData::sendAvatarDataPacket() {
void AvatarData::sendAvatarDataPacket(bool sendAll) {
auto nodeList = DependencyManager::get<NodeList>();
// about 2% of the time, we send a full update (meaning, we transmit all the joint data), even if nothing has changed.
// this is to guard against a joint moving once, the packet getting lost, and the joint never moving again.
bool cullSmallData = (randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO);
bool cullSmallData = !sendAll && (randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO);
auto dataDetail = cullSmallData ? SendAllData : CullSmallData;
QByteArray avatarByteArray = toByteArrayStateful(dataDetail);

View file

@ -256,6 +256,11 @@ namespace AvatarDataPacket {
SixByteQuat rotation[numValidRotations]; // encodeded and compressed by packOrientationQuatToSixBytes()
uint8_t translationValidityBits[ceil(numJoints / 8)]; // one bit per joint, if true then a compressed translation follows.
SixByteTrans translation[numValidTranslations]; // encodeded and compressed by packFloatVec3ToSignedTwoByteFixed()
SixByteQuat leftHandControllerRotation;
SixByteTrans leftHandControllerTranslation;
SixByteQuat rightHandControllerRotation;
SixByteTrans rightHandControllerTranslation;
};
*/
size_t maxJointDataSize(size_t numJoints);
@ -707,11 +712,11 @@ signals:
void sessionUUIDChanged();
public slots:
void sendAvatarDataPacket();
void sendAvatarDataPacket(bool sendAll = false);
void sendIdentityPacket();
void setJointMappingsFromNetworkReply();
void setSessionUUID(const QUuid& sessionUUID) {
virtual void setSessionUUID(const QUuid& sessionUUID) {
if (sessionUUID != getID()) {
if (sessionUUID == QUuid()) {
setID(AVATAR_SELF_ID);

View file

@ -12,6 +12,7 @@
#include <GLMHelpers.h>
// These properties have JSDoc documentation in HMDScriptingInterface.h.
class AbstractHMDScriptingInterface : public QObject {
Q_OBJECT
Q_PROPERTY(bool active READ isHMDMode)
@ -30,7 +31,27 @@ public:
bool isHMDMode() const;
signals:
/**jsdoc
* Triggered when the <code>HMD.ipdScale</code> property value changes.
* @function HMD.IPDScaleChanged
* @returns {Signal}
*/
void IPDScaleChanged();
/**jsdoc
* Triggered when Interface's display mode changes and when the user puts on or takes off their HMD.
* @function HMD.displayModeChanged
* @param {boolean} isHMDMode - <code>true</code> if the display mode is HMD, otherwise <code>false</code>. This is the
* same value as provided by <code>HMD.active</code>.
* @returns {Signal}
* @example <caption>Report when the display mode changes.</caption>
* HMD.displayModeChanged.connect(function (isHMDMode) {
* print("Display mode changed");
* print("isHMD = " + isHMDMode);
* print("HMD.active = " + HMD.active);
* print("HMD.mounted = " + HMD.mounted);
* });
*/
void displayModeChanged(bool isHMDMode);
private:

View file

@ -18,6 +18,9 @@
#include "render-utils/simple_vert.h"
#include "render-utils/simple_frag.h"
#include "render-utils/simple_transparent_frag.h"
#include "render-utils/forward_simple_frag.h"
#include "render-utils/forward_simple_transparent_frag.h"
#include "RenderPipelines.h"
@ -35,13 +38,23 @@ static const float SPHERE_ENTITY_SCALE = 0.5f;
ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
_procedural._vertexSource = simple_vert::getSource();
_procedural._fragmentSource = simple_frag::getSource();
// FIXME: Setup proper uniform slots and use correct pipelines for forward rendering
_procedural._opaquefragmentSource = simple_frag::getSource();
// FIXME: Transparent procedural entities only seem to work if they use the opaque pipelines
//_procedural._transparentfragmentSource = simple_transparent_frag::getSource();
_procedural._transparentfragmentSource = simple_frag::getSource();
_procedural._opaqueState->setCullMode(gpu::State::CULL_NONE);
_procedural._opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL);
PrepareStencil::testMaskDrawShape(*_procedural._opaqueState);
_procedural._opaqueState->setBlendFunction(false,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
_procedural._transparentState->setCullMode(gpu::State::CULL_BACK);
_procedural._transparentState->setDepthTest(true, true, gpu::LESS_EQUAL);
PrepareStencil::testMask(*_procedural._transparentState);
_procedural._transparentState->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
}
bool ShapeEntityRenderer::needsRenderUpdate() const {
@ -218,9 +231,9 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
if (mat) {
outColor = glm::vec4(mat->getAlbedo(), mat->getOpacity());
if (_procedural.isReady()) {
_procedural.prepare(batch, _position, _dimensions, _orientation);
outColor = _procedural.getColor(outColor);
outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f;
_procedural.prepare(batch, _position, _dimensions, _orientation, outColor);
proceduralRender = true;
}
}

View file

@ -477,18 +477,19 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* @property {boolean} visible=true - Whether or not the entity is rendered. If <code>true</code> then the entity is rendered.
* @property {boolean} canCastShadows=true - Whether or not the entity casts shadows. Currently applicable only to
* {@link Entities.EntityType|Model} and {@link Entities.EntityType|Shape} entities. Shadows are cast if inside a
* {@link Entities.EntityType|Zone} entity with <code>castShadows</code> enabled in its {@link Entities.EntityProperties-Zone|keyLight} property.
* {@link Entities.EntityType|Zone} entity with <code>castShadows</code> enabled in its
* {@link Entities.EntityProperties-Zone|keyLight} property.
*
* @property {Vec3} position=0,0,0 - The position of the entity.
* @property {Quat} rotation=0,0,0,1 - The orientation of the entity with respect to world coordinates.
* @property {Vec3} registrationPoint=0.5,0.5,0.5 - The point in the entity that is set to the entity's position and is rotated
* about, {@link Vec3|Vec3.ZERO} &ndash; {@link Vec3|Vec3.ONE}. A value of {@link Vec3|Vec3.ZERO} is the entity's
* minimum x, y, z corner; a value of {@link Vec3|Vec3.ONE} is the entity's maximum x, y, z corner.
* about, {@link Vec3(0)|Vec3.ZERO} &ndash; {@link Vec3(0)|Vec3.ONE}. A value of {@link Vec3(0)|Vec3.ZERO} is the entity's
* minimum x, y, z corner; a value of {@link Vec3(0)|Vec3.ONE} is the entity's maximum x, y, z corner.
*
* @property {Vec3} naturalPosition=0,0,0 - The center of the entity's unscaled mesh model if it has one, otherwise
* {@link Vec3|Vec3.ZERO}. <em>Read-only.</em>
* {@link Vec3(0)|Vec3.ZERO}. <em>Read-only.</em>
* @property {Vec3} naturalDimensions - The dimensions of the entity's unscaled mesh model if it has one, otherwise
* {@link Vec3|Vec3.ONE}. <em>Read-only.</em>
* {@link Vec3(0)|Vec3.ONE}. <em>Read-only.</em>
*
* @property {Vec3} velocity=0,0,0 - The linear velocity of the entity in m/s with respect to world coordinates.
* @property {number} damping=0.39347 - How much to slow down the linear velocity of an entity over time, <code>0.0</code>
@ -505,13 +506,13 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* @property {Vec3} gravity=0,0,0 - The acceleration due to gravity in m/s<sup>2</sup> that the entity should move with, in
* world coordinates. Set to <code>{ x: 0, y: -9.8, z: 0 }</code> to simulate Earth's gravity. Gravity is applied to an
* entity's motion only if its <code>dynamic</code> property is <code>true</code>. If changing an entity's
* <code>gravity</code> from {@link Vec3|Vec3.ZERO}, you need to give it a small <code>velocity</code> in order to kick off
* physics simulation.
* <code>gravity</code> from {@link Vec3(0)|Vec3.ZERO}, you need to give it a small <code>velocity</code> in order to kick
* off physics simulation.
* The <code>gravity</code> value is applied in addition to the <code>acceleration</code> value.
* @property {Vec3} acceleration=0,0,0 - A general acceleration in m/s<sup>2</sup> that the entity should move with, in world
* coordinates. The acceleration is applied to an entity's motion only if its <code>dynamic</code> property is
* <code>true</code>. If changing an entity's <code>acceleration</code> from {@link Vec3|Vec3.ZERO}, you need to give it a
* small <code>velocity</code> in order to kick off physics simulation.
* <code>true</code>. If changing an entity's <code>acceleration</code> from {@link Vec3(0)|Vec3.ZERO}, you need to give it
* a small <code>velocity</code> in order to kick off physics simulation.
* The <code>acceleration</code> value is applied in addition to the <code>gravity</code> value.
* @property {number} restitution=0.5 - The "bounciness" of an entity when it collides, <code>0.0</code> &ndash;
* <code>0.99</code>. The higher the value, the more bouncy.

View file

@ -759,7 +759,7 @@ QVector<QUuid> EntityScriptingInterface::findEntitiesByType(const QString entity
foreach(EntityItemPointer entity, entities) {
if (entity->getType() == type) {
result << entity->getEntityItemID();
result << entity->getEntityItemID().toString();
}
}
}

View file

@ -694,7 +694,7 @@ public slots:
* @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity.
* @param {Vec3} voxelCoords - The voxel coordinates. May be fractional and outside the entity's bounding box.
* @returns {Vec3} The world coordinates of the <code>voxelCoords</code> if the <code>entityID</code> is a
* {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}.
* {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}.
* @example <caption>Create a PolyVox cube with the 0,0,0 voxel replaced by a sphere.</caption>
* // Cube PolyVox with 0,0,0 voxel missing.
* var polyVox = Entities.addEntity({
@ -729,7 +729,7 @@ public slots:
* @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity.
* @param {Vec3} worldCoords - The world coordinates. May be outside the entity's bounding box.
* @returns {Vec3} The voxel coordinates of the <code>worldCoords</code> if the <code>entityID</code> is a
* {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. The value may be fractional.
* {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. The value may be fractional.
*/
// FIXME move to a renderable entity interface
Q_INVOKABLE glm::vec3 worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords);
@ -741,7 +741,7 @@ public slots:
* @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity.
* @param {Vec3} voxelCoords - The voxel coordinates. May be fractional and outside the entity's bounding box.
* @returns {Vec3} The local coordinates of the <code>voxelCoords</code> if the <code>entityID</code> is a
* {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}.
* {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}.
* @example <caption>Get the world dimensions of a voxel in a PolyVox entity.</caption>
* var polyVox = Entities.addEntity({
* type: "PolyVox",
@ -763,7 +763,7 @@ public slots:
* @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity.
* @param {Vec3} localCoords - The local coordinates. May be outside the entity's bounding box.
* @returns {Vec3} The voxel coordinates of the <code>worldCoords</code> if the <code>entityID</code> is a
* {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. The value may be fractional.
* {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. The value may be fractional.
*/
// FIXME move to a renderable entity interface
Q_INVOKABLE glm::vec3 localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords);

View file

@ -2320,6 +2320,16 @@ bool EntityTree::readFromMap(QVariantMap& map) {
_persistDataVersion = map["DataVersion"].toInt();
}
_namedPaths.clear();
if (map.contains("Paths")) {
QVariantMap namedPathsMap = map["Paths"].toMap();
for(QVariantMap::const_iterator iter = namedPathsMap.begin(); iter != namedPathsMap.end(); ++iter) {
QString namedPathName = iter.key();
QString namedPathViewPoint = iter.value().toString();
_namedPaths[namedPathName] = namedPathViewPoint;
}
}
// map will have a top-level list keyed as "Entities". This will be extracted
// and iterated over. Each member of this list is converted to a QVariantMap, then
// to a QScriptValue, and then to EntityItemProperties. These properties are used

View file

@ -301,6 +301,8 @@ public:
static bool addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName);
static bool removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName);
std::map<QString, QString> getNamedPaths() const { return _namedPaths; }
signals:
void deletingEntity(const EntityItemID& entityID);
void deletingEntityPointer(EntityItem* entityID);
@ -417,6 +419,8 @@ private:
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromOverlayOperator;
bool _serverlessDomain { false };
std::map<QString, QString> _namedPaths;
};
#endif // hifi_EntityTree_h

View file

@ -57,7 +57,7 @@ namespace graphics {
// limit range and altitude to no less than 1.0 metres
static inline float convertHazeRangeToHazeRangeFactor(const float hazeRange) { return -LOG_P_005 / glm::max(hazeRange, 1.0f); }
static inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight) { return -LOG_P_005 / glm::max(hazeHeight, 1.0f); }
static inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight) { return -(LOG_P_005 * glm::sign(hazeHeight)) / glm::max(glm::abs(hazeHeight), 1.0f); }
// Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5
// s = dot(lookAngle, sunAngle) = cos(a)

View file

@ -314,7 +314,17 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
_shareablePlaceName.clear();
setDomainInfo(lookupUrl, trigger);
emit lookupResultsFinished();
handlePath(DOMAIN_SPAWNING_POINT, LookupTrigger::Internal, false);
QString path = DOMAIN_SPAWNING_POINT;
QUrlQuery queryArgs(lookupUrl);
const QString LOCATION_QUERY_KEY = "location";
if (queryArgs.hasQueryItem(LOCATION_QUERY_KEY)) {
path = queryArgs.queryItemValue(LOCATION_QUERY_KEY);
} else {
path = DEFAULT_NAMED_PATH;
}
handlePath(path, LookupTrigger::Internal, false);
return true;
}
@ -431,7 +441,9 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
QUrl domainURL;
domainURL.setScheme(URL_SCHEME_HIFI);
domainURL.setHost(domainHostname);
domainURL.setPort(domainPort);
if (domainPort > 0) {
domainURL.setPort(domainPort);
}
emit possibleDomainChangeRequired(domainURL, domainID);
} else {
QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString();
@ -602,7 +614,9 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri
QUrl domainURL;
domainURL.setScheme(URL_SCHEME_HIFI);
domainURL.setHost(domainIPString);
domainURL.setPort(domainPort);
if (domainPort > 0) {
domainURL.setPort(domainPort);
}
hostChanged = setDomainInfo(domainURL, trigger);
return true;
@ -623,7 +637,9 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri
QUrl domainURL;
domainURL.setScheme(URL_SCHEME_HIFI);
domainURL.setHost(domainHostname);
domainURL.setPort(domainPort);
if (domainPort > 0) {
domainURL.setPort(domainPort);
}
hostChanged = setDomainInfo(domainURL, trigger);
return true;
@ -755,7 +771,9 @@ bool AddressManager::setHost(const QString& host, LookupTrigger trigger, quint16
_domainURL = QUrl();
_domainURL.setScheme(URL_SCHEME_HIFI);
_domainURL.setHost(host);
_domainURL.setPort(port);
if (port > 0) {
_domainURL.setPort(port);
}
// any host change should clear the shareable place name
_shareablePlaceName.clear();

View file

@ -173,15 +173,15 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) {
QString previousHost = _domainURL.host();
_domainURL = domainURL;
if (domainURL.scheme() != URL_SCHEME_HIFI) {
setIsConnected(true);
} else if (previousHost != domainURL.host()) {
if (previousHost != domainURL.host()) {
qCDebug(networking) << "Updated domain hostname to" << domainURL.host();
if (!domainURL.host().isEmpty()) {
// re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname
qCDebug(networking, "Looking up DS hostname %s.", domainURL.host().toLocal8Bit().constData());
QHostInfo::lookupHost(domainURL.host(), this, SLOT(completedHostnameLookup(const QHostInfo&)));
if (domainURL.scheme() == URL_SCHEME_HIFI) {
// re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname
qCDebug(networking, "Looking up DS hostname %s.", domainURL.host().toLocal8Bit().constData());
QHostInfo::lookupHost(domainURL.host(), this, SLOT(completedHostnameLookup(const QHostInfo&)));
}
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(
LimitedNodeList::ConnectionStep::SetDomainHostname);
@ -250,6 +250,17 @@ void DomainHandler::activateICEPublicSocket() {
emit completedSocketDiscovery();
}
QString DomainHandler::getViewPointFromNamedPath(QString namedPath) {
auto lookup = _namedPaths.find(namedPath);
if (lookup != _namedPaths.end()) {
return lookup->second;
}
if (namedPath == DEFAULT_NAMED_PATH) {
return DOMAIN_SPAWNING_POINT;
}
return "";
}
void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) {
for (int i = 0; i < hostInfo.addresses().size(); i++) {
if (hostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) {
@ -297,6 +308,11 @@ void DomainHandler::setIsConnected(bool isConnected) {
}
}
void DomainHandler::connectedToServerless(std::map<QString, QString> namedPaths) {
_namedPaths = namedPaths;
setIsConnected(true);
}
void DomainHandler::requestDomainSettings() {
qCDebug(networking) << "Requesting settings from domain server";

View file

@ -76,6 +76,10 @@ public:
void setIsConnected(bool isConnected);
bool isServerless() const { return _domainURL.scheme() != URL_SCHEME_HIFI; }
void connectedToServerless(std::map<QString, QString> namedPaths);
QString getViewPointFromNamedPath(QString namedPath);
bool hasSettings() const { return !_settingsObject.isEmpty(); }
void requestDomainSettings();
const QJsonObject& getSettingsObject() const { return _settingsObject; }
@ -200,9 +204,11 @@ private:
int _checkInPacketsSinceLastReply { 0 };
QTimer _apiRefreshTimer;
std::map<QString, QString> _namedPaths;
};
const QString DOMAIN_SPAWNING_POINT { "/0, -10, 0" };
const QString DEFAULT_NAMED_PATH { "/" };
#endif // hifi_DomainHandler_h

View file

@ -413,7 +413,16 @@ void NodeList::sendDomainServerCheckIn() {
}
void NodeList::handleDSPathQuery(const QString& newPath) {
if (_domainHandler.isSocketKnown()) {
if (_domainHandler.isServerless()) {
if (_domainHandler.isConnected()) {
auto viewpoint = _domainHandler.getViewPointFromNamedPath(newPath);
if (!newPath.isEmpty()) {
DependencyManager::get<AddressManager>()->goToViewpointForPath(viewpoint, newPath);
}
} else {
_domainHandler.setPendingPath(newPath);
}
} else if (_domainHandler.isSocketKnown()) {
// if we have a DS socket we assume it will get this packet and send if off right away
sendDSPathQuery(newPath);
} else {
@ -427,10 +436,17 @@ void NodeList::sendPendingDSPathQuery() {
QString pendingPath = _domainHandler.getPendingPath();
if (!pendingPath.isEmpty()) {
qCDebug(networking) << "Attempting to send pending query to DS for path" << pendingPath;
// this is a slot triggered if we just established a network link with a DS and want to send a path query
sendDSPathQuery(_domainHandler.getPendingPath());
if (_domainHandler.isServerless()) {
auto viewpoint = _domainHandler.getViewPointFromNamedPath(pendingPath);
if (!pendingPath.isEmpty()) {
DependencyManager::get<AddressManager>()->goToViewpointForPath(viewpoint, pendingPath);
}
} else {
qCDebug(networking) << "Attempting to send pending query to DS for path" << pendingPath;
// this is a slot triggered if we just established a network link with a DS and want to send a path query
sendDSPathQuery(_domainHandler.getPendingPath());
}
// clear whatever the pending path was
_domainHandler.clearPendingPath();
@ -498,7 +514,7 @@ void NodeList::processDomainServerPathResponse(QSharedPointer<ReceivedMessage> m
QString viewpoint = QString::fromUtf8(message->getRawMessage() + message->getPosition(), numViewpointBytes);
// Hand it off to the AddressManager so it can handle it as a relative viewpoint
if (DependencyManager::get<AddressManager>()->goToViewpointForPath(viewpoint, pathQuery)) {
if (!pathQuery.isEmpty() && DependencyManager::get<AddressManager>()->goToViewpointForPath(viewpoint, pathQuery)) {
qCDebug(networking) << "Going to viewpoint" << viewpoint << "which was the lookup result for path" << pathQuery;
} else {
qCDebug(networking) << "Could not go to viewpoint" << viewpoint

View file

@ -219,7 +219,29 @@ bool Procedural::isReady() const {
return true;
}
void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation) {
std::string Procedural::replaceProceduralBlock(const std::string& fragmentSource) {
std::string fragmentShaderSource = fragmentSource;
size_t replaceIndex = fragmentShaderSource.find(PROCEDURAL_COMMON_BLOCK);
if (replaceIndex != std::string::npos) {
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_COMMON_BLOCK.size(), ProceduralCommon_frag::getSource());
}
replaceIndex = fragmentShaderSource.find(PROCEDURAL_VERSION);
if (replaceIndex != std::string::npos) {
if (_data.version == 1) {
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V1 1");
} else if (_data.version == 2) {
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V2 1");
}
}
replaceIndex = fragmentShaderSource.find(PROCEDURAL_BLOCK);
if (replaceIndex != std::string::npos) {
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_BLOCK.size(), _shaderSource.toLocal8Bit().data());
}
return fragmentShaderSource;
}
void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, const glm::vec4& color) {
_entityDimensions = size;
_entityPosition = position;
_entityOrientation = glm::mat3_cast(orientation);
@ -242,58 +264,48 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm
}
// Build the fragment shader
std::string fragmentShaderSource = _fragmentSource;
size_t replaceIndex = fragmentShaderSource.find(PROCEDURAL_COMMON_BLOCK);
if (replaceIndex != std::string::npos) {
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_COMMON_BLOCK.size(), ProceduralCommon_frag::getSource());
}
replaceIndex = fragmentShaderSource.find(PROCEDURAL_VERSION);
if (replaceIndex != std::string::npos) {
if (_data.version == 1) {
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V1 1");
} else if (_data.version == 2) {
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V2 1");
}
}
replaceIndex = fragmentShaderSource.find(PROCEDURAL_BLOCK);
if (replaceIndex != std::string::npos) {
fragmentShaderSource.replace(replaceIndex, PROCEDURAL_BLOCK.size(), _shaderSource.toLocal8Bit().data());
}
std::string opaqueShaderSource = replaceProceduralBlock(_opaquefragmentSource);
std::string transparentShaderSource = replaceProceduralBlock(_transparentfragmentSource);
// Leave this here for debugging
// qCDebug(procedural) << "FragmentShader:\n" << fragmentShaderSource.c_str();
_fragmentShader = gpu::Shader::createPixel(fragmentShaderSource);
_shader = gpu::Shader::createProgram(_vertexShader, _fragmentShader);
_opaqueFragmentShader = gpu::Shader::createPixel(opaqueShaderSource);
_opaqueShader = gpu::Shader::createProgram(_vertexShader, _opaqueFragmentShader);
_transparentFragmentShader = gpu::Shader::createPixel(transparentShaderSource);
_transparentShader = gpu::Shader::createProgram(_vertexShader, _transparentFragmentShader);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("iChannel0"), 0));
slotBindings.insert(gpu::Shader::Binding(std::string("iChannel1"), 1));
slotBindings.insert(gpu::Shader::Binding(std::string("iChannel2"), 2));
slotBindings.insert(gpu::Shader::Binding(std::string("iChannel3"), 3));
gpu::Shader::makeProgram(*_shader, slotBindings);
gpu::Shader::makeProgram(*_opaqueShader, slotBindings);
gpu::Shader::makeProgram(*_transparentShader, slotBindings);
_opaquePipeline = gpu::Pipeline::create(_shader, _opaqueState);
_transparentPipeline = gpu::Pipeline::create(_shader, _transparentState);
_opaquePipeline = gpu::Pipeline::create(_opaqueShader, _opaqueState);
_transparentPipeline = gpu::Pipeline::create(_transparentShader, _transparentState);
for (size_t i = 0; i < NUM_STANDARD_UNIFORMS; ++i) {
const std::string& name = STANDARD_UNIFORM_NAMES[i];
_standardUniformSlots[i] = _shader->getUniforms().findLocation(name);
_standardOpaqueUniformSlots[i] = _opaqueShader->getUniforms().findLocation(name);
_standardTransparentUniformSlots[i] = _transparentShader->getUniforms().findLocation(name);
}
_start = usecTimestampNow();
_frameCount = 0;
}
batch.setPipeline(isFading() ? _transparentPipeline : _opaquePipeline);
bool transparent = color.a < 1.0f;
batch.setPipeline(transparent ? _transparentPipeline : _opaquePipeline);
if (_shaderDirty || _uniformsDirty) {
setupUniforms();
if (_shaderDirty || _uniformsDirty || _prevTransparent != transparent) {
setupUniforms(transparent);
}
if (_shaderDirty || _uniformsDirty || _channelsDirty) {
setupChannels(_shaderDirty || _uniformsDirty);
if (_shaderDirty || _uniformsDirty || _channelsDirty || _prevTransparent != transparent) {
setupChannels(_shaderDirty || _uniformsDirty, transparent);
}
_prevTransparent = transparent;
_shaderDirty = _uniformsDirty = _channelsDirty = false;
for (auto lambda : _uniforms) {
@ -319,12 +331,12 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm
}
}
void Procedural::setupUniforms() {
void Procedural::setupUniforms(bool transparent) {
_uniforms.clear();
// Set any userdata specified uniforms
foreach(QString key, _data.uniforms.keys()) {
std::string uniformName = key.toLocal8Bit().data();
int32_t slot = _shader->getUniforms().findLocation(uniformName);
int32_t slot = (transparent ? _transparentShader : _opaqueShader)->getUniforms().findLocation(uniformName);
if (gpu::Shader::INVALID_LOCATION == slot) {
continue;
}
@ -385,15 +397,17 @@ void Procedural::setupUniforms() {
}
}
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[TIME]) {
auto uniformSlots = transparent ? _standardTransparentUniformSlots : _standardOpaqueUniformSlots;
if (gpu::Shader::INVALID_LOCATION != uniformSlots[TIME]) {
_uniforms.push_back([=](gpu::Batch& batch) {
// Minimize floating point error by doing an integer division to milliseconds, before the floating point division to seconds
float time = (float)((usecTimestampNow() - _start) / USECS_PER_MSEC) / MSECS_PER_SECOND;
batch._glUniform(_standardUniformSlots[TIME], time);
batch._glUniform(uniformSlots[TIME], time);
});
}
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[DATE]) {
if (gpu::Shader::INVALID_LOCATION != uniformSlots[DATE]) {
_uniforms.push_back([=](gpu::Batch& batch) {
QDateTime now = QDateTime::currentDateTimeUtc();
QDate date = now.date();
@ -406,40 +420,41 @@ void Procedural::setupUniforms() {
v.z = date.day();
float fractSeconds = (time.msec() / 1000.0f);
v.w = (time.hour() * 3600) + (time.minute() * 60) + time.second() + fractSeconds;
batch._glUniform(_standardUniformSlots[DATE], v);
batch._glUniform(uniformSlots[DATE], v);
});
}
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[FRAME_COUNT]) {
if (gpu::Shader::INVALID_LOCATION != uniformSlots[FRAME_COUNT]) {
_uniforms.push_back([=](gpu::Batch& batch) {
batch._glUniform(_standardUniformSlots[FRAME_COUNT], ++_frameCount);
batch._glUniform(uniformSlots[FRAME_COUNT], ++_frameCount);
});
}
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[SCALE]) {
if (gpu::Shader::INVALID_LOCATION != uniformSlots[SCALE]) {
// FIXME move into the 'set once' section, since this doesn't change over time
_uniforms.push_back([=](gpu::Batch& batch) {
batch._glUniform(_standardUniformSlots[SCALE], _entityDimensions);
batch._glUniform(uniformSlots[SCALE], _entityDimensions);
});
}
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[ORIENTATION]) {
if (gpu::Shader::INVALID_LOCATION != uniformSlots[ORIENTATION]) {
// FIXME move into the 'set once' section, since this doesn't change over time
_uniforms.push_back([=](gpu::Batch& batch) {
batch._glUniform(_standardUniformSlots[ORIENTATION], _entityOrientation);
batch._glUniform(uniformSlots[ORIENTATION], _entityOrientation);
});
}
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[POSITION]) {
if (gpu::Shader::INVALID_LOCATION != uniformSlots[POSITION]) {
// FIXME move into the 'set once' section, since this doesn't change over time
_uniforms.push_back([=](gpu::Batch& batch) {
batch._glUniform(_standardUniformSlots[POSITION], _entityPosition);
batch._glUniform(uniformSlots[POSITION], _entityPosition);
});
}
}
void Procedural::setupChannels(bool shouldCreate) {
if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[CHANNEL_RESOLUTION]) {
void Procedural::setupChannels(bool shouldCreate, bool transparent) {
auto uniformSlots = transparent ? _standardTransparentUniformSlots : _standardOpaqueUniformSlots;
if (gpu::Shader::INVALID_LOCATION != uniformSlots[CHANNEL_RESOLUTION]) {
if (!shouldCreate) {
// Instead of modifying the last element, just remove and recreate it.
_uniforms.pop_back();
@ -451,7 +466,7 @@ void Procedural::setupChannels(bool shouldCreate) {
channelSizes[i] = vec3(_channels[i]->getWidth(), _channels[i]->getHeight(), 1.0);
}
}
batch._glUniform3fv(_standardUniformSlots[CHANNEL_RESOLUTION], MAX_PROCEDURAL_TEXTURE_CHANNELS, &channelSizes[0].x);
batch._glUniform3fv(uniformSlots[CHANNEL_RESOLUTION], MAX_PROCEDURAL_TEXTURE_CHANNELS, &channelSizes[0].x);
});
}
}

View file

@ -55,8 +55,8 @@ public:
bool isReady() const;
bool isEnabled() const { return _enabled; }
void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation);
const gpu::ShaderPointer& getShader() const { return _shader; }
void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, const glm::vec4& color = glm::vec4(1));
const gpu::ShaderPointer& getOpaqueShader() const { return _opaqueShader; }
glm::vec4 getColor(const glm::vec4& entityColor);
quint64 getFadeStartTime() const { return _fadeStartTime; }
@ -65,7 +65,8 @@ public:
void setDoesFade(bool doesFade) { _doesFade = doesFade; }
std::string _vertexSource;
std::string _fragmentSource;
std::string _opaquefragmentSource;
std::string _transparentfragmentSource;
gpu::StatePointer _opaqueState { std::make_shared<gpu::State>() };
gpu::StatePointer _transparentState { std::make_shared<gpu::State>() };
@ -101,13 +102,16 @@ protected:
// Rendering objects
UniformLambdas _uniforms;
int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS];
int32_t _standardOpaqueUniformSlots[NUM_STANDARD_UNIFORMS];
int32_t _standardTransparentUniformSlots[NUM_STANDARD_UNIFORMS];
NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS];
gpu::PipelinePointer _opaquePipeline;
gpu::PipelinePointer _transparentPipeline;
gpu::ShaderPointer _vertexShader;
gpu::ShaderPointer _fragmentShader;
gpu::ShaderPointer _shader;
gpu::ShaderPointer _opaqueFragmentShader;
gpu::ShaderPointer _transparentFragmentShader;
gpu::ShaderPointer _opaqueShader;
gpu::ShaderPointer _transparentShader;
// Entity metadata
glm::vec3 _entityDimensions;
@ -116,13 +120,16 @@ protected:
private:
// This should only be called from the render thread, as it shares data with Procedural::prepare
void setupUniforms();
void setupChannels(bool shouldCreate);
void setupUniforms(bool transparent);
void setupChannels(bool shouldCreate, bool transparent);
std::string replaceProceduralBlock(const std::string& fragmentSource);
mutable quint64 _fadeStartTime { 0 };
mutable bool _hasStartedFade { false };
mutable bool _isFading { false };
bool _doesFade { true };
bool _prevTransparent { false };
};
#endif

View file

@ -20,7 +20,7 @@
ProceduralSkybox::ProceduralSkybox() : graphics::Skybox() {
_procedural._vertexSource = skybox_vert::getSource();
_procedural._fragmentSource = skybox_frag::getSource();
_procedural._opaquefragmentSource = skybox_frag::getSource();
// Adjust the pipeline state for background using the stencil test
_procedural.setDoesFade(false);
// Must match PrepareStencil::STENCIL_BACKGROUND
@ -61,8 +61,8 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum,
auto& procedural = skybox._procedural;
procedural.prepare(batch, glm::vec3(0), glm::vec3(1), glm::quat());
auto textureSlot = procedural.getShader()->getTextures().findLocation("cubeMap");
auto bufferSlot = procedural.getShader()->getUniformBuffers().findLocation("skyboxBuffer");
auto textureSlot = procedural.getOpaqueShader()->getTextures().findLocation("cubeMap");
auto bufferSlot = procedural.getOpaqueShader()->getUniformBuffers().findLocation("skyboxBuffer");
skybox.prepare(batch, textureSlot, bufferSlot);
batch.draw(gpu::TRIANGLE_STRIP, 4);
}

View file

@ -0,0 +1,23 @@
<!
// DefaultMaterials.slh
// libraries/render-utils/src
//
// Created by Sam Gondelman on 3/22/18
// Copyright 2018 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
!>
<@if not DEFAULT_MATERIAL_SLH@>
<@def DEFAULT_MATERIAL_SLH@>
const float DEFAULT_ROUGHNESS = 0.9;
const float DEFAULT_SHININESS = 10.0;
const float DEFAULT_METALLIC = 0.0;
const vec3 DEFAULT_SPECULAR = vec3(0.1);
const vec3 DEFAULT_EMISSIVE = vec3(0.0);
const float DEFAULT_OCCLUSION = 1.0;
const float DEFAULT_SCATTERING = 0.0;
const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;
<@endif@>

View file

@ -26,14 +26,7 @@ float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold));
}
const float DEFAULT_ROUGHNESS = 0.9;
const float DEFAULT_SHININESS = 10.0;
const float DEFAULT_METALLIC = 0.0;
const vec3 DEFAULT_SPECULAR = vec3(0.1);
const vec3 DEFAULT_EMISSIVE = vec3(0.0);
const float DEFAULT_OCCLUSION = 1.0;
const float DEFAULT_SCATTERING = 0.0;
const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE;
<@include DefaultMaterials.slh@>
void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {
if (alpha != 1.0) {

View file

@ -20,7 +20,6 @@
<@include LightAmbient.slh@>
<@include LightDirectional.slh@>
<@func fetchGlobalLight()@>
// Get light
Light light = getKeyLight();
@ -32,12 +31,13 @@
vec3 color = vec3(0.0);
<@endfunc@>
<@func prepareGlobalLight(isScattering)@>
<@func prepareGlobalLight(positionES, normalWS)@>
// prepareGlobalLight
// Transform directions to worldspace
vec3 fragNormal = vec3((normal));
vec3 fragEyeVector = vec3(invViewMat * vec4(-position, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
vec3 fragNormalWS = vec3(<$normalWS$>);
vec3 fragPositionWS = vec3(invViewMat * vec4(<$positionES$>, 1.0));
vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;
vec3 fragEyeDirWS = normalize(fragEyeVectorWS);
<$fetchGlobalLight()$>
@ -46,7 +46,7 @@
<@func declareEvalAmbientGlobalColor()@>
vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) {
<$prepareGlobalLight()$>
<$prepareGlobalLight(position, normal)$>
color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(lightAmbient);
return color;
}
@ -67,14 +67,14 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
<@endif@> ) {
<$prepareGlobalLight($supportScattering$)$>
<$prepareGlobalLight(position, normal)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
@ -85,7 +85,7 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
@ -114,14 +114,14 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
<@endif@>
) {
<$prepareGlobalLight($supportScattering$)$>
<$prepareGlobalLight(position, normal)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
@ -131,7 +131,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
@ -141,7 +141,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
// Attenuate the light if haze effect selected
if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {
color = computeHazeColorKeyLightAttenuation(color, lightDirection, position);
color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS);
}
return color;
@ -180,9 +180,9 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur
<$declareLightingDirectional()$>
vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity, vec3 prevLighting) {
<$prepareGlobalLight()$>
<$prepareGlobalLight(position, normal)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
color = prevLighting;
color += emissive * isEmissiveEnabled();
@ -190,16 +190,15 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);
color += ambientDiffuse;
color += ambientSpecular / opacity;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += directionalSpecular / opacity;
color += (ambientSpecular + directionalSpecular) / opacity;
return color;
}
@ -211,37 +210,37 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl
<$declareLightingDirectional()$>
vec3 evalGlobalLightingAlphaBlendedWithHaze(
mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,
mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 normalWS,
vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity)
{
<$prepareGlobalLight()$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
<$prepareGlobalLight(positionES, normalWS)$>
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
color += emissive * isEmissiveEnabled();
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);
color += ambientDiffuse;
color += ambientSpecular / opacity;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += directionalSpecular / opacity;
color += (ambientSpecular + directionalSpecular) / opacity;
// Haze
if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
vec4 colorV4 = computeHazeColor(
vec4(color, 1.0), // fragment original color
position, // fragment position in eye coordinates
fragEyeVector, // fragment position in world coordinates
invViewMat[3].y, // eye height in world coordinates
lightDirection // keylight direction vector
positionES, // fragment position in eye coordinates
fragPositionWS, // fragment position in world coordinates
invViewMat[3].xyz, // eye position in world coordinates
lightDirection // keylight direction vector in world coordinates
);
color = colorV4.rgb;
@ -251,7 +250,7 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
}
vec3 evalGlobalLightingAlphaBlendedWithHaze(
mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position,
mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 positionES, vec3 positionWS,
vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting)
{
<$fetchGlobalLight()$>
@ -276,9 +275,9 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
vec4 colorV4 = computeHazeColor(
vec4(color, 1.0), // fragment original color
position, // fragment position in eye coordinates
surface.eyeDir, // fragment eye vector in world coordinates
invViewMat[3].y, // eye height in world coordinates
positionES, // fragment position in eye coordinates
positionWS, // fragment position in world coordinates
invViewMat[3].xyz, // eye position in world coordinates
lightDirection // keylight direction vector
);

View file

@ -142,15 +142,18 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
// Mask out haze on the tablet
PrepareStencil::testMask(*state);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), HazeEffect_TransformBufferSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), HazeEffect_ColorMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), HazeEffect_LinearDepthMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), HazeEffect_LightingMapSlot));
gpu::Shader::makeProgram(*program, slotBindings);
_hazePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
gpu::doInBatch("DrawHaze::build", args->_context, [program](gpu::Batch& batch) {
batch.runLambda([program]() {
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), HazeEffect_TransformBufferSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), HazeEffect_ColorMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), HazeEffect_LinearDepthMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), HazeEffect_LightingMapSlot));
gpu::Shader::makeProgram(*program, slotBindings);
});
});
}
auto sourceFramebufferSize = glm::ivec2(inputBuffer->getDimensions());

View file

@ -20,13 +20,13 @@
<@include LightAmbient.slh@>
<@include LightDirectional.slh@>
<@func prepareGlobalLight(isScattering)@>
<@func prepareGlobalLight(positionES, normalWS)@>
// prepareGlobalLight
// Transform directions to worldspace
vec3 fragNormal = vec3((normal));
vec3 fragEyeVector = vec3(invViewMat * vec4(-1.0*position, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
vec3 fragNormalWS = vec3(<$normalWS$>);
vec3 fragPositionWS = vec3(invViewMat * vec4(<$positionES$>, 1.0));
vec3 fragEyeVectorWS = invViewMat[3].xyz - fragPositionWS;
vec3 fragEyeDirWS = normalize(fragEyeVectorWS);
// Get light
Light light = getKeyLight();
@ -42,7 +42,7 @@
<@func declareEvalAmbientGlobalColor()@>
vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) {
<$prepareGlobalLight()$>
<$prepareGlobalLight(position, normal)$>
color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(lightAmbient);
return color;
}
@ -63,14 +63,14 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
<@endif@> ) {
<$prepareGlobalLight($supportScattering$)$>
<$prepareGlobalLight(position, normal)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
@ -81,7 +81,7 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@> );
@ -109,14 +109,14 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
<@endif@>
) {
<$prepareGlobalLight($supportScattering$)$>
<$prepareGlobalLight(position, normal)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
@ -126,7 +126,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation
<@if supportScattering@>
,scattering, midNormalCurvature, lowNormalCurvature
<@endif@>
@ -137,7 +137,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
// FIXME - temporarily removed until we support it for forward...
// Attenuate the light if haze effect selected
// if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {
// color = computeHazeColorKeyLightAttenuation(color, lightDirection, position);
// color = computeHazeColorKeyLightAttenuation(color, lightDirection, fragPositionWS);
// }
return color;
@ -180,25 +180,24 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur
<$declareLightingDirectional()$>
vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) {
<$prepareGlobalLight()$>
<$prepareGlobalLight(position, normal)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
color += emissive * isEmissiveEnabled();
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);
color += ambientDiffuse;
color += ambientSpecular / opacity;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += directionalSpecular / opacity;
color += (ambientSpecular + directionalSpecular) / opacity;
return color;
}
@ -207,34 +206,33 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal,
vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity)
{
<$prepareGlobalLight()$>
<$prepareGlobalLight(position, normal)$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragEyeDirWS);
color += emissive * isEmissiveEnabled();
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surfaceWS, metallic, fresnel, albedo, obscurance);
color += ambientDiffuse;
color += ambientSpecular / opacity;
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse;
color += directionalSpecular / opacity;
color += (ambientSpecular + directionalSpecular) / opacity;
// Haze
// FIXME - temporarily removed until we support it for forward...
/* if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
vec4 colorV4 = computeHazeColor(
vec4(color, 1.0), // fragment original color
position, // fragment position in eye coordinates
fragEyeVector, // fragment position in world coordinates
invViewMat[3].y, // eye height in world coordinates
positionES, // fragment position in eye coordinates
fragPositionWS, // fragment position in world coordinates
invViewMat[3].xyz, // eye position in world coordinates
lightDirection // keylight direction vector
);

View file

@ -40,6 +40,7 @@
#include "simple_vert.h"
#include "simple_textured_frag.h"
#include "simple_transparent_textured_frag.h"
#include "simple_textured_unlit_frag.h"
#include "simple_fade_vert.h"
#include "simple_textured_fade_frag.h"
@ -49,6 +50,19 @@
#include "glowLine_vert.h"
#include "glowLine_frag.h"
#include "forward_simple_textured_frag.h"
#include "forward_simple_textured_transparent_frag.h"
#include "forward_simple_textured_unlit_frag.h"
#include "DeferredLightingEffect.h"
#if defined(USE_GLES)
static bool DISABLE_DEFERRED = true;
#else
static const QString RENDER_FORWARD{ "HIFI_RENDER_FORWARD" };
static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD);
#endif
#include "grid_frag.h"
//#define WANT_DEBUG
@ -679,6 +693,7 @@ gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() {
QHash<SimpleProgramKey, gpu::PipelinePointer> GeometryCache::_simplePrograms;
gpu::ShaderPointer GeometryCache::_simpleShader;
gpu::ShaderPointer GeometryCache::_transparentShader;
gpu::ShaderPointer GeometryCache::_unlitShader;
gpu::ShaderPointer GeometryCache::_simpleFadeShader;
gpu::ShaderPointer GeometryCache::_unlitFadeShader;
@ -774,8 +789,12 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool
bool unlit, bool depthBias) {
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true), nullptr,
[](const render::ShapePipeline& , gpu::Batch& batch, render::Args*) {
[](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get<TextureCache>()->getWhiteTexture());
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch,
pipeline.pipeline->getProgram()->getUniformBuffers().findLocation("keyLightBuffer"),
pipeline.pipeline->getProgram()->getUniformBuffers().findLocation("lightAmbientBuffer"),
pipeline.pipeline->getProgram()->getUniformBuffers().findLocation("skyboxMap"));
}
);
}
@ -798,7 +817,7 @@ render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading
return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline;
}
render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) {
render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) {
return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline;
}
@ -843,7 +862,7 @@ void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, siz
_shapes[shape].drawWireInstances(batch, count);
}
void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer,
void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer,
gpu::BufferPointer fadeBuffer1, gpu::BufferPointer fadeBuffer2, gpu::BufferPointer fadeBuffer3) {
gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT);
gpu::BufferView texCoord2View(fadeBuffer1, TEXCOORD4_ELEMENT);
@ -2003,7 +2022,7 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const
auto program = gpu::Shader::createProgram(VS, PS);
state->setCullMode(gpu::State::CULL_NONE);
state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setBlendFunction(true,
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
@ -2231,29 +2250,41 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
static std::once_flag once;
std::call_once(once, [&]() {
auto VS = simple_vert::getShader();
auto PS = simple_textured_frag::getShader();
auto PSUnlit = simple_textured_unlit_frag::getShader();
auto PS = DISABLE_DEFERRED ? forward_simple_textured_frag::getShader() : simple_textured_frag::getShader();
// Use the forward pipeline for both here, otherwise transparents will be unlit
auto PSTransparent = DISABLE_DEFERRED ? forward_simple_textured_transparent_frag::getShader() : forward_simple_textured_transparent_frag::getShader();
auto PSUnlit = DISABLE_DEFERRED ? forward_simple_textured_unlit_frag::getShader() : simple_textured_unlit_frag::getShader();
_simpleShader = gpu::Shader::createProgram(VS, PS);
_transparentShader = gpu::Shader::createProgram(VS, PSTransparent);
_unlitShader = gpu::Shader::createProgram(VS, PSUnlit);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO));
slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), render::ShapePipeline::Slot::LIGHTING_MODEL));
slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), render::ShapePipeline::Slot::KEY_LIGHT));
slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER));
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), render::ShapePipeline::Slot::MAP::LIGHT_AMBIENT));
gpu::Shader::makeProgram(*_simpleShader, slotBindings);
gpu::Shader::makeProgram(*_transparentShader, slotBindings);
gpu::Shader::makeProgram(*_unlitShader, slotBindings);
});
} else {
static std::once_flag once;
std::call_once(once, [&]() {
auto VS = simple_fade_vert::getShader();
auto PS = simple_textured_fade_frag::getShader();
auto PSUnlit = simple_textured_unlit_fade_frag::getShader();
auto PS = DISABLE_DEFERRED ? forward_simple_textured_frag::getShader() : simple_textured_fade_frag::getShader();
auto PSUnlit = DISABLE_DEFERRED ? forward_simple_textured_unlit_frag::getShader() : simple_textured_unlit_fade_frag::getShader();
_simpleFadeShader = gpu::Shader::createProgram(VS, PS);
_unlitFadeShader = gpu::Shader::createProgram(VS, PSUnlit);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO));
slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), render::ShapePipeline::Slot::LIGHTING_MODEL));
slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), render::ShapePipeline::Slot::KEY_LIGHT));
slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER));
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), render::ShapePipeline::Slot::MAP::LIGHT_AMBIENT));
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), render::ShapePipeline::Slot::MAP::FADE_MASK));
gpu::Shader::makeProgram(*_simpleFadeShader, slotBindings);
gpu::Shader::makeProgram(*_unlitFadeShader, slotBindings);
@ -2282,7 +2313,8 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
PrepareStencil::testMaskDrawShapeNoAA(*state);
}
gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : (config.isFading() ? _simpleFadeShader : _simpleShader);
gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) :
(config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _transparentShader : _simpleShader));
gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state);
_simplePrograms.insert(config, pipeline);
return pipeline;
@ -2363,11 +2395,11 @@ void renderFadeInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& c
pipeline->prepare(batch, args);
if (isWire) {
DependencyManager::get<GeometryCache>()->renderWireFadeShapeInstances(batch, shape, data.count(),
DependencyManager::get<GeometryCache>()->renderWireFadeShapeInstances(batch, shape, data.count(),
buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]);
}
else {
DependencyManager::get<GeometryCache>()->renderFadeShapeInstances(batch, shape, data.count(),
DependencyManager::get<GeometryCache>()->renderFadeShapeInstances(batch, shape, data.count(),
buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]);
}
});
@ -2383,15 +2415,15 @@ void GeometryCache::renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch,
renderInstances(args, batch, color, true, pipeline, shape);
}
void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color,
int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,
void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color,
int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,
const render::ShapePipelinePointer& pipeline) {
assert(pipeline != nullptr);
renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, false, pipeline, shape);
}
void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color,
int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,
void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color,
int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,
const render::ShapePipelinePointer& pipeline) {
assert(pipeline != nullptr);
renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, true, pipeline, shape);

View file

@ -471,6 +471,7 @@ private:
QHash<int, GridBuffer> _registeredGridBuffers;
static gpu::ShaderPointer _simpleShader;
static gpu::ShaderPointer _transparentShader;
static gpu::ShaderPointer _unlitShader;
static gpu::ShaderPointer _simpleFadeShader;
static gpu::ShaderPointer _unlitFadeShader;
@ -478,8 +479,6 @@ private:
static render::ShapePipelinePointer _simpleTransparentPipeline;
static render::ShapePipelinePointer _simpleOpaqueFadePipeline;
static render::ShapePipelinePointer _simpleTransparentFadePipeline;
static render::ShapePipelinePointer _simpleOpaqueOverlayPipeline;
static render::ShapePipelinePointer _simpleTransparentOverlayPipeline;
static render::ShapePipelinePointer _simpleWirePipeline;
gpu::PipelinePointer _glowLinePipeline;

View file

@ -47,14 +47,14 @@ void main(void) {
}
vec4 fragColor = texture(colorMap, varTexCoord0);
vec4 eyeFragPos = unpackPositionFromZeye(varTexCoord0);
vec4 fragPositionES = unpackPositionFromZeye(varTexCoord0);
mat4 viewInverse = getViewInverse();
vec4 worldFragPos = viewInverse * eyeFragPos;
vec4 worldEyePos = viewInverse[3];
vec4 fragPositionWS = viewInverse * fragPositionES;
vec4 eyePositionWS = viewInverse[3];
Light light = getKeyLight();
vec3 lightDirection = getLightDirection(light);
vec3 lightDirectionWS = getLightDirection(light);
outFragColor = computeHazeColor(fragColor, eyeFragPos.xyz, worldFragPos.xyz, worldEyePos.y, lightDirection);
outFragColor = computeHazeColor(fragColor, fragPositionES.xyz, fragPositionWS.xyz, eyePositionWS.xyz, lightDirectionWS);
}

View file

@ -43,16 +43,16 @@ layout(std140) uniform hazeBuffer {
// Input:
// color - fragment original color
// lightDirection - parameters of the keylight
// worldFragPos - fragment position in world coordinates
// lightDirectionWS - parameters of the keylight
// fragPositionWS - fragment position in world coordinates
// Output:
// fragment colour after haze effect
//
// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission
//
vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirection, vec3 worldFragPos) {
vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 fragPositionWS) {
// Directional light attenuation is simulated by assuming the light source is at a fixed height above the
// fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height
// fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height
//
// The distance is computed from the height and the directional light orientation
// The distance is limited to height * 1,000, which gives an angle of ~0.057 degrees
@ -65,7 +65,7 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirection, vec3 w
}
// Note that we need the sine to be positive
float sin_pitch = abs(lightDirection.y);
float sin_pitch = abs(lightDirectionWS.y);
float distance;
const float minimumSinPitch = 0.001;
@ -79,7 +79,7 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirection, vec3 w
// Note that the haze base reference affects only the haze density as function of altitude
float hazeDensityDistribution =
hazeParams.hazeKeyLightRangeFactor *
exp(-hazeParams.hazeKeyLightAltitudeFactor * (worldFragPos.y - hazeParams.hazeBaseReference));
exp(-hazeParams.hazeKeyLightAltitudeFactor * (fragPositionWS.y - hazeParams.hazeBaseReference));
float hazeIntegral = hazeDensityDistribution * distance;
@ -92,33 +92,34 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirection, vec3 w
}
// Input:
// fragColor - fragment original color
// eyeFragPos - fragment position in eye coordinates
// worldFragPos - fragment position in world coordinates
// worldEyeHeight - eye height in world coordinates
// fragColor - fragment original color
// fragPositionES - fragment position in eye coordinates
// fragPositionWS - fragment position in world coordinates
// eyePositionWS - eye position in world coordinates
// Output:
// fragment colour after haze effect
//
// General algorithm taken from http://www.iquilezles.org/www/articles/fog/fog.htm, with permission
//
vec4 computeHazeColor(vec4 fragColor, vec3 eyeFragPos, vec3 worldFragPos, float worldEyeHeight, vec3 lightDirection) {
vec4 computeHazeColor(vec4 fragColor, vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePositionWS, vec3 lightDirectionWS) {
// Distance to fragment
float distance = length(eyeFragPos);
float distance = length(fragPositionES);
float eyeWorldHeight = eyePositionWS.y;
// Convert haze colour from uniform into a vec4
vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0);
// Directional light component is a function of the angle from the eye, between the fragment and the sun
vec3 eyeFragDir = normalize(worldFragPos);
float glareComponent = max(0.0, dot(eyeFragDir, -lightDirection));
float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));
vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);
// Use the haze colour for the glare colour, if blend is not enabled
vec4 blendedHazeColor;
if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {
// Directional light component is a function of the angle from the eye, between the fragment and the sun
vec3 fragToEyeDirWS = normalize(fragPositionWS - eyePositionWS);
float glareComponent = max(0.0, dot(fragToEyeDirWS, -lightDirectionWS));
float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));
vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);
blendedHazeColor = mix(hazeColor, glareColor, power);
} else {
blendedHazeColor = hazeColor;
@ -134,12 +135,12 @@ vec4 computeHazeColor(vec4 fragColor, vec3 eyeFragPos, vec3 worldFragPos, float
// Note that the haze base reference affects only the haze density as function of altitude
vec3 hazeDensityDistribution =
hazeParams.colorModulationFactor *
exp(-hazeParams.hazeHeightFactor * (worldEyeHeight - hazeParams.hazeBaseReference));
exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));
vec3 hazeIntegral = hazeDensityDistribution * distance;
vec3 hazeIntegral = hazeDensityDistribution * distance;
const float slopeThreshold = 0.01;
float deltaHeight = worldFragPos.y - worldEyeHeight;
float deltaHeight = fragPositionWS.y - eyeWorldHeight;
if (abs(deltaHeight) > slopeThreshold) {
float t = hazeParams.hazeHeightFactor * deltaHeight;
hazeIntegral *= (1.0 - exp (-t)) / t;
@ -162,12 +163,12 @@ vec4 computeHazeColor(vec4 fragColor, vec3 eyeFragPos, vec3 worldFragPos, float
// Note that the haze base reference affects only the haze density as function of altitude
float hazeDensityDistribution =
hazeParams.hazeRangeFactor *
exp(-hazeParams.hazeHeightFactor * (worldEyeHeight - hazeParams.hazeBaseReference));
exp(-hazeParams.hazeHeightFactor * (eyeWorldHeight - hazeParams.hazeBaseReference));
float hazeIntegral = hazeDensityDistribution * distance;
const float slopeThreshold = 0.01;
float deltaHeight = worldFragPos.y - worldEyeHeight;
float deltaHeight = fragPositionWS.y - eyeWorldHeight;
if (abs(deltaHeight) > slopeThreshold) {
float t = hazeParams.hazeHeightFactor * deltaHeight;
// Protect from wild values

View file

@ -111,15 +111,11 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie
}
<@endif@>
if (!(isObscuranceEnabled() > 0.0)) {
obscurance = 1.0;
}
obscurance = mix(1.0, obscurance, isObscuranceEnabled());
float lightEnergy = obscurance * getLightAmbientIntensity(ambient);
if (isAlbedoEnabled() > 0.0) {
diffuse *= albedo;
}
diffuse *= mix(vec3(1), albedo, isAlbedoEnabled());
lightEnergy *= isAmbientEnabled();
diffuse *= lightEnergy * isDiffuseEnabled();

View file

@ -13,11 +13,19 @@
<@func declareLightingModel()@>
#ifndef PRECISIONQ
#ifdef GL_ES
#define PRECISIONQ highp
#else
#define PRECISIONQ
#endif
#endif
struct LightingModel {
vec4 _UnlitEmissiveLightmapBackground;
vec4 _ScatteringDiffuseSpecularAlbedo;
vec4 _AmbientDirectionalPointSpot;
vec4 _ShowContourObscuranceWireframe;
PRECISIONQ vec4 _UnlitEmissiveLightmapBackground;
PRECISIONQ vec4 _ScatteringDiffuseSpecularAlbedo;
PRECISIONQ vec4 _AmbientDirectionalPointSpot;
PRECISIONQ vec4 _ShowContourObscuranceWireframe;
};
uniform lightingModelBuffer{
@ -256,9 +264,7 @@ void evalFragShading(out vec3 diffuse, out vec3 specular,
float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {
vec4 shading = evalPBRShading(metallic, fresnel, surface);
diffuse = vec3(shading.w);
if (isAlbedoEnabled() > 0.0) {
diffuse *= albedo;
}
diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());
specular = shading.xyz;
}

View file

@ -228,14 +228,14 @@ vec3 fetchLightmapMap(vec2 uv) {
}
<@endfunc@>
<@func evalMaterialNormalLOD(fragPos, fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@>
<@func evalMaterialNormalLOD(fragPosES, fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@>
{
vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz);
vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz);
vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);
// attenuate the normal map divergence from the mesh normal based on distance
// The attenuation range [20,100] meters from the eye is arbitrary for now
vec3 localNormal = mix(<$fetchedNormal$>, vec3(0.0, 1.0, 0.0), smoothstep(20.0, 100.0, (-<$fragPos$>).z));
vec3 localNormal = mix(<$fetchedNormal$>, vec3(0.0, 1.0, 0.0), smoothstep(20.0, 100.0, (-<$fragPosES$>).z));
<$normal$> = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);
}
<@endfunc@>

View file

@ -1,10 +1,8 @@
// glsl / C++ compatible source as interface for Shadows
#ifdef __cplusplus
# define MAT4 glm::mat4
# define VEC3 glm::vec3
#else
# define MAT4 mat4
# define VEC3 vec3
#endif
#define SHADOW_CASCADE_MAX_COUNT 4

View file

@ -311,9 +311,6 @@ void diffuseProfileGPU(gpu::TexturePointer& profileMap, RenderArgs* args) {
auto ps = subsurfaceScattering_makeProfile_frag::getShader();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
makePipeline = gpu::Pipeline::create(program, state);
@ -342,26 +339,27 @@ void diffuseScatterGPU(const gpu::TexturePointer& profileMap, gpu::TexturePointe
int height = lut->getHeight();
gpu::PipelinePointer makePipeline;
{
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
auto ps = subsurfaceScattering_makeLUT_frag::getShader();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
auto ps = subsurfaceScattering_makeLUT_frag::getShader();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringProfile"), 0));
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
makePipeline = gpu::Pipeline::create(program, state);
}
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
makePipeline = gpu::Pipeline::create(program, state);
auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("diffuseScatter"));
makeFramebuffer->setRenderBuffer(0, lut);
gpu::doInBatch("SubsurfaceScattering::diffuseScatterGPU", args->_context, [=](gpu::Batch& batch) {
batch.enableStereo(false);
batch.runLambda([program] (){
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringProfile"), 0));
gpu::Shader::makeProgram(*program, slotBindings);
});
batch.setViewportTransform(glm::ivec4(0, 0, width, height));
batch.setFramebuffer(makeFramebuffer);
@ -385,9 +383,6 @@ void computeSpecularBeckmannGPU(gpu::TexturePointer& beckmannMap, RenderArgs* ar
auto ps = subsurfaceScattering_makeSpecularBeckmann_frag::getShader();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
makePipeline = gpu::Pipeline::create(program, state);
@ -495,7 +490,6 @@ gpu::PipelinePointer DebugSubsurfaceScattering::getShowLUTPipeline() {
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());

View file

@ -167,7 +167,7 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con
outputs.edit3() = halfLinearDepthTexture;
outputs.edit4() = halfNormalTexture;
auto linearDepthPipeline = getLinearDepthPipeline();
auto linearDepthPipeline = getLinearDepthPipeline(renderContext);
auto downsamplePipeline = getDownsamplePipeline();
auto depthViewport = args->_viewport;
@ -209,17 +209,12 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con
}
const gpu::PipelinePointer& LinearDepthPass::getLinearDepthPipeline() {
const gpu::PipelinePointer& LinearDepthPass::getLinearDepthPipeline(const render::RenderContextPointer& renderContext) {
gpu::ShaderPointer program;
if (!_linearDepthPipeline) {
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
auto ps = surfaceGeometry_makeLinearDepth_frag::getShader();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DepthLinearPass_FrameTransformSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), DepthLinearPass_DepthMapSlot));
gpu::Shader::makeProgram(*program, slotBindings);
program = gpu::Shader::createProgram(vs, ps);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
@ -230,8 +225,18 @@ const gpu::PipelinePointer& LinearDepthPass::getLinearDepthPipeline() {
// Good to go add the brand new pipeline
_linearDepthPipeline = gpu::Pipeline::create(program, state);
gpu::doInBatch("LinearDepthPass::run", renderContext->args->_context, [program](gpu::Batch& batch) {
batch.runLambda([program]() {
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DepthLinearPass_FrameTransformSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), DepthLinearPass_DepthMapSlot));
gpu::Shader::makeProgram(*program, slotBindings);
});
});
}
return _linearDepthPipeline;
}
@ -455,7 +460,7 @@ void SurfaceGeometryPass::run(const render::RenderContextPointer& renderContext,
outputs.edit2() = curvatureFramebuffer;
outputs.edit3() = lowCurvatureFramebuffer;
auto curvaturePipeline = getCurvaturePipeline();
auto curvaturePipeline = getCurvaturePipeline(renderContext);
auto diffuseVPipeline = _diffusePass.getBlurVPipeline();
auto diffuseHPipeline = _diffusePass.getBlurHPipeline();
@ -536,21 +541,12 @@ void SurfaceGeometryPass::run(const render::RenderContextPointer& renderContext,
config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage());
}
const gpu::PipelinePointer& SurfaceGeometryPass::getCurvaturePipeline() {
const gpu::PipelinePointer& SurfaceGeometryPass::getCurvaturePipeline(const render::RenderContextPointer& renderContext) {
if (!_curvaturePipeline) {
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
auto ps = surfaceGeometry_makeCurvature_frag::getShader();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), SurfaceGeometryPass_FrameTransformSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("surfaceGeometryParamsBuffer"), SurfaceGeometryPass_ParamsSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), SurfaceGeometryPass_DepthMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), SurfaceGeometryPass_NormalMapSlot));
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
#ifdef USE_STENCIL_TEST
@ -559,6 +555,17 @@ const gpu::PipelinePointer& SurfaceGeometryPass::getCurvaturePipeline() {
#endif
// Good to go add the brand new pipeline
_curvaturePipeline = gpu::Pipeline::create(program, state);
gpu::doInBatch("SurfaceGeometryPass::CurvaturePipeline", renderContext->args->_context, [program](gpu::Batch& batch) {
batch.runLambda([program]() {
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), SurfaceGeometryPass_FrameTransformSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("surfaceGeometryParamsBuffer"), SurfaceGeometryPass_ParamsSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), SurfaceGeometryPass_DepthMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), SurfaceGeometryPass_NormalMapSlot));
gpu::Shader::makeProgram(*program, slotBindings);
});
});
}
return _curvaturePipeline;

View file

@ -81,7 +81,7 @@ private:
LinearDepthFramebufferPointer _linearDepthFramebuffer;
const gpu::PipelinePointer& getLinearDepthPipeline();
const gpu::PipelinePointer& getLinearDepthPipeline(const render::RenderContextPointer& renderContext);
gpu::PipelinePointer _linearDepthPipeline;
const gpu::PipelinePointer& getDownsamplePipeline();
@ -195,7 +195,7 @@ private:
SurfaceGeometryFramebufferPointer _surfaceGeometryFramebuffer;
const gpu::PipelinePointer& getCurvaturePipeline();
const gpu::PipelinePointer& getCurvaturePipeline(const render::RenderContextPointer& renderContext);
gpu::PipelinePointer _curvaturePipeline;

View file

@ -27,19 +27,24 @@ ToneMappingEffect::ToneMappingEffect() {
_parametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) &parameters));
}
void ToneMappingEffect::init() {
void ToneMappingEffect::init(RenderArgs* args) {
auto blitPS = toneMapping_frag::getShader();
auto blitVS = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
auto blitProgram = gpu::ShaderPointer(gpu::Shader::createProgram(blitVS, blitPS));
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("toneMappingParamsBuffer"), ToneMappingEffect_ParamsSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), ToneMappingEffect_LightingMapSlot));
gpu::Shader::makeProgram(*blitProgram, slotBindings);
auto blitState = std::make_shared<gpu::State>();
blitState->setColorWriteMask(true, true, true, true);
_blitLightBuffer = gpu::PipelinePointer(gpu::Pipeline::create(blitProgram, blitState));
gpu::doInBatch("ToneMappingEffect::toneMapping", args->_context, [blitProgram](gpu::Batch& batch) {
batch.runLambda([blitProgram]() {
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("toneMappingParamsBuffer"), ToneMappingEffect_ParamsSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), ToneMappingEffect_LightingMapSlot));
gpu::Shader::makeProgram(*blitProgram, slotBindings);
});
});
}
void ToneMappingEffect::setExposure(float exposure) {
@ -59,7 +64,7 @@ void ToneMappingEffect::setToneCurve(ToneCurve curve) {
void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& lightingBuffer, const gpu::FramebufferPointer& requestedDestinationFramebuffer) {
if (!_blitLightBuffer) {
init();
init(args);
}
auto destinationFramebuffer = requestedDestinationFramebuffer;

View file

@ -59,7 +59,7 @@ private:
typedef gpu::BufferView UniformBufferView;
gpu::BufferView _parametersBuffer;
void init();
void init(RenderArgs* args);
};
class ToneMappingConfig : public render::Job::Config {

View file

@ -23,11 +23,11 @@
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$>
in vec4 _position;
in vec4 _positionES;
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec3 _normal;
in vec3 _tangent;
in vec3 _normalWS;
in vec3 _tangentWS;
in vec3 _color;
layout(location = 0) out vec4 _fragColor0;
@ -56,9 +56,9 @@ void main(void) {
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
vec3 fresnel = getFresnelF0(metallic, albedo);
vec3 fragPosition = _position.xyz;
vec3 fragPosition = _positionES.xyz;
vec3 fragNormal;
<$evalMaterialNormal(normalTex, _normal, _tangent, fragNormal)$>
<$evalMaterialNormal(normalTex, _normalWS, _tangentWS, fragNormal)$>
TransformCamera cam = getTransformCamera();

View file

@ -0,0 +1,83 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// forward_simple.frag
// fragment shader
//
// Created by Andrzej Kapolka on 9/15/14.
// Copyright 2014 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 DefaultMaterials.slh@>
<@include ForwardGlobalLight.slh@>
<$declareEvalSkyboxGlobalColor()$>
// the interpolated normal
in vec3 _normal;
in vec3 _modelNormal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _position;
in vec4 _eyePosition;
layout(location = 0) out vec4 _fragColor0;
//PROCEDURAL_COMMON_BLOCK
#line 1001
//PROCEDURAL_BLOCK
#line 2030
void main(void) {
vec3 normal = normalize(_normal.xyz);
vec3 diffuse = _color.rgb;
vec3 specular = DEFAULT_SPECULAR;
float shininess = DEFAULT_SHININESS;
float emissiveAmount = 0.0;
#ifdef PROCEDURAL
#ifdef PROCEDURAL_V1
specular = getProceduralColor().rgb;
// Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline
//specular = pow(specular, vec3(2.2));
emissiveAmount = 1.0;
#else
emissiveAmount = getProceduralColors(diffuse, specular, shininess);
#endif
#endif
TransformCamera cam = getTransformCamera();
vec3 fragPosition = _eyePosition.xyz;
if (emissiveAmount > 0.0) {
_fragColor0 = vec4(evalSkyboxGlobalColor(
cam._viewInverse,
1.0,
DEFAULT_OCCLUSION,
fragPosition,
normal,
diffuse,
specular,
DEFAULT_METALLIC,
max(0.0, 1.0 - shininess / 128.0)),
1.0);
} else {
_fragColor0 = vec4(evalSkyboxGlobalColor(
cam._viewInverse,
1.0,
DEFAULT_OCCLUSION,
fragPosition,
normal,
diffuse,
DEFAULT_FRESNEL,
length(specular),
max(0.0, 1.0 - shininess / 128.0)),
1.0);
}
}

View file

@ -0,0 +1,51 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// forward_simple_textured.slf
// fragment shader
//
// Created by Clément Brisset on 5/29/15.
// Copyright 2014 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 DefaultMaterials.slh@>
<@include ForwardGlobalLight.slh@>
<$declareEvalSkyboxGlobalColor()$>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
// the albedo texture
uniform sampler2D originalTexture;
// the interpolated normal
in vec3 _normal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _eyePosition;
layout(location = 0) out vec4 _fragColor0;
void main(void) {
vec4 texel = texture(originalTexture, _texCoord0);
float colorAlpha = _color.a * texel.a;
TransformCamera cam = getTransformCamera();
vec3 fragPosition = _eyePosition.xyz;
_fragColor0 = vec4(evalSkyboxGlobalColor(
cam._viewInverse,
1.0,
DEFAULT_OCCLUSION,
fragPosition,
normalize(_normal),
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_METALLIC,
DEFAULT_ROUGHNESS),
1.0);
}

View file

@ -0,0 +1,52 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// forward_simple_textured_transparent.slf
// fragment shader
//
// Created by Clément Brisset on 5/29/15.
// Copyright 2014 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 DefaultMaterials.slh@>
<@include ForwardGlobalLight.slh@>
<$declareEvalGlobalLightingAlphaBlended()$>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
// the albedo texture
uniform sampler2D originalTexture;
// the interpolated normal
in vec3 _normal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _eyePosition;
layout(location = 0) out vec4 _fragColor0;
void main(void) {
vec4 texel = texture(originalTexture, _texCoord0);
float colorAlpha = _color.a * texel.a;
TransformCamera cam = getTransformCamera();
vec3 fragPosition = _eyePosition.xyz;
_fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(
cam._viewInverse,
1.0,
DEFAULT_OCCLUSION,
fragPosition,
normalize(_normal),
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_ROUGHNESS, colorAlpha),
colorAlpha);
}

View file

@ -0,0 +1,31 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// simple_textured_unlit.frag
// fragment shader
//
// Created by Clément Brisset on 5/29/15.
// Copyright 2014 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 LightingModel.slh@>
<@include gpu/Color.slh@>
layout(location = 0) out vec4 _fragColor0;
// the albedo texture
uniform sampler2D originalTexture;
in vec4 _color;
in vec2 _texCoord0;
void main(void) {
vec4 texel = texture(originalTexture, _texCoord0.st);
float colorAlpha = _color.a * texel.a;
_fragColor0 = vec4(_color.rgb * texel.rgb * isUnlitEnabled(), colorAlpha);
}

View file

@ -0,0 +1,84 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// forward_simple_transparent.frag
// fragment shader
//
// Created by Andrzej Kapolka on 9/15/14.
// Copyright 2014 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 DefaultMaterials.slh@>
<@include ForwardGlobalLight.slh@>
<$declareEvalGlobalLightingAlphaBlended()$>
// the interpolated normal
in vec3 _normal;
in vec3 _modelNormal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _eyePosition;
layout(location = 0) out vec4 _fragColor0;
//PROCEDURAL_COMMON_BLOCK
#line 1001
//PROCEDURAL_BLOCK
#line 2030
void main(void) {
vec3 normal = normalize(_normal.xyz);
vec3 diffuse = _color.rgb;
vec3 specular = DEFAULT_SPECULAR;
float shininess = DEFAULT_SHININESS;
float emissiveAmount = 0.0;
#ifdef PROCEDURAL
#ifdef PROCEDURAL_V1
specular = getProceduralColor().rgb;
// Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline
//specular = pow(specular, vec3(2.2));
emissiveAmount = 1.0;
#else
emissiveAmount = getProceduralColors(diffuse, specular, shininess);
#endif
#endif
TransformCamera cam = getTransformCamera();
vec3 fragPosition = _eyePosition.xyz;
if (emissiveAmount > 0.0) {
_fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(
cam._viewInverse,
1.0,
DEFAULT_OCCLUSION,
fragPosition,
normal,
specular,
DEFAULT_FRESNEL,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_ROUGHNESS, _color.a),
_color.a);
} else {
_fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(
cam._viewInverse,
1.0,
DEFAULT_OCCLUSION,
fragPosition,
normal,
diffuse,
DEFAULT_FRESNEL,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_ROUGHNESS, _color.a),
_color.a);
}
}

View file

@ -22,19 +22,19 @@
<@include Fade.slh@>
<$declareFadeFragment()$>
in vec4 _position;
in vec4 _positionES;
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec3 _normal;
in vec3 _normalWS;
in vec3 _color;
in vec4 _worldPosition;
in vec4 _positionWS;
void main(void) {
vec3 fadeEmissive;
FadeObjectParams fadeParams;
<$fetchFadeObjectParams(fadeParams)$>
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
applyFade(fadeParams, _positionWS.xyz, fadeEmissive);
Material mat = getMaterial();
BITFIELD matKey = getMaterialKey(mat);
@ -61,7 +61,7 @@ void main(void) {
float scattering = getMaterialScattering(mat);
packDeferredFragment(
normalize(_normal),
normalize(_normalWS),
opacity,
albedo,
roughness,

View file

@ -22,9 +22,9 @@
out float _alpha;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec4 _position;
out vec4 _worldPosition;
out vec3 _normal;
out vec4 _positionES;
out vec4 _positionWS;
out vec3 _normalWS;
out vec3 _color;
void main(void) {
@ -38,7 +38,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _positionWS)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$>
}

View file

@ -19,11 +19,11 @@
<@include MaterialTextures.slh@>
<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION, SCATTERING)$>
in vec4 _position;
in vec4 _positionES;
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec3 _normal;
in vec3 _tangent;
in vec3 _normalWS;
in vec3 _tangentWS;
in vec3 _color;
void main(void) {
@ -46,8 +46,8 @@ void main(void) {
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragNormal;
<$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
vec3 fragNormalWS;
<$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$>
float metallic = getMaterialMetallic(mat);
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
@ -56,7 +56,7 @@ void main(void) {
<$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>;
packDeferredFragment(
normalize(fragNormal.xyz),
normalize(fragNormalWS.xyz),
opacity,
albedo,
roughness,

View file

@ -20,11 +20,11 @@
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
out vec4 _position;
out vec4 _positionES;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec3 _normal;
out vec3 _tangent;
out vec3 _normalWS;
out vec3 _tangentWS;
out vec3 _color;
out float _alpha;
@ -40,7 +40,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$>
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$>
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangentWS)$>
}

View file

@ -2,7 +2,7 @@
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// model_normal_specular_map_fade.frag
// model_normal_map_fade.frag
// fragment shader
//
// Created by Olivier Prat on 06/05/17.
@ -22,20 +22,20 @@
<@include Fade.slh@>
<$declareFadeFragment()$>
in vec4 _position;
in vec4 _positionES;
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec3 _normal;
in vec3 _tangent;
in vec3 _normalWS;
in vec3 _tangentWS;
in vec3 _color;
in vec4 _worldPosition;
in vec4 _positionWS;
void main(void) {
vec3 fadeEmissive;
FadeObjectParams fadeParams;
<$fetchFadeObjectParams(fadeParams)$>
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
applyFade(fadeParams, _positionWS.xyz, fadeEmissive);
Material mat = getMaterial();
BITFIELD matKey = getMaterialKey(mat);
@ -56,8 +56,8 @@ void main(void) {
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragNormal;
<$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
vec3 fragNormalWS;
<$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$>
float metallic = getMaterialMetallic(mat);
<$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>;
@ -65,12 +65,12 @@ void main(void) {
float scattering = getMaterialScattering(mat);
packDeferredFragment(
normalize(fragNormal.xyz),
normalize(fragNormalWS.xyz),
opacity,
albedo,
roughness,
metallic,
emissive+fadeEmissive,
emissive + fadeEmissive,
occlusionTex,
scattering);
}

View file

@ -20,12 +20,12 @@
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
out vec4 _position;
out vec4 _worldPosition;
out vec4 _positionES;
out vec4 _positionWS;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec3 _normal;
out vec3 _tangent;
out vec3 _normalWS;
out vec3 _tangentWS;
out vec3 _color;
out float _alpha;
@ -41,8 +41,8 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$>
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _positionWS)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$>
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangentWS)$>
}

View file

@ -28,9 +28,9 @@
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec4 _position;
in vec4 _worldPosition;
in vec3 _normal;
in vec4 _positionES;
in vec4 _positionWS;
in vec3 _normalWS;
in vec3 _color;
in float _alpha;
@ -58,33 +58,35 @@ void main(void) {
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragPosition = _position.xyz;
vec3 fragPositionES = _positionES.xyz;
vec3 fragPositionWS = _positionWS.xyz;
// Lighting is done in world space
vec3 fragNormal = normalize(_normal);
vec3 fragNormalWS = normalize(_normalWS);
TransformCamera cam = getTransformCamera();
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;
vec3 fragToEyeDirWS = normalize(fragToEyeWS);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);
vec4 localLighting = vec4(0.0);
<$fetchClusterInfo(_worldPosition)$>;
<$fetchClusterInfo(_positionWS)$>;
if (hasLocalLights(numLights, clusterPos, dims)) {
localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface,
localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,
metallic, fresnel, albedo, 0.0,
vec4(0), vec4(0), opacity);
}
_fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(
_fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(
cam._viewInverse,
1.0,
occlusionTex,
fragPosition,
fragPositionES,
fragPositionWS,
albedo,
fresnel,
metallic,
emissive,
surface, opacity, localLighting.rgb),
surfaceWS, opacity, localLighting.rgb),
opacity);
}

View file

@ -22,9 +22,9 @@
out float _alpha;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec4 _position;
out vec4 _worldPosition;
out vec3 _normal;
out vec4 _positionES;
out vec4 _positionWS;
out vec3 _normalWS;
out vec3 _color;
void main(void) {
@ -38,7 +38,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _positionWS)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$>
}

View file

@ -24,11 +24,11 @@
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec4 _position;
in vec3 _normal;
in vec4 _positionES;
in vec4 _positionWS;
in vec3 _normalWS;
in vec3 _color;
in float _alpha;
in vec4 _worldPosition;
out vec4 _fragColor;
@ -37,7 +37,7 @@ void main(void) {
FadeObjectParams fadeParams;
<$fetchFadeObjectParams(fadeParams)$>
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
applyFade(fadeParams, _positionWS.xyz, fadeEmissive);
Material mat = getMaterial();
BITFIELD matKey = getMaterialKey(mat);
@ -60,20 +60,21 @@ void main(void) {
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragPosition = _position.xyz;
vec3 fragPositionES = _positionES.xyz;
vec3 fragPositionWS = _positionWS.xyz;
// Lighting is done in world space
vec3 fragNormal = normalize(_normal);
vec3 fragNormalWS = normalize(_normalWS);
TransformCamera cam = getTransformCamera();
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;
vec3 fragToEyeDirWS = normalize(fragToEyeWS);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);
vec4 localLighting = vec4(0.0);
<$fetchClusterInfo(_worldPosition)$>;
<$fetchClusterInfo(_positionWS)$>;
if (hasLocalLights(numLights, clusterPos, dims)) {
localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface,
localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,
metallic, fresnel, albedo, 0.0,
vec4(0), vec4(0), opacity);
}
@ -82,11 +83,12 @@ void main(void) {
cam._viewInverse,
1.0,
occlusionTex,
fragPosition,
fragPositionES,
fragPositionWS,
albedo,
fresnel,
metallic,
emissive+fadeEmissive,
surface, opacity, localLighting.rgb),
emissive + fadeEmissive,
surfaceWS, opacity, localLighting.rgb),
opacity);
}

View file

@ -28,10 +28,10 @@
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec4 _position;
in vec4 _worldPosition;
in vec3 _normal;
in vec3 _tangent;
in vec4 _positionES;
in vec4 _positionWS;
in vec3 _normalWS;
in vec3 _tangentWS;
in vec3 _color;
in float _alpha;
@ -59,20 +59,22 @@ void main(void) {
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragPosition = _position.xyz;
vec3 fragNormal;
<$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
vec3 fragPositionES = _positionES.xyz;
vec3 fragPositionWS = _positionWS.xyz;
// Lighting is done in world space
vec3 fragNormalWS;
<$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$>
TransformCamera cam = getTransformCamera();
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;
vec3 fragToEyeDirWS = normalize(fragToEyeWS);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);
vec4 localLighting = vec4(0.0);
<$fetchClusterInfo(_worldPosition)$>;
<$fetchClusterInfo(_positionWS)$>;
if (hasLocalLights(numLights, clusterPos, dims)) {
localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface,
localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,
metallic, fresnel, albedo, 0.0,
vec4(0), vec4(0), opacity);
}
@ -81,11 +83,12 @@ void main(void) {
cam._viewInverse,
1.0,
occlusionTex,
fragPosition,
fragPositionES,
fragPositionWS,
albedo,
fresnel,
metallic,
emissive,
surface, opacity, localLighting.rgb),
surfaceWS, opacity, localLighting.rgb),
opacity);
}

View file

@ -22,10 +22,10 @@
out float _alpha;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec4 _position;
out vec4 _worldPosition;
out vec3 _normal;
out vec3 _tangent;
out vec4 _positionES;
out vec4 _positionWS;
out vec3 _normalWS;
out vec3 _tangentWS;
out vec3 _color;
void main(void) {
@ -39,8 +39,8 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$>
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _positionWS)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$>
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangentWS)$>
}

View file

@ -31,12 +31,12 @@
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec4 _position;
in vec3 _normal;
in vec3 _tangent;
in vec4 _positionES;
in vec3 _normalWS;
in vec3 _tangentWS;
in vec3 _color;
in float _alpha;
in vec4 _worldPosition;
in vec4 _positionWS;
out vec4 _fragColor;
@ -45,7 +45,7 @@ void main(void) {
FadeObjectParams fadeParams;
<$fetchFadeObjectParams(fadeParams)$>
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
applyFade(fadeParams, _positionWS.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);
@ -68,21 +68,22 @@ void main(void) {
vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragPosition = _position.xyz;
vec3 fragPositionES = _positionES.xyz;
vec3 fragPositionWS = _positionWS.xyz;
// Lighting is done in world space
vec3 fragNormal;
<$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$>
vec3 fragNormalWS;
<$evalMaterialNormalLOD(_positionES, normalTex, _normalWS, _tangentWS, fragNormalWS)$>
TransformCamera cam = getTransformCamera();
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
vec3 fragToEyeWS = cam._viewInverse[3].xyz - fragPositionWS;
vec3 fragToEyeDirWS = normalize(fragToEyeWS);
SurfaceData surfaceWS = initSurfaceData(roughness, fragNormalWS, fragToEyeDirWS);
vec4 localLighting = vec4(0.0);
<$fetchClusterInfo(_worldPosition)$>;
<$fetchClusterInfo(_positionWS)$>;
if (hasLocalLights(numLights, clusterPos, dims)) {
localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface,
localLighting = evalLocalLighting(cluster, numLights, fragPositionWS, surfaceWS,
metallic, fresnel, albedo, 0.0,
vec4(0), vec4(0), opacity);
}
@ -91,11 +92,12 @@ void main(void) {
cam._viewInverse,
1.0,
occlusionTex,
fragPosition,
fragPositionES,
fragPositionWS,
albedo,
fresnel,
metallic,
emissive+fadeEmissive,
surface, opacity, localLighting.rgb),
emissive + fadeEmissive,
surfaceWS, opacity, localLighting.rgb),
opacity);
}

View file

@ -24,7 +24,7 @@
in vec2 _texCoord0;
in vec3 _color;
in float _alpha;
in vec4 _worldPosition;
in vec4 _positionWS;
out vec4 _fragColor;
@ -33,7 +33,7 @@ void main(void) {
FadeObjectParams fadeParams;
<$fetchFadeObjectParams(fadeParams)$>
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
applyFade(fadeParams, _positionWS.xyz, fadeEmissive);
Material mat = getMaterial();
BITFIELD matKey = getMaterialKey(mat);

View file

@ -23,17 +23,17 @@
<$declareMaterialTextures(ALBEDO)$>
in vec2 _texCoord0;
in vec3 _normal;
in vec3 _normalWS;
in vec3 _color;
in float _alpha;
in vec4 _worldPosition;
in vec4 _positionWS;
void main(void) {
vec3 fadeEmissive;
FadeObjectParams fadeParams;
<$fetchFadeObjectParams(fadeParams)$>
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
applyFade(fadeParams, _positionWS.xyz, fadeEmissive);
Material mat = getMaterial();
BITFIELD matKey = getMaterialKey(mat);
@ -48,7 +48,7 @@ void main(void) {
albedo *= _color;
albedo += fadeEmissive;
packDeferredFragmentUnlit(
normalize(_normal),
normalize(_normalWS),
opacity,
albedo * isUnlitEnabled());
}

View file

@ -13,7 +13,6 @@
//
<@include DeferredBufferWrite.slh@>
<@include graphics/Material.slh@>
// the interpolated normal
in vec3 _normal;
@ -29,9 +28,8 @@ in vec4 _position;
#line 2030
void main(void) {
Material material = getMaterial();
vec3 normal = normalize(_normal.xyz);
vec3 diffuse = _color.rgb;
vec3 normal = normalize(_normal.xyz);
vec3 diffuse = _color.rgb;
vec3 specular = DEFAULT_SPECULAR;
float shininess = DEFAULT_SHININESS;
float emissiveAmount = 0.0;
@ -43,49 +41,30 @@ void main(void) {
// Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline
//specular = pow(specular, vec3(2.2));
emissiveAmount = 1.0;
#else
#else
emissiveAmount = getProceduralColors(diffuse, specular, shininess);
#endif
#endif
const float ALPHA_THRESHOLD = 0.999;
if (_color.a < ALPHA_THRESHOLD) {
if (emissiveAmount > 0.0) {
packDeferredFragmentTranslucent(
normal,
_color.a,
specular,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
} else {
packDeferredFragmentTranslucent(
normal,
_color.a,
diffuse,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
}
if (emissiveAmount > 0.0) {
packDeferredFragmentLightmap(
normal,
1.0,
diffuse,
max(0.0, 1.0 - shininess / 128.0),
DEFAULT_METALLIC,
specular,
vec3(clamp(emissiveAmount, 0.0, 1.0)));
} else {
if (emissiveAmount > 0.0) {
packDeferredFragmentLightmap(
normal,
1.0,
diffuse,
max(0.0, 1.0 - shininess / 128.0),
DEFAULT_METALLIC,
specular,
vec3(clamp(emissiveAmount, 0.0, 1.0)));
} else {
packDeferredFragment(
normal,
1.0,
diffuse,
max(0.0, 1.0 - shininess / 128.0),
length(specular),
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
}
packDeferredFragment(
normal,
1.0,
diffuse,
max(0.0, 1.0 - shininess / 128.0),
length(specular),
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
}
}

View file

@ -23,6 +23,7 @@ out vec3 _modelNormal;
out vec4 _color;
out vec2 _texCoord0;
out vec4 _position;
out vec4 _eyePosition;
void main(void) {
_color = color_sRGBAToLinear(inColor);
@ -33,6 +34,6 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _eyePosition, gl_Position)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
}

View file

@ -13,7 +13,6 @@
//
<@include DeferredBufferWrite.slh@>
<@include graphics/Material.slh@>
<@include Fade.slh@>
<$declareFadeFragmentInstanced()$>
@ -39,7 +38,6 @@ void main(void) {
<$fetchFadeObjectParamsInstanced(fadeParams)$>
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
Material material = getMaterial();
vec3 normal = normalize(_normal.xyz);
vec3 diffuse = _color.rgb;
vec3 specular = DEFAULT_SPECULAR;

View file

@ -26,6 +26,7 @@ out vec3 _modelNormal;
out vec4 _color;
out vec2 _texCoord0;
out vec4 _position;
out vec4 _eyePosition;
out vec4 _worldPosition;
void main(void) {
@ -37,7 +38,7 @@ void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _eyePosition, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
<$passThroughFadeObjectParams()$>

View file

@ -12,9 +12,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include gpu/Color.slh@>
<@include DeferredBufferWrite.slh@>
<@include graphics/Material.slh@>
// the albedo texture
uniform sampler2D originalTexture;
@ -26,29 +24,14 @@ in vec2 _texCoord0;
void main(void) {
vec4 texel = texture(originalTexture, _texCoord0);
float colorAlpha = _color.a;
if (_color.a <= 0.0) {
texel = color_sRGBAToLinear(texel);
colorAlpha = -_color.a;
}
const float ALPHA_THRESHOLD = 0.999;
if (colorAlpha * texel.a < ALPHA_THRESHOLD) {
packDeferredFragmentTranslucent(
normalize(_normal),
colorAlpha * texel.a,
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
} else {
packDeferredFragment(
normalize(_normal),
1.0,
_color.rgb * texel.rgb,
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
}
packDeferredFragment(
normalize(_normal),
1.0,
_color.rgb * texel.rgb,
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
}

View file

@ -14,7 +14,6 @@
<@include gpu/Color.slh@>
<@include DeferredBufferWrite.slh@>
<@include graphics/Material.slh@>
<@include Fade.slh@>

View file

@ -0,0 +1,65 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// simple_transparent.frag
// fragment shader
//
// Created by Andrzej Kapolka on 9/15/14.
// Copyright 2014 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 DeferredBufferWrite.slh@>
// the interpolated normal
in vec3 _normal;
in vec3 _modelNormal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _position;
//PROCEDURAL_COMMON_BLOCK
#line 1001
//PROCEDURAL_BLOCK
#line 2030
void main(void) {
vec3 normal = normalize(_normal.xyz);
vec3 diffuse = _color.rgb;
vec3 specular = DEFAULT_SPECULAR;
float shininess = DEFAULT_SHININESS;
float emissiveAmount = 0.0;
#ifdef PROCEDURAL
#ifdef PROCEDURAL_V1
specular = getProceduralColor().rgb;
// Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline
//specular = pow(specular, vec3(2.2));
emissiveAmount = 1.0;
#else
emissiveAmount = getProceduralColors(diffuse, specular, shininess);
#endif
#endif
if (emissiveAmount > 0.0) {
packDeferredFragmentTranslucent(
normal,
_color.a,
specular,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
} else {
packDeferredFragmentTranslucent(
normal,
_color.a,
diffuse,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
}
}

Some files were not shown because too many files have changed in this diff Show more