Skip to content
This repository has been archived by the owner on Jul 21, 2023. It is now read-only.

Commit

Permalink
Segment auto export to apk, some extra metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
knot126 committed May 11, 2023
1 parent 21981e1 commit 7b2976e
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 9 deletions.
46 changes: 39 additions & 7 deletions blender_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"name": "Smash Hit Blender Tools",
"description": "Blender-based tools for editing, saving and loading Smash Hit segments",
"author": "Smash Hit Lab",
"version": (2, 1, 4),
"version": (2, 1, 5),
"blender": (3, 2, 0),
"location": "File > Import/Export and 3D View > Tools",
"warning": "",
Expand Down Expand Up @@ -123,6 +123,36 @@ def execute(self, context):
def sh_draw_export_gz(self, context):
self.layout.operator("sh.export_compressed", text="Compressed Segment (.xml.gz.mp3)")

class sh_export_auto(bpy.types.Operator):
"""
Auto find APK path and use level/room/segment name to export
"""

bl_idname = "sh.export_auto"
bl_label = "Export to APK"

def execute(self, context):
sh_properties = context.scene.sh_properties

result = segment_export.sh_export_segment(
None,
context,
compress = True,
params = {
"sh_vrmultiply": sh_properties.sh_vrmultiply,
"sh_box_bake_mode": sh_properties.sh_box_bake_mode,
"sh_meshbake_template": segment_export.tryTemplatesPath(),
"bake_menu_segment": sh_properties.sh_menu_segment,
"bake_vertex_light": sh_properties.sh_ambient_occlusion,
"lighting_enabled": sh_properties.sh_lighting,
}
)

return result

def sh_draw_export_auto(self, context):
self.layout.operator("sh.export_auto", text="Export to APK")

class sh_export_test(Operator):
"""
Compressed segment export
Expand Down Expand Up @@ -235,21 +265,21 @@ class sh_SceneProperties(PropertyGroup):

sh_level: StringProperty(
name = "Level name",
description = "The name of the checkpoint that this segment belongs to. The checkpoints will go in alphabetical order, so it's recommended to prefix with 0_, 1_, 2_, etc",
description = "The name of the checkpoint that this segment belongs to.",
default = "",
maxlen = SH_MAX_STR_LEN,
)

sh_room: StringProperty(
name = "Room name",
description = "The name of the room that this segment belongs to. The rooms will go in alphabetical order, so it's recommended to prefix with 0_, 1_, 2_, etc",
description = "The name of the room that this segment belongs to.",
default = "",
maxlen = SH_MAX_STR_LEN,
)

sh_segment: StringProperty(
name = "Segment name",
description = "The name of this segment. You don't need to prefix this because the order will be random",
description = "The name of this segment",
default = "",
maxlen = SH_MAX_STR_LEN,
)
Expand Down Expand Up @@ -831,9 +861,9 @@ def draw(self, context):
scene = context.scene
sh_properties = scene.sh_properties

# layout.prop(sh_properties, "sh_level")
# layout.prop(sh_properties, "sh_room")
# layout.prop(sh_properties, "sh_segment")
layout.prop(sh_properties, "sh_level")
layout.prop(sh_properties, "sh_room")
layout.prop(sh_properties, "sh_segment")

layout.prop(sh_properties, "sh_len")
layout.prop(sh_properties, "sh_box_bake_mode")
Expand Down Expand Up @@ -1041,6 +1071,7 @@ def run_updater():
sh_ShowMessage,
sh_export,
sh_export_gz,
sh_export_auto,
sh_export_binary,
sh_export_test,
sh_import,
Expand All @@ -1059,6 +1090,7 @@ def register():
# Add the export operator to menu
bpy.types.TOPBAR_MT_file_export.append(sh_draw_export)
bpy.types.TOPBAR_MT_file_export.append(sh_draw_export_gz)
bpy.types.TOPBAR_MT_file_export.append(sh_draw_export_auto)
bpy.types.TOPBAR_MT_file_export.append(sh_draw_export_binary)
bpy.types.TOPBAR_MT_file_export.append(sh_draw_export_test)

Expand Down
31 changes: 30 additions & 1 deletion segment_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import tempfile
import bake_mesh
import obstacle_db
import util

from bpy.props import (StringProperty, BoolProperty, IntProperty, IntVectorProperty, FloatProperty, FloatVectorProperty, EnumProperty, PointerProperty)
from bpy.types import (Panel, Menu, Operator, PropertyGroup)
Expand Down Expand Up @@ -182,7 +183,14 @@ def sh_create_root(scene, params):
creator = bpy.context.preferences.addons["blender_tools"].preferences.creator

if (creator):
seg_props["creator"] = creator
seg_props["shbt-meta-creator"] = creator

# Export time
seg_props["shbt-meta-time"] = hex(util.get_time())[2:]

# Export user trace if the creator wasn't specified
if (not creator):
seg_props["shbt-meta-trace"] = util.get_trace()

# Create main root and return it
level_root = et.Element("segment", seg_props)
Expand Down Expand Up @@ -423,8 +431,29 @@ def sh_export_segment(filepath, context, *, compress = False, params = {}):
This function exports the blender scene to a Smash Hit compatible XML file.
"""

