Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Please sign up or log in to edit the wiki.

Module:Dimensions: Difference between revisions

From the Star Citizen Wiki, the fidelity™ encyclopedia
Content deleted Content added
No edit summary
Undo revision 272552 by Alistair3149 (talk)
Tag: Undo
 
(25 intermediate revisions by the same user not shown)
Line 1: Line 1:
--- Module:Dimensions
--- Used to display an isometric cube showing the dimensions of an object
---
--- TODO: Add i18n
--- TODO: Brush up isometric functions for more generic use cases
--- TODO: Don't hardcode --container-size, it should be based on the current container
require( 'strict' )
require( 'strict' )


Line 4: Line 10:


local i18n = require( 'Module:i18n' ):new()
local i18n = require( 'Module:i18n' ):new()
local lang = mw.getContentLanguage()


--- Wrapper function for Module:i18n.translate
--- Wrapper function for Module:i18n.translate
Line 14: Line 21:




--- Get the text HTML object
---
--- @param data table
--- @return mw.html
local function getTextHTML( data )
local function getTextHTML( data )
if not data.label and not data.value then return end
if not data.label and not data.value then return end
local html = mw.html.create( 'div' )
local html = mw.html.create( 'div' )
:addClass( 'template-dimensions-box-text' )
:addClass( 'template-dimensions-box-text' )


if data.variant then
if data.variant then
html:addClass( 'template-dimensions-box-text-' .. data.variant )
html:addClass( 'template-dimensions-box-text-' .. data.variant )
end
end


if data.label then
if data.label then
html:tag( 'div' )
html:tag( 'div' )
:addClass( 'template-dimensions-label' )
:addClass( 'template-dimensions-label' )
:wikitext( data.label )
:wikitext( data.label )
:done()
:done()
end
end


if data.value then
if data.value then
html:tag( 'div' )
html:tag( 'div' )
:addClass( 'template-dimensions-data' )
:addClass( 'template-dimensions-data' )
:wikitext( data.value )
:wikitext( data.value )
:done()
:done()
end
end


return html
return html
end
end




--- Create a human-sized object for reference
local function getObjectHTML( data )
--- FIXME: Figure out how to do a box properly, haven't done trigonometry in ages...
local html = mw.html.create( 'div' )
---
:addClass( 'template-dimensions-object' )
--- @param type string|nil
:css( {
--- @return mw.html|nil
[ '--object-length' ] = data.length,
local function getReferenceObjectHTML( type )
[ '--object-width' ] = data.width,
if not type then return end
[ '--object-height' ] = data.height,
} )


local isometric = html:tag( 'div' )
local refData = {}
if type == 'human' then
:addClass( 'template-dimensions-isometric' )
refData.length = 0.2;
:css( {
refData.width = 0.4;
[ 'transform-style' ] = 'preserve-3d',
refData.height = 1.8;
[ 'grid-template-areas' ] = "'layer'"
end
} )
if refData == {} then return end


local html = mw.html.create( 'div' )
-- Top layer
:addClass( 'template-dimensions-reference template-dimensions-box-faces' )
isometric:tag( 'div' )
:attr( 'title', string.format( '%s for reference', type ) )
:addClass( 'template-dimensions-layer template-dimensions-layer-top' )
:css( 'transform-style', 'preserve-3d' )
:css( 'transform-style', 'preserve-3d' )
:tag( 'div' )
:tag( 'div' )
:addClass( 'template-dimensions-box-faces' )
:addClass( 'template-dimensions-box-face template-dimensions-box-face-top' )
:done()
:css( 'transform-style', 'preserve-3d' )
:tag( 'div' )
:tag( 'div' )
:addClass( 'template-dimensions-box-face template-dimensions-box-face-top' )
:addClass( 'template-dimensions-box-face template-dimensions-box-face-front' )
:done()
:done()
:tag( 'div' )
--:tag( 'div' )
:addClass( 'template-dimensions-box-face template-dimensions-box-face-front' )
--:addClass( 'template-dimensions-box-face template-dimensions-box-face-right' )
:done()
--:done()
:tag( 'div' )
:addClass( 'template-dimensions-box-face template-dimensions-box-face-right' )
:done()
:done()
:node( getTextHTML( {
label = 'Mass',
value = data.mass,
variant = 'fill'
} ) )
:done()


