Port from git

This commit is contained in:
emb 2015-01-01 10:14:26 -06:00
commit 93094bcbed
772 changed files with 621608 additions and 0 deletions

2
.hgignore Normal file
View File

@ -0,0 +1,2 @@
syntax: glob
Build/

View File

@ -0,0 +1,749 @@
<?xml version="1.0"?>
<menu>
<header>
<listname>MAME</listname>
<lastlistupdate>03/10/2012</lastlistupdate>
<listversion>.145 Ongoing</listversion>
<exporterversion>HyperList XML Exporter Version 1.3 Copywrite (c) 2009-2011 William Strong</exporterversion>
</header>
<game name="alphamis" index="" image="">
<description>Alpha Mission</description>
<cloneof>aso</cloneof>
<crc />
<manufacturer>SNK</manufacturer>
<year>1985</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="altbeast" index="" image="">
<description>Altered Beast (set 8, 8751 317-0078)</description>
<cloneof />
<crc />
<manufacturer>Sega</manufacturer>
<year>1988</year>
<genre>Beat-'Em-Up</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="arkanoid" index="" image="">
<description>Arkanoid (World)</description>
<cloneof />
<crc />
<manufacturer>Taito Corporation Japan</manufacturer>
<year>1986</year>
<genre>Breakout</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="btoads" index="" image="">
<description>Battle Toads</description>
<cloneof />
<crc />
<manufacturer>Rare</manufacturer>
<year>1994</year>
<genre>Beat-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="bosco" index="" image="">
<description>Bosconian (new version)</description>
<cloneof />
<crc />
<manufacturer>Namco</manufacturer>
<year>1981</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="bublbobl" index="" image="">
<description>Bubble Bobble</description>
<cloneof />
<crc />
<manufacturer>Taito Corporation</manufacturer>
<year>1986</year>
<genre>Platform</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="btime" index="" image="">
<description>Burger Time (Data East set 1)</description>
<cloneof />
<crc />
<manufacturer>Data East Corporation</manufacturer>
<year>1982</year>
<genre>Platform</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="cabalus" index="" image="">
<description>Cabal (US set 1, Trackball version)</description>
<cloneof>cabal</cloneof>
<crc />
<manufacturer>TAD Corporation (Fabtek license)</manufacturer>
<year>1988</year>
<genre>Shooter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="dinou" index="" image="">
<description>Cadillacs and Dinosaurs (USA 930201)</description>
<cloneof>dino</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1993</year>
<genre>Beat-'Em-Up</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="centiped" index="" image="">
<description>Centipede (revision 3)</description>
<cloneof />
<crc />
<manufacturer>Atari</manufacturer>
<year>1980</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="darius" index="" image="">
<description>Darius (World)</description>
<cloneof />
<crc />
<manufacturer>Taito Corporation Japan</manufacturer>
<year>1986</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="digdug" index="" image="">
<description>Dig Dug (rev 2)</description>
<cloneof />
<crc />
<manufacturer>Namco</manufacturer>
<year>1982</year>
<genre>Maze</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="ddonpach" index="" image="">
<description>DoDonPachi (International, Master Ver. 97/02/05)</description>
<cloneof />
<crc />
<manufacturer>Cave (Atlus license)</manufacturer>
<year>1997</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="dkong" index="" image="">
<description>Donkey Kong (US set 1)</description>
<cloneof />
<crc />
<manufacturer>Nintendo of America</manufacturer>
<year>1981</year>
<genre>Platform</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="galaga88" index="" image="">
<description>Galaga '88</description>
<cloneof />
<crc />
<manufacturer>Namco</manufacturer>
<year>1987</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="galaxian" index="" image="">
<description>Galaxian (Namco set 1)</description>
<cloneof />
<crc />
<manufacturer>Namco</manufacturer>
<year>1979</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="gngt" index="" image="">
<description>Ghosts'n Goblins (US)</description>
<cloneof>gng</cloneof>
<crc />
<manufacturer>Capcom (Taito America license)</manufacturer>
<year>1985</year>
<genre>Platform</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="ghoulsu" index="" image="">
<description>Ghouls'n Ghosts (USA)</description>
<cloneof>ghouls</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1988</year>
<genre>Platform</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="gt2k" index="" image="">
<description>Golden Tee 2K (v1.00)</description>
<cloneof />
<crc />
<manufacturer>Incredible Technologies</manufacturer>
<year>2000</year>
<genre>Sports/Golf</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="gradius" index="" image="">
<description>Gradius (Japan, ROM version)</description>
<cloneof>nemesis</cloneof>
<crc />
<manufacturer>Konami</manufacturer>
<year>1985</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="gyruss" index="" image="">
<description>Gyruss (Konami)</description>
<cloneof />
<crc />
<manufacturer>Konami</manufacturer>
<year>1983</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="hsf2" index="" image="">
<description>Hyper Street Fighter 2: The Anniversary Edition (USA 040202)</description>
<cloneof />
<crc />
<manufacturer>Capcom</manufacturer>
<year>2004</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="joust" index="" image="">
<description>Joust (White/Green label)</description>
<cloneof />
<crc />
<manufacturer>Williams</manufacturer>
<year>1982</year>
<genre>Platform</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="jrpacman" index="" image="">
<description>Jr. Pac-Man</description>
<cloneof />
<crc />
<manufacturer>Bally Midway</manufacturer>
<year>1983</year>
<genre>Maze</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="kinst" index="" image="">
<description>Killer Instinct (v1.5d)</description>
<cloneof />
<crc />
<manufacturer>Rare</manufacturer>
<year>1994</year>
<genre>Fighter</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="kinst2" index="" image="">
<description>Killer Instinct 2 (v1.4)</description>
<cloneof />
<crc />
<manufacturer>Rare</manufacturer>
<year>1995</year>
<genre>Fighter</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="marble" index="" image="">
<description>Marble Madness (set 1)</description>
<cloneof />
<crc />
<manufacturer>Atari Games</manufacturer>
<year>1984</year>
<genre>Maze</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="mario" index="" image="">
<description>Mario Bros. (US, Revision F)</description>
<cloneof />
<crc />
<manufacturer>Nintendo of America</manufacturer>
<year>1983</year>
<genre>Platform</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="mshu" index="" image="">
<description>Marvel Super Heroes (USA 951024)</description>
<cloneof>msh</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1995</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="mshvsfu" index="" image="">
<description>Marvel Super Heroes Vs. Street Fighter (USA 970827)</description>
<cloneof>mshvsf</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1997</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="mvscu" index="" image="">
<description>Marvel Vs. Capcom: Clash of Super Heroes (USA 980123)</description>
<cloneof>mvsc</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1998</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="mslug" index="" image="">
<description>Metal Slug - Super Vehicle-001</description>
<cloneof />
<crc />
<manufacturer>Nazca</manufacturer>
<year>1996</year>
<genre>Platform</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="mslug2" index="" image="">
<description>Metal Slug 2 - Super Vehicle-001/II</description>
<cloneof />
<crc />
<manufacturer>SNK</manufacturer>
<year>1998</year>
<genre>Platform</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="mslug3" index="" image="">
<description>Metal Slug 3 (NGM-2560)</description>
<cloneof />
<crc />
<manufacturer>SNK</manufacturer>
<year>2000</year>
<genre>Platform</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="mslug4" index="" image="">
<description>Metal Slug 4 (NGM-2630)</description>
<cloneof />
<crc />
<manufacturer>Mega / Playmore</manufacturer>
<year>2002</year>
<genre>Platform</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="mslug5" index="" image="">
<description>Metal Slug 5 (NGM-2680)</description>
<cloneof />
<crc />
<manufacturer>SNK Playmore</manufacturer>
<year>2003</year>
<genre>Platform</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="mslugx" index="" image="">
<description>Metal Slug X - Super Vehicle-001</description>
<cloneof />
<crc />
<manufacturer>SNK</manufacturer>
<year>1999</year>
<genre>Platform</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="mwalku" index="" image="">
<description>Michael Jackson's Moonwalker (US, FD1094/8751 317-0158)</description>
<cloneof>mwalk</cloneof>
<crc />
<manufacturer>Sega</manufacturer>
<year>1990</year>
<genre>Maze</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="milliped" index="" image="">
<description>Millipede</description>
<cloneof />
<crc />
<manufacturer>Atari</manufacturer>
<year>1982</year>
<genre>Shoot-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="missile" index="" image="">
<description>Missile Command (rev 3)</description>
<cloneof />
<crc />
<manufacturer>Atari</manufacturer>
<year>1980</year>
<genre>Shooter</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="mk" index="" image="">
<description>Mortal Kombat (rev 5.0 T-Unit 03/19/93)</description>
<cloneof />
<crc />
<manufacturer>Midway</manufacturer>
<year>1992</year>
<genre>Fighter</genre>
<rating>AAMA - Red (Life Like Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="mk3" index="" image="">
<description>Mortal Kombat 3 (rev 2.1)</description>
<cloneof />
<crc />
<manufacturer>Midway</manufacturer>
<year>1994</year>
<genre>Fighter</genre>
<rating>AAMA - Red (Life Like Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="mk2" index="" image="">
<description>Mortal Kombat II (rev L3.1)</description>
<cloneof />
<crc />
<manufacturer>Midway</manufacturer>
<year>1993</year>
<genre>Fighter</genre>
<rating>AAMA - Red (Life Like Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="mrdrillr" index="" image="">
<description>Mr. Driller (Japan, DRI1/VER.A2)</description>
<cloneof />
<crc />
<manufacturer>Namco</manufacturer>
<year>1999</year>
<genre>Puzzle</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="mspacman" index="" image="">
<description>Ms. Pac-Man</description>
<cloneof />
<crc />
<manufacturer>Midway</manufacturer>
<year>1981</year>
<genre>Maze</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="nbajamte" index="" image="">
<description>NBA Jam TE (rev 4.0 03/23/94)</description>
<cloneof />
<crc />
<manufacturer>Midway</manufacturer>
<year>1994</year>
<genre>Sports/Basketball</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="neobombe" index="" image="">
<description>Neo Bomberman</description>
<cloneof />
<crc />
<manufacturer>Hudson</manufacturer>
<year>1997</year>
<genre>Maze</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="25pacman" index="" image="">
<description>Pac-Man - 25th Anniversary Edition (Rev 2.00)</description>
<cloneof />
<crc />
<manufacturer>Namco</manufacturer>
<year>2005</year>
<genre>Maze</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="puzzloopu" index="" image="">
<description>Puzz Loop (USA)</description>
<cloneof>puzzloop</cloneof>
<crc />
<manufacturer>Mitchell</manufacturer>
<year>1998</year>
<genre>Puzzle</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="pbobble" index="" image="">
<description>Puzzle Bobble (Japan, B-System)</description>
<cloneof />
<crc />
<manufacturer>Taito Corporation</manufacturer>
<year>1994</year>
<genre>Puzzle</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="rampage" index="" image="">
<description>Rampage (ver 3 8-27-86)</description>
<cloneof />
<crc />
<manufacturer>Bally Midway</manufacturer>
<year>1986</year>
<genre>Action</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="rampart" index="" image="">
<description>Rampart (Trackball)</description>
<cloneof />
<crc />
<manufacturer>Atari Games</manufacturer>
<year>1990</year>
<genre>Shooter</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="rygar" index="" image="">
<description>Rygar (US set 1)</description>
<cloneof />
<crc />
<manufacturer>Tecmo</manufacturer>
<year>1986</year>
<genre>Platform</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="shufshot" index="" image="">
<description>Shuffleshot (v1.40)</description>
<cloneof />
<crc />
<manufacturer>Strata/Incredible Technologies</manufacturer>
<year>1997</year>
<genre>Sports</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="simpbowl" index="" image="">
<description>Simpsons Bowling (GQ829 UAA)</description>
<cloneof />
<crc />
<manufacturer>Konami</manufacturer>
<year>2000</year>
<genre>Sports/Bowling</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="sfa3u" index="" image="">
<description>Street Fighter Alpha 3 (USA 980904)</description>
<cloneof>sfa3</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1998</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="sf2ceua" index="" image="">
<description>Street Fighter II': Champion Edition (USA 920313)</description>
<cloneof>sf2ce</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1992</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="sfiii3u" index="" image="">
<description>Street Fighter III 3rd Strike: Fight for the Future (USA 990608)</description>
<cloneof>sfiii3</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1999</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="strider" index="" image="">
<description>Strider (USA, B-Board 89624B-2)</description>
<cloneof />
<crc />
<manufacturer>Capcom</manufacturer>
<year>1989</year>
<genre>Platform</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="ssridersubc" index="" image="">
<description>Sunset Riders (2 Players ver UBC)</description>
<cloneof>ssriders</cloneof>
<crc />
<manufacturer>Konami</manufacturer>
<year>1991</year>
<genre>Platform</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="sgemf" index="" image="">
<description>Super Gem Fighter Mini Mix (USA 970904)</description>
<cloneof />
<crc />
<manufacturer>Capcom</manufacturer>
<year>1997</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="spf2t" index="" image="">
<description>Super Puzzle Fighter II Turbo (USA 960620)</description>
<cloneof />
<crc />
<manufacturer>Capcom</manufacturer>
<year>1996</year>
<genre>Puzzle</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="tapper" index="" image="">
<description>Tapper (Budweiser, set 1)</description>
<cloneof />
<crc />
<manufacturer>Bally Midway</manufacturer>
<year>1983</year>
<genre>Miscellaneous</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="tmnt2pj" index="" image="">
<description>Teenage Mutant Ninja Turtles (Japan 2 Players)</description>
<cloneof>tmnt</cloneof>
<crc />
<manufacturer>Konami</manufacturer>
<year>1990</year>
<genre>Beat-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="tmnt22pu" index="" image="">
<description>Teenage Mutant Ninja Turtles - Turtles in Time (2 Players ver UDA)</description>
<cloneof>tmnt2</cloneof>
<crc />
<manufacturer>Konami</manufacturer>
<year>1991</year>
<genre>Beat-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="tgm2" index="" image="">
<description>Tetris the Absolute The Grand Master 2</description>
<cloneof />
<crc />
<manufacturer>Arika</manufacturer>
<year>2000</year>
<genre>Puzzle</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="kof2000" index="" image="">
<description>The King of Fighters 2000 (NGM-2570) (NGH-2570)</description>
<cloneof />
<crc />
<manufacturer>SNK</manufacturer>
<year>2000</year>
<genre>Fighter</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="simpsons2p" index="" image="">
<description>The Simpsons (2 Players World, set 1)</description>
<cloneof>simpsons</cloneof>
<crc />
<manufacturer>Konami</manufacturer>
<year>1991</year>
<genre>Beat-'Em-Up</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="tron" index="" image="">
<description>Tron (8/9)</description>
<cloneof />
<crc />
<manufacturer>Bally Midway</manufacturer>
<year>1982</year>
<genre>Compilation</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="umk3" index="" image="">
<description>Ultimate Mortal Kombat 3 (rev 1.2)</description>
<cloneof />
<crc />
<manufacturer>Midway</manufacturer>
<year>1994</year>
<genre>Fighter</genre>
<rating>AAMA - Red (Animated Violence Strong)</rating>
<enabled>Yes</enabled>
</game>
<game name="wcbowldx" index="" image="">
<description>World Class Bowling Deluxe (v2.00)</description>
<cloneof />
<crc />
<manufacturer>Incredible Technologies</manufacturer>
<year>1999</year>
<genre>Sports/Bowling</genre>
<rating>AAMA - Green (Suitable For All Ages)</rating>
<enabled>Yes</enabled>
</game>
<game name="xmen2pe" index="" image="">
<description>X-Men (2 Players ver EAA)</description>
<cloneof>xmen</cloneof>
<crc />
<manufacturer>Konami</manufacturer>
<year>1992</year>
<genre>Beat-'Em-Up</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="xmvsfu" index="" image="">
<description>X-Men Vs. Street Fighter (USA 961023)</description>
<cloneof>xmvsf</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1996</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
<game name="xmcotau" index="" image="">
<description>X-Men: Children of the Atom (USA 950105)</description>
<cloneof>xmcota</cloneof>
<crc />
<manufacturer>Capcom</manufacturer>
<year>1994</year>
<genre>Fighter</genre>
<rating>AAMA - Yellow (Animated Violence Mild)</rating>
<enabled>Yes</enabled>
</game>
</menu>

View File

@ -0,0 +1,13 @@
# override the default layout with something else if desired
#layout = Default
launcher = MAME
list.path = ../ROMs/MAME
list.extensions = zip
media.video = ../Media/Arcade/Videos
media.title = ../Media/Arcade/Titles
media.snap = ../Media/Arcade/Snaps
media.box = ../Media/Arcade/Boxes
media.cart = ../Media/Arcade/Carts

View File

@ -0,0 +1,7 @@
<menu>
<!-- This is the main menu. Mark which collections you would like to make visible -->
<item collection="Nintendo Entertainment System"/>
<item collection="NES and Arcade"/>
<item collection="Arcade"/>
<item collection="Main"/>
</menu>

View File

@ -0,0 +1,9 @@
# override the default layout with something else if desired
# layout = SomeCustomBuiltTheme
media.video = ../Media/Systems/Videos
media.title = ../Media/Systems/Titles
media.box = ../Media/Systems/Boxes
media.cart = ../Media/Systems/Carts
media.snap = ../Media/Systems/Snaps

View File

@ -0,0 +1,5 @@
<menu>
<!-- This is the main menu. Mark which collections you would like to make visible -->
<item collection="Arcade" import="true"/>
<item collection="Nintendo Entertainment System" import="true"/>
</menu>

View File

@ -0,0 +1,9 @@
# override the default layout with something else if desired
# layout = SomeCustomBuiltTheme
media.video = ../Media/Systems/Videos
media.title = ../Media/Systems/Titles
media.box = ../Media/Systems/Boxes
media.cart = ../Media/Systems/Carts
media.snap = ../Media/Systems/Snaps

View File

@ -0,0 +1,13 @@
# override the default layout with something else if desired
#layout = SomeNewLayout
launcher = Nestopia
list.path = ../ROMs/Nintendo NES
list.extensions = nes
media.video = ../Media/Nintendo NES/Videos
media.title = ../Media/Nintendo NES/Titles
media.box = ../Media/Nintendo NES/Boxes
media.cart = ../Media/Nintendo NES/Carts
media.snap = ../Media/Nintendo NES/Snaps

View File

@ -0,0 +1,7 @@
previousItem = Up
nextItem = Down
pageUp = Left
pageDown = Right
select = Space
back = Escape
quit = Q

View File

@ -0,0 +1,2 @@
executable = D:\Emulators\fceux\fceux.exe
arguments = "%ITEM_FILEPATH%"

View File

@ -0,0 +1,6 @@
executable = ../HyperLaunch/HyperLaunch.exe
arguments = -s "%ITEM_COLLECTION_NAME%" -r "%ITEM_FILEPATH%" -p RetroFE -f "%RETROFE_EXEC_PATH%"
# For v3.0.1.1 compliant version, comment out the above arguments
# and uncomment the following line:
#arguments = "%ITEM_COLLECTION_NAME%" "%ITEM_NAME%"

View File

@ -0,0 +1,2 @@
executable = D:/Emulators/MAME/mamepp.exe
arguments = "%ITEM_NAME%"

View File

@ -0,0 +1,2 @@
executable = D:\Emulators\nestopia\nestopia.exe
arguments = "%ITEM_FILEPATH%"

Binary file not shown.

View File

@ -0,0 +1,128 @@
<!-- todo: add collection name text tag, metadata tags -->
<!-- todo: collection name text tag will load image, or text if image does not exist -->
<layout width="1920" height="1080" font="Age.otf" fontColor="ecf0f1">
<sound type="load" src="load.wav" />
<sound type="unload" src="unload.wav" />
<sound type="highlight" src="highlight.wav" />
<sound type="select" src="select.wav" />
<menu imageType="title" algorithm="easeincircular" x="center" y="center" xOrigin="center" yOrigin="center" speed="0.05" acceleration="0.05" height="25">
<!-- todo: the menu does not support the standard onEnter onExit, onHighlightEnter onHighlightExit tags like the rest of the system does. -->
<item xOffset="-500" yOffset="0" layer="1" fontSize="5" height="0" transparency="0" />
<item xOffset="-650" yOffset="200" layer="2" fontSize="7" height="30" transparency="0.1"/>
<item xOffset="-700" yOffset="300" layer="3" fontSize="10" height="60" transparency="0.25"/>
<item xOffset="-500" yOffset="350" layer="4" fontSize="20" height="100" transparency="0.5"/>
<item xOffset="0" yOffset="375" layer="5" fontSize="40" height="200" transparency="1" selected="true" />
<item xOffset="500" yOffset="350" layer="4" fontSize="20" height="100" transparency="0.5"/>
<item xOffset="700" yOffset="300" layer="3" fontSize="10" height="60" transparency="0.25"/>
<item xOffset="650" yOffset="200" layer="2" fontSize="7" height="30" transparency="0.1"/>
<item xOffset="500" yOffset="1" layer="1" fontSize="5" height="0" transparency="0"/>
</menu>
<image x="center" y="center" height="stretch" width="stretch" xOrigin="center" yOrigin="center" src="background.png" layer="0" transparency="0.5"/>
<image x="30" y="20" height="80" src="logo.png" layer="1" transparency="0.3">
<onEnter>
<set duration=".5">
<animate type="y" from="top" to="20" algorithm="easeinquadratic"/>
<animate type="yOrigin" from="bottom" to="top" algorithm="easeincircular"/>
</set>
</onEnter>
<onExit>
<set duration=".25">
<animate type="y" from="20" to="top" algorithm="easeinquadratic"/>
<animate type="yOrigin" from="top" to="bottom" algorithm="easeincircular"/>
</set>
</onExit>
</image>
<reloadableText type="manufacturer" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-10" fontSize="20" layer="0">
</reloadableText>
<reloadableText type="year" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-30" fontSize="20" layer="0">
</reloadableText>
<reloadableText type="title" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-50" fontSize="20" layer="0">
</reloadableText>
<!--
<reloadableText type="numberPlayers" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-70" fontSize="20" layer="0">
</reloadableText>
<reloadableText type="numberButtons" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-90" fontSize="20" layer="0">
</reloadableText>
-->
<reloadableImage type="cart" x="left" xOffset="-1" y="center" yOffset="-100" height="460" xOrigin="right" yOrigin="center" fontSize="20" layer="1">
<onHighlightEnter>
<set duration=".2">
<animate type="x" from="left" to="center" algorithm="easeinquadratic"/>
<animate type="xOffset" from="-1" to="-325" algorithm="easeinquadratic"/>
<animate type="angle" from="-90" to="0" algorithm="easeinquadratic"/>
</set>
</onHighlightEnter>
<onHighlightExit>
<set duration=".1">
<animate type="x" from="center" to="left" algorithm="easeoutquintic"/>
<animate type="xOffset" from="-325" to="-1" algorithm="easeoutquintic"/>
<animate type="angle" from="0" to="-90" algorithm="easeinquadratic"/>
</set>
</onHighlightExit>
</reloadableImage>
<reloadableImage type="box" x="right" xOffset="1" y="center" yOffset="-100" height="460" xOrigin="left" yOrigin="center" fontSize="20" layer="1">
<onHighlightEnter>
<set duration=".2">
<animate type="x" from="right" to="center" algorithm="easeinquadratic"/>
<animate type="xOffset" from="1" to="325" algorithm="easeinquadratic"/>
<animate type="angle" from="90" to="0" algorithm="easeinquadratic"/>
</set>
</onHighlightEnter>
<onHighlightExit>
<set duration=".1">
<animate type="x" from="center" to="right" algorithm="easeoutquintic"/>
<animate type="xOffset" from="325" to="1" algorithm="easeoutquintic"/>
<animate type="angle" from="0" to="90" algorithm="easeinquadratic"/>
</set>
</onHighlightExit>
</reloadableImage>
<reloadableVideo imageType="snap" x="center" xOrigin="center" yOrigin="top" fontSize="20" layer="0" height="600" width="800">
<onHighlightEnter>
<set duration=".2">
<animate type="y" from="bottom" to="100" algorithm="easeinoutquadratic"/>
<animate type="width" from="0" to="400" algorithm="easeoutquadratic"/>
<animate type="transparency" from="0" to="0.5" algorithm="easeinquadratic"/>
</set>
<set duration=".2">
<animate type="y" from="100" to="130" algorithm="easeinoutquadratic"/>
<animate type="width" from="400" to="800" algorithm="easeoutquadratic"/>
<animate type="transparency" from=".5" to="0.75" algorithm="easeinquadratic"/>
</set>
</onHighlightEnter>
<onHighlightExit>
<set duration=".2">
<animate type="y" to="100" from="130" algorithm="easeinoutquadratic"/>
<animate type="width" to="400" from="800" algorithm="easeoutquadratic"/>
<animate type="transparency" from=".75" to="0.5" algorithm="easeinquadratic"/>
</set>
<set duration=".2">
<animate type="y" to="bottom" from="100" algorithm="easeinoutquadratic"/>
<animate type="width" to="0" from="400" algorithm="easeoutquadratic"/>
<animate type="transparency" to="0.5" from="0" algorithm="easeinquadratic"/>
</set>
</onHighlightExit>
</reloadableVideo>
<text value="RetroFE Beta - For test purposes only" fontSize="20" x="right" y="bottom" xOrigin="right" yOrigin="bottom" xOffset="-10" yOffset="-10" />
</layout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

View File

@ -0,0 +1,90 @@
<!-- todo: add collection name text tag, metadata tags -->
<!-- todo: collection name text tag will load image, or text if image does not exist -->
<layout width="1024" height="768" font="Age.otf" fontColor="ecf0f1">
<sound type="load" src="load.wav" />
<sound type="unload" src="unload.wav" />
<sound type="highlight" src="highlight.wav" />
<sound type="select" src="select.wav" />
<menu imageType="title" algorithm="easeincircular" x="center" y="center" xOrigin="center" yOrigin="center" speed="0.05" acceleration="0.05" height="25">
<!-- todo: the menu does not support the standard onEnter onExit, onHighlightEnter onHighlightExit tags like the rest of the system does. -->
<item xOffset="-100" yOffset="-120" layer="1" fontSize="5" height="15" transparency="0" />
<item xOffset="-250" yOffset="-80" layer="2" fontSize="7" height="20" transparency="0.1"/>
<item xOffset="-400" yOffset="0" layer="3" fontSize="10" height="30" transparency="0.25"/>
<item xOffset="-300" yOffset="133" layer="4" fontSize="20" height="60" transparency="0.5"/>
<item xOffset="0" yOffset="175" layer="5" fontSize="40" height="150" transparency="1" selected="true" />
<item xOffset="300" yOffset="133" layer="4" fontSize="20" height="60" transparency="0.5"/>
<item xOffset="400" yOffset="0" layer="3" fontSize="10" height="30" transparency="0.25"/>
<item xOffset="250" yOffset="-80" layer="2" fontSize="7" height="15" transparency="0.1"/>
<item xOffset="100" yOffset="-120" layer="1" fontSize="5" height="0" transparency="0"/>
</menu>
<image x="center" y="center" height="stretch" width="stretch" xOrigin="center" yOrigin="center" src="background.png" layer="0" transparency="0.5"/>
<image x="30" y="20" height="50" src="logo.png" layer="1" transparency="0.3">
<onEnter>
<set duration=".5">
<animate type="y" from="top" to="20" algorithm="easeinquadratic"/>
<animate type="yOrigin" from="bottom" to="top" algorithm="easeincircular"/>
</set>
</onEnter>
<onExit>
<set duration=".25">
<animate type="y" from="20" to="top" algorithm="easeinquadratic"/>
<animate type="yOrigin" from="top" to="bottom" algorithm="easeincircular"/>
</set>
</onExit>
</image>
<reloadableText type="manufacturer" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-10" fontSize="20" layer="0">
</reloadableText>
<reloadableText type="year" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-30" fontSize="20" layer="0">
</reloadableText>
<reloadableText type="title" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-50" fontSize="20" layer="0">
</reloadableText>
<!--
<reloadableText type="numberPlayers" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-70" fontSize="20" layer="0">
</reloadableText>
<reloadableText type="numberButtons" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-90" fontSize="20" layer="0">
</reloadableText>
-->
<reloadableVideo imageType="snap" x="center" xOrigin="center" yOrigin="top" fontSize="20" height="240" layer="0">
<onHighlightEnter>
<set duration=".2">
<animate type="y" from="bottom" to="100" algorithm="easeinoutquadratic"/>
<animate type="width" from="0" to="200" algorithm="easeoutquadratic"/>
<animate type="transparency" from="0" to="0.5" algorithm="easeinquadratic"/>
</set>
<set duration=".2">
<animate type="y" from="100" to="130" algorithm="easeinoutquadratic"/>
<animate type="width" from="200" to="320" algorithm="easeoutquadratic"/>
<animate type="transparency" from=".5" to="0.75" algorithm="easeinquadratic"/>
</set>
</onHighlightEnter>
<onHighlightExit>
<set duration=".2">
<animate type="y" to="100" from="130" algorithm="easeinoutquadratic"/>
<animate type="width" to="200" from="320" algorithm="easeoutquadratic"/>
<animate type="transparency" from=".75" to="0.5" algorithm="easeinquadratic"/>
</set>
<set duration=".2">
<animate type="y" to="bottom" from="100" algorithm="easeinoutquadratic"/>
<animate type="width" to="0" from="200" algorithm="easeoutquadratic"/>
<animate type="transparency" to="0.5" from="0" algorithm="easeinquadratic"/>
</set>
</onHighlightExit>
</reloadableVideo>
<text value="RetroFE Beta - For test purposes only" fontSize="20" x="right" y="bottom" xOrigin="right" yOrigin="bottom" xOffset="-10" yOffset="-10" />
</layout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

View File

@ -0,0 +1,49 @@
##############################################################################
#
# For support, visit www.retrofe.com
# or visit irc.foreverchat.net (channel #retrofe)
#
# For Documentation, visit www.retrofe.com/documentation
#
##############################################################################
#######################################
# Display
#######################################
fullscreen = no
horizontal = stretch # or enter in the screen pixel width (i.e 1024)
vertical = stretch # or enter in the screen pixel width (i.e 768)
layout = Default 16x9
hideMouse = yes
showParenthesis = yes
showSquareBrackets = yes
# If you would like RetroFE first load a different collection other than the
# main menu, uncomment the line below and replace it with your collection name.
# firstCollection = Arcade
#######################################
# Video playback settings
#######################################
# set to "no" for very old/slow systems
videoEnable = yes
# Number of times to loop video playback (enter 0 to continuously loop)
videoLoop = 0
#######################################
# General
#######################################
# exit the frontend when the back button is pressed on the first page
exitOnFirstPageBack = yes
# enter 0 attract mode, otherwise enter the number of seconds to wait before enabling attract mode
attractModeTime = 45
#######################################
# Debugging
#######################################
# do not set to "yes" unless you want your hard drive to quickly fill up
debug.logfps = no

View File

@ -0,0 +1,4 @@
This program requires Ubuntu 14.04 and requires the following packages to be installed:
sudo apt-get install zlib1g libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 libsdl2-ttf-2.0 \
libgstreamer1.0 libgstreamer-plugins-base1.0 libgstreamer-plugins-good1.0 libglib2.0

Binary file not shown.

34
Build Instructions.txt Normal file
View File

@ -0,0 +1,34 @@
Windows Setup
===============================
Install Python 2.7
Install sphinx with python
Install visual studio 2012
Install cmake
Install git
Install 7zip
Install gstreamer and gstreamer-devel (x86, not 64 bit!) from http://gstreamer.freedesktop/org/data/pkg/windows/1.4.0
To build:
1. Run "Source/SetupEnvironment.bat" to setup necessary variables and paths to compile in visual studio
2. Generate your visual studio solution files with running:
cmake Source -BBuild -DGSTREAMER_ROOT=c:/gstreamer/1.0/x86 -DVERSION_MAJOR=0 -DVERSION_MINOR=0 -DVERSION_BUILD=0
3. Compile your environment:
cd Build
msbuild RetroFE.sln
Runnable environment is stored in Build/Artifacts/RetroFE
Linux Setup
===============================
Install ubuntu or xubuntu 14.04
Run the following command
sudo apt-get install git g++ cmake zlib1g-dev libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 libsdl2-ttf-2.0 \
libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libsdl2-ttf-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
libgstreamer-plugins-good1.0-dev zlib1g-dev libglib2.0-0 libglib2.0-dev sqlite3
To Build:
cmake Source -BBuild -DVERSION_MAJOR=0 -DVERSION_MINOR=0 -DVERSION_BUILD=0
cd Build
make
Runnable environment is stored in Build/Artifacts/RetroFE

49
CMake/FindGStreamer.cmake Normal file
View File

@ -0,0 +1,49 @@
FILE(TO_CMAKE_PATH "$ENV{GSTREAMER_ROOT}" TRY1_DIR)
FILE(TO_CMAKE_PATH "${GSTREAMER_ROOT}" TRY2_DIR)
FILE(GLOB GSTREAMER_ROOT ${TRY1_DIR} ${TRY2_DIR})
FIND_PATH(GSTREAMER_gst_INCLUDE_DIR gst/gst.h
PATHS ${GSTREAMER_ROOT}/include ${GSTREAMER_ROOT}/include/gstreamer-1.0 /usr/local/include/gstreamer-1.0 /usr/include/gstreamer-1.0
ENV INCLUDE DOC "Directory containing gst/gst.h include file")
FIND_PATH(GSTREAMER_gstconfig_INCLUDE_DIR gst/gstconfig.h
PATHS ${GSTREAMER_ROOT}/include ${GSTREAMER_ROOT}/lib/include ${GSTREAMER_ROOT}/include/gstreamer-1.0 /usr/local/include/gstreamer-1.0 /usr/include/gstreamer-1.0 /usr/local/lib/include/gstreamer-1.0 /usr/lib/include/gstreamer-1.0
ENV INCLUDE DOC "Directory containing gst/gstconfig.h include file")
FIND_LIBRARY(GSTREAMER_gstaudio_LIBRARY NAMES gstaudio-1.0 libgstaudio-1.0 gstaudio
PATHS ${GSTREAMER_ROOT}/bin ${GSTREAMER_ROOT}/win32/bin ${GSTREAMER_ROOT}/bin/bin C:/gstreamer/bin ${GSTREAMER_ROOT}/lib ${GSTREAMER_ROOT}/win32/lib /usr/local/lib /usr/lib
ENV LIB
DOC "gstaudio library to link with"
NO_SYSTEM_ENVIRONMENT_PATH)
FIND_LIBRARY(GSTREAMER_gstreamer_LIBRARY NAMES gstreamer-1.0 libgstreamer-1.0 gstreamer
PATHS ${GSTREAMER_ROOT}/bin ${GSTREAMER_ROOT}/win32/bin ${GSTREAMER_ROOT}/bin/bin C:/gstreamer/bin ${GSTREAMER_ROOT}/lib ${GSTREAMER_ROOT}/win32/lib /usr/local/lib /usr/lib
ENV LIB
DOC "gstreamer library to link with"
NO_SYSTEM_ENVIRONMENT_PATH)
FIND_LIBRARY(GSTREAMER_gstbase_LIBRARY NAMES gstbase-1.0 libgstbase-1.0 gstbase
PATHS ${GSTREAMER_ROOT}/bin ${GSTREAMER_ROOT}/win32/bin ${GSTREAMER_ROOT}/bin/bin C:/gstreamer/bin ${GSTREAMER_ROOT}/lib ${GSTREAMER_ROOT}/win32/lib /usr/local/lib /usr/lib
ENV LIB
DOC "gstbase library to link with"
NO_SYSTEM_ENVIRONMENT_PATH)
FIND_LIBRARY(GSTREAMER_gstvideo_LIBRARY NAMES gstvideo-1.0 libgstvideo-1.0 gstvideo
PATHS ${GSTREAMER_ROOT}/bin ${GSTREAMER_ROOT}/win32/bin ${GSTREAMER_ROOT}/bin/bin C:/gstreamer/bin ${GSTREAMER_ROOT}/lib ${GSTREAMER_ROOT}/win32/lib /usr/local/lib /usr/lib
ENV LIB
DOC "gstvideo library to link with"
NO_SYSTEM_ENVIRONMENT_PATH)
#IF (GSTREAMER_gst_INCLUDE_DIR AND GSTREAMER_gstconfig_INCLUDE_DIR AND
# GSTREAMER_gstaudio_LIBRARY AND GSTREAMER_gstbase_LIBRARY AND
# GSTREAMER_gstreamer_LIBRARY AND GSTREAMER_gstvideo_LIBRARY)
SET(GSTREAMER_INCLUDE_DIRS ${GSTREAMER_gst_INCLUDE_DIR} ${GSTREAMER_gstconfig_INCLUDE_DIR})
list(REMOVE_DUPLICATES GSTREAMER_INCLUDE_DIRS)
SET(GSTREAMER_LIBRARIES ${GSTREAMER_gstaudio_LIBRARY} ${GSTREAMER_gstbase_LIBRARY}
${GSTREAMER_gstreamer_LIBRARY} ${GSTREAMER_gstvideo_LIBRARY})
list(REMOVE_DUPLICATES GSTREAMER_LIBRARIES)
SET(GSTREAMER_FOUND TRUE)
#ENDIF (GSTREAMER_gst_INCLUDE_DIR AND GSTREAMER_gstconfig_INCLUDE_DIR AND
# GSTREAMER_gstaudio_LIBRARY AND GSTREAMER_gstbase_LIBRARY AND
# GSTREAMER_gstreamer_LIBRARY AND GSTREAMER_gstvideo_LIBRARY)

43
CMake/FindGlib2.cmake Normal file
View File

@ -0,0 +1,43 @@
FILE(TO_CMAKE_PATH "$ENV{GLIB2_ROOT}" TRY1_DIR)
FILE(TO_CMAKE_PATH "${GLIB2_ROOT}" TRY2_DIR)
FILE(GLOB GLIB2_ROOT ${TRY1_DIR} ${TRY2_DIR})
FIND_PATH(GLIB_glib_2_INCLUDE_DIR glib.h
PATHS ${GLIB2_ROOT}/include ${GLIB2_ROOT}/include/glib-2.0 /usr/local/include/glib-2.0 /usr/include/glib-2.0 /opt/local/include/glib-2.0
ENV INCLUDE DOC "Directory containing glib.h include file")
FIND_PATH(GLIB_glibconfig_2_INCLUDE_DIR glibconfig.h
PATHS ${GLIB2_ROOT}/include ${GLIB2_ROOT}/include/glib-2.0 ${GLIB2_ROOT}/lib/include ${GLIB2_ROOT}/lib/glib-2.0/include /usr/local/include/glib-2.0 /usr/include/glib-2.0 /usr/lib/glib-2.0/include /usr/local/lib/glib-2.0/include /opt/local/lib/glib-2.0/include
ENV INCLUDE DOC "Directory containing glibconfig.h include file")
FIND_LIBRARY(GLIB_glib_2_LIBRARY NAMES glib-2.0
PATHS ${GLIB2_ROOT}/bin ${GLIB2_ROOT}/win32/bin ${GLIB2_ROOT}/lib ${GLIB2_ROOT}/win32/lib /usr/local/lib /usr/lib /opt/local/lib
ENV LIB
DOC "glib library to link with"
NO_SYSTEM_ENVIRONMENT_PATH)
FIND_LIBRARY(GLIB_gmodule_2_LIBRARY NAMES gmodule-2.0
PATHS ${GLIB2_ROOT}/bin ${GLIB2_ROOT}/win32/bin ${GLIB2_ROOT}/lib ${GLIB2_ROOT}/win32/lib /usr/local/lib /usr/lib /opt/local/lib
ENV LIB
DOC "gmodule library to link with"
NO_SYSTEM_ENVIRONMENT_PATH)
FIND_LIBRARY(GLIB_gobject_2_LIBRARY NAMES gobject-2.0
PATHS ${GLIB2_ROOT}/bin ${GLIB2_ROOT}/win32/bin ${GLIB2_ROOT}/lib ${GLIB2_ROOT}/win32/lib /usr/local/lib /usr/lib /opt/local/lib
ENV LIB
DOC "gobject library to link with"
NO_SYSTEM_ENVIRONMENT_PATH)
FIND_LIBRARY(GLIB_gthread_2_LIBRARY NAMES gthread-2.0
PATHS ${GLIB2_ROOT}/bin ${GLIB2_ROOT}/win32/bin ${GLIB2_ROOT}/lib ${GLIB2_ROOT}/win32/lib /usr/local/lib /usr/lib /opt/local/lib
ENV LIB
DOC "gthread library to link with"
NO_SYSTEM_ENVIRONMENT_PATH)
#IF (GLIB_glib_2_INCLUDE_DIR AND GLIB_glibconfig_2_INCLUDE_DIR AND GLIB_glib_2_LIBRARY AND GLIB_gmodule_2_LIBRARY AND GLIB_gobject_2_LIBRARY AND GLIB_gthread_2_LIBRARY)
SET(GLIB2_INCLUDE_DIRS ${GLIB_glib_2_INCLUDE_DIR} ${GLIB_glib_2_INCLUDE_DIR}/glib-2.0 ${GLIB_glibconfig_2_INCLUDE_DIR})
list(REMOVE_DUPLICATES GLIB2_INCLUDE_DIRS)
SET(GLIB2_LIBRARIES ${GLIB_glib_2_LIBRARY} ${GLIB_gmodule_2_LIBRARY} ${GLIB_gobject_2_LIBRARY} ${GLIB_gthread_2_LIBRARY})
list(REMOVE_DUPLICATES GLIB2_LIBRARIES)
SET(GLIB2_FOUND TRUE)
#ENDIF (GLIB_glib_2_INCLUDE_DIR AND GLIB_glibconfig_2_INCLUDE_DIR AND GLIB_glib_2_LIBRARY AND GLIB_gmodule_2_LIBRARY AND GLIB_gobject_2_LIBRARY AND GLIB_gthread_2_LIBRARY)

87
CMake/FindSDL2.cmake Normal file
View File

@ -0,0 +1,87 @@
# - Find SDL2 library and headers
#
# Find module for SDL 2.0 (http://www.libsdl.org/).
# It defines the following variables:
# SDL2_INCLUDE_DIRS - The location of the headers, e.g., SDL.h.
# SDL2_LIBRARIES - The libraries to link against to use SDL2.
# SDL2_FOUND - If false, do not try to use SDL2.
# SDL2_VERSION_STRING - Human-readable string containing the version of SDL2.
#
# This module responds to the the flag:
# SDL2_BUILDING_LIBRARY
# If this is defined, then no SDL2_main will be linked in because
# only applications need main().
# Otherwise, it is assumed you are building an application and this
# module will attempt to locate and set the the proper link flags
# as part of the returned SDL2_LIBRARIES variable.
#
# Also defined, but not for general use are:
# SDL2_INCLUDE_DIR - The directory that contains SDL.h.
# SDL2_LIBRARY - The location of the SDL2 library.
# SDL2MAIN_LIBRARY - The location of the SDL2main library.
#
#=============================================================================
# Copyright 2013 Benjamin Eikel
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_SDL2 QUIET sdl2)
find_path(SDL2_INCLUDE_DIR
NAMES SDL2/SDL.h
HINTS
${SDL2_ROOT}/include
)
find_library(SDL2_LIBRARY
NAMES SDL2
HINTS
${SDL2_ROOT}/lib
PATH_SUFFIXES x86
)
if(NOT SDL2_BUILDING_LIBRARY)
find_library(SDL2MAIN_LIBRARY
NAMES SDL2main
HINTS
${SDL2_ROOT}/lib
PATH_SUFFIXES x86
)
endif()
if(SDL2_INCLUDE_DIR AND EXISTS "${SDL2_INCLUDE_DIR}/SDL2/SDL_version.h")
file(STRINGS "${SDL2_INCLUDE_DIR}/SDL2/SDL_version.h" SDL2_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_INCLUDE_DIR}/SDL2/SDL_version.h" SDL2_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_INCLUDE_DIR}/SDL2/SDL_version.h" SDL2_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+$")
string(REGEX REPLACE "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MAJOR "${SDL2_VERSION_MAJOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MINOR "${SDL2_VERSION_MINOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_PATCH "${SDL2_VERSION_PATCH_LINE}")
set(SDL2_VERSION_STRING ${SDL2_VERSION_MAJOR}.${SDL2_VERSION_MINOR}.${SDL2_VERSION_PATCH})
unset(SDL2_VERSION_MAJOR_LINE)
unset(SDL2_VERSION_MINOR_LINE)
unset(SDL2_VERSION_PATCH_LINE)
unset(SDL2_VERSION_MAJOR)
unset(SDL2_VERSION_MINOR)
unset(SDL2_VERSION_PATCH)
endif()
set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR} ${SDL2_INCLUDE_DIR}/SDL2)
set(SDL2_LIBRARIES ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SDL2
REQUIRED_VARS SDL2_INCLUDE_DIR SDL2_LIBRARY
VERSION_VAR SDL2_VERSION_STRING)
mark_as_advanced(SDL2_INCLUDE_DIR SDL2_LIBRARY)

View File

@ -0,0 +1,70 @@
# - Find SDL2_image library and headers
#
# Find module for SDL_image 2.0 (http://www.libsdl.org/projects/SDL_image/).
# It defines the following variables:
# SDL2_IMAGE_INCLUDE_DIRS - The location of the headers, e.g., SDL_image.h.
# SDL2_IMAGE_LIBRARIES - The libraries to link against to use SDL2_image.
# SDL2_IMAGE_FOUND - If false, do not try to use SDL2_image.
# SDL2_IMAGE_VERSION_STRING
# Human-readable string containing the version of SDL2_image.
#
# Also defined, but not for general use are:
# SDL2_IMAGE_INCLUDE_DIR - The directory that contains SDL_image.h.
# SDL2_IMAGE_LIBRARY - The location of the SDL2_image library.
#
#=============================================================================
# Copyright 2013 Benjamin Eikel
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_SDL2_IMAGE QUIET SDL2_image)
find_path(SDL2_IMAGE_INCLUDE_DIR
NAMES SDL2/SDL_image.h
HINTS
${SDL2_IMAGE_ROOT}/include
)
find_library(SDL2_IMAGE_LIBRARY
NAMES SDL2_image
HINTS
${SDL2_IMAGE_ROOT}/lib
PATH_SUFFIXES x86
)
if(SDL2_IMAGE_INCLUDE_DIR AND EXISTS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2/SDL_image.h")
file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2/SDL_image.h" SDL2_IMAGE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2/SDL_image.h" SDL2_IMAGE_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2/SDL_image.h" SDL2_IMAGE_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+[0-9]+$")
string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MAJOR "${SDL2_IMAGE_VERSION_MAJOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MINOR "${SDL2_IMAGE_VERSION_MINOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_PATCH "${SDL2_IMAGE_VERSION_PATCH_LINE}")
set(SDL2_IMAGE_VERSION_STRING ${SDL2_IMAGE_VERSION_MAJOR}.${SDL2_IMAGE_VERSION_MINOR}.${SDL2_IMAGE_VERSION_PATCH})
unset(SDL2_IMAGE_VERSION_MAJOR_LINE)
unset(SDL2_IMAGE_VERSION_MINOR_LINE)
unset(SDL2_IMAGE_VERSION_PATCH_LINE)
unset(SDL2_IMAGE_VERSION_MAJOR)
unset(SDL2_IMAGE_VERSION_MINOR)
unset(SDL2_IMAGE_VERSION_PATCH)
endif()
set(SDL2_IMAGE_INCLUDE_DIRS ${SDL2_IMAGE_INCLUDE_DIR} ${SDL2_IMAGE_INCLUDE_DIR}/SDL2)
set(SDL2_IMAGE_LIBRARIES ${SDL2_IMAGE_LIBRARY})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SDL2_image
REQUIRED_VARS SDL2_IMAGE_INCLUDE_DIRS SDL2_IMAGE_LIBRARIES
VERSION_VAR SDL2_IMAGE_VERSION_STRING)
mark_as_advanced(SDL2_IMAGE_INCLUDE_DIR SDL2_IMAGE_LIBRARY)

