first commit

This commit is contained in:
Rainer 2025-08-22 02:31:04 +02:00
commit dabddc3f2b
127 changed files with 1812 additions and 0 deletions

21
LICENSE.txt Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2022 MrRar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

111
README.md Normal file
View file

@ -0,0 +1,111 @@
# Edit Skin Mod
[![ContentDB](https://content.minetest.net/packages/Mr.%20Rar/edit_skin/shields/downloads/)](https://content.minetest.net/packages/Mr.%20Rar/edit_skin/)
![screenshot](screenshot.png)
This mod allows advanced skin customization.
New players get a randomly selected male or female skin.
It is compatible with sfinv, sfinv_buttons, i3, unified_inventory, inventory_plus, smart_inventory, and 3d_armor.
Use the /skin command to open the skin configuration screen.
This mod requires Minetest 5.5+
This mod was originally made for MineClone 5.
## License
Code under MIT license
Author: MrRar
See media_credits.txt for media licensing.
## API
### `edit_skin.register_item(item)`
Register a skin item. `item` is a table with item properties listed below.
### Item properties
`type`
Set the item type. Valid values are: "base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"
`texture`
Set to the image file that will be used. Transparent or semitransparnt parts of the texture can be colored by the `mask` texture. If this property is omitted "blank.png" is used.
`mask`
Set the color mask texture. Coloring is only applied to non transparent areas of the texture.
Coloring only works for "base", "bottom, "top", and "hair".
`preview_rotation`
A table containing properties `x` and `y`. `x` and `y` represent the x and y rotation of the item preview.
`alex`
If set to true the item will be default for female character.
`steve`
If set to true the item will be default for male character.
`restricted_to_admin`
This item can only be selected by players with `edit_skin_admin` privilege.
`for_player`
This property is used to restrict the item to a specific player or players. If set to a string, the string is a player name. If set to a table, the table is an array of player names.
`rank`
This property is used to change the application order of the skin item when applied to a player.
The default ranks for each item type are:
base: 10
footwear: 20
eye: 30
mouth: 40
bottom: 50
top: 60
hair: 70
headwear: 80
Lower ranks are applied to the player first and can thus be covered by higher rank items.
### `edit_skin.show_formspec(player)`
Show the skin configuration screen.
`player` is a player ObjectRef.
### `edit_skin.register_on_set_skin(func)`
Register a function to be called whenever a player skin changes.
The function will be given a player ObjectRef as a parameter.
### `edit_skin.save(player)`
Save player skin. `player` is a player ObjectRef.
### `edit_skin.update_player_skin(player)`
Update a player based on skin data in edit_skin.players.
`player` is a player ObjectRef.
### `edit_skin.base_color`
A table of ColorSpec integers that the player can select to color the base item.
These colors are separate from `edit_skin.color` because this mod registers a mesh hand node for each base and base color combination. The number of junk mesh hand nodes should be kept to a minimum.
### `edit_skin.color`
A table of ColorSpec integers that the player can select to color colorable skin items.
### `edit_skin.players`
A table mapped by player ObjectRef containing tables holding the player's selected skin items and colors.
Only stores skin information for logged in players.
### `edit_skin.player_formspecs`
A table mapped by player ObjectRef containing tables holding player formspec state. The tables have the following properties:
`active_tab`
Set to the name of the current active tab.
`page_num`
Set to the current formspec page number.
### `edit_skin.compile_skin(skin)`
`skin` is a table with skin item properties.
Returns an image string.

691
init.lua Normal file
View file

@ -0,0 +1,691 @@
-- Edit Skin Mod
local S = minetest.get_translator("edit_skin")
local color_to_string = minetest.colorspec_to_colorstring
edit_skin = {
item_names = {"base", "footwear", "eye", "mouth", "bottom", "top", "hair", "headwear"},
tab_names = {"template", "base", "headwear", "hair", "eye", "mouth", "top", "bottom", "footwear"},
tab_descriptions = {
template = S("Templates"),
base = S("Bases"),
footwear = S("Footwears"),
eye = S("Eyes"),
mouth = S("Mouths"),
bottom = S("Bottoms"),
top = S("Tops"),
hair = S("Hairs"),
headwear = S("Headwears")
},
steve = {}, -- Stores skin values for Steve skin
alex = {}, -- Stores skin values for Alex skin
base = {}, -- List of base textures
-- Base color is separate to keep the number of junk nodes registered in check
base_color = {0xffeeb592, 0xffb47a57, 0xff8d471d},
color = {
0xff613915, -- 1 Dark brown Steve hair, Alex bottom
0xff97491b, -- 2 Medium brown
0xffb17050, -- 3 Light brown
0xffe2bc7b, -- 4 Beige
0xff706662, -- 5 Gray
0xff151515, -- 6 Black
0xffc21c1c, -- 7 Red
0xff178c32, -- 8 Green Alex top
0xffae2ad3, -- 9 Plum
0xffebe8e4, -- 10 White
0xffe3dd26, -- 11 Yellow
0xff449acc, -- 12 Light blue Steve top
0xff124d87, -- 13 Dark blue Steve bottom
0xfffc0eb3, -- 14 Pink
0xffd0672a, -- 15 Orange Alex hair
},
footwear = {},
mouth = {},
eye = {},
bottom = {},
top = {},
hair = {},
headwear = {},
masks = {},
preview_rotations = {},
ranks = {},
player_skins = {},
player_formspecs = {},
restricted_to_player = {},
restricted_to_admin = {},
}
minetest.register_privilege("edit_skin_admin", {
description = S("Allows access to restricted skin items."),
give_to_singleplayer = true,
give_to_admin = true,
})
function edit_skin.register_item(item)
assert(edit_skin[item.type], "Skin item type " .. item.type .. " does not exist.")
local texture = item.texture or "blank.png"
if item.steve then
edit_skin.steve[item.type] = texture
end
if item.alex then
edit_skin.alex[item.type] = texture
end
if item.restricted_to_admin then
edit_skin.restricted_to_admin[texture] = true
end
if item.for_player then
edit_skin.restricted_to_player[texture] = {}
if type(item.for_player) == "string" then
edit_skin.restricted_to_player[texture][item.for_player] = true
else
for i, name in pairs(item.for_player) do
edit_skin.restricted_to_player[texture][name] = true
end
end
end
table.insert(edit_skin[item.type], texture)
edit_skin.masks[texture] = item.mask
edit_skin.preview_rotations[texture] = item.preview_rotation
edit_skin.ranks[texture] = item.rank
end
function edit_skin.save(player)
if not player:is_player() then return end
local skin = edit_skin.player_skins[player]
if not skin then return end
player:get_meta():set_string("edit_skin:skin", minetest.serialize(skin))
end
minetest.register_chatcommand("skin", {
description = S("Open skin configuration screen."),
privs = {},
func = function(name, param) edit_skin.show_formspec(minetest.get_player_by_name(name)) end
})
function edit_skin.compile_skin(skin)
if not skin then return "blank.png" end
local ranks = {}
local layers = {}
for i, item in ipairs(edit_skin.item_names) do
local texture = skin[item]
local layer = ""
local rank = edit_skin.ranks[texture] or i * 10
if texture and texture ~= "blank.png" then
if skin[item .. "_color"] and edit_skin.masks[texture] then
local color = color_to_string(skin[item .. "_color"])
layer = "(" .. edit_skin.masks[texture] .. "^[colorize:" .. color .. ":alpha)"
end
if #layer > 0 then layer = layer .. "^" end
layer = layer .. texture
layers[rank] = layer
table.insert(ranks, rank)
end
end
table.sort(ranks)
local output = ""
for i, rank in ipairs(ranks) do
if #output > 0 then output = output .. "^" end
output = output .. layers[rank]
end
return output
end
function edit_skin.update_player_skin(player)
local output = edit_skin.compile_skin(edit_skin.player_skins[player])
player_api.set_texture(player, 1, output)
-- Set player first person hand node
local base = edit_skin.player_skins[player].base
local base_color = edit_skin.player_skins[player].base_color
local node_id = base:gsub(".png$", "") .. color_to_string(base_color):gsub("#", "")
player:get_inventory():set_stack("hand", 1, "edit_skin:" .. node_id)
for i = 1, #edit_skin.registered_on_set_skins do
edit_skin.registered_on_set_skins[i](player)
end
local name = player:get_player_name()
if
minetest.global_exists("armor") and
armor.textures and armor.textures[name]
then
armor.textures[name].skin = output
armor.update_player_visuals(armor, player)
end
if minetest.global_exists("i3") then i3.set_fs(player) end
end
minetest.register_on_joinplayer(function(player)
local function table_get_random(t)
return t[math.random(#t)]
end
local skin = player:get_meta():get_string("edit_skin:skin")
if skin then
skin = minetest.deserialize(skin)
end
if skin then
edit_skin.player_skins[player] = skin
else
if math.random() > 0.5 then
skin = table.copy(edit_skin.steve)
else
skin = table.copy(edit_skin.alex)
end
edit_skin.player_skins[player] = skin
edit_skin.save(player)
end
edit_skin.player_formspecs[player] = {
active_tab = "template",
page_num = 1,
has_admin_priv = minetest.check_player_privs(player, "edit_skin_admin"),
}
player:get_inventory():set_size("hand", 1)
edit_skin.update_player_skin(player)
if minetest.global_exists("inventory_plus") and inventory_plus.register_button then
inventory_plus.register_button(player, "edit_skin", S("Edit Skin"))
end
-- Needed for 3D Armor + sfinv
if minetest.global_exists("armor") then
minetest.after(0.01, function()
if player:is_player() then
edit_skin.update_player_skin(player)
end
end)
end
end)
minetest.register_on_leaveplayer(function(player)
player:get_inventory():set_size("hand", 0)
edit_skin.player_skins[player] = nil
edit_skin.player_formspecs[player] = nil
end)
minetest.register_on_shutdown(function()
for _, player in pairs(minetest.get_connected_players()) do
player:get_inventory():set_size("hand", 0)
end
end)
edit_skin.registered_on_set_skins = {}
function edit_skin.register_on_set_skin(func)
table.insert(edit_skin.registered_on_set_skins, func)
end
function edit_skin.show_formspec(player)
local formspec_data = edit_skin.player_formspecs[player]
local has_admin_priv = minetest.check_player_privs(player, "edit_skin_admin")
if has_admin_priv ~= formspec_data.has_admin_priv then
formspec_data.has_admin_priv = has_admin_priv
for i, name in pairs(edit_skin.item_names) do
formspec_data[name] = nil
end
end
local active_tab = formspec_data.active_tab
local page_num = formspec_data.page_num
local skin = edit_skin.player_skins[player]
local formspec = "formspec_version[3]size[14.2,11]"
for i, tab in pairs(edit_skin.tab_names) do
if tab == active_tab then
formspec = formspec ..
"style[" .. tab .. ";bgcolor=green]"
end
local y = 0.3 + (i - 1) * 0.8
formspec = formspec ..
"style[" .. tab .. ";content_offset=16,0]" ..
"button[0.3," .. y .. ";4,0.8;" .. tab .. ";" .. edit_skin.tab_descriptions[tab] .. "]" ..
"image[0.4," .. y + 0.1 .. ";0.6,0.6;edit_skin_icons.png^[verticalframe:9:" .. i - 1 .. "]"
end
local mesh = player:get_properties().mesh or ""
local textures = player_api.get_textures(player)
textures[2] = "blank.png" -- Clear out the armor
formspec = formspec ..
"model[11,0.3;3,7;player_mesh;" .. mesh .. ";" ..
table.concat(textures, ",") ..
";0,180;false;true;0,0]"
if active_tab == "template" then
formspec = formspec ..
"model[5,2;2,3;player_mesh;" .. mesh .. ";" ..
edit_skin.compile_skin(edit_skin.steve) ..
",blank.png,blank.png;0,180;false;true;0,0]" ..
"button[5,5.2;2,0.8;steve;" .. S("Select") .. "]" ..
"model[7.5,2;2,3;player_mesh;" .. mesh .. ";" ..
edit_skin.compile_skin(edit_skin.alex) ..
",blank.png,blank.png;0,180;false;true;0,0]" ..
"button[7.5,5.2;2,0.8;alex;" .. S("Select") .. "]"
else
formspec = formspec ..
"style_type[button,image_button;border=false;bgcolor=#00000000]"
if not formspec_data[active_tab] then edit_skin.filter_active_tab(player) end
local textures = formspec_data[active_tab]
local page_start = (page_num - 1) * 16 + 1
local page_end = math.min(page_start + 16 - 1, #textures)
for j = page_start, page_end do
local i = j - page_start + 1
local texture = textures[j]
local preview = edit_skin.masks[skin.base] .. "^[colorize:gray^" .. skin.base
local color = color_to_string(skin[active_tab .. "_color"])
local mask = edit_skin.masks[texture]
if color and mask then
preview = preview .. "^(" .. mask .. "^[colorize:" .. color .. ":alpha)"
end
preview = preview .. "^" .. texture
local mesh = "edit_skin_head.obj"
if active_tab == "top" then
mesh = "edit_skin_top.obj"
elseif active_tab == "bottom" or active_tab == "footwear" then
mesh = "edit_skin_bottom.obj"
end
local rot_x = -10
local rot_y = 20
if edit_skin.preview_rotations[texture] then
rot_x = edit_skin.preview_rotations[texture].x
rot_y = edit_skin.preview_rotations[texture].y
end
i = i - 1
local x = 4.5 + i % 4 * 1.6
local y = 0.3 + math.floor(i / 4) * 1.6
formspec = formspec ..
"model[" .. x .. "," .. y ..
";1.5,1.5;" .. mesh .. ";" .. mesh .. ";" ..
preview ..
";" .. rot_x .. "," .. rot_y .. ";false;false;0,0]"
if skin[active_tab] == texture then
formspec = formspec ..
"style[" .. texture ..
";bgcolor=;bgimg=edit_skin_select_overlay.png;" ..
"bgimg_pressed=edit_skin_select_overlay.png;bgimg_middle=14,14]"
end
formspec = formspec .. "button[" .. x .. "," .. y .. ";1.5,1.5;" .. texture .. ";]"
end
end
if skin[active_tab .. "_color"] then
local colors = edit_skin.color
if active_tab == "base" then colors = edit_skin.base_color end
local tab_color = active_tab .. "_color"
local selected_color = skin[tab_color]
for i, colorspec in pairs(colors) do
local color = color_to_string(colorspec)
i = i - 1
local x = 4.6 + i % 6 * 0.9
local y = 8 + math.floor(i / 6) * 0.9
formspec = formspec ..
"image_button[" .. x .. "," .. y ..
";0.8,0.8;blank.png^[noalpha^[colorize:" ..
color .. ":alpha;" .. colorspec .. ";]"
if selected_color == colorspec then
formspec = formspec ..
"style[" .. color ..
";bgcolor=;bgimg=edit_skin_select_overlay.png;bgimg_middle=14,14]" ..
"button[" .. x .. "," .. y .. ";0.8,0.8;" .. color .. ";]"
end
end
if not (active_tab == "base") then
-- Bitwise Operations !?!?!
local red = math.floor(selected_color / 0x10000) - 0xff00
local green = math.floor(selected_color / 0x100) - 0xff0000 - red * 0x100
local blue = selected_color - 0xff000000 - red * 0x10000 - green * 0x100
formspec = formspec ..
"container[10.2,8]" ..
"scrollbaroptions[min=0;max=255;smallstep=20]" ..
"box[0.4,0;2.49,0.38;red]" ..
"label[0.2,0.2;-]" ..
"scrollbar[0.4,0;2.5,0.4;horizontal;red;" .. red .."]" ..
"label[2.9,0.2;+]" ..
"box[0.4,0.6;2.49,0.38;green]" ..
"label[0.2,0.8;-]" ..
"scrollbar[0.4,0.6;2.5,0.4;horizontal;green;" .. green .."]" ..
"label[2.9,0.8;+]" ..
"box[0.4,1.2;2.49,0.38;blue]" ..
"label[0.2,1.4;-]" ..
"scrollbar[0.4,1.2;2.5,0.4;horizontal;blue;" .. blue .. "]" ..
"label[2.9,1.4;+]" ..
"container_end[]"
end
end
local page_count = 1
if edit_skin[active_tab] then
page_count = math.ceil(#formspec_data[active_tab] / 16)
end
if page_num > 1 then
formspec = formspec ..
"image_button[4.5,6.7;1,1;edit_skin_arrow.png^[transformFX;previous_page;]"
end
if page_num < page_count then
formspec = formspec ..
"image_button[9.8,6.7;1,1;edit_skin_arrow.png;next_page;]"
end
if page_count > 1 then
formspec = formspec ..
"label[7.3,7.2;" .. page_num .. " / " .. page_count .. "]"
end
minetest.show_formspec(player:get_player_name(), "edit_skin:edit_skin", formspec)
end
function edit_skin.filter_active_tab(player)
local formspec_data = edit_skin.player_formspecs[player]
local active_tab = formspec_data.active_tab
local admin_priv = formspec_data.has_admin_priv
local name = player:get_player_name()
formspec_data[active_tab] = {}
local textures = formspec_data[active_tab]
for i, texture in pairs(edit_skin[active_tab]) do
if admin_priv or not edit_skin.restricted_to_admin[texture] then
local restriction = edit_skin.restricted_to_player[texture]
if restriction then
if restriction[name] then
table.insert(textures, texture)
end
else
table.insert(textures, texture)
end
end
end
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "edit_skin:edit_skin" then return false end
local formspec_data = edit_skin.player_formspecs[player]
local active_tab = formspec_data.active_tab
-- Cancel formspec resend after scrollbar move
if formspec_data.form_send_job then
formspec_data.form_send_job:cancel()
end
if fields.quit then
edit_skin.save(player)
return true
end
if fields.alex then
edit_skin.player_skins[player] = table.copy(edit_skin.alex)
edit_skin.update_player_skin(player)
edit_skin.show_formspec(player)
return true
elseif fields.steve then
edit_skin.player_skins[player] = table.copy(edit_skin.steve)
edit_skin.update_player_skin(player)
edit_skin.show_formspec(player)
return true
end
for i, tab in pairs(edit_skin.tab_names) do
if fields[tab] then
formspec_data.active_tab = tab
formspec_data.page_num = 1
edit_skin.show_formspec(player)
return true
end
end
local skin = edit_skin.player_skins[player]
if not skin then return true end
if fields.next_page then
local page_num = formspec_data.page_num
page_num = page_num + 1
local page_count = math.ceil(#formspec_data[active_tab] / 16)
if page_num > page_count then
page_num = page_count
end
formspec_data.page_num = page_num
edit_skin.show_formspec(player)
return true
elseif fields.previous_page then
local page_num = formspec_data.page_num
page_num = page_num - 1
if page_num < 1 then page_num = 1 end
formspec_data.page_num = page_num
edit_skin.show_formspec(player)
return true
end
if
skin[active_tab .. "_color"] and (
fields.red and fields.red:find("^CHG") or
fields.green and fields.green:find("^CHG") or
fields.blue and fields.blue:find("^CHG")
)
then
local red = fields.red:gsub("%a%a%a:", "")
local green = fields.green:gsub("%a%a%a:", "")
local blue = fields.blue:gsub("%a%a%a:", "")
red = tonumber(red) or 0
green = tonumber(green) or 0
blue = tonumber(blue) or 0
local color = 0xff000000 + red * 0x10000 + green * 0x100 + blue
if color >= 0 and color <= 0xffffffff then
-- We delay resedning the form because otherwise it will break dragging scrollbars
formspec_data.form_send_job = minetest.after(0.2, function()
if player and player:is_player() then
skin[active_tab .. "_color"] = color
edit_skin.update_player_skin(player)
edit_skin.show_formspec(player)
formspec_data.form_send_job = nil
end
end)
return true
end
end
local field
for f, value in pairs(fields) do
if value == "" then
field = f
break
end
end
-- See if field is a texture
if field and edit_skin[active_tab] then
for i, texture in pairs(formspec_data[active_tab]) do
if texture == field then
skin[active_tab] = texture
edit_skin.update_player_skin(player)
edit_skin.show_formspec(player)
return true
end
end
end
-- See if field is a color
local number = tonumber(field)
if number and skin[active_tab .. "_color"] then
local color = math.floor(number)
if color and color >= 0 and color <= 0xffffffff then
skin[active_tab .. "_color"] = color
edit_skin.update_player_skin(player)
edit_skin.show_formspec(player)
return true
end
end
return true
end)
local function init()
local f = io.open(minetest.get_modpath("edit_skin") .. "/list.json")
assert(f, "Can't open the file list.json")
local data = f:read("*all")
assert(data, "Can't read data from list.json")
local json, error = minetest.parse_json(data)
assert(json, error)
f:close()
for _, item in pairs(json) do
edit_skin.register_item(item)
end
edit_skin.steve.base_color = edit_skin.base_color[1]
edit_skin.steve.hair_color = edit_skin.color[1]
edit_skin.steve.top_color = edit_skin.color[12]
edit_skin.steve.bottom_color = edit_skin.color[13]
edit_skin.alex.base_color = edit_skin.base_color[1]
edit_skin.alex.hair_color = edit_skin.color[15]
edit_skin.alex.top_color = edit_skin.color[8]
edit_skin.alex.bottom_color = edit_skin.color[1]
-- Register junk first person hand nodes
local function make_texture(base, colorspec)
local output = ""
if edit_skin.masks[base] then
output = edit_skin.masks[base] ..
"^[colorize:" .. color_to_string(colorspec) .. ":alpha"
end
if #output > 0 then output = output .. "^" end
output = output .. base
return output
end
for _, base in pairs(edit_skin.base) do
for _, base_color in pairs(edit_skin.base_color) do
local id = base:gsub(".png$", "") .. color_to_string(base_color):gsub("#", "")
minetest.register_node("edit_skin:" .. id, {
drawtype = "mesh",
groups = { not_in_creative_inventory = 1 },
tiles = { make_texture(base, base_color) },
use_texture_alpha = "clip",
mesh = "edit_skin_hand.obj",
})
end
end
minetest.after(0, function()
local hand_def = minetest.registered_items[""]
local range = hand_def and hand_def.range
for _, base in pairs(edit_skin.base) do
for _, base_color in pairs(edit_skin.base_color) do
local id = base:gsub(".png$", "") .. color_to_string(base_color):gsub("#", "")
minetest.override_item("edit_skin:" .. id, {range = range})
end
end
end)
if minetest.global_exists("i3_extrabuttons") then
i3_extrabuttons.new_tab("edit_skin", {
description = S("Erscheinungsbild"),
--image = "edit_skin_button.png", -- Icon covers label
access = function(player, data) return true end,
formspec = function(player, data, fs) end,
fields = function(player, data, fields)
i3.set_tab(player, "inventory")
edit_skin.show_formspec(player)
end,
})
elseif minetest.global_exists("i3") then
i3.new_tab("edit_skin", {
description = S("Skin"),
--image = "edit_skin_button.png", -- Icon covers label
access = function(player, data) return true end,
formspec = function(player, data, fs) end,
fields = function(player, data, fields)
i3.set_tab(player, "inventory")
edit_skin.show_formspec(player)
end,
})
end
if minetest.global_exists("sfinv_buttons") then
sfinv_buttons.register_button("edit_skin", {
title = S("Edit Skin"),
action = function(player) edit_skin.show_formspec(player) end,
tooltip = S("Open skin configuration screen."),
image = "edit_skin_button.png",
})
elseif minetest.global_exists("sfinv") then
sfinv.register_page("edit_skin", {
title = S("Edit Skin"),
get = function(self, player, context) return "" end,
on_enter = function(self, player, context)
sfinv.contexts[player:get_player_name()].page = sfinv.get_homepage_name(player)
edit_skin.show_formspec(player)
end
})
end
if minetest.global_exists("unified_inventory") then
unified_inventory.register_button("edit_skin", {
type = "image",
image = "edit_skin_button.png",
tooltip = S("Edit Skin"),
action = function(player)
edit_skin.show_formspec(player)
end,
})
end
if minetest.global_exists("armor") and armor.get_player_skin then
armor.get_player_skin = function(armor, name)
return edit_skin.compile_skin(edit_skin.player_skins[minetest.get_player_by_name(name)])
end
end
if minetest.global_exists("inventory_plus") then
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == "" and fields.edit_skin then
edit_skin.show_formspec(player)
return true
end
return false
end)
end
if minetest.global_exists("smart_inventory") then
smart_inventory.register_page({
name = "skin_edit",
icon = "edit_skin_button.png",
tooltip = S("Edit Skin"),
smartfs_callback = function(state) return end,
sequence = 100,
on_button_click = function(state)
local player = minetest.get_player_by_name(state.location.rootState.location.player)
edit_skin.show_formspec(player)
end,
is_visible_func = function(state) return true end,
})
end
end
init()

349
list.json Normal file
View file

@ -0,0 +1,349 @@
[
{
"type": "footwear",
"texture": "edit_skin_footwear_1.png",
"steve": true,
"alex": true,
"rank": 55
},
{
"type": "footwear",
"texture": "edit_skin_footwear_2.png"
},
{
"type": "footwear",
"texture": "edit_skin_footwear_3.png"
},
{
"type": "footwear",
"texture": "edit_skin_footwear_4.png",
"rank": 55
},
{
"type": "footwear"
},
{
"type": "eye",
"texture": "edit_skin_eye_1.png"
},
{
"type": "eye",
"texture": "edit_skin_eye_2.png"
},
{
"type": "eye",
"texture": "edit_skin_eye_3.png"
},
{
"type": "eye",
"texture": "edit_skin_eye_4.png"
},
{
"type": "eye",
"texture": "edit_skin_eye_5.png",
"steve": true,
"alex": true
},
{
"type": "eye",
"texture": "edit_skin_eye_6.png"
},
{
"type": "eye",
"texture": "edit_skin_eye_7.png"
},
{
"type": "mouth",
"texture": "edit_skin_mouth_1.png",
"steve": true
},
{
"type": "mouth",
"texture": "edit_skin_mouth_2.png"
},
{
"type": "mouth",
"texture": "edit_skin_mouth_3.png"
},
{
"type": "mouth",
"texture": "edit_skin_mouth_4.png"
},
{
"type": "mouth",
"texture": "edit_skin_mouth_5.png"
},
{
"type": "mouth",
"texture": "edit_skin_mouth_6.png"
},
{
"type": "mouth",
"texture": "edit_skin_mouth_7.png",
"alex": true
},
{
"type": "mouth"
},
{
"type": "hair",
"texture": "edit_skin_hair_1.png",
"mask": "edit_skin_hair_1_mask.png"
},
{
"type": "hair",
"texture": "edit_skin_hair_2.png",
"mask": "edit_skin_hair_2_mask.png"
},
{
"type": "hair",
"texture": "edit_skin_hair_3.png",
"mask": "edit_skin_hair_3_mask.png"
},
{
"type": "hair",
"texture": "edit_skin_hair_4.png",
"mask": "edit_skin_hair_4_mask.png"
},
{
"type": "hair",
"texture": "edit_skin_hair_5.png",
"mask": "edit_skin_hair_5_mask.png"
},
{
"type": "hair",
"texture": "edit_skin_hair_6.png",
"mask": "edit_skin_hair_6_mask.png"
},
{
"type": "hair",
"texture": "edit_skin_hair_7.png",
"mask": "edit_skin_hair_7_mask.png"
},
{
"type": "hair",
"texture": "edit_skin_hair_8.png",
"mask": "edit_skin_hair_8_mask.png"
},
{
"type": "hair",
"texture": "edit_skin_hair_9.png",
"mask": "edit_skin_hair_9_mask.png"
},
{
"type": "hair",
"texture": "edit_skin_hair_10.png",
"mask": "edit_skin_hair_10_mask.png",
"steve": true
},
{
"type": "hair",
"texture": "edit_skin_hair_11.png",
"mask": "edit_skin_hair_11_mask.png",
"alex": true
},
{
"type": "hair",
"texture": "edit_skin_hair_12.png",
"mask": "edit_skin_hair_12_mask.png"
},
{
"type": "hair"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_1.png"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_2.png"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_3.png"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_4.png"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_5.png"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_6.png",
"preview_rotation": {
"x": -10,
"y": 200
}
},
{
"type": "headwear",
"texture": "edit_skin_headwear_7.png"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_8.png",
"restricted_to_admin": true
},
{
"type": "headwear",
"texture": "edit_skin_headwear_9.png"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_10.png"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_11.png"
},
{
"type": "headwear",
"texture": "edit_skin_headwear_12.png"
},
{
"type": "headwear",
"steve": true,
"alex": true
},
{
"type": "bottom",
"texture": "edit_skin_bottom_1.png",
"mask": "edit_skin_bottom_1_mask.png"
},
{
"type": "bottom",
"texture": "edit_skin_bottom_2.png",
"mask": "edit_skin_bottom_2_mask.png"
},
{
"type": "bottom",
"texture": "edit_skin_bottom_3.png",
"mask": "edit_skin_bottom_3_mask.png"
},
{
"type": "bottom",
"texture": "edit_skin_bottom_4.png",
"mask": "edit_skin_bottom_4_mask.png",
"steve": true,
"alex": true
},
{
"type": "bottom",
"texture": "edit_skin_bottom_5.png",
"mask": "edit_skin_bottom_5_mask.png",
"rank": 65
},
{
"type": "bottom",
"texture": "edit_skin_bottom_6.png",
"mask": "edit_skin_bottom_6_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_1.png",
"mask": "edit_skin_top_1_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_2.png",
"mask": "edit_skin_top_2_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_3.png",
"mask": "edit_skin_top_3_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_4.png",
"mask": "edit_skin_top_4_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_5.png",
"mask": "edit_skin_top_5_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_6.png",
"mask": "edit_skin_top_6_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_7.png",
"mask": "edit_skin_top_7_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_8.png",
"mask": "edit_skin_top_8_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_9.png",
"mask": "edit_skin_top_9_mask.png",
"alex": true
},
{
"type": "top",
"texture": "edit_skin_top_10.png",
"mask": "edit_skin_top_10_mask.png",
"steve": true
},
{
"type": "top",
"texture": "edit_skin_top_11.png",
"mask": "edit_skin_top_11_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_12.png",
"mask": "edit_skin_top_12_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_13.png",
"mask": "edit_skin_top_12_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_14.png",
"mask": "edit_skin_top_14_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_15.png",
"mask": "edit_skin_top_15_mask.png",
"rank": 85
},
{
"type": "top",
"texture": "edit_skin_top_16.png",
"mask": "edit_skin_top_16_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_17.png",
"mask": "edit_skin_top_17_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_18.png",
"mask": "edit_skin_top_18_mask.png"
},
{
"type": "top",
"texture": "edit_skin_top_19.png",
"mask": "edit_skin_top_19_mask.png"
},
{
"type": "base",
"texture": "edit_skin_base_1.png",
"mask": "edit_skin_base_1_mask.png",
"steve": true,
"alex": true
}
]

15
locale/edit_skin.de.tr Normal file
View file

@ -0,0 +1,15 @@
# textdomain: edit_skin
Edit Skin=Skins
Advanced player skin customization=Erweiterte Anpassung des Spieler-Skins
Templates=Vorlage
Bases=Hauttyp
Footwears=Schuhe
Eyes=Augen
Mouths=Mund
Bottoms=Hose
Tops=Oberteil
Hairs=Haare
Headwears=Hüte
Open skin configuration screen.=Öffnet den Skin-Editor.
Allows access to restricted skin items.=Erlaube Zugriff auf gesperrte Skin-Eigenschaften.
Select=Auswählen

15
locale/edit_skin.es.tr Normal file
View file

@ -0,0 +1,15 @@
# textdomain: edit_skin
Edit Skin=Modificar apariencia
Templates=Modelos
Arm size=Brazos
Bases=Piel
Footwears=Calzado
Eyes=Ojos
Mouths=Boca
Bottoms=Piernas
Tops=Torso
Hairs=Pelo
Headwears=Cabeza
Open skin configuration screen.=Abrir configuración de apariencia.
Allows access to restricted skin items.=Permite acceder a elementos restringidos.
Select=Seleccionar

13
locale/edit_skin.fr.tr Normal file
View file

@ -0,0 +1,13 @@
# textdomain: edit_skin
Templates=Modèles
Arm size=Taille des bras
Bases=Teint
Footwears=Chaussures
Eyes=Yeux
Mouths=Bouches
Bottoms=Bas
Tops=Haut
Hairs=Cheveux
Headwears=Coiffe
Open skin configuration screen.=Ouvrir l'écran de configuration du costume.
Select=Sélectionner

14
locale/edit_skin.ja.tr Normal file
View file

@ -0,0 +1,14 @@
# textdomain: edit_skin
Skins=スキン
Templates=テンプレート
Arm size=腕の大きさ
Bases=ベース
Footwears=靴
Eyes=目
Mouths=口
Bottoms=下衣
Tops=上衣
Hairs=髪
Headwears=帽子
Open skin configuration screen.=スキン設定画面を開きます。
Select=選択

14
locale/edit_skin.ru.tr Normal file
View file

@ -0,0 +1,14 @@
# textdomain: edit_skin
Edit Skin=Ред. скин
Templates=Шаблоны
Bases=Основы
Footwears=Обувь
Eyes=Глаза
Mouths=Рот
Bottoms=Нижние части
Tops=Верхние части
Hairs=Волосы
Headwears=Голвные уборы
Open skin configuration screen.=Открыть окно настройки скина.
Allows access to restricted skin items.=Открывает доступ к ограниченным вариантам кожи.
Select=Выбрать

15
locale/edit_skin.uk.tr Normal file
View file

@ -0,0 +1,15 @@
# textdomain: edit_skin
Edit Skin=Редактор Персонажа
Advanced player skin customization=Просунуте налаштування зовнішнього вигляду гравця
Templates=Шаблони
Bases=Основи
Footwears=Взуття
Eyes=Очі
Mouths=Роти
Bottoms=Нижня частина
Tops=Верхня частина
Hairs=Волосся
Headwears=Головний убір
Open skin configuration screen.=Відкрити вікно редагування персонажа.
Allows access to restricted skin items.=Відкриває доступ до заборонених предметів персонажа.
Select=Обрати

14
locale/template.txt Normal file
View file

@ -0,0 +1,14 @@
# textdomain: edit_skin
Edit Skin=
Templates=
Bases=
Footwears=
Eyes=
Mouths=
Bottoms=
Tops=
Hairs=
Headwears=
Open skin configuration screen.=
Allows access to restricted skin items.=
Select=

136
media_credits.txt Normal file
View file

@ -0,0 +1,136 @@
edit_skin_base_1.png
edit_skin_button.png
edit_skin_footwear_3.png
edit_skin_headwear_1.png
edit_skin_headwear_3.png
edit_skin_headwear_4.png
edit_skin_headwear_5.png
edit_skin_headwear_8.png
edit_skin_headwear_9.png
edit_skin_headwear_10.png
edit_skin_headwear_11.png
edit_skin_headwear_12.png
edit_skin_mouth_2.png
edit_skin_mouth_3.png
edit_skin_mouth_4.png
edit_skin_mouth_5.png
edit_skin_select_overlay.png
edit_skin_top_2.png
edit_skin_top_5.png
edit_skin_eye_5.png
edit_skin_hair_8.png
edit_skin_top_6.png
edit_skin_bottom_3.png
edit_skin_eye_7.png
edit_skin_mouth_7.png
edit_skin_hair_6.png
edit_skin_eye_6.png
edit_skin_top_11.png
edit_skin_top_12.png
edit_skin_top_13.png
edit_skin_top_14.png
edit_skin_top_15.png
edit_skin_bottom_5.png
edit_skin_hair_12.png
edit_skin_top_16.png
edit_skin_top_17.png
edit_skin_icons.png
edit_skin_footwear_4.png
Original work by MrRar
License: CC BY-SA 4.0
edit_skin_top_1.png
edit_skin_mouth_1.png
edit_skin_hair_1.png
edit_skin_hair_2.png
edit_skin_eye_1.png
edit_skin_eye_2.png
edit_skin_footwear_1.png
edit_skin_headwear_2.png
edit_skin_mouth_1.png
edit_skin_top_1.png
edit_skin_mouth_2.png
Name: Pixel Perfection resource pack for Minecraft 1.11
Author: XSSheep. Adapted for edit_skin by MrRar.
License: CC BY-SA 4.0
Source: https://www.planetminecraft.com/texture_pack/131pixel-perfection/
edit_skin_hair_3.png
edit_skin_eye_3.png
edit_skin_footwear_2.png
Name: the 10the doctor
Author: lovehart. Adapted for edit_skin by MrRar.
License: CC BY-SA 3.0
Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:367
edit_skin_hair_4.png
Blonde Girl
Author: Rin. Adapted for edit_skin by MrRar.
License: CC BY-SA 3.0
Source: http://minetest.fensta.bplaced.net/#id=918
edit_skin_hair_5.png
Name: hobbit from lottmob
Author: lovehart. Adapted for edit_skin by MrRar.
License: CC BY-SA 3.0
Source: http://minetest.fensta.bplaced.net/#id=336
edit_skin_top_4.png
Name: Oliver_MV
Author: hansuke123. Adapted for edit_skin by MrRar.
License: CC BY-SA 3.0
Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:291
edit_skin_eye_4.png
Name: lisa
Author: hansuke123
License: CC BY-SA 3.0
Source: http://minetest.fensta.bplaced.net/#!page:1,filtertype:Id,filter:88
edit_skin_headwear_7.png
Name: Ryu
Author: Ginsu23. Adapted for edit_skin by MrRar.
License: CC BY-SA 3.0
Source: http://minetest.fensta.bplaced.net/#id=464
edit_skin_top_8.png
Name: Hoodie Enderman
Author: Kpenguin. Adapted for edit_skin by MrRar.
License: CC BY-SA 3.0
Source: http://minetest.fensta.bplaced.net/#id=962
edit_skin_hair_9.png
Name: Trader 1
Author: TenPlus1. Adapted for edit_skin by MrRar.
License: CC BY-SA 3.0
Source: http://minetest.fensta.bplaced.net/#id=1258
edit_skin_bottom_4.png
edit_skin_top_9.png
edit_skin_top_10.png
edit_skin_hair_10.png
edit_skin_hair_11.png
Name: Pixel Perfection Legacy 1.19
Author: Nova_Wostra. Adapted for edit_skin by MrRar.
License: CC BY-SA 4.0
Source: https://www.planetminecraft.com/texture-pack/pixel-perfection-chorus-edit/
edit_skin_bottom.obj
edit_skin_head.obj
edit_skin_top.obj
Name: character.blend in player_api mod from Minetest Game
Author: celeron55, MirceaKitsune, Jordach, kilbith, sofar, xunto, Rogier-5, TeTpaAka, Desour, stujones11, An0n3m0us. Adapted for mcl_skins by MrRar.
License: CC BY-SA 3.0
Source: https://github.com/minetest/minetest_game
edit_skin_hand.obj
Name: Newhand Mod
Author: jordan4ibanez. Adapted for edit_skin by MrRar.
License: CC BY-SA 3.0
Source: https://forum.minetest.net/viewtopic.php?t=16435
edit_skin_top_18.png
Name: Duke v1
Author: Rael BlackRabbit. Adapted for edit_skin by MrRar.
License: CC BY-SA 4.0
Source: http://minetest.fensta.bplaced.net/#name=Duke%20v1

8
mod.conf Normal file
View file

@ -0,0 +1,8 @@
name = edit_skin
author = Mr. Rar
description = Advanced player skin customization
depends = player_api
min_minetest_version = 5.5
optional_depends = i3,i3_extrabuttons,sfinv,sfinv_buttons,unified_inventory,inventory_plus,smart_inventory,creative
release = 30155
title = Edit Skin

108
models/edit_skin_bottom.obj Normal file
View file

@ -0,0 +1,108 @@
# Blender v2.93.5 OBJ File: ''
# www.blender.org
mtllib bottom.mtl
o bottom
v -2.100000 4.358421 1.050001
v -2.100000 1.648314 1.049999
v 2.100000 1.648314 1.049999
v 2.100000 4.358421 1.050001
v -2.100000 1.648314 -1.050001
v -2.100000 4.358421 -1.049998
v 2.100000 1.648314 -1.050001
v 2.100000 4.358421 -1.049998
v 0.000000 1.648314 -1.050001
v 0.000000 -4.651686 -1.050003
v 0.000000 -4.651686 1.049997
v 0.000000 1.648314 1.049999
v 0.000000 -4.651686 -1.050003
v 0.000000 -4.651686 1.049997
v -2.100000 -4.651685 1.049997
v -2.100000 -4.651685 -1.050003
v -2.100000 1.648315 1.049999
v -2.100000 1.648315 -1.050001
v 0.000000 1.648314 1.049999
v 2.100000 1.648315 -1.050001
v 2.100000 -4.651685 -1.050003
v 0.000000 1.648314 -1.050001
v 2.100000 -4.651685 1.049997
v 2.100000 1.648315 1.049999
vt 0.500000 0.161316
vt 0.500000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.161316
vt 0.437500 0.000000
vt 0.437500 0.161316
vt 0.312500 0.000000
vt 0.312500 0.161316
vt 0.562500 0.375000
vt 0.562500 0.500000
vt 0.437500 0.500000
vt 0.437500 0.375000
vt 0.125000 0.375000
vt 0.125000 0.000000
vt 0.187500 0.000000
vt 0.187500 0.375000
vt 0.187500 0.375000
vt 0.187500 0.500000
vt 0.125000 0.500000
vt 0.125000 0.375000
vt 0.000000 0.375000
vt 0.062500 0.375000
vt 0.062500 0.000000
vt 0.000000 0.000000
vt 0.187500 0.375000
vt 0.250000 0.375000
vt 0.250000 0.000000
vt 0.187500 0.000000
vt 0.062500 0.375000
vt 0.062500 0.000000
vt 0.125000 0.375000
vt 0.125000 0.000000
vt 0.250000 0.000000
vt 0.250000 0.375000
vt 0.000000 0.375000
vt 0.000000 0.000000
vt 0.250000 0.161316
vt 0.250000 0.000000
vt 0.125000 0.375000
vt 0.125000 0.500000
vt 0.062500 0.500000
vt 0.062500 0.375000
vt 0.187500 0.375000
vt 0.125000 0.375000
vt 0.125000 0.500000
vt 0.187500 0.500000
vt 0.125000 0.375000
vt 0.062500 0.375000
vt 0.062500 0.500000
vt 0.125000 0.500000
vt 0.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 1.000000
vn 0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 -1.0000 -0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Character
s 1
f 1/1/1 2/2/1 3/3/1 4/4/1
f 5/5/2 2/2/2 1/1/2 6/6/2
f 7/7/3 5/5/3 6/6/3 8/8/3
f 7/9/4 3/10/4 2/11/4 5/12/4
f 9/13/2 10/14/2 11/15/2 12/16/2
f 13/17/4 14/18/4 15/19/4 16/20/4
f 17/21/2 18/22/2 16/23/2 15/24/2
f 19/25/1 17/26/1 15/27/1 14/28/1
f 20/29/3 21/30/3 10/14/3 9/13/3
f 18/22/3 22/31/3 13/32/3 16/23/3
f 12/16/1 11/15/1 23/33/1 24/34/1
f 22/31/5 19/25/5 14/28/5 13/32/5
f 24/35/5 23/36/5 21/30/5 20/29/5
f 4/37/5 3/38/5 7/7/5 8/8/5
f 18/39/6 17/40/6 19/41/6 22/42/6
f 10/43/4 21/44/4 23/45/4 11/46/4
f 20/47/6 9/48/6 12/49/6 24/50/6
f 4/51/6 8/52/6 6/53/6 1/54/6

42
models/edit_skin_hand.obj Normal file
View file

@ -0,0 +1,42 @@
# Blender v2.93.5 OBJ File: ''
# www.blender.org
mtllib edit_skin_hand.mtl
o Player_Cube
v -0.297523 0.244203 -0.255826
v 0.194758 0.166759 -0.215068
v 0.147194 0.125461 0.280948
v -0.345088 0.202905 0.240190
v -0.545452 -1.417096 -0.417921
v -0.053170 -1.494540 -0.377162
v -0.100734 -1.535838 0.118854
v -0.593016 -1.458394 0.078095
vt 0.750000 0.375000
vt 0.812500 0.375000
vt 0.812500 0.500000
vt 0.750000 0.500000
vt 0.687500 0.375000
vt 0.750000 0.375000
vt 0.750000 0.500000
vt 0.687500 0.500000
vt 0.625000 0.375000
vt 0.625000 0.000000
vt 0.687500 0.000000
vt 0.750000 0.000000
vt 0.812500 0.000000
vt 0.812500 0.375000
vt 0.875000 0.000000
vt 0.875000 0.375000
vn 0.1469 0.9845 0.0961
vn -0.1469 -0.9845 -0.0961
vn -0.0951 -0.0826 0.9920
vn -0.9846 0.1549 -0.0815
vn 0.0951 0.0826 -0.9920
vn 0.9846 -0.1549 0.0815
usemtl Character
s off
f 1/1/1 4/2/1 3/3/1 2/4/1
f 8/5/2 5/6/2 6/7/2 7/8/2
f 7/9/3 3/10/3 4/11/3 8/5/3
f 8/5/4 4/11/4 1/12/4 5/6/4
f 5/6/5 1/12/5 2/13/5 6/14/5
f 6/14/6 2/13/6 3/15/6 7/16/6

72
models/edit_skin_head.obj Normal file
View file

@ -0,0 +1,72 @@
# Blender v2.93.5 OBJ File: ''
# www.blender.org
mtllib head.mtl
o head
v -2.100000 -2.100004 2.099999
v 2.100000 2.099997 -2.100001
v 2.100000 2.099997 2.099999
v 2.300000 -2.300003 -2.300001
v 2.300000 2.299997 2.299999
v 2.100000 -2.100004 2.099999
v 2.100000 -2.100004 -2.100001
v -2.100000 2.099997 2.099999
v -2.100000 2.099997 -2.100001
v -2.100000 -2.100004 -2.100001
v 2.300000 2.299997 -2.300001
v 2.300000 -2.300003 2.299999
v -2.300000 2.299997 2.299999
v -2.300000 -2.300003 2.299999
v -2.300000 2.299997 -2.300001
v -2.300000 -2.300003 -2.300001
vt 0.500000 0.750000
vt 0.375000 0.750000
vt 0.375000 0.500000
vt 0.500000 0.500000
vt 0.250000 0.750000
vt 0.250000 0.500000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.375000 0.750000
vt 0.375000 1.000000
vt 0.250000 1.000000
vt 0.250000 0.750000
vt 0.250000 1.000000
vt 0.125000 1.000000
vt 0.000000 0.750000
vt 0.000000 0.500000
vt 1.000000 0.750000
vt 0.875000 0.750000
vt 0.875000 0.500000
vt 1.000000 0.500000
vt 0.750000 0.750000
vt 0.750000 0.500000
vt 0.625000 0.750000
vt 0.625000 0.500000
vt 0.875000 0.750000
vt 0.875000 1.000000
vt 0.750000 1.000000
vt 0.750000 0.750000
vt 0.750000 1.000000
vt 0.625000 1.000000
vt 0.500000 0.750000
vt 0.500000 0.500000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
vn 1.0000 0.0000 0.0000
usemtl Character
s off
f 3/1/1 8/2/1 1/3/1 6/4/1
f 8/2/2 9/5/2 10/6/2 1/3/2
f 9/5/3 2/7/3 7/8/3 10/6/3
f 7/9/4 6/10/4 1/11/4 10/12/4
f 9/5/5 8/13/5 3/14/5 2/7/5
f 3/15/6 6/16/6 7/8/6 2/7/6
f 5/17/1 13/18/1 14/19/1 12/20/1
f 13/18/2 15/21/2 16/22/2 14/19/2
f 15/21/3 11/23/3 4/24/3 16/22/3
f 4/25/4 12/26/4 14/27/4 16/28/4
f 15/21/5 13/29/5 5/30/5 11/23/5
f 5/31/6 12/32/6 4/24/6 11/23/6

174
models/edit_skin_top.obj Normal file
View file

@ -0,0 +1,174 @@
# Blender v2.93.5 OBJ File: ''
# www.blender.org
mtllib top.mtl
o top
v -2.100000 -3.149994 1.049999
v -2.100000 -3.149994 -1.050001
v -2.100000 3.150004 1.049999
v -2.100000 3.150004 -1.050001
v -4.200000 3.150003 -1.050001
v -4.200000 3.150003 1.049999
v -2.100000 3.150003 1.049999
v -2.100000 3.150003 -1.050001
v -4.200000 -3.149994 -1.050001
v -4.200000 -3.149994 1.049999
v -2.100000 -3.149994 1.049999
v -2.100000 -3.149994 -1.050001
v 2.100000 -3.149994 -1.050001
v 2.100000 -3.149994 1.049999
v 2.100000 3.150004 -1.050001
v 2.100000 3.150004 1.049999
v 2.100000 -3.149994 -1.050001
v 2.100000 -3.149994 1.049999
v 4.200000 -3.149994 1.049999
v 4.200000 -3.149994 -1.050001
v 2.100000 3.150003 -1.050001
v 2.100000 3.150003 1.049999
v 4.200000 3.150003 1.049999
v 4.200000 3.150003 -1.050001
v 2.100000 3.150004 -1.050001
v 2.100000 3.150004 -1.050001
v 2.100000 3.150004 1.049999
v 2.100000 3.150004 1.049999
v 2.100000 -3.149994 1.049999
v 2.100000 -3.149994 1.049999
v 2.100000 -3.149994 -1.050001
v 2.100000 -3.149994 -1.050001
v -2.100000 3.150004 1.049999
v -2.100000 3.150004 1.049999
v -2.100000 -3.149994 1.049999
v -2.100000 -3.149994 1.049999
v -2.100000 3.150004 -1.050001
v -2.100000 3.150004 -1.050001
v -2.100000 -3.149994 -1.050001
v -2.100000 -3.149994 -1.050001
v -4.200000 3.150003 -1.050001
v -4.200000 3.150003 -1.050001
v -4.200000 -3.149994 -1.050001
v -4.200000 -3.149994 -1.050001
v -2.100000 3.150003 1.049999
v -2.100000 3.150003 1.049999
v -2.100000 -3.149994 1.049999
v -2.100000 -3.149994 1.049999
v -4.200000 3.150003 1.049999
v -4.200000 3.150003 1.049999
v -4.200000 -3.149994 1.049999
v -4.200000 -3.149994 1.049999
v -2.100000 3.150003 -1.050001
v -2.100000 3.150003 -1.050001
v -2.100000 -3.149994 -1.050001
v -2.100000 -3.149994 -1.050001
v 2.100000 3.150003 -1.050001
v 2.100000 3.150003 -1.050001
v 2.100000 3.150003 1.049999
v 2.100000 3.150003 1.049999
v 2.100000 -3.149994 1.049999
v 2.100000 -3.149994 1.049999
v 2.100000 -3.149994 -1.050001
v 2.100000 -3.149994 -1.050001
v 4.200000 3.150003 1.049999
v 4.200000 3.150003 1.049999
v 4.200000 -3.149994 1.049999
v 4.200000 -3.149994 1.049999
v 4.200000 3.150003 -1.050001
v 4.200000 3.150003 -1.050001
v 4.200000 -3.149994 -1.050001
v 4.200000 -3.149994 -1.050001
vt 0.625000 0.375000
vt 0.500000 0.375000
vt 0.500000 0.000000
vt 0.625000 0.000000
vt 0.500000 0.375000
vt 0.437500 0.375000
vt 0.437500 0.000000
vt 0.500000 0.000000
vt 0.437500 0.375000
vt 0.312500 0.375000
vt 0.312500 0.000000
vt 0.437500 0.000000
vt 0.562500 0.375000
vt 0.562500 0.500000
vt 0.437500 0.500000
vt 0.437500 0.375000
vt 0.437500 0.375000
vt 0.437500 0.500000
vt 0.312500 0.500000
vt 0.312500 0.375000
vt 0.812500 0.375000
vt 0.875000 0.375000
vt 0.875000 0.000000
vt 0.812500 0.000000
vt 0.750000 0.375000
vt 0.812500 0.375000
vt 0.812500 0.000000
vt 0.750000 0.000000
vt 0.750000 0.375000
vt 0.812500 0.375000
vt 0.812500 0.500000
vt 0.750000 0.500000
vt 0.687500 0.375000
vt 0.750000 0.375000
vt 0.750000 0.500000
vt 0.687500 0.500000
vt 0.250000 0.375000
vt 0.250000 0.000000
vt 0.312500 0.000000
vt 0.312500 0.375000
vt 0.687500 0.375000
vt 0.750000 0.375000
vt 0.750000 0.000000
vt 0.687500 0.000000
vt 0.625000 0.375000
vt 0.687500 0.375000
vt 0.687500 0.000000
vt 0.625000 0.000000
vt 0.625000 0.375000
vt 0.625000 0.000000
vt 0.687500 0.000000
vt 0.687500 0.375000
vt 0.687500 0.375000
vt 0.687500 0.500000
vt 0.750000 0.500000
vt 0.750000 0.375000
vt 0.687500 0.375000
vt 0.687500 0.000000
vt 0.750000 0.000000
vt 0.750000 0.375000
vt 0.750000 0.375000
vt 0.750000 0.000000
vt 0.812500 0.000000
vt 0.812500 0.375000
vt 0.750000 0.375000
vt 0.750000 0.500000
vt 0.812500 0.500000
vt 0.812500 0.375000
vt 0.812500 0.375000
vt 0.812500 0.000000
vt 0.875000 0.000000
vt 0.875000 0.375000
vn -0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
vn 1.0000 0.0000 0.0000
usemtl Character
s off
f 27/1/1 3/2/1 1/3/1 14/4/1
f 33/5/2 4/6/2 2/7/2 35/8/2
f 37/9/3 25/10/3 31/11/3 39/12/3
f 13/13/4 29/14/4 36/15/4 40/16/4
f 38/17/5 34/18/5 16/19/5 15/20/5
f 7/21/1 6/22/1 10/23/1 11/24/1
f 8/25/6 45/26/6 47/27/6 12/28/6
f 17/29/4 20/30/4 19/31/4 18/32/4
f 24/33/5 21/34/5 22/35/5 23/36/5
f 28/37/6 30/38/6 32/39/6 26/40/6
f 5/41/3 53/42/3 55/43/3 9/44/3
f 49/45/2 41/46/2 43/47/2 51/48/2
f 65/49/6 67/50/6 71/51/6 69/52/6
f 42/53/5 50/54/5 46/55/5 54/56/5
f 70/57/3 72/58/3 63/59/3 57/60/3
f 58/61/2 64/62/2 61/63/2 59/64/2
f 56/65/4 48/66/4 52/67/4 44/68/4
f 60/69/1 62/70/1 68/71/1 66/72/1

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Some files were not shown because too many files have changed in this diff Show more