Skip to content

Commit

Permalink
Merge pull request #591 from KhronosGroup/validation-warning-handling…
Browse files Browse the repository at this point in the history
…-draft

Draft for handling ignored validation warnings
  • Loading branch information
UX3D-haertl authored Feb 12, 2025
2 parents b809c22 + 0255dbf commit 8e3e13f
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 25 deletions.
7 changes: 6 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ <h2 class="title is-spaced">Display</h2>
<b-tab-item label="Validator" icon="video" class="tabItemScrollable tab-item">
<template #header>
<div @click="collapseActiveTab($event, 2)"
v-bind:style="[tabsHidden === false && activeTab === 2 ? {'height': '100%'} : {}]">
v-bind:style="[tabContent === false && activeTab === 2 ? {'height': '100%'} : {}]">
<!-- to get colored icons use: https://stackoverflow.com/a/43916743 -->
<div style="max-width:fit-content; margin-left: auto; margin-right: auto;" v-html="getValidationCounter()"></div>
<span
Expand All @@ -325,6 +325,11 @@ <h2 class="title is-spaced" v-bind:data="validationReport">glTF Validator</h2>
<p>Number of warnings: {{validationReport?.issues?.numWarnings ?? 0}}</p>
<p>Number of infos: {{validationReport?.issues?.numInfos ?? 0}}</p>
</div>

<div v-show='validationReportDescription?.message !== undefined && validationReportDescription?.message !== ""'>
<p style="margin-top: 10px; margin-bottom: 10px; font-size:smaller;">{{validationReportDescription?.message}}</p>
</div>

<button class="button is-rounded" style="width: fit-content; flex-shrink: 0; margin-bottom: 12px;" v-on:click="copyToClipboard(JSON.stringify(validationReport, undefined, 4))">Copy</button>
<button class="button is-rounded" style="width: fit-content; flex-shrink: 0;" v-on:click="downloadJSON(validationReport?.uri?.substring(validationReport.uri.lastIndexOf('/') + 1) + '.report.json', validationReport)">Download</button>
<span style="margin-top: 5px;">Powered by <a href="https://github.com/KhronosGroup/glTF-Validator" target="_blank" rel="noopener noreferrer">glTF-Validator</a></span>
Expand Down
46 changes: 45 additions & 1 deletion src/logic/uimodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,53 @@ class UIModel
);
}

/**
* Creates a descriptive summary of the given validation report.
*
* If there are no issues, messages, or warnings in the given
* report, then an empty object is returned.
*
* Otherwise, the result will be an object that contains
* `numIgnoredWarnings:number` that counts the number of warnings
* that are ignored by the sample viewer, and a `message:string`
* that explains why these warnings are ignored.
*
* @param {any} validationReport The glTF validator validation report
* @returns The description
*/
createValidationReportDescription(validationReport) {
const issues = validationReport?.issues;
const messages = issues?.messages;
const numWarnings = issues?.numWarnings ?? 0;
if (!issues || !messages || numWarnings === 0) {
return {};
}
let numIgnoredWarnings = 0;
for (const message of messages) {
if (message.code === "MESH_PRIMITIVE_GENERATED_TANGENT_SPACE") {
numIgnoredWarnings++;
}
}
if (numIgnoredWarnings === 0) {
return {};
}
return {
numIgnoredWarnings: numIgnoredWarnings,
message: `The validation generated ${issues.numWarnings} warnings. `
+`${numIgnoredWarnings} of these warnings have been about missing `
+`tangent space information. Omitting the tangent space information `
+`may be a conscious decision by the designer, but it may limit `
+`the portability of the asset. The glTF-Sample-Viewer generates `
+`tangents using the default MikkTSpace algorithm in this case.`
};
}

updateValidationReport(validationReportObservable)
{
validationReportObservable.subscribe(data => this.app.validationReport = data);
validationReportObservable.subscribe(data => {
this.app.validationReport = data;
this.app.validationReportDescription = this.createValidationReportDescription(data);
});
}

