diff --git a/stepmania/README-FIRST.TXT b/stepmania/README-FIRST.TXT index bf76c476e4..128207b7d3 100644 --- a/stepmania/README-FIRST.TXT +++ b/stepmania/README-FIRST.TXT @@ -35,48 +35,61 @@ Table of Contents 11. Questions, Bugs, Suggestions, and Help 12. The StepMania Editor 13. The .SM File Format -14. Building StepMania from CVS Source -15. Version History +14. Background Animations +15. The .CRS File Format +16. Building StepMania from CVS Source +17. Version History ************************************************************ 1. About StepMania ************************************************************ -StepMania game system is capable of playing many game types. Currently, it supports games Dance Dance Revolution and Pump It Up, with future support for EZ 2 Dancer, BeatMania, Guitar Freaks, DrumMania, Para Para Paradise and more. +StepMania game system is capable of playing many game types. Currently, it +supports games Dance Dance Revolution and Pump It Up, with future support for EZ +2 Dancer, BeatMania, Guitar Freaks, DrumMania, Para Para Paradise and more. ************************************************************ 2. Minimum Requirements ************************************************************ -* Windows 98, Windows ME, Windows 2000, or Windows XP. -* Required: Pentium II, Pentium III, Celeron, Athlon, or compatible processor, 266MHz minimum (400 MHz highly recommended). -* 64 MB of RAM. -* Video card that supports High Color (16-bit color) and has 16MB video RAM. -* DirectX 8.1 compatible video card with drivers. -* DirectX 8.1 compatible sound card with drivers. -* DivX 5 video codec (for movie visualizations). +* Windows 98, Windows ME, Windows 2000, or Windows XP +* Pentium II, Pentium III, Celeron, Athlon, or compatible processor, 266MHz + minimum (400 MHz highly recommended) +* 64 MB of RAM +* Video card that supports High Color (16-bit color) and has 16MB video RAM +* DirectX 8.1 compatible video card with drivers +* DirectX 8.1 compatible sound card with drivers +* DivX 5 video codec (for movie visualizations) ************************************************************ 3. DirectX ************************************************************ -DirectX 8.1 is required before installing StepMania. If DirectX 8.1 is not installed on your computer, the StepMania installer will display a warning and abort the installation. +DirectX 8.1 is required before installing StepMania. If DirectX 8.1 is not +installed on your computer, the StepMania installer will display a warning +and abort the installation. ************************************************************ 4. Installation ************************************************************ -To install StepMania, download the file stepmania3.exe to a known location on your hard drive, then double-click the file icon to begin the installation. The installer automatically remove an older version of the program if one is present. The default installation directory is 'C:\Program Files\StepMania'. +To install StepMania, download the file stepmania3.exe to a known location +on your hard drive, then double-click the file icon to begin the installation. +The installer automatically remove an older version of the program if one is +present. The default installation directory is 'C:\Program Files\StepMania'. ************************************************************ 5. Controls ************************************************************ -Use the "Config Key/Joy" option from the Title Menu to configure your keyboad or dance pad. +Use the "Config Key/Joy" option from the Title Menu to configure your +keyboad or dance pad. Any time: * F4 = toggle fullscreen * F5 = toggle detail + * Tab = increase game speed 4x + * LShift = decrease game speed to 1/4x In menus: * Arrow keys navigate menus @@ -85,12 +98,14 @@ In menus: In gameplay: * F11 = decrease offset * F12 = increase offset + * Hold Escape = abort playing ************************************************************ 6. How StepMania Loads Songs ************************************************************ -All song files for a specific song (data file, music file, banner, background) must reside in a single folder. This folder must have the following path: +All song files for a specific song (data file, music file, banner, background) +must reside in a single folder. This folder must have the following path: Songs/// @@ -100,44 +115,94 @@ For example, the song B4U may consist of the following files: Songs/Dance Dance Revolution 4th Mix/B4U/b4u.mp3 Songs/Dance Dance Revolution 4th Mix/B4U/b4u-banner.png Songs/Dance Dance Revolution 4th Mix/B4U/b4u.png + Songs/Dance Dance Revolution 4th Mix/B4U/b4u-movie.avi + +StepMania supports the SM, DWI, and BMS song file formats. + +If a song file does not specify a valid banner file, StepMania first looks +for a graphic in the song folder that contains the letters "banner". If that +search fails, StepMania will guess which image is most appropriate. + +If a song file does not specify a valid background file, StepMania first looks +for a graphic in the song folder that contains the letters "bg" or "background". +If that search fails, StepMania will guess which image is most appropriate. + +If a song file does not specify a valid CDTitle file, StepMania will look +for a graphic in the song folder that contains the letters "cdtitle". If that +search fails, StepMania will guess which image is most appropriate. + +Also, for compatibility with DWI, if can reading CDTitles from the .\CDTitles +folder. Song makers are not encouraged to not use this feature and instead +should put the CDTitle graphic in the song folder. Having a separate CDTitles +folder breaks the principle that all files needed to play a song should reside +in the song folder. + +If a song file does not specify a valid movie background file, StepMania will +look for a movie in the song folder that contains the letters "movie". If +that search fails, StepMania will use the first movie in the song folder. ************************************************************ 7. Connecting Dance Pads ************************************************************ -There are several devices that allow you to connect PlayStation dance pads to your PC. +There are several devices that allow you to connect PlayStation dance pads to +your PC. * Not recommended: generic PlayStation->USB converter -Using a generic PlayStation->USB converter is not recommended to play any dancing game on the PC. The vast majority of these converters are not capable of registering simultaneous presses of Left+Right or Up+Down. This restriction will cause the player to miss many notes where two buttons must be hit simultaneously. +Using a generic PlayStation->USB converter is not recommended to play any +dancing game on the PC. The vast majority of these converters are not capable +of registering simultaneous presses of Left+Right or Up+Down. This +restriction will cause the player to miss many notes where two buttons must +be hit simultaneously. * Highly Recommended: Special PlayStation->USB adaptor -There is just one brand of PlayStation->USB adaptor that functions perfectly with StepMania. These adaptors are available for purchase at the StepMania web site (www.stepmania.com) and through some importers (www.liksang.com). The adaptor is made by “Boom”, and it small and black with a detachable USB cable. These adaptors cost about $15 and allow you to attach one dance pad per adaptor. The primary advantage of these adaptors is that they do not require special drivers and require no configuring. +There is just one brand of PlayStation->USB adaptor that functions perfectly +with StepMania. These adaptors are available for purchase at the StepMania +web site (www.stepmania.com) and through some importers (www.liksang.com). +The adaptor is made by “Boom”, and it small and black with a detachable USB +cable. These adaptors cost about $15 and allow you to attach one dance pad +per adaptor. The primary advantage of these adaptors is that they do not +require special drivers and require no configuring. * Semi-Recommended: PlayStation->Parallel adaptor -PlayStation->Parallel converters do not have the simultaneous button problem that USB converters do. The disadvantage of these adaptors is that home-made drivers are required to use these devices. These drivers are often finicky and incompatible with some sound cards. PlayStation->Parallel adaptors can be purchased from the StepMania web site or any importer. +PlayStation->Parallel converters do not have the simultaneous button problem +that USB converters do. The disadvantage of these adaptors is that home-made +drivers are required to use these devices. These drivers are often finicky +and incompatible with some sound cards. PlayStation->Parallel adaptors can +be purchased from the StepMania web site or any importer. -For Windows 98 and Windows Me users, the recommended driver is “DirectPad Pro 5.0 for Win9x”. For Windows 2000 and Windows XP, the recommended drivers are NTPad XP 1.x. Both of these drivers can be downloaded from Aldos web site: http://www.aldostools.com/dpad.html +For Windows 98 and Windows Me users, the recommended driver is "DirectPad Pro +5.0 for Win9x". For Windows 2000 and Windows XP, the recommended drivers are +NTPad XP 1.x. Both of these drivers can be downloaded from Aldos web site: +http://www.aldostools.com/dpad.html ************************************************************ 8. Compatibility Issues ************************************************************ -Some video card/driver combinations have visual errors when running StepMania. If you experience any visual errors, please visit your video card manufacturer's web site and download the latest Direct3D 8.1 drivers. Below is a list of known issues that are thought to be video card driver bugs: +Some video card/driver combinations have visual errors when running StepMania. +If you experience any visual errors, please visit your video card manufacturer's +web site and download the latest Direct3D 8.1 drivers. Below is a list of known +issues that are thought to be video card driver bugs: * S3 Savage family cards (e.g. Diamond Stealth) Symptom: The right edge of some graphics appears "cut off". -Explanation: Drivers do not properly handle textures > 512x512, resulting in cropped textures. Please use the Low texture detail option to force texture to be 512x512 or smaller. +Explanation: Drivers do not properly handle textures > 512x512, resulting in +cropped textures. Please use the Low texture detail option to force texture to +be 512x512 or smaller. * SiS cards Symptom: Garbled fonts. -Explanation: Drivers have errors in handling texture coordinates. Only known solution is to upgrade drivers. +Explanation: Drivers have errors in handling texture coordinates. Only known +solution is to upgrade drivers. * Any card older than two years Symptom: Various graphical glitches. -Explanation: These problems are most often video card driver bugs. Please upgrade to the latest drivers, which will hopefully fix the errors. +Explanation: These problems are most often video card driver bugs. Please +upgrade to the latest drivers, which will hopefully fix the errors. ************************************************************ @@ -150,15 +215,21 @@ You need to download DirectX 8.1. http://www.microsoft.com/directx * Music rates of over 100% do not work on my computer. Why? -Some very old sound cards do not support sound playback rates that are greater than the original sample rate. This problem is likely to be corrected by newer sound card drivers. +Some very old sound cards do not support sound playback rates that are greater +than the original sample rate. This problem is likely to be corrected by newer +sound card drivers. -* StepMania reports “Direct3D Create Device failed”. +* StepMania reports "Direct3D Create Device failed". -This error means that your video card or drivers do not support Direct3D 8. Download the latest drivers for your video card. If your video card is older than 2 or 3 years, Direct3D 8 drivers may not be available. Sorry. +This error means that your video card or drivers do not support Direct3D 8. +Download the latest drivers for your video card. If your video card is older +than 2 or 3 years, Direct3D 8 drivers may not be available. Sorry. * I’m looking to purchase a video card. What works well with StepMania? -Just about any video card manufactured in the last year will run StepMania flawlessly at 60 frames per second. I recommend any card with an nVidia GeForce chip or an ATI Radeon chip. +Just about any video card manufactured in the last year will run StepMania +flawlessly at 60 frames per second. I recommend any card with an nVidia +GeForce chip or an ATI Radeon chip. * How can I improve performance with my existing video card @@ -169,136 +240,391 @@ Just about any video card manufactured in the last year will run StepMania flawl 10. StepMania Packages - .smzip ************************************************************ -The StepMania package format was created to make the distribution of songs and other add-ons very easy.  StepMania package files have the extension '.smzip' and can be installed by double-clicking the .smzip file. +The StepMania package format was created to make the distribution of songs and +other add-ons very easy.  StepMania package files have the extension '.smzip' +and can be installed by double-clicking the .smzip file. -A StepMania package is 'installed' by extracting all files in the package to the StepMania program directory. This allows songs, courses, themes, and visualizations to all be installed by the Package Manager. +A StepMania package is 'installed' by extracting all files in the package to the +StepMania program directory. This allows songs, courses, themes, and +visualizations to all be installed by the Package Manager. -The file format of an .smzip file is actually the PK-Zip standard.  This means you can rename any .smzip file to have the extension '.zip', and then open the file in any compression package (e.g. WinZip). +The file format of an .smzip file is actually the PK-Zip standard.  This means +you can rename any .smzip file to have the extension '.zip', and then open the +file in any compression package (e.g. WinZip). -The StepMania Package Manager (smpackage.exe) can also create song packages for you. Simply launch the Package Manager (Start Menu->Programs->StepMania->Package Manager), click the song you want to create a package for, click the Export button, and a .smzip package will be placed on your desktop. +The StepMania Package Manager (smpackage.exe) can also create song packages +for you. Simply launch the Package Manager +(Start Menu->Programs->StepMania->Package Manager), click the song you want to +create a package for, click the Export button, and a .smzip package will be +placed on your desktop. ************************************************************ 11. Questions, Bugs, Suggestions, and Help ************************************************************ -If you have a question or problem about StepMania, please try asking your question to the StepMania message board. A link is available from the StepMania web site – http://www.stepmania.com. +If you have a question or problem about StepMania, please try asking your +question to the StepMania message board. A link is available from the StepMania +web site - http://www.stepmania.com. -If you have found a bug, please file a bug report into the SourceForge bug tracking system (http://sourceforge.net/tracker/?group_id=37892&atid=421366).  This will allow the developers to track and fix bugs much more efficiently.   +If you have found a bug, please file a bug report into the SourceForge bug +tracking system (http://sourceforge.net/tracker/?group_id=37892&atid=421366).   +This will allow the developers to track and fix bugs much more efficiently.   -* In a bug report, please specify your video card brand and model, and your OS version. -* PLEASE, PLEASE enter your e-mail address on the bug reports. In many cases, we need more information from the bug reporter. +* In a bug report, please specify your video card brand and model, and your OS +version. +* PLEASE, PLEASE enter your e-mail address on the bug reports. In many cases, +we need more information from the bug reporter. -Please use SourceForge's feature request system to enter new feature requests (http://sourceforge.net/tracker/?atid=421369&group_id=37892&func=browse). Also, please discuss feature ideas on the StepMania message board or the StepMania developers list (stepmania-devs@sourceforge.net).   +Please use SourceForge's feature request system to enter new feature requests +(http://sourceforge.net/tracker/?atid=421369&group_id=37892&func=browse). Also, +please discuss feature ideas on the StepMania message board or the StepMania +developers list (stepmania-devs@sourceforge.net).   -If you would like to help with development of StepMania, please send an email to the StepMania developers list (stepmania-devs@sourceforge.net) or to Chris (chris@videogamers.com). +If you would like to help with development of StepMania, please send an email +to the StepMania developers list (stepmania-devs@sourceforge.net) or to Chris +(chris@videogamers.com). ************************************************************ 12. The StepMania editor ************************************************************ -The StepMania editor allows you to edit, record, synchronize, and play back note patterns. Current, it support saving only in the .SM format. If you save a song that was originally in DWI or BMS format, the old DWI and BMS files will be renamed to have ".old" appended to avoid conflicts when the song is next loaded. All of the commands are listed along the left side of the screen. +The StepMania editor allows you to edit, record, synchronize, and play back +note patterns. Current, it support saving only in the .SM format. If you save +a song that was originally in DWI or BMS format, the old DWI and BMS files will +be renamed to have ".old" appended to avoid conflicts when the song is next +loaded. All of the commands are listed along the left side of the screen. ************************************************************ 13. The .SM file format ************************************************************ -The .SM song file format was created to be one file format that supports all game types that StepMania can play (dance, pump, beat, guitar, etc). The .SM file syntax is identical to DWI except for some different tags and meanings. These are a list of all supported tags. +The .SM song file format was created to be one file format that supports all +game types that StepMania can play (dance, pump, beat, guitar, etc). The .SM +file syntax is identical to DWI except for some different tags and meanings. +These are a list of all supported tags. -All images can be in png, gif, jpg, or bmp format. All sounds can be in ogg, mp3, or wav format. +All images can be in png, gif, jpg, or bmp format. All sounds can be in ogg, +mp3, or wav format. #TITLE:...; - The "main title" of the song. -#SUBTITLE:...; - This text will appear underneath the main title of the song on the Select Music screen. e.g. "-Dirty Mix-", "(remix)". +#SUBTITLE:...; - This text will appear underneath the main title of the song +on the Select Music screen. e.g. "-Dirty Mix-", "(remix)". #ARTIST:...; - The artist of the song. #CREDIT:...; - Give yourself some credit here for creating a wonderful song. #BPM:...; - BPM of the music -#BANNER:...; - The file name of the banner image. e.g. "b4u-banner.png". This image must reside in the song folder. -#BACKGROUND:...; - The file name of the background image. e.g. "b4u-bg.png". This image must reside in the song folder. -#CDTITLE:...; - The file name of the spinning CD logo. e.g. "b4u-cdtitle.png". This image must reside in the song folder. -#MUSIC:...; - The file name of the music file. e.g. "b4u.mp3". This image must reside in the song folder. -#MUSICBYTES:...; - The size in bytes of the music file that this song was last synchronized with. A "Song may be out of synch" warning will be displayed if the value of this tag does not match the actual size of the music file. -#OFFSET:...; - The time in seconds at which beat 0 occurs in the music. This is specified as a floating point value. e.g. "2.34". -#SAMPLESTART:...; - The time in seconds to start the music sample that plays on the Select Music screen. This is specified as a floating point value. e.g. "32.34". -#SAMPLELENGTH:...; - The time in seconds let the sample music play after starting. This is specified as a floating point value. e.g. "32.34". Note that in the last 1 second of playing the music will fade out. -#FREEZE:...; - A value of the format "beat=sec". Indicates that at 'beat', the motion of the arrows should stop for "sec" seconds. Both of these values are specified as floating point values. Multiple freezes can be given by separating them with commas. e.g. "60=2.23,80=1.12". - -#BPMS:...; - A value of the format "beat=bpm". Indicates that at 'beat', the speed of the arrows will change to "bpm". Both of these values are specified as floating point values. You must specifiy a BPM value for beat 0. Multiple freezes can be given by separating them with commas. e.g. "0=160,120=80". +#BANNER:...; - The file name of the banner image. e.g. "b4u-banner.png". +This image must reside in the song folder. +#BACKGROUND:...; - The file name of the background image. e.g. "b4u-bg.png". +This image must reside in the song folder. +#CDTITLE:...; - The file name of the spinning CD logo. e.g. "b4u-cdtitle.png". +This image must reside in the song folder. +#MOVIEBACKGROUND:...; - The file name of the a background movie. e.g. "b4u-movie.avi". +This movie must reside in the song folder. +#MUSIC:...; - The file name of the music file. e.g. "b4u.mp3". This image +must reside in the song folder. +#MUSICBYTES:...; - The size in bytes of the music file that this song was last +synchronized with. A "Song may be out of synch" warning will be displayed if +the value of this tag does not match the actual size of the music file. +#OFFSET:...; - The time in seconds at which beat 0 occurs in the music. This +is specified as a floating point value. e.g. "2.34". +#SAMPLESTART:...; - The time in seconds to start the music sample that plays +on the Select Music screen. This is specified as a floating point value. e.g. +"32.34". +#SAMPLELENGTH:...; - The time in seconds let the sample music play after +starting. This is specified as a floating point value. e.g. "32.34". Note +that in the last 1 second of playing the music will fade out. +#BPMS:...; - A value of the format "beat=bpm". Indicates that at 'beat', the +speed of the arrows will change to "bpm". Both of these values are specified +as floating point values. You must specifiy a BPM value for beat 0. Multiple +BPMs can be given by separating them with commas. e.g. "0=160,120=80". +#STOPS:...; - A value of the format "beat=sec". Indicates that at 'beat', +the motion of the arrows should stop for "sec" seconds. Both of these values +are specified as floating point values. Multiple stops can be given by +separating them with commas. e.g. "60=2.23,80=1.12". +#ANIMATIONS:...; - A value of the format "beat=anim name". Indicates that at 'beat', +the background animation should change to the animation names 'anim name'. 'beat' +is a floating point value and 'anim name' is a string. Different animation change +are separated by commas. e.g. "60=falling,80=flower". Each pattern of steps for different modes have the same basic format: -#NOTES:(NotesType):(Description):(DifficultyClass):(DifficultyMeter):(RadarValues):(NoteData); +#NOTES::::::; -NotesType: Must be one of the currently supported types in StepMania: "dance-single", "dance-double", "dance-couple", "dance-solo", "pump-single", "pump-double". +NotesType: Must be one of the currently supported types in StepMania: +"dance-single", "dance-double", "dance-couple", "dance-solo", "pump-single", +"pump-double". -Description: This will be displayed on the gameplay screen. This can be any text, but is most commonly "Basic", "Another", "Trick", "Standard", "SSR", "Maniac", "Heavy", or "Challenge". +Description: This will be displayed on the gameplay screen. This can be any +text, but is most commonly "Basic", "Another", "Trick", "Standard", "SSR", +"Maniac", "Heavy", or "Challenge". -DifficultyClass: This value must be "easy", "medium", or "hard". These values correspond the levels of difficulty on the Select Difficulty screen. +DifficultyClass: This value must be "easy", "medium", or "hard". These values +correspond the levels of difficulty on the Select Difficulty screen. -DifficultyMeter: The difficulty of these notes as a bar rating. The value must be an integer between 1 and 10. +DifficultyMeter: The difficulty of these notes as a bar rating. The value must +be an integer between 1 and 10. -RadarValues: The values that will be displayed on the Groove Radar as floats between 0.00 and 1.00. The 5 values must be separated by commas, and are specified in the order: "stream,voltage,air,freeze,chaos". For MAX300, these values are "0.95,0.98,0.22,0.12,0.13". These values will automatically be written when you save the song in the StepMania editor, but you may edit the .SM file afterward to tweak them. +RadarValues: The values that will be displayed on the Groove Radar as floats +between 0.00 and 1.00. The 5 values must be separated by commas, and are +specified in the order: "stream,voltage,air,freeze,chaos". For MAX300, these +values are "0.95,0.98,0.22,0.12,0.13". These values will automatically be +written when you save the song in the StepMania editor, but you may edit the +.SM file afterward to tweak them. -NoteData: +NoteData: This value requires a longer explanation. The format is pretty +similar to that used in KSF files. -, // measure 32 -1000 +Each note is represented by a character: + +1 = a regular "tap note" +2 = beginning of a "hold note" +3 = end of a "hold note" +a-z,A-z = reserved for game types that have sounds associated with notes + +Notes are grouped into rows. The number of notes in a row depends on the +NotesType field. + +dance-single = 4 notes/row +dance-double = 8 notes/row +dance-couple = 8 notes/row +dance-solo = 6 notes/row +pump-single = 5 notes/row +pump-double = 10 notes/row + +For example, a note row for a dance-single pattern may look like "1001" (press +Left and Right simultaneously. A note row for a dance-double pattern may look +like "10010000" (press Left and Right simultaneously on the left pad). + +Note rows are grouped into measures. The number of note rows in a measure will +determine the time value of each note. For example, if there are 4 note rows +in a measure, each note will be treated as a quarter note. If there are 8 notes +rows in a measure, each note will be treated as a eighth note. If there are 12 +notes rows in a measure, each note will be treated as a triplet note. Measures +are separated by a comma. + +Example: + + // measure 1 +2010 0000 +0100 0000 +: // measure 2 +0001 +0100 0001 0000 +3010 0000 -1000 0000 -, // measure 33 -0010 -0100 -0010 0000 +; + +************************************************************ +14. Background Animations +************************************************************ + +\BGAnimations\\ + +The BGAnimations folder should contain several folders for individual background animations. Currently, these background animations cycle in order of their folder names, changing every 4 measures of the song. + +In an animation folder, each sprite represents one layer. Multiple layers can be specified by having multiple sprites. Layers are drawn from back to front in order of their file name. Different "layer effects" are specified by adding tokens to the file name. Here are an explanation of the currently supported tokens: + +usesongbg - Use the song's background file instead of this graphics file. Since this graphics file will not be used, you might want to make this graphic a 1x1 graphic to save space. + +add - use additive blending instead of normal blending. + +cyclecolor - cycle the color of the layer over the colors of the rainbow + +cyclealpha - cycle the alpha channel of the layer over type + +startonrandomframe - Start the animation on a random frame. This is mainly useful for Tile or Particle effects. + +dontanimate - Stay on the first frame of this animation. This is only useful for layers with multiple frames. + +(stretch effects) - These scretch the graphic across the extire screen. +scretchscrollleft, +stretchscrollright, +stretchscrollup, +stretchscrolldown, + - Scroll the layer in a direction + +stretchwater, +stretchbubble, +stretchtwist, +stretchspin, + - Deform the background sprite with an effect. Only stretch spin is currently implemented. + +(particle effects) - Use the graphic to make individual particles on the screen. +particlesspiralout, +particlesspiralin, + - Spiral particles away from/toward the center of the screen. +particlesfloatup, +particlesfloatdown, +particlesfloatleft, +particlesfloatright, + - Scroll the particles across the screen. +particlesbounce, + - Particles start traveling in random directions and bounce when they hit the edge of the screen. + +(tile effects) - Tile the graphics across the screen, forming a grid of graphics. +tilestill, +tilescrollleft, +tilescrollright, +tilescrollup, +tilescrolldown, + - Scroll the tiles + +tileflipx, +tileflipy, + - Flip the tiles along the X or Y axis. + +tilepulse, + - Tiles zoom in and out. ************************************************************ -14. Building StepMania from CVS source +15. The .CRS File Format ************************************************************ -CVS is the repository that manages the StepMania source code. Our CVS server is graciously provided by SourceForge. You can get the absolute-latest bleeding edge updates to StepMania by taking the source from CVS. Below are instructions on how to configure your computer to download source code from CVS and complile the source into a working executable. +Place holder... + +Header section... +#COURSE:...; - name of the course +#LIVES:<0..10>; - An integer between 0 and 10. This line is optional. +#REPEAT:; - start over after last stage? +#SONG:\:; - + group folder - The name of the folder that contains the song folder. + song folder - the name of the folder that contains files for the song + description - BASIC, TRICK, SSR, MANIAC, HEAVY, etc. + +//The modifiers section could be a list of comma-separated tags, like: +//"1.5x,REVERSE,SUDDEN", etc. We'd have to come up with a standard set for +//features common to both SM and DWI... and new ones could be added for features +//only supported by SM perhaps (Space, Drunk, etc...). +// +//The number of songs in a course is just how many "#SONG:"... lines there are. +// +//So... and "ENDLESS" mode would be as simple as: #COURSE:Endless; #REPEATS:YES; +//#SONG:*:7..9; +// +//New features could be added to the end of the "#SONG" line in the future. +//...how does this all sound to you? That way courses could easily be used between +//versions and passed around. :) +// + +************************************************************ +15. Building StepMania from CVS source +************************************************************ + +CVS is the repository that manages the StepMania source code. Our CVS server is +graciously provided by SourceForge. You can get the absolute-latest bleeding +edge updates to StepMania by taking the source from CVS. Below are instructions +on how to configure your computer to download source code from CVS and complile +the source into a working executable. * Step 1: Install and configure Visual C++ -The StepMania source can currently be built with Microsoft Visual C++ 6.0 or Visual C++ .Net. Installing Visual C++ or Visual Studio with all the default options is sufficient. +The StepMania source can currently be built with Microsoft Visual C++ 6.0 or +Visual C++ .Net. Installing Visual C++ or Visual Studio with all the default +options is sufficient. * Step 2: Install the Direct X 8.1 SDK -The DirectX 8.1 SDK is a free (but large) download from Microsoft (link here). Install it using all the default settings. The SDK installer will configure Visual C++ with the correct paths needed to find the DirectX 8.1 libraries and headers. +The DirectX 8.1 SDK is a free (but large) download from Microsoft (link here). +Install it using all the default settings. The SDK installer will configure +Visual C++ with the correct paths needed to find the DirectX 8.1 libraries and +headers. * Step 3: Install WinCVS -A CVS client is required to "checkout" the course from the CVS server. Download version 1.2 of WinCVS here - http://www.cvsgui.org. -IMPORTANT: Now, open and close WinCVS once. This will cause WinCVS to create registry entries, which is required for the next step... +A CVS client is required to "checkout" the course from the CVS server. Download +version 1.2 of WinCVS here - http://www.cvsgui.org. +IMPORTANT: Now, open and close WinCVS once. This will cause WinCVS to create +registry entries, which is required for the next step... * Step 4: Use SourceForge Setup to install SSH and configure WinCVS -A small utility called SourceForge Setup will greatly simplify the steps needed to configure SSH and WinCVS. Download SourceForge Setup here - link here. Use the following settings when prompted by SF Setup: +A small utility called SourceForge Setup will greatly simplify the steps needed +to configure SSH and WinCVS. Download SourceForge Setup here - link here. Use +the following settings when prompted by SF Setup: - Unpack SSH directory: c:\ssh - SSH install direcotory: c:\ssh - Your home directory: c:\ssh - Your SourceForge user name: -yourusername- - Name of the project: stepmania -- The directory where you will be keeping checked out project sources: c:\stepmania -IMPORTANT: If you are using Windows 2000 or Windows XP SourceForge Setup will not correctly write changes to the c:\autoexec.bat file. Verify that the following lines are present after you run SF Setup: +- The directory where you will be keeping checked out project sources: +c:\stepmania +IMPORTANT: If you are using Windows 2000 or Windows XP SourceForge Setup will +not correctly write changes to the c:\autoexec.bat file. Verify that the +following lines are present after you run SF Setup: rem SourceForge setup stuff SET PATH=%PATH%;c:\ssh SET HOME=c:\ssh -IMPORTANT: You must restart after running SF Setup so that the new environment variables take effect. +IMPORTANT: You must restart after running SF Setup so that the new environment +variables take effect. * DONE! Enjoy staying on the bleeding edge of StepMania releases!  ************************************************************ -15. Version History +16. Version History ************************************************************ +------------------------Version 3.00 beta 4------------------ +BUG FIX: Fixed crash entering Config Joy/Key (duh!) +BUG FIX: Smarter bannner/backgroung/cdtitle discovery +NEW FEATURE: Supports reading CDTitles from the .\CDTitles folder (compatible + with DWI). Song makers are not encouraged to use this feature and instead should + put the CDTitle graphic in the song folder. Having a separate CDTitles folder + breaks the principle that all files needed to play a song should reside in the + song folder. +BUG FIX: Fixed "D3DCreateTextureFromFile" error. This happend a lot on a Voodoo3 + and Win98. +BUG FIX: Fixed "Divide by 0"/"Access Violoation" when loading a song - I think. +OPTIMIZATION: Faster loading at "Nth Stage" screen. + +------------------------Version 3.00 beta 3------------------ +BUG FIX: Fixed crash BemaniRuler's "Connected" +BUG FIX: #BPMCHANGE in DWI files now read fractional values (BemaniRuler's Naturally) +BUG FIX: Dizzy works correctly again +BUG FIX: Subtitle extraction now works for "Dub-I-Dub" and "SP-Trip Machine" +BUG FIX: No longer crashes on Titles starting with '(' +BUG FIX: Earlier scrolling for songs that have early notes (BMR's A) +BUG FIX: Inserted blank time for songs that have note right at end of song (AM-3P) +OPTIMIZATION: Faster loading of gameplay screen +BUG FIX: Sample music no longer studders on Select Music screen +BUG FIX: "Shaky" artifacts no longer appear while holding a hold note +CHANGE: Re-added support for movie visualizations (by popular demand). +NEW FEATURE: Movie backgrounds. Either specify with the "#MOVIEBACKGROUND" tag, + or the first movie file in the song directory will be used. Works with + BemaniRuler's background movies. Background movie will not play will not play + if BackgroundMode is set to "OFF". +NEW FEATURE: Song-specific animations. Place all animations in a folder called + "BGAnimations" within the song folder. See "13. The .SM file format" and + "14. Background Animations" in README-FIRST.txt for details. +CHANGE: Appearance Options now available from Title Menu. Here you can choose + the announcer and note skin. + +------------------------Version 3.00 beta 2------------------ +BUG FIX: Fixed crash when loading MAX2 files from ddrei.com +CHANGE: "JudgeWindow" option name changed to "Difficulty" +CHANGE: Initial difficulty made easier +BUG FIX: Song loading now smarter about how it picks banners, backgrounds, + and CDTitles. See readme "6. How StepMania Loads Songs" for details. +BUG FIX: #BPMS in SM files now read fractional values +NEW FEATURE: Background brightness (Game Options) +BUG FIX: BemaniRuler songs (like Pulse) now loaded correctly +BUG FIX: Stationary arrows don't press unless note is a hit +BUG FIX: Size of combo text capped to a reasonable level +BUG FIX: Song background now stretched correctly when used in a background animation +OPTIMIZATION: Reduced lag while starting music sample (Select Music screen) +NEW FEATURE: Menu Timer - accessable from Game Options +BUG FIX: Changes saved in editor now show up immediately (instead of after restart) + ------------------------Version 3.00 beta 1------------------ NEW FEATURE: Roulette NEW FEATURE: AutoPlay (selectable from Game Options screen) @@ -309,8 +635,10 @@ NEW FEATURE: "Judge Window" option to adjust difficulty of step judging NEW FEATURE: Song data cache for faster loading. NEW FEATURE: Groove Radar NEW FEATURE: Dark Mode (selectable from Player Options screen) +NEW FEATURE (partially complete): Nonstop Challenge (Oni) NEW FEATURE (partially complete): Pump It Up support -NEW FEATURE (partially complete): Background Animations (defaut animations go in BGAnimations dir) +NEW FEATURE (partially complete): Background Animations (defaut animations go in + BGAnimations dir) ------------------------Version 2.90------------------------- CHANGE: Ogg Vorbis music support re-enabled @@ -327,7 +655,8 @@ OPTIMIZATION: Major speedup to BitmapText loading CHANGE: Menus changes to accomodate MAX-style menus CHANGE: Now compiles in Visual C++.Net OPTIMIZATION: Max texture size and texture color options are now supported. -BUG FIX: Scaled sprite alignment (no more transparent strip along the edge of "danger" static) +BUG FIX: Scaled sprite alignment (no more transparent strip along the edge of + "danger" static) NEW FEATURE: Repeating input NEW FEATURE: Select Group menu NEW FEATURE: Edit / Record / Playback @@ -338,9 +667,11 @@ BUG FIX: Statistics now save and load correctly BUG FIX: Better framerate during gameplay ------------------------Version 1.64------------------------- -NEW FEATURE: Group banners on Select Music screen. Just put a banner in the group folder. +NEW FEATURE: Group banners on Select Music screen. Just put a banner in the group + folder. BUG FIX: Hacked around a Savage texture loading bug. -CHANGE: Added "hold NEXT for options" after choosing a song. Most people don't know about this feature! +CHANGE: Added "hold NEXT for options" after choosing a song. Most people don't know + about this feature! CHANGE: Faster song loading CHANGE: more accurate synching at song rates other than 100% CHANGE: Assist tick calibrated automatically by detecting sound card play latency @@ -357,12 +688,14 @@ BUG FIX: Prefs, songs, and default mappings now load if StepMania.ini doesn't e BUG FIX: Pad 2 can now be used to navigate the title screen BUG FIX: Crash if change sort while a section item was selected BUG FIX: BPM changes to 0 when section is selected -BUG FIX: Pixel/Texel alignment bug causing a strip of color along right and bottom edges moving between menus. +BUG FIX: Pixel/Texel alignment bug causing a strip of color along right and bottom + edges moving between menus. BUG FIX: Graphical glitches on Results screen BUG FIX: Hold Steps now look better when Scroll Speed is > 1 BUG FIX: Wrong Ghost Arrow graphic being used BUG FIX: Boost/Scroll Speed interaction is now like MAX -BUG FIX: DWI's with newlines before semicolon are no longer corrupt when saving using Synchronize +BUG FIX: DWI's with newlines before semicolon are no longer corrupt when saving + using Synchronize BUG FIX: #516498 - Installing Stepmania Deletes records BUG FIX: #517003 - Joystick mappings not flushed BUG FIX: Multiple NEXT presses not allowed on Caution screen @@ -400,15 +733,18 @@ BUG FIX: #506597 - Empty Sort Crash BUG FIX: #511543/#511186 - Visualizations not shown correctly ------------------------Version 1.59------------------------- -NEW FEATURE: More texture loading hints (DITHER, NO_MIP_MAPS) for increased quality and faster loading time. +NEW FEATURE: More texture loading hints (DITHER, NO_MIP_MAPS) for increased + quality and faster loading time. BUG FIX: #506274 Crash changing song after sorting. BUG FIX: #506343 TextureColor=32 Auto-Reset -CHANGE: SMLauncher integrated with the main StepMania executable. Now the pretty error screen will appear automatically. +CHANGE: SMLauncher integrated with the main StepMania executable. Now the + pretty error screen will appear automatically. NEW FEATURE: Added Low-Medium-High detail prompt to installer. NEW FEATURE: Song sort order is now rememebered. OPTIMIZATION: Instantaneous Song Sort Order switch. OPTIMIZATION: Instantaneous Song Group expand/collapse. -CHANGE: Song Sort groups that begin with a number now appear under the "NUM" group. +CHANGE: Song Sort groups that begin with a number now appear under the "NUM" + group. BUG FIX: "Player's Best" is now sorted by num times played decending BUG FIX: #506835 - PREV from Song Select Fade Glitch BUG FIX: #506827 - Song Selected Graphic Errors @@ -422,12 +758,14 @@ OPTIMIZATION: Improved animation of and optimized drawing of rolling score displ OPTIMIZATION: Toned down motion blur effect in "Failed" for increased performance. BUG FIX: Fixed matrix stack bug that caused some shadows not to draw OPTIMIZATION: Major optimization of BitmapText. Now about 2x faster. -NEW FEATURE: F4-F8: Toggle Fullscreen, Change Resolution, Change Display Color, Change Texture Color, Toggle Statistics +NEW FEATURE: F4-F8: Toggle Fullscreen, Change Resolution, Change Display Color, + Change Texture Color, Toggle Statistics NEW FEATURE: Remebers last selected Steps NEW FEATURE: Stage number saved to .ini file. BUG FIX: Default key buttons don't work if .ini file not present on startup CHANGE: Hold Arrows are now drawn last to first, like in DDR MAX. -NEW FEATURE: Hold Arrows allow you to not hold the button for a second without NG'ing them. +NEW FEATURE: Hold Arrows allow you to not hold the button for a second without + NG'ing them. CHANGE: Regular Arrows on the same line as a Hold Arrow now appear green. NEW FEATURE: Hold Arrows now turn gray player doesn't hold the button. BUG FIX: #510980 Danger is a static box, not text @@ -435,30 +773,38 @@ BUG FIX: #510980 Danger is a static box, not text ------------------------Version 1.57------------------------- NEW FEATURE: smzip package installer and manager CHANGE: Installer now uninstalls previous version. -BUG FIX: Package Manager now converts all non-HTTP-friendly characters to '_' when exporting. -CHANGE: Much better texture loading algorithm. Texture quality and loading time of non-power of 2 texture improved greatly. +BUG FIX: Package Manager now converts all non-HTTP-friendly characters to '_' when + exporting. +CHANGE: Much better texture loading algorithm. Texture quality and loading time of + non-power of 2 texture improved greatly. CHANGE: New 5th Mix theme graphics. Thanks thingmabobr! -BUG FIX: #507170 Speed Problem (Got rid of "pauses" caused by buffered writing to log) +BUG FIX: #507170 Speed Problem (Got rid of "pauses" caused by buffered writing to + log) BUG FIX: #506309 Installer doesn't overwrite files BUG FIX: #511187 old banners are shown diagonal ------------------------Version 1.56------------------------- -BUG FIX: 506314 Fixed "Hall of mirrors" on nVidia cards (actually, just a work around for a driver bug) +BUG FIX: 506314 Fixed "Hall of mirrors" on nVidia cards (actually, just a work + around for a driver bug) CHANGE: Couple and Solo now appear in Select Style CHANGE: New Title Menu options (but you can choose them yet :-) -BUG FIX: Fixed jibberish at the top of Arial Bold font by shifting all letters up one pixel +BUG FIX: Fixed jibberish at the top of Arial Bold font by shifting all letters + up one pixel BUG FIX: 505896 Menu Problems [unreadable/illegible font?] BUG FIX: Ugly textures with Voodoo3 BUG FIX: Ignore Joystick D-pad now works again. -BUG FIX: Installer-created icon "Open Songs Folder" now fixed for OSes that had problems. +BUG FIX: Installer-created icon "Open Songs Folder" now fixed for OSes that had + problems. BUG FIX: BMS parse crash fixed. BUG FIX: Player2 couldn't press up to select different steps -BUG FIX: Player2's side in StepsSelector no longer has multiple bouncing difficulty icons +BUG FIX: Player2's side in StepsSelector no longer has multiple bouncing difficulty + icons BUG FIX: 507380 Multiple FAILED with Esc presses BUG FIX: 507860 - Esc in No Fail Mode = lock up CHANGE: Improved response time to user input when change sort in SelectMusic BUG FIX: Announcer no longer makes dancing comments while FAILED is showing. -OPTIMIZATION: Added texture alpha hints - significantly improved texture quality for 16-bit textures. +OPTIMIZATION: Added texture alpha hints - significantly improved texture quality + for 16-bit textures. ------------------------Version 1.55------------------------- BUG FIX: "4nd Stage" is now "4th Stage" @@ -474,8 +820,10 @@ CHANGE: cleaned up debug messages OPTIMIZATION: Improved texture loading time CHANGE: Maximize button no longer toggles fullscreen. CHANGE: MusicWheel response to user input is improved -OPTIMIZATION: Preview in SelectMusic now uses banner instead of background for faster loading -NEW FEATURE: Change resolution, display color depth, texture color depth, and toggle texture filtering +OPTIMIZATION: Preview in SelectMusic now uses banner instead of background for faster + loading +NEW FEATURE: Change resolution, display color depth, texture color depth, and toggle + texture filtering NEW FEATURE: Check at startup time that all required theme elements are present NEW FEATURE: installer NEW FEATURE: motion blur "Failed" effect @@ -485,11 +833,14 @@ CHANGE: All documentation is now in "Docs" folder CHANGE: New "Danger" animation ------------------------Version 1.50------------------------- -Bug fix: No longer crashes on foreign chars in BMS files. Please report all songs that still cause a crash. -Change: Added sepatate background movie property to Song. Now status backgrounds will display in SelectMusic if the Song has a movie background. +Bug fix: No longer crashes on foreign chars in BMS files. Please report all songs that + still cause a crash. +Change: Added sepatate background movie property to Song. Now status backgrounds will + display in SelectMusic if the Song has a movie background. Change: Asset directory structure has completely changed in preparation for theme support. Optimization: BitmapText is now ~80% faster. -New Feature: 5th Mix style SelectMusic and auto-generated text banners. Loads 100x faster than the previous SelectSong screen. +New Feature: 5th Mix style SelectMusic and auto-generated text banners. Loads 100x faster + than the previous SelectSong screen. Change: Error messages in Release builds no longer show source file line and number. Bug Fix: Fade transition now fades all the way to black (doesn't leave a "hazy" screen). Bug Fix: Multiple joysticks now work again. @@ -497,16 +848,26 @@ Bug Fix: Multiple joysticks now work again. -------------------------Version 0.97------------------------- Bug fix: Songs with same title no longer change positions while scrolling. Bug fix: Wrong group name for DWI files in the Songs folder. -Bug fix: Fixed a problem that caused the music to become out of sync if many sound effect are played. This was causing the song to become out of sync near the end. Note that this change makes the music much more accurate, and some BMS files may be out of sync if they appeared in sync before. -Bug fix: Dancing waits 2 seconds before starting music playback. This allows some slower systems to catch up. +Bug fix: Fixed a problem that caused the music to become out of sync if many sound + effect are played. This was causing the song to become out of sync near the end. + Note that this change makes the music much more accurate, and some BMS files may + be out of sync if they appeared in sync before. +Bug fix: Dancing waits 2 seconds before starting music playback. This allows some + slower systems to catch up. Bug fix: Little now works correctly. It is accessible from the PlayerOptions menu. -Optimization: Lower priority for movie decoding, which is a major speed boost on slower computers. -Change: Freeze arrow scoring now matches DDR MAX. The start of a freeze arrow is judged as other steps are (perfect, great, good, etc).  Missing the start of a freeze will should break your combo, but NG'ing the freeze arrow will not. -New feature: Basic song statistics tracking. Times played, top score, top combo, and top grade are shown on SelectSong screen. +Optimization: Lower priority for movie decoding, which is a major speed boost on + slower computers. +Change: Freeze arrow scoring now matches DDR MAX. The start of a freeze arrow is judged + as other steps are (perfect, great, good, etc).  Missing the start of a freeze will + should break your combo, but NG'ing the freeze arrow will not. +New feature: Basic song statistics tracking. Times played, top score, top combo, and + top grade are shown on SelectSong screen. New feature: Assist tick, accessible from the SongOptions menu. -New feature: Music Rate, accessible from the SongOptions menu. You can speed up or slow down the rate of music playback. Great for practicing hard step patterns. +New feature: Music Rate, accessible from the SongOptions menu. You can speed up or + slow down the rate of music playback. Great for practicing hard step patterns. New feature: Freeze arrow scores are now shown on the Results screen. -Change: Arrow ghost now appear different depending on the combo length (roughly matches DDR MAX). +Change: Arrow ghost now appear different depending on the combo length (roughly matches + DDR MAX). Change: Added some animation to the Results screen. Change: Revamped input mapping to allow assignment and clearing of specific slots. @@ -526,9 +887,12 @@ Bug fix: Freezes in Telephone Operator are now correct Bug fix: Nonsense help messages fixed Bug fix: D3D init failure now opens browser to correct troubleshooting page Optimization: Drawing of freeze arrows is much more efficient -Optimization: In SelectSong, only one preview graphic is drawn. This saves fill rate and leaves room for group/sort/BPM text. -Change: DWI files now use the DWI directory structure. StepMania also automatically crop and rotate the song banner. BMS files still reside in the Songs folder. -Change: Now hold Next to get to PlayerOptions and SongOptions menus (Previously, you would hold Next to bypass these menus). +Optimization: In SelectSong, only one preview graphic is drawn. This saves fill rate + and leaves room for group/sort/BPM text. +Change: DWI files now use the DWI directory structure. StepMania also automatically + crop and rotate the song banner. BMS files still reside in the Songs folder. +Change: Now hold Next to get to PlayerOptions and SongOptions menus (Previously, you + would hold Next to bypass these menus). New feautre: FPS counter. Can toggle from GameOptions. New feature: Disable joystick d-pad (for DirectPad Pro and NTPad). New Feature: Song background movies diff --git a/stepmania/src/AnnouncerManager.cpp b/stepmania/src/AnnouncerManager.cpp index 0882829f2f..b47a93259a 100644 --- a/stepmania/src/AnnouncerManager.cpp +++ b/stepmania/src/AnnouncerManager.cpp @@ -11,6 +11,7 @@ */ #include "AnnouncerManager.h" +#include "PrefsManager.h" #include "RageLog.h" @@ -26,11 +27,10 @@ AnnouncerManager::AnnouncerManager() { CStringArray arrayAnnouncerNames; GetAnnouncerNames( arrayAnnouncerNames ); - for( int i=0; im_sAnnouncer ); } void AnnouncerManager::GetAnnouncerNames( CStringArray& AddTo ) @@ -47,6 +47,24 @@ void AnnouncerManager::GetAnnouncerNames( CStringArray& AddTo ) void AnnouncerManager::SwitchAnnouncer( CString sAnnouncerName ) { + if( sAnnouncerName == "" ) + { + m_sCurAnnouncerName = ""; + return; + } + + + CStringArray asAnnouncerNames; + GetAnnouncerNames( asAnnouncerNames ); + for( int i=0; im_fStartBeat; + float score2 = seg2->m_fStartBeat; + + if( score1 == score2 ) + return 0; + else if( score1 < score2 ) + return -1; + else + return 1; +} + +void SortAnimSegArray( CArray &arrayAnimSegs ) +{ + qsort( arrayAnimSegs.GetData(), arrayAnimSegs.GetSize(), sizeof(AnimSeg), CompareAnimSegs ); +} Background::Background() { m_fSongBeat = 0; + m_bFreeze = false; - m_bShowDanger = false; + m_bInDanger = false; + + m_BackgroundMode = MODE_STATIC_BG; m_sprDanger.SetZoom( 2 ); m_sprDanger.SetEffectWagging(); @@ -33,157 +59,260 @@ Background::Background() m_sprDanger.SetXY( CENTER_X, CENTER_Y ); m_sprDangerBackground.Load( THEME->GetPathTo(GRAPHIC_GAMEPLAY_DANGER_BACKGROUND) ); - m_sprDangerBackground.StretchTo( CRect((int)SCREEN_LEFT, (int)SCREEN_TOP, (int)SCREEN_RIGHT, (int)SCREEN_BOTTOM) ); + m_sprDangerBackground.StretchTo( CRect(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) ); - m_pCurBackgroundAnimation = NULL; + m_quadBGBrightness.StretchTo( CRect(SCREEN_LEFT, SCREEN_TOP, SCREEN_RIGHT, SCREEN_BOTTOM) ); + m_quadBGBrightness.SetDiffuseColor( D3DXCOLOR(0,0,0,1-0.5f) ); +} + +Background::~Background() +{ + for( int i=0; im_BPMSegments.GetSize() + pSong->m_FreezeSegments.GetSize() >= 3 ) - GetDirListing( BG_ANIMS_DIR+"techno*.*", asBGAnimNames, true ); - else if( pSong->m_BPMSegments[0].m_fBPM > 160 ) - GetDirListing( BG_ANIMS_DIR+"trance*.*", asBGAnimNames, true ); + + m_pSong = pSong; + + // + // figure out what BackgroundMode to use + // + if( PREFSMAN->m_BackgroundMode == PrefsManager::BGMODE_OFF ) + m_BackgroundMode = MODE_STATIC_BG; + else if( pSong->HasMovieBackground() ) + m_BackgroundMode = MODE_MOVIE_BG; + else if( PREFSMAN->m_BackgroundMode == PrefsManager::BGMODE_MOVIEVIS ) + m_BackgroundMode = MODE_MOVIE_VIS; else - GetDirListing( BG_ANIMS_DIR+"pop*.*", asBGAnimNames, true ); - - // pick 4 random animations from this array - for( int i=0; iHasBackgroundMovie() ) -// { -// m_sprSongBackground.Load( pSong->GetBackgroundMoviePath() ); -// m_sprSongBackground.SetZoomY( -1 ); // flip -// } -// else - if( pSong->HasBackground() ) - { - m_sprSongBackground.Load( pSong->GetBackgroundPath(), false, 2, 0, true ); - } - else - { - m_sprSongBackground.Load( THEME->GetPathTo(GRAPHIC_FALLBACK_BACKGROUND), false, 2, 0, true ); - } - - m_sprSongBackground.StretchTo( CRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ) ); - m_sprSongBackground.SetDiffuseColor( D3DXCOLOR(0,0,0,1) ); + m_sprSongBackground.Load( pSong->HasBackground() ? pSong->GetBackgroundPath() : THEME->GetPathTo(GRAPHIC_FALLBACK_BACKGROUND), true, 2, 0, true, m_BackgroundMode==MODE_ANIMATIONS ); + + m_sprSongBackground.StretchTo( CRect(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) ); - - if( PREFSMAN->m_visMode == VIS_MODE_MOVIE && !bDisableVisualizations ) + switch( m_BackgroundMode ) { - // load a random visualization - CStringArray sVisualizationNames; - GetDirListing( MOVIE_VIS_DIR + "*.avi", sVisualizationNames ); - GetDirListing( MOVIE_VIS_DIR + "*.mpg", sVisualizationNames ); - GetDirListing( MOVIE_VIS_DIR + "*.mpeg", sVisualizationNames ); - if( sVisualizationNames.GetSize() > 0 ) // there is at least one visualization + case MODE_STATIC_BG: + // do nothing + break; + case MODE_MOVIE_BG: + m_sprMovieBackground.Load( pSong->GetMovieBackgroundPath() ); + m_sprMovieBackground.StretchTo( CRect(SCREEN_LEFT+10,SCREEN_TOP+16,SCREEN_RIGHT-10,SCREEN_BOTTOM-16) ); + m_sprMovieBackground.SetZoomY( m_sprMovieBackground.GetZoomY()*-1 ); + m_sprMovieBackground.StopAnimating( ); + break; + case MODE_MOVIE_VIS: { - int iIndexRandom = rand() % sVisualizationNames.GetSize(); - - m_sprVisualizationOverlay.Load( MOVIE_VIS_DIR + sVisualizationNames[iIndexRandom] ); - m_sprVisualizationOverlay.StretchTo( CRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ) ); - m_sprVisualizationOverlay.SetZoomY( m_sprVisualizationOverlay.GetZoomY()*-1 ); - m_sprVisualizationOverlay.SetBlendModeAdd(); - m_sprVisualizationOverlay.SetDiffuseColor( D3DXCOLOR(0,0,0,0) ); - this->AddActor( &m_sprVisualizationOverlay ); + CStringArray arrayPossibleMovies; + GetDirListing( VISUALIZATIONS_DIR + CString("*.avi"), arrayPossibleMovies ); + GetDirListing( VISUALIZATIONS_DIR + CString("*.mpg"), arrayPossibleMovies ); + GetDirListing( VISUALIZATIONS_DIR + CString("*.mpeg"), arrayPossibleMovies ); + if( arrayPossibleMovies.GetSize() > 0 ) + { + int index = rand() % arrayPossibleMovies.GetSize(); + m_sprMovieVis.Load( VISUALIZATIONS_DIR + arrayPossibleMovies[index] ); + m_sprMovieVis.StretchTo( CRect(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) ); + m_sprMovieVis.SetZoomY( m_sprMovieVis.GetZoomY()*-1 ); + m_sprMovieVis.SetBlendModeAdd(); + } } + break; + case MODE_ANIMATIONS: + { + // + // Load background animations + // + CStringArray asBGAnimNames; + + // First look in the song folder for animations + GetDirListing( pSong->m_sSongDir+"BGAnimations\\*.*", asBGAnimNames, true ); + + if( asBGAnimNames.GetSize() > 0 ) + { + for( int i=0; im_sSongDir+"BGAnimations\\"+asBGAnimNames[i], pSong) ); + + } + else + { + // We're going to try to classify songs as trance, pop, or techno based on some data about the song + if( pSong->m_BPMSegments.GetSize() + pSong->m_StopSegments.GetSize() >= 3 ) + GetDirListing( BG_ANIMS_DIR+"techno*.*", asBGAnimNames, true ); + else if( pSong->m_BPMSegments[0].m_fBPM > 160 ) + GetDirListing( BG_ANIMS_DIR+"trance*.*", asBGAnimNames, true ); + else + GetDirListing( BG_ANIMS_DIR+"pop*.*", asBGAnimNames, true ); + + // load different animations + for( int i=0; im_AnimationSegments.GetSize() > 0 ) + { + // the song has a plan. Use it. + for( int i=0; im_AnimationSegments.GetSize(); i++ ) + { + const AnimationSegment& aniseg = pSong->m_AnimationSegments[i]; + + int iIndex = -1; + for( int j=0; jm_fLastBeat; i+=16 ) + m_aAnimSegs.Add( AnimSeg((float)i,rand()%m_BackgroundAnimations.GetSize()) ); // change BG every 4 bars + + for( i=0; im_BPMSegments.GetSize(); i++ ) + { + const BPMSegment& bpmseg = pSong->m_BPMSegments[i]; + m_aAnimSegs.Add( AnimSeg(bpmseg.m_fStartBeat,int(bpmseg.m_fBPM)%m_BackgroundAnimations.GetSize()) ); // change BG every BPM change + } + SortAnimSegArray( m_aAnimSegs ); + } + } + break; + default: + ASSERT(0); } + return true; } + void Background::Update( float fDeltaTime ) { ActorFrame::Update( fDeltaTime ); - if( m_fSongBeat < 8 ) - m_pCurBackgroundAnimation = NULL; - else - { - if( m_BackgroundAnimations.GetSize() > 0 ) - { - int iIndexToSwitchTo = int(m_fSongBeat/BEATS_PER_MEASURE/4) % m_BackgroundAnimations.GetSize(); - m_pCurBackgroundAnimation = m_BackgroundAnimations[ iIndexToSwitchTo ]; - } - } - - if( DangerVisible() ) { m_sprDangerBackground.Update( fDeltaTime ); m_sprDanger.Update( fDeltaTime ); } else - { - switch( PREFSMAN->m_visMode ) + { + if( m_bFreeze ) + return; + + m_sprSongBackground.Update( fDeltaTime ); + + switch( m_BackgroundMode ) { - case VIS_MODE_ANIMATION: - if( m_pCurBackgroundAnimation && !m_bFreeze ) - m_pCurBackgroundAnimation->Update( fDeltaTime, m_fSongBeat ); - else - m_sprSongBackground.Update( fDeltaTime ); + case MODE_STATIC_BG: + // do nothing break; - - case VIS_MODE_MOVIE: - m_sprVisualizationOverlay.Update( fDeltaTime ); - // fall through and draw background - - case VIS_MODE_NONE: - m_sprSongBackground.Update( fDeltaTime ); + case MODE_MOVIE_BG: + m_sprMovieBackground.Update( fDeltaTime ); break; + case MODE_MOVIE_VIS: + m_sprMovieVis.Update( fDeltaTime ); + break; + case MODE_ANIMATIONS: + if( GetCurBGA() ) + GetCurBGA()->Update( fDeltaTime, m_fSongBeat ); + break; + default: + ASSERT(0); } + + m_quadBGBrightness.Update( fDeltaTime ); } - m_sprVisualizationOverlay.Update( fDeltaTime ); - m_sprSongBackground.Update( fDeltaTime ); - m_sprDanger.Update( fDeltaTime ); - m_sprDangerBackground.Update( fDeltaTime ); +} + +void Background::SetSongBeat( const float fSongBeat, const bool bFreeze, const float fMusicSeconds ) +{ + m_fSongBeat = fSongBeat; + m_bFreeze = bFreeze; + m_fMusicSeconds = fMusicSeconds; + if( m_BackgroundMode == MODE_MOVIE_BG && !m_bStartedBGMovie && m_fMusicSeconds > 0 ) + m_sprMovieBackground.StartAnimating(); } void Background::DrawPrimitives() { ActorFrame::DrawPrimitives(); + if( DangerVisible() ) { m_sprDangerBackground.Draw(); m_sprDanger.Draw(); } else - { - switch( PREFSMAN->m_visMode ) + { + + switch( m_BackgroundMode ) { - case VIS_MODE_ANIMATION: - if( m_pCurBackgroundAnimation ) - m_pCurBackgroundAnimation->Draw(); + case MODE_STATIC_BG: + m_sprSongBackground.Draw(); + break; + case MODE_MOVIE_BG: + ::Sleep(4); // let the movie decode a frame + m_sprMovieBackground.Draw(); + break; + case MODE_MOVIE_VIS: + m_sprSongBackground.Draw(); + ::Sleep(4); // let the movie decode a frame + m_sprMovieVis.Draw(); + break; + case MODE_ANIMATIONS: + if( GetCurBGA() ) + GetCurBGA()->Draw(); else m_sprSongBackground.Draw(); break; - - case VIS_MODE_MOVIE: - m_sprSongBackground.Draw(); - m_sprVisualizationOverlay.Draw(); - break; - - case VIS_MODE_NONE: - m_sprSongBackground.Draw(); - break; + default: + ASSERT(0); } + + m_quadBGBrightness.Draw(); } } bool Background::DangerVisible() { - return m_bShowDanger && (TIMER->GetTimeSinceStart() - (int)TIMER->GetTimeSinceStart()) > 0.5f; + return m_bInDanger && (TIMER->GetTimeSinceStart() - (int)TIMER->GetTimeSinceStart()) > 0.5f; +} + + +void Background::FadeIn() +{ + m_quadBGBrightness.BeginTweening( 0.5f ); + m_quadBGBrightness.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,1-PREFSMAN->m_fBGBrightness) ); +} + +void Background::FadeOut() +{ + m_quadBGBrightness.BeginTweening( 0.5f ); + m_quadBGBrightness.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,1-0.5f) ); + } diff --git a/stepmania/src/Background.h b/stepmania/src/Background.h index 9d2ea46ac7..53d6c4aac6 100644 --- a/stepmania/src/Background.h +++ b/stepmania/src/Background.h @@ -13,53 +13,88 @@ #include "Sprite.h" +#include "Quad.h" #include "ActorFrame.h" #include "Song.h" #include "BackgroundAnimation.h" +struct AnimSeg +{ + AnimSeg() {}; + AnimSeg( float b, int i ) { m_fStartBeat = b; m_iAnimationIndex = i; }; + float m_fStartBeat; + int m_iAnimationIndex; +}; + class Background : public ActorFrame { public: Background(); + ~Background(); + virtual bool LoadFromSong( Song *pSong, bool bDisableVisualizations = false ); virtual void Update( float fDeltaTime ); virtual void DrawPrimitives(); - void SetSongBeat( const float fSongBeat, const bool bFreeze ) { m_fSongBeat = fSongBeat; m_bFreeze = bFreeze; }; + void SetSongBeat( const float fSongBeat, const bool bFreeze, const float fMusicSeconds ); - virtual void SetDiffuseColor( D3DXCOLOR c ) - { - m_sprSongBackground.SetDiffuseColor( c ); - m_sprVisualizationOverlay.SetDiffuseColor( c ); - m_sprSongBackground.SetDiffuseColor( c ); - m_sprDanger.SetDiffuseColor( c ); - m_sprDangerBackground.SetDiffuseColor( c ); - }; + void FadeIn(); + void FadeOut(); - virtual void TurnDangerOn() { m_bShowDanger = true; }; - virtual void TurnDangerOff() { m_bShowDanger = false; }; + virtual void TurnDangerOn() { m_bInDanger = true; }; + virtual void TurnDangerOff() { m_bInDanger = false; }; - virtual bool IsDangerOn() { return m_bShowDanger; }; + virtual bool IsInDanger() { return m_bInDanger; }; protected: bool DangerVisible(); - CArray m_BackgroundAnimations; - BackgroundAnimation* m_pCurBackgroundAnimation; + Song* m_pSong; - Sprite m_sprVisualizationOverlay; + enum BackgroundMode { MODE_STATIC_BG, MODE_MOVIE_BG, MODE_ANIMATIONS, MODE_MOVIE_VIS }; + BackgroundMode m_BackgroundMode; + Sprite m_sprSongBackground; Sprite m_sprDanger; Sprite m_sprDangerBackground; - bool m_bShowDanger; + // for movie BG + Sprite m_sprMovieBackground; + + // for animations + CArray m_BackgroundAnimations; + CArray m_aAnimSegs; + BackgroundAnimation* GetCurBGA() + { + if( m_aAnimSegs.GetSize() == 0 ) + return NULL; + + if( m_fSongBeat < m_pSong->m_fFirstBeat || m_fSongBeat > m_pSong->m_fLastBeat ) + return NULL; + + for( int i=0; i m_fSongBeat ) + break; + int iIndex = m_aAnimSegs[i].m_iAnimationIndex; + return m_BackgroundAnimations[iIndex]; + }; + + + // for movie vis + Sprite m_sprMovieVis; + + Quad m_quadBGBrightness; + + bool m_bInDanger; float m_fSongBeat; bool m_bFreeze; + float m_fMusicSeconds; + bool m_bStartedBGMovie; }; diff --git a/stepmania/src/Banner.cpp b/stepmania/src/Banner.cpp index 4635d590f3..2a1444b626 100644 --- a/stepmania/src/Banner.cpp +++ b/stepmania/src/Banner.cpp @@ -52,7 +52,7 @@ bool Banner::LoadFromSong( Song* pSong ) // NULL means no song if( pSong == NULL ) Banner::Load( THEME->GetPathTo(GRAPHIC_FALLBACK_BANNER) ); else if( pSong->HasBanner() ) Banner::Load( pSong->GetBannerPath() ); - else if( pSong->HasBackground() ) Banner::Load( pSong->GetBackgroundPath() ); +// else if( pSong->HasBackground() ) Banner::Load( pSong->GetBackgroundPath() ); else Banner::Load( THEME->GetPathTo(GRAPHIC_FALLBACK_BANNER) ); return true; diff --git a/stepmania/src/BaseClasses/streams.h b/stepmania/src/BaseClasses/streams.h index d8ac319a00..8baa6fedf6 100644 --- a/stepmania/src/BaseClasses/streams.h +++ b/stepmania/src/BaseClasses/streams.h @@ -124,7 +124,7 @@ typedef struct { // #include "baseclasses/reftime.h" // Helper class for REFERENCE_TIME management #include "baseclasses/wxdebug.h" // Debug support for logging and ASSERTs -#include // ActiveMovie video interfaces and definitions +#include "baseclasses/amvideo.h" // ActiveMovie video interfaces and definitions //include amaudio.h explicitly if you need it. it requires the DX SDK. //#include // ActiveMovie audio interfaces and definitions diff --git a/stepmania/src/Combo.cpp b/stepmania/src/Combo.cpp index 963696631e..9f8f17b7c2 100644 --- a/stepmania/src/Combo.cpp +++ b/stepmania/src/Combo.cpp @@ -11,6 +11,8 @@ #include "Combo.h" #include "ThemeManager.h" +#include "ScreenManager.h" +#include "ScreenGameplay.h" Combo::Combo() @@ -46,6 +48,21 @@ void Combo::ContinueCombo() if( m_iCurCombo > m_iMaxCombo ) m_iMaxCombo = m_iCurCombo; + switch( m_iMaxCombo ) + { + case 100: SCREENMAN->SendMessageToTopScreen( SM_100Combo, 0 ); break; + case 200: SCREENMAN->SendMessageToTopScreen( SM_200Combo, 0 ); break; + case 300: SCREENMAN->SendMessageToTopScreen( SM_300Combo, 0 ); break; + case 400: SCREENMAN->SendMessageToTopScreen( SM_400Combo, 0 ); break; + case 500: SCREENMAN->SendMessageToTopScreen( SM_500Combo, 0 ); break; + case 600: SCREENMAN->SendMessageToTopScreen( SM_600Combo, 0 ); break; + case 700: SCREENMAN->SendMessageToTopScreen( SM_700Combo, 0 ); break; + case 800: SCREENMAN->SendMessageToTopScreen( SM_800Combo, 0 ); break; + case 900: SCREENMAN->SendMessageToTopScreen( SM_900Combo, 0 ); break; + case 1000: SCREENMAN->SendMessageToTopScreen( SM_1000Combo, 0 ); break; + } + + if( m_iCurCombo <= 4 ) { m_textComboNumber.SetDiffuseColor( D3DXCOLOR(1,1,1,0) ); // invisible @@ -57,7 +74,7 @@ void Combo::ContinueCombo() m_sprCombo.SetDiffuseColor( D3DXCOLOR(1,1,1,1) ); // visible m_textComboNumber.SetText( ssprintf("%d", m_iCurCombo) ); - float fNewZoom = 0.5f + m_iCurCombo/800.0f; + float fNewZoom = min( 0.5f + m_iCurCombo/800.0f, 1.1f ); m_textComboNumber.SetZoom( fNewZoom ); //this->SetZoom( 1.2f ); @@ -68,6 +85,9 @@ void Combo::ContinueCombo() void Combo::EndCombo() { + if( m_iCurCombo > 50 ) + SCREENMAN->SendMessageToTopScreen( SM_ComboStopped, 0 ); + m_iCurCombo = 0; m_textComboNumber.SetDiffuseColor( D3DXCOLOR(1,1,1,0) ); // invisible diff --git a/stepmania/src/CourseContentsFrame.cpp b/stepmania/src/CourseContentsFrame.cpp index bcaa77d56d..6e4d6053c3 100644 --- a/stepmania/src/CourseContentsFrame.cpp +++ b/stepmania/src/CourseContentsFrame.cpp @@ -66,10 +66,10 @@ void CourseContentsFrame::SetFromCourse( Course* pCourse ) m_Meters[i].SetFromNotes( NULL ); Song* pSong = pCourse->m_apSongs[i]; - for( int j=0; jm_arrayNotes.GetSize(); j++ ) + for( int j=0; jm_apNotes.GetSize(); j++ ) { - Notes* pNotes = pSong->m_arrayNotes[j]; - if( pSong->m_arrayNotes[j]->m_DifficultyClass == pCourse->m_aDifficultyClasses[i] ) + Notes* pNotes = pSong->m_apNotes[j]; + if( pSong->m_apNotes[j]->m_DifficultyClass == pCourse->m_aDifficultyClasses[i] ) { m_Meters[i].SetFromNotes( pNotes ); break; diff --git a/stepmania/src/CroppedSprite.cpp b/stepmania/src/CroppedSprite.cpp index 16141e201e..c530741f2b 100644 --- a/stepmania/src/CroppedSprite.cpp +++ b/stepmania/src/CroppedSprite.cpp @@ -55,7 +55,7 @@ void CroppedSprite::CropToSize( float fWidth, float fHeight ) float fFinalZoom = this->GetZoom(); // find which dimension is larger - bool bXDimNeedsToBeCropped = GetZoomedWidth() > m_fCropWidth; + bool bXDimNeedsToBeCropped = GetZoomedWidth() > m_fCropWidth+0.01; if( bXDimNeedsToBeCropped ) // crop X { diff --git a/stepmania/src/GameConstantsAndTypes.h b/stepmania/src/GameConstantsAndTypes.h index 5bf6388df3..b07076ed82 100644 --- a/stepmania/src/GameConstantsAndTypes.h +++ b/stepmania/src/GameConstantsAndTypes.h @@ -48,7 +48,7 @@ enum MAX_NOTE_TRACKS // leave this at the end }; -const int MAX_BEATS = 300 * 2; // 300 bpm * 2 mins +const int MAX_BEATS = 1500; // BMR's Pulse has about 1300 const int BEATS_PER_MEASURE = 4; const int MAX_MEASURES = MAX_BEATS / BEATS_PER_MEASURE; @@ -56,7 +56,7 @@ const int ELEMENTS_PER_BEAT = 12; // It is important that this number is evenly const int ELEMENTS_PER_MEASURE = ELEMENTS_PER_BEAT * BEATS_PER_MEASURE; const int MAX_TAP_NOTE_ROWS = MAX_BEATS*ELEMENTS_PER_BEAT; -const int MAX_HOLD_NOTE_ELEMENTS = 200; +const int MAX_HOLD_NOTES = 400; // BMR's Connected has about 300 enum NoteType { diff --git a/stepmania/src/GameManager.cpp b/stepmania/src/GameManager.cpp index 0cd499c58f..95acfbd94f 100644 --- a/stepmania/src/GameManager.cpp +++ b/stepmania/src/GameManager.cpp @@ -11,7 +11,7 @@ */ #include "GameManager.h" - +#include "PrefsManager.h" GameManager* GAMEMAN = NULL; // global and accessable from anywhere in our program @@ -557,8 +557,15 @@ GameManager::GameManager() CStringArray asSkinNames; GetSkinNames( asSkinNames ); - for( int p=0; pm_sNoteSkin; + for( int i=0; iStyleInputToGameInput( si ); InstrumentButton b = gi.button; - return GetCurrentGameDef()->GetPathToGraphic( m_sCurrentSkin[p], b, gbg ); + return GetCurrentGameDef()->GetPathToGraphic( m_sCurrentSkin, b, gbg ); } void GameManager::GetTweenColors( const PlayerNumber p, const int col, CArray &aTweenColorsAddTo ) { StyleInput StyleI( p, col ); GameInput GameI = GetCurrentStyleDef()->StyleInputToGameInput( StyleI ); - GetCurrentGameDef()->GetTweenColors( m_sCurrentSkin[p], GameI.button, aTweenColorsAddTo ); + GetCurrentGameDef()->GetTweenColors( m_sCurrentSkin, GameI.button, aTweenColorsAddTo ); } diff --git a/stepmania/src/GameManager.h b/stepmania/src/GameManager.h index a4ee7db568..0f095972dc 100644 --- a/stepmania/src/GameManager.h +++ b/stepmania/src/GameManager.h @@ -25,7 +25,7 @@ public: Game m_CurGame; Style m_CurStyle; NotesType m_CurNotesType; // only used in Edit - CString m_sCurrentSkin[NUM_PLAYERS]; + CString m_sCurrentSkin; PlayerNumber m_sMasterPlayerNumber; GameDef* GetCurrentGameDef(); diff --git a/stepmania/src/GhostArrow.cpp b/stepmania/src/GhostArrow.cpp index 345acf6e4c..72b2e6de21 100644 --- a/stepmania/src/GhostArrow.cpp +++ b/stepmania/src/GhostArrow.cpp @@ -35,10 +35,10 @@ void GhostArrow::Step( TapNoteScore score ) { switch( score ) { - case TNS_PERFECT: SetDiffuseColor( D3DXCOLOR(1.0f,1.0f,0.3f,0.6f) ); break; // yellow - case TNS_GREAT: SetDiffuseColor( D3DXCOLOR(0.0f,1.0f,0.4f,0.6f) ); break; // green - case TNS_GOOD: SetDiffuseColor( D3DXCOLOR(0.3f,0.8f,1.0f,0.6f) ); break; - case TNS_BOO: SetDiffuseColor( D3DXCOLOR(0.8f,0.0f,0.6f,0.6f) ); break; + case TNS_PERFECT: SetDiffuseColor( D3DXCOLOR(1.0f,1.0f,0.3f,1) ); break; // yellow + case TNS_GREAT: SetDiffuseColor( D3DXCOLOR(0.0f,1.0f,0.4f,1) ); break; // green + case TNS_GOOD: SetDiffuseColor( D3DXCOLOR(0.3f,0.8f,1.0f,1) ); break; + case TNS_BOO: SetDiffuseColor( D3DXCOLOR(0.8f,0.0f,0.6f,1) ); break; case TNS_MISS: ASSERT( false ); break; } SetZoom( 1.0f ); diff --git a/stepmania/src/GhostArrowBright.cpp b/stepmania/src/GhostArrowBright.cpp index a31a3d1aa8..e1c256f01a 100644 --- a/stepmania/src/GhostArrowBright.cpp +++ b/stepmania/src/GhostArrowBright.cpp @@ -31,11 +31,11 @@ void GhostArrowBright::Step( TapNoteScore score ) { switch( score ) { - case TNS_PERFECT: SetDiffuseColor( D3DXCOLOR(1.0f,1.0f,0.3f,1.0f) ); break; // yellow - case TNS_GREAT: SetDiffuseColor( D3DXCOLOR(0.0f,1.0f,0.4f,1.0f) ); break; // green - case TNS_GOOD: SetDiffuseColor( D3DXCOLOR(0.3f,0.8f,1.0f,1.0f) ); break; - case TNS_BOO: SetDiffuseColor( D3DXCOLOR(0.8f,0.0f,0.6f,1.0f) ); break; - case TNS_MISS: ASSERT( false ); break; + case TNS_PERFECT: SetDiffuseColor( D3DXCOLOR(1.0f,1.0f,0.3f,1) ); break; // yellow + case TNS_GREAT: SetDiffuseColor( D3DXCOLOR(0.0f,1.0f,0.4f,1) ); break; // green + case TNS_GOOD: SetDiffuseColor( D3DXCOLOR(0.3f,0.8f,1.0f,1) ); break; + case TNS_BOO: SetDiffuseColor( D3DXCOLOR(0.8f,0.0f,0.6f,1) ); break; + case TNS_MISS: ASSERT( false ); break; } SetState( 0 ); SetZoom( 1.0f ); diff --git a/stepmania/src/GrayArrow.cpp b/stepmania/src/GrayArrow.cpp index c7a79d7c73..ab0b2379cf 100644 --- a/stepmania/src/GrayArrow.cpp +++ b/stepmania/src/GrayArrow.cpp @@ -14,7 +14,7 @@ #include "GrayArrow.h" #include "ThemeManager.h" -const float GRAY_ARROW_POP_UP_TIME = 0.3f; +const float GRAY_ARROW_POP_UP_TIME = 0.15f; GrayArrow::GrayArrow() @@ -32,7 +32,7 @@ void GrayArrow::SetBeat( const float fSongBeat ) void GrayArrow::Step() { - SetZoom( 0.50 ); + SetZoom( 0.75f ); BeginTweening( GRAY_ARROW_POP_UP_TIME ); SetTweenZoom( 1.0f ); } diff --git a/stepmania/src/LifeMeterBar.cpp b/stepmania/src/LifeMeterBar.cpp index 6a3ea50edd..fabb7558b3 100644 --- a/stepmania/src/LifeMeterBar.cpp +++ b/stepmania/src/LifeMeterBar.cpp @@ -45,7 +45,7 @@ void LifeMeterBar::ChangeLife( TapNoteScore score ) case TNS_MISS: fDeltaLife = -0.080f; break; } - if( IsHot() && score < TNS_GREAT ) + if( IsHot() && score < TNS_GOOD ) fDeltaLife = -0.10f; // make it take a while to get back to "doing great" m_fLifePercentage += fDeltaLife; diff --git a/stepmania/src/MenuElements.cpp b/stepmania/src/MenuElements.cpp index 3ef7172290..335769e752 100644 --- a/stepmania/src/MenuElements.cpp +++ b/stepmania/src/MenuElements.cpp @@ -62,7 +62,7 @@ MenuElements::MenuElements() this->AddActor( &m_Invisible ); } -void MenuElements::Load( CString sBackgroundPath, CString sTopEdgePath, CString sHelpText ) +void MenuElements::Load( CString sBackgroundPath, CString sTopEdgePath, CString sHelpText, bool bShowStyleIcon, bool bTimerEnabled, int iTimerSeconds ) { LOG->WriteLine( "MenuElements::MenuElements()" ); @@ -80,13 +80,20 @@ void MenuElements::Load( CString sBackgroundPath, CString sTopEdgePath, CString m_sprStyleIcon.StopAnimating(); m_sprStyleIcon.SetXY( STYLE_ICON_LOCAL_X, STYLE_ICON_LOCAL_Y ); m_sprStyleIcon.SetZ( -1 ); - if( GAMEMAN->m_CurStyle == STYLE_NONE ) + if( GAMEMAN->m_CurStyle == STYLE_NONE || !bShowStyleIcon ) m_sprStyleIcon.SetDiffuseColor( D3DXCOLOR(1,1,1,0) ); else m_sprStyleIcon.SetState( GAMEMAN->m_CurStyle ); m_MenuTimer.SetXY( TIMER_LOCAL_X, TIMER_LOCAL_Y ); m_MenuTimer.SetZ( -1 ); + if( !bTimerEnabled || !PREFSMAN->m_bMenuTimer ) + { + m_MenuTimer.SetTimer( 99 ); + m_MenuTimer.StopTimer(); + } + else + m_MenuTimer.SetTimer( iTimerSeconds ); m_frameBottomBar.SetZ( -1 ); @@ -233,5 +240,10 @@ void MenuElements::DrawBottomLayer() m_sprBG.Draw(); } +void MenuElements::StopTimer() +{ + m_MenuTimer.StopTimer(); +} + diff --git a/stepmania/src/MenuElements.h b/stepmania/src/MenuElements.h index 2a203a567e..a6a2dc2207 100644 --- a/stepmania/src/MenuElements.h +++ b/stepmania/src/MenuElements.h @@ -33,7 +33,10 @@ public: virtual void DrawPrimitives(); - void Load( CString sBackgroundPath, CString sTopEdgePath, CString sHelpText ); + void Load( CString sBackgroundPath, CString sTopEdgePath, CString sHelpText, bool bShowStyleIcon, bool bTimerEnabled, int iTimerSeconds ); + void StallTimer(); + void SetTimer( int iTimerSeconds ); + void StopTimer(); void DrawTopLayer(); void DrawBottomLayer(); diff --git a/stepmania/src/MenuTimer.cpp b/stepmania/src/MenuTimer.cpp index de7147fac1..61acb6aa14 100644 --- a/stepmania/src/MenuTimer.cpp +++ b/stepmania/src/MenuTimer.cpp @@ -15,12 +15,15 @@ #include "GameConstantsAndTypes.h" #include "ThemeManager.h" #include "ScreenManager.h" +#include "AnnouncerManager.h" const float TIMER_SECONDS = 99; MenuTimer::MenuTimer() { m_fSecondsLeft = TIMER_SECONDS; + m_fStallSeconds = 0; + m_bTimerStopped = false; m_textDigit1.Load( THEME->GetPathTo(FONT_TIMER_NUMBERS) ); m_textDigit1.TurnShadowOff(); @@ -40,10 +43,21 @@ void MenuTimer::Update( float fDeltaTime ) { ActorFrame::Update( fDeltaTime ); + if( m_bTimerStopped ) + return; + + if( m_fStallSeconds > 0 ) + { + m_fStallSeconds -= fDeltaTime; + return; + } + float fOldSecondsLeft = m_fSecondsLeft; float fNewSecondsLeft = fOldSecondsLeft - fDeltaTime; - if( fOldSecondsLeft > 5 && fNewSecondsLeft < 5 ) // transition to below 5 + if( fOldSecondsLeft > 5.5 && fNewSecondsLeft < 5.5 ) // transition to below 5.5 + SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_MENU_HURRY_UP) ); + else if( fOldSecondsLeft > 5 && fNewSecondsLeft < 5 ) // transition to below 5 { m_textDigit1.SetEffectGlowing( 10, D3DXCOLOR(1,0,0,0), D3DXCOLOR(1,0,0,1) ); m_textDigit2.SetEffectGlowing( 10, D3DXCOLOR(1,0,0,0), D3DXCOLOR(1,0,0,1) ); @@ -80,10 +94,15 @@ void MenuTimer::Update( float fDeltaTime ) void MenuTimer::StopTimer() { - + m_bTimerStopped = true; } void MenuTimer::StallTimer() { - + m_fStallSeconds = 1; +} + +void MenuTimer::SetTimer( int iSeconds ) +{ + m_fSecondsLeft = (float)iSeconds; } diff --git a/stepmania/src/MenuTimer.h b/stepmania/src/MenuTimer.h index 02b8677f53..0ddac389f6 100644 --- a/stepmania/src/MenuTimer.h +++ b/stepmania/src/MenuTimer.h @@ -25,9 +25,13 @@ public: virtual void Update( float fDeltaTime ); void StopTimer(); void StallTimer(); + void SetTimer( int iTimerSeconds ); protected: float m_fSecondsLeft; + float m_fStallSeconds; + + bool m_bTimerStopped; BitmapText m_textDigit1; BitmapText m_textDigit2; diff --git a/stepmania/src/MusicWheel.cpp b/stepmania/src/MusicWheel.cpp index 33a6212351..f0738169ca 100644 --- a/stepmania/src/MusicWheel.cpp +++ b/stepmania/src/MusicWheel.cpp @@ -23,7 +23,7 @@ const float FADE_TIME = 1.0f; -const float SWITCH_MUSIC_TIME = 0.15f; +const float SWITCH_MUSIC_TIME = 0.10f; const float SAMPLE_MUSIC_DELAY = 0.20f; const float ROULETTE_SWITCH_MUSIC_TIME = SWITCH_MUSIC_TIME/2; const int ROULETTE_SWITCHES_IN_SLOWING_DOWN = 5; @@ -924,6 +924,8 @@ void MusicWheel::PrevMusic( bool bSendSongChangedMessage ) if( fabsf(m_fPositionOffsetFromSelection) > 0.5f ) // wheel is busy spinning return; + m_fTimeLeftBeforePlayMusicSample = 0; + switch( m_WheelState ) { case STATE_SELECTING_MUSIC: @@ -966,9 +968,11 @@ void MusicWheel::NextMusic( bool bSendSongChangedMessage ) return; } - if( fabsf(m_fPositionOffsetFromSelection) > 0.5 ) // wheel is very busy spinning + if( fabsf(m_fPositionOffsetFromSelection) > 0.5f ) // wheel is very busy spinning return; + m_fTimeLeftBeforePlayMusicSample = 0; + switch( m_WheelState ) { case STATE_SELECTING_MUSIC: @@ -1038,7 +1042,7 @@ bool MusicWheel::Select() // return true of a playable item was chosen if( m_WheelState == STATE_ROULETTE_SPINNING ) { m_WheelState = STATE_ROULETTE_SLOWING_DOWN; - m_iSwitchesLeftInSpinDown = ROULETTE_SWITCHES_IN_SLOWING_DOWN; + m_iSwitchesLeftInSpinDown = ROULETTE_SWITCHES_IN_SLOWING_DOWN/2+1 + rand()%(ROULETTE_SWITCHES_IN_SLOWING_DOWN/2); m_fTimeLeftInState = 0.1f; return false; } diff --git a/stepmania/src/NoteData.cpp b/stepmania/src/NoteData.cpp index 195570ca92..05a08d54f3 100644 --- a/stepmania/src/NoteData.cpp +++ b/stepmania/src/NoteData.cpp @@ -134,13 +134,16 @@ CString NoteData::GetSMNoteDataString() CStringArray asMeasureLines; asMeasureLines.Add( ssprintf(" // measure %d", m+1) ); + for( int i=iMeasureStartIndex; i<=iMeasureLastIndex; i+=iNoteIndexSpacing ) { - CString sLineString; - for( int c=0; c=iOldestIndexFoundSoFar; i-- ) // iterate back to front + { + if( !IsRowEmpty(i) ) + { + iOldestIndexFoundSoFar = i; + break; + } + } + for( i=0; i iOldestIndexFoundSoFar ) iOldestIndexFoundSoFar = m_HoldNotes[i].m_iEndIndex; } - for( i=MAX_TAP_NOTE_ROWS-1; i>=iOldestIndexFoundSoFar; i-- ) // iterate back to front - { - for( int t=0; t &aFreezeSegments = SONGMAN->GetCurrentSong()->m_FreezeSegments; - for( i=0; i &aStopSegments = SONGMAN->GetCurrentSong()->m_StopSegments; + for( i=0; i 0, then it was completed and don't draw it! - if( hn.m_iEndIndex < BeatToNoteRow(m_fSongBeat) && m_HoldNoteLife[i] > 0 ) + if( hn.m_iEndIndex < BeatToNoteRow(m_fSongBeat) && fLife > 0 ) continue; // skip @@ -298,6 +299,9 @@ void NoteField::DrawPrimitives() if( j < iIndexFirstArrowToDraw || iIndexLastArrowToDraw < j) continue; // skip this arrow + if( fLife > 0 && NoteRowToBeat(j) < m_fSongBeat ) + continue; + CreateHoldNoteInstance( instances[iCount++], bActive, (float)j, hn, fHoldNoteLife ); } diff --git a/stepmania/src/NoteField.h b/stepmania/src/NoteField.h index 987a5822f7..3703426aa8 100644 --- a/stepmania/src/NoteField.h +++ b/stepmania/src/NoteField.h @@ -41,7 +41,7 @@ public: void RemoveTapNoteRow( int iIndex ); void SetHoldNoteLife( int iIndex, float fLife ); - float m_HoldNoteLife[MAX_HOLD_NOTE_ELEMENTS]; // 1.0 = full life, 0 = dead + float m_HoldNoteLife[MAX_HOLD_NOTES]; // 1.0 = full life, 0 = dead float m_fBeginMarker, m_fEndMarker; // only used with MODE_EDIT diff --git a/stepmania/src/Notes.cpp b/stepmania/src/Notes.cpp index 7c38ecc2d6..ab53239d6d 100644 --- a/stepmania/src/Notes.cpp +++ b/stepmania/src/Notes.cpp @@ -114,8 +114,8 @@ bool Notes::LoadFromBMSFile( const CString &sPath ) { LOG->WriteLine( "Notes::LoadFromBMSFile( '%s' )", sPath ); - NoteData tempNoteData; - tempNoteData.m_iNumTracks = MAX_NOTE_TRACKS; + NoteData* pNoteData = new NoteData; + pNoteData->m_iNumTracks = MAX_NOTE_TRACKS; CStdioFile file; if( !file.Open( sPath, CFile::modeRead|CFile::shareDenyNone ) ) @@ -228,7 +228,7 @@ bool Notes::LoadFromBMSFile( const CString &sPath ) mapBMSTrackToDanceNote( iTrackNum, iColumnNumber, cNoteChar ); if( iColumnNumber != -1 ) - tempNoteData.m_TapNotes[iColumnNumber][iNoteIndex] = cNoteChar; + pNoteData->m_TapNotes[iColumnNumber][iNoteIndex] = cNoteChar; } } } @@ -241,14 +241,14 @@ bool Notes::LoadFromBMSFile( const CString &sPath ) for( int i=0; im_TapNotes[DANCE_NOTE_PAD1_UP], + pNoteData->m_TapNotes[DANCE_NOTE_PAD1_UPRIGHT], + MAX_TAP_NOTE_ROWS*sizeof(pNoteData->m_TapNotes[0][0]) ); memcpy( - tempNoteData.m_TapNotes[DANCE_NOTE_PAD2_UP], - tempNoteData.m_TapNotes[DANCE_NOTE_PAD2_UPRIGHT], - MAX_TAP_NOTE_ROWS*sizeof(tempNoteData.m_TapNotes[0][0]) + pNoteData->m_TapNotes[DANCE_NOTE_PAD2_UP], + pNoteData->m_TapNotes[DANCE_NOTE_PAD2_UPRIGHT], + MAX_TAP_NOTE_ROWS*sizeof(pNoteData->m_TapNotes[0][0]) ); } } @@ -288,11 +288,14 @@ bool Notes::LoadFromBMSFile( const CString &sPath ) throw RageException( "Invalid NotesType." ); } - NoteData tempNoteData2; - tempNoteData2.m_iNumTracks = iNumNewTracks; - tempNoteData2.LoadTransformed( &tempNoteData, iNumNewTracks, iTransformNewToOld ); + NoteData* pNoteData2 = new NoteData; + pNoteData2->m_iNumTracks = iNumNewTracks; + pNoteData2->LoadTransformed( pNoteData, iNumNewTracks, iTransformNewToOld ); - m_sSMNoteData = tempNoteData2.GetSMNoteDataString(); + m_sSMNoteData = pNoteData2->GetSMNoteDataString(); + + delete pNoteData; + delete pNoteData2; TidyUpData(); @@ -370,15 +373,16 @@ bool Notes::LoadFromDWITokens( CMap mapDanceNoteToNoteDataColumn; - if( m_NotesType == NOTES_TYPE_DANCE_SINGLE ) + switch( m_NotesType ) { + case NOTES_TYPE_DANCE_SINGLE: mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3; - } - else if( m_NotesType == NOTES_TYPE_DANCE_DOUBLE || m_NotesType == NOTES_TYPE_DANCE_COUPLE ) - { + break; + case NOTES_TYPE_DANCE_DOUBLE: + case NOTES_TYPE_DANCE_COUPLE: mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2; @@ -387,18 +391,18 @@ bool Notes::LoadFromDWITokens( mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_DOWN] = 5; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_UP] = 6; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_RIGHT] = 7; - } - else if( m_NotesType == NOTES_TYPE_DANCE_SOLO ) - { + break; + case NOTES_TYPE_DANCE_SOLO: mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPLEFT] = 1; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 2; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 3; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPRIGHT] = 4; mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 5; - } - else + break; + default: ASSERT(0); + } m_sDescription = sDescription; @@ -406,8 +410,10 @@ bool Notes::LoadFromDWITokens( //m_DifficultyClass = DifficultyClassFromDescriptionAndMeter( m_sDescription, m_iMeter ); - NoteData tempNoteData; - tempNoteData.m_iNumTracks = mapDanceNoteToNoteDataColumn.GetCount(); + NoteData* pNoteData = new NoteData; + ASSERT( pNoteData ); + printf( "sizeof NoteData = %d\n", sizeof(NoteData) ); + pNoteData->m_iNumTracks = mapDanceNoteToNoteDataColumn.GetCount(); for( int pad=0; pad<2; pad++ ) // foreach pad { @@ -428,6 +434,7 @@ bool Notes::LoadFromDWITokens( double fCurrentBeat = 0; double fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE; + for( int i=0; im_TapNotes[iCol1][iIndex] = '2'; } if( note2 != DANCE_NOTE_NONE ) { int iCol2 = mapDanceNoteToNoteDataColumn[note2]; - tempNoteData.m_TapNotes[iCol2][iIndex] = '2'; + pNoteData->m_TapNotes[iCol2][iIndex] = '2'; } } break; default: // this is a note character { - int iIndex = BeatToNoteRow( (float)fCurrentBeat ); + int iIndex = BeatToNoteRow( (float)fCurrentBeat ); - DanceNote note1, note2; - DWIcharToNote( c, (InstrumentNumber)pad, note1, note2 ); + DanceNote note1, note2; + DWIcharToNote( c, (InstrumentNumber)pad, note1, note2 ); - if( note1 != DANCE_NOTE_NONE ) - { - int iCol1 = mapDanceNoteToNoteDataColumn[note1]; - tempNoteData.m_TapNotes[iCol1][iIndex] = '1'; - } - if( note2 != DANCE_NOTE_NONE ) - { - int iCol2 = mapDanceNoteToNoteDataColumn[note2]; - tempNoteData.m_TapNotes[iCol2][iIndex] = '1'; - } + if( note1 != DANCE_NOTE_NONE ) + { + int iCol1 = mapDanceNoteToNoteDataColumn[note1]; + pNoteData->m_TapNotes[iCol1][iIndex] = '1'; + } + if( note2 != DANCE_NOTE_NONE ) + { + int iCol2 = mapDanceNoteToNoteDataColumn[note2]; + pNoteData->m_TapNotes[iCol2][iIndex] = '1'; + } - fCurrentBeat += fCurrentIncrementer; + fCurrentBeat += fCurrentIncrementer; } break; } } } - tempNoteData.Convert2sAnd3sToHoldNotes(); // this will expand the HoldNote begin markers we wrote into actual HoldNotes + pNoteData->Convert2sAnd3sToHoldNotes(); // this will expand the HoldNote begin markers we wrote into actual HoldNotes - ASSERT( tempNoteData.m_iNumTracks > 0 ); + ASSERT( pNoteData->m_iNumTracks > 0 ); - m_sSMNoteData = tempNoteData.GetSMNoteDataString(); + m_sSMNoteData = pNoteData->GetSMNoteDataString(); + + delete pNoteData; TidyUpData(); @@ -628,6 +637,28 @@ DifficultyClass Notes::DifficultyClassFromDescriptionAndMeter( CString sDescript // ////////////////////////////////////////////// +int CompareNotesPointersByRadarValues(const void *arg1, const void *arg2) +{ + Notes* pNotes1 = *(Notes**)arg1; + Notes* pNotes2 = *(Notes**)arg2; + + float fScore1 = 0; + float fScore2 = 0; + + for( int r=0; rm_fRadarValues[r]; + fScore2 += pNotes2->m_fRadarValues[r]; + } + + if( fScore1 < fScore2 ) + return -1; + else if( fScore1 == fScore2 ) + return 0; + else + return 1; +} + int CompareNotesPointersByMeter(const void *arg1, const void *arg2) { Notes* pNotes1 = *(Notes**)arg1; @@ -639,7 +670,7 @@ int CompareNotesPointersByMeter(const void *arg1, const void *arg2) if( iScore1 < iScore2 ) return -1; else if( iScore1 == iScore2 ) - return 0; + return CompareNotesPointersByRadarValues( arg1, arg2 ); else return 1; } diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index 180de53a0f..4007b1d68c 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -249,8 +249,6 @@ void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff ) ASSERT( col >= 0 && col <= m_iNumTracks ); - m_GrayArrowRow.Step( col ); - // look for the closest matching step int iIndexStartLookingAt = BeatToNoteRow( fSongBeat ); @@ -294,6 +292,8 @@ void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff ) } } + bool bDestroyedNote = false; + if( iIndexOverlappingNote != -1 ) { // compute the score for this hit @@ -303,11 +303,13 @@ void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff ) TapNoteScore &score = m_TapNoteScores[col][iIndexOverlappingNote]; - if( fPercentFromPerfect < 0.30f ) score = TNS_PERFECT; - else if( fPercentFromPerfect < 0.55f ) score = TNS_GREAT; - else if( fPercentFromPerfect < 0.78f ) score = TNS_GOOD; + if( fPercentFromPerfect < 0.25f ) score = TNS_PERFECT; + else if( fPercentFromPerfect < 0.50f ) score = TNS_GREAT; + else if( fPercentFromPerfect < 0.75f ) score = TNS_GOOD; else score = TNS_BOO; + bDestroyedNote = score >= TNS_GOOD; + bool bRowDestroyed = true; for( int t=0; t dwMaxSize || ddii.Height > dwMaxSize; /* - // HACK: The stupid Savage driver will report that it can hold the entire texture, - // then allocate something smaller than the dimensions we need! - // after allocating the texture, make sure it's the size we expect. If not, - // load it again with scaling turned on. + // HACK: On a Voodoo3 and Win98, D3DXCreateTextureFromFileEx sometimes fails for no good reason. + // So, we'll try the call 2x in a row in case the first one fails */ // I'm taking out the Savage hack because it's causing problems. Tough luck for them. I think // the problem can be worked around by setting MaxTextureSize to 512. - if( FAILED( hr = D3DXCreateTextureFromFileEx( - m_pd3dDevice, // device - m_sFilePath, // soure file - bStretch ? dwMaxSize : D3DX_DEFAULT, // width - bStretch ? dwMaxSize : D3DX_DEFAULT, // height - iMipMaps, // mip map levels - 0, // usage (is a render target?) - fmtTexture, // our preferred texture format - D3DPOOL_MANAGED, // which memory pool - (bStretch ? D3DX_FILTER_BOX : D3DX_FILTER_NONE) | (bDither ? D3DX_FILTER_DITHER : 0), // filter - D3DX_FILTER_BOX | (bDither ? D3DX_FILTER_DITHER : 0), // mip filter - 0, // no color key - &ddii, // struct to fill with source image info - NULL, // no palette - &m_pd3dTexture ) ) ) + for( int i=0; i<2; i++ ) { - throw RageException( hr, "D3DXCreateTextureFromFileEx() failed for file '%s'.", m_sFilePath ); + if( FAILED( hr = D3DXCreateTextureFromFileEx( + m_pd3dDevice, // device + m_sFilePath, // soure file + bStretch ? dwMaxSize : D3DX_DEFAULT, // width + bStretch ? dwMaxSize : D3DX_DEFAULT, // height + iMipMaps, // mip map levels + 0, // usage (is a render target?) + fmtTexture, // our preferred texture format + D3DPOOL_MANAGED, // which memory pool + (bStretch ? D3DX_FILTER_BOX : D3DX_FILTER_NONE) | (bDither ? D3DX_FILTER_DITHER : 0), // filter + D3DX_FILTER_BOX | (bDither ? D3DX_FILTER_DITHER : 0), // mip filter + 0, // no color key + &ddii, // struct to fill with source image info + NULL, // no palette + &m_pd3dTexture ) ) ) + { + if( i==0 ) + { + LOG->WriteLine( "WARNING! D3DXCreateTextureFromFileEx failed. Sleep and try one more time..." ); + ::Sleep( 10 ); + continue; + } + throw RageException( hr, "D3DXCreateTextureFromFileEx() failed for file '%s'.", m_sFilePath ); + } + else + break; } ///////////////////// diff --git a/stepmania/src/RageDisplay.cpp b/stepmania/src/RageDisplay.cpp index b8843d8776..ee0cb4915f 100644 --- a/stepmania/src/RageDisplay.cpp +++ b/stepmania/src/RageDisplay.cpp @@ -242,7 +242,7 @@ bool RageDisplay::SwitchDisplayMode( // device is not yet created. We need to create it if( FAILED( hr = m_pd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, - D3DCREATE_SOFTWARE_VERTEXPROCESSING, + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &m_d3dpp, &m_pd3dDevice) ) ) { LOG->WriteLineHr( hr, "failed to create device: %d, %u, %u, %u.", bWindowed, dwWidth, dwHeight, dwBPP ); diff --git a/stepmania/src/RageMovieTexture.cpp b/stepmania/src/RageMovieTexture.cpp index e9fb22cb00..3ede8f5bf9 100644 --- a/stepmania/src/RageMovieTexture.cpp +++ b/stepmania/src/RageMovieTexture.cpp @@ -426,13 +426,13 @@ HRESULT RageMovieTexture::CreateD3DTexture() // Create the texture that maps to this media type ////////////////////////////////////////////////// if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice, - m_iSourceHeight, m_iSourceHeight, + m_iSourceWidth, m_iSourceHeight, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pd3dTexture[0] ) ) ) throw RageException( hr, "Could not create the D3DX texture!" ); if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice, - m_iSourceHeight, m_iSourceHeight, + m_iSourceWidth, m_iSourceHeight, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pd3dTexture[1] ) ) ) throw RageException( hr, "Could not create the D3DX texture!" ); @@ -491,3 +491,20 @@ void RageMovieTexture::CleanupDShow() if (m_pGB) m_pGB.Release (); } +void RageMovieTexture::Play() +{ + PlayMovie(); +} + +void RageMovieTexture::SetPosition( float fSeconds ) +{ + m_pMP->put_CurrentPosition(0); +} + +void RageMovieTexture::Pause() +{ + HRESULT hr; + if( FAILED( hr = m_pMC->Pause() ) ) + throw RageException( hr, "Could not pause the DirectShow graph." ); + +} diff --git a/stepmania/src/RageMovieTexture.h b/stepmania/src/RageMovieTexture.h index f8391f9b76..58d66bc45b 100644 --- a/stepmania/src/RageMovieTexture.h +++ b/stepmania/src/RageMovieTexture.h @@ -96,6 +96,9 @@ public: ); LPDIRECT3DTEXTURE8 GetD3DTexture(); + virtual void Play(); + virtual void SetPosition( float fSeconds ); + virtual void Pause(); LPDIRECT3DTEXTURE8 m_pd3dTexture[2]; // double buffered int m_iIndexActiveTexture; // either 0 or 1 diff --git a/stepmania/src/RageSound.cpp b/stepmania/src/RageSound.cpp index b3c78e8a95..1822939868 100644 --- a/stepmania/src/RageSound.cpp +++ b/stepmania/src/RageSound.cpp @@ -41,7 +41,7 @@ RageSound::RageSound( HWND hWnd ) "The most likely cause of this problem is that you do not have a sound card\n" "installed, or that you have not yet installed a driver for your sound card.\n" "Before running this program again, please verify that your sound card is\n" - "is working in other Screens applications." + "is working in other applications." ); } @@ -93,6 +93,9 @@ void RageSound::PlayOnceStreamed( CString sPath ) void RageSound::PlayOnceStreamedFromDir( CString sDir ) { + if( sDir == "" ) + return; + // make sure there's a backslash at the end of this path if( sDir[sDir.GetLength()-1] != '\\' ) sDir += "\\"; diff --git a/stepmania/src/RageTexture.h b/stepmania/src/RageTexture.h index 811f720b4e..23ab42e16b 100644 --- a/stepmania/src/RageTexture.h +++ b/stepmania/src/RageTexture.h @@ -60,6 +60,9 @@ public: ) = 0; virtual LPDIRECT3DTEXTURE8 GetD3DTexture() = 0; + virtual void Play() {}; + virtual void SetPosition( float fSeconds ) {}; + virtual void Pause() {}; int GetSourceWidth() {return m_iSourceWidth;}; int GetSourceHeight() {return m_iSourceHeight;}; diff --git a/stepmania/src/RageTextureManager.h b/stepmania/src/RageTextureManager.h index cc76cabdb4..7f8df0003f 100644 --- a/stepmania/src/RageTextureManager.h +++ b/stepmania/src/RageTextureManager.h @@ -28,6 +28,8 @@ public: void SetPrefs( const DWORD dwMaxSize, const DWORD dwTextureColorDepth ) { + if( dwMaxSize == m_iMaxTextureSize && dwTextureColorDepth == m_iTextureColorDepth ) + return; ASSERT( m_iMaxTextureSize >= 64 ); m_iMaxTextureSize = dwMaxSize; m_iTextureColorDepth = dwTextureColorDepth; diff --git a/stepmania/src/RageUtil.cpp b/stepmania/src/RageUtil.cpp index 5286cbbf96..e202783d43 100644 --- a/stepmania/src/RageUtil.cpp +++ b/stepmania/src/RageUtil.cpp @@ -347,16 +347,23 @@ DWORD GetFileSizeInBytes( const CString &sFilePath ) bool DoesFileExist( const CString &sPath ) { - //LOG->WriteLine( "DoesFileExist(%s)", sPath ); - DWORD dwAttr = GetFileAttributes( sPath ); - if( dwAttr == (DWORD)-1 ) - return FALSE; - else - return TRUE; - + return bool(dwAttr != (DWORD)-1); } +bool IsAFile( const CString &sPath ) +{ + return DoesFileExist(sPath) && ! IsADirectory(sPath); +} + +bool IsADirectory( const CString &sPath ) +{ + DWORD dwAttr = GetFileAttributes( sPath ); + return (dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + + + int CompareCStringsAsc(const void *arg1, const void *arg2) { CString str1 = *(CString *)arg1; diff --git a/stepmania/src/RageUtil.h b/stepmania/src/RageUtil.h index 2dc342ed97..8eaa1737ad 100644 --- a/stepmania/src/RageUtil.h +++ b/stepmania/src/RageUtil.h @@ -102,6 +102,8 @@ int GetHashForFile( CString sPath ); int GetHashForDirectory( CString sDir ); // a hash value that remains the same as long as nothing in the directory has changed bool DoesFileExist( const CString &sPath ); +bool IsAFile( const CString &sPath ); +bool IsADirectory( const CString &sPath ); DWORD GetFileSizeInBytes( const CString &sFilePath ); int CompareCStringsAsc(const void *arg1, const void *arg2); diff --git a/stepmania/src/ScreenAppearanceOptions.cpp b/stepmania/src/ScreenAppearanceOptions.cpp new file mode 100644 index 0000000000..eff4698aee --- /dev/null +++ b/stepmania/src/ScreenAppearanceOptions.cpp @@ -0,0 +1,138 @@ +#include "stdafx.h" +/* +----------------------------------------------------------------------------- + Class: ScreenAppearanceOptions + + Desc: See header. + + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Chris Danford +----------------------------------------------------------------------------- +*/ + +#include "ScreenAppearanceOptions.h" +#include +#include "RageTextureManager.h" +#include "RageUtil.h" +#include "RageMusic.h" +#include "ScreenManager.h" +#include "PrefsManager.h" +#include "ScreenOptions.h" +#include "ScreenTitleMenu.h" +#include "GameConstantsAndTypes.h" +#include "StepMania.h" +#include "ThemeManager.h" +#include "RageLog.h" +#include "AnnouncerManager.h" +#include "GameManager.h" + + + +enum { + AO_ANNOUNCER = 0, + AO_SKIN, + NUM_APPEARANCE_OPTIONS_LINES +}; + +OptionLineData g_AppearanceOptionsLines[NUM_APPEARANCE_OPTIONS_LINES] = { + { "Announcer", 1, {"OFF"} }, // fill this in on ImportOptions() + { "Note Skin", 0, {""} }, // fill this in on ImportOptions() +}; + +ScreenAppearanceOptions::ScreenAppearanceOptions() : + ScreenOptions( + THEME->GetPathTo(GRAPHIC_PLAYER_OPTIONS_BACKGROUND), + THEME->GetPathTo(GRAPHIC_PLAYER_OPTIONS_TOP_EDGE) + ) +{ + LOG->WriteLine( "ScreenAppearanceOptions::ScreenAppearanceOptions()" ); + + Init( + INPUTMODE_BOTH, + g_AppearanceOptionsLines, + NUM_APPEARANCE_OPTIONS_LINES + ); + m_Menu.StopTimer(); +} + +void ScreenAppearanceOptions::ImportOptions() +{ + // fill in announcer names + CStringArray arrayAnnouncerNames; + ANNOUNCER->GetAnnouncerNames( arrayAnnouncerNames ); + + m_OptionLineData[AO_ANNOUNCER].iNumOptions = arrayAnnouncerNames.GetSize() + 1; + + for( int i=0; iGetCurrentAnnouncerName())==0 ) + { + m_iSelectedOption[0][AO_ANNOUNCER] = i; + break; + } + } + if( m_iSelectedOption[0][AO_ANNOUNCER] == -1 ) + m_iSelectedOption[0][AO_ANNOUNCER] = 0; + + + // fill in skin names + CStringArray arraySkinNames; + GAMEMAN->GetSkinNames( arraySkinNames ); + + m_OptionLineData[AO_SKIN].iNumOptions = arraySkinNames.GetSize(); + + for( i=0; im_sCurrentSkin)==0 ) + { + m_iSelectedOption[0][AO_SKIN] = i; + break; + } + } + if( m_iSelectedOption[0][AO_SKIN] == -1 ) + m_iSelectedOption[0][AO_SKIN] = 0; +} + +void ScreenAppearanceOptions::ExportOptions() +{ + int iSelectedAnnouncer = m_iSelectedOption[0][AO_ANNOUNCER]; + CString sNewAnnouncer = m_OptionLineData[AO_ANNOUNCER].szOptionsText[iSelectedAnnouncer]; + if( iSelectedAnnouncer == 0 ) + sNewAnnouncer = ""; + PREFSMAN->m_sAnnouncer = sNewAnnouncer; + ANNOUNCER->SwitchAnnouncer( sNewAnnouncer ); + + int iSelectedSkin = m_iSelectedOption[0][AO_SKIN]; + CString sNewSkin = m_OptionLineData[AO_SKIN].szOptionsText[iSelectedSkin]; + PREFSMAN->m_sNoteSkin = sNewSkin; + GAMEMAN->m_sCurrentSkin = sNewSkin; +} + +void ScreenAppearanceOptions::GoToPrevState() +{ + SCREENMAN->SetNewScreen( new ScreenTitleMenu ); + PREFSMAN->SavePrefsToDisk(); + +} + +void ScreenAppearanceOptions::GoToNextState() +{ + SCREENMAN->SetNewScreen( new ScreenTitleMenu ); + PREFSMAN->SavePrefsToDisk(); +} + + + + + diff --git a/stepmania/src/ScreenAppearanceOptions.h b/stepmania/src/ScreenAppearanceOptions.h new file mode 100644 index 0000000000..53680756ee --- /dev/null +++ b/stepmania/src/ScreenAppearanceOptions.h @@ -0,0 +1,32 @@ +/* +----------------------------------------------------------------------------- + Class: ScreenAppearanceOptions + + Desc: Select a theme and announcer. + + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Chris Danford +----------------------------------------------------------------------------- +*/ + +#include "Screen.h" +#include "ScreenOptions.h" +#include "Sprite.h" +#include "BitmapText.h" +#include "RandomSample.h" +#include "TransitionFade.h" +#include "Quad.h" + + +class ScreenAppearanceOptions : public ScreenOptions +{ +public: + ScreenAppearanceOptions(); + +private: + void ImportOptions(); + void ExportOptions(); + + void GoToNextState(); + void GoToPrevState(); +}; diff --git a/stepmania/src/ScreenCaution.cpp b/stepmania/src/ScreenCaution.cpp index 7cdefd966f..1ddaacc397 100644 --- a/stepmania/src/ScreenCaution.cpp +++ b/stepmania/src/ScreenCaution.cpp @@ -54,8 +54,7 @@ void ScreenCaution::HandleScreenMessage( const ScreenMessage SM ) m_Wipe.CloseWipingRight( SM_GoToSelectMusic ); break; case SM_DoneOpening: - if( PREFSMAN->m_bAnnouncer ) - SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_CAUTION) ); + SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_CAUTION) ); break; case SM_GoToSelectMusic: SCREENMAN->SetNewScreen( new ScreenSelectStyle ); diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index 52b196fd5d..3026725d5b 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -93,7 +93,7 @@ ScreenEdit::ScreenEdit() if( m_pNotes == NULL ) { m_pNotes = new Notes; - m_pSong->m_arrayNotes.Add( m_pNotes ); + m_pSong->m_apNotes.Add( m_pNotes ); } NoteData noteData; @@ -165,7 +165,7 @@ ScreenEdit::ScreenEdit() m_soundInvalid.Load( THEME->GetPathTo(SOUND_MENU_INVALID) ); - m_soundMusic.Load( m_pSong->GetMusicPath() ); + m_soundMusic.Load( m_pSong->GetMusicPath(), true ); // enable accurate sync m_soundMusic.SetPlaybackRate( 0.5f ); @@ -402,20 +402,19 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ } break; case DIK_ESCAPE: - m_pSong->LoadFromSMFile( m_pSong->GetCacheFilePath() ); SCREENMAN->SetNewScreen( new ScreenEditMenu ); break; case DIK_S: { // copy edit into current Notes - Notes* pNotes; - pNotes = SONGMAN->GetCurrentNotes(PLAYER_1); + Song* pSong = SONGMAN->GetCurrentSong(); + Notes* pNotes = SONGMAN->GetCurrentNotes(PLAYER_1); if( pNotes == NULL ) { // allocate a new Notes - SONGMAN->GetCurrentSong()->m_arrayNotes.SetSize( SONGMAN->GetCurrentSong()->m_arrayNotes.GetSize() + 1 ); - pNotes = SONGMAN->GetCurrentSong()->m_arrayNotes[ SONGMAN->GetCurrentSong()->m_arrayNotes.GetSize()-1 ]; + pNotes = new Notes; + pSong->m_apNotes.Add( pNotes ); pNotes->m_NotesType = GAMEMAN->m_CurNotesType; pNotes->m_sDescription = "Untitled"; pNotes->m_iMeter = 1; @@ -664,12 +663,15 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ float fDeltaBPM; switch( DeviceI.button ) { - case DIK_F7: fDeltaBPM = - 0.025f; break; - case DIK_F8: fDeltaBPM = + 0.025f; break; + case DIK_F7: fDeltaBPM = - 0.020f; break; + case DIK_F8: fDeltaBPM = + 0.020f; break; default: ASSERT(0); } - if( type == IET_FAST_REPEAT ) - fDeltaBPM *= 40; + switch( type ) + { + case IET_SLOW_REPEAT: fDeltaBPM *= 10; break; + case IET_FAST_REPEAT: fDeltaBPM *= 40; break; + } float fNewBPM = fBPM + fDeltaBPM; for( int i=0; im_BPMSegments.GetSize(); i++ ) @@ -696,30 +698,33 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ float fFreezeDelta; switch( DeviceI.button ) { - case DIK_F9: fFreezeDelta = -0.025f; break; - case DIK_F10: fFreezeDelta = +0.025f; break; + case DIK_F9: fFreezeDelta = -0.020f; break; + case DIK_F10: fFreezeDelta = +0.020f; break; default: ASSERT(0); } - if( type == IET_FAST_REPEAT ) - fFreezeDelta *= 40; - - for( int i=0; im_FreezeSegments.GetSize(); i++ ) + switch( type ) { - if( m_pSong->m_FreezeSegments[i].m_fStartBeat == m_fBeat ) + case IET_SLOW_REPEAT: fFreezeDelta *= 10; break; + case IET_FAST_REPEAT: fFreezeDelta *= 40; break; + } + + for( int i=0; im_StopSegments.GetSize(); i++ ) + { + if( m_pSong->m_StopSegments[i].m_fStartBeat == m_fBeat ) break; } - if( i == m_pSong->m_FreezeSegments.GetSize() ) // there is no BPMSegment at the current beat + if( i == m_pSong->m_StopSegments.GetSize() ) // there is no BPMSegment at the current beat { - // create a new FreezeSegment + // create a new StopSegment if( fFreezeDelta > 0 ) - m_pSong->AddFreezeSegment( FreezeSegment(m_fBeat, fFreezeDelta) ); + m_pSong->AddStopSegment( StopSegment(m_fBeat, fFreezeDelta) ); } - else // FreezeSegment being modified is m_FreezeSegments[i] + else // StopSegment being modified is m_StopSegments[i] { - m_pSong->m_FreezeSegments[i].m_fFreezeSeconds += fFreezeDelta; - if( m_pSong->m_FreezeSegments[i].m_fFreezeSeconds <= 0 ) - m_pSong->m_FreezeSegments.RemoveAt( i ); + m_pSong->m_StopSegments[i].m_fStopSeconds += fFreezeDelta; + if( m_pSong->m_StopSegments[i].m_fStopSeconds <= 0 ) + m_pSong->m_StopSegments.RemoveAt( i ); } } break; @@ -729,12 +734,15 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ float fOffsetDelta; switch( DeviceI.button ) { - case DIK_F11: fOffsetDelta = -0.025f; break; - case DIK_F12: fOffsetDelta = +0.025f; break; + case DIK_F11: fOffsetDelta = -0.020f; break; + case DIK_F12: fOffsetDelta = +0.020f; break; default: ASSERT(0); } - if( type == IET_FAST_REPEAT ) - fOffsetDelta *= 40; + switch( type ) + { + case IET_SLOW_REPEAT: fOffsetDelta *= 10; break; + case IET_FAST_REPEAT: fOffsetDelta *= 40; break; + } m_pSong->m_fBeat0OffsetInSeconds += fOffsetDelta; } @@ -753,8 +761,11 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ case DIK_F2: fOffsetDelta = +0.025f; break; default: ASSERT(0); } - if( type == IET_FAST_REPEAT ) - fOffsetDelta *= 40; + switch( type ) + { + case IET_SLOW_REPEAT: fOffsetDelta *= 10; break; + case IET_FAST_REPEAT: fOffsetDelta *= 40; break; + } m_pSong->m_fMusicSampleStartSeconds += fOffsetDelta; } @@ -769,8 +780,11 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ case DIK_ADD: fDelta = +0.025f; break; default: ASSERT(0); } - if( type == IET_FAST_REPEAT ) - fDelta *= 40; + switch( type ) + { + case IET_SLOW_REPEAT: fDelta *= 10; break; + case IET_FAST_REPEAT: fDelta *= 40; break; + } m_pSong->m_fMusicSampleLengthSeconds += fDelta; } @@ -849,10 +863,15 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ } } + float fSongBeat, fBPS; + bool bFreeze; + m_pSong->GetBeatAndBPSFromElapsedTime( m_soundMusic.GetPositionSeconds(), fSongBeat, fBPS, bFreeze ); + const float fMaxBeatDifference = fBPS * PREFSMAN->m_fJudgeWindow / PREFSMAN->m_SongOptions.m_fMusicRate; + switch( StyleI.player ) { case PLAYER_1: - m_Player.HandlePlayerStep( m_fBeat, StyleI.col, 0.35f ); + m_Player.HandlePlayerStep( m_fBeat, StyleI.col, fMaxBeatDifference ); return; } diff --git a/stepmania/src/ScreenEditMenu.cpp b/stepmania/src/ScreenEditMenu.cpp index d394926143..2bd7621ee0 100644 --- a/stepmania/src/ScreenEditMenu.cpp +++ b/stepmania/src/ScreenEditMenu.cpp @@ -112,7 +112,8 @@ ScreenEditMenu::ScreenEditMenu() m_Menu.Load( THEME->GetPathTo(GRAPHIC_EDIT_BACKGROUND), THEME->GetPathTo(GRAPHIC_EDIT_TOP_EDGE), - ssprintf("%s %s change music START to continue", CString(char(1)), CString(char(2)) ) + ssprintf("%s %s change music START to continue", CString(char(1)), CString(char(2)) ), + false, true, 40 ); this->AddActor( &m_Menu ); diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index f12fb19262..dfd47c5820 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -164,7 +164,8 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) m_Menu.Load( THEME->GetPathTo(GRAPHIC_EVALUATION_BACKGROUND), m_ResultMode==RM_ARCADE_SUMMARY ? THEME->GetPathTo(GRAPHIC_EVALUATION_SUMMARY_TOP_EDGE) : THEME->GetPathTo(GRAPHIC_EVALUATION_TOP_EDGE), - "Press START to continue." + "Press START to continue.", + false, true, 40 ); this->AddActor( &m_Menu ); diff --git a/stepmania/src/ScreenEz2SelectPlayer.cpp b/stepmania/src/ScreenEz2SelectPlayer.cpp index 38114c1ef2..6ec609b317 100644 --- a/stepmania/src/ScreenEz2SelectPlayer.cpp +++ b/stepmania/src/ScreenEz2SelectPlayer.cpp @@ -91,7 +91,8 @@ ScreenEz2SelectPlayer::ScreenEz2SelectPlayer() m_Menu.Load( THEME->GetPathTo(GRAPHIC_SELECT_STYLE_BACKGROUND), THEME->GetPathTo(GRAPHIC_SELECT_STYLE_TOP_EDGE), - ssprintf("Use %c to select your pad", char(4) ) + ssprintf("Use %c %c to select, then press START", char(1), char(2) ), + false, true, 40 ); this->AddActor( &m_Menu ); diff --git a/stepmania/src/ScreenEz2SelectStyle.cpp b/stepmania/src/ScreenEz2SelectStyle.cpp index f9c5308761..d129361fbc 100644 --- a/stepmania/src/ScreenEz2SelectStyle.cpp +++ b/stepmania/src/ScreenEz2SelectStyle.cpp @@ -173,7 +173,8 @@ ScreenEz2SelectStyle::ScreenEz2SelectStyle() m_Menu.Load( THEME->GetPathTo(GRAPHIC_SELECT_STYLE_BACKGROUND), THEME->GetPathTo(GRAPHIC_SELECT_STYLE_TOP_EDGE), - ssprintf("Use %c %c to select, then press START", char(1), char(2) ) + ssprintf("Use %c %c to select, then press START", char(1), char(2) ), + false, true, 40 ); this->AddActor( &m_Menu ); diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index ba5dd5f92c..44cb9c4104 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -50,7 +50,7 @@ const float TIME_BETWEEN_DANCING_COMMENTS = 15; // received while STATE_DANCING -const ScreenMessage SM_SongEnded = ScreenMessage(SM_User+102); +const ScreenMessage SM_NotesEnded = ScreenMessage(SM_User+102); const ScreenMessage SM_LifeIs0 = ScreenMessage(SM_User+103); @@ -91,10 +91,10 @@ ScreenGameplay::ScreenGameplay() Song* pSong = pCourse->m_apSongs[i]; DifficultyClass dc = pCourse->m_aDifficultyClasses[i]; - for( int j=0; jm_arrayNotes.GetSize(); j++ ) + for( int j=0; jm_apNotes.GetSize(); j++ ) { - Notes* pNotes = pSong->m_arrayNotes[j]; - if( pSong->m_arrayNotes[j]->m_DifficultyClass == dc ) + Notes* pNotes = pSong->m_apNotes[j]; + if( pSong->m_apNotes[j]->m_DifficultyClass == dc ) { m_apSongQueue.Add( pSong ); for( int p=0; pGetPathTo(SOUND_GAMEPLAY_FAILED) ); m_announcerReady.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_READY) ); - m_announcerHereWeGo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_HERE_WE_GO_NORMAL) ); + if( PREFSMAN->IsExtraStage() || PREFSMAN->IsExtraStage2() ) + m_announcerHereWeGo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_HERE_WE_GO_EXTRA) ); + else if( PREFSMAN->IsFinalStage() ) + m_announcerHereWeGo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_HERE_WE_GO_FINAL) ); + else + m_announcerHereWeGo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_HERE_WE_GO_NORMAL) ); m_announcerDanger.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_COMMENT_DANGER) ); m_announcerGood.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_COMMENT_GOOD) ); m_announcerHot.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_COMMENT_HOT) ); + + m_announcer100Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_100_COMBO) ); + m_announcer200Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_200_COMBO) ); + m_announcer300Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_300_COMBO) ); + m_announcer400Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_400_COMBO) ); + m_announcer500Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_500_COMBO) ); + m_announcer600Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_600_COMBO) ); + m_announcer700Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_700_COMBO) ); + m_announcer800Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_800_COMBO) ); + m_announcer900Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_900_COMBO) ); + m_announcer1000Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_1000_COMBO) ); + m_announcerComboStopped.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_COMBO_STOPPED) ); + m_announcerCleared.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_CLEARED) ); m_announcerFailComment.Load(ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_FAILED) ); @@ -342,7 +360,9 @@ void ScreenGameplay::LoadNextSong() ); } - m_soundMusic.Load( m_pCurSong->GetMusicPath() ); + m_soundMusic.Load( m_pCurSong->GetMusicPath(), true ); // enable accurate sync + float fStartSeconds = min( 0, m_pCurSong->GetElapsedTimeFromBeat(m_pCurSong->m_fFirstBeat-4) ); + m_soundMusic.SetPositionSeconds( fStartSeconds ); m_soundMusic.SetPlaybackRate( PREFSMAN->m_SongOptions.m_fMusicRate ); m_Background.LoadFromSong( m_pCurSong ); @@ -357,6 +377,7 @@ void ScreenGameplay::Update( float fDeltaTime ) //LOG->WriteLine( "ScreenGameplay::Update(%f)", fDeltaTime ); Screen::Update( fDeltaTime ); + m_soundMusic.Update( fDeltaTime ); if( m_pCurSong == NULL ) return; @@ -368,7 +389,7 @@ void ScreenGameplay::Update( float fDeltaTime ) m_pCurSong->GetBeatAndBPSFromElapsedTime( fPositionSeconds, fSongBeat, fBPS, bFreeze ); - m_Background.SetSongBeat( fSongBeat, bFreeze ); + m_Background.SetSongBeat( fSongBeat, bFreeze, fPositionSeconds ); //LOG->WriteLine( "m_fOffsetInBeats = %f, m_fBeatsPerSecond = %f, m_Music.GetPositionSeconds = %f", m_fOffsetInBeats, m_fBeatsPerSecond, m_Music.GetPositionSeconds() ); @@ -427,35 +448,31 @@ void ScreenGameplay::Update( float fDeltaTime ) case STATE_DANCING: // Check for end of song - if( m_DancingState == STATE_DANCING && - m_soundMusic.GetLengthSeconds() - m_soundMusic.GetPositionSeconds() < 2 ) - this->SendScreenMessage( SM_SongEnded, 1 ); + if( fSongBeat > m_pCurSong->m_fLastBeat+4 ) + this->SendScreenMessage( SM_NotesEnded, 0 ); // Check to see if it's time to play a gameplay comment - if( PREFSMAN->m_bAnnouncer ) + m_fTimeLeftBeforeDancingComment -= fDeltaTime; + if( m_fTimeLeftBeforeDancingComment <= 0 ) { - m_fTimeLeftBeforeDancingComment -= fDeltaTime; - if( m_fTimeLeftBeforeDancingComment <= 0 ) - { - m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; // reset for the next comment + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; // reset for the next comment - bool bAllInDanger = true; - for( int p=0; pm_bAnnouncer ) - m_announcerReady.PlayRandom(); + m_announcerReady.PlayRandom(); break; case SM_User+3: break; @@ -630,9 +646,8 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM ) break; case SM_User+5: m_sprHereWeGo.StartFocusing(); - if( PREFSMAN->m_bAnnouncer ) - m_announcerHereWeGo.PlayRandom(); - m_Background.SetDiffuseColor( D3DXCOLOR(0.8f,0.8f,0.8f,1) ); + m_announcerHereWeGo.PlayRandom(); + m_Background.FadeIn(); m_soundMusic.Play(); m_soundMusic.SetPlaybackRate( PREFSMAN->m_SongOptions.m_fMusicRate ); break; @@ -653,7 +668,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM ) this->SendScreenMessage( SM_BeginFailed, 0 ); m_DancingState = STATE_OUTRO; break; - case SM_SongEnded: + case SM_NotesEnded: if( m_DancingState == STATE_OUTRO ) // gameplay already ended return; // ignore @@ -664,13 +679,91 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM ) else // cleared { m_StarWipe.CloseWipingRight( SM_ShowCleared ); - if( PREFSMAN->m_bAnnouncer ) - m_announcerCleared.PlayRandom(); // crowd cheer + m_announcerCleared.PlayRandom(); // crowd cheer } m_DancingState = STATE_OUTRO; break; - // received while STATE_OUTRO + case SM_100Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer100Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_200Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer200Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_300Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer300Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_400Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer400Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_500Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer500Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_600Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer600Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_700Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer700Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_800Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer800Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_900Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer900Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_1000Combo: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcer1000Combo.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + case SM_ComboStopped: + if( m_fTimeLeftBeforeDancingComment < 12 ) + { + m_announcerComboStopped.PlayRandom(); + m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; + } + break; + + + // received while STATE_OUTRO case SM_ShowCleared: m_sprCleared.StartFocusing(); SCREENMAN->SendMessageToTopScreen( SM_HideCleared, 2.5 ); @@ -692,8 +785,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM ) this->SendScreenMessage( SM_ShowFailed, 0.2f ); break; case SM_ShowFailed: - if( PREFSMAN->m_bAnnouncer ) - m_soundFail.PlayRandom(); + m_soundFail.PlayRandom(); // make the background invisible so we don't waste mem bandwidth drawing it m_Background.BeginTweening( 1 ); @@ -714,8 +806,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM ) SCREENMAN->SendMessageToTopScreen( SM_HideFailed, 3.0f ); break; case SM_PlayFailComment: - if( PREFSMAN->m_bAnnouncer ) - m_announcerFailComment.PlayRandom(); + m_announcerFailComment.PlayRandom(); break; case SM_HideFailed: m_sprFailed.StopTweening(); diff --git a/stepmania/src/ScreenGameplay.h b/stepmania/src/ScreenGameplay.h index 6332ca7433..207cf57ee4 100644 --- a/stepmania/src/ScreenGameplay.h +++ b/stepmania/src/ScreenGameplay.h @@ -26,6 +26,20 @@ #include "DifficultyBanner.h" +// messages sent by Combo +const ScreenMessage SM_100Combo = ScreenMessage(SM_User+200); +const ScreenMessage SM_200Combo = ScreenMessage(SM_User+201); +const ScreenMessage SM_300Combo = ScreenMessage(SM_User+202); +const ScreenMessage SM_400Combo = ScreenMessage(SM_User+203); +const ScreenMessage SM_500Combo = ScreenMessage(SM_User+204); +const ScreenMessage SM_600Combo = ScreenMessage(SM_User+205); +const ScreenMessage SM_700Combo = ScreenMessage(SM_User+206); +const ScreenMessage SM_800Combo = ScreenMessage(SM_User+207); +const ScreenMessage SM_900Combo = ScreenMessage(SM_User+208); +const ScreenMessage SM_1000Combo = ScreenMessage(SM_User+209); +const ScreenMessage SM_ComboStopped = ScreenMessage(SM_User+210); + + class ScreenGameplay : public Screen { public: @@ -95,6 +109,17 @@ private: RandomSample m_announcerDanger; RandomSample m_announcerGood; RandomSample m_announcerHot; + RandomSample m_announcer100Combo; + RandomSample m_announcer200Combo; + RandomSample m_announcer300Combo; + RandomSample m_announcer400Combo; + RandomSample m_announcer500Combo; + RandomSample m_announcer600Combo; + RandomSample m_announcer700Combo; + RandomSample m_announcer800Combo; + RandomSample m_announcer900Combo; + RandomSample m_announcer1000Combo; + RandomSample m_announcerComboStopped; RandomStream m_announcerCleared; RandomStream m_announcerFailComment; RandomStream m_announcerGameOver; diff --git a/stepmania/src/ScreenMusicScroll.cpp b/stepmania/src/ScreenMusicScroll.cpp index 69b174f5bd..0d875cae9d 100644 --- a/stepmania/src/ScreenMusicScroll.cpp +++ b/stepmania/src/ScreenMusicScroll.cpp @@ -42,8 +42,8 @@ const CString CREDIT_LINES[] = "", "GRAPHICS:", "TofuBoy (Lucas Tang)", - "DJ McFox (Ryan McKanna)", "SPiGuMuS", + "DJ McFox (Ryan McKanna)", "", "", "", @@ -53,7 +53,7 @@ const CString CREDIT_LINES[] = "", "", "SOUND:", - "Kyle 'Keel' Ward", + "Kyle 'KeeL' Ward", "", "", "", @@ -80,10 +80,11 @@ const CString CREDIT_LINES[] = "", "", "SPECIAL THANKS TO:", - "SimWolf", - "Dance With Intensity", - "DDR Llama", + "DDRLlama", "DDRManiaX", + "SimWolf", + "DJ DraftHorse", + "Dance With Intensity", "Lagged", "The Melting Pot", "DDRJamz Global BBS", diff --git a/stepmania/src/ScreenOptions.cpp b/stepmania/src/ScreenOptions.cpp index 54b274d2c8..c6e50b6b4a 100644 --- a/stepmania/src/ScreenOptions.cpp +++ b/stepmania/src/ScreenOptions.cpp @@ -50,7 +50,8 @@ ScreenOptions::ScreenOptions( CString sBackgroundPath, CString sTopEdgePath ) m_Menu.Load( sBackgroundPath, sTopEdgePath, - ssprintf("%s %s to change line %s %s to select between options then press START", CString(char(3)), CString(char(4)), CString(char(1)), CString(char(2)) ) + ssprintf("%s %s to change line %s %s to select between options then press START", CString(char(3)), CString(char(4)), CString(char(1)), CString(char(2)) ), + false, true, 40 ); this->AddActor( &m_Menu ); m_Menu.TweenOnScreenFromBlack( SM_None ); @@ -132,12 +133,14 @@ void ScreenOptions::GetWidthXY( PlayerNumber p, int iRow, float &fWidthOut, floa void ScreenOptions::InitOptionsText() { + const float fLineGap = LINE_GAP_Y - max(0, (m_iNumOptionLines-10)*2); + // init m_textOptions from optionLines for( int i=0; iGetSkinNames( arraySkinNames ); - - m_OptionLineData[PO_SKIN].iNumOptions = arraySkinNames.GetSize(); - - for( int i=0; im_PlayerOptions[p]; @@ -103,14 +91,6 @@ void ScreenPlayerOptions::ImportOptions() m_iSelectedOption[p][PO_HOLD_NOTES] = po.m_bHoldNotes ? 1 : 0; m_iSelectedOption[p][PO_DARK] = po.m_bDark ? 1 : 0; m_iSelectedOption[p][PO_DRAIN] = po.m_DrainType; - - // highlight currently selected skin - for( int s=0; im_sCurrentSkin[p] ) - { - m_iSelectedOption[p][PO_SKIN] = s; - break; - } } } @@ -139,10 +119,7 @@ void ScreenPlayerOptions::ExportOptions() po.m_ColorType = (PlayerOptions::ColorType)m_iSelectedOption[p][PO_COLOR]; po.m_bHoldNotes = (m_iSelectedOption[p][PO_HOLD_NOTES] == 1); po.m_bDark = (m_iSelectedOption[p][PO_DARK] == 1); - po.m_DrainType = (PlayerOptions::DrainType)m_iSelectedOption[p][PO_DRAIN]; - - int iSelectedSkin = m_iSelectedOption[p][PO_SKIN]; - GAMEMAN->m_sCurrentSkin[p] = m_OptionLineData[PO_SKIN].szOptionsText[iSelectedSkin]; + po.m_DrainType = (PlayerOptions::DrainType)m_iSelectedOption[p][PO_DRAIN]; } } diff --git a/stepmania/src/ScreenSandbox.cpp b/stepmania/src/ScreenSandbox.cpp index 31b9faa4f0..872588cdfa 100644 --- a/stepmania/src/ScreenSandbox.cpp +++ b/stepmania/src/ScreenSandbox.cpp @@ -22,7 +22,12 @@ ScreenSandbox::ScreenSandbox() { - m_sound.Load( THEME->GetPathTo(SOUND_MENU_START) ); + m_text.Load( THEME->GetPathTo(FONT_NORMAL) ); + m_text.SetXY( CENTER_X, CENTER_Y ); + this->AddActor( &m_text ); + + m_sound.Load( THEME->GetPathTo(SOUND_MENU_MUSIC) ); + m_sound.SetPositionSeconds( -10 ); m_sound.Play(); //this->AddActor( &m_spr ); @@ -32,6 +37,8 @@ ScreenSandbox::ScreenSandbox() void ScreenSandbox::Update( float fDeltaTime ) { Screen::Update( fDeltaTime ); + m_sound.Update( fDeltaTime ); + m_text.SetText( ssprintf("%f", m_sound.GetPositionSeconds()) ); } void ScreenSandbox::DrawPrimitives() diff --git a/stepmania/src/ScreenSandbox.h b/stepmania/src/ScreenSandbox.h index 3e5fe63d35..1a9186bc4a 100644 --- a/stepmania/src/ScreenSandbox.h +++ b/stepmania/src/ScreenSandbox.h @@ -1,3 +1,4 @@ +#pragma once /* ----------------------------------------------------------------------------- File: ScreenSandbox.h @@ -8,10 +9,6 @@ ----------------------------------------------------------------------------- */ -#ifndef _ScreenSandbox_H_ -#define _ScreenSandbox_H_ - - #include "Screen.h" #include "Sprite.h" #include "BitmapText.h" @@ -30,10 +27,7 @@ public: virtual void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ); virtual void HandleScreenMessage( const ScreenMessage SM ); - Sprite m_spr; - - RageSoundSample m_sound; + BitmapText m_text; + RageSoundStream m_sound; }; - -#endif \ No newline at end of file diff --git a/stepmania/src/ScreenSelectCourse.cpp b/stepmania/src/ScreenSelectCourse.cpp index 33cbdcf829..bef9c26927 100644 --- a/stepmania/src/ScreenSelectCourse.cpp +++ b/stepmania/src/ScreenSelectCourse.cpp @@ -61,8 +61,9 @@ ScreenSelectCourse::ScreenSelectCourse() THEME->GetPathTo(GRAPHIC_SELECT_COURSE_BACKGROUND), THEME->GetPathTo(GRAPHIC_SELECT_COURSE_TOP_EDGE), ssprintf("%c or %c change course then press START", - char(1), char(2), char(3), char(3), char(4), char(4), char(3), char(4), char(3), char(4) ) - ); + char(1), char(2), char(3), char(3), char(4), char(4), char(3), char(4), char(3), char(4) ), + false, true, 60 + ); this->AddActor( &m_Menu ); m_CourseInfoFrame.SetXY( COURSE_INFO_FRAME_X, COURSE_INFO_FRAME_Y ); diff --git a/stepmania/src/ScreenSelectDifficulty.cpp b/stepmania/src/ScreenSelectDifficulty.cpp index 8ac758df6c..2be425c227 100644 --- a/stepmania/src/ScreenSelectDifficulty.cpp +++ b/stepmania/src/ScreenSelectDifficulty.cpp @@ -81,7 +81,8 @@ ScreenSelectDifficulty::ScreenSelectDifficulty() m_Menu.Load( THEME->GetPathTo(GRAPHIC_SELECT_DIFFICULTY_BACKGROUND) , THEME->GetPathTo(GRAPHIC_SELECT_DIFFICULTY_TOP_EDGE), - ssprintf("Use %c %c to select, then press START", char(1), char(2)) + ssprintf("Use %c %c to select, then press START", char(1), char(2)), + false, true, 40 ); this->AddActor( &m_Menu ); diff --git a/stepmania/src/ScreenSelectGroup.cpp b/stepmania/src/ScreenSelectGroup.cpp index 8ae409444f..4777e247e2 100644 --- a/stepmania/src/ScreenSelectGroup.cpp +++ b/stepmania/src/ScreenSelectGroup.cpp @@ -60,7 +60,8 @@ ScreenSelectGroup::ScreenSelectGroup() m_Menu.Load( THEME->GetPathTo(GRAPHIC_SELECT_GROUP_BACKGROUND) , THEME->GetPathTo(GRAPHIC_SELECT_GROUP_TOP_EDGE), - ssprintf("Use %c %c to select, then press START", char(1), char(2)) + ssprintf("Use %c %c to select, then press START", char(1), char(2)), + false, true, 40 ); this->AddActor( &m_Menu ); @@ -101,8 +102,6 @@ ScreenSelectGroup::ScreenSelectGroup() m_textGroup[i].SetXY( BUTTON_X, BUTTON_START_Y + BUTTON_GAP_Y*i ); m_textGroup[i].SetText( SONGMAN->ShortenGroupName( sGroupName ) ); m_textGroup[i].SetZoom( 0.8f ); - if( m_textGroup[i].GetWidestLineWidthInSourcePixels()*0.8f > m_sprGroupButton[i].GetUnzoomedWidth() ) - m_textGroup[i].SetZoomX( m_textGroup[i].GetWidestLineWidthInSourcePixels()*0.8f / (float)m_sprGroupButton[i].GetUnzoomedWidth() ); m_textGroup[i].SetShadowLength( 2 ); if( i == 0 ) m_textGroup[i].TurnRainbowOn(); diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index 85898c857f..49bfba3d38 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -74,8 +74,9 @@ ScreenSelectMusic::ScreenSelectMusic() THEME->GetPathTo(GRAPHIC_SELECT_MUSIC_BACKGROUND), THEME->GetPathTo(GRAPHIC_SELECT_MUSIC_TOP_EDGE), ssprintf("%c or %c change music %c%c easier difficulty %c%c harder difficulty %c%c%c%c change sort", - char(1), char(2), char(3), char(3), char(4), char(4), char(3), char(4), char(3), char(4) ) - ); + char(1), char(2), char(3), char(3), char(4), char(4), char(3), char(4), char(3), char(4) ), + false, true, 60 + ); this->AddActor( &m_Menu ); m_SongInfoFrame.SetXY( SONG_INFO_FRAME_X, SONG_INFO_FRAME_Y ); diff --git a/stepmania/src/ScreenSelectStyle.cpp b/stepmania/src/ScreenSelectStyle.cpp index 11eff954cf..12b71c8ad6 100644 --- a/stepmania/src/ScreenSelectStyle.cpp +++ b/stepmania/src/ScreenSelectStyle.cpp @@ -99,7 +99,8 @@ ScreenSelectStyle::ScreenSelectStyle() m_Menu.Load( THEME->GetPathTo(GRAPHIC_SELECT_STYLE_BACKGROUND), THEME->GetPathTo(GRAPHIC_SELECT_STYLE_TOP_EDGE), - ssprintf("Use %c %c to select, then press START", char(1), char(2) ) + ssprintf("Use %c %c to select, then press START", char(1), char(2) ), + false, true, 40 ); this->AddActor( &m_Menu ); diff --git a/stepmania/src/ScreenStage.cpp b/stepmania/src/ScreenStage.cpp index c13a0b8470..4419e17857 100644 --- a/stepmania/src/ScreenStage.cpp +++ b/stepmania/src/ScreenStage.cpp @@ -26,11 +26,14 @@ #include "AnnouncerManager.h" const ScreenMessage SM_StartFadingOut = ScreenMessage(SM_User + 1); +const ScreenMessage SM_DoneFadingIn = ScreenMessage(SM_User + 2); const ScreenMessage SM_GoToNextState = ScreenMessage(SM_User + 3); ScreenStage::ScreenStage() { + m_pNextScreen = NULL; + m_textStage.Load( THEME->GetPathTo(FONT_STAGE) ); m_textStage.TurnShadowOff(); @@ -79,7 +82,8 @@ ScreenStage::ScreenStage() m_textStage.SetTweenDiffuseColor( D3DXCOLOR(1,1,1,1) ); this->AddActor( &m_textStage ); - this->SendScreenMessage( SM_StartFadingOut, 3 ); + this->SendScreenMessage( SM_DoneFadingIn, 0.6f ); + this->SendScreenMessage( SM_StartFadingOut, 1.2f ); } @@ -92,8 +96,11 @@ void ScreenStage::HandleScreenMessage( const ScreenMessage SM ) m_textStage.SetTweenDiffuseColor( D3DXCOLOR(1,1,1,0) ); this->SendScreenMessage( SM_GoToNextState, 0.8f ); break; + case SM_DoneFadingIn: + m_pNextScreen = new ScreenGameplay; + break; case SM_GoToNextState: - SCREENMAN->SetNewScreen( new ScreenGameplay ); + SCREENMAN->SetNewScreen( m_pNextScreen ); break; } } diff --git a/stepmania/src/ScreenStage.h b/stepmania/src/ScreenStage.h index 3c209e370f..a472eeecbf 100644 --- a/stepmania/src/ScreenStage.h +++ b/stepmania/src/ScreenStage.h @@ -24,6 +24,7 @@ private: bool m_bTryExtraStage; BitmapText m_textStage; + Screen* m_pNextScreen; }; diff --git a/stepmania/src/ScreenTitleMenu.cpp b/stepmania/src/ScreenTitleMenu.cpp index 1c6c913f62..0c5cd14e6b 100644 --- a/stepmania/src/ScreenTitleMenu.cpp +++ b/stepmania/src/ScreenTitleMenu.cpp @@ -23,6 +23,7 @@ #include "ScreenEditMenu.h" #include "ScreenSelectStyle.h" #include "ScreenSelectGame.h" +#include "ScreenAppearanceOptions.h" #include "RageLog.h" #include "SongManager.h" #include "AnnouncerManager.h" @@ -40,12 +41,13 @@ const CString CHOICE_TEXT[ScreenTitleMenu::NUM_TITLE_MENU_CHOICES] = { "SWITCH GAME", "CONFIG KEY/JOY", "GAME OPTIONS", + "APPEARANCE OPTIONS", "EDIT/RECORD/SYNCH", "EXIT", }; -const float CHOICES_START_Y = 66; -const float CHOICES_GAP_Y = 56; +const float CHOICES_START_Y = 62; +const float CHOICES_GAP_Y = 52; const float HELP_X = CENTER_X; const float HELP_Y = SCREEN_HEIGHT-55; @@ -57,6 +59,7 @@ const ScreenMessage SM_GoToSelectStyle = ScreenMessage(SM_User+3); const ScreenMessage SM_GoToSelectGame = ScreenMessage(SM_User+4); const ScreenMessage SM_GoToMapInstruments = ScreenMessage(SM_User+5); const ScreenMessage SM_GoToGameOptions = ScreenMessage(SM_User+6); +const ScreenMessage SM_GoToAppearanceOptions= ScreenMessage(SM_User+7); const ScreenMessage SM_GoToEdit = ScreenMessage(SM_User+10); const ScreenMessage SM_DoneOpening = ScreenMessage(SM_User+11); const ScreenMessage SM_GoToEz2 = ScreenMessage(SM_User+12); @@ -101,7 +104,7 @@ ScreenTitleMenu::ScreenTitleMenu() m_textVersion.Load( THEME->GetPathTo(FONT_NORMAL) ); m_textVersion.SetHorizAlign( Actor::align_right ); - m_textVersion.SetText( "v3.0 beta 1" ); + m_textVersion.SetText( "v3.0 beta 4" ); m_textVersion.SetDiffuseColor( D3DXCOLOR(0.6f,0.6f,0.6f,1) ); // light gray m_textVersion.SetXY( SCREEN_RIGHT-16, SCREEN_BOTTOM-20 ); m_textVersion.SetZoom( 0.5f ); @@ -146,12 +149,14 @@ ScreenTitleMenu::ScreenTitleMenu() SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_TITLE_MENU_GAME_NAME) ); + m_soundAttract.Load( ANNOUNCER->GetPathTo(ANNOUNCER_TITLE_MENU_ATTRACT) ); m_soundChange.Load( THEME->GetPathTo(SOUND_TITLE_MENU_CHANGE) ); m_soundSelect.Load( THEME->GetPathTo(SOUND_MENU_START) ); m_soundInvalid.Load( THEME->GetPathTo(SOUND_MENU_INVALID) ); + for( i=0; i<3000; i++ ) - this->SendScreenMessage( SM_PlayAttract, (float)15+i*15 ); + this->SendScreenMessage( SM_PlayAttract, (float)20+i*20 ); m_TitleMenuChoice = CHOICE_GAME_START; @@ -184,13 +189,9 @@ void ScreenTitleMenu::HandleScreenMessage( const ScreenMessage SM ) switch( SM ) { case SM_DoneOpening: - if( PREFSMAN->m_bAnnouncer ) - { - m_soundTitle.PlayRandom(); - } break; case SM_PlayAttract: - SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_TITLE_MENU_ATTRACT) ); + m_soundAttract.PlayRandom(); break; case SM_GoToCaution: SCREENMAN->SetNewScreen( new ScreenCaution ); @@ -207,6 +208,9 @@ void ScreenTitleMenu::HandleScreenMessage( const ScreenMessage SM ) case SM_GoToGameOptions: SCREENMAN->SetNewScreen( new ScreenGameOptions ); break; + case SM_GoToAppearanceOptions: + SCREENMAN->SetNewScreen( new ScreenAppearanceOptions ); + break; case SM_GoToEdit: SCREENMAN->SetNewScreen( new ScreenEditMenu ); break; @@ -294,6 +298,10 @@ void ScreenTitleMenu::MenuStart( const PlayerNumber p ) m_soundSelect.PlayRandom(); m_Fade.CloseWipingRight( SM_GoToGameOptions ); return; + case CHOICE_APPEARANCE_OPTIONS: + m_soundSelect.PlayRandom(); + m_Fade.CloseWipingRight( SM_GoToAppearanceOptions ); + return; case CHOICE_EDIT: if( SONGMAN->m_pSongs.GetSize() == 0 ) { @@ -322,6 +330,8 @@ void ScreenTitleMenu::MenuStart( const PlayerNumber p ) m_soundSelect.PlayRandom(); PostQuitMessage(0); return; + default: + ASSERT(0); } } diff --git a/stepmania/src/ScreenTitleMenu.h b/stepmania/src/ScreenTitleMenu.h index d3a1a199e6..8066f83128 100644 --- a/stepmania/src/ScreenTitleMenu.h +++ b/stepmania/src/ScreenTitleMenu.h @@ -33,6 +33,7 @@ public: CHOICE_SELECT_GAME, CHOICE_MAP_INSTRUMENTS, CHOICE_GAME_OPTIONS, + CHOICE_APPEARANCE_OPTIONS, CHOICE_EDIT, CHOICE_EXIT, NUM_TITLE_MENU_CHOICES // leave this at the end! @@ -57,7 +58,6 @@ private: TransitionFade m_Fade; - RandomStream m_soundTitle; RandomStream m_soundAttract; RandomSample m_soundChange; RandomSample m_soundSelect; diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index 6d830eba87..95dd41ef86 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -19,7 +19,7 @@ #include "NoteData.h" -const int FILE_CACHE_VERSION = 29; // increment this to force a cache reload (useful when the SM file format changes) +const int FILE_CACHE_VERSION = 43; // increment this to force a cache reload (useful when the SM file format changes) int CompareBPMSegments(const void *arg1, const void *arg2) @@ -44,11 +44,11 @@ void SortBPMSegmentsArray( CArray &arrayBPMSegments ) qsort( arrayBPMSegments.GetData(), arrayBPMSegments.GetSize(), sizeof(BPMSegment), CompareBPMSegments ); } -int CompareFreezeSegments(const void *arg1, const void *arg2) +int CompareStopSegments(const void *arg1, const void *arg2) { // arg1 and arg2 are of type Step** - FreezeSegment* seg1 = (FreezeSegment*)arg1; - FreezeSegment* seg2 = (FreezeSegment*)arg2; + StopSegment* seg1 = (StopSegment*)arg1; + StopSegment* seg2 = (StopSegment*)arg2; float score1 = seg1->m_fStartBeat; float score2 = seg2->m_fStartBeat; @@ -61,9 +61,31 @@ int CompareFreezeSegments(const void *arg1, const void *arg2) return 1; } -void SortFreezeSegmentsArray( CArray &arrayFreezeSegments ) +void SortStopSegmentsArray( CArray &arrayStopSegments ) { - qsort( arrayFreezeSegments.GetData(), arrayFreezeSegments.GetSize(), sizeof(FreezeSegment), CompareFreezeSegments ); + qsort( arrayStopSegments.GetData(), arrayStopSegments.GetSize(), sizeof(StopSegment), CompareStopSegments ); +} + +int CompareAnimationSegments(const void *arg1, const void *arg2) +{ + // arg1 and arg2 are of type Step** + AnimationSegment* seg1 = (AnimationSegment*)arg1; + AnimationSegment* seg2 = (AnimationSegment*)arg2; + + float score1 = seg1->m_fStartBeat; + float score2 = seg2->m_fStartBeat; + + if( score1 == score2 ) + return 0; + else if( score1 < score2 ) + return -1; + else + return 1; +} + +void SortAnimationSegmentsArray( CArray &arrayAnimationSegments ) +{ + qsort( arrayAnimationSegments.GetData(), arrayAnimationSegments.GetSize(), sizeof(AnimationSegment), CompareAnimationSegments ); } @@ -78,14 +100,16 @@ Song::Song() m_fMusicSampleLengthSeconds = 16; // start fading out at m_fMusicSampleLengthSeconds-1 seconds m_iMusicBytes = 0; m_fMusicLengthSeconds = 0; + m_fFirstBeat = -1; + m_fLastBeat = -1; } Song::~Song() { - for( int i=0; iLoadFromBMSFile( m_sSongDir + arrayBMSFileNames[i] ); - m_arrayNotes.Add( pNewNotes ); + m_apNotes.Add( pNewNotes ); } CString sPath = m_sSongDir + arrayBMSFileNames[0]; @@ -525,7 +552,7 @@ bool Song::LoadFromBMSDir( CString sDir ) value_name = line; } - if( stricmp(value_name, sTagToLookFor) == 0 ) + if( 0==stricmp(value_name, sTagToLookFor) == 0 ) { fBPM = (float)atof( value_data ); break; @@ -588,7 +615,7 @@ bool Song::LoadFromBMSDir( CString sDir ) value_name = line; } - if( stricmp(value_name, sTagToLookFor) == 0 ) + if( 0==stricmp(value_name, sTagToLookFor) == 0 ) { // find the BPM at the time of this freeze float fBPM = -1; @@ -616,9 +643,9 @@ bool Song::LoadFromBMSDir( CString sDir ) } else { - FreezeSegment newSeg( fFreezeStartBeat, fFreezeSecs ); - AddFreezeSegment( newSeg ); - LOG->WriteLine( "Inserting new Freeze at beat %f, secs %f", newSeg.m_fStartBeat, newSeg.m_fFreezeSeconds ); + StopSegment newSeg( fFreezeStartBeat, fFreezeSecs ); + AddStopSegment( newSeg ); + LOG->WriteLine( "Inserting new Freeze at beat %f, secs %f", newSeg.m_fStartBeat, newSeg.m_fStopSeconds ); } file.Close(); @@ -681,7 +708,7 @@ bool Song::LoadFromDWIFile( CString sPath ) // split the value string into tokens CStringArray arrayValueTokens; - split( sValueString, ":", arrayValueTokens ); + split( sValueString, ":", arrayValueTokens, false ); for( int j=0; jWriteLine( "Adding a freeze segment: beat: %f, seconds = %f", fFreezeBeat, fFreezeSeconds ); } } - else if( sValueName == "#CHANGEBPM" || sValueName == "#BPMCHANGE" ) + else if( 0==stricmp(sValueName,"#CHANGEBPM") || 0==stricmp(sValueName,"#BPMCHANGE") ) { CStringArray arrayBPMChangeExpressions; split( arrayValueTokens[1], ",", arrayBPMChangeExpressions ); @@ -750,13 +780,13 @@ bool Song::LoadFromDWIFile( CString sPath ) split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues ); float fIndex = atoi( arrayBPMChangeValues[0] ) * ELEMENTS_PER_BEAT / 4.0f; float fBeat = NoteRowToBeat( fIndex ); - float fNewBPM = (float)atoi( arrayBPMChangeValues[1] ); + float fNewBPM = (float)atof( arrayBPMChangeValues[1] ); AddBPMSegment( BPMSegment(fBeat, fNewBPM) ); } } - else if( sValueName == "#SINGLE" || sValueName == "#DOUBLE" || sValueName == "#COUPLE" ) + else if( 0==stricmp(sValueName,"#SINGLE") || 0==stricmp(sValueName,"#DOUBLE") || 0==stricmp(sValueName,"#COUPLE") ) { Notes* pNewNotes = new Notes; pNewNotes->LoadFromDWITokens( @@ -766,7 +796,7 @@ bool Song::LoadFromDWIFile( CString sPath ) arrayValueTokens[3], arrayValueTokens.GetSize() == 5 ? arrayValueTokens[4] : "" ); - m_arrayNotes.Add( pNewNotes ); + m_apNotes.Add( pNewNotes ); } else // do nothing. We don't care about this value name @@ -782,7 +812,7 @@ bool Song::LoadFromSMFile( CString sPath ) LOG->WriteLine( "Song::LoadFromSMDir(%s)", sPath ); m_BPMSegments.RemoveAll(); - m_FreezeSegments.RemoveAll(); + m_StopSegments.RemoveAll(); int i; @@ -839,49 +869,55 @@ bool Song::LoadFromSMFile( CString sPath ) CString sValueName = arrayValueTokens.GetAt( 0 ); // handle the data - if( sValueName == "#TITLE" ) + if( 0==stricmp(sValueName,"#TITLE") ) GetMainAndSubTitlesFromFullTitle( arrayValueTokens[1], m_sMainTitle, m_sSubTitle ); - else if( sValueName == "#SUBTITLE" ) + else if( 0==stricmp(sValueName,"#SUBTITLE") ) m_sSubTitle = arrayValueTokens[1]; - else if( sValueName == "#ARTIST" ) + else if( 0==stricmp(sValueName,"#ARTIST") ) m_sArtist = arrayValueTokens[1]; - else if( sValueName == "#CREDIT" ) + else if( 0==stricmp(sValueName,"#CREDIT") ) m_sCredit = arrayValueTokens[1]; - else if( sValueName == "#BANNER" ) + else if( 0==stricmp(sValueName,"#BANNER") ) m_sBannerFile = arrayValueTokens[1]; - else if( sValueName == "#BACKGROUND" ) + else if( 0==stricmp(sValueName,"#BACKGROUND") ) m_sBackgroundFile = arrayValueTokens[1]; -// else if( sValueName == "#BACKGROUNDMOVIE" ) -// m_sBackgroundMovieFile = arrayValueTokens[1]; - - else if( sValueName == "#CDTITLE" ) + else if( 0==stricmp(sValueName,"#CDTITLE") ) m_sCDTitleFile = arrayValueTokens[1]; - else if( sValueName == "#MUSIC" ) + else if( 0==stricmp(sValueName,"#MOVIEBACKGROUND") ) + m_sMovieBackgroundFile = arrayValueTokens[1]; + + else if( 0==stricmp(sValueName,"#MUSIC") ) m_sMusicFile = arrayValueTokens[1]; - else if( sValueName == "#MUSICBYTES" ) + else if( 0==stricmp(sValueName,"#MUSICBYTES") ) m_iMusicBytes = atoi( arrayValueTokens[1] ); - else if( sValueName == "#MUSICLENGTH" ) + else if( 0==stricmp(sValueName,"#MUSICLENGTH") ) m_fMusicLengthSeconds = (float)atof( arrayValueTokens[1] ); - else if( sValueName == "#SAMPLESTART" ) + else if( 0==stricmp(sValueName,"#FIRSTBEAT") ) + m_fFirstBeat = (float)atof( arrayValueTokens[1] ); + + else if( 0==stricmp(sValueName,"#LASTBEAT") ) + m_fLastBeat = (float)atof( arrayValueTokens[1] ); + + else if( 0==stricmp(sValueName,"#SAMPLESTART") ) m_fMusicSampleStartSeconds = TimeToSeconds( arrayValueTokens[1] ); - else if( sValueName == "#SAMPLELENGTH" ) + else if( 0==stricmp(sValueName,"#SAMPLELENGTH") ) m_fMusicSampleLengthSeconds = TimeToSeconds( arrayValueTokens[1] ); - else if( sValueName == "#OFFSET" ) + else if( 0==stricmp(sValueName,"#OFFSET") ) m_fBeat0OffsetInSeconds = (float)atof( arrayValueTokens[1] ); - else if( sValueName == "#FREEZES" ) + else if( 0==stricmp(sValueName,"#STOPS") || 0==stricmp(sValueName,"#FREEZES") ) { CStringArray arrayFreezeExpressions; split( arrayValueTokens[1], ",", arrayFreezeExpressions ); @@ -893,17 +929,17 @@ bool Song::LoadFromSMFile( CString sPath ) float fFreezeBeat = (float)atof( arrayFreezeValues[0] ); float fFreezeSeconds = (float)atof( arrayFreezeValues[1] ); - FreezeSegment new_seg; + StopSegment new_seg; new_seg.m_fStartBeat = fFreezeBeat; - new_seg.m_fFreezeSeconds = fFreezeSeconds; + new_seg.m_fStopSeconds = fFreezeSeconds; - LOG->WriteLine( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fFreezeSeconds ); + LOG->WriteLine( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - AddFreezeSegment( new_seg ); + AddStopSegment( new_seg ); } } - else if( sValueName == "#BPMS" ) + else if( 0==stricmp(sValueName,"#BPMS") ) { CStringArray arrayBPMChangeExpressions; split( arrayValueTokens[1], ",", arrayBPMChangeExpressions ); @@ -913,7 +949,7 @@ bool Song::LoadFromSMFile( CString sPath ) CStringArray arrayBPMChangeValues; split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues ); float fBeat = (float)atof( arrayBPMChangeValues[0] ); - float fNewBPM = (float)atoi( arrayBPMChangeValues[1] ); + float fNewBPM = (float)atof( arrayBPMChangeValues[1] ); BPMSegment new_seg; new_seg.m_fStartBeat = fBeat; @@ -923,19 +959,36 @@ bool Song::LoadFromSMFile( CString sPath ) } } - else if( sValueName == "#NOTES" ) + else if( 0==stricmp(sValueName,"#ANIMATIONS") ) + { + CStringArray arrayAnimationExpressions; + split( arrayValueTokens[1], ",", arrayAnimationExpressions ); + + for( int b=0; bm_NotesType == StringToNotesType(arrayValueTokens[1]) && - m_arrayNotes[j]->m_sDescription == arrayValueTokens[2] ) - pNewNotes = m_arrayNotes[j]; + for( int j=0; jm_NotesType == StringToNotesType(arrayValueTokens[1]) && + m_apNotes[j]->m_sDescription == arrayValueTokens[2] ) + pNewNotes = m_apNotes[j]; if( pNewNotes == NULL ) // we didn't find a match that was already loaded { pNewNotes = new Notes; - m_arrayNotes.Add( pNewNotes ); + m_apNotes.Add( pNewNotes ); } if( arrayValueTokens.GetSize() != 7 ) @@ -968,120 +1021,164 @@ void Song::TidyUpData() if( m_BPMSegments.GetSize() == 0 ) throw RageException( "No #BPM specified in '%s.'", GetSongFilePath() ); - if( m_sMusicFile == "" || !DoesFileExist(GetMusicPath()) ) + if( !HasMusic() ) { CStringArray arrayPossibleMusic; GetDirListing( m_sSongDir + CString("*.mp3"), arrayPossibleMusic ); GetDirListing( m_sSongDir + CString("*.ogg"), arrayPossibleMusic ); GetDirListing( m_sSongDir + CString("*.wav"), arrayPossibleMusic ); - if( arrayPossibleMusic.GetSize() != 0 ) // we found a match + if( arrayPossibleMusic.GetSize() > 0 ) // we found a match m_sMusicFile = arrayPossibleMusic[0]; else throw RageException( "The song in '%s' is missing a music file. You must place a music file in the song folder or remove the song", m_sSongDir ); } - // Save length of music - if( GetMusicPath() != "" ) - { - RageSoundStream sound; - sound.Load( GetMusicPath() ); - m_fMusicLengthSeconds = sound.GetLengthSeconds(); - } + RageSoundStream sound; + sound.Load( GetMusicPath() ); + m_fMusicLengthSeconds = sound.GetLengthSeconds(); + + + // + // Here's the problem: We have a directory full of images. We want to determine which + // image is the banner, which is the background, and which is the CDTitle. + // + + // + // First, check the file name for hints. + // if( !HasBanner() ) { m_sBannerFile = ""; - // find the smallest image in the directory + // find an image with "banner" in the file name CStringArray arrayPossibleBanners; - GetDirListing( m_sSongDir + CString("*.png"), arrayPossibleBanners ); - GetDirListing( m_sSongDir + CString("*.jpg"), arrayPossibleBanners ); - GetDirListing( m_sSongDir + CString("*.bmp"), arrayPossibleBanners ); - - DWORD dwSmallestFileSoFar = 0xFFFFFFFF; - CString sSmallestFileSoFar = ""; - - for( int i=0; i 0 ) + m_sBannerFile = arrayPossibleBanners[0]; } if( !HasBackground() ) { m_sBackgroundFile = ""; - // find the largest image in the directory - CStringArray arrayPossibleBackgrounds; - GetDirListing( m_sSongDir + CString("*.png"), arrayPossibleBackgrounds ); - GetDirListing( m_sSongDir + CString("*.jpg"), arrayPossibleBackgrounds ); - GetDirListing( m_sSongDir + CString("*.bmp"), arrayPossibleBackgrounds ); - - DWORD dwLargestFileSoFar = 0; - CString sLargestFileSoFar = ""; - - for( int i=0; i dwLargestFileSoFar ) // we have a new leader! - { - dwLargestFileSoFar = this_size; - sLargestFileSoFar = arrayPossibleBackgrounds[i]; - } - } - - if( sLargestFileSoFar != "" ) // we found a match - m_sBackgroundFile = sLargestFileSoFar; + // find an image with "bg" or "background" in the file name + CStringArray arrayPossibleBGs; + GetDirListing( m_sSongDir + CString("*bg*.png"), arrayPossibleBGs ); + GetDirListing( m_sSongDir + CString("*bg*.jpg"), arrayPossibleBGs ); + GetDirListing( m_sSongDir + CString("*bg*.bmp"), arrayPossibleBGs ); + GetDirListing( m_sSongDir + CString("*background*.png"), arrayPossibleBGs ); + GetDirListing( m_sSongDir + CString("*background*.jpg"), arrayPossibleBGs ); + GetDirListing( m_sSongDir + CString("*background*.bmp"), arrayPossibleBGs ); + if( arrayPossibleBGs.GetSize() > 0 ) + m_sBackgroundFile = arrayPossibleBGs[0]; } -// if( !DoesFileExist(GetBackgroundMoviePath()) ) -// { -// m_sBackgroundMovieFile = ""; -// -// CStringArray arrayPossibleBackgroundMovies; -// GetDirListing( m_sSongDir + CString("*.avi"), arrayPossibleBackgroundMovies ); -// GetDirListing( m_sSongDir + CString("*.mpg"), arrayPossibleBackgroundMovies ); -// GetDirListing( m_sSongDir + CString("*.mpeg"), arrayPossibleBackgroundMovies ); -// -// if( arrayPossibleBackgroundMovies.GetSize() > 0 ) // we found a match -// m_sBackgroundMovieFile = arrayPossibleBackgroundMovies[0]; -// } - if( !HasCDTitle() ) { m_sCDTitleFile = ""; + + // find an image with "cdtitle" in the file name + CStringArray arrayPossibleCDTitles; + GetDirListing( m_sSongDir + CString("*cdtitle*.png"), arrayPossibleCDTitles ); + GetDirListing( m_sSongDir + CString("*cdtitle*.jpg"), arrayPossibleCDTitles ); + GetDirListing( m_sSongDir + CString("*cdtitle*.bmp"), arrayPossibleCDTitles ); + if( arrayPossibleCDTitles.GetSize() > 0 ) + m_sCDTitleFile = arrayPossibleCDTitles[0]; } - for( int i=0; i= 320 && ddii.Height >= 240 ) + { + m_sBackgroundFile = arrayImages[i]; + continue; + } + if( !HasBanner() && 100 < ddii.Width && ddii.Width < 320 && 64 < ddii.Height && ddii.Height < 240 ) + { + m_sBannerFile = arrayImages[i]; + continue; + } + if( !HasCDTitle() && ddii.Width <= 100 && ddii.Height <= 64 ) + { + m_sCDTitleFile = arrayImages[i]; + continue; + } + } + } + + + + if( !HasMovieBackground() ) + { + CStringArray arrayPossibleMovies; + GetDirListing( m_sSongDir + CString("*movie*.avi"), arrayPossibleMovies ); + GetDirListing( m_sSongDir + CString("*movie*.mpg"), arrayPossibleMovies ); + GetDirListing( m_sSongDir + CString("*movie*.mpeg"), arrayPossibleMovies ); + GetDirListing( m_sSongDir + CString("*.avi"), arrayPossibleMovies ); + GetDirListing( m_sSongDir + CString("*.mpg"), arrayPossibleMovies ); + GetDirListing( m_sSongDir + CString("*.mpeg"), arrayPossibleMovies ); + if( arrayPossibleMovies.GetSize() > 0 ) + m_sMovieBackgroundFile = arrayPossibleMovies[0]; + } + + // + // calculate radar values and first/last beat + // + for( i=0; iGetNoteData( &tempNoteData ); for( int r=0; rm_fRadarValues[r] = tempNoteData.GetRadarValue( (RadarCategory)r, m_fMusicLengthSeconds ); + + float fFirstBeat = tempNoteData.GetFirstBeat(); + float fLastBeat = tempNoteData.GetLastBeat(); + if( m_fFirstBeat == -1 ) + m_fFirstBeat = fFirstBeat; + else + m_fFirstBeat = min( m_fFirstBeat, fFirstBeat ); + if( m_fLastBeat == -1 ) + m_fLastBeat = fLastBeat; + else + m_fLastBeat = max( m_fLastBeat, fLastBeat ); } } void Song::GetNotesThatMatch( NotesType nt, CArray& arrayAddTo ) { - for( int i=0; im_NotesType == nt ) - arrayAddTo.Add( m_arrayNotes[i] ); + for( int i=0; im_NotesType == nt ) + arrayAddTo.Add( m_apNotes[i] ); } void Song::SaveToCacheFile() @@ -1138,26 +1235,17 @@ void Song::SaveToSMFile( CString sPath ) fprintf( fp, "#CREDIT:%s;\n", m_sCredit ); fprintf( fp, "#BANNER:%s;\n", m_sBannerFile ); fprintf( fp, "#BACKGROUND:%s;\n", m_sBackgroundFile ); -// fprintf( fp, "#BACKGROUNDMOVIE:%s;\n", m_sBackgroundMovieFile ); fprintf( fp, "#CDTITLE:%s;\n", m_sCDTitleFile ); + fprintf( fp, "#MOVIEBACKGROUND:%s;\n", m_sMovieBackgroundFile ); fprintf( fp, "#MUSIC:%s;\n", m_sMusicFile ); fprintf( fp, "#MUSICBYTES:%u;\n", m_iMusicBytes ); fprintf( fp, "#MUSICLENGTH:%.2f;\n", m_fMusicLengthSeconds ); + fprintf( fp, "#FIRSTBEAT:%.2f;\n", m_fFirstBeat ); + fprintf( fp, "#LASTBEAT:%.2f;\n", m_fLastBeat ); fprintf( fp, "#OFFSET:%.2f;\n", m_fBeat0OffsetInSeconds ); fprintf( fp, "#SAMPLESTART:%.2f;\n", m_fMusicSampleStartSeconds ); fprintf( fp, "#SAMPLELENGTH:%.2f;\n", m_fMusicSampleLengthSeconds ); - fprintf( fp, "#FREEZES:" ); - for( i=0; iWriteSMNotesTag( fp ); + for( i=0; iWriteSMNotesTag( fp ); fclose( fp ); } diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index acd20c53ae..24175dddf5 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -289,11 +289,11 @@ void SongManager::ReadStatisticsFromDisk() // Search for the corresponding Notes pointer. Notes* pNotes = NULL; - for( i=0; im_arrayNotes.GetSize(); i++ ) + for( i=0; im_apNotes.GetSize(); i++ ) { - if( pSong->m_arrayNotes[i]->m_sDescription == szNotesName ) // match! + if( pSong->m_apNotes[i]->m_sDescription == szNotesName ) // match! { - pNotes = pSong->m_arrayNotes[i]; + pNotes = pSong->m_apNotes[i]; break; } } @@ -330,9 +330,9 @@ void SongManager::SaveStatisticsToDisk() { Song* pSong = m_pSongs[i]; - for( int j=0; jm_arrayNotes.GetSize(); j++ ) // for each Notes + for( int j=0; jm_apNotes.GetSize(); j++ ) // for each Notes { - Notes* pNotes = pSong->m_arrayNotes[j]; + Notes* pNotes = pSong->m_apNotes[j]; if( pNotes->m_TopGrade == GRADE_NO_DATA ) continue; // skip diff --git a/stepmania/src/Sprite.h b/stepmania/src/Sprite.h index b461550b0c..294631177d 100644 --- a/stepmania/src/Sprite.h +++ b/stepmania/src/Sprite.h @@ -41,8 +41,8 @@ public: virtual void DrawPrimitives(); virtual void Update( float fDeltaTime ); - virtual void StartAnimating() { m_bIsAnimating = TRUE; }; - virtual void StopAnimating() { m_bIsAnimating = FALSE; }; + virtual void StartAnimating() { m_bIsAnimating = TRUE; if(m_pTexture) m_pTexture->Play(); }; + virtual void StopAnimating() { m_bIsAnimating = FALSE; if(m_pTexture) m_pTexture->Pause(); }; virtual void SetState( int iNewState ); int GetNumStates() { return m_iNumStates; }; diff --git a/stepmania/src/StepMania.dsp b/stepmania/src/StepMania.dsp index b5f49e2112..1b08529ca6 100644 --- a/stepmania/src/StepMania.dsp +++ b/stepmania/src/StepMania.dsp @@ -848,6 +848,14 @@ SOURCE=.\Screen.h # End Source File # Begin Source File +SOURCE=.\ScreenAppearanceOptions.cpp +# End Source File +# Begin Source File + +SOURCE=.\ScreenAppearanceOptions.h +# End Source File +# Begin Source File + SOURCE=.\ScreenCaution.cpp # End Source File # Begin Source File diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj index f7a24db8d7..4690a7e53e 100644 --- a/stepmania/src/StepMania.vcproj +++ b/stepmania/src/StepMania.vcproj @@ -146,6 +146,12 @@ + + + + diff --git a/stepmania/src/smpackage/smpackage.dsp b/stepmania/src/smpackage/smpackage.dsp index e18b18f9a1..d8d8b77ccd 100644 --- a/stepmania/src/smpackage/smpackage.dsp +++ b/stepmania/src/smpackage/smpackage.dsp @@ -38,7 +38,7 @@ RSC=rc.exe # PROP BASE Target_Dir "" # PROP Use_MFC 6 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "../" +# PROP Output_Dir "../../" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c diff --git a/stepmania/src/smpackage/smpackageDlg.cpp b/stepmania/src/smpackage/smpackageDlg.cpp index 7cd26b6b41..da7c032b7a 100644 --- a/stepmania/src/smpackage/smpackageDlg.cpp +++ b/stepmania/src/smpackage/smpackageDlg.cpp @@ -166,7 +166,7 @@ void CSmpackageDlg::OnButtonExport() '+', '=', '[', ']', '{', '}', '|', ':', '\"', '\\', '<', '>', ',', '?', '/' }; - for( int i=0; i m_BPMSegments; // this must be sorted before gameplay - CArray m_FreezeSegments; // this must be sorted before gameplay + CArray m_StopSegments; // this must be sorted before gameplay + CArray m_AnimationSegments; // this must be sorted before gameplay void AddBPMSegment( BPMSegment seg ); - void AddFreezeSegment( FreezeSegment seg ); + void AddStopSegment( StopSegment seg ); + void AddAnimationSegment( AnimationSegment seg ); + void GetMinMaxBPM( float &fMinBPM, float &fMaxBPM ) { fMaxBPM = 0; @@ -114,20 +130,27 @@ public: break; return m_BPMSegments[i].m_fBPM; }; + CString GetAnimationAtBeat( float fBeat ) + { + for( int i=0; i fBeat ) + break; + return m_AnimationSegments[i].m_sAnimationName; + }; void GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut ); float GetElapsedTimeFromBeat( float fBeat ); - CArray m_arrayNotes; + CArray m_apNotes; void GetNotesThatMatch( NotesType nt, CArray& arrayAddTo ); int GetNumTimesPlayed() { int iTotalNumTimesPlayed = 0; - for( int i=0; im_iNumTimesPlayed; + iTotalNumTimesPlayed += m_apNotes[i]->m_iNumTimesPlayed; } return iTotalNumTimesPlayed; }