for k, v in pairs( refData ) do
-- Mid layer
local cssVar = string.format( '--reference-%s', k )
isometric:tag( 'div' )
html:css( cssVar, tostring( v ) )
:addClass( 'template-dimensions-layer template-dimensions-layer-mid' )
end
:css( 'transform-style', 'preserve-3d' )
:node( getTextHTML( {
label = 'Height',
value = data.height,
variant = 'y'
} ) )
:done()


return html
-- Bottom layer
end
isometric:tag( 'div' )

:addClass( 'template-dimensions-layer template-dimensions-layer-bottom' )

:tag( 'div' )
--- Get the object HTML object
:addClass( 'template-dimensions-reference template-dimensions-box-faces' )
---
:css( 'transform-style', 'preserve-3d' )
--- @param data table
:tag( 'div' )
--- @return mw.html
:addClass( 'template-dimensions-box-face template-dimensions-box-face-top' )
local function getObjectHTML( data )
:done()
:tag( 'div' )
local html = mw.html.create( 'div' )
:addClass( 'template-dimensions-box-face template-dimensions-box-face-front' )
:addClass( 'template-dimensions' )
:css( {
:done()
[ '--object-length' ] = data.length.number,
:tag( 'div' )
[ '--object-width' ] = data.width.number,
:addClass( 'template-dimensions-box-face template-dimensions-box-face-right' )
[ '--object-height' ] = data.height.number,
:done()
} )
:done()

:node( getTextHTML( {
local isometric = html:tag( 'div' )
label = 'Length',
:addClass( 'template-dimensions-isometric' )
value = data.length,
:css( {
variant = 'z'
[ 'transform-style' ] = 'preserve-3d',
} ) )
[ 'grid-template-areas' ] = "'layer'"
:node( getTextHTML( {
} )
label = 'Width',

value = data.width,
-- Top layer
variant = 'x'
isometric:tag( 'div' )
} ) )
:addClass( 'template-dimensions-layer template-dimensions-layer-top' )
:done()
:css( 'transform-style', 'preserve-3d' )
:tag( 'div' )
:addClass( 'template-dimensions-box-faces' )
:css( 'transform-style', 'preserve-3d' )
:tag( 'div' )
:addClass( 'template-dimensions-box-face template-dimensions-box-face-top' )
:done()
:tag( 'div' )
:addClass( 'template-dimensions-box-face template-dimensions-box-face-front' )
:done()
:tag( 'div' )
:addClass( 'template-dimensions-box-face template-dimensions-box-face-right' )
:done()
:done()
:node( getTextHTML( {
label = data.height.label,
value = data.height.value,
variant = 'y'
} ) )
:node( getTextHTML( {
label = data.mass.label,
value = data.mass.value,
variant = 'z'
} ) )
:done()

-- Bottom layer
isometric:tag( 'div' )
:addClass( 'template-dimensions-layer template-dimensions-layer-bottom' )
:css( 'transform-style', 'preserve-3d' )
:node( getReferenceObjectHTML( data.referenceType ) )
:node( getTextHTML( {
label = data.length.label,
value = data.length.value,
variant = 'z'
} ) )
:node( getTextHTML( {
label = data.width.label,
value = data.width.value,
variant = 'x'
} ) )
:done()


return html
return html
end
end




--- Return string containing the number with separator and unit
local function getOutputHTML( data )
---
local html = mw.html.create( 'div' )
--- @param arg string|number|nil
:addClass( 'template-dimensions' )
--- @param unit string
:node( getObjectHTML( data) )
--- @param altArg string|number|nil
return html
--- @return string|nil
local function getDimensionsValue( arg, unit, altArg )
if not arg or not unit then return end
local num = tonumber( arg )
if not num then return end

local value = string.format( '%s %s', lang:formatNum( num ), unit )
if not altArg or arg == altArg then
return value
end

local altValue = getDimensionsValue( altArg, unit )
if not altValue then
return value
end
return string.format(
'%s <span class="template-dimensions-data-subtle">(%s)</span>',
value,
altValue
)
end
end




--- Format arguments into data used by HTML functions
---
--- @param args table
--- @return table|nil
local function getDimensionsData( args )
local function getDimensionsData( args )
local lengthNum = tonumber( args.length )
return {
length = tonumber( args.length ),
local widthNum = tonumber( args.width )
width = tonumber( args.width ),
local heightNum = tonumber( args.height )

height = tonumber( args.height ),
if not lengthNum or not widthNum or not heightNum then return end
mass = tonumber( args.mass )
-- TODO: Make this cleaner by using another table to map the units?
}
local lengthValue = getDimensionsValue( args.length, 'm', args.lengthAlt )
local widthValue = getDimensionsValue( args.width, 'm', args.widthAlt )
local heightValue = getDimensionsValue( args.height, 'm', args.heightAlt )

