Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
180 KB
Referenced Files
None
Subscribers
None
diff --git a/data/locale/messages.pot b/data/locale/messages.pot
index 7627f74..ffd77bd 100644
--- a/data/locale/messages.pot
+++ b/data/locale/messages.pot
@@ -1,1889 +1,2027 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the meandmyshadow package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: meandmyshadow 0.5svn\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-12 23:16+0800\n"
+"POT-Creation-Date: 2018-08-20 00:04+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../src/AchievementList.cpp:43
msgid "Newbie"
msgstr ""
#: ../src/AchievementList.cpp:43
msgid "Complete a level."
msgstr ""
#: ../src/AchievementList.cpp:44
msgid "Experienced player"
msgstr ""
#: ../src/AchievementList.cpp:44
msgid "Complete 50 levels."
msgstr ""
#: ../src/AchievementList.cpp:45
msgid "Good job!"
msgstr ""
#: ../src/AchievementList.cpp:45
msgid "Receive a gold medal."
msgstr ""
#: ../src/AchievementList.cpp:46
msgid "Expert"
msgstr ""
#: ../src/AchievementList.cpp:46
msgid "Earn 50 gold medal."
msgstr ""
#: ../src/AchievementList.cpp:48
msgid "Graduate"
msgstr ""
#: ../src/AchievementList.cpp:48
msgid "Complete the tutorial level pack."
msgstr ""
#: ../src/AchievementList.cpp:49
msgid "Outstanding graduate"
msgstr ""
#: ../src/AchievementList.cpp:49
msgid "Complete the tutorial level pack with gold for all levels."
msgstr ""
#: ../src/AchievementList.cpp:51
msgid "Hooked"
msgstr ""
#: ../src/AchievementList.cpp:51
msgid "Play Me and My Shadow for more than 2 hours."
msgstr ""
#: ../src/AchievementList.cpp:52
msgid "Loyal fan of Me and My Shadow"
msgstr ""
#: ../src/AchievementList.cpp:52
msgid "Play Me and My Shadow for more than 24 hours."
msgstr ""
#: ../src/AchievementList.cpp:54
msgid "Constructor"
msgstr ""
#: ../src/AchievementList.cpp:54
msgid "Use the level editor for more than 2 hours."
msgstr ""
#: ../src/AchievementList.cpp:55
msgid "The creator"
msgstr ""
#: ../src/AchievementList.cpp:55
msgid "Use the level editor for more than 24 hours."
msgstr ""
#: ../src/AchievementList.cpp:57
msgid "Look, cute level!"
msgstr ""
#: ../src/AchievementList.cpp:57
msgid "Create a level for the first time."
msgstr ""
#: ../src/AchievementList.cpp:58
msgid "The level museum"
msgstr ""
#: ../src/AchievementList.cpp:58
msgid "Create 50 levels."
msgstr ""
#: ../src/AchievementList.cpp:60
msgid "Hello, World!"
msgstr ""
#: ../src/AchievementList.cpp:60
msgid "Write a script for the first time."
msgstr ""
#: ../src/AchievementList.cpp:62
msgid "Frog"
msgstr ""
#: ../src/AchievementList.cpp:62
msgid "Jump 1000 times."
msgstr ""
#: ../src/AchievementList.cpp:64
msgid "Wanderer"
msgstr ""
#: ../src/AchievementList.cpp:64
msgid "Travel 100 meters."
msgstr ""
#: ../src/AchievementList.cpp:65
msgid "Runner"
msgstr ""
#: ../src/AchievementList.cpp:65
msgid "Travel 1 kilometer."
msgstr ""
#: ../src/AchievementList.cpp:66
msgid "Long distance runner"
msgstr ""
#: ../src/AchievementList.cpp:66
msgid "Travel 10 kilometers."
msgstr ""
#: ../src/AchievementList.cpp:67
msgid "Marathon runner"
msgstr ""
#: ../src/AchievementList.cpp:67
msgid "Travel 42,195 meters."
msgstr ""
#: ../src/AchievementList.cpp:69
msgid "Be careful!"
msgstr ""
#: ../src/AchievementList.cpp:69
msgid "Die for the first time."
msgstr ""
#: ../src/AchievementList.cpp:70
msgid "It doesn't matter..."
msgstr ""
#: ../src/AchievementList.cpp:70
msgid "Die 50 times."
msgstr ""
#: ../src/AchievementList.cpp:71
msgid "Expert of trial and error"
msgstr ""
#: ../src/AchievementList.cpp:71
msgid "Die 1000 times."
msgstr ""
#: ../src/AchievementList.cpp:73
msgid "Keep an eye for moving blocks!"
msgstr ""
#: ../src/AchievementList.cpp:73
msgid "Get squashed for the first time."
msgstr ""
#: ../src/AchievementList.cpp:74
msgid "Potato masher"
msgstr ""
#: ../src/AchievementList.cpp:74
msgid "Get squashed 50 times."
msgstr ""
#: ../src/AchievementList.cpp:76
msgid "Double kill"
msgstr ""
#: ../src/AchievementList.cpp:76
msgid "Get both the player and the shadow dead."
msgstr ""
#: ../src/AchievementList.cpp:78
msgid "Bad luck"
msgstr ""
#: ../src/AchievementList.cpp:78
msgid "Die 5 times in under 5 seconds."
msgstr ""
#: ../src/AchievementList.cpp:79
msgid "This level is too dangerous"
msgstr ""
#: ../src/AchievementList.cpp:79
msgid "Die 10 times in under 5 seconds."
msgstr ""
#: ../src/AchievementList.cpp:81
msgid "You forgot your friend"
msgstr ""
#: ../src/AchievementList.cpp:81
msgid "Finish the level with the player or the shadow dead."
msgstr ""
#: ../src/AchievementList.cpp:82
msgid "Just in time"
msgstr ""
#: ../src/AchievementList.cpp:82
msgid "Reach the exit with the player and the shadow simultaneously."
msgstr ""
#: ../src/AchievementList.cpp:84
msgid "Recorder"
msgstr ""
#: ../src/AchievementList.cpp:84
msgid "Record 100 times."
msgstr ""
#: ../src/AchievementList.cpp:85
msgid "Shadowmaster"
msgstr ""
#: ../src/AchievementList.cpp:85
msgid "Record 1000 times."
msgstr ""
#: ../src/AchievementList.cpp:87
msgid "Switch puller"
msgstr ""
#: ../src/AchievementList.cpp:87
msgid "Pull the switch 100 times."
msgstr ""
#: ../src/AchievementList.cpp:88
msgid "The switch is broken!"
msgstr ""
#: ../src/AchievementList.cpp:88
msgid "Pull the switch 1000 times."
msgstr ""
#: ../src/AchievementList.cpp:90
msgid "Swapper"
msgstr ""
#: ../src/AchievementList.cpp:90
msgid "Swap 100 times."
msgstr ""
#: ../src/AchievementList.cpp:91
msgid "Player to shadow to player to shadow..."
msgstr ""
#: ../src/AchievementList.cpp:91
msgid "Swap 1000 times."
msgstr ""
#: ../src/AchievementList.cpp:93
msgid "Play it save"
msgstr ""
#: ../src/AchievementList.cpp:93
msgid "Save 1000 times."
msgstr ""
#: ../src/AchievementList.cpp:94
msgid "This game is too hard"
msgstr ""
#: ../src/AchievementList.cpp:94
msgid "Load the game 1000 times."
msgstr ""
#: ../src/AchievementList.cpp:96
msgid "No, thanks"
msgstr ""
#: ../src/AchievementList.cpp:96
msgid "Complete a level with checkpoint, but without saving."
msgstr ""
#: ../src/AchievementList.cpp:98
msgid "Panic save"
msgstr ""
#: ../src/AchievementList.cpp:98
msgid "Save twice in 1 second."
msgstr ""
#: ../src/AchievementList.cpp:99
msgid "Panic load"
msgstr ""
#: ../src/AchievementList.cpp:99
msgid "Load twice in 1 second."
msgstr ""
#: ../src/AchievementList.cpp:101
msgid "Bad saving position"
msgstr ""
#: ../src/AchievementList.cpp:101
msgid "Load the game and die within 1 second."
msgstr ""
#: ../src/AchievementList.cpp:102
msgid "This level is too hard"
msgstr ""
#: ../src/AchievementList.cpp:102
msgid "Load the same save and die 100 times."
msgstr ""
#: ../src/AchievementList.cpp:104
msgid "Quick swap"
msgstr ""
#: ../src/AchievementList.cpp:104
msgid "Swap twice in under a second."
msgstr ""
#: ../src/AchievementList.cpp:107
msgid "Horizontal confusion"
msgstr ""
#: ../src/AchievementList.cpp:107
msgid "Press left and right simultaneously."
msgstr ""
#: ../src/AchievementList.cpp:109
msgid "Cheater"
msgstr ""
#: ../src/AchievementList.cpp:109
msgid "Cheat in game."
msgstr ""
#: ../src/AchievementList.cpp:111
msgid "Programmer"
msgstr ""
#: ../src/AchievementList.cpp:111
msgid "Play the development version of Me and My Shadow."
msgstr ""
#: ../src/Addons.cpp:44
msgid "Levels"
msgstr ""
#: ../src/Addons.cpp:44
msgid "Single level which usually contain demanding puzzles"
msgstr ""
#: ../src/Addons.cpp:45
msgid "Levelpacks"
msgstr ""
#: ../src/Addons.cpp:45
msgid "Collection of levels with the same author or style"
msgstr ""
#: ../src/Addons.cpp:46
msgid "Themes"
msgstr ""
#: ../src/Addons.cpp:46
msgid "Give every block and background a new look and feel"
msgstr ""
#: ../src/Addons.cpp:55 ../src/TitleMenu.cpp:46
msgid "Addons"
msgstr ""
#: ../src/Addons.cpp:87
msgid "Unable to initialize addon menu:"
msgstr ""
#: ../src/Addons.cpp:95 ../src/Addons.cpp:158 ../src/Addons.cpp:662
#: ../src/Addons.cpp:690 ../src/CreditsMenu.cpp:89 ../src/LevelSelect.cpp:168
-#: ../src/StatisticsScreen.cpp:160
+#: ../src/StatisticsScreen.cpp:159
msgid "Back"
msgstr ""
#: ../src/Addons.cpp:169
msgid "ERROR: unable to download addons file!"
msgstr ""
# TRANSLATORS: addon_list is the name of a file and should not be translated.
#: ../src/Addons.cpp:182
msgid "ERROR: unable to load addon_list file!"
msgstr ""
#: ../src/Addons.cpp:193
msgid "ERROR: Invalid file format of addons file!"
msgstr ""
#: ../src/Addons.cpp:205
msgid "ERROR: Addon list version is unsupported!"
msgstr ""
# TRANSLATORS: installed_addons is the name of a file and should not be translated.
#: ../src/Addons.cpp:226
msgid "ERROR: Unable to create the installed_addons file."
msgstr ""
#: ../src/Addons.cpp:238
msgid "ERROR: Invalid file format of the installed_addons!"
msgstr ""
# TRANSLATORS: indicates the author of an addon.
#: ../src/Addons.cpp:389 ../src/Addons.cpp:621
#, c-format
msgid "by %s"
msgstr ""
#: ../src/Addons.cpp:397
msgid "Installed"
msgstr ""
#: ../src/Addons.cpp:402
msgid "Updatable"
msgstr ""
#: ../src/Addons.cpp:412
msgid "Not installed"
msgstr ""
#: ../src/Addons.cpp:625
#, c-format
msgid "Version: %d\n"
msgstr ""
#: ../src/Addons.cpp:627
#, c-format
msgid "Installed version: %d\n"
msgstr ""
#: ../src/Addons.cpp:630
#, c-format
msgid "License: %s\n"
msgstr ""
#: ../src/Addons.cpp:633
#, c-format
msgid "Website: %s\n"
msgstr ""
#: ../src/Addons.cpp:637
msgid "(No descriptions provided)"
msgstr ""
#: ../src/Addons.cpp:657 ../src/Addons.cpp:684
msgid "Remove"
msgstr ""
#: ../src/Addons.cpp:673
msgid "Update"
msgstr ""
#: ../src/Addons.cpp:679
msgid "Install"
msgstr ""
+#: ../src/Addons.cpp:774
+#, c-format
+msgid "This addon can't be removed because it's needed by %s."
+msgstr ""
+
+#: ../src/Addons.cpp:774 ../src/Addons.cpp:1051
+msgid "Dependency"
+msgstr ""
+
+#: ../src/Addons.cpp:803
+#, c-format
+msgid "WARNING: File '%s' appears to have been removed already."
+msgstr ""
+
+#: ../src/Addons.cpp:803 ../src/Addons.cpp:810 ../src/Addons.cpp:818
+#: ../src/Addons.cpp:825 ../src/Addons.cpp:834 ../src/Addons.cpp:840
+#: ../src/Addons.cpp:859 ../src/Addons.cpp:866 ../src/Addons.cpp:893
+#: ../src/Addons.cpp:900 ../src/Addons.cpp:907 ../src/Addons.cpp:918
+#: ../src/Addons.cpp:947 ../src/Addons.cpp:952 ../src/Addons.cpp:962
+#: ../src/Addons.cpp:968 ../src/Addons.cpp:981 ../src/Addons.cpp:986
+#: ../src/Addons.cpp:1008 ../src/Addons.cpp:1014 ../src/Addons.cpp:1044
+msgid "Addon error"
+msgstr ""
+
+#: ../src/Addons.cpp:810
+#, c-format
+msgid "ERROR: Unable to remove file '%s'!"
+msgstr ""
+
+#: ../src/Addons.cpp:818
+#, c-format
+msgid "WARNING: Directory '%s' appears to have been removed already."
+msgstr ""
+
+#: ../src/Addons.cpp:825
+#, c-format
+msgid "ERROR: Unable to remove directory '%s'!"
+msgstr ""
+
+#: ../src/Addons.cpp:834
+#, c-format
+msgid "WARNING: Level '%s' appears to have been removed already."
+msgstr ""
+
+#: ../src/Addons.cpp:840
+#, c-format
+msgid "ERROR: Unable to remove level '%s'!"
+msgstr ""
+
+#: ../src/Addons.cpp:859
+#, c-format
+msgid "WARNING: Levelpack directory '%s' appears to have been removed already."
+msgstr ""
+
+#: ../src/Addons.cpp:866
+#, c-format
+msgid "ERROR: Unable to remove levelpack directory '%s'!"
+msgstr ""
+
+#: ../src/Addons.cpp:893
+#, c-format
+msgid "ERROR: Unable to download addon file %s."
+msgstr ""
+
+#: ../src/Addons.cpp:900
+#, c-format
+msgid "ERROR: Unable to extract addon file %s."
+msgstr ""
+
+#: ../src/Addons.cpp:907
+msgid "ERROR: Addon is missing metadata!"
+msgstr ""
+
+#: ../src/Addons.cpp:918
+msgid "ERROR: Invalid file format for metadata file!"
+msgstr ""
+
+#: ../src/Addons.cpp:947
+#, c-format
+msgid "WARNING: File '%s' already exists, addon may be broken or not working!"
+msgstr ""
+
+#: ../src/Addons.cpp:952
+#, c-format
+msgid ""
+"WARNING: Unable to copy file '%s' to '%s', addon may be broken or not "
+"working!"
+msgstr ""
+
+#: ../src/Addons.cpp:962
+#, c-format
+msgid ""
+"WARNING: Destination directory '%s' already exists, addon may be broken or "
+"not working!"
+msgstr ""
+
+#: ../src/Addons.cpp:968 ../src/Addons.cpp:1014
+#, c-format
+msgid ""
+"WARNING: Unable to move directory '%s' to '%s', addon may be broken or not "
+"working!"
+msgstr ""
+
+#: ../src/Addons.cpp:981
+#, c-format
+msgid "WARNING: Level '%s' already exists, addon may be broken or not working!"
+msgstr ""
+
+#: ../src/Addons.cpp:986
+#, c-format
+msgid ""
+"WARNING: Unable to copy level '%s' to '%s', addon may be broken or not "
+"working!"
+msgstr ""
+
+#: ../src/Addons.cpp:1008
+#, c-format
+msgid ""
+"WARNING: Levelpack directory '%s' already exists, addon may be broken or not "
+"working!"
+msgstr ""
+
+#: ../src/Addons.cpp:1044
+#, c-format
+msgid "ERROR: Addon requires another addon (%s) which can't be found!"
+msgstr ""
+
+#: ../src/Addons.cpp:1051
+#, c-format
+msgid "The addon %s is needed and will be installed now."
+msgstr ""
+
#: ../src/Block.cpp:822 ../src/LevelEditor.cpp:265
msgid "On"
msgstr ""
#: ../src/Block.cpp:823 ../src/LevelEditor.cpp:266
msgid "Off"
msgstr ""
#: ../src/CommandManager.cpp:41
#, c-format
msgid "Undo %s"
msgstr ""
#: ../src/CommandManager.cpp:43
msgid "Can't undo"
msgstr ""
#: ../src/CommandManager.cpp:49
#, c-format
msgid "Redo %s"
msgstr ""
#: ../src/CommandManager.cpp:51
msgid "Can't redo"
msgstr ""
#: ../src/Commands.cpp:189
msgid "Resize level"
msgstr ""
-#: ../src/Commands.cpp:783
+#: ../src/Commands.cpp:805
msgid "Modify level property"
msgstr ""
-#: ../src/Commands.cpp:893
+#: ../src/Commands.cpp:915
#, c-format
msgid "Add scenery layer %s"
msgstr ""
-#: ../src/Commands.cpp:893
+#: ../src/Commands.cpp:915
#, c-format
msgid "Delete scenery layer %s"
msgstr ""
-#: ../src/Commands.cpp:922
+#: ../src/Commands.cpp:944
#, c-format
msgid "Modify the property of scenery layer %s"
msgstr ""
-#: ../src/Commands.cpp:1009
+#: ../src/Commands.cpp:1031
#, c-format
msgid "Move %d object(s) from layer %s to layer %s"
msgstr ""
#: ../src/CreditsMenu.cpp:35 ../src/TitleMenu.cpp:53
msgid "Credits"
msgstr ""
# TRANSLATORS: Font used in GUI:
# - Use "knewave" for languages using Latin and Latin-derived alphabets
# - "DroidSansFallback" can be used for non-Latin writing systems
#: ../src/Functions.cpp:560 ../src/Functions.cpp:561 ../src/Functions.cpp:562
#: ../src/Functions.cpp:579
msgid "knewave"
msgstr ""
# TRANSLATORS: Font used for normal text:
# - Use "Blokletters-Viltstift" for languages using Latin and Latin-derived alphabets
# - "DroidSansFallback" can be used for non-Latin writing systems
#: ../src/Functions.cpp:566
msgid "Blokletters-Viltstift"
msgstr ""
#: ../src/Functions.cpp:665
msgid "Loading..."
msgstr ""
-#: ../src/Functions.cpp:1225 ../src/Functions.cpp:1252
+#: ../src/Functions.cpp:1235 ../src/Functions.cpp:1262
#: ../src/LevelEditor.cpp:559 ../src/LevelEditor.cpp:693
#: ../src/LevelEditor.cpp:758 ../src/LevelEditor.cpp:821
#: ../src/LevelEditor.cpp:908 ../src/LevelEditor.cpp:1033
#: ../src/LevelEditor.cpp:1083 ../src/LevelEditor.cpp:1180
-#: ../src/LevelEditor.cpp:1244 ../src/LevelEditor.cpp:2918
-#: ../src/LevelEditSelect.cpp:242 ../src/LevelEditSelect.cpp:274
-#: ../src/LevelEditSelect.cpp:310
+#: ../src/LevelEditor.cpp:1244 ../src/LevelEditor.cpp:2899
+#: ../src/LevelEditSelect.cpp:243 ../src/LevelEditSelect.cpp:275
+#: ../src/LevelEditSelect.cpp:315
msgid "OK"
msgstr ""
-#: ../src/Functions.cpp:1226 ../src/Functions.cpp:1238
-#: ../src/Functions.cpp:1248 ../src/LevelEditor.cpp:565
+#: ../src/Functions.cpp:1236 ../src/Functions.cpp:1248
+#: ../src/Functions.cpp:1258 ../src/LevelEditor.cpp:565
#: ../src/LevelEditor.cpp:699 ../src/LevelEditor.cpp:764
#: ../src/LevelEditor.cpp:827 ../src/LevelEditor.cpp:914
#: ../src/LevelEditor.cpp:1039 ../src/LevelEditor.cpp:1089
#: ../src/LevelEditor.cpp:1186 ../src/LevelEditor.cpp:1250
-#: ../src/LevelEditor.cpp:2924 ../src/LevelEditSelect.cpp:246
-#: ../src/LevelEditSelect.cpp:278 ../src/LevelEditSelect.cpp:314
+#: ../src/LevelEditor.cpp:2905 ../src/LevelEditSelect.cpp:247
+#: ../src/LevelEditSelect.cpp:279 ../src/LevelEditSelect.cpp:319
#: ../src/OptionsMenu.cpp:289
msgid "Cancel"
msgstr ""
-#: ../src/Functions.cpp:1230
+#: ../src/Functions.cpp:1240
msgid "Abort"
msgstr ""
-#: ../src/Functions.cpp:1231 ../src/Functions.cpp:1247
+#: ../src/Functions.cpp:1241 ../src/Functions.cpp:1257
msgid "Retry"
msgstr ""
-#: ../src/Functions.cpp:1232
+#: ../src/Functions.cpp:1242
msgid "Ignore"
msgstr ""
-#: ../src/Functions.cpp:1236 ../src/Functions.cpp:1242
+#: ../src/Functions.cpp:1246 ../src/Functions.cpp:1252
msgid "Yes"
msgstr ""
-#: ../src/Functions.cpp:1237 ../src/Functions.cpp:1243
+#: ../src/Functions.cpp:1247 ../src/Functions.cpp:1253
msgid "No"
msgstr ""
# TRANSLATORS: Please do not remove %s or %d from your translation:
# - %d means the level number in a levelpack
# - %s means the name of current level
-#: ../src/Game.cpp:281 ../src/Game.cpp:1193
+#: ../src/Game.cpp:281 ../src/Game.cpp:1213
#, c-format
msgid "Level %d %s"
msgstr ""
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
-#: ../src/Game.cpp:872
+#: ../src/Game.cpp:892
#, c-format
msgid "Press %s key to save the game."
msgstr ""
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
-#: ../src/Game.cpp:877
+#: ../src/Game.cpp:897
#, c-format
msgid "Press %s key to swap the position of player and shadow."
msgstr ""
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
-#: ../src/Game.cpp:882
+#: ../src/Game.cpp:902
#, c-format
msgid "Press %s key to activate the switch."
msgstr ""
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
-#: ../src/Game.cpp:887
+#: ../src/Game.cpp:907
#, c-format
msgid "Press %s key to teleport."
msgstr ""
# TRANSLATORS: Please do not remove %s from your translation:
# - first %s means currently configured key to restart game
# - Second %s means configured key to load from last save
-#: ../src/Game.cpp:929
+#: ../src/Game.cpp:949
#, c-format
msgid "Press %s to restart current level or press %s to load the game."
msgstr ""
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with currently configured key to restart game
-#: ../src/Game.cpp:940
+#: ../src/Game.cpp:960
#, c-format
msgid "Press %s to restart current level."
msgstr ""
-#: ../src/Game.cpp:953
+#: ../src/Game.cpp:973
msgid "Your shadow has died."
msgstr ""
-#: ../src/Game.cpp:1009
+#: ../src/Game.cpp:1029
#, c-format
msgid "%d recordings"
msgstr ""
-#: ../src/Game.cpp:1181
+#: ../src/Game.cpp:1201
msgid "You've finished:"
msgstr ""
# TRANSLATORS: Please do not remove %-.2f from your translation:
# - %-.2f means time in seconds
# - s is shortened form of a second. Try to keep it so.
-#: ../src/Game.cpp:1248
+#: ../src/Game.cpp:1268
#, c-format
msgid "Time: %-.2fs"
msgstr ""
# TRANSLATORS: Please do not remove %-.2f from your translation:
# - %-.2f means time in seconds
# - s is shortened form of a second. Try to keep it so.
-#: ../src/Game.cpp:1257
+#: ../src/Game.cpp:1277
#, c-format
msgid "Best time: %-.2fs"
msgstr ""
-#: ../src/Game.cpp:1268
+#: ../src/Game.cpp:1288
#, c-format
msgid "Target time: %-.2fs"
msgstr ""
# TRANSLATORS: Please do not remove %d from your translation:
# - %d means the number of recordings user has made
-#: ../src/Game.cpp:1289
+#: ../src/Game.cpp:1309
#, c-format
msgid "Recordings: %d"
msgstr ""
# TRANSLATORS: Please do not remove %d from your translation:
# - %d means the number of recordings user has made
-#: ../src/Game.cpp:1297
+#: ../src/Game.cpp:1317
#, c-format
msgid "Best recordings: %d"
msgstr ""
-#: ../src/Game.cpp:1307
+#: ../src/Game.cpp:1327
#, c-format
msgid "Target recordings: %d"
msgstr ""
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with name of a prize medal (gold, silver or bronze)
-#: ../src/Game.cpp:1320
+#: ../src/Game.cpp:1340
#, c-format
msgid "You earned the %s medal"
msgstr ""
-#: ../src/Game.cpp:1320
+#: ../src/Game.cpp:1340
msgid "GOLD"
msgstr ""
-#: ../src/Game.cpp:1320
+#: ../src/Game.cpp:1340
msgid "SILVER"
msgstr ""
-#: ../src/Game.cpp:1320
+#: ../src/Game.cpp:1340
msgid "BRONZE"
msgstr ""
# TRANSLATORS: used as return to the level selector menu
-#: ../src/Game.cpp:1347
+#: ../src/Game.cpp:1367
msgid "Menu"
msgstr ""
# TRANSLATORS: used as restart level
-#: ../src/Game.cpp:1354 ../src/InputManager.cpp:47
+#: ../src/Game.cpp:1374 ../src/InputManager.cpp:47
msgid "Restart"
msgstr ""
# TRANSLATORS: used as next level
-#: ../src/Game.cpp:1361
+#: ../src/Game.cpp:1381
msgid "Next"
msgstr ""
-#: ../src/Game.cpp:1387
+#: ../src/Game.cpp:1407
msgid "Game replay is done."
msgstr ""
-#: ../src/Game.cpp:1387
+#: ../src/Game.cpp:1407
msgid "Game Replay"
msgstr ""
-#: ../src/Game.cpp:1724 ../src/Game.cpp:1726
+#: ../src/Game.cpp:1744 ../src/Game.cpp:1746
msgid "Congratulations"
msgstr ""
-#: ../src/Game.cpp:1726
+#: ../src/Game.cpp:1746
msgid "You have finished the levelpack!"
msgstr ""
#: ../src/InputManager.cpp:46
msgid "Up (in menu)"
msgstr ""
#: ../src/InputManager.cpp:46
msgid "Down (in menu)"
msgstr ""
#: ../src/InputManager.cpp:46
msgid "Left"
msgstr ""
#: ../src/InputManager.cpp:46
msgid "Right"
msgstr ""
#: ../src/InputManager.cpp:46
msgid "Jump"
msgstr ""
#: ../src/InputManager.cpp:46
msgid "Action"
msgstr ""
#: ../src/InputManager.cpp:46
msgid "Space (Record)"
msgstr ""
#: ../src/InputManager.cpp:46
msgid "Cancel recording"
msgstr ""
#: ../src/InputManager.cpp:47
msgid "Escape"
msgstr ""
#: ../src/InputManager.cpp:47
msgid "Tab (View shadow/Level prop.)"
msgstr ""
#: ../src/InputManager.cpp:47
msgid "Save game (in editor)"
msgstr ""
#: ../src/InputManager.cpp:47
msgid "Load game"
msgstr ""
#: ../src/InputManager.cpp:47
msgid "Swap (in editor)"
msgstr ""
#: ../src/InputManager.cpp:48
msgid "Teleport (in editor)"
msgstr ""
#: ../src/InputManager.cpp:48
msgid "Suicide (in editor)"
msgstr ""
#: ../src/InputManager.cpp:48
msgid "Shift (in editor)"
msgstr ""
#: ../src/InputManager.cpp:48
msgid "Next block type (in Editor)"
msgstr ""
#: ../src/InputManager.cpp:49
msgid "Previous block type (in editor)"
msgstr ""
#: ../src/InputManager.cpp:49
msgid "Select (in menu)"
msgstr ""
# TRANSLAOTRS: This is used when the name of the key code is not found.
#: ../src/InputManager.cpp:156
#, c-format
msgid "(Key %d)"
msgstr ""
#: ../src/InputManager.cpp:163
#, c-format
msgid "Joystick axis %d %s"
msgstr ""
#: ../src/InputManager.cpp:166
#, c-format
msgid "Joystick button %d"
msgstr ""
#: ../src/InputManager.cpp:171
#, c-format
msgid "Joystick hat %d left"
msgstr ""
#: ../src/InputManager.cpp:174
#, c-format
msgid "Joystick hat %d right"
msgstr ""
#: ../src/InputManager.cpp:177
#, c-format
msgid "Joystick hat %d up"
msgstr ""
#: ../src/InputManager.cpp:180
#, c-format
msgid "Joystick hat %d down"
msgstr ""
# TRANSLAOTRS: This is used when the JOYSTICK_HAT value is invalid.
#: ../src/InputManager.cpp:185
#, c-format
msgid "Joystick hat %d %d"
msgstr ""
#: ../src/InputManager.cpp:202
msgid "OR"
msgstr ""
#: ../src/InputManager.cpp:416
msgid "Select an item and press a key to change it."
msgstr ""
#: ../src/InputManager.cpp:419
msgid "Press backspace to clear the selected item."
msgstr ""
#: ../src/LevelEditor.cpp:56
msgid "Block"
msgstr ""
#: ../src/LevelEditor.cpp:56
msgid "Player Start"
msgstr ""
#: ../src/LevelEditor.cpp:56
msgid "Shadow Start"
msgstr ""
#: ../src/LevelEditor.cpp:57
msgid "Exit"
msgstr ""
#: ../src/LevelEditor.cpp:57
msgid "Shadow Block"
msgstr ""
#: ../src/LevelEditor.cpp:57
msgid "Spikes"
msgstr ""
#: ../src/LevelEditor.cpp:58
msgid "Checkpoint"
msgstr ""
-#: ../src/LevelEditor.cpp:58 ../src/LevelEditSelect.cpp:305
+#: ../src/LevelEditor.cpp:58 ../src/LevelEditSelect.cpp:310
msgid "Swap"
msgstr ""
#: ../src/LevelEditor.cpp:58
msgid "Fragile"
msgstr ""
#: ../src/LevelEditor.cpp:59
msgid "Moving Block"
msgstr ""
#: ../src/LevelEditor.cpp:59
msgid "Moving Shadow Block"
msgstr ""
#: ../src/LevelEditor.cpp:59
msgid "Moving Spikes"
msgstr ""
#: ../src/LevelEditor.cpp:60
msgid "Teleporter"
msgstr ""
#: ../src/LevelEditor.cpp:60
msgid "Button"
msgstr ""
#: ../src/LevelEditor.cpp:60
msgid "Switch"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Conveyor Belt"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Shadow Conveyor Belt"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Notification Block"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Collectable"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Pushable"
msgstr ""
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:310
msgid "Select"
msgstr ""
#: ../src/LevelEditor.cpp:65
msgid "Add"
msgstr ""
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:311
msgid "Delete"
msgstr ""
#: ../src/LevelEditor.cpp:65 ../src/LevelPlaySelect.cpp:66
#: ../src/TitleMenu.cpp:43
msgid "Play"
msgstr ""
-#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:2847
+#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:2828
msgid "Level settings"
msgstr ""
#: ../src/LevelEditor.cpp:65
msgid "Save level"
msgstr ""
#: ../src/LevelEditor.cpp:65
msgid "Back to menu"
msgstr ""
#: ../src/LevelEditor.cpp:65
msgid "Configure"
msgstr ""
#: ../src/LevelEditor.cpp:84
#, c-format
msgid "%s (Scenery)"
msgstr ""
#: ../src/LevelEditor.cpp:267
msgid "Toggle"
msgstr ""
#: ../src/LevelEditor.cpp:270
msgid "Complete"
msgstr ""
#: ../src/LevelEditor.cpp:271
msgid "One step"
msgstr ""
#: ../src/LevelEditor.cpp:272
msgid "Two steps"
msgstr ""
#: ../src/LevelEditor.cpp:273
msgid "Gone"
msgstr ""
#: ../src/LevelEditor.cpp:291
msgid "Negative infinity"
msgstr ""
#: ../src/LevelEditor.cpp:293
msgid "Zero"
msgstr ""
#: ../src/LevelEditor.cpp:295
msgid "Level size"
msgstr ""
#: ../src/LevelEditor.cpp:297
msgid "Positive infinity"
msgstr ""
#: ../src/LevelEditor.cpp:299
msgid "Default"
msgstr ""
#: ../src/LevelEditor.cpp:308
msgid "Deselect"
msgstr ""
#: ../src/LevelEditor.cpp:318 ../src/LevelEditor.cpp:1136
#, c-format
msgid "Horizontal repeat start: %s"
msgstr ""
#: ../src/LevelEditor.cpp:320 ../src/LevelEditor.cpp:1137
#, c-format
msgid "Horizontal repeat end: %s"
msgstr ""
#: ../src/LevelEditor.cpp:322 ../src/LevelEditor.cpp:1138
#, c-format
msgid "Vertical repeat start: %s"
msgstr ""
#: ../src/LevelEditor.cpp:324 ../src/LevelEditor.cpp:1139
#, c-format
msgid "Vertical repeat end: %s"
msgstr ""
#: ../src/LevelEditor.cpp:329 ../src/LevelEditor.cpp:1150
msgid "Custom scenery"
msgstr ""
#: ../src/LevelEditor.cpp:335 ../src/LevelEditor.cpp:600
#: ../src/LevelEditor.cpp:602
msgid "Visible"
msgstr ""
#: ../src/LevelEditor.cpp:344
msgid "Link"
msgstr ""
#: ../src/LevelEditor.cpp:345
msgid "Remove Links"
msgstr ""
#: ../src/LevelEditor.cpp:349 ../src/LevelEditor.cpp:624
#: ../src/LevelEditor.cpp:626
msgid "Automatic"
msgstr ""
#: ../src/LevelEditor.cpp:359 ../src/LevelEditor.cpp:649
#, c-format
msgid "Behavior: %s"
msgstr ""
#: ../src/LevelEditor.cpp:362
msgid "Path"
msgstr ""
#: ../src/LevelEditor.cpp:363
msgid "Remove Path"
msgstr ""
#: ../src/LevelEditor.cpp:365 ../src/LevelEditor.cpp:371
#: ../src/LevelEditor.cpp:587 ../src/LevelEditor.cpp:589
msgid "Activated"
msgstr ""
#: ../src/LevelEditor.cpp:366 ../src/LevelEditor.cpp:612
#: ../src/LevelEditor.cpp:614
msgid "Looping"
msgstr ""
-#: ../src/LevelEditor.cpp:372 ../src/LevelEditor.cpp:3507
+#: ../src/LevelEditor.cpp:372 ../src/LevelEditor.cpp:3502
msgid "Speed"
msgstr ""
#: ../src/LevelEditor.cpp:378 ../src/LevelEditor.cpp:668
#, c-format
msgid "State: %s"
msgstr ""
-#: ../src/LevelEditor.cpp:382 ../src/LevelEditor.cpp:3492
+#: ../src/LevelEditor.cpp:382 ../src/LevelEditor.cpp:3487
msgid "Message"
msgstr ""
#: ../src/LevelEditor.cpp:384 ../src/LevelEditor.cpp:1202
-#: ../src/LevelEditor.cpp:3806
+#: ../src/LevelEditor.cpp:3801
msgid "Appearance"
msgstr ""
#: ../src/LevelEditor.cpp:389 ../src/LevelEditor.cpp:431
#: ../src/LevelEditor.cpp:715
msgid "Scripting"
msgstr ""
#: ../src/LevelEditor.cpp:402 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Background layer: %s"
msgstr ""
#: ../src/LevelEditor.cpp:409 ../src/LevelEditor.cpp:866
#: ../src/LevelEditor.cpp:884
msgid "Blocks layer"
msgstr ""
#: ../src/LevelEditor.cpp:417 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Foreground layer: %s"
msgstr ""
#: ../src/LevelEditor.cpp:423
msgid "Add new layer"
msgstr ""
#: ../src/LevelEditor.cpp:424
msgid "Delete selected layer"
msgstr ""
#: ../src/LevelEditor.cpp:425
msgid "Configure selected layer"
msgstr ""
#: ../src/LevelEditor.cpp:426
msgid "Move selected object to layer"
msgstr ""
#: ../src/LevelEditor.cpp:430 ../src/OptionsMenu.cpp:55
msgid "Settings"
msgstr ""
#: ../src/LevelEditor.cpp:463
msgid ""
"NOTE: the layers are sorted by name alphabetically.\n"
"The layer is background layer if its name is < 'f'\n"
"by dictionary order, otherwise it's foreground layer."
msgstr ""
#: ../src/LevelEditor.cpp:539
msgid "Notification block"
msgstr ""
#: ../src/LevelEditor.cpp:545
msgid "Enter message here:"
msgstr ""
#: ../src/LevelEditor.cpp:646
msgid "Behavior"
msgstr ""
#: ../src/LevelEditor.cpp:665
msgid "State"
msgstr ""
#: ../src/LevelEditor.cpp:673
msgid "Conveyor belt speed"
msgstr ""
#: ../src/LevelEditor.cpp:679
msgid "Enter speed here:"
msgstr ""
#: ../src/LevelEditor.cpp:690
msgid "NOTE: 1 Speed = 0.08 block/s"
msgstr ""
#: ../src/LevelEditor.cpp:721
msgid "Id:"
msgstr ""
#: ../src/LevelEditor.cpp:787
msgid "Level Scripting"
msgstr ""
#: ../src/LevelEditor.cpp:892
msgid "Add layer"
msgstr ""
#: ../src/LevelEditor.cpp:898
msgid "Enter the layer name:"
msgstr ""
#: ../src/LevelEditor.cpp:943
#, c-format
msgid "Are you sure you want to delete layer '%s'?"
msgstr ""
#: ../src/LevelEditor.cpp:944
msgid "Delete layer"
msgstr ""
#: ../src/LevelEditor.cpp:968
msgid "Layer settings"
msgstr ""
#: ../src/LevelEditor.cpp:974
msgid "Layer name:"
msgstr ""
#: ../src/LevelEditor.cpp:989
msgid "Layer moving speed (1 speed = 0.8 block/s):"
msgstr ""
#: ../src/LevelEditor.cpp:1010
msgid "Speed of following camera:"
msgstr ""
#: ../src/LevelEditor.cpp:1062
msgid "Move to layer"
msgstr ""
#: ../src/LevelEditor.cpp:1068
msgid "Enter the layer name (create new layer if necessary):"
msgstr ""
#: ../src/LevelEditor.cpp:1132
msgid "Repeat mode"
msgstr ""
#: ../src/LevelEditor.cpp:1156
msgid "Custom scenery:"
msgstr ""
#: ../src/LevelEditor.cpp:1219
msgid "(Use the default appearance for this block)"
msgstr ""
#: ../src/LevelEditor.cpp:1464 ../src/LevelEditor.cpp:1704
#: ../src/LevelEditor.cpp:1716 ../src/LevelEditor.cpp:1750
-#: ../src/LevelEditor.cpp:4375
+#: ../src/LevelEditor.cpp:4376
msgid "Custom scenery block"
msgstr ""
#: ../src/LevelEditor.cpp:1672
msgid "Toolbox"
msgstr ""
#: ../src/LevelEditor.cpp:1704
#, c-format
msgid "Resize %s"
msgstr ""
#: ../src/LevelEditor.cpp:1704
#, c-format
msgid "Move %s"
msgstr ""
#: ../src/LevelEditor.cpp:1708
#, c-format
msgid "Move %d objects"
msgstr ""
#: ../src/LevelEditor.cpp:1716
#, c-format
msgid "Add %s"
msgstr ""
#: ../src/LevelEditor.cpp:1716
#, c-format
msgid "Remove %s"
msgstr ""
#: ../src/LevelEditor.cpp:1720
#, c-format
msgid "Add %d objects"
msgstr ""
#: ../src/LevelEditor.cpp:1720
#, c-format
msgid "Remove %d objects"
msgstr ""
#: ../src/LevelEditor.cpp:1726
#, c-format
msgid "Add path to %s"
msgstr ""
#: ../src/LevelEditor.cpp:1726
#, c-format
msgid "Remove a path point from %s"
msgstr ""
#: ../src/LevelEditor.cpp:1731
#, c-format
msgid "Remove all paths from %s"
msgstr ""
#: ../src/LevelEditor.cpp:1736
#, c-format
msgid "Add link from %s to %s"
msgstr ""
#: ../src/LevelEditor.cpp:1741
#, c-format
msgid "Remove all links from %s"
msgstr ""
#: ../src/LevelEditor.cpp:1747
msgid "Modify the %2 property of %1"
msgstr ""
#: ../src/LevelEditor.cpp:1795
#, c-format
msgid "Edit the script of %s"
msgstr ""
#: ../src/LevelEditor.cpp:1797
msgid "Edit the script of level"
msgstr ""
#: ../src/LevelEditor.cpp:2122 ../src/LevelEditor.cpp:2202
msgid "The level has unsaved changes."
msgstr ""
#: ../src/LevelEditor.cpp:2126 ../src/LevelEditor.cpp:2204
msgid "Are you sure you want to quit?"
msgstr ""
#: ../src/LevelEditor.cpp:2126 ../src/LevelEditor.cpp:2204
msgid "Quit prompt"
msgstr ""
-#: ../src/LevelEditor.cpp:2792 ../src/LevelEditor.cpp:2794
+#: ../src/LevelEditor.cpp:2773 ../src/LevelEditor.cpp:2775
#, c-format
msgid "Level \"%s\" saved"
msgstr ""
-#: ../src/LevelEditor.cpp:2792 ../src/LevelEditor.cpp:2794
+#: ../src/LevelEditor.cpp:2773 ../src/LevelEditor.cpp:2775
msgid "Saved"
msgstr ""
-#: ../src/LevelEditor.cpp:2854 ../src/LevelEditSelect.cpp:206
+#: ../src/LevelEditor.cpp:2835 ../src/LevelEditSelect.cpp:207
msgid "Name:"
msgstr ""
-#: ../src/LevelEditor.cpp:2861
+#: ../src/LevelEditor.cpp:2842
msgid "Theme:"
msgstr ""
-#: ../src/LevelEditor.cpp:2868
+#: ../src/LevelEditor.cpp:2849
msgid "Examples: %DATA%/themes/classic"
msgstr ""
-#: ../src/LevelEditor.cpp:2870
+#: ../src/LevelEditor.cpp:2851
msgid "or %USER%/themes/Orange"
msgstr ""
-#: ../src/LevelEditor.cpp:2873
+#: ../src/LevelEditor.cpp:2854
msgid "Music:"
msgstr ""
-#: ../src/LevelEditor.cpp:2882
+#: ../src/LevelEditor.cpp:2863
msgid "Target time (s):"
msgstr ""
-#: ../src/LevelEditor.cpp:2898
+#: ../src/LevelEditor.cpp:2879
msgid "Target recordings:"
msgstr ""
-#: ../src/LevelEditor.cpp:2914
+#: ../src/LevelEditor.cpp:2895
msgid "Restart level editor is required"
msgstr ""
-#: ../src/LevelEditor.cpp:3660 ../src/LevelEditor.cpp:3699
-#: ../src/LevelEditor.cpp:3720
+#: ../src/LevelEditor.cpp:3655 ../src/LevelEditor.cpp:3694
+#: ../src/LevelEditor.cpp:3715
msgid "Please enter a layer name."
msgstr ""
-#: ../src/LevelEditor.cpp:3660 ../src/LevelEditor.cpp:3664
-#: ../src/LevelEditor.cpp:3699 ../src/LevelEditor.cpp:3703
-#: ../src/LevelEditor.cpp:3720 ../src/LevelEditor.cpp:3724
+#: ../src/LevelEditor.cpp:3655 ../src/LevelEditor.cpp:3659
+#: ../src/LevelEditor.cpp:3694 ../src/LevelEditor.cpp:3698
+#: ../src/LevelEditor.cpp:3715 ../src/LevelEditor.cpp:3719
+#: ../src/LevelEditSelect.cpp:727
msgid "Error"
msgstr ""
-#: ../src/LevelEditor.cpp:3664 ../src/LevelEditor.cpp:3703
+#: ../src/LevelEditor.cpp:3659 ../src/LevelEditor.cpp:3698
#, c-format
msgid "The layer '%s' already exists."
msgstr ""
-#: ../src/LevelEditor.cpp:3724
+#: ../src/LevelEditor.cpp:3719
msgid "Source and destination layers are the same."
msgstr ""
-#: ../src/LevelEditor.cpp:3741
+#: ../src/LevelEditor.cpp:3736
msgid "Scenery"
msgstr ""
-#: ../src/LevelEditor.cpp:4165 ../src/LevelEditor.cpp:4193
+#: ../src/LevelEditor.cpp:4166 ../src/LevelEditor.cpp:4194
#, c-format
msgid "Speed: %d = %0.2f block/s"
msgstr ""
-#: ../src/LevelEditor.cpp:4178
+#: ../src/LevelEditor.cpp:4179
msgid "Stop at this point"
msgstr ""
-#: ../src/LevelEditor.cpp:4183
+#: ../src/LevelEditor.cpp:4184
#, c-format
msgid "Pause: %d = %0.3fs"
msgstr ""
-#: ../src/LevelEditSelect.cpp:40 ../src/TitleMenu.cpp:45
+#: ../src/LevelEditSelect.cpp:41 ../src/TitleMenu.cpp:45
msgid "Map Editor"
msgstr ""
-#: ../src/LevelEditSelect.cpp:65
+#: ../src/LevelEditSelect.cpp:66
msgid "New Levelpack"
msgstr ""
-#: ../src/LevelEditSelect.cpp:70
+#: ../src/LevelEditSelect.cpp:71
msgid "Pack Properties"
msgstr ""
-#: ../src/LevelEditSelect.cpp:75
+#: ../src/LevelEditSelect.cpp:76
msgid "Remove Pack"
msgstr ""
-#: ../src/LevelEditSelect.cpp:80
+#: ../src/LevelEditSelect.cpp:81
msgid "Move Map"
msgstr ""
-#: ../src/LevelEditSelect.cpp:88
+#: ../src/LevelEditSelect.cpp:89
msgid "Remove Map"
msgstr ""
-#: ../src/LevelEditSelect.cpp:93
+#: ../src/LevelEditSelect.cpp:94
msgid "Edit Map"
msgstr ""
-#: ../src/LevelEditSelect.cpp:203
+#: ../src/LevelEditSelect.cpp:204
msgid "Properties"
msgstr ""
-#: ../src/LevelEditSelect.cpp:215
+#: ../src/LevelEditSelect.cpp:216
msgid "Description:"
msgstr ""
-#: ../src/LevelEditSelect.cpp:224
+#: ../src/LevelEditSelect.cpp:225
msgid "Congratulation text:"
msgstr ""
-#: ../src/LevelEditSelect.cpp:233
+#: ../src/LevelEditSelect.cpp:234
msgid "Music list:"
msgstr ""
-#: ../src/LevelEditSelect.cpp:262 ../src/LevelEditSelect.cpp:473
+#: ../src/LevelEditSelect.cpp:263 ../src/LevelEditSelect.cpp:481
msgid "Add level"
msgstr ""
-#: ../src/LevelEditSelect.cpp:265
+#: ../src/LevelEditSelect.cpp:266
msgid "File name:"
msgstr ""
-#: ../src/LevelEditSelect.cpp:290
+#: ../src/LevelEditSelect.cpp:291
msgid "Move level"
msgstr ""
-#: ../src/LevelEditSelect.cpp:293
+#: ../src/LevelEditSelect.cpp:294
msgid "Level: "
msgstr ""
-#: ../src/LevelEditSelect.cpp:303
+#: ../src/LevelEditSelect.cpp:308
msgid "Before"
msgstr ""
-#: ../src/LevelEditSelect.cpp:304
+#: ../src/LevelEditSelect.cpp:309
msgid "After"
msgstr ""
-#: ../src/LevelEditSelect.cpp:532
+#: ../src/LevelEditSelect.cpp:540
#, c-format
msgid "Are you sure remove the level pack '%s'?"
msgstr ""
-#: ../src/LevelEditSelect.cpp:532 ../src/LevelEditSelect.cpp:560
+#: ../src/LevelEditSelect.cpp:540 ../src/LevelEditSelect.cpp:568
msgid "Remove prompt"
msgstr ""
-#: ../src/LevelEditSelect.cpp:560
+#: ../src/LevelEditSelect.cpp:568
#, c-format
msgid "Are you sure remove the map '%s'?"
msgstr ""
-#: ../src/LevelEditSelect.cpp:681
+#: ../src/LevelEditSelect.cpp:689
msgid "No file name given for the new level."
msgstr ""
-#: ../src/LevelEditSelect.cpp:681
+#: ../src/LevelEditSelect.cpp:689
msgid "Missing file name"
msgstr ""
-#: ../src/LevelEditSelect.cpp:772
+#: ../src/LevelEditSelect.cpp:727
+#, c-format
+msgid "The file %s already exists."
+msgstr ""
+
+#: ../src/LevelEditSelect.cpp:780
msgid "The entered level number isn't valid!"
msgstr ""
-#: ../src/LevelEditSelect.cpp:772
+#: ../src/LevelEditSelect.cpp:780
msgid "Illegal number"
msgstr ""
#: ../src/LevelInfoRender.cpp:19
msgid "Choose a level"
msgstr ""
#: ../src/LevelInfoRender.cpp:20
msgid "Time:"
msgstr ""
-#: ../src/LevelInfoRender.cpp:21 ../src/StatisticsScreen.cpp:260
+#: ../src/LevelInfoRender.cpp:21 ../src/StatisticsScreen.cpp:259
msgid "Recordings:"
msgstr ""
#: ../src/LevelPlaySelect.cpp:41
msgid "Select Level"
msgstr ""
# TRANSLATORS: Used for button which clear any level progress like unlocked levels and highscores.
#: ../src/OptionsMenu.cpp:66
msgid "Clear Progress"
msgstr ""
#: ../src/OptionsMenu.cpp:109
msgid "General"
msgstr ""
#: ../src/OptionsMenu.cpp:110
msgid "Controls"
msgstr ""
#: ../src/OptionsMenu.cpp:121
msgid "Music"
msgstr ""
#: ../src/OptionsMenu.cpp:129
msgid "Sound"
msgstr ""
#: ../src/OptionsMenu.cpp:137
msgid "Resolution"
msgstr ""
#: ../src/OptionsMenu.cpp:177
msgid "Language"
msgstr ""
# TRANSLATORS: as detect user's language automatically
#: ../src/OptionsMenu.cpp:185
msgid "Auto-Detect"
msgstr ""
#: ../src/OptionsMenu.cpp:209
msgid "Theme"
msgstr ""
#: ../src/OptionsMenu.cpp:247
msgid "Internet proxy"
msgstr ""
#: ../src/OptionsMenu.cpp:256
msgid "Fullscreen"
msgstr ""
#: ../src/OptionsMenu.cpp:261
msgid "Quick record"
msgstr ""
#: ../src/OptionsMenu.cpp:266
msgid "Internet"
msgstr ""
#: ../src/OptionsMenu.cpp:271
msgid "Fade transition"
msgstr ""
#: ../src/OptionsMenu.cpp:294
msgid "Save Changes"
msgstr ""
#: ../src/OptionsMenu.cpp:513
msgid "Do you really want to reset level progress?"
msgstr ""
#: ../src/OptionsMenu.cpp:513
msgid "Warning"
msgstr ""
#: ../src/StatisticsManager.cpp:386
msgid "New achievement:"
msgstr ""
#: ../src/StatisticsManager.cpp:394
#, c-format
msgid "Achieved on %s"
msgstr ""
#: ../src/StatisticsManager.cpp:400
msgid "Unknown achievement"
msgstr ""
#: ../src/StatisticsManager.cpp:406
#, c-format
msgid "Achieved %1.0f%%"
msgstr ""
#: ../src/StatisticsManager.cpp:410
msgid "Not achieved"
msgstr ""
-#: ../src/StatisticsScreen.cpp:58 ../src/TitleMenu.cpp:55
+#: ../src/StatisticsScreen.cpp:57 ../src/TitleMenu.cpp:55
msgid "Achievements and Statistics"
msgstr ""
-#: ../src/StatisticsScreen.cpp:167
+#: ../src/StatisticsScreen.cpp:166
msgid "Achievements"
msgstr ""
-#: ../src/StatisticsScreen.cpp:168
+#: ../src/StatisticsScreen.cpp:167
msgid "Statistics"
msgstr ""
-#: ../src/StatisticsScreen.cpp:235
+#: ../src/StatisticsScreen.cpp:234
msgid "Total"
msgstr ""
-#: ../src/StatisticsScreen.cpp:247
+#: ../src/StatisticsScreen.cpp:246
msgid "Traveling distance (m)"
msgstr ""
-#: ../src/StatisticsScreen.cpp:248
+#: ../src/StatisticsScreen.cpp:247
msgid "Jump times"
msgstr ""
-#: ../src/StatisticsScreen.cpp:249
+#: ../src/StatisticsScreen.cpp:248
msgid "Die times"
msgstr ""
-#: ../src/StatisticsScreen.cpp:250
+#: ../src/StatisticsScreen.cpp:249
msgid "Squashed times"
msgstr ""
-#: ../src/StatisticsScreen.cpp:261
+#: ../src/StatisticsScreen.cpp:260
msgid "Switch pulled times:"
msgstr ""
-#: ../src/StatisticsScreen.cpp:262
+#: ../src/StatisticsScreen.cpp:261
msgid "Swap times:"
msgstr ""
-#: ../src/StatisticsScreen.cpp:263
+#: ../src/StatisticsScreen.cpp:262
msgid "Save times:"
msgstr ""
-#: ../src/StatisticsScreen.cpp:264
+#: ../src/StatisticsScreen.cpp:263
msgid "Load times:"
msgstr ""
-#: ../src/StatisticsScreen.cpp:269
+#: ../src/StatisticsScreen.cpp:268
msgid "Completed levels:"
msgstr ""
-#: ../src/StatisticsScreen.cpp:307
+#: ../src/StatisticsScreen.cpp:306
msgid "In-game time:"
msgstr ""
-#: ../src/StatisticsScreen.cpp:309
+#: ../src/StatisticsScreen.cpp:308
msgid "Level editing time:"
msgstr ""
-#: ../src/StatisticsScreen.cpp:311
+#: ../src/StatisticsScreen.cpp:310
msgid "Created levels:"
msgstr ""
#: ../src/TitleMenu.cpp:44
msgid "Options"
msgstr ""
#: ../src/TitleMenu.cpp:47
msgid "Quit"
msgstr ""
#: ../src/TitleMenu.cpp:131
msgid "Enable internet in order to install addons."
msgstr ""
#: ../src/TitleMenu.cpp:131
msgid "Internet disabled"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Return"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Escape"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Backspace"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Tab"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Space"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "CapsLock"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PrintScreen"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "ScrollLock"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Pause"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Insert"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Home"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PageUp"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Delete"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "End"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PageDown"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Down"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Up"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Numlock"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "SysReq"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Ctrl"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Shift"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Alt"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left GUI"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Ctrl"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Shift"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Alt"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right GUI"
msgstr ""
diff --git a/data/locale/zh_CN.po b/data/locale/zh_CN.po
index 867c719..158926f 100644
--- a/data/locale/zh_CN.po
+++ b/data/locale/zh_CN.po
@@ -1,2210 +1,2348 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the meandmyshadow package.
# user <acme_pjz@hotmail.com>, 2018.
msgid ""
msgstr ""
"Project-Id-Version: meandmyshadow 0.5svn\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-12 23:16+0800\n"
-"PO-Revision-Date: 2018-08-12 23:18+0800\n"
+"POT-Creation-Date: 2018-08-20 00:04+0800\n"
+"PO-Revision-Date: 2018-08-20 00:15+0800\n"
"Last-Translator: acme_pjz <acme_pjz@hotmail.com>\n"
"Language-Team: Jz Pan\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 2.1.1\n"
#: ../src/AchievementList.cpp:43
msgid "Newbie"
msgstr "新手"
#: ../src/AchievementList.cpp:43
msgid "Complete a level."
msgstr "完成一个关卡。"
#: ../src/AchievementList.cpp:44
msgid "Experienced player"
msgstr "有经验的玩家"
#: ../src/AchievementList.cpp:44
msgid "Complete 50 levels."
msgstr "完成 50 个关卡。"
#: ../src/AchievementList.cpp:45
msgid "Good job!"
msgstr "干得好!"
#: ../src/AchievementList.cpp:45
msgid "Receive a gold medal."
msgstr "获得一个金牌。"
#: ../src/AchievementList.cpp:46
msgid "Expert"
msgstr "专家"
#: ../src/AchievementList.cpp:46
msgid "Earn 50 gold medal."
msgstr "获得 50 个金牌。"
#: ../src/AchievementList.cpp:48
msgid "Graduate"
msgstr "毕业生"
#: ../src/AchievementList.cpp:48
msgid "Complete the tutorial level pack."
msgstr "完成教程关卡包。"
#: ../src/AchievementList.cpp:49
msgid "Outstanding graduate"
msgstr "优秀毕业生"
#: ../src/AchievementList.cpp:49
msgid "Complete the tutorial level pack with gold for all levels."
msgstr "以全部金牌的成绩完成教学关卡包。"
#: ../src/AchievementList.cpp:51
msgid "Hooked"
msgstr "入迷"
#: ../src/AchievementList.cpp:51
msgid "Play Me and My Shadow for more than 2 hours."
msgstr "玩 Me and My Shadow 超过 2 小时。"
#: ../src/AchievementList.cpp:52
msgid "Loyal fan of Me and My Shadow"
msgstr "Me and My Shadow 忠实粉丝"
#: ../src/AchievementList.cpp:52
msgid "Play Me and My Shadow for more than 24 hours."
msgstr "玩 Me and My Shadow 超过 24 小时。"
#: ../src/AchievementList.cpp:54
msgid "Constructor"
msgstr "建造师"
#: ../src/AchievementList.cpp:54
msgid "Use the level editor for more than 2 hours."
msgstr "使用地图编辑器超过 2 小时。"
#: ../src/AchievementList.cpp:55
msgid "The creator"
msgstr "造物主"
#: ../src/AchievementList.cpp:55
msgid "Use the level editor for more than 24 hours."
msgstr "使用地图编辑器超过 24 小时。"
#: ../src/AchievementList.cpp:57
msgid "Look, cute level!"
msgstr "看,可爱的关卡!"
#: ../src/AchievementList.cpp:57
msgid "Create a level for the first time."
msgstr "第一次创建关卡。"
#: ../src/AchievementList.cpp:58
msgid "The level museum"
msgstr "关卡博物馆"
#: ../src/AchievementList.cpp:58
msgid "Create 50 levels."
msgstr "创建 50 个关卡。"
#: ../src/AchievementList.cpp:60
msgid "Hello, World!"
msgstr "你好,世界!"
#: ../src/AchievementList.cpp:60
msgid "Write a script for the first time."
msgstr "第一次写脚本。"
#: ../src/AchievementList.cpp:62
msgid "Frog"
msgstr "青蛙"
#: ../src/AchievementList.cpp:62
msgid "Jump 1000 times."
msgstr "跳跃 1000 次。"
#: ../src/AchievementList.cpp:64
msgid "Wanderer"
msgstr "漫步者"
#: ../src/AchievementList.cpp:64
msgid "Travel 100 meters."
msgstr "旅行 100 米。"
#: ../src/AchievementList.cpp:65
msgid "Runner"
msgstr "跑步者"
#: ../src/AchievementList.cpp:65
msgid "Travel 1 kilometer."
msgstr "旅行 1 千米。"
#: ../src/AchievementList.cpp:66
msgid "Long distance runner"
msgstr "长跑者"
#: ../src/AchievementList.cpp:66
msgid "Travel 10 kilometers."
msgstr "旅行 10 千米。"
#: ../src/AchievementList.cpp:67
msgid "Marathon runner"
msgstr "马拉松运动员"
#: ../src/AchievementList.cpp:67
msgid "Travel 42,195 meters."
msgstr "旅行 42,195 米。"
#: ../src/AchievementList.cpp:69
msgid "Be careful!"
msgstr "小心!"
#: ../src/AchievementList.cpp:69
msgid "Die for the first time."
msgstr "第一次死掉。"
#: ../src/AchievementList.cpp:70
msgid "It doesn't matter..."
msgstr "没关系……"
#: ../src/AchievementList.cpp:70
msgid "Die 50 times."
msgstr "死掉 50 次。"
#: ../src/AchievementList.cpp:71
msgid "Expert of trial and error"
msgstr "试错专家"
#: ../src/AchievementList.cpp:71
msgid "Die 1000 times."
msgstr "死掉 1000 次。"
#: ../src/AchievementList.cpp:73
msgid "Keep an eye for moving blocks!"
msgstr "小心移动方块!"
#: ../src/AchievementList.cpp:73
msgid "Get squashed for the first time."
msgstr "第一次被夹死。"
#: ../src/AchievementList.cpp:74
msgid "Potato masher"
msgstr "马铃薯捣碎器"
#: ../src/AchievementList.cpp:74
msgid "Get squashed 50 times."
msgstr "被夹死 50 次。"
#: ../src/AchievementList.cpp:76
msgid "Double kill"
msgstr "双重击杀"
#: ../src/AchievementList.cpp:76
msgid "Get both the player and the shadow dead."
msgstr "让玩家和阴影都死掉。"
#: ../src/AchievementList.cpp:78
msgid "Bad luck"
msgstr "运气不好"
#: ../src/AchievementList.cpp:78
msgid "Die 5 times in under 5 seconds."
msgstr "在 5 秒之内死掉 5 次。"
#: ../src/AchievementList.cpp:79
msgid "This level is too dangerous"
msgstr "这关太危险了"
#: ../src/AchievementList.cpp:79
msgid "Die 10 times in under 5 seconds."
msgstr "在 5 秒之内死掉 10 次。"
#: ../src/AchievementList.cpp:81
msgid "You forgot your friend"
msgstr "你忘了你的伙伴"
#: ../src/AchievementList.cpp:81
msgid "Finish the level with the player or the shadow dead."
msgstr "在玩家或者阴影死掉的情况下完成关卡。"
#: ../src/AchievementList.cpp:82
msgid "Just in time"
msgstr "准时到达"
#: ../src/AchievementList.cpp:82
msgid "Reach the exit with the player and the shadow simultaneously."
msgstr "玩家和阴影同时到达终点。"
#: ../src/AchievementList.cpp:84
msgid "Recorder"
msgstr "记录员"
#: ../src/AchievementList.cpp:84
msgid "Record 100 times."
msgstr "记录 100 次。"
#: ../src/AchievementList.cpp:85
msgid "Shadowmaster"
msgstr "影子大师"
#: ../src/AchievementList.cpp:85
msgid "Record 1000 times."
msgstr "记录 1000 次。"
#: ../src/AchievementList.cpp:87
msgid "Switch puller"
msgstr "拨弄开关"
#: ../src/AchievementList.cpp:87
msgid "Pull the switch 100 times."
msgstr "使用开关 100 次。"
#: ../src/AchievementList.cpp:88
msgid "The switch is broken!"
msgstr "开关坏掉了!"
#: ../src/AchievementList.cpp:88
msgid "Pull the switch 1000 times."
msgstr "使用开关 1000 次。"
#: ../src/AchievementList.cpp:90
msgid "Swapper"
msgstr "交换者"
#: ../src/AchievementList.cpp:90
msgid "Swap 100 times."
msgstr "交换 100 次。"
#: ../src/AchievementList.cpp:91
msgid "Player to shadow to player to shadow..."
msgstr "玩家到阴影再到玩家再到阴影…"
#: ../src/AchievementList.cpp:91
msgid "Swap 1000 times."
msgstr "交换 1000 次。"
#: ../src/AchievementList.cpp:93
msgid "Play it save"
msgstr "安全游戏"
#: ../src/AchievementList.cpp:93
msgid "Save 1000 times."
msgstr "保存进度 1000 次。"
#: ../src/AchievementList.cpp:94
msgid "This game is too hard"
msgstr "这游戏太难了"
#: ../src/AchievementList.cpp:94
msgid "Load the game 1000 times."
msgstr "读取进度 1000 次。"
#: ../src/AchievementList.cpp:96
msgid "No, thanks"
msgstr "不用,谢谢"
#: ../src/AchievementList.cpp:96
msgid "Complete a level with checkpoint, but without saving."
msgstr "完成一个有记录点的关卡,但是没有使用保存进度功能。"
#: ../src/AchievementList.cpp:98
msgid "Panic save"
msgstr "慌张地保存"
#: ../src/AchievementList.cpp:98
msgid "Save twice in 1 second."
msgstr "在 1 秒之内保存两次。"
#: ../src/AchievementList.cpp:99
msgid "Panic load"
msgstr "慌张地读取"
#: ../src/AchievementList.cpp:99
msgid "Load twice in 1 second."
msgstr "在 1 秒之内读取两次。"
#: ../src/AchievementList.cpp:101
msgid "Bad saving position"
msgstr "糟糕的存盘位置"
#: ../src/AchievementList.cpp:101
msgid "Load the game and die within 1 second."
msgstr "读取进度并在 1 秒之内死掉。"
#: ../src/AchievementList.cpp:102
msgid "This level is too hard"
msgstr "这一关太难了"
#: ../src/AchievementList.cpp:102
msgid "Load the same save and die 100 times."
msgstr "读取一个相同进度并死掉 100 次。"
#: ../src/AchievementList.cpp:104
msgid "Quick swap"
msgstr "快速交换"
#: ../src/AchievementList.cpp:104
msgid "Swap twice in under a second."
msgstr "在一秒之内交换两次。"
#: ../src/AchievementList.cpp:107
msgid "Horizontal confusion"
msgstr "横向混乱"
#: ../src/AchievementList.cpp:107
msgid "Press left and right simultaneously."
msgstr "同时按下左和右方向键。"
#: ../src/AchievementList.cpp:109
msgid "Cheater"
msgstr "作弊者"
#: ../src/AchievementList.cpp:109
msgid "Cheat in game."
msgstr "在游戏中作弊。"
#: ../src/AchievementList.cpp:111
msgid "Programmer"
msgstr "程序员"
#: ../src/AchievementList.cpp:111
msgid "Play the development version of Me and My Shadow."
msgstr "玩 Me and My Shadow 的开发版本。"
#: ../src/Addons.cpp:44
msgid "Levels"
msgstr "关卡"
#: ../src/Addons.cpp:44
msgid "Single level which usually contain demanding puzzles"
msgstr "单个关卡,里面通常包含高难谜题"
#: ../src/Addons.cpp:45
msgid "Levelpacks"
msgstr "关卡包"
#: ../src/Addons.cpp:45
msgid "Collection of levels with the same author or style"
msgstr "相同作者或风格的关卡构成的集合"
#: ../src/Addons.cpp:46
msgid "Themes"
msgstr "主题"
#: ../src/Addons.cpp:46
msgid "Give every block and background a new look and feel"
msgstr "为每个方块和背景赋予新的外观"
#: ../src/Addons.cpp:55 ../src/TitleMenu.cpp:46
msgid "Addons"
msgstr "附加组件"
#: ../src/Addons.cpp:87
msgid "Unable to initialize addon menu:"
msgstr "不能初始化附加组件菜单:"
#: ../src/Addons.cpp:95 ../src/Addons.cpp:158 ../src/Addons.cpp:662
#: ../src/Addons.cpp:690 ../src/CreditsMenu.cpp:89 ../src/LevelSelect.cpp:168
-#: ../src/StatisticsScreen.cpp:160
+#: ../src/StatisticsScreen.cpp:159
msgid "Back"
msgstr "后退"
#: ../src/Addons.cpp:169
msgid "ERROR: unable to download addons file!"
msgstr "错误: 无法下载附加组件!"
# TRANSLATORS: addon_list is the name of a file and should not be translated.
#: ../src/Addons.cpp:182
msgid "ERROR: unable to load addon_list file!"
msgstr "错误: 无法加载文件 addon_list!"
#: ../src/Addons.cpp:193
msgid "ERROR: Invalid file format of addons file!"
msgstr "错误: 文件 addons 的格式无效!"
#: ../src/Addons.cpp:205
msgid "ERROR: Addon list version is unsupported!"
msgstr "错误: 附加组件列表的版本是不支持的!"
# TRANSLATORS: installed_addons is the name of a file and should not be translated.
# TRANSLATORS: installed_addons is the name of a file and should not be
# translated.
#: ../src/Addons.cpp:226
msgid "ERROR: Unable to create the installed_addons file."
msgstr "错误: 无法创建文件 installed_addons。"
#: ../src/Addons.cpp:238
msgid "ERROR: Invalid file format of the installed_addons!"
msgstr "错误: 文件 installed_addons 的格式无效!"
# TRANSLATORS: indicates the author of an addon.
#: ../src/Addons.cpp:389 ../src/Addons.cpp:621
#, c-format
msgid "by %s"
msgstr "作者 %s"
#: ../src/Addons.cpp:397
msgid "Installed"
msgstr "已安装"
#: ../src/Addons.cpp:402
msgid "Updatable"
msgstr "可更新"
#: ../src/Addons.cpp:412
msgid "Not installed"
msgstr "未安装"
#: ../src/Addons.cpp:625
#, c-format
msgid "Version: %d\n"
msgstr "版本: %d\n"
#: ../src/Addons.cpp:627
#, c-format
msgid "Installed version: %d\n"
msgstr "已安装的版本: %d\n"
#: ../src/Addons.cpp:630
#, c-format
msgid "License: %s\n"
msgstr "授权: %s\n"
#: ../src/Addons.cpp:633
#, c-format
msgid "Website: %s\n"
msgstr "网址: %s\n"
#: ../src/Addons.cpp:637
msgid "(No descriptions provided)"
msgstr "(没有提供说明)"
#: ../src/Addons.cpp:657 ../src/Addons.cpp:684
msgid "Remove"
msgstr "移除"
#: ../src/Addons.cpp:673
msgid "Update"
msgstr "更新"
#: ../src/Addons.cpp:679
msgid "Install"
msgstr "安装"
+#: ../src/Addons.cpp:774
+#, c-format
+msgid "This addon can't be removed because it's needed by %s."
+msgstr "此附加组件无法移除,因为它被 %s 所依赖。"
+
+#: ../src/Addons.cpp:774 ../src/Addons.cpp:1051
+msgid "Dependency"
+msgstr "依赖项"
+
+#: ../src/Addons.cpp:803
+#, c-format
+msgid "WARNING: File '%s' appears to have been removed already."
+msgstr "警告:文件 '%s' 似乎已经被移除。"
+
+#: ../src/Addons.cpp:803 ../src/Addons.cpp:810 ../src/Addons.cpp:818
+#: ../src/Addons.cpp:825 ../src/Addons.cpp:834 ../src/Addons.cpp:840
+#: ../src/Addons.cpp:859 ../src/Addons.cpp:866 ../src/Addons.cpp:893
+#: ../src/Addons.cpp:900 ../src/Addons.cpp:907 ../src/Addons.cpp:918
+#: ../src/Addons.cpp:947 ../src/Addons.cpp:952 ../src/Addons.cpp:962
+#: ../src/Addons.cpp:968 ../src/Addons.cpp:981 ../src/Addons.cpp:986
+#: ../src/Addons.cpp:1008 ../src/Addons.cpp:1014 ../src/Addons.cpp:1044
+msgid "Addon error"
+msgstr "附加组件错误"
+
+#: ../src/Addons.cpp:810
+#, c-format
+msgid "ERROR: Unable to remove file '%s'!"
+msgstr "错误:无法移除文件 '%s'!"
+
+#: ../src/Addons.cpp:818
+#, c-format
+msgid "WARNING: Directory '%s' appears to have been removed already."
+msgstr "警告:文件夹 '%s' 似乎已经被移除。"
+
+#: ../src/Addons.cpp:825
+#, c-format
+msgid "ERROR: Unable to remove directory '%s'!"
+msgstr "错误:无法移除文件夹 '%s'!"
+
+#: ../src/Addons.cpp:834
+#, c-format
+msgid "WARNING: Level '%s' appears to have been removed already."
+msgstr "警告:关卡 '%s' 似乎已经被移除。"
+
+#: ../src/Addons.cpp:840
+#, c-format
+msgid "ERROR: Unable to remove level '%s'!"
+msgstr "错误:无法移除关卡 '%s'!"
+
+#: ../src/Addons.cpp:859
+#, c-format
+msgid "WARNING: Levelpack directory '%s' appears to have been removed already."
+msgstr "警告:关卡包文件夹 '%s' 似乎已经被移除。"
+
+#: ../src/Addons.cpp:866
+#, c-format
+msgid "ERROR: Unable to remove levelpack directory '%s'!"
+msgstr "错误:无法移除关卡包文件夹 '%s'!"
+
+#: ../src/Addons.cpp:893
+#, c-format
+msgid "ERROR: Unable to download addon file %s."
+msgstr "错误:无法下载附加组件 %s。"
+
+#: ../src/Addons.cpp:900
+#, c-format
+msgid "ERROR: Unable to extract addon file %s."
+msgstr "错误:无法解压附加组件 %s。"
+
+#: ../src/Addons.cpp:907
+msgid "ERROR: Addon is missing metadata!"
+msgstr "错误:附加组件缺少 metadata 文件!"
+
+#: ../src/Addons.cpp:918
+msgid "ERROR: Invalid file format for metadata file!"
+msgstr "错误:附加组件 metadata 文件的格式无效!"
+
+#: ../src/Addons.cpp:947
+#, c-format
+msgid "WARNING: File '%s' already exists, addon may be broken or not working!"
+msgstr "警告:文件 '%s' 已经存在,附加组件可能损坏或无法使用!"
+
+#: ../src/Addons.cpp:952
+#, c-format
+msgid ""
+"WARNING: Unable to copy file '%s' to '%s', addon may be broken or not "
+"working!"
+msgstr "警告:无法复制文件 '%s' 到 '%s',附加组件可能损坏或无法使用!"
+
+#: ../src/Addons.cpp:962
+#, c-format
+msgid ""
+"WARNING: Destination directory '%s' already exists, addon may be broken or "
+"not working!"
+msgstr "警告:目标文件夹 '%s' 已经存在,附加组件可能损坏或无法使用!"
+
+#: ../src/Addons.cpp:968 ../src/Addons.cpp:1014
+#, c-format
+msgid ""
+"WARNING: Unable to move directory '%s' to '%s', addon may be broken or not "
+"working!"
+msgstr "警告:无法移动文件夹 '%s' 到 '%s',附加组件可能损坏或无法使用!"
+
+#: ../src/Addons.cpp:981
+#, c-format
+msgid "WARNING: Level '%s' already exists, addon may be broken or not working!"
+msgstr "警告:关卡 '%s' 已经存在,附加组件可能损坏或无法使用!"
+
+#: ../src/Addons.cpp:986
+#, c-format
+msgid ""
+"WARNING: Unable to copy level '%s' to '%s', addon may be broken or not "
+"working!"
+msgstr "警告:无法复制关卡 '%s' 到 '%s',附加组件可能损坏或无法使用!"
+
+#: ../src/Addons.cpp:1008
+#, c-format
+msgid ""
+"WARNING: Levelpack directory '%s' already exists, addon may be broken or not "
+"working!"
+msgstr "警告:关卡包文件夹 '%s' 已经存在,附加组件可能损坏或无法使用!"
+
+#: ../src/Addons.cpp:1044
+#, c-format
+msgid "ERROR: Addon requires another addon (%s) which can't be found!"
+msgstr "错误:附加组件依赖另一个附加组件 (%s) 但是无法找到!"
+
+#: ../src/Addons.cpp:1051
+#, c-format
+msgid "The addon %s is needed and will be installed now."
+msgstr "附加组件 %s 是依赖项,将会被安装。"
+
#: ../src/Block.cpp:822 ../src/LevelEditor.cpp:265
msgid "On"
msgstr "开启"
#: ../src/Block.cpp:823 ../src/LevelEditor.cpp:266
msgid "Off"
msgstr "关闭"
#: ../src/CommandManager.cpp:41
#, c-format
msgid "Undo %s"
msgstr "撤消 %s"
#: ../src/CommandManager.cpp:43
msgid "Can't undo"
msgstr "不能撤消"
#: ../src/CommandManager.cpp:49
#, c-format
msgid "Redo %s"
msgstr "重做 %s"
#: ../src/CommandManager.cpp:51
msgid "Can't redo"
msgstr "不能重做"
#: ../src/Commands.cpp:189
msgid "Resize level"
msgstr "改变关卡大小"
-#: ../src/Commands.cpp:783
+#: ../src/Commands.cpp:805
msgid "Modify level property"
msgstr "修改关卡属性"
-#: ../src/Commands.cpp:893
+#: ../src/Commands.cpp:915
#, c-format
msgid "Add scenery layer %s"
msgstr "添加风景图层 %s"
-#: ../src/Commands.cpp:893
+#: ../src/Commands.cpp:915
#, c-format
msgid "Delete scenery layer %s"
msgstr "删除风景图层 %s"
-#: ../src/Commands.cpp:922
+#: ../src/Commands.cpp:944
#, c-format
msgid "Modify the property of scenery layer %s"
msgstr "修改风景图层 %s 的属性"
-#: ../src/Commands.cpp:1009
+#: ../src/Commands.cpp:1031
#, c-format
msgid "Move %d object(s) from layer %s to layer %s"
msgstr "将 %d 个对象从图层 %s 移动到图层 %s"
#: ../src/CreditsMenu.cpp:35 ../src/TitleMenu.cpp:53
msgid "Credits"
msgstr "作者"
# TRANSLATORS: Font used in GUI:
# - Use "knewave" for languages using Latin and Latin-derived alphabets
# - "DroidSansFallback" can be used for non-Latin writing systems
#: ../src/Functions.cpp:560 ../src/Functions.cpp:561 ../src/Functions.cpp:562
#: ../src/Functions.cpp:579
msgid "knewave"
msgstr "DroidSansFallback"
# TRANSLATORS: Font used for normal text:
# - Use "Blokletters-Viltstift" for languages using Latin and Latin-derived alphabets
# - "DroidSansFallback" can be used for non-Latin writing systems
# - Use "Blokletters-Viltstift" for languages using Latin and Latin-derived
# alphabets
#: ../src/Functions.cpp:566
msgid "Blokletters-Viltstift"
msgstr "DroidSansFallback"
#: ../src/Functions.cpp:665
msgid "Loading..."
msgstr "正在读取..."
-#: ../src/Functions.cpp:1225 ../src/Functions.cpp:1252
+#: ../src/Functions.cpp:1235 ../src/Functions.cpp:1262
#: ../src/LevelEditor.cpp:559 ../src/LevelEditor.cpp:693
#: ../src/LevelEditor.cpp:758 ../src/LevelEditor.cpp:821
#: ../src/LevelEditor.cpp:908 ../src/LevelEditor.cpp:1033
#: ../src/LevelEditor.cpp:1083 ../src/LevelEditor.cpp:1180
-#: ../src/LevelEditor.cpp:1244 ../src/LevelEditor.cpp:2918
-#: ../src/LevelEditSelect.cpp:242 ../src/LevelEditSelect.cpp:274
-#: ../src/LevelEditSelect.cpp:310
+#: ../src/LevelEditor.cpp:1244 ../src/LevelEditor.cpp:2899
+#: ../src/LevelEditSelect.cpp:243 ../src/LevelEditSelect.cpp:275
+#: ../src/LevelEditSelect.cpp:315
msgid "OK"
msgstr "确定"
-#: ../src/Functions.cpp:1226 ../src/Functions.cpp:1238
-#: ../src/Functions.cpp:1248 ../src/LevelEditor.cpp:565
+#: ../src/Functions.cpp:1236 ../src/Functions.cpp:1248
+#: ../src/Functions.cpp:1258 ../src/LevelEditor.cpp:565
#: ../src/LevelEditor.cpp:699 ../src/LevelEditor.cpp:764
#: ../src/LevelEditor.cpp:827 ../src/LevelEditor.cpp:914
#: ../src/LevelEditor.cpp:1039 ../src/LevelEditor.cpp:1089
#: ../src/LevelEditor.cpp:1186 ../src/LevelEditor.cpp:1250
-#: ../src/LevelEditor.cpp:2924 ../src/LevelEditSelect.cpp:246
-#: ../src/LevelEditSelect.cpp:278 ../src/LevelEditSelect.cpp:314
+#: ../src/LevelEditor.cpp:2905 ../src/LevelEditSelect.cpp:247
+#: ../src/LevelEditSelect.cpp:279 ../src/LevelEditSelect.cpp:319
#: ../src/OptionsMenu.cpp:289
msgid "Cancel"
msgstr "取消"
-#: ../src/Functions.cpp:1230
+#: ../src/Functions.cpp:1240
msgid "Abort"
msgstr "终止"
-#: ../src/Functions.cpp:1231 ../src/Functions.cpp:1247
+#: ../src/Functions.cpp:1241 ../src/Functions.cpp:1257
msgid "Retry"
msgstr "重试"
-#: ../src/Functions.cpp:1232
+#: ../src/Functions.cpp:1242
msgid "Ignore"
msgstr "忽略"
-#: ../src/Functions.cpp:1236 ../src/Functions.cpp:1242
+#: ../src/Functions.cpp:1246 ../src/Functions.cpp:1252
msgid "Yes"
msgstr "是"
-#: ../src/Functions.cpp:1237 ../src/Functions.cpp:1243
+#: ../src/Functions.cpp:1247 ../src/Functions.cpp:1253
msgid "No"
msgstr "否"
# TRANSLATORS: Please do not remove %s or %d from your translation:
# - %d means the level number in a levelpack
# - %s means the name of current level
-#: ../src/Game.cpp:281 ../src/Game.cpp:1193
+#: ../src/Game.cpp:281 ../src/Game.cpp:1213
#, c-format
msgid "Level %d %s"
msgstr "第 %d 关 %s"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
-#: ../src/Game.cpp:872
+#: ../src/Game.cpp:892
#, c-format
msgid "Press %s key to save the game."
msgstr "按 %s 键来保存游戏。"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
-#: ../src/Game.cpp:877
+#: ../src/Game.cpp:897
#, c-format
msgid "Press %s key to swap the position of player and shadow."
msgstr "按 %s 键交换你和阴影的位置。"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
-#: ../src/Game.cpp:882
+#: ../src/Game.cpp:902
#, c-format
msgid "Press %s key to activate the switch."
msgstr "按 %s 键来激活开关。"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
-#: ../src/Game.cpp:887
+#: ../src/Game.cpp:907
#, c-format
msgid "Press %s key to teleport."
msgstr "按 %s 键传送。"
# TRANSLATORS: Please do not remove %s from your translation:
# - first %s means currently configured key to restart game
# - Second %s means configured key to load from last save
-#: ../src/Game.cpp:929
+#: ../src/Game.cpp:949
#, c-format
msgid "Press %s to restart current level or press %s to load the game."
msgstr "按 %s 键重新开始游戏,或者按 %s 键读取进度。"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with currently configured key to restart game
-#: ../src/Game.cpp:940
+#: ../src/Game.cpp:960
#, c-format
msgid "Press %s to restart current level."
msgstr "按 %s 键重新开始游戏。"
-#: ../src/Game.cpp:953
+#: ../src/Game.cpp:973
msgid "Your shadow has died."
msgstr "你的阴影死掉了。"
-#: ../src/Game.cpp:1009
+#: ../src/Game.cpp:1029
#, c-format
msgid "%d recordings"
msgstr "记录数 %d"
-#: ../src/Game.cpp:1181
+#: ../src/Game.cpp:1201
msgid "You've finished:"
msgstr "恭喜你完成了:"
# TRANSLATORS: Please do not remove %-.2f from your translation:
# - %-.2f means time in seconds
# - s is shortened form of a second. Try to keep it so.
-#: ../src/Game.cpp:1248
+#: ../src/Game.cpp:1268
#, c-format
msgid "Time: %-.2fs"
msgstr "时间: %-.2f秒"
# TRANSLATORS: Please do not remove %-.2f from your translation:
# - %-.2f means time in seconds
# - s is shortened form of a second. Try to keep it so.
-#: ../src/Game.cpp:1257
+#: ../src/Game.cpp:1277
#, c-format
msgid "Best time: %-.2fs"
msgstr "最佳时间: %-.2f秒"
-#: ../src/Game.cpp:1268
+#: ../src/Game.cpp:1288
#, c-format
msgid "Target time: %-.2fs"
msgstr "目标时间: %-.2f秒"
# TRANSLATORS: Please do not remove %d from your translation:
# - %d means the number of recordings user has made
-#: ../src/Game.cpp:1289
+#: ../src/Game.cpp:1309
#, c-format
msgid "Recordings: %d"
msgstr "记录次数: %d"
# TRANSLATORS: Please do not remove %d from your translation:
# - %d means the number of recordings user has made
-#: ../src/Game.cpp:1297
+#: ../src/Game.cpp:1317
#, c-format
msgid "Best recordings: %d"
msgstr "最佳记录次数: %d"
-#: ../src/Game.cpp:1307
+#: ../src/Game.cpp:1327
#, c-format
msgid "Target recordings: %d"
msgstr "目标记录次数: %d"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with name of a prize medal (gold, silver or bronze)
-#: ../src/Game.cpp:1320
+#: ../src/Game.cpp:1340
#, c-format
msgid "You earned the %s medal"
msgstr "你拿到了%s"
-#: ../src/Game.cpp:1320
+#: ../src/Game.cpp:1340
msgid "GOLD"
msgstr "金牌"
-#: ../src/Game.cpp:1320
+#: ../src/Game.cpp:1340
msgid "SILVER"
msgstr "银牌"
-#: ../src/Game.cpp:1320
+#: ../src/Game.cpp:1340
msgid "BRONZE"
msgstr "铜牌"
# TRANSLATORS: used as return to the level selector menu
-#: ../src/Game.cpp:1347
+#: ../src/Game.cpp:1367
msgid "Menu"
msgstr "菜单"
# TRANSLATORS: used as restart level
-#: ../src/Game.cpp:1354 ../src/InputManager.cpp:47
+#: ../src/Game.cpp:1374 ../src/InputManager.cpp:47
msgid "Restart"
msgstr "重新开始"
# TRANSLATORS: used as next level
-#: ../src/Game.cpp:1361
+#: ../src/Game.cpp:1381
msgid "Next"
msgstr "下一关"
-#: ../src/Game.cpp:1387
+#: ../src/Game.cpp:1407
msgid "Game replay is done."
msgstr "游戏重放已经完成。"
-#: ../src/Game.cpp:1387
+#: ../src/Game.cpp:1407
msgid "Game Replay"
msgstr "游戏重放"
-#: ../src/Game.cpp:1724 ../src/Game.cpp:1726
+#: ../src/Game.cpp:1744 ../src/Game.cpp:1746
msgid "Congratulations"
msgstr "恭喜你"
-#: ../src/Game.cpp:1726
+#: ../src/Game.cpp:1746
msgid "You have finished the levelpack!"
msgstr "你已经完成了整个关卡包!"
#: ../src/InputManager.cpp:46
msgid "Up (in menu)"
msgstr "上(在菜单中)"
#: ../src/InputManager.cpp:46
msgid "Down (in menu)"
msgstr "下(在菜单中)"
# TRANSLATORS: name of a key
#: ../src/InputManager.cpp:46
msgid "Left"
msgstr "左"
# TRANSLATORS: name of a key
#: ../src/InputManager.cpp:46
msgid "Right"
msgstr "右"
#: ../src/InputManager.cpp:46
msgid "Jump"
msgstr "跳跃"
#: ../src/InputManager.cpp:46
msgid "Action"
msgstr "动作键"
#: ../src/InputManager.cpp:46
msgid "Space (Record)"
msgstr "空格(记录键)"
#: ../src/InputManager.cpp:46
msgid "Cancel recording"
msgstr "取消记录"
# TRANSLATORS: name of a key
#: ../src/InputManager.cpp:47
msgid "Escape"
msgstr "退出"
#: ../src/InputManager.cpp:47
msgid "Tab (View shadow/Level prop.)"
msgstr "Tab (切换视角/关卡属性)"
#: ../src/InputManager.cpp:47
msgid "Save game (in editor)"
msgstr "保存游戏(在地图编辑器中)"
#: ../src/InputManager.cpp:47
msgid "Load game"
msgstr "读取游戏"
#: ../src/InputManager.cpp:47
msgid "Swap (in editor)"
msgstr "交换玩家和阴影的位置(在地图编辑器中)"
#: ../src/InputManager.cpp:48
msgid "Teleport (in editor)"
msgstr "传送(在地图编辑器中)"
#: ../src/InputManager.cpp:48
msgid "Suicide (in editor)"
msgstr "自杀(在地图编辑器中)"
#: ../src/InputManager.cpp:48
msgid "Shift (in editor)"
msgstr "Shift (地图编辑器辅助按键)"
#: ../src/InputManager.cpp:48
msgid "Next block type (in Editor)"
msgstr "下一个砖块类型(在地图编辑器中)"
#: ../src/InputManager.cpp:49
msgid "Previous block type (in editor)"
msgstr "上一个砖块类型(在地图编辑器中)"
#: ../src/InputManager.cpp:49
msgid "Select (in menu)"
msgstr "选择键(在菜单中)"
# TRANSLAOTRS: This is used when the name of the key code is not found.
#: ../src/InputManager.cpp:156
#, c-format
msgid "(Key %d)"
msgstr "(按键 %d)"
#: ../src/InputManager.cpp:163
#, c-format
msgid "Joystick axis %d %s"
msgstr "手柄摇杆 %d %s"
#: ../src/InputManager.cpp:166
#, c-format
msgid "Joystick button %d"
msgstr "手柄按钮 %d"
#: ../src/InputManager.cpp:171
#, c-format
msgid "Joystick hat %d left"
msgstr "手柄帽 %d 向左"
#: ../src/InputManager.cpp:174
#, c-format
msgid "Joystick hat %d right"
msgstr "手柄帽 %d 向右"
#: ../src/InputManager.cpp:177
#, c-format
msgid "Joystick hat %d up"
msgstr "手柄帽 %d 向上"
#: ../src/InputManager.cpp:180
#, c-format
msgid "Joystick hat %d down"
msgstr "手柄帽 %d 向下"
# TRANSLAOTRS: This is used when the JOYSTICK_HAT value is invalid.
#: ../src/InputManager.cpp:185
#, c-format
msgid "Joystick hat %d %d"
msgstr "手柄帽 %d %d"
#: ../src/InputManager.cpp:202
msgid "OR"
msgstr "或"
#: ../src/InputManager.cpp:416
msgid "Select an item and press a key to change it."
msgstr "选择一个条目并按下按键来修改它。"
#: ../src/InputManager.cpp:419
msgid "Press backspace to clear the selected item."
msgstr "按 backspace 键清除选中的条目。"
#: ../src/LevelEditor.cpp:56
msgid "Block"
msgstr "砖块"
#: ../src/LevelEditor.cpp:56
msgid "Player Start"
msgstr "玩家起点"
#: ../src/LevelEditor.cpp:56
msgid "Shadow Start"
msgstr "阴影起点"
#: ../src/LevelEditor.cpp:57
msgid "Exit"
msgstr "终点"
#: ../src/LevelEditor.cpp:57
msgid "Shadow Block"
msgstr "阴影砖块"
#: ../src/LevelEditor.cpp:57
msgid "Spikes"
msgstr "带刺砖块"
#: ../src/LevelEditor.cpp:58
msgid "Checkpoint"
msgstr "记录点"
-#: ../src/LevelEditor.cpp:58 ../src/LevelEditSelect.cpp:305
+#: ../src/LevelEditor.cpp:58 ../src/LevelEditSelect.cpp:310
msgid "Swap"
msgstr "交换点"
#: ../src/LevelEditor.cpp:58
msgid "Fragile"
msgstr "易碎砖块"
#: ../src/LevelEditor.cpp:59
msgid "Moving Block"
msgstr "移动砖块"
#: ../src/LevelEditor.cpp:59
msgid "Moving Shadow Block"
msgstr "移动阴影砖块"
#: ../src/LevelEditor.cpp:59
msgid "Moving Spikes"
msgstr "移动的刺"
#: ../src/LevelEditor.cpp:60
msgid "Teleporter"
msgstr "传送点"
#: ../src/LevelEditor.cpp:60
msgid "Button"
msgstr "按钮"
#: ../src/LevelEditor.cpp:60
msgid "Switch"
msgstr "开关"
#: ../src/LevelEditor.cpp:61
msgid "Conveyor Belt"
msgstr "传送带"
#: ../src/LevelEditor.cpp:61
msgid "Shadow Conveyor Belt"
msgstr "阴影传送带"
#: ../src/LevelEditor.cpp:61
msgid "Notification Block"
msgstr "消息方块"
#: ../src/LevelEditor.cpp:61
msgid "Collectable"
msgstr "可收集的物品"
#: ../src/LevelEditor.cpp:61
msgid "Pushable"
msgstr "可推动方块"
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:310
msgid "Select"
msgstr "选择"
#: ../src/LevelEditor.cpp:65
msgid "Add"
msgstr "添加"
# TRANSLATORS: name of a key
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:311
msgid "Delete"
msgstr "删除"
#: ../src/LevelEditor.cpp:65 ../src/LevelPlaySelect.cpp:66
#: ../src/TitleMenu.cpp:43
msgid "Play"
msgstr "开始游戏"
-#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:2847
+#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:2828
msgid "Level settings"
msgstr "关卡设置"
#: ../src/LevelEditor.cpp:65
msgid "Save level"
msgstr "保存关卡"
#: ../src/LevelEditor.cpp:65
msgid "Back to menu"
msgstr "回主菜单"
#: ../src/LevelEditor.cpp:65
msgid "Configure"
msgstr "设置"
#: ../src/LevelEditor.cpp:84
#, c-format
msgid "%s (Scenery)"
msgstr "%s (风景)"
#: ../src/LevelEditor.cpp:267
msgid "Toggle"
msgstr "切换"
#: ../src/LevelEditor.cpp:270
msgid "Complete"
msgstr "完整的"
#: ../src/LevelEditor.cpp:271
msgid "One step"
msgstr "踩了一次"
#: ../src/LevelEditor.cpp:272
msgid "Two steps"
msgstr "踩了两次"
#: ../src/LevelEditor.cpp:273
msgid "Gone"
msgstr "已经破碎"
#: ../src/LevelEditor.cpp:291
msgid "Negative infinity"
msgstr "负无穷"
#: ../src/LevelEditor.cpp:293
msgid "Zero"
msgstr "零"
#: ../src/LevelEditor.cpp:295
msgid "Level size"
msgstr "关卡大小"
#: ../src/LevelEditor.cpp:297
msgid "Positive infinity"
msgstr "正无穷"
#: ../src/LevelEditor.cpp:299
msgid "Default"
msgstr "默认"
#: ../src/LevelEditor.cpp:308
msgid "Deselect"
msgstr "取消选择"
#: ../src/LevelEditor.cpp:318 ../src/LevelEditor.cpp:1136
#, c-format
msgid "Horizontal repeat start: %s"
msgstr "水平重复起点: %s"
#: ../src/LevelEditor.cpp:320 ../src/LevelEditor.cpp:1137
#, c-format
msgid "Horizontal repeat end: %s"
msgstr "水平重复终点: %s"
#: ../src/LevelEditor.cpp:322 ../src/LevelEditor.cpp:1138
#, c-format
msgid "Vertical repeat start: %s"
msgstr "垂直重复起点: %s"
#: ../src/LevelEditor.cpp:324 ../src/LevelEditor.cpp:1139
#, c-format
msgid "Vertical repeat end: %s"
msgstr "垂直重复终点: %s"
#: ../src/LevelEditor.cpp:329 ../src/LevelEditor.cpp:1150
msgid "Custom scenery"
msgstr "自定义风景"
#: ../src/LevelEditor.cpp:335 ../src/LevelEditor.cpp:600
#: ../src/LevelEditor.cpp:602
msgid "Visible"
msgstr "可见"
#: ../src/LevelEditor.cpp:344
msgid "Link"
msgstr "链接"
#: ../src/LevelEditor.cpp:345
msgid "Remove Links"
msgstr "移除链接"
#: ../src/LevelEditor.cpp:349 ../src/LevelEditor.cpp:624
#: ../src/LevelEditor.cpp:626
msgid "Automatic"
msgstr "自动"
#: ../src/LevelEditor.cpp:359 ../src/LevelEditor.cpp:649
#, c-format
msgid "Behavior: %s"
msgstr "行为: %s"
#: ../src/LevelEditor.cpp:362
msgid "Path"
msgstr "路径"
#: ../src/LevelEditor.cpp:363
msgid "Remove Path"
msgstr "移除路径"
#: ../src/LevelEditor.cpp:365 ../src/LevelEditor.cpp:371
#: ../src/LevelEditor.cpp:587 ../src/LevelEditor.cpp:589
msgid "Activated"
msgstr "激活"
#: ../src/LevelEditor.cpp:366 ../src/LevelEditor.cpp:612
#: ../src/LevelEditor.cpp:614
msgid "Looping"
msgstr "循环"
-#: ../src/LevelEditor.cpp:372 ../src/LevelEditor.cpp:3507
+#: ../src/LevelEditor.cpp:372 ../src/LevelEditor.cpp:3502
msgid "Speed"
msgstr "速度"
#: ../src/LevelEditor.cpp:378 ../src/LevelEditor.cpp:668
#, c-format
msgid "State: %s"
msgstr "状态: %s"
-#: ../src/LevelEditor.cpp:382 ../src/LevelEditor.cpp:3492
+#: ../src/LevelEditor.cpp:382 ../src/LevelEditor.cpp:3487
msgid "Message"
msgstr "消息"
#: ../src/LevelEditor.cpp:384 ../src/LevelEditor.cpp:1202
-#: ../src/LevelEditor.cpp:3806
+#: ../src/LevelEditor.cpp:3801
msgid "Appearance"
msgstr "外观"
#: ../src/LevelEditor.cpp:389 ../src/LevelEditor.cpp:431
#: ../src/LevelEditor.cpp:715
msgid "Scripting"
msgstr "脚本"
#: ../src/LevelEditor.cpp:402 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Background layer: %s"
msgstr "背景图层: %s"
#: ../src/LevelEditor.cpp:409 ../src/LevelEditor.cpp:866
#: ../src/LevelEditor.cpp:884
msgid "Blocks layer"
msgstr "方块图层"
#: ../src/LevelEditor.cpp:417 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Foreground layer: %s"
msgstr "前景图层: %s"
#: ../src/LevelEditor.cpp:423
msgid "Add new layer"
msgstr "添加图层"
#: ../src/LevelEditor.cpp:424
msgid "Delete selected layer"
msgstr "删除选中图层"
#: ../src/LevelEditor.cpp:425
msgid "Configure selected layer"
msgstr "设置选中图层"
#: ../src/LevelEditor.cpp:426
msgid "Move selected object to layer"
msgstr "移动选中对象到图层"
#: ../src/LevelEditor.cpp:430 ../src/OptionsMenu.cpp:55
msgid "Settings"
msgstr "选项"
#: ../src/LevelEditor.cpp:463
msgid ""
"NOTE: the layers are sorted by name alphabetically.\n"
"The layer is background layer if its name is < 'f'\n"
"by dictionary order, otherwise it's foreground layer."
msgstr ""
"说明: 图层按照名字以字母顺序排列。\n"
"如果图层的名字按字典顺序 < 'f'\n"
"则它是背景图层,否则它是前景图层。"
#: ../src/LevelEditor.cpp:539
msgid "Notification block"
msgstr "消息方块"
#: ../src/LevelEditor.cpp:545
msgid "Enter message here:"
msgstr "输入消息:"
#: ../src/LevelEditor.cpp:646
msgid "Behavior"
msgstr "行为"
#: ../src/LevelEditor.cpp:665
msgid "State"
msgstr "状态"
#: ../src/LevelEditor.cpp:673
msgid "Conveyor belt speed"
msgstr "传送带速度"
#: ../src/LevelEditor.cpp:679
msgid "Enter speed here:"
msgstr "输入速度:"
#: ../src/LevelEditor.cpp:690
msgid "NOTE: 1 Speed = 0.08 block/s"
msgstr "说明: 速度 1 = 0.08 格/秒"
#: ../src/LevelEditor.cpp:721
msgid "Id:"
msgstr "Id:"
#: ../src/LevelEditor.cpp:787
msgid "Level Scripting"
msgstr "关卡脚本"
#: ../src/LevelEditor.cpp:892
msgid "Add layer"
msgstr "添加图层"
#: ../src/LevelEditor.cpp:898
msgid "Enter the layer name:"
msgstr "输入图层名称:"
#: ../src/LevelEditor.cpp:943
#, c-format
msgid "Are you sure you want to delete layer '%s'?"
msgstr "你确定要删除图层 '%s' 吗?"
#: ../src/LevelEditor.cpp:944
msgid "Delete layer"
msgstr "删除图层"
#: ../src/LevelEditor.cpp:968
msgid "Layer settings"
msgstr "图层设置"
#: ../src/LevelEditor.cpp:974
msgid "Layer name:"
msgstr "图层名:"
#: ../src/LevelEditor.cpp:989
msgid "Layer moving speed (1 speed = 0.8 block/s):"
msgstr "图层移动速度 (速度 1 = 0.8 格/秒):"
#: ../src/LevelEditor.cpp:1010
msgid "Speed of following camera:"
msgstr "摄像机跟随速度:"
#: ../src/LevelEditor.cpp:1062
msgid "Move to layer"
msgstr "移动到图层"
#: ../src/LevelEditor.cpp:1068
msgid "Enter the layer name (create new layer if necessary):"
msgstr "输入图层名称 (必要时创建新图层):"
#: ../src/LevelEditor.cpp:1132
msgid "Repeat mode"
msgstr "重复模式"
#: ../src/LevelEditor.cpp:1156
msgid "Custom scenery:"
msgstr "自定义风景:"
#: ../src/LevelEditor.cpp:1219
msgid "(Use the default appearance for this block)"
msgstr "(使用此方块的默认外观)"
#: ../src/LevelEditor.cpp:1464 ../src/LevelEditor.cpp:1704
#: ../src/LevelEditor.cpp:1716 ../src/LevelEditor.cpp:1750
-#: ../src/LevelEditor.cpp:4375
+#: ../src/LevelEditor.cpp:4376
msgid "Custom scenery block"
msgstr "自定义风景方块"
#: ../src/LevelEditor.cpp:1672
msgid "Toolbox"
msgstr "工具箱"
#: ../src/LevelEditor.cpp:1704
#, c-format
msgid "Resize %s"
msgstr "改变 %s 的大小"
#: ../src/LevelEditor.cpp:1704
#, c-format
msgid "Move %s"
msgstr "移动 %s"
#: ../src/LevelEditor.cpp:1708
#, c-format
msgid "Move %d objects"
msgstr "移动 %d 个对象"
#: ../src/LevelEditor.cpp:1716
#, c-format
msgid "Add %s"
msgstr "添加 %s"
#: ../src/LevelEditor.cpp:1716
#, c-format
msgid "Remove %s"
msgstr "移除 %s"
#: ../src/LevelEditor.cpp:1720
#, c-format
msgid "Add %d objects"
msgstr "添加 %d 个对象"
#: ../src/LevelEditor.cpp:1720
#, c-format
msgid "Remove %d objects"
msgstr "移除 %d 个对象"
#: ../src/LevelEditor.cpp:1726
#, c-format
msgid "Add path to %s"
msgstr "添加路径到 %s"
#: ../src/LevelEditor.cpp:1726
#, c-format
msgid "Remove a path point from %s"
msgstr "移除 %s 的一个路径点"
#: ../src/LevelEditor.cpp:1731
#, c-format
msgid "Remove all paths from %s"
msgstr "移除 %s 的所有路径"
#: ../src/LevelEditor.cpp:1736
#, c-format
msgid "Add link from %s to %s"
msgstr "添加从 %s 到 %s 的链接"
#: ../src/LevelEditor.cpp:1741
#, c-format
msgid "Remove all links from %s"
msgstr "移除 %s 的所有链接"
#: ../src/LevelEditor.cpp:1747
msgid "Modify the %2 property of %1"
msgstr "修改 %1 的 %2 属性"
#: ../src/LevelEditor.cpp:1795
#, c-format
msgid "Edit the script of %s"
msgstr "编辑 %s 的脚本"
#: ../src/LevelEditor.cpp:1797
msgid "Edit the script of level"
msgstr "编辑关卡脚本"
#: ../src/LevelEditor.cpp:2122 ../src/LevelEditor.cpp:2202
msgid "The level has unsaved changes."
msgstr "关卡有未保存的变更。"
#: ../src/LevelEditor.cpp:2126 ../src/LevelEditor.cpp:2204
msgid "Are you sure you want to quit?"
msgstr "你确定要退出吗?"
#: ../src/LevelEditor.cpp:2126 ../src/LevelEditor.cpp:2204
msgid "Quit prompt"
msgstr "退出提示"
-#: ../src/LevelEditor.cpp:2792 ../src/LevelEditor.cpp:2794
+#: ../src/LevelEditor.cpp:2773 ../src/LevelEditor.cpp:2775
#, c-format
msgid "Level \"%s\" saved"
msgstr "关卡“%s”已保存"
-#: ../src/LevelEditor.cpp:2792 ../src/LevelEditor.cpp:2794
+#: ../src/LevelEditor.cpp:2773 ../src/LevelEditor.cpp:2775
msgid "Saved"
msgstr "已保存"
-#: ../src/LevelEditor.cpp:2854 ../src/LevelEditSelect.cpp:206
+#: ../src/LevelEditor.cpp:2835 ../src/LevelEditSelect.cpp:207
msgid "Name:"
msgstr "名称:"
-#: ../src/LevelEditor.cpp:2861
+#: ../src/LevelEditor.cpp:2842
msgid "Theme:"
msgstr "主题:"
-#: ../src/LevelEditor.cpp:2868
+#: ../src/LevelEditor.cpp:2849
msgid "Examples: %DATA%/themes/classic"
msgstr "例子: %DATA%/themes/classic"
-#: ../src/LevelEditor.cpp:2870
+#: ../src/LevelEditor.cpp:2851
msgid "or %USER%/themes/Orange"
msgstr "或者 %USER%/themes/Orange"
-#: ../src/LevelEditor.cpp:2873
+#: ../src/LevelEditor.cpp:2854
msgid "Music:"
msgstr "音乐:"
-#: ../src/LevelEditor.cpp:2882
+#: ../src/LevelEditor.cpp:2863
msgid "Target time (s):"
msgstr "目标时间(秒):"
-#: ../src/LevelEditor.cpp:2898
+#: ../src/LevelEditor.cpp:2879
msgid "Target recordings:"
msgstr "目标记录数:"
-#: ../src/LevelEditor.cpp:2914
+#: ../src/LevelEditor.cpp:2895
msgid "Restart level editor is required"
msgstr "需要重新启动地图编辑器"
-#: ../src/LevelEditor.cpp:3660 ../src/LevelEditor.cpp:3699
-#: ../src/LevelEditor.cpp:3720
+#: ../src/LevelEditor.cpp:3655 ../src/LevelEditor.cpp:3694
+#: ../src/LevelEditor.cpp:3715
msgid "Please enter a layer name."
msgstr "请输入图层名称。"
-#: ../src/LevelEditor.cpp:3660 ../src/LevelEditor.cpp:3664
-#: ../src/LevelEditor.cpp:3699 ../src/LevelEditor.cpp:3703
-#: ../src/LevelEditor.cpp:3720 ../src/LevelEditor.cpp:3724
+#: ../src/LevelEditor.cpp:3655 ../src/LevelEditor.cpp:3659
+#: ../src/LevelEditor.cpp:3694 ../src/LevelEditor.cpp:3698
+#: ../src/LevelEditor.cpp:3715 ../src/LevelEditor.cpp:3719
+#: ../src/LevelEditSelect.cpp:727
msgid "Error"
msgstr "错误"
-#: ../src/LevelEditor.cpp:3664 ../src/LevelEditor.cpp:3703
+#: ../src/LevelEditor.cpp:3659 ../src/LevelEditor.cpp:3698
#, c-format
msgid "The layer '%s' already exists."
msgstr "图层 '%s' 已经存在。"
-#: ../src/LevelEditor.cpp:3724
+#: ../src/LevelEditor.cpp:3719
msgid "Source and destination layers are the same."
msgstr "源和目标图层相同。"
-#: ../src/LevelEditor.cpp:3741
+#: ../src/LevelEditor.cpp:3736
msgid "Scenery"
msgstr "风景"
-#: ../src/LevelEditor.cpp:4165 ../src/LevelEditor.cpp:4193
+#: ../src/LevelEditor.cpp:4166 ../src/LevelEditor.cpp:4194
#, c-format
msgid "Speed: %d = %0.2f block/s"
msgstr "速度: %d = %0.2f 格/秒"
-#: ../src/LevelEditor.cpp:4178
+#: ../src/LevelEditor.cpp:4179
msgid "Stop at this point"
msgstr "在此点停止"
-#: ../src/LevelEditor.cpp:4183
+#: ../src/LevelEditor.cpp:4184
#, c-format
msgid "Pause: %d = %0.3fs"
msgstr "暂停: %d = %0.3f 秒"
-#: ../src/LevelEditSelect.cpp:40 ../src/TitleMenu.cpp:45
+#: ../src/LevelEditSelect.cpp:41 ../src/TitleMenu.cpp:45
msgid "Map Editor"
msgstr "地图编辑器"
-#: ../src/LevelEditSelect.cpp:65
+#: ../src/LevelEditSelect.cpp:66
msgid "New Levelpack"
msgstr "新建关卡包"
-#: ../src/LevelEditSelect.cpp:70
+#: ../src/LevelEditSelect.cpp:71
msgid "Pack Properties"
msgstr "关卡包属性"
-#: ../src/LevelEditSelect.cpp:75
+#: ../src/LevelEditSelect.cpp:76
msgid "Remove Pack"
msgstr "删除关卡包"
-#: ../src/LevelEditSelect.cpp:80
+#: ../src/LevelEditSelect.cpp:81
msgid "Move Map"
msgstr "移动地图"
-#: ../src/LevelEditSelect.cpp:88
+#: ../src/LevelEditSelect.cpp:89
msgid "Remove Map"
msgstr "删除地图"
-#: ../src/LevelEditSelect.cpp:93
+#: ../src/LevelEditSelect.cpp:94
msgid "Edit Map"
msgstr "编辑地图"
-#: ../src/LevelEditSelect.cpp:203
+#: ../src/LevelEditSelect.cpp:204
msgid "Properties"
msgstr "属性"
-#: ../src/LevelEditSelect.cpp:215
+#: ../src/LevelEditSelect.cpp:216
msgid "Description:"
msgstr "描述:"
-#: ../src/LevelEditSelect.cpp:224
+#: ../src/LevelEditSelect.cpp:225
msgid "Congratulation text:"
msgstr "完成提示:"
-#: ../src/LevelEditSelect.cpp:233
+#: ../src/LevelEditSelect.cpp:234
msgid "Music list:"
msgstr "音乐列表:"
-#: ../src/LevelEditSelect.cpp:262 ../src/LevelEditSelect.cpp:473
+#: ../src/LevelEditSelect.cpp:263 ../src/LevelEditSelect.cpp:481
msgid "Add level"
msgstr "增加关卡"
-#: ../src/LevelEditSelect.cpp:265
+#: ../src/LevelEditSelect.cpp:266
msgid "File name:"
msgstr "文件名:"
-#: ../src/LevelEditSelect.cpp:290
+#: ../src/LevelEditSelect.cpp:291
msgid "Move level"
msgstr "移动关卡"
-#: ../src/LevelEditSelect.cpp:293
+#: ../src/LevelEditSelect.cpp:294
msgid "Level: "
msgstr "关卡: "
-#: ../src/LevelEditSelect.cpp:303
+#: ../src/LevelEditSelect.cpp:308
msgid "Before"
msgstr "之前"
-#: ../src/LevelEditSelect.cpp:304
+#: ../src/LevelEditSelect.cpp:309
msgid "After"
msgstr "之后"
-#: ../src/LevelEditSelect.cpp:532
+#: ../src/LevelEditSelect.cpp:540
#, c-format
msgid "Are you sure remove the level pack '%s'?"
msgstr "你确定要删除关卡包 '%s' 吗?"
-#: ../src/LevelEditSelect.cpp:532 ../src/LevelEditSelect.cpp:560
+#: ../src/LevelEditSelect.cpp:540 ../src/LevelEditSelect.cpp:568
msgid "Remove prompt"
msgstr "删除提示"
-#: ../src/LevelEditSelect.cpp:560
+#: ../src/LevelEditSelect.cpp:568
#, c-format
msgid "Are you sure remove the map '%s'?"
msgstr "你确定要删除关卡 '%s' 吗?"
-#: ../src/LevelEditSelect.cpp:681
+#: ../src/LevelEditSelect.cpp:689
msgid "No file name given for the new level."
msgstr "没有给新关卡指定文件名。"
-#: ../src/LevelEditSelect.cpp:681
+#: ../src/LevelEditSelect.cpp:689
msgid "Missing file name"
msgstr "文件名未指定"
-#: ../src/LevelEditSelect.cpp:772
+#: ../src/LevelEditSelect.cpp:727
+#, c-format
+msgid "The file %s already exists."
+msgstr "文件 %s 已经存在。"
+
+#: ../src/LevelEditSelect.cpp:780
msgid "The entered level number isn't valid!"
msgstr "输入的关卡编号无效!"
-#: ../src/LevelEditSelect.cpp:772
+#: ../src/LevelEditSelect.cpp:780
msgid "Illegal number"
msgstr "无效编号"
#: ../src/LevelInfoRender.cpp:19
msgid "Choose a level"
msgstr "选择一个关卡"
#: ../src/LevelInfoRender.cpp:20
msgid "Time:"
msgstr "时间:"
-#: ../src/LevelInfoRender.cpp:21 ../src/StatisticsScreen.cpp:260
+#: ../src/LevelInfoRender.cpp:21 ../src/StatisticsScreen.cpp:259
msgid "Recordings:"
msgstr "记录次数:"
#: ../src/LevelPlaySelect.cpp:41
msgid "Select Level"
msgstr "选择关卡"
# TRANSLATORS: Used for button which clear any level progress like unlocked levels and highscores.
# TRANSLATORS: Used for button which clear any level progress like unlocked
# levels and highscores.
#: ../src/OptionsMenu.cpp:66
msgid "Clear Progress"
msgstr "清除进度"
#: ../src/OptionsMenu.cpp:109
msgid "General"
msgstr "通用"
#: ../src/OptionsMenu.cpp:110
msgid "Controls"
msgstr "控制"
#: ../src/OptionsMenu.cpp:121
msgid "Music"
msgstr "音乐"
#: ../src/OptionsMenu.cpp:129
msgid "Sound"
msgstr "音效"
#: ../src/OptionsMenu.cpp:137
msgid "Resolution"
msgstr "分辨率"
#: ../src/OptionsMenu.cpp:177
msgid "Language"
msgstr "语言"
# TRANSLATORS: as detect user's language automatically
#: ../src/OptionsMenu.cpp:185
msgid "Auto-Detect"
msgstr "自动检测"
#: ../src/OptionsMenu.cpp:209
msgid "Theme"
msgstr "主题"
#: ../src/OptionsMenu.cpp:247
msgid "Internet proxy"
msgstr "网络代理"
#: ../src/OptionsMenu.cpp:256
msgid "Fullscreen"
msgstr "全屏幕"
#: ../src/OptionsMenu.cpp:261
msgid "Quick record"
msgstr "快速记录"
#: ../src/OptionsMenu.cpp:266
msgid "Internet"
msgstr "网络"
#: ../src/OptionsMenu.cpp:271
msgid "Fade transition"
msgstr "淡出过渡"
#: ../src/OptionsMenu.cpp:294
msgid "Save Changes"
msgstr "保存变更"
#: ../src/OptionsMenu.cpp:513
msgid "Do you really want to reset level progress?"
msgstr "你确定要清除游戏进度吗?"
#: ../src/OptionsMenu.cpp:513
msgid "Warning"
msgstr "警告"
#: ../src/StatisticsManager.cpp:386
msgid "New achievement:"
msgstr "新成就:"
#: ../src/StatisticsManager.cpp:394
#, c-format
msgid "Achieved on %s"
msgstr "在 %s 达成成就"
#: ../src/StatisticsManager.cpp:400
msgid "Unknown achievement"
msgstr "未知成就"
#: ../src/StatisticsManager.cpp:406
#, c-format
msgid "Achieved %1.0f%%"
msgstr "已达成 %1.0f%%"
#: ../src/StatisticsManager.cpp:410
msgid "Not achieved"
msgstr "未达成"
-#: ../src/StatisticsScreen.cpp:58 ../src/TitleMenu.cpp:55
+#: ../src/StatisticsScreen.cpp:57 ../src/TitleMenu.cpp:55
msgid "Achievements and Statistics"
msgstr "成就与统计信息"
-#: ../src/StatisticsScreen.cpp:167
+#: ../src/StatisticsScreen.cpp:166
msgid "Achievements"
msgstr "成就"
-#: ../src/StatisticsScreen.cpp:168
+#: ../src/StatisticsScreen.cpp:167
msgid "Statistics"
msgstr "统计信息"
-#: ../src/StatisticsScreen.cpp:235
+#: ../src/StatisticsScreen.cpp:234
msgid "Total"
msgstr "总计"
-#: ../src/StatisticsScreen.cpp:247
+#: ../src/StatisticsScreen.cpp:246
msgid "Traveling distance (m)"
msgstr "旅行距离(米)"
-#: ../src/StatisticsScreen.cpp:248
+#: ../src/StatisticsScreen.cpp:247
msgid "Jump times"
msgstr "跳跃次数"
-#: ../src/StatisticsScreen.cpp:249
+#: ../src/StatisticsScreen.cpp:248
msgid "Die times"
msgstr "死亡次数"
-#: ../src/StatisticsScreen.cpp:250
+#: ../src/StatisticsScreen.cpp:249
msgid "Squashed times"
msgstr "被夹次数"
-#: ../src/StatisticsScreen.cpp:261
+#: ../src/StatisticsScreen.cpp:260
msgid "Switch pulled times:"
msgstr "使用开关次数:"
-#: ../src/StatisticsScreen.cpp:262
+#: ../src/StatisticsScreen.cpp:261
msgid "Swap times:"
msgstr "交换次数:"
-#: ../src/StatisticsScreen.cpp:263
+#: ../src/StatisticsScreen.cpp:262
msgid "Save times:"
msgstr "保存游戏次数:"
-#: ../src/StatisticsScreen.cpp:264
+#: ../src/StatisticsScreen.cpp:263
msgid "Load times:"
msgstr "读取游戏次数:"
-#: ../src/StatisticsScreen.cpp:269
+#: ../src/StatisticsScreen.cpp:268
msgid "Completed levels:"
msgstr "完成关卡数:"
-#: ../src/StatisticsScreen.cpp:307
+#: ../src/StatisticsScreen.cpp:306
msgid "In-game time:"
msgstr "游戏用时:"
-#: ../src/StatisticsScreen.cpp:309
+#: ../src/StatisticsScreen.cpp:308
msgid "Level editing time:"
msgstr "地图编辑用时:"
-#: ../src/StatisticsScreen.cpp:311
+#: ../src/StatisticsScreen.cpp:310
msgid "Created levels:"
msgstr "创建的关卡:"
#: ../src/TitleMenu.cpp:44
msgid "Options"
msgstr "选项"
#: ../src/TitleMenu.cpp:47
msgid "Quit"
msgstr "退出"
#: ../src/TitleMenu.cpp:131
msgid "Enable internet in order to install addons."
msgstr "启用网络访问才能下载附加组件。"
#: ../src/TitleMenu.cpp:131
msgid "Internet disabled"
msgstr "网络已禁用"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Return"
msgstr "回车"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Escape"
msgstr "Escape"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Backspace"
msgstr "退格"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Tab"
msgstr "Tab"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Space"
msgstr "空格"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "CapsLock"
msgstr "CapsLock"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PrintScreen"
msgstr "PrintScreen"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "ScrollLock"
msgstr "ScrollLock"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Pause"
msgstr "Pause"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Insert"
msgstr "Insert"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Home"
msgstr "Home"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PageUp"
msgstr "PageUp"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Delete"
msgstr "Delete"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "End"
msgstr "End"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PageDown"
msgstr "PageDown"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right"
msgstr "右"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left"
msgstr "左"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Down"
msgstr "下"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Up"
msgstr "上"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Numlock"
msgstr "Numlock"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "SysReq"
msgstr "SysReq"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Ctrl"
msgstr "左 Ctrl"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Shift"
msgstr "左 Shift"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Alt"
msgstr "左 Alt"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left GUI"
msgstr "左 GUI"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Ctrl"
msgstr "右 Ctrl"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Shift"
msgstr "右 Shift"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Alt"
msgstr "右 Alt"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right GUI"
msgstr "右 GUI"
# TRANSLATORS: Filename is coming before this text
#~ msgid ""
#~ "%s already exists.\n"
#~ "Do you want to overwrite it?"
#~ msgstr ""
#~ "%s 已经存在。\n"
#~ "你是否想要覆盖它?"
#~ msgid "Overwrite Prompt"
#~ msgstr "文件覆盖提示"
#~ msgid "Can't open file %s."
#~ msgstr "不能打开文件 %s。"
#~ msgid "Save File"
#~ msgstr "保存文件"
#~ msgid "Load File"
#~ msgstr "打开文件"
#~ msgid "Search In"
#~ msgstr "在此搜索"
#~ msgid "File Name"
#~ msgstr "文件名"
#~ msgid "Stop"
#~ msgstr "停止"
#~ msgid "Rename scenery layer %s to %s"
#~ msgstr "将风景图层 %s 重命名为 %s"
#~ msgid "Rename layer"
#~ msgstr "重命名图层"
#~ msgid "Enter the new name for layer '%s':"
#~ msgstr "输入图层 '%s' 的新名称:"
# TRANSLATORS: name of a key
#~ msgid "Return"
#~ msgstr "回车"
# TRANSLATORS: name of a key
#~ msgid "Backspace"
#~ msgstr "退格"
# TRANSLATORS: name of a key
#~ msgid "Tab"
#~ msgstr "Tab"
# TRANSLATORS: name of a key
#~ msgid "Space"
#~ msgstr "空格"
# TRANSLATORS: name of a key
#~ msgid "CapsLock"
#~ msgstr "CapsLock"
# TRANSLATORS: name of a key
#~ msgid "PrintScreen"
#~ msgstr "PrintScreen"
# TRANSLATORS: name of a key
#~ msgid "ScrollLock"
#~ msgstr "ScrollLock"
# TRANSLATORS: name of a key
#~ msgid "Pause"
#~ msgstr "Pause"
# TRANSLATORS: name of a key
#~ msgid "Insert"
#~ msgstr "Insert"
# TRANSLATORS: name of a key
#~ msgid "Home"
#~ msgstr "Home"
# TRANSLATORS: name of a key
#~ msgid "PageUp"
#~ msgstr "PageUp"
# TRANSLATORS: name of a key
#~ msgid "End"
#~ msgstr "End"
# TRANSLATORS: name of a key
#~ msgid "PageDown"
#~ msgstr "PageDown"
# TRANSLATORS: name of a key
#~ msgid "Down"
#~ msgstr "下"
# TRANSLATORS: name of a key
#~ msgid "Up"
#~ msgstr "上"
# TRANSLATORS: name of a key
#~ msgid "Numlock"
#~ msgstr "Numlock"
# TRANSLATORS: name of a key
#~ msgid "SysReq"
#~ msgstr "SysReq"
# TRANSLATORS: name of a key
#~ msgid "Left Ctrl"
#~ msgstr "左 Ctrl"
# TRANSLATORS: name of a key
#~ msgid "Left Shift"
#~ msgstr "左 Shift"
# TRANSLATORS: name of a key
#~ msgid "Left Alt"
#~ msgstr "左 Alt"
# TRANSLATORS: name of a key
#~ msgid "Left GUI"
#~ msgstr "左 GUI"
# TRANSLATORS: name of a key
#~ msgid "Right Ctrl"
#~ msgstr "右 Ctrl"
# TRANSLATORS: name of a key
#~ msgid "Right Shift"
#~ msgstr "右 Shift"
# TRANSLATORS: name of a key
#~ msgid "Right Alt"
#~ msgstr "右 Alt"
# TRANSLATORS: name of a key
#~ msgid "Right GUI"
#~ msgstr "右 GUI"
# TRANSLATORS: name of a key
#~ msgid "backspace"
#~ msgstr "backspace"
# TRANSLATORS: name of a key
#~ msgid "tab"
#~ msgstr "tab"
# TRANSLATORS: name of a key
#~ msgid "clear"
#~ msgstr "clear"
# TRANSLATORS: name of a key
#~ msgid "return"
#~ msgstr "回车"
# TRANSLATORS: name of a key
#~ msgid "pause"
#~ msgstr "pause"
# TRANSLATORS: name of a key
#~ msgid "escape"
#~ msgstr "escape"
# TRANSLATORS: name of a key
#~ msgid "space"
#~ msgstr "空格"
# TRANSLATORS: name of a key
#~ msgid "delete"
#~ msgstr "delete"
# TRANSLATORS: name of a key
#~ msgid "enter"
#~ msgstr "enter"
# TRANSLATORS: name of a key
#~ msgid "equals"
#~ msgstr "equals"
# TRANSLATORS: name of a key
#~ msgid "up"
#~ msgstr "上"
# TRANSLATORS: name of a key
#~ msgid "down"
#~ msgstr "下"
# TRANSLATORS: name of a key
#~ msgid "right"
#~ msgstr "右"
# TRANSLATORS: name of a key
#~ msgid "left"
#~ msgstr "左"
# TRANSLATORS: name of a key
#~ msgid "insert"
#~ msgstr "insert"
# TRANSLATORS: name of a key
#~ msgid "home"
#~ msgstr "home"
# TRANSLATORS: name of a key
#~ msgid "end"
#~ msgstr "end"
# TRANSLATORS: name of a key
#~ msgid "page up"
#~ msgstr "page up"
# TRANSLATORS: name of a key
#~ msgid "page down"
#~ msgstr "page down"
# TRANSLATORS: name of a key
#~ msgid "numlock"
#~ msgstr "numlock"
# TRANSLATORS: name of a key
#~ msgid "caps lock"
#~ msgstr "caps lock"
# TRANSLATORS: name of a key
#~ msgid "scroll lock"
#~ msgstr "scroll lock"
# TRANSLATORS: name of a key
#~ msgid "right shift"
#~ msgstr "右 shift"
# TRANSLATORS: name of a key
#~ msgid "left shift"
#~ msgstr "左 shift"
# TRANSLATORS: name of a key
#~ msgid "right ctrl"
#~ msgstr "右 ctrl"
# TRANSLATORS: name of a key
#~ msgid "left ctrl"
#~ msgstr "左 ctrl"
# TRANSLATORS: name of a key
#~ msgid "right alt"
#~ msgstr "右 alt"
# TRANSLATORS: name of a key
#~ msgid "left alt"
#~ msgstr "左 alt"
# TRANSLATORS: name of a key
#~ msgid "right meta"
#~ msgstr "右 meta"
# TRANSLATORS: name of a key
#~ msgid "left meta"
#~ msgstr "左 meta"
# TRANSLATORS: name of a key
#~ msgid "left super"
#~ msgstr "左 super"
# TRANSLATORS: name of a key
#~ msgid "right super"
#~ msgstr "右 super"
# TRANSLATORS: name of a key
#~ msgid "alt gr"
#~ msgstr "alt gr"
# TRANSLATORS: name of a key
#~ msgid "compose"
#~ msgstr "compose"
# TRANSLATORS: name of a key
#~ msgid "help"
#~ msgstr "help"
# TRANSLATORS: name of a key
#~ msgid "print screen"
#~ msgstr "print screen"
# TRANSLATORS: name of a key
#~ msgid "sys req"
#~ msgstr "sys req"
# TRANSLATORS: name of a key
#~ msgid "break"
#~ msgstr "break"
# TRANSLATORS: name of a key
#~ msgid "menu"
#~ msgstr "menu"
# TRANSLATORS: name of a key
#~ msgid "power"
#~ msgstr "power"
# TRANSLATORS: name of a key
#~ msgid "euro"
#~ msgstr "euro"
# TRANSLATORS: name of a key
#~ msgid "undo"
#~ msgstr "undo"
#~ msgid "Level themes"
#~ msgstr "关卡主题"
diff --git a/src/Addons.cpp b/src/Addons.cpp
index a83fa63..73de3c3 100644
--- a/src/Addons.cpp
+++ b/src/Addons.cpp
@@ -1,1066 +1,1066 @@
/*
* Copyright (C) 2011-2013 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow 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.
*
* Me and My Shadow 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 Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Addons.h"
#include "GameState.h"
#include "Functions.h"
#include "FileManager.h"
#include "GUIObject.h"
#include "GUIOverlay.h"
#include "GUIScrollBar.h"
#include "GUITextArea.h"
#include "GUIListBox.h"
#include "POASerializer.h"
#include "LevelPackManager.h"
#include "InputManager.h"
#include "ThemeManager.h"
#include <string>
#include <sstream>
#include <iostream>
#include "libs/tinyformat/tinyformat.h"
#include <SDL.h>
#include <SDL_ttf.h>
using namespace std;
static const char* predefinedCategories[] = {
"levels", __("Levels"), __("Single level which usually contain demanding puzzles"),
"levelpacks", __("Levelpacks"), __("Collection of levels with the same author or style"),
"themes", __("Themes"), __("Give every block and background a new look and feel"),
NULL,
};
static std::map<std::string, std::string> categoryNameMap;
static std::map<std::string, std::string> categoryDescriptionMap;
Addons::Addons(SDL_Renderer &renderer, ImageManager &imageManager):selected(NULL){
//Render the title.
title = titleTextureFromText(renderer, _("Addons"), objThemes.getTextColor(false), SCREEN_WIDTH);
//Load placeholder addon icons and screenshot.
addonIcon["levels"] = imageManager.loadImage(getDataPath() + "/gfx/addon1.png");
addonIcon["levelpacks"] = imageManager.loadImage(getDataPath() + "/gfx/addon2.png");
addonIcon["themes"] = imageManager.loadImage(getDataPath() + "/gfx/addon3.png");
addonIcon[std::string()] = imageManager.loadImage(getDataPath() + "/gfx/addon0.png");
//Load predefined categories.
if (categoryNameMap.empty()) {
for (int i = 0; predefinedCategories[i]; i += 3) {
categoryNameMap[predefinedCategories[i]] = predefinedCategories[i + 1];
categoryDescriptionMap[predefinedCategories[i]] = predefinedCategories[i + 2];
}
}
screenshot=imageManager.loadTexture(getDataPath()+"/gfx/screenshot.png", renderer);
//Open the addons file in the user cache path for writing (downloading) to.
FILE* addon=fopen((getUserPath(USER_CACHE)+"addons").c_str(),"wb");
//Clear the GUI if any.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//Try to get(download) the addonsList.
if(getAddonsList(addon, renderer, imageManager)==false){
//It failed so we show the error message.
GUIObjectRoot=new GUIObject(imageManager,renderer,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
GUIObject* obj=new GUILabel(imageManager,renderer,90,96,200,32,_("Unable to initialize addon menu:"));
obj->name="lbl";
GUIObjectRoot->addChild(obj);
obj=new GUILabel(imageManager,renderer,120,130,200,32,error.c_str());
obj->name="lbl";
GUIObjectRoot->addChild(obj);
obj=new GUIButton(imageManager,renderer,90,550,200,32,_("Back"));
obj->name="cmdBack";
obj->eventCallback=this;
GUIObjectRoot->addChild(obj);
return;
}
//Now create the GUI.
createGUI(renderer, imageManager);
}
Addons::~Addons(){
//If the GUIObjectRoot exist delete it.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
void Addons::createGUI(SDL_Renderer& renderer, ImageManager& imageManager){
//Downloaded the addons file now we can create the GUI.
GUIObjectRoot=new GUIObject(imageManager,renderer,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//Create list of categories
categoryList = new GUISingleLineListBox(imageManager, renderer, (SCREEN_WIDTH - 500) / 2, 100, 500, 32);
categoryList->name="lstTabs";
//Loop through the categories and add them to the list.
//FIXME: Hack for easy detecting which categories there are.
{
set<string> categories;
for (const auto& a : addons) {
categories.insert(a.type);
}
for (const auto& c : categories) {
auto it = categoryNameMap.find(c);
categoryList->addItem(c, it == categoryNameMap.end() ? c.c_str() : _(it->second));
}
}
categoryList->value=0;
categoryList->eventCallback=this;
GUIObjectRoot->addChild(categoryList);
//category description
categoryDescription = new GUILabel(imageManager, renderer, 0, 136, SCREEN_WIDTH, 32, "", 0, true, true, GUIGravityCenter);
if (categoryList->value >= 0 && categoryList->value < (int)categoryList->item.size()) {
auto it = categoryDescriptionMap.find(categoryList->item[categoryList->value].first);
if (it != categoryDescriptionMap.end()) categoryDescription->caption = _(it->second);
}
GUIObjectRoot->addChild(categoryDescription);
//Create the list for the addons.
//By default levels will be selected.
list=new GUIListBox(imageManager,renderer,SCREEN_WIDTH*0.1,176,SCREEN_WIDTH*0.8,SCREEN_HEIGHT-228);
addonsToList(categoryList->getName(), renderer, imageManager);
list->name="lstAddons";
list->clickEvents=true;
list->eventCallback=this;
list->value=-1;
GUIObjectRoot->addChild(list);
type="levels";
//The back button.
GUIObject* obj=new GUIButton(imageManager,renderer,20,20,-1,32,_("Back"));
obj->name="cmdBack";
obj->eventCallback=this;
GUIObjectRoot->addChild(obj);
}
bool Addons::getAddonsList(FILE* file, SDL_Renderer& renderer, ImageManager& imageManager){
//First we download the file.
if(downloadFile(getSettings()->getValue("addon_url"),file)==false){
//NOTE: We keep the console output English so we put the string literal here twice.
cerr<<"ERROR: unable to download addons file!"<<endl;
error=_("ERROR: unable to download addons file!");
return false;
}
fclose(file);
//Load the downloaded file.
ifstream addonFile;
addonFile.open((getUserPath(USER_CACHE)+"addons").c_str());
if(!addonFile.good()) {
//NOTE: We keep the console output English so we put the string literal here twice.
cerr<<"ERROR: unable to load addon_list file!"<<endl;
/// TRANSLATORS: addon_list is the name of a file and should not be translated.
error=_("ERROR: unable to load addon_list file!");
return false;
}
//Parse the addonsfile.
TreeStorageNode obj;
{
POASerializer objSerializer;
if(!objSerializer.readNode(addonFile,&obj,true)){
//NOTE: We keep the console output English so we put the string literal here twice.
cerr<<"ERROR: Invalid file format of addons file!"<<endl;
error=_("ERROR: Invalid file format of addons file!");
return false;
}
}
//Check the addon version in the addons list.
int version=0;
if(!obj.attributes["version"].empty())
version=atoi(obj.attributes["version"][0].c_str());
if(version<MIN_VERSION || version>MAX_VERSION){
//NOTE: We keep the console output English so we put the string literal here twice.
cerr<<"ERROR: Addon list version is unsupported! (received: "<<version<<" supported:"<<MIN_VERSION<<"-"<<MAX_VERSION<<")"<<endl;
error=_("ERROR: Addon list version is unsupported!");
return false;
}
//Also load the installed_addons file.
ifstream iaddonFile;
iaddonFile.open((getUserPath(USER_CONFIG)+"installed_addons").c_str());
if(!iaddonFile) {
//The installed_addons file doesn't exist, so we create it.
ofstream iaddons;
iaddons.open((getUserPath(USER_CONFIG)+"installed_addons").c_str());
iaddons<<" "<<endl;
iaddons.close();
//Also load the installed_addons file.
iaddonFile.open((getUserPath(USER_CONFIG)+"installed_addons").c_str());
if(!iaddonFile) {
//NOTE: We keep the console output English so we put the string literal here twice.
cerr<<"ERROR: Unable to create the installed_addons file."<<endl;
/// TRANSLATORS: installed_addons is the name of a file and should not be translated.
error=_("ERROR: Unable to create the installed_addons file.");
return false;
}
}
//And parse the installed_addons file.
TreeStorageNode obj1;
{
POASerializer objSerializer;
if(!objSerializer.readNode(iaddonFile,&obj1,true)){
//NOTE: We keep the console output English so we put the string literal here twice.
cerr<<"ERROR: Invalid file format of the installed_addons!"<<endl;
error=_("ERROR: Invalid file format of the installed_addons!");
return false;
}
}
//Fill the vector.
fillAddonList(obj,obj1, renderer, imageManager);
//Close the files.
iaddonFile.close();
addonFile.close();
return true;
}
void Addons::fillAddonList(TreeStorageNode &objAddons, TreeStorageNode &objInstalledAddons,
SDL_Renderer& renderer, ImageManager& imageManager){
//Loop through the blocks of the addons file.
//These should contain the types levels, levelpacks, themes.
for(unsigned int i=0;i<objAddons.subNodes.size();i++){
TreeStorageNode* block=objAddons.subNodes[i];
if(block==NULL) continue;
//Check what kind of block it is, only category at the moment.
if(block->name=="category" && block->value.size()>0){
string type=block->value[0];
//Now loop the entries(subNodes) of the block.
for(unsigned int i=0;i<block->subNodes.size();i++){
TreeStorageNode* entry=block->subNodes[i];
if(entry==NULL) continue;
if(entry->name=="entry" && entry->value.size()==1){
//The entry is valid so create a new Addon.
Addon addon;
addon.icon=nullptr;
addon.screenshot=nullptr;
addon.type=type;
addon.name=entry->value[0];
addon.version = 0;
addon.installedVersion = 0;
if(!entry->attributes["file"].empty())
addon.file=entry->attributes["file"][0];
if(!entry->attributes["author"].empty())
addon.author=entry->attributes["author"][0];
if(!entry->attributes["description"].empty())
addon.description=entry->attributes["description"][0];
if(!entry->attributes["license"].empty())
addon.license=entry->attributes["license"][0];
if(!entry->attributes["website"].empty())
addon.website=entry->attributes["website"][0];
if(entry->attributes["icon"].size()>1){
//There are (at least) two values, the url to the icon and its md5sum used for caching.
addon.icon=loadCachedImage(
entry->attributes["icon"][0].c_str(),
entry->attributes["icon"][1].c_str(),
imageManager
);
}
if(entry->attributes["screenshot"].size()>1){
//There are (at least) two values, the url to the screenshot and its md5sum used for caching.
addon.screenshot=loadCachedTexture(
entry->attributes["screenshot"][0].c_str(),
entry->attributes["screenshot"][1].c_str(),
renderer,
imageManager
);
}
if(!entry->attributes["version"].empty())
addon.version=atoi(entry->attributes["version"][0].c_str());
addon.upToDate=false;
addon.installed=false;
//Check if the addon is already installed.
for(unsigned int i=0;i<objInstalledAddons.subNodes.size();i++){
TreeStorageNode* installed=objInstalledAddons.subNodes[i];
if(installed==NULL) continue;
if(installed->name=="entry" && installed->value.size()==3){
if(addon.type.compare(installed->value[0])==0 && addon.name.compare(installed->value[1])==0) {
addon.installed=true;
addon.installedVersion=atoi(installed->value[2].c_str());
if(addon.installedVersion>=addon.version) {
addon.upToDate=true;
}
//Read the dependencies and content from the file.
for(unsigned int j=0;j<installed->subNodes.size();j++){
if(installed->subNodes[j]->name=="content"){
TreeStorageNode* obj=installed->subNodes[j];
for(unsigned int k=0;k<obj->subNodes.size();k++){
if(obj->subNodes[k]->value.size()==1)
addon.content.push_back(pair<string,string>(obj->subNodes[k]->name,obj->subNodes[k]->value[0]));
}
}else if(installed->subNodes[j]->name=="dependencies"){
TreeStorageNode* obj=installed->subNodes[j];
for(unsigned int k=0;k<obj->subNodes.size();k++){
if(obj->subNodes[k]->value.size()==1)
addon.dependencies.push_back(pair<string,string>(obj->subNodes[k]->name,obj->subNodes[k]->value[0]));
}
}
}
}
}
}
//Finally put him in the list.
addons.push_back(addon);
}
}
}
}
}
void Addons::addonsToList(const std::string &type, SDL_Renderer& renderer, ImageManager&){
//Clear the list.
list->clearItems();
//Loop through the addons.
for(unsigned int i=0;i<addons.size();i++) {
//Make sure the addon is of the requested type.
if(addons[i].type!=type)
continue;
const Addon& addon=addons[i];
string entry=addon.name+" by "+addon.author;
if(addon.installed){
if(addon.upToDate){
entry+=" *";
}else{
entry+=" +";
}
}
SurfacePtr surf = createSurface(list->width,74);
//Check if there's an icon for the addon.
if(addon.icon){
applySurface(5, 5, addon.icon, surf.get(), NULL);
}else{
auto it = addonIcon.find(type);
if (it == addonIcon.end()) it = addonIcon.find(std::string());
assert(it != addonIcon.end());
applySurface(5, 5, it->second, surf.get(), NULL);
}
SDL_Surface* nameSurf=TTF_RenderUTF8_Blended(fontGUI,addon.name.c_str(),objThemes.getTextColor(true));
SDL_SetSurfaceAlphaMod(nameSurf,0xFF);
applySurface(74,-1,nameSurf,surf.get(),NULL);
SDL_FreeSurface(nameSurf);
/// TRANSLATORS: indicates the author of an addon.
string authorLine = tfm::format(_("by %s"),addon.author);
SDL_Surface* authorSurf=TTF_RenderUTF8_Blended(fontText,authorLine.c_str(),objThemes.getTextColor(true));
SDL_SetSurfaceAlphaMod(authorSurf,0xFF);
applySurface(74,43,authorSurf,surf.get(),NULL);
SDL_FreeSurface(authorSurf);
if(addon.installed){
if(addon.upToDate){
SDL_Surface* infoSurf=TTF_RenderUTF8_Blended(fontText,_("Installed"),objThemes.getTextColor(true));
SDL_SetSurfaceAlphaMod(infoSurf,0xFF);
applySurface(surf->w-infoSurf->w-32,(surf->h-infoSurf->h)/2,infoSurf,surf.get(),NULL);
SDL_FreeSurface(infoSurf);
}else{
SDL_Surface* infoSurf=TTF_RenderUTF8_Blended(fontText,_("Updatable"),objThemes.getTextColor(true));
SDL_SetSurfaceAlphaMod(infoSurf,0xFF);
applySurface(surf->w-infoSurf->w-32,(surf->h-infoSurf->h)/2,infoSurf,surf.get(),NULL);
SDL_FreeSurface(infoSurf);
}
}else{
SDL_Color c = objThemes.getTextColor(true);
c.r = c.r / 2 + 128;
c.g = c.g / 2 + 128;
c.b = c.b / 2 + 128;
SDL_Surface* infoSurf = TTF_RenderUTF8_Blended(fontText, _("Not installed"), c);
SDL_SetSurfaceAlphaMod(infoSurf,0xFF);
applySurface(surf->w-infoSurf->w-32,(surf->h-infoSurf->h)/2,infoSurf,surf.get(),NULL);
SDL_FreeSurface(infoSurf);
}
list->addItem(renderer,entry,textureFromSurface(renderer,std::move(surf)));
}
}
bool Addons::saveInstalledAddons(){
//Open the file.
ofstream iaddons;
iaddons.open((getUserPath(USER_CONFIG)+"installed_addons").c_str());
if(!iaddons) return false;
TreeStorageNode installed;
//Loop through all the addons.
vector<Addon>::iterator it;
for(it=addons.begin();it!=addons.end();++it){
//Check if the level is installed or not.
if(it->installed) {
TreeStorageNode *entry=new TreeStorageNode;
entry->name="entry";
entry->value.push_back(it->type);
entry->value.push_back(it->name);
char version[64];
sprintf(version,"%d",it->installedVersion);
entry->value.push_back(version);
//Now add a subNode for each content.
TreeStorageNode* content=new TreeStorageNode;
content->name="content";
for(unsigned int i=0;i<it->content.size();i++){
TreeStorageNode* contentEntry=new TreeStorageNode;
contentEntry->name=it->content[i].first;
contentEntry->value.push_back(it->content[i].second);
//Add the content node to the entry node.
content->subNodes.push_back(contentEntry);
}
entry->subNodes.push_back(content);
//Now add a sub node for the dependencies.
TreeStorageNode* deps=new TreeStorageNode;
deps->name="dependencies";
for(unsigned int i=0;i<it->dependencies.size();i++){
TreeStorageNode* depsEntry=new TreeStorageNode;
depsEntry->name=it->dependencies[i].first;
depsEntry->value.push_back(it->dependencies[i].second);
//Add the content node to the entry node.
deps->subNodes.push_back(depsEntry);
}
entry->subNodes.push_back(deps);
//And add the entry to the top node.
installed.subNodes.push_back(entry);
}
}
//And write away the file.
POASerializer objSerializer;
objSerializer.writeNode(&installed,iaddons,true,true);
return true;
}
SharedTexture Addons::loadCachedTexture(const char* url,const char* md5sum,
SDL_Renderer& renderer, ImageManager& imageManager){
//Check if the image is cached.
string imageFile=getUserPath(USER_CACHE)+"images/"+md5sum;
if(fileExists(imageFile.c_str())){
//It is, so load the image.
return imageManager.loadTexture(imageFile, renderer);
}else{
//Download the image.
FILE* file=fopen(imageFile.c_str(),"wb");
//Downloading failed.
if(!downloadFile(url,file)){
cerr<<"ERROR: Unable to download image from "<<url<<endl;
fclose(file);
return NULL;
}
fclose(file);
//Load the image.
return imageManager.loadTexture(imageFile, renderer);
}
}
SDL_Surface* Addons::loadCachedImage(const char* url, const char* md5sum,
ImageManager& imageManager){
//Check if the image is cached.
string imageFile = getUserPath(USER_CACHE) + "images/" + md5sum;
if (fileExists(imageFile.c_str())){
//It is, so load the image.
return imageManager.loadImage(imageFile);
} else{
//Download the image.
FILE* file = fopen(imageFile.c_str(), "wb");
//Downloading failed.
if (!downloadFile(url, file)){
cerr << "ERROR: Unable to download image from " << url << endl;
fclose(file);
return NULL;
}
fclose(file);
//Load the image.
return imageManager.loadImage(imageFile);
}
}
void Addons::handleEvents(ImageManager& imageManager, SDL_Renderer& renderer){
//Check if we should quit.
if(event.type==SDL_QUIT){
//Save the installed addons before exiting.
saveInstalledAddons();
setNextState(STATE_EXIT);
}
//Check if escape is pressed, if so return to the main menu.
if(inputMgr.isKeyDownEvent(INPUTMGR_ESCAPE)){
setNextState(STATE_MENU);
}
//Check horizontal movement
int value = categoryList->value;
if (inputMgr.isKeyDownEvent(INPUTMGR_RIGHT)){
isKeyboardOnly = true;
value++;
if (value >= (int)categoryList->item.size()) value = 0;
} else if (inputMgr.isKeyDownEvent(INPUTMGR_LEFT)){
isKeyboardOnly = true;
value--;
if (value < 0) value = categoryList->item.size() - 1;
}
if (value >= 0 && value < (int)categoryList->item.size()) {
if (categoryList->value != value) {
categoryList->value = value;
GUIEventCallback_OnEvent(imageManager, renderer, categoryList->name, categoryList, GUIEventChange);
return;
}
//Check vertical movement
if (inputMgr.isKeyDownEvent(INPUTMGR_UP)){
isKeyboardOnly = true;
list->value--;
if (list->value < 0) list->value = 0;
//FIXME: ad-hoc stupid code
list->scrollScrollbar(0xC0000000);
list->scrollScrollbar(list->value);
} else if (inputMgr.isKeyDownEvent(INPUTMGR_DOWN)){
isKeyboardOnly = true;
list->value++;
if (list->value >= (int)list->item.size()) list->value = list->item.size() - 1;
//FIXME: ad-hoc stupid code
list->scrollScrollbar(0xC0000000);
list->scrollScrollbar(list->value);
}
if (isKeyboardOnly && inputMgr.isKeyDownEvent(INPUTMGR_SELECT) && list->value >= 0 && list->value<(int)list->item.size()) {
GUIEventCallback_OnEvent(imageManager, renderer, list->name, list, GUIEventChange); // ???
GUIEventCallback_OnEvent(imageManager, renderer, list->name, list, GUIEventClick);
return;
}
}
}
void Addons::logic(ImageManager&, SDL_Renderer&){}
void Addons::render(ImageManager&, SDL_Renderer& renderer){
//Draw background.
objThemes.getBackground(true)->draw(renderer);
//Draw the title.
drawTitleTexture(SCREEN_WIDTH, *title, renderer);
}
void Addons::resize(ImageManager& imageManager, SDL_Renderer& renderer){
//Delete the gui (if any).
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//Now create a new one.
createGUI(renderer, imageManager);
}
void Addons::showAddon(ImageManager& imageManager, SDL_Renderer& renderer){
//Make sure an addon is selected.
if(!selected)
return;
//Skip next mouse up event since we're clicking a list box and showing a new window.
GUISkipNextMouseUpEvent = true;
//Create a root object.
GUIObject* root=new GUIFrame(imageManager,renderer,(SCREEN_WIDTH-600)/2,(SCREEN_HEIGHT-400)/2,600,400,selected->name.c_str());
//Create the 'by creator' label.
GUIObject* obj=new GUILabel(imageManager,renderer,0,50,600,50,tfm::format(_("by %s"),selected->author).c_str(),0,true,true,GUIGravityCenter);
root->addChild(obj);
//Create the description text.
std::string s = tfm::format(_("Version: %d\n"), selected->version);
if (selected->installed) {
s += tfm::format(_("Installed version: %d\n"), selected->installedVersion);
}
if (!selected->license.empty()) {
s += tfm::format(_("License: %s\n"), appendURLToLicense(selected->license));
}
if (!selected->website.empty()) {
s += tfm::format(_("Website: %s\n"), selected->website);
}
s += '\n';
if (selected->description.empty()) {
s += _("(No descriptions provided)");
} else {
s += selected->description;
}
GUITextArea* description=new GUITextArea(imageManager,renderer,10,100,370,200);
description->setString(renderer, s, true);
description->editable=false;
description->onResize();
description->extractHyperlinks();
root->addChild(description);
//Create the screenshot image. (If a screenshot is missing, we use the default screenshot.)
GUIImage* img=new GUIImage(imageManager,renderer,390,100,200,150,selected->screenshot?selected->screenshot:screenshot);
root->addChild(img);
GUIButton *cancelButton;
//Add buttons depending on the installed/update status.
if(selected->installed && !selected->upToDate){
GUIObject* bRemove=new GUIButton(imageManager,renderer,root->width*0.97,350,-1,32,_("Remove"),0,true,true,GUIGravityRight);
bRemove->name="cmdRemove";
bRemove->eventCallback=this;
root->addChild(bRemove);
//Create a back button.
cancelButton = new GUIButton(imageManager, renderer, root->width*0.03, 350, -1, 32, _("Back"), 0, true, true, GUIGravityLeft);
cancelButton->name = "cmdCloseOverlay";
cancelButton->eventCallback = this;
root->addChild(cancelButton);
//Update widget sizes.
root->render(renderer, 0,0,false);
//Create a nicely centered button.
obj = new GUIButton(imageManager, renderer,
(int)floor((cancelButton->left + cancelButton->width + bRemove->left - bRemove->width)*0.5), 350,
-1, 32, _("Update"), 0, true, true, GUIGravityCenter);
obj->name="cmdUpdate";
obj->eventCallback=this;
root->addChild(obj);
}else{
if(!selected->installed){
obj=new GUIButton(imageManager,renderer,root->width*0.9,350,-1,32,_("Install"),0,true,true,GUIGravityRight);
obj->name="cmdInstall";
obj->eventCallback=this;
root->addChild(obj);
}else if(selected->upToDate){
obj=new GUIButton(imageManager,renderer,root->width*0.9,350,-1,32,_("Remove"),0,true,true,GUIGravityRight);
obj->name="cmdRemove";
obj->eventCallback=this;
root->addChild(obj);
}
//Create a back button.
cancelButton = new GUIButton(imageManager, renderer, root->width*0.1, 350, -1, 32, _("Back"), 0, true, true, GUIGravityLeft);
cancelButton->name = "cmdCloseOverlay";
cancelButton->eventCallback = this;
root->addChild(cancelButton);
}
new AddonOverlay(renderer, root, cancelButton, description, TabFocus | ReturnControls);
}
void Addons::GUIEventCallback_OnEvent(ImageManager& imageManager, SDL_Renderer& renderer, std::string name,GUIObject* obj,int eventType){
if(name=="lstTabs"){
//Get the category type.
type=categoryList->getName();
//Get the description of current category.
auto it = categoryDescriptionMap.find(type);
if (it != categoryDescriptionMap.end()) categoryDescription->caption = _(it->second);
else categoryDescription->caption.clear();
//Get the list corresponding with the category and select the first entry.
addonsToList(type, renderer, imageManager);
list->value=-1;
//Call an event as if an entry in the addons listbox was clicked.
GUIEventCallback_OnEvent(imageManager, renderer, "lstAddons",list,GUIEventChange);
}else if(name=="lstAddons"){
//Check which type of event.
if(eventType==GUIEventChange){
//Get the addon struct that belongs to it.
Addon* addon=NULL;
//Make sure the addon list on screen isn't empty.
if (list->value >= 0 && list->value < (int)list->item.size()){
//Get the name of the (newly) selected entry.
string entry=list->getItem(list->value);
//Loop through the addons of the selected category.
for(unsigned int i=0;i<addons.size();i++){
//Make sure the addons are of the same type.
if(addons[i].type!=categoryList->getName())
continue;
string prefix=addons[i].name;
if(!entry.compare(0,prefix.size(),prefix)){
addon=&addons[i];
}
}
}
//Set the new addon as selected and unselect the list.
selected=addon;
if (!isKeyboardOnly) list->value = -1;
}else if(eventType==GUIEventClick){
//Make sure an addon is selected.
if(selected){
showAddon(imageManager,renderer);
}
}
}else if(name=="cmdBack"){
saveInstalledAddons();
setNextState(STATE_MENU);
}else if(name=="cmdCloseOverlay"){
//We can safely delete the GUIObjectRoot, since it's handled by the GUIOverlay.
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}else if(name=="cmdUpdate"){
//NOTE: This simply removes the addon and reinstalls it.
//The complete addon is downloaded either way so no need for checking what has been changed/added/removed/etc...
if(selected){
removeAddon(imageManager,renderer,selected);
installAddon(imageManager,renderer,selected);
}
addonsToList(categoryList->getName(), renderer, imageManager);
}else if(name=="cmdInstall"){
if(selected)
installAddon(imageManager,renderer,selected);
addonsToList(categoryList->getName(), renderer, imageManager);
}else if(name=="cmdRemove"){
//TODO: Check for dependencies.
//Loop through the addons to check if this addon is a dependency of another addon.
vector<Addon>::iterator it;
for(it=addons.begin();it!=addons.end();++it){
//Check if the addon has dependencies.
if(!it->dependencies.empty()){
vector<pair<string,string> >::iterator depIt;
for(depIt=it->dependencies.begin();depIt!=it->dependencies.end();++depIt){
if(depIt->first=="addon" && depIt->second==selected->name){
- msgBox(imageManager,renderer,"This addon can't be removed because it's needed by "+it->name,MsgBoxOKOnly,"Dependency");
+ msgBox(imageManager,renderer,tfm::format(_("This addon can't be removed because it's needed by %s."),it->name),MsgBoxOKOnly,_("Dependency"));
return;
}
}
}
}
if(selected)
removeAddon(imageManager,renderer,selected);
addonsToList(categoryList->getName(), renderer, imageManager);
}
//NOTE: In case of install/remove/update we can delete the GUIObjectRoot, since it's managed by the GUIOverlay.
if(name=="cmdUpdate" || name=="cmdInstall" || name=="cmdRemove"){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
void Addons::removeAddon(ImageManager& imageManager,SDL_Renderer& renderer, Addon* addon){
//To remove an addon we loop over the content vector in the structure.
//NOTE: This should contain all INSTALLED content, if something failed during installation it isn't added.
for(unsigned int i=0;i<addon->content.size();i++){
//Check the type of content.
if(addon->content[i].first=="file"){
string file=getUserPath(USER_DATA)+addon->content[i].second;
//Check if the file exists.
if(!fileExists(file.c_str())){
cerr<<"WARNING: File '"<<file<<"' appears to have been removed already."<<endl;
- msgBox(imageManager,renderer,"WARNING: File '"+file+"' appears to have been removed already.",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: File '%s' appears to have been removed already."),file),MsgBoxOKOnly,_("Addon error"));
continue;
}
//Remove the file.
if(!removeFile(file.c_str())){
cerr<<"ERROR: Unable to remove file '"<<file<<"'!"<<endl;
- msgBox(imageManager,renderer,"ERROR: Unable to remove file '"+file+"'!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("ERROR: Unable to remove file '%s'!"),file),MsgBoxOKOnly,_("Addon error"));
continue;
}
}else if(addon->content[i].first=="folder"){
string dir=getUserPath(USER_DATA)+addon->content[i].second;
//Check if the directory exists.
if(!dirExists(dir.c_str())){
cerr<<"WARNING: Directory '"<<dir<<"' appears to have been removed already."<<endl;
- msgBox(imageManager,renderer,"WARNING: Directory '"+dir+"' appears to have been removed already.",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Directory '%s' appears to have been removed already."),dir),MsgBoxOKOnly,_("Addon error"));
continue;
}
//Remove the directory.
if(!removeDirectory(dir.c_str())){
cerr<<"ERROR: Unable to remove directory '"<<dir<<"'!"<<endl;
- msgBox(imageManager,renderer,"ERROR: Unable to remove directory '"+dir+"'!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("ERROR: Unable to remove directory '%s'!"),dir),MsgBoxOKOnly,_("Addon error"));
continue;
}
}else if(addon->content[i].first=="level"){
string file=getUserPath(USER_DATA)+"levels/"+addon->content[i].second;
//Check if the level file exists.
if(!fileExists(file.c_str())){
cerr<<"WARNING: Level '"<<file<<"' appears to have been removed already."<<endl;
- msgBox(imageManager,renderer,"WARNING: Level '"+file+"' appears to have been removed already.",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Level '%s' appears to have been removed already."),file),MsgBoxOKOnly,_("Addon error"));
continue;
}
//Remove the level file.
if(!removeFile(file.c_str())){
cerr<<"ERROR: Unable to remove level '"<<file<<"'!"<<endl;
- msgBox(imageManager,renderer,"ERROR: Unable to remove level '"+file+"'!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("ERROR: Unable to remove level '%s'!"),file),MsgBoxOKOnly,_("Addon error"));
continue;
}
//Also remove the level from the Levels levelpack.
LevelPack* levelsPack=getLevelPackManager()->getLevelPack("Levels/");
for(int i=0;i<levelsPack->getLevelCount();i++){
if(levelsPack->getLevelFile(i)==file){
//Remove the level and break out of the loop.
levelsPack->removeLevel(i);
break;
}
}
}else if(addon->content[i].first=="levelpack"){
//FIXME: We assume no trailing slash since there mustn't be one for installing, bad :(
string dir=getUserPath(USER_DATA)+"levelpacks/"+addon->content[i].second+"/";
//Check if the directory exists.
if(!dirExists(dir.c_str())){
cerr<<"WARNING: Levelpack directory '"<<dir<<"' appears to have been removed already."<<endl;
- msgBox(imageManager,renderer,"WARNING: Levelpack directory '"+dir+"' appears to have been removed already.",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Levelpack directory '%s' appears to have been removed already."),dir),MsgBoxOKOnly,_("Addon error"));
continue;
}
//Remove the directory.
if(!removeDirectory(dir.c_str())){
cerr<<"ERROR: Unable to remove levelpack directory '"<<dir<<"'!"<<endl;
- msgBox(imageManager,renderer,"ERROR: Unable to remove levelpack directory '"+dir+"'!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("ERROR: Unable to remove levelpack directory '%s'!"),dir),MsgBoxOKOnly,_("Addon error"));
continue;
}
//Also remove the levelpack from the levelpackManager.
getLevelPackManager()->removeLevelPack(dir);
}
}
//Now that the content has been removed clear the content list itself.
addon->content.clear();
//And finally set the addon to not installed.
addon->installed=false;
addon->installedVersion=0;
//Also clear the 'offline' information.
addon->content.clear();
addon->dependencies.clear();
}
void Addons::installAddon(ImageManager& imageManager,SDL_Renderer& renderer, Addon* addon){
string tmpDir=getUserPath(USER_CACHE)+"tmp/";
string fileName=fileNameFromPath(addon->file,true);
//Download the selected addon to the tmp folder.
if(!downloadFile(addon->file,tmpDir)){
cerr<<"ERROR: Unable to download addon file "<<addon->file<<endl;
- msgBox(imageManager,renderer,"ERROR: Unable to download addon file "+addon->file,MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("ERROR: Unable to download addon file %s."),addon->file),MsgBoxOKOnly,_("Addon error"));
return;
}
//Now extract the addon.
if(!extractFile(tmpDir+fileName,tmpDir+"/addon/")){
cerr<<"ERROR: Unable to extract addon file "<<addon->file<<endl;
- msgBox(imageManager,renderer,"ERROR: Unable to extract addon file "+addon->file,MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("ERROR: Unable to extract addon file %s."),addon->file),MsgBoxOKOnly,_("Addon error"));
return;
}
ifstream metadata((tmpDir+"/addon/metadata").c_str());
if(!metadata){
cerr<<"ERROR: Addon is missing metadata!"<<endl;
- msgBox(imageManager,renderer,"ERROR: Addon is missing metadata!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,_("ERROR: Addon is missing metadata!"),MsgBoxOKOnly,_("Addon error"));
return;
}
//Read the metadata from the addon.
TreeStorageNode obj;
{
POASerializer objSerializer;
if(!objSerializer.readNode(metadata,&obj,true)){
//NOTE: We keep the console output English so we put the string literal here twice.
cerr<<"ERROR: Invalid file format for metadata file!"<<endl;
- msgBox(imageManager,renderer,"ERROR: Invalid file format for metadata file!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,_("ERROR: Invalid file format for metadata file!"),MsgBoxOKOnly,_("Addon error"));
return;
}
}
//Loop through the subNodes.
for(unsigned int i=0;i<obj.subNodes.size();i++){
//Check for the content subNode (there should only be one).
if(obj.subNodes[i]->name=="content"){
TreeStorageNode* obj1=obj.subNodes[i];
//Loop through the subNodes of that.
for(unsigned int j=0;j<obj1->subNodes.size();j++){
TreeStorageNode* obj2=obj1->subNodes[j];
//This code happens for all types of content.
string source=tmpDir+"addon/content/";
if(obj2->value.size()>0)
source+=obj2->value[0];
//The destination MUST be in the user data path.
string dest=getUserPath(USER_DATA);
if(obj2->value.size()>1)
dest+=obj2->value[1];
//Check what the content type is.
if(obj2->name=="file" && obj2->value.size()==2){
//Now copy the file.
if(fileExists(dest.c_str())){
cerr<<"WARNING: File '"<<dest<<"' already exists, addon may be broken or not working!"<<endl;
- msgBox(imageManager,renderer,"WARNING: File '"+dest+"' already exists, addon may be broken or not working!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: File '%s' already exists, addon may be broken or not working!"),dest),MsgBoxOKOnly,_("Addon error"));
continue;
}
if(!copyFile(source.c_str(),dest.c_str())){
cerr<<"WARNING: Unable to copy file '"<<source<<"' to '"<<dest<<"', addon may be broken or not working!"<<endl;
- msgBox(imageManager,renderer,"WARNING: Unable to copy file '"+source+"' to '"+dest+"', addon may be broken or not working!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Unable to copy file '%s' to '%s', addon may be broken or not working!"),source,dest),MsgBoxOKOnly,_("Addon error"));
continue;
}
//Add it to the content vector.
addon->content.push_back(pair<string,string>("file",obj2->value[1]));
}else if(obj2->name=="folder" && obj2->value.size()==2){
//The dest must NOT exist, otherwise it will fail.
if(dirExists(dest.c_str())){
cerr<<"WARNING: Destination directory '"<<dest<<"' already exists, addon may be broken or not working!"<<endl;
- msgBox(imageManager,renderer,"WARNING: Destination directory '"+dest+"' already exists, addon may be broken or not working!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Destination directory '%s' already exists, addon may be broken or not working!"),dest),MsgBoxOKOnly,_("Addon error"));
continue;
}
//FIXME: Copy the directory instead of renaming it, in case the same folder/parts of the folder are needed in different places.
if(!renameDirectory(source.c_str(),dest.c_str())){
cerr<<"WARNING: Unable to move directory '"<<source<<"' to '"<<dest<<"', addon may be broken or not working!"<<endl;
- msgBox(imageManager,renderer,"WARNING: Unable to move directory '"+source+"' to '"+dest+"', addon may be broken or not working!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Unable to move directory '%s' to '%s', addon may be broken or not working!"),source,dest),MsgBoxOKOnly,_("Addon error"));
continue;
}
//Add it to the content vector.
addon->content.push_back(pair<string,string>("folder",obj2->value[1]));
}else if(obj2->name=="level" && obj2->value.size()==1){
//The destination MUST be in the levels folder in the user data path.
dest+="levels/"+fileNameFromPath(source);
//Now copy the file.
if(fileExists(dest.c_str())){
cerr<<"WARNING: Level '"<<dest<<"' already exists, addon may be broken or not working!"<<endl;
- msgBox(imageManager,renderer,"WARNING: Level '"+dest+"' already exists, addon may be broken or not working!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Level '%s' already exists, addon may be broken or not working!"),dest),MsgBoxOKOnly,_("Addon error"));
continue;
}
if(!copyFile(source.c_str(),dest.c_str())){
cerr<<"WARNING: Unable to copy level '"<<source<<"' to '"<<dest<<"', addon may be broken or not working!"<<endl;
- msgBox(imageManager,renderer,"WARNING: Unable to copy level '"+source+"' to '"+dest+"', addon may be broken or not working!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Unable to copy level '%s' to '%s', addon may be broken or not working!"),source,dest),MsgBoxOKOnly,_("Addon error"));
continue;
}
//It's a level so add it to the Levels levelpack.
LevelPack* levelsPack=getLevelPackManager()->getLevelPack("Levels/");
if(levelsPack){
levelsPack->addLevel(dest);
levelsPack->setLocked(levelsPack->getLevelCount()-1);
}else{
cerr<<"ERROR: Unable to add level to Levels levelpack"<<endl;
}
addon->content.push_back(pair<string,string>("level",fileNameFromPath(source)));
}else if(obj2->name=="levelpack" && obj2->value.size()==1){
//TODO: Check if the source contains a trailing slash.
//The destination MUST be in the user data path.
dest+="levelpacks/"+fileNameFromPath(source);
//The dest must NOT exist, otherwise it will fail.
if(dirExists(dest.c_str())){
cerr<<"WARNING: Levelpack directory '"<<dest<<"' already exists, addon may be broken or not working!"<<endl;
- msgBox(imageManager,renderer,"WARNING: Levelpack directory '"+dest+"' already exists, addon may be broken or not working!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Levelpack directory '%s' already exists, addon may be broken or not working!"),dest),MsgBoxOKOnly,_("Addon error"));
continue;
}
//FIXME: Copy the directory instead of renaming it, in case the same folder/parts of the folder are needed in different places.
if(!renameDirectory(source.c_str(),dest.c_str())){
cerr<<"WARNING: Unable to move directory '"<<source<<"' to '"<<dest<<"', addon may be broken or not working!"<<endl;
- msgBox(imageManager,renderer,"WARNING: Unable to move directory '"+source+"' to '"+dest+"', addon may be broken or not working!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager,renderer,tfm::format(_("WARNING: Unable to move directory '%s' to '%s', addon may be broken or not working!"),source,dest),MsgBoxOKOnly,_("Addon error"));
continue;
}
//It's a levelpack so add it to the levelpack manager.
getLevelPackManager()->loadLevelPack(dest);
addon->content.push_back(pair<string,string>("levelpack",fileNameFromPath(source)));
}
}
}else if(obj.subNodes[i]->name=="dependencies"){
TreeStorageNode* obj1=obj.subNodes[i];
//Loop through the subNodes of that.
for(unsigned int j=0;j<obj1->subNodes.size();j++){
TreeStorageNode* obj2=obj1->subNodes[j];
if(obj2->name=="addon" && obj2->value.size()>0){
Addon* dep=NULL;
//Check if the requested addon can be found.
vector<Addon>::iterator it;
for(it=addons.begin();it!=addons.end();++it){
if(it->name==obj2->value[0]){
dep=&(*it);
break;
}
}
if(!dep){
cerr<<"ERROR: Addon requires another addon ("<<obj2->value[0]<<") which can't be found!"<<endl;
- msgBox(imageManager,renderer,"ERROR: Addon requires another addon ("+obj2->value[0]+") which can't be found!",MsgBoxOKOnly,"Addon error");
+ msgBox(imageManager, renderer, tfm::format(_("ERROR: Addon requires another addon (%s) which can't be found!"), obj2->value[0]), MsgBoxOKOnly, _("Addon error"));
continue;
}
//The addon has been found, try to install it.
//FIXME: Somehow prevent recursion, maybe max depth (??)
if(!dep->installed){
- msgBox(imageManager,renderer,"The addon "+dep->name+" is needed and will be installed now.",MsgBoxOKOnly,"Dependency");
+ msgBox(imageManager, renderer, tfm::format(_("The addon %s is needed and will be installed now."), dep->name), MsgBoxOKOnly, _("Dependency"));
installAddon(imageManager,renderer, dep);
}
//Add the dependency to the addon.
addon->dependencies.push_back(pair<string,string>("addon",dep->name));
}
}
}
}
//The addon is installed and up to date, but not necessarily flawless.
addon->installed=true;
addon->upToDate=true;
addon->installedVersion=addon->version;
}
diff --git a/src/LevelEditSelect.cpp b/src/LevelEditSelect.cpp
index baa34e3..0210151 100644
--- a/src/LevelEditSelect.cpp
+++ b/src/LevelEditSelect.cpp
@@ -1,823 +1,823 @@
/*
* Copyright (C) 2012-2013 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow 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.
*
* Me and My Shadow 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 Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LevelEditSelect.h"
#include "GameState.h"
#include "Functions.h"
#include "FileManager.h"
#include "Globals.h"
#include "GUIObject.h"
#include "GUIListBox.h"
#include "GUIScrollBar.h"
#include "GUISpinBox.h"
#include "InputManager.h"
#include "StatisticsManager.h"
#include "Game.h"
#include "GUIOverlay.h"
#include <algorithm>
#include <string>
#include <iostream>
#include "libs/tinyformat/tinyformat.h"
using namespace std;
LevelEditSelect::LevelEditSelect(ImageManager& imageManager, SDL_Renderer& renderer):LevelSelect(imageManager,renderer,_("Map Editor"),LevelPackManager::CUSTOM_PACKS){
//Create the gui.
createGUI(imageManager,renderer, true);
//Set the levelEditGUIObjectRoot.
levelEditGUIObjectRoot=GUIObjectRoot;
//show level list
changePack();
refresh(imageManager, renderer);
}
LevelEditSelect::~LevelEditSelect(){
selectedNumber=NULL;
}
void LevelEditSelect::createGUI(ImageManager& imageManager,SDL_Renderer &renderer, bool initial){
if(initial){
//The levelpack name text field.
levelpackName=new GUITextBox(imageManager,renderer,280,104,240,32);
levelpackName->eventCallback=this;
levelpackName->visible=false;
GUIObjectRoot->addChild(levelpackName);
//Create the six buttons at the bottom of the screen.
newPack = new GUIButton(imageManager, renderer, 0, 0, -1, 32, _("New Levelpack"));
newPack->name = "cmdNewLvlpack";
newPack->eventCallback = this;
GUIObjectRoot->addChild(newPack);
propertiesPack = new GUIButton(imageManager, renderer, 0, 0, -1, 32, _("Pack Properties"), 0, true, true, GUIGravityCenter);
propertiesPack->name = "cmdLvlpackProp";
propertiesPack->eventCallback = this;
GUIObjectRoot->addChild(propertiesPack);
removePack = new GUIButton(imageManager, renderer, 0, 0, -1, 32, _("Remove Pack"), 0, true, true, GUIGravityRight);
removePack->name = "cmdRmLvlpack";
removePack->eventCallback = this;
GUIObjectRoot->addChild(removePack);
move = new GUIButton(imageManager, renderer, 0, 0, -1, 32, _("Move Map"));
move->name = "cmdMoveMap";
move->eventCallback = this;
//NOTE: Set enabled equal to the inverse of initial.
//When resizing the window initial will be false and therefor the move button can stay enabled.
move->enabled = false;
GUIObjectRoot->addChild(move);
remove = new GUIButton(imageManager, renderer, 0, 0, -1, 32, _("Remove Map"), 0, false, true, GUIGravityCenter);
remove->name = "cmdRmMap";
remove->eventCallback = this;
GUIObjectRoot->addChild(remove);
edit = new GUIButton(imageManager, renderer, 0, 0, -1, 32, _("Edit Map"), 0, false, true, GUIGravityRight);
edit->name = "cmdEdit";
edit->eventCallback = this;
GUIObjectRoot->addChild(edit);
}
//Move buttons to default position
const int x1 = int(SCREEN_WIDTH*0.02), x2 = int(SCREEN_WIDTH*0.5), x3 = int(SCREEN_WIDTH*0.98);
const int y1 = SCREEN_HEIGHT - 120, y2 = SCREEN_HEIGHT - 60;
newPack->left = x1; newPack->top = y1; newPack->gravity = GUIGravityLeft;
propertiesPack->left = x2; propertiesPack->top = y1; propertiesPack->gravity = GUIGravityCenter;
removePack->left = x3; removePack->top = y1; removePack->gravity = GUIGravityRight;
move->left = x1; move->top = y2; move->gravity = GUIGravityLeft;
remove->left = x2; remove->top = y2; remove->gravity = GUIGravityCenter;
edit->left = x3; edit->top = y2; edit->gravity = GUIGravityRight;
isVertical = false;
//Reset the font size
newPack->smallFont = false; newPack->width = -1;
propertiesPack->smallFont = false; propertiesPack->width = -1;
removePack->smallFont = false; removePack->width = -1;
move->smallFont = false; move->width = -1;
remove->smallFont = false; remove->width = -1;
edit->smallFont = false; edit->width = -1;
//Now update widgets and then check if they overlap
GUIObjectRoot->render(renderer, 0, 0, false);
if (propertiesPack->left - propertiesPack->gravityX < newPack->left + newPack->width ||
propertiesPack->left - propertiesPack->gravityX + propertiesPack->width > removePack->left - removePack->gravityX)
{
newPack->smallFont = true; newPack->width = -1;
propertiesPack->smallFont = true; propertiesPack->width = -1;
removePack->smallFont = true; removePack->width = -1;
move->smallFont = true; move->width = -1;
remove->smallFont = true; remove->width = -1;
edit->smallFont = true; edit->width = -1;
}
// NOTE: the following code is necessary (e.g. for Germany)
//Check again
GUIObjectRoot->render(renderer, 0, 0, false);
if (propertiesPack->left - propertiesPack->gravityX < newPack->left + newPack->width ||
propertiesPack->left - propertiesPack->gravityX + propertiesPack->width > removePack->left - removePack->gravityX)
{
newPack->left = SCREEN_WIDTH*0.02;
newPack->top = SCREEN_HEIGHT - 140;
newPack->smallFont = false;
newPack->width = -1;
newPack->gravity = GUIGravityLeft;
propertiesPack->left = SCREEN_WIDTH*0.02;
propertiesPack->top = SCREEN_HEIGHT - 100;
propertiesPack->smallFont = false;
propertiesPack->width = -1;
propertiesPack->gravity = GUIGravityLeft;
removePack->left = SCREEN_WIDTH*0.02;
removePack->top = SCREEN_HEIGHT - 60;
removePack->smallFont = false;
removePack->width = -1;
removePack->gravity = GUIGravityLeft;
move->left = SCREEN_WIDTH*0.98;
move->top = SCREEN_HEIGHT - 140;
move->smallFont = false;
move->width = -1;
move->gravity = GUIGravityRight;
remove->left = SCREEN_WIDTH*0.98;
remove->top = SCREEN_HEIGHT - 100;
remove->smallFont = false;
remove->width = -1;
remove->gravity = GUIGravityRight;
edit->left = SCREEN_WIDTH*0.98;
edit->top = SCREEN_HEIGHT - 60;
edit->smallFont = false;
edit->width = -1;
edit->gravity = GUIGravityRight;
isVertical = true;
}
}
void LevelEditSelect::changePack(){
packName=levelpacks->item[levelpacks->value].second;
if(packName=="Custom Levels"){
//Disable some levelpack buttons.
propertiesPack->enabled=false;
removePack->enabled=false;
}else{
//Enable some levelpack buttons.
propertiesPack->enabled=true;
removePack->enabled=true;
}
//Set last levelpack.
getSettings()->setValue("lastlevelpack",levelpacks->getName());
//Now let levels point to the right pack.
levels=getLevelPackManager()->getLevelPack(levelpacks->getName());
//invalidate the tooltip
toolTip.number = -1;
}
void LevelEditSelect::packProperties(ImageManager& imageManager,SDL_Renderer& renderer, bool newPack){
//Open a message popup.
GUIObject* root=new GUIFrame(imageManager,renderer,(SCREEN_WIDTH-600)/2,(SCREEN_HEIGHT-390)/2,600,390,_("Properties"));
GUIObject* obj;
obj=new GUILabel(imageManager,renderer,40,50,240,36,_("Name:"));
root->addChild(obj);
obj=new GUITextBox(imageManager,renderer,60,80,480,36,packName.c_str());
if(newPack)
obj->caption="";
obj->name="LvlpackName";
root->addChild(obj);
obj=new GUILabel(imageManager,renderer,40,120,240,36,_("Description:"));
root->addChild(obj);
obj=new GUITextBox(imageManager,renderer,60,150,480,36,levels->levelpackDescription.c_str());
if(newPack)
obj->caption="";
obj->name="LvlpackDescription";
root->addChild(obj);
obj=new GUILabel(imageManager,renderer,40,190,240,36,_("Congratulation text:"));
root->addChild(obj);
obj=new GUITextBox(imageManager,renderer,60,220,480,36,levels->congratulationText.c_str());
if(newPack)
obj->caption="";
obj->name="LvlpackCongratulation";
root->addChild(obj);
obj = new GUILabel(imageManager, renderer, 40, 260, 240, 36, _("Music list:"));
root->addChild(obj);
obj = new GUITextBox(imageManager, renderer, 60, 290, 480, 36, levels->levelpackMusicList.c_str());
if (newPack)
obj->caption = "";
obj->name = "LvlpackMusic";
root->addChild(obj);
obj=new GUIButton(imageManager,renderer,root->width*0.3,390-44,-1,36,_("OK"),0,true,true,GUIGravityCenter);
obj->name="cfgOK";
obj->eventCallback=this;
root->addChild(obj);
GUIButton *cancelButton = new GUIButton(imageManager, renderer, root->width*0.7, 390 - 44, -1, 36, _("Cancel"), 0, true, true, GUIGravityCenter);
cancelButton->name = "cfgCancel";
cancelButton->eventCallback = this;
root->addChild(cancelButton);
//Create the gui overlay.
//NOTE: We don't need to store a pointer since it will auto cleanup itself.
new AddonOverlay(renderer, root, cancelButton, NULL, UpDownFocus | TabFocus | ReturnControls | LeftRightControls);
if(newPack){
packName.clear();
}
}
void LevelEditSelect::addLevel(ImageManager& imageManager,SDL_Renderer& renderer){
//Open a message popup.
GUIObject* root=new GUIFrame(imageManager,renderer,(SCREEN_WIDTH-600)/2,(SCREEN_HEIGHT-200)/2,600,200,_("Add level"));
GUIObject* obj;
obj=new GUILabel(imageManager,renderer,40,80,240,36,_("File name:"));
root->addChild(obj);
char s[64];
SDL_snprintf(s,64,"map%02d.map",levels->getLevelCount()+1);
obj=new GUITextBox(imageManager,renderer,300,80,240,36,s);
obj->name="LvlFile";
root->addChild(obj);
obj=new GUIButton(imageManager,renderer,root->width*0.3,200-44,-1,36,_("OK"),0,true,true,GUIGravityCenter);
obj->name="cfgAddOK";
obj->eventCallback=this;
root->addChild(obj);
GUIButton *cancelButton = new GUIButton(imageManager, renderer, root->width*0.7, 200 - 44, -1, 36, _("Cancel"), 0, true, true, GUIGravityCenter);
cancelButton->name = "cfgAddCancel";
cancelButton->eventCallback = this;
root->addChild(cancelButton);
//Dim the screen using the tempSurface.
//NOTE: We don't need to store a pointer since it will auto cleanup itself.
new AddonOverlay(renderer, root, cancelButton, NULL, UpDownFocus | TabFocus | ReturnControls | LeftRightControls);
}
void LevelEditSelect::moveLevel(ImageManager& imageManager,SDL_Renderer& renderer){
//Open a message popup.
GUIObject* root=new GUIFrame(imageManager,renderer,(SCREEN_WIDTH-600)/2,(SCREEN_HEIGHT-200)/2,600,200,_("Move level"));
GUIObject* obj;
obj=new GUILabel(imageManager,renderer,40,60,240,36,_("Level: "));
root->addChild(obj);
GUISpinBox *spinBox = new GUISpinBox(imageManager, renderer, 300, 60, 240, 36);
spinBox->caption = tfm::format("%d", selectedNumber->getNumber() + 1);
spinBox->format = "%1.0f";
spinBox->limitMin = 1.0f;
spinBox->limitMax = float(levels->getLevelCount());
spinBox->name = "MoveLevel";
root->addChild(spinBox);
obj=new GUISingleLineListBox(imageManager,renderer,root->width*0.5,110,240,36,true,true,GUIGravityCenter);
obj->name="lstPlacement";
vector<string> v;
v.push_back(_("Before"));
v.push_back(_("After"));
v.push_back(_("Swap"));
(dynamic_cast<GUISingleLineListBox*>(obj))->addItems(v);
obj->value=0;
root->addChild(obj);
obj=new GUIButton(imageManager,renderer,root->width*0.3,200-44,-1,36,_("OK"),0,true,true,GUIGravityCenter);
obj->name="cfgMoveOK";
obj->eventCallback=this;
root->addChild(obj);
GUIButton *cancelButton = new GUIButton(imageManager, renderer, root->width*0.7, 200 - 44, -1, 36, _("Cancel"), 0, true, true, GUIGravityCenter);
cancelButton->name = "cfgMoveCancel";
cancelButton->eventCallback = this;
root->addChild(cancelButton);
//Create the gui overlay.
//NOTE: We don't need to store a pointer since it will auto cleanup itself.
new AddonOverlay(renderer, root, cancelButton, NULL, TabFocus | ReturnControls | LeftRightControls);
}
void LevelEditSelect::refresh(ImageManager& imageManager, SDL_Renderer& renderer, bool change){
int m=levels->getLevelCount();
if(change){
numbers.clear();
//clear the selected level
if(selectedNumber!=NULL){
selectedNumber=NULL;
}
//Disable the level specific buttons.
move->enabled=false;
remove->enabled=false;
edit->enabled=false;
for(int n=0;n<=m;n++){
numbers.emplace_back(imageManager, renderer);
}
}
for(int n=0;n<m;n++){
SDL_Rect box={(n%LEVELS_PER_ROW)*64+80,(n/LEVELS_PER_ROW)*64+184,0,0};
numbers[n].init(renderer,n,box);
}
SDL_Rect box={(m%LEVELS_PER_ROW)*64+80,(m/LEVELS_PER_ROW)*64+184,0,0};
numbers[m].init(renderer,"+",box,m);
m++; //including the "+" button
if(m>LEVELS_DISPLAYED_IN_SCREEN){
levelScrollBar->maxValue=(m-LEVELS_DISPLAYED_IN_SCREEN+LEVELS_PER_ROW-1)/LEVELS_PER_ROW;
levelScrollBar->visible=true;
}else{
levelScrollBar->maxValue=0;
levelScrollBar->visible=false;
}
if(!levels->levelpackDescription.empty())
levelpackDescription->caption=_CC(levels->getDictionaryManager(),levels->levelpackDescription);
else
levelpackDescription->caption="";
//invalidate the tooltip
toolTip.number = -1;
}
void LevelEditSelect::selectNumber(ImageManager& imageManager, SDL_Renderer& renderer, unsigned int number, bool selected){
if (selected) {
if (number >= 0 && number < levels->getLevelCount()) {
levels->setCurrentLevel(number);
setNextState(STATE_LEVEL_EDITOR);
} else {
addLevel(imageManager, renderer);
}
}else{
move->enabled = false;
remove->enabled = false;
edit->enabled = false;
selectedNumber = NULL;
if (number == numbers.size() - 1){
if (isKeyboardOnly) {
selectedNumber = &numbers[number];
} else {
addLevel(imageManager, renderer);
}
} else if (number >= 0 && number < levels->getLevelCount()) {
selectedNumber=&numbers[number];
//Enable the level specific buttons.
//NOTE: We check if 'remove levelpack' is enabled, if not then it's the Levels levelpack.
if(removePack->enabled)
move->enabled=true;
remove->enabled=true;
edit->enabled=true;
}
}
}
void LevelEditSelect::handleEvents(ImageManager& imageManager, SDL_Renderer& renderer){
//Call handleEvents() of base class.
LevelSelect::handleEvents(imageManager, renderer);
if (section == 3) {
//Check focus movement
if (inputMgr.isKeyDownEvent(INPUTMGR_RIGHT)){
isKeyboardOnly = true;
section2 += isVertical ? 3 : 1;
} else if (inputMgr.isKeyDownEvent(INPUTMGR_LEFT)){
isKeyboardOnly = true;
section2 -= isVertical ? 3 : 1;
} else if (inputMgr.isKeyDownEvent(INPUTMGR_UP)){
isKeyboardOnly = true;
section2 -= isVertical ? 1 : 3;
} else if (inputMgr.isKeyDownEvent(INPUTMGR_DOWN)){
isKeyboardOnly = true;
section2 += isVertical ? 1 : 3;
}
if (section2 > 6) section2 -= 6;
else if (section2 < 1) section2 += 6;
//Check if enter is pressed
if (isKeyboardOnly && inputMgr.isKeyDownEvent(INPUTMGR_SELECT) && section2 >= 1 && section2 <= 6) {
GUIButton *buttons[6] = {
newPack, propertiesPack, removePack, move, remove, edit
};
GUIEventCallback_OnEvent(imageManager, renderer, buttons[section2 - 1]->name, buttons[section2 - 1], GUIEventClick);
}
}
}
void LevelEditSelect::render(ImageManager& imageManager,SDL_Renderer &renderer){
//Let the levelselect render.
LevelSelect::render(imageManager,renderer);
//Draw highlight in keyboard only mode.
if (isKeyboardOnly) {
GUIButton *buttons[6] = {
newPack, propertiesPack, removePack, move, remove, edit
};
for (int i = 0; i < 6; i++) {
buttons[i]->state = (section == 3 && section2 - 1 == i) ? 1 : 0;
}
}
}
void LevelEditSelect::resize(ImageManager& imageManager, SDL_Renderer &renderer){
//Let the levelselect resize.
LevelSelect::resize(imageManager, renderer);
//Create the GUI.
createGUI(imageManager,renderer, false);
//NOTE: This is a workaround for buttons failing when resizing.
if(packName=="Custom Levels"){
removePack->enabled=false;
propertiesPack->enabled=false;
}
if(selectedNumber)
selectNumber(imageManager, renderer, selectedNumber->getNumber(),false);
}
void LevelEditSelect::renderTooltip(SDL_Renderer& renderer,unsigned int number,int dy){
if (!toolTip.name || toolTip.number != number) {
SDL_Color fg = objThemes.getTextColor(true);
toolTip.number = number;
if (number < (unsigned int)levels->getLevelCount()){
//Render the name of the level.
toolTip.name = textureFromText(renderer, *fontText, _CC(levels->getDictionaryManager(), levels->getLevelName(number)), fg);
} else {
//Add level button
toolTip.name = textureFromText(renderer, *fontText, _("Add level"), fg);
}
}
//Check if name isn't null.
if(!toolTip.name)
return;
//Now draw a square the size of the three texts combined.
SDL_Rect r=numbers[number].box;
r.y-=dy*64;
const SDL_Rect nameSize = rectFromTexture(*toolTip.name);
r.w=nameSize.w;
r.h=nameSize.h;
//Make sure the tooltip doesn't go outside the window.
if(r.y>SCREEN_HEIGHT-200){
r.y-=nameSize.h+4;
}else{
r.y+=numbers[number].box.h+2;
}
if(r.x+r.w>SCREEN_WIDTH-50)
r.x=SCREEN_WIDTH-50-r.w;
//Draw a rectange
Uint32 color=0xFFFFFFFF;
drawGUIBox(r.x-5,r.y-5,r.w+10,r.h+10,renderer,color);
//Calc the position to draw.
SDL_Rect r2=r;
//Now we render the name if the surface isn't null.
if(toolTip.name){
//Draw the name.
applyTexture(r2.x, r2.y, toolTip.name, renderer);
}
}
void LevelEditSelect::GUIEventCallback_OnEvent(ImageManager& imageManager, SDL_Renderer& renderer, std::string name,GUIObject* obj,int eventType){
//NOTE: We check for the levelpack change to enable/disable some levelpack buttons.
if(name=="cmdLvlPack"){
//We call changepack and return to prevent the LevelSelect to undo what we did.
changePack();
refresh(imageManager, renderer);
return;
}
//Let the level select handle his GUI events.
LevelSelect::GUIEventCallback_OnEvent(imageManager,renderer,name,obj,eventType);
//Check for the edit button.
if(name=="cmdNewLvlpack"){
//Create a new pack.
packProperties(imageManager,renderer, true);
}else if(name=="cmdLvlpackProp"){
//Show the pack properties.
packProperties(imageManager,renderer, false);
}else if(name=="cmdRmLvlpack"){
//Show an "are you sure" message.
if(msgBox(imageManager,renderer,tfm::format(_("Are you sure remove the level pack '%s'?"),packName),MsgBoxYesNo,_("Remove prompt"))==MsgBoxYes){
//Remove the directory.
if(!removeDirectory(levels->levelpackPath.c_str())){
cerr<<"ERROR: Unable to remove levelpack directory "<<levels->levelpackPath<<endl;
}
//Remove it from the vector (levelpack list).
vector<pair<string,string> >::iterator it;
for(it=levelpacks->item.begin();it!=levelpacks->item.end();++it){
if(it->second==packName)
levelpacks->item.erase(it);
}
//Remove it from the levelpackManager.
getLevelPackManager()->removeLevelPack(levels->levelpackPath);
//And call changePack.
levelpacks->value=levelpacks->item.size()-1;
changePack();
refresh(imageManager, renderer);
}
}else if(name=="cmdMoveMap"){
if(selectedNumber!=NULL){
moveLevel(imageManager,renderer);
}
}else if(name=="cmdRmMap"){
if(selectedNumber!=NULL){
//Show an "are you sure" message.
if (msgBox(imageManager, renderer, tfm::format(_("Are you sure remove the map '%s'?"), levels->getLevel(selectedNumber->getNumber())->name), MsgBoxYesNo, _("Remove prompt")) != MsgBoxYes) {
return;
}
if(packName!="Custom Levels"){
if(!removeFile((levels->levelpackPath+"/"+levels->getLevel(selectedNumber->getNumber())->file).c_str())){
cerr<<"ERROR: Unable to remove level "<<(levels->levelpackPath+"/"+levels->getLevel(selectedNumber->getNumber())->file).c_str()<<endl;
}
levels->removeLevel(selectedNumber->getNumber());
levels->saveLevels(levels->levelpackPath+"/levels.lst");
}else{
//This is the levels levelpack so we just remove the file.
if(!removeFile(levels->getLevel(selectedNumber->getNumber())->file.c_str())){
cerr<<"ERROR: Unable to remove level "<<levels->getLevel(selectedNumber->getNumber())->file<<endl;
}
levels->removeLevel(selectedNumber->getNumber());
}
//And refresh the selection screen.
refresh(imageManager, renderer);
}
}else if(name=="cmdEdit"){
if(selectedNumber!=NULL){
levels->setCurrentLevel(selectedNumber->getNumber());
setNextState(STATE_LEVEL_EDITOR);
}
}
//Check for levelpack properties events.
if(name=="cfgOK"){
//Now loop throught the children of the GUIObjectRoot in search of the fields.
for(unsigned int i=0;i<GUIObjectRoot->childControls.size();i++){
if(GUIObjectRoot->childControls[i]->name=="LvlpackName"){
//Check if the name changed.
if(packName!=GUIObjectRoot->childControls[i]->caption){
//Delete the old one.
if(!packName.empty()){
if(!renameDirectory((getUserPath(USER_DATA)+"custom/levelpacks/"+packName).c_str(),(getUserPath(USER_DATA)+"custom/levelpacks/"+GUIObjectRoot->childControls[i]->caption).c_str())){
cerr<<"ERROR: Unable to move levelpack directory "<<(getUserPath(USER_DATA)+"custom/levelpacks/"+packName)<<" to "<<(getUserPath(USER_DATA)+"custom/levelpacks/"+GUIObjectRoot->childControls[i]->caption)<<endl;
}
//Remove the old one from the levelpack manager.
getLevelPackManager()->removeLevelPack(levelpacks->getName());
//And the levelpack list.
vector<pair<string,string> >::iterator it1;
for(it1=levelpacks->item.begin();it1!=levelpacks->item.end();++it1){
if(it1!=levelpacks->item.end()){
levelpacks->item.erase(it1);
break;
}
}
}else{
//It's a new levelpack so we need to change the levels array.
LevelPack* pack=new LevelPack;
levels=pack;
//Now create the dirs.
if(!createDirectory((getUserPath(USER_DATA)+"custom/levelpacks/"+GUIObjectRoot->childControls[i]->caption).c_str())){
cerr<<"ERROR: Unable to create levelpack directory "<<(getUserPath(USER_DATA)+"custom/levelpacks/"+GUIObjectRoot->childControls[i]->caption)<<endl;
}
if(!createFile((getUserPath(USER_DATA)+"custom/levelpacks/"+GUIObjectRoot->childControls[i]->caption+"/levels.lst").c_str())){
cerr<<"ERROR: Unable to create levelpack file "<<(getUserPath(USER_DATA)+"custom/levelpacks/"+GUIObjectRoot->childControls[i]->caption+"/levels.lst")<<endl;
}
}
//And set the new name.
packName=GUIObjectRoot->childControls[i]->caption;
levels->levelpackName=packName;
levels->levelpackPath=(getUserPath(USER_DATA)+"custom/levelpacks/"+packName+"/");
//Also add the levelpack location
getLevelPackManager()->addLevelPack(levels);
levelpacks->addItem(levels->levelpackPath,GUIObjectRoot->childControls[i]->caption);
levelpacks->value=levelpacks->item.size()-1;
//And call changePack.
changePack();
}
}
if(GUIObjectRoot->childControls[i]->name=="LvlpackDescription"){
levels->levelpackDescription=GUIObjectRoot->childControls[i]->caption;
}
if(GUIObjectRoot->childControls[i]->name=="LvlpackCongratulation"){
levels->congratulationText=GUIObjectRoot->childControls[i]->caption;
}
if (GUIObjectRoot->childControls[i]->name == "LvlpackMusic"){
levels->levelpackMusicList = GUIObjectRoot->childControls[i]->caption;
}
}
//Refresh the leveleditselect to show the correct information.
refresh(imageManager, renderer);
//Save the configuration.
levels->saveLevels(getUserPath(USER_DATA)+"custom/levelpacks/"+packName+"/levels.lst");
getSettings()->setValue("lastlevelpack",levels->levelpackPath);
//Clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}else if(name=="cfgCancel"){
//Check if packName is empty, if so it was a new levelpack and we need to revert to an existing one.
if(packName.empty()){
packName=levelpacks->item[levelpacks->value].second;
changePack();
}
//Clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
//Check for add level events.
if(name=="cfgAddOK"){
//Check if the file name isn't null.
//Now loop throught the children of the GUIObjectRoot in search of the fields.
for(unsigned int i=0;i<GUIObjectRoot->childControls.size();i++){
if(GUIObjectRoot->childControls[i]->name=="LvlFile"){
if(GUIObjectRoot->childControls[i]->caption.empty()){
msgBox(imageManager,renderer,_("No file name given for the new level."),MsgBoxOKOnly,_("Missing file name"));
return;
}else{
string tmp_caption = GUIObjectRoot->childControls[i]->caption;
//Replace all spaces with a underline.
size_t j;
for(;(j=tmp_caption.find(" "))!=string::npos;){
tmp_caption.replace(j,1,"_");
}
//If there isn't ".map" extension add it.
size_t found=tmp_caption.find_first_of(".");
if(found!=string::npos)
tmp_caption.replace(tmp_caption.begin()+found+1,tmp_caption.end(),"map");
else if (tmp_caption.substr(found+1)!="map")
tmp_caption.append(".map");
/* Create path and file in it */
string path=(levels->levelpackPath+"/"+tmp_caption);
if(packName=="Custom Levels"){
path=(getUserPath(USER_DATA)+"/custom/levels/"+tmp_caption);
}
//First check if the file doesn't exist already.
FILE* f;
f=fopen(path.c_str(),"rb");
//Check if it exists.
if(f){
//Close the file.
fclose(f);
//Let the currentState render once to prevent multiple GUI overlapping and prevent the screen from going black.
currentState->render(imageManager,renderer);
levelEditGUIObjectRoot->render(renderer);
//Notify the user.
- msgBox(imageManager,renderer,string("The file "+tmp_caption+" already exists."),MsgBoxOKOnly,"Error");
+ msgBox(imageManager, renderer, tfm::format(_("The file %s already exists."), tmp_caption), MsgBoxOKOnly, _("Error"));
return;
}
if(!createFile(path.c_str())){
cerr<<"ERROR: Unable to create level file "<<path<<endl;
}else{
//Update statistics.
statsMgr.newAchievement("create1");
if((++statsMgr.createdLevels)>=50) statsMgr.newAchievement("create50");
}
levels->addLevel(path);
//NOTE: Also add the level to the levels levelpack in case of custom levels.
if(packName=="Custom Levels"){
LevelPack* levelsPack=getLevelPackManager()->getLevelPack("Levels/");
if(levelsPack){
levelsPack->addLevel(path);
levelsPack->setLocked(levelsPack->getLevelCount()-1);
}else{
cerr<<"ERROR: Unable to add level to Levels levelpack"<<endl;
}
}
if(packName!="Custom Levels")
levels->saveLevels(getUserPath(USER_DATA)+"custom/levelpacks/"+packName+"/levels.lst");
refresh(imageManager, renderer);
//Clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
return;
}
}
}
}
}else if(name=="cfgAddCancel"){
//Clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
//Check for move level events.
if(name=="cfgMoveOK"){
//Check if the entered level number is valid.
//Now loop throught the children of the GUIObjectRoot in search of the fields.
int level=0;
int placement=0;
for(unsigned int i=0;i<GUIObjectRoot->childControls.size();i++){
if(GUIObjectRoot->childControls[i]->name=="MoveLevel"){
level=atoi(GUIObjectRoot->childControls[i]->caption.c_str());
if(level<=0 || level>levels->getLevelCount()){
msgBox(imageManager,renderer,_("The entered level number isn't valid!"),MsgBoxOKOnly,_("Illegal number"));
return;
}
}
if(GUIObjectRoot->childControls[i]->name=="lstPlacement"){
placement=GUIObjectRoot->childControls[i]->value;
}
}
//Now we execute the swap/move.
//Check for the place before.
if(placement==0){
//We place the selected level before the entered level.
levels->moveLevel(selectedNumber->getNumber(),level-1);
}else if(placement==1){
//We place the selected level after the entered level.
if(level<selectedNumber->getNumber())
levels->moveLevel(selectedNumber->getNumber(),level);
else
levels->moveLevel(selectedNumber->getNumber(),level+1);
}else if(placement==2){
//We swap the selected level with the entered level.
levels->swapLevel(selectedNumber->getNumber(),level-1);
}
//And save the change.
if(packName!="Custom Levels")
levels->saveLevels(getUserPath(USER_DATA)+"custom/levelpacks/"+packName+"/levels.lst");
refresh(imageManager, renderer);
//Clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}else if(name=="cfgMoveCancel"){
//Clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, May 16, 8:29 PM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
63829
Default Alt Text
(180 KB)

Event Timeline