Merged develop into default for release 0.7.1 beta.

This commit is contained in:
Pieter Hulshoff 2016-05-14 13:28:27 +02:00
commit 338658e4ba
42 changed files with 1550 additions and 1420 deletions

View File

@ -6,6 +6,10 @@ pageUp = A
pageDown = B
letterUp = N
letterDown = M
nextPlaylist = P
addPlaylist = I
removePlaylist = O
random = R
select = Space
back = Escape
quit = Q

View File

@ -12,7 +12,7 @@
<!-----------------MAIN MENU Section----------------->
<!-- This is the title text that shows at the bottom of the main menu list. -->
<reloadableText type="title" x="center" y="center" xOrigin="center" yOrigin="center" yOffset="394" fontSize="48" layer="5">
<reloadableText type="playlist" x="center" y="center" xOrigin="center" yOrigin="center" yOffset="394" fontSize="48" layer="5">
<onMenuEnter menuIndex="0">
<set duration=".2">
<animate type="alpha" from="0" to="1" algorithm="easeinquadratic"/>
@ -367,4 +367,4 @@
</onHighlightExit>
</reloadableVideo>
</layout>
</layout>

View File

@ -76,7 +76,7 @@
</reloadableVideo>
<reloadableImage type="titleshot" x="397" y="520" xOrigin="center" yOrigin="center" height="360" maxWidth="400" layer="2">
<reloadableImage type="screentitle" x="397" y="520" xOrigin="center" yOrigin="center" height="360" maxWidth="400" layer="2">
<onMenuEnter menuIndex="1">
<set duration=".1">
<animate type="alpha" from="0" to="1" algorithm="easeinquadratic"/>

View File

@ -90,7 +90,7 @@
</reloadableVideo>
<reloadableImage type="titleshot" x="397" y="520" xOrigin="center" yOrigin="center" height="360" maxWidth="400" layer="2">
<reloadableImage type="screentitle" x="397" y="520" xOrigin="center" yOrigin="center" height="360" maxWidth="400" layer="2">
<onMenuEnter menuIndex="1">
<set duration=".1">
<animate type="alpha" from="0" to="1" algorithm="easeinquadratic"/>

View File