disabledAnimations(disabledAnimationsObservable)
Expand Down
11 changes: 2 additions & 9 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ import {

import {validateBytes} from "gltf-validator";

const ignoredIssues = [
// This sample renderer supports tangent space generation.
"MESH_PRIMITIVE_GENERATED_TANGENT_SPACE"
];

export default async () => {
const canvas = document.getElementById("canvas");
const context = canvas.getContext("webgl2", {
Expand Down Expand Up @@ -75,8 +70,7 @@ export default async () => {
const buffer = await response.arrayBuffer();
return await validateBytes(new Uint8Array(buffer), {
externalResourceFunction: externalRefFunction,
uri: model.mainFile,
ignoredIssues
uri: model.mainFile
});
} else if (Array.isArray(model.mainFile)) {
const externalRefFunction = (uri) => {
Expand Down Expand Up @@ -106,8 +100,7 @@ export default async () => {
return await validateBytes(new Uint8Array(buffer),
{
externalResourceFunction: externalRefFunction,
uri: model.mainFile[0],
ignoredIssues
uri: model.mainFile[0]
});
}
} catch (error) {
Expand Down
75 changes: 61 additions & 14 deletions src/ui/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const appCreated = createApp({
disabledAnimations: [],

validationReport: {},
validationReportDescription: {},

ibl: true,
iblIntensity: 0.0,
Expand Down Expand Up @@ -222,25 +223,71 @@ const appCreated = createApp({
element.click();
document.body.removeChild(element);
},
getValidationCounter: function(){
let number = 0;

/**
* Creates a div string summarizing the given issues.
*
* If the given issues are empty or do not contain any errors,
* warnings, or infos, then the empty string is returned.
*
* Otherwise, the div contains the number of errors/warnings/infos
* with an appropriate background color. When all warnings of
* the given report are ignored, then this will only be a
* small "info" div. Clicking on that will expand the details
* about the ignored warnings.
*
* @param {any} issues The `issues` property that is part of
* the validation report of the glTF Validator
* @returns The div string
*/
getValidationInfoDiv : function(issues) {
if (!issues) {
return "";
}
let info = "";
let color = "white";
if (this.validationReport?.issues?.numErrors > 0) {
number = this.validationReport?.issues?.numErrors;
if (issues.numErrors > 0) {
info = `${issues.numErrors}`;
color = "red";
} else if (this.validationReport?.issues?.numWarnings > 0) {
number = this.validationReport?.issues?.numWarnings;
color = "yellow";
} else if (this.validationReport?.issues?.numInfos > 0) {
number = this.validationReport?.issues?.numInfos;
} else if (issues.numWarnings > 0) {
const allIgnored = issues.numWarnings ===
this.validationReportDescription?.numIgnoredWarnings;
if (allIgnored) {
info = "i";
color = "lightBlue";
} else {
info = `${issues.numWarnings}`;
color = "yellow";
}
} else if (issues.numInfos > 0) {
info = `${issues.numInfos}`;
}
if (number !== 0) {
return `<div style="display:flex;color:black; font-weight:bold; background-color:${color}; border-radius:50%; width:fit-content; min-width:2rem; align-items:center;aspect-ratio:1/1;justify-content:center;">${number}</div>`;
if (info.length > 3) {
info = "999+";
}
if (this.tabsHidden === false && this.activeTab === 2) {
return `<img src="assets/ui/Capture 50X50.svg" width="50px" height="100%">`;
if (info === "") {
return "";
}
const padding = this.isMobile ? "right:-3px;top:-18px;" : "right:-18px;top:-18px;";
const infoDiv =
`<div style="display:flex;color:black; position:absolute; ${padding} ` +
`font-size:80%; font-weight:bold; background-color:${color}; border-radius:50%; width:fit-content; ` +
`min-width:2rem; align-items:center;aspect-ratio:1/1;justify-content:center;">${info}</div>`;
return infoDiv;
},

getValidationCounter: function(){
const infoDiv = this.getValidationInfoDiv(this.validationReport?.issues);
if (this.tabContentHidden === false && this.activeTab === 2) {
return `<div style="position:relative; width:50px; height:100%">`
+ `<img src="assets/ui/Capture 50X50.svg" width="50px" height="100%">`
+ infoDiv
+ `</div>`;
}
return '<img src="assets/ui/Capture 30X30.svg" width="30px">';
return `<div style="position:relative; width:50px; height:100%">`
+ `<img src="assets/ui/Capture 30X30.svg" width="30px">`
+ infoDiv
+ `</div>`;
},
setAnimationState: function(value)
{
Expand Down

0 comments on commit 8e3e13f

Please sign in to comment.