Difference between revisions of "Module:3D viewer advanced"

From Team Fortress Wiki
Jump to: navigation, search
m (startframe fix)
m (+ tfc and tfc_half classes)
 
(45 intermediate revisions by 4 users not shown)
Line 3: Line 3:
 
local utils = require('Module:Utils')
 
local utils = require('Module:Utils')
 
local HtmlBuilder = require('Module:HtmlBuilder')
 
local HtmlBuilder = require('Module:HtmlBuilder')
 +
local frame = nil
  
function p.viewer(frame)
+
-- Expands the template Common string for a given value. Note that some common string values include an additional parameter, here called opt_arg.
     local args = utils.get_args(frame)
+
function common_string(arg, opt_arg)
     local startframe = utils.processArg(args['startframe'], '')
+
    return frame:expandTemplate{title='Common string', args={arg, opt_arg}}
     local image = utils.processArg(args['image'], '')
+
end
     local image_0 = utils.processArg(args['image-0'], '')
+
 
     local fallback = utils.processArg(args['fallback'], '')
+
-- Returns ' (text)', with correct parenthesis characters in Chinese.
    local basepagename = mw.title.getCurrentTitle().baseText
+
function paren(text)
 +
    if if_lang == '/zh_hans' or if_lang == '/zh-hant' then
 +
        return ' (' .. text .. ')'
 +
    else
 +
        return ' (' .. text .. ')'
 +
    end
 +
end
 +
 
 +
function p.viewer(f)
 +
     local args = utils.get_args(f)
 +
     local startframe = utils.processArg(args['startframe'])
 +
     local image = utils.processArg(args['image'])
 +
     local image_0 = utils.processArg(args['image-0'])
 +
     local fallback = utils.processArg(args['fallback'])
 
     local startframe_class
 
     local startframe_class
 
     if startframe ~= '' then
 
     if startframe ~= '' then
 
         startframe_class = mw.text.trim(startframe)
 
         startframe_class = mw.text.trim(startframe)
 
     else
 
     else
         startframe_class = utils.expandWikitext('{{File:' .. image_0 or (image or basepagename) .. '|startframe}}')
+
         startframe_class = utils.expandWikitext('{{File:' .. (image_0 or image) .. '|startframe}}')
 
     end
 
     end
 
     local output_view = HtmlBuilder.create('div')
 
     local output_view = HtmlBuilder.create('div')
Line 22: Line 36:
 
         .wikitext(fallback)
 
         .wikitext(fallback)
  
    local span_3d_url = output_view
+
     for i = 0,10 do
        .tag('span')
 
            .addClass('viewer-3d-url-0')
 
            .wikitext(utils.expandWikitext('{{trim|{{File:' .. (image_0 or image) .. '}}}}'))
 
 
 
    local span_3d_map = output_view
 
        .tag('span')
 
            .addClass('viewer-3d-map-0')
 
            .wikitext(utils.expandWikitext('{{trim|{{File:' .. (image_0 or image) .. '}}}}'))
 
 
 
     for i = 1,10 do
 
 
         local image_n = utils.processArg(args['image-' .. i], '')
 
         local image_n = utils.processArg(args['image-' .. i], '')
         if image_n then
+
         if image_n ~= '' then
 
             span_image_url_n = output_view
 
             span_image_url_n = output_view
 
                 .tag('span')
 
                 .tag('span')
 
                 .addClass('viewer-3d-url-' .. i)
 
                 .addClass('viewer-3d-url-' .. i)
                 .wikitext(utils.expandWikitext('{{trim|{{File:' .. (image_n or image) .. '}}}}'))
+
                 .wikitext(utils.expandWikitext('{{File:' .. image_n .. '|url}}'))
           
+
 
 
             span_image_map_n = output_view
 
             span_image_map_n = output_view
 
                 .tag('span')
 
                 .tag('span')
 
                 .addClass('viewer-3d-map-' .. i)
 
                 .addClass('viewer-3d-map-' .. i)
                 .wikitext(utils.expandWikitext('{{trim|{{File:' .. image_n .. '}}}}'))
+
                 .wikitext(utils.expandWikitext('{{File:' .. image_n .. '|map}}'))
 
         end
 
         end
 
     end
 
     end
Line 54: Line 58:
 
         .tag('div')
 
         .tag('div')
 
         .attr('id', 'switch-to-2d')
 
         .attr('id', 'switch-to-2d')
 +
 +
    return tostring(output_view)
 +
end
 +
 +