@ -1227,7 +1227,7 @@
<enabled>Yes</enabled>
</game>
<game name="Chi Chi&apos;s Pro Challenge Golf (USA)" index="" image="">
<description>Chi Chi\&apos;s Pro Challenge Golf (USA)</description>
<description>Chi Chi&apos;s Pro Challenge Golf (USA)</description>
<cloneof></cloneof>
<crc>9c3973a4</crc>
<manufacturer>Coconuts Japan</manufacturer>
@ -1337,7 +1337,7 @@
<enabled>Yes</enabled>
</game>
<game name="College Football&apos;s National Championship (USA)" index="" image="">
<description>College Football\&apos;s National Championship (USA)</description>
<description>College Football&apos;s National Championship (USA)</description>
<cloneof></cloneof>
<crc>172c5dbb</crc>
<manufacturer>Bluesky Innovations</manufacturer>
@ -1347,7 +1347,7 @@
<enabled>Yes</enabled>
</game>
<game name="College Football&apos;s National Championship II (USA)" index="" image="">
<description>College Football\&apos;s National Championship II (USA)</description>
<description>College Football&apos;s National Championship II (USA)</description>
<cloneof></cloneof>
<crc>65b64413</crc>
<manufacturer>Bluesky Innovations</manufacturer>
@ -1477,7 +1477,7 @@
<enabled>Yes</enabled>
</game>
<game name="Crystal&apos;s Pony Tale (USA)" index="" image="">
<description>Crystal\&apos;s Pony Tale (USA)</description>
<description>Crystal&apos;s Pony Tale (USA)</description>
<cloneof></cloneof>
<crc>6cf7a4df</crc>
<manufacturer>Artech Studios</manufacturer>
@ -1547,7 +1547,7 @@
<enabled>Yes</enabled>
</game>
<game name="Dashin&apos; Desperadoes (USA)" index="" image="">
<description>Dashin\&apos; Desperadoes (USA)</description>
<description>Dashin&apos; Desperadoes (USA)</description>
<cloneof></cloneof>
<crc>dcb76fb7</crc>
<manufacturer>Data East</manufacturer>
@ -1557,7 +1557,7 @@
<enabled>Yes</enabled>
</game>
<game name="David Crane&apos;s Amazing Tennis (USA)" index="" image="">
<description>David Crane\&apos;s Amazing Tennis (USA)</description>
<description>David Crane&apos;s Amazing Tennis (USA)</description>
<cloneof></cloneof>
<crc>9177088c</crc>
<manufacturer>Absolute Entertainment</manufacturer>
@ -1567,7 +1567,7 @@
<enabled>Yes</enabled>
</game>
<game name="David Robinson&apos;s Supreme Court (USA, Europe)" index="" image="">
<description>David Robinson\&apos;s Supreme Court (USA, Europe)</description>
<description>David Robinson&apos;s Supreme Court (USA, Europe)</description>
<cloneof></cloneof>
<crc>512b7599</crc>
<manufacturer>Sega</manufacturer>
@ -1677,7 +1677,7 @@
<enabled>Yes</enabled>
</game>
<game name="Dick Vitale&apos;s &apos;Awesome, Baby!&apos; College Hoops (USA)" index="" image="">
<description>Dick Vitale\&apos;s \&apos;Awesome, Baby!\&apos; College Hoops (USA)</description>
<description>Dick Vitale&apos;s &apos;Awesome, Baby!&apos; College Hoops (USA)</description>
<cloneof></cloneof>
<crc>1312cf22</crc>
<manufacturer>Time Warner Interactive</manufacturer>
@ -1687,7 +1687,7 @@
<enabled>Yes</enabled>
</game>
<game name="Dino Dini&apos;s Soccer (Europe)" index="" image="">
<description>Dino Dini\&apos;s Soccer (Europe)</description>
<description>Dino Dini&apos;s Soccer (Europe)</description>
<cloneof></cloneof>
<crc>4608f53a</crc>
<manufacturer>Dini and Dini Productions</manufacturer>
@ -1717,7 +1717,7 @@
<enabled>Yes</enabled>
</game>
<game name="Dinosaur&apos;s Tale, A (USA)" index="" image="">
<description>Dinosaur\&apos;s Tale, A (USA)</description>
<description>Dinosaur&apos;s Tale, A (USA)</description>
<cloneof></cloneof>
<crc>70155b5b</crc>
<manufacturer>Malibu</manufacturer>
@ -1817,7 +1817,7 @@
<enabled>Yes</enabled>
</game>
<game name="Dr. Robotnik&apos;s Mean Bean Machine (USA)" index="" image="">
<description>Dr. Robotnik\&apos;s Mean Bean Machine (USA)</description>
<description>Dr. Robotnik&apos;s Mean Bean Machine (USA)</description>
<cloneof></cloneof>
<crc>c7ca517f</crc>
<manufacturer>Sega</manufacturer>
@ -1837,7 +1837,7 @@
<enabled>Yes</enabled>
</game>
<game name="Dragon&apos;s Fury (USA, Europe)" index="" image="">
<description>Dragon\&apos;s Fury (USA, Europe)</description>
<description>Dragon&apos;s Fury (USA, Europe)</description>
<cloneof></cloneof>
<crc>58037bc6</crc>
<manufacturer>TechnoSoft</manufacturer>
@ -1847,7 +1847,7 @@
<enabled>Yes</enabled>
</game>
<game name="Dragon&apos;s Revenge (USA, Europe)" index="" image="">
<description>Dragon\&apos;s Revenge (USA, Europe)</description>
<description>Dragon&apos;s Revenge (USA, Europe)</description>
<cloneof></cloneof>
<crc>841edbc0</crc>
<manufacturer>Tengen</manufacturer>
@ -2057,7 +2057,7 @@
<enabled>Yes</enabled>
</game>
<game name="Evander Holyfield&apos;s &apos;Real Deal&apos; Boxing (World)" index="" image="">
<description>Evander Holyfield\&apos;s \&apos;Real Deal\&apos; Boxing (World)</description>
<description>Evander Holyfield&apos;s &apos;Real Deal&apos; Boxing (World)</description>
<cloneof></cloneof>
<crc>4fef37c8</crc>
<manufacturer>ACME Interactive</manufacturer>
@ -2407,7 +2407,7 @@
<enabled>Yes</enabled>
</game>
<game name="Fun &apos;N&apos; Games (USA)" index="" image="">
<description>Fun \&apos;N\&apos; Games (USA)</description>
<description>Fun &apos;N&apos; Games (USA)</description>
<cloneof></cloneof>
<crc>b5ae351d</crc>
<manufacturer>Leland Interactive Media</manufacturer>
@ -2547,7 +2547,7 @@
<enabled>Yes</enabled>
</game>
<game name="George Foreman&apos;s KO Boxing (USA)" index="" image="">
<description>George Foreman\&apos;s KO Boxing (USA)</description>
<description>George Foreman&apos;s KO Boxing (USA)</description>
<cloneof></cloneof>
<crc>e1fdc787</crc>
<manufacturer>Beam Software</manufacturer>
@ -2567,7 +2567,7 @@
<enabled>Yes</enabled>
</game>
<game name="Ghouls &apos;n Ghosts (USA, Europe) (Rev A)" index="" image="">
<description>Ghouls \&apos;n Ghosts (USA, Europe) (Rev A)</description>
<description>Ghouls &apos;n Ghosts (USA, Europe) (Rev A)</description>
<cloneof></cloneof>
<crc>4f2561d5</crc>
<manufacturer>AM8</manufacturer>
@ -2607,7 +2607,7 @@
<enabled>Yes</enabled>
</game>
<game name="Goofy&apos;s Hysterical History Tour (USA)" index="" image="">
<description>Goofy\&apos;s Hysterical History Tour (USA)</description>
<description>Goofy&apos;s Hysterical History Tour (USA)</description>
<cloneof></cloneof>
<crc>4e1cc833</crc>
<manufacturer>Imagineering</manufacturer>
@ -2707,7 +2707,7 @@
<enabled>Yes</enabled>
</game>
<game name="Hard Drivin&apos; (World)" index="true" image="h">
<description>Hard Drivin\&apos; (World)</description>
<description>Hard Drivin&apos; (World)</description>
<cloneof></cloneof>
<crc>3225baaf</crc>
<manufacturer>Sterling Silver Software</manufacturer>
@ -2727,7 +2727,7 @@
<enabled>Yes</enabled>
</game>
<game name="HardBall &apos;94 (USA, Europe)" index="" image="">
<description>HardBall \&apos;94 (USA, Europe)</description>
<description>HardBall &apos;94 (USA, Europe)</description>
<cloneof></cloneof>
<crc>ea9c4878</crc>
<manufacturer>MindSpan</manufacturer>
@ -2737,7 +2737,7 @@
<enabled>Yes</enabled>
</game>
<game name="HardBall &apos;95 (USA)" index="" image="">
<description>HardBall \&apos;95 (USA)</description>
<description>HardBall &apos;95 (USA)</description>
<cloneof></cloneof>
<crc>ed10bc9e</crc>
<manufacturer>MindSpan</manufacturer>
@ -2977,7 +2977,7 @@
<enabled>Yes</enabled>
</game>
<game name="Izzy&apos;s Quest for the Olympic Rings (USA, Europe)" index="" image="">
<description>Izzy\&apos;s Quest for the Olympic Rings (USA, Europe)</description>
<description>Izzy&apos;s Quest for the Olympic Rings (USA, Europe)</description>
<cloneof></cloneof>
<crc>77b416e4</crc>
<manufacturer>Alexandria</manufacturer>
@ -2987,7 +2987,7 @@
<enabled>Yes</enabled>
</game>
<game name="Jack Nicklaus&apos; Power Challenge Golf (USA, Europe)" index="true" image="j">
<description>Jack Nicklaus\&apos; Power Challenge Golf (USA, Europe)</description>
<description>Jack Nicklaus&apos; Power Challenge Golf (USA, Europe)</description>
<cloneof></cloneof>
<crc>5545e909</crc>
<manufacturer>Accolade</manufacturer>
@ -3037,7 +3037,7 @@
<enabled>Yes</enabled>
</game>
<game name="James &apos;Buster&apos; Douglas Knockout Boxing (USA, Europe)" index="" image="">
<description>James \&apos;Buster\&apos; Douglas Knockout Boxing (USA, Europe)</description>
<description>James &apos;Buster&apos; Douglas Knockout Boxing (USA, Europe)</description>
<cloneof></cloneof>
<crc>87bbcf2a</crc>
<manufacturer>Domark</manufacturer>
@ -3097,7 +3097,7 @@
<enabled>Yes</enabled>
</game>
<game name="Jerry Glanville&apos;s Pigskin Footbrawl (USA)" index="" image="">
<description>Jerry Glanville\&apos;s Pigskin Footbrawl (USA)</description>
<description>Jerry Glanville&apos;s Pigskin Footbrawl (USA)</description>
<cloneof></cloneof>
<crc>e7f48d30</crc>
<manufacturer>Developer Resources</manufacturer>
@ -3117,7 +3117,7 @@
<enabled>Yes</enabled>
</game>
<game name="Jimmy White&apos;s Whirlwind Snooker (Europe)" index="" image="">
<description>Jimmy White\&apos;s Whirlwind Snooker (Europe)</description>
<description>Jimmy White&apos;s Whirlwind Snooker (Europe)</description>
<cloneof></cloneof>
<crc>0aef5b1f</crc>
<manufacturer>Virgin Interactive</manufacturer>
@ -3177,7 +3177,7 @@
<enabled>Yes</enabled>
</game>
<game name="John Madden Football &apos;92 (USA, Europe)" index="" image="">
<description>John Madden Football \&apos;92 (USA, Europe)</description>
<description>John Madden Football &apos;92 (USA, Europe)</description>
<cloneof></cloneof>
<crc>046e3945</crc>
<manufacturer>Park Place Productions</manufacturer>
@ -3187,7 +3187,7 @@
<enabled>Yes</enabled>
</game>
<game name="John Madden Football &apos;93 (USA, Europe)" index="" image="">
<description>John Madden Football \&apos;93 (USA, Europe)</description>
<description>John Madden Football &apos;93 (USA, Europe)</description>
<cloneof></cloneof>
<crc>ca323b3e</crc>
<manufacturer>Park Place Productions</manufacturer>
@ -3357,7 +3357,7 @@
<enabled>Yes</enabled>
</game>
<game name="King&apos;s Bounty - The Conqueror&apos;s Quest (USA, Europe)" index="" image="">
<description>King\&apos;s Bounty - The Conqueror\&apos;s Quest (USA, Europe)</description>
<description>King&apos;s Bounty - The Conqueror&apos;s Quest (USA, Europe)</description>
<cloneof></cloneof>
<crc>aa68a92e</crc>
<manufacturer>New World Computing</manufacturer>
@ -3377,7 +3377,7 @@
<enabled>Yes</enabled>
</game>
<game name="Krusty&apos;s Super Fun House (USA, Europe) (v1.1)" index="" image="">
<description>Krusty\&apos;s Super Fun House (USA, Europe) (v1.1)</description>
<description>Krusty&apos;s Super Fun House (USA, Europe) (v1.1)</description>
<cloneof></cloneof>
<crc>56976261</crc>
<manufacturer>Audiogenic</manufacturer>
@ -3637,7 +3637,7 @@
<enabled>Yes</enabled>
</game>
<game name="Madden NFL &apos;94 (USA, Europe)" index="" image="">
<description>Madden NFL \&apos;94 (USA, Europe)</description>
<description>Madden NFL &apos;94 (USA, Europe)</description>
<cloneof></cloneof>
<crc>d14b811b</crc>
<manufacturer>High Score Productions</manufacturer>
@ -3727,7 +3727,7 @@
<enabled>Yes</enabled>
</game>
<game name="Mary Shelley&apos;s Frankenstein (USA)" index="" image="">
<description>Mary Shelley\&apos;s Frankenstein (USA)</description>
<description>Mary Shelley&apos;s Frankenstein (USA)</description>
<cloneof></cloneof>
<crc>48993dc3</crc>
<manufacturer>Bits Studios</manufacturer>
@ -3767,7 +3767,7 @@
<enabled>Yes</enabled>
</game>
<game name="McDonald&apos;s Treasure Land Adventure (USA)" index="" image="">
<description>McDonald\&apos;s Treasure Land Adventure (USA)</description>
<description>McDonald&apos;s Treasure Land Adventure (USA)</description>
<cloneof></cloneof>
<crc>04ef4899</crc>
<manufacturer>Treasure</manufacturer>
@ -3897,7 +3897,7 @@
<enabled>Yes</enabled>
</game>
<game name="Michael Jackson&apos;s Moonwalker (World) (Rev A)" index="" image="">
<description>Michael Jackson\&apos;s Moonwalker (World) (Rev A)</description>
<description>Michael Jackson&apos;s Moonwalker (World) (Rev A)</description>
<cloneof></cloneof>
<crc>11ce1f9e</crc>
<manufacturer>Ultimate Productions</manufacturer>
@ -3927,7 +3927,7 @@
<enabled>Yes</enabled>
</game>
<game name="Mickey&apos;s Ultimate Challenge (USA)" index="" image="">
<description>Mickey\&apos;s Ultimate Challenge (USA)</description>
<description>Mickey&apos;s Ultimate Challenge (USA)</description>
<cloneof></cloneof>
<crc>30b512ee</crc>
<manufacturer>Designer Software</manufacturer>
@ -4177,7 +4177,7 @@
<enabled>Yes</enabled>
</game>
<game name="NBA Action &apos;94 (USA)" index="true" image="n">
<description>NBA Action \&apos;94 (USA)</description>
<description>NBA Action &apos;94 (USA)</description>
<cloneof></cloneof>
<crc>99c348ba</crc>
<manufacturer>Sega</manufacturer>
@ -4187,7 +4187,7 @@
<enabled>Yes</enabled>
</game>
<game name="NBA Action &apos;95 Starring David Robinson (USA, Europe)" index="" image="">
<description>NBA Action \&apos;95 Starring David Robinson (USA, Europe)</description>
<description>NBA Action &apos;95 Starring David Robinson (USA, Europe)</description>
<cloneof></cloneof>
<crc>aa7006d6</crc>
<manufacturer>Sega</manufacturer>
@ -4277,7 +4277,7 @@
<enabled>Yes</enabled>
</game>
<game name="NBA Showdown &apos;94 (USA, Europe)" index="" image="">
<description>NBA Showdown \&apos;94 (USA, Europe)</description>
<description>NBA Showdown &apos;94 (USA, Europe)</description>
<cloneof></cloneof>
<crc>160b7090</crc>
<manufacturer>Electronic Arts</manufacturer>
@ -4337,7 +4337,7 @@
<enabled>Yes</enabled>
</game>
<game name="NFL Football &apos;94 Starring Joe Montana (USA)" index="" image="">
<description>NFL Football \&apos;94 Starring Joe Montana (USA)</description>
<description>NFL Football &apos;94 Starring Joe Montana (USA)</description>
<cloneof></cloneof>
<crc>0d486ed5</crc>
<manufacturer>Bluesky Innovations</manufacturer>
@ -4367,7 +4367,7 @@
<enabled>Yes</enabled>
</game>
<game name="NFL Sports Talk Football &apos;93 Starring Joe Montana (USA, Europe)" index="" image="">
<description>NFL Sports Talk Football \&apos;93 Starring Joe Montana (USA, Europe)</description>
<description>NFL Sports Talk Football &apos;93 Starring Joe Montana (USA, Europe)</description>
<cloneof></cloneof>
<crc>ce0b1fe1</crc>
<manufacturer>Bluesky Innovations</manufacturer>
@ -4377,7 +4377,7 @@
<enabled>Yes</enabled>
</game>
<game name="NFL &apos;95 (USA, Europe)" index="" image="">
<description>NFL \&apos;95 (USA, Europe)</description>
<description>NFL &apos;95 (USA, Europe)</description>
<cloneof></cloneof>
<crc>b58e4a81</crc>
<manufacturer>Sega</manufacturer>
@ -4427,7 +4427,7 @@
<enabled>Yes</enabled>
</game>
<game name="NHL All-Star Hockey &apos;95 (USA)" index="" image="">
<description>NHL All-Star Hockey \&apos;95 (USA)</description>
<description>NHL All-Star Hockey &apos;95 (USA)</description>
<cloneof></cloneof>
<crc>e6c0218b</crc>
<manufacturer>Sega</manufacturer>
@ -4447,7 +4447,7 @@
<enabled>Yes</enabled>
</game>
<game name="NHL &apos;94 (USA, Europe)" index="" image="">
<description>NHL \&apos;94 (USA, Europe)</description>
<description>NHL &apos;94 (USA, Europe)</description>
<cloneof></cloneof>
<crc>9438f5dd</crc>
<manufacturer>High Score Productions</manufacturer>
@ -4467,7 +4467,7 @@
<enabled>Yes</enabled>
</game>
<game name="Nigel Mansell&apos;s World Championship Racing (USA)" index="" image="">
<description>Nigel Mansell\&apos;s World Championship Racing (USA)</description>
<description>Nigel Mansell&apos;s World Championship Racing (USA)</description>
<cloneof></cloneof>
<crc>6bc57b2c</crc>
<manufacturer>Gremlin Interactive</manufacturer>
@ -4487,7 +4487,7 @@
<enabled>Yes</enabled>
</game>
<game name="Nobunaga&apos;s Ambition (USA)" index="" image="">
<description>Nobunaga\&apos;s Ambition (USA)</description>
<description>Nobunaga&apos;s Ambition (USA)</description>
<cloneof></cloneof>
<crc>b9bc07bc</crc>
<manufacturer>Koei</manufacturer>
@ -4497,7 +4497,7 @@
<enabled>Yes</enabled>
</game>
<game name="Normy&apos;s Beach Babe-O-Rama (USA, Europe)" index="" image="">
<description>Normy\&apos;s Beach Babe-O-Rama (USA, Europe)</description>
<description>Normy&apos;s Beach Babe-O-Rama (USA, Europe)</description>
<cloneof></cloneof>
<crc>b56a8220</crc>
<manufacturer>Realtime Associates</manufacturer>
@ -5087,7 +5087,7 @@
<enabled>Yes</enabled>
</game>
<game name="R.B.I. Baseball &apos;93 (USA)" index="" image="">
<description>R.B.I. Baseball \&apos;93 (USA)</description>
<description>R.B.I. Baseball &apos;93 (USA)</description>
<cloneof></cloneof>
<crc>beafce84</crc>
<manufacturer>Tengen</manufacturer>
@ -5097,7 +5097,7 @@
<enabled>Yes</enabled>
</game>
<game name="R.B.I. Baseball &apos;94 (USA, Europe)" index="" image="">
<description>R.B.I. Baseball \&apos;94 (USA, Europe)</description>
<description>R.B.I. Baseball &apos;94 (USA, Europe)</description>
<cloneof></cloneof>
<crc>4eb4d5e4</crc>
<manufacturer>Tengen</manufacturer>
@ -5107,7 +5107,7 @@
<enabled>Yes</enabled>
</game>
<game name="Race Drivin&apos; (USA)" index="" image="">
<description>Race Drivin\&apos; (USA)</description>
<description>Race Drivin&apos; (USA)</description>
<cloneof></cloneof>
<crc>d737cf3d</crc>
<manufacturer>Polygames</manufacturer>
@ -5187,7 +5187,7 @@
<enabled>Yes</enabled>
</game>
<game name="Ren &amp; Stimpy Show Presents Stimpy&apos;s Invention, The (USA)" index="" image="">
<description>Ren &amp; Stimpy Show Presents Stimpy\&apos;s Invention, The (USA)</description>
<description>Ren &amp; Stimpy Show Presents Stimpy&apos;s Invention, The (USA)</description>
<cloneof></cloneof>
<crc>d9503ba5</crc>
<manufacturer>Blue Sky Software</manufacturer>
@ -5217,7 +5217,7 @@
<enabled>Yes</enabled>
</game>
<game name="Richard Scarry&apos;s BusyTown (USA)" index="" image="">
<description>Richard Scarry\&apos;s BusyTown (USA)</description>
<description>Richard Scarry&apos;s BusyTown (USA)</description>
<cloneof></cloneof>
<crc>7bb60c3f</crc>
<manufacturer>Novotrade</manufacturer>
@ -5337,7 +5337,7 @@
<enabled>Yes</enabled>
</game>
<game name="Rock n&apos; Roll Racing (USA)" index="" image="">
<description>Rock n\&apos; Roll Racing (USA)</description>
<description>Rock n&apos; Roll Racing (USA)</description>
<cloneof></cloneof>
<crc>6abab577</crc>
<manufacturer>Blizzard Entertainment</manufacturer>
@ -5597,7 +5597,7 @@
<enabled>Yes</enabled>
</game>
<game name="Shanghai II - Dragon&apos;s Eye (USA)" index="" image="">
<description>Shanghai II - Dragon\&apos;s Eye (USA)</description>
<description>Shanghai II - Dragon&apos;s Eye (USA)</description>
<cloneof></cloneof>
<crc>ebe9e840</crc>
<manufacturer>Activision</manufacturer>
@ -5687,7 +5687,7 @@
<enabled>Yes</enabled>
</game>
<game name="Simpsons, The - Bart&apos;s Nightmare (USA, Europe)" index="" image="">
<description>Simpsons, The - Bart\&apos;s Nightmare (USA, Europe)</description>
<description>Simpsons, The - Bart&apos;s Nightmare (USA, Europe)</description>
<cloneof></cloneof>
<crc>24d7507c</crc>
<manufacturer>Sculptured Software</manufacturer>
@ -5707,7 +5707,7 @@
<enabled>Yes</enabled>
</game>
<game name="Skitchin&apos; (USA, Europe)" index="" image="">
<description>Skitchin\&apos; (USA, Europe)</description>
<description>Skitchin&apos; (USA, Europe)</description>
<cloneof></cloneof>
<crc>f785f9d7</crc>
<manufacturer>Electronic Arts</manufacturer>
@ -5887,7 +5887,7 @@
<enabled>Yes</enabled>
</game>
<game name="Sorcerer&apos;s Kingdom (USA) (v1.1)" index="" image="">
<description>Sorcerer\&apos;s Kingdom (USA) (v1.1)</description>
<description>Sorcerer&apos;s Kingdom (USA) (v1.1)</description>
<cloneof></cloneof>
<crc>bb1fc9ce</crc>
<manufacturer>Treco</manufacturer>
@ -5907,7 +5907,7 @@
<enabled>Yes</enabled>
</game>
<game name="Space Invaders &apos;91 (USA)" index="" image="">
<description>Space Invaders \&apos;91 (USA)</description>
<description>Space Invaders &apos;91 (USA)</description>
<cloneof></cloneof>
<crc>bb83b528</crc>
<manufacturer>Taito</manufacturer>
@ -5977,7 +5977,7 @@
<enabled>Yes</enabled>
</game>
<game name="Spider-Man and X-Men - Arcade&apos;s Revenge (USA, Europe)" index="" image="">
<description>Spider-Man and X-Men - Arcade\&apos;s Revenge (USA, Europe)</description>
<description>Spider-Man and X-Men - Arcade&apos;s Revenge (USA, Europe)</description>
<cloneof></cloneof>
<crc>4a4414ea</crc>
<manufacturer>Software Creations</manufacturer>
@ -6127,7 +6127,7 @@
<enabled>Yes</enabled>
</game>
<game name="Street Fighter II&apos; - Special Champion Edition (USA)" index="" image="">
<description>Street Fighter II\&apos; - Special Champion Edition (USA)</description>
<description>Street Fighter II&apos; - Special Champion Edition (USA)</description>
<cloneof></cloneof>
<crc>13fe08a1</crc>
<manufacturer>Capcom</manufacturer>
@ -6767,7 +6767,7 @@
<enabled>Yes</enabled>
</game>
<game name="Tiny Toon Adventures - Buster&apos;s Hidden Treasure (USA)" index="" image="">
<description>Tiny Toon Adventures - Buster\&apos;s Hidden Treasure (USA)</description>
<description>Tiny Toon Adventures - Buster&apos;s Hidden Treasure (USA)</description>
<cloneof></cloneof>
<crc>a26d3ae0</crc>
<manufacturer>Konami</manufacturer>
@ -6787,7 +6787,7 @@
<enabled>Yes</enabled>
</game>
<game name="TNN Outdoors Bass Tournament &apos;96 (USA)" index="" image="">
<description>TNN Outdoors Bass Tournament \&apos;96 (USA)</description>
<description>TNN Outdoors Bass Tournament &apos;96 (USA)</description>
<cloneof></cloneof>
<crc>5c523c0b</crc>
<manufacturer>Imagitec Design</manufacturer>
@ -6797,7 +6797,7 @@
<enabled>Yes</enabled>
</game>
<game name="Todd&apos;s Adventures in Slime World (USA)" index="" image="">
<description>Todd\&apos;s Adventures in Slime World (USA)</description>
<description>Todd&apos;s Adventures in Slime World (USA)</description>
<cloneof></cloneof>
<crc>652e8b7d</crc>
<manufacturer>Epyx</manufacturer>
@ -7127,7 +7127,7 @@
<enabled>Yes</enabled>
</game>
<game name="Unnecessary Roughness &apos;95 (USA)" index="" image="">
<description>Unnecessary Roughness \&apos;95 (USA)</description>
<description>Unnecessary Roughness &apos;95 (USA)</description>
<cloneof></cloneof>
<crc>9920e7b7</crc>
<manufacturer>Accolade</manufacturer>
@ -7337,7 +7337,7 @@
<enabled>Yes</enabled>
</game>
<game name="Wayne&apos;s World (USA)" index="" image="">
<description>Wayne\&apos;s World (USA)</description>
<description>Wayne&apos;s World (USA)</description>
<cloneof></cloneof>
<crc>d2cf6ebe</crc>
<manufacturer>Gray Matter</manufacturer>
@ -7407,7 +7407,7 @@
<enabled>Yes</enabled>
</game>
<game name="Williams Arcade&apos;s Greatest Hits (USA)" index="" image="">
<description>Williams Arcade\&apos;s Greatest Hits (USA)</description>
<description>Williams Arcade&apos;s Greatest Hits (USA)</description>
<cloneof></cloneof>
<crc>d68e9c00</crc>
<manufacturer>Digital Eclipse</manufacturer>
@ -7457,7 +7457,7 @@
<enabled>Yes</enabled>
</game>
<game name="Wiz&apos;n&apos;Liz (USA)" index="" image="">
<description>Wiz\&apos;n\&apos;Liz (USA)</description>
<description>Wiz&apos;n&apos;Liz (USA)</description>
<cloneof></cloneof>
<crc>df036b62</crc>
<manufacturer>Raising Hell</manufacturer>
@ -7587,7 +7587,7 @@
<enabled>Yes</enabled>
</game>
<game name="World Series Baseball &apos;95 (USA)" index="" image="">
<description>World Series Baseball \&apos;95 (USA)</description>
<description>World Series Baseball &apos;95 (USA)</description>
<cloneof></cloneof>
<crc>25130077</crc>
<manufacturer>Blue Sky Software</manufacturer>
@ -7597,7 +7597,7 @@
<enabled>Yes</enabled>
</game>
<game name="World Series Baseball &apos;96 (USA)" index="" image="">
<description>World Series Baseball \&apos;96 (USA)</description>
<description>World Series Baseball &apos;96 (USA)</description>
<cloneof></cloneof>
<crc>04ee8272</crc>
<manufacturer>Blue Sky Software</manufacturer>
@ -7787,7 +7787,7 @@
<enabled>Yes</enabled>
</game>
<game name="Zool - Ninja of the &apos;Nth&apos; Dimension (USA)" index="" image="">
<description>Zool - Ninja of the \&apos;Nth\&apos; Dimension (USA)</description>
<description>Zool - Ninja of the &apos;Nth&apos; Dimension (USA)</description>
<cloneof></cloneof>
<crc>cb2939f1</crc>
<manufacturer>Gremlin Interactive</manufacturer>

