Skip to content

Instantly share code, notes, and snippets.

@zach-capalbo
Created June 23, 2019 00:23
Show Gist options
  • Save zach-capalbo/ada1c4323bdc6d2f516ca0f4cb66f807 to your computer and use it in GitHub Desktop.
Save zach-capalbo/ada1c4323bdc6d2f516ca0f4cb66f807 to your computer and use it in GitHub Desktop.
Tool for exporting Oculus Quill files
require 'json'
require 'fileutils'
class ::Hash
def deep_merge!(other_hash, &block)
merge!(other_hash) do |key, this_val, other_val|
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
this_val.deep_merge(other_val, &block)
elsif block_given?
block.call(key, this_val, other_val)
else
other_val
end
end
end
end
class QuillScene
EXPORTER_PATH = "E:/Oculus Apps/Software/oculus-quill/QuillExporter"
attr_accessor :scene_name, :output_path
attr_reader :json, :layers, :layer_index
DEFAULT_OPTS = {
output_path: "E:/models"
}
def initialize(opts = {})
opts = DEFAULT_OPTS.merge(opts)
opts.each{ |k,v| instance_variable_set("@#{k}", v) unless v.nil? }
@json = JSON.parse(File.read(File.join(scene_path, "Quill.json")))
@layer_index = {}
@layers = get_layers(json["Sequence"]["RootLayer"]).flatten
end
def inspect; "#<QuillScene:#{@scene_name}>"; end
def scene_path; File.join(ENV["HOME"], "Documents", "Quill", scene_name); end
def get_layers(layer, prefix=[])
@layer_index[(prefix + [layer["Name"]]).join("/")] = layer
return (prefix + [layer["Name"]]).join("/") if layer["Type"] == "Paint"
return layer["Implementation"]["Children"].map{|l| get_layers(l, prefix + [layer["Name"]])}.reject(&:nil?) if layer["Type"] == "Group"
end
def summary
puts @layers.join("\n")
end
def export_all!(opts = {})
@layers.each do |layer|
export!(layer, opts)
end
end
def full_output_path
File.join(output_path, scene_name)
end
def export!(layer, opts = {})
info = @layer_index[layer]
animated = info["Implementation"]["Frames"].size > 1
format = opts[:format] || (animated ? "Alembic" : "FBX")
extension = opts[:ext] || (format == "Alembic" ? "abc" : "fbx")
optimize = opts.fetch(:optimize, false)
settings = {
"Exporter": format,
"InputFile": scene_path,
"ExtraInputs": [],
"Options": {
"BakeTransforms": true,
"ColorSpace": "Linear",
"ExcludeList": @layers - [layer],
"UseFullNames": true,
"ExportCurves": false,
"ExportHidden": false,
"ExportMeshes": true,
"ExportUVs": true,
"ExportAnimation": animated,
"Scale": 1.0,
"UVSafetyBandTexels": 8.0,
"GroupExtraInputs": false,
"Optimize":
{
"Optimize": optimize,
"OptimizeKeepOldLayers": false,
"OptimizeSimplifyThreshhold": 0.02,
"OptimizeIncludeList": [ layer ]
}
},
"OutputFile": File.join(full_output_path, "#{layer.split("/")[-1]}.#{extension}")
}.deep_merge!(opts.fetch(:settings, {}))
FileUtils.mkdir_p full_output_path
File.write(File.join(EXPORTER_PATH, "settings.json"), settings.to_json)
system(File.join(EXPORTER_PATH, "QuillExporter.exe"), "settings.json")
end
end
# E.g.:
# QuillScene.new(scene_name: "Castle_anim_color").export!("Root/Dragon1/Mblur", format: "FBX", optimize: true)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment