mirror of
https://github.com/FunKey-Project/RetroFE.git
synced 2026-02-12 01:46:07 +01:00
Port from git
This commit is contained in:
commit
93094bcbed
749
Assets/Environment/Common/Collections/Arcade/Include.xml
Normal file
749
Assets/Environment/Common/Collections/Arcade/Include.xml
Normal 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>
|
||||
13
Assets/Environment/Common/Collections/Arcade/Settings.conf
Normal file
13
Assets/Environment/Common/Collections/Arcade/Settings.conf
Normal 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
|
||||
|
||||
7
Assets/Environment/Common/Collections/Main/Menu.xml
Normal file
7
Assets/Environment/Common/Collections/Main/Menu.xml
Normal 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>
|
||||
9
Assets/Environment/Common/Collections/Main/Settings.conf
Normal file
9
Assets/Environment/Common/Collections/Main/Settings.conf
Normal 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
|
||||
|
||||
@ -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>
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
7
Assets/Environment/Common/Controls.conf
Normal file
7
Assets/Environment/Common/Controls.conf
Normal file
@ -0,0 +1,7 @@
|
||||
previousItem = Up
|
||||
nextItem = Down
|
||||
pageUp = Left
|
||||
pageDown = Right
|
||||
select = Space
|
||||
back = Escape
|
||||
quit = Q
|
||||
2
Assets/Environment/Common/Launchers/Fceux.conf
Normal file
2
Assets/Environment/Common/Launchers/Fceux.conf
Normal file
@ -0,0 +1,2 @@
|
||||
executable = D:\Emulators\fceux\fceux.exe
|
||||
arguments = "%ITEM_FILEPATH%"
|
||||
6
Assets/Environment/Common/Launchers/HyperLaunch.conf
Normal file
6
Assets/Environment/Common/Launchers/HyperLaunch.conf
Normal 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%"
|
||||
2
Assets/Environment/Common/Launchers/MAME.conf
Normal file
2
Assets/Environment/Common/Launchers/MAME.conf
Normal file
@ -0,0 +1,2 @@
|
||||
executable = D:/Emulators/MAME/mamepp.exe
|
||||
arguments = "%ITEM_NAME%"
|
||||
2
Assets/Environment/Common/Launchers/Nestopia.conf
Normal file
2
Assets/Environment/Common/Launchers/Nestopia.conf
Normal file
@ -0,0 +1,2 @@
|
||||
executable = D:\Emulators\nestopia\nestopia.exe
|
||||
arguments = "%ITEM_FILEPATH%"
|
||||
BIN
Assets/Environment/Common/Layouts/Default 16x9/Age.otf
Normal file
BIN
Assets/Environment/Common/Layouts/Default 16x9/Age.otf
Normal file
Binary file not shown.
128
Assets/Environment/Common/Layouts/Default 16x9/Layout.xml
Normal file
128
Assets/Environment/Common/Layouts/Default 16x9/Layout.xml
Normal 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>
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Assets/Environment/Common/Layouts/Default 16x9/background.png
Normal file
BIN
Assets/Environment/Common/Layouts/Default 16x9/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
BIN
Assets/Environment/Common/Layouts/Default 16x9/highlight.wav
Normal file
BIN
Assets/Environment/Common/Layouts/Default 16x9/highlight.wav
Normal file
Binary file not shown.
BIN
Assets/Environment/Common/Layouts/Default 16x9/load.wav
Normal file
BIN
Assets/Environment/Common/Layouts/Default 16x9/load.wav
Normal file
Binary file not shown.
BIN
Assets/Environment/Common/Layouts/Default 16x9/logo.png
Normal file
BIN
Assets/Environment/Common/Layouts/Default 16x9/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.8 KiB |
BIN
Assets/Environment/Common/Layouts/Default 16x9/select.wav
Normal file
BIN
Assets/Environment/Common/Layouts/Default 16x9/select.wav
Normal file
Binary file not shown.
BIN
Assets/Environment/Common/Layouts/Default 16x9/square.png
Normal file
BIN
Assets/Environment/Common/Layouts/Default 16x9/square.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 208 B |
BIN
Assets/Environment/Common/Layouts/Default 16x9/unload.wav
Normal file
BIN
Assets/Environment/Common/Layouts/Default 16x9/unload.wav
Normal file
Binary file not shown.
BIN
Assets/Environment/Common/Layouts/Default 4x3/Age.otf
Normal file
BIN
Assets/Environment/Common/Layouts/Default 4x3/Age.otf
Normal file
Binary file not shown.
90
Assets/Environment/Common/Layouts/Default 4x3/Layout.xml
Normal file
90
Assets/Environment/Common/Layouts/Default 4x3/Layout.xml
Normal 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>
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
Assets/Environment/Common/Layouts/Default 4x3/background.png
Normal file
BIN
Assets/Environment/Common/Layouts/Default 4x3/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
BIN
Assets/Environment/Common/Layouts/Default 4x3/highlight.wav
Normal file
BIN
Assets/Environment/Common/Layouts/Default 4x3/highlight.wav
Normal file
Binary file not shown.
BIN
Assets/Environment/Common/Layouts/Default 4x3/load.wav
Normal file
BIN
Assets/Environment/Common/Layouts/Default 4x3/load.wav
Normal file
Binary file not shown.
BIN
Assets/Environment/Common/Layouts/Default 4x3/logo.png
Normal file
BIN
Assets/Environment/Common/Layouts/Default 4x3/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.8 KiB |
BIN
Assets/Environment/Common/Layouts/Default 4x3/select.wav
Normal file
BIN
Assets/Environment/Common/Layouts/Default 4x3/select.wav
Normal file
Binary file not shown.
BIN
Assets/Environment/Common/Layouts/Default 4x3/square.png
Normal file
BIN
Assets/Environment/Common/Layouts/Default 4x3/square.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 208 B |
BIN
Assets/Environment/Common/Layouts/Default 4x3/unload.wav
Normal file
BIN
Assets/Environment/Common/Layouts/Default 4x3/unload.wav
Normal file
Binary file not shown.
49
Assets/Environment/Common/Settings.conf
Normal file
49
Assets/Environment/Common/Settings.conf
Normal 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
|
||||
4
Assets/Environment/Linux/README-UBUNTU.txt
Normal file
4
Assets/Environment/Linux/README-UBUNTU.txt
Normal 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
|
||||
BIN
Assets/Environment/Windows/RetroFE.lnk
Normal file
BIN
Assets/Environment/Windows/RetroFE.lnk
Normal file
Binary file not shown.
34
Build Instructions.txt
Normal file
34
Build Instructions.txt
Normal 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
49
CMake/FindGStreamer.cmake
Normal 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
43
CMake/FindGlib2.cmake
Normal 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
87
CMake/FindSDL2.cmake
Normal 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)
|
||||
70
CMake/FindSDL2_image.cmake
Normal file
70
CMake/FindSDL2_image.cmake
Normal 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)
|
||||
72
CMake/FindSDL2_mixer.cmake
Normal file
72
CMake/FindSDL2_mixer.cmake
Normal 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
73
CMake/FindSDL2_ttf.cmake
Normal 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
8
LICENSE.txt
Normal 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.
|
||||
1
Scripts/SetupEnvironment.bat
Normal file
1
Scripts/SetupEnvironment.bat
Normal file
@ -0,0 +1 @@
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/vcvarsall.bat"
|
||||
224
Source/CMakeLists.txt
Normal file
224
Source/CMakeLists.txt
Normal 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()
|
||||
|
||||
67
Source/Collection/CollectionInfo.cpp
Normal file
67
Source/Collection/CollectionInfo.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
28
Source/Collection/CollectionInfo.h
Normal file
28
Source/Collection/CollectionInfo.h
Normal 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;
|
||||
};
|
||||
126
Source/Collection/CollectionInfoBuilder.cpp
Normal file
126
Source/Collection/CollectionInfoBuilder.cpp
Normal 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);
|
||||
}
|
||||
25
Source/Collection/CollectionInfoBuilder.h
Normal file
25
Source/Collection/CollectionInfoBuilder.h
Normal 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
160
Source/Collection/Item.cpp
Normal 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
56
Source/Collection/Item.h
Normal 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;
|
||||
};
|
||||
|
||||
108
Source/Collection/MenuParser.cpp
Normal file
108
Source/Collection/MenuParser.cpp
Normal 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;
|
||||
|
||||
}
|
||||
17
Source/Collection/MenuParser.h
Normal file
17
Source/Collection/MenuParser.h
Normal 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);
|
||||
|
||||
};
|
||||
78
Source/Control/UserInput.cpp
Normal file
78
Source/Control/UserInput.cpp
Normal 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;
|
||||
}
|
||||
|
||||
38
Source/Control/UserInput.h
Normal file
38
Source/Control/UserInput.h
Normal 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;
|
||||
};
|
||||
750
Source/Database/CollectionDatabase.cpp
Normal file
750
Source/Database/CollectionDatabase.cpp
Normal 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;
|
||||
}
|
||||
44
Source/Database/CollectionDatabase.h
Normal file
44
Source/Database/CollectionDatabase.h
Normal 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;
|
||||
};
|
||||
295
Source/Database/Configuration.cpp
Normal file
295
Source/Database/Configuration.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
43
Source/Database/Configuration.h
Normal file
43
Source/Database/Configuration.h
Normal 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
50
Source/Database/DB.cpp
Normal 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
21
Source/Database/DB.h
Normal 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;
|
||||
};
|
||||
|
||||
119
Source/Database/MamelistMetadata.cpp
Normal file
119
Source/Database/MamelistMetadata.cpp
Normal 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;
|
||||
}
|
||||
18
Source/Database/MamelistMetadata.h
Normal file
18
Source/Database/MamelistMetadata.h
Normal 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;
|
||||
};
|
||||
10
Source/Database/Metadata.h
Normal file
10
Source/Database/Metadata.h
Normal 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
326
Source/Execute/Launcher.cpp
Normal 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 ¤tDirectory, 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
40
Source/Execute/Launcher.h
Normal 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 ¤tDirectory, 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;
|
||||
};
|
||||
370
Source/Graphics/Animate/Tween.cpp
Normal file
370
Source/Graphics/Animate/Tween.cpp
Normal 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);
|
||||
}
|
||||
55
Source/Graphics/Animate/Tween.h
Normal file
55
Source/Graphics/Animate/Tween.h
Normal 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;
|
||||
};
|
||||
45
Source/Graphics/Animate/TweenTypes.h
Normal file
45
Source/Graphics/Animate/TweenTypes.h
Normal 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
|
||||
};
|
||||
282
Source/Graphics/Component/Component.cpp
Normal file
282
Source/Graphics/Component/Component.cpp
Normal 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;
|
||||
}
|
||||
122
Source/Graphics/Component/Component.h
Normal file
122
Source/Graphics/Component/Component.h
Normal 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;
|
||||
};
|
||||
75
Source/Graphics/Component/Image.cpp
Normal file
75
Source/Graphics/Component/Image.cpp
Normal 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());
|
||||
}
|
||||
}
|
||||
24
Source/Graphics/Component/Image.h
Normal file
24
Source/Graphics/Component/Image.h
Normal 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;
|
||||
};
|
||||
30
Source/Graphics/Component/ImageBuilder.cpp
Normal file
30
Source/Graphics/Component/ImageBuilder.cpp
Normal 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;
|
||||
}
|
||||
15
Source/Graphics/Component/ImageBuilder.h
Normal file
15
Source/Graphics/Component/ImageBuilder.h
Normal 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);
|
||||
};
|
||||
172
Source/Graphics/Component/ReloadableMedia.cpp
Normal file
172
Source/Graphics/Component/ReloadableMedia.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
38
Source/Graphics/Component/ReloadableMedia.h
Normal file
38
Source/Graphics/Component/ReloadableMedia.h
Normal 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;
|
||||
};
|
||||
157
Source/Graphics/Component/ReloadableText.cpp
Normal file
157
Source/Graphics/Component/ReloadableText.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
48
Source/Graphics/Component/ReloadableText.h
Normal file
48
Source/Graphics/Component/ReloadableText.h
Normal 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;
|
||||
};
|
||||
654
Source/Graphics/Component/ScrollingList.cpp
Normal file
654
Source/Graphics/Component/ScrollingList.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
105
Source/Graphics/Component/ScrollingList.h
Normal file
105
Source/Graphics/Component/ScrollingList.h
Normal 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;
|
||||
};
|
||||
|
||||
103
Source/Graphics/Component/Text.cpp
Normal file
103
Source/Graphics/Component/Text.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
29
Source/Graphics/Component/Text.h
Normal file
29
Source/Graphics/Component/Text.h
Normal 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;
|
||||
};
|
||||
36
Source/Graphics/Component/VideoBuilder.cpp
Normal file
36
Source/Graphics/Component/VideoBuilder.cpp
Normal 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;
|
||||
}
|
||||
|
||||
18
Source/Graphics/Component/VideoBuilder.h
Normal file
18
Source/Graphics/Component/VideoBuilder.h
Normal 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;
|
||||
};
|
||||
84
Source/Graphics/Component/VideoComponent.cpp
Normal file
84
Source/Graphics/Component/VideoComponent.cpp
Normal 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());
|
||||
}
|
||||
}
|
||||
32
Source/Graphics/Component/VideoComponent.h
Normal file
32
Source/Graphics/Component/VideoComponent.h
Normal 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;
|
||||
};
|
||||
35
Source/Graphics/ComponentItemBinding.cpp
Normal file
35
Source/Graphics/ComponentItemBinding.cpp
Normal 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;
|
||||
}
|
||||
23
Source/Graphics/ComponentItemBinding.h
Normal file
23
Source/Graphics/ComponentItemBinding.h
Normal 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;
|
||||
};
|
||||
29
Source/Graphics/ComponentItemBindingBuilder.cpp
Normal file
29
Source/Graphics/ComponentItemBindingBuilder.cpp
Normal 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;
|
||||
}
|
||||
18
Source/Graphics/ComponentItemBindingBuilder.h
Normal file
18
Source/Graphics/ComponentItemBindingBuilder.h
Normal 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
145
Source/Graphics/Font.cpp
Normal 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
42
Source/Graphics/Font.h
Normal 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;
|
||||
};
|
||||
|
||||
|
||||
72
Source/Graphics/FontCache.cpp
Normal file
72
Source/Graphics/FontCache.cpp
Normal 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;
|
||||
}
|
||||
|
||||
26
Source/Graphics/FontCache.h
Normal file
26
Source/Graphics/FontCache.h
Normal 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;
|
||||
|
||||
};
|
||||
|
||||
14
Source/Graphics/MenuNotifierInterface.h
Normal file
14
Source/Graphics/MenuNotifierInterface.h
Normal 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
406
Source/Graphics/Page.cpp
Normal 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
Loading…
x
Reference in New Issue
Block a user