View File

@ -0,0 +1,72 @@
# Downloaded from http://cmake.3232098.n2.nabble.com/Find-modules-for-SDL2-td7585211.html and adapted to SDL2_mixer
#
# - Find SDL2_mixer library and headers
#
# Find module for SDL_mixer 2.0 (http://www.libsdl.org/projects/SDL_mixer/).
# It defines the following variables:
# SDL2_MIXER_INCLUDE_DIRS - The location of the headers, e.g., SDL_mixer.h.
# SDL2_MIXER_LIBRARIES - The libraries to link against to use SDL2_mixer.
# SDL2_MIXER_FOUND - If false, do not try to use SDL2_mixer.
# SDL2_MIXER_VERSION_STRING
# Human-readable string containing the version of SDL2_mixer.
#
# Also defined, but not for general use are:
# SDL2_MIXER_INCLUDE_DIR - The directory that contains SDL_mixer.h.
# SDL2_MIXER_LIBRARY - The location of the SDL2_mixer library.
#
#=============================================================================
# Copyright 2013 Benjamin Eikel
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_SDL2_MIXER QUIET SDL2_mixer)
find_path(SDL2_MIXER_INCLUDE_DIR
NAMES SDL2/SDL_mixer.h
HINTS
${SDL2_MIXER_ROOT}/include
)
find_library(SDL2_MIXER_LIBRARY
NAMES SDL2_mixer
HINTS
${SDL2_MIXER_ROOT}/lib
PATH_SUFFIXES x86
)
if(SDL2_MIXER_INCLUDE_DIR AND EXISTS "${SDL2_MIXER_INCLUDE_DIR}/SDL2/SDL_mixer.h")
file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL2/SDL_mixer.h" SDL2_MIXER_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL2/SDL_mixer.h" SDL2_MIXER_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL2/SDL_mixer.h" SDL2_MIXER_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+[0-9]+$")
string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MAJOR "${SDL2_MIXER_VERSION_MAJOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MINOR "${SDL2_MIXER_VERSION_MINOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_PATCH "${SDL2_MIXER_VERSION_PATCH_LINE}")
set(SDL2_MIXER_VERSION_STRING ${SDL2_MIXER_VERSION_MAJOR}.${SDL2_MIXER_VERSION_MINOR}.${SDL2_MIXER_VERSION_PATCH})
unset(SDL2_MIXER_VERSION_MAJOR_LINE)
unset(SDL2_MIXER_VERSION_MINOR_LINE)
unset(SDL2_MIXER_VERSION_PATCH_LINE)
unset(SDL2_MIXER_VERSION_MAJOR)
unset(SDL2_MIXER_VERSION_MINOR)
unset(SDL2_MIXER_VERSION_PATCH)
endif()
set(SDL2_MIXER_INCLUDE_DIRS ${SDL2_MIXER_INCLUDE_DIR} ${SDL2_MIXER_INCLUDE_DIR}/SDL2)
set(SDL2_MIXER_LIBRARIES ${SDL2_MIXER_LIBRARY})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SDL2_mixer
REQUIRED_VARS SDL2_MIXER_INCLUDE_DIRS SDL2_MIXER_LIBRARIES
VERSION_VAR SDL2_MIXER_VERSION_STRING)
mark_as_advanced(SDL2_MIXER_INCLUDE_DIR SDL2_MIXER_LIBRARY)

73
CMake/FindSDL2_ttf.cmake Normal file
View File

