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:
Serie Sumei
2021-01-02 15:51:47 -06:00
parent 09a8a8e616
commit 647e2ed7b6
6 changed files with 619 additions and 0 deletions
+30
View File
@@ -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>
+453
View File
@@ -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))