View File

@ -22,6 +22,9 @@ showSquareBrackets = yes
# specify the name of the first collection to load on start
firstCollection = Main
# specify whether RetroFE should switch to Favorites list if it exists.
autoFavorites = true
#######################################
# Video playback settings
#######################################

View File

@ -17,8 +17,22 @@
#include "Item.h"
#include "../Database/Configuration.h"
#include "../Utility/Utils.h"
#include "../Utility/Log.h"
#include <sstream>
#include <fstream>
#include <algorithm>
#include <exception>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef _WIN32
#include <Windows.h>
#endif
#ifdef __linux
#include <errno.h>
#include <cstring>
#endif
CollectionInfo::CollectionInfo(std::string name,
std::string listPath,
@ -27,6 +41,7 @@ CollectionInfo::CollectionInfo(std::string name,
std::string metadataPath)
: name(name)
, listpath(listPath)
, saveRequest(false)
, metadataType(metadataType)
, menusort(true)
, metadataPath_(metadataPath)
@ -39,13 +54,25 @@ CollectionInfo::~CollectionInfo()
// remove items from the subcollections so their destructors do not
// delete the items since the parent collection will delete them.
std::vector<CollectionInfo *>::iterator subit;
for (subit != subcollections_.begin(); subit != subcollections_.end(); subit++)
for (subit = subcollections_.begin(); subit != subcollections_.end(); subit++)
{
CollectionInfo *info = *subit;
info->items.clear();
}
Playlists_T::iterator pit = playlists.begin();
while(pit != playlists.end())
{
if(pit->second != &items)
{
delete pit->second;
}
playlists.erase(pit);
pit = playlists.begin();
}
std::vector<Item *>::iterator it = items.begin();
while(it != items.end())
{
@ -55,6 +82,68 @@ CollectionInfo::~CollectionInfo()
}
}
bool CollectionInfo::Save()
{
bool retval = true;
if(saveRequest)
{
std::string dir = Utils::combinePath(Configuration::absolutePath, "collections", name, "playlists");
std::string file = Utils::combinePath(Configuration::absolutePath, "collections", name, "playlists/favorites.txt");
Logger::write(Logger::ZONE_INFO, "Collection", "Saving " + file);
std::ofstream filestream;
try
{
// Create playlists directory if it does not exist yet.
struct stat info;
if ( stat( dir.c_str(), &info ) != 0 )
{
#if defined(_WIN32) && !defined(__GNUC__)
if(!CreateDirectory(dir.c_str(), NULL))
{
if(ERROR_ALREADY_EXISTS != GetLastError())
{
Logger::write(Logger::ZONE_WARNING, "Collection", "Could not create directory " + dir);
return false;
}
}
#else
#if defined(__MINGW32__)
if(mkdir(dir.c_str()) == -1)
#else
if(mkdir(dir.c_str(), 0755) == -1)
#endif
{
Logger::write(Logger::ZONE_WARNING, "Collection", "Could not create directory " + dir);
return false;
}
#endif
}
else if ( !(info.st_mode & S_IFDIR) )
{
Logger::write(Logger::ZONE_WARNING, "Collection", dir + " exists, but is not a directory.");
return false;
}
filestream.open(file.c_str());
std::vector<Item *> *saveitems = playlists["favorites"];
for(std::vector<Item *>::iterator it = saveitems->begin(); it != saveitems->end(); it++)
{
filestream << (*it)->name << std::endl;
}
filestream.close();
}
catch(std::exception &)
{
Logger::write(Logger::ZONE_ERROR, "Collection", "Save failed: " + file);
retval = false;
}
}
return retval;
}
std::string CollectionInfo::settingsPath() const
{
return Utils::combinePath(Configuration::absolutePath, "collections", name);
@ -95,5 +184,8 @@ bool CollectionInfo::itemIsLess(Item *lhs, Item *rhs)
void CollectionInfo::sortItems()
{
std::sort(items.begin(), items.end(), itemIsLess);
for(Playlists_T::iterator it = playlists.begin(); it != playlists.end(); it++)
{
std::sort(it->second->begin(), it->second->end(), itemIsLess);
}
}

View File

@ -17,6 +17,7 @@
#include <string>
#include <vector>
#include <map>
class Item;
@ -26,15 +27,21 @@ public:
CollectionInfo(std::string name, std::string listPath, std::string extensions, std::string metadataType, std::string metadataPath);
virtual ~CollectionInfo();
std::string settingsPath() const;
bool Save();
void sortItems();
void addSubcollection(CollectionInfo *info);
bool hasSubcollections();
void extensionList(std::vector<std::string> &extensions);
std::string name;
std::string listpath;
bool saveRequest;
std::string metadataType;
std::string launcher;
std::vector<Item *> items;
typedef std::map<std::string, std::vector <Item *> *> Playlists_T;
Playlists_T playlists;
bool menusort;
private:
std::vector<CollectionInfo *> subcollections_;

View File

@ -81,7 +81,7 @@ bool CollectionInfoBuilder::createCollectionDirectory(std::string name)
#if defined(__MINGW32__)
if(mkdir(it->c_str()) == -1)
#else
if(mkdir(it->c_str(), 0744) == -1)
if(mkdir(it->c_str(), 0755) == -1)
#endif
{
std::cout << "Could not create folder \"" << *it << "\":" << errno << std::endl;
@ -119,18 +119,23 @@ bool CollectionInfoBuilder::createCollectionDirectory(std::string name)
settingsFile << "list.menuSort = yes" << std::endl;
settingsFile << std::endl;
settingsFile << "launcher = mame" << std::endl;
settingsFile << "metadata.type = MAME" << std::endl;
settingsFile << "#metadata.type = MAME" << std::endl;
settingsFile << std::endl;
settingsFile << "#media.screenshot = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "screenshot") << std::endl;
settingsFile << "#media.screentitle = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "screentitle") << std::endl;
settingsFile << "#media.artwork_back = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "artwork_back") << std::endl;
settingsFile << "#media.artwork_front = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "artwork_front") << std::endl;
settingsFile << "#media.logo = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "logo") << std::endl;
settingsFile << "#media.medium_back = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "medium_back") << std::endl;
settingsFile << "#media.medium_front = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "medium_front") << std::endl;
settingsFile << "#media.screenshot = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "screenshot") << std::endl;
settingsFile << "#media.screentitle = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "screentitle") << std::endl;
settingsFile << "#media.video = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "video") << std::endl;
settingsFile << "#manufacturer = " << std::endl;
settingsFile << "#year = " << std::endl;
settingsFile << "#genre = " << std::endl;
settingsFile << std::endl;
settingsFile << "#media.screenshot = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "screenshot") << std::endl;
settingsFile << "#media.screentitle = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "screentitle") << std::endl;
settingsFile << "#media.artwork_back = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "artwork_back") << std::endl;
settingsFile << "#media.artwork_front = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "artwork_front") << std::endl;
settingsFile << "#media.logo = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "logo") << std::endl;
settingsFile << "#media.medium_back = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "medium_back") << std::endl;
settingsFile << "#media.medium_front = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "medium_front") << std::endl;
settingsFile << "#media.screenshot = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "screenshot") << std::endl;
settingsFile << "#media.screentitle = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "screentitle") << std::endl;
settingsFile << "#media.video = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "medium_artwork", "video") << std::endl;
settingsFile << "#media.system_artwork = " << Utils::combinePath("%BASE_MEDIA_PATH%", "%ITEM_COLLECTION_NAME%", "system_artwork") << std::endl;
settingsFile.close();
filename = Utils::combinePath(collectionPath, "menu.txt");
@ -230,9 +235,12 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me
DIR *dp;
struct dirent *dirp;
std::string path = info->listpath;
std::map<std::string, Item *> allMap;
std::map<std::string, Item *> includeFilter;
std::map<std::string, Item *> favoritesFilter;
std::map<std::string, Item *> excludeFilter;
std::string includeFile = Utils::combinePath(Configuration::absolutePath, "collections", info->name, "include.txt");
std::string favoritesFile = Utils::combinePath(Configuration::absolutePath, "collections", info->name, "playlists/favorites.txt");
std::string excludeFile = Utils::combinePath(Configuration::absolutePath, "collections", info->name, "exclude.txt");
std::string launcher;
@ -266,14 +274,12 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me
info->extensionList(extensions);
dp = opendir(path.c_str());
Logger::write(Logger::ZONE_INFO, "CollectionInfoBuilder", "Scanning directory \"" + path + "\"");
if(dp == NULL)
{
Logger::write(Logger::ZONE_INFO, "CollectionInfoBuilder", "Could not read directory \"" + path + "\". Ignore if this is a menu.");
return false;
}
if(showMissing)
@ -287,7 +293,7 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me
}
}
while((dirp = readdir(dp)) != NULL)
while(dp != NULL && (dirp = readdir(dp)) != NULL)
{
std::string file = dirp->d_name;
@ -322,7 +328,10 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me
}
}
closedir(dp);
if(dp != NULL)
{
closedir(dp);
}
while(includeFilter.size() > 0)
{
@ -341,6 +350,27 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me
excludeFilter.erase(it);
}
for(std::vector<Item *>::iterator it = info->items.begin(); it != info->items.end(); it++) {
allMap[(*it)->fullTitle] = *it;
}
ImportBasicList(info, favoritesFile, favoritesFilter);
info->playlists["all"] = &info->items;
info->playlists["favorites"] = new std::vector<Item *>();
// add the favorites list
for(std::map<std::string, Item *>::iterator it = favoritesFilter.begin(); it != favoritesFilter.end(); it++)
{
std::map<std::string, Item *>::iterator itemit = allMap.find(it->first);
if(itemit != allMap.end())
{
info->playlists["favorites"]->push_back(itemit->second);
}
}
metaDB_.injectMetadata(info);
return true;