@ -0,0 +1,73 @@
# Downloaded from http://cmake.3232098.n2.nabble.com/Find-modules-for-SDL2-td7585211.html and adapted to SDL2_ttf
#
# - Find SDL2_ttf library and headers
#
# Find module for SDL_ttf 2.0 (http://www.libsdl.org/projects/SDL_ttf/).
# It defines the following variables:
# SDL2_TTF_INCLUDE_DIRS - The location of the headers, e.g., SDL_ttf.h.
# SDL2_TTF_LIBRARIES - The libraries to link against to use SDL2_ttf.
# SDL2_TTF_FOUND - If false, do not try to use SDL2_ttf.
# SDL2_TTF_VERSION_STRING
# Human-readable string containing the version of SDL2_ttf.
#
# Also defined, but not for general use are:
# SDL2_TTF_INCLUDE_DIR - The directory that contains SDL_ttf.h.
# SDL2_TTF_LIBRARY - The location of the SDL2_ttf library.
#
#=============================================================================
# Copyright 2013 Benjamin Eikel
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_SDL2_TTF QUIET SDL2_ttf)
find_path(SDL2_TTF_INCLUDE_DIR
NAMES SDL2/SDL_ttf.h
HINTS
${SDL2_TTF_ROOT}
PATH_SUFFIXES include
)
find_library(SDL2_TTF_LIBRARY
NAMES SDL2_ttf
HINTS
${SDL2_TTF_ROOT}/lib
PATH_SUFFIXES x86
)
if(SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL2/SDL_ttf.h")
file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL2/SDL_ttf.h" SDL2_TTF_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL2/SDL_ttf.h" SDL2_TTF_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL2/SDL_ttf.h" SDL2_TTF_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+[0-9]+$")
string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MAJOR "${SDL2_TTF_VERSION_MAJOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MINOR "${SDL2_TTF_VERSION_MINOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_PATCH "${SDL2_TTF_VERSION_PATCH_LINE}")
set(SDL2_TTF_VERSION_STRING ${SDL2_TTF_VERSION_MAJOR}.${SDL2_TTF_VERSION_MINOR}.${SDL2_TTF_VERSION_PATCH})
unset(SDL2_TTF_VERSION_MAJOR_LINE)
unset(SDL2_TTF_VERSION_MINOR_LINE)
unset(SDL2_TTF_VERSION_PATCH_LINE)
unset(SDL2_TTF_VERSION_MAJOR)
unset(SDL2_TTF_VERSION_MINOR)
unset(SDL2_TTF_VERSION_PATCH)
endif()
set(SDL2_TTF_INCLUDE_DIRS ${SDL2_TTF_INCLUDE_DIR} ${SDL2_TTF_INCLUDE_DIR}/SDL2)
set(SDL2_TTF_LIBRARIES ${SDL2_TTF_LIBRARY})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SDL2_ttf
REQUIRED_VARS SDL2_TTF_INCLUDE_DIRS SDL2_TTF_LIBRARIES
VERSION_VAR SDL2_TTF_VERSION_STRING)
mark_as_advanced(SDL2_TTF_INCLUDE_DIR SDL2_TTF_LIBRARY)

8
LICENSE.txt Normal file
View File

@ -0,0 +1,8 @@
All information contained herein is, and remains
the property of Puddle Jump Creative. The intellectual and technical
concepts contained herein are proprietary to Puddle Jump Creative
may be covered by U.S. and Foreign Patents, patents in process,
and are protected by trade secret or copyright law.
Dissemination of this information or reproduction of this material
is strictly forbidden unless prior written permission is obtained
from Puddle Jump Creative.

View File

@ -0,0 +1 @@
"C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/vcvarsall.bat"

224
Source/CMakeLists.txt Normal file
View File