# Set wait cursor
context.window.cursor_set('WAIT')

# If the filepath is None, then find it from the apk and force enable
# compression
if (filepath == None):
props = context.scene.sh_properties

filepath = util.find_apk()

if (not filepath):
raise FileNotFoundError("There is currently no APK open in APK Editor Studio. Please open a Smash Hit APK with a valid structure and try again.")

if (not props.sh_level or not props.sh_room or not props.sh_segment):
raise FileNotFoundError("You have not set one of the level, room or segment name properties needed to use auto export to apk feature. Please set these in the scene tab and try again.")

filepath += "/segments/" + props.sh_level + "/" + props.sh_room + "/" + props.sh_segment + ".xml.gz.mp3"

util.prepare_folders(filepath)

compress = True

# Export to xml string
content = createSegmentText(context, params)

# Binary segments
Expand Down
2 changes: 1 addition & 1 deletion segment_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def sh_import_segment(fp, context, compressed = False):

for d in drm:
if (d == "NoImport"):
show_message("Import error", "There was an error importing this segment.")
show_message("Import error", "The creator of this segment has requested that it not be imported. We encourage you to respect this request.")
return {"FINISHED"}

# Segment length
Expand Down
80 changes: 80 additions & 0 deletions util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import common
import os
import os.path as ospath
import pathlib
import tempfile
import getpass
import math
import time
import hashlib

def get_time():
"""
Get the current UNIX timestamp
"""

return math.floor(time.time())

def get_hash(data):
"""
Compute the SHA1 hash of a utf8 string
"""

return hashlib.sha1(data.encode('utf-8')).hexdigest()

def get_trace():
"""
The user trace is the first two hex digits of the SHA1 hash of the user's
username. This means there is only 256 possible values of the trace, so it's
only really useful for confirming that some untampered segments might have
been made by the same person, with a relatively high probability of error.
It is meant so that someone can tell if some segments in a mod without a
given creator name are by the same creator, and for tracking segments in
general, while still trying to minimise privacy risk.
"""

username = getpass.getuser()

result = get_hash(username)[:2]

return result

def prepare_folders(path):
"""
Make the folders for the file of the given name
"""

os.makedirs(pathlib.Path(path).parent, exist_ok = True)

def find_apk():
"""
Find the path to an APK
"""

# Search for templates.xml (how we find the APK) and set path
path = ""

### Try to find from APK Editor Studio ###

try:
# Get the search path
search_path = tempfile.gettempdir() + "/apk-editor-studio/apk"

# Enumerate files
dirs = os.listdir(search_path)

for d in dirs:
cand = str(os.path.abspath(search_path + "/" + d + "/assets/templates.xml.mp3"))

print("Trying the path:", cand)

if ospath.exists(cand):
path = str(pathlib.Path(cand).parent)
break
except FileNotFoundError:
print("Smash Hit Tools: No APK Editor Studio folder found.")

print("Final apk path:", path)

return path

0 comments on commit 7b2976e

Please sign in to comment.