View File

@ -30,6 +30,7 @@ UserInput::UserInput(Configuration &c)
for(unsigned int i = 0; i < KeyCodeMax; ++i)
{
keyHandlers_[i] = NULL;
currentKeyState_[i] = false;
lastKeyState_[i] = false;
}
}
@ -66,13 +67,18 @@ bool UserInput::initialize()
retVal = MapKey("down", KeyCodeRight) && retVal;
}
retVal = MapKey("pageDown", KeyCodePageDown) && retVal;
retVal = MapKey("pageUp", KeyCodePageUp) && retVal;
MapKey("letterDown", KeyCodeLetterDown);
MapKey("letterUp", KeyCodeLetterUp);
retVal = MapKey("select", KeyCodeSelect) && retVal;
retVal = MapKey("back", KeyCodeBack) && retVal;
retVal = MapKey("quit", KeyCodeQuit) && retVal;
retVal = MapKey("pageDown", KeyCodePageDown);
retVal = MapKey("pageUp", KeyCodePageUp);
MapKey("letterDown", KeyCodeLetterDown, false);
MapKey("letterUp", KeyCodeLetterUp, false);
MapKey("nextPlaylist", KeyCodeNextPlaylist, false);
MapKey("addPlaylist", KeyCodeAddPlaylist, false);
MapKey("removePlaylist", KeyCodeRemovePlaylist, false);
MapKey("random", KeyCodeRandom, false);
// these features will need to be implemented at a later time
// retVal = MapKey("admin", KeyCodeAdminMode) && retVal;
// retVal = MapKey("remove", KeyCodeHideItem) && retVal;
@ -87,6 +93,11 @@ bool UserInput::initialize()
}
bool UserInput::MapKey(std::string keyDescription, KeyCode_E key)
{
return MapKey(keyDescription, key, true);
}
bool UserInput::MapKey(std::string keyDescription, KeyCode_E key, bool required)
{
SDL_Scancode scanCode;
std::string description;
@ -95,7 +106,8 @@ bool UserInput::MapKey(std::string keyDescription, KeyCode_E key)
if(!config_.getProperty(configKey, description))
{
Logger::write(Logger::ZONE_ERROR, "Input", "Missing property " + configKey);
Logger::Zone zone = (required) ? Logger::ZONE_ERROR : Logger::ZONE_INFO;
Logger::write(zone, "Input", "Missing property " + configKey);
return false;
}
@ -223,6 +235,9 @@ void UserInput::resetStates()
bool UserInput::update(SDL_Event &e)
{
bool updated = false;
memcpy(lastKeyState_, currentKeyState_, sizeof(lastKeyState_));
for(unsigned int i = 0; i < KeyCodeMax; ++i)
{
InputHandler *h = keyHandlers_[i];
@ -230,7 +245,7 @@ bool UserInput::update(SDL_Event &e)
{
if(h->update(e)) updated = true;
lastKeyState_[i] = h->pressed();
currentKeyState_[i] = h->pressed();
}
}
@ -239,5 +254,11 @@ bool UserInput::update(SDL_Event &e)
bool UserInput::keystate(KeyCode_E code)
{
return lastKeyState_[code];
return currentKeyState_[code];
}
bool UserInput::newKeyPressed(KeyCode_E code)
{
return currentKeyState_[code] && !lastKeyState_[code];
}

View File

@ -39,6 +39,10 @@ public:
KeyCodePageUp,
KeyCodeLetterDown,
KeyCodeLetterUp,
KeyCodeNextPlaylist,
KeyCodeRandom,
KeyCodeAddPlaylist,
KeyCodeRemovePlaylist,
KeyCodeAdminMode,
KeyCodeHideItem,
KeyCodeQuit,
@ -51,12 +55,14 @@ public:
void resetStates();
bool update(SDL_Event &e);
bool keystate(KeyCode_E);
bool newKeyPressed(KeyCode_E code);
private:
bool MapKey(std::string keyDescription, KeyCode_E key);
bool MapKey(std::string keyDescription, KeyCode_E key, bool required);
Configuration &config_;
std::vector<SDL_Joystick *> joysticks_;
InputHandler *keyHandlers_[KeyCodeMax];
bool lastKeyState_[KeyCodeMax];
bool currentKeyState_[KeyCodeMax];
};

View File

@ -130,15 +130,14 @@ bool Configuration::parseLine(std::string collection, std::string keyPrefix, std
key = trimEnds(key);
value = line.substr(position + delimiter.length(), line.length());
value = trimEnds(value);
// only overwrite the collection name if we know it. We could be parsing a launcher configuration
if(collection != "")
{
value = Utils::replace(value, "%ITEM_COLLECTION_NAME%", collection);
}
properties_.insert(PropertiesPair(key, value));
std::stringstream ss;
@ -305,11 +304,9 @@ std::string Configuration::convertToAbsolutePath(std::string prefix, std::string
}
// check to see if it is already an absolute path
#ifdef WIN32
if((first != '\\') && (first != '/') && (second != ':'))
#else
if(first != Utils::pathSeparator)
#endif
if((first != Utils::pathSeparator) &&
//(first != '.') &&
(second != ':'))
{
path = Utils::combinePath(prefix, path);
}
@ -338,6 +335,10 @@ void Configuration::getMediaPropertyAbsolutePath(std::string collectionName, std
void Configuration::getMediaPropertyAbsolutePath(std::string collectionName, std::string mediaType, bool system, std::string &value)
{
std::string key = "collections." + collectionName + ".media." + mediaType;
if (system)
{
key = "collections." + collectionName + ".media.system_artwork";
}
// use user-overridden setting if it exists
if(getPropertyAbsolutePath(key, value))

View File

@ -417,7 +417,14 @@ bool MetadataDatabase::importMamelist(std::string filename, std::string collecti
}
sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", NULL, NULL, &error);
for (rapidxml::xml_node<> * game = rootNode->first_node("game"); game; game = game->next_sibling())
std::string gameNodeName = "game";
// support new mame formats
if(rootNode->first_node(gameNodeName.c_str()) == NULL) {
gameNodeName = "machine";
}
for (rapidxml::xml_node<> * game = rootNode->first_node(gameNodeName.c_str()); game; game = game->next_sibling())
{
rapidxml::xml_attribute<> *nameNode = game->first_attribute("name");
rapidxml::xml_attribute<> *cloneOfXml = game->first_attribute("cloneof");

View File

@ -67,29 +67,28 @@ bool Launcher::run(std::string collection, Item *collectionItem)
Logger::write(Logger::ZONE_ERROR, "Launcher", "No launcher arguments specified for launcher " + launcherName);
return false;
}
if(!findFile(selectedItemsPath, matchedExtension, selectedItemsDirectory, collectionItem->name, extensionstr))
{
// FindFile() prints out diagnostic messages for us, no need to print anything here
return false;
}
// It is ok to continue if the file could not be found. We could be launching a merged romset
findFile(selectedItemsPath, matchedExtension, selectedItemsDirectory, collectionItem->name, extensionstr);
args = replaceVariables(args,
selectedItemsPath,
collectionItem->name,
collectionItem->filename(),
Utils::getFileName(selectedItemsPath),
selectedItemsDirectory,
collection);
executablePath = replaceVariables(executablePath,
selectedItemsPath,
collectionItem->name,
collectionItem->filename(),
Utils::getFileName(selectedItemsPath),
selectedItemsDirectory,
collection);
currentDirectory = replaceVariables(currentDirectory,
selectedItemsPath,
collectionItem->name,
collectionItem->filename(),
Utils::getFileName(selectedItemsPath),
selectedItemsDirectory,
collection);
@ -329,7 +328,7 @@ bool Launcher::findFile(std::string &foundFilePath, std::string &foundFilename,
<< filenameWithoutExtension << "\" in folder \""
<< directory;
Logger::write(Logger::ZONE_ERROR, "Launcher", ss.str());
Logger::write(Logger::ZONE_WARNING, "Launcher", ss.str());
}

View File

@ -1,460 +1,460 @@
/* This file is part of RetroFE.
*
* RetroFE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RetroFE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Component.h"
#include "../Animate/Tween.h"
#include "../../Graphics/ViewInfo.h"
#include "../../Utility/Log.h"
#include "../../SDL.h"
Component::Component()
{
tweens_ = NULL;
selectedItem_ = NULL;
newItemSelectedSinceEnter = false;
backgroundTexture_ = NULL;
freeGraphicsMemory();
}
Component::Component(const Component &copy)
{
tweens_ = NULL;
selectedItem_ = NULL;
newItemSelectedSinceEnter = false;
backgroundTexture_ = NULL;
freeGraphicsMemory();
/* This file is part of RetroFE.
*
* RetroFE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RetroFE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Component.h"
#include "../Animate/Tween.h"
#include "../../Graphics/ViewInfo.h"
#include "../../Utility/Log.h"
#include "../../SDL.h"
Component::Component(Page &p)
: page(p)
{
tweens_ = NULL;
newItemSelectedSinceEnter = false;
backgroundTexture_ = NULL;
freeGraphicsMemory();
}
Component::Component(const Component &copy)
: page(copy.page)
{
tweens_ = NULL;
newItemSelectedSinceEnter = false;
backgroundTexture_ = NULL;
freeGraphicsMemory();
if(copy.tweens_)
{
AnimationEvents *tweens = new AnimationEvents(*copy.tweens_);
setTweens(tweens);
}
}
Component::~Component()
{
freeGraphicsMemory();
}
void Component::freeGraphicsMemory()
{
currentAnimationState = HIDDEN;
enterRequested = false;
exitRequested = false;
menuEnterRequested = false;
menuEnterIndex = -1;
menuScrollRequested = false;
menuExitRequested = false;
menuExitIndex = -1;
newItemSelected = false;
highlightExitComplete = false;
currentTweens_ = NULL;
currentTweenIndex_ = 0;
currentTweenComplete_ = false;
elapsedTweenTime_ = 0;
scrollActive = false;
if(backgroundTexture_)
{
SDL_LockMutex(SDL::getMutex());
SDL_DestroyTexture(backgroundTexture_);
SDL_UnlockMutex(SDL::getMutex());
backgroundTexture_ = NULL;
}
}
void Component::allocateGraphicsMemory()
{
if(!backgroundTexture_)
{
// make a 4x4 pixel wide surface to be stretched during rendering, make it a white background so we can use
// color later
SDL_Surface *surface = SDL_CreateRGBSurface(0, 4, 4, 32, 0, 0, 0, 0);
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 255, 255, 255));
SDL_LockMutex(SDL::getMutex());
backgroundTexture_ = SDL_CreateTextureFromSurface(SDL::getRenderer(), surface);
SDL_UnlockMutex(SDL::getMutex());
SDL_FreeSurface(surface);
SDL_SetTextureBlendMode(backgroundTexture_, SDL_BLENDMODE_BLEND);
}
}
Item *Component::getSelectedItem()
{
return selectedItem_;
}
void Component::triggerEnterEvent()
{
enterRequested = true;
}
void Component::triggerExitEvent()
{
exitRequested = true;
}
void Component::triggerMenuEnterEvent(int menuIndex)
{
menuEnterRequested = true;
menuEnterIndex = menuIndex;
}
void Component::triggerMenuScrollEvent()
{
menuScrollRequested = true;
}
void Component::triggerMenuExitEvent(int menuIndex)
{
menuExitRequested = true;
menuExitIndex = menuIndex;
}
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);
}
bool Component::isMenuScrolling()
{
return (currentAnimationState == MENU_ENTER || currentAnimationState == MENU_SCROLL || currentAnimationState == MENU_EXIT || menuScrollRequested);
}
void Component::setTweens(AnimationEvents *set)
{
tweens_ = set;
forceIdle();
}
void Component::forceIdle()
{
currentAnimationState = IDLE;
currentTweenIndex_ = 0;
currentTweenComplete_ = false;
elapsedTweenTime_ = 0;
currentTweens_ = NULL;
}
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.
std::stringstream ss;
switch(currentAnimationState)
{
case MENU_ENTER:
currentTweens_ = NULL;
currentAnimationState = IDLE;
break;
case MENU_SCROLL:
currentTweens_ = NULL;
currentAnimationState = IDLE;
break;
case MENU_EXIT:
currentTweens_ = NULL;
currentAnimationState = IDLE;
break;
case ENTER:
currentTweens_ = tweens_->getAnimation("enter", menuEnterIndex);
currentAnimationState = HIGHLIGHT_ENTER;
break;
case EXIT:
currentTweens_ = NULL;
currentAnimationState = HIDDEN;
break;
case HIGHLIGHT_ENTER:
currentTweens_ = tweens_->getAnimation("idle", menuEnterIndex);
currentAnimationState = IDLE;
break;
case IDLE:
// prevent us from automatically jumping to the exit tween upon enter
if(enterRequested)
{
enterRequested = false;
newItemSelected = false;
}
else if(menuExitRequested && (!menuEnterRequested || menuExitRequested <= menuEnterRequested))
{
currentTweens_ = tweens_->getAnimation("menuExit", menuExitIndex);
currentAnimationState = MENU_EXIT;
menuExitRequested = false;
}
else if(menuEnterRequested && (!menuExitRequested || menuExitRequested > menuEnterRequested))
{
currentTweens_ = tweens_->getAnimation("menuEnter", menuEnterIndex);
currentAnimationState = MENU_ENTER;
menuEnterRequested = false;
}
else if(menuScrollRequested)
{
menuScrollRequested = false;
currentTweens_ = tweens_->getAnimation("menuScroll", menuEnterIndex);
currentAnimationState = MENU_SCROLL;
}
else if(scrollActive || newItemSelected || exitRequested)
{
currentTweens_ = tweens_->getAnimation("highlightExit", menuEnterIndex);
currentAnimationState = HIGHLIGHT_EXIT;
}
else
{
currentTweens_ = tweens_->getAnimation("idle", menuEnterIndex);
currentAnimationState = IDLE;
}
break;
case HIGHLIGHT_EXIT:
// intentionally break down
case HIGHLIGHT_WAIT:
if(exitRequested && (currentAnimationState == HIGHLIGHT_WAIT))
{
currentTweens_ = tweens_->getAnimation("highlightExit", menuEnterIndex);
currentAnimationState = HIGHLIGHT_EXIT;
}
else if(exitRequested && (currentAnimationState == HIGHLIGHT_EXIT))
{
currentTweens_ = tweens_->getAnimation("exit", menuEnterIndex);
currentAnimationState = EXIT;
exitRequested = false;
}
else if(scrollActive)
{
currentTweens_ = NULL;
currentAnimationState = HIGHLIGHT_WAIT;
}
else if(newItemSelected)
{
currentTweens_ = tweens_->getAnimation("highlightEnter", menuEnterIndex);
currentAnimationState = HIGHLIGHT_ENTER;
highlightExitComplete = true;
newItemSelected = false;
}
else
{
currentTweens_ = NULL;
currentAnimationState = HIGHLIGHT_WAIT;
}
break;
case HIDDEN:
if(enterRequested || exitRequested)
{
currentTweens_ = tweens_->getAnimation("enter", menuEnterIndex);
currentAnimationState = ENTER;
}
else if(menuExitRequested && (!menuEnterRequested || menuExitRequested <= menuEnterRequested))
{
currentTweens_ = tweens_->getAnimation("menuExit", menuExitIndex);
currentAnimationState = MENU_EXIT;
menuExitRequested = false;
}
else if(menuEnterRequested && (!menuExitRequested || menuExitRequested > menuEnterRequested))
{
currentTweens_ = tweens_->getAnimation("menuEnter", menuEnterIndex);
currentAnimationState = MENU_ENTER;
menuEnterRequested = false;
}
else if(menuScrollRequested)
{
menuScrollRequested = false;
currentTweens_ = tweens_->getAnimation("menuScroll", menuEnterIndex);
currentAnimationState = MENU_SCROLL;
}
else
{
currentTweens_ = NULL;
currentAnimationState = HIDDEN;
}
}
currentTweenIndex_ = 0;
currentTweenComplete_ = false;
elapsedTweenTime_ = 0;
}
currentTweenComplete_ = animate(isIdle());
}
void Component::draw()
{
if(backgroundTexture_)
{
SDL_Rect rect;
rect.h = static_cast<int>(baseViewInfo.ScaledHeight());
rect.w = static_cast<int>(baseViewInfo.ScaledWidth());
rect.x = static_cast<int>(baseViewInfo.XRelativeToOrigin());
rect.y = static_cast<int>(baseViewInfo.YRelativeToOrigin());
SDL_SetTextureColorMod(backgroundTexture_,
static_cast<char>(baseViewInfo.BackgroundRed*255),
static_cast<char>(baseViewInfo.BackgroundGreen*255),
static_cast<char>(baseViewInfo.BackgroundBlue*255));
SDL::renderCopy(backgroundTexture_, static_cast<char>(baseViewInfo.BackgroundAlpha*255), NULL, &rect, baseViewInfo.Angle);
}
}
bool Component::animate(bool loop)
{
bool completeDone = false;
if(!currentTweens_ || currentTweenIndex_ >= currentTweens_->size())
{
completeDone = true;
}
else if(currentTweens_)
{
bool currentDone = true;
TweenSet *tweens = currentTweens_->tweenSet(currentTweenIndex_);
for(unsigned int i = 0; i < tweens->size(); i++)
{
Tween *tween = tweens->tweens()->at(i);
double elapsedTime = elapsedTweenTime_;
//todo: too many levels of nesting
if(elapsedTime < tween->duration)
{
currentDone = false;
}
else
{
elapsedTime = static_cast<float>(tween->duration);
}
float value = tween->animate(elapsedTime);
switch(tween->property)
{
case TWEEN_PROPERTY_X:
baseViewInfo.X = value;
break;
case TWEEN_PROPERTY_Y:
baseViewInfo.Y = value;
break;
case TWEEN_PROPERTY_HEIGHT:
baseViewInfo.Height = value;
break;
case TWEEN_PROPERTY_WIDTH:
baseViewInfo.Width = value;
break;
case TWEEN_PROPERTY_ANGLE:
baseViewInfo.Angle = value;
break;
case TWEEN_PROPERTY_ALPHA:
baseViewInfo.Alpha = value;
break;
case TWEEN_PROPERTY_X_ORIGIN:
baseViewInfo.XOrigin = value;
break;
case TWEEN_PROPERTY_Y_ORIGIN:
baseViewInfo.YOrigin = value;
break;
case TWEEN_PROPERTY_X_OFFSET:
baseViewInfo.XOffset = value;
break;
case TWEEN_PROPERTY_Y_OFFSET:
baseViewInfo.YOffset = value;
break;
case TWEEN_PROPERTY_FONT_SIZE:
baseViewInfo.FontSize = value;
break;
case TWEEN_PROPERTY_BACKGROUND_ALPHA:
baseViewInfo.BackgroundAlpha = value;
break;
}
}
if(currentDone)
{
currentTweenIndex_++;
elapsedTweenTime_ = 0;
}
}
if(!currentTweens_ || currentTweenIndex_ >= currentTweens_->tweenSets()->size())
{
if(loop)
{
currentTweenIndex_ = 0;
}
completeDone = true;
}
return completeDone;
}
}
}
Component::~Component()
{
freeGraphicsMemory();
}
void Component::freeGraphicsMemory()
{
currentAnimationState = HIDDEN;
enterRequested = false;
exitRequested = false;
menuEnterRequested = false;
menuEnterIndex = -1;
menuScrollRequested = false;
menuExitRequested = false;
menuExitIndex = -1;
newItemSelected = false;
playlistChanged = false;
highlightExitComplete = false;
currentTweens_ = NULL;
currentTweenIndex_ = 0;
currentTweenComplete_ = false;
elapsedTweenTime_ = 0;
scrollActive = false;
if(backgroundTexture_)
{
SDL_LockMutex(SDL::getMutex());
SDL_DestroyTexture(backgroundTexture_);
SDL_UnlockMutex(SDL::getMutex());
backgroundTexture_ = NULL;
}
}
void Component::allocateGraphicsMemory()
{
if(!backgroundTexture_)
{
// make a 4x4 pixel wide surface to be stretched during rendering, make it a white background so we can use
// color later
SDL_Surface *surface = SDL_CreateRGBSurface(0, 4, 4, 32, 0, 0, 0, 0);
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 255, 255, 255));
SDL_LockMutex(SDL::getMutex());
backgroundTexture_ = SDL_CreateTextureFromSurface(SDL::getRenderer(), surface);
SDL_UnlockMutex(SDL::getMutex());
SDL_FreeSurface(surface);
SDL_SetTextureBlendMode(backgroundTexture_, SDL_BLENDMODE_BLEND);
}
}
void Component::triggerEnterEvent()
{
enterRequested = true;
}
void Component::triggerExitEvent()
{
exitRequested = true;
}
void Component::triggerMenuEnterEvent(int menuIndex)
{
menuEnterRequested = true;
menuEnterIndex = menuIndex;
}
void Component::triggerMenuScrollEvent()
{
menuScrollRequested = true;
}
void Component::triggerMenuExitEvent(int menuIndex)
{
menuExitRequested = true;
menuExitIndex = menuIndex;
}
void Component::triggerHighlightEvent()
{
newItemSelected = true;
}
void Component::triggerPlaylistChangeEvent(std::string name)
{
playlistChanged = true;
this->playlistName = name;
}
bool Component::isIdle()
{
return (currentAnimationState == IDLE);
}
bool Component::isHidden()
{
return (currentAnimationState == HIDDEN);
}
bool Component::isWaiting()
{
return (currentAnimationState == HIGHLIGHT_WAIT);
}
bool Component::isMenuScrolling()
{
return (currentAnimationState == MENU_ENTER || currentAnimationState == MENU_SCROLL || currentAnimationState == MENU_EXIT || menuScrollRequested);
}
void Component::setTweens(AnimationEvents *set)
{
tweens_ = set;
forceIdle();
}
void Component::forceIdle()
{
currentAnimationState = IDLE;
currentTweenIndex_ = 0;
currentTweenComplete_ = false;
elapsedTweenTime_ = 0;
currentTweens_ = NULL;
}
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.
std::stringstream ss;
switch(currentAnimationState)
{
case MENU_ENTER:
currentTweens_ = NULL;
currentAnimationState = IDLE;
break;
case MENU_SCROLL:
currentTweens_ = NULL;
currentAnimationState = IDLE;
break;
case MENU_EXIT:
currentTweens_ = NULL;
currentAnimationState = IDLE;
break;
case ENTER:
currentTweens_ = tweens_->getAnimation("enter", menuEnterIndex);
currentAnimationState = HIGHLIGHT_ENTER;
break;
case EXIT:
currentTweens_ = NULL;
currentAnimationState = HIDDEN;
break;
case HIGHLIGHT_ENTER:
currentTweens_ = tweens_->getAnimation("idle", menuEnterIndex);
currentAnimationState = IDLE;
break;
case IDLE:
// prevent us from automatically jumping to the exit tween upon enter
if(enterRequested)
{
enterRequested = false;
newItemSelected = false;
}
else if(menuExitRequested && (!menuEnterRequested || menuExitRequested <= menuEnterRequested))
{
currentTweens_ = tweens_->getAnimation("menuExit", menuExitIndex);
currentAnimationState = MENU_EXIT;
menuExitRequested = false;
}
else if(menuEnterRequested && (!menuExitRequested || menuExitRequested > menuEnterRequested))
{
currentTweens_ = tweens_->getAnimation("menuEnter", menuEnterIndex);
currentAnimationState = MENU_ENTER;
menuEnterRequested = false;
}
else if(menuScrollRequested)
{
menuScrollRequested = false;
currentTweens_ = tweens_->getAnimation("menuScroll", menuEnterIndex);
currentAnimationState = MENU_SCROLL;
}
else if(scrollActive || newItemSelected || exitRequested)
{
currentTweens_ = tweens_->getAnimation("highlightExit", menuEnterIndex);
currentAnimationState = HIGHLIGHT_EXIT;
}
else
{
currentTweens_ = tweens_->getAnimation("idle", menuEnterIndex);
currentAnimationState = IDLE;
}
break;
case HIGHLIGHT_EXIT:
// intentionally break down
case HIGHLIGHT_WAIT:
if(exitRequested && (currentAnimationState == HIGHLIGHT_WAIT))
{
currentTweens_ = tweens_->getAnimation("highlightExit", menuEnterIndex);
currentAnimationState = HIGHLIGHT_EXIT;
}
else if(exitRequested && (currentAnimationState == HIGHLIGHT_EXIT))
{
currentTweens_ = tweens_->getAnimation("exit", menuEnterIndex);
currentAnimationState = EXIT;
exitRequested = false;
}
else if(scrollActive)
{
currentTweens_ = NULL;
currentAnimationState = HIGHLIGHT_WAIT;
}
else if(newItemSelected)
{
currentTweens_ = tweens_->getAnimation("highlightEnter", menuEnterIndex);
currentAnimationState = HIGHLIGHT_ENTER;
highlightExitComplete = true;
newItemSelected = false;
}
else
{
currentTweens_ = NULL;
currentAnimationState = HIGHLIGHT_WAIT;
}
break;
case HIDDEN:
if(enterRequested || exitRequested)
{
currentTweens_ = tweens_->getAnimation("enter", menuEnterIndex);
currentAnimationState = ENTER;
}
else if(menuExitRequested && (!menuEnterRequested || menuExitRequested <= menuEnterRequested))
{
currentTweens_ = tweens_->getAnimation("menuExit", menuExitIndex);
currentAnimationState = MENU_EXIT;
menuExitRequested = false;
}
else if(menuEnterRequested && (!menuExitRequested || menuExitRequested > menuEnterRequested))
{
currentTweens_ = tweens_->getAnimation("menuEnter", menuEnterIndex);
currentAnimationState = MENU_ENTER;
menuEnterRequested = false;
}
else if(menuScrollRequested)
{
menuScrollRequested = false;
currentTweens_ = tweens_->getAnimation("menuScroll", menuEnterIndex);
currentAnimationState = MENU_SCROLL;
}
else
{
currentTweens_ = NULL;
currentAnimationState = HIDDEN;
}
}
currentTweenIndex_ = 0;
currentTweenComplete_ = false;
elapsedTweenTime_ = 0;
}
currentTweenComplete_ = animate(isIdle());
}
void Component::draw()
{
if(backgroundTexture_)
{
SDL_Rect rect;
rect.h = static_cast<int>(baseViewInfo.ScaledHeight());
rect.w = static_cast<int>(baseViewInfo.ScaledWidth());
rect.x = static_cast<int>(baseViewInfo.XRelativeToOrigin());
rect.y = static_cast<int>(baseViewInfo.YRelativeToOrigin());
SDL_SetTextureColorMod(backgroundTexture_,
static_cast<char>(baseViewInfo.BackgroundRed*255),
static_cast<char>(baseViewInfo.BackgroundGreen*255),
static_cast<char>(baseViewInfo.BackgroundBlue*255));
SDL::renderCopy(backgroundTexture_, static_cast<char>(baseViewInfo.BackgroundAlpha*255), NULL, &rect, baseViewInfo.Angle);
}
}
bool Component::animate(bool loop)
{
bool completeDone = false;
if(!currentTweens_ || currentTweenIndex_ >= currentTweens_->size())
{
completeDone = true;
}
else if(currentTweens_)
{
bool currentDone = true;
TweenSet *tweens = currentTweens_->tweenSet(currentTweenIndex_);
for(unsigned int i = 0; i < tweens->size(); i++)
{
Tween *tween = tweens->tweens()->at(i);
double elapsedTime = elapsedTweenTime_;
//todo: too many levels of nesting
if(elapsedTime < tween->duration)
{
currentDone = false;
}
else
{
elapsedTime = static_cast<float>(tween->duration);
}
float value = tween->animate(elapsedTime);
switch(tween->property)
{
case TWEEN_PROPERTY_X:
baseViewInfo.X = value;
break;
case TWEEN_PROPERTY_Y:
baseViewInfo.Y = value;
break;
case TWEEN_PROPERTY_HEIGHT:
baseViewInfo.Height = value;
break;
case TWEEN_PROPERTY_WIDTH:
baseViewInfo.Width = value;
break;
case TWEEN_PROPERTY_ANGLE:
baseViewInfo.Angle = value;
break;
case TWEEN_PROPERTY_ALPHA:
baseViewInfo.Alpha = value;
break;
case TWEEN_PROPERTY_X_ORIGIN:
baseViewInfo.XOrigin = value;
break;
case TWEEN_PROPERTY_Y_ORIGIN:
baseViewInfo.YOrigin = value;
break;
case TWEEN_PROPERTY_X_OFFSET:
baseViewInfo.XOffset = value;
break;
case TWEEN_PROPERTY_Y_OFFSET:
baseViewInfo.YOffset = value;
break;
case TWEEN_PROPERTY_FONT_SIZE:
baseViewInfo.FontSize = value;
break;
case TWEEN_PROPERTY_BACKGROUND_ALPHA:
baseViewInfo.BackgroundAlpha = value;
break;
}
}
if(currentDone)
{
currentTweenIndex_++;
elapsedTweenTime_ = 0;
}
}
if(!currentTweens_ || currentTweenIndex_ >= currentTweens_->tweenSets()->size())
{
if(loop)
{
currentTweenIndex_ = 0;
}
completeDone = true;
}
return completeDone;
}

View File

@ -19,15 +19,15 @@
#include "../../SDL.h"
#include "../MenuNotifierInterface.h"
#include "../Page.h"
#include "../ViewInfo.h"
#include "../Animate/Tween.h"
#include "../Animate/AnimationEvents.h"
#include "../../Collection/Item.h"
class Component
{
public:
Component();
Component(Page &p);
Component(const Component &copy);
virtual ~Component();
virtual void freeGraphicsMemory();
@ -39,7 +39,8 @@ public:
void triggerMenuEnterEvent(int menuIndex = -1);
void triggerMenuExitEvent(int menuIndex = -1);
void triggerMenuScrollEvent();
void triggerHighlightEvent(Item *selectedItem);
void triggerHighlightEvent();
void triggerPlaylistChangeEvent(std::string name);
bool isIdle();
bool isHidden();
bool isWaiting();
@ -54,7 +55,8 @@ public:
bool scrollActive;
protected:
Item *getSelectedItem();
Page &page;
enum AnimationState
{
IDLE,
@ -78,6 +80,8 @@ protected:
bool menuExitRequested;
int menuExitIndex;
bool newItemSelected;
bool playlistChanged;
std::string playlistName;
bool highlightExitComplete;
bool newItemSelectedSinceEnter;
private:
@ -87,7 +91,6 @@ private:
AnimationEvents *tweens_;
Animation *currentTweens_;
Item *selectedItem_;
SDL_Texture *backgroundTexture_;
unsigned int currentTweenIndex_;

View File

@ -18,7 +18,8 @@
#include "../ViewInfo.h"
#include "../../SDL.h"
Container::Container()
Container::Container(Page &p)
: Component(p)
{
allocateGraphicsMemory();
}

View File

@ -22,7 +22,7 @@
class Container : public Component
{
public:
Container();
Container(Page &p);
virtual ~Container();
void freeGraphicsMemory();
void allocateGraphicsMemory();

View File

@ -19,8 +19,9 @@
#include "../../Utility/Log.h"
#include <SDL2/SDL_image.h>
Image::Image(std::string file, float scaleX, float scaleY)
: texture_(NULL)
Image::Image(std::string file, Page &p, float scaleX, float scaleY)
: Component(p)
, texture_(NULL)
, file_(file)
, scaleX_(scaleX)
, scaleY_(scaleY)

View File

@ -22,7 +22,7 @@
class Image : public Component
{
public:
Image(std::string file, float scaleX, float scaleY);
Image(std::string file, Page &p, float scaleX, float scaleY);
virtual ~Image();
void freeGraphicsMemory();
void allocateGraphicsMemory();

View File

@ -18,7 +18,7 @@
#include "../../Utility/Log.h"
#include <fstream>
Image * ImageBuilder::CreateImage(std::string path, std::string name, float scaleX, float scaleY)
Image * ImageBuilder::CreateImage(std::string path, Page &p, std::string name, float scaleX, float scaleY)
{
Image *image = NULL;
std::vector<std::string> extensions;
@ -35,7 +35,7 @@ Image * ImageBuilder::CreateImage(std::string path, std::string name, float scal
if(Utils::findMatchingFile(prefix, extensions, file))
{
image = new Image(file, scaleX, scaleY);
image = new Image(file, p, scaleX, scaleY);
}
return image;

View File

@ -15,6 +15,7 @@
*/
#pragma once
#include "../Page.h"
#include "Image.h"
#include "VideoComponent.h"
#include "../../Video/VideoFactory.h"
@ -23,5 +24,5 @@
class ImageBuilder
{
public:
Image * CreateImage(std::string path, std::string name, float scaleX, float scaleY);
Image * CreateImage(std::string path, Page &p, std::string name, float scaleX, float scaleY);
};

View File

@ -28,8 +28,9 @@
#include <vector>
#include <iostream>
ReloadableMedia::ReloadableMedia(Configuration &config, bool systemMode, std::string type, bool isVideo, Font *font, float scaleX, float scaleY)
: config_(config)
ReloadableMedia::ReloadableMedia(Configuration &config, bool systemMode, std::string type, Page &p, int displayOffset, bool isVideo, Font *font, float scaleX, float scaleY)
: Component(p)
, config_(config)
, systemMode_(systemMode)
, loadedComponent_(NULL)
, reloadRequested_(false)
@ -41,6 +42,8 @@ ReloadableMedia::ReloadableMedia(Configuration &config, bool systemMode, std::st
, type_(type)
, scaleX_(scaleX)
, scaleY_(scaleY)
, displayOffset_(displayOffset)
{
allocateGraphicsMemory();
}
@ -145,7 +148,7 @@ void ReloadableMedia::reloadTexture()
loadedComponent_ = NULL;
}
Item *selectedItem = getSelectedItem();
Item *selectedItem = page.getSelectedItem(displayOffset_);
if(!selectedItem) return;
config_.getProperty("currentCollection", currentCollection_);
@ -252,7 +255,10 @@ void ReloadableMedia::reloadTexture()
}
else if(typeLC == "manufacturer")
{
if ( selectedItem->leaf ) // item is a leaf
basename = selectedItem->manufacturer;
else // item is a collection
(void)config_.getProperty("collections." + selectedItem->name + ".manufacturer", basename );
}
else if(typeLC == "genre")
{
@ -324,7 +330,7 @@ void ReloadableMedia::reloadTexture()
// if image and artwork was not specified, fall back to displaying text
if(!loadedComponent_ && textFallback_)
{
loadedComponent_ = new Text(selectedItem->fullTitle, FfntInst_, scaleX_, scaleY_);
loadedComponent_ = new Text(selectedItem->fullTitle, page, FfntInst_, scaleX_, scaleY_);
baseViewInfo.ImageWidth = loadedComponent_->baseViewInfo.ImageWidth;
baseViewInfo.ImageHeight = loadedComponent_->baseViewInfo.ImageHeight;
}
@ -343,11 +349,11 @@ Component *ReloadableMedia::findComponent(std::string collection, std::string ty
if(type == "video")
{
component = videoBuild.createVideo(imagePath, basename, scaleX_, scaleY_);
component = videoBuild.createVideo(imagePath, page, basename, scaleX_, scaleY_);
}
else
{
component = imageBuild.CreateImage(imagePath, basename, scaleX_, scaleY_);
component = imageBuild.CreateImage(imagePath, page, basename, scaleX_, scaleY_);
}
return component;

View File

@ -27,7 +27,7 @@ class Image;
class ReloadableMedia : public Component
{
public:
ReloadableMedia(Configuration &config, bool systemMode, std::string type, bool isVideo, Font *font, float scaleX, float scaleY);
ReloadableMedia(Configuration &config, bool systemMode, std::string type, Page &page, int displayOffset, bool isVideo, Font *font, float scaleX, float scaleY);
virtual ~ReloadableMedia();
void update(float dt);
void draw();
@ -54,4 +54,6 @@ private:
float scaleX_;
float scaleY_;
std::string currentCollection_;
Page *page_;
int displayOffset_;
};

View File

@ -23,8 +23,10 @@
#include <vector>
#include <iostream>
ReloadableText::ReloadableText(std::string type, Font *font, std::string layoutKey, float scaleX, float scaleY)
: imageInst_(NULL)
ReloadableText::ReloadableText(std::string type, Page &page, Configuration &config, Font *font, std::string layoutKey, float scaleX, float scaleY)
: Component(page)
, config_(config)
, imageInst_(NULL)
, layoutKey_(layoutKey)
, reloadRequested_(false)
, firstLoad_(true)
@ -59,7 +61,22 @@ ReloadableText::ReloadableText(std::string type, Font *font, std::string layoutK
{
type_ = TextTypeGenre;
}
else if(type == "playlist")
{
type_ = TextTypePlaylist;
}
else if(type == "collectionName")
{
type_ = TextTypeCollectionName;
}
else if(type == "collectionSize")
{
type_ = TextTypeCollectionSize;
}
else if(type == "collectionIndex")
{
type_ = TextTypeCollectionIndex;
}
allocateGraphicsMemory();
}
@ -75,7 +92,8 @@ ReloadableText::~ReloadableText()
void ReloadableText::update(float dt)
{
if(newItemSelected)
if((type_ != TextTypePlaylist && newItemSelected) ||
(type_ == TextTypePlaylist && playlistChanged))
{
reloadRequested_ = true;
}
@ -128,7 +146,7 @@ void ReloadableText::ReloadTexture()
imageInst_ = NULL;
}
Item *selectedItem = getSelectedItem();
Item *selectedItem = page.getSelectedItem();
if (selectedItem != NULL)
{
@ -143,22 +161,47 @@ void ReloadableText::ReloadTexture()
ss << selectedItem->numberPlayers;
break;
case TextTypeYear:
ss << selectedItem->year;
if (selectedItem->leaf) // item is a leaf
text = selectedItem->year;
else // item is a collection
(void)config_.getProperty("collections." + selectedItem->name + ".year", text );
ss << text;
break;
case TextTypeTitle:
ss << selectedItem->title;
break;
case TextTypeManufacturer:
ss << selectedItem->manufacturer;
if (selectedItem->leaf) // item is a leaf
text = selectedItem->manufacturer;
else // item is a collection
(void)config_.getProperty("collections." + selectedItem->name + ".manufacturer", text );
ss << text;
break;
case TextTypeGenre:
ss << selectedItem->genre;
if (selectedItem->leaf) // item is a leaf
text = selectedItem->genre;
else // item is a collection
(void)config_.getProperty("collections." + selectedItem->name + ".genre", text );
ss << text;
break;
case TextTypePlaylist:
ss << playlistName;
break;
case TextTypeCollectionName:
ss << page.getCollectionName();
break;
case TextTypeCollectionSize:
ss << page.getCollectionSize();
break;
case TextTypeCollectionIndex:
ss << (1+page.getSelectedIndex());
break;
default:
break;
}
imageInst_ = new Text(ss.str(), fontInst_, scaleX_, scaleY_);
imageInst_ = new Text(ss.str(), page, fontInst_, scaleX_, scaleY_);
}
}

View File

@ -17,6 +17,7 @@
#include "Component.h"
#include "Text.h"
#include "../Font.h"
#include "../Page.h"
#include "../../Collection/Item.h"
#include <SDL2/SDL.h>
#include <string>
@ -24,7 +25,7 @@
class ReloadableText : public Component
{
public:
ReloadableText(std::string type, Font *font, std::string layoutKey, float scaleX, float scaleY);
ReloadableText(std::string type, Page &page, Configuration &config, Font *font, std::string layoutKey, float scaleX, float scaleY);
virtual ~ReloadableText();
void update(float dt);
void draw();
@ -43,10 +44,15 @@ private:
TextTypeTitle,
TextTypeManufacturer,
TextTypeGenre,
TextTypePlaylist,
TextTypeCollectionName,
TextTypeCollectionSize,
TextTypeCollectionIndex
};
void ReloadTexture();
Configuration &config_;
Text *imageInst_;
TextType type_;
std::string layoutKey_;

File diff suppressed because it is too large Load Diff

View File

@ -1,136 +1,139 @@
/* This file is part of RetroFE.
*
* RetroFE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RetroFE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#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,
std::string layoutKey,
std::string imageType);
ScrollingList(const ScrollingList &copy);
virtual ~ScrollingList();
void triggerMenuEnterEvent();
void triggerMenuExitEvent();
bool allocateTexture(ComponentItemBinding *s);
void deallocateTexture(ComponentItemBinding *s);
void setItems(std::vector<ComponentItemBinding *> *spriteList);
void destroyItems();
void setPoints(std::vector<ViewInfo *> *scrollPoints, std::vector<AnimationEvents *> *tweenPoints);
void setScrollDirection(ScrollDirection direction);
void pageUp();
void pageDown();
void letterUp();
void letterDown();
bool isIdle();
/* This file is part of RetroFE.
*
* RetroFE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RetroFE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vector>
#include "Component.h"
#include "../Animate/Tween.h"
#include "../Page.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,
Page &p,
float scaleX,
float scaleY,
Font *font,
std::string layoutKey,
std::string imageType);
ScrollingList(const ScrollingList &copy);
virtual ~ScrollingList();
void triggerMenuEnterEvent();
void triggerMenuExitEvent();
bool allocateTexture(unsigned int index, Item *i);
void deallocateTexture(unsigned int index);
void setItems(std::vector<Item *> *items);
void destroyItems();
void setPoints(std::vector<ViewInfo *> *scrollPoints, std::vector<AnimationEvents *> *tweenPoints);
void setScrollDirection(ScrollDirection direction);
unsigned int getSelectedIndex();
unsigned int getSize();
void pageUp();
void pageDown();
void letterUp();
void letterDown();
void letterChange(bool increment);
void random();
bool isIdle();
unsigned int getScrollOffsetIndex();
void setScrollOffsetIndex(unsigned int index);
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);
void setScrollAcceleration(float value);
void setStartScrollTime(float value);
bool horizontalScroll;
private:
void click(double nextScrollTime);
void deallocateSpritePoints();
void allocateSpritePoints();
void updateSprite(unsigned int spriteIndex, unsigned int pointIndex, bool newScroll, float dt, double nextScrollTime);
unsigned int getNextTween(unsigned int currentIndex, std::vector<ViewInfo *> *list);
void resetTweens(Component *c, AnimationEvents *sets, ViewInfo *currentViewInfo, ViewInfo *nextViewInfo, double scrollTime);
enum ScrollState
{
ScrollStateActive,
ScrollStatePageChange,
ScrollStateStopping,
ScrollStateIdle
};
std::vector<ComponentItemBinding *> *spriteList_;
std::vector<ViewInfo *> *scrollPoints_;
std::vector<AnimationEvents *> *tweenPoints_;
std::vector<MenuNotifierInterface *> notificationComponents_;
float tweenEnterTime_;
bool focus_;
unsigned int firstSpriteIndex_;
unsigned int selectedSpriteListIndex_;
bool scrollStopRequested_;
bool notifyAllRequested_;
ScrollDirection currentScrollDirection_;
ScrollDirection requestedScrollDirection_;
ScrollState currentScrollState_;
float scrollAcceleration_;
float startScrollTime_;
float scrollPeriod_;
int circularIncrement(unsigned int index, unsigned int offset, std::vector<ComponentItemBinding *> *list);
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_;
std::string layoutKey_;
std::string imageType_;
};
void setSelectedIndex(int selectedIndex);
Item *getItemByOffset(int offset);
void addComponentForNotifications(MenuNotifierInterface *c);
void removeComponentForNotifications(MenuNotifierInterface *c);
void freeGraphicsMemory();
void update(float dt);
void draw();
void draw(unsigned int layer);
void setScrollAcceleration(float value);
void setStartScrollTime(float value);
bool horizontalScroll;
void deallocateSpritePoints();
void allocateSpritePoints();
private:
void click(double nextScrollTime);
void resetTweens(Component *c, AnimationEvents *sets, ViewInfo *currentViewInfo, ViewInfo *nextViewInfo, double scrollTime);
unsigned int loopIncrement(unsigned int offset, unsigned int i, unsigned int size);
unsigned int loopDecrement(unsigned int offset, unsigned int i, unsigned int size);
enum ScrollState
{
ScrollStateActive,
ScrollStatePageChange,
ScrollStateStopping,
ScrollStateIdle
};
std::vector<Component *> *spriteList_;
std::vector<ViewInfo *> *scrollPoints_;
std::vector<AnimationEvents *> *tweenPoints_;
std::vector<MenuNotifierInterface *> notificationComponents_;
bool focus_;
unsigned int itemIndex_;
unsigned int componentIndex_;
unsigned int selectedOffsetIndex_;
bool scrollStopRequested_;
bool notifyAllRequested_;
ScrollDirection currentScrollDirection_;
ScrollDirection requestedScrollDirection_;
ScrollState currentScrollState_;
float scrollAcceleration_;
float startScrollTime_;
float scrollPeriod_;
Configuration &config_;
float scaleX_;
float scaleY_;
Font *fontInst_;
std::string layoutKey_;
std::string imageType_;
std::vector<Item *> *items_;
std::vector<Component *> components_;
};

View File

@ -20,8 +20,9 @@
#include "../Font.h"
#include <sstream>
Text::Text(std::string text, Font *font, float scaleX, float scaleY)
: textData_(text)
Text::Text(std::string text, Page &p, Font *font, float scaleX, float scaleY)
: Component(p)
, textData_(text)
, fontInst_(font)
, scaleX_(scaleX)
, scaleY_(scaleY)

View File

@ -16,7 +16,7 @@
#pragma once
#include "Component.h"
#include "../Page.h"
#include <SDL2/SDL.h>
#include <vector>
@ -26,7 +26,7 @@ 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, float scaleX, float scaleY);
Text(std::string text, Page &p, Font *font, float scaleX, float scaleY);
virtual ~Text();
void setText(std::string text);
void allocateGraphicsMemory();

View File

@ -21,7 +21,7 @@
#include <fstream>
VideoComponent * VideoBuilder::createVideo(std::string path, std::string name, float scaleX, float scaleY)
VideoComponent * VideoBuilder::createVideo(std::string path, Page &page, std::string name, float scaleX, float scaleY)
{
VideoComponent *component = NULL;
std::vector<std::string> extensions;
@ -40,7 +40,7 @@ VideoComponent * VideoBuilder::createVideo(std::string path, std::string name, f
if(video)
{
component = new VideoComponent(video, file, scaleX, scaleY);
component = new VideoComponent(video, page, file, scaleX, scaleY);
}
}

View File

@ -17,13 +17,14 @@
#include "Image.h"
#include "VideoComponent.h"
#include "../Page.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);
VideoComponent * createVideo(std::string path, Page &page, std::string name, float scaleX, float scaleY);
private:
VideoFactory factory_;

View File

@ -20,8 +20,9 @@
#include "../../Utility/Log.h"
#include "../../SDL.h"
VideoComponent::VideoComponent(IVideo *videoInst, std::string videoFile, float scaleX, float scaleY)
: videoFile_(videoFile)
VideoComponent::VideoComponent(IVideo *videoInst, Page &p, std::string videoFile, float scaleX, float scaleY)
: Component(p)
, videoFile_(videoFile)
, videoInst_(videoInst)
, scaleX_(scaleX)
, scaleY_(scaleY)

View File

@ -16,6 +16,7 @@
#pragma once
#include "Component.h"
#include "Image.h"
#include "../Page.h"
#include "../../Collection/Item.h"
#include "../../Video/IVideo.h"
#include <SDL2/SDL.h>
@ -24,7 +25,7 @@
class VideoComponent : public Component
{
public:
VideoComponent(IVideo *videoInst, std::string videoFile, float scaleX, float scaleY);
VideoComponent(IVideo *videoInst, Page &p, std::string videoFile, float scaleX, float scaleY);
virtual ~VideoComponent();
void update(float dt);
void draw();

View File

@ -145,7 +145,7 @@ bool Font::initialize(std::string fontPath, int fontSize, SDL_Color color)
SDL_LockMutex(SDL::getMutex());
texture = SDL_CreateTextureFromSurface(SDL::getRenderer(), atlasSurface);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_ADD);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_FreeSurface(atlasSurface);
SDL_UnlockMutex(SDL::getMutex());

View File

@ -23,17 +23,18 @@
#include "Component/ScrollingList.h"
#include "../Sound/Sound.h"
#include "ComponentItemBindingBuilder.h"
#include <algorithm>
#include <sstream>
Page::Page(Configuration &config)
: config_(config)
, activeMenu_(NULL)
, menuDepth_(0)
, items_(NULL)
, scrollActive_(false)
, selectedItem_(NULL)
, textStatusComponent_(NULL)
, selectedItemChanged_(false)
, playlistChanged_(false)
, loadSoundChunk_(NULL)
, unloadSoundChunk_(NULL)
, highlightSoundChunk_(NULL)
@ -43,6 +44,11 @@ Page::Page(Configuration &config)
}
Page::~Page()
{
}
void Page::DeInitialize()
{
MenuVector_T::iterator it = menus_.begin();
while(it != menus_.end())
@ -89,6 +95,19 @@ Page::~Page()
delete selectSoundChunk_;
selectSoundChunk_ = NULL;
}
CollectionVector_T::iterator itc = collections_.begin();
while(itc != collections_.end())
{
itc->collection->Save();
if(itc->collection)
{
delete itc->collection;
}
collections_.erase(itc);
itc = collections_.begin();
}
}
@ -278,6 +297,12 @@ Item *Page::getSelectedItem()
return selectedItem_;
}
Item *Page::getSelectedItem(int offset)
{
return activeMenu_->getItemByOffset(offset);
}
void Page::removeSelectedItem()
{
/*
@ -315,25 +340,39 @@ float Page::getMinShowTime()
return minShowTime_;
}
void Page::playlistChange()
{
if(activeMenu_)
{
activeMenu_->triggerPlaylistChangeEvent(playlist_->first);
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->triggerPlaylistChangeEvent(playlist_->first);
}
}
}
void Page::highlight()
{
Item *item = selectedItem_;
if(item)
if(!item) return;
if(activeMenu_)
{
if(activeMenu_)
{
activeMenu_->triggerHighlightEvent(item);
activeMenu_->scrollActive = scrollActive_;
}
activeMenu_->triggerHighlightEvent();
activeMenu_->scrollActive = scrollActive_;
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->triggerHighlightEvent(item);
(*it)->scrollActive = scrollActive_;
}
(*it)->triggerHighlightEvent();
(*it)->scrollActive = scrollActive_;
}
}
}
@ -392,6 +431,11 @@ void Page::pageScroll(ScrollDirection direction)
}
}
void Page::selectRandom()
{
if(activeMenu_) activeMenu_->random();
}
void Page::letterScroll(ScrollDirection direction)
{
if(activeMenu_)
@ -407,11 +451,19 @@ void Page::letterScroll(ScrollDirection direction)
}
}
unsigned int Page::getCollectionSize()
{
return activeMenu_->getSize();
}
unsigned int Page::getSelectedIndex()
{
return activeMenu_->getSelectedIndex();
}
bool Page::pushCollection(CollectionInfo *collection)
{
collections_.push_back(collection);
std::vector<ComponentItemBinding *> *sprites = ComponentItemBindingBuilder::buildCollectionItems(&collection->items);
int menuExitIndex = -1;
int menuEnterIndex = -1;
@ -426,19 +478,31 @@ bool Page::pushCollection(CollectionInfo *collection)
menuExitIndex = menuDepth_ - 1;
}
// grow the menu as needed
if(menus_.size() >= menuDepth_ && activeMenu_)
{
ScrollingList *newList = new ScrollingList(*activeMenu_);
newList->forceIdle();
pushMenu(newList);
activeMenu_ = new ScrollingList(*activeMenu_);
activeMenu_->forceIdle();
pushMenu(activeMenu_);
}
activeMenu_ = menus_[menuDepth_];
activeMenu_->collectionName = collection->name;
activeMenu_->destroyItems();
activeMenu_->setItems(sprites);
activeMenu_->setItems(&collection->items);
activeMenu_->triggerMenuEnterEvent();
// build the collection info instance
MenuInfo_S info;
info.collection = collection;
info.menu = activeMenu_;
info.playlist = collection->playlists.begin();
info.queueDelete = false;
collections_.push_back(info);
playlist_ = info.playlist;
playlistChanged_ = true;
if(menuDepth_ < menus_.size())
{
menuEnterIndex = menuDepth_;
@ -469,22 +533,26 @@ bool Page::popCollection()
{
int menuExitIndex = -1;
int menuEnterIndex = -1;
CollectionInfo *collection = NULL;
if(menuDepth_ <= 1)
{
return false;
}
if(collections_.size() <= 1)
{
return false;
}
if(!activeMenu_) return false;
if(menuDepth_ <= 1) return false;
if(collections_.size() <= 1) return false;
// queue the collection for deletion
MenuInfo_S *info = &collections_.back();
info->queueDelete = true;
deleteCollections_.push_back(*info);
// get the next collection off of the stack
collections_.pop_back();
collection = collections_.back();
info = &collections_.back();
playlist_ = info->playlist;
playlistChanged_ = true;
if(activeMenu_)
{
activeMenu_->triggerMenuExitEvent();
}
menuDepth_--;
@ -500,7 +568,7 @@ bool Page::popCollection()
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->collectionName = collection->name;
(*it)->collectionName = info->collection->name;
if(menuEnterIndex >= 0)
{
@ -517,6 +585,54 @@ bool Page::popCollection()
return true;
}
void Page::nextPlaylist()
{
MenuInfo_S &info = collections_.back();
info.collection->Save();
unsigned int numlists = info.collection->playlists.size();
for(unsigned int i = 0; i <= numlists; ++i)
{
playlist_++;
// wrap
if(playlist_ == info.collection->playlists.end()) playlist_ = info.collection->playlists.begin();
// find the first playlist
if(playlist_->second->size() != 0) break;
}
activeMenu_->setItems(playlist_->second);
activeMenu_->triggerMenuEnterEvent();
playlistChanged_ = true;
}
void Page::favPlaylist()
{
MenuInfo_S &info = collections_.back();
info.collection->Save();
unsigned int numlists = info.collection->playlists.size();
// Store current playlist
CollectionInfo::Playlists_T::iterator playlist_store = playlist_;
for(unsigned int i = 0; i <= numlists; ++i)
{
playlist_++;
// wrap
if(playlist_ == info.collection->playlists.end()) playlist_ = info.collection->playlists.begin();
// find the first playlist
if(playlist_->second->size() != 0 && playlist_->first == "favorites") break;
}
// Do not change playlist if favorites does not exist or if it's empty
if ( playlist_->second->size() == 0 || playlist_->first != "favorites")
playlist_ = playlist_store;
activeMenu_->setItems(playlist_->second);
activeMenu_->triggerMenuEnterEvent();
playlistChanged_ = true;
}
void Page::update(float dt)
{
@ -526,6 +642,12 @@ void Page::update(float dt)
menu->update(dt);
}
if(playlistChanged_)
{
playlistChange();
playlistChanged_ = false;
}
if(selectedItemChanged_ && !scrollActive_)
{
@ -544,7 +666,33 @@ void Page::update(float dt)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->update(dt);
if(*it) (*it)->update(dt);
}
}
// many nodes still have handles on the collection info. We need to delete
// them once everything is done using them
std::list<MenuInfo_S>::iterator del = deleteCollections_.begin();
while(del != deleteCollections_.end())
{
MenuInfo_S &info = *del;
if(info.queueDelete && info.menu && info.menu->isIdle())
{
std::list<MenuInfo_S>::iterator next = del;
++next;
if(info.collection)
{
info.collection->Save();
delete info.collection;
}
deleteCollections_.erase(del);
del = next;
}
else
{
++del;
}
}
}
@ -555,7 +703,7 @@ void Page::draw()
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->draw();
if(*it && (*it)->baseViewInfo.Layer == i) (*it)->draw();
}
for(MenuVector_T::iterator it = menus_.begin(); it != menus_.end(); it++)
@ -567,16 +715,58 @@ void Page::draw()
}
void Page::removePlaylist()
{
if(!selectedItem_) return;
if(!selectedItem_->leaf) return;
MenuInfo_S &info = collections_.back();
CollectionInfo *collection = info.collection;
std::vector<Item *> *items = collection->playlists["favorites"];
std::vector<Item *>::iterator it = std::find(items->begin(), items->end(), selectedItem_);
if(it != items->end())
{
items->erase(it);
collection->saveRequest = true;
if(activeMenu_)
{
activeMenu_->deallocateSpritePoints();
activeMenu_->allocateSpritePoints();
}
}
}
void Page::addPlaylist()
{
if(!selectedItem_) return;
if(!selectedItem_->leaf) return;
MenuInfo_S &info = collections_.back();
CollectionInfo *collection = info.collection;
std::vector<Item *> *items = collection->playlists["favorites"];
if(playlist_->first != "favorites" && std::find(items->begin(), items->end(), selectedItem_) == items->end())
{
items->push_back(selectedItem_);
collection->saveRequest = true;
if(activeMenu_)
{
activeMenu_->deallocateSpritePoints();
activeMenu_->allocateSpritePoints();
}
}
}
std::string Page::getCollectionName()
{
CollectionInfo *info = collections_.back();
if(collections_.size() == 0) return "";
if(info)
{
return info->name;
}
MenuInfo_S &info = collections_.back();
return info.collection->name;
return "";
}
void Page::freeGraphicsMemory()

View File

@ -16,13 +16,13 @@
#pragma once
#include "MenuNotifierInterface.h"
#include "../Collection/CollectionInfo.h"
#include <map>
#include <string>
#include <list>
#include <vector>
class CollectionInfo;
class Component;
class Configuration;
class ScrollingList;
@ -43,9 +43,12 @@ public:
Page(Configuration &c);
virtual ~Page();
void DeInitialize();
virtual void onNewItemSelected(Item *);
bool pushCollection(CollectionInfo *collection);
bool popCollection();
void nextPlaylist();
void favPlaylist();
void pushMenu(ScrollingList *s);
bool isMenusFull();
void setLoadSound(Sound *chunk);
@ -55,6 +58,9 @@ public:
bool addComponent(Component *c);
void pageScroll(ScrollDirection direction);
void letterScroll(ScrollDirection direction);
unsigned int getCollectionSize();
unsigned int getSelectedIndex();
void selectRandom();
void start();
void startComponents();
void stop();
@ -62,6 +68,7 @@ public:
bool isHorizontalScroll();
unsigned int getMenuDepth();
Item *getSelectedItem();
Item *getSelectedItem(int offset);
void removeSelectedItem();
void setScrollOffsetIndex(unsigned int i);
unsigned int getScrollOffsetIndex();
@ -78,33 +85,50 @@ public:
std::string getCollectionName();
void setMinShowTime(float value);
float getMinShowTime();
void addPlaylist();
void removePlaylist();
private:
void highlight();
void playlistChange();
std::string collectionName_;
Configuration &config_;
struct MenuInfo_S
{
CollectionInfo *collection;
ScrollingList *menu;
CollectionInfo::Playlists_T::iterator playlist;
bool queueDelete;
};
typedef std::vector<ScrollingList *> MenuVector_T;
typedef std::vector<CollectionInfo *> CollectionInfo_T;
typedef std::list<MenuInfo_S> CollectionVector_T;
ScrollingList *activeMenu_;
unsigned int menuDepth_;
MenuVector_T menus_;
CollectionInfo_T collections_;
CollectionVector_T collections_;
CollectionVector_T deleteCollections_;
static const unsigned int NUM_LAYERS = 8;
static const unsigned int NUM_LAYERS = 20;
std::vector<Component *> LayerComponents[NUM_LAYERS];
std::vector<Item *> *items_;
std::list<ScrollingList *> deleteMenuList_;
std::list<CollectionInfo *> deleteCollectionList_;
bool scrollActive_;
Item *selectedItem_;
Text *textStatusComponent_;
bool selectedItemChanged_;
bool playlistChanged_;
Sound *loadSoundChunk_;
Sound *unloadSoundChunk_;
Sound *highlightSoundChunk_;
Sound *selectSoundChunk_;
float minShowTime_;
float elapsedTime_;
CollectionInfo::Playlists_T::iterator playlist_;
};

View File

@ -320,13 +320,13 @@ bool PageBuilder::buildComponents(xml_node<> *layout, Page *page)
{
for(xml_node<> *componentXml = layout->first_node("menu"); componentXml; componentXml = componentXml->next_sibling("menu"))
{
ScrollingList *scrollingList = buildMenu(componentXml);
ScrollingList *scrollingList = buildMenu(componentXml,*page);
page->pushMenu(scrollingList);
}
for(xml_node<> *componentXml = layout->first_node("container"); componentXml; componentXml = componentXml->next_sibling("container"))
{
Container *c = new Container();
Container *c = new Container(*page);
buildViewInfo(componentXml, c->baseViewInfo);
loadTweens(c, componentXml);
page->addComponent(c);
@ -346,7 +346,7 @@ bool PageBuilder::buildComponents(xml_node<> *layout, Page *page)
std::string imagePath;
imagePath = Utils::combinePath(Configuration::convertToAbsolutePath(layoutPath, imagePath), std::string(src->value()));
Image *c = new Image(imagePath, scaleX_, scaleY_);
Image *c = new Image(imagePath, *page, scaleX_, scaleY_);
buildViewInfo(componentXml, c->baseViewInfo);
loadTweens(c, componentXml);
page->addComponent(c);
@ -365,7 +365,7 @@ bool PageBuilder::buildComponents(xml_node<> *layout, Page *page)
else
{
Font *font = addFont(componentXml, NULL);
Text *c = new Text(value->value(), font, scaleX_, scaleY_);
Text *c = new Text(value->value(), *page, font, scaleX_, scaleY_);
buildViewInfo(componentXml, c->baseViewInfo);
@ -377,7 +377,7 @@ bool PageBuilder::buildComponents(xml_node<> *layout, Page *page)
for(xml_node<> *componentXml = layout->first_node("statusText"); componentXml; componentXml = componentXml->next_sibling("statusText"))
{
Font *font = addFont(componentXml, NULL);
Text *c = new Text("", font, scaleX_, scaleY_);
Text *c = new Text("", *page, font, scaleX_, scaleY_);
buildViewInfo(componentXml, c->baseViewInfo);
@ -403,8 +403,9 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
std::string reloadableVideoPath;
xml_attribute<> *type = componentXml->first_attribute("type");
xml_attribute<> *mode = componentXml->first_attribute("mode");
xml_attribute<> *selectedOffsetXml = componentXml->first_attribute("selectedOffset");
bool systemMode = false;
int selectedOffset = 0;
if(tagName == "reloadableVideo")
{
type = componentXml->first_attribute("imageType");
@ -430,6 +431,13 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
}
}
if(selectedOffsetXml)
{
std::stringstream ss;
ss << selectedOffsetXml->value();
ss >> selectedOffset;
}
Component *c = NULL;
@ -438,13 +446,13 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
if(type)
{
Font *font = addFont(componentXml, NULL);
c = new ReloadableText(type->value(), font, layoutKey, scaleX_, scaleY_);
c = new ReloadableText(type->value(), *page, config_, font, layoutKey, scaleX_, scaleY_);
}
}
else
{
Font *font = addFont(componentXml, NULL);
c = new ReloadableMedia(config_, systemMode, type->value(), (tagName == "reloadableVideo"), font, scaleX_, scaleY_);
c = new ReloadableMedia(config_, systemMode, type->value(), *page, selectedOffset, (tagName == "reloadableVideo"), font, scaleX_, scaleY_);
xml_attribute<> *textFallback = componentXml->first_attribute("textFallback");
if(textFallback && Utils::toLower(textFallback->value()) == "true")
@ -564,7 +572,7 @@ void PageBuilder::buildTweenSet(AnimationEvents *tweens, xml_node<> *componentXm
}
ScrollingList * PageBuilder::buildMenu(xml_node<> *menuXml)
ScrollingList * PageBuilder::buildMenu(xml_node<> *menuXml, Page &page)
{
ScrollingList *menu = NULL;
std::string menuType = "vertical";
@ -596,7 +604,7 @@ ScrollingList * PageBuilder::buildMenu(xml_node<> *menuXml)
// on default, text will be rendered to the menu. Preload it into cache.
Font *font = addFont(itemDefaults, NULL);
menu = new ScrollingList(config_, scaleX_, scaleY_, font, layoutKey, imageType);
menu = new ScrollingList(config_, page, scaleX_, scaleY_, font, layoutKey, imageType);
if(scrollTimeXml)
{

View File

@ -58,7 +58,7 @@ private:
void loadTweens(Component *c, rapidxml::xml_node<> *componentXml);
AnimationEvents *createTweenInstance(rapidxml::xml_node<> *componentXml);
void buildTweenSet(AnimationEvents *tweens, rapidxml::xml_node<> *componentXml, std::string tagName, std::string tweenName);
ScrollingList * buildMenu(rapidxml::xml_node<> *menuXml);
ScrollingList * buildMenu(rapidxml::xml_node<> *menuXml, Page &p);
void buildCustomMenu(ScrollingList *menu, rapidxml::xml_node<> *menuXml, rapidxml::xml_node<> *itemDefaults);
void buildVerticalMenu(ScrollingList *menu, rapidxml::xml_node<> *menuXml, rapidxml::xml_node<> *itemDefaults);
int parseMenuPosition(std::string strIndex);

View File

@ -24,12 +24,16 @@
#include <cstdlib>
#include <fstream>
#include <dirent.h>
#include <time.h>
static bool ImportConfiguration(Configuration *c);
static bool StartLogging();
int main(int argc, char **argv)
{
// Initialize random seed
srand(static_cast<unsigned int>(time(0)));
Configuration::initialize();
Configuration config;

View File

@ -178,6 +178,7 @@ bool RetroFE::deInitialize()
if(currentPage_)
{
currentPage_->DeInitialize();
delete currentPage_;
currentPage_ = NULL;
}
@ -288,6 +289,7 @@ void RetroFE::run()
}
// delete the splash screen and use the standard menu
currentPage_->DeInitialize();
delete currentPage_;
currentPage_ = loadPage();
@ -389,7 +391,6 @@ void RetroFE::run()
render();
}
}
}
@ -447,7 +448,11 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput(Page *page)
if (!input_.keystate(UserInput::KeyCodePageUp) &&
!input_.keystate(UserInput::KeyCodePageDown) &&
!input_.keystate(UserInput::KeyCodeLetterUp) &&
!input_.keystate(UserInput::KeyCodeLetterDown))
!input_.keystate(UserInput::KeyCodeLetterDown) &&
!input_.keystate(UserInput::KeyCodeNextPlaylist) &&
!input_.keystate(UserInput::KeyCodeAddPlaylist) &&
!input_.keystate(UserInput::KeyCodeRemovePlaylist) &&
!input_.keystate(UserInput::KeyCodeRandom))
{
keyLastTime_ = 0;
keyDelayTime_= 0.3f;
@ -475,6 +480,22 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput(Page *page)
{
page->letterScroll(Page::ScrollDirectionForward);
}
if(input_.newKeyPressed(UserInput::KeyCodeNextPlaylist))
{
page->nextPlaylist();
}
if(input_.newKeyPressed(UserInput::KeyCodeRemovePlaylist))
{
page->removePlaylist();
}
if(input_.newKeyPressed(UserInput::KeyCodeAddPlaylist))
{
page->addPlaylist();
}
if(input_.keystate(UserInput::KeyCodeRandom))
{
page->selectRandom();
}
}
if (input_.keystate(UserInput::KeyCodeAdminMode))
@ -508,6 +529,12 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput(Page *page)
page->setScrollOffsetIndex(lastMenuOffsets_[nextPageItem_->name]);
}
bool autoFavorites = true;
config_.getProperty("autoFavorites", autoFavorites);
if (autoFavorites)
page->favPlaylist(); // Switch to favorites if it exists
state = RETROFE_NEXT_PAGE_REQUEST;
}
}

View File

@ -194,11 +194,8 @@ void Utils::replaceSlashesWithUnderscores(std::string &content)
std::string Utils::getDirectory(std::string filePath)
{
#ifdef WIN32
filePath = Utils::replace(filePath, "/", "\\");
#endif
std::string directory = filePath;
const size_t last_slash_idx = filePath.rfind(pathSeparator);
if (std::string::npos != last_slash_idx)
{
@ -210,9 +207,6 @@ std::string Utils::getDirectory(std::string filePath)
std::string Utils::getParentDirectory(std::string directory)
{
#ifdef WIN32
directory = Utils::replace(directory, "/", "\\");
#endif
size_t last_slash_idx = directory.find_last_of(pathSeparator);
if(directory.length() - 1 == last_slash_idx)
{
@ -231,9 +225,6 @@ std::string Utils::getParentDirectory(std::string directory)
std::string Utils::getFileName(std::string filePath)
{
#ifdef WIN32
filePath = Utils::replace(filePath, "/", "\\");
#endif
std::string filename = filePath;