Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions blender/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Player Animation Tools

The `.blend` files are [Blender](https://www.blender.org/) projects.
`emote_creator.blend` is the rig for blender 5.2+ and only for the latest version of Emotecraft!
[Emotecraft wiki](https://docs.zigythebird.com/emotecraft/creatingemotes/) if you're stuck.

`emote_creator.blend` is the latest rig for blender, it has the most features. It is made for Blender 5.2+ and intended to work only on the latest version of PAL (1.2.5+mc.26.2 at the time this is written)! Other rigs work fine on versions lower.
Read [Emotecraft wiki](https://docs.zigythebird.com/emotecraft/creatingemotes/) to learn more about `emote_creator.blend`.

`.bbmodel` files are models for [Blockbench](https://blockbench.net/). You can use them as well.
To use them, you'll need to install the [GeckoLib](https://geckolib.com/) Blockbench plugin first.
Expand Down
Binary file modified blender/emote_creator.blend
Binary file not shown.
120 changes: 35 additions & 85 deletions blender/export.py
Original file line number Diff line number Diff line change
@@ -1,112 +1,62 @@
import sys, bpy, json
from pathlib import Path
project_dir = Path(bpy.data.filepath).parent
rig_object = bpy.data.objects["export_armature"]
import base64
import tempfile
import os
rig_object = bpy.context.active_object
action = rig_object.animation_data.action
scene = bpy.context.scene

emote_save_folder = project_dir
blender_save_folder = project_dir

prefix = ""
filename = prefix + action.name

name = f"{filename}"
description = ""
author = "3APA3EH"

isLoop = action.use_cyclic
baking_error_threshold = 0.001 # how much error is fine when converting baked animation to bezier keyframes
# 0: just make every keyframe bezier; >0: curve is allowed to be off by this much

#from what bones to read the animation
export_bones = [
"body",
"body_control",
"body", "body_control",
"head",
"left_arm",
"left_leg",
"right_arm",
"right_leg",
"torso",
"left_arm_bend",
"left_leg_bend",
"right_arm_bend",
"right_leg_bend",
"torso_bend",
"right_item",
"left_item",
"cape",
"cape_bend",
"waist"
"left_arm", "right_arm",
"left_leg", "right_leg",
"waist", "torso", "cape",
"left_item", "right_item",
]
for pivot_bone in action.emote.pivot_bones:
export_bones.append(pivot_bone.name)

# https://misode.github.io/text-component/
badges = [
# {
# "translate": "mineemotes.emote.badge.dance",
# "fallback": "Dance",
# "color": "#E73A3A"
# },
# {
# "translate": "mineemotes.emote.badge.test",
# "fallback": "Test",
# "color": "#003A3A"
# }
# {
# "translate": "mineemotes.emote.badge.bendless",
# "fallback": "Bendless",
# "color": "#34c415"
# }
]
#end of the settings

# how many decimal places to keep in values
value_precision = 3
collect_animation_data = bpy.data.texts['collect_animation_data.py'].as_module().collect_animation_data
create_emote = bpy.data.texts['set_up_bedrock.py'].as_module().create_emote

framerate = scene.render.fps/scene.render.fps_base
print(f"Exporting {action.name}.json!")
preview_frame = scene.frame_current
scene.frame_set(0)

animation_data, work_action = collect_animation_data(rig_object, export_bones)
emote = create_emote(rig_object, export_bones, animation_data)

bpy.data.actions.remove(work_action)

bpy.ops.wm.save_mainfile(filepath=f"{blender_save_folder}\\{filename}.blend")
emote_save_folder = action.emote.emote_save_path

print("Rendering icon...")
scene.frame_set(preview_frame)
bpy.ops.render.render()

collect_animation_data = bpy.data.texts['collect_animation_data.py'].as_module().collect_animation_data
create_emote = bpy.data.texts['set_up_bedrock.py'].as_module().create_emote

print(f"Exporting {filename}.json!")
is_vanilla = rig_object.pose.bones["settings"]["vanilla"]
image = bpy.data.images["Render Result"]

preview_frame = scene.frame_current
scene.frame_set(0)
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
path = tmp.name

animation_data, work_action = collect_animation_data(baking_error_threshold,
isLoop,
int(action.frame_start),
int(action.frame_end),
export_bones
)

emote = create_emote(filename,
scene.frame_start,
int(action.frame_start),
int(action.frame_end),
isLoop,
name, author, description, badges,
export_bones,
animation_data,
value_precision
)
try:
image.save_render(path)

bpy.data.actions.remove(work_action)
with open(path, "rb") as f:
image_base64 = base64.b64encode(f.read()).decode("ascii")
finally:
os.remove(path)

emote["animations"][action.name]["player_animation_library"]["iconData"] = image_base64

print("Saving json...")
with open(str(emote_save_folder / (prefix + filename + ".json")), 'w', encoding="utf-8") as e:
with open(str(emote_save_folder + "/" + action.name + ".json"), 'w', encoding="utf-8") as e:
json.dump(emote, e, ensure_ascii=False, indent=4)
scene.frame_set(preview_frame)
print("Rendering icon...")
scene.render.filepath = str(emote_save_folder / (prefix + filename + ".png"))
bpy.ops.render.render(write_still = 1)


print("Emote has been exported successfuly!")
Loading
Loading