-- <<<- ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- These are tools for importing media and building containers. ------------------------------------------------------------------------ -- Open the Dream library container. open LibraryContainer \ dir: (parentDir theScriptDir) \ path: "dream.sxl" \ mode: @readable open LibraryContainer \ dir: (parentDir theScriptDir) \ path: "dreamimp.sxl" \ mode: @readable if (((systemQuery @osName) = "Macintosh") and ((systemQuery @cpuType) = "MC68040") and (isDir theStartDir "dtk") and (isDir theStartDir "dtk/dirimp")) do ( open LibraryContainer \ dir: (spawn theStartDir "dtk/dirimp") \ path: "dirimp.sxl" ) ------------------------------------------------------------------------ -- Make our own special builder module, to be sanitary. module DreamBuilder uses Dream uses ScriptX end in module DreamBuilder ------------------------------------------------------------------------ thePuppetImporterLoaded := false global theImageCache := undefined global theImportContainer := undefined ------------------------------------------------------------------------ function lose loser -> ( if (theImportContainer != undefined) do ( addToContents theImportContainer loser local slowButSmall := false -- fast if (slowButSmall) then ( update theImportContainer makePurgeable loser ) ) ) function importImage fileName invis hotX hotY #key \ dir: (theScriptDir) \ fileType: (@pict) \ -> ( local pictKey := #(fileName, invis, hotX, hotY) if (theImageCache == undefined) do ( theImageCache := #(:) ) local p := theImageCache[pictKey] if (p != empty) do (return p) print #("Importing", fileType, fileName) local invisBrush := if (invis == undefined) then ( whiteBrush ) else ( new Brush color: invis ) local str := getStream dir fileName @readable local bm := importMedia theImportExportEngine \ str @image fileType @bitmap -- colormap: theDefault8Colormap local bb := bm.bbox -- Work-around for Windows: make width multiple of 4 local bb1 := new Rect \ x2: (logicalAnd ((max 1 bb.width) + 3) (logicalNot 3)) \ y2: (logicalAnd ((max 1 bb.height) + 3) (logicalNot 3)) local bm1 := new BitmapSurface colorMap: theDefault8Colormap bbox: bb1 erase bm1 invisBrush bm := bm as BitmapSurface transfer bm1 bm bm1.bbox (new TwoDMatrix) bm := undefined bm1.invisibleColor := invis local reg := bm1 as Region local bb := reg.bbox local mat := new TwoDMatrix tx: (-hotX) ty: (-hotY) local bb2 := transform bb mat @create -- Work-around for Windows: make width multiple of 4 bb2.width := logicalAnd (bb2.width + 3) (logicalNot 3) bb2.height := logicalAnd (bb2.height + 3) (logicalNot 3) local bm2 := new BitmapSurface colorMap: theDefault8Colormap bbox: bb2 bm1.invisibleColor := undefined transfer bm2 bm1 bm2.bbox mat bm1 := undefined bm2 := bm2 as Bitmap bm2.invisibleColor := invis theImageCache[pictKey] := bm2 if (theImportContainer != undefined) do ( lose bm2 ) -- garbageCollect() return bm2 ) ------------------------------------------------------------------------ function importSound fileName #key \ dir: (theScriptDir) \ fileType: (@aiff) \ -> ( local str := getStream dir fileName @readable local sound := importMedia theImportExportEngine \ str @sound fileType @AudioStream return sound ) ------------------------------------------------------------------------ function makeDreamPluginModule modName -> ( -- This is the manual way to make a module. -- Note the use of @uses, instead of uses:, since without the @, -- it's a ScriptX keyword, and you get a syntax error. local modUses := #( new UseClause \ @module @Dream \ @import @all, new UseClause \ @module @ScriptX \ @import @all ) return (new ModuleClass \ @name modName \ @uses modUses) ) function importDreamPluginDatabase fileName dir tc mod startup -> ( -- Initialize the database. local database := #(:) -- Initialize the image cache. theImageCache := undefined -- This is the container to store the stuff in. theImportContainer := tc -- If the database file exists, then load it into the module. -- Loading the file "database.sx" should return a keyed list. if (isFile dir "database.sx") do ( database := fileIn dir \ name: fileName \ module: mod \ debugInfo: false print #(" database", fileName, getClass database, "size", size database) garbageCollect() ) -- if -- Store the copyright, if any, into the tc.copyright. local copyright := database[@copyright] if (copyright != empty) then ( print #(" copyright", copyright) ) else ( copyright := new String ) tc.copyright := copyright -- Store the credits, if any, into the tc[@credits]. local credits := database[@credits] if (credits != empty) then ( print #(" credits", credits) ) else ( credits := new String ) tc[@credits] := credits -- Create a keyed list of named puppets, by importing any -- director files specified in database[@puppets]. local puppets := #(:) local puppetFiles := database[@puppets] if (puppetFiles != empty) do ( -- The database[@puppets] keyed list has StringConstant keys -- that specify the puppetName, and keyed list values that -- specify how to import the puppet. The puppets are all -- imported and put into another keyed list, with the same -- puppetName keys, whose values are the actual imported -- puppets. That keyed list of imported puppets is stored -- in the title container as tc[@puppets]. forEachBinding puppetFiles (puppetName puppetData xxx -> -- If there's no data, then fake it. if (puppetData == undefined) do ( puppetData := #(:) ) -- If there's a @name key, then use that as the file -- name, otherwise use the puppetName by default. local fname := puppetData[@name] if (fname == empty) do (fname := puppetName) -- If there's a @type key, then assume director. local ftype := puppetData[@type] if (ftype == empty) do (ftype := @director) local pieces := undefined local filePath if (ftype == @director) then ( -- Load the puppet importer, if it's not already loaded. if (not thePuppetImporterLoaded) do ( thePuppetImporterLoaded := true print #(" [Loading Director to Puppet importer ...]") print (theContainerDir as Array) fileIn theContainerDir \ name: "pupimp.sx" \ debugInfo: false ) -- if -- Import the director file, as articulated puppet -- pieces. See "pupimp.sx" for a description of this -- data format. filePath := dir as Array append filePath fname pieces := importMedia theImportExportEngine \ filePath \ @Metaphor @Director @PuppetParts ) else ( filePath := fname pieces := fileIn dir \ module: (getModule @DreamBuilder) \ debugInfo: false \ name: fname ) -- Crawl over the pieces, importing media files, ramifying -- sound streams, and putting stuff into the container. for piece in pieces do ( for frame in piece do ( local bm := frame[1] if (isAKindOf bm String) do ( print #("importing pict file", bm) local str := getStream dir bm @readable bm := importMedia theImportExportEngine \ str @image @pict @bitmap \ colormap: theDefault8Colormap frame[1] := bm lose bm ) local sound := frame[6] if (sound != undefined) do ( -- Ramify the sound, by copying it -- into a RamStream. local is is := sound.inputStream local rs := new RamStream \ maxSize: (streamLength is) seekFromStart is 0 pipe rs is seekFromStart rs 0 sound.inputStream := rs lose sound ) ) ) print #(" puppet", puppetName, filePath) -- Put the new pieces into the puppets keyed list. puppets[puppetName] := pieces lose pieces ) ok -- forEachBinding puppetFiles ) -- if (puppetFiles != empty) -- Put the new keyed list of puppets into the title container. tc[@puppets] := puppets lose puppets -- Create a keyed list of named images, by importing any images -- specified in database[@images]. local images := #(:) local imageFiles := database[@images] if (imageFiles != empty) do ( -- The database[@images] keyed list has StringConstant keys -- that specify the imageName, and keyed list values that -- specify how to import the image. The images are all -- imported and put into another keyed list, with the same -- imageName keys, whose values are the actual imported -- images. That keyed list of imported images is stored -- in the title container as tc[@images]. forEachBinding imageFiles (imageName imageData xxx -> -- If there's no data, then fake it. if (imageData == undefined) do ( imageData := #(:) ) -- If there's a @name key, then use that as the file -- name, otherwise use the imageName by default. local fname := imageData[@name] if (fname == empty) do (fname := imageName) -- If there's a @type key, then use that is the file -- type, otherwise use @dib by default. local fileType := imageData[@type] if (fileType == empty) do (fileType := @dib) -- Open the file and import the image. local str := getStream dir fname @readable local image := importMedia theImportExportEngine \ str @image fileType @bitmap \ colormap: theDefault8Colormap -- Copy the image into another bitmap whose colormap is -- the default colormap, so it's quick to draw. -- If there's are @hotx and @hoty keys, translate the -- bitmap so that the (0, 0) origin is at the specified -- hot spot. The hot spot defaults to (0, 0), which is -- the upper left corner. local bb := copy image.bbox local extra bb.width := logicalAnd (bb.width + 3) (logicalNot 3) bb.height := logicalAnd (bb.height + 3) (logicalNot 3) local hotx := imageData[@hotX] if (hotx == empty) do (hotx := 0) local hoty := imageData[@hotY] if (hoty == empty) do (hoty := 0) local mat := new TwoDMatrix tx: (-hotx) ty: (-hoty) transform bb mat @mutate local bms := new BitmapSurface \ bbox: bb \ colorMap: theDefault8Colormap transfer bms (image as BitmapSurface) bb mat -- If there's an @invisibleColor key, set the bitmap's -- invisible color. local invis := imageData[@invisibleColor] if (invis == empty) do (invis := undefined) bms.invisibleColor := invis -- Put each imported image into the new keyed list, -- under the same name. local b := bms as Bitmap b.invisibleColor := bms.invisibleColor images[imageName] := b print #(" image", imageName, fname, fileType, bms, bms.bbox) lose b ) ok -- forEachBinding ) -- if (imageFiles != empty) -- Put the new keyed list of images into the title container. tc[@images] := images lose images -- Create a keyed list of named sounds, by importing any sounds -- specified in database[@sounds]. local sounds := #(:) local soundFiles := database[@sounds] if (soundFiles != empty) do ( -- The database[@sounds] keyed list has StringConstant keys -- that specify the soundName, and keyed list values that -- specify how to import the sound. The sounds are all -- imported and put into another keyed list, with the same -- soundName keys, whose values are the actual imported -- sounds. That keyed list of imported sounds is stored -- in the title container as tc[@sounds]. forEachBinding soundFiles (soundName soundData xxx -> -- If there's no data, then fake it. if (soundData == undefined) do ( soundData := #(:) ) -- If there's a @name key, then use that as the file -- name, otherwise use the soundName by default. local fname := soundData[@name] if (fname == empty) do (fname := soundName) -- If there's a @type key, then use that is the file -- type, otherwise use @aiff by default. local fileType := soundData[@type] if (fileType == empty) do (fileType := @aiff) -- Open the file and import the sound. local str := getStream dir fname @readable local sound := importMedia theImportExportEngine \ str @sound fileType @player \ container: tc -- Put each imported sound into the new keyed list, -- under the same name. sounds[soundName] := sound print #(" sound", soundName, fname, fileType, sound) lose sound ) ok -- forEachBinding ) -- if (soundFiles != empty) -- Put the new keyed list of images into the title container. tc[@sounds] := sounds lose sounds tc[@temp] := undefined -- Make a preStartupAction that hides the menu bar. Kludge. -- Careful to define it in the module, using fileIn. tc.preStartupAction := fileIn "(tc -> hide tc.systemMenuBar )" module: mod -- Make an outer startup action that loads everything and -- calls the inner startup action on the title container. tc.startupAction := fileIn "(tc -> load tc load tc[@module] load tc[@startupAction] tc[@startupAction] tc )" module: mod -- Store the inner startup action in the container. tc[@startupAction] := startup print #(" startup action", tc.preStartupAction, tc.startupAction, tc[@startupAction]) -- Store the module in the title container. tc[@module] := mod print #(" module", mod) -- Clear out the image cache. theImageCache := undefined return database ) ------------------------------------------------------------------------ ok -- >>>