@ -0,0 +1,224 @@
cmake_minimum_required (VERSION 2.8)
project (RetroFE)
set(RETROFE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..)
set(RETROFE_THIRD_PARTY_DIR "${RETROFE_DIR}/ThirdParty")
list(APPEND CMAKE_MODULE_PATH "${RETROFE_DIR}/CMake")
##############################################################
# Setup some variables to help find external libraries
##############################################################
set(SQLITE3_ROOT "${RETROFE_THIRD_PARTY_DIR}/sqlite3")
set(RAPIDXML_ROOT "${RETROFE_THIRD_PARTY_DIR}/rapidxml-1.13")
if(WIN32)
set(CMAKE_PREFIX_PATH "${RETROFE_DIR}/ThirdParty/win32")
set(SDL2_ROOT "${RETROFE_THIRD_PARTY_DIR}/SDL2-2.0.3")
set(SDL2_IMAGE_ROOT "${RETROFE_THIRD_PARTY_DIR}/SDL2_image-2.0.0")
set(SDL2_MIXER_ROOT "${RETROFE_THIRD_PARTY_DIR}/SDL2_mixer-2.0.0")
set(SDL2_TTF_ROOT "${RETROFE_THIRD_PARTY_DIR}/SDL2_ttf-2.0.12")
set(ZLIB_ROOT "${RETROFE_THIRD_PARTY_DIR}/zlib128-dll")
set(GSTREAMER_ROOT "C:/gstreamer/1.0/x86" CACHE STRING "location of where your gstreamer include and lib folders reside")
set(GLIB2_ROOT "${GSTREAMER_ROOT}")
set(DIRENT_INCLUDE_DIR "${RETROFE_THIRD_PARTY_DIR}/dirent-1.20.1/include")
endif()
if(MSVC)
find_package(Glib2 REQUIRED)
find_package(GStreamer REQUIRED)
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
find_package(SDL2_mixer REQUIRED)
find_package(SDL2_ttf REQUIRED)
find_package(ZLIB REQUIRED)
else()
include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
pkg_search_module(SDL2_IMAGE REQUIRED SDL2_image)
pkg_search_module(SDL2_MIXER REQUIRED SDL2_mixer)
pkg_search_module(SDL2_TTF REQUIRED SDL2_ttf)
pkg_search_module(ZLIB REQUIRED zlib)
pkg_search_module(GSTREAMER REQUIRED gstreamer-1.0 gstbase-1.0)
pkg_search_module(Glib2 REQUIRED glib-2.0 gobject-2.0 gthread-2.0 gmodule-2.0)
find_package(Threads REQUIRED)
endif()
set(RETROFE_INCLUDE_DIRS
"${GLIB2_INCLUDE_DIRS}"
"${GSTREAMER_INCLUDE_DIRS}"
"${SDL2_INCLUDE_DIRS}"
"${SDL2_IMAGE_INCLUDE_DIRS}"
"${SDL2_MIXER_INCLUDE_DIRS}"
"${SDL2_TTF_INCLUDE_DIRS}"
"${ZLIB_INCLUDE_DIRS}"
"${SQLITE3_ROOT}"
"${RAPIDXML_ROOT}"
"${DIRENT_INCLUDE_DIR}"
)
set(RETROFE_LIBRARIES
${GLIB2_LIBRARIES}
${GSTREAMER_LIBRARIES}
${SDL2_LIBRARIES}
${SDL2_IMAGE_LIBRARIES}
${SDL2_MIXER_LIBRARIES}
${SDL2_TTF_LIBRARIES}
${ZLIB_LIBRARIES}
)
if(NOT MSVC)
LIST(APPEND RETROFE_LIBRARIES ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif()
set(RETROFE_HEADERS
"${RETROFE_DIR}/Source/Collection/CollectionInfo.h"
"${RETROFE_DIR}/Source/Collection/CollectionInfoBuilder.h"
"${RETROFE_DIR}/Source/Collection/Item.h"
"${RETROFE_DIR}/Source/Collection/MenuParser.h"
"${RETROFE_DIR}/Source/Control/UserInput.h"
"${RETROFE_DIR}/Source/Database/CollectionDatabase.h"
"${RETROFE_DIR}/Source/Database/Configuration.h"
"${RETROFE_DIR}/Source/Database/DB.h"
"${RETROFE_DIR}/Source/Database/MamelistMetadata.h"
"${RETROFE_DIR}/Source/Execute/Launcher.h"
"${RETROFE_DIR}/Source/Graphics/Animate/Tween.h"
"${RETROFE_DIR}/Source/Graphics/Animate/TweenTypes.h"
"${RETROFE_DIR}/Source/Graphics/ComponentItemBinding.h"
"${RETROFE_DIR}/Source/Graphics/Component/Component.h"
"${RETROFE_DIR}/Source/Graphics/Font.h"
"${RETROFE_DIR}/Source/Graphics/FontCache.h"
"${RETROFE_DIR}/Source/Graphics/Component/Image.h"
"${RETROFE_DIR}/Source/Graphics/Component/Text.h"
"${RETROFE_DIR}/Source/Graphics/PageBuilder.h"
"${RETROFE_DIR}/Source/Graphics/MenuNotifierInterface.h"
"${RETROFE_DIR}/Source/Graphics/Page.h"
"${RETROFE_DIR}/Source/Graphics/Component/ImageBuilder.h"
"${RETROFE_DIR}/Source/Graphics/Component/ReloadableMedia.h"
"${RETROFE_DIR}/Source/Graphics/Component/ReloadableText.h"
"${RETROFE_DIR}/Source/Graphics/Component/ScrollingList.h"
"${RETROFE_DIR}/Source/Graphics/Component/VideoComponent.h"
"${RETROFE_DIR}/Source/Graphics/Component/VideoBuilder.h"
"${RETROFE_DIR}/Source/Sound/Sound.h"
"${RETROFE_DIR}/Source/Utility/Log.h"
"${RETROFE_DIR}/Source/Utility/Utils.h"
"${RETROFE_DIR}/Source/Video/IVideo.h"
"${RETROFE_DIR}/Source/Video/GStreamerVideo.h"
"${RETROFE_DIR}/Source/Video/VideoFactory.h"
"${RETROFE_DIR}/Source/Graphics/ComponentItemBindingBuilder.h"
"${RETROFE_DIR}/Source/Graphics/ViewInfo.h"
"${RETROFE_DIR}/Source/RetroFE.h"
"${RETROFE_DIR}/Source/SDL.h"
"${RETROFE_DIR}/Source/Version.h"
)
set(RETROFE_SOURCES
"${RETROFE_DIR}/Source/Collection/CollectionInfo.cpp"
"${RETROFE_DIR}/Source/Collection/CollectionInfoBuilder.cpp"
"${RETROFE_DIR}/Source/Collection/Item.cpp"
"${RETROFE_DIR}/Source/Collection/MenuParser.cpp"
"${RETROFE_DIR}/Source/Control/UserInput.cpp"
"${RETROFE_DIR}/Source/Database/CollectionDatabase.cpp"
"${RETROFE_DIR}/Source/Database/Configuration.cpp"
"${RETROFE_DIR}/Source/Database/DB.cpp"
"${RETROFE_DIR}/Source/Database/MamelistMetadata.cpp"
"${RETROFE_DIR}/Source/Execute/Launcher.cpp"
"${RETROFE_DIR}/Source/Graphics/Animate/Tween.cpp"
"${RETROFE_DIR}/Source/Graphics/Font.cpp"
"${RETROFE_DIR}/Source/Graphics/FontCache.cpp"
"${RETROFE_DIR}/Source/Graphics/PageBuilder.cpp"
"${RETROFE_DIR}/Source/Graphics/Page.cpp"
"${RETROFE_DIR}/Source/Graphics/ViewInfo.cpp"
"${RETROFE_DIR}/Source/Graphics/ComponentItemBindingBuilder.cpp"
"${RETROFE_DIR}/Source/Graphics/ComponentItemBinding.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/Component.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/Image.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/ImageBuilder.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/Text.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/ReloadableMedia.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/ReloadableText.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/ScrollingList.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/VideoBuilder.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/VideoComponent.cpp"
"${RETROFE_DIR}/Source/Sound/Sound.cpp"
"${RETROFE_DIR}/Source/Utility/Log.cpp"
"${RETROFE_DIR}/Source/Utility/Utils.cpp"
"${RETROFE_DIR}/Source/Video/GStreamerVideo.cpp"
"${RETROFE_DIR}/Source/Video/VideoFactory.cpp"
"${RETROFE_DIR}/Source/Main.cpp"
"${RETROFE_DIR}/Source/RetroFE.cpp"
"${RETROFE_DIR}/Source/SDL.cpp"
"${RETROFE_DIR}/Source/Version.cpp"
"${SQLITE3_ROOT}/sqlite3.c"
)
set(EXECUTABLE_OUTPUT_PATH "${RETROFE_DIR}/Build" CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH "${RETROFE_DIR}/Build" CACHE PATH "Build directory" FORCE)
include_directories(${RETROFE_INCLUDE_DIRS})
add_executable(RetroFE ${RETROFE_SOURCES} ${RETROFE_HEADERS})
target_link_libraries(RetroFE ${RETROFE_LIBRARIES})
set_target_properties(RetroFE PROPERTIES LINKER_LANGUAGE CXX)
add_definitions(-DRETROFE_VERSION_MAJOR=${VERSION_MAJOR})
add_definitions(-DRETROFE_VERSION_MINOR=${VERSION_MINOR})
add_definitions(-DRETROFE_VERSION_BUILD=${VERSION_BUILD})
if(MSVC)
set(CMAKE_DEBUG_POSTFIX "d")
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /WX")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP /WX")
set_target_properties(RetroFE PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS")
endif()
set(RETROFE_OUTPUT_PATH "../Build/Artifacts/RetroFE")
ADD_CUSTOM_COMMAND(TARGET RetroFE POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "../Build/Artifacts/RetroFE" )
ADD_CUSTOM_COMMAND(TARGET RetroFE POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "../Assets/Environment/Common" "${RETROFE_OUTPUT_PATH}" )
if(WIN32)
set(RETROFE_OUTPUT_CORE_PATH "${RETROFE_OUTPUT_PATH}/Core")
file(GLOB CORE_FILES
"${GSTREAMER_ROOT}/lib/*.dll"
"${GSTREAMER_ROOT}/lib/gstreamer-1.0/*.dll"
"${GSTREAMER_ROOT}/bin/*.dll"
"${SDL2_ROOT}/lib/x86/*.dll"
"${SDL2_IMAGE_ROOT}/lib/x86/*.dll"
"${SDL2_TTF_ROOT}/lib/x86/*.dll"
"${SDL2_MIXER_ROOT}/lib/x86/*.dll"
)
ADD_CUSTOM_COMMAND(TARGET RetroFE POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${RETROFE_OUTPUT_CORE_PATH}" )
ADD_CUSTOM_COMMAND(TARGET RetroFE POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "../Assets/Environment/Windows" "${RETROFE_OUTPUT_PATH}" )
foreach(CORE_FILE ${CORE_FILES})
ADD_CUSTOM_COMMAND(TARGET RetroFE POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CORE_FILE}" "${RETROFE_OUTPUT_CORE_PATH}" )
endforeach()
ADD_CUSTOM_COMMAND(TARGET RetroFE POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "../Build/Debug/RetroFE.exe" "${RETROFE_OUTPUT_CORE_PATH}" )
else()
ADD_CUSTOM_COMMAND(TARGET RetroFE POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "../Assets/Environment/Linux" "${RETROFE_OUTPUT_PATH}" )
ADD_CUSTOM_COMMAND(TARGET RetroFE POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "../Build/RetroFE" "${RETROFE_OUTPUT_PATH}" )
endif()

View File

@ -0,0 +1,67 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "CollectionInfo.h"
#include "../Database/Configuration.h"
#include <sstream>
CollectionInfo::CollectionInfo(std::string name,
std::string listPath,
std::string extensions,
std::string metadataType,
std::string metadataPath)
: Name(name)
, ListPath(listPath)
, Extensions(extensions)
, MetadataType(metadataType)
, MetadataPath(metadataPath)
{
}
CollectionInfo::~CollectionInfo()
{
}
std::string CollectionInfo::GetName() const
{
return Name;
}
std::string CollectionInfo::GetSettingsPath() const
{
return Configuration::GetAbsolutePath() + "/Collections/" + GetName();
}
std::string CollectionInfo::GetListPath() const
{
return ListPath;
}
std::string CollectionInfo::GetMetadataType() const
{
return MetadataType;
}
std::string CollectionInfo::GetMetadataPath() const
{
return MetadataPath;
}
std::string CollectionInfo::GetExtensions() const
{
return Extensions;
}
void CollectionInfo::GetExtensions(std::vector<std::string> &extensions)
{
std::istringstream ss(Extensions);
std::string token;
while(std::getline(ss, token, ','))
{
extensions.push_back(token);
}
}

View File

@ -0,0 +1,28 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <string>
#include <vector>
class CollectionInfo
{
public:
CollectionInfo(std::string name, std::string listPath, std::string extensions, std::string metadataType, std::string metadataPath);
virtual ~CollectionInfo();
std::string GetName() const;
std::string GetSettingsPath() const;
std::string GetListPath() const;
std::string GetMetadataType() const;
std::string GetMetadataPath() const;
std::string GetExtensions() const;
void GetExtensions(std::vector<std::string> &extensions);
private:
std::string Name;
std::string ListPath;
std::string Extensions;
std::string MetadataType;
std::string MetadataPath;
};

View File

@ -0,0 +1,126 @@
#include "CollectionInfoBuilder.h"
#include "CollectionInfo.h"
#include "../Database/Configuration.h"
#include "../Utility/Log.h"
#include <sstream>
#include <vector>
CollectionInfoBuilder::CollectionInfoBuilder(Configuration *c)
: Conf(c)
{
}
CollectionInfoBuilder::~CollectionInfoBuilder()
{
std::map<std::string, CollectionInfo *>::iterator it = InfoMap.begin();
for(it == InfoMap.begin(); it != InfoMap.end(); ++it)
{
delete it->second;
}
InfoMap.clear();
}
bool CollectionInfoBuilder::LoadAllCollections()
{
std::vector<std::string> collections;
Conf->GetChildKeyCrumbs("collections", collections);
if(collections.size() == 0)
{
Logger::Write(Logger::ZONE_ERROR, "Collections", "No collections were found. Please configure Settings.conf");
return false;
}
bool retVal = true;
std::vector<std::string>::iterator it;
for(it = collections.begin(); it != collections.end(); ++it)
{
// todo: There is nothing that should really stop us from creating a collection
// in the main folder. I just need to find some time to look at the impacts if
// I remove this conditional check.
if(*it != "Main")
{
if(ImportCollection(*it))
{
Logger::Write(Logger::ZONE_INFO, "Collections", "Adding collection " + *it);
}
else
{
// Continue processing the rest of the collections if an error occurs during import.
// ImportCollection() will print out an error to the log file.
retVal = false;
}
}
}
return retVal;
}
void CollectionInfoBuilder::GetCollections(std::vector<CollectionInfo *> &collections)
{
std::map<std::string, CollectionInfo *>::iterator InfoMapIt;
for(InfoMapIt = InfoMap.begin(); InfoMapIt != InfoMap.end(); ++InfoMapIt)
{
collections.push_back(InfoMapIt->second);
}
}
bool CollectionInfoBuilder::ImportCollection(std::string name)
{
// create a new instance if one does not exist
if(InfoMap.find(name) != InfoMap.end())
{
return true;
}
std::string listItemsPathKey = "collections." + name + ".list.path";
std::string listFilterKey = "collections." + name + ".list.filter";
std::string extensionsKey = "collections." + name + ".list.extensions";
std::string launcherKey = "collections." + name + ".launcher";
//todo: metadata is not fully not implemented
std::string metadataTypeKey = "collections." + name + ".metadata.type";
std::string metadataPathKey = "collections." + name + ".metadata.path";
std::string listItemsPath;
std::string launcherName;
std::string extensions;
std::string metadataType;
std::string metadataPath;
if(!Conf->GetPropertyAbsolutePath(listItemsPathKey, listItemsPath))
{
Logger::Write(Logger::ZONE_INFO, "Collections", "Property \"" + listItemsPathKey + "\" does not exist. Assuming \"" + name + "\" is a menu");
return false;
}
if(!Conf->GetProperty(extensionsKey, extensions))
{
Logger::Write(Logger::ZONE_INFO, "Collections", "Property \"" + extensionsKey + "\" does not exist. Assuming \"" + name + "\" is a menu");
return false;
}
(void)Conf->GetProperty(metadataTypeKey, metadataType);
(void)Conf->GetProperty(metadataPathKey, metadataPath);
if(!Conf->GetProperty(launcherKey, launcherName))
{
std::stringstream ss;
ss << "Warning: launcher property \""
<< launcherKey
<< "\" points to a launcher that is not configured (launchers."
<< launcherName
<< "). Your collection will be viewable, however you will not be able to "
<< "launch any of the items in your collection.";
Logger::Write(Logger::ZONE_WARNING, "Collections", ss.str());
}
InfoMap[name] = new CollectionInfo(name, listItemsPath, extensions, metadataType, metadataPath);
return (InfoMap[name] != NULL);
}

View File

@ -0,0 +1,25 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <string>
#include <map>
#include <vector>
class Configuration;
class CollectionInfo;
class CollectionInfoBuilder
{
public:
CollectionInfoBuilder(Configuration *c);
virtual ~CollectionInfoBuilder();
bool LoadAllCollections();
void GetCollections(std::vector<CollectionInfo *> &keys);
private:
bool ImportCollection(std::string name);
std::map<std::string, CollectionInfo *> InfoMap;
Configuration *Conf;
};

160
Source/Collection/Item.cpp Normal file
View File

@ -0,0 +1,160 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "Item.h"
#include "../Utility/Utils.h"
#include <sstream>
#include <algorithm>
Item::Item()
: NumberPlayers(0)
, NumberButtons(0)
, Leaf(true)
{
}
Item::~Item()
{
}
const std::string Item::GetFileName() const
{
return Utils::GetFileName(FilePath);
}
const std::string& Item::GetFilePath() const
{
return FilePath;
}
void Item::SetFilePath(const std::string& filepath)
{
FilePath = filepath;
}
const std::string& Item::GetLauncher() const
{
return Launcher;
}
void Item::SetLauncher(const std::string& launcher)
{
Launcher = launcher;
}
const std::string& Item::GetManufacturer() const
{
return Manufacturer;
}
void Item::SetManufacturer(const std::string& manufacturer)
{
Manufacturer = manufacturer;
}
const std::string& Item::GetName() const
{
return Name;
}
void Item::SetName(const std::string& name)
{
Name = name;
}
int Item::GetNumberButtons() const
{
return NumberButtons;
}
std::string Item::GetNumberButtonsString()
{
std::stringstream ss;
ss << NumberButtons;
return ss.str();
}
void Item::SetNumberButtons(int numberbuttons)
{
NumberButtons = numberbuttons;
}
int Item::GetNumberPlayers() const
{
return NumberPlayers;
}
std::string Item::GetNumberPlayersString()
{
std::stringstream ss;
ss << NumberButtons;
return ss.str();
}
void Item::SetNumberPlayers(int numberplayers)
{
NumberPlayers = numberplayers;
}
const std::string& Item::GetTitle() const
{
return Title;
}
const std::string& Item::GetLCTitle() const
{
return LCTitle;
}
void Item::SetTitle(const std::string& title)
{
Title = title;
LCTitle = Title;
std::transform(LCTitle.begin(), LCTitle.end(), LCTitle.begin(), ::tolower);
}
const std::string& Item::GetYear() const
{
return Year;
}
void Item::SetYear(const std::string& year)
{
Year = year;
}
bool Item::IsLeaf() const
{
return Leaf;
}
void Item::SetIsLeaf(bool leaf)
{
Leaf = leaf;
}
const std::string& Item::GetFullTitle() const
{
return FullTitle;
}
void Item::SetFullTitle(const std::string& fulltitle)
{
FullTitle = fulltitle;
}
const std::string& Item::GetCloneOf() const
{
return CloneOf;
}
void Item::SetCloneOf(const std::string& cloneOf)
{
CloneOf = cloneOf;
}
bool Item::operator<(const Item &rhs) { return LCTitle < rhs.LCTitle; }
bool Item::operator>(const Item &rhs) { return LCTitle > rhs.LCTitle; }

56
Source/Collection/Item.h Normal file
View File

@ -0,0 +1,56 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <string>
class Item
{
public:
Item();
virtual ~Item();
const std::string GetFileName() const;
const std::string& GetFilePath() const;
void SetFilePath(const std::string& filepath);
const std::string& GetLauncher() const;
void SetLauncher(const std::string& launcher);
const std::string& GetManufacturer() const;
void SetManufacturer(const std::string& manufacturer);
const std::string& GetName() const;
void SetName(const std::string& name);
int GetNumberButtons() const;
std::string GetNumberButtonsString();
void SetNumberButtons(int numberbuttons);
void SetNumberPlayers(int numberplayers);
int GetNumberPlayers() const;
std::string GetNumberPlayersString();
const std::string& GetTitle() const;
const std::string& GetLCTitle() const;
void SetTitle(const std::string& title);
const std::string& GetYear() const;
void SetYear(const std::string& year);
bool IsLeaf() const;
void SetIsLeaf(bool leaf);
const std::string& GetFullTitle() const;
void SetFullTitle(const std::string& fulltitle);
const std::string& GetCloneOf() const;
void SetCloneOf(const std::string& cloneOf);
bool operator<(const Item& rhs);
bool operator>(const Item& rhs);
private:
std::string Launcher;
std::string FilePath;
std::string Name;
std::string Title;
std::string LCTitle;
std::string FullTitle;
std::string Year;
std::string Manufacturer;
std::string CloneOf;
int NumberPlayers;
int NumberButtons;
bool Leaf;
};

View File

@ -0,0 +1,108 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "MenuParser.h"
#include "Item.h"
#include "../Utility/Log.h"
#include "../Database/Configuration.h"
#include "../Database/CollectionDatabase.h"
#include "../Database/DB.h"
#include <algorithm>
#include <rapidxml.hpp>
#include <fstream>
#include <sstream>
bool VectorSort(const Item *d1, const Item *d2)
{
return d1->GetLCTitle() < d2->GetLCTitle();
}
MenuParser::MenuParser()
{
}
MenuParser::~MenuParser()
{
}
//todo: clean up this method, too much nesting
bool MenuParser::GetMenuItems(CollectionDatabase *cdb, std::string collectionName, std::vector<Item *> &items)
{
bool retVal = false;
//todo: magic string
std::string menuFilename = Configuration::GetAbsolutePath() + "/Collections/" + collectionName + "/Menu.xml";
rapidxml::xml_document<> doc;
rapidxml::xml_node<> * rootNode;
Logger::Write(Logger::ZONE_INFO, "Menu", "Checking if menu exists at \"" + menuFilename + "\"");
try
{
std::ifstream file(menuFilename.c_str());
// gracefully exit if there is no menu file for the pa
if(file.good())
{
Logger::Write(Logger::ZONE_INFO, "Menu", "Found menu");
std::vector<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
buffer.push_back('\0');
doc.parse<0>(&buffer[0]);
rootNode = doc.first_node("menu");
for (rapidxml::xml_node<> * itemNode = rootNode->first_node("item"); itemNode; itemNode = itemNode->next_sibling())
{
rapidxml::xml_attribute<> *collectionAttribute = itemNode->first_attribute("collection");
rapidxml::xml_attribute<> *importAttribute = itemNode->first_attribute("import");
if(!collectionAttribute)
{
retVal = false;
Logger::Write(Logger::ZONE_ERROR, "Menu", "Menu item tag is missing collection attribute");
break;
}
else
{
//todo: too much nesting! Ack!
std::string import;
if(importAttribute)
{
import = importAttribute->value();
}
if(import != "true")
{
//todo, check for empty string
std::string title = collectionAttribute->value();
Item *item = new Item();
item->SetTitle(title);
item->SetFullTitle(title);
item->SetName(collectionAttribute->value());
item->SetIsLeaf(false);
items.push_back(item);
}
else
{
std::string collectionName = collectionAttribute->value();
Logger::Write(Logger::ZONE_INFO, "Menu", "Loading collection into menu: " + collectionName);
cdb->GetCollection(collectionAttribute->value(), items);
}
}
}
std::sort( items.begin(), items.end(), VectorSort);
retVal = true;
}
}
catch(std::ifstream::failure &e)
{
std::stringstream ss;
ss << "Unable to open menu file \"" << menuFilename << "\": " << e.what();
Logger::Write(Logger::ZONE_ERROR, "Menu", ss.str());
}
return retVal;
}

View File

@ -0,0 +1,17 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Item.h"
#include <vector>
class CollectionDatabase;
class MenuParser
{
public:
MenuParser();
virtual ~MenuParser();
bool GetMenuItems(CollectionDatabase *cdb, std::string collectionName, std::vector<Item *> &items);
};

View File

@ -0,0 +1,78 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "UserInput.h"
#include "../Database/Configuration.h"
#include "../Utility/Log.h"
UserInput::UserInput(Configuration *c)
: Config(c)
{
}
UserInput::~UserInput()
{
}
bool UserInput::Initialize()
{
bool retVal = true;
retVal = MapKey("nextItem", KeyCodeNextItem) && retVal;
retVal = MapKey("previousItem", KeyCodePreviousItem) && retVal;
retVal = MapKey("pageDown", KeyCodePageDown) && retVal;
retVal = MapKey("pageUp", KeyCodePageUp) && retVal;
retVal = MapKey("select", KeyCodeSelect) && retVal;
retVal = MapKey("back", KeyCodeBack) && retVal;
retVal = MapKey("quit", KeyCodeQuit) && retVal;
// these features will need to be implemented at a later time
// retVal = MapKey("admin", KeyCodeAdminMode) && retVal;
// retVal = MapKey("remove", KeyCodeHideItem) && retVal;
return retVal;
}
SDL_Scancode UserInput::GetScancode(KeyCode_E key)
{
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
std::map<KeyCode_E, SDL_Scancode>::iterator it = KeyMap.find(key);
if(it != KeyMap.end())
{
scancode = it->second;
}
return scancode;
}
bool UserInput::MapKey(std::string keyDescription, KeyCode_E key)
{
bool retVal = false;
SDL_Scancode scanCode;
std::string description;
std::string configKey = "controls." + keyDescription;
if(!Config->GetProperty(configKey, description))
{
Logger::Write(Logger::ZONE_ERROR, "Configuration", "Missing property " + configKey);
}
else
{
scanCode = SDL_GetScancodeFromName(description.c_str());
if(scanCode == SDL_SCANCODE_UNKNOWN)
{
Logger::Write(Logger::ZONE_ERROR, "Configuration", "Unsupported property value for " + configKey + "(" + description + "). See Documentation/Keycodes.txt for valid inputs");
}
else
{
KeyMap[key] = scanCode;
retVal = true;
}
}
return retVal;
}

View File

@ -0,0 +1,38 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <map>
#include <SDL2/SDL.h>
#include <string>
class Configuration;
class UserInput
{
public:
enum KeyCode_E
{
KeyCodeNextItem,
KeyCodePreviousItem,
KeyCodeSelect,
KeyCodeBack,
KeyCodePageDown,
KeyCodePageUp,
KeyCodeAdminMode,
KeyCodeHideItem,
KeyCodeQuit
};
UserInput(Configuration *c);
virtual ~UserInput();
bool Initialize();
SDL_Scancode GetScancode(KeyCode_E key);
private:
bool MapKey(std::string keyDescription, KeyCode_E key);
std::map<KeyCode_E, SDL_Scancode> KeyMap;
Configuration *Config;
};

View File

@ -0,0 +1,750 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "CollectionDatabase.h"
#include "../Collection/CollectionInfoBuilder.h"
#include "../Collection/CollectionInfo.h"
#include "../Collection/Item.h"
#include "../Utility/Log.h"
#include "../Utility/Utils.h"
#include "MamelistMetadata.h"
#include "Configuration.h"
#include "DB.h"
#include <algorithm>
#include <dirent.h>
#include <fstream>
#include <list>
#include <rapidxml.hpp>
#include <sstream>
#include <string>
#include <map>
#include <sys/types.h>
#include <sqlite3.h>
#include <zlib.h>
#include <exception>
CollectionDatabase::CollectionDatabase(DB *db, Configuration *c)
: Config(c)
, DBInstance(db)
{
}
CollectionDatabase::~CollectionDatabase()
{
}
bool CollectionDatabase::ResetDatabase()
{
bool retVal = true;
int rc;
char *error = NULL;
sqlite3 *handle = DBInstance->GetHandle();
Logger::Write(Logger::ZONE_INFO, "Database", "Erasing");
std::string sql;
sql.append("DROP TABLE IF EXISTS CollectionItems;");
sql.append("DROP TABLE IF EXISTS Meta;");
sql.append("DROP TABLE IF EXISTS Collections;");
rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error);
if(rc != SQLITE_OK)
{
std::stringstream ss;
ss << "Unable to create Configurations table. Error: " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
//CheckDatabase();
return retVal;
}
bool CollectionDatabase::CheckDatabase()
{
bool retVal = true;
int rc;
char *error = NULL;
sqlite3 *handle = DBInstance->GetHandle();
std::string sql;
sql.append("CREATE TABLE IF NOT EXISTS CollectionItems(");
sql.append("collectionName TEXT KEY,");
sql.append("filePath TEXT NOT NULL DEFAULT '',");
sql.append("name TEXT NOT NULL DEFAULT '',");
sql.append("hidden INT NOT NULL DEFAULT 0);");
sql.append("CREATE TABLE IF NOT EXISTS Meta(");
sql.append("collectionName TEXT KEY,");
sql.append("name TEXT NOT NULL DEFAULT '',");
sql.append("title TEXT NOT NULL DEFAULT '',");
sql.append("year TEXT NOT NULL DEFAULT '',");
sql.append("manufacturer TEXT NOT NULL DEFAULT '',");
sql.append("cloneOf TEXT NOT NULL DEFAULT '',");
sql.append("players INTEGER,");
sql.append("buttons INTEGER);");
sql.append("CREATE UNIQUE INDEX IF NOT EXISTS MetaUniqueId ON Meta(collectionName, name);");
sql.append("CREATE TABLE IF NOT EXISTS Collections(");
sql.append("collectionName TEXT KEY,");
sql.append("crc32 UNSIGNED INTEGER NOT NULL DEFAULT 0);");
sql.append("CREATE UNIQUE INDEX IF NOT EXISTS CollectionsUniqueId ON Collections(collectionName);");
rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error);
if(rc != SQLITE_OK)
{
std::stringstream ss;
ss << "Unable to create Configurations table. Error: " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
return retVal;
}
bool CollectionDatabase::Import()
{
bool retVal = true;
// should keep allocation here
CollectionInfoBuilder cib(Config);
(void)cib.LoadAllCollections();
std::vector<CollectionInfo *> collections;
cib.GetCollections(collections);
std::vector<CollectionInfo *>::iterator it;
for(it = collections.begin(); it != collections.end() && retVal; ++it)
{
CollectionInfo *info = *it;
std::string title = info->GetName();
unsigned long crc32 = CalculateCollectionCrc32(info);
std::stringstream crcStr;
crcStr << crc32;
if(title != "Main")
{
if(CollectionChanged(info, crc32))
{
std::string msg = "Detected collection \"" + title + "\" has changed (new CRC: " + crcStr.str() + "). Rebuilding database for this collection.";
Logger::Write(Logger::ZONE_INFO, "Database", msg);
(void)ImportDirectory(info, crc32);
retVal = true;
}
else
{
std::stringstream ss;
std::string msg = "Collection \"" + title + "\" has not changed (CRC: " + crcStr.str() + "). Using existing database settings.";
Logger::Write(Logger::ZONE_INFO, "Database", msg);
}
}
//std::cout << "Importing collection metadata for " << info->GetFullTitle() << " (collections." << info->GetName() << ")" << std::endl;
//ImportMetadata(info);
}
Logger::Write(Logger::ZONE_INFO, "Database", "COMPLETE");
Sleep(1000);
return retVal;
}
unsigned long CollectionDatabase::CalculateCollectionCrc32(CollectionInfo *info)
{
unsigned long crc = crc32(0L, Z_NULL, 0);
// start off by reading all of the contents in the collection configuration folders
std::string settingsFile = info->GetSettingsPath() + "/Settings.conf";
crc = CrcFile(settingsFile, crc);
std::string includeFile = info->GetSettingsPath() + "/Include.txt";
crc = CrcFile(includeFile, crc);
std::string excludeFile = info->GetSettingsPath() + "/Exclude.txt";
crc = CrcFile(excludeFile, crc);
std::string mamelistFile = info->GetSettingsPath() + "/Mamelist.xml";
crc = CrcFile(mamelistFile, crc);
DIR *dp;
struct dirent *dirp;
std::string path = info->GetListPath();
dp = opendir(path.c_str());
if(dp == NULL)
{
Logger::Write(Logger::ZONE_ERROR, "Database", "Could not read directory for caching \"" + info->GetListPath() + "\"");
return crc;
}
std::vector<std::string> extensions;
info->GetExtensions(extensions);
std::vector<std::string>::iterator extensionsIt;
// md5sum each filename for the matching extension
while((dirp = readdir(dp)) != NULL)
{
std::string file = dirp->d_name;
for(extensionsIt = extensions.begin(); extensionsIt != extensions.end(); ++extensionsIt)
{
std::string comparator = "." + *extensionsIt;
int start = file.length() - comparator.length() + 1;
if(start >= 0 && file.compare(start, comparator.length(), *extensionsIt) == 0)
{
std::string filename = dirp->d_name;
filename.append("\n");
crc = crc32(crc, (const unsigned char *)filename.c_str(), (unsigned int)filename.length());
}
}
}
return crc;
}
unsigned long CollectionDatabase::CrcFile(std::string file, unsigned long crc)
{
// CRC both the filename and its contents
crc = crc32(crc, (const unsigned char *)file.c_str(), (unsigned int)file.length());
std::ifstream ifFile(file.c_str());
if(ifFile.good())
{
std::stringstream ss;
ss << ifFile.rdbuf();
crc = crc32(crc, (const unsigned char *)ss.str().c_str(), (unsigned int)ss.str().length());
Logger::Write(Logger::ZONE_INFO, "Database", "Crcing \"" + file + "\"");
ifFile.close();
}
return crc;
}
bool CollectionDatabase::CollectionChanged(CollectionInfo *info, unsigned long crc32)
{
bool retVal = true;
sqlite3 *handle = DBInstance->GetHandle();
int rc;
sqlite3_stmt *stmt;
sqlite3_prepare_v2(handle,
"SELECT crc32 "
"FROM Collections WHERE collectionName=? and crc32=?;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 2, crc32);
rc = sqlite3_step(stmt);
if(rc == SQLITE_ROW)
{
retVal = false;
}
return retVal;
}
bool CollectionDatabase::SetHidden(std::string collectionName, Item *item, bool hidden)
{
bool retVal = true;
char *error = NULL;
sqlite3 *handle = DBInstance->GetHandle();
std::string mode = (hidden) ? "hidden":"visible";
int isHidden = (hidden)?1:0;
Logger::Write(Logger::ZONE_DEBUG, "Database", "Marking \"" + item->GetFullTitle() + "\" " + mode);
sqlite3_stmt *stmt;
sqlite3_prepare_v2(handle,
"UPDATE CollectionItems SET hidden=? WHERE collectionName=? AND name=?;",
-1, &stmt, 0);
sqlite3_bind_int(stmt, 1, isHidden);
sqlite3_bind_text(stmt, 2, collectionName.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, item->GetFullTitle().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error);
return retVal;
}
//todo: This file needs MASSIVE REFACTORING!
bool CollectionDatabase::ImportDirectory(CollectionInfo *info, unsigned long crc32)
{
DIR *dp;
struct dirent *dirp;
std::string path = info->GetListPath();
std::map<std::string, Item *> includeFilter;
std::map<std::string, Item *> excludeFilter;
std::map<std::string, Item *> includeList;
std::map<std::string, Item *> metaList;
bool retVal = true;
char *error = NULL;
sqlite3 *handle = DBInstance->GetHandle();
std::string includeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Include.txt";
std::string excludeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Exclude.txt";
std::string includeHyperListFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Include.xml";
if(!ImportBasicList(info, includeFile, includeFilter))
{
ImportHyperList(info, includeHyperListFile, includeFilter);
}
//todo: this shouldn't be read twice, perform a copy
ImportHyperList(info, includeHyperListFile, metaList);
(void)ImportBasicList(info, excludeFile, excludeFilter);
dp = opendir(path.c_str());
std::vector<std::string> extensions;
info->GetExtensions(extensions);
std::vector<std::string>::iterator extensionsIt;
if(dp == NULL)
{
Logger::Write(Logger::ZONE_ERROR, "Database", "Could not read directory \"" + info->GetListPath() + "\"");
//todo: store into a database
}
else
{
while((dirp = readdir(dp)) != NULL)
{
std::string file = dirp->d_name;
Utils::NormalizeBackSlashes(file);
size_t position = file.find_last_of(".");
std::string basename = (std::string::npos == position)? file : file.substr(0, position);
if((includeFilter.size() == 0 || includeFilter.find(basename) != includeFilter.end()) &&
(excludeFilter.size() == 0 || excludeFilter.find(basename) == excludeFilter.end()))
{
for(extensionsIt = extensions.begin(); extensionsIt != extensions.end(); ++extensionsIt)
{
std::string comparator = "." + *extensionsIt;
int start = file.length() - comparator.length() + 1;
if(start >= 0)
{
if(file.compare(start, comparator.length(), *extensionsIt) == 0)
{
if(includeList.find(basename) == includeList.end())
{
Item *i = new Item();
i->SetFullTitle(file);
includeList[basename] = i;
}
if(metaList.find(basename) == metaList.end())
{
Item *i = new Item();
i->SetFullTitle(file);
metaList[basename] = i;
}
}
}
}
}
}
}
while(includeFilter.size() > 0)
{
std::map<std::string, Item *>::iterator it = includeFilter.begin();
delete it->second;
includeFilter.erase(it);
}
while(excludeFilter.size() > 0)
{
std::map<std::string, Item *>::iterator it = excludeFilter.begin();
delete it->second;
excludeFilter.erase(it);
}
Logger::Write(Logger::ZONE_INFO, "Database", "Scanning to import \"" + path + "\"");
sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", NULL, NULL, &error);
sqlite3_stmt *stmt;
sqlite3_prepare_v2(handle,
"DELETE FROM Collections WHERE collectionName=?;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
sqlite3_prepare_v2(handle,
"DELETE FROM CollectionItems WHERE collectionName=?;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
sqlite3_prepare_v2(handle,
"DELETE FROM Meta WHERE collectionName=?;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
if(sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error) != SQLITE_OK)
{
std::stringstream ss;
ss << "Updating cache collection failure " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
std::map<std::string, Item *>::iterator it;
if(sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", NULL, NULL, &error) != SQLITE_OK)
{
std::stringstream ss;
ss << "Delete cache collection failure " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
for(it = includeList.begin(); it != includeList.end(); it++)
{
std::string basename = it->first;
Item *file = it->second;
std::string name = file->GetFullTitle();
Utils::NormalizeBackSlashes(name);
file->SetFullTitle(name);
sqlite3_prepare_v2(handle,
"INSERT OR REPLACE INTO CollectionItems (collectionName, filePath, name) VALUES (?,?,?);",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, file->GetFullTitle().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, basename.c_str(), -1, SQLITE_TRANSIENT);
//todo: better error handling for all of these messages
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
for(it = metaList.begin(); it != metaList.end(); it++)
{
std::string basename = it->first;
Item *file = it->second;
sqlite3_prepare_v2(handle,
"INSERT OR REPLACE INTO Meta (collectionName, name, title, year, manufacturer, cloneOf, players, buttons) VALUES (?,?,?,?,?,?,?,?);",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, basename.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, basename.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, file->GetYear().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, file->GetManufacturer().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, file->GetCloneOf().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 7, file->GetNumberPlayersString().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 8, file->GetNumberButtonsString().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
sqlite3_prepare_v2(handle,
"INSERT OR REPLACE INTO Collections (collectionName, crc32) VALUES (?,?);",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 2, crc32);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
if(sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error) != SQLITE_OK)
{
std::stringstream ss;
ss << "Updating cache collection failure " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
Logger::Write(Logger::ZONE_INFO, "Database", "Imported files from \"" + path + "\" into database");
//todo: create a helper method to get this file directly (copy paste hazard)
std::string mamelistFile = info->GetSettingsPath() + "/Mamelist.xml";
std::ifstream infile(mamelistFile.c_str());
if(infile.good())
{
Logger::Write(Logger::ZONE_INFO, "Database", "Updating Mamelist metadata for \"" + info->GetName() + "\" (\"" + mamelistFile + "\") into database. This will take a while...");
MamelistMetadata mld(DBInstance);
mld.Import(mamelistFile, info->GetName());
}
infile.close();
while(includeList.size() > 0)
{
std::map<std::string, Item *>::iterator it = includeList.begin();
delete it->second;
includeList.erase(it);
}
while(metaList.size() > 0)
{
std::map<std::string, Item *>::iterator it = metaList.begin();
delete it->second;
metaList.erase(it);
}
return retVal;
}
bool CollectionDatabase::ImportBasicList(CollectionInfo *info, std::string file, std::map<std::string, Item *> &list)
{
bool retVal = false;
Logger::Write(Logger::ZONE_DEBUG, "Database", "Checking to see if \"" + file + "\" exists");
std::ifstream includeStream(file.c_str());
if (includeStream.good())
{
Logger::Write(Logger::ZONE_DEBUG, "Database", "Importing \"" + file + "\"");
std::string line;
while(std::getline(includeStream, line))
{
if(list.find(line) == list.end())
{
Item *i = new Item();
line.erase( std::remove(line.begin(), line.end(), '\r'), line.end() );
i->SetFullTitle(line);
list[line] = i;
Logger::Write(Logger::ZONE_DEBUG, "Database", "Including \"" + line + "\" (if file exists)");
}
}
retVal = true;
}
return retVal;
}
bool CollectionDatabase::ImportHyperList(CollectionInfo *info, std::string hyperlistFile, std::map<std::string, Item *> &list)
{
bool retVal = false;
rapidxml::xml_document<> doc;
std::ifstream file(hyperlistFile.c_str());
std::vector<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
Logger::Write(Logger::ZONE_DEBUG, "Database", "Checking to see if \"" + hyperlistFile + "\" exists");
if(!file.good())
{
Logger::Write(Logger::ZONE_INFO, "Database", "Could not find HyperList file: " + hyperlistFile);
return retVal;
}
try
{
Logger::Write(Logger::ZONE_INFO, "Database", "Importing: " + hyperlistFile);
buffer.push_back('\0');
doc.parse<0>(&buffer[0]);
rapidxml::xml_node<> *root = doc.first_node("menu");
if(!root)
{
Logger::Write(Logger::ZONE_ERROR, "CollectionDatabase", "Does not appear to be a HyperList file (missing <menu> tag)");
return NULL;
}
else
{
for(rapidxml::xml_node<> *game = root->first_node("game"); game; game = game->next_sibling("game"))
{
rapidxml::xml_attribute<> *nameXml = game->first_attribute("name");
rapidxml::xml_node<> *descriptionXml = game->first_node("description");
rapidxml::xml_node<> *cloneofXml = game->first_node("cloneof");
rapidxml::xml_node<> *crcXml = game->first_node("crc");
rapidxml::xml_node<> *manufacturerXml = game->first_node("manufacturer");
rapidxml::xml_node<> *yearXml = game->first_node("year");
rapidxml::xml_node<> *genreXml = game->first_node("genre");
rapidxml::xml_node<> *ratingXml = game->first_node("rating");
rapidxml::xml_node<> *enabledXml = game->first_node("enabled");
std::string name = (nameXml) ? nameXml->value() : "";
std::string description = (descriptionXml) ? descriptionXml->value() : "";
std::string crc = (crcXml) ? crcXml->value() : "";
std::string cloneOf = (cloneofXml) ? cloneofXml->value() : "";
std::string manufacturer = (manufacturerXml) ? manufacturerXml->value() : "";
std::string year = (yearXml) ? yearXml->value() : "";
std::string genre = (genreXml) ? genreXml->value() : "";
std::string rating = (ratingXml) ? ratingXml->value() : "";
std::string enabled = (enabledXml) ? enabledXml->value() : "";
if(name.length() > 0 && list.find(name) == list.end())
{
Item *i = new Item();
i->SetFullTitle(name);
i->SetYear(year);
i->SetManufacturer(manufacturer);
i->SetCloneOf(cloneOf);
list[name] = i;
Logger::Write(Logger::ZONE_DEBUG, "Database", "Including \"" + name + "\" (if file exists)");
}
}
}
}
catch(rapidxml::parse_error &e)
{
std::string what = e.what();
long line = static_cast<long>(std::count(&buffer.front(), e.where<char>(), char('\n')) + 1);
std::stringstream ss;
ss << "Could not parse layout file. [Line: " << line << "] Reason: " << e.what();
Logger::Write(Logger::ZONE_ERROR, "Layout", ss.str());
}
catch(std::exception &e)
{
std::string what = e.what();
Logger::Write(Logger::ZONE_ERROR, "Layout", "Could not parse layout file. Reason: " + what);
}
return retVal;
}
/*
bool CollectionDatabase::ImportMetadata(CollectionInfo *info)
{
bool retVal = true;
std::string type = info->GetMetadataType();
if(type.compare("mamelist") == 0)
{
MamelistMetadata meta;
//todo: pass in collectionName
retVal = meta.Import(info->GetMetadataPath(), "arcade");
}
else if(!type.empty())
{
std::stringstream ss;
ss << "Unsupported metadata type \"" << type << "\" for " << info->GetFullTitle() << " (collections." << info->GetName() << ".metadata.type)" << std::endl;
Log::Write(Log::ERROR, "Database", ss.str());
retVal = false;
}
return retVal;
}
*/
bool CollectionDatabase::GetCollection(std::string collectionName, std::vector<Item *> &list)
{
bool retVal = true;
sqlite3 *handle = DBInstance->GetHandle();
int rc;
sqlite3_stmt *stmt;
bool showParenthesis = true;
bool showSquareBrackets = true;
(void)Config->GetProperty("showParenthesis", showParenthesis);
(void)Config->GetProperty("showSquareBrackets", showSquareBrackets);
//todo: program crashes if this query fails
sqlite3_prepare_v2(handle,
"SELECT DISTINCT CollectionItems.filePath, CollectionItems.name, Meta.title, Meta.year, Meta.manufacturer, Meta.players, Meta.buttons, Meta.cloneOf "
"FROM CollectionItems, Meta WHERE CollectionItems.collectionName=? AND Meta.collectionName=? AND CollectionItems.name=Meta.name AND CollectionItems.hidden=0 ORDER BY title ASC;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, collectionName.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, collectionName.c_str(), -1, SQLITE_TRANSIENT);
rc = sqlite3_step(stmt);
while(rc == SQLITE_ROW)
{
std::string filePath = (char *)sqlite3_column_text(stmt, 0);
std::string name = (char *)sqlite3_column_text(stmt, 1);
std::string fullTitle = (char *)sqlite3_column_text(stmt, 2);
std::string year = (char *)sqlite3_column_text(stmt, 3);
std::string manufacturer = (char *)sqlite3_column_text(stmt, 4);
int numberPlayers = (int)sqlite3_column_int(stmt, 5);
int numberButtons = (int)sqlite3_column_int(stmt, 6);
std::string cloneOf = (char *)sqlite3_column_text(stmt, 7);
std::string launcher;
std::string title = fullTitle;
if(!showParenthesis)
{
std::string::size_type firstPos = title.find_first_of("(");
std::string::size_type secondPos = title.find_first_of(")", firstPos);
while(firstPos != std::string::npos && secondPos != std::string::npos)
{
firstPos = title.find_first_of("(");
secondPos = title.find_first_of(")", firstPos);
if (firstPos != std::string::npos)
{
title.erase(firstPos, (secondPos - firstPos) + 1);
}
}
}
if(!showSquareBrackets)
{
std::string::size_type firstPos = title.find_first_of("[");
std::string::size_type secondPos = title.find_first_of("]", firstPos);
while(firstPos != std::string::npos && secondPos != std::string::npos)
{
firstPos = title.find_first_of("[");
secondPos = title.find_first_of("]", firstPos);
if (firstPos != std::string::npos && secondPos != std::string::npos)
{
title.erase(firstPos, (secondPos - firstPos) + 1);
}
}
}
Item *item = new Item();
item->SetFilePath(filePath);
item->SetName(name);
item->SetTitle(title);
item->SetFullTitle(fullTitle);
item->SetYear(year);
item->SetManufacturer(manufacturer);
item->SetNumberPlayers(numberPlayers);
item->SetNumberButtons(numberButtons);
item->SetCloneOf(cloneOf);
//std::cout << "loading " << title << std::endl;
if(Config->GetProperty("collections." + collectionName + ".launcher", launcher))
{
item->SetLauncher(launcher);
}
list.push_back(item);
rc = sqlite3_step(stmt);
}
//todo: query the metadata table to populate each item
return retVal;
}

View File

@ -0,0 +1,44 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <string>
#include <vector>
#include <map>
class DB;
class Configuration;
class CollectionInfo;
class Item;
class CollectionDatabase
{
public:
CollectionDatabase(DB *db, Configuration *c);
virtual ~CollectionDatabase();
bool Import();
bool ResetDatabase();
bool CheckDatabase();
bool GetCollection(std::string collectionName, std::vector<Item *> &list);
bool SetHidden(std::string collectionName, Item *item, bool hidden);
private:
unsigned long CalculateCollectionCrc32(CollectionInfo *info);
bool CollectionChanged(CollectionInfo *info, unsigned long crc32);
unsigned long CrcFile(std::string file, unsigned long crc);
// bool ImportMetadata(CollectionInfo *info);
bool ImportDirectory(CollectionInfo *info, unsigned long crc32);
bool ImportBasicList(CollectionInfo *info,
std::string file,
std::map<std::string, Item *> &list);
bool ImportHyperList(CollectionInfo *info,
std::string file,
std::map<std::string, Item *> &list);
std::map<std::string, Item *> *ImportHyperList(CollectionInfo *info);
Configuration *Config;
DB *DBInstance;
};

View File

@ -0,0 +1,295 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "Configuration.h"
#include "../Utility/Log.h"
#include "../Utility/Utils.h"
#include <algorithm>
#include <locale>
#include <fstream>
#include <sstream>
std::string Configuration::AbsolutePath;
Configuration::Configuration()
: Verbose(false)
{
}
Configuration::~Configuration()
{
}
bool Configuration::Import(std::string keyPrefix, std::string file)
{
bool retVal = true;
int lineCount = 0;
std::string line;
Logger::Write(Logger::ZONE_INFO, "Configuration", "Importing " + file);
std::ifstream ifs(file.c_str());
if (!ifs.is_open())
{
Logger::Write(Logger::ZONE_ERROR, "Configuration", "Could not open " + file);
return false;
}
while (std::getline (ifs, line))
{
lineCount++;
retVal = retVal && ParseLine(keyPrefix, line, lineCount);
}
ifs.close();
return retVal;
}
bool Configuration::ParseLine(std::string keyPrefix, std::string line, int lineCount)
{
bool retVal = false;
std::string key;
std::string value;
size_t position;
std::string delimiter = "=";
// strip out any comments
if((position = line.find("#")) != std::string::npos)
{
line = line.substr(0, position);
}
// unix only wants \n. Windows uses \r\n. Strip off the \r for unix.
line.erase( std::remove(line.begin(), line.end(), '\r'), line.end() );
if(line.empty() || (line.find_first_not_of(" \t\r") == std::string::npos))
{
retVal = true;
}
// all configuration fields must have an assignment operator
else if((position = line.find(delimiter)) != std::string::npos)
{
if(keyPrefix.size() != 0)
{
keyPrefix += ".";
}
key = keyPrefix + line.substr(0, position);
key = TrimEnds(key);
value = line.substr(position + delimiter.length(), line.length());
value = TrimEnds(value);
Properties.insert(PropertiesPair(key, value));
std::stringstream ss;
ss << "Dump: " << "\"" << key << "\" = \"" << value << "\"";
Logger::Write(Logger::ZONE_INFO, "Configuration", ss.str());
retVal = true;
}
else
{
std::stringstream ss;
ss << "Missing an assignment operator (=) on line " << lineCount;
Logger::Write(Logger::ZONE_ERROR, "Configuration", ss.str());
}
return retVal;
}
std::string Configuration::TrimEnds(std::string str)
{
// strip off any initial tabs or spaces
size_t trimStart = str.find_first_not_of(" \t");
if(trimStart != std::string::npos)
{
size_t trimEnd = str.find_last_not_of(" \t");
str = str.substr(trimStart, trimEnd - trimStart + 1);
}
return str;
}
bool Configuration::GetProperty(std::string key, std::string &value)
{
bool retVal = false;
if(Properties.find(key) != Properties.end())
{
value = Properties[key];
retVal = true;
}
else if(Verbose)
{
Logger::Write(Logger::ZONE_DEBUG, "Configuration", "Missing property " + key);
}
return retVal;
}
bool Configuration::GetProperty(std::string key, int &value)
{
std::string strValue;
bool retVal = GetProperty(key, strValue);
if(retVal)
{
std::stringstream ss;
ss << strValue;
ss >> value;
}
return retVal;
}
bool Configuration::GetProperty(std::string key, bool &value)
{
std::string strValue;
bool retVal = GetProperty(key, strValue);
if(retVal)
{
std::stringstream ss;
ss << strValue;
for(unsigned int i=0; i < strValue.length(); ++i)
{
std::locale loc;
strValue[i] = std::tolower(strValue[i], loc);
}
if(!strValue.compare("yes") || !strValue.compare("true"))
{
value = true;
}
else
{
value = false;
}
}
return retVal;
}
void Configuration::SetProperty(std::string key, std::string value)
{
Properties[key] = value;
}
bool Configuration::PropertyExists(std::string key)
{
return (Properties.find(key) != Properties.end());
}
bool Configuration::PropertyPrefixExists(std::string key)
{
PropertiesType::iterator it;
for(it = Properties.begin(); it != Properties.end(); ++it)
{
std::string search = key + ".";
if(it->first.compare(0, search.length(), search) == 0)
{
return true;
}
}
return false;
}
void Configuration::GetChildKeyCrumbs(std::string parent, std::vector<std::string> &children)
{
PropertiesType::iterator it;
for(it = Properties.begin(); it != Properties.end(); ++it)
{
std::string search = parent + ".";
if(it->first.compare(0, search.length(), search) == 0)
{
std::string crumb = Utils::Replace(it->first, search, "");
std::size_t end = crumb.find_first_of(".");
if(end != std::string::npos)
{
crumb = crumb.substr(0, end);
}
if(std::find(children.begin(), children.end(), crumb) == children.end())
{
children.push_back(crumb);
}
}
}
}
std::string Configuration::ConvertToAbsolutePath(std::string prefix, std::string path)
{
char first = ' ';
char second = ' ';
if(path.length() >= 0)
{
first = path.c_str()[0];
}
if(path.length() >= 1)
{
second = path.c_str()[1];
}
// check to see if it is already an absolute path
if((first != '/') &&
(first != '\\') &&
//(first != '.') &&
(second != ':'))
{
path = prefix + "/" + path;
}
return path;
}
bool Configuration::GetPropertyAbsolutePath(std::string key, std::string &value)
{
bool retVal = GetProperty(key, value);
if(retVal)
{
value = ConvertToAbsolutePath(GetAbsolutePath(), value);
}
return retVal;
}
void Configuration::SetAbsolutePath(std::string absolutePath)
{
AbsolutePath = absolutePath;
}
std::string Configuration::GetAbsolutePath()
{
return AbsolutePath;
}
bool Configuration::IsVerbose() const
{
return Verbose;
}
void Configuration::SetVerbose(bool verbose)
{
this->Verbose = verbose;
}

View File

@ -0,0 +1,43 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <string>
#include <map>
#include <vector>
class Configuration
{
public:
Configuration();
virtual ~Configuration();
// gets the global configuration
bool Import(std::string keyPrefix, std::string file);
bool GetProperty(std::string key, std::string &value);
bool GetProperty(std::string key, int &value);
bool GetProperty(std::string key, bool &value);
void GetChildKeyCrumbs(std::string parent, std::vector<std::string> &children);
void SetProperty(std::string key, std::string value);
bool PropertyExists(std::string key);
bool PropertyPrefixExists(std::string key);
bool GetPropertyAbsolutePath(std::string key, std::string &value);
static void SetAbsolutePath(std::string absolutePath);
static std::string GetAbsolutePath();
static std::string ConvertToAbsolutePath(std::string prefix, std::string path);
bool IsVerbose() const;
void SetVerbose(bool verbose);
bool IsRequiredPropertiesSet();
private:
bool ParseLine(std::string keyPrefix, std::string line, int lineCount);
std::string TrimEnds(std::string str);
typedef std::map<std::string, std::string> PropertiesType;
typedef std::pair<std::string, std::string> PropertiesPair;
bool Verbose;
static std::string AbsolutePath;
PropertiesType Properties;
};

50
Source/Database/DB.cpp Normal file
View File

@ -0,0 +1,50 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "DB.h"
#include "Configuration.h"
#include "../Utility/Log.h"
#include <sstream>
#include <fstream>
DB::DB()
: Path(Configuration::GetAbsolutePath() + "/cache.db")
, Handle(NULL)
{
}
DB::~DB()
{
DeInitialize();
}
bool DB::Initialize()
{
bool retVal = false;
if(sqlite3_open(Path.c_str(), &Handle) != 0)
{
std::stringstream ss;
ss << "Cannot open database: \"" << Path << "\"" << sqlite3_errmsg(Handle);
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
}
else
{
Logger::Write(Logger::ZONE_INFO, "Database", "Opened database \"" + Path + "\"");
retVal = true;
}
return retVal;
}
void DB::DeInitialize()
{
if(Handle != NULL)
{
sqlite3_close(Handle);
Handle = NULL;
}
}

21
Source/Database/DB.h Normal file
View File

@ -0,0 +1,21 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <sqlite3.h>
#include <string>
class DB
{
public:
DB();
bool Initialize();
void DeInitialize();
virtual ~DB();
sqlite3 *GetHandle() { return Handle; }
private:
sqlite3 *Handle;
std::string Path;
};

View File

@ -0,0 +1,119 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "MamelistMetadata.h"
#include "DB.h"
#include "../Utility/Log.h"
#include "Metadata.h"
#include <rapidxml.hpp>
#include <fstream>
#include <sstream>
#include <vector>
#include <sqlite3.h>
MamelistMetadata::MamelistMetadata(DB *dbInstance)
: DBInstance(dbInstance)
{
}
MamelistMetadata::~MamelistMetadata()
{
}
bool MamelistMetadata::Import(std::string filename, std::string collection)
{
bool retVal = true;
rapidxml::xml_document<> doc;
rapidxml::xml_node<> * rootNode;
char *error = NULL;
sqlite3 *handle = DBInstance->GetHandle();
std::ifstream f(filename.c_str());
if (!f.good())
{
Logger::Write(Logger::ZONE_ERROR, "Mamelist", "Could not find mamelist metadata file at \"" + filename + "\"");
retVal = false;
}
f.close();
if(retVal)
{
Logger::Write(Logger::ZONE_INFO, "Mamelist", "Importing mamelist file \"" + filename + "\"");
std::ifstream file(filename.c_str());
std::vector<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
buffer.push_back('\0');
doc.parse<0>(&buffer[0]);
rootNode = doc.first_node("mame");
sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", NULL, NULL, &error);
for (rapidxml::xml_node<> * game = rootNode->first_node("game"); game; game = game->next_sibling())
{
rapidxml::xml_attribute<> *nameNode = game->first_attribute("name");
rapidxml::xml_attribute<> *cloneOfXml = game->first_attribute("cloneof");
if(nameNode != NULL)
{
std::string name = nameNode->value();
rapidxml::xml_node<> *descriptionNode = game->first_node("description");
rapidxml::xml_node<> *yearNode = game->first_node("year");
rapidxml::xml_node<> *manufacturerNode = game->first_node("manufacturer");
rapidxml::xml_node<> *inputNode = game->first_node("input");
std::string description = (descriptionNode == NULL) ? nameNode->value() : descriptionNode->value();
std::string year = (yearNode == NULL) ? "" : yearNode->value();
std::string manufacturer = (manufacturerNode == NULL) ? "" : manufacturerNode->value();
std::string cloneOf = (cloneOfXml == NULL) ? "" : cloneOfXml->value();
std::string players;
std::string buttons;
if(inputNode != NULL)
{
rapidxml::xml_attribute<> *playersAttribute = inputNode->first_attribute("players");
rapidxml::xml_attribute<> *buttonsAttribute = inputNode->first_attribute("buttons");
if(playersAttribute)
{
players = playersAttribute->value();
}
if(buttonsAttribute)
{
buttons = buttonsAttribute->value();
}
}
sqlite3_stmt *stmt;
sqlite3_prepare_v2(handle,
"UPDATE OR REPLACE Meta SET title=?, year=?, manufacturer=?, players=?, buttons=?, cloneOf=? WHERE name=? AND collectionName=?;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, description.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, year.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, manufacturer.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, players.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, buttons.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, cloneOf.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 7, name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 8, collection.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
}
sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error);
}
return retVal;
}

View File

@ -0,0 +1,18 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Metadata.h"
class DB;
class MamelistMetadata : Metadata
{
public:
MamelistMetadata(DB *dbInstance);
virtual ~MamelistMetadata();
bool Import(std::string file, std::string collectionName);
private:
DB *DBInstance;
};

View File

@ -0,0 +1,10 @@
#pragma once
#include <string>
class Metadata
{
public:
virtual ~Metadata() {}
virtual bool Import(std::string file, std::string collectionName) = 0;
};

326
Source/Execute/Launcher.cpp Normal file
View File

@ -0,0 +1,326 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "Launcher.h"
#include "../Collection/Item.h"
#include "../Utility/Log.h"
#include "../Database/Configuration.h"
#include "../Utility/Utils.h"
#include "../RetroFE.h"
#include "../SDL.h"
#include <cstdlib>
#include <locale>
#include <sstream>
#include <fstream>
#ifdef WIN32
#include <windows.h>
#include <cstring>
#endif
Launcher::Launcher(RetroFE *p)
: Config(p->GetConfiguration())
, RetroFEInst(p)
{
}
bool Launcher::Run(std::string collection, Item *collectionItem)
{
std::string launcherName = collectionItem->GetLauncher();
std::string executablePath;
std::string selectedItemsDirectory;
std::string selectedItemsPath;
std::string currentDirectory;
std::string extensions;
std::string matchedExtension;
std::string args;
if(!GetLauncherExecutable(executablePath, currentDirectory, launcherName))
{
Logger::Write(Logger::ZONE_ERROR, "Launcher", "Failed to find launcher executable (launcher: " + launcherName + " executable: " + executablePath + ")");
return false;
}
if(!GetExtensions(extensions, collection))
{
Logger::Write(Logger::ZONE_ERROR, "Launcher", "No file extensions configured for collection \"" + collection + "\"");
return false;
}
if(!GetCollectionDirectory(selectedItemsDirectory, collection))
{
Logger::Write(Logger::ZONE_ERROR, "Launcher", "Could not find files in directory \"" + selectedItemsDirectory + "\" for collection \"" + collection + "\"");
return false;
}
if(!GetLauncherArgs(args, launcherName))
{
Logger::Write(Logger::ZONE_ERROR, "Launcher", "No launcher arguments specified for launcher " + launcherName);
return false;
}
if(!FindFile(selectedItemsPath, matchedExtension, selectedItemsDirectory, collectionItem->GetName(), extensions))
{
// FindFile() prints out diagnostic messages for us, no need to print anything here
return false;
}
args = ReplaceVariables(args,
selectedItemsPath,
collectionItem->GetName(),
collectionItem->GetFileName(),
selectedItemsDirectory,
collection);
executablePath = ReplaceVariables(executablePath,
selectedItemsPath,
collectionItem->GetName(),
collectionItem->GetFileName(),
selectedItemsDirectory,
collection);
currentDirectory = ReplaceVariables(currentDirectory,
selectedItemsPath,
collectionItem->GetName(),
collectionItem->GetFileName(),
selectedItemsDirectory,
collection);
if(!ExecuteCommand(executablePath, args, currentDirectory))
{
Logger::Write(Logger::ZONE_ERROR, "Launcher", "Failed to launch.");
return false;
}
return true;
}
std::string Launcher::ReplaceVariables(std::string str,
std::string itemFilePath,
std::string itemName,
std::string itemFilename,
std::string itemDirectory,
std::string itemCollectionName)
{
str = Utils::Replace(str, "%ITEM_FILEPATH%", itemFilePath);
str = Utils::Replace(str, "%ITEM_NAME%", itemName);
str = Utils::Replace(str, "%ITEM_FILENAME%", itemFilename);
str = Utils::Replace(str, "%ITEM_DIRECTORY%", itemDirectory);
str = Utils::Replace(str, "%ITEM_COLLECTION_NAME%", itemCollectionName);
str = Utils::Replace(str, "%RETROFE_PATH%", Configuration::GetAbsolutePath());
#ifdef WIN32
str = Utils::Replace(str, "%RETROFE_EXEC_PATH%", Configuration::GetAbsolutePath() + "/RetroFE.exe");
#else
str = Utils::Replace(str, "%RETROFE_EXEC_PATH%", Configuration::GetAbsolutePath() + "/RetroFE");
#endif
return str;
}
bool Launcher::ExecuteCommand(std::string executable, std::string args, std::string currentDirectory)
{
bool retVal = false;
std::string executionString = "\"" + executable + "\" " + args;
Logger::Write(Logger::ZONE_INFO, "Launcher", "Attempting to launch: " + executionString);
Logger::Write(Logger::ZONE_INFO, "Launcher", " from within folder: " + currentDirectory);
//todo: use delegation instead of depending on knowing the RetroFE class (tie to an interface)
RetroFEInst->LaunchEnter();
#ifdef WIN32
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
char applicationName[256];
char currDir[256];
memset(&applicationName, 0, sizeof(applicationName));
memset(&startupInfo, 0, sizeof(startupInfo));
memset(&processInfo, 0, sizeof(processInfo));
strncpy(applicationName, executionString.c_str(), sizeof(applicationName));
strncpy(currDir, currentDirectory.c_str(), sizeof(currDir));
startupInfo.dwFlags = STARTF_USESTDHANDLES;
startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startupInfo.wShowWindow = SW_SHOWDEFAULT;
if(!CreateProcess(NULL, applicationName, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo))
#else
if(system(executionString.c_str()) != 0)
#endif
{
Logger::Write(Logger::ZONE_ERROR, "Launcher", "Failed to run: " + executable);
}
else
{
#ifdef WIN32
while(WAIT_OBJECT_0 != MsgWaitForMultipleObjects(1, &processInfo.hProcess, FALSE, INFINITE, QS_ALLINPUT))
{
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
DispatchMessage(&msg);
}
}
// result = GetExitCodeProcess(processInfo.hProcess, &exitCode);
CloseHandle(processInfo.hProcess);
#endif
retVal = true;
}
Logger::Write(Logger::ZONE_INFO, "Launcher", "Completed");
RetroFEInst->LaunchExit();
return retVal;
}
bool Launcher::GetLauncherName(std::string &launcherName, std::string collection)
{
std::string launcherKey = "collections." + collection + ".launcher";
// find the launcher for the particular item
if(!Config->GetProperty(launcherKey, launcherName))
{
std::stringstream ss;
ss << "Launch failed. Could not find a configured launcher for collection \""
<< collection
<< "\" (could not find a property for \""
<< launcherKey
<< "\")";
Logger::Write(Logger::ZONE_ERROR, "Launcher", ss.str());
return false;
}
std::stringstream ss;
ss << "collections."
<< collection
<< " is configured to use launchers."
<< launcherName
<< "\"";
Logger::Write(Logger::ZONE_DEBUG, "Launcher", ss.str());
return true;
}
bool Launcher::GetLauncherExecutable(std::string &executable, std::string &currentDirectory, std::string launcherName)
{
std::string executableKey = "launchers." + launcherName + ".executable";
if(!Config->GetProperty(executableKey, executable))
{
return false;
}
std::string currentDirectoryKey = "launchers." + launcherName + ".currentDirectory";
currentDirectory = Utils::GetDirectory(executable);
Config->GetProperty(currentDirectoryKey, currentDirectory);
return true;
}
bool Launcher::GetLauncherArgs(std::string &args, std::string launcherName)
{
std::string argsKey = "launchers." + launcherName + ".arguments";
if(!Config->GetProperty(argsKey, args))
{
Logger::Write(Logger::ZONE_ERROR, "Launcher", "No arguments specified for: " + argsKey);
return false;
}
return true;
}
bool Launcher::GetExtensions(std::string &extensions, std::string collection)
{
std::string extensionsKey = "collections." + collection + ".list.extensions";
if(!Config->GetProperty(extensionsKey, extensions))
{
Logger::Write(Logger::ZONE_ERROR, "Launcher", "No extensions specified for: " + extensionsKey);
return false;
}
extensions = Utils::Replace(extensions, " ", "");
extensions = Utils::Replace(extensions, ".", "");
return true;
}
bool Launcher::GetCollectionDirectory(std::string &directory, std::string collection)
{
std::string itemsPathKey = "collections." + collection + ".list.path";
std::string itemsPathValue;
// find the items path folder (i.e. ROM path)
if(!Config->GetPropertyAbsolutePath(itemsPathKey, itemsPathValue))
{
directory = "";
}
else
{
directory += itemsPathValue + "/";
}
return true;
}
bool Launcher::FindFile(std::string &foundFilePath, std::string &foundFilename, std::string directory, std::string filenameWithoutExtension, std::string extensions)
{
std::string extension;
bool fileFound = false;
std::stringstream ss;
ss << extensions;
while(!fileFound && std::getline(ss, extension, ',') )
{
std::string selectedItemsPath = directory + filenameWithoutExtension + "." + extension;
std::ifstream f(selectedItemsPath.c_str());
if (f.good())
{
std::stringstream ss;
ss <<"Checking to see if \""
<< selectedItemsPath << "\" exists [Yes]";
fileFound = true;
Logger::Write(Logger::ZONE_INFO, "Launcher", ss.str());
foundFilePath = selectedItemsPath;
foundFilename = extension;
}
else
{
std::stringstream ss;
ss << "Checking to see if \""
<< selectedItemsPath << "\" exists [No]";
Logger::Write(Logger::ZONE_WARNING, "Launcher", ss.str());
}
f.close();
}
// get the launchers executable
if(!fileFound)
{
std::stringstream ss;
ss <<"Could not find any files with the name \""
<< filenameWithoutExtension << "\" in folder \""
<< directory;
Logger::Write(Logger::ZONE_ERROR, "Launcher", ss.str());
}
return fileFound;
}

40
Source/Execute/Launcher.h Normal file
View File

@ -0,0 +1,40 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <string>
class Configuration;
class Item;
class RetroFE;
class Launcher
{
public:
Launcher(RetroFE *p);
bool Run(std::string collection, Item *collectionItem);
private:
std::string ReplaceString(
std::string subject,
const std::string &search,
const std::string &replace);
bool GetLauncherName(std::string &launcherName, std::string collection);
bool GetLauncherExecutable(std::string &executable, std::string &currentDirectory, std::string launcherName);
bool GetLauncherArgs(std::string &args, std::string launcherName);
bool GetExtensions(std::string &extensions, std::string launcherName);
bool GetCollectionDirectory(std::string &directory, std::string collection);
bool ExecuteCommand(std::string executable, std::string arguments, std::string currentDirectory);
bool FindFile(std::string &foundFilePath, std::string &foundFilename, std::string directory, std::string filenameWithoutExtension, std::string extensions);
std::string ReplaceVariables(std::string str,
std::string itemFilePath,
std::string itemName,
std::string itemFilename,
std::string itemDirectory,
std::string itemCollectionName);
Configuration *Config;
RetroFE *RetroFEInst;
};

View File

@ -0,0 +1,370 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "Tween.h"
#include <algorithm>
#define _USE_MATH_DEFINES
#include <math.h>
#include <string>
std::map<std::string, TweenAlgorithm> Tween::TweenTypeMap;
std::map<std::string, TweenProperty> Tween::TweenPropertyMap;
Tween::Tween(TweenProperty property, TweenAlgorithm type, double start, double end, double duration)
: Property(property)
, Type(type)
, Start(start)
, End(end)
, Duration(duration)
{
}
TweenProperty Tween::GetProperty() const
{
return Property;
}
bool Tween::GetTweenProperty(std::string name, TweenProperty &property)
{
bool retVal = false;
if(TweenPropertyMap.size() == 0)
{
TweenPropertyMap["x"] = TWEEN_PROPERTY_X;
TweenPropertyMap["y"] = TWEEN_PROPERTY_Y;
TweenPropertyMap["angle"] = TWEEN_PROPERTY_ANGLE;
TweenPropertyMap["transparency"] = TWEEN_PROPERTY_TRANSPARENCY;
TweenPropertyMap["width"] = TWEEN_PROPERTY_WIDTH;
TweenPropertyMap["height"] = TWEEN_PROPERTY_HEIGHT;
TweenPropertyMap["xorigin"] = TWEEN_PROPERTY_X_ORIGIN;
TweenPropertyMap["yorigin"] = TWEEN_PROPERTY_Y_ORIGIN;
TweenPropertyMap["xoffset"] = TWEEN_PROPERTY_X_OFFSET;
TweenPropertyMap["yoffset"] = TWEEN_PROPERTY_Y_OFFSET;
TweenPropertyMap["fontSize"] = TWEEN_PROPERTY_FONT_SIZE;
}
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
if(TweenPropertyMap.find(name) != TweenPropertyMap.end())
{
property = TweenPropertyMap[name];
retVal = true;
}
return retVal;
}
TweenAlgorithm Tween::GetTweenType(std::string name)
{
if(TweenTypeMap.size() == 0)
{
TweenTypeMap["easeinquadratic"] = EASE_IN_QUADRATIC;
TweenTypeMap["easeoutquadratic"] = EASE_OUT_QUADRATIC;
TweenTypeMap["easeinoutquadratic"] = EASE_INOUT_QUADRATIC;
TweenTypeMap["easeincubic"] = EASE_IN_CUBIC;
TweenTypeMap["easeoutcubic"] = EASE_OUT_CUBIC;
TweenTypeMap["easeinoutcubic"] = EASE_INOUT_CUBIC;
TweenTypeMap["easeinquartic"] = EASE_IN_QUARTIC;
TweenTypeMap["easeoutquartic"] = EASE_OUT_QUARTIC;
TweenTypeMap["easeinoutquartic"] = EASE_INOUT_QUARTIC;
TweenTypeMap["easeinquintic"] = EASE_IN_QUINTIC;
TweenTypeMap["easeoutquintic"] = EASE_OUT_QUINTIC;
TweenTypeMap["easeinoutquintic"] = EASE_INOUT_QUINTIC;
TweenTypeMap["easeinsine"] = EASE_IN_SINE;
TweenTypeMap["easeoutsine"] = EASE_OUT_SINE;
TweenTypeMap["easeinoutsine"] = EASE_INOUT_SINE;
TweenTypeMap["easeinexponential"] = EASE_IN_EXPONENTIAL;
TweenTypeMap["easeoutexponential"] = EASE_OUT_EXPONENTIAL;
TweenTypeMap["easeinoutexponential"] = EASE_INOUT_EXPONENTIAL;
TweenTypeMap["easeincircular"] = EASE_IN_CIRCULAR;
TweenTypeMap["easeoutcircular"] = EASE_OUT_CIRCULAR;
TweenTypeMap["easeinoutcircular"] = EASE_INOUT_CIRCULAR;
TweenTypeMap["linear"] = LINEAR;
}
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
if(TweenTypeMap.find(name) != TweenTypeMap.end())
{
return TweenTypeMap[name];
}
else
{
return TweenTypeMap["linear"];
}
}
float Tween::Animate(double elapsedTime)
{
return AnimateSingle(Type, Start, End, Duration, elapsedTime);
}
//todo: SDL likes floats, consider having casting being performed elsewhere
float Tween::AnimateSingle(TweenAlgorithm type, double start, double end, double duration, double elapsedTime)
{
double a = start;
double b = end - start;
double result = 0;
switch(type)
{
case EASE_IN_QUADRATIC:
result = EaseInQuadratic(elapsedTime, duration, a, b);
break;
case EASE_OUT_QUADRATIC:
result = EaseOutQuadratic(elapsedTime, duration, a, b);
break;
case EASE_INOUT_QUADRATIC:
result = EaseInOutQuadratic(elapsedTime, duration, a, b);
break;
case EASE_IN_CUBIC:
result = EaseInCubic(elapsedTime, duration, a, b);
break;
case EASE_OUT_CUBIC:
result = EaseOutCubic(elapsedTime, duration, a, b);
break;
case EASE_INOUT_CUBIC:
result = EaseInOutCubic(elapsedTime, duration, a, b);
break;
case EASE_IN_QUARTIC:
result = EaseInQuartic(elapsedTime, duration, a, b);
break;
case EASE_OUT_QUARTIC:
result = EaseOutQuartic(elapsedTime, duration, a, b);
break;
case EASE_INOUT_QUARTIC:
result = EaseInOutQuartic(elapsedTime, duration, a, b);
break;
case EASE_IN_QUINTIC:
result = EaseInQuintic(elapsedTime, duration, a, b);
break;
case EASE_OUT_QUINTIC:
result = EaseOutQuintic(elapsedTime, duration, a, b);
break;
case EASE_INOUT_QUINTIC:
result = EaseInOutQuintic(elapsedTime, duration, a, b);
break;
case EASE_IN_SINE:
result = EaseInSine(elapsedTime, duration, a, b);
break;
case EASE_OUT_SINE:
result = EaseOutSine(elapsedTime, duration, a, b);
break;
case EASE_INOUT_SINE:
result = EaseInOutSine(elapsedTime, duration, a, b);
break;
case EASE_IN_EXPONENTIAL:
result = EaseInExponential(elapsedTime, duration, a, b);
break;
case EASE_OUT_EXPONENTIAL:
result = EaseOutExponential(elapsedTime, duration, a, b);
break;
case EASE_INOUT_EXPONENTIAL:
result = EaseInOutExponential(elapsedTime, duration, a, b);
break;
case EASE_IN_CIRCULAR:
result = EaseInCircular(elapsedTime, duration, a, b);
break;
case EASE_OUT_CIRCULAR:
result = EaseOutCircular(elapsedTime, duration, a, b);
break;
case EASE_INOUT_CIRCULAR:
result = EaseInOutCircular(elapsedTime, duration, a, b);
break;
case LINEAR:
default:
result = Linear(elapsedTime, duration, a, b);
break;
}
return static_cast<float>(result);
}
double Tween::Linear(double t, double d, double b, double c)
{
if(d == 0) return b;
return c*t/d + b;
};
double Tween::EaseInQuadratic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return c*t*t + b;
};
double Tween::EaseOutQuadratic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return -c * t*(t-2) + b;
};
double Tween::EaseInOutQuadratic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d/2;
if (t < 1) return c/2*t*t + b;
t--;
return -c/2 * (t*(t-2) - 1) + b;
};
double Tween::EaseInCubic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return c*t*t*t + b;
};
double Tween::EaseOutCubic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
t--;
return c*(t*t*t + 1) + b;
};
double Tween::EaseInOutCubic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d/2;
if (t < 1) return c/2*t*t*t + b;
t -= 2;
return c/2*(t*t*t + 2) + b;
};
double Tween::EaseInQuartic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return c*t*t*t*t + b;
};
double Tween::EaseOutQuartic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
t--;
return -c * (t*t*t*t - 1) + b;
};
double Tween::EaseInOutQuartic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d/2;
if (t < 1) return c/2*t*t*t*t + b;
t -= 2;
return -c/2 * (t*t*t*t - 2) + b;
};
double Tween::EaseInQuintic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return c*t*t*t*t*t + b;
};
double Tween::EaseOutQuintic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
t--;
return c*(t*t*t*t*t + 1) + b;
};
double Tween::EaseInOutQuintic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d/2;
if (t < 1) return c/2*t*t*t*t*t + b;
t -= 2;
return c/2*(t*t*t*t*t + 2) + b;
};
double Tween::EaseInSine(double t, double d, double b, double c)
{
return -c * cos(t/d * (M_PI/2)) + c + b;
};
double Tween::EaseOutSine(double t, double d, double b, double c)
{
return c * sin(t/d * (M_PI/2)) + b;
};
double Tween::EaseInOutSine(double t, double d, double b, double c)
{
return -c/2 * (cos( M_PI*t/d) - 1) + b;
};
double Tween::EaseInExponential(double t, double d, double b, double c)
{
return c * pow( 2, 10 * (t/d - 1) ) + b;
};
double Tween::EaseOutExponential(double t, double d, double b, double c)
{
return c * ( - pow( 2, -10 * t/d ) + 1 ) + b;
};
double Tween::EaseInOutExponential(double t, double d, double b, double c)
{
t /= d/2;
if (t < 1) return c/2 * pow( 2, 10 * (t - 1) ) + b;
t--;
return c/2 * ( -1* pow( 2, -10 * t) + 2 ) + b;
};
double Tween::EaseInCircular(double t, double d, double b, double c)
{
t /= d;
return -c * (sqrt(1 - t*t) - 1) + b;
};
double Tween::EaseOutCircular(double t, double d, double b, double c)
{
t /= d;
t--;
return c * sqrt(1 - t*t) + b;
};
double Tween::EaseInOutCircular(double t, double d, double b, double c)
{
t /= d/2;
if (t < 1) return -c/2 * (sqrt(1 - t*t) - 1) + b;
t -= 2;
return c/2 * (sqrt(1 - t*t) + 1) + b;
}
;
//todo: sdl requires floats, should the casting be done at this layer?
float Tween::GetDuration() const
{
return static_cast<float>(Duration);
}

