Collect metadata from glb file
Signed-off-by: Justin Georgi <justin.georgi@gmail.com>
This commit is contained in:
@@ -23,6 +23,11 @@
|
|||||||
"ExtensionMessagesFiles": {
|
"ExtensionMessagesFiles": {
|
||||||
"GlModelHandlerMagic": "GlModelHandler.i18n.magic.php"
|
"GlModelHandlerMagic": "GlModelHandler.i18n.magic.php"
|
||||||
},
|
},
|
||||||
|
"MessagesDirs": {
|
||||||
|
"GlModelViewer": [
|
||||||
|
"i18n"
|
||||||
|
]
|
||||||
|
},
|
||||||
"ResourceFileModulePaths": {
|
"ResourceFileModulePaths": {
|
||||||
"localBasePath": "modules",
|
"localBasePath": "modules",
|
||||||
"remoteExtPath": "GlModelViewer/modules"
|
"remoteExtPath": "GlModelViewer/modules"
|
||||||
@@ -37,12 +42,16 @@
|
|||||||
],
|
],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"mediawiki.util",
|
"mediawiki.util",
|
||||||
|
"mediawiki.storage",
|
||||||
"mediawiki.api"
|
"mediawiki.api"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ext.glmv.upl": {
|
"ext.glmv.upl": {
|
||||||
"styles": [
|
"styles": [
|
||||||
"glmv-upl.css"
|
"glmv-upl.css"
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
"mediawiki.storage"
|
||||||
],
|
],
|
||||||
"packageFiles": [
|
"packageFiles": [
|
||||||
"glmv-upl.js"
|
"glmv-upl.js"
|
||||||
|
|||||||
6
i18n/en.json
Normal file
6
i18n/en.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"exif-glmv-meshes": "Number of meshes",
|
||||||
|
"exif-glmv-textures": "Number of textures",
|
||||||
|
"exif-glmv-version": "GLTF version",
|
||||||
|
"exif-glmv-generator": "Model generator"
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ use ImageHandler;
|
|||||||
use Html;
|
use Html;
|
||||||
|
|
||||||
class GlModelHandler extends ImageHandler {
|
class GlModelHandler extends ImageHandler {
|
||||||
|
private const glmvVersion = '0.1';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model cannot be displayed directly in a browser but can be rendered.
|
* Model cannot be displayed directly in a browser but can be rendered.
|
||||||
*
|
*
|
||||||
@@ -120,6 +122,7 @@ class GlModelHandler extends ImageHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an associative array mapping magic word IDs to parameter names.
|
* Get an associative array mapping magic word IDs to parameter names.
|
||||||
|
*
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
public function getParamMap() {
|
public function getParamMap() {
|
||||||
@@ -130,6 +133,97 @@ class GlModelHandler extends ImageHandler {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used to generate an array element for each metadata value. That array is then used to generate the table of metadata values on the image page.
|
||||||
|
*
|
||||||
|
* @param array &$array An array containing elements for each type of visibility and each of those elements being an array of metadata items. This function adds a value to that array.
|
||||||
|
* @param string $visibility ('visible' or 'collapsed') if this value is hidden by default.
|
||||||
|
* @param string $type Type of metadata tag (currently always 'exif')
|
||||||
|
* @param string $id The name of the metadata tag (like 'artist' for example). its name in the table displayed is the message "$type-$id" (Ex exif-artist ).
|
||||||
|
* @param string $value Thingy goes into a wikitext table; it used to be escaped but that was incompatible with previous practise of customized display with wikitext formatting via messages such as 'exif-model-value'. So the escaping is taken back out, but generally this seems a confusing interface.
|
||||||
|
* @param bool | string $param Value to pass to the message for the name of the field as $1. Currently this parameter doesn't seem to ever be used.
|
||||||
|
*/
|
||||||
|
//public static function addMeta (&$array, $visibility, $type, $id, $value, $param = false ) {
|
||||||
|
// $array[$visibility][] = [
|
||||||
|
// 'id' => "$type-$id",
|
||||||
|
// 'name' => $name,
|
||||||
|
// 'value' => $value
|
||||||
|
// ];
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get image size information and metadata array.
|
||||||
|
*
|
||||||
|
* @param MediaHandlerState $state An object for
|
||||||
|
* saving process-local state. This is normally a
|
||||||
|
* File object which will be passed back to other
|
||||||
|
* MediaHandler methods like pageCount(), if they
|
||||||
|
* are called in the same request. The handler
|
||||||
|
* can use this object to save its state.
|
||||||
|
* @param string $path The filename
|
||||||
|
*
|
||||||
|
* @return array|null Null to fall back to
|
||||||
|
* getImageSize(), or an array with width, height,
|
||||||
|
* bits, and metadata keys. All keys are optional.
|
||||||
|
*/
|
||||||
|
public function getSizeAndMetadata ($state, $path) {
|
||||||
|
|
||||||
|
$gltf = fopen($path, 'r');
|
||||||
|
fseek($gltf,12);
|
||||||
|
$glMetaLength = unpack("Iint", fread($gltf, 4));
|
||||||
|
fseek($gltf,20);
|
||||||
|
$glMeta = json_decode(fread($gltf,$glMetaLength['int']),true);
|
||||||
|
fclose($gltf);
|
||||||
|
$newMeta = array(
|
||||||
|
'Type' => $glType
|
||||||
|
);
|
||||||
|
foreach($glMeta['asset'] as $key => $value) {
|
||||||
|
switch ($key) {
|
||||||
|
case 'author':
|
||||||
|
$newMeta['Author'] = $value;
|
||||||
|
break;
|
||||||
|
case 'copyright':
|
||||||
|
$newMeta['Copyright'] = $value;
|
||||||
|
break;
|
||||||
|
case 'generator':
|
||||||
|
$newMeta['glmv-generator'] = $value;
|
||||||
|
break;
|
||||||
|
case 'version':
|
||||||
|
$newMeta['glmv-version'] = $value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$newMeta['glmv-meshes'] = count($glMeta['meshes']);
|
||||||
|
$newMeta['glmv-textures'] = count($glMeta['textures']);
|
||||||
|
$newMeta['glmv-metadata'] = self::glmvVersion;
|
||||||
|
return array(
|
||||||
|
'width' => 600,
|
||||||
|
'height' => 800,
|
||||||
|
'metadata' => $newMeta
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the metadata is valid for this handler.
|
||||||
|
*
|
||||||
|
* If it returns MediaHandler::METADATA_BAD (or false), Image will reload the metadata from the file and update the database.
|
||||||
|
* MediaHandler::METADATA_GOOD for if the metadata is a-ok,
|
||||||
|
* MediaHandler::METADATA_COMPATIBLE if metadata is old but backwards compatible (which may or may not trigger a metadata reload).
|
||||||
|
*
|
||||||
|
* TODO: This version is for testing/dev only. Better checking will be requried in the future
|
||||||
|
* @param File $image
|
||||||
|
* @return bool|int
|
||||||
|
*/
|
||||||
|
public function isFileMetadataValid ($image) {
|
||||||
|
$meta = $image->getMetadataItems('glmv-metadata');
|
||||||
|
if (!isset($meta['glmv-metadata']) || $meta['glmv-metadata'] != self::glmvVersion) {
|
||||||
|
return self::METADATA_BAD;
|
||||||
|
}
|
||||||
|
return self::METADATA_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Small helper function to display information on the browser console
|
* Small helper function to display information on the browser console
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -42,8 +42,16 @@ class GlModelHooks {
|
|||||||
* @param OutputPage $out compiled page html and manipulation methods
|
* @param OutputPage $out compiled page html and manipulation methods
|
||||||
*/
|
*/
|
||||||
public static function onBeforePageDisplay($out) {
|
public static function onBeforePageDisplay($out) {
|
||||||
|
$file = MediaWikiServices::getInstance()->getRepoGroup()->findFile($out->getTitle());
|
||||||
|
if ($file) {
|
||||||
|
echo '<script>';
|
||||||
|
self::console_log('Metadata:');
|
||||||
|
self::console_log($file->getMetadata());
|
||||||
|
echo '</script>';
|
||||||
|
}
|
||||||
preg_match('/(<model-viewer src="\S*?\.(glb|gltf"))/',$out->getHTML(),$findGltf);
|
preg_match('/(<model-viewer src="\S*?\.(glb|gltf"))/',$out->getHTML(),$findGltf);
|
||||||
if ($findGltf[0]) {
|
if ($findGltf[0]) {
|
||||||
|
|
||||||
$out->addHeadItems(
|
$out->addHeadItems(
|
||||||
Html::rawElement(
|
Html::rawElement(
|
||||||
'script',
|
'script',
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ class GlModelTransformOutput extends MediaTransformOutput {
|
|||||||
//Add important additional attributes and render model-viewer with hotspots
|
//Add important additional attributes and render model-viewer with hotspots
|
||||||
$attrModelView = array_merge(['src' => $srcUrl, 'class' => 'mv-model', 'interpolation-decay' => '100', 'interaction-prompt' => 'none'], $attrModelView);
|
$attrModelView = array_merge(['src' => $srcUrl, 'class' => 'mv-model', 'interpolation-decay' => '100', 'interaction-prompt' => 'none'], $attrModelView);
|
||||||
$attrModelView['style'] = 'width: 100%; height: 100%;';
|
$attrModelView['style'] = 'width: 100%; height: 100%;';
|
||||||
$attrModelView['onload'] = 'modelLoaded()';
|
$attrModelView['onload'] = 'modelLoaded(event)';
|
||||||
$hotspotHtml = (isset($hotspots)) ? implode($hotspots) : '';
|
$hotspotHtml = (isset($hotspots)) ? implode($hotspots) : '';
|
||||||
|
|
||||||
$elModel = Html::rawElement('model-viewer', $attrModelView, $hotspotHtml);
|
$elModel = Html::rawElement('model-viewer', $attrModelView, $hotspotHtml);
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ checkForGltf = function (e) {
|
|||||||
const mvPreview = document.createElement('model-viewer')
|
const mvPreview = document.createElement('model-viewer')
|
||||||
mvPreview.style['width'] = '180px'
|
mvPreview.style['width'] = '180px'
|
||||||
mvPreview.style['height'] = '180px'
|
mvPreview.style['height'] = '180px'
|
||||||
|
mvPreview.addEventListener('load',(e) => {
|
||||||
|
mw.storage.session.set( 'mw_glbMeta', JSON.stringify($(e.target.originalGltfJson.asset)))
|
||||||
|
},
|
||||||
|
{once: true})
|
||||||
|
|
||||||
const dThumbCap = document.createElement('div')
|
const dThumbCap = document.createElement('div')
|
||||||
dThumbCap.classList.add('thumbcaption')
|
dThumbCap.classList.add('thumbcaption')
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ let currentSet = 'default'
|
|||||||
* Disables hiding of various child items
|
* Disables hiding of various child items
|
||||||
* once model has loaded
|
* once model has loaded
|
||||||
*/
|
*/
|
||||||
modelLoaded = function() {
|
modelLoaded = function(e) {
|
||||||
$('.awaiting-model').css('display', 'flex').removeClass('awaiting-model')
|
$('.awaiting-model').css('display', 'flex').removeClass('awaiting-model')
|
||||||
if (typeof enableMenu != 'undefined') {enableMenu()}
|
if (typeof enableMenu != 'undefined') {enableMenu()}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user