Files
2025-09-29 00:52:08 +02:00

215 lines
7.0 KiB
Ruby
Executable File

#
# File:: pipeline/util/autodeskMotionbuilder.rb
# Description:: Autodesk Motionbuilder Interface
#
# Author:: Mike Wilson <mike.wilson@rockstarnorth.com>
# Date:: 3 February 2011
#
#----------------------------------------------------------------------------
# Uses
#----------------------------------------------------------------------------
require 'pipeline/config/projects'
require 'pipeline/os/path'
require 'pipeline/os/start'
require 'pipeline/os/sysinfo'
require 'pipeline/util/application'
require 'rexml/document'
require 'singleton'
#----------------------------------------------------------------------------
# Implementation
#----------------------------------------------------------------------------
module Pipeline
#
# == Description
# Autodesk Motionbuilder application interface, to determine installed versions,
# install directories etc. Essentially a friendly wrapper for Motionbuilder for
# the Windows Registry that now copes with x86 registry on Windows x64.
#
class AutodeskMotionbuilder
include Singleton
#---------------------------------------------------------------------
# Public Constants
#---------------------------------------------------------------------
# Plugin direcotries for different verisons of max
# VERSION_DIRS = {
# 0.0 => 'maxBlank',
# 11.0 => 'max2009',
# 12.0 => 'max2010',
# 13.0 => 'max2011',
# 14.0 => 'max2012'
# }
#---------------------------------------------------------------------
# Public Methods
#---------------------------------------------------------------------
# Class constructor ensures we only reg dump once.
def initialize( )
init( )
end
#
# == Description
# Return whether any versions of Autodesk's 3dsmax is installed on
# the local machine.
#
def is_installed?( )
( not ( @native.empty? and @x86.empty? ) )
end
#
# == Description
# Get the root directory for max installations
#
def get_root_dir( )
"dcc/#{Pipeline::Config::instance().max_options.toolset_mode.to_s}/"
end
#
# == Description
# Return an array of installed 3dsmax versions (as floats).
#
def versions( )
( @native.keys + @x86.keys ).uniq
end
#
# == Description
# Return the latest installed version of Autodesk's 3dsmax on the local
# machine - nil if no versions are installed.
#
def latest_version( )
installed_versions = versions( )
installed_versions.sort!() do |x,y| y <=> x end
return installed_versions[0] if installed_versions.size > 0
return nil
end
#
# == Description
# Return a Hash of Hashes of installed versions (key) and their install
# locations (string path) for all installed 3dsmax versions (if their
# installdir is available in the Registry).
#
# Hash is of the form:
# { :x86 => { ... }, :x64 => { ... } }
#
def installdirs( )
return nil unless is_installed?
if ( :x64 == OS::WinSystemInfo::SysType( ) ) then
{ :x64 => @native, :x86 => @x86 }
else
{ :x86 => @native, :x64 => {} }
end
end
#
# == Description
# Return autodeskMotionbuilder class static log object.
#
def AutodeskMotionbuilder::log( )
@@log = Log.new( 'AutodeskMotionbuilder' ) if ( @@log.nil? )
@@log
end
private
#---------------------------------------------------------------------
# Private Data
#---------------------------------------------------------------------
@@log = nil
#---------------------------------------------------------------------
# Private Constants
#---------------------------------------------------------------------
DCC_COMMON_DIR = 'dcc/common/'
REGISTRY_DUMP = OS::Path::combine( 'install', '3dsmaxRegDump.exe' )
REGISTRY_FILE = '3dsmaxRegDump.xml'
XML_XPATH_NATIVE_VERSION = 'Applications/AutodeskMotionBuilder/mbNative/version'
XML_XPATH_X86_VERSION = 'Applications/AutodeskMotionBuilder/mbX86/version'
INIT_SCRIPT_X86 = 'rockstarnorthconfiginit.ms'
INIT_SCRIPT_X64 = 'rockstarnorthconfiginit64.ms'
#---------------------------------------------------------------------
# Private Methods
#---------------------------------------------------------------------
#
# == Description
# This private method runs the 3dsmaxRegDump executable and writes out
# our info XML file that is then parsed into an internal structure.
#
def init( )
begin
toolsbin = Pipeline::Config::instance().toolsbin
toolstmp = Pipeline::Config::instance().temp()
regdump = OS::Path::combine( toolsbin, REGISTRY_DUMP )
xmlout = OS::Path::combine( toolstmp, REGISTRY_FILE )
FileUtils::mkdir_p( toolstmp )
AutodeskMotionbuilder::log().info( "Starting \"#{regdump} #{xmlout}\"..." )
status, sout, serr = OS::start( "#{regdump} #{xmlout}" )
# Parse our XML file.
parse( xmlout )
rescue Exception => ex
AutodeskMotionbuilder::log().exception( ex, 'Unhandled exception during reg dump' )
end
end
#
# == Description
# Parse the passed in 3dsmax reg dump XML file; initialising our internal
# data ready to be returned by our instance methods.
#
def parse( filename )
@native = {}
@x86 = {}
File::open( filename, 'r' ) do |fp|
doc = REXML::Document::new( fp )
doc.elements.each( XML_XPATH_NATIVE_VERSION ) do |nativeElem|
@native[nativeElem.attributes['id']] = nativeElem.attributes['installdir']
end
doc.elements.each( XML_XPATH_X86_VERSION ) do |x86Elem|
@x86[x86Elem.attributes['id']] = x86Elem.attributes['installdir']
end
end
end
end
end # Pipeline module
#----------------------------------------------------------------------------
# Entry (Unit Testing)
#----------------------------------------------------------------------------
if ( __FILE__ == $0 ) then
autodeskMotionbuilder = Pipeline::autodeskMotionbuilder::instance( )
puts "Autodesk Motionbuilder installed?: #{autodeskMotionbuilder.is_installed?}"
autodeskMotionbuilder.installdirs.each_pair do |platform, dirs|
puts "Platform: #{platform}"
dirs.each_pair do |version, installdir|
puts "\t#{version} => #{installdir}"
end
end
puts "Versions: #{autodeskMotionbuilder.versions.join('; ')}"
puts "Latest: #{autodeskMotionbuilder.latest_version}"
puts "Root dir: #{autodeskMotionbuilder.get_root_dir()}"
end
# pipeline/util/autodeskMotionbuilder.rb