View File

@ -0,0 +1,55 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "TweenTypes.h"
#include <string>
#include <map>
class ViewInfo;
class Tween
{
public:
Tween(TweenProperty name, TweenAlgorithm type, double start, double end, double duration);
float Animate(double elapsedTime);
static float AnimateSingle(TweenAlgorithm type, double start, double end, double duration, double elapsedTime);
static TweenAlgorithm GetTweenType(std::string name);
static bool GetTweenProperty(std::string name, TweenProperty &property);
TweenProperty GetProperty() const;
float GetDuration() const;
private:
static double EaseInQuadratic(double elapsedTime, double duration, double b, double c);
static double EaseOutQuadratic(double elapsedTime, double duration, double b, double c);
static double EaseInOutQuadratic(double elapsedTime, double duration, double b, double c);
static double EaseInCubic(double elapsedTime, double duration, double b, double c);
static double EaseOutCubic(double elapsedTime, double duration, double b, double c);
static double EaseInOutCubic(double elapsedTime, double duration, double b, double c);
static double EaseInQuartic(double elapsedTime, double duration, double b, double c);
static double EaseOutQuartic(double elapsedTime, double duration, double b, double c);
static double EaseInOutQuartic(double elapsedTime, double duration, double b, double c);
static double EaseInQuintic(double elapsedTime, double duration, double b, double c);
static double EaseOutQuintic(double elapsedTime, double duration, double b, double c);
static double EaseInOutQuintic(double elapsedTime, double duration, double b, double c);
static double EaseInSine(double elapsedTime, double duration, double b, double c);
static double EaseOutSine(double elapsedTime, double duration, double b, double c);
static double EaseInOutSine(double elapsedTime, double duration, double b, double c);
static double EaseInExponential(double elapsedTime, double duration, double b, double c);
static double EaseOutExponential(double elapsedTime, double duration, double b, double c);
static double EaseInOutExponential(double elapsedTime, double duration, double b, double c);
static double EaseInCircular(double elapsedTime, double duration, double b, double c);
static double EaseOutCircular(double elapsedTime, double duration, double b, double c);
static double EaseInOutCircular(double elapsedTime, double duration, double b, double c);
static double Linear(double elapsedTime, double duration, double b, double c);
static std::map<std::string, TweenAlgorithm> TweenTypeMap;
static std::map<std::string, TweenProperty> TweenPropertyMap;
TweenProperty Property;
TweenAlgorithm Type;
double Start;
double End;
double Duration;
};

