# # File:: pipeline/util/autodeskMotionbuilder.rb # Description:: Autodesk Motionbuilder Interface # # Author:: Mike Wilson # 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