mirror of
https://github.com/RuthAndRoth/Ruth2.git
synced 2026-08-14 09:02:22 +00:00
Add shape slider exports
The get-sliders.py script extracts slider values for shape, eyes and hair from the avatar appearance XML file. Additionally the shape sliders can be separated into head and body to allow importing one or the other on top of an existing shape. Signed-off-by: Serie Sumei <seriesumei@avimail.org>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
# Shape Imports
|
||||
|
||||
Three of the four required wearables (shape, hair, eyes) on an avatar are included in the XML file when saving avatar appearance. By extracting the slider values from the appearance XML we can create XML files suitable for import into a new or existing wearable.
|
||||
|
||||
Export avatar appearance via Firestorm menu Developer -> Avatar -> Character Tests -> Appearance To XML
|
||||
|
||||
When working with mesh heads and bodies it is often desirable to be able to copy the sliders for one or the other into a new shap, such as when trying out a new mesh head, you want your usual body sliders. We can split the shape sliders into head and body subsets and create an XML file that can easily be imported to merge existing sliders into a new shape.
|
||||
|
||||
These import XML files are also suitable for checking into the git repository as a record of the shapes shipped with Ruth. Creating a shape from the in-world is as simple as making a new default shape (or hair or eyes) and importing the XML files on top of that. The shape wearable is stored here as separate head and body files so they may also be used individually.
|
||||
|
||||
## Extraction Script
|
||||
|
||||
The python script ``get-sliders.py`` extracts specific subsets of the appearance XML file. It supports the following options:
|
||||
|
||||
* ``--shape``
|
||||
Extract all of the shape sliders
|
||||
* ``--head``
|
||||
Extract the set of shape sliders that correspond to the avatar head
|
||||
* ``--body``
|
||||
Extract the set of shape sliders that correspond to the avatar body
|
||||
* ``--hair``
|
||||
Extract all of the hair sliders
|
||||
* ``--eyes``
|
||||
Extract all of the eye sliders
|
||||
|
||||
### Installation
|
||||
|
||||
This script was written and tested using Python 3. It has a single external dependency:
|
||||
|
||||
* lxml
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" ?>
|
||||
<linden_genepool version="1.0">
|
||||
<archetype name="???">
|
||||
<param id="33" name="height" display="Height" value="0.000" u8="136" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="34" name="thickness" display="Body Thickness" value="0.000" u8="81" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="36" name="shoulders" display="Shoulders" value="-0.500" u8="103" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="37" name="hip width" display="Hip Width" value="0.000" u8="136" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="38" name="torso length" display="Torso Length" value="0.000" u8="127" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="80" name="male" display="male" value="0.000" u8="0" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="105" name="breast size" display="Breast Size" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="151" name="big_butt_legs" display="Butt Size" value="0.000" u8="0" type="param_morph" wearable="shape" group="1"/>
|
||||
<param id="152" name="muscular_legs" display="Leg Muscles" value="0.000" u8="0" type="param_morph" wearable="shape" group="1"/>
|
||||
<param id="157" name="belly size" display="Belly Size" value="0.000" u8="0" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="507" name="breast_gravity" display="Breast Buoyancy" value="0.000" u8="109" type="param_morph" wearable="shape" group="0"/>
|
||||
<param id="515" name="foot_size" display="Foot Size" value="0.000" u8="63" type="param_morph" wearable="shape" group="0"/>
|
||||
<param id="637" name="body fat" display="Body Fat" value="0.000" u8="0" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="649" name="torso muscles" display="Torso Muscles" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="675" name="hand size" display="Hand Size" value="0.000" u8="127" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="676" name="love_handles" display="Love Handles" value="0.000" u8="85" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="683" name="neck thickness" display="Neck Thickness" value="-0.150" u8="106" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="684" name="breast_female_cleavage" display="Breast Cleavage" value="0.000" u8="47" type="param_morph" wearable="shape" group="0"/>
|
||||
<param id="692" name="leg length" display="Leg Length" value="0.000" u8="127" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="693" name="arm length" display="Arm Length" value="0.600" u8="204" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="753" name="saddlebags" display="Saddle Bags" value="0.000" u8="36" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="756" name="neck length" display="Neck Length" value="0.000" u8="127" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="841" name="bowed_legs" display="Knee Angle" value="0.000" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="842" name="hip length" display="Hip Length" value="0.000" u8="127" type="param_skeleton" wearable="shape" group="0"/>
|
||||
<param id="11001" name="hover" display="Hover" value="0.000" u8="127" type="param_skeleton" wearable="shape" group="0"/>
|
||||
</archetype>
|
||||
</linden_genepool>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" ?>
|
||||
<linden_genepool version="1.0">
|
||||
<archetype name="???">
|
||||
<param id="98" name="eye lightness" display="Eye Lightness" value="0.100" u8="25" type="param_color" wearable="eyes" group="0"/>
|
||||
<param id="99" name="eye color" display="Eye Color" value="0.500" u8="127" type="param_color" wearable="eyes" group="0"/>
|
||||
</archetype>
|
||||
</linden_genepool>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" ?>
|
||||
<linden_genepool version="1.0">
|
||||
<archetype name="???">
|
||||
<param id="16" name="pointy_eyebrows" display="Eyebrow Points" value="0.000" u8="36" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="31" name="arced_eyebrows" display="Eyebrow Arc" value="0.500" u8="63" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="112" name="rainbow color" display="Rainbow Color" value="0.000" u8="0" type="param_color" wearable="hair" group="0"/>
|
||||
<param id="113" name="red hair" display="Red Hair" value="0.000" u8="0" type="param_color" wearable="hair" group="0"/>
|
||||
<param id="114" name="blonde hair" display="Blonde Hair" value="0.500" u8="127" type="param_color" wearable="hair" group="0"/>
|
||||
<param id="115" name="white hair" display="White Hair" value="0.000" u8="0" type="param_color" wearable="hair" group="0"/>
|
||||
<param id="119" name="eyebrow size" display="Eyebrow Size" value="0.500" u8="127" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="130" name="front fringe" display="Front Fringe" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="131" name="side fringe" display="Side Fringe" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="132" name="back fringe" display="Back Fringe" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="133" name="hair front" display="Hair Front" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="134" name="hair sides" display="Hair Sides" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="135" name="hair back" display="Hair Back" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="136" name="hair sweep" display="Hair Sweep" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="137" name="hair tilt" display="Hair Tilt" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="140" name="hair_part_middle" display="Middle Part" value="0.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="141" name="hair_part_right" display="Right Part" value="0.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="142" name="hair_part_left" display="Left Part" value="0.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="143" name="hair_sides_full" display="Full Hair Sides" value="-4.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="177" name="hair_rumpled" display="Rumpled Hair" value="0.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="181" name="hair_big_front" display="Big Hair Front" value="-1.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="182" name="hair_big_top" display="Big Hair Top" value="-1.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="183" name="hair_big_back" display="Big Hair Back" value="-1.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="184" name="hair_spiked" display="Spiked Hair" value="0.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="192" name="bangs_part_middle" display="Part Bangs" value="0.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="674" name="hair_shear_back" display="Shear Back" value="-1.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="750" name="eyebrow density" display="Eyebrow Density" value="0.700" u8="178" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="754" name="hair_taper_back" display="Taper Back" value="-1.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="755" name="hair_taper_front" display="Taper Front" value="-1.500" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="757" name="lower_eyebrows" display="Eyebrow Height" value="-1.000" u8="127" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="762" name="hair_shear_front" display="Shear Front" value="0.000" u8="0" type="param_morph" wearable="hair" group="0"/>
|
||||
<param id="763" name="hair volume" display="Hair Volume" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="785" name="pigtails" display="Pigtails" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
<param id="789" name="ponytail" display="Ponytail" value="0.000" u8="0" type="param_driver" wearable="hair" group="0"/>
|
||||
</archetype>
|
||||
</linden_genepool>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" ?>
|
||||
<linden_genepool version="1.0">
|
||||
<archetype name="???">
|
||||
<param id="1" name="big_brow" display="Brow Size" value="0.000" u8="33" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="2" name="nose_big_out" display="Nose Size" value="0.000" u8="61" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="4" name="broad_nostrils" display="Nostril Width" value="0.000" u8="85" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="5" name="cleft_chin" display="Chin Cleft" value="0.000" u8="23" type="param_morph" wearable="shape" group="0"/>
|
||||
<param id="6" name="bulbous_nose_tip" display="Nose Tip Shape" value="0.000" u8="58" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="7" name="weak_chin" display="Chin Angle" value="0.000" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="8" name="double_chin" display="Chin-Neck" value="0.000" u8="63" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="10" name="sunken_cheeks" display="Lower Cheeks" value="0.000" u8="85" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="11" name="noble_nose_bridge" display="Upper Bridge" value="0.000" u8="63" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="12" name="jowls" display="Jowls" value="0.000" u8="42" type="param_morph" wearable="shape" group="0"/>
|
||||
<param id="13" name="cleft_chin_upper" display="Upper Chin Cleft" value="0.000" u8="0" type="param_morph" wearable="shape" group="0"/>
|
||||
<param id="14" name="high_cheek_bones" display="Cheek Bones" value="0.000" u8="85" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="15" name="ears_out" display="Ear Angle" value="0.000" u8="63" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="17" name="square_jaw" display="Jaw Shape" value="0.000" u8="85" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="18" name="puffy_upper_cheeks" display="Upper Cheeks" value="0.000" u8="95" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="19" name="upturned_nose_tip" display="Nose Tip Angle" value="0.000" u8="153" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="20" name="bulbous_nose" display="Nose Thickness" value="0.000" u8="63" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="21" name="upper_eyelid_fold" display="Upper Eyelid Fold" value="0.000" u8="34" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="22" name="attached_earlobes" display="Attached Earlobes" value="0.000" u8="0" type="param_morph" wearable="shape" group="0"/>
|
||||
<param id="23" name="baggy_eyes" display="Eye Bags" value="0.000" u8="63" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="24" name="wide_eyes" display="Eye Opening" value="0.000" u8="109" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="25" name="wide_lip_cleft" display="Lip Cleft" value="0.000" u8="88" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="27" name="wide_nose_bridge" display="Bridge Width" value="0.000" u8="132" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="35" name="big_ears" display="Ear Size" value="0.000" u8="85" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="155" name="lip width" display="Lip Width" value="0.000" u8="104" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="185" name="deep_chin" display="Chin Depth" value="0.000" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="186" name="egg_head" display="Egg Head" value="0.000" u8="144" type="param_morph" wearable="shape" group="1"/>
|
||||
<param id="193" name="head shape" display="Head Shape" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="196" name="eye spacing" display="Eye Spacing" value="0.000" u8="170" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="505" name="lip thickness" display="Lip Thickness" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="506" name="mouth_height" display="Mouth Position" value="0.000" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="517" name="wide_nose" display="Nose Width" value="0.000" u8="85" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="518" name="eyelashes_long" display="Eyelash Length" value="0.000" u8="42" type="param_morph" wearable="shape" group="0"/>
|
||||
<param id="629" name="forehead angle" display="Forehead Angle" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="647" name="squash_stretch_head" display="Head Stretch" value="0.000" u8="85" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="650" name="eyelid_corner_up" display="Outer Eye Corner" value="0.000" u8="132" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="653" name="tall_lips" display="Lip Fullness" value="0.000" u8="85" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="656" name="crooked_nose" display="Crooked Nose" value="0.000" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="659" name="mouth corner" display="Mouth Corner" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="662" name="face shear" display="Face Shear" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="663" name="shift_mouth" display="Shift Mouth" value="0.000" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="664" name="pop_eye" display="Eye Pop" value="0.000" u8="127" type="param_morph" wearable="shape" group="0"/>
|
||||
<param id="665" name="jaw_jut" display="Jaw Jut" value="0.000" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="682" name="head size" display="Head Size" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="690" name="eye size" display="Eye Size" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="758" name="lower_bridge_nose" display="Lower Bridge" value="0.000" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="759" name="low_septum_nose" display="Nostril Division" value="0.500" u8="153" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="760" name="jaw_angle" display="Jaw Angle" value="0.000" u8="95" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="764" name="lip_cleft_deep" display="Lip Cleft Depth" value="0.000" u8="74" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="765" name="puffy_lower_lids" display="Puffy Eyelids" value="0.000" u8="27" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="769" name="eye depth" display="Eye Depth" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="773" name="head length" display="Head Length" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="796" name="pointy_ears" display="Ear Tips" value="0.000" u8="30" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="799" name="lip ratio" display="Lip Ratio" value="0.500" u8="127" type="param_driver" wearable="shape" group="0"/>
|
||||
<param id="880" name="eyelid_inner_corner_up" display="Inner Eye Corner" value="0.000" u8="132" type="param_driver" wearable="shape" group="0"/>
|
||||
</archetype>
|
||||
</linden_genepool>
|
||||
Executable
+453
@@ -0,0 +1,453 @@
|
||||
#!/usr/bin/env python
|
||||
# get-sliders.py
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright 2021 Serie Sumei
|
||||
|
||||
# Extract interesting attributes from exported shape XML files.
|
||||
|
||||
# Export avatar appearance via Firestorm's menu
|
||||
# Developer -> Avatar -> Character Tests -> Appearance To XML
|
||||
|
||||
# Run this to extract the slider values for the basic types: shape, hair, eyes
|
||||
# shape can also be split into head and body to simplify copying only a head
|
||||
# or body sliders to a new shape.
|
||||
|
||||
# The resulting XML files can be imported on top of an existing or a new shape.
|
||||
|
||||
# The --text option will display the slider values as showin in the edit
|
||||
# dialogs. This is useful for just getting the numbers.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import sys
|
||||
import traceback
|
||||
from xml.dom import minidom
|
||||
|
||||
from lxml import etree
|
||||
|
||||
CONSOLE_MESSAGE_FORMAT = '%(levelname)s: %(name)s %(message)s'
|
||||
DEFAULT_VERBOSE_LEVEL = 1
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
# --debug sets this True
|
||||
dump_stack_trace = False
|
||||
|
||||
MALE_TORSO = [
|
||||
678, # Torso Muscles (male)
|
||||
683, # Neck Thickness
|
||||
756, # Neck Length
|
||||
36, # Shoulders
|
||||
685, # Pectorals
|
||||
693, # Arm Length
|
||||
675, # Hand Size
|
||||
38, # Torso Length
|
||||
676, # Love Handles
|
||||
157, # Belly Size
|
||||
]
|
||||
MALE_LEGS = [
|
||||
152, # Leg Muscles
|
||||
692, # Leg Length
|
||||
37, # Hip Width
|
||||
842, # Hip Length
|
||||
151, # Butt Size
|
||||
879, # Package
|
||||
753, # Saddle Bags
|
||||
841, # Knee Angle
|
||||
515, # Foot Size
|
||||
]
|
||||
MALE_FACIAL = [
|
||||
752, # Hair Thickness
|
||||
166, # Sideburns
|
||||
167, # Moustache
|
||||
169, # Chin Curtains
|
||||
168, # Soulpatch
|
||||
]
|
||||
|
||||
BODY_SLIDERS = {
|
||||
"body": [
|
||||
33, # Height
|
||||
34, # Body Thickness
|
||||
637, # Body Fat
|
||||
11001, # Hover
|
||||
],
|
||||
"torso": [
|
||||
649, # Torso Muscles (female)
|
||||
683, # Neck Thickness
|
||||
756, # Neck Length
|
||||
36, # Shoulders
|
||||
105, # Breast Size
|
||||
507, # Breast Buoyancy
|
||||
684, # Breast Cleavage
|
||||
693, # Arm Length
|
||||
675, # Hand Size
|
||||
38, # Torso Length
|
||||
676, # Love Handles
|
||||
157, # Belly Size
|
||||
],
|
||||
"legs": [
|
||||
152, # Leg Muscles
|
||||
692, # Leg Length
|
||||
37, # Hip Width
|
||||
842, # Hip Length
|
||||
151, # Butt Size
|
||||
753, # Saddle Bags
|
||||
841, # Knee Angle
|
||||
515, # Foot Size
|
||||
],
|
||||
}
|
||||
|
||||
HEAD_SLIDERS = {
|
||||
"head": [
|
||||
682, # Head Size
|
||||
647, # Head Stretch
|
||||
193, # Head Shape
|
||||
186, # Egg Head 646?
|
||||
773, # Head Length
|
||||
662, # Face Shear
|
||||
629, # Forehead Angle
|
||||
1, # Brow Size
|
||||
18, # Upper Cheeks
|
||||
10, # Lower Cheeks
|
||||
14, # Cheek Bones
|
||||
],
|
||||
"eyes": [
|
||||
690, # Eye Size
|
||||
24, # Eye Opening
|
||||
196, # Eye Spacing
|
||||
650, # Outer Eye Corner
|
||||
880, # Inner Eye Corner
|
||||
769, # Eye Depth
|
||||
21, # Upper Eyelid Fold
|
||||
23, # Eye Bags
|
||||
765, # Puffy Eyelids
|
||||
518, # Eyelash Length
|
||||
664, # Eye Pop
|
||||
],
|
||||
"ears": [
|
||||
35, # Ear Size
|
||||
15, # Ear Angle
|
||||
22, # Attached Earlobes
|
||||
796, # Ear Tips
|
||||
],
|
||||
"nose": [
|
||||
2, # Nose Size
|
||||
517, # Nose Width
|
||||
4, # Nostril Width
|
||||
759, # Nosrtil Division
|
||||
20, # Nose Thickness
|
||||
11, # Upper Bridge
|
||||
758, # Lower Bridge
|
||||
27, # Bridge Width
|
||||
19, # Nose Tip Angle
|
||||
6, # Nose Tip Shape
|
||||
656, # Crooked Nose
|
||||
],
|
||||
"mouth": [
|
||||
155, # Lip Width
|
||||
653, # Lip Fullness
|
||||
505, # Lip Thickness
|
||||
799, # Lip Ratio
|
||||
506, # Mouth Position
|
||||
659, # Mouth Corner
|
||||
764, # Lip Cleft Depth
|
||||
25, # Lip Cleft
|
||||
663, # Shift Mouth
|
||||
],
|
||||
"chin": [
|
||||
7, # Chin Angle
|
||||
17, # Jaw Shape
|
||||
185, # Chin Depth
|
||||
760, # Jaw Angle
|
||||
665, # Jaw Jut
|
||||
12, # Jowls
|
||||
5, # Chin Cleft
|
||||
13, # Upper Chin Cleft
|
||||
8, # Chin-Neck
|
||||
],
|
||||
}
|
||||
|
||||
HAIR_SLIDERS = {
|
||||
"color": [
|
||||
115, # White Hair
|
||||
112, # Rainbow Color
|
||||
114, # Blonde Hair
|
||||
113, # Red Hair
|
||||
],
|
||||
"style": [
|
||||
763, # Hair: Volume
|
||||
133, # Hair: Front
|
||||
134, # Hair: Sides
|
||||
135, # Hair: Back
|
||||
181, # Big Hair: Front
|
||||
182, # Big Hair: Top
|
||||
183, # Big Hair: Back
|
||||
130, # Front Fringe
|
||||
131, # Side Fringe
|
||||
132, # Back Fringe
|
||||
143, # Full Hair Sides
|
||||
136, # Hair Sweep
|
||||
762, # Shear Front
|
||||
674, # Shear Back
|
||||
755, # Taper Front
|
||||
754, # Taper Back
|
||||
177, # Rumpled Hair
|
||||
785, # Pigtails
|
||||
789, # Ponytail
|
||||
184, # Spiked Hair
|
||||
137, # Hair Tilt
|
||||
140, # Middle Part
|
||||
141, # Right Part
|
||||
142, # Left Part
|
||||
192, # Part Bangs
|
||||
],
|
||||
"eyebrows": [
|
||||
119, # Eyebrow Size
|
||||
750, # Eyebrow Density
|
||||
757, # Eyebrow Height
|
||||
31, # Eyebrow Arc
|
||||
16, # Eyebrow Points
|
||||
],
|
||||
"facial": [
|
||||
],
|
||||
}
|
||||
|
||||
EYE_SLIDERS = {
|
||||
"eyes": [
|
||||
99, # Eye Color
|
||||
98, # Eye Lightness
|
||||
]
|
||||
}
|
||||
|
||||
def is_male(doc):
|
||||
male = doc.find('.//param[@id="80"][@wearable="shape"]')
|
||||
return (male.get("u8") == "255")
|
||||
|
||||
def do_shape(opts):
|
||||
name = opts.rest[0]
|
||||
root = etree.parse(name)
|
||||
etree.indent(root, space=" ")
|
||||
|
||||
# Make adjustments for gender attributes
|
||||
male_shape = is_male(root)
|
||||
if male_shape:
|
||||
# Stuff the male attributes into the dicts
|
||||
BODY_SLIDERS['torso'] = MALE_TORSO
|
||||
BODY_SLIDERS['legs'] = MALE_LEGS
|
||||
HAIR_SLIDERS['facial'] = MALE_FACIAL
|
||||
|
||||
if opts.body:
|
||||
wearable = "shape"
|
||||
sliders = BODY_SLIDERS
|
||||
elif opts.eyes:
|
||||
wearable = "eyes"
|
||||
sliders = EYE_SLIDERS
|
||||
elif opts.hair:
|
||||
wearable = "hair"
|
||||
sliders = HAIR_SLIDERS
|
||||
elif opts.head:
|
||||
wearable = "shape"
|
||||
sliders = HEAD_SLIDERS
|
||||
elif opts.shape:
|
||||
wearable = "shape"
|
||||
sliders = HEAD_SLIDERS
|
||||
sliders.update(BODY_SLIDERS)
|
||||
else:
|
||||
wearable = "shape"
|
||||
sliders = HEAD_SLIDERS
|
||||
sliders.update(BODY_SLIDERS)
|
||||
sliders.update(HAIR_SLIDERS)
|
||||
sliders.update(EYE_SLIDERS)
|
||||
|
||||
# Create the new output document
|
||||
doc = etree.Element('linden_genepool', {'version': '1.0'})
|
||||
etree.indent(doc, space=" ")
|
||||
archetype = etree.SubElement(doc, 'archetype', {'name': '???'})
|
||||
|
||||
# Get all of the param elements
|
||||
for element in root.findall('.//param'):
|
||||
# Check shape params by id
|
||||
id = int(element.get("id"))
|
||||
if id == 80:
|
||||
# Keep the gender element
|
||||
if opts.body or opts.shape:
|
||||
archetype.append(element)
|
||||
if [True for values in sliders.keys() if id in sliders[values]]:
|
||||
archetype.append(element)
|
||||
|
||||
if opts.text:
|
||||
# Show the lists of slider values
|
||||
for k in sliders.keys():
|
||||
str = k + ":"
|
||||
for v in sliders[k]:
|
||||
e = doc.find(".//param[@id='%s']" % v)
|
||||
if e is not None:
|
||||
# The 'u8' attribute is a scaled 8 bit (0-255)
|
||||
# The slider numbers are scaled 0-100
|
||||
str += " %d," % int(round(int(e.get('u8')) / 2.55))
|
||||
print(str)
|
||||
else:
|
||||
buff = etree.tostring(doc, xml_declaration=True, encoding="utf-8")
|
||||
prettybuff = minidom.parseString(buff)
|
||||
sys.stdout.write(prettybuff.toprettyxml(indent=" ", newl=''))
|
||||
|
||||
def base_parser(parser):
|
||||
"""Set up some of the common CLI options
|
||||
These are the basic options that match the library CLIs so
|
||||
command-line/environment setups for those also work with these
|
||||
demonstration programs.
|
||||
"""
|
||||
|
||||
element_group = parser.add_mutually_exclusive_group()
|
||||
element_group.add_argument(
|
||||
'--body',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='body',
|
||||
help='Include body elements',
|
||||
)
|
||||
element_group.add_argument(
|
||||
'--eyes',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='eyes',
|
||||
help='Include eye elements',
|
||||
)
|
||||
element_group.add_argument(
|
||||
'--hair',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='hair',
|
||||
help='Include hair elements',
|
||||
)
|
||||
element_group.add_argument(
|
||||
'--head',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='head',
|
||||
help='Include head elements',
|
||||
)
|
||||
element_group.add_argument(
|
||||
'--shape',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='shape',
|
||||
help='Include shape elements (head+body)',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--text',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='text',
|
||||
help='Output text instead of XML',
|
||||
)
|
||||
|
||||
# Global arguments
|
||||
parser.add_argument(
|
||||
'-v', '--verbose',
|
||||
action='count',
|
||||
dest='verbose_level',
|
||||
default=1,
|
||||
help='Increase verbosity of output. Can be repeated.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--debug',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help='show tracebacks on errors',
|
||||
)
|
||||
parser.add_argument(
|
||||
'rest',
|
||||
nargs='*',
|
||||
help='the rest of the args',
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def configure_logging(opts):
|
||||
"""Typical app logging setup
|
||||
Based on OSC/cliff
|
||||
"""
|
||||
|
||||
global dump_stack_trace
|
||||
|
||||
root_logger = logging.getLogger('')
|
||||
|
||||
# Requests logs some stuff at INFO that we don't want
|
||||
# unless we have DEBUG
|
||||
requests_log = logging.getLogger("requests")
|
||||
requests_log.setLevel(logging.ERROR)
|
||||
|
||||
# Other modules we don't want DEBUG output for so
|
||||
# don't reset them below
|
||||
iso8601_log = logging.getLogger("iso8601")
|
||||
iso8601_log.setLevel(logging.ERROR)
|
||||
|
||||
# Always send higher-level messages to the console via stderr
|
||||
console = logging.StreamHandler(sys.stderr)
|
||||
formatter = logging.Formatter(CONSOLE_MESSAGE_FORMAT)
|
||||
console.setFormatter(formatter)
|
||||
root_logger.addHandler(console)
|
||||
|
||||
# Set logging to the requested level
|
||||
dump_stack_trace = False
|
||||
if opts.verbose_level == 0:
|
||||
# --quiet
|
||||
root_logger.setLevel(logging.ERROR)
|
||||
elif opts.verbose_level == 1:
|
||||
# This is the default case, no --debug, --verbose or --quiet
|
||||
root_logger.setLevel(logging.WARNING)
|
||||
elif opts.verbose_level == 2:
|
||||
# One --verbose
|
||||
root_logger.setLevel(logging.INFO)
|
||||
elif opts.verbose_level >= 3:
|
||||
# Two or more --verbose
|
||||
root_logger.setLevel(logging.DEBUG)
|
||||
requests_log.setLevel(logging.DEBUG)
|
||||
|
||||
if opts.debug:
|
||||
# --debug forces traceback
|
||||
dump_stack_trace = True
|
||||
root_logger.setLevel(logging.DEBUG)
|
||||
requests_log.setLevel(logging.DEBUG)
|
||||
|
||||
return
|
||||
|
||||
|
||||
def run(opts):
|
||||
"""Default run command"""
|
||||
|
||||
if opts.debug:
|
||||
# Do some basic testing here
|
||||
sys.stdout.write("Default run command\n")
|
||||
sys.stdout.write("Verbose level: %s\n" % opts.verbose_level)
|
||||
sys.stdout.write("Debug: %s\n" % opts.debug)
|
||||
sys.stdout.write("dump_stack_trace: %s\n" % dump_stack_trace)
|
||||
sys.stdout.write("args: %s\n" % opts.rest)
|
||||
|
||||
do_shape(opts)
|
||||
|
||||
|
||||
def setup():
|
||||
"""Parse command line and configure logging"""
|
||||
opts = base_parser(
|
||||
argparse.ArgumentParser(description='template')
|
||||
).parse_args()
|
||||
configure_logging(opts)
|
||||
return opts
|
||||
|
||||
|
||||
def main(opts, run):
|
||||
try:
|
||||
return run(opts)
|
||||
except Exception as e:
|
||||
if dump_stack_trace:
|
||||
_logger.error(traceback.format_exc(e))
|
||||
else:
|
||||
_logger.error('Exception raised: ' + str(e))
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
opts = setup()
|
||||
sys.exit(main(opts, run))
|
||||
Reference in New Issue
Block a user