View File

@ -0,0 +1,45 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
enum TweenAlgorithm
{
LINEAR,
EASE_IN_QUADRATIC,
EASE_OUT_QUADRATIC,
EASE_INOUT_QUADRATIC,
EASE_IN_CUBIC,
EASE_OUT_CUBIC,
EASE_INOUT_CUBIC,
EASE_IN_QUARTIC,
EASE_OUT_QUARTIC,
EASE_INOUT_QUARTIC,
EASE_IN_QUINTIC,
EASE_OUT_QUINTIC,
EASE_INOUT_QUINTIC,
EASE_IN_SINE,
EASE_OUT_SINE,
EASE_INOUT_SINE,
EASE_IN_EXPONENTIAL,
EASE_OUT_EXPONENTIAL,
EASE_INOUT_EXPONENTIAL,
EASE_IN_CIRCULAR,
EASE_OUT_CIRCULAR,
EASE_INOUT_CIRCULAR,
};
enum TweenProperty
{
TWEEN_PROPERTY_HEIGHT,
TWEEN_PROPERTY_WIDTH,
TWEEN_PROPERTY_ANGLE,
TWEEN_PROPERTY_TRANSPARENCY,
TWEEN_PROPERTY_X,
TWEEN_PROPERTY_Y,
TWEEN_PROPERTY_X_ORIGIN,
TWEEN_PROPERTY_Y_ORIGIN,
TWEEN_PROPERTY_X_OFFSET,
TWEEN_PROPERTY_Y_OFFSET,
TWEEN_PROPERTY_FONT_SIZE
};

View File

@ -0,0 +1,282 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "Component.h"
#include "../Animate/Tween.h"
#include "../../Graphics/ViewInfo.h"
#include "../../Utility/Log.h"
Component::Component()
{
OnEnterTweens = NULL;
OnExitTweens = NULL;
OnIdleTweens = NULL;
OnHighlightEnterTweens = NULL;
OnHighlightExitTweens = NULL;
SelectedItem = NULL;
NewItemSelectedSinceEnter = false;
FreeGraphicsMemory();
}
Component::~Component()
{
FreeGraphicsMemory();
}
void Component::FreeGraphicsMemory()
{
CurrentAnimationState = HIDDEN;
EnterRequested = false;
ExitRequested = false;
NewItemSelected = false;
HighlightExitComplete = false;
CurrentTweens = NULL;
CurrentTweenIndex = 0;
CurrentTweenComplete = false;
ElapsedTweenTime =0;
ScrollActive = false;
}
void Component::AllocateGraphicsMemory()
{
}
void Component::TriggerEnterEvent()
{
EnterRequested = true;
}
void Component::TriggerExitEvent()
{
ExitRequested = true;
}
void Component::TriggerHighlightEvent(Item *selectedItem)
{
NewItemSelected = true;
this->SelectedItem = selectedItem;
}
bool Component::IsIdle()
{
return (CurrentAnimationState == IDLE);
}
bool Component::IsHidden()
{
return (CurrentAnimationState == HIDDEN);
}
bool Component::IsWaiting()
{
return (CurrentAnimationState == HIGHLIGHT_WAIT);
}
void Component::Update(float dt)
{
ElapsedTweenTime += dt;
HighlightExitComplete = false;
if(IsHidden() || IsWaiting() || (IsIdle() && ExitRequested))
{
CurrentTweenComplete = true;
}
if(CurrentTweenComplete)
{
CurrentTweens = NULL;
// There was no request to override our state path. Continue on as normal.
switch(CurrentAnimationState)
{
case ENTER:
CurrentTweens = OnHighlightEnterTweens;
CurrentAnimationState = HIGHLIGHT_ENTER;
break;
case EXIT:
CurrentTweens = NULL;
CurrentAnimationState = HIDDEN;
break;
case HIGHLIGHT_ENTER:
CurrentTweens = OnIdleTweens;
CurrentAnimationState = IDLE;
break;
case IDLE:
// prevent us from automatically jumping to the exit tween upon enter
if(EnterRequested)
{
EnterRequested = false;
NewItemSelected = false;
}
else if(IsScrollActive() || NewItemSelected || ExitRequested)
{
CurrentTweens = OnHighlightExitTweens;
CurrentAnimationState = HIGHLIGHT_EXIT;
}
else
{
CurrentTweens = OnIdleTweens;
CurrentAnimationState = IDLE;
}
break;
case HIGHLIGHT_EXIT:
// intentionally break down
case HIGHLIGHT_WAIT:
if(ExitRequested && (CurrentAnimationState == HIGHLIGHT_WAIT))
{
CurrentTweens = OnHighlightExitTweens;
CurrentAnimationState = HIGHLIGHT_EXIT;
}
else if(ExitRequested && (CurrentAnimationState == HIGHLIGHT_EXIT))
{
CurrentTweens = OnExitTweens;
CurrentAnimationState = EXIT;
ExitRequested = false;
}
else if(IsScrollActive())
{
CurrentTweens = NULL;
CurrentAnimationState = HIGHLIGHT_WAIT;
}
else if(NewItemSelected)
{
CurrentTweens = OnHighlightEnterTweens;
CurrentAnimationState = HIGHLIGHT_ENTER;
HighlightExitComplete = true;
NewItemSelected = false;
}
else
{
CurrentTweens = NULL;
CurrentAnimationState = HIGHLIGHT_WAIT;
}
break;
case HIDDEN:
if(EnterRequested || ExitRequested)
{
CurrentTweens = OnEnterTweens;
CurrentAnimationState = ENTER;
}
else
{
CurrentTweens = NULL;
CurrentAnimationState = HIDDEN;
}
}
CurrentTweenIndex = 0;
CurrentTweenComplete = false;
ElapsedTweenTime = 0;
}
CurrentTweenComplete = Animate(IsIdle());
}
bool Component::Animate(bool loop)
{
bool completeDone = false;
if(!CurrentTweens || CurrentTweenIndex >= CurrentTweens->size())
{
completeDone = true;
}
else if(CurrentTweens)
{
bool currentDone = true;
std::vector<Tween *> *tweenSet = CurrentTweens->at(CurrentTweenIndex);
for(unsigned int i = 0; i < tweenSet->size(); i++)
{
Tween *tween = tweenSet->at(i);
float elapsedTime = ElapsedTweenTime;
//todo: too many levels of nesting
if(elapsedTime < tween->GetDuration())
{
currentDone = false;
}
else
{
elapsedTime = tween->GetDuration();
}
float value = tween->Animate(elapsedTime);
switch(tween->GetProperty())
{
case TWEEN_PROPERTY_X:
GetBaseViewInfo()->SetX(value);
break;
case TWEEN_PROPERTY_Y:
GetBaseViewInfo()->SetY(value);
break;
case TWEEN_PROPERTY_HEIGHT:
GetBaseViewInfo()->SetHeight(value);
break;
case TWEEN_PROPERTY_WIDTH:
GetBaseViewInfo()->SetWidth(value);
break;
case TWEEN_PROPERTY_ANGLE:
GetBaseViewInfo()->SetAngle(value);
break;
case TWEEN_PROPERTY_TRANSPARENCY:
GetBaseViewInfo()->SetTransparency(value);
break;
case TWEEN_PROPERTY_X_ORIGIN:
GetBaseViewInfo()->SetXOrigin(value);
break;
case TWEEN_PROPERTY_Y_ORIGIN:
GetBaseViewInfo()->SetYOrigin(value);
break;
case TWEEN_PROPERTY_X_OFFSET:
GetBaseViewInfo()->SetXOffset(value);
break;
case TWEEN_PROPERTY_Y_OFFSET:
GetBaseViewInfo()->SetYOffset(value);
break;
case TWEEN_PROPERTY_FONT_SIZE:
GetBaseViewInfo()->SetFontSize(value);
break;
}
}
if(currentDone)
{
CurrentTweenIndex++;
ElapsedTweenTime = 0;
}
}
if(!CurrentTweens || CurrentTweenIndex >= CurrentTweens->size())
{
if(loop)
{
CurrentTweenIndex = 0;
}
completeDone = true;
}
return completeDone;
}

View File

@ -0,0 +1,122 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <vector>
#include "../MenuNotifierInterface.h"
#include "../ViewInfo.h"
#include "../Animate/Tween.h"
#include "../../Collection/Item.h"
class Component
{
public:
Component();
virtual ~Component();
virtual void FreeGraphicsMemory();
virtual void AllocateGraphicsMemory();
virtual void LaunchEnter() {}
virtual void LaunchExit() {}
void TriggerEnterEvent();
void TriggerExitEvent();
void TriggerHighlightEvent(Item *selectedItem);
bool IsIdle();
bool IsHidden();
bool IsWaiting();
typedef std::vector<std::vector<Tween *> *> TweenSets;
void SetOnEnterTweens(TweenSets *tweens)
{
this->OnEnterTweens = tweens;
}
void SetOnExitTweens(TweenSets *tweens)
{
this->OnExitTweens = tweens;
}
void SetOnIdleTweens(TweenSets *tweens)
{
this->OnIdleTweens = tweens;
}
void SetOnHighlightEnterTweens(TweenSets *tweens)
{
this->OnHighlightEnterTweens = tweens;
}
void SetOnHighlightExitTweens(TweenSets *tweens)
{
this->OnHighlightExitTweens = tweens;
}
virtual void Update(float dt);
virtual void Draw() = 0;
ViewInfo *GetBaseViewInfo()
{
return &BaseViewInfo;
}
void UpdateBaseViewInfo(ViewInfo &info)
{
BaseViewInfo = info;
}
bool IsScrollActive() const
{
return ScrollActive;
}
void SetScrollActive(bool scrollActive)
{
ScrollActive = scrollActive;
}
protected:
Item *GetSelectedItem()
{
return SelectedItem;
}
enum AnimationState
{
IDLE,
ENTER,
HIGHLIGHT_EXIT,
HIGHLIGHT_WAIT,
HIGHLIGHT_ENTER,
EXIT,
HIDDEN
};
AnimationState CurrentAnimationState;
bool EnterRequested;
bool ExitRequested;
bool NewItemSelected;
bool HighlightExitComplete;
bool NewItemSelectedSinceEnter;
private:
bool Animate(bool loop);
bool IsTweenSequencingComplete();
void ResetTweenSequence(std::vector<ViewInfo *> *tweens);
TweenSets *OnEnterTweens;
TweenSets *OnExitTweens;
TweenSets *OnIdleTweens;
TweenSets *OnHighlightEnterTweens;
TweenSets *OnHighlightExitTweens;
TweenSets *CurrentTweens;
unsigned int CurrentTweenIndex;
bool CurrentTweenComplete;
ViewInfo BaseViewInfo;
float ElapsedTweenTime;
Tween *TweenInst;
Item *SelectedItem;
bool ScrollActive;
};

View File

@ -0,0 +1,75 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "Image.h"
#include "../ViewInfo.h"
#include "../../SDL.h"
#include "../../Utility/Log.h"
#include <SDL2/SDL_image.h>
Image::Image(std::string file, float scaleX, float scaleY)
: Texture(NULL)
, File(file)
, ScaleX(scaleX)
, ScaleY(scaleY)
{
AllocateGraphicsMemory();
}
Image::~Image()
{
FreeGraphicsMemory();
}
void Image::FreeGraphicsMemory()
{
Component::FreeGraphicsMemory();
SDL_LockMutex(SDL::GetMutex());
if (Texture != NULL)
{
SDL_DestroyTexture(Texture);
Texture = NULL;
}
SDL_UnlockMutex(SDL::GetMutex());
}
void Image::AllocateGraphicsMemory()
{
int width;
int height;
Component::AllocateGraphicsMemory();
if(!Texture)
{
SDL_LockMutex(SDL::GetMutex());
Texture = IMG_LoadTexture(SDL::GetRenderer(), File.c_str());
if (Texture != NULL)
{
SDL_SetTextureBlendMode(Texture, SDL_BLENDMODE_BLEND);
SDL_QueryTexture(Texture, NULL, NULL, &width, &height);
GetBaseViewInfo()->SetImageWidth(width * ScaleX);
GetBaseViewInfo()->SetImageHeight(height * ScaleY);
}
SDL_UnlockMutex(SDL::GetMutex());
}
}
void Image::Draw()
{
if(Texture)
{
ViewInfo *info = GetBaseViewInfo();
SDL_Rect rect;
rect.x = static_cast<int>(info->GetXRelativeToOrigin());
rect.y = static_cast<int>(info->GetYRelativeToOrigin());
rect.h = static_cast<int>(info->GetHeight());
rect.w = static_cast<int>(info->GetWidth());
SDL::RenderCopy(Texture, static_cast<char>((info->GetTransparency() * 255)), NULL, &rect, info->GetAngle());
}
}

View File

@ -0,0 +1,24 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Component.h"
#include <SDL2/SDL.h>
#include <string>
class Image : public Component
{
public:
Image(std::string file, float scaleX, float scaleY);
virtual ~Image();
void FreeGraphicsMemory();
void AllocateGraphicsMemory();
void Draw();
protected:
SDL_Texture *Texture;
std::string File;
float ScaleX;
float ScaleY;
};

View File

@ -0,0 +1,30 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "ImageBuilder.h"
#include "../../Utility/Utils.h"
#include "../../Utility/Log.h"
#include <fstream>
Image * ImageBuilder::CreateImage(std::string path, std::string name, float scaleX, float scaleY)
{
Image *image = NULL;
std::vector<std::string> extensions;
extensions.push_back("png");
extensions.push_back("PNG");
extensions.push_back("jpg");
extensions.push_back("JPG");
extensions.push_back("jpeg");
extensions.push_back("JPEG");
std::string prefix = path + "/" + name;
std::string file;
if(Utils::FindMatchingFile(prefix, extensions, file))
{
image = new Image(file, scaleX, scaleY);
}
return image;
}

View File

@ -0,0 +1,15 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Image.h"
#include "VideoComponent.h"
#include "../../Video/VideoFactory.h"
//todo: this is more of a factory than a builder
class ImageBuilder
{
public:
Image * CreateImage(std::string path, std::string name, float scaleX, float scaleY);
};

View File

