int main( int argc, char **argv ) { // Option parsing // ============== argc -= (argc > 0); argv += (argc > 0); option::Stats stats( usage, argc, argv ); option::Option* options = new option::Option[ stats.options_max ]; option::Option* buffer = new option::Option[ stats.buffer_max ]; option::Parser parse( usage, argc, argv, options, buffer ); if( options[ HELP ] || parse.nonOptionsCount() == 0 ) { int columns = getenv( "COLUMNS" ) ? atoi( getenv( "COLUMNS" ) ) : 80; option::printUsage( std::cout, usage, columns ); if( options[ HELP ] ) exit( 0 ); else exit( 1 ); } if( options[ QUIET ] )LOG::SetDefaultLoggerLevel( LOG::CHECK ); // unknown options for( option::Option* opt = options[ UNKNOWN ]; opt; opt = opt->next() ){ LOG( ERROR ) << "Unknown option: " << std::string( opt->name,opt->namelen ); } if( parse.error() ) exit( 1 ); // all non options are treated as smf's options SMF *smf; int retVal = 0; for( int i = 0; i < parse.nonOptionsCount(); ++i ){ smf = SMF::open( parse.nonOption( i ) ); if(! smf ){ LOG( ERROR ) << "cannot open smf file"; retVal = 1; } else { LOG(INFO) << "\n" << smf->info(); smf->good(); delete smf; } } delete [] options; delete [] buffer; return retVal; }
//TODO go over this function to see if it can be refactored void TileCache::addSource( const std::string fileName ) { OIIO_NAMESPACE_USING; ImageInput *image = nullptr; if( (image = ImageInput::open( fileName )) ){ image->close(); delete image; _nTiles++; map.push_back( nTiles ); fileNames.push_back( fileName ); return; } SMT *smt = nullptr; if( (smt = SMT::open( fileName )) ){ if(! smt->nTiles ) return; _nTiles += smt->nTiles; map.push_back( nTiles ); fileNames.push_back( fileName ); delete smt; return; } SMF *smf = nullptr; if( (smf = SMF::open( fileName )) ){ // get the fileNames here auto smtList = smf->getSMTList(); for( auto i : smtList ) addSource( i.second ); delete smf; return; } LOG(ERROR) << "unrecognised format: " << fileName; }
int main( int argc, char **argv ) #endif { bool fail = false; // Generic Options // -l --load <string>, smf file to load // -s --save <string>, prefix for output // -v --verbose, Display extra output // -q --quiet, Supress standard output // -d --decompile, Decompile loaded map // -c --slowcomp, better quality but slower string saveFile= "", loadFile = ""; bool verbose = false, quiet = false, decompile = false, slowcomp = false; // // Map Dimensions // -x --width <int>, Width in spring map units // -z --length <int>, Length in spring map units // -y --floor <float>, Height of the map in spring map units // -Y --ceiling <float>, Depth of the map in spring map units int width = 2, length = 2; float floor = 0, ceiling = 1; // // Tiles and Tileindex // -a --add-smt <string> // -i --tileindex <image> vector<string> tileFiles; string tilemapFile = ""; // // Height // -e --heightmap <image> // --lowpass, whether to filter the heightmap with a lowpass filter // --invert, whether to invert the heightmap values string heightFile = ""; bool invert = false; //FIXME bool lowpass = false; // // Terrain Type // -t --typemap <image> string typeFile = ""; // // Minimap // -m --minimap <image> string minimapFile = ""; // // Metal // -r --metalmap <image> string metalFile = ""; // // Grass // -g --grassmap <image> string grassFile = ""; // // Features // -f --features <text> string featuresFile = ""; try { // Define the command line object. CmdLine cmd( "Converts a series of image and text files to .smf and" ".smt files used in SpringRTS maps.", ' ', "0.5" ); // Define a value argument and add it to the command line. // Generic Options // ///////////////////// ValueArg<string> arg_load( "l", "load", "Filename to load (.smf)", false, "", ".smf", cmd); ValueArg<string> arg_save( "s", "save", "Output prefix for the spring map file(.smf)", false, "", "fileprefix", cmd); SwitchArg arg_verbose( "v", "verbose", "Extra information printed to standard output.", cmd, false ); SwitchArg arg_quiet( "q", "quiet", "Supress information printing to standard output.", cmd, false ); SwitchArg arg_decompile( "d", "decompile", "Supress information printing to standard output.", cmd, false ); SwitchArg arg_slowcomp( "c", "slowcomp", "Use slower but better compression on DXT1 textures.", cmd, false ); // Map Dimensions // //////////////////// ValueArg<int> arg_width( "x", "width", "The Width of the map in spring map units. Must be multiples of 2", false, 2, "int", cmd ); ValueArg<int> arg_length( "z", "length", "The Length of the map in spring map units. Must be multiples of 2", false, 2, "int", cmd ); ValueArg<float> arg_floor( "y", "floor", "The deepest point on the map in spring map units, with zero being sea level.", false, 0, "float", cmd ); ValueArg<float> arg_ceiling( "Y", "ceiling", "The highest point on the map in spring map units, with zero being sea level.", false, 1, "float", cmd ); // Tiles and Tileindex // ///////////////////////// MultiArg<string> arg_add_smt( "a", "add-smt", "External tile files.", false, ".smt", cmd ); ValueArg<string> arg_tileindex( "i", "tileindex", "The index image to use for referencing tiles.", false, "", "image", cmd); // Height // //////////// ValueArg<string> arg_height( "e", "heightmap", "Image to use for vertical displacement of the terrain.", false, "", "image", cmd ); SwitchArg arg_invert( "", "invert", "Invert the meaning of black and white.", cmd, false ); //FIXME SwitchArg arg_lowpass( // "", "lowpass", // "Lowpass filter smoothing hard edges from 8bit colour.", // cmd, false ); // Terrain Type // ////////////////// ValueArg<string> arg_type( "t", "typemap", "Image to define terrain types.", false, "", "image", cmd ); // Minimap // ///////////// ValueArg<string> arg_minimap( "m", "minimap", "Image file to use for the minimap", false, "", "image", cmd ); // Metal // /////////// ValueArg<string> arg_metal( "r", "metalmap", "Image used for built in resourcing scheme.", false, "", "image", cmd); // Grass // /////////// ValueArg<string> arg_grass( "g", "grassmap", "Image used to place grass.", false, "", "image", cmd ); // Features // ////////////// ValueArg<string> arg_features( "f", "featurelist", "Text file defining type, location, rotation of feature and " "decal to paint to diffuse texture.", false, "", ".csv", cmd ); // Parse the args. cmd.parse( argc, argv ); // Get the value parsed by each arg. // Generic Options loadFile = arg_load.getValue(); saveFile = arg_save.getValue(); verbose = arg_verbose.getValue(); quiet = arg_quiet.getValue(); decompile = arg_decompile.getValue(); slowcomp = arg_slowcomp.getValue(); // Map Dimensions width = arg_width.getValue(); length = arg_length.getValue(); floor = arg_floor.getValue(); ceiling = arg_ceiling.getValue(); // SMT options tileFiles = arg_add_smt.getValue(); // SMT Input Filenames tilemapFile = arg_tileindex.getValue(); // Height heightFile = arg_height.getValue(); invert = arg_invert.getValue(); //FIXME lowpass = arg_lowpass.getValue(); // Terrain Type typeFile = arg_type.getValue(); // Minimap minimapFile = arg_minimap.getValue(); // Metal Map metalFile = arg_metal.getValue(); // Grass Map grassFile = arg_grass.getValue(); // Feature List featuresFile = arg_features.getValue(); } catch ( ArgException &e ) { cerr << "error: " << e.error() << " for arg " << e.argId() << endl; exit( -1 ); } // Test arguments for validity before continuing // /////////////////////////////////////////////////// if ( width < 2 || width > 256 || width % 2 ) { if( !quiet )cout << "ERROR: Width needs to be multiples of 2 between and including 2 and 64" << endl; fail = true; } if ( length < 2 || length > 256 || length % 2 ) { if( !quiet )cout << "ERROR: Length needs to be multiples of 2 between and including 2 and 64" << endl; fail = true; } if(decompile && !strcmp(loadFile.c_str(), "")) { fail = true; if( !quiet )cout << "ERROR: no file specified to decompile" << endl; } if( fail ) exit(-1); // Globals // ///////////// SMF smf; smf.verbose = verbose; smf.quiet = quiet; smf.slowcomp = slowcomp; smf.invert = invert; // Load file if(strcmp(loadFile.c_str(), ""))smf.load(loadFile); // decompile loaded file if(decompile) { loadFile.erase(loadFile.size()-4); smf.setOutPrefix(loadFile); smf.decompileAll(0); } // Change attributes smf.setDimensions(width, length, floor, ceiling); if( strcmp(heightFile.c_str(), "") ) smf.setHeightFile( heightFile ); if( strcmp(typeFile.c_str(), "") ) smf.setTypeFile( typeFile ); if( strcmp(minimapFile.c_str(), "") ) smf.setMinimapFile( minimapFile ); if( strcmp(metalFile.c_str(), "") ) smf.setMetalFile( metalFile ); if( strcmp(tilemapFile.c_str(), "") ) smf.setTilemapFile(tilemapFile ); if( strcmp(featuresFile.c_str(), "") ) smf.setFeaturesFile( featuresFile ); if( strcmp(grassFile.c_str(), "") ) smf.setGrassFile(grassFile); if( !strcmp(grassFile.c_str(), "") ) smf.unsetGrassFile(); for(unsigned int i = 0; i < tileFiles.size(); ++i ) { smf.addTileFile(tileFiles[i]); } //Save if( strcmp(saveFile.c_str(), "") )smf.save( saveFile ); return 0; }
void SMFWriter::save( const QString& sFilename, Song *pSong ) { INFOLOG( "save" ); const int DRUM_CHANNEL = 9; vector<SMFEvent*> eventList; SMF smf; // Standard MIDI format 1 files should have the first track being the tempo map // which is a track that contains global meta events only. SMFTrack *pTrack0 = new SMFTrack(); pTrack0->addEvent( new SMFCopyRightNoticeMetaEvent( pSong->__author , 0 ) ); pTrack0->addEvent( new SMFTrackNameMetaEvent( pSong->__name , 0 ) ); pTrack0->addEvent( new SMFSetTempoMetaEvent( pSong->__bpm , 0 ) ); pTrack0->addEvent( new SMFTimeSignatureMetaEvent( 4 , 4 , 24 , 8 , 0 ) ); smf.addTrack( pTrack0 ); // Standard MIDI Format 1 files should have note events in tracks =>2 SMFTrack *pTrack1 = new SMFTrack(); smf.addTrack( pTrack1 ); AutomationPath *vp = pSong->get_velocity_automation_path(); InstrumentList *iList = pSong->get_instrument_list(); // ogni pattern sara' una diversa traccia int nTick = 1; for ( unsigned nPatternList = 0 ; nPatternList < pSong->get_pattern_group_vector()->size() ; nPatternList++ ) { // infoLog( "[save] pattern list pos: " + toString( nPatternList ) ); PatternList *pPatternList = ( *(pSong->get_pattern_group_vector()) )[ nPatternList ]; int nStartTicks = nTick; int nMaxPatternLength = 0; for ( unsigned nPattern = 0 ; nPattern < pPatternList->size() ; nPattern++ ) { Pattern *pPattern = pPatternList->get( nPattern ); // infoLog( " |-> pattern: " + pPattern->getName() ); if ( ( int )pPattern->get_length() > nMaxPatternLength ) { nMaxPatternLength = pPattern->get_length(); } for ( unsigned nNote = 0; nNote < pPattern->get_length(); nNote++ ) { const Pattern::notes_t* notes = pPattern->get_notes(); FOREACH_NOTE_CST_IT_BOUND(notes,it,nNote) { Note *pNote = it->second; if ( pNote ) { float rnd = (float)rand()/(float)RAND_MAX; if ( pNote->get_probability() < rnd ) { continue; } float fPos = nPatternList + (float)nNote/(float)nMaxPatternLength; float velocity_adjustment = vp->get_value(fPos); int nVelocity = (int)( 127.0 * pNote->get_velocity() * velocity_adjustment ); int nInstr = iList->index(pNote->get_instrument()); Instrument *pInstr = pNote->get_instrument(); int nPitch = pNote->get_midi_key(); eventList.push_back( new SMFNoteOnEvent( nStartTicks + nNote, DRUM_CHANNEL, nPitch, nVelocity ) ); int nLength = 12; if ( pNote->get_length() != -1 ) { nLength = pNote->get_length(); } eventList.push_back( new SMFNoteOffEvent( nStartTicks + nNote + nLength, DRUM_CHANNEL, nPitch, nVelocity ) ); } } } } nTick += nMaxPatternLength; }
int main( int argc, char **argv ) { // == temporary/global variables SMF *smf = nullptr; SMT *smt = nullptr; bool force = false; uint32_t mapWidth = 0, mapLength = 0; string outFileName; fstream tempFile; uint32_t tileSize = 32; float mapFloor = 0.01f, mapCeiling = 1.0f; // Options Parsing // =============== bool fail = false; argc -= (argc > 0); argv += (argc > 0); option::Stats stats( usage, argc, argv ); option::Option* options = new option::Option[ stats.options_max ]; option::Option* buffer = new option::Option[ stats.buffer_max ]; option::Parser parse( usage, argc, argv, options, buffer ); // unknown options for( option::Option* opt = options[ UNKNOWN ]; opt; opt = opt->next() ){ LOG( ERROR ) << "Unknown option: " << string( opt->name, opt->namelen ); fail = true; } // -h --help if( options[ HELP ] || argc == 0 ){ int columns = getenv( "COLUMNS" ) ? atoi( getenv( "COLUMNS" ) ) : 80; option::printUsage( std::cout, usage, columns ); exit( 1 ); } // -v --verbose LOG::SetDefaultLoggerLevel( LOG::WARN ); if( options[ VERBOSE ] ) LOG::SetDefaultLoggerLevel( LOG::INFO ); // -q --quiet if( options[ QUIET ] ) LOG::SetDefaultLoggerLevel( LOG::CHECK ); // -o --output filename if( options[ OUTPUT ] ) outFileName = options[ OUTPUT ].arg; else outFileName = "output.smf"; // -f --force if( options[ FORCE ] ){ force = true; } // --mapsize if( options[ MAPSIZE ] ){ std::tie( mapWidth, mapLength ) = valxval( options[ MAPSIZE ].arg ); if( mapWidth % 2 || mapLength % 2 ){ LOG( ERROR ) << "map sizes must be multiples of two"; fail = true; } } if( (! mapWidth || ! mapLength) && (! options[ TILEMAP ]) ){ //FIXME dont error here, check first if a tilefile is specified. LOG( ERROR ) << "--mapsize not specified"; fail = true; } //TODO add squarewidth //TODO add texels // --tilesize // take the tilesize from the first smt added if( parse.nonOptionsCount() ){ CHECK( SMT::test( parse.nonOption( 0 ) ) ) << " additional arguments are not smt files"; smt = SMT::open( parse.nonOption( 0 ) ); tileSize = smt->tileSize; delete smt; smt = nullptr; } // take the tilesize from the arguments if( options[ TILESIZE ] ){ tileSize = atoi( options[ TILESIZE ].arg ); } if( tileSize % 4 ){ LOG( ERROR ) << "tile size must be a multiple of 4"; fail = true; } // -y --floor if( options[ FLOOR ] ){ mapFloor = atof( options[ FLOOR ].arg ); } // -Y --ceiling if( options[ CEILING ] ){ mapCeiling = atof( options[ CEILING ].arg ); } // --tilemap SMF *smfTemp = nullptr; TileMap *tileMap = nullptr; if( options[ TILEMAP ] ){ if( SMF::test( options[ TILEMAP ].arg ) ){ smfTemp = SMF::open( options[ TILEMAP ].arg ); tileMap = smfTemp->getMap(); delete smfTemp; } else { tileMap = TileMap::createCSV( options[ TILEMAP ].arg ); } } // Fix up map height and length to match tile source, and smt files. if( tileMap != nullptr ){ int diffuseWidth = tileSize * tileMap->width; int diffuseHeight = tileSize * tileMap->height; if( diffuseWidth % 1024 || diffuseHeight % 1024){ LOG( ERROR ) << "(tileMap * tileSize) % 1024 != 0," "supplied arguments do not construct a valid map"; fail = true; } mapWidth = diffuseWidth / 512; mapLength = diffuseHeight / 512; LOG( INFO ) << "Checking input dimensions" << "\n\ttileMap: " << tileMap->width << "x" << tileMap->height << "\n\ttileSize: " << tileSize << "x" << tileSize << "\n\tdiffuse= " << diffuseWidth << "x" << diffuseHeight << "\n\tmapSize= " << mapWidth << "x" << mapLength; } //TODO collect feature information from the command line. // end option parsing if( fail || parse.error() ){ exit( 1 ); } // == lets do it! == if(! (smf = SMF::create( outFileName, force )) ){ LOG(FATAL) << "Unable to create: " << outFileName; } // == Information Collection == // === header information === // * width & length smf->setSize( mapWidth, mapLength ); // * squareWidth // TODO // * squareTexels // TODO // * tileSize smf->setTileSize( tileSize ); // * floor & ceiling smf->setDepth( mapFloor, mapCeiling ); // === extra header information === // * enable grass if( options[ GRASS ] ){ smf->enableGrass(true); } // map header and smt files // * add smt files for( int i = 0; i < parse.nonOptionsCount(); ++i ){ smf->addTileFile( parse.nonOption( i ) ); } // features // * add features if( options[ FEATURES ] ){ smf->addFeatures( options[ FEATURES ].arg ); } // == calculate remaining file properties == smf->updateSpecs(); smf->updatePtrs(); // == Write == // header smf->writeHeader(); // extra headers smf->writeExtraHeaders(); // height if( options[ HEIGHT ] ){ ImageBuf heightBuf( options[ HEIGHT ].arg ); smf->writeHeight( &heightBuf ); } else { smf->writeHeight(); } // type if( options[ TYPE ] ){ ImageBuf typeBuf( options[ TYPE ].arg ); smf->writeType( &typeBuf ); } else { smf->writeType(); } // map header // map smt's smf->writeTileHeader(); // tilemap smf->writeMap( tileMap ); // minimap if( options[ MINI ] ){ ImageBuf miniBuf( options[ MINI ].arg ); smf->writeMini( &miniBuf ); } else { smf->writeMini(); } // metalmap if( options[ METAL ] ){ ImageBuf metalBuf( options[ METAL ].arg ); smf->writeMetal( &metalBuf ); } else { smf->writeMetal(); } // features smf->writeFeatures(); // grass if( options[ GRASS ] ){ ImageBuf grassBuf( options[ GRASS ].arg ); smf->writeGrass( &grassBuf ); } LOG(INFO) << smf->info(); smf->good(); delete smf; delete [] options; delete [] buffer; return 0; }