Skip to content

Instantly share code, notes, and snippets.

@sehraf
Last active January 9, 2023 13:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sehraf/cb6d128fcd1fba7a1f37b15292d210f4 to your computer and use it in GitHub Desktop.
Save sehraf/cb6d128fcd1fba7a1f37b15292d210f4 to your computer and use it in GitHub Desktop.
Skryim RaceMenu BodySlide morphe converter. Converts the racemenu preset BodySlide morphs to a BodySlide studio preset. Tested once with mixed results...
import json
import xml.etree.ElementTree as ET
import xml.dom.minidom as MD
# BodySlide options, too be completed
bodyslide_elems = [
"Ankles",
"AppleCheeks",
"Arms",
"Back",
"Belly",
"BigBelly",
"BigButt",
"BigTorso",
"BreastCleavage",
"BreastFlatness",
"BreastGravity",
"BreastHeight",
"BreastPerkiness",
"Breasts",
"BreastsFantasy",
"BreastsSH",
"BreastsSmall",
"BreastsSSH",
"BreastWidth",
"Butt",
"ButtCrack",
"ButtShape2",
"ButtSmall",
"CalfSize",
"CalfSmooth",
"ChubbyArms",
"ChubbyButt",
"ChubbyLegs",
"ChubbyWaist",
"DoubleMelon",
"Groin",
"HipBone",
"Hips",
"KneeHeight",
"Legs",
"NippleAreola",
"NippleDistance",
"NippleDown",
"NippleLength",
"NippleSize",
"NippleTip",
"NippleUp",
"NipplePerkiness",
"RoundAss",
"PushUp",
"ShoulderSmooth",
"ShoulderWidth",
"SlimThighs",
"Thighs",
"TummyTuck",
"Waist",
"WideWaistLine",
]
def load_json(file):
with open(file, 'r') as handle:
parsed = json.load(handle)
return parsed
def save_xml(file, data):
with open(file, 'w') as handle:
handle.write(prettify(data.getroot()))
def prettify(elem):
"""Return a pretty-printed XML string for the Element.
"""
rough_string = ET.tostring(elem, 'utf-8')
reparsed = MD.parseString(rough_string)
return reparsed.toprettyxml(indent="\t", )
def convert_racemenu_2_bodyslide(file_name: str):
# read input file
input = load_json(file_name + '.jslot')
# get bodyMorph node
body_morph = input['bodyMorphs']
# print(body_morph)
# fill missing entries
for e in bodyslide_elems:
if e not in [a['name'] for a in body_morph]:
body_morph.append(
{
'name': e,
'keys': [
{
'value': 0
}
]
}
)
# build xml
r = ET.Element('SliderPresets')
tree = ET.ElementTree(r)
root = tree.getroot()
preset = ET.SubElement(root, 'Preset')
preset.attrib['name'] = file_name + ' preset'
preset.attrib['set'] = file_name + ' Body' # ???
group = ET.SubElement(preset, 'Group')
group.attrib['name'] = 'CBAdvanced'
# calculate new values
for entry in body_morph:
# get name and value
value = entry['keys'][0]['value']
name = entry['name']
if name not in bodyslide_elems:
print('missing option', name)
bodyslide_elems.append(name)
# math time
value_new = value # -2 - +2
value_new *= 25 # scale to -50 - +50
value_new += 50 # shift to 0 - 100
value_new = round(value_new)
print('{:10}\t{: 2.3f}\t{}'.format(name, value, value_new))
# add to xml
slider = ET.SubElement(preset, 'SetSlider')
slider.attrib['name'] = name
slider.attrib['size'] = 'small'
slider.attrib['value'] = str(value_new)
# print(prettify(root))
save_xml(file_name + '.xml', tree)
def diff_xml(file_a, file_b):
a = ET.ElementTree()
a.parse(file_a)
a_root = a.getroot()
a_preset = a_root.find('Preset')
b = ET.ElementTree()
b.parse(file_b)
b_root = b.getroot()
b_preset = b_root.find('Preset')
for entry in a_preset:
if entry.tag != 'SetSlider': continue
name = entry.attrib['name']
if name not in bodyslide_elems:
print('missing option', name)
bodyslide_elems.append(name)
for entry in b_preset:
if entry.tag != 'SetSlider': continue
name = entry.attrib['name']
if name not in bodyslide_elems:
print('missing option', name)
bodyslide_elems.append(name)
for name in bodyslide_elems:
a_entry = None
b_entry = None
for a_it in a_preset:
if a_it.tag != 'SetSlider': continue
if a_it.attrib['name'] == name and a_it.attrib['size'] == 'small':
a_entry = a_it
for b_it in b_preset:
if b_it.tag != 'SetSlider': continue
if b_it.attrib['name'] == name and b_it.attrib['size'] == 'small':
b_entry = b_it
if a_entry is None and b_entry is None:
continue
if a_entry is None:
a_entry = ET.Element('SetSlider')
a_entry.attrib['value'] = 0
if b_entry is None:
b_entry = ET.Element('SetSlider')
b_entry.attrib['value'] = 0
# print(name, a_entry.attrib['value'], b_entry.attrib['value'])
a_value = int(a_entry.attrib['value'])
b_value = int(b_entry.attrib['value'])
diff = abs(a_value - b_value)
print('{:15} {:5d}'.format(name, diff))
if __name__ == "__main__":
# place <name>.jslot RaceMenu preset file in the same directory as this script.
# will generate <name>.xml which can be loaded by BodySlide Studio
convert_racemenu_2_bodyslide('Flun')
diff_xml('Flun.xml', 'Flun-manuell.xml')
@Spac3fl00f
Copy link

how
do i use the code?

@sehraf
Copy link
Author

sehraf commented Dec 8, 2022

See the comment:

# place .jslot RaceMenu preset file in the same directory as this script.
# will generate .xml which can be loaded by BodySlide Studio

Change the file name (Flun) to something else.
Also keep in mind that this is two years old, no idea if it still works or not 🤷‍♂️

(Of course you need to be able to use python)

@johnnyboy073
Copy link

Can you elaborate? Give an idiots guide and step by step to use this. Please and thank you. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment