Compare commits

...

5 Commits

Author SHA1 Message Date
67b8f999c1 Bump tp version 0.1.0 and cleanup
Signed-off-by: Justin Georgi <justin.georgi@gmail.com>
2024-11-12 08:20:00 -07:00
81576e283b Merge pull request 'Add Gltf metadata' (#38) from bas-add-metadata into main
Reviewed-on: #38
2024-11-12 03:57:31 +00:00
d559e786d1 Display metadata on file page
Signed-off-by: Justin Georgi <justin.georgi@gmail.com>
2024-11-11 20:55:07 -07:00
9e1f89b92b Enable metadata versioning
Signed-off-by: Justin Georgi <justin.georgi@gmail.com>
2024-11-11 20:35:08 -07:00
0c5c1c61d3 Collect metadata from glb file
Signed-off-by: Justin Georgi <justin.georgi@gmail.com>
2024-11-10 19:52:08 -07:00
6 changed files with 117 additions and 5 deletions

View File

@@ -3,7 +3,7 @@
"author": "Justin Georgi", "author": "Justin Georgi",
"url": "https://gitea.azgeorgis.net/jgeorgi/mwModelViewer", "url": "https://gitea.azgeorgis.net/jgeorgi/mwModelViewer",
"description": "This extension allows .glb and .gltf files to be added, displayed, and annotated in MediaWiki", "description": "This extension allows .glb and .gltf files to be added, displayed, and annotated in MediaWiki",
"version": "0.0.7", "version": "0.1.0",
"license-name": "MIT", "license-name": "MIT",
"type": "media", "type": "media",
"manifest_version": 2, "manifest_version": 2,
@@ -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"

7
i18n/en.json Normal file
View File

@@ -0,0 +1,7 @@
{
"exif-glmv-meshes": "Number of meshes",
"exif-glmv-textures": "Number of textures",
"exif-glmv-version": "GLTF version",
"exif-glmv-generator": "Model generator",
"exif-glmv-metadata": "GLMV metadata version"
}

View File

@@ -2,9 +2,12 @@
namespace MediaWiki\Extension\GlModelViewer; namespace MediaWiki\Extension\GlModelViewer;
use ImageHandler; use ImageHandler;
use BitmapMetadataHandler;
use Html; use Html;
class GlModelHandler extends ImageHandler { class GlModelHandler extends ImageHandler {
private const GLMV_VERSION = '0.2';
/** /**
* 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 +123,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 +134,97 @@ class GlModelHandler extends ImageHandler {
]; ];
} }
/**
* 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(
'glmv-meshes' => count($glMeta['meshes']),
'glmv-textures' => count($glMeta['textures'])
);
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-metadata'] = self::GLMV_VERSION;
$metaHandler = new BitmapMetadataHandler;
$metaHandler->addMetadata($newMeta,'native');
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 required 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::GLMV_VERSION) {
return self::METADATA_BAD;
}
return self::METADATA_GOOD;
}
/**
* Get an array structure that the UI will format this into a table where the visible
* fields are always visible, and the collapsed fields are optionally visible.
*
* The function should return false if there is no metadata to display.
*
* @param File $image
* @param bool|IContextSource $context Context to use (optional)
* @return bool|array
*/
public function formatMetadata( $image, $context = false ) {
$glmvMetadata = $image->getMetadataArray();
if (!count( $glmvMetadata ) ) {
return false;
} else {
return $this->formatMetadataHelper( $glmvMetadata, $context );
}
}
/** /**
* Small helper function to display information on the browser console * Small helper function to display information on the browser console
* *

View File

@@ -42,9 +42,10 @@ 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) {
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',
array( array(

View File

@@ -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);

View File

@@ -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()}
} }