-- TODO: Perhaps this can be done in a loop
local data = {
length = {
number = lengthNum,
label = t( 'label_Length' ),
value = lengthValue
},
width = {
number = widthNum,
label = t( 'label_Width' ),
value = widthValue
},
height = {
number = heightNum,
label = t( 'label_Height' ),
value = heightValue
},
mass = {
label = t( 'label_Mass' ),
value = getDimensionsValue( args.mass, 'kg' ) or '-'
},
referenceType = args.referenceType
}

return data
end
end


function p.main( frame )
local args = require( 'Module:Arguments' ).getArgs( frame )
local data = getDimensionsData( args )


--- Lua entry point
return tostring( getOutputHTML( data ) ) .. frame:extensionTag{
---
name = 'templatestyles', args = { src = 'Module:Dimensions/styles.css' }
--- @param args table
}
--- @param frame table
--- @return string|nil
function p._main( args, frame )
if not args.length or not args.width or not args.height then return end
-- Frame object can be missing if function is invoked from Lua
frame = frame or mw.getCurrentFrame()

local data = getDimensionsData( args )
if not data then return end
return frame:extensionTag {
name = 'templatestyles', args = { src = 'Module:Dimensions/styles.css' }
} .. tostring( getObjectHTML( data ) )
end

--- Wikitext entry point
---
--- @return string|nil
function p.main( frame )
local args = require( 'Module:Arguments' ).getArgs( frame )
return p._main( args, frame )
end
end



Latest revision as of 05:18, 26 February 2025

Module documentation[view][edit][history][purge]
This documentation is transcluded from Module:Dimensions/doc. Changes can be proposed in the talk page.
Function list
L 18 — t
L 27 — getTextHTML
L 59 — getReferenceObjectHTML
L 97 — getObjectHTML
L 169 — getDimensionsValue
L 195 — getDimensionsData
L 239 — p._main
L 254 — p.main

--- Module:Dimensions
--- Used to display an isometric cube showing the dimensions of an object
---
--- TODO: Add i18n
--- TODO: Brush up isometric functions for more generic use cases
--- TODO: Don't hardcode --container-size, it should be based on the current container
require( 'strict' )

local p = {}

local i18n = require( 'Module:i18n' ):new()
local lang = mw.getContentLanguage()

--- Wrapper function for Module:i18n.translate
---
--- @param key string The translation key
--- @return string If the key was not found, the key is returned
local function t( key )
	return i18n:translate( key )
end


--- Get the text HTML object
---
--- @param data table
--- @return mw.html
local function getTextHTML( data )
	if not data.label and not data.value then return end
	local html = mw.html.create( 'div' )
		:addClass( 'template-dimensions-box-text' )

	if data.variant then
		html:addClass( 'template-dimensions-box-text-' .. data.variant )
	end

	if data.label then
		html:tag( 'div' )
			:addClass( 'template-dimensions-label' )
			:wikitext( data.label )
			:done()
	end

	if data.value then
		html:tag( 'div' )
			:addClass( 'template-dimensions-data' )
			:wikitext( data.value )
			:done()
	end

	return html
end


--- Create a human-sized object for reference
--- FIXME: Figure out how to do a box properly, haven't done trigonometry in ages...
---
--- @param type string|nil
--- @return mw.html|nil
local function getReferenceObjectHTML( type )
	if not type then return end

	local refData = {}
	if type == 'human' then
		refData.length = 0.2;
		refData.width = 0.4;
		refData.height = 1.8;
	end
	if refData == {} then return end

	local html = mw.html.create( 'div' )
		:addClass( 'template-dimensions-reference template-dimensions-box-faces' )
		:attr( 'title', string.format( '%s for reference', type ) )
		:css( 'transform-style', 'preserve-3d' )
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-top' )
		:done()
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-front' )
		:done()
		--:tag( 'div' )
		--:addClass( 'template-dimensions-box-face template-dimensions-box-face-right' )
		--:done()

	for k, v in pairs( refData ) do
		local cssVar = string.format( '--reference-%s', k )
		html:css( cssVar, tostring( v ) )
	end

	return html