@ -0,0 +1,172 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "ReloadableMedia.h"
#include "ImageBuilder.h"
#include "VideoBuilder.h"
#include "../ViewInfo.h"
#include "../../Video/VideoFactory.h"
#include "../../Database/Configuration.h"
#include "../../Utility/Log.h"
#include "../../Utility/Utils.h"
#include "../../SDL.h"
#include <fstream>
#include <vector>
#include <iostream>
ReloadableMedia::ReloadableMedia(std::string imagePath, std::string videoPath, bool isVideo, float scaleX, float scaleY)
: LoadedComponent(NULL)
, ImagePath(imagePath)
, VideoPath(videoPath)
, ReloadRequested(false)
, FirstLoad(true)
, IsVideo(isVideo)
, ScaleX(scaleX)
, ScaleY(scaleY)
{
AllocateGraphicsMemory();
}
ReloadableMedia::~ReloadableMedia()
{
if (LoadedComponent != NULL)
{
delete LoadedComponent;
}
}
void ReloadableMedia::Update(float dt)
{
if(NewItemSelected)
{
ReloadRequested = true;
}
// wait for the right moment to reload the image
if (ReloadRequested && (HighlightExitComplete || FirstLoad))
{
ReloadTexture();
ReloadRequested = false;
FirstLoad = false;
}
if(LoadedComponent)
{
LoadedComponent->Update(dt);
}
// needs to be ran at the end to prevent the NewItemSelected flag from being detected
Component::Update(dt);
}
void ReloadableMedia::AllocateGraphicsMemory()
{
FirstLoad = true;
if(LoadedComponent)
{
LoadedComponent->AllocateGraphicsMemory();
}
// NOTICE! needs to be done last to prevent flags from being missed
Component::AllocateGraphicsMemory();
}
void ReloadableMedia::LaunchEnter()
{
if(LoadedComponent)
{
LoadedComponent->LaunchEnter();
}
}
void ReloadableMedia::LaunchExit()
{
if(LoadedComponent)
{
LoadedComponent->LaunchExit();
}
}
void ReloadableMedia::FreeGraphicsMemory()
{
Component::FreeGraphicsMemory();
if(LoadedComponent)
{
LoadedComponent->FreeGraphicsMemory();
}
}
void ReloadableMedia::ReloadTexture()
{
bool found = false;
if(LoadedComponent)
{
delete LoadedComponent;
LoadedComponent = NULL;
}
Item *selectedItem = GetSelectedItem();
if (selectedItem != NULL)
{
if(IsVideo)
{
std::vector<std::string> names;
names.push_back(selectedItem->GetName());
if(selectedItem->GetCloneOf().length() > 0)
{
names.push_back(selectedItem->GetCloneOf());
}
for(unsigned int n = 0; n < names.size() && !found; ++n)
{
std::string filePrefix;
filePrefix.append(VideoPath);
filePrefix.append("/");
filePrefix.append(names[n]);
std::string file;
VideoBuilder videoBuild;
LoadedComponent = videoBuild.CreateVideo(VideoPath, names[n], ScaleX, ScaleY);
if(LoadedComponent)
{
LoadedComponent->AllocateGraphicsMemory();
found = true;
}
}
}
if(!LoadedComponent)
{
ImageBuilder imageBuild;
LoadedComponent = imageBuild.CreateImage(ImagePath, selectedItem->GetFullTitle(), ScaleX, ScaleY);
if (LoadedComponent != NULL)
{
LoadedComponent->AllocateGraphicsMemory();
GetBaseViewInfo()->SetImageWidth(LoadedComponent->GetBaseViewInfo()->GetImageWidth());
GetBaseViewInfo()->SetImageHeight(LoadedComponent->GetBaseViewInfo()->GetImageHeight());
}
}
}
}
void ReloadableMedia::Draw()
{
ViewInfo *info = GetBaseViewInfo();
if(LoadedComponent)
{
info->SetImageHeight(LoadedComponent->GetBaseViewInfo()->GetImageHeight());
info->SetImageWidth(LoadedComponent->GetBaseViewInfo()->GetImageWidth());
LoadedComponent->UpdateBaseViewInfo(*info);
LoadedComponent->Draw();
}
}

View File

@ -0,0 +1,38 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Component.h"
#include "../../Video/IVideo.h"
#include "../../Collection/Item.h"
#include <SDL2/SDL.h>
#include <string>
class Image;
//todo: this class should aggregate Image, Text, and Video component classes
class ReloadableMedia : public Component
{
public:
ReloadableMedia(std::string imagePath, std::string videoPath, bool isVideo, float scaleX, float scaleY);
virtual ~ReloadableMedia();
void Update(float dt);
void Draw();
void FreeGraphicsMemory();
void AllocateGraphicsMemory();
void LaunchEnter();
void LaunchExit();
private:
void ReloadTexture();
Component *LoadedComponent;
std::string ImagePath;
std::string VideoPath;
bool ReloadRequested;
bool FirstLoad;
IVideo *VideoInst;
bool IsVideo;
float ScaleX;
float ScaleY;
};

View File

@ -0,0 +1,157 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "ReloadableText.h"
#include "../ViewInfo.h"
#include "../../Database/Configuration.h"
#include "../../Utility/Log.h"
#include "../../SDL.h"
#include <fstream>
#include <vector>
#include <iostream>
ReloadableText::ReloadableText(std::string type, Font *font, SDL_Color color, std::string layoutKey, std::string collection, float scaleX, float scaleY)
: ImageInst(NULL)
, LayoutKey(layoutKey)
, Collection(collection)
, ReloadRequested(false)
, FirstLoad(true)
, FontInst(font)
, FontColor(color)
, ScaleX(scaleX)
, ScaleY(scaleY)
{
Type = TextTypeUnknown;
if(type == "numberButtons")
{
Type = TextTypeNumberButtons;
}
else if(type == "numberPlayers")
{
Type = TextTypeNumberPlayers;
}
else if(type == "year")
{
Type = TextTypeYear;
}
else if(type == "title")
{
Type = TextTypeTitle;
}
else if(type == "manufacturer")
{
Type = TextTypeManufacturer;
}
AllocateGraphicsMemory();
}
ReloadableText::~ReloadableText()
{
if (ImageInst != NULL)
{
delete ImageInst;
}
}
void ReloadableText::Update(float dt)
{
if(NewItemSelected)
{
ReloadRequested = true;
}
// wait for the right moment to reload the image
if (ReloadRequested && (HighlightExitComplete || FirstLoad))
{
ReloadTexture();
ReloadRequested = false;
FirstLoad = false;
}
// needs to be ran at the end to prevent the NewItemSelected flag from being detected
Component::Update(dt);
}
void ReloadableText::AllocateGraphicsMemory()
{
FirstLoad = true;
ReloadTexture();
// NOTICE! needs to be done last to prevent flags from being missed
Component::AllocateGraphicsMemory();
}
void ReloadableText::LaunchEnter()
{
}
void ReloadableText::LaunchExit()
{
}
void ReloadableText::FreeGraphicsMemory()
{
Component::FreeGraphicsMemory();
if (ImageInst != NULL)
{
delete ImageInst;
ImageInst = NULL;
}
}
void ReloadableText::ReloadTexture()
{
if (ImageInst != NULL)
{
delete ImageInst;
ImageInst = NULL;
}
Item *selectedItem = GetSelectedItem();
if (selectedItem != NULL)
{
std::stringstream ss;
std::string text;
switch(Type)
{
case TextTypeNumberButtons:
ss << selectedItem->GetNumberButtons();
break;
case TextTypeNumberPlayers:
ss << selectedItem->GetNumberPlayers();
break;
case TextTypeYear:
ss << selectedItem->GetYear();
break;
case TextTypeTitle:
ss << selectedItem->GetTitle();
break;
case TextTypeManufacturer:
ss << selectedItem->GetManufacturer();
break;
default:
break;
}
ImageInst = new Text(ss.str(), FontInst, FontColor, ScaleX, ScaleY);
}
}
void ReloadableText::Draw()
{
ViewInfo *info = GetBaseViewInfo();
if(ImageInst)
{
ImageInst->UpdateBaseViewInfo(*info);
ImageInst->Draw();
}
}

View File

@ -0,0 +1,48 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Component.h"
#include "Text.h"
#include "../Font.h"
#include "../../Collection/Item.h"
#include <SDL2/SDL.h>
#include <string>
class ReloadableText : public Component
{
public:
ReloadableText(std::string type, Font *font, SDL_Color color, std::string layoutKey, std::string collectionName, float scaleX, float scaleY);
virtual ~ReloadableText();
void Update(float dt);
void Draw();
void FreeGraphicsMemory();
void AllocateGraphicsMemory();
void LaunchEnter();
void LaunchExit();
private:
enum TextType
{
TextTypeUnknown = 0,
TextTypeNumberButtons,
TextTypeNumberPlayers,
TextTypeYear,
TextTypeTitle,
TextTypeManufacturer,
};
void ReloadTexture();
Text *ImageInst;
TextType Type;
std::string LayoutKey;
std::string Collection;
bool ReloadRequested;
bool FirstLoad;
Font *FontInst;
SDL_Color FontColor;
float ScaleX;
float ScaleY;
};

View File