function p.viewer_new(f)
 +
    frame = f
 +
    local args = utils.get_args(f)
 +
   
 +
    -- button classes mapping
 +
    local button_classes = {
 +
        red            = 'view-selector-red',
 +
        blu            = 'view-selector-blu',
 +
        red_half        = 'view-selector-red-',
 +
        blu_half        = 'view-selector-blu-',
 +
        red_full        = 'view-selector-red-full',
 +
        blu_full        = 'view-selector-blu-full',
 +
        tfc            = 'view-selector-tfc-full',
 +
        tfc_half        = 'view-selector-tfc-',
 +
        tfc_red_half    = 'view-selector-tfcred-',
 +
        tfc_blu_half    = 'view-selector-tfcblu-',
 +
        tfc_yellow_half = 'view-selector-tfcyellow-',
 +
        tfc_green_half  = 'view-selector-tfcgreen-',
 +
        australium_half = 'view-selector-australium-',
 +
        australium_full = 'view-selector-australium-full',
 +
        australium      = 'view-selector-australium-full',
 +
        default_half    = 'view-selector-default-',
 +
        default_full    = 'view-selector-default-full',
 +
        default        = 'view-selector-default-full'
 +
    }
 +
 +
    -- create output container
 +
    local output_view = HtmlBuilder.create('div')
 +
        .addClass('viewer-3d-container')
 +
   
 +
    -- create container for viewer
 +
    local startimage = utils.processArg(args['3d-image-1'])
 +
    -- if first button is colored then add RED to filename
 +
    if utils.processArg(args['3d-button-1']) == 'colored_pair' then
 +
    startimage = startimage .. ' RED'
 +
    end
 +
    local startframe = args['3d-startframe'] or utils.expandWikitext('{{File:' .. startimage .. ' 3D.jpg|startframe}}')
 +
    local viewer_container = output_view
 +
        .tag('div')
 +
        .addClass('viewer-3d')
 +
        .addClass('startframe-' .. startframe)
 +
 +
    -- add 3D and 2D selectors
 +
    local viewer_3d_frame = viewer_container
 +
        .tag('div')
 +
        .addClass('viewer-3d-frame')
 +
 +
    local switch_to_2d = viewer_container
 +
        .tag('div')
 +
        .attr('id', 'switch-to-2d')
 +
 +
    -- create container for model selector buttons
 +
    local buttons_container = output_view
 +
        .tag('ul')
 +
        .addClass('buttons-container-3d')
 +
 +
    -- create container for 2D image
 +
    local image_2d
 +
    if args['image'] then
 +
        image_2d = args['image']
 +
    elseif args['team-colors'] == 'yes' then
 +
        image_2d = args['skin-image-red'] or mw.title.getCurrentTitle().baseText .. ' RED.png'
 +
    else
 +
        image_2d = mw.title.getCurrentTitle().baseText .. '.png'
 +
    end
 +
    local viewer_2d_frame = output_view
 +
        .tag('div')
 +
        .wikitext(utils.expandWikitext('{{2D viewer|' .. image_2d .. '|' .. (args['imagewidth'] or '250px') .. '}}'))
 +
 +
    -- row button counter for half width buttons
 +
    local current_row_count = 0
 +
    local colored = false
 +
    local i = 1
 +
    while utils.processArg(args['3d-image-' .. i]) ~= '' or colored do
 +
    -- the "or colored" ensures that if the last image pair is team-colored, it will still be processed.
 +
        local image_postfix = ' 3D.jpg'
 +
        local viewname_postfix = ''
 +
        if colored then
 +
            -- if we are the second half of a team-colored image, use the details from the first half.
 +
            i = i - 1
 +
        end
 +
        local image_n = utils.processArg(args['3d-image-' .. i])
 +
        local button_n = utils.processArg(args['3d-button-' .. i])
 +
        local button_class = button_classes[button_n]
 +
        local viewname_n = utils.processArg(args['3d-viewname-' .. i])
 +
        if colored then
 +
            i = i + 1
 +
            image_postfix = ' BLU 3D.jpg'
 +
            viewname_postfix = paren(common_string('BLU'))
 +
            button_class = 'view-selector-blu'
 +
            colored = false
 +
        elseif not colored and button_n == 'colored_pair' then
 +
            image_postfix = ' RED 3D.jpg'
 +
            viewname_postfix = paren(common_string('RED'))
 +
            button_class = 'view-selector-red'
 +
            colored = true
 +
        end
 +
        if image_n ~= '' then
 +
            span_image_url_n = viewer_container
 +
                .tag('span')
 +
                .addClass('viewer-3d-url-' .. (i-1))
 +
                .wikitext(utils.expandWikitext('{{File:' .. image_n .. image_postfix .. '|url}}'))
 +
 +
            span_image_map_n = viewer_container
 +
                .tag('span')
 +
                .addClass('viewer-3d-map-' .. (i-1))
 +
                .wikitext(utils.expandWikitext('{{File:' .. image_n .. image_postfix .. '|map}}'))
 +
 +
            -- if there is only one 3d image then don't attach selector
 +
            if i == 1 and args['3d-image-2'] == nil and args['3d-image-3'] == nil then
 +
            break
 +
            end
 +
            -- add selector button for this model (changing class if it's a half-width button)
 +
            if button_n:sub(-5) == '_half' then
 +
                if current_row_count == 0 then
 +
                    button_class = button_class .. 'left'
 +
                    current_row_count = 1
 +
                else
 +
                    button_class = button_class .. 'right'
 +
                    current_row_count = 0
 +
                end
 +
            end
 +
            -- selector is 0-indexed
 +
            button_class = button_class .. ' selector-' .. (i-1)
 +
           
 +
            li_button_n = buttons_container
 +
                .tag('li')
 +
                .addClass(button_class)
 +
                .wikitext(utils.expandWikitext('[[:File:' .. image_n .. image_postfix .. '|' .. viewname_n .. viewname_postfix .. ']]'))
 +
        end
 +
 +
        i = i + 1
 +
    end
  
 
     return tostring(output_view)
 
     return tostring(output_view)

Latest revision as of 19:12, 7 March 2025

Usage

Wikitext Output
{{#invoke:3D viewer advanced|viewer_new
  | 3d-image-1 = Sandvich
  | 3d-image-2 = Sandvich Alt
  | 3d-viewname-1 = Default
  | 3d-viewname-2 = Nommed
  | 3d-button-1 = default_half
  | 3d-button-2 = default_half
}}
https://wiki.teamfortress.com/w/images/f/fa/Sandvich_3D.jpg?1701675677.9229810243,200,280,3,0,257,54,143,267,56,286,261,58,428,259,48,571,268,53,713,263,50,860,261,36,1009,270,48,1151,266,42,1302,262,28,1448,272,47,1581,268,36,1730,264,24,1871,273,49,1989,270,33,2127,265,26,2272,275,55,2390,271,34,2526,266,32,2664,275,64,2773,271,36,2907,266,45,3030,275,53,3146,271,39,3275,266,28,3417,276,35,3541,269,42,3666,266,16,3818,276,21,3948,269,28,4083,265,7,4236,275,11,4375,269,16,4513,263,4,4660,273,5,4801,267,7,4938,261,1,5082,272,2,5223,265,3,5365,259,1,5524,269,0,5673,264,0,5828,257,6,5992,267,3,6141,261,0,6302,255,13,6463,265,8,6606,260,4,6767,254,25,6915,263,19,7043,258,13,7195,252,32,7330,262,30,7439,257,29,7573,252,28,7703,261,26,7813,255,28,7945,252,28,8086,261,26,8220,255,28,8349,253,30,8503,261,31,8649,255,30,8789,253,28,8953,262,40,9101,255,31,9252,254,32,9416,263,47,9563,256,37,9718,256,40,9875,265,50,10022,258,47https://wiki.teamfortress.com/w/images/c/ca/Sandvich_Alt_3D.jpg?1701675821.43084310230,200,280,3,0,257,54,143,266,56,286,260,58,428,259,48,571,268,53,713,263,50,860,261,36,1009,270,48,1151,265,42,1301,262,28,1447,272,46,1580,268,36,1728,263,24,1868,273,49,1986,270,33,2124,264,26,2269,274,55,2386,271,34,2522,265,32,2660,275,64,2769,271,36,2903,266,45,3026,275,52,3142,270,39,3271,266,28,3413,275,35,3537,269,42,3662,266,16,3814,275,21,3944,269,28,4079,264,7,4232,274,11,4371,268,16,4509,263,4,4655,273,5,4795,267,7,4932,261,1,5076,271,2,5216,265,3,5358,259,1,5516,269,0,5665,263,0,5819,256,6,5983,267,3,6132,261,0,6293,255,13,6454,265,8,6597,260,4,6758,253,25,6906,263,19,7034,258,13,7186,252,32,7321,262,30,7430,256,29,7564,252,28,7693,261,26,7803,255,28,7934,252,28,8074,261,26,8207,254,28,8336,252,30,8490,261,31,8636,254,30,8776,253,28,8940,261,40,9088,255,31,9239,254,32,9403,263,47,9550,256,37,9705,256,40,9862,264,50,10009,258,47
Unknownweapon.png
{{#invoke:3D viewer advanced|viewer_new
  | 3d-image-1 = Sandvich
  | 3d-image-2 = Sandvich Alt
  | 3d-image-3 = Sandvich Festive
  | 3d-viewname-1 = Default
  | 3d-viewname-2 = Nommed
  | 3d-viewname-3 = Festive
  | 3d-button-1 = default_half
  | 3d-button-2 = default_half
  | 3d-button-3 = colored_pair
}}

Note the lack of an image-4, viewname-4, or button-4. colored_pair fills these automatically.

https://wiki.teamfortress.com/w/images/f/fa/Sandvich_3D.jpg?1701675677.9229810243,200,280,3,0,257,54,143,267,56,286,261,58,428,259,48,571,268,53,713,263,50,860,261,36,1009,270,48,1151,266,42,1302,262,28,1448,272,47,1581,268,36,1730,264,24,1871,273,49,1989,270,33,2127,265,26,2272,275,55,2390,271,34,2526,266,32,2664,275,64,2773,271,36,2907,266,45,3030,275,53,3146,271,39,3275,266,28,3417,276,35,3541,269,42,3666,266,16,3818,276,21,3948,269,28,4083,265,7,4236,275,11,4375,269,16,4513,263,4,4660,273,5,4801,267,7,4938,261,1,5082,272,2,5223,265,3,5365,259,1,5524,269,0,5673,264,0,5828,257,6,5992,267,3,6141,261,0,6302,255,13,6463,265,8,6606,260,4,6767,254,25,6915,263,19,7043,258,13,7195,252,32,7330,262,30,7439,257,29,7573,252,28,7703,261,26,7813,255,28,7945,252,28,8086,261,26,8220,255,28,8349,253,30,8503,261,31,8649,255,30,8789,253,28,8953,262,40,9101,255,31,9252,254,32,9416,263,47,9563,256,37,9718,256,40,9875,265,50,10022,258,47https://wiki.teamfortress.com/w/images/c/ca/Sandvich_Alt_3D.jpg?1701675821.43084310230,200,280,3,0,257,54,143,266,56,286,260,58,428,259,48,571,268,53,713,263,50,860,261,36,1009,270,48,1151,265,42,1301,262,28,1447,272,46,1580,268,36,1728,263,24,1868,273,49,1986,270,33,2124,264,26,2269,274,55,2386,271,34,2522,265,32,2660,275,64,2769,271,36,2903,266,45,3026,275,52,3142,270,39,3271,266,28,3413,275,35,3537,269,42,3662,266,16,3814,275,21,3944,269,28,4079,264,7,4232,274,11,4371,268,16,4509,263,4,4655,273,5,4795,267,7,4932,261,1,5076,271,2,5216,265,3,5358,259,1,5516,269,0,5665,263,0,5819,256,6,5983,267,3,6132,261,0,6293,255,13,6454,265,8,6597,260,4,6758,253,25,6906,263,19,7034,258,13,7186,252,32,7321,262,30,7430,256,29,7564,252,28,7693,261,26,7803,255,28,7934,252,28,8074,261,26,8207,254,28,8336,252,30,8490,261,31,8636,254,30,8776,253,28,8940,261,40,9088,255,31,9239,254,32,9403,263,47,9550,256,37,9705,256,40,9862,264,50,10009,258,47https://wiki.teamfortress.com/w/images/f/fc/Sandvich_Festive_RED_3D.jpg?1701676162.79497313357,280,217,3,0,210,98,171,215,99,342,210,100,513,212,98,676,216,99,839,211,98,1003,213,90,1158,215,97,1307,212,92,1461,213,83,1627,213,97,1788,212,86,1958,213,80,2144,211,100,2319,212,84,2508,213,81,2698,209,99,2878,213,85,3070,213,72,3263,208,83,3453,214,86,3639,212,57,3835,208,67,4028,213,80,4206,211,44,4398,209,53,4585,212,67,4758,209,35,4937,210,44,5111,210,47,5281,208,26,5451,210,27,5623,208,29,5792,207,14,5962,209,14,6129,206,16,6293,205,9,6462,208,9,6631,204,10,6798,205,8,6976,207,8,7149,202,8,7325,204,9,7511,205,8,7684,202,8,7867,204,20,8045,203,19,8206,202,18,8383,205,41,8540,202,36,8680,203,38,8837,205,24,9020,201,17,9195,203,19,9369,206,12,9583,202,4,9792,204,6,9983,206,8,10215,204,0,10445,205,1,10658,207,13,10892,208,5,11133,207,7,11369,208,30,11602,210,22,11843,208,24,12080,209,59,12291,213,52,12507,209,54,12722,209,84,12908,215,82,13097,210,82https://wiki.teamfortress.com/w/images/c/cf/Sandvich_Festive_BLU_3D.jpg?1701676318.94506713357,280,217,3,0,210,98,171,215,99,342,210,100,513,212,98,676,216,99,839,211,98,1003,213,90,1158,215,97,1307,212,92,1461,213,83,1627,213,97,1788,212,86,1958,213,80,2144,211,100,2319,212,84,2508,213,81,2698,209,99,2878,213,85,3070,213,72,3263,208,83,3453,214,86,3639,212,57,3835,208,67,4028,213,80,4206,211,44,4398,209,53,4585,212,67,4758,209,35,4937,210,44,5111,210,47,5281,208,26,5451,210,27,5623,208,29,5792,207,14,5962,209,14,6129,206,16,6293,205,9,6462,208,9,6631,204,10,6798,205,8,6976,207,8,7149,202,8,7325,204,9,7511,205,8,7684,202,8,7867,204,20,8045,203,19,8206,202,18,8383,205,41,8540,202,36,8680,203,38,8837,205,24,9020,201,17,9195,203,19,9369,206,12,9583,202,4,9792,204,6,9983,206,8,10215,204,0,10445,205,1,10658,207,13,10892,208,5,11133,207,7,11369,208,30,11602,210,22,11843,208,24,12080,209,59,12291,213,52,12507,209,54,12722,209,84,12908,215,82,13097,210,82
Unknownweapon.png
{{#invoke:3D viewer advanced|viewer_new
  | 3d-image-1 = Sniper Rifle
  | 3d-image-2 = Sniper Rifle Australium
  | 3d-viewname-1 = Default
  | 3d-viewname-2 = Australium
  | 3d-button-1 = default_half
  | 3d-button-2 = australium_half
}}
https://wiki.teamfortress.com/w/images/1/11/Sniper_Rifle_3D.jpg?2018082416044812406,280,150,3,0,106,127,30,81,127,61,105,127,93,107,109,167,81,109,246,104,110,324,108,84,457,82,83,599,102,84,738,110,60,919,83,59,1112,98,61,1301,113,38,1518,84,37,1748,94,39,1974,117,20,2214,86,19,2466,90,22,2713,123,7,2962,89,5,3223,88,9,3478,128,1,3723,92,0,3978,85,4,4227,134,5,4452,95,4,4686,83,8,4914,140,21,5104,99,20,5301,82,24,5493,145,49,5633,102,48,5778,82,51,5920,148,88,5998,104,87,6079,82,88,6158,150,117,6196,104,118,6233,82,119,6269,148,112,6347,104,111,6428,82,111,6507,145,89,6647,102,86,6792,83,86,6934,140,67,7124,99,62,7321,84,63,7513,134,48,7738,95,41,7972,86,42,8200,128,32,8445,92,24,8700,88,26,8949,123,22,9198,89,12,9459,90,14,9714,117,19,9954,86,8,10206,93,10,10453,113,23,10670,84,12,10900,96,14,11126,110,37,11307,83,26,11500,99,29,11689,108,61,11822,82,53,11964,102,55,12103,107,95,12177,81,90,12256,104,91https://wiki.teamfortress.com/w/images/3/35/Sniper_Rifle_Australium_3D.jpg?2018082415221512451,280,143,3,0,111,127,31,85,127,62,100,127,94,111,108,168,85,108,247,99,109,324,112,82,457,85,82,599,98,83,738,114,57,920,86,57,1113,95,58,1303,116,36,1522,87,35,1753,93,37,1980,120,18,2222,88,17,2476,90,19,2725,124,6,2977,90,4,3240,88,8,3498,128,1,3744,92,0,4001,87,4,4252,132,7,4478,93,5,4713,86,9,4942,136,24,5132,95,22,5329,86,26,5521,140,52,5661,97,51,5805,87,53,5946,142,90,6023,98,89,6103,87,90,6181,143,117,6219,99,118,6256,87,119,6292,142,111,6369,98,110,6449,87,110,6527,140,87,6667,97,84,6811,87,84,6952,136,65,7142,95,60,7339,88,61,7531,132,46,7757,93,39,7992,89,40,8221,128,31,8467,92,22,8724,90,24,8975,124,21,9227,90,11,9490,91,13,9748,120,19,9990,88,8,10244,93,10,10493,116,24,10712,87,13,10943,94,15,11170,114,39,11352,86,29,11545,96,31,11735,112,63,11868,85,55,12010,98,57,12149,111,97,12223,85,92,12302,99,93
Unknownweapon.png
{{#invoke:3D viewer advanced|viewer_new
  | 3d-image-1 = Sniper Rifle
  | 3d-image-2 = Sniper Rifle Australium
  | 3d-viewname-1 = Default
  | 3d-viewname-2 = Australium
  | 3d-button-1 = default
  | 3d-button-2 = australium
}}
https://wiki.teamfortress.com/w/images/1/11/Sniper_Rifle_3D.jpg?2018082416044812406,280,150,3,0,106,127,30,81,127,61,105,127,93,107,109,167,81,109,246,104,110,324,108,84,457,82,83,599,102,84,738,110,60,919,83,59,1112,98,61,1301,113,38,1518,84,37,1748,94,39,1974,117,20,2214,86,19,2466,90,22,2713,123,7,2962,89,5,3223,88,9,3478,128,1,3723,92,0,3978,85,4,4227,134,5,4452,95,4,4686,83,8,4914,140,21,5104,99,20,5301,82,24,5493,145,49,5633,102,48,5778,82,51,5920,148,88,5998,104,87,6079,82,88,6158,150,117,6196,104,118,6233,82,119,6269,148,112,6347,104,111,6428,82,111,6507,145,89,6647,102,86,6792,83,86,6934,140,67,7124,99,62,7321,84,63,7513,134,48,7738,95,41,7972,86,42,8200,128,32,8445,92,24,8700,88,26,8949,123,22,9198,89,12,9459,90,14,9714,117,19,9954,86,8,10206,93,10,10453,113,23,10670,84,12,10900,96,14,11126,110,37,11307,83,26,11500,99,29,11689,108,61,11822,82,53,11964,102,55,12103,107,95,12177,81,90,12256,104,91https://wiki.teamfortress.com/w/images/3/35/Sniper_Rifle_Australium_3D.jpg?2018082415221512451,280,143,3,0,111,127,31,85,127,62,100,127,94,111,108,168,85,108,247,99,109,324,112,82,457,85,82,599,98,83,738,114,57,920,86,57,1113,95,58,1303,116,36,1522,87,35,1753,93,37,1980,120,18,2222,88,17,2476,90,19,2725,124,6,2977,90,4,3240,88,8,3498,128,1,3744,92,0,4001,87,4,4252,132,7,4478,93,5,4713,86,9,4942,136,24,5132,95,22,5329,86,26,5521,140,52,5661,97,51,5805,87,53,5946,142,90,6023,98,89,6103,87,90,6181,143,117,6219,99,118,6256,87,119,6292,142,111,6369,98,110,6449,87,110,6527,140,87,6667,97,84,6811,87,84,6952,136,65,7142,95,60,7339,88,61,7531,132,46,7757,93,39,7992,89,40,8221,128,31,8467,92,22,8724,90,24,8975,124,21,9227,90,11,9490,91,13,9748,120,19,9990,88,8,10244,93,10,10493,116,24,10712,87,13,10943,94,15,11170,114,39,11352,86,29,11545,96,31,11735,112,63,11868,85,55,12010,98,57,12149,111,97,12223,85,92,12302,99,93
Unknownweapon.png
{{#invoke:3D viewer advanced|viewer_new
  | 3d-image-1 = Soldier Classic RED
  | 3d-image-2 = Soldier Classic BLU
  | 3d-image-3 = Soldier Classic YELLOW
  | 3d-image-4 = Soldier Classic GREEN
  | 3d-viewname-1 = RED
  | 3d-viewname-2 = BLU
  | 3d-viewname-3 = YELLOW
  | 3d-viewname-4 = GREEN
  | 3d-button-1 = tfc_red_half
  | 3d-button-2 = tfc_blu_half
  | 3d-button-3 = tfc_yellow_half
  | 3d-button-4 = tfc_green_half
}}
https://wiki.teamfortress.com/w/images/d/dc/Soldier_Classic_RED_3D.jpg?1739287939.1760172360,127,280,1,0,276,8,106,271,16,200,264,18,287,261,21,371,261,22,454,260,19,549,258,18,653,256,21,759,257,20,866,256,16,976,256,16,1081,254,18,1178,252,14,1273,248,13,1368,245,15,1457,242,21,1541,246,24,1625,250,24,1709,256,18,1795,263,9,1894,270,3,2002,275,0,2112,278,0,2223,278,1https://wiki.teamfortress.com/w/images/a/ad/Soldier_Classic_BLU_3D.jpg?1739287886.6298442360,127,280,1,0,276,8,106,271,16,200,264,18,287,261,21,371,261,22,454,260,19,549,258,18,653,256,21,759,257,20,866,256,16,976,256,16,1081,254,18,1178,252,14,1273,248,13,1368,245,15,1457,242,21,1541,246,24,1625,250,24,1709,256,18,1795,263,9,1894,270,3,2002,275,0,2112,278,0,2223,278,1https://wiki.teamfortress.com/w/images/1/1a/Soldier_Classic_YELLOW_3D.jpg?1739287998.3259952360,127,280,1,0,276,8,106,271,16,200,264,18,287,261,21,371,261,22,454,260,19,549,258,18,653,256,21,759,257,20,866,256,16,976,256,16,1081,254,18,1178,252,14,1273,248,13,1368,245,15,1457,242,21,1541,246,24,1625,250,24,1709,256,18,1795,263,9,1894,270,3,2002,275,0,2112,278,0,2223,278,1https://wiki.teamfortress.com/w/images/c/cd/Soldier_Classic_GREEN_3D.jpg?1739287914.2229632360,127,280,1,0,276,8,106,271,16,200,264,18,287,261,21,371,261,22,454,260,19,549,258,18,653,256,21,759,257,20,866,256,16,976,256,16,1081,254,18,1178,252,14,1273,248,13,1368,245,15,1457,242,21,1541,246,24,1625,250,24,1709,256,18,1795,263,9,1894,270,3,2002,275,0,2112,278,0,2223,278,1
Unknownweapon.png

Parameters

3d-image-n
Filename for the nth 3D image, excluding the ' 3D.jpg', where n is an integer that starts at 1.
3d-button-n
View button class for the nth 3D image, where the class is one of the following:
default_half: for default coloured buttons that are half width
default_full or default: for default coloured buttons that are full width
australium_half: for australium coloured buttons that are half width
australium_full or australium: for australium coloured buttons that are full width
colored_pair for a red and blue button pair.
Note: When using this setting, do NOT specify 3d-image-(n+1), 3d-button-(n+1), or 3d-viewname-(n+1).
3d-viewname-n
View name for the nth 3D image, where n is an integer that starts at 1.
When colored_pair is active, (RED) or (BLU) will be appended to the appropriate viewname.
3d-startframe (optional)
Allows you to override the starting frame for the 3D images, by setting to an integer value between 0 and 15.

3D images are added to the viewer in the order they are defined.


local p = {}

local utils = require('Module:Utils')
local HtmlBuilder = require('Module:HtmlBuilder')
local frame = nil

-- Expands the template Common string for a given value. Note that some common string values include an additional parameter, here called opt_arg.
function common_string(arg, opt_arg)
    return frame:expandTemplate{title='Common string', args={arg, opt_arg}}
end

-- Returns ' (text)', with correct parenthesis characters in Chinese.
function paren(text)
    if if_lang == '/zh_hans' or if_lang == '/zh-hant' then
        return ' (' .. text .. ')'
    else
        return ' (' .. text .. ')'
    end
end

function p.viewer(f)
    local args = utils.get_args(f)
    local startframe = utils.processArg(args['startframe'])
    local image = utils.processArg(args['image'])
    local image_0 = utils.processArg(args['image-0'])
    local fallback = utils.processArg(args['fallback'])
    local startframe_class
    if startframe ~= '' then
        startframe_class = mw.text.trim(startframe)
    else
        startframe_class = utils.expandWikitext('{{File:' .. (image_0 or image) .. '|startframe}}')
    end
    local output_view = HtmlBuilder.create('div')
        .addClass('viewer-3d')
        .addClass('startframe-' .. startframe_class)
        .wikitext(fallback)

    for i = 0,10 do
        local image_n = utils.processArg(args['image-' .. i], '')
        if image_n ~= '' then
            span_image_url_n = output_view
                .tag('span')
                .addClass('viewer-3d-url-' .. i)
                .wikitext(utils.expandWikitext('{{File:' .. image_n .. '|url}}'))

            span_image_map_n = output_view
                .tag('span')
                .addClass('viewer-3d-map-' .. i)
                .wikitext(utils.expandWikitext('{{File:' .. image_n .. '|map}}'))
        end
    end

    local viewer_3d_frame = output_view
        .tag('div')
        .addClass('viewer-3d-frame')

    local switch_to_2d = output_view
        .tag('div')
        .attr('id', 'switch-to-2d')

    return tostring(output_view)
end

function p.viewer_new(f)
    frame = f
    local args = utils.get_args(f)
    
    -- button classes mapping
    local button_classes = {
        red             = 'view-selector-red',
        blu             = 'view-selector-blu',
        red_half        = 'view-selector-red-',
        blu_half        = 'view-selector-blu-',
        red_full        = 'view-selector-red-full',
        blu_full        = 'view-selector-blu-full',
        tfc             = 'view-selector-tfc-full',
        tfc_half        = 'view-selector-tfc-',
        tfc_red_half    = 'view-selector-tfcred-',
        tfc_blu_half    = 'view-selector-tfcblu-',
        tfc_yellow_half = 'view-selector-tfcyellow-',
        tfc_green_half  = 'view-selector-tfcgreen-',
        australium_half = 'view-selector-australium-',
        australium_full = 'view-selector-australium-full',
        australium      = 'view-selector-australium-full',
        default_half    = 'view-selector-default-',
        default_full    = 'view-selector-default-full',
        default         = 'view-selector-default-full'
    }

    -- create output container
    local output_view = HtmlBuilder.create('div')
        .addClass('viewer-3d-container')
    
    -- create container for viewer
    local startimage = utils.processArg(args['3d-image-1'])
    -- if first button is colored then add RED to filename
    if utils.processArg(args['3d-button-1']) == 'colored_pair' then
    	startimage = startimage .. ' RED'
    end
    local startframe = args['3d-startframe'] or utils.expandWikitext('{{File:' .. startimage .. ' 3D.jpg|startframe}}')
    local viewer_container = output_view
        .tag('div')
        .addClass('viewer-3d')
        .addClass('startframe-' .. startframe)

    -- add 3D and 2D selectors
    local viewer_3d_frame = viewer_container
        .tag('div')
        .addClass('viewer-3d-frame')

    local switch_to_2d = viewer_container
        .tag('div')
        .attr('id', 'switch-to-2d')

    -- create container for model selector buttons
    local buttons_container = output_view
        .tag('ul')
        .addClass('buttons-container-3d')

    -- create container for 2D image
    local image_2d
    if args['image'] then
        image_2d = args['image']
    elseif args['team-colors'] == 'yes' then
        image_2d = args['skin-image-red'] or mw.title.getCurrentTitle().baseText .. ' RED.png'
    else
        image_2d = mw.title.getCurrentTitle().baseText .. '.png'
    end
    local viewer_2d_frame = output_view
        .tag('div')
        .wikitext(utils.expandWikitext('{{2D viewer|' .. image_2d .. '|' .. (args['imagewidth'] or '250px') .. '}}'))

    -- row button counter for half width buttons
    local current_row_count = 0
    local colored = false
    local i = 1
    while utils.processArg(args['3d-image-' .. i]) ~= '' or colored do
    -- the "or colored" ensures that if the last image pair is team-colored, it will still be processed.
        local image_postfix = ' 3D.jpg'
        local viewname_postfix = ''
        if colored then
            -- if we are the second half of a team-colored image, use the details from the first half.
            i = i - 1
        end
        local image_n = utils.processArg(args['3d-image-' .. i])
        local button_n = utils.processArg(args['3d-button-' .. i])
        local button_class = button_classes[button_n]
        local viewname_n = utils.processArg(args['3d-viewname-' .. i])
        if colored then
            i = i + 1
            image_postfix = ' BLU 3D.jpg'
            viewname_postfix = paren(common_string('BLU'))
            button_class = 'view-selector-blu'
            colored = false
        elseif not colored and button_n == 'colored_pair' then
            image_postfix = ' RED 3D.jpg'
            viewname_postfix = paren(common_string('RED'))
            button_class = 'view-selector-red'
            colored = true
        end
        if image_n ~= '' then
            span_image_url_n = viewer_container
                .tag('span')
                .addClass('viewer-3d-url-' .. (i-1))
                .wikitext(utils.expandWikitext('{{File:' .. image_n .. image_postfix .. '|url}}'))

            span_image_map_n = viewer_container
                .tag('span')
                .addClass('viewer-3d-map-' .. (i-1))
                .wikitext(utils.expandWikitext('{{File:' .. image_n .. image_postfix .. '|map}}'))

            -- if there is only one 3d image then don't attach selector
            if i == 1 and args['3d-image-2'] == nil and args['3d-image-3'] == nil then
            	break
            end
            -- add selector button for this model (changing class if it's a half-width button)
            if button_n:sub(-5) == '_half' then
                if current_row_count == 0 then
                    button_class = button_class .. 'left'
                    current_row_count = 1
                else
                    button_class = button_class .. 'right'
                    current_row_count = 0
                end
            end
            -- selector is 0-indexed
            button_class = button_class .. ' selector-' .. (i-1)
            
            li_button_n = buttons_container
                .tag('li')
                .addClass(button_class)
                .wikitext(utils.expandWikitext('[[:File:' .. image_n .. image_postfix .. '|' .. viewname_n .. viewname_postfix .. ']]'))
        end

        i = i + 1
    end

    return tostring(output_view)
end

return p