Created
June 23, 2019 00:23
-
-
Save zach-capalbo/ada1c4323bdc6d2f516ca0f4cb66f807 to your computer and use it in GitHub Desktop.
Tool for exporting Oculus Quill files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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