end


--- Get the object HTML object
---
--- @param data table
--- @return mw.html
local function getObjectHTML( data )
	local html = mw.html.create( 'div' )
		:addClass( 'template-dimensions' )
		:css( {
			[ '--object-length' ] = data.length.number,
			[ '--object-width' ] = data.width.number,
			[ '--object-height' ] = data.height.number,
		} )

	local isometric = html:tag( 'div' )
		:addClass( 'template-dimensions-isometric' )
		:css( {
			[ 'transform-style' ] = 'preserve-3d',
			[ 'grid-template-areas' ] = "'layer'"
		} )

	-- Top layer
	isometric:tag( 'div' )
		:addClass( 'template-dimensions-layer template-dimensions-layer-top' )
		:css( 'transform-style', 'preserve-3d' )
		:tag( 'div' )
		:addClass( 'template-dimensions-box-faces' )
		:css( 'transform-style', 'preserve-3d' )
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-top' )
		:done()
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-front' )
		:done()
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-right' )
		:done()
		:done()
		:node( getTextHTML( {
			label = data.height.label,
			value = data.height.value,
			variant = 'y'
		} ) )
		:node( getTextHTML( {
			label = data.mass.label,
			value = data.mass.value,
			variant = 'z'
		} ) )
		:done()

	-- Bottom layer
	isometric:tag( 'div' )
		:addClass( 'template-dimensions-layer template-dimensions-layer-bottom' )
		:css( 'transform-style', 'preserve-3d' )
		:node( getReferenceObjectHTML( data.referenceType ) )
		:node( getTextHTML( {
			label = data.length.label,
			value = data.length.value,
			variant = 'z'
		} ) )
		:node( getTextHTML( {
			label = data.width.label,
			value = data.width.value,
			variant = 'x'
		} ) )
		:done()

	return html
end


--- Return string containing the number with separator and unit
---
--- @param arg string|number|nil
--- @param unit string
--- @param altArg string|number|nil
--- @return string|nil
local function getDimensionsValue( arg, unit, altArg )
	if not arg or not unit then return end
	local num = tonumber( arg )
	if not num then return end

	local value = string.format( '%s %s', lang:formatNum( num ), unit )
	if not altArg or arg == altArg then
		return value
	end

	local altValue = getDimensionsValue( altArg, unit )
	if not altValue then
		return value
	end
	return string.format(
		'%s <span class="template-dimensions-data-subtle">(%s)</span>',
		value,
		altValue
	)
end


--- Format arguments into data used by HTML functions
---
--- @param args table
--- @return table|nil
local function getDimensionsData( args )
	local lengthNum = tonumber( args.length )
	local widthNum = tonumber( args.width )
	local heightNum = tonumber( args.height )

	if not lengthNum or not widthNum or not heightNum then return end
	-- TODO: Make this cleaner by using another table to map the units?
	local lengthValue = getDimensionsValue( args.length, 'm', args.lengthAlt )
	local widthValue = getDimensionsValue( args.width, 'm', args.widthAlt )
	local heightValue = getDimensionsValue( args.height, 'm', args.heightAlt )

	-- TODO: Perhaps this can be done in a loop
	local data = {
		length = {
			number = lengthNum,
			label = t( 'label_Length' ),
			value = lengthValue
		},
		width = {
			number = widthNum,
			label = t( 'label_Width' ),
			value = widthValue
		},
		height = {
			number = heightNum,
			label = t( 'label_Height' ),
			value = heightValue
		},
		mass = {
			label = t( 'label_Mass' ),
			value = getDimensionsValue( args.mass, 'kg' ) or '-'
		},
		referenceType = args.referenceType
	}

	return data
end


--- Lua entry point
---
--- @param args table
--- @param frame table
--- @return string|nil
function p._main( args, frame )
	if not args.length or not args.width or not args.height then return end
	-- Frame object can be missing if function is invoked from Lua
	frame = frame or mw.getCurrentFrame()

	local data = getDimensionsData( args )
	if not data then return end
	return frame:extensionTag {
		name = 'templatestyles', args = { src = 'Module:Dimensions/styles.css' }
	} .. tostring( getObjectHTML( data ) )
end

--- Wikitext entry point
---
--- @return string|nil
function p.main( frame )
	local args = require( 'Module:Arguments' ).getArgs( frame )
	return p._main( args, frame )
end

return p