@ -0,0 +1,654 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "../Animate/Tween.h"
#include "../Animate/TweenTypes.h"
#include "../ComponentItemBinding.h"
#include "../Font.h"
#include "ScrollingList.h"
#include "ImageBuilder.h"
#include "VideoBuilder.h"
#include "VideoComponent.h"
#include "ReloadableMedia.h"
#include "Text.h"
#include "../../Database/Configuration.h" // todo: decouple the GUI from the data
#include "../../Collection/Item.h"
#include "../../Utility/Log.h"
#include "../../SDL.h"
#include "../ViewInfo.h"
#include <math.h>
#include <SDL2/SDL_image.h>
#include <sstream>
//todo: remove coupling from configuration data (if possible)
ScrollingList::ScrollingList(Configuration *c,
float scaleX,
float scaleY,
Font *font,
SDL_Color fontColor,
std::string layoutKey,
std::string collectionName,
std::string imageType)
: IsScrollChangedStarted(true)
, IsScrollChangedSignalled(false)
, IsScrollChangedComplete(false)
, SpriteList(NULL)
, ScrollPoints(NULL)
, TweenEnterTime(0)
, FirstSpriteIndex(0)
, SelectedSpriteListIndex(0)
, CurrentAnimateTime(0) // in seconds
, ScrollTime(0) // in seconds
, CurrentScrollDirection(ScrollDirectionIdle)
, RequestedScrollDirection(ScrollDirectionIdle)
, CurrentScrollState(ScrollStateIdle)
, ScrollAcceleration(6) // todo: make configurable
, ScrollVelocity(0)
, Config(c)
, ScaleX(scaleX)
, ScaleY(scaleY)
, FontInst(font)
, FontColor(fontColor)
, LayoutKey(layoutKey)
, CollectionName(collectionName)
, ImageType(imageType)
, MaxLayer(0)
{
}
ScrollingList::~ScrollingList()
{
}
void ScrollingList::SetItems(std::vector<ComponentItemBinding *> *spriteList)
{
SpriteList = spriteList;
FirstSpriteIndex = 0;
// loop the scroll points if there are not enough
unsigned int originalSize = SpriteList->size();
while(ScrollPoints && ScrollPoints->size()+4 > SpriteList->size())
{
for(unsigned int i = 0; i < originalSize; ++i)
{
Item *newItem = new Item();
Item *originalItem = SpriteList->at(i)->GetCollectionItem();
*newItem = *originalItem;
ComponentItemBinding *newSprite = new ComponentItemBinding(newItem);
SpriteList->push_back(newSprite);
}
}
for(unsigned int i = 0; SpriteList && ScrollPoints && i < SelectedSpriteListIndex; ++i)
{
CircularDecrement(FirstSpriteIndex, SpriteList);
}
IsScrollChangedComplete = true;
}
void ScrollingList::SetPoints(std::vector<ViewInfo *> *scrollPoints)
{
ScrollPoints = scrollPoints;
for(unsigned int i = 0; i != scrollPoints->size(); ++i)
{
ViewInfo *info = scrollPoints->at(i);
MaxLayer = (MaxLayer < info->GetLayer()) ? MaxLayer : info->GetLayer();
}
}
void ScrollingList::SetSelectedIndex(int selectedIndex)
{
SelectedSpriteListIndex = selectedIndex;
for(unsigned int i = 0; SpriteList && ScrollPoints && i < SelectedSpriteListIndex; ++i)
{
CircularDecrement(FirstSpriteIndex, SpriteList);
}
}
void ScrollingList::Click()
{
if(CurrentScrollDirection == ScrollDirectionBack)
{
CircularDecrement(FirstSpriteIndex, SpriteList);
IsScrollChangedComplete = true;
}
if(CurrentScrollDirection == ScrollDirectionForward)
{
CircularIncrement(FirstSpriteIndex, SpriteList);
IsScrollChangedComplete = true;
}
}
unsigned int ScrollingList::GetNextTween(unsigned int currentIndex, std::vector<ViewInfo *> *list)
{
if(CurrentScrollDirection == ScrollDirectionForward)
{
CircularDecrement(currentIndex, list);
}
else if(CurrentScrollDirection == ScrollDirectionBack)
{
CircularIncrement(currentIndex, list);
}
return currentIndex;
}
void ScrollingList::PageUp()
{
if(ScrollPoints && ScrollPoints->size() > 4)
{
ScrollVelocity = 0;
unsigned int counts = ScrollPoints->size() - 4;
for(unsigned int i = 0; i < counts; i++)
{
CircularDecrement(FirstSpriteIndex, SpriteList);
}
}
CurrentScrollState = ScrollStatePageChange;
IsScrollChangedStarted = true;
IsScrollChangedSignalled = false;
IsScrollChangedComplete = false;
}
void ScrollingList::PageDown()
{
if(ScrollPoints && ScrollPoints->size() > 4)
{
unsigned int counts = ScrollPoints->size() - 4;
ScrollVelocity = 0;
for(unsigned int i = 0; i < counts; i++)
{
CircularIncrement(FirstSpriteIndex, SpriteList);
}
}
CurrentScrollState = ScrollStatePageChange;
IsScrollChangedStarted = true;
IsScrollChangedSignalled = false;
IsScrollChangedComplete = false;
}
void ScrollingList::FreeGraphicsMemory()
{
Component::FreeGraphicsMemory();
TweenEnterTime = 0;
CurrentAnimateTime = 0;
ScrollTime = 0;
CurrentScrollDirection = ScrollDirectionIdle;
RequestedScrollDirection = ScrollDirectionIdle;
CurrentScrollState = ScrollStateIdle;
ScrollAcceleration = 6; // todo: make configurable
ScrollVelocity = 0;
for(unsigned int i = 0; i < SpriteList->size(); i++)
{
ComponentItemBinding *s = SpriteList->at(i);
DeallocateTexture(s);
}
}
void ScrollingList::Update(float dt)
{
float scrollPeriod = 0;
Component::Update(dt);
if(!ScrollPoints)
{
return;
}
switch(CurrentScrollState)
{
case ScrollStateActive:
if(RequestedScrollDirection != CurrentScrollDirection)
{
CurrentScrollState = ScrollStateStopping;
}
break;
case ScrollStateIdle:
ScrollTime = 0;
CurrentAnimateTime = 0;
ScrollVelocity = 0;
if(RequestedScrollDirection != ScrollDirectionIdle)
{
CurrentScrollState = ScrollStateActive;
CurrentScrollDirection = RequestedScrollDirection;
}
break;
default:
break;
};
if(CurrentScrollState != ScrollStatePageChange && CurrentScrollState != ScrollStateIdle)
{
IsScrollChangedStarted = true;
ScrollTime += dt;
CurrentAnimateTime += dt;
ScrollVelocity = ScrollTime * ScrollAcceleration;
// clip at 5 items scrolled per second
if(ScrollVelocity > 30)
{
ScrollVelocity = 30;
}
if(ScrollVelocity > 0)
{
scrollPeriod = 1 / ScrollVelocity;
}
// have we exceeded the time of when to stop on the next item in the list?
if(CurrentScrollState == ScrollStateStopping && CurrentAnimateTime >= scrollPeriod)
{
Click();
CurrentAnimateTime = 0;
ScrollVelocity = 0;
CurrentScrollState = ScrollStateIdle;
}
}
while(CurrentScrollState != ScrollStatePageChange && ScrollVelocity > 0 && CurrentAnimateTime >= scrollPeriod)
{
Click();
CurrentAnimateTime -= scrollPeriod;
}
if(ScrollPoints && SpriteList->size() > 0 && FirstSpriteIndex < SpriteList->size())
{
unsigned int spriteIndex = FirstSpriteIndex;
unsigned int numIterations = (ScrollPoints->size() > SpriteList->size()) ? SpriteList->size() : ScrollPoints->size();
unsigned int start = (ScrollPoints->size() > SpriteList->size()) ? SelectedSpriteListIndex : 0;
for(unsigned int i = start; i < start+numIterations; i++)
{
ComponentItemBinding *s = SpriteList->at(spriteIndex);
unsigned int nextI = GetNextTween(i, ScrollPoints);
ViewInfo *currentViewInfo = ScrollPoints->at(i);
ViewInfo *nextViewInfo = ScrollPoints->at(nextI);
AllocateTexture(s);
Component *c = s->GetComponent();
if(c)
{
currentViewInfo->SetImageHeight(c->GetBaseViewInfo()->GetImageHeight());
currentViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth());
nextViewInfo->SetImageHeight(c->GetBaseViewInfo()->GetImageHeight());
nextViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth());
//todo: 30 is a magic number
ViewInfo *spriteViewInfo = c->GetBaseViewInfo();
spriteViewInfo->SetX(Tween::AnimateSingle(LINEAR, currentViewInfo->GetX(), nextViewInfo->GetX(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetY(Tween::AnimateSingle(LINEAR, currentViewInfo->GetY(), nextViewInfo->GetY(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetXOrigin(Tween::AnimateSingle(LINEAR, currentViewInfo->GetXOrigin(), nextViewInfo->GetXOrigin(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetYOrigin(Tween::AnimateSingle(LINEAR, currentViewInfo->GetYOrigin(), nextViewInfo->GetYOrigin(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetXOffset(Tween::AnimateSingle(LINEAR, currentViewInfo->GetXOffset(), nextViewInfo->GetXOffset(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetYOffset(Tween::AnimateSingle(LINEAR, currentViewInfo->GetYOffset(), nextViewInfo->GetYOffset(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetHeight(Tween::AnimateSingle(LINEAR, currentViewInfo->GetHeight(), nextViewInfo->GetHeight(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetWidth(Tween::AnimateSingle(LINEAR, currentViewInfo->GetWidth(), nextViewInfo->GetWidth(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetTransparency(Tween::AnimateSingle(LINEAR, currentViewInfo->GetTransparency(), nextViewInfo->GetTransparency(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetAngle(Tween::AnimateSingle(LINEAR, currentViewInfo->GetAngle(), nextViewInfo->GetAngle(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetFontSize(Tween::AnimateSingle(LINEAR, currentViewInfo->GetFontSize(), nextViewInfo->GetFontSize(), scrollPeriod, CurrentAnimateTime));
c->Update(dt);
}
CircularIncrement(spriteIndex, SpriteList);
}
// start freeing up memory if the list is too large
if(SpriteList->size() + 4 > ScrollPoints->size())
{
spriteIndex = FirstSpriteIndex;
CircularDecrement(spriteIndex, SpriteList);
DeallocateTexture(SpriteList->at(spriteIndex));
CircularDecrement(spriteIndex, SpriteList);
DeallocateTexture(SpriteList->at(spriteIndex));
// point to the end of the list to start deallocating..
// It's not fast, but it's easy to read
spriteIndex = FirstSpriteIndex;
for(unsigned int i = 0; i < ScrollPoints->size(); i++)
{
CircularIncrement(spriteIndex, SpriteList);
}
CircularIncrement(spriteIndex, SpriteList);
DeallocateTexture(SpriteList->at(spriteIndex));
CircularIncrement(spriteIndex, SpriteList);
DeallocateTexture(SpriteList->at(spriteIndex));
}
}
if(IsScrollChangedStarted && !IsScrollChangedSignalled)
{
IsScrollChangedSignalled = true;
ComponentItemBinding *sprite = GetPendingCollectionItemSprite();
Item *item = NULL;
if(sprite)
{
item = sprite->GetCollectionItem();
}
for(std::vector<MenuNotifierInterface *>::iterator it = NotificationComponents.begin();
it != NotificationComponents.end();
it++)
{
MenuNotifierInterface *c = *it;
if(c && item)
{
c->OnNewItemSelected(item);
}
}
if(CurrentScrollState == ScrollStatePageChange)
{
IsScrollChangedComplete = true;
CurrentScrollState = ScrollStateIdle;
}
}
if(IsScrollChangedStarted && IsScrollChangedSignalled && IsScrollChangedComplete)
{
IsScrollChangedStarted = false;
IsScrollChangedComplete = false;
IsScrollChangedSignalled = false;
}
}
void ScrollingList::AllocateTexture(ComponentItemBinding *s)
{
//todo: move this outside of the Draw routine
if(s && s->GetComponent() == NULL)
{
const Item *item = s->GetCollectionItem();
//todo: will create a runtime fault if not of the right type
//todo: remove coupling from knowing the collection name
std::string collectionKey ="collections." + CollectionName + ".media." + ImageType;
std::string videoKey ="collections." + CollectionName + ".media.video";
std::string imagePath;
std::string videoPath;
Component *t = NULL;
/*
// todo: to be supported at a later date
if(c->GetProperty(videoKey, videoPath))
{
t = new VideoComponent(videoPath, item->GetFullTitle(), ScaleX, ScaleY);
}
*/
if(!t && Config->GetPropertyAbsolutePath(collectionKey, imagePath))
{
ImageBuilder imageBuild;
t = imageBuild.CreateImage(imagePath, item->GetName(), ScaleX, ScaleY);
if(!t && item->GetTitle() != item->GetFullTitle())
{
t = imageBuild.CreateImage(imagePath, item->GetFullTitle(), ScaleX, ScaleY);
}
}
if (!t)
{
t = new Text(item->GetTitle(), FontInst, FontColor, ScaleX, ScaleY);
}
if(t)
{
s->SetComponent(t);
}
}
}
void ScrollingList::DeallocateTexture(ComponentItemBinding *s)
{
if(s && s->GetComponent() != NULL)
{
delete s->GetComponent();
}
s->SetComponent(NULL);
}
void ScrollingList::Draw()
{
//todo: Poor design implementation.
// caller should instead call ScrollingList::Draw(unsigned int layer)
}
//todo: this is kind of a hack. Aggregation needs to happen differently
void ScrollingList::Draw(unsigned int layer)
{
if(ScrollPoints && SpriteList && SpriteList->size() > 0 && FirstSpriteIndex < SpriteList->size())
{
unsigned int spriteIndex = FirstSpriteIndex;
for(unsigned int i = 0; i < ScrollPoints->size(); i++)
{
std::vector<ComponentItemBinding *>::iterator it = SpriteList->begin() + spriteIndex;
Component *c = (*it)->GetComponent();
ViewInfo *currentViewInfo = ScrollPoints->at(i);
if(currentViewInfo && currentViewInfo->GetLayer() == layer)
{
c->Draw();
}
CircularIncrement(spriteIndex, SpriteList);
}
}
}
void ScrollingList::SetScrollDirection(ScrollDirection direction)
{
RequestedScrollDirection = direction;
}
void ScrollingList::RemoveSelectedItem()
{
ComponentItemBinding *sprite = GetSelectedCollectionItemSprite();
if(sprite)
{
Item *item = sprite->GetCollectionItem();
DeallocateTexture(sprite);
int index = (FirstSpriteIndex + SelectedSpriteListIndex) % SpriteList->size();
std::vector<ComponentItemBinding *>::iterator it = SpriteList->begin() + index;
SpriteList->erase(it);
delete sprite;
if(item)
{
delete item;
}
if(SelectedSpriteListIndex >= SpriteList->size())
{
SelectedSpriteListIndex = 0;
}
if(FirstSpriteIndex >= SpriteList->size())
{
FirstSpriteIndex = 0;
}
}
IsScrollChangedComplete = true;
}
std::vector<ComponentItemBinding *> *ScrollingList::GetCollectionItemSprites()
{
return SpriteList;
}
ComponentItemBinding* ScrollingList::GetSelectedCollectionItemSprite()
{
ComponentItemBinding *item = NULL;
if(SpriteList && SpriteList->size() > 0)
{
int index = (FirstSpriteIndex + SelectedSpriteListIndex) % SpriteList->size();
item = SpriteList->at(index);
}
return item;
}
ComponentItemBinding* ScrollingList::GetPendingCollectionItemSprite()
{
ComponentItemBinding *item = NULL;
unsigned int index = FirstSpriteIndex;
if(CurrentScrollState != ScrollStatePageChange)
{
if(CurrentScrollDirection == ScrollDirectionBack)
{
CircularDecrement(index, SpriteList);
}
if(CurrentScrollDirection == ScrollDirectionForward)
{
CircularIncrement(index, SpriteList);
}
}
if(SpriteList && SpriteList->size() > 0)
{
index = (index + SelectedSpriteListIndex) % SpriteList->size();
item = SpriteList->at(index);
}
return item;
}
void ScrollingList::AddComponentForNotifications(MenuNotifierInterface *c)
{
NotificationComponents.push_back(c);
}
void ScrollingList::RemoveComponentForNotifications(MenuNotifierInterface *c)
{
for(std::vector<MenuNotifierInterface *>::iterator it = NotificationComponents.begin();
it != NotificationComponents.end();
it++)
{
if(c == *it)
{
NotificationComponents.erase(it);
break;
}
}
}
ComponentItemBinding* ScrollingList::GetPendingSelectedCollectionItemSprite()
{
ComponentItemBinding *item = NULL;
unsigned int index = SelectedSpriteListIndex;
if(CurrentScrollDirection == ScrollDirectionBack)
{
CircularDecrement(index, SpriteList);
}
if(CurrentScrollDirection == ScrollDirectionForward)
{
CircularIncrement(index, SpriteList);
}
if(SpriteList && SpriteList->size() > 0)
{
index = (index + SelectedSpriteListIndex) % SpriteList->size();
item = SpriteList->at(index);
}
return item;
}
bool ScrollingList::IsIdle()
{
return (Component::IsIdle() && CurrentScrollState == ScrollStateIdle);
}
void ScrollingList::CircularIncrement(unsigned int &index, std::vector<ViewInfo*>* list)
{
index++;
if(index >= list->size())
{
index = 0;
}
}
void ScrollingList::CircularDecrement(unsigned int &index, std::vector<ViewInfo*>* list)
{
if(index > 0)
{
index--;
}
else
{
if(list->size() > 0)
{
index = list->size() - 1;
}
else
{
index = 0;
}
}
}
void ScrollingList::CircularIncrement(unsigned int &index, std::vector<ComponentItemBinding*> *list)
{
index++;
if(index >= list->size())
{
index = 0;
}
}
void ScrollingList::CircularDecrement(unsigned int &index, std::vector<ComponentItemBinding*> *list)
{
if(index > 0)
{
index--;
}
else
{
if(list && list->size() > 0)
{
index = list->size() - 1;
}
else
{
index = 0;
}
}
}

View File

@ -0,0 +1,105 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <vector>
#include "Component.h"
#include "../Animate/Tween.h"
#include "../ComponentItemBinding.h"
#include "../MenuNotifierInterface.h"
#include "../ViewInfo.h"
#include "../../Database/Configuration.h"
#include <SDL2/SDL.h>
//todo: This scrolling implementation needs to be overhauled
// It needs to have a common interface to support different menu types
// (It was originally sandbox code that creeped into here)
class Configuration;
class Font;
class ScrollingList : public Component
{
public:
enum ScrollDirection
{
ScrollDirectionBack,
ScrollDirectionForward,
ScrollDirectionIdle,
};
ScrollingList(Configuration *c, float scaleX, float scaleY, Font *font, SDL_Color fontColor, std::string layoutKey, std::string CollectionName, std::string imageType);
virtual ~ScrollingList();
void AllocateTexture(ComponentItemBinding *s);
void DeallocateTexture(ComponentItemBinding *s);
void SetItems(std::vector<ComponentItemBinding *> *spriteList);
void SetPoints(std::vector<ViewInfo *> *scrollPoints);
void SetScrollDirection(ScrollDirection direction);
void PageUp();
void PageDown();
bool IsIdle();
void SetSelectedIndex(int selectedIndex);
ComponentItemBinding *GetSelectedCollectionItemSprite();
ComponentItemBinding *GetPendingCollectionItemSprite();
ComponentItemBinding *GetPendingSelectedCollectionItemSprite();
void AddComponentForNotifications(MenuNotifierInterface *c);
void RemoveComponentForNotifications(MenuNotifierInterface *c);
std::vector<ComponentItemBinding *> *GetCollectionItemSprites();
void RemoveSelectedItem();
void FreeGraphicsMemory();
void Update(float dt);
void Draw();
void Draw(unsigned int layer);
private:
void Click();
unsigned int GetNextTween(unsigned int currentIndex, std::vector<ViewInfo *> *list);
bool IsScrollChangedStarted;
bool IsScrollChangedSignalled;
bool IsScrollChangedComplete;
enum ScrollState
{
ScrollStateActive,
ScrollStatePageChange,
ScrollStateStopping,
ScrollStateIdle
};
std::vector<ComponentItemBinding *> *SpriteList;
std::vector<ViewInfo *> *ScrollPoints;
std::vector<MenuNotifierInterface *> NotificationComponents;
float TweenEnterTime;
unsigned int FirstSpriteIndex;
unsigned int SelectedSpriteListIndex;
float CurrentAnimateTime;
float ScrollTime;
ScrollDirection CurrentScrollDirection;
ScrollDirection RequestedScrollDirection;
ScrollState CurrentScrollState;
float ScrollAcceleration;
float ScrollVelocity;
void CircularIncrement(unsigned &index, std::vector<ComponentItemBinding *> *list);
void CircularDecrement(unsigned &index, std::vector<ComponentItemBinding *> *list);
void CircularIncrement(unsigned &index, std::vector<ViewInfo *> *list);
void CircularDecrement(unsigned &index, std::vector<ViewInfo *> *list);
void UpdateOffset(float dt);
std::string Collection;
Configuration *Config;
float ScaleX;
float ScaleY;
Font *FontInst;
SDL_Color FontColor;
std::string LayoutKey;
std::string CollectionName;
std::string ImageType;
unsigned int MaxLayer;
};

View File

@ -0,0 +1,103 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "Text.h"
#include "../../Utility/Log.h"
#include "../../SDL.h"
#include "../Font.h"
#include <sstream>
Text::Text(std::string text, Font *font, SDL_Color fontColor, float scaleX, float scaleY)
: TextData(text)
, FontInst(font)
, FontColor(fontColor)
, ScaleX(scaleX)
, ScaleY(scaleY)
{
AllocateGraphicsMemory();
}
Text::~Text()
{
FreeGraphicsMemory();
}
void Text::FreeGraphicsMemory()
{
Component::FreeGraphicsMemory();
}
void Text::AllocateGraphicsMemory()
{
//todo: make the font blend color a parameter that is passed in
Component::AllocateGraphicsMemory();
}
void Text::Draw()
{
SDL_Texture *t = FontInst->GetTexture();
ViewInfo *info = GetBaseViewInfo();
float imageHeight = 0;
float imageWidth = 0;
// determine image width
for(unsigned int i = 0; i < TextData.size(); ++i)
{
Font::GlyphInfo glyph;
if(FontInst->GetRect(TextData[i], glyph))
{
imageWidth += glyph.Advance;
imageHeight = (imageHeight >= glyph.Rect.h) ? imageHeight : glyph.Rect.h;
}
}
float scale = (float)info->GetFontSize() / (float)imageHeight;
float width = info->GetRawWidth();
float height = info->GetRawHeight();
info->SetWidth(imageWidth*scale);
info->SetHeight(imageHeight*scale);
float xOrigin = info->GetXRelativeToOrigin();
float yOrigin = info->GetYRelativeToOrigin();
info->SetWidth(width);
info->SetHeight(height);
SDL_Rect rect;
rect.x = static_cast<int>(xOrigin);
for(unsigned int i = 0; i < TextData.size(); ++i)
{
Font::GlyphInfo glyph;
if(FontInst->GetRect(TextData[i], glyph) && glyph.Rect.h > 0)
{
SDL_Rect charRect = glyph.Rect;
float h = static_cast<float>(charRect.h * scale);
float w = static_cast<float>(charRect.w * scale);
rect.h = static_cast<int>(h);
rect.w = static_cast<int>(w);
rect.y = static_cast<int>(yOrigin);
/*
std::stringstream ss;
ss << " cx:" << charRect.x << " cy:" << charRect.y << " cw:" << charRect.w << " ch:" << charRect.h;
ss << " x:" << rect.x << " y:" << rect.y << " w:" << rect.w << " h:" << rect.h;
Logger::Write(Logger::ZONE_DEBUG, "Text", ss.str());
*/
SDL_LockMutex(SDL::GetMutex());
SDL_SetTextureColorMod(t, FontColor.r, FontColor.g, FontColor.b);
SDL_UnlockMutex(SDL::GetMutex());
SDL::RenderCopy(t, static_cast<char>(info->GetTransparency() * 255), &charRect, &rect, info->GetAngle());
rect.x += static_cast<int>(glyph.Advance * scale);
}
}
}

View File

@ -0,0 +1,29 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Component.h"
#include <SDL2/SDL.h>
#include <vector>
class Font;
class Text : public Component
{
public:
//todo: should have a Font flass that references fontcache, pass that in as an argument
Text(std::string text, Font *font, SDL_Color fontColor, float scaleX, float scaleY);
virtual ~Text();
void AllocateGraphicsMemory();
void FreeGraphicsMemory();
void Draw();
private:
std::string TextData;
Font *FontInst;
SDL_Color FontColor;
float ScaleX;
float ScaleY;
};

View File

@ -0,0 +1,36 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "VideoBuilder.h"
#include "../../Utility/Utils.h"
#include "../../Utility/Log.h"
#include "../../Video/VideoFactory.h"
#include <fstream>
VideoComponent * VideoBuilder::CreateVideo(std::string path, std::string name, float scaleX, float scaleY)
{
VideoComponent *component = NULL;
std::vector<std::string> extensions;
extensions.push_back("mp4");
extensions.push_back("MP4");
extensions.push_back("avi");
extensions.push_back("AVI");
std::string prefix = path + "/" + name;
std::string file;
if(Utils::FindMatchingFile(prefix, extensions, file))
{
IVideo *video = Factory.CreateVideo();
if(video)
{
component = new VideoComponent(video, file, scaleX, scaleY);
}
}
return component;
}

View File

@ -0,0 +1,18 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Image.h"
#include "VideoComponent.h"
#include "../../Video/VideoFactory.h"
//todo: this is more of a factory than a builder
class VideoBuilder
{
public:
VideoComponent * CreateVideo(std::string path, std::string name, float scaleX, float scaleY);
private:
VideoFactory Factory;
};

View File

@ -0,0 +1,84 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "VideoComponent.h"
#include "../ViewInfo.h"
#include "../../Database/Configuration.h"
#include "../../Utility/Log.h"
#include "../../SDL.h"
VideoComponent::VideoComponent(IVideo *videoInst, std::string videoFile, float scaleX, float scaleY)
: VideoTexture(NULL)
, VideoFile(videoFile)
, VideoInst(videoInst)
, ScaleX(scaleX)
, ScaleY(scaleY)
, IsPlaying(false)
{
// AllocateGraphicsMemory();
}
VideoComponent::~VideoComponent()
{
FreeGraphicsMemory();
if(VideoInst)
{
VideoInst->Stop();
}
}
void VideoComponent::Update(float dt)
{
if(IsPlaying)
{
VideoInst->Update(dt);
}
Component::Update(dt);
}
void VideoComponent::AllocateGraphicsMemory()
{
Component::AllocateGraphicsMemory();
if(!IsPlaying)
{
IsPlaying = VideoInst->Play(VideoFile);
}
}
void VideoComponent::FreeGraphicsMemory()
{
VideoInst->Stop();
IsPlaying = false;
if (VideoTexture != NULL)
{
SDL_LockMutex(SDL::GetMutex());
SDL_DestroyTexture(VideoTexture);
SDL_UnlockMutex(SDL::GetMutex());
}
Component::FreeGraphicsMemory();
}
void VideoComponent::Draw()
{
ViewInfo *info = GetBaseViewInfo();
SDL_Rect rect;
rect.x = static_cast<int>(info->GetXRelativeToOrigin());
rect.y = static_cast<int>(info->GetYRelativeToOrigin());
rect.h = static_cast<int>(info->GetHeight());
rect.w = static_cast<int>(info->GetWidth());
VideoInst->Draw();
SDL_Texture *texture = VideoInst->GetTexture();
if(texture)
{
SDL::RenderCopy(texture, static_cast<int>(info->GetTransparency() * 255), NULL, &rect, info->GetAngle());
}
}

View File

@ -0,0 +1,32 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Component.h"
#include "Image.h"
#include "../../Collection/Item.h"
#include "../../Video/IVideo.h"
#include <SDL2/SDL.h>
#include <string>
class VideoComponent : public Component
{
public:
VideoComponent(IVideo *videoInst, std::string videoFile, float scaleX, float scaleY);
virtual ~VideoComponent();
void Update(float dt);
void Draw();
void FreeGraphicsMemory();
void AllocateGraphicsMemory();
void LaunchEnter() {FreeGraphicsMemory(); }
void LaunchExit() { AllocateGraphicsMemory(); }
private:
SDL_Texture *VideoTexture;
std::string VideoFile;
std::string Name;
IVideo *VideoInst;
float ScaleX;
float ScaleY;
bool IsPlaying;
};

View File

@ -0,0 +1,35 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "ComponentItemBinding.h"
ComponentItemBinding::ComponentItemBinding( Component *c, Item *item)
: CollectionComponent(c)
, CollectionItem(item)
{
}
ComponentItemBinding::ComponentItemBinding(Item *item)
: CollectionComponent(NULL)
, CollectionItem(item)
{
}
ComponentItemBinding::~ComponentItemBinding()
{
}
Item* ComponentItemBinding::GetCollectionItem() const
{
return CollectionItem;
}
void ComponentItemBinding::SetComponent(Component *c)
{
CollectionComponent = c;
}
Component* ComponentItemBinding::GetComponent() const
{
return CollectionComponent;
}

View File

@ -0,0 +1,23 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Component/Component.h"
#include "../Collection/Item.h"
class ComponentItemBinding
{
public:
ComponentItemBinding(Component *c, Item *item);
ComponentItemBinding(Item *item);
virtual ~ComponentItemBinding();
Item* GetCollectionItem() const;
void SetComponent(Component *c);
Component* GetComponent() const;
private:
Component *CollectionComponent;
Item *CollectionItem;
};

View File

@ -0,0 +1,29 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "ComponentItemBindingBuilder.h"
#include "ComponentItemBinding.h"
#include "../Database/CollectionDatabase.h"
#include "../Collection/Item.h"
ComponentItemBindingBuilder::ComponentItemBindingBuilder()
{
}
ComponentItemBindingBuilder::~ComponentItemBindingBuilder()
{
}
std::vector<ComponentItemBinding *> *ComponentItemBindingBuilder::BuildCollectionItems(std::vector<Item *> *infoList)
{
std::vector<ComponentItemBinding *> *sprites = new std::vector<ComponentItemBinding *>();
std::vector<Item *>::iterator it;
for(it = infoList->begin(); it != infoList->end(); ++it)
{
ComponentItemBinding *s = new ComponentItemBinding(*it);
sprites->push_back(s);
}
return sprites;
}

View File

@ -0,0 +1,18 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <vector>
#include <string>
class Item;
class ComponentItemBinding;
class ComponentItemBindingBuilder
{
public:
ComponentItemBindingBuilder();
virtual ~ComponentItemBindingBuilder();
static std::vector<ComponentItemBinding *> *BuildCollectionItems(std::vector<Item *> *infoList);
};

145
Source/Graphics/Font.cpp Normal file
View File

@ -0,0 +1,145 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "Font.h"
#include "../SDL.h"
#include "../Utility/Log.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
Font::Font()
: Texture(NULL)
{
}
Font::~Font()
{
DeInitialize();
}
SDL_Texture *Font::GetTexture()
{
return Texture;
}
bool Font::GetRect(unsigned int charCode, GlyphInfo &glyph)
{
std::map<unsigned int, GlyphInfoBuild *>::iterator it = Atlas.find(charCode);
if(it != Atlas.end())
{
GlyphInfoBuild *info = it->second;
glyph = info->Glyph;
return true;
}
return false;
}
bool Font::Initialize(std::string fontPath, SDL_Color color)
{
TTF_Font *font = TTF_OpenFont(fontPath.c_str(), 128);
if (!font)
{
Logger::Write(Logger::ZONE_ERROR, "FontCache", "TTF_OpenFont failed");
return false;
}
int x = 0;
int y = 0;
int atlasHeight = 0;
int atlasWidth = 0;
for(unsigned short int i = 32; i < 128; ++i)
{
GlyphInfoBuild *info = new GlyphInfoBuild;
memset(info, sizeof(GlyphInfoBuild), 0);
info->Surface = TTF_RenderGlyph_Blended(font, i, color);
TTF_GlyphMetrics(font, i, &info->Glyph.MinX, &info->Glyph.MaxX, &info->Glyph.MinY, &info->Glyph.MaxY, &info->Glyph.Advance);
if(x + info->Surface->w >= 1024)
{
atlasHeight += y;
atlasWidth = (atlasWidth >= x) ? atlasWidth : x;
x = 0;
y = 0;
}
info->Glyph.Rect.w = info->Surface->w;
info->Glyph.Rect.h = info->Surface->h;
info->Glyph.Rect.x = x;
info->Glyph.Rect.y = atlasHeight;
Atlas[i] = info;
x += info->Glyph.Rect.w;
y = (y > info->Glyph.Rect.h) ? y : info->Glyph.Rect.h;
/*
std::stringstream ss;
ss << " tw:" << atlasWidth << " th:" << atlasHeight << " x:" << x << " y:" << y << " w:" << info->Glyph.Rect.w << " h:" << info->Glyph.Rect.h;
Logger::Write(Logger::ZONE_ERROR, "FontCache", ss.str());
*/
}
atlasWidth = (atlasWidth >= x) ? atlasWidth : x;
atlasHeight += y;
unsigned int rmask;
unsigned int gmask;
unsigned int bmask;
unsigned int amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
SDL_Surface *atlasSurface = SDL_CreateRGBSurface(0, atlasWidth, atlasHeight, 24, rmask, gmask, bmask, amask);
std::map<unsigned int, GlyphInfoBuild *>::iterator it;
for(it = Atlas.begin(); it != Atlas.end(); it++)
{
GlyphInfoBuild *info = it->second;
SDL_BlitSurface(info->Surface, NULL, atlasSurface, &info->Glyph.Rect);
SDL_FreeSurface(info->Surface);
info->Surface = NULL;
}
SDL_LockMutex(SDL::GetMutex());
SDL_SetColorKey(atlasSurface, SDL_TRUE, SDL_MapRGB(atlasSurface->format, 0, 0, 0));
Texture = SDL_CreateTextureFromSurface(SDL::GetRenderer(), atlasSurface);
SDL_FreeSurface(atlasSurface);
SDL_UnlockMutex(SDL::GetMutex());
TTF_CloseFont(font);
return true;
}
void Font::DeInitialize()
{
if(Texture)
{
SDL_LockMutex(SDL::GetMutex());
SDL_DestroyTexture(Texture);
Texture = NULL;
SDL_UnlockMutex(SDL::GetMutex());
}
std::map<unsigned int, GlyphInfoBuild *>::iterator atlasIt = Atlas.begin();
while(atlasIt != Atlas.end())
{
delete atlasIt->second;
Atlas.erase(atlasIt);
atlasIt = Atlas.begin();
}
}

42
Source/Graphics/Font.h Normal file
View File

@ -0,0 +1,42 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <SDL2/SDL.h>
#include <map>
#include <string>
class Font
{
public:
struct GlyphInfo
{
int MinX;
int MaxX;
int MinY;
int MaxY;
int Advance;
SDL_Rect Rect;
};
Font();
virtual ~Font();
bool Initialize(std::string fontPath, SDL_Color color);
void DeInitialize();
SDL_Texture *GetTexture();
bool GetRect(unsigned int charCode, GlyphInfo &glyph);
private:
struct GlyphInfoBuild
{
Font::GlyphInfo Glyph;
SDL_Surface *Surface;
};
std::map<unsigned int, GlyphInfoBuild *> Atlas;
SDL_Texture *Texture;
};

View File

@ -0,0 +1,72 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "FontCache.h"
#include "Font.h"
#include "../Utility/Log.h"
#include "../SDL.h"
#include <SDL2/SDL_ttf.h>
#include <sstream>
//todo: memory leak when launching games
FontCache::FontCache()
: IsInitialized(false)
{
}
FontCache::~FontCache()
{
DeInitialize();
}
void FontCache::DeInitialize()
{
IsInitialized = false;
std::map<std::string, Font *>::iterator it = FontFaceMap.begin();
while(it != FontFaceMap.end())
{
delete it->second;
FontFaceMap.erase(it);
it = FontFaceMap.begin();
}
SDL_LockMutex(SDL::GetMutex());
TTF_Quit();
SDL_UnlockMutex(SDL::GetMutex());
}
void FontCache::Initialize()
{
//todo: make bool
TTF_Init();
IsInitialized = true;
}
Font *FontCache::GetFont(std::string fontPath)
{
Font *t = NULL;
std::map<std::string, Font *>::iterator it = FontFaceMap.find(fontPath);
if(it != FontFaceMap.end())
{
t = it->second;
}
return t;
}
bool FontCache::LoadFont(std::string fontPath, SDL_Color color)
{
std::map<std::string, Font *>::iterator it = FontFaceMap.find(fontPath);
if(it == FontFaceMap.end())
{
Font *f = new Font();
f->Initialize(fontPath, color);
FontFaceMap[fontPath] = f;
}
return true;
}

View File

@ -0,0 +1,26 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Font.h"
#include <string>
#include <map>
class FontCache
{
public:
void Initialize();
void DeInitialize();
FontCache();
bool LoadFont(std::string font, SDL_Color color);
Font *GetFont(std::string font);
virtual ~FontCache();
private:
bool IsInitialized;
std::map<std::string, Font *> FontFaceMap;
};

View File

@ -0,0 +1,14 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "../Collection/Item.h"
class MenuNotifierInterface
{
public:
virtual ~MenuNotifierInterface() {}
virtual void OnNewItemSelected(Item *) = 0;
};

406
Source/Graphics/Page.cpp Normal file
View File

@ -0,0 +1,406 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#include "Page.h"
#include "ComponentItemBinding.h"
#include "Component/Component.h"
#include "../Utility/Log.h"
#include "Component/ScrollingList.h"
#include "../Sound/Sound.h"
#include "ComponentItemBindingBuilder.h"
#include <sstream>
Page::Page(std::string collectionName)
: CollectionName(collectionName)
, Menu(NULL)
, Items(NULL)
, ScrollActive(false)
, SelectedItem(NULL)
, SelectedItemChanged(false)
, LoadSoundChunk(NULL)
, UnloadSoundChunk(NULL)
, HighlightSoundChunk(NULL)
, SelectSoundChunk(NULL)
, HasSoundedWhenActive(false)
, FirstSoundPlayed(false)
{
}
Page::~Page()
{
if(Menu)
{
Menu->RemoveComponentForNotifications(this);
}
for(unsigned int i = 0; i < sizeof(LayerComponents)/sizeof(LayerComponents[0]); ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
delete *it;
}
LayerComponents[i].clear();
}
if(Menu)
{
delete Menu;
}
if(LoadSoundChunk)
{
delete LoadSoundChunk;
LoadSoundChunk = NULL;
}
if(UnloadSoundChunk)
{
delete UnloadSoundChunk;
UnloadSoundChunk = NULL;
}
if(HighlightSoundChunk)
{
delete HighlightSoundChunk;
HighlightSoundChunk = NULL;
}
if(SelectSoundChunk)
{
delete SelectSoundChunk;
SelectSoundChunk = NULL;
}
}
void Page::OnNewItemSelected(Item *item)
{
SelectedItem = item;
SelectedItemChanged = true;
}
void Page::SetMenu(ScrollingList *s)
{
// todo: delete the old menu
Menu = s;
if(Menu)
{
Menu->AddComponentForNotifications(this);
}
}
bool Page::AddComponent(Component *c)
{
bool retVal = false;
unsigned int layer = c->GetBaseViewInfo()->GetLayer();
if(layer < NUM_LAYERS)
{
LayerComponents[layer].push_back(c);
retVal = true;
}
else
{
std::stringstream ss;
ss << "Component layer too large Layer: " << layer;
Logger::Write(Logger::ZONE_ERROR, "Page", ss.str());
}
return retVal;
}
bool Page::IsIdle()
{
bool idle = true;
if(Menu != NULL && !Menu->IsIdle())
{
idle = false;
}
for(unsigned int i = 0; i < NUM_LAYERS && idle; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end() && idle; ++it)
{
idle = (*it)->IsIdle();
}
}
return idle;
}
bool Page::IsHidden()
{
bool hidden = true;
if(Menu != NULL)
{
hidden = Menu->IsHidden();
}
for(unsigned int i = 0; hidden && i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); hidden && it != LayerComponents[i].end(); ++it)
{
hidden = (*it)->IsHidden();
}
}
return hidden;
}
void Page::Start()
{
Menu->TriggerEnterEvent();
if(LoadSoundChunk)
{
LoadSoundChunk->Play();
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->TriggerEnterEvent();
}
}
}
void Page::Stop()
{
Menu->TriggerExitEvent();
if(UnloadSoundChunk)
{
UnloadSoundChunk->Play();
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->TriggerExitEvent();
}
}
}
Item *Page::GetSelectedItem()
{
return SelectedItem;
}
void Page::RemoveSelectedItem()
{
if(Menu)
{
//todo: change method to RemoveItem() and pass in SelectedItem
Menu->RemoveSelectedItem();
SelectedItem = NULL;
}
}
void Page::Highlight()
{
Item *item = SelectedItem;
if(item)
{
if(Menu)
{
Menu->TriggerHighlightEvent(item);
Menu->SetScrollActive(ScrollActive);
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->TriggerHighlightEvent(item);
(*it)->SetScrollActive(ScrollActive);
}
}
}
}
void Page::SetScrolling(ScrollDirection direction)
{
ScrollingList::ScrollDirection menuDirection;
switch(direction)
{
case ScrollDirectionForward:
menuDirection = ScrollingList::ScrollDirectionForward;
ScrollActive = true;
break;
case ScrollDirectionBack:
menuDirection = ScrollingList::ScrollDirectionBack;
ScrollActive = true;
break;
case ScrollDirectionIdle:
default:
menuDirection = ScrollingList::ScrollDirectionIdle;
ScrollActive = false;
break;
}
if(Menu)
{
Menu->SetScrollDirection(menuDirection);
}
}
void Page::PageScroll(ScrollDirection direction)
{
if(Menu)
{
if(direction == ScrollDirectionForward)
{
Menu->PageDown();
}
if(direction == ScrollDirectionBack)
{
Menu->PageUp();
}
}
}
void Page::SetItems(std::vector<Item *> *items)
{
std::vector<ComponentItemBinding *> *sprites = ComponentItemBindingBuilder::BuildCollectionItems(items);
if(Menu != NULL)
{
Menu->SetItems(sprites);
}
}
void Page::Update(float dt)
{
if(Menu != NULL)
{
Menu->Update(dt);
}
if(SelectedItemChanged && !HasSoundedWhenActive && HighlightSoundChunk)
{
// skip the first sound being played (as it is part of the on-enter)
if(FirstSoundPlayed)
{
HighlightSoundChunk->Play();
HasSoundedWhenActive = true;
}
FirstSoundPlayed = true;
}
if(SelectedItemChanged && !ScrollActive)
{
Highlight();
SelectedItemChanged = false;
HasSoundedWhenActive = false;
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->Update(dt);
}
}
}
void Page::Draw()
{
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->Draw();
}
Menu->Draw(i);
}
}
const std::string& Page::GetCollectionName() const
{
return CollectionName;
}
void Page::FreeGraphicsMemory()
{
Logger::Write(Logger::ZONE_DEBUG, "Page", "Free");
Menu->FreeGraphicsMemory();
if(LoadSoundChunk) LoadSoundChunk->Free();
if(UnloadSoundChunk) UnloadSoundChunk->Free();
if(HighlightSoundChunk) HighlightSoundChunk->Free();
if(SelectSoundChunk) SelectSoundChunk->Free();
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->FreeGraphicsMemory();
}
}
}
void Page::AllocateGraphicsMemory()
{
FirstSoundPlayed = false;
Logger::Write(Logger::ZONE_DEBUG, "Page", "Allocating graphics memory");
Menu->AllocateGraphicsMemory();
if(LoadSoundChunk) LoadSoundChunk->Allocate();
if(UnloadSoundChunk) UnloadSoundChunk->Allocate();
if(HighlightSoundChunk) HighlightSoundChunk->Allocate();
if(SelectSoundChunk) SelectSoundChunk->Allocate();
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->AllocateGraphicsMemory();
}
}
Logger::Write(Logger::ZONE_DEBUG, "Page", "Allocate graphics memory complete");
}
void Page::LaunchEnter()
{
Menu->LaunchEnter();
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->LaunchEnter();
}
}
}
void Page::LaunchExit()
{
Menu->LaunchExit();
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->LaunchExit();
}
}
}

Some files were not shown because too many files have changed in this diff Show More