Compare commits
1924 Commits
6.15
...
start-6.99
| Author | SHA1 | Date | |
|---|---|---|---|
| 366a09d708 | |||
| 3fe3df9f23 | |||
| e942545e39 | |||
| 9fe39eb8f3 | |||
| b1b17bd9cc | |||
| 1b34b59f5e | |||
| 719f06339c | |||
| 7abba42bca | |||
| c1120fc5b2 | |||
| 7d29b8968a | |||
| 994adf2ca5 | |||
| bd55020512 | |||
| b4f7d641b0 | |||
| 1197cff85b | |||
| 5e8fc44fb3 | |||
| 5df33b0f56 | |||
| fc9e826976 | |||
| e80d6f95a9 | |||
| 8815e5efb8 | |||
| 9874bc4dc3 | |||
| 82b597f62b | |||
| 4b35493447 | |||
| 69b203fbaa | |||
| 875a585e90 | |||
| 935d065712 | |||
| c0c44896a8 | |||
| b7a9266bf3 | |||
| 8bf5f05270 | |||
| 996d3c2fd6 | |||
| f68a4caec2 | |||
| f06e5861e7 | |||
| a93f4f1f76 | |||
| 572054c6e1 | |||
| bc3f659f4b | |||
| db63d0db4e | |||
| e7424e1140 | |||
| c345b6a84c | |||
| 5fd9bbe651 | |||
| d19b49d418 | |||
| f5103f4bf9 | |||
| dc5357c7f2 | |||
| 61f940a2f2 | |||
| b38d0edb2c | |||
| 36834b094d | |||
| cefdc342b6 | |||
| 1c409025e1 | |||
| 29cbac1c95 | |||
| 596cc4e6b6 | |||
| 19d52e85f1 | |||
| 75789bb8f2 | |||
| 55c00a86aa | |||
| 3f4f86f0fd | |||
| 81c3e0c28e | |||
| dc058298f7 | |||
| 4609a1139c | |||
| 9b5cb37b74 | |||
| ff0893155d | |||
| 127f46c1d9 | |||
| 2edea5b052 | |||
| a256ed1c1e | |||
| 54d8b5733c | |||
| d59e6d0d45 | |||
| 66d3fbd6b0 | |||
| f83f217385 | |||
| c0b6d2dd3e | |||
| 42e6d3f368 | |||
| 9e3d1db244 | |||
| 8f0d132104 | |||
| 3813f0dc26 | |||
| 1cb04cd09f | |||
| fa8d11a13c | |||
| c9c74ec020 | |||
| cccd957545 | |||
| 938a6f3fa8 | |||
| ad2763a460 | |||
| 779912dd80 | |||
| f058d56d0f | |||
| c081ad9f78 | |||
| bbd505b378 | |||
| 1382c299fb | |||
| 84429c3826 | |||
| 971e33aa97 | |||
| 9cf92c7f34 | |||
| 20ca7fb463 | |||
| 5834069ddf | |||
| ee2dc4aaea | |||
| 7057ce19a1 | |||
| a190738a24 | |||
| 60a9589a80 | |||
| 2ea6291b0d | |||
| 4bd9c96d9c | |||
| 46c1f8067c | |||
| 4deae69732 | |||
| ac09cb8363 | |||
| b397f4b235 | |||
| 389749b221 | |||
| 2da32702fe | |||
| f6b2161ac9 | |||
| 6343c2cd6b | |||
| 7960b6b7be | |||
| f9875d9bad | |||
| 72027f7f69 | |||
| da532392d9 | |||
| b1a392e171 | |||
| 252baf8f1e | |||
| 75d41125a1 | |||
| 76c7c2aa86 | |||
| 61466cf927 | |||
| 2befad5da1 | |||
| c1c046788b | |||
| 1af82edd66 | |||
| 6a9835ad43 | |||
| 5402d84831 | |||
| b30e7de686 | |||
| 312d64b361 | |||
| 8bfb4d9f00 | |||
| 7253663eff | |||
| df6e8db1f1 | |||
| 7bc51c30db | |||
| d2aa4adfe4 | |||
| f29df20878 | |||
| 57e935e1f4 | |||
| 88cb519b4d | |||
| 4a9becb351 | |||
| 0a4e788349 | |||
| ed9f598098 | |||
| 529bb95a43 | |||
| d8a945095e | |||
| 77b65c7778 | |||
| 2ed8af936c | |||
| 3ecf7cf565 | |||
| 0902ccd28b | |||
| 2a217bf064 | |||
| 3243f4c3ac | |||
| 4cf2921310 | |||
| 53fc982bba | |||
| 8a88c6d6f9 | |||
| 136e31ada7 | |||
| dfe32a1339 | |||
| bab6f8afc6 | |||
| c0ea8ebcf2 | |||
| 033fcbbeaf | |||
| a2398afaf1 | |||
| cacef7e71a | |||
| 54f9662bc0 | |||
| 0fea7ee77c | |||
| 1c71db539e | |||
| e8a0b8413d | |||
| e192814d02 | |||
| 066a6a6185 | |||
| 4034f87f26 | |||
| 3ee319ba9e | |||
| 4c094852e8 | |||
| a4aef8ceb1 | |||
| 5794e8b3b7 | |||
| 3ab4f62cf8 | |||
| 7f70d22344 | |||
| 4a7ca192e9 | |||
| 74fce0049c | |||
| 22397c225f | |||
| 8f80e828c7 | |||
| c901b4c1bd | |||
| 2f1455351d | |||
| 83c7eef6c8 | |||
| f29ab675ec | |||
| d4e1a1d1f3 | |||
| cede3f651d | |||
| 4ed0c8e313 | |||
| ba4c6d8b10 | |||
| 87f2975dd0 | |||
| 15717d87af | |||
| 59174e44fb | |||
| b6778f1a9e | |||
| e693038479 | |||
| f1cae21fdb | |||
| 33e557c04f | |||
| 32773f3832 | |||
| 32a6de49c9 | |||
| 64f6038b52 | |||
| 813ef90eb2 | |||
| 3ef409b4f2 | |||
| 34ad1df5b2 | |||
| 41afb8e5b2 | |||
| 15e0d57277 | |||
| 04ce5eaf09 | |||
| 130d92c5a2 | |||
| 504f2ff708 | |||
| 99f44f7eff | |||
| 0a95f50724 | |||
| 4da7ac8af7 | |||
| b8c6a62c8f | |||
| 8ecc3a200f | |||
| c8d45d3715 | |||
| 328e389f19 | |||
| 53d9a60544 | |||
| 7985a39a00 | |||
| 60ce7ca8c9 | |||
| e3ee421221 | |||
| d373cf93e6 | |||
| 2e3f6991a2 | |||
| e8d78b9deb | |||
| ca4eb8857d | |||
| 91cc4aa85a | |||
| 53328bf2a8 | |||
| 6d6cc7e6c0 | |||
| 411028297e | |||
| 7186ccc22e | |||
| 4b3b9dd3f1 | |||
| c619ee7ef2 | |||
| 49df5bed9c | |||
| b3e2801f38 | |||
| fa2292a811 | |||
| 3da77b1ce7 | |||
| b89e630e77 | |||
| 03701d8c39 | |||
| c4d41109a6 | |||
| 7ef976d637 | |||
| bdc7cf062e | |||
| d562fdba93 | |||
| 66acf402ec | |||
| b053705869 | |||
| 8c6060b2ba | |||
| 06f5ddffbf | |||
| 6b259960a1 | |||
| 4555020fee | |||
| 87d3b65f4b | |||
| 479eac2ebb | |||
| 5f80db6880 | |||
| d66a9f0bd7 | |||
| be42df7e09 | |||
| 05b1d38e8f | |||
| 6f377d8253 | |||
| dd02654228 | |||
| acc82e3030 | |||
| 84871c65c1 | |||
| a704363c54 | |||
| 86609614b8 | |||
| ace45f4ef0 | |||
| 2f114e59df | |||
| 43bed3a92b | |||
| 4b3c5ecbbc | |||
| d34ec5d0fd | |||
| b45d9f957b | |||
| 001a5f747c | |||
| 1d3e8e1ad7 | |||
| 2453eb2cbe | |||
| 4024f4f6bd | |||
| dbefae5855 | |||
| a147e41609 | |||
| 724f9d91aa | |||
| 8f9f42352b | |||
| 463d9cde79 | |||
| 92cae431f2 | |||
| 1f93fbfd0b | |||
| f8094c21b1 | |||
| 833cf20f56 | |||
| 581d30debb | |||
| 71d771d172 | |||
| d6745e7492 | |||
| 8a66bab786 | |||
| 20be450e1a | |||
| 4277d2b049 | |||
| 8ddf658543 | |||
| 3d3f437f57 | |||
| 99330bb1eb | |||
| eff11fec79 | |||
| af0784af3b | |||
| 4607b2db38 | |||
| acbaa4c9ba | |||
| b9d4a6f6f5 | |||
| d82ff5c7d6 | |||
| 569f6c0f95 | |||
| 1a5f693ccd | |||
| 92ed019e6c | |||
| ebbca682f7 | |||
| 33f2c0670d | |||
| 7f85657c0a | |||
| c24b99a0a6 | |||
| c2a2572aec | |||
| dd5796a59d | |||
| 280ef1c396 | |||
| a2a48e4603 | |||
| 52413479a6 | |||
| 919bbbca87 | |||
| 9c8a4e17f3 | |||
| cb359e8a45 | |||
| 20bfd1298f | |||
| 108ca1f981 | |||
| 8573bb76f9 | |||
| 1176d159af | |||
| f554e19a1a | |||
| be17f9cc6b | |||
| bdf788b5eb | |||
| 27cd90d6db | |||
| 60b8ee46a1 | |||
| 7e533fbb8f | |||
| 329ff9fc5c | |||
| 980104b35e | |||
| e51000c947 | |||
| ef69a69a3f | |||
| c4880e33f3 | |||
| 00d3da2040 | |||
| 895350ed4d | |||
| f97b59c414 | |||
| 62e85b728c | |||
| ead4e44d80 | |||
| 0b5a54f0f8 | |||
| 626981c349 | |||
| bed9699983 | |||
| dc97bdb194 | |||
| f6df843499 | |||
| 46ba33dde1 | |||
| 1a969be8fd | |||
| c8de62c682 | |||
| 4197f10d18 | |||
| c403d13119 | |||
| 9b4ec3206c | |||
| 61da5d93ec | |||
| 1486932b49 | |||
| 4e5199b6a1 | |||
| 2e8494a2c8 | |||
| f753db5862 | |||
| 18d4039aa1 | |||
| 1125cc4b32 | |||
| 137e71c461 | |||
| 027099daad | |||
| c6472da521 | |||
| aedd0273a4 | |||
| 6872f3db62 | |||
| 8311fafeb4 | |||
| 7cba90c0d0 | |||
| 36c9df4353 | |||
| 4705aa2b6f | |||
| 5ae2ae3075 | |||
| b45998fdec | |||
| 4c273f6a3b | |||
| 0098a41633 | |||
| 20b80bb706 | |||
| 3327378d4f | |||
| 7cc4820e96 | |||
| 725ba33062 | |||
| f85b13642b | |||
| 95dd481b3a | |||
| 479a13f5fc | |||
| 1fb9fe7bb8 | |||
| 3daae9b0f0 | |||
| 4fa044fbc0 | |||
| 2c676c2fc2 | |||
| d0ad2d924f | |||
| 02a1447837 | |||
| 2422e2c477 | |||
| 2ae0592486 | |||
| 56fc7f8603 | |||
| dbe1ccc29e | |||
| 02e2916a82 | |||
| 2e6a836e2d | |||
| 5f671d9990 | |||
| 4286cdca0e | |||
| 6793a176e0 | |||
| 4f790bdc11 | |||
| cc841c5f52 | |||
| 53d3039ee8 | |||
| f2d69c078e | |||
| ce76ab25f6 | |||
| a8c0cc096c | |||
| 60a6f6adfc | |||
| c471e3ff26 | |||
| 249ebb8b0c | |||
| 24de1990ce | |||
| 8cac7510ee | |||
| fae51e39bd | |||
| 4c94285195 | |||
| 0a6797340f | |||
| e3f2c70144 | |||
| 6c97478a81 | |||
| 738321cc4e | |||
| 2990efac7a | |||
| 31419d103b | |||
| 57b6d6124b | |||
| a01f3b8432 | |||
| 76477f103e | |||
| 394c19b9c2 | |||
| c159dcce30 | |||
| 50d8f356e2 | |||
| 366257119b | |||
| 64159e840b | |||
| 680131beb3 | |||
| 857a5a06b5 | |||
| 4dab5e849b | |||
| 925cd35947 | |||
| 17b77dcce2 | |||
| 96260b4ec8 | |||
| 16d361c714 | |||
| 738f93b156 | |||
| 23b03ea790 | |||
| 6a27c02a9b | |||
| d1f6132637 | |||
| c612db1551 | |||
| d5e8e70d7c | |||
| 724cae119b | |||
| 845d318a44 | |||
| 28ec3f2326 | |||
| f7e763f8a8 | |||
| 8e5c2a1532 | |||
| 077ae1b609 | |||
| 179301421c | |||
| 88439529e4 | |||
| 74b7cbe06c | |||
| 4d8144d320 | |||
| 251cfacb22 | |||
| b9a47a2bb8 | |||
| 9a06636789 | |||
| 413c2dee85 | |||
| a7000ffb14 | |||
| 76b7b471a4 | |||
| 97000fd87a | |||
| f639a201a6 | |||
| b63be138d5 | |||
| 55a45c54be | |||
| 2fc9c3d4c0 | |||
| ef9cffdbf6 | |||
| c3a87909ce | |||
| 3d553e31f0 | |||
| fa1d3b7e21 | |||
| e6dc0aa644 | |||
| 0994579c2a | |||
| 45e1854786 | |||
| 7897a9c369 | |||
| 7fa4517439 | |||
| 8a69b0c03f | |||
| 0a3ca8bc3a | |||
| ab4951d08c | |||
| c7de8a8b50 | |||
| 635ccdf130 | |||
| 246888c794 | |||
| 845d78df2e | |||
| a325ffff22 | |||
| 6372563998 | |||
| 91c46649e1 | |||
| 5f920b5b0a | |||
| 689d3acc63 | |||
| 6fe2f8afa2 | |||
| 776ea299c3 | |||
| 1580502949 | |||
| c092d687d7 | |||
| a5301ec50c | |||
| d0e01f5c9c | |||
| c717c42b13 | |||
| 65ed8f87b0 | |||
| 0f2b67745c | |||
| 30ce6b5033 | |||
| d6768da6c8 | |||
| 6c8e997cf2 | |||
| 62458fa036 | |||
| bcf47fd43a | |||
| 39b168eda9 | |||
| 80130db047 | |||
| 2942ddc53d | |||
| b127da3a41 | |||
| 0375b7cf1a | |||
| 294e6611ef | |||
| c03d1fddd1 | |||
| 59e3eecb92 | |||
| 0e11a964cc | |||
| 3744a729b3 | |||
| 9dafe56266 | |||
| a705f46018 | |||
| 1bf516bd79 | |||
| 533b22e9d8 | |||
| 94e1681802 | |||
| bee2a91d3d | |||
| 1c80515112 | |||
| 6eec5cd454 | |||
| 263a2d4c51 | |||
| 042a87b2ce | |||
| c823bef1c6 | |||
| c7e5856fdb | |||
| 1d3a8a0459 | |||
| 77ae9668b8 | |||
| a964d2fc9a | |||
| 27ecb992e9 | |||
| fd3c89c3ff | |||
| c7bae1eee8 | |||
| a45df6e964 | |||
| 905b0e0534 | |||
| bfeae69e5e | |||
| 1e0b224ccc | |||
| 1fc90fb3b5 | |||
| bebbc73210 | |||
| 9615971e2e | |||
| 55f8782da9 | |||
| 651da7e487 | |||
| 248793923a | |||
| 66e07d6e9b | |||
| 079d311228 | |||
| afb1da6248 | |||
| 72c1aa0f8d | |||
| b4b7fcfc26 | |||
| 372d8cb748 | |||
| 6ee38b1817 | |||
| ee24f4f96d | |||
| 16ae08345e | |||
| e651810ade | |||
| ec59eef066 | |||
| f8f147ad30 | |||
| d50c922c87 | |||
| d0bbf09783 | |||
| d69c59beca | |||
| b3a1571038 | |||
| d91f9ce376 | |||
| ee1295c98b | |||
| 94cc959880 | |||
| 1c7685550d | |||
| 37f5738b86 | |||
| bde2cf84f7 | |||
| e393d647f0 | |||
| 1d534a6162 | |||
| 0cbc06a241 | |||
| 911f179631 | |||
| 043a2c7213 | |||
| 87073bcd0b | |||
| 9e895e2575 | |||
| eec2d6e7d6 | |||
| 44a8128326 | |||
| 292e24b640 | |||
| a37c841d16 | |||
| 878bde34fc | |||
| 6e49ed1a15 | |||
| 2c6c97b27a | |||
| 143cb26ae3 | |||
| 2d1af033f8 | |||
| 1abb87e2a2 | |||
| a53eb8b3ce | |||
| 26ea3fb14e | |||
| 3232620a12 | |||
| 28fbf90342 | |||
| 8f7a2acba5 | |||
| f50726b5ce | |||
| 94d11b0e01 | |||
| 71ef71611b | |||
| 3da1b368e0 | |||
| 4fea47f3f2 | |||
| 00a92329dd | |||
| fe79eb948f | |||
| e85c0ade0f | |||
| 45c6eb156f | |||
| e45a935c7e | |||
| 094c07ce3c | |||
| 1d3a14bc99 | |||
| 7aa971a978 | |||
| d0b3ba90f2 | |||
| 45b8cb3051 | |||
| 4829a32c29 | |||
| e355c451e5 | |||
| 3301f8c87b | |||
| 13c4c97e59 | |||
| 6355e0d623 | |||
| 94f0ff71a1 | |||
| 3e966d308f | |||
| 2c49d5902d | |||
| 816d60eae0 | |||
| be258d878d | |||
| 92c4c68942 | |||
| fc25414deb | |||
| 137e8ba77d | |||
| 0a26eeaa7e | |||
| 9dec1f32ab | |||
| 499762aad4 | |||
| 6cac00a688 | |||
| 37d31a6f85 | |||
| 116d344519 | |||
| 6739a9a268 | |||
| 96058a9de3 | |||
| b6e71f20c2 | |||
| ebd9274776 | |||
| f3a52917cd | |||
| f24379aec6 | |||
| 49fa961502 | |||
| 3abba0c7e9 | |||
| ab00c6a876 | |||
| 769a65467a | |||
| 62c66b3794 | |||
| 19889c7457 | |||
| bc3ee8667c | |||
| d2c6f47299 | |||
| 16a4019a40 | |||
| ec37eb9a84 | |||
| 96d4440960 | |||
| 738f939f2e | |||
| cc4591848f | |||
| 57afa2ca46 | |||
| 7b3072983f | |||
| b1ae62b45f | |||
| dc80ec27e1 | |||
| 17ef16b3c3 | |||
| 7fdd823745 | |||
| 1cfba7a745 | |||
| 2942dd3390 | |||
| 3afa5e5944 | |||
| d7b463a445 | |||
| 123dd8d0c7 | |||
| 98d66242c4 | |||
| 205efcccdd | |||
| 23e7301b6d | |||
| 711f7bb608 | |||
| b4271b6b7b | |||
| d3b7a84bcd | |||
| 278eb7f522 | |||
| 6349eff9b7 | |||
| 2518af39ca | |||
| 85457996d4 | |||
| 73ca7320b4 | |||
| 8c3903cb04 | |||
| f02bf4e826 | |||
| f591a66dda | |||
| 5cde6f1eb4 | |||
| 24959e2e0a | |||
| 9d2858f558 | |||
| cdd045f30d | |||
| 80a0031ab5 | |||
| 9d01fe5d81 | |||
| 198e7aaa43 | |||
| 98d7e022fe | |||
| 9091a0fea0 | |||
| ad91211ca1 | |||
| 083e69f826 | |||
| 43124767b9 | |||
| 1cc4b21275 | |||
| 63cf67e078 | |||
| 32ff178ae7 | |||
| 6b48d71a1e | |||
| 77533e042f | |||
| 97ef93855e | |||
| 42e9b0f81a | |||
| bc213c48fd | |||
| ced53fe72a | |||
| df7eef44ce | |||
| c9f935d008 | |||
| 7937e7e103 | |||
| 0b8045f7b6 | |||
| bc8ca388af | |||
| 101b0c62d1 | |||
| ab70f0f11b | |||
| cfd3331ede | |||
| db8dc43ab9 | |||
| 9b571dc8ce | |||
| 2a3e691305 | |||
| 0ba7f0011a | |||
| f8d051f2cd | |||
| 1f877be8a3 | |||
| 4ebde6fc38 | |||
| e53c1673dc | |||
| c745bc47e3 | |||
| c601a0ff2b | |||
| 681efdf8fa | |||
| 4d8859ec79 | |||
| a3cbf14ede | |||
| 4f13cb73b0 | |||
| 61a37f225c | |||
| 379b340210 | |||
| 5f3dba9725 | |||
| f16cc57d52 | |||
| 61cbc9e6c7 | |||
| 5867d4f7ac | |||
| cc92d83fd6 | |||
| 298e4ae2de | |||
| 436f4f2c8b | |||
| 4af52c43a4 | |||
| 984448ae4f | |||
| 7cae393d72 | |||
| 667676f55b | |||
| 2ff748c5e1 | |||
| 65513fb8d7 | |||
| 992d9ca419 | |||
| bc02b71c76 | |||
| 01cccefcc1 | |||
| c2e71a4b31 | |||
| f86b91f29a | |||
| 7836e58608 | |||
| eddab9a802 | |||
| f6fa2d391f | |||
| e119633cc6 | |||
| aa9a2461cc | |||
| 71555a229e | |||
| 3b009de99c | |||
| 92b00df7af | |||
| bbf671555f | |||
| 929a1e916e | |||
| e6e2761396 | |||
| 1412429d23 | |||
| 6210907701 | |||
| d8c2d743bd | |||
| 5181b90473 | |||
| ed5b914c12 | |||
| 9e9611be7d | |||
| 967abe7bd2 | |||
| 0c3ce7955c | |||
| 7c1a7465d5 | |||
| ef894d3040 | |||
| 8c823cc638 | |||
| 0920d32457 | |||
| 5c4650bce1 | |||
| 65f3e0cef9 | |||
| 0835958d92 | |||
| 4aae1808ed | |||
| dd4d3410a6 | |||
| 0212094b9d | |||
| 1b69f5930c | |||
| 1be159692b | |||
| be0c6e6262 | |||
| 0e7e9ccced | |||
| 06d9557e4d | |||
| dd150047a6 | |||
| 838c8862a5 | |||
| de5c0a8d9c | |||
| 362759fdfb | |||
| aed9864f26 | |||
| 378d0cab7b | |||
| 11107dcbdd | |||
| bb711f187e | |||
| ecd1ccf0e7 | |||
| d89d4f4f94 | |||
| cd2029e759 | |||
| c50e91e970 | |||
| d7482744e8 | |||
| 7cc5cfcbae | |||
| 918158fcae | |||
| 23e2f4f0a8 | |||
| 25a6ec4ce6 | |||
| 96351b039c | |||
| bcfc7d1d89 | |||
| e33bb7a3ae | |||
| 924da674c6 | |||
| 8e58ce8617 | |||
| 6274355089 | |||
| 13d74b8d56 | |||
| 8f1ec59948 | |||
| fccef8c639 | |||
| 0c04e5e861 | |||
| 6f328c8984 | |||
| 61d2ad2202 | |||
| 93acff591f | |||
| 314446cffd | |||
| e5186a7d63 | |||
| aaba96b31e | |||
| ca1f9855fa | |||
| 3c6eb040f8 | |||
| 856a99c3f2 | |||
| 959434f404 | |||
| 435ef3f5b6 | |||
| e5d39cf4de | |||
| c03fa98992 | |||
| 195d3eb8e2 | |||
| f6a2e7ed1f | |||
| cb3bc2341f | |||
| dcc38c3ab6 | |||
| d37188abfe | |||
| b97ec70769 | |||
| aaec19d784 | |||
| c44ef66bcb | |||
| 104e46bb45 | |||
| 4da70a637c | |||
| e10325aa7d | |||
| c0f4395a53 | |||
| fd6f59e39a | |||
| de69ac7843 | |||
| a6174993d1 | |||
| d263552a79 | |||
| e67f671fe6 | |||
| bee097f3cd | |||
| 61c2fc4e49 | |||
| 6f7398e4ae | |||
| 5f1e49978b | |||
| 564a82c187 | |||
| ea2243ea86 | |||
| 4be828ede3 | |||
| 88e14a14d8 | |||
| b583d53f61 | |||
| fa79703f09 | |||
| e122d22ef8 | |||
| 34c070d37b | |||
| b9c5f2f988 | |||
| adb4ab80db | |||
| b55e36853e | |||
| 46c547a9b0 | |||
| 6c753a4a09 | |||
| 88417761ee | |||
| 5bff9be02c | |||
| de4c50bb2a | |||
| 5895fbcced | |||
| 5fc7f32b5a | |||
| a30500d665 | |||
| 9cd9e126a2 | |||
| 6d7da4f882 | |||
| bffa96a344 | |||
| 393df20e44 | |||
| 6acf2605bb | |||
| bd1524c362 | |||
| d9db6cc96a | |||
| 1f004edc6a | |||
| d6b9ea81de | |||
| d869f67126 | |||
| 92630baa6e | |||
| e8adc17543 | |||
| d72a03aeb4 | |||
| f5e75a7c4c | |||
| 2aa92d02d3 | |||
| b04e511767 | |||
| 34616cdbd3 | |||
| dfccf93175 | |||
| 34a62d74b5 | |||
| 41c48a5941 | |||
| c4f2d2894b | |||
| fc77c0e0ec | |||
| 99fa4e9c15 | |||
| 913a1078df | |||
| ed5e38727c | |||
| 28a5d5fcf2 | |||
| a96e9614c4 | |||
| 598d4faea0 | |||
| 3776ec0ef7 | |||
| 8a2546a83c | |||
| 566cb0f1cf | |||
| 6fee9e81e9 | |||
| 5ef6952c95 | |||
| 366306b8cc | |||
| 7d74ff010c | |||
| bb2a80f5e8 | |||
| 0c31f22fb4 | |||
| fb74356541 | |||
| ee18baed5e | |||
| 9f8b327aa8 | |||
| ba34df1a2e | |||
| 35584ebcba | |||
| dedc3af9d4 | |||
| 57652ce002 | |||
| 1f4f5e5030 | |||
| 0a6a43e139 | |||
| f930a2addb | |||
| 77f3ba0198 | |||
| 7dd98cd421 | |||
| 3ebf9d4b28 | |||
| eefc1412fa | |||
| a0f38b9442 | |||
| 123e96b872 | |||
| 14672d6f9b | |||
| ccc950a703 | |||
| aee59b6a05 | |||
| 1a5345f089 | |||
| 6ee705dd21 | |||
| fe197216b9 | |||
| 462730fcae | |||
| 972da30f8c | |||
| 5f07ce8c32 | |||
| 1940c98e67 | |||
| c1f8a23f17 | |||
| 7da459ae63 | |||
| 9125823bc9 | |||
| 188a0bac0a | |||
| 7d33f1663c | |||
| d3c075e11f | |||
| 2c984ed8f5 | |||
| 7f3563bcb0 | |||
| a6ab0e84e6 | |||
| d40dc4acc6 | |||
| d9d8eb4175 | |||
| 18df24da42 | |||
| 99f4b021d3 | |||
| 19bc668e0a | |||
| fe0a6a8e47 | |||
| d8c51b32b2 | |||
| 92b1a67e4a | |||
| 5a41588969 | |||
| 749236868a | |||
| c741f0cded | |||
| 638ecbbd2a | |||
| 697664de8f | |||
| b66379b203 | |||
| 92492d1198 | |||
| a325ea8bff | |||
| 4b3627a1e3 | |||
| 44ea36b475 | |||
| 1348a53fa8 | |||
| c34c8ebd3c | |||
| e2650d11dd | |||
| a73abc82e3 | |||
| d08933ce88 | |||
| 09ca171e81 | |||
| 7affd8cfbb | |||
| 73763275fb | |||
| 9d93ef10b5 | |||
| 6fd7fd89e5 | |||
| 3fa1dbe10e | |||
| f52735ef53 | |||
| 50988a167b | |||
| 60232028c2 | |||
| f1384edaf5 | |||
| bed8233afe | |||
| a1fd8c6d1c | |||
| 8868d6c99a | |||
| 293b191739 | |||
| ce4ebffd69 | |||
| b08a0daa10 | |||
| 3bd0557948 | |||
| 5ceb663fb3 | |||
| 8c684678c9 | |||
| 8749f3d178 | |||
| a001313516 | |||
| 4fc8554384 | |||
| 91f0b8452a | |||
| d1d71b8065 | |||
| 96929bce42 | |||
| 3c38654a8b | |||
| baeb458879 | |||
| 7ecb7a36a0 | |||
| a688687736 | |||
| 32c904935b | |||
| 1484505bd4 | |||
| cba6a15dda | |||
| c4cc830b7a | |||
| e83ec927de | |||
| caa9ebc25c | |||
| 9175fad5c1 | |||
| 13d8861459 | |||
| 7e7525e3d3 | |||
| 6e789307ef | |||
| ec8308b82c | |||
| f5efeec320 | |||
| 649fda046c | |||
| dcd829931c | |||
| d63f5ba134 | |||
| 647c1a026b | |||
| 3ea8d6a368 | |||
| 625a6afb1f | |||
| 9d8ccec0ee | |||
| 32554bf5e6 | |||
| a03c4d6f39 | |||
| eeefba5a45 | |||
| 22d87d62d6 | |||
| 8a1d6cd934 | |||
| 5769fbfb5a | |||
| 6912acaa3d | |||
| 1df3f281fd | |||
| f1c0df3156 | |||
| 6c5c1ff1bd | |||
| e37c0ac09b | |||
| c0572eb996 | |||
| 1b745a9c21 | |||
| cc855e3573 | |||
| 7089bb2d95 | |||
| 256d33e20f | |||
| d6b66629e0 | |||
| d813a1b58f | |||
| 7f6c8efb57 | |||
| af5420c949 | |||
| 5b28bc1bcd | |||
| 42d5d62575 | |||
| 525657843c | |||
| c4b15d9c84 | |||
| 099f3d5cc8 | |||
| 07b4407f03 | |||
| e8adb1b30b | |||
| 8995873089 | |||
| cda0083a3e | |||
| e32eae2946 | |||
| b6a1c28bfc | |||
| 457673a3bb | |||
| 10f2620590 | |||
| 9d9c924d82 | |||
| 23a7f8d00d | |||
| 259c010d4e | |||
| b728d85b00 | |||
| bf1e3af046 | |||
| bfb8bbfc29 | |||
| 259dd579eb | |||
| 8554a64c8b | |||
| 36c8ed2648 | |||
| a02ee4cef0 | |||
| 5e337bb971 | |||
| 4e2916c3f0 | |||
| c4ebac7fcf | |||
| 01899980a5 | |||
| 11c4f64f9d | |||
| 0334c56441 | |||
| f63731d18d | |||
| 33c07fc986 | |||
| 7a398bc847 | |||
| e9dbadab56 | |||
| 622bfa44fb | |||
| 73cfd1b29c | |||
| eae987f665 | |||
| bcd95d937c | |||
| 87fea5b4c7 | |||
| ee29f1c2c0 | |||
| 995d483072 | |||
| 5a209b0384 | |||
| db6911da6d | |||
| 2e2d29b0f5 | |||
| 77fc911f7e | |||
| a4f659387f | |||
| 33a452dab6 | |||
| d9b4d916c8 | |||
| 599cc25f7c | |||
| 4054cd1c72 | |||
| eb1f96ad20 | |||
| c1d1a766c7 | |||
| 2cb7632e96 | |||
| e14464081e | |||
| 49fa613b48 | |||
| c7dca40479 | |||
| d9d7801a50 | |||
| 44edd1c723 | |||
| a46ddc9e55 | |||
| c12560fed3 | |||
| f7dbfeec3f | |||
| 2b44ffe0e2 | |||
| 643fe8928b | |||
| a6f9d787ef | |||
| cf993a71da | |||
| 8f9ecee00a | |||
| 8ffe6eaad4 | |||
| 3256bd10b7 | |||
| 2b5bf3055e | |||
| 51743d03e6 | |||
| 50fdc88754 | |||
| f04f3e7961 | |||
| d38e96dfac | |||
| d09f5764bd | |||
| 608a55b942 | |||
| 0141ef770e | |||
| d936a9a28b | |||
| bc941d4e7a | |||
| a777919dcf | |||
| 73c9479474 | |||
| 179af6dffb | |||
| 8cab84384b | |||
| 92e0e32c83 | |||
| 0f73bda3a5 | |||
| 1a19c95b60 | |||
| 2269a3a70c | |||
| afa4d561c6 | |||
| b0524459b6 | |||
| 5142810101 | |||
| 365544d62f | |||
| 3e77dafbc7 | |||
| ec45a88c61 | |||
| 9c6b3ca4d0 | |||
| d4eefdc3ab | |||
| 2771c25f37 | |||
| 46137dd7cf | |||
| 006efeb15f | |||
| 3b18174c8c | |||
| e50f3147a9 | |||
| 145b33bd3d | |||
| edc5b84082 | |||
| d99c52614c | |||
| 39e626cca3 | |||
| cf848e8d2f | |||
| 0a6f6ae8d3 | |||
| fde580d67d | |||
| dde4c3fee3 | |||
| 461d1a2ef5 | |||
| 28ccb37b58 | |||
| e36908d9e5 | |||
| 63c94e7987 | |||
| 41767642f4 | |||
| e33987183a | |||
| 32c4029b4b | |||
| fec8125ae3 | |||
| c368a70d0b | |||
| 70a3a3c454 | |||
| 17d4933ff6 | |||
| 774cb588d1 | |||
| 1e68f0e583 | |||
| e911f5a2d0 | |||
| abd473a384 | |||
| 43143e69eb | |||
| 43f6c19b1e | |||
| 2e97d84c5b | |||
| 6132dde743 | |||
| 613f7c0511 | |||
| 572c829179 | |||
| 533b969d5c | |||
| 177b0c0bde | |||
| dde25cfcc7 | |||
| 85e86fe406 | |||
| abaf4056dd | |||
| 32a0e92b69 | |||
| 7d4a1d7532 | |||
| 9031bf8100 | |||
| 8c4b21ad62 | |||
| 8e21344356 | |||
| b3620191d8 | |||
| 8ecdef81c9 | |||
| 43db399352 | |||
| 798dd075ba | |||
| 6794e5fa36 | |||
| 799716565c | |||
| de15d2045f | |||
| 219767251c | |||
| 5272af0b06 | |||
| 2325691fcb | |||
| 2f072f4a26 | |||
| e57842386c | |||
| 09d682cd23 | |||
| b03f96a756 | |||
| 4d553c9db6 | |||
| 61f09261d4 | |||
| b38551eef8 | |||
| 79cf7df614 | |||
| e2eecee1d8 | |||
| 2d51144c43 | |||
| d4565981b1 | |||
| e0ffeeea2a | |||
| a8e83dc58c | |||
| ea6666185a | |||
| efe70fad93 | |||
| f4fec843e1 | |||
| fadbe0e226 | |||
| 69068c8720 | |||
| f7960006cc | |||
| fb214d9ab8 | |||
| d5d68632e7 | |||
| b5ec036687 | |||
| 3e1a5c18a9 | |||
| b480580399 | |||
| 2822624e85 | |||
| 205019a769 | |||
| 3d935e164d | |||
| 915fc5d6d8 | |||
| 3b60108c7a | |||
| c624331af5 | |||
| 1e096ec479 | |||
| d9ba99962c | |||
| 6e3cd02fdc | |||
| 98520d6d74 | |||
| 5085b1300b | |||
| 88275fa716 | |||
| ce752343ca | |||
| f74fb6ab29 | |||
| 7b185e022a | |||
| f9523a63f3 | |||
| 524d9a77a2 | |||
| 7362261469 | |||
| bf98392005 | |||
| 037686e7a1 | |||
| 9df83fb0ae | |||
| 1486757426 | |||
| b9671f7c77 | |||
| f95ff022d4 | |||
| 25661cf69e | |||
| c2cb614750 | |||
| e326c8d66e | |||
| 030edbd5d8 | |||
| 4bab0874b7 | |||
| 26b5b3a315 | |||
| bc94ee0cfa | |||
| a7aba0642b | |||
| 956b9aff4a | |||
| 25bea3444f | |||
| 71ea4caeb9 | |||
| 9d354bfcf9 | |||
| b548b851ce | |||
| 6d2faf0d02 | |||
| 154c9f9d4a | |||
| 579701cd30 | |||
| aacbd640e0 | |||
| 01e8296661 | |||
| 32f2fc8126 | |||
| 076e342f65 | |||
| b186a703e2 | |||
| c9bfd1e377 | |||
| 3365a073cb | |||
| 33e615bbf2 | |||
| a1adafa600 | |||
| 153d435571 | |||
| 6a8ad2e80c | |||
| 1395aba079 | |||
| 54e89492f3 | |||
| a69bb2edfa | |||
| b4b5a5fa59 | |||
| 389f3de5f4 | |||
| d457b345d7 | |||
| ace21dca93 | |||
| 6d72e96bc2 | |||
| f4f6cd1215 | |||
| 7de6e764a5 | |||
| 4c9a56de23 | |||
| e54a18e4ad | |||
| 4183e60fc7 | |||
| b25d19509c | |||
| d6c1444432 | |||
| edd1222e0e | |||
| c0106e8bee | |||
| 99be725ede | |||
| b0d04c3eac | |||
| b463732c42 | |||
| 5827121db5 | |||
| 7994a28363 | |||
| f6a9cb92b2 | |||
| 446a6a640f | |||
| 570a85e472 | |||
| f1f6c84758 | |||
| 3acf232631 | |||
| 0a2a2b35fe | |||
| 0eedc523bb | |||
| 5f59f4e126 | |||
| 9d6f1e5110 | |||
| fc653f265c | |||
| 0f32739675 | |||
| a333bcdc44 | |||
| 3c3be23f1f | |||
| 6b91fb9847 | |||
| 2219e4aebf | |||
| 97b9c02aa8 | |||
| 864c959b4d | |||
| 1a873b2d6a | |||
| e3d20823ae | |||
| 069b679e7d | |||
| 82b28baf87 | |||
| ffc150e569 | |||
| 7bb1b85b66 | |||
| 827f597e07 | |||
| b3f5e0c964 | |||
| 3dec76ecf4 | |||
| 897caf7abc | |||
| 0cac58e4a0 | |||
| cce422709b | |||
| b4d68fdb85 | |||
| 1acf4e1243 | |||
| bb53094f66 | |||
| 3d840f5c6d | |||
| db332a1f0f | |||
| 443a9001f5 | |||
| b7f9ad1808 | |||
| 5aa7658cdf | |||
| 5dd2fae7a9 | |||
| 3a5e571aea | |||
| 5ee03ed977 | |||
| 6710463318 | |||
| 893d36d4a3 | |||
| 8f8b7e1fd9 | |||
| e46c78fb36 | |||
| 5fd25efe0b | |||
| 4d2f567bc4 | |||
| 0aa5016758 | |||
| aac6291147 | |||
| 3cd4c18d6a | |||
| fe4bad7c11 | |||
| 251dbb2dee | |||
| 2ed6b14dc2 | |||
| a5162ac666 | |||
| 2a0adb3dbf | |||
| 7edfe2cca8 | |||
| 757ecb37b4 | |||
| 0ebcd4a7f3 | |||
| ef1e6b0676 | |||
| db94d03b64 | |||
| 87b994b67a | |||
| e5064f0794 | |||
| 6751172cfe | |||
| 6c0d7802d9 | |||
| ab7fd52fbd | |||
| c6cb66dc61 | |||
| 4b5ff75412 | |||
| 6dd5724be1 | |||
| 32f3bbb67d | |||
| 51cca16196 | |||
| 1fa87f753e | |||
| 48cc2ae4cf | |||
| e463c886cc | |||
| 2efb7058f8 | |||
| 1c582ab21a | |||
| 4f30e7ac85 | |||
| 0e223e4c7a | |||
| b431d32825 | |||
| 8f41a8be99 | |||
| e9b260aae9 | |||
| 2505af9985 | |||
| 18fff449f3 | |||
| cc437eb47c | |||
| 14cd7e71b4 | |||
| 03499adffc | |||
| c738e39268 | |||
| 922af0d651 | |||
| bfe91ab358 | |||
| 0cfe13e214 | |||
| 1246258f73 | |||
| 9655ef6a0d | |||
| 3fde29fecd | |||
| 04d5f374ef | |||
| acf0207f12 | |||
| 2ebc6fb26e | |||
| 1c1c70e951 | |||
| 3ff3054f5d | |||
| eee003c184 | |||
| 661a884566 | |||
| e35860c235 | |||
| abfbebe996 | |||
| 075555c294 | |||
| 30eb973810 | |||
| e60d332de6 | |||
| 835fe5db03 | |||
| 9705ff7837 | |||
| 56aea76e25 | |||
| f90ce46577 | |||
| 5355f87e1d | |||
| fd3d21229b | |||
| 1c819fec4d | |||
| 1256909852 | |||
| cf933f2b37 | |||
| f3031a3cab | |||
| ddf5e82bd5 | |||
| 95184394a4 | |||
| 8fbea7d329 | |||
| 7fd9de354f | |||
| 70f5d97aef | |||
| 1e8813e668 | |||
| b07403855c | |||
| 3ca12ea1d6 | |||
| 5ce0347e54 | |||
| ec2104d656 | |||
| e686b1228a | |||
| 2667268f0d | |||
| d3e5341c2d | |||
| 878aae6686 | |||
| 2df74bb052 | |||
| 66f73ab014 | |||
| 8b7ccada49 | |||
| 27845de14b | |||
| d59b550e04 | |||
| 4f26fd98a0 | |||
| e3fe09a1ae | |||
| 657b072ffa | |||
| def9865849 | |||
| 98cff70eaf | |||
| 0c4eb467fe | |||
| 3e6ed73769 | |||
| 6c29701b0d | |||
| 273dbf780e | |||
| 35831b0ba7 | |||
| 275f56a384 | |||
| dbb6551d20 | |||
| 6d74eecc5c | |||
| eae4fd3f1b | |||
| 687b3ad1cd | |||
| def04ec41c | |||
| cdbc67f3d5 | |||
| 2fd4f04bd8 | |||
| 2edbd375fd | |||
| d685c3963a | |||
| 4218e2d950 | |||
| f96a6eee04 | |||
| 12650ae9f7 | |||
| 9dee75e243 | |||
| e9a2579a64 | |||
| 7ca20972af | |||
| 3b6c187ad1 | |||
| c4e50aa700 | |||
| 4736b75cc7 | |||
| 775a007a41 | |||
| ae64c83d01 | |||
| 723622b7f5 | |||
| 7903ee1235 | |||
| da6629c210 | |||
| a994adfed7 | |||
| 66fc4eb85e | |||
| 04d4a113ac | |||
| fd6417bc3c | |||
| 74eee18415 | |||
| d5d27062d7 | |||
| 4983e581ba | |||
| ab37f35cf8 | |||
| 4a4fbb9b3f | |||
| 9b2617e48c | |||
| 80c2d4cee2 | |||
| 6255511d02 | |||
| e61ccaa6c8 | |||
| a2f31d5798 | |||
| 29f22d1e79 | |||
| fe78160055 | |||
| ba5d433dd1 | |||
| 3516bfc3c5 | |||
| 17fa9b6a14 | |||
| d0a8ab1976 | |||
| 051ca25fe7 | |||
| 3e097905e3 | |||
| d516731d24 | |||
| 2ddd430484 | |||
| 099c8a53d3 | |||
| dcbf0d05e5 | |||
| dd70a48e3f | |||
| fe954a9e33 | |||
| 5f5791a8e3 | |||
| 1c90ce4dea | |||
| 8bbd3a0000 | |||
| 72e430ef49 | |||
| 1c017a7589 | |||
| b9836c3eaa | |||
| 479f45f46f | |||
| e3204944f6 | |||
| debcd2043b | |||
| b57ceed621 | |||
| e6e0e80527 | |||
| 3c0b350a4f | |||
| b9a065d48a | |||
| c00e5abf80 | |||
| 2b3e06bf6d | |||
| 293b165aef | |||
| 3dbbb3129c | |||
| 7b5378fcf1 | |||
| 0e9d90e761 | |||
| d6acab6bd4 | |||
| b6096f6e95 | |||
| 84f2da4a27 | |||
| 3f6dfcb08e | |||
| f68e38b011 | |||
| 7bb92310b5 | |||
| ebab397625 | |||
| 776c0c2eb0 | |||
| c4bf9c07ca | |||
| 8d8703bec6 | |||
| cdfb2a162e | |||
| 842116e037 | |||
| 12403dab26 | |||
| 0dcb0e9fad | |||
| 450740318c | |||
| 455940abda | |||
| 38e2d1aaa9 | |||
| 8b640426a2 | |||
| 19a8c5512e | |||
| 9c50bce587 | |||
| 3f06c505ce | |||
| 04e5b93f91 | |||
| 052ed5c8e3 | |||
| 881a1a684f | |||
| 5bb41aa035 | |||
| 62c69c8357 | |||
| 93c4da6216 | |||
| 40cedc59cb | |||
| 3e44420023 | |||
| 16aacb8fef | |||
| 96a6d8cf3f | |||
| 4e2d68bb4a | |||
| b3c96949d9 | |||
| ac421dd971 | |||
| 97d7cf4f91 | |||
| cdfe0a5e9a | |||
| 170286d6ce | |||
| 5efa00294c | |||
| 1b47b4b420 | |||
| 2868b5c12e | |||
| 4cd7fbf7be | |||
| 1ed8555b4e | |||
| a7655a6809 | |||
| cd64333364 | |||
| 4de7b7c504 | |||
| df4634bb6a | |||
| fa338784d9 | |||
| ca501350e1 | |||
| db597d3a2b | |||
| 49b3ba9e34 | |||
| d7bdbe0420 | |||
| 86f9c2e0fb | |||
| c7d4b3e45a | |||
| 1bbe821474 | |||
| f9d46b15c8 | |||
| 8d80e6399a | |||
| e2ec6a57ff | |||
| 661466df50 | |||
| 2d45112fc4 | |||
| bf4b6c6dcd | |||
| 170aa7fd79 | |||
| 825ad67c6e | |||
| cfd2c66ea4 | |||
| 323258443f | |||
| e7c45601de | |||
| 61a18e8a0d | |||
| 2c5b292888 | |||
| 8a7538338f | |||
| c088bd776e | |||
| 7a2232ee46 | |||
| d52067a8d2 | |||
| 821344d0f2 | |||
| 2536f989c7 | |||
| 828cb7dc3b | |||
| eac8b86fcf | |||
| ef13f95cc2 | |||
| 3fa528cca1 | |||
| 585d2185bc | |||
| 817c43ed75 | |||
| ba75191d37 | |||
| df8dfa0ddb | |||
| 093269ebcd | |||
| 556ab591f9 | |||
| a91727c886 | |||
| ff567918b1 | |||
| e4f16f0d4e | |||
| 98f3488520 | |||
| ac7830ff50 | |||
| 12d60b81b8 | |||
| 8744787348 | |||
| fb37b423bd | |||
| 5e171a3ac9 | |||
| f8ffb1641f | |||
| eb86123a47 | |||
| cd1e6e7766 | |||
| 2fa5056ffd | |||
| ebe6b092a7 | |||
| 78a37292cc | |||
| 749a83d28b | |||
| 91a8aa22b7 | |||
| f7084cc07b | |||
| fa900941d5 | |||
| 4da5cea54c | |||
| d83ab22d45 | |||
| c1229f65a1 | |||
| 8b8bf8d6aa | |||
| 08200cb5e8 | |||
| bce5bb7d14 | |||
| f07fed4804 | |||
| 8112bd6af4 | |||
| e0443512e6 | |||
| cbfe972ace | |||
| e078700af9 | |||
| 0c74863be9 | |||
| 2779280b83 | |||
| 176c86a73e | |||
| 694c2d9e85 | |||
| 7fd7dba118 | |||
| b998b4c967 | |||
| 206eb4d2cb | |||
| bbee178ff9 | |||
| 67775552b5 | |||
| 54f02890cb | |||
| b7bce5efd2 | |||
| 8f13c8e37a | |||
| eccc452d80 | |||
| 7a1c36f8db | |||
| 654095786e | |||
| c12adecf9f | |||
| fc6013c5de | |||
| 3dd9f07fe2 | |||
| 5308fdd0b8 | |||
| 273d1e296c | |||
| 152af7dc7b | |||
| 43b34f22a3 | |||
| 3330b451d0 | |||
| 5290296952 | |||
| 8fc784aef5 | |||
| 110c8b890b | |||
| b6c686d770 | |||
| 6358db88ff | |||
| b2611fd613 | |||
| 5eb3af0188 | |||
| ad71c17f77 | |||
| 0d7dec8e4e | |||
| 112fbbfc08 | |||
| 4ee5240c72 | |||
| 025e359394 | |||
| 143bcfad08 | |||
| a39ebd13e0 | |||
| e7c0a5f19f | |||
| f0b03dc426 | |||
| 3d2ad79b6b | |||
| 9f28a93c56 | |||
| 386dd1d799 | |||
| e85ebf3a50 | |||
| 81eb2e6f42 | |||
| 9d021a2ec1 | |||
| 439fac65e2 | |||
| dee484a16b | |||
| 90457d6f20 | |||
| 245c30d7a7 | |||
| 81b28293ca | |||
| 392f71b214 | |||
| 257a5281ed | |||
| d44f70a145 | |||
| ec9198f25d | |||
| 1ffd4f97fc | |||
| e8968252ab | |||
| ae618ddd76 | |||
| 73d36d34c8 | |||
| 4126b0574a | |||
| 005aa1a64c | |||
| a63231d36f | |||
| db530f7def | |||
| 627261f51d | |||
| d080b71f29 | |||
| 0a62195625 | |||
| 571bb43459 | |||
| 817b9d5c9f | |||
| 6f3fa9bf8d | |||
| 2de5a7d9f7 | |||
| d26f1a65e8 | |||
| 667c2e59d3 | |||
| b4411a027f | |||
| 142831ec44 | |||
| 2dd58759de | |||
| 866f3a11b2 | |||
| 8a2d779320 | |||
| 2ef8cd4c3f | |||
| 88ec1e66e6 | |||
| f6bfeefc8e | |||
| bbdf9023fe | |||
| b0070122f8 | |||
| ad51bfb30f | |||
| d15ae51825 | |||
| 2efa265983 | |||
| cc6513c93a | |||
| a81865484c | |||
| d70eb13cb0 | |||
| 4b5d94eeb9 | |||
| 5674a4ddac | |||
| 5bb6483ab4 | |||
| f62e4b6eb7 | |||
| c54a613393 | |||
| 2c4be00267 | |||
| 0b8c22e0d8 | |||
| 65a7dca95f | |||
| fdcfaface0 | |||
| 5f08884b52 | |||
| 3595eee11c | |||
| b33eb54c34 | |||
| c86fc743bc | |||
| 10b82603b9 | |||
| 1a1ae36299 | |||
| cc004c00f0 | |||
| cda96afd14 | |||
| 966630ea16 | |||
| 8c746bdccc | |||
| 4fac7da3bb | |||
| 4045958cd2 | |||
| 45155a9ff4 | |||
| 83ad789654 | |||
| 21eaa5ee9c | |||
| e2bc9aa6d0 | |||
| 670721ac52 | |||
| 69bcd84d5d | |||
| 7357fa4c5b | |||
| d51c768112 | |||
| 32ae4fef3a | |||
| fd5ee77f1c | |||
| b9acbfccd7 | |||
| d05059e64d | |||
| bc80e38bb5 | |||
| 838233a68f | |||
| 6968d973a6 | |||
| 199f6aa70c | |||
| e195ea5221 | |||
| ea1ebb4bba | |||
| b7e33bb2b9 | |||
| d2d777be0c | |||
| 4c924b4971 | |||
| ddd4a1a4ea | |||
| c68f240061 | |||
| 5d9d4955ff | |||
| fb4eeaaaeb | |||
| a0b04c2d99 | |||
| 6a60039aac | |||
| 96485ec8d0 | |||
| 86b38b5e40 | |||
| 2e6ff091e2 | |||
| e91972589c | |||
| eb5a8b8beb | |||
| e1320c4661 | |||
| 2db0d397a6 | |||
| 7f85af9c54 | |||
| 3a981be8c6 | |||
| 95b51dae6f | |||
| 9eef533e8a | |||
| 8e4930d031 | |||
| 2b9621e7cf | |||
| 747bf2c3c1 | |||
| e398518bd1 | |||
| 48bdab0ed5 | |||
| ab122f92ad | |||
| ef0b374959 | |||
| dbfc04afc4 | |||
| 7d6687f46f | |||
| f8483ec22e | |||
| 0b690bbe43 | |||
| 871aa08f41 | |||
| e2c2e2e841 | |||
| ba9dfa8f4c | |||
| cad5b436e5 | |||
| 312fdcea96 | |||
| 518a969aab | |||
| e6687bd7b8 | |||
| 74260589f4 | |||
| aefd6e6a9e | |||
| 58e60ee148 | |||
| fdc2b21e0b | |||
| 9d6c15e10b | |||
| f271d3890b | |||
| 69a4a29014 | |||
| f72771c026 | |||
| d2e05c481f | |||
| f999cfc2c7 | |||
| 6c7812b8a4 | |||
| b841358e22 | |||
| 3419343e85 | |||
| 917fc68e27 | |||
| fadd0279a8 | |||
| bbcc75dd2d | |||
| f0b44d8c02 | |||
| eddf89697d | |||
| 92a155c780 | |||
| 6661e6e058 | |||
| 68c49a9aa1 | |||
| 1ae7d4bd54 | |||
| 8330ef062e | |||
| 5493ba998e | |||
| ed59d8a351 | |||
| 077def41ae | |||
| 7480a33eaf | |||
| 4e1e8832cc | |||
| fe290a42c1 | |||
| 54ae627ed2 | |||
| a3d30e9012 | |||
| 021e9c6335 | |||
| 3833f01f2d | |||
| 2060dc288e | |||
| fe10a1d57e | |||
| 563e50334c | |||
| a630c1daa4 | |||
| 97380ceae6 | |||
| 7f8a4ec63d | |||
| 88eaf9ad53 | |||
| 0e8a7f4b30 | |||
| 42cd424723 | |||
| d7319907e8 | |||
| 3c942cfea1 | |||
| 2884b93971 | |||
| 494f445b33 | |||
| f23299fc9a | |||
| d53f00a55a | |||
| 89315c90e8 | |||
| 3fedc41772 | |||
| da4db2e4a2 | |||
| 7e0f611279 | |||
| 56ff162681 | |||
| 0eebc91e3d | |||
| 284dc98394 | |||
| f11928f91f | |||
| 1bcbdc1411 | |||
| 19067d10ea | |||
| e53c9f596b | |||
| 970420e275 | |||
| 9d3d2877d9 | |||
| 32af9095cb | |||
| ea6304f4bc | |||
| 695a804813 | |||
| 88d23f22a4 | |||
| 754b6dc069 | |||
| b72466a1e3 | |||
| d7d7795b99 | |||
| f4c03d58c9 | |||
| 431231ed68 | |||
| 34521e8656 | |||
| 16765ff731 | |||
| 2e59973c8d | |||
| e0277b2b59 | |||
| 91ddb05f27 | |||
| 70b215054d | |||
| afe596eb7d | |||
| 811f04e783 | |||
| 38543b0979 | |||
| 0574b03aeb | |||
| 460ccfcacb | |||
| 50e0f04b9a | |||
| 77bc0f095f | |||
| 064e7f544a | |||
| 06f329ae3b | |||
| d05283200b | |||
| d700c3ea17 | |||
| 3c381320c0 | |||
| 876d07f467 | |||
| 691adcb82d | |||
| 0321b19eaa | |||
| 02a84d71a6 | |||
| 504a81b86a | |||
| 0baf603f90 | |||
| 7593b7a3e3 | |||
| b07a146f27 | |||
| 2eee59c530 | |||
| 9b50b5bdb5 | |||
| 4911348396 | |||
| 2a9759e7d2 | |||
| 4366e29c05 | |||
| c612eef65d | |||
| 48cd830628 | |||
| 7be08a2e2d | |||
| 3d4def2072 | |||
| 259ef699d4 | |||
| 2a79d00726 | |||
| eb27efd9e0 | |||
| c94ce0ac7d | |||
| 0acd9a38fa | |||
| 5a0a60e8ba | |||
| 02854ef0a0 | |||
| 62e5b63229 | |||
| c2c537baa2 | |||
| 89223eb90f | |||
| 2ba95ea13b | |||
| e4af56c5ae | |||
| 5accf191dc | |||
| a011e15e14 | |||
| 2c9b67c87e | |||
| 895c8f2dde | |||
| 47e5f54776 | |||
| 13ff44ec32 | |||
| 8d03df8553 | |||
| 5bdac85eab | |||
| f391f2d9c6 | |||
| ebebd6c6b9 | |||
| e7b4a1d156 | |||
| a93d083cce | |||
| c38d6c07f7 | |||
| 0d1a6f1926 | |||
| b6e86ec2f2 | |||
| d867e5a578 | |||
| 8fd52a383e | |||
| 44c73da13b | |||
| 79daaf3387 | |||
| 6ccb9bc261 | |||
| 5f6608e43a | |||
| dbdf3f1b61 | |||
| 39bc31ede3 | |||
| 07eaf04454 | |||
| c77be46006 | |||
| 5be1d2dee8 | |||
| b04b095055 | |||
| 0a26b7bdff | |||
| 2755ac54db | |||
| e7155dae52 | |||
| b499c5b7bc | |||
| 30e06d21b7 | |||
| c01b910aa5 | |||
| 748920b136 | |||
| e07fbd55cb | |||
| 6cf01c4261 | |||
| afdb276473 | |||
| 445d16bde6 | |||
| 3d9f73500c | |||
| 165e3490fc | |||
| 7ab1a9b6d8 | |||
| 526e44dbae | |||
| f33f5fad35 | |||
| ee36c66333 | |||
| fc6c7e7549 | |||
| eb4b3613cd | |||
| 2859390ff7 | |||
| 654c648feb | |||
| ad07fa19d7 | |||
| 4d1cb10fd3 | |||
| d936b0f482 | |||
| 915b67758a | |||
| 16b152ddf8 | |||
| 3cc56f5c9d | |||
| ac69e0e45b | |||
| e0f53d1030 | |||
| 4e8eafe92e | |||
| 263fd588af | |||
| fac0b5af94 | |||
| 02a266f2d7 | |||
| 392df791ee | |||
| fa797518c1 | |||
| 1791824b14 | |||
| 407f37dd9e | |||
| af50b50110 | |||
| 1af7616961 | |||
| 0d8100c1d8 | |||
| 9b8ab5430c | |||
| d7e325ba89 | |||
| cae94fe7eb | |||
| bbb50748e4 | |||
| c34253c6af | |||
| a027dd6579 | |||
| 4a5cdd31f4 | |||
| 83703f757f | |||
| 58f68de94a | |||
| 963dfd0c62 | |||
| cd7f00b9e3 | |||
| 0c0b560321 | |||
| 3c31888f54 | |||
| 1f057d8945 | |||
| a28e207511 | |||
| 35dd42a9f9 | |||
| 9cb00851aa | |||
| 73f4ae8d28 | |||
| 5e0edd9d95 | |||
| dfbb5aa79e | |||
| 62d9bbf522 | |||
| e832d56310 | |||
| 45fc6fb1b2 | |||
| be39d4c825 | |||
| 7baf6559ed | |||
| 13ee3550f9 | |||
| 4f63b6f2e0 | |||
| 536d765359 | |||
| 20c4dcac26 | |||
| 58bd1a7bde | |||
| bacb4f067d | |||
| e4d82fcfc2 | |||
| 754f457574 | |||
| 96984da285 | |||
| 1d1d1cb405 | |||
| 6beb2ed831 | |||
| 80ac28bd07 | |||
| e4e39cdfeb | |||
| 25c03ae410 | |||
| 7ef4449fc1 | |||
| b1353fdfcc | |||
| 3a3cad9fd4 | |||
| 6e6784a5e7 | |||
| cf22336e3a | |||
| be69bd95af | |||
| bc19194c58 | |||
| 62ac5b09b1 | |||
| 9ccc66da0e | |||
| 1d6ec0fcfd | |||
| d9510a7569 | |||
| 5412165427 |
@@ -5,14 +5,19 @@
|
||||
*.pyo
|
||||
|
||||
*~
|
||||
*.bak
|
||||
*.bak
|
||||
|
||||
saves
|
||||
tmp
|
||||
cache
|
||||
|
||||
log.txt
|
||||
/errors.txt
|
||||
/traceback.txt
|
||||
|
||||
styles.txt
|
||||
|
||||
/android
|
||||
/build
|
||||
/dist
|
||||
/dists
|
||||
@@ -20,27 +25,18 @@ log.txt
|
||||
/jedit
|
||||
/lint.txt
|
||||
/renpy.code
|
||||
/traceback.txt
|
||||
/testing*
|
||||
/*testing*
|
||||
/screenshot*
|
||||
/errors.txt
|
||||
/styles.txt
|
||||
/Microsoft.VC90.CRT.manifest
|
||||
/console.exe
|
||||
/msvcr90.dll
|
||||
/python27.dll
|
||||
/renpy.exe
|
||||
/lib/windows-x86
|
||||
/lib/linux-x86_64
|
||||
/lib/linux-i686
|
||||
/lib/python2.7
|
||||
/lib
|
||||
/lib.old
|
||||
/doc
|
||||
/.pydevproject
|
||||
/.pydevproject.bak
|
||||
/.project
|
||||
/.settings
|
||||
/LICENSE.txt
|
||||
/template/README.html
|
||||
/templates/english/README.html
|
||||
/the_question/README.html
|
||||
/tutorial/README.html
|
||||
/renpy/angle/*.pyx
|
||||
@@ -49,6 +45,10 @@ log.txt
|
||||
/module/build
|
||||
/module/gen
|
||||
/editra
|
||||
/launcher/game/theme
|
||||
/launcher/game/script_version.rpy
|
||||
|
||||
dl
|
||||
renpy/vc_version.py
|
||||
.externalToolBuilders
|
||||
rapt
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
==============================
|
||||
The Ren'Py Visual Novel Engine
|
||||
==============================
|
||||
|
||||
http://www.renpy.org
|
||||
|
||||
Ren'Py development takes place on the ``master`` branch, and occasionally
|
||||
on feature branches.
|
||||
|
||||
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
Ren'Py depends on a number of python modules written in Cython and C. For
|
||||
changes to Ren'Py that only involve python modules, you can use the modules
|
||||
found in the latest nightly build. Otherwise, you'll have to compile the
|
||||
modules yourself.
|
||||
|
||||
The development scripts assume a POSIX-like platform. The scripts should run
|
||||
on Linux or Mac OS X, and can be made to run on Windows using an environment
|
||||
like Msys.
|
||||
|
||||
Nightly Build
|
||||
-------------
|
||||
|
||||
Nightly builds can be downloaded from:
|
||||
|
||||
http://nightly.renpy.org
|
||||
|
||||
Note that the latest nightly build is at the bottom of the list. Once you've
|
||||
unpacked the nightly, change into this repository, and run::
|
||||
|
||||
./after_checkout.sh <path-to-nightly>
|
||||
|
||||
Once this script completes, you should be able to run Ren'Py using renpy.sh,
|
||||
renpy.app, or renpy.exe, as appropriate for your platform.
|
||||
|
||||
If the current nightly build doesn't work, please wait 24 hours for a new
|
||||
build to occur. If that build still doesn't work, contact Tom (`pytom at bishoujo.us`,
|
||||
or @renpytom on twitter) to find out what's wrong.
|
||||
|
||||
The ``doc`` symlink will dangle until documentation is built, as described
|
||||
below.
|
||||
|
||||
Compiling the Modules
|
||||
----------------------
|
||||
|
||||
Building the modules requires you have the many dependencies installed on
|
||||
your system. On Ubuntu and Debian, these dependencies can be installed with
|
||||
the command::
|
||||
|
||||
apt-get install python-dev python-pygame libavcodec-dev libavformat-dev \
|
||||
libavresample-dev libfreetype6-dev libglew1.6-dev libsdl1.2-dev \
|
||||
libsdl-image1.2-dev libfribidi-dev libswscale-dev libesd0-dev libpulse-dev
|
||||
|
||||
Other platforms may have an equivalent command. Otherwise, you'll need to
|
||||
build `renpy-deps <https://github.com/renpy/renpy-deps>`_.
|
||||
|
||||
We strongly suggest installing the Ren'Py modules into a Python
|
||||
virtualenv. `This page <http://dabapps.com/blog/introduction-to-pip-and-virtualenv-python/>`_
|
||||
describes how to install pip and the virtualenv tool, and set up a new virtualenv.
|
||||
|
||||
After activating the virtualenv, install cython::
|
||||
|
||||
pip install -U cython
|
||||
|
||||
Next, set RENPY_DEPS_INSTALL To a \::-separated list of paths containing the
|
||||
dependencies, and RENPY_CYTHON to the name of the cython command::
|
||||
|
||||
export RENPY_DEPS_INSTALL=/usr::/usr/lib/x86_64-linux-gnu/
|
||||
export RENPY_CYTHON=cython
|
||||
|
||||
Finally, change into the `modules` directory, and run::
|
||||
|
||||
python setup.py install
|
||||
|
||||
Ren'Py will be installed into the activated virtualenv. It can then be run
|
||||
using the command::
|
||||
|
||||
python -O renpy.py
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
Building the documentation requires Ren'Py to work. You'll either need to
|
||||
link in a nightly build, or compile the modules as described above. You'll
|
||||
also need the `Sphinx <http://sphinx-doc.org/>`_ documentation generator.
|
||||
If you have pip working, install Sphinx using::
|
||||
|
||||
pip install -U sphinx
|
||||
|
||||
Once Sphinx is installed, change into the ``sphinx`` directory inside the
|
||||
Ren'Py checkout and run::
|
||||
|
||||
./build.sh
|
||||
|
||||
Format
|
||||
------
|
||||
|
||||
Ren'Py's documentation consists of reStructuredText files found in sphinx/source, and
|
||||
generated documentation found in function docstrings scattered throughout the code. Do
|
||||
not edit the files in sphinx/source/inc directly, as they will be overwritten.
|
||||
|
||||
Docstrings may include tags on the first few lines:
|
||||
|
||||
\:doc: `section` `kind`
|
||||
Indicates that this functions should be documented. `section` gives
|
||||
the name of the include file the function will be documented in, while
|
||||
`kind` indicates the kind of object to be documented (one of ``function``,
|
||||
``method`` or ``class``. If omitted, `kind` will be auto-detected.
|
||||
\:name: `name`
|
||||
The name of the function to be documented. Function names are usually
|
||||
detected, so this is only necessary when a function has multiple aliases.
|
||||
\:args: `args`
|
||||
This overrides the detected argument list. It can be used if some arguments
|
||||
to the function are deprecated.
|
||||
|
||||
For example::
|
||||
|
||||
def warp_speed(factor, transwarp=False):
|
||||
"""
|
||||
:doc: warp
|
||||
:name: renpy.warp_speed
|
||||
:args: (factor)
|
||||
|
||||
Exceeds the speed of light.
|
||||
"""
|
||||
|
||||
renpy.engine.warp_drive.engage(factor)
|
||||
|
||||
|
||||
Translating
|
||||
===========
|
||||
|
||||
For best practices when it comes to translating the launcher and template
|
||||
game, please read:
|
||||
|
||||
http://lemmasoft.renai.us/forums/viewtopic.php?p=321603#p321603
|
||||
|
||||
|
||||
Contributing
|
||||
============
|
||||
|
||||
For bug fixes, documentation improvements, and simple changes, just
|
||||
make a pull request. For more complex changes, it might make sense
|
||||
to file an issue first so we can discuss the design.
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from renpy import version_tuple #@UnresolvedImport
|
||||
|
||||
version = ".".join(str(i) for i in version_tuple)
|
||||
short_version = ".".join(str(i) for i in version_tuple[:3])
|
||||
print "Version", version
|
||||
|
||||
ap = argparse.ArgumentParser()
|
||||
|
||||
ap.add_argument("--release", action="store_true")
|
||||
ap.add_argument("--prerelease", action="store_true")
|
||||
ap.add_argument("--experimental", action="store_true")
|
||||
ap.add_argument("--no-tag", "-n", action="store_true")
|
||||
|
||||
args = ap.parse_args()
|
||||
|
||||
if args.release:
|
||||
links = [ "release", "prerelease", "experimental" ]
|
||||
tag = True
|
||||
elif args.prerelease:
|
||||
links = [ "prerelease", "experimental" ]
|
||||
tag = True
|
||||
elif args.experimental:
|
||||
links = [ "experimental" ]
|
||||
tag = False
|
||||
else:
|
||||
links = [ ]
|
||||
tag = False
|
||||
|
||||
|
||||
def check_dirty():
|
||||
if args.no_tag:
|
||||
return
|
||||
|
||||
if subprocess.check_call([ "git", "diff", "--quiet", "HEAD" ]):
|
||||
print "Directory not checked in: {}".format(os.getcwd())
|
||||
sys.exit(1)
|
||||
|
||||
os.chdir("/home/tom/ab/renpy")
|
||||
check_dirty()
|
||||
|
||||
os.chdir("/home/tom/ab/renpy/android")
|
||||
check_dirty()
|
||||
|
||||
if not args.no_tag:
|
||||
subprocess.check_call([ "git", "tag", "-a", "rapt-" + version, "-m", "Tagging RAPT release." ])
|
||||
|
||||
os.chdir("/home/tom/ab/renpy/dl")
|
||||
|
||||
for i in links:
|
||||
if os.path.exists(i):
|
||||
os.unlink(i)
|
||||
os.symlink(short_version, i)
|
||||
|
||||
os.chdir("/home/tom/ab/renpy")
|
||||
|
||||
if tag and not args.no_tag:
|
||||
cmd = [ "git", "tag", "-a", version, "-m", "Ren'Py " + version ]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
os.chdir("/home/tom/ab/website")
|
||||
subprocess.check_call("./upload.sh")
|
||||
@@ -1,8 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
ln -s ../help.html tutorial/README.html
|
||||
ln -s ../help.html the_question/README.html
|
||||
ln -s ../help.html template/README.html
|
||||
ROOT="$(dirname $(python -c "import os;print(os.path.realpath('$0'))"))"
|
||||
|
||||
ln -s sphinx/source/license.rst LICENSE.txt
|
||||
ln -s sphinx/build/html doc
|
||||
ln -s "$ROOT/help.html" "$ROOT/tutorial/README.html"
|
||||
ln -s "$ROOT/help.html" "$ROOT/the_question/README.html"
|
||||
ln -s "$ROOT/help.html" "$ROOT/templates/english/README.html"
|
||||
|
||||
ln -s "$ROOT/sphinx/source/license.rst" "$ROOT/LICENSE.txt"
|
||||
|
||||
if [ "$1" != "" ]; then
|
||||
ln -s "$1/lib" "$ROOT/lib"
|
||||
ln -s "$1/renpy.app" "$ROOT"
|
||||
ln -s "$1/renpy.exe" "$ROOT"
|
||||
fi
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# This file sets up the normal python modules. It's used to help eclipse
|
||||
# This file sets up the normal python modules. It's used to help eclipse
|
||||
# do type detection, by providing an importable version of the cython code.
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import modulefinder
|
||||
import shutil
|
||||
from distutils.core import setup
|
||||
import py2exe #@UnresolvedImport @UnusedImport
|
||||
import sys
|
||||
import zipfile
|
||||
import traceback
|
||||
import os
|
||||
|
||||
# The pythonpath on my system.
|
||||
sys.path.insert(0, 'c:\\msys\\1.0\\newbuild\\install\\bin')
|
||||
sys.path.insert(0, 'c:\\msys\\1.0\\newbuild\\install\\python')
|
||||
|
||||
def move_from_dist(fn):
|
||||
"""
|
||||
Moves the file `fn` from the dist directory to the main
|
||||
directory. (This means we don't need symlinks on windows.)
|
||||
"""
|
||||
|
||||
if os.path.isdir(fn):
|
||||
shutil.rmtree(fn)
|
||||
elif os.path.exists(fn):
|
||||
os.unlink(fn)
|
||||
|
||||
os.rename("dist/" + fn, fn)
|
||||
|
||||
import renpy
|
||||
renpy.setup_modulefinder(modulefinder) #@UndefinedVariable
|
||||
|
||||
def main():
|
||||
|
||||
sys.argv[1:] = [ 'py2exe', '-a', '--dll-excludes', 'w9xpopen.exe', ]
|
||||
|
||||
setup(name="Ren'Py",
|
||||
windows=[ dict(script="renpy.py",
|
||||
dest_base="renpy",
|
||||
icon_resources=[ (1, "newicon.ico") ],
|
||||
),
|
||||
],
|
||||
|
||||
console=[ dict(script="renpy.py", dest_base="console") ],
|
||||
|
||||
zipfile='lib/windows-x86/renpy.code',
|
||||
|
||||
options={ 'py2exe' : { 'excludes' : [ 'doctest',
|
||||
'pygame.macosx',
|
||||
'pygame.surfarray',
|
||||
'pygame.mixer',
|
||||
'pygame.mixer_music',
|
||||
'_ssl',
|
||||
'_hashlib',
|
||||
'win32con',
|
||||
'win32api',
|
||||
'Numeric',
|
||||
'os2emxpath',
|
||||
'macpath',
|
||||
'multiprocessing',
|
||||
'_multiprocessing',
|
||||
],
|
||||
'optimize' : 2,
|
||||
} },
|
||||
)
|
||||
|
||||
|
||||
zfold = zipfile.ZipFile("dist/lib/windows-x86/renpy.code")
|
||||
zfnew = zipfile.ZipFile("dist/lib/windows-x86/renpy.code.new", "w", zipfile.ZIP_STORED)
|
||||
|
||||
seen = { }
|
||||
|
||||
for fn in zfold.namelist():
|
||||
if fn.startswith("renpy/"):
|
||||
|
||||
# Keep around .pyo files that load pyd files.
|
||||
pydfn = fn.replace("/", ".").replace(".pyo", ".pyd")
|
||||
if not os.path.exists("dist/lib/windows-x86/" + pydfn):
|
||||
continue
|
||||
|
||||
if fn in seen:
|
||||
continue
|
||||
|
||||
if fn == "SDL_mixer.dll":
|
||||
continue
|
||||
|
||||
seen[fn] = True
|
||||
|
||||
zfnew.writestr(fn, zfold.read(fn))
|
||||
|
||||
zfold.close()
|
||||
zfnew.close()
|
||||
|
||||
os.unlink("dist/lib/windows-x86/renpy.code")
|
||||
os.rename("dist/lib/windows-x86/renpy.code.new", "dist/lib/windows-x86/renpy.code")
|
||||
|
||||
# Take these files from the old python.
|
||||
shutil.copy("c:/Python26/Microsoft.VC90.CRT.manifest", "Microsoft.VC90.CRT.manifest")
|
||||
shutil.copy("c:/Python26/msvcr90.dll", "msvcr90.dll")
|
||||
|
||||
move_from_dist("lib/windows-x86")
|
||||
move_from_dist("console.exe")
|
||||
move_from_dist("python27.dll")
|
||||
move_from_dist("renpy.exe")
|
||||
|
||||
|
||||
try:
|
||||
main()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import collections
|
||||
import glob
|
||||
import re
|
||||
import os
|
||||
|
||||
# A map from string to filename, line number where the string is found.
|
||||
strings = collections.defaultdict(list)
|
||||
|
||||
def process(fn):
|
||||
|
||||
lineno = 0
|
||||
|
||||
for data in file(fn, "r"):
|
||||
|
||||
lineno += 1
|
||||
|
||||
matches = [ ]
|
||||
|
||||
matches += re.finditer(r'\bu\"(\\"|[^"])+\"', data)
|
||||
matches += re.finditer(r"\bu\'(\\'|[^'])+\'", data)
|
||||
|
||||
for m in matches:
|
||||
s = m.group(0)[2:-1]
|
||||
|
||||
if "\\u" in s:
|
||||
continue
|
||||
|
||||
if len(s) == 1:
|
||||
continue
|
||||
|
||||
strings[s].append("%s:%d" % (fn, lineno))
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
files = [ ]
|
||||
|
||||
files += glob.glob("launcher/*.rpy")
|
||||
files += glob.glob("common/*.rpy")
|
||||
files += glob.glob("common/*.rpym")
|
||||
files += glob.glob("common/_layout/*.rpym")
|
||||
files += glob.glob("common/_compat/*.rpym")
|
||||
|
||||
if "launcher/strings.rpy" in files:
|
||||
files.remove("launcher/strings.rpy")
|
||||
|
||||
for fn in files:
|
||||
process(fn)
|
||||
|
||||
converse = [ ]
|
||||
|
||||
for k, v in strings.iteritems():
|
||||
v = " ".join(sorted(v))
|
||||
converse.append((v, k))
|
||||
|
||||
converse.sort()
|
||||
|
||||
f = file("launcher/strings.rpy", "w")
|
||||
|
||||
files = set(i for i in os.listdir("launcher") if i.endswith(".rpy"))
|
||||
|
||||
print >>f, """\
|
||||
init python:
|
||||
LAUNCHER_RPYS = %r
|
||||
|
||||
TRANSLATION_STRINGS = [
|
||||
""" % files
|
||||
|
||||
for v, k in converse:
|
||||
# print
|
||||
# print "#:", v
|
||||
# print "#, python-format"
|
||||
|
||||
print >>f, " u\"%s\"," % unicode(k)
|
||||
|
||||
print >>f, """\
|
||||
]
|
||||
"""
|
||||
@@ -1,35 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# This file contains warpers that are used by ATL. They need to be defined
|
||||
# early, so Ren'Py knows about them when parsing other files.
|
||||
|
||||
python early hide:
|
||||
|
||||
# pause is defined internally, but would look like:
|
||||
#
|
||||
# @renpy.atl_warper
|
||||
# def pause(t):
|
||||
# if t >= 1.0:
|
||||
# return 1.0
|
||||
# else:
|
||||
# return 0.0
|
||||
|
||||
@renpy.atl_warper
|
||||
def linear(t):
|
||||
return t
|
||||
|
||||
@renpy.atl_warper
|
||||
def easeout(x):
|
||||
import math
|
||||
return 1.0 - math.cos(x * math.pi / 2.0)
|
||||
|
||||
@renpy.atl_warper
|
||||
def easein(x):
|
||||
import math
|
||||
return math.cos((1.0 - x) * math.pi / 2.0)
|
||||
|
||||
@renpy.atl_warper
|
||||
def ease(x):
|
||||
import math
|
||||
return .5 - math.cos(math.pi * x) / 2.0
|
||||
@@ -1,329 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init -1135 python:
|
||||
|
||||
class __GalleryAllPriorCondition(object):
|
||||
|
||||
def check(self, all_prior):
|
||||
return all_prior
|
||||
|
||||
|
||||
class __GalleryArbitraryCondition(object):
|
||||
def __init__(self, condition):
|
||||
self.condition = condition
|
||||
|
||||
def check(self, all_prior):
|
||||
return eval(self.condition)
|
||||
|
||||
|
||||
class __GalleryUnlockCondition(object):
|
||||
def __init__(self, images):
|
||||
self.images = images
|
||||
|
||||
def check(self, all_prior):
|
||||
for i in self.images:
|
||||
if not renpy.seen_image(i):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class __GalleryImage(object):
|
||||
def __init__(self, gallery, displayables):
|
||||
|
||||
# The gallery object we belong to.
|
||||
self.gallery = gallery
|
||||
|
||||
# A list of conditions for this image to be displayed.
|
||||
self.conditions = [ ]
|
||||
|
||||
# A list of displayables to show.
|
||||
self.displayables = displayables
|
||||
|
||||
# A list of transforms to apply to those displayables, or None
|
||||
# to not apply a transform.
|
||||
self.transforms = [ None ] * len(displayables)
|
||||
|
||||
|
||||
def check_unlock(self, all_prior):
|
||||
"""
|
||||
Returns True if the image is unlocked.
|
||||
"""
|
||||
|
||||
for i in self.conditions:
|
||||
if not i.check(all_prior):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def show(self, locked, index, count):
|
||||
"""
|
||||
Shows this image when it's unlocked.
|
||||
"""
|
||||
|
||||
renpy.transition(self.gallery.transition)
|
||||
ui.saybehavior()
|
||||
|
||||
displayables = [ ]
|
||||
|
||||
for d, transform in zip(self.displayables, self.transforms):
|
||||
|
||||
if transform is not None:
|
||||
d = transform(d)
|
||||
else:
|
||||
d = config.default_transform(d)
|
||||
|
||||
displayables.append(d)
|
||||
|
||||
renpy.show_screen("_gallery", locked=locked, index=index + 1, count=count, displayables=displayables, gallery=self.gallery)
|
||||
ui.interact()
|
||||
|
||||
class __GalleryButton(object):
|
||||
def __init__(self, gallery):
|
||||
self.gallery = gallery
|
||||
self.images = [ ]
|
||||
self.conditions = [ ]
|
||||
|
||||
def check_unlock(self):
|
||||
for i in self.conditions:
|
||||
if not i.check(True):
|
||||
return False
|
||||
|
||||
for i in self.images:
|
||||
if i.check_unlock(False):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def show(self):
|
||||
|
||||
all_prior = True
|
||||
|
||||
for i, img in enumerate(self.images):
|
||||
locked = not img.check_unlock(all_prior)
|
||||
img.show(locked, i, len(self.images))
|
||||
|
||||
renpy.transition(self.gallery.transition)
|
||||
|
||||
class Gallery(object):
|
||||
"""
|
||||
:doc: gallery class
|
||||
|
||||
This class supports the creation of an image gallery by handling the
|
||||
locking of images, providing an action that can show one or more images,
|
||||
and a providing method that creates buttons that use that action.
|
||||
|
||||
.. attribute:: transition
|
||||
|
||||
The transition that is used when changing images.
|
||||
|
||||
.. attribute:: locked_button
|
||||
|
||||
The default displayable used by make_button for a locked button.
|
||||
|
||||
.. attribute:: hover_border
|
||||
|
||||
The default hover border used by make_button.
|
||||
|
||||
.. attribute:: idle_border
|
||||
|
||||
The default idle border used by make_button.
|
||||
"""
|
||||
|
||||
transition = None
|
||||
|
||||
hover_border = None
|
||||
idle_border = None
|
||||
|
||||
locked_button = None
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# A map from button name (or image) to __GalleryButton object.
|
||||
self.buttons = { }
|
||||
|
||||
self.button_ = None
|
||||
self.image_ = None
|
||||
self.unlockable = None
|
||||
|
||||
def button(self, name):
|
||||
"""
|
||||
:doc: gallery method
|
||||
|
||||
Creates a new button, named `name`.
|
||||
|
||||
`name`
|
||||
The name of the button being created.
|
||||
"""
|
||||
|
||||
self.button_ = __GalleryButton(self)
|
||||
self.unlockable = self.button_
|
||||
self.buttons[name] = self.button_
|
||||
|
||||
def image(self, *displayables):
|
||||
"""
|
||||
:doc: gallery method
|
||||
|
||||
Adds a new image to the current button, where an image consists
|
||||
of one or more displayables.
|
||||
"""
|
||||
|
||||
self.image_ = __GalleryImage(self, displayables)
|
||||
self.button_.images.append(self.image_)
|
||||
self.unlockable = self.image_
|
||||
|
||||
display = image
|
||||
|
||||
def transform(self, *transforms):
|
||||
"""
|
||||
:doc: gallery method
|
||||
|
||||
Applies transforms to the last image registered. This should be
|
||||
called with the same number of transforms as the image has
|
||||
displayables. The transforms are applied to the corresponding
|
||||
displayables.
|
||||
|
||||
If a transform is None, the default transform is used.
|
||||
"""
|
||||
|
||||
self.image_.transforms = transforms
|
||||
|
||||
def unlock(self, *images):
|
||||
"""
|
||||
:doc: gallery method
|
||||
|
||||
A condition that takes one or more image names as argument, and
|
||||
is satisfied when all the named images have been seen by the
|
||||
player. The image names should be given as strings.
|
||||
"""
|
||||
|
||||
self.unlockable.conditions.append(__GalleryUnlockCondition(images))
|
||||
|
||||
def condition(self, expression):
|
||||
"""
|
||||
:doc: gallery method
|
||||
|
||||
A condition that is satisfied when an expression evaluates to true.
|
||||
|
||||
`expression`
|
||||
A string giving a python expression.
|
||||
"""
|
||||
|
||||
if not isinstance(expression, basestring):
|
||||
raise Exception("Gallery condition must be a string containing an expression.")
|
||||
|
||||
self.unlockable.conditions.append(__GalleryArbitraryCondition(expression))
|
||||
|
||||
def allprior(self):
|
||||
"""
|
||||
:doc: gallery method
|
||||
|
||||
A condition that is true if all prior images associated with the
|
||||
current button have been unlocked.
|
||||
"""
|
||||
|
||||
self.unlockable.conditions.append(__GalleryAllPriorCondition())
|
||||
|
||||
def unlock_image(self, *images):
|
||||
"""
|
||||
:doc: gallery method
|
||||
|
||||
A convenience method that is equivalent to calling image and unlock
|
||||
with the same parameters. This will cause an image to be displayed
|
||||
if it has been seen before.
|
||||
|
||||
The images should be specified as strings giving image names.
|
||||
"""
|
||||
|
||||
self.image(*images)
|
||||
self.unlock(*images)
|
||||
|
||||
def Action(self, name):
|
||||
"""
|
||||
:doc: gallery method
|
||||
|
||||
An action that displays the images associated with the given button
|
||||
name.
|
||||
"""
|
||||
|
||||
if name not in self.buttons:
|
||||
raise Exception("{0!r} is not a button defined in this gallery.".format(name))
|
||||
|
||||
b = self.buttons[name]
|
||||
|
||||
if b.check_unlock():
|
||||
return ui.invokesinnewcontext(b.show)
|
||||
else:
|
||||
return None
|
||||
|
||||
def make_button(self, name, unlocked, locked=None, hover_border=None, idle_border=None, **properties):
|
||||
"""
|
||||
:doc: gallery method
|
||||
|
||||
This creates a button that displays the images associated with the given
|
||||
button name.
|
||||
|
||||
`name`
|
||||
The name of the button that will be created.
|
||||
|
||||
`unlocked`
|
||||
A displayable that is displayed for this button when it is
|
||||
unlocked.
|
||||
|
||||
`locked`
|
||||
A displayable that is displayed for this button when it is
|
||||
locked. If None, the locked_button field of the gallery
|
||||
object is used instead.
|
||||
|
||||
`hover_border`
|
||||
A displayable that is used to overlay this button when when
|
||||
it is unlocked and has focus. If None, the hover_border
|
||||
field of the gallery object is used.
|
||||
|
||||
`idle_border`
|
||||
A displayable that is used to overlay this button when when
|
||||
it is unlocked but unfocused. If None, the idle_border
|
||||
field of the gallery object is used.
|
||||
|
||||
Additional keyword arguments become style properties of the
|
||||
created button object.
|
||||
"""
|
||||
|
||||
action = self.Action(name)
|
||||
|
||||
if locked is None:
|
||||
locked = self.locked_button
|
||||
|
||||
if hover_border is None:
|
||||
hover_border = self.hover_border
|
||||
|
||||
if idle_border is None:
|
||||
idle_border = self.idle_border
|
||||
|
||||
return Button(action=action, child=unlocked, insensitive_child=locked, hover_foreground=hover_border, idle_foreground=idle_border, **properties)
|
||||
|
||||
|
||||
init -1135:
|
||||
|
||||
# Displays a set of images in the gallery, or indicates that the images
|
||||
# are locked. This is given the following arguments:
|
||||
#
|
||||
# locked
|
||||
# True if the image is locked.
|
||||
# displayables
|
||||
# A list of transformed displayables that should be shown to the user.
|
||||
# index
|
||||
# A 1-based index of the image being shown.
|
||||
# count
|
||||
# The number of images attached to the current button.
|
||||
# gallery
|
||||
# The image gallery object.
|
||||
screen _gallery:
|
||||
if locked:
|
||||
add "#000"
|
||||
text "Image [index] of [count] locked." align (0.5, 0.5)
|
||||
else:
|
||||
for d in displayables:
|
||||
add d
|
||||
|
||||
@@ -1,914 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# This file consists of renpy functions that aren't expected to be
|
||||
# touched by the user too much. We reserve the _ prefix for names
|
||||
# defined in the library.
|
||||
|
||||
init -1180 python:
|
||||
|
||||
# These are settings that the user can tweak to control the
|
||||
# look of the main menu and the load/save/escape screens.
|
||||
|
||||
# basics: The version of Ren'Py this script is intended for, or
|
||||
# None if it's intended for the current version.
|
||||
config.script_version = None
|
||||
|
||||
# The minimum version of the module we work with. Don't change
|
||||
# this unless you know what you're doing.
|
||||
config.module_version = 6007001
|
||||
|
||||
# Should we warn the user if the module is missing or has a bad
|
||||
# version?
|
||||
config.module_warning = False
|
||||
|
||||
# basics: A map from a string that's displayed by the interface to
|
||||
# a translated value of that string.
|
||||
config.translations = { }
|
||||
|
||||
# Used internally to maintain compatiblity with old
|
||||
# translations of strings.
|
||||
config.old_names = { }
|
||||
|
||||
# basics: True if the skip indicator should be shown.
|
||||
config.skip_indicator = True
|
||||
|
||||
# basics: The width of a thumbnail.
|
||||
config.thumbnail_width = 66
|
||||
|
||||
# basics: The height of a thumbnail.
|
||||
config.thumbnail_height = 50
|
||||
|
||||
# basics: If not None, the default value of the fullscreen
|
||||
# preference when the game is first run.
|
||||
config.default_fullscreen = None
|
||||
|
||||
# basics: If not None, the default value of the text_cps
|
||||
# preference when the game is first run.
|
||||
config.default_text_cps = None
|
||||
|
||||
# If not None, the default value of afm_time
|
||||
config.default_afm_time = None
|
||||
|
||||
# If not None, the default value of afm_enable
|
||||
config.default_afm_enable = None
|
||||
|
||||
# Should we automatically define images?
|
||||
config.automatic_images = None
|
||||
|
||||
# Prefixes to strip from automatic images.
|
||||
config.automatic_images_strip = [ ]
|
||||
|
||||
# A save to automatically load, if it exists.
|
||||
config.auto_load = None
|
||||
|
||||
# Layers to clear when entering the menus.
|
||||
config.menu_clear_layers = [ ]
|
||||
|
||||
# Should we start the game with scene black or just scene?
|
||||
config.start_scene_black = False
|
||||
|
||||
# Voice and Sound samples.
|
||||
config.sample_sound = None
|
||||
config.sample_voice = None
|
||||
|
||||
# This is updated to give the user an idea of where a save is
|
||||
# taking place.
|
||||
save_name = ''
|
||||
|
||||
# Should the window be shown during transitions?
|
||||
_window_during_transitions = False
|
||||
|
||||
def _default_with_callback(trans, paired=None):
|
||||
if (_window_during_transitions and not
|
||||
renpy.context_nesting_level() and
|
||||
not renpy.count_displayables_in_layer('transient')):
|
||||
|
||||
# narrator("", interact=False)
|
||||
ui.window(style=style.say_window["empty"])
|
||||
ui.null()
|
||||
|
||||
return trans
|
||||
|
||||
config.with_callback = _default_with_callback
|
||||
|
||||
|
||||
def _default_empty_window():
|
||||
|
||||
who = _last_say_who
|
||||
|
||||
if who is not None:
|
||||
who = eval(who)
|
||||
|
||||
if who is None:
|
||||
who = narrator
|
||||
|
||||
if isinstance(who, NVLCharacter):
|
||||
nvl_show_core()
|
||||
else:
|
||||
store.narrator("", interact=False)
|
||||
|
||||
config.empty_window = _default_empty_window
|
||||
|
||||
style.skip_indicator = Style(style.default, heavy=True, help='The skip indicator.')
|
||||
style.skip_indicator.xpos = 10
|
||||
style.skip_indicator.ypos = 10
|
||||
|
||||
# This is used to jump to a label with a transition.
|
||||
def _intra_jumps_core(label, transition):
|
||||
renpy.transition(getattr(config, transition))
|
||||
renpy.jump(label)
|
||||
|
||||
_intra_jumps = renpy.curry(_intra_jumps_core)
|
||||
|
||||
# The function that's used to translate strings in the game menu.
|
||||
def _(s):
|
||||
"""
|
||||
Translates s into another language or something.
|
||||
"""
|
||||
|
||||
if s in config.translations:
|
||||
return config.translations[s]
|
||||
|
||||
if s in config.old_names and config.old_names[s] in config.translations:
|
||||
return config.translations[config.old_names[s]]
|
||||
|
||||
return s
|
||||
|
||||
config.extend_interjection = "{fast}"
|
||||
|
||||
def extend(what, interact=True):
|
||||
who = _last_say_who
|
||||
|
||||
if who is not None:
|
||||
who = eval(who)
|
||||
|
||||
if who is None:
|
||||
who = narrator
|
||||
|
||||
if isinstance(who, basestring):
|
||||
who = unknown.copy(who)
|
||||
|
||||
# This ensures extend works even with NVL mode.
|
||||
who.do_extend()
|
||||
|
||||
what = _last_say_what + config.extend_interjection + what
|
||||
|
||||
renpy.exports.say(who, what, interact=interact)
|
||||
store._last_say_what = what
|
||||
|
||||
extend.record_say = False
|
||||
|
||||
# Are the windows currently hidden?
|
||||
_windows_hidden = False
|
||||
|
||||
def toggle_skipping():
|
||||
|
||||
if not config.skipping:
|
||||
config.skipping = "slow"
|
||||
else:
|
||||
config.skipping = None
|
||||
|
||||
if renpy.context()._menu:
|
||||
renpy.jump("_noisy_return")
|
||||
else:
|
||||
renpy.restart_interaction()
|
||||
|
||||
config.help = None
|
||||
|
||||
def _help(help=None):
|
||||
|
||||
if help is None:
|
||||
help = config.help
|
||||
|
||||
if help is None:
|
||||
return
|
||||
|
||||
if renpy.has_label(help):
|
||||
renpy.call_in_new_context(help)
|
||||
return
|
||||
|
||||
_preferences.fullscreen = False
|
||||
|
||||
try:
|
||||
import webbrowser
|
||||
webbrowser.open_new("file:///" + config.basedir + "/" + help)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Called to make a screenshot happen.
|
||||
def _screenshot():
|
||||
import os.path
|
||||
import os
|
||||
import __main__
|
||||
|
||||
# Pick the directory to save into.
|
||||
dest = config.renpy_base.rstrip("/")
|
||||
|
||||
# Guess if we're an OSX App.
|
||||
if dest.endswith("/Contents/Resources/autorun"):
|
||||
# Go up 4 directories.
|
||||
dest = os.path.dirname(dest)
|
||||
dest = os.path.dirname(dest)
|
||||
dest = os.path.dirname(dest)
|
||||
dest = os.path.dirname(dest)
|
||||
|
||||
# Try to pick a filename.
|
||||
i = 1
|
||||
while True:
|
||||
fn = os.path.join(dest, config.screenshot_pattern % i)
|
||||
if not os.path.exists(fn):
|
||||
break
|
||||
i += 1
|
||||
|
||||
try:
|
||||
renpy.screenshot(fn)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if config.screenshot_callback is not None:
|
||||
config.screenshot_callback(fn)
|
||||
|
||||
def _screenshot_callback(fn):
|
||||
renpy.notify(_("Saved screenshot as %s.") % fn)
|
||||
|
||||
config.screenshot_callback = _screenshot_callback
|
||||
|
||||
_predict_screens = [ ]
|
||||
|
||||
init -1180 python hide:
|
||||
|
||||
import os
|
||||
config.screenshot_pattern = os.environ.get("RENPY_SCREENSHOT_PATTERN", "screenshot%04d.png")
|
||||
|
||||
def dump_styles():
|
||||
if config.developer:
|
||||
renpy.style.write_text("styles.txt")
|
||||
|
||||
# This is run when entering the game menu.
|
||||
config.game_menu_action = None
|
||||
|
||||
def invoke_game_menu():
|
||||
if renpy.context()._menu:
|
||||
if renpy.context()._main_menu:
|
||||
return
|
||||
else:
|
||||
renpy.jump("_noisy_return")
|
||||
else:
|
||||
if config.game_menu_action:
|
||||
renpy.display.behavior.run(config.game_menu_action)
|
||||
else:
|
||||
renpy.call_in_new_context('_game_menu')
|
||||
|
||||
def keymap_toggle_skipping():
|
||||
if renpy.context()._menu:
|
||||
return
|
||||
|
||||
toggle_skipping()
|
||||
|
||||
def fast_skip():
|
||||
if config.fast_skipping or config.developer:
|
||||
config.skipping = "fast"
|
||||
|
||||
if renpy.context()._menu:
|
||||
renpy.jump("_noisy_return")
|
||||
|
||||
def reload_game():
|
||||
if not config.developer:
|
||||
return
|
||||
|
||||
renpy.call_in_new_context("_save_reload_game")
|
||||
|
||||
def launch_editor():
|
||||
if not config.developer:
|
||||
return
|
||||
|
||||
filename, line = renpy.get_filename_line()
|
||||
renpy.launch_editor([ filename ], line)
|
||||
|
||||
# The default keymap. We might also want to put some of this into
|
||||
# the launcher.
|
||||
km = renpy.Keymap(
|
||||
rollback = renpy.rollback,
|
||||
screenshot = _screenshot,
|
||||
toggle_fullscreen = renpy.toggle_fullscreen,
|
||||
toggle_music = renpy.toggle_music,
|
||||
toggle_skip = keymap_toggle_skipping,
|
||||
fast_skip = fast_skip,
|
||||
game_menu = invoke_game_menu,
|
||||
hide_windows = renpy.curried_call_in_new_context("_hide_windows"),
|
||||
launch_editor = launch_editor,
|
||||
dump_styles = dump_styles,
|
||||
reload_game = reload_game,
|
||||
developer = renpy.curried_call_in_new_context("_developer"),
|
||||
quit = renpy.quit_event,
|
||||
iconify = renpy.iconify,
|
||||
help = _help,
|
||||
choose_renderer = renpy.curried_call_in_new_context("_choose_renderer"),
|
||||
)
|
||||
|
||||
config.underlay = [ km ]
|
||||
|
||||
def skip_indicator():
|
||||
|
||||
### skip_indicator default
|
||||
# (text) The style and placement of the skip indicator.
|
||||
|
||||
if config.skip_indicator is True:
|
||||
|
||||
if config.skipping == "slow" and config.skip_indicator:
|
||||
ui.text(_(u"Skip Mode"), style='skip_indicator')
|
||||
|
||||
if config.skipping == "fast" and config.skip_indicator:
|
||||
ui.text(_(u"Fast Skip Mode"), style='skip_indicator')
|
||||
|
||||
return
|
||||
|
||||
if not config.skip_indicator:
|
||||
return
|
||||
|
||||
if not config.skipping:
|
||||
return
|
||||
|
||||
ui.add(renpy.easy.displayable(config.skip_indicator))
|
||||
|
||||
config.overlay_functions.append(skip_indicator)
|
||||
|
||||
# Hyperlink functions. Duplicated in _errorhandling.rpym.
|
||||
def hyperlink_styler(target):
|
||||
return style.hyperlink_text
|
||||
|
||||
def hyperlink_function(target):
|
||||
if target.startswith("http:"):
|
||||
try:
|
||||
import webbrowser
|
||||
webbrowser.open(target)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
renpy.call_in_new_context(target)
|
||||
|
||||
style.default.hyperlink_functions = (hyperlink_styler, hyperlink_function, None)
|
||||
|
||||
# Prediction of screens.
|
||||
def predict():
|
||||
|
||||
for s in _predict_screens:
|
||||
if renpy.has_screen(s):
|
||||
renpy.predict_screen(s)
|
||||
|
||||
s = _game_menu_screen
|
||||
|
||||
if s is None:
|
||||
return
|
||||
|
||||
if renpy.has_screen(s):
|
||||
renpy.predict_screen(s)
|
||||
return
|
||||
|
||||
if s.endswith("_screen"):
|
||||
s = s[:-7]
|
||||
if renpy.has_screen(s):
|
||||
renpy.predict_screen(s)
|
||||
return
|
||||
|
||||
|
||||
config.predict_callbacks.append(predict)
|
||||
|
||||
def imagemap_auto_function(auto_param, variant):
|
||||
rv = auto_param % variant
|
||||
|
||||
if renpy.loadable(rv):
|
||||
return rv
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
config.imagemap_auto_function = imagemap_auto_function
|
||||
|
||||
|
||||
label _hide_windows:
|
||||
|
||||
if renpy.context()._menu:
|
||||
return
|
||||
|
||||
if _windows_hidden:
|
||||
return
|
||||
|
||||
python:
|
||||
_windows_hidden = True
|
||||
ui.saybehavior(dismiss=['dismiss', 'hide_windows'])
|
||||
ui.interact(suppress_overlay=True, suppress_window=True)
|
||||
_windows_hidden = False
|
||||
|
||||
return
|
||||
|
||||
|
||||
# This code here handles check for the correct version of the Ren'Py module.
|
||||
|
||||
label _save_reload_game:
|
||||
python hide:
|
||||
renpy.take_screenshot((config.thumbnail_width, config.thumbnail_height))
|
||||
renpy.music.stop()
|
||||
|
||||
ui.add(Solid((0, 0, 0, 255)))
|
||||
ui.text("Saving game...",
|
||||
size=32, xalign=0.5, yalign=0.5, color=(255, 255, 255, 255))
|
||||
|
||||
renpy.pause(0)
|
||||
|
||||
renpy.save("_reload-1", "reload save game")
|
||||
|
||||
ui.add(Solid((0, 0, 0, 255)))
|
||||
ui.text("Reloading script...",
|
||||
size=32, xalign=0.5, yalign=0.5, color=(255, 255, 255, 255))
|
||||
|
||||
renpy.pause(0)
|
||||
|
||||
renpy.utter_restart()
|
||||
|
||||
label _load_reload_game:
|
||||
|
||||
if not renpy.can_load("_reload-1"):
|
||||
return
|
||||
|
||||
python hide:
|
||||
renpy.rename_save("_reload-1", "_reload-2")
|
||||
|
||||
ui.add(Solid((0, 0, 0, 255)))
|
||||
ui.text("Reloading game...",
|
||||
size=32, xalign=0.5, yalign=0.5, color=(255, 255, 255, 255))
|
||||
|
||||
ui.pausebehavior(0)
|
||||
ui.interact(suppress_underlay=True, suppress_overlay=True)
|
||||
|
||||
renpy.load("_reload-2")
|
||||
|
||||
return
|
||||
|
||||
init -1001:
|
||||
image text = renpy.ParameterizedText(style="centered_text")
|
||||
|
||||
# Lock the library object.
|
||||
$ config.locked = True
|
||||
|
||||
|
||||
# Implement config.default_fullscreen and config.default_text_cps.
|
||||
init 1180 python:
|
||||
|
||||
if not persistent._set_preferences:
|
||||
persistent._set_preferences = True
|
||||
|
||||
if config.default_fullscreen is not None:
|
||||
_preferences.fullscreen = config.default_fullscreen
|
||||
|
||||
if config.default_text_cps is not None:
|
||||
_preferences.text_cps = config.default_text_cps
|
||||
|
||||
if config.default_afm_time is not None:
|
||||
_preferences.afm_time = config.default_afm_time
|
||||
|
||||
if config.default_afm_enable is not None:
|
||||
_preferences.afm_enable = config.default_afm_enable
|
||||
_preferences.using_afm_enable = True
|
||||
else:
|
||||
_preferences.afm_enable = True
|
||||
_preferences.using_afm_enable = False
|
||||
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Code that originated in 00gamemenu.rpy
|
||||
init -1180 python:
|
||||
|
||||
######################################################################
|
||||
# First up, we define a bunch of configuration variable, which the
|
||||
# user can change.
|
||||
|
||||
# menus: Music to play when entering the game menu.
|
||||
config.game_menu_music = None
|
||||
|
||||
# menus: Sound played when entering the library without clicking a
|
||||
# button.
|
||||
config.enter_sound = None
|
||||
|
||||
# menus: Sound played when leaving the library without clicking a
|
||||
# button.
|
||||
config.exit_sound = None
|
||||
|
||||
# menus: Transition that occurs when entering the game menu.
|
||||
config.enter_transition = None
|
||||
|
||||
# menus: Transition that occurs when leaving the game menu.
|
||||
config.exit_transition = None
|
||||
|
||||
# menus: Transition that's used when going from one screen to another.
|
||||
config.intra_transition = None
|
||||
|
||||
# menus: Transition that's used when going from the main to the game
|
||||
# menu.
|
||||
config.main_game_transition = None
|
||||
|
||||
# menus: Transition that's used when going from the game to the main
|
||||
# menu.
|
||||
config.game_main_transition = None
|
||||
|
||||
# menus: Transition that's used at the end of the game, when returning
|
||||
# to the main menu.
|
||||
config.end_game_transition = None
|
||||
|
||||
# menus: Transition that's used at the end of the splash screen, when
|
||||
# it is shown.
|
||||
config.end_splash_transition = None
|
||||
|
||||
# Transition that's used after the game is loaded.
|
||||
config.after_load_transition = None
|
||||
|
||||
# basics: True if autosave should be used.
|
||||
config.has_autosave = True
|
||||
|
||||
# basics: True if quicksave has been enabled.
|
||||
config.has_quicksave = False
|
||||
|
||||
# A list of layers to clear when entering the main and game menus.
|
||||
config.clear_layers = [ ]
|
||||
|
||||
# The _window_subtitle used inside menus.
|
||||
config.menu_window_subtitle = ''
|
||||
|
||||
# The screen that we go to when entering the game menu.
|
||||
_game_menu_screen = None
|
||||
|
||||
style.error_root = Style(style.default)
|
||||
style.error_title = Style(style.default)
|
||||
style.error_body = Style(style.default)
|
||||
|
||||
def _show_exception(title, message):
|
||||
|
||||
ui.window(style='error_root')
|
||||
ui.vbox()
|
||||
|
||||
ui.text(title, style='error_title')
|
||||
ui.text("")
|
||||
ui.text(message, style='error_body')
|
||||
ui.text("")
|
||||
ui.text(_(u"Please click to continue."), style='error_body')
|
||||
|
||||
ui.close()
|
||||
|
||||
ui.saybehavior()
|
||||
|
||||
ui.interact()
|
||||
|
||||
def _enter_menu():
|
||||
config.skipping = None
|
||||
|
||||
renpy.movie_stop(only_fullscreen=True)
|
||||
renpy.take_screenshot((config.thumbnail_width, config.thumbnail_height))
|
||||
|
||||
for i in config.menu_clear_layers:
|
||||
renpy.scene(layer=i)
|
||||
|
||||
renpy.context()._menu = True
|
||||
renpy.context()._main_menu = False
|
||||
renpy.context_dynamic("main_menu")
|
||||
renpy.context_dynamic("_window_subtitle")
|
||||
renpy.context_dynamic("_window")
|
||||
|
||||
store.main_menu = False
|
||||
store._window_subtitle = config.menu_window_subtitle
|
||||
store._window = False
|
||||
|
||||
store.mouse_visible = True
|
||||
store.suppress_overlay = True
|
||||
ui.clear()
|
||||
|
||||
for i in config.clear_layers:
|
||||
renpy.scene(layer=i)
|
||||
|
||||
# Run at the end of init, to set up autosaving based on the user's
|
||||
# choices.
|
||||
init 1180 python:
|
||||
|
||||
if config.has_autosave:
|
||||
config.autosave_slots = 10
|
||||
else:
|
||||
config.autosave_frequency = None
|
||||
|
||||
# Factored this all into one place, to make our lives a bit easier.
|
||||
label _enter_game_menu:
|
||||
$ _enter_menu()
|
||||
|
||||
$ renpy.transition(config.enter_transition)
|
||||
|
||||
if renpy.has_label("enter_game_menu"):
|
||||
call expression "enter_game_menu" from _call_enter_game_menu_1
|
||||
|
||||
if config.game_menu_music:
|
||||
$ renpy.music.play(config.game_menu_music, if_changed=True)
|
||||
|
||||
return
|
||||
|
||||
# Entry points from the game into menu-space.
|
||||
label _game_menu(_game_menu_screen=_game_menu_screen):
|
||||
if not _game_menu_screen:
|
||||
return
|
||||
|
||||
$ renpy.play(config.enter_sound)
|
||||
|
||||
call _enter_game_menu from _call__enter_game_menu_0
|
||||
|
||||
if renpy.has_label("game_menu"):
|
||||
jump expression "game_menu"
|
||||
|
||||
if renpy.has_screen(_game_menu_screen):
|
||||
$ renpy.show_screen(_game_menu_screen)
|
||||
$ ui.interact()
|
||||
jump _noisy_return
|
||||
|
||||
jump expression _game_menu_screen
|
||||
|
||||
label _game_menu_save:
|
||||
call _enter_game_menu from _call__enter_game_menu_1
|
||||
|
||||
if renpy.has_label("_save_screen"):
|
||||
jump expression "_save_screen"
|
||||
else:
|
||||
jump expression "save_screen"
|
||||
|
||||
label _game_menu_load:
|
||||
call _enter_game_menu from _call__enter_game_menu_2
|
||||
|
||||
if renpy.has_label("_load_screen"):
|
||||
jump expression "_load_screen"
|
||||
else:
|
||||
jump expression "load_screen"
|
||||
|
||||
label _game_menu_preferences:
|
||||
call _enter_game_menu from _call__enter_game_menu_3
|
||||
|
||||
if renpy.has_label("_prefs_screen"):
|
||||
jump expression "_prefs_screen"
|
||||
else:
|
||||
jump expression "preferences_screen"
|
||||
|
||||
label _quit:
|
||||
$ renpy.quit()
|
||||
|
||||
label _return_skipping:
|
||||
$ config.skipping = "slow"
|
||||
jump _return
|
||||
|
||||
# Make some noise, then return.
|
||||
label _noisy_return:
|
||||
$ renpy.play(config.exit_sound)
|
||||
|
||||
# Return to the game.
|
||||
label _return:
|
||||
|
||||
if renpy.context()._main_menu:
|
||||
$ renpy.transition(config.game_main_transition)
|
||||
jump _main_menu_screen
|
||||
|
||||
$ renpy.transition(config.exit_transition)
|
||||
|
||||
return
|
||||
|
||||
label _confirm_quit:
|
||||
|
||||
if renpy.has_label("confirm_quit"):
|
||||
jump expression "confirm_quit"
|
||||
elif renpy.has_label("_compat_confirm_quit"):
|
||||
jump expression "_compat_confirm_quit"
|
||||
else:
|
||||
jump expression "_quit_prompt"
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Code that originated in 00mainmenu.rpy
|
||||
|
||||
init -1180 python hide:
|
||||
|
||||
# menus: Music to play at the main menu.
|
||||
config.main_menu_music = None
|
||||
|
||||
# advanced: Callbacks to run at start.
|
||||
config.start_callbacks = [ ]
|
||||
|
||||
|
||||
# This fixes up the context, if necessary, then calls the real
|
||||
# after_load.
|
||||
label _after_load:
|
||||
$ renpy.context()._menu = False
|
||||
$ renpy.context()._main_menu = False
|
||||
|
||||
if config.after_load_transition:
|
||||
$ renpy.transition(config.after_load_transition, force=True)
|
||||
|
||||
if renpy.has_label("after_load"):
|
||||
jump expression "after_load"
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
# This is the true starting point of the program. Sssh... Don't
|
||||
# tell anyone.
|
||||
label _start:
|
||||
|
||||
python hide:
|
||||
renpy.context()._menu = False
|
||||
renpy.context()._main_menu = False
|
||||
|
||||
for i in config.start_callbacks:
|
||||
i()
|
||||
|
||||
$ renpy.block_rollback()
|
||||
|
||||
call _gl_test
|
||||
|
||||
call _load_reload_game from _call__load_reload_game_1
|
||||
|
||||
if not _restart and config.auto_load and renpy.can_load(config.auto_load):
|
||||
$ renpy.load(config.auto_load)
|
||||
|
||||
if config.start_scene_black:
|
||||
scene black
|
||||
else:
|
||||
scene
|
||||
|
||||
if not _restart:
|
||||
$ ui.pausebehavior(0)
|
||||
$ ui.interact(suppress_underlay=True, suppress_overlay=True)
|
||||
|
||||
$ renpy.block_rollback()
|
||||
|
||||
$ _old_game_menu_screen = _game_menu_screen
|
||||
$ _old_predict_screens = _predict_screens
|
||||
$ _game_menu_screen = None
|
||||
$ _predict_screens = [ 'main_menu' ]
|
||||
|
||||
if renpy.has_label("splashscreen") and not _restart:
|
||||
call expression "splashscreen" from _call_splashscreen_1
|
||||
|
||||
$ _game_menu_screen = _old_game_menu_screen
|
||||
$ del _old_game_menu_screen
|
||||
|
||||
$ renpy.block_rollback()
|
||||
|
||||
if config.main_menu_music:
|
||||
$ renpy.music.play(config.main_menu_music, if_changed=True)
|
||||
else:
|
||||
$ renpy.music.stop()
|
||||
|
||||
# Clean out any residual scene from the splashscreen.
|
||||
if config.start_scene_black:
|
||||
scene black
|
||||
else:
|
||||
scene
|
||||
|
||||
|
||||
# This has to be python, to deal with a case where _restart may
|
||||
# change across a shift-reload.
|
||||
python:
|
||||
if _restart is None:
|
||||
renpy.transition(config.end_splash_transition)
|
||||
else:
|
||||
renpy.transition(_restart[0])
|
||||
renpy.jump(_restart[1])
|
||||
|
||||
label _invoke_main_menu:
|
||||
|
||||
# Again, this has to be python.
|
||||
python:
|
||||
if _restart:
|
||||
renpy.call_in_new_context(_restart[2])
|
||||
else:
|
||||
renpy.call_in_new_context("_main_menu")
|
||||
|
||||
|
||||
# If the main menu returns, then start the game.
|
||||
jump start
|
||||
|
||||
# At this point, we've been switched into a new context. So we
|
||||
# initialize it.
|
||||
label _main_menu(_main_menu_screen="_main_menu_screen"):
|
||||
|
||||
$ _enter_menu()
|
||||
|
||||
python:
|
||||
renpy.dynamic("_load_prompt")
|
||||
_load_prompt = False
|
||||
|
||||
renpy.context()._main_menu = True
|
||||
store.main_menu = True
|
||||
|
||||
jump expression _main_menu_screen
|
||||
|
||||
# This is called to show the main menu to the user.
|
||||
label _main_menu_screen:
|
||||
|
||||
# Let the user completely override the main menu. (But please note
|
||||
# it still lives in the menu context, rather than the game context.)
|
||||
if renpy.has_label("main_menu"):
|
||||
jump expression "main_menu"
|
||||
|
||||
# New name.
|
||||
elif renpy.has_label("main_menu_screen"):
|
||||
jump expression "main_menu_screen"
|
||||
|
||||
# Compatibility name.
|
||||
elif renpy.has_label("_library_main_menu"):
|
||||
jump expression "_library_main_menu"
|
||||
|
||||
return
|
||||
|
||||
init 1180 python hide:
|
||||
|
||||
def create_automatic_images():
|
||||
|
||||
seps = config.automatic_images
|
||||
|
||||
if seps is True:
|
||||
seps = [ ' ', '/', '_' ]
|
||||
|
||||
for dir, fn in renpy.loader.listdirfiles():
|
||||
|
||||
if fn.startswith("_"):
|
||||
continue
|
||||
|
||||
# Only .png and .jpg
|
||||
if not fn.lower().endswith(".png") and not fn.lower().endswith(".jpg"):
|
||||
continue
|
||||
|
||||
# Strip the extension, replace slashes.
|
||||
shortfn = fn[:-4].replace("\\", "/")
|
||||
|
||||
# Determine the name.
|
||||
name = ( shortfn, )
|
||||
for sep in seps:
|
||||
name = tuple(j for i in name for j in i.split(sep))
|
||||
|
||||
# Strip name components.
|
||||
while name:
|
||||
for i in config.automatic_images_strip:
|
||||
if name[0] == i:
|
||||
name = name[1:]
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
# Only names of 2 components or more.
|
||||
if len(name) < 2:
|
||||
continue
|
||||
|
||||
# Reject if it already exists.
|
||||
if name in renpy.display.image.images:
|
||||
continue
|
||||
|
||||
renpy.image(name, fn)
|
||||
|
||||
if config.automatic_images:
|
||||
create_automatic_images()
|
||||
|
||||
|
||||
# After init, make some changes based on if config.developer is True.
|
||||
init 1180 python hide:
|
||||
|
||||
if config.developer:
|
||||
if config.debug_sound is None:
|
||||
config.debug_sound = True
|
||||
|
||||
renpy.load_module("_developer")
|
||||
|
||||
|
||||
|
||||
# Entry point for the developer screen. The rest of it is loaded from
|
||||
# _developer.rpym
|
||||
label _developer:
|
||||
|
||||
if not config.developer:
|
||||
return
|
||||
|
||||
$ _enter_menu()
|
||||
|
||||
jump expression "_developer_screen"
|
||||
|
||||
|
||||
# Translations.
|
||||
init -1180 python:
|
||||
|
||||
def _language_activate():
|
||||
|
||||
if persistent._language:
|
||||
language = persistent._language
|
||||
else:
|
||||
language = "translations"
|
||||
|
||||
if renpy.loadable(language + ".rpt"):
|
||||
config.translator = renpy.Translator(language)
|
||||
else:
|
||||
config.translator = None
|
||||
|
||||
_language_activate()
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# Common stuff that's used by the various Ren'Py menus. This includes
|
||||
# the default definitions of config.main_menu and config.game_menu, as
|
||||
# well as the default definitions of the various preferences (and the objects
|
||||
# holding those preferences)
|
||||
|
||||
init -1150 python:
|
||||
|
||||
config.main_menu = [
|
||||
(u"Start Game", "start", "True"),
|
||||
(u"Load Game", _intra_jumps("load_screen", "main_game_transition"), "True"),
|
||||
(u"Preferences", _intra_jumps("preferences_screen", "main_game_transition"), "True"),
|
||||
(u"Help", _help, "True", "config.help"),
|
||||
(u"Quit", ui.jumps("_quit"), "True"),
|
||||
]
|
||||
|
||||
config.game_menu = [
|
||||
( None, u"Return", ui.jumps("_return"), 'True'),
|
||||
( "preferences", u"Preferences", _intra_jumps("preferences_screen", "intra_transition"), 'True' ),
|
||||
( "save", u"Save Game", _intra_jumps("save_screen", "intra_transition"), 'not main_menu' ),
|
||||
( "load", u"Load Game", _intra_jumps("load_screen", "intra_transition"), 'True'),
|
||||
( None, u"Main Menu", ui.callsinnewcontext("_main_menu_prompt"), 'not main_menu' ),
|
||||
( "help", u"Help", _help, "True", "config.help"),
|
||||
( None, u"Quit", ui.callsinnewcontext("_quit_prompt"), 'True' ),
|
||||
]
|
||||
|
||||
label _quit_prompt:
|
||||
$ renpy.loadsave.force_autosave()
|
||||
|
||||
if layout.yesno_prompt(None, layout.QUIT):
|
||||
jump _quit
|
||||
else:
|
||||
return
|
||||
|
||||
label _main_menu_prompt:
|
||||
$ renpy.loadsave.force_autosave()
|
||||
|
||||
if layout.yesno_prompt(None, layout.MAIN_MENU):
|
||||
$ renpy.full_restart(transition=config.game_main_transition)
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# This file contains the code to implement Ren'Py's music room function,
|
||||
# which consists of the ability to set up a playlist (the aforementioned
|
||||
# "music room"), and then a series of actions that let the player
|
||||
# navigate through the music room.
|
||||
|
||||
init -1135 python:
|
||||
|
||||
class __MusicRoomPlay(Action):
|
||||
"""
|
||||
The action returned by MusicRoom.Play when called with a file.
|
||||
"""
|
||||
|
||||
def __init__(self, mr, filename):
|
||||
self.mr = mr
|
||||
self.filename = filename
|
||||
self.selected = self.get_selected()
|
||||
|
||||
def __call__(self):
|
||||
self.mr.play(self.filename, 0)
|
||||
|
||||
def get_sensitive(self):
|
||||
return self.mr.is_unlocked(self.filename)
|
||||
|
||||
def get_selected(self):
|
||||
return renpy.music.get_playing(self.mr.channel) == self.filename
|
||||
|
||||
def periodic(self, st):
|
||||
if self.selected != self.get_selected():
|
||||
renpy.restart_interaction()
|
||||
|
||||
return .1
|
||||
|
||||
class MusicRoom(object):
|
||||
"""
|
||||
:doc: music_room class
|
||||
|
||||
A music room that contains a series of songs that can be unlocked
|
||||
by the user, and actions that can play entries from the list in
|
||||
order.
|
||||
"""
|
||||
|
||||
def __init__(self, channel="music", fadeout=0.0, fadein=0.0):
|
||||
"""
|
||||
`channel`
|
||||
The channel that this music room will operate on.
|
||||
|
||||
`fadeout`
|
||||
The number of seconds it takes to fade out the old
|
||||
music when changing tracks.
|
||||
|
||||
`fadein`
|
||||
The number of seconds it takes to fade in the new
|
||||
music when changing tracks.
|
||||
"""
|
||||
|
||||
self.channel = channel
|
||||
self.fadeout = fadeout
|
||||
self.fadein = fadein
|
||||
|
||||
# The list of strings giving the titles of songs that make up the
|
||||
# playlist.
|
||||
self.playlist = [ ]
|
||||
|
||||
# A set of filenames, so we can quickly check if a valid filename
|
||||
# has been provided.
|
||||
self.filenames = set()
|
||||
|
||||
# The set of songs that are always unlocked.
|
||||
self.always_unlocked = set()
|
||||
|
||||
|
||||
def add(self, filename, always_unlocked=False):
|
||||
"""
|
||||
:doc: music_room method
|
||||
|
||||
Adds the music file `filename` to this music room. The music room
|
||||
will play unlocked files in the order that they are added to the
|
||||
room.
|
||||
|
||||
`always_unlocked`
|
||||
If true, the music file will be always unlocked. This allows
|
||||
the file to show up in the music room before it has been
|
||||
played in the game.
|
||||
"""
|
||||
|
||||
self.playlist.append(filename)
|
||||
self.filenames.add(filename)
|
||||
|
||||
if always_unlocked:
|
||||
self.always_unlocked.add(filename)
|
||||
|
||||
def is_unlocked(self, filename):
|
||||
"""
|
||||
:doc: music_room method
|
||||
|
||||
Returns true if the filename has been unlocked (or is always
|
||||
unlocked), and false if it is still locked.
|
||||
"""
|
||||
|
||||
if filename in self.always_unlocked:
|
||||
return True
|
||||
|
||||
return renpy.seen_audio(filename)
|
||||
|
||||
def unlocked_playlist(self):
|
||||
"""
|
||||
Returns a list of filenames in the playlist that have been
|
||||
unlocked.
|
||||
"""
|
||||
|
||||
return [ i for i in self.playlist if self.is_unlocked(i) ]
|
||||
|
||||
def play(self, filename=None, offset=0):
|
||||
"""
|
||||
Starts the music room playing. The file we start playing with is
|
||||
selected in two steps.
|
||||
|
||||
If `filename` is an unlocked file, we start by playing it.
|
||||
Otherwise, we start by playing the currently playing file, and if
|
||||
that doesn't exist or isn't unlocked, we start with the first file.
|
||||
|
||||
We then apply `offset`. If `offset` is positive, we advance that many
|
||||
files, otherwise we go back that many files.
|
||||
|
||||
The selected file is then played.
|
||||
|
||||
"""
|
||||
|
||||
playlist = self.unlocked_playlist()
|
||||
|
||||
if not playlist:
|
||||
return
|
||||
|
||||
if filename is None:
|
||||
filename = renpy.music.get_playing(channel=self.channel)
|
||||
|
||||
try:
|
||||
idx = playlist.index(filename)
|
||||
except ValueError:
|
||||
idx = 0
|
||||
|
||||
idx = (idx + offset) % len(playlist)
|
||||
|
||||
playlist = playlist[idx:] + playlist[:idx]
|
||||
|
||||
renpy.music.play(playlist, channel=self.channel, fadeout=self.fadeout, fadein=self.fadein)
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stops the music from playing.
|
||||
"""
|
||||
|
||||
renpy.music.stop(channel=self.channel, fadeout=self.fadeout)
|
||||
|
||||
def next(self):
|
||||
"""
|
||||
Plays the next file in the playlist.
|
||||
"""
|
||||
|
||||
return self.play(None, 1)
|
||||
|
||||
def previous(self):
|
||||
"""
|
||||
Plays the previous file in the playlist.
|
||||
"""
|
||||
|
||||
return self.play(None, -1)
|
||||
|
||||
def Play(self, filename=None):
|
||||
"""
|
||||
:doc: music_room method
|
||||
|
||||
Causes the music room to start playing. If `filename` is given, that
|
||||
file begins playing. Otherwise, the currently playing file starts
|
||||
over (if it's unlocked), or the first file starts playing.
|
||||
|
||||
If `filename` is given, buttons with this action will be insensitive
|
||||
while `filename` is locked, and will be selected when `filename`
|
||||
is playing.
|
||||
"""
|
||||
|
||||
if filename is None:
|
||||
return self.play
|
||||
|
||||
if filename not in self.filenames:
|
||||
raise Exception("{0!r} is not a filename registered with this music room.".format(filename))
|
||||
|
||||
return __MusicRoomPlay(self, filename)
|
||||
|
||||
def Stop(self):
|
||||
"""
|
||||
:doc: music_room method
|
||||
|
||||
Stops the music.
|
||||
"""
|
||||
|
||||
return self.stop
|
||||
|
||||
|
||||
def Next(self):
|
||||
"""
|
||||
:doc: music_room method
|
||||
|
||||
An action that causes the music room to play the next unlocked file
|
||||
in the playlist.
|
||||
"""
|
||||
|
||||
return self.next
|
||||
|
||||
def Previous(self):
|
||||
"""
|
||||
:doc: music_room method
|
||||
|
||||
An action that causes the music room to play the previous unlocked
|
||||
file in the playlist.
|
||||
"""
|
||||
|
||||
return self.previous
|
||||
@@ -1,328 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# This file is responsible for creating and defining the default styles
|
||||
# used by the system.
|
||||
|
||||
# This file should be considered part of the Ren'Py library, and not
|
||||
# something that needs to be modified by the user. Instead, just update
|
||||
# the appropriate style property in an init: block in your script.
|
||||
#
|
||||
# For example, to change the default window backgrounds to a
|
||||
# transparent dark red, add:
|
||||
#
|
||||
# init:
|
||||
# $ style.window.background = "#8008"
|
||||
#
|
||||
# to your script. No need to mess around here, it will just make your
|
||||
# life harder when a new version of Ren'Py is released.
|
||||
|
||||
init -1200 python hide:
|
||||
|
||||
# Style Declarations #################################################
|
||||
|
||||
style.default = Style(None, help='root of style hierarchy')
|
||||
style.text = Style(style.default, help='style of text')
|
||||
|
||||
style.fixed = Style(style.default, help='fixed layouts')
|
||||
style.hbox = Style(style.default, help='horizontal boxes')
|
||||
style.vbox = Style(style.default, help='vertical boxes')
|
||||
style.grid = Style(style.default, help='grid layouts')
|
||||
style.side = Style(style.default, help='side layouts')
|
||||
|
||||
style.window = Style(style.default, help='windows created with ui.window')
|
||||
|
||||
style.image_placement = Style(style.default, help='default placement of images on the screen')
|
||||
style.image = Style(style.default, help="default style of images")
|
||||
|
||||
style.motion = Style(style.default, help="default style of motions and zooms.")
|
||||
style.animation = Style(style.default, help="default style of animations.")
|
||||
|
||||
style.say_label = Style(style.default, help='the name of the character speaking dialogue.')
|
||||
style.say_dialogue = Style(style.default, help='used for dialogue text')
|
||||
style.say_thought = Style(style.default, help='used by the default narrator')
|
||||
style.say_window = Style(style.window, help='windows containing dialogue and thoughts')
|
||||
style.say_who_window = Style(style.window, help='window containing the label in two-window-say mode')
|
||||
style.say_two_window_vbox = Style(style.vbox, help='vbox containing the two windows in two-window-say mode')
|
||||
style.say_vbox = Style(style.vbox, help='contains the label (if present) and the body of dialogue')
|
||||
|
||||
style.menu = Style(style.default, help='the vbox containing an in-game menu')
|
||||
style.menu_caption = Style(style.default, help='in-game menu caption text')
|
||||
style.menu_choice = Style(style.default, help='text of an in-game menu choice')
|
||||
style.menu_choice_button = Style(style.default, help='buttons containing in-game menu choices')
|
||||
style.menu_choice_chosen = Style(style.menu_choice, help='text of an in-game menu choice that has been chosen')
|
||||
style.menu_choice_chosen_button = Style(style.menu_choice_button, help='buttons containing chosen in-game menu choices')
|
||||
style.menu_window = Style(style.window, help='a window containing a menu')
|
||||
|
||||
style.input = Style(style.default, help='style of an input control')
|
||||
style.input_text = Style(style.input, help='text of an input box')
|
||||
style.input_prompt = Style(style.default, help='prompt of an input box')
|
||||
style.input_window = Style(style.window, help='window of an input box')
|
||||
|
||||
style.centered_window = Style(style.default, help='window containing centered text')
|
||||
style.centered_text = Style(style.default, help='centered text')
|
||||
|
||||
style.imagemap = Style(style.image_placement, help='default style of imagemaps')
|
||||
style.hotspot = Style(style.default, help='default style of hotspots inside imagemaps')
|
||||
style.hotbar = Style(style.default, help='default style of hotbars inside imagemaps')
|
||||
style.imagemap_button = style.hotspot
|
||||
|
||||
style.image_button = Style(style.default, help='default style of image buttons')
|
||||
style.image_button_image = Style(style.default, help='default style of images inside image buttons')
|
||||
|
||||
style.hyperlink = Style(style.default, help=None) # ignored
|
||||
style.hyperlink_text = Style(style.default, help='hyperlinked text')
|
||||
style.ruby_text = Style(style.default, help='ruby text')
|
||||
|
||||
style.viewport = Style(style.default, help='default style of viewports')
|
||||
style.transform = Style(style.motion, help='default style of transforms')
|
||||
|
||||
style.list = Style(style.default)
|
||||
style.list_box = Style(style.vbox)
|
||||
style.list_row = Style(style.default)
|
||||
style.list_row_box = Style(style.hbox)
|
||||
style.list_spacer = Style(style.default)
|
||||
style.list_text = Style(style.default)
|
||||
|
||||
style.tile = Style(style.default, help='default style of tile')
|
||||
|
||||
# The base styles that can be customized by themes.
|
||||
|
||||
style.frame = Style(style.default, help='base style for frames.')
|
||||
style.menu_frame = Style(style.frame, help='base style for frames used in the game and main menus.')
|
||||
|
||||
style.button = Style(style.default, help='base style for buttons.')
|
||||
style.button_text = Style(style.default, help='base style for button text')
|
||||
|
||||
style.small_button = Style(style.button, help="base style for small buttons")
|
||||
style.small_button_text = Style(style.button_text, help="base style for small button text")
|
||||
style.radio_button = Style(style.button, help="base style for radio buttons")
|
||||
style.radio_button_text = Style(style.button_text, help="base style for radio button text")
|
||||
style.check_button = Style(style.button, help="base style for check buttons")
|
||||
style.check_button_text = Style(style.button_text, help="base style for check button text")
|
||||
|
||||
style.large_button = Style(style.default, help="base style for large buttons")
|
||||
style.large_button_text = Style(style.default, help="base style for large button text")
|
||||
|
||||
style.label = Style(style.default, help="base style for windows surrounding labels")
|
||||
style.label_text = Style(style.default, help="base style for label text")
|
||||
|
||||
style.prompt = Style(style.default, help="base style for windows surrounding prompts")
|
||||
style.prompt_text = Style(style.default, help="base style for prompt text")
|
||||
|
||||
style.bar = Style(style.default, help='base style for horizontal bars')
|
||||
style.vbar = Style(style.default, help='base style for vertical bars')
|
||||
|
||||
style.slider = Style(style.default, help='base style for horizontal sliders')
|
||||
style.vslider = Style(style.default, help='base style for vertical sliders')
|
||||
|
||||
style.scrollbar = Style(style.default, help='base style for horizontal scrollbars')
|
||||
style.vscrollbar = Style(style.default, help='base style for vertical scollbars')
|
||||
|
||||
style.mm_root = Style(style.default, help="main menu root window")
|
||||
style.gm_root = Style(style.default, help="game menu root window")
|
||||
|
||||
|
||||
init -1090 python:
|
||||
|
||||
# Colors #############################################################
|
||||
|
||||
# The Default Style ###################################################
|
||||
|
||||
# Text properties.
|
||||
style.default.font = "DejaVuSans.ttf"
|
||||
style.default.language = "unicode"
|
||||
style.default.antialias = True
|
||||
style.default.size = 22
|
||||
style.default.color = (255, 255, 255, 255)
|
||||
style.default.black_color = (0, 0, 0, 255)
|
||||
style.default.bold = False
|
||||
style.default.italic = False
|
||||
style.default.underline = False
|
||||
style.default.strikethrough = False
|
||||
style.default.kerning = 0.0
|
||||
style.default.drop_shadow = None
|
||||
style.default.drop_shadow_color = (0, 0, 0, 255)
|
||||
style.default.outlines = [ ]
|
||||
style.default.minwidth = 0
|
||||
style.default.text_align = 0
|
||||
style.default.justify = False
|
||||
style.default.text_y_fudge = 0
|
||||
style.default.first_indent = 0
|
||||
style.default.rest_indent = 0
|
||||
style.default.line_spacing = 0
|
||||
style.default.line_leading = 0
|
||||
style.default.line_overlap_split = 0
|
||||
style.default.layout = "tex"
|
||||
style.default.subtitle_width = 0.9
|
||||
style.default.slow_cps = None
|
||||
style.default.slow_cps_multiplier = 1.0
|
||||
style.default.slow_abortable = False
|
||||
# style.default.hyperlink_functions (set in 00library.rpy)
|
||||
|
||||
# Window properties.
|
||||
style.default.background = None
|
||||
style.default.xpadding = 0
|
||||
style.default.ypadding = 0
|
||||
style.default.xmargin = 0
|
||||
style.default.ymargin = 0
|
||||
style.default.xfill = False
|
||||
style.default.yfill = False
|
||||
style.default.xminimum = 0 # Includes margins and padding.
|
||||
style.default.yminimum = 0 # Includes margins and padding.
|
||||
|
||||
# Placement properties.
|
||||
style.default.xpos = None # 0
|
||||
style.default.ypos = None # 0
|
||||
style.default.xanchor = None # 0
|
||||
style.default.yanchor = None # 0
|
||||
style.default.xmaximum = None
|
||||
style.default.ymaximum = None
|
||||
style.default.xoffset = 0
|
||||
style.default.yoffset = 0
|
||||
style.default.subpixel = False
|
||||
|
||||
# Sound properties.
|
||||
style.default.sound = None
|
||||
|
||||
# Box properties.
|
||||
style.default.spacing = 0
|
||||
style.default.first_spacing = None
|
||||
style.default.box_layout = None
|
||||
style.default.box_wrap = False
|
||||
|
||||
# Focus properties.
|
||||
style.default.focus_mask = None
|
||||
style.default.focus_rect = None
|
||||
|
||||
# Bar properties.
|
||||
style.default.fore_bar = Null()
|
||||
style.default.aft_bar = Null()
|
||||
style.default.thumb = None
|
||||
style.default.thumb_shadow = None
|
||||
style.default.left_gutter = 0
|
||||
style.default.right_gutter = 0
|
||||
style.default.thumb_offset = 0
|
||||
style.default.unscrollable = None
|
||||
|
||||
# Misc.
|
||||
style.default.activate_sound = None
|
||||
style.default.clipping = False
|
||||
|
||||
# Boxes.
|
||||
style.hbox.box_layout = 'horizontal'
|
||||
style.vbox.box_layout = 'vertical'
|
||||
|
||||
# Motions, zooms, rotozooms, and transforms.
|
||||
style.motion.xanchor = 0
|
||||
style.motion.yanchor = 0
|
||||
style.motion.xpos = 0
|
||||
style.motion.ypos = 0
|
||||
|
||||
# Windows.
|
||||
style.window.background = Solid((0, 0, 0, 192))
|
||||
style.window.xpadding = 6
|
||||
style.window.ypadding = 6
|
||||
style.window.xmargin = 0
|
||||
style.window.ymargin = 0
|
||||
style.window.xfill = True
|
||||
style.window.yfill = False
|
||||
style.window.yminimum = 150 # Includes margins and padding.
|
||||
style.window.xalign = 0.5
|
||||
style.window.yalign = 1.0
|
||||
|
||||
# Dialogue
|
||||
style.say_label.bold = True
|
||||
style.say_vbox.spacing = 8
|
||||
|
||||
# Two window styles.
|
||||
style.say_who_window.xminimum = 200
|
||||
style.say_who_window.yminimum = 34
|
||||
style.say_who_window.xfill = False
|
||||
style.say_who_window.xalign = 0
|
||||
|
||||
style.say_two_window_vbox.yalign = 1.0
|
||||
|
||||
# Menus.
|
||||
style.menu_choice.idle_color = "#0ff"
|
||||
style.menu_choice.hover_color = "#ff0"
|
||||
style.input.color = "#ff0"
|
||||
|
||||
# Styles used by centered.
|
||||
style.centered_window.xalign = 0.5
|
||||
style.centered_window.xfill = False
|
||||
style.centered_window.yalign = 0.5
|
||||
style.centered_window.yfill = False
|
||||
style.centered_window.xpadding = 10
|
||||
|
||||
style.centered_text.textalign = 0.5
|
||||
style.centered_text.xalign = 0.5
|
||||
style.centered_text.yalign = 0.5
|
||||
style.centered_text.layout = "subtitle"
|
||||
|
||||
# Hyperlinks.
|
||||
style.hyperlink_text.underline = True
|
||||
style.hyperlink_text.hover_color = "#0ff"
|
||||
style.hyperlink_text.idle_color = "#08f"
|
||||
|
||||
# Ruby.
|
||||
style.ruby_text.size = 22
|
||||
style.ruby_text.xoffset = 0
|
||||
style.default.ruby_style = style.ruby_text
|
||||
|
||||
# Bars.
|
||||
style.default.bar_invert = False
|
||||
style.default.bar_resizing = False
|
||||
style.default.bar_vertical = False
|
||||
|
||||
style.vbar.bar_vertical = True
|
||||
style.vslider.bar_vertical = True
|
||||
style.vscrollbar.bar_vertical = True
|
||||
style.vscrollbar.bar_invert = True
|
||||
|
||||
# Viewport
|
||||
style.viewport.clipping = True
|
||||
|
||||
# Transform
|
||||
style.transform.subpixel = True
|
||||
|
||||
# Menu windows.
|
||||
style.mm_root.background = "#000"
|
||||
style.mm_root.xfill = True
|
||||
style.mm_root.yfill = True
|
||||
|
||||
style.gm_root.background = "#000"
|
||||
style.gm_root.xfill = True
|
||||
style.gm_root.yfill = True
|
||||
|
||||
# Lists.
|
||||
style.list_row.xfill = True
|
||||
|
||||
style.list_row.ymargin = 0
|
||||
style.list_row.background = "#eee"
|
||||
style.list_row[1].background = "#ddd"
|
||||
style.list_row.hover_background = "#fff"
|
||||
style.list_row[1].hover_background = "#fff"
|
||||
style.list_row.selected_background = "#cce"
|
||||
style.list_row[1].selected_background = "#cce"
|
||||
style.list_text.color = "#000"
|
||||
style.list_text.size = 14
|
||||
style.list_spacer.xminimum = 15
|
||||
|
||||
# Tile
|
||||
style.tile.clipping = True
|
||||
|
||||
|
||||
######################################################################
|
||||
|
||||
# Error messages.
|
||||
style.error_root.background = Solid((220, 220, 255, 255))
|
||||
style.error_root.xfill = True
|
||||
style.error_root.yfill = True
|
||||
style.error_root.xpadding = 20
|
||||
style.error_root.ypadding = 20
|
||||
|
||||
style.error_title.color = (255, 128, 128, 255)
|
||||
style.error_body.color = (128, 128, 255, 255)
|
||||
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# This extra contains a basic implementation of voice support. Right
|
||||
# now, voice is given its own toggle, and can either be turned on or
|
||||
# turned off. In the future, we'll probably provide some way of
|
||||
# toggling it on or off for individual characters.
|
||||
#
|
||||
# To use it, place a voice "<sndfile>" line before each voiced line of
|
||||
# dialogue.
|
||||
#
|
||||
# voice "e_1001.ogg"
|
||||
# e "Voice support lets you add the spoken word to your games."
|
||||
#
|
||||
# Normally, a voice is cancelled at the start of the next
|
||||
# interaction. If you want a voice to span interactions, call
|
||||
# voice_sustain.
|
||||
#
|
||||
# voice "e_1002.ogg"
|
||||
# e "Voice sustain is a technique that allows the same voice file.."
|
||||
#
|
||||
# $ voice_sustain()
|
||||
# e "...to play for two lines of dialogue."
|
||||
|
||||
init -1120:
|
||||
|
||||
python:
|
||||
|
||||
_voice = object()
|
||||
_voice.play = None
|
||||
_voice.sustain = False
|
||||
_voice.seen_in_lint = False
|
||||
|
||||
# Call this to specify the voice file that will be played for
|
||||
# the user.
|
||||
def voice(file, **kwargs):
|
||||
|
||||
if not config.has_voice:
|
||||
return
|
||||
|
||||
_voice.play = file
|
||||
_last_voice_play = file
|
||||
|
||||
# Call this to specify that the currently playing voice file
|
||||
# should be sustained through the current interaction.
|
||||
def voice_sustain(ignored="", **kwargs):
|
||||
if not config.has_voice:
|
||||
return
|
||||
|
||||
_voice.sustain = True
|
||||
|
||||
# Call this to replay the last bit of voice.
|
||||
def voice_replay():
|
||||
renpy.sound.play(_last_voice_play, channel="voice")
|
||||
|
||||
# Returns true if we can replay the voice.
|
||||
def voice_can_replay():
|
||||
return _last_voice_play != None
|
||||
|
||||
python hide:
|
||||
|
||||
# basics: True if the game will have voice.
|
||||
config.has_voice = True
|
||||
|
||||
# This is called on each interaction, to ensure that the
|
||||
# appropriate voice file is played for the user.
|
||||
def voice_interact():
|
||||
|
||||
if not config.has_voice:
|
||||
return
|
||||
|
||||
if _voice.play and not config.skipping:
|
||||
renpy.sound.play(_voice.play, channel="voice")
|
||||
store._last_voice_play = _voice.play
|
||||
elif not _voice.sustain:
|
||||
renpy.sound.stop(channel="voice")
|
||||
store._last_voice_play = _voice.play
|
||||
|
||||
_voice.play = None
|
||||
_voice.sustain = False
|
||||
|
||||
config.start_interact_callbacks.append(voice_interact)
|
||||
config.say_sustain_callbacks.append(voice_sustain)
|
||||
|
||||
def voice_afm_callback():
|
||||
return not renpy.sound.is_playing(channel="voice")
|
||||
|
||||
config.afm_callback = voice_afm_callback
|
||||
|
||||
python early hide:
|
||||
|
||||
def parse_voice(l):
|
||||
fn = l.simple_expression()
|
||||
if fn is None:
|
||||
renpy.error('expected simple expression (string)')
|
||||
|
||||
if not l.eol():
|
||||
renpy.error('expected end of line')
|
||||
|
||||
return fn
|
||||
|
||||
def execute_voice(fn):
|
||||
fn = eval(fn)
|
||||
voice(fn)
|
||||
|
||||
def lint_voice(fn):
|
||||
_voice.seen_in_lint = True
|
||||
|
||||
fn = _try_eval(fn, 'voice filename')
|
||||
if isinstance(fn, basestring) and not renpy.loadable(fn):
|
||||
renpy.error('voice file %r is not loadable' % fn)
|
||||
|
||||
renpy.statements.register('voice',
|
||||
parse=parse_voice,
|
||||
execute=execute_voice,
|
||||
lint=lint_voice)
|
||||
|
||||
def parse_voice_sustain(l):
|
||||
if not l.eol():
|
||||
renpy.error('expected end of line')
|
||||
|
||||
return None
|
||||
|
||||
def execute_voice_sustain(parsed):
|
||||
voice_sustain()
|
||||
|
||||
renpy.statements.register('voice sustain',
|
||||
parse=parse_voice_sustain,
|
||||
execute=execute_voice_sustain)
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python:
|
||||
|
||||
layout.provides('joystick_preferences')
|
||||
|
||||
label joystick_preferences_screen:
|
||||
|
||||
$ renpy.show_screen('joystick_preferences')
|
||||
$ ui.interact()
|
||||
|
||||
jump _noisy_return
|
||||
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python:
|
||||
|
||||
layout.provides('load_save')
|
||||
|
||||
label load_screen:
|
||||
|
||||
$ renpy.show_screen('load')
|
||||
$ ui.interact()
|
||||
jump _noisy_return
|
||||
|
||||
label save_screen:
|
||||
|
||||
$ renpy.show_screen('save')
|
||||
$ ui.interact()
|
||||
jump _noisy_return
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python:
|
||||
|
||||
layout.provides('main_menu')
|
||||
|
||||
label main_menu_screen:
|
||||
|
||||
$ renpy.show_screen("main_menu")
|
||||
$ ui.interact()
|
||||
|
||||
return
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python:
|
||||
|
||||
layout.provides('preferences')
|
||||
|
||||
label preferences_screen:
|
||||
|
||||
$ renpy.show_screen('preferences')
|
||||
$ ui.interact()
|
||||
|
||||
jump _noisy_return
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python hide:
|
||||
|
||||
layout.provides('yesno_prompt')
|
||||
|
||||
def yesno_prompt(screen, message):
|
||||
rv = renpy.call_screen('yesno_prompt', message=message, yes_action=Return(True), no_action=Return(False))
|
||||
return rv
|
||||
|
||||
layout.yesno_prompt = yesno_prompt
|
||||
@@ -0,0 +1,2 @@
|
||||
lib\windows-i686\python.exe -OO renpy.py
|
||||
pause
|
||||
@@ -1,124 +1,51 @@
|
||||
#!/home/tom/bin/renpython
|
||||
# Builds a distributions of Ren'Py.
|
||||
#!/home/tom/bin/renpython -O
|
||||
|
||||
# Builds a distribution of Ren'Py.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import zipfile
|
||||
import tarfile
|
||||
import zlib
|
||||
import compileall
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import argparse
|
||||
import glob
|
||||
|
||||
CWD = os.getcwdu()
|
||||
ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
zlib.Z_DEFAULT_COMPRESSION = 9
|
||||
def copy_tutorial_file(src, dest):
|
||||
"""
|
||||
Copies a file from src to dst. Lines between "# tutorial-only" and
|
||||
"# end-tutorial-only" comments are omitted from the copy.
|
||||
"""
|
||||
|
||||
# Gets the data for the given file.
|
||||
def data(fn):
|
||||
sf = open(src, "rb")
|
||||
df = open(dest, "wb")
|
||||
|
||||
rv = file(fn, "rb").read()
|
||||
# True if we want to copy the line.
|
||||
copy = True
|
||||
|
||||
if fn.startswith("renpy.app"):
|
||||
return rv
|
||||
for l in sf:
|
||||
if "# tutorial-only" in l:
|
||||
copy = False
|
||||
elif "# end-tutorial-only" in l:
|
||||
copy = True
|
||||
else:
|
||||
if copy:
|
||||
df.write(l)
|
||||
|
||||
if fn.endswith(".rpy") or fn.endswith(".rpym") or fn.endswith(".py") or fn.endswith(".txt"):
|
||||
rv = rv.replace("\n", "\r\n")
|
||||
rv = rv.replace("\r\r\n", "\r\n")
|
||||
sf.close()
|
||||
df.close()
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
def tarup(filename, prefix, files):
|
||||
|
||||
tf = tarfile.open(filename, "w:bz2")
|
||||
tf.dereference = True
|
||||
|
||||
sys.stdout.write(filename)
|
||||
sys.stdout.flush()
|
||||
|
||||
for fn in files:
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
|
||||
tf.add(fn, prefix + "/" + fn, False)
|
||||
|
||||
sys.stdout.write("\n")
|
||||
|
||||
tf.close()
|
||||
|
||||
|
||||
# Creates a zip file.
|
||||
def zipup(filename, prefix, files):
|
||||
|
||||
zf = zipfile.ZipFile(filename, "w")
|
||||
|
||||
sys.stdout.write(filename)
|
||||
sys.stdout.flush()
|
||||
|
||||
for fn in files:
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
|
||||
zi = zipfile.ZipInfo(prefix + "/" + fn)
|
||||
|
||||
st = os.stat(fn)
|
||||
|
||||
zi.date_time = time.gmtime(st.st_mtime)[:6]
|
||||
zi.compress_type = zipfile.ZIP_DEFLATED
|
||||
zi.create_system = 3
|
||||
zi.external_attr = long(st.st_mode) << 16
|
||||
|
||||
zf.writestr(zi, data(fn))
|
||||
|
||||
zf.close()
|
||||
|
||||
sys.stdout.write("\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
|
||||
def tree(root):
|
||||
|
||||
rv = [ ]
|
||||
|
||||
for dirname, dirs, filenames in os.walk(root):
|
||||
|
||||
if "saves" in dirs:
|
||||
dirs.remove("saves")
|
||||
|
||||
if ".svn" in dirs:
|
||||
dirs.remove(".svn")
|
||||
|
||||
if ".doctrees" in dirs:
|
||||
dirs.remove(".doctrees")
|
||||
|
||||
|
||||
for f in filenames:
|
||||
if f[-1] == '~' or f[0] == '.':
|
||||
continue
|
||||
|
||||
if f.endswith(".bak") or f.endswith(".pyc"):
|
||||
continue
|
||||
|
||||
if f == "semantic.cache":
|
||||
continue
|
||||
|
||||
if "libSDL_mixer" in f or "mixer_music" in f:
|
||||
continue
|
||||
|
||||
rv.append(dirname + "/" + f)
|
||||
|
||||
return rv
|
||||
|
||||
def main():
|
||||
|
||||
if not sys.flags.optimize:
|
||||
raise Exception("Not running with python optimization.")
|
||||
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("version")
|
||||
ap.add_argument("--fast", action="store_true")
|
||||
|
||||
|
||||
args = ap.parse_args()
|
||||
|
||||
# Revision updating is done early, so we can do it even if the rest
|
||||
@@ -131,81 +58,123 @@ def main():
|
||||
match_version = ".".join(str(i) for i in renpy.version_tuple[:2]) #@UndefinedVariable
|
||||
zip_version = ".".join(str(i) for i in renpy.version_tuple[:3]) #@UndefinedVariable
|
||||
|
||||
s = subprocess.check_output([ "git", "describe", "--dirty", "--match", match_version ])
|
||||
s = subprocess.check_output([ "git", "describe", "--tags", "--dirty", "--match", match_version ])
|
||||
parts = s.strip().split("-")
|
||||
vc_version = int(parts[1])
|
||||
|
||||
|
||||
if len(parts) <= 2:
|
||||
vc_version = 0
|
||||
else:
|
||||
vc_version = int(parts[1])
|
||||
|
||||
if parts[-1] == "dirty":
|
||||
vc_version += 1
|
||||
|
||||
|
||||
with open("renpy/vc_version.py", "w") as f:
|
||||
f.write("vc_version = {}".format(vc_version))
|
||||
|
||||
reload(sys.modules['renpy.vc_version']) #@UndefinedVariable
|
||||
try:
|
||||
reload(sys.modules['renpy.vc_version']) #@UndefinedVariable
|
||||
except:
|
||||
import renpy.vc_version # @UnusedImport
|
||||
|
||||
reload(sys.modules['renpy'])
|
||||
|
||||
# Check that the versions match.
|
||||
full_version = ".".join(str(i) for i in renpy.version_tuple) #@UndefinedVariable
|
||||
if args.version != "experimental" and not full_version.startswith(args.version):
|
||||
raise Exception("The command-line and Ren'Py versions do not match.")
|
||||
if args.version != "renpy-experimental" \
|
||||
and not args.version.startswith("renpy-nightly-") \
|
||||
and not full_version.startswith(args.version):
|
||||
|
||||
print "Version {} ({})".format(args.version, full_version)
|
||||
|
||||
# Copy over the screens, to keep them up to date.
|
||||
shutil.copy("tutorial/game/screens.rpy", "template/game/screens.rpy")
|
||||
|
||||
# Copy in the windows version of zsync
|
||||
shutil.copy("../zsync.exe", "lib/windows-x86/zsync.exe")
|
||||
shutil.copy("../zsyncmake.exe", "lib/windows-x86/zsyncmake.exe")
|
||||
|
||||
# Compile all the python files.
|
||||
compileall.compile_dir("renpy/", ddir="renpy/", force=1, quiet=1)
|
||||
|
||||
# Compile the various games
|
||||
|
||||
if not args.fast:
|
||||
for i in [ 'tutorial', 'launcher', 'template', 'the_question' ]:
|
||||
print "Compiling", i
|
||||
subprocess.check_call(["./renpy.sh", i, "compile" ])
|
||||
raise Exception("The command-line and Ren'Py versions do not match.")
|
||||
|
||||
# The destination directory.
|
||||
destination = os.path.join("dl", args.version)
|
||||
|
||||
|
||||
print "Version {} ({})".format(args.version, full_version)
|
||||
|
||||
# Perhaps autobuild.
|
||||
if "RENPY_BUILD_ALL" in os.environ:
|
||||
print("Autobuild...")
|
||||
subprocess.check_call(["scripts/autobuild.sh"])
|
||||
|
||||
# Copy over the screens, to keep them up to date.
|
||||
copy_tutorial_file("tutorial/game/screens.rpy", "templates/english/game/screens.rpy")
|
||||
|
||||
# Compile all the python files.
|
||||
compileall.compile_dir("renpy/", ddir="renpy/", force=1, quiet=1)
|
||||
|
||||
# Generate launcher/game/script_version.rpy
|
||||
with open("launcher/game/script_version.rpy", "w") as f:
|
||||
f.write("init -999 python:\n")
|
||||
f.write(" config.script_version = {!r}\n".format(renpy.version_tuple[:3])) # @UndefinedVariable
|
||||
|
||||
# Compile the various games.
|
||||
if not args.fast:
|
||||
for i in [ 'tutorial', 'launcher', 'the_question' ] + glob.glob("templates/*"):
|
||||
print "Compiling", i
|
||||
subprocess.check_call(["./renpy.sh", i, "quit" ])
|
||||
|
||||
|
||||
# Kick off the rapt build.
|
||||
if not args.fast:
|
||||
out = open("/tmp/rapt_build.txt", "wb")
|
||||
|
||||
print("Building RAPT.")
|
||||
|
||||
android = os.path.abspath("android")
|
||||
|
||||
rapt_build = subprocess.Popen([
|
||||
os.path.join(android, "build_renpy.sh"),
|
||||
"renpy",
|
||||
ROOT,
|
||||
],
|
||||
cwd = android,
|
||||
stdout=out,
|
||||
stderr=out)
|
||||
|
||||
code = rapt_build.wait()
|
||||
|
||||
if code:
|
||||
print "RAPT build failed. The output is in /tmp/rapt_build.txt."
|
||||
sys.exit(1)
|
||||
else:
|
||||
print "RAPT build succeeded."
|
||||
|
||||
if not os.path.exists(destination):
|
||||
os.makedirs(destination)
|
||||
|
||||
if args.fast:
|
||||
|
||||
cmd = [
|
||||
"./renpy.sh",
|
||||
"launcher",
|
||||
"distribute",
|
||||
"launcher",
|
||||
"./renpy.sh",
|
||||
"launcher",
|
||||
"distribute",
|
||||
"launcher",
|
||||
"--package",
|
||||
"sdk",
|
||||
"--destination",
|
||||
"--destination",
|
||||
destination,
|
||||
"--no-update",
|
||||
]
|
||||
|
||||
else:
|
||||
cmd = [
|
||||
"./renpy.sh",
|
||||
"launcher",
|
||||
"distribute",
|
||||
"launcher",
|
||||
"--destination",
|
||||
"./renpy.sh",
|
||||
"launcher",
|
||||
"distribute",
|
||||
"launcher",
|
||||
"--destination",
|
||||
destination,
|
||||
]
|
||||
|
||||
|
||||
print
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
# Sign the update.
|
||||
if not args.fast:
|
||||
subprocess.check_call([
|
||||
"scripts/sign_update.py",
|
||||
"/home/tom/ab/keys/renpy_private.pem",
|
||||
subprocess.check_call([
|
||||
"scripts/sign_update.py",
|
||||
"/home/tom/ab/keys/renpy_private.pem",
|
||||
os.path.join(destination, "updates.json"),
|
||||
])
|
||||
|
||||
@@ -213,55 +182,56 @@ def main():
|
||||
# Write 7z.exe.
|
||||
sdk = "renpy-{}-sdk".format(zip_version)
|
||||
|
||||
if args.version.startswith("renpy-nightly-"):
|
||||
sdk = args.version + "-sdk"
|
||||
|
||||
if not args.fast:
|
||||
|
||||
shutil.copy("renpy-ppc.zip", os.path.join(destination, "renpy-ppc.zip"))
|
||||
# shutil.copy("renpy-ppc.zip", os.path.join(destination, "renpy-ppc.zip"))
|
||||
|
||||
with open("7z.sfx", "rb") as f:
|
||||
sfx = f.read()
|
||||
|
||||
|
||||
os.chdir(destination)
|
||||
|
||||
if os.path.exists(sdk):
|
||||
shutil.rmtree(sdk)
|
||||
|
||||
|
||||
subprocess.check_call([ "unzip", "-q", sdk + ".zip" ])
|
||||
|
||||
|
||||
if os.path.exists(sdk + ".7z"):
|
||||
os.unlink(sdk + ".7z")
|
||||
|
||||
|
||||
sys.stdout.write("Creating -sdk.7z")
|
||||
|
||||
|
||||
p = subprocess.Popen([ "7z", "a", sdk +".7z", sdk], stdout=subprocess.PIPE)
|
||||
for i, _l in enumerate(p.stdout):
|
||||
if i % 10 != 0:
|
||||
continue
|
||||
|
||||
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
|
||||
if p.wait() != 0:
|
||||
raise Exception("7z failed")
|
||||
|
||||
|
||||
with open(sdk + ".7z", "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
|
||||
with open(sdk + ".7z.exe", "wb") as f:
|
||||
f.write(sfx)
|
||||
f.write(data)
|
||||
|
||||
|
||||
os.unlink(sdk + ".7z")
|
||||
shutil.rmtree(sdk)
|
||||
|
||||
else:
|
||||
os.chdir(destination)
|
||||
|
||||
|
||||
if os.path.exists(sdk + ".7z.exe"):
|
||||
os.unlink(sdk + ".7z.exe")
|
||||
|
||||
print
|
||||
print "Did you run me with renpython -OO?"
|
||||
print "Did you update renpy.py and launcher/script_version.rpy?"
|
||||
|
||||
|
||||
print
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
# This contains code for the new day planner. You probably
|
||||
# don't want to change this file, but it might make sense to
|
||||
# change many of the variables or styles defined here from
|
||||
# other files.
|
||||
|
||||
init -100 python:
|
||||
|
||||
# The frame containing the day planner.
|
||||
style.dp_frame = Style(style.frame)
|
||||
style.dp_vbox = Style(style.vbox)
|
||||
style.dp_hbox = Style(style.hbox)
|
||||
|
||||
# The frame and vbox containing a single choice.
|
||||
style.dp_choices = Style(style.default)
|
||||
style.dp_choices_vbox = Style(style.vbox)
|
||||
style.dp_choices.xalign = 0.5
|
||||
|
||||
# Buttons.
|
||||
style.dp_choice_button = Style(style.button)
|
||||
style.dp_choice_button_text = Style(style.button_text)
|
||||
|
||||
style.dp_done_button = Style(style.button)
|
||||
style.dp_done_button_text = Style(style.button_text)
|
||||
|
||||
# Labels.
|
||||
style.dp_label = Style(style.label)
|
||||
style.dp_label_text = Style(style.label_text)
|
||||
|
||||
# The title of the done button.
|
||||
dp_done_title = "Done Planning"
|
||||
|
||||
# A map from period name to the information we know about that
|
||||
# period.
|
||||
__periods = { }
|
||||
|
||||
# The period we're updating.
|
||||
__period = None
|
||||
|
||||
class __Period(object):
|
||||
|
||||
def __init__(self, name, var):
|
||||
self.name = name
|
||||
self.var = var
|
||||
self.acts = [ ]
|
||||
|
||||
def dp_period(name, var):
|
||||
__periods[name] = store.__period = __Period(name, var)
|
||||
|
||||
__None = object()
|
||||
|
||||
def dp_choice(name, value=__None, enable="True", show="True"):
|
||||
|
||||
if not __period:
|
||||
raise Exception("Choices must be part of a defined period.")
|
||||
|
||||
if value is __None:
|
||||
value = name
|
||||
|
||||
__period.acts.append((name, value, enable, show))
|
||||
|
||||
def __set_noncurried(var, value):
|
||||
setattr(store, var, value)
|
||||
return True
|
||||
|
||||
__set = renpy.curry(__set_noncurried)
|
||||
|
||||
|
||||
label day_planner(periods):
|
||||
|
||||
python hide:
|
||||
renpy.choice_for_skipping()
|
||||
|
||||
label day_planner_repeat:
|
||||
|
||||
if renpy.has_label("dp_callback"):
|
||||
call dp_callback
|
||||
|
||||
python hide:
|
||||
|
||||
ui.window(style=style.dp_frame)
|
||||
ui.vbox(style=style.dp_vbox)
|
||||
ui.hbox(style=style.dp_hbox)
|
||||
|
||||
can_continue = True
|
||||
|
||||
for p in periods:
|
||||
|
||||
if p not in __periods:
|
||||
raise Exception("Period %r was never defined." % p)
|
||||
|
||||
ui.window(style=style.dp_choices)
|
||||
ui.vbox(style=style.dp_choices_vbox)
|
||||
|
||||
p = __periods[p]
|
||||
v = getattr(store, p.var)
|
||||
|
||||
layout.label(p.name, "dp")
|
||||
|
||||
valid_choice = False
|
||||
|
||||
for name, value, enable, show in p.acts:
|
||||
show = eval(show)
|
||||
enable = eval(enable)
|
||||
|
||||
selected = (v == value)
|
||||
|
||||
if show:
|
||||
layout.button(
|
||||
name,
|
||||
"dp_choice",
|
||||
clicked=__set(p.var, value),
|
||||
selected=selected,
|
||||
enabled=enable,
|
||||
)
|
||||
|
||||
if show and enable and selected:
|
||||
valid_choice = True
|
||||
|
||||
if not valid_choice:
|
||||
can_continue = False
|
||||
|
||||
ui.close()
|
||||
|
||||
ui.close() # hbox.
|
||||
|
||||
layout.button(
|
||||
dp_done_title,
|
||||
"dp_done",
|
||||
clicked=ui.returns(False),
|
||||
enabled=can_continue)
|
||||
|
||||
ui.close() # vbox
|
||||
|
||||
if ui.interact():
|
||||
jump day_planner_repeat
|
||||
else:
|
||||
return
|
||||
@@ -1,328 +0,0 @@
|
||||
# The Ren'Py/DSE event dispatcher. This file contains the code that
|
||||
# actually supports the running of events. Specifically, it contains
|
||||
# code that determines which events are available, which events can
|
||||
# run, and to actually run the events that should be run during a
|
||||
# given period.
|
||||
|
||||
# This isn't really intended to be user-changable.
|
||||
|
||||
init -100 python:
|
||||
|
||||
# A list of all of the events that the system knowns about,
|
||||
# it's filtered to determine which events should run when.
|
||||
all_events = [ ]
|
||||
|
||||
# The base class for events. When constructed, an event
|
||||
# automatically adds itself to all_events.
|
||||
#
|
||||
# The first parameter for this is a unique name for the event,
|
||||
# which is also used as the label that is called when the
|
||||
# event executes.
|
||||
#
|
||||
# All other parameters are expressions. These expressions can
|
||||
# be either strings, or objects having an eval method. Many
|
||||
# interesting objects are given below.
|
||||
#
|
||||
# Keyword arguments are also kept on the object. Currently,
|
||||
# there is one useful keyword argument, priority. This
|
||||
# controls the order in which events are in the event list.
|
||||
# (Events with lower priority number are evaluated first. If a
|
||||
# priority is not specified, it's 100.)
|
||||
class event(object):
|
||||
|
||||
def __repr__(self):
|
||||
return '<event ' + self.name + '>'
|
||||
|
||||
def __init__(self, name, *args, **kwargs):
|
||||
|
||||
self.name = name
|
||||
|
||||
exprs = [ ]
|
||||
|
||||
for i in args:
|
||||
if isinstance(i, basestring):
|
||||
exprs.append(event.evaluate(i))
|
||||
else:
|
||||
exprs.append(i)
|
||||
|
||||
self.exprs = exprs
|
||||
|
||||
self.priority = kwargs.get('priority', 100)
|
||||
|
||||
all_events.append(self)
|
||||
|
||||
# Checks to see if this event is valid. It's called with
|
||||
# a list of events that have already checked out to be
|
||||
# True, and returns True if this event checks out.
|
||||
def check(self, valid):
|
||||
|
||||
for i in self.exprs:
|
||||
if not i.eval(self.name, valid):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def properties(self):
|
||||
|
||||
rv = { }
|
||||
|
||||
for i in self.exprs:
|
||||
rv.update(i.properties())
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
# The base class for all of the event checks given below.
|
||||
class event_check(object):
|
||||
|
||||
def properties(self):
|
||||
return { }
|
||||
|
||||
def __invert__(self):
|
||||
return event.false(self)
|
||||
|
||||
def __and__(self, other):
|
||||
return event.and_op(self, other)
|
||||
|
||||
def __or__(self, other):
|
||||
return event.or_op(self, other)
|
||||
|
||||
|
||||
# This evaluates the expression given as an argument, and the
|
||||
# returns true if it evaluates to true.
|
||||
class evaluate(event_check):
|
||||
|
||||
def __init__(self, expr):
|
||||
self.expr = expr
|
||||
|
||||
def eval(self, name, valid):
|
||||
return eval(self.expr)
|
||||
|
||||
# If present as a condition to an event, an object of this
|
||||
# type ensures that the event will only execute once.
|
||||
class once(event_check):
|
||||
def eval(self, name, valid):
|
||||
return name not in events_executed
|
||||
|
||||
# Returns True if no event of higher priority can execute,
|
||||
# and false otherwise. In general, solo events should be
|
||||
# the lowest priority, and are run if nothing else is.
|
||||
class solo(event_check):
|
||||
def eval(self, name, valid):
|
||||
|
||||
# True if valid is empty.
|
||||
return not valid
|
||||
|
||||
# Returns True if no event of higher priority can execute.
|
||||
# This also prevents other events from executing.
|
||||
class only(solo):
|
||||
|
||||
def properties(self):
|
||||
return dict(only=True)
|
||||
|
||||
|
||||
# Returns True if the given events have happend already,
|
||||
# at any time in the game. False if at least one hasn't
|
||||
# happened yet.
|
||||
class happened(event_check):
|
||||
def __init__(self, *events):
|
||||
self.events = events
|
||||
|
||||
def eval(self, name, valid):
|
||||
for i in self.events:
|
||||
if i not in events_executed:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
# Returns True probability of the time, where probability
|
||||
# is a number between 0 and 1.
|
||||
class random(event_check):
|
||||
|
||||
def __init__(self, probability):
|
||||
self.probability = probability
|
||||
|
||||
def eval(self, name, valid):
|
||||
return renpy.random.random() <= self.probability
|
||||
|
||||
# Chooses only one from the group.
|
||||
class choose_one(event_check):
|
||||
|
||||
def __init__(self, group, group_count=1):
|
||||
self.group = group
|
||||
self.group_count = group_count
|
||||
|
||||
def eval(self, name, valid):
|
||||
return True
|
||||
|
||||
def properties(self):
|
||||
return dict(group=self.group,
|
||||
group_count=self.group_count)
|
||||
|
||||
|
||||
# Evaluates its argument, and returns true if it is false
|
||||
# and vice-versa.
|
||||
class false(event_check):
|
||||
def __init__(self, cond):
|
||||
self.cond = cond
|
||||
|
||||
def eval(self, name, valid):
|
||||
return not self.cond.eval(name, valid)
|
||||
|
||||
# Handles the and operator.
|
||||
class and_op(event_check):
|
||||
|
||||
def __init__(self, *args):
|
||||
self.args = args
|
||||
|
||||
def eval(self, name, valid):
|
||||
for i in self.args:
|
||||
if not i.eval(name, valid):
|
||||
return False
|
||||
return True
|
||||
|
||||
# Handles the or operator.
|
||||
class or_op(event_check):
|
||||
|
||||
def __init__(self, *args):
|
||||
self.args = args
|
||||
|
||||
def eval(self, name, valid):
|
||||
for i in self.args:
|
||||
if i.eval(name, valid):
|
||||
return True
|
||||
return False
|
||||
|
||||
# Returns True if all of the events given as arguments have
|
||||
# happened yesterday or earlier, or False otherwise.
|
||||
class depends(event_check):
|
||||
def __init__(self, *events):
|
||||
self.events = events
|
||||
|
||||
def eval(self, name, valid):
|
||||
for i in self.events:
|
||||
if i not in events_executed_yesterday:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# The number of periods to skip.
|
||||
skip_periods = 0
|
||||
|
||||
# This returns True if the current period should be skipped,
|
||||
# or False if the current period should execute. If it returns
|
||||
# True, it decrements skip_periods.
|
||||
def check_skip_period():
|
||||
|
||||
global skip_periods
|
||||
|
||||
if skip_periods:
|
||||
skip_periods -= 1
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __events_init():
|
||||
store.events_executed = { }
|
||||
store.events_executed_yesterday = { }
|
||||
|
||||
config.start_callbacks.append(__events_init)
|
||||
|
||||
|
||||
# This should called at the end of a (game) day, to let things
|
||||
# like depends_yesterday to work.
|
||||
label events_end_day:
|
||||
|
||||
$ skip_periods = 0
|
||||
|
||||
python hide:
|
||||
|
||||
# We can't skip between days.
|
||||
skip_periods = 0
|
||||
|
||||
for k in events_executed:
|
||||
events_executed_yesterday[k] = True
|
||||
|
||||
return
|
||||
|
||||
# This is called once per period, to determine, and then execute, the
|
||||
# events that should be run for that period.
|
||||
label events_run_period:
|
||||
|
||||
$ events = [ ]
|
||||
|
||||
python hide:
|
||||
|
||||
eobjs = [ ]
|
||||
egroups = { }
|
||||
eingroup = { }
|
||||
|
||||
for i in all_events:
|
||||
if not i.check(eobjs):
|
||||
continue
|
||||
|
||||
eobjs.append(i)
|
||||
|
||||
props = i.properties()
|
||||
|
||||
if 'group' in props:
|
||||
group = props['group']
|
||||
count = props['group_count']
|
||||
|
||||
egroups.setdefault(group, [ ]).extend([ i ] * count)
|
||||
eingroup[i] = group
|
||||
|
||||
if 'only' in props:
|
||||
break
|
||||
|
||||
echosen = { }
|
||||
|
||||
for k in egroups:
|
||||
echosen[k] = renpy.random.choice(egroups[k])
|
||||
|
||||
for i in eobjs:
|
||||
|
||||
if i in eingroup and echosen[eingroup[i]] is not i:
|
||||
continue
|
||||
|
||||
events.append(i.name)
|
||||
|
||||
|
||||
while not check_skip_period() and events:
|
||||
|
||||
$ _event = events.pop(0)
|
||||
$ events_executed[_event] = True
|
||||
|
||||
call expression _event from call_expression_event_1
|
||||
|
||||
return
|
||||
|
||||
# If this is jumped to, it will end the current period immediately,
|
||||
# and return control to the main program.
|
||||
label events_end_period:
|
||||
|
||||
$ skip_period = 1
|
||||
return
|
||||
|
||||
# If this is jumped to, it will end the current period and skip
|
||||
# the next period. Use this if, say, the user goes on a date that
|
||||
# takes up two time slots.
|
||||
label events_skip_period:
|
||||
|
||||
$ skip_period = 2
|
||||
return
|
||||
|
||||
|
||||
init 100:
|
||||
python hide:
|
||||
# Sort all events on priority.
|
||||
all_events.sort(key=lambda i : i.priority)
|
||||
|
||||
python hide:
|
||||
|
||||
for i in all_events:
|
||||
if not renpy.has_label(i.name):
|
||||
raise Exception("'%s' is defined as an event somewhere in the game, but no label named '%s' was defined anywhere." % (i.name, i.name))
|
||||
|
||||
|
||||
@@ -1,767 +0,0 @@
|
||||
# This file contains the events that will be part of the game. It's
|
||||
# expected that the user will add and remove events as appropriate
|
||||
# for this game.
|
||||
|
||||
|
||||
# Some characters that are used in events in the game.
|
||||
init:
|
||||
$ t = Character('Teacher')
|
||||
$ gg = Character('Glasses Girl', color=(192, 255, 192, 255))
|
||||
$ sg = Character('Sporty Girl', color=(255, 255, 192, 255))
|
||||
$ bg = Character('Both Girls')
|
||||
$ narrator = Character(' ')
|
||||
|
||||
# First up, we define some simple events for the various actions, that
|
||||
# are run only if no higher-priority event is about to occur.
|
||||
|
||||
init:
|
||||
$ event("class", "act == 'class'", event.only(), priority=200)
|
||||
$ event("class_bad", "act == 'class'", priority=210)
|
||||
$ event("cut1", "act == 'cut'", event.choose_one('cut'), priority=200)
|
||||
$ event("cut2", "act == 'cut'", event.choose_one('cut'), priority=200)
|
||||
$ event("study", "act == 'study'", event.solo(), priority=200)
|
||||
$ event("hang", "act == 'hang'", event.solo(), priority=200)
|
||||
$ event("exercise", "act == 'exercise'", event.solo(), priority=200)
|
||||
$ event("play", "act == 'play'", event.solo(), priority=200)
|
||||
|
||||
label class:
|
||||
|
||||
"I make it to class just in time, and proceed to listen to the
|
||||
teacher droning on about a wide range of topics, none of which
|
||||
are remotely interesting."
|
||||
|
||||
return
|
||||
|
||||
# For test purposes only.
|
||||
label class_bad:
|
||||
|
||||
"You shouldn't be seeing this."
|
||||
|
||||
"This is because class was declared with event.only(), which
|
||||
should suspend processing of further events."
|
||||
|
||||
"This is really for testing purposes only."
|
||||
|
||||
return
|
||||
|
||||
label cut1:
|
||||
|
||||
"I cut class, and spend the morning goofing off instead."
|
||||
$ intelligence -= 10
|
||||
|
||||
return
|
||||
|
||||
label cut2:
|
||||
|
||||
"I cut class, and spend the morning playing computer games."
|
||||
|
||||
return
|
||||
|
||||
label study:
|
||||
|
||||
"I head on down to the library, and start reading about the topics
|
||||
I should have been reading about in class."
|
||||
|
||||
$ intelligence += 10
|
||||
return
|
||||
|
||||
label hang:
|
||||
|
||||
"I spend the afternoon hanging out with my friends, killing
|
||||
some time."
|
||||
|
||||
return
|
||||
|
||||
label exercise:
|
||||
|
||||
"I decide to go out for a run through the town, to keep myself in
|
||||
shape."
|
||||
|
||||
$ strength += 10
|
||||
return
|
||||
|
||||
label play:
|
||||
|
||||
"I pop a DVD into my video game console, and spend the evening
|
||||
rolling small cities up into balls."
|
||||
|
||||
$ strength -= 10
|
||||
return
|
||||
|
||||
|
||||
# Below here are special events that are triggered when certain
|
||||
# conditions are true.
|
||||
|
||||
# This is an introduction event, that runs once when we first go
|
||||
# to class.
|
||||
|
||||
init:
|
||||
$ event("introduction", "act == 'class'", event.once(), event.only())
|
||||
|
||||
label introduction:
|
||||
|
||||
"I run to school, and make it to my seat just as the bell
|
||||
signalling the start of class rings."
|
||||
|
||||
t "Before we start, I have an announcement to make."
|
||||
|
||||
t "We will have two new students joining us. Girls, come on in."
|
||||
|
||||
"Two girls walk in, and stand in front of the class."
|
||||
|
||||
"They're twins."
|
||||
|
||||
"Identical twins."
|
||||
|
||||
"Identical black hair, and the same pretty face."
|
||||
|
||||
"Despite that, it's still fairly easy to tell them apart."
|
||||
|
||||
"The one on the left is wearing glasses."
|
||||
|
||||
"Not too thick, but enough to let me know she probably reads alot
|
||||
of books."
|
||||
|
||||
"If I look a little closely, I can find another difference."
|
||||
|
||||
"The one on the right probably exercises a bit more."
|
||||
|
||||
"I can tell by the muscle tone in her legs."
|
||||
|
||||
"I realize that I'm staring at her legs, and quickly look up."
|
||||
|
||||
"Suddenly, I realize that she's been talking for all this town."
|
||||
|
||||
sg "... to this town. And we hope to be friends with all of you."
|
||||
|
||||
sg "Well, that's about it. Sis, do you have anything to say?"
|
||||
|
||||
"The girl with glasses pauses for a second, and then quickly says:"
|
||||
|
||||
gg "{size=-4}It's good to meet you all.{/size}"
|
||||
|
||||
"She stops, and goes back to not saying anything."
|
||||
|
||||
t "Well, if that's all, you can take your seats and we can start
|
||||
the class."
|
||||
|
||||
"They do, and our teacher begins his lecture."
|
||||
|
||||
"I don't think anyone pays much attention to it, however."
|
||||
|
||||
return
|
||||
|
||||
|
||||
# These are the events with glasses girl.
|
||||
|
||||
init:
|
||||
# The glasses girl is studying in the library, but we do not
|
||||
# talk to her.
|
||||
#
|
||||
#
|
||||
$ event("gg_studying",
|
||||
|
||||
# This takes place when the action is 'study'.
|
||||
"act == 'study'",
|
||||
|
||||
# This will only take place if no higher-priority
|
||||
# event will occur.
|
||||
event.solo(),
|
||||
|
||||
# This takes place at least one day after seeing the
|
||||
# introduction event.
|
||||
event.depends("introduction"),
|
||||
|
||||
# This takes priority over the study event.
|
||||
priority=190)
|
||||
|
||||
# She asks to borrow our pen.
|
||||
$ event("borrow_pen",
|
||||
|
||||
# This takes place when we go to study, and we have an int
|
||||
# >= 50.
|
||||
"act == 'study' and intelligence >= 50",
|
||||
|
||||
# It runs only once.
|
||||
event.once(),
|
||||
|
||||
# It requires the introduction event to have run at least
|
||||
# one day before.
|
||||
event.depends("introduction"))
|
||||
|
||||
# After the pen, she smiles when she sees us.
|
||||
$ event("gg_smiling", "act == 'study'",
|
||||
event.solo(), event.depends("borrow_pen"),
|
||||
priority = 180)
|
||||
|
||||
# The bookslide.
|
||||
$ event("bookslide", "act == 'study' and intelligence == 100",
|
||||
event.once(), event.depends("borrow_pen"))
|
||||
|
||||
# She makes us cookies.
|
||||
$ event("cookies", "act == 'study'",
|
||||
event.once(), event.depends("bookslide"))
|
||||
|
||||
# Her solo ending.
|
||||
$ event("gg_confess", "act == 'class'",
|
||||
event.once(), event.depends("cookies"))
|
||||
|
||||
|
||||
label gg_studying:
|
||||
|
||||
"I head to the library, to get some studying done."
|
||||
|
||||
"The glasses girl is there, but she's busy reading a book, taking
|
||||
notes as she does so."
|
||||
|
||||
"I decide not to disturb her, and instead start reading my own
|
||||
book."
|
||||
|
||||
$ intelligence += 10
|
||||
|
||||
return
|
||||
|
||||
label borrow_pen:
|
||||
|
||||
"I head to the library, to get some studying done."
|
||||
|
||||
"The glasses girl is there, but she's busy reading a book."
|
||||
|
||||
"I decide not to disturb her, and instead start reading my own
|
||||
book."
|
||||
|
||||
"Suddenly, I feel a tap on my shoulder."
|
||||
|
||||
"I look up, and see the glasses girl standing right next to me."
|
||||
|
||||
gg "Excuse me, but can I borrow your pen?"
|
||||
|
||||
gg "Mine ran out of ink."
|
||||
|
||||
"I dig through my bag, to find the pen I had stashed there."
|
||||
|
||||
"While I'm looking, I point out that she seems to come to the
|
||||
library alot."
|
||||
|
||||
gg "Hm... I guess you're right."
|
||||
|
||||
gg "There's so much stuff here, and I want to know about it all."
|
||||
|
||||
gg "Surely, you must feel the same way, as you're here almost as
|
||||
much as I am."
|
||||
|
||||
"I don't have the heart to tell her that I'm only here to study so
|
||||
that I don't fail out."
|
||||
|
||||
"My hand brushes the pen, and I quickly pull it out and give it to
|
||||
her."
|
||||
|
||||
gg "Thank you."
|
||||
|
||||
"She says, and she goes back to studying."
|
||||
|
||||
return
|
||||
|
||||
label gg_smiling:
|
||||
|
||||
"I head to the library, to get some studying done."
|
||||
|
||||
"The glasses girl is there, and smiles at me for a second before
|
||||
turning back to her book."
|
||||
|
||||
"I decide not to disturb her, and instead start reading my own
|
||||
book."
|
||||
|
||||
$ intelligence += 10
|
||||
|
||||
return
|
||||
|
||||
label bookslide:
|
||||
|
||||
"I head to the library, to get some studying done."
|
||||
|
||||
"The glasses girl is standing right by the entrance, putting a
|
||||
book back into a bookcase containing science books."
|
||||
|
||||
"It looks quite old, and quite weak, as if it could break at any
|
||||
time."
|
||||
|
||||
"Suddenly, I hear a loud crack come from the bookcase."
|
||||
|
||||
"Without thinking, I throw myself between the girl and the
|
||||
bookcase, pushing her out of the way in the process."
|
||||
|
||||
"As the shelves fail one by one, I'm hit with large textbooks on
|
||||
topics ranging from Astronomy to Zoology."
|
||||
|
||||
"She's safe, but I'm knocked off my feet by the falling books."
|
||||
|
||||
"Before the dust even settled, the girl with glasses realized what
|
||||
happened and asked:"
|
||||
|
||||
gg "Are you alright?"
|
||||
|
||||
"I tell her that I am, all the while rubbing a bruise left by a
|
||||
particularly large Physics book."
|
||||
|
||||
gg "You saved me."
|
||||
|
||||
"She points out. I shrug... I guess I did, but it's not like I'm a
|
||||
hero or anything."
|
||||
|
||||
"She extends out her hand, I take it, and she helps me to get up."
|
||||
|
||||
gg "Wow... Um..."
|
||||
|
||||
"She doesn't know what to say."
|
||||
|
||||
"I suggest that we help clean up the mess, mostly to take her off
|
||||
the spot."
|
||||
|
||||
"She agrees, and together we begin piling the books up into neat
|
||||
piles."
|
||||
|
||||
return
|
||||
|
||||
|
||||
label cookies:
|
||||
|
||||
"I head to the library, to get some studying done."
|
||||
|
||||
"The glasses girl is there, apparently waiting for me."
|
||||
|
||||
"She's holding a package in her hands."
|
||||
|
||||
gg "Here."
|
||||
|
||||
"She says, and she hands me the package."
|
||||
|
||||
"I take it from her, and open it."
|
||||
|
||||
"It contains fresh homemade cookies. Ginger snaps, I think."
|
||||
|
||||
gg "It's to thank you."
|
||||
|
||||
"She points out... She's probably not used to this. Especially
|
||||
with guys."
|
||||
|
||||
"I take one of them, and stick it in my mouth."
|
||||
|
||||
"The taste is exquisite."
|
||||
|
||||
"It's perhaps one of the best cookies I've ever tasted."
|
||||
|
||||
"Of course it is. It's the only cookie I'd ever tasted that was
|
||||
made for me by a beutiful girl."
|
||||
|
||||
"I tell her this... that it's delicious, not the girl part."
|
||||
|
||||
"But I do let slip that if I could eat these every day, I'd be the
|
||||
happiest guy in the world."
|
||||
|
||||
"At this, she can only blush."
|
||||
|
||||
return
|
||||
|
||||
label gg_confess:
|
||||
|
||||
"I once again barely make it to class on time."
|
||||
|
||||
"I sit down, at my desk, and put some of my books into it."
|
||||
|
||||
"My hand brushes a folded sheet of paper, one I didn't remember
|
||||
putting in there."
|
||||
|
||||
"It's a girl's handwriting... \"Meet me on the roof at lunch.\""
|
||||
|
||||
"That's all it says... no signature or anything."
|
||||
|
||||
"Lunch is a few hours away, but the time passes like a blur."
|
||||
|
||||
"It's all I can do to avoid racing up to the roof... but I give it
|
||||
some time anyway."
|
||||
|
||||
"It wouldn't make sense for me to get there first."
|
||||
|
||||
"I let two minutes elapse before leaving the classroom, and then
|
||||
slowly walk the flights of stairs up to the roof."
|
||||
|
||||
"Standing there, I find the glasses girl."
|
||||
|
||||
"She's holding what looks like a homemade lunch... big enough for
|
||||
two."
|
||||
|
||||
"I look at it, then her, then remember what I had said after she
|
||||
made me the cookies."
|
||||
|
||||
"Finally, I ask her... \"Does this mean?\""
|
||||
|
||||
"She nods. It's all the confirmation I need."
|
||||
|
||||
"I sit down next to my new girlfriend... and together we start
|
||||
eating her lunch."
|
||||
|
||||
"I'm probably the happiest guy in the world."
|
||||
|
||||
"But I still have to find out her name."
|
||||
|
||||
".:. Ending 1."
|
||||
|
||||
$ renpy.full_restart()
|
||||
|
||||
|
||||
init:
|
||||
|
||||
$ event("catchme", "act == 'exercise'",
|
||||
event.depends('introduction'), event.once())
|
||||
|
||||
$ event("cantcatchme", "act == 'exercise'",
|
||||
event.depends('catchme'), event.solo(), priority=190)
|
||||
|
||||
$ event("caughtme", "act == 'exercise' and strength >= 50",
|
||||
event.depends('catchme'), event.once())
|
||||
|
||||
$ event("together", "act == 'exercise' and strength >= 50",
|
||||
event.depends('caughtme'), event.solo(), priority=180)
|
||||
|
||||
$ event("apart", "act == 'exercise' and strength < 50",
|
||||
event.depends('caughtme'), event.solo(), priority=180)
|
||||
|
||||
$ event("pothole", "act == 'exercise' and strength >= 100",
|
||||
event.depends('caughtme'), event.once())
|
||||
|
||||
$ event("dontsee", "act == 'exercise'",
|
||||
event.depends('pothole'), event.solo(), priority=170)
|
||||
|
||||
$ event("sg_confess", "act == 'class'",
|
||||
event.depends('dontsee'), event.once())
|
||||
|
||||
|
||||
label catchme:
|
||||
|
||||
"I decide to go out for a run, to keep myself in shape."
|
||||
|
||||
"As I'm running through the town, I see a girl."
|
||||
|
||||
"She's one of the twins who transferred into my class."
|
||||
|
||||
"She waves, and comes over to me."
|
||||
|
||||
sg "I didn't know you were a runner."
|
||||
|
||||
"I point out that I'm not really a runner... I just run a little
|
||||
bit at a time."
|
||||
|
||||
"I ask her if she wants to run with me for a while."
|
||||
|
||||
sg "As if! You couldn't keep up with me."
|
||||
|
||||
"I point out that I probably can."
|
||||
|
||||
sg "Well, let's see."
|
||||
|
||||
"We set off running, but she quickly pulls past me."
|
||||
|
||||
sg "See? Well, maybe we can try it again when you're a bit
|
||||
faster."
|
||||
|
||||
sg "Until then, later."
|
||||
|
||||
"Even though I'm jogging, she pulls away as if it is nothing."
|
||||
|
||||
return
|
||||
|
||||
label cantcatchme:
|
||||
|
||||
"I'm out running again, when the sporty girl catches up to me."
|
||||
|
||||
sg "Still at it?"
|
||||
|
||||
sg "Well, keep up the good work. One day you'll be as fast as me!"
|
||||
|
||||
sg "Well, maybe."
|
||||
|
||||
"She pulls out past me, and disappears into the distance. One day
|
||||
I'll catch up to her."
|
||||
|
||||
$ strength += 10
|
||||
|
||||
return
|
||||
|
||||
label caughtme:
|
||||
|
||||
"I'm out running again, when the sporty girl catches up to me."
|
||||
|
||||
sg "Still at it?"
|
||||
|
||||
sg "Well, keep up the good work. One day you'll be as fast as me!"
|
||||
|
||||
sg "Well, maybe."
|
||||
|
||||
|
||||
"Today, however, I'm not about to let this stand unchallenged."
|
||||
|
||||
"I break out into a run, and for the first time ever, I keep up
|
||||
with her."
|
||||
|
||||
"We both run, neck and neck, me keeping up with her."
|
||||
|
||||
"Finally, she starts slowing down, and we come to a stop
|
||||
together."
|
||||
|
||||
sg "Not bad."
|
||||
|
||||
"She pauses to catch her breath."
|
||||
|
||||
sg "You've been practicing, and it really shows."
|
||||
|
||||
sg "You've finally become fast enough to run with me."
|
||||
|
||||
"I nod, accepting her praise."
|
||||
|
||||
sg "We should do this more often... it's better to run with
|
||||
someone else, to keep the challenge up."
|
||||
|
||||
"I nod again."
|
||||
|
||||
sg "Well, shall we go?"
|
||||
|
||||
"I nod a third time, and we take off, running side by side."
|
||||
|
||||
$ strength += 10
|
||||
|
||||
return
|
||||
|
||||
label together:
|
||||
|
||||
"I start running, and meet up with the sporty girl as she passes
|
||||
the street in front of my house."
|
||||
|
||||
"She's still better than me... she's been running for over a mile
|
||||
before reaching this point."
|
||||
|
||||
"Still, I can keep up with her for the rest of the run. And that's
|
||||
not bad."
|
||||
|
||||
$ strength += 10
|
||||
|
||||
return
|
||||
|
||||
label apart:
|
||||
|
||||
"I start running, and meet up with the sporty girl as she passes
|
||||
the street in front of my house."
|
||||
|
||||
"I try to keep up with her, but she pulls away from me."
|
||||
|
||||
"When she's a block away, she slows down and lets me catch up."
|
||||
|
||||
sg "It's your own fault... this is what you get for not
|
||||
practicing."
|
||||
|
||||
"She's right, of course, and I redouble my efforts to try to keep
|
||||
up with her."
|
||||
|
||||
$ strength += 10
|
||||
return
|
||||
|
||||
label pothole:
|
||||
|
||||
"I start running, and meet up with the sporty girl as she passes
|
||||
the street in front of my house."
|
||||
|
||||
"We run together for several miles."
|
||||
|
||||
"I think about how much I've improved in our time together."
|
||||
|
||||
"And, although she probably won't admit it, I think she's improved
|
||||
as well."
|
||||
|
||||
"I guess a little friendly competition is usually for the best."
|
||||
|
||||
"A small yelp pulls me out of my thought."
|
||||
|
||||
sg "Ow!"
|
||||
|
||||
"The sporty girl sits down, grabbing her ankle."
|
||||
|
||||
"I ask her what happened."
|
||||
|
||||
sg "I... hit a... pothole. Twisted my... ankle."
|
||||
|
||||
"I wince in sympathy."
|
||||
|
||||
"We wait a bit. I'm not sure what to do."
|
||||
|
||||
"Finally, I ask her if she can walk on it."
|
||||
|
||||
"She tries for a bit, but then winces in pain."
|
||||
|
||||
sg "No, I don't think so."
|
||||
|
||||
"I realize that we can't stay here."
|
||||
|
||||
"And so, I crouch down and motion for her to climb up onto my
|
||||
back."
|
||||
|
||||
sg "What are you doing?"
|
||||
|
||||
"I explain that she can't stay out in the middle of the street
|
||||
forever, and she won't get any help until I can get her home."
|
||||
|
||||
"And the only way to do that is for me to carry her."
|
||||
|
||||
"She accepts this, and climbs up onto my back."
|
||||
|
||||
"She wraps her arms around my neck, and I place my hands
|
||||
underneath her to make a seat."
|
||||
|
||||
"I stand up, and start carrying her home."
|
||||
|
||||
return
|
||||
|
||||
label dontsee:
|
||||
|
||||
"I go running again."
|
||||
|
||||
"But this time, I don't see the sporty girl."
|
||||
|
||||
"I finish the course that we usually take, but it's not the same
|
||||
without her."
|
||||
|
||||
return
|
||||
|
||||
label sg_confess:
|
||||
|
||||
"I once again barely make it to class on time."
|
||||
|
||||
"I sit down, at my desk, and put some of my books into it."
|
||||
|
||||
"My hand brushes a folded sheet of paper, one I didn't remember
|
||||
putting in there."
|
||||
|
||||
"It's a girl's handwriting... \"Meet me on the roof at lunch.\""
|
||||
|
||||
"That's all it says... no signature or anything."
|
||||
|
||||
"Lunch is a few hours away, but the time passes like a blur."
|
||||
|
||||
"It's all I can do to avoid racing up to the roof... but I give it
|
||||
some time anyway."
|
||||
|
||||
"It wouldn't make sense for me to get there first."
|
||||
|
||||
"I let two minutes elapse before leaving the classroom, and then
|
||||
slowly walk the flights of stairs up to the roof."
|
||||
|
||||
"Standing there, I find the sporty girl."
|
||||
|
||||
"She's leaning on a crutch."
|
||||
|
||||
"I look at it for a second, and she notices that."
|
||||
|
||||
sg "I went to the doctor, and he gave me this."
|
||||
|
||||
sg "Looks like we won't be running together for a while."
|
||||
|
||||
"I nod."
|
||||
|
||||
sg "And that's why I asked you here."
|
||||
|
||||
sg "I couldn't stand the though of not seeing you for a few
|
||||
weeks."
|
||||
|
||||
"I search my feelings, and realize I feel the same way."
|
||||
|
||||
sg "So I thought..."
|
||||
|
||||
"She doesn't say it... she doesn't need to."
|
||||
|
||||
"We both know how we feel about each other."
|
||||
|
||||
"And with that, we went from being running partners to partners in
|
||||
a deeper sense."
|
||||
|
||||
"Now if I only knew her name..."
|
||||
|
||||
".:. Ending 2."
|
||||
|
||||
$ renpy.full_restart()
|
||||
|
||||
|
||||
init:
|
||||
|
||||
# This needs to be higher-priority than either girl's ending.
|
||||
$ event('both_confess', 'act == "class"',
|
||||
event.depends("dontsee"), event.depends("cookies"),
|
||||
event.once(), priority = 50)
|
||||
|
||||
label both_confess:
|
||||
|
||||
"I once again barely make it to class on time."
|
||||
|
||||
"I sit down, at my desk, and put some of my books into it."
|
||||
|
||||
"My hand brushes a folded sheet of paper, then another."
|
||||
|
||||
"I take the first one out, and read it."
|
||||
|
||||
"It's a girl's handwriting... \"Meet me on the roof at lunch.\""
|
||||
|
||||
"That's all it says... no signature or anything."
|
||||
|
||||
"I take a look at the second one, and it says the same thing."
|
||||
|
||||
"Sure, the handwriting is a little different, but..."
|
||||
|
||||
"Lunch is a few hours away, but the time passes like a blur."
|
||||
|
||||
"It's all I can do to avoid racing up to the roof... but I give it
|
||||
some time anyway."
|
||||
|
||||
"I let two minutes elapse before leaving the classroom, and then
|
||||
slowly walk the flights of stairs up to the roof."
|
||||
|
||||
"Standing there are the twins."
|
||||
|
||||
"Both of them."
|
||||
|
||||
"As in, the two notes came from the two twins."
|
||||
|
||||
"I ask them what they are doing there, feigning ignorance."
|
||||
|
||||
sg "Well, I invited you up here to confess to you..."
|
||||
|
||||
sg "... and then I found out that my sister here was about to do
|
||||
the same thing."
|
||||
|
||||
gg "{size=-4}...I was...{/size}"
|
||||
|
||||
sg "When we found out, we were quite shocked, but after comparing
|
||||
notes, we decide what we're going to do..."
|
||||
|
||||
"I quickly run through the possibilities in my head."
|
||||
|
||||
"The best cases involve them never talking to me again."
|
||||
|
||||
"The worst cases involve me being thrown off the roof."
|
||||
|
||||
bg "We're going to share you!"
|
||||
|
||||
"Eh?"
|
||||
|
||||
"That wasn't something I considered."
|
||||
|
||||
"Each of the girls grabs onto one of my arms."
|
||||
|
||||
"I don't know what the future holds for us..."
|
||||
|
||||
"... and I don't know if this will work out."
|
||||
|
||||
"But I do know that one day I will work up the courage to find out
|
||||
their names."
|
||||
|
||||
".:. Ending 3."
|
||||
|
||||
$ renpy.full_restart()
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
# This is the main program. This can be changed quite a bit to
|
||||
# customize it for your program... But remember what you do, so you
|
||||
# can integrate with a new version of DSE when it comes out.
|
||||
|
||||
# Set up a default theme.
|
||||
init python:
|
||||
register_stat("Strength", "strength", 10, 100)
|
||||
register_stat("Intelligence", "intelligence", 10, 100)
|
||||
|
||||
dp_period("Morning", "morning_act")
|
||||
dp_choice("Attend Class", "class")
|
||||
dp_choice("Cut Class", "cut")
|
||||
|
||||
dp_period("Afternoon", "afternoon_act")
|
||||
dp_choice("Study", "study")
|
||||
dp_choice("Hang Out", "hang")
|
||||
|
||||
dp_period("Evening", "evening_act")
|
||||
dp_choice("Exercise", "exercise")
|
||||
dp_choice("Play Games", "play")
|
||||
|
||||
|
||||
# This is the entry point into the game.
|
||||
label start:
|
||||
|
||||
# Initialize the default values of some of the variables used in
|
||||
# the game.
|
||||
$ day = 0
|
||||
|
||||
# Show a default background.
|
||||
scene black
|
||||
|
||||
# The script here is run before any event.
|
||||
|
||||
"In case you're just tuning in, here's the story of my life to
|
||||
date."
|
||||
|
||||
"I'm a guy in the second year of high school."
|
||||
|
||||
"I'm not good at sports or school or even something as simple as
|
||||
remembering peoples names."
|
||||
|
||||
"In short, I am your usual random loser guy."
|
||||
|
||||
"And this is my story..."
|
||||
|
||||
|
||||
# We jump to day to start the first day.
|
||||
jump day
|
||||
|
||||
|
||||
# This is the label that is jumped to at the start of a day.
|
||||
label day:
|
||||
|
||||
# Increment the day it is.
|
||||
$ day += 1
|
||||
|
||||
# We may also want to compute the name for the day here, but
|
||||
# right now we don't bother.
|
||||
|
||||
"It's day [day]."
|
||||
|
||||
# Here, we want to set up some of the default values for the
|
||||
# day planner. In a more complicated game, we would probably
|
||||
# want to add and remove choices from the dp_ variables
|
||||
# (especially dp_period_acts) to reflect the choices the
|
||||
# user has available to him.
|
||||
|
||||
$ morning_act = None
|
||||
$ afternoon_act = None
|
||||
$ evening_act = None
|
||||
|
||||
# Now, we call the day planner, which may set the act variables
|
||||
# to new values. We call it with a list of periods that we want
|
||||
# to compute the values for.
|
||||
call day_planner(["Morning", "Afternoon", "Evening"])
|
||||
|
||||
|
||||
# We process each of the three periods of the day, in turn.
|
||||
label morning:
|
||||
|
||||
# Tell the user what period it is.
|
||||
centered "Morning"
|
||||
|
||||
# Set these variables to appropriate values, so they can be
|
||||
# picked up by the expression in the various events defined below.
|
||||
$ period = "morning"
|
||||
$ act = morning_act
|
||||
|
||||
# Ensure that the stats are in the proper range.
|
||||
$ normalize_stats()
|
||||
|
||||
# Execute the events for the morning.
|
||||
call events_run_period
|
||||
|
||||
# That's it for the morning, so we fall through to the
|
||||
# afternoon.
|
||||
|
||||
label afternoon:
|
||||
|
||||
# It's possible that we will be skipping the afternoon, if one
|
||||
# of the events in the morning jumped to skip_next_period. If
|
||||
# so, we should skip the afternoon.
|
||||
if check_skip_period():
|
||||
jump evening
|
||||
|
||||
# The rest of this is the same as for the morning.
|
||||
|
||||
centered "Afternoon"
|
||||
|
||||
$ period = "afternoon"
|
||||
$ act = afternoon_act
|
||||
|
||||
$ normalize_stats()
|
||||
|
||||
call events_run_period
|
||||
|
||||
|
||||
label evening:
|
||||
|
||||
# The evening is the same as the afternoon.
|
||||
if check_skip_period():
|
||||
jump night
|
||||
|
||||
centered "Evening"
|
||||
|
||||
$ period = "evening"
|
||||
$ act = evening_act
|
||||
|
||||
$ normalize_stats()
|
||||
|
||||
call events_run_period
|
||||
|
||||
|
||||
label night:
|
||||
|
||||
# This is now the end of the day, and not a period in which
|
||||
# events can be run. We put some boilerplate end-of-day text
|
||||
# in here.
|
||||
|
||||
centered "Night"
|
||||
|
||||
"It's getting late, so I decide to go to sleep."
|
||||
|
||||
# We call events_end_day to let it know that the day is done.
|
||||
call events_end_day
|
||||
|
||||
# And we jump back to day to start the next day. This goes
|
||||
# on forever, until an event ends the game.
|
||||
jump day
|
||||
|
||||
|
||||
# This is a callback that is called by the day planner. One of the
|
||||
# uses of this is to show the statistics to the user.
|
||||
label dp_callback:
|
||||
|
||||
# Add in a line of dialogue asking the question that's on
|
||||
# everybody's mind.
|
||||
$ narrator("What should I do today?", interact=False)
|
||||
$ display_stats()
|
||||
|
||||
return
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
init -100 python:
|
||||
|
||||
style.stats_frame = Style(style.frame)
|
||||
style.stats_vbox = Style(style.vbox)
|
||||
|
||||
style.stats_label = Style(style.label)
|
||||
style.stats_label_text = Style(style.label_text)
|
||||
|
||||
style.stat_side = Style(style.default)
|
||||
|
||||
style.stat_label = Style(style.label)
|
||||
style.stat_label_text = Style(style.label_text)
|
||||
style.stat_bar = Style(style.bar)
|
||||
style.stat_value_label = Style(style.label)
|
||||
style.stat_value_label_text = Style(style.label_text)
|
||||
|
||||
__dse_stats = [ ]
|
||||
|
||||
class __Stat(object):
|
||||
|
||||
def __init__(self, name, var, default, max):
|
||||
self.name = name
|
||||
self.var = var
|
||||
self.default = default
|
||||
self.max = max
|
||||
|
||||
def __init_stats():
|
||||
for s in __dse_stats:
|
||||
setattr(store, s.var, s.default)
|
||||
|
||||
config.start_callbacks.append(__init_stats)
|
||||
|
||||
def register_stat(name, var, default, max):
|
||||
__dse_stats.append(__Stat(name, var, default, max))
|
||||
|
||||
def normalize_stats():
|
||||
for s in __dse_stats:
|
||||
|
||||
v = getattr(store, s.var)
|
||||
|
||||
if v > s.max:
|
||||
v = s.max
|
||||
if v < 0:
|
||||
v = 0
|
||||
|
||||
setattr(store, s.var, v)
|
||||
|
||||
|
||||
def display_stats(name=True, bar=True, value=True, max=True):
|
||||
|
||||
normalize_stats()
|
||||
|
||||
ui.window(style=style.stats_frame)
|
||||
ui.vbox(style=style.stats_vbox)
|
||||
|
||||
layout.label("Statistics", "stats")
|
||||
|
||||
for s in __dse_stats:
|
||||
v = getattr(store, s.var)
|
||||
|
||||
ui.side(['l', 'r', 'c'], style=style.stat_side)
|
||||
|
||||
if name:
|
||||
layout.label(s.name, "stat")
|
||||
else:
|
||||
ui.null()
|
||||
|
||||
if value and max:
|
||||
layout.label("%d/%d" % (v, s.max), "stat_value")
|
||||
elif value:
|
||||
layout.label("%d" % (v,), "stat_value")
|
||||
elif max:
|
||||
layout.label("%d" % (max,), "stat_value")
|
||||
else:
|
||||
ui.null()
|
||||
|
||||
if bar:
|
||||
ui.bar(s.max, v, style=style.stat_bar)
|
||||
else:
|
||||
ui.null()
|
||||
|
||||
ui.close()
|
||||
|
||||
ui.close()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# This file contains styles for the day planner.
|
||||
|
||||
init python:
|
||||
|
||||
# Place the day planner.
|
||||
style.dp_frame.ypos = 120
|
||||
style.dp_frame.yanchor = 0.0
|
||||
style.dp_frame.xalign = 0.5
|
||||
|
||||
# Spacing betweeen the choices and the done button.
|
||||
style.dp_vbox.box_spacing = 20
|
||||
|
||||
# Spacing between the choice columns.
|
||||
style.dp_hbox.box_spacing = 20
|
||||
|
||||
# Center the choices.
|
||||
style.dp_choices.xalign = 0.5
|
||||
|
||||
# Center the label of each choice.
|
||||
style.dp_label.xalign = 0.5
|
||||
style.dp_label_text.text_align = 0.5
|
||||
|
||||
# Make each choice button the same size, and centered.
|
||||
style.dp_choice_button.size_group = "dp_choice"
|
||||
style.dp_choice_button.xalign = 0.5
|
||||
|
||||
# Center the done button.
|
||||
style.dp_done_button.xalign = 0.5
|
||||
|
||||
# Put a margin on the stats frame.
|
||||
style.stats_frame.xmargin = 10
|
||||
style.stats_frame.ymargin = 5
|
||||
|
||||
# Space between the label and the stats.
|
||||
style.stats_vbox.box_first_spacing = 10
|
||||
|
||||
# Put blank space around each stat name, and right-justify.
|
||||
style.stat_label.xminimum = 140
|
||||
style.stat_label_text.xalign = 1.0
|
||||
style.stat_label.xmargin = 5
|
||||
|
||||
# Put blank space around each stat value, and right-justify.
|
||||
style.stat_value_label.xminimum = 100
|
||||
style.stat_value_label_text.xalign = 1.0
|
||||
|
||||
|
||||
# Center the stat bar vertically.
|
||||
style.stat_bar.yalign = 0.5
|
||||
|
||||
@@ -42,86 +42,90 @@ display: none;
|
||||
|
||||
|
||||
|
||||
<p><a name="Basic_Help" id="Basic_Help"></a></p>
|
||||
<h2><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=1" title="Edit section: Basic Help">edit</a>]</span> <span class="mw-headline">Basic Help</span></h2>
|
||||
<p>To advance through the game, <tt>left-click</tt> or press the <tt>space</tt> or <tt>enter</tt> keys. When at a menu, <tt>left-click</tt> to make a choice, or use the arrow keys to select a choice and <tt>enter</tt> to activate it.</p>
|
||||
<p><a name="Game_Menu" id="Game_Menu"></a></p>
|
||||
<h3><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=2" title="Edit section: Game Menu">edit</a>]</span> <span class="mw-headline">Game Menu</span></h3>
|
||||
<p>When playing a game, <tt>right-click</tt> or press the <tt>escape</tt> key to enter the game menu. The game menu gives the following choices:</p>
|
||||
<dl>
|
||||
<dt>Return</dt>
|
||||
<dd>Returns to the game.</dd>
|
||||
<dt>Save Game</dt>
|
||||
<dd>Allows you to save a game by clicking on a save slot.</dd>
|
||||
<dt>Load Game</dt>
|
||||
<dd>Allows you to load a game by clicking on a save slot. Clicking on "Auto" accesses the automatic save slots.</dd>
|
||||
<dt>Preferences</dt>
|
||||
<p><a name="Basic_Help" id="Basic_Help"></a></p>
|
||||
<h2><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=1" title="Edit section: Basic Help">edit</a>]</span> <span class="mw-headline">Basic Help</span></h2>
|
||||
<p>To advance through the game, <tt>left-click</tt> or press the <tt>space</tt> or <tt>enter</tt> keys. When at a menu, <tt>left-click</tt> to make a choice, or use the arrow keys to select a choice and <tt>enter</tt> to activate it.</p>
|
||||
<p><a name="Game_Menu" id="Game_Menu"></a></p>
|
||||
<h3><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=2" title="Edit section: Game Menu">edit</a>]</span> <span class="mw-headline">Game Menu</span></h3>
|
||||
<p>When playing a game, <tt>right-click</tt> or press the <tt>escape</tt> key to enter the game menu. The game menu gives the following choices:</p>
|
||||
<dl>
|
||||
<dt>Return</dt>
|
||||
<dd>Returns to the game.</dd>
|
||||
<dt>Save Game</dt>
|
||||
<dd>Allows you to save a game by clicking on a save slot.</dd>
|
||||
<dt>Load Game</dt>
|
||||
<dd>Allows you to load a game by clicking on a save slot. Clicking on "Auto" accesses the automatic save slots.</dd>
|
||||
<dt>Preferences</dt>
|
||||
<dd>Changes the game preferences (options/configuration):
|
||||
<dl>
|
||||
<dt>Display</dt>
|
||||
<dd>Switches between fullscreen and windowed mode.</dd>
|
||||
<dt>Transitions</dt>
|
||||
<dd>Controls the display of transitions between game screens.</dd>
|
||||
<dt>Text Speed</dt>
|
||||
<dd>Controls the rate at which text displays. The further to the right this slider is, the faster the text will display. All the way to the right causes text to be shown instantly.</dd>
|
||||
<dt>Joystick</dt>
|
||||
<dd>Lets you control the game using a joystick.</dd>
|
||||
<dt>Skip</dt>
|
||||
<dd>Chooses between skipping messages that have been already seen (in any play through the game), and skipping all messages.</dd>
|
||||
<dt>Begin Skipping</dt>
|
||||
<dd>Returns to the game, while skipping.</dd>
|
||||
<dt>After Choices</dt>
|
||||
<dd>Controls if skipping stops upon reaching a menu.</dd>
|
||||
<dt>Auto-Forward Time</dt>
|
||||
<dd>Controls automatic advance. The further to the left this slider is, the shorter the amount of time before the game advances. All the way to the right means text will never auto-forward.</dd>
|
||||
<dt>Music, Sound, and Voice Volume</dt>
|
||||
<dd>Controls the volume of the Music, Sound effect, and Voice channels, respectively. The further to the right these are, the louder the volume.</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Main Menu</dt>
|
||||
<dd>Returns to the main menu, ending the current game.</dd>
|
||||
<dt>Help</dt>
|
||||
<dd>Shows this help screen.</dd>
|
||||
<dt>Quit</dt>
|
||||
<dd>Exits the game; the game will be closed and ended.</dd>
|
||||
</dl>
|
||||
<p><a name="Key_and_Mouse_Bindings" id="Key_and_Mouse_Bindings"></a></p>
|
||||
<h3><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=3" title="Edit section: Key and Mouse Bindings">edit</a>]</span> <span class="mw-headline">Key and Mouse Bindings</span></h3>
|
||||
<dl>
|
||||
<dt>Left-click, Enter</dt>
|
||||
<dd>Advances through the game, activates menu choices, buttons, and sliders.</dd>
|
||||
<dt>Space</dt>
|
||||
<dd>Advances through the game, but does not activate choices.</dd>
|
||||
<dt>Arrow Keys</dt>
|
||||
<dd>Selects menu choices, buttons, and sliders.</dd>
|
||||
<dt>Ctrl</dt>
|
||||
<dd>Causes skipping to occur while the ctrl key is held down.</dd>
|
||||
<dt>Tab</dt>
|
||||
<dd>Toggles skipping, causing it to occur until tab is pressed again.</dd>
|
||||
<dt>Mousewheel-Up, PageUp</dt>
|
||||
<dd>Causes rollback to occur. Rollback reverses the game back in time, showing prior text and even allowing menu choices to be changed.</dd>
|
||||
<dt>Mousewheel-Down, PageDown</dt>
|
||||
<dd>Causes rollforward to occur, cancelling out a previous rollback.</dd>
|
||||
<dt>Right-click, Escape</dt>
|
||||
<dd>Enters the game menu. When in the game menu, returns to the game.</dd>
|
||||
<dt>Middle-click, H</dt>
|
||||
<dd>Hides the text window and other transient displays.</dd>
|
||||
<dt>F</dt>
|
||||
<dd>Toggles fullscreen mode</dd>
|
||||
<dt>S</dt>
|
||||
<dd>Takes a screenshot, saving it in a file named screenshotxxxx.png, where xxxx is a serial number.</dd>
|
||||
<dt>Alt-H, Command-H</dt>
|
||||
<dd>Hides (iconifies) the window.</dd>
|
||||
<dt>Alt-F4, Command-Q</dt>
|
||||
<dd>Quits the game.</dd>
|
||||
<dt>Delete</dt>
|
||||
<dd>When a save slot is selected, deletes that save slot.</dd>
|
||||
</dl>
|
||||
<p><a name="Legal_Notice" id="Legal_Notice"></a></p>
|
||||
<h2><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=4" title="Edit section: Legal Notice">edit</a>]</span> <span class="mw-headline">Legal Notice</span></h2>
|
||||
<p>This game uses source code from a number of open source projects. For a list, and a location where the source code can be downloaded from, please view the LICENSE.txt file in the renpy directory, or visit <a href="http://www.renpy.org/wiki/renpy/License" class="external free" title="http://www.renpy.org/wiki/renpy/License" rel="nofollow">http://www.renpy.org/wiki/renpy/License</a> .</p>
|
||||
<dl>
|
||||
<dt>Display</dt>
|
||||
<dd>Switches between fullscreen and windowed mode.</dd>
|
||||
<dt>Transitions</dt>
|
||||
<dd>Controls the display of transitions between game screens.</dd>
|
||||
<dt>Text Speed</dt>
|
||||
<dd>Controls the rate at which text displays. The further to the right this slider is, the faster the text will display. All the way to the right causes text to be shown instantly.</dd>
|
||||
<dt>Joystick</dt>
|
||||
<dd>Lets you control the game using a joystick.</dd>
|
||||
<dt>Skip</dt>
|
||||
<dd>Chooses between skipping messages that have been already seen (in any play through the game), and skipping all messages.</dd>
|
||||
<dt>Begin Skipping</dt>
|
||||
<dd>Returns to the game, while skipping.</dd>
|
||||
<dt>After Choices</dt>
|
||||
<dd>Controls if skipping stops upon reaching a menu.</dd>
|
||||
<dt>Auto-Forward Time</dt>
|
||||
<dd>Controls automatic advance. The further to the left this slider is, the shorter the amount of time before the game advances. All the way to the right means text will never auto-forward.</dd>
|
||||
<dt>Music, Sound, and Voice Volume</dt>
|
||||
<dd>Controls the volume of the Music, Sound effect, and Voice channels, respectively. The further to the right these are, the louder the volume.</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Main Menu</dt>
|
||||
<dd>Returns to the main menu, ending the current game.</dd>
|
||||
<dt>Help</dt>
|
||||
<dd>Shows this help screen.</dd>
|
||||
<dt>Quit</dt>
|
||||
<dd>Exits the game; the game will be closed and ended.</dd>
|
||||
</dl>
|
||||
<p><a name="Key_and_Mouse_Bindings" id="Key_and_Mouse_Bindings"></a></p>
|
||||
<h3><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=3" title="Edit section: Key and Mouse Bindings">edit</a>]</span> <span class="mw-headline">Key and Mouse Bindings</span></h3>
|
||||
<dl>
|
||||
<dt>Left-click, Enter</dt>
|
||||
<dd>Advances through the game, activates menu choices, buttons, and sliders.</dd>
|
||||
<dt>Space</dt>
|
||||
<dd>Advances through the game, but does not activate choices.</dd>
|
||||
<dt>Arrow Keys</dt>
|
||||
<dd>Selects menu choices, buttons, and sliders.</dd>
|
||||
<dt>Ctrl</dt>
|
||||
<dd>Causes skipping to occur while the ctrl key is held down.</dd>
|
||||
<dt>Tab</dt>
|
||||
<dd>Toggles skipping, causing it to occur until tab is pressed again.</dd>
|
||||
<dt>Mousewheel-Up, PageUp</dt>
|
||||
<dd>Causes rollback to occur. Rollback reverses the game back in time, showing prior text and even allowing menu choices to be changed.</dd>
|
||||
<dt>Mousewheel-Down, PageDown</dt>
|
||||
<dd>Causes rollforward to occur, cancelling out a previous rollback.</dd>
|
||||
<dt>Right-click, Escape</dt>
|
||||
<dd>Enters the game menu. When in the game menu, returns to the game.</dd>
|
||||
<dt>Middle-click, H</dt>
|
||||
<dd>Hides the text window and other transient displays.</dd>
|
||||
<dt>F</dt>
|
||||
<dd>Toggles fullscreen mode</dd>
|
||||
<dt>S</dt>
|
||||
<dd>Takes a screenshot, saving it in a file named screenshotxxxx.png, where xxxx is a serial number.</dd>
|
||||
<dt>Alt-M, Command-H</dt>
|
||||
<dd>Hides (iconifies) the window.</dd>
|
||||
<dt>Alt-F4, Command-Q</dt>
|
||||
<dd>Quits the game.</dd>
|
||||
<dt>Delete</dt>
|
||||
<dd>When a save slot is selected, deletes that save slot.</dd>
|
||||
<dt>v</dt>
|
||||
<dd>Toggles self-voicing mode, which reads text to the user using an os-supplied
|
||||
speech synthesizer. For more information, please read the <a href="http://www.renpy.org/dev-doc/html/self_voicing.html">self-voicing</a>
|
||||
documentation.</dd>
|
||||
</dl>
|
||||
<p><a name="Legal_Notice" id="Legal_Notice"></a></p>
|
||||
<h2><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=4" title="Edit section: Legal Notice">edit</a>]</span> <span class="mw-headline">Legal Notice</span></h2>
|
||||
<p>This game uses source code from a number of open source projects. For a list, and a location where the source code can be downloaded from, please view the LICENSE.txt file in the renpy directory, or visit <a href="http://www.renpy.org/wiki/renpy/License" class="external free" title="http://www.renpy.org/wiki/renpy/License" rel="nofollow">http://www.renpy.org/wiki/renpy/License</a> .</p>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
@@ -1,27 +1,45 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
# Checks for various abilities that might be taken away from us by
|
||||
# Checks for various abilities that might be taken away from us by
|
||||
# redistributors.
|
||||
|
||||
init 1 python in ability:
|
||||
|
||||
|
||||
from store import config
|
||||
import store
|
||||
import store.updater as updater
|
||||
|
||||
|
||||
import os
|
||||
|
||||
|
||||
EXECUTABLES = [ "renpy.exe", "renpy.app", "renpy.sh" ]
|
||||
|
||||
# can_distribute - True if we can distribute
|
||||
|
||||
# can_distribute - True if we can distribute
|
||||
for i in EXECUTABLES:
|
||||
if not os.path.exists(os.path.join(config.renpy_base, i)):
|
||||
can_distribute = False
|
||||
else:
|
||||
can_distribute = True
|
||||
|
||||
|
||||
|
||||
|
||||
# can_update - True if we can update.
|
||||
can_update = updater.can_update() or (store.UPDATE_SIMULATE is not None)
|
||||
|
||||
|
||||
|
||||
@@ -1,31 +1,49 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
screen about:
|
||||
|
||||
|
||||
$ version = renpy.version()
|
||||
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
|
||||
window:
|
||||
xfill True
|
||||
|
||||
|
||||
has vbox xfill True
|
||||
|
||||
add "logo.png" xalign 0.5 yoffset -5
|
||||
add "images/logo.png" xalign 0.5 yoffset -5
|
||||
|
||||
null height 15
|
||||
|
||||
|
||||
text _("[version!q]") xalign 0.5 bold True
|
||||
|
||||
|
||||
null height 20
|
||||
|
||||
textbutton _("View license") action interface.OpenLicense() xalign 0.5
|
||||
|
||||
|
||||
textbutton _("Back") action Jump("front_page") style "l_left_button"
|
||||
|
||||
label about:
|
||||
call screen about
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
label add_file:
|
||||
|
||||
python hide:
|
||||
import os
|
||||
import codecs
|
||||
|
||||
filename = interface.input(_("FILENAME"), _("Enter the name of the script file to create."), filename="withslash", cancel=Jump("navigation"))
|
||||
|
||||
if "." in filename and not filename.endswith(".rpy"):
|
||||
interface.error(_("The filename must have the .rpy extension."), label="navigation")
|
||||
elif "." not in filename:
|
||||
filename += ".rpy"
|
||||
|
||||
path = os.path.join(project.current.gamedir, filename)
|
||||
dir = os.path.dirname(path)
|
||||
|
||||
if os.path.exists(path):
|
||||
interface.error(_("The file already exists."), label="navigation")
|
||||
|
||||
contents = u"\uFEFF"
|
||||
contents += _("# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n")
|
||||
contents += "\n"
|
||||
|
||||
try:
|
||||
os.makedirs(dir)
|
||||
except:
|
||||
pass
|
||||
|
||||
contents = u"\uFEFF"
|
||||
contents += _("# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n")
|
||||
|
||||
with open(path, "wb") as f:
|
||||
f.write(contents.encode("utf-8"))
|
||||
|
||||
jump navigation_refresh
|
||||
|
||||
@@ -0,0 +1,674 @@
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init python:
|
||||
ANDROID_NO_RAPT = 0
|
||||
ANDROID_NO_JDK = 1
|
||||
ANDROID_NO_SDK = 2
|
||||
ANDROID_NO_KEY = 3
|
||||
ANDROID_NO_CONFIG = 4
|
||||
ANDROID_OK = 5
|
||||
|
||||
NO_RAPT_TEXT = _("To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher.")
|
||||
NO_JDK_TEXT = _("A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher.")
|
||||
NO_SDK_TEXT = _("RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this.")
|
||||
NO_KEY_TEXT = _("RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore.")
|
||||
NO_CONFIG_TEXT = _("The current project has not been configured. Use \"Configure\" to configure it before building.")
|
||||
OK_TEXT = _("Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device.")
|
||||
|
||||
PHONE_TEXT = _("Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button.")
|
||||
TABLET_TEXT = _("Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button.")
|
||||
OUYA_TEXT = _("Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button.")
|
||||
|
||||
INSTALL_SDK_TEXT = _("Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package.")
|
||||
CONFIGURE_TEXT = _("Configures the package name, version, and other information about this project.")
|
||||
PLAY_KEYS_TEXT = _("Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details.")
|
||||
BUILD_TEXT = _("Builds the Android package.")
|
||||
BUILD_AND_INSTALL_TEXT = _("Builds the Android package, and installs it on an Android device connected to your computer.")
|
||||
|
||||
CONNECT_TEXT = _("Connects to an Android device running ADB in TCP/IP mode.")
|
||||
DISCONNECT_TEXT = _("Disconnects from an Android device running ADB in TCP/IP mode.")
|
||||
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
import os
|
||||
import json
|
||||
|
||||
def find_rapt():
|
||||
|
||||
global RAPT_PATH
|
||||
|
||||
candidates = [ ]
|
||||
|
||||
RAPT_PATH = os.path.join(config.renpy_base, "rapt")
|
||||
|
||||
if os.path.isdir(RAPT_PATH):
|
||||
import sys
|
||||
sys.path.insert(0, os.path.join(RAPT_PATH, "buildlib"))
|
||||
else:
|
||||
RAPT_PATH = None
|
||||
RAPT_PATH is None
|
||||
|
||||
find_rapt()
|
||||
|
||||
import threading
|
||||
|
||||
if RAPT_PATH:
|
||||
import rapt
|
||||
import rapt.build
|
||||
import rapt.configure
|
||||
import rapt.install_sdk
|
||||
import rapt.plat
|
||||
import rapt.interface
|
||||
else:
|
||||
rapt = None
|
||||
|
||||
def AndroidState():
|
||||
"""
|
||||
Determines the state of the android install, and returns it.
|
||||
"""
|
||||
|
||||
if RAPT_PATH is None:
|
||||
return ANDROID_NO_RAPT
|
||||
if renpy.windows and not "JAVA_HOME" in os.environ:
|
||||
return ANDROID_NO_JDK
|
||||
if not os.path.exists(rapt.plat.path("android-sdk/extras/google/play_licensing")):
|
||||
return ANDROID_NO_SDK
|
||||
if not os.path.exists(rapt.plat.path("android.keystore")):
|
||||
return ANDROID_NO_KEY
|
||||
if not os.path.exists(rapt.plat.path("local.properties")):
|
||||
return ANDROID_NO_KEY
|
||||
if not os.path.exists(os.path.join(project.current.path, ".android.json")):
|
||||
return ANDROID_NO_CONFIG
|
||||
return ANDROID_OK
|
||||
|
||||
|
||||
def AndroidStateText(state):
|
||||
"""
|
||||
Returns text corresponding to the state.
|
||||
"""
|
||||
|
||||
if state == ANDROID_NO_RAPT:
|
||||
return NO_RAPT_TEXT
|
||||
if state == ANDROID_NO_JDK:
|
||||
return NO_JDK_TEXT
|
||||
if state == ANDROID_NO_SDK:
|
||||
return NO_SDK_TEXT
|
||||
if state == ANDROID_NO_KEY:
|
||||
return NO_KEY_TEXT
|
||||
if state == ANDROID_NO_CONFIG:
|
||||
return NO_CONFIG_TEXT
|
||||
if state == ANDROID_OK:
|
||||
return OK_TEXT
|
||||
|
||||
def AndroidIfState(state, needed, action):
|
||||
"""
|
||||
If `state` is `needed` or better, `action` is returned. Otherwise,
|
||||
returns None, disabling the button.
|
||||
"""
|
||||
|
||||
if state >= needed:
|
||||
return action
|
||||
else:
|
||||
return None
|
||||
|
||||
class AndroidInterface(object):
|
||||
|
||||
def __init__(self):
|
||||
self.process = None
|
||||
self.filename = project.current.temp_filename("android.txt")
|
||||
|
||||
self.info_msg = ""
|
||||
|
||||
with open(self.filename, "w"):
|
||||
pass
|
||||
|
||||
def log(self, msg):
|
||||
with open(self.filename, "a") as f:
|
||||
f.write("\n")
|
||||
f.write(msg)
|
||||
f.write("\n")
|
||||
|
||||
def info(self, prompt):
|
||||
self.info_msg = prompt
|
||||
interface.processing(prompt, pause=False)
|
||||
self.log(prompt)
|
||||
|
||||
def yesno(self, prompt, submessage=None):
|
||||
return interface.yesno(prompt, submessage=submessage)
|
||||
|
||||
def yesno_choice(self, prompt, default=None):
|
||||
choices = [ (True, "Yes"), (False, "No") ]
|
||||
return interface.choice(prompt, choices, default)
|
||||
|
||||
def terms(self, url, prompt):
|
||||
submessage = _("{a=%s}%s{/a}") % (url, url)
|
||||
|
||||
if not interface.yesno(prompt, submessage=submessage):
|
||||
self.fail("You must accept the terms and conditions to proceed.", edit=False)
|
||||
|
||||
|
||||
def input(self, prompt, empty=None):
|
||||
|
||||
if empty is None:
|
||||
empty = ''
|
||||
|
||||
while True:
|
||||
rv = interface.input(_("QUESTION"), prompt, default=empty, cancel=Jump("android"))
|
||||
|
||||
rv = rv.strip()
|
||||
|
||||
if rv:
|
||||
return rv
|
||||
|
||||
def choice(self, prompt, choices, default):
|
||||
return interface.choice(prompt, choices, default, cancel=Jump("android"))
|
||||
|
||||
def fail(self, prompt, edit=True):
|
||||
self.log(prompt)
|
||||
prompt = re.sub(r'(http://\S+)', r'{a=\1}\1{/a}', prompt)
|
||||
|
||||
# Open android.txt in the editor.
|
||||
if edit:
|
||||
editor.EditAbsolute(self.filename)()
|
||||
|
||||
interface.error(prompt, label="android")
|
||||
|
||||
def success(self, prompt):
|
||||
self.log(prompt)
|
||||
interface.info(prompt, pause=False)
|
||||
|
||||
def final_success(self, prompt):
|
||||
self.log(prompt)
|
||||
interface.info(prompt, label="android")
|
||||
|
||||
def run_yes_thread(self):
|
||||
import time
|
||||
|
||||
try:
|
||||
while self.run_yes:
|
||||
self.process.stdin.write('y\n')
|
||||
self.process.stdin.flush()
|
||||
time.sleep(.2)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
def call(self, cmd, cancel=False, use_path=False, yes=False):
|
||||
|
||||
print
|
||||
print " ".join(cmd)
|
||||
|
||||
self.cmd = cmd
|
||||
|
||||
f = open(self.filename, "a")
|
||||
|
||||
f.write("\n\n\n")
|
||||
|
||||
if cancel:
|
||||
cancel_action = self.cancel
|
||||
else:
|
||||
cancel_action = None
|
||||
|
||||
startupinfo = None
|
||||
if renpy.windows:
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
|
||||
self.yes_thread = None
|
||||
|
||||
try:
|
||||
interface.processing(self.info_msg, show_screen=True, cancel=cancel_action)
|
||||
|
||||
kwargs = { }
|
||||
if yes:
|
||||
kwargs["stdin"] = subprocess.PIPE
|
||||
|
||||
try:
|
||||
self.process = subprocess.Popen(cmd, cwd=RAPT_PATH, stdout=f, stderr=f, startupinfo=startupinfo, **kwargs)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc(file=f)
|
||||
raise
|
||||
|
||||
if yes:
|
||||
import threading
|
||||
self.run_yes = True
|
||||
self.yes_thread = threading.Thread(target=self.run_yes_thread)
|
||||
self.yes_thread.daemon = True
|
||||
self.yes_thread.start()
|
||||
|
||||
renpy.call_screen("android_process", interface=self)
|
||||
finally:
|
||||
f.close()
|
||||
interface.hide_screen()
|
||||
|
||||
if yes and self.yes_thread:
|
||||
self.run_yes = False
|
||||
self.yes_thread.join()
|
||||
|
||||
self.process = None
|
||||
self.yes_thread = None
|
||||
|
||||
def check_process(self):
|
||||
rv = self.process.poll()
|
||||
|
||||
if rv is not None:
|
||||
if rv:
|
||||
raise subprocess.CalledProcessError(rv, self.cmd)
|
||||
else:
|
||||
return True
|
||||
|
||||
def download(self, url, dest):
|
||||
try:
|
||||
d = Downloader(url, dest)
|
||||
cancel_action = [ d.cancel, Jump("android") ]
|
||||
interface.processing(self.info_msg, show_screen=True, cancel=cancel_action, bar_value=DownloaderValue(d))
|
||||
ui.timer(.1, action=d.check, repeat=True)
|
||||
ui.interact()
|
||||
finally:
|
||||
interface.hide_screen()
|
||||
|
||||
def background(self, f):
|
||||
try:
|
||||
t = threading.Thread(target=f)
|
||||
t.start()
|
||||
|
||||
interface.processing(self.info_msg, show_screen=True)
|
||||
|
||||
while t.is_alive():
|
||||
renpy.pause(0)
|
||||
t.join(0.25)
|
||||
|
||||
finally:
|
||||
interface.hide_screen()
|
||||
|
||||
|
||||
def cancel(self):
|
||||
if self.process:
|
||||
self.process.terminate()
|
||||
|
||||
renpy.jump("android")
|
||||
|
||||
|
||||
class AndroidBuild(Action):
|
||||
"""
|
||||
Activates an Android build process.
|
||||
"""
|
||||
|
||||
def __init__(self, label):
|
||||
self.label = label
|
||||
|
||||
def __call__(self):
|
||||
renpy.jump(self.label)
|
||||
|
||||
class LaunchEmulator(Action):
|
||||
|
||||
def __init__(self, emulator, variants):
|
||||
self.emulator = emulator
|
||||
self.variants = variants
|
||||
|
||||
def __call__(self):
|
||||
|
||||
env = {
|
||||
"RENPY_EMULATOR" : self.emulator,
|
||||
"RENPY_VARIANT" : self.variants,
|
||||
}
|
||||
|
||||
p = project.current
|
||||
p.launch(env=env)
|
||||
|
||||
def update_android_json(p, gui):
|
||||
"""
|
||||
Updates .android.json to include the google play information.
|
||||
|
||||
`p`
|
||||
The project to update json for.
|
||||
"""
|
||||
|
||||
p.update_dump(True, gui=gui)
|
||||
|
||||
build = p.dump["build"]
|
||||
|
||||
filename = os.path.join(p.path, ".android.json")
|
||||
|
||||
with open(filename, "r") as f:
|
||||
android_json = json.load(f)
|
||||
|
||||
if "google_play_key" in build:
|
||||
android_json["google_play_key"] = build["google_play_key"]
|
||||
else:
|
||||
android_json.pop("google_play_key", None)
|
||||
|
||||
if "google_play_salt" in build:
|
||||
|
||||
if len(build["google_play_salt"]) != 20:
|
||||
raise Exception("build.google_play_salt must be exactly 20 bytes long.")
|
||||
|
||||
android_json["google_play_salt"] = ", ".join(str(i) for i in build["google_play_salt"])
|
||||
else:
|
||||
android_json.pop("google_play_salt", None)
|
||||
|
||||
|
||||
with open(filename, "w") as f:
|
||||
json.dump(android_json, f)
|
||||
|
||||
def android_build(command, p=None, gui=True):
|
||||
"""
|
||||
This actually builds the package.
|
||||
"""
|
||||
|
||||
if p is None:
|
||||
p = project.current
|
||||
|
||||
update_android_json(p, gui)
|
||||
|
||||
dist = p.temp_filename("android.dist")
|
||||
|
||||
if os.path.exists(dist):
|
||||
shutil.rmtree(dist)
|
||||
|
||||
if gui:
|
||||
reporter = distribute.GuiReporter()
|
||||
rapt_interface = AndroidInterface()
|
||||
else:
|
||||
reporter = distribute.TextReporter()
|
||||
rapt_interface = rapt.interface.Interface()
|
||||
|
||||
distribute.Distributor(p,
|
||||
reporter=reporter,
|
||||
packages=[ 'android' ],
|
||||
build_update=False,
|
||||
noarchive=True,
|
||||
packagedest=dist,
|
||||
report_success=False,
|
||||
)
|
||||
|
||||
with interface.nolinks():
|
||||
rapt.build.build(rapt_interface, dist, command)
|
||||
|
||||
# The android support can stick unicode into os.environ. Fix that.
|
||||
init 100 python:
|
||||
for k, v in list(os.environ.items()):
|
||||
if not isinstance(v, str):
|
||||
os.environ[k] = renpy.fsencode(v)
|
||||
|
||||
screen android_process(interface):
|
||||
|
||||
zorder 100
|
||||
|
||||
default ft = FileTail(interface.filename)
|
||||
|
||||
text "[ft.text!q]":
|
||||
size 14
|
||||
color TEXT
|
||||
font "Roboto-Light.ttf"
|
||||
xpos 75
|
||||
ypos 350
|
||||
|
||||
timer .1 action interface.check_process repeat True
|
||||
timer .2 action ft.update repeat True
|
||||
|
||||
|
||||
screen android:
|
||||
|
||||
default tt = Tooltip(None)
|
||||
$ state = AndroidState()
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
window:
|
||||
|
||||
has vbox
|
||||
|
||||
label _("Android: [project.current.name!q]")
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
hbox:
|
||||
|
||||
# Left side.
|
||||
frame:
|
||||
style "l_indent"
|
||||
xmaximum ONEHALF
|
||||
xfill True
|
||||
|
||||
has vbox
|
||||
|
||||
add SEPARATOR2
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
has vbox
|
||||
|
||||
text _("Emulation:")
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
frame style "l_indent":
|
||||
|
||||
has vbox
|
||||
|
||||
textbutton _("Phone"):
|
||||
action LaunchEmulator("touch", "small phone touch android")
|
||||
hovered tt.Action(PHONE_TEXT)
|
||||
|
||||
textbutton _("Tablet"):
|
||||
action LaunchEmulator("touch", "medium tablet touch android")
|
||||
hovered tt.Action(TABLET_TEXT)
|
||||
|
||||
textbutton _("Television / OUYA"):
|
||||
action LaunchEmulator("tv", "small tv ouya android")
|
||||
hovered tt.Action(OUYA_TEXT)
|
||||
|
||||
|
||||
add SPACER
|
||||
add SEPARATOR2
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
has vbox
|
||||
|
||||
text _("Build:")
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
frame style "l_indent":
|
||||
|
||||
has vbox
|
||||
|
||||
textbutton _("Install SDK & Create Keys"):
|
||||
action AndroidIfState(state, ANDROID_NO_SDK, Jump("android_installsdk"))
|
||||
hovered tt.Action(INSTALL_SDK_TEXT)
|
||||
|
||||
textbutton _("Configure"):
|
||||
action AndroidIfState(state, ANDROID_NO_CONFIG, Jump("android_configure"))
|
||||
hovered tt.Action(CONFIGURE_TEXT)
|
||||
|
||||
textbutton _("Build Package"):
|
||||
action AndroidIfState(state, ANDROID_OK, AndroidBuild("android_build"))
|
||||
hovered tt.Action(BUILD_TEXT)
|
||||
|
||||
textbutton _("Build & Install"):
|
||||
action AndroidIfState(state, ANDROID_OK, AndroidBuild("android_build_and_install"))
|
||||
hovered tt.Action(BUILD_AND_INSTALL_TEXT)
|
||||
|
||||
add SPACER
|
||||
add SEPARATOR2
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
has vbox
|
||||
|
||||
text _("Other:")
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
frame style "l_indent":
|
||||
|
||||
has vbox
|
||||
|
||||
textbutton _("Remote ADB Connect"):
|
||||
action AndroidIfState(state, ANDROID_OK, Jump("android_connect"))
|
||||
hovered tt.Action(CONNECT_TEXT)
|
||||
|
||||
textbutton _("Remote ADB Disconnect"):
|
||||
action AndroidIfState(state, ANDROID_OK, Jump("android_disconnect"))
|
||||
hovered tt.Action(DISCONNECT_TEXT)
|
||||
|
||||
|
||||
# Right side.
|
||||
frame:
|
||||
style "l_indent"
|
||||
xmaximum ONEHALF
|
||||
xfill True
|
||||
|
||||
has vbox
|
||||
|
||||
add SEPARATOR2
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
has vbox
|
||||
|
||||
add SPACER
|
||||
|
||||
if tt.value:
|
||||
text tt.value
|
||||
else:
|
||||
text AndroidStateText(state)
|
||||
|
||||
|
||||
textbutton _("Back") action Jump("front_page") style "l_left_button"
|
||||
|
||||
|
||||
label android:
|
||||
|
||||
if RAPT_PATH is None:
|
||||
$ interface.yesno(_("Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"), no=Jump("front_page"))
|
||||
$ add_dlc("rapt", restart=True)
|
||||
|
||||
call screen android
|
||||
|
||||
|
||||
label android_installsdk:
|
||||
|
||||
python:
|
||||
with interface.nolinks():
|
||||
rapt.install_sdk.install_sdk(AndroidInterface())
|
||||
|
||||
jump android
|
||||
|
||||
|
||||
label android_configure:
|
||||
|
||||
python:
|
||||
rapt.configure.configure(AndroidInterface(), project.current.path)
|
||||
|
||||
jump android
|
||||
|
||||
|
||||
label android_build:
|
||||
|
||||
$ android_build([ 'release' ])
|
||||
|
||||
jump android
|
||||
|
||||
|
||||
label android_build_and_install:
|
||||
|
||||
$ android_build([ 'release', 'install' ])
|
||||
|
||||
jump android
|
||||
|
||||
label android_connect:
|
||||
|
||||
python hide:
|
||||
|
||||
if persistent.connect_address is not None:
|
||||
address = persistent.connect_address
|
||||
else:
|
||||
address = ""
|
||||
|
||||
while True:
|
||||
address = interface.input(
|
||||
_("Remote ADB Address"),
|
||||
_("Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."),
|
||||
default=address,
|
||||
cancel=Jump("android"),
|
||||
)
|
||||
|
||||
address = address.strip()
|
||||
|
||||
try:
|
||||
host, port = address.split(":")
|
||||
except:
|
||||
interface.error(_("Invalid remote ADB address"), _("The address must contain one exactly one ':'."), label=None)
|
||||
continue
|
||||
|
||||
if " " in host:
|
||||
interface.error(_("Invalid remote ADB address"), _("The host may not contain whitespace."), label=None)
|
||||
continue
|
||||
|
||||
try:
|
||||
int(port)
|
||||
except:
|
||||
interface.error(_("Invalid remote ADB address"), _("The port must be a number."), label=None)
|
||||
continue
|
||||
|
||||
break
|
||||
|
||||
persistent.connect_address = address
|
||||
|
||||
rapt_interface = AndroidInterface()
|
||||
rapt.build.connect(rapt_interface, address)
|
||||
|
||||
jump android
|
||||
|
||||
label android_disconnect:
|
||||
|
||||
python hide:
|
||||
|
||||
rapt_interface = AndroidInterface()
|
||||
rapt.build.disconnect(rapt_interface)
|
||||
|
||||
jump android
|
||||
|
||||
init python:
|
||||
|
||||
def android_build_command():
|
||||
ap = renpy.arguments.ArgumentParser()
|
||||
ap.add_argument("project", help="The path to the project directory.")
|
||||
ap.add_argument("command", help="Commands to pass to ant. (Try 'release' 'install'.)", nargs='+')
|
||||
|
||||
args = ap.parse_args()
|
||||
|
||||
p = project.Project(args.project)
|
||||
|
||||
android_build(args.command, p=p, gui=False)
|
||||
|
||||
return False
|
||||
|
||||
renpy.arguments.register_command("android_build", android_build_command)
|
||||
|
||||
@@ -1,8 +1,26 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
# Ren'Py archiver. This builds a Ren'Py archive file, and the
|
||||
# associated index file. These files are really easy to
|
||||
# associated index file. These files are really easy to
|
||||
# reverse-engineer, but are probably better than nothing.
|
||||
|
||||
init python in archiver:
|
||||
@@ -23,16 +41,16 @@ init python in archiver:
|
||||
|
||||
# The archive file.
|
||||
self.f = open(filename, "wb")
|
||||
|
||||
|
||||
# The index to the file.
|
||||
self.index = _dict()
|
||||
|
||||
|
||||
# A fixed key minimizes difference between archive versions.
|
||||
self.key = 0x42424242
|
||||
|
||||
padding = "RPA-3.0 XXXXXXXXXXXXXXXX XXXXXXXX\n"
|
||||
self.f.write(padding)
|
||||
|
||||
|
||||
def add(self, name, path):
|
||||
"""
|
||||
Adds a file to the archive.
|
||||
@@ -55,7 +73,7 @@ init python in archiver:
|
||||
self.index[name].append((offset ^ self.key, dlen ^ self.key, ""))
|
||||
|
||||
def close(self):
|
||||
|
||||
|
||||
indexoff = self.f.tell()
|
||||
|
||||
self.f.write(dumps(self.index, HIGHEST_PROTOCOL).encode("zlib"))
|
||||
@@ -64,4 +82,4 @@ init python in archiver:
|
||||
self.f.write("RPA-3.0 %016x %08x\n" % (indexoff, self.key))
|
||||
|
||||
self.f.close()
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
# http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/pefile.html
|
||||
# Contains a reasonable description of the format.
|
||||
@@ -5,7 +26,7 @@
|
||||
import struct
|
||||
import sys
|
||||
import array
|
||||
import pefile
|
||||
import pefile # @UnresolvedImport
|
||||
|
||||
# This class performs various operations on memory-loaded binary files,
|
||||
# including modifications.
|
||||
@@ -16,7 +37,7 @@ class BinFile(object):
|
||||
self.a[addr+1] = (value >> 8) & 0xff
|
||||
self.a[addr+2] = (value >> 16) & 0xff
|
||||
self.a[addr+3] = (value >> 24) & 0xff
|
||||
|
||||
|
||||
def u32(self):
|
||||
addr = self.addr
|
||||
rv = self.a[addr]
|
||||
@@ -46,7 +67,7 @@ class BinFile(object):
|
||||
rv += unichr(self.u16())
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
def seek(self, addr):
|
||||
self.addr = addr
|
||||
|
||||
@@ -55,7 +76,7 @@ class BinFile(object):
|
||||
|
||||
def substring(self, start, len): #@ReservedAssignment
|
||||
return self.a[start:start+len].tostring()
|
||||
|
||||
|
||||
def __init__(self, data):
|
||||
self.a = array.array('B')
|
||||
self.a.fromstring(data)
|
||||
@@ -66,7 +87,7 @@ class BinFile(object):
|
||||
|
||||
# The virtual address of the resource segment.
|
||||
resource_virtual = 0
|
||||
|
||||
|
||||
# This parses a data block out of the resources.
|
||||
def parse_data(bf, offset):
|
||||
bf.seek(offset)
|
||||
@@ -95,7 +116,7 @@ def parse_directory(bf, offset):
|
||||
n_id = bf.u16()
|
||||
|
||||
entries = [ ]
|
||||
|
||||
|
||||
for _i in range(n_named + n_id):
|
||||
entries.append((bf.u32(), bf.u32()))
|
||||
|
||||
@@ -113,8 +134,8 @@ def parse_directory(bf, offset):
|
||||
value = parse_data(bf, value)
|
||||
|
||||
rv[name] = value
|
||||
|
||||
return rv
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
##############################################################################
|
||||
@@ -124,7 +145,7 @@ def show_resources(d, prefix):
|
||||
if not isinstance(d, dict):
|
||||
print prefix, "Codepage", d[0], "length", len(d[1])
|
||||
return
|
||||
|
||||
|
||||
for k in d:
|
||||
print prefix, k
|
||||
show_resources(d[k], prefix + " ")
|
||||
@@ -141,7 +162,7 @@ class Packer(object):
|
||||
|
||||
self.entries = ""
|
||||
self.entries_offset = 0
|
||||
|
||||
|
||||
head = self.pack_dict(d, 0)
|
||||
|
||||
self.data = ""
|
||||
@@ -151,44 +172,44 @@ class Packer(object):
|
||||
self.entries_offset = len(head)
|
||||
|
||||
return self.pack_dict(d, 0) + self.entries + self.data
|
||||
|
||||
|
||||
def pack_name(self, s):
|
||||
rv = self.data_offset + len(self.data)
|
||||
|
||||
l = len(s)
|
||||
s = s.encode("utf-16le")
|
||||
self.data += struct.pack("<H", l) + s + "\0\0"
|
||||
|
||||
|
||||
return rv
|
||||
|
||||
def pack_tuple(self, t):
|
||||
codepage, data = t
|
||||
|
||||
rv = len(self.entries) + self.entries_offset
|
||||
rv = len(self.entries) + self.entries_offset
|
||||
|
||||
if len(self.data) % 2:
|
||||
self.data += "P"
|
||||
|
||||
daddr = len(self.data) + self.data_offset
|
||||
|
||||
|
||||
self.entries += struct.pack("<IIII", daddr + resource_virtual, len(data), codepage, 0)
|
||||
self.data += data
|
||||
|
||||
# if len(self.data) % 1 == 1:
|
||||
# self.data += 'P'
|
||||
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
def pack_dict(self, d, offset):
|
||||
name_entries = sorted((a, b) for a, b in d.iteritems() if isinstance(a, unicode))
|
||||
id_entries = sorted((a, b) for a, b in d.iteritems() if isinstance(a, int))
|
||||
|
||||
|
||||
rv = struct.pack("<IIHHHH", 0, 0, 4, 0, len(name_entries), len(id_entries))
|
||||
|
||||
|
||||
offset += len(rv) + (len(name_entries) + len(id_entries)) * 8
|
||||
|
||||
|
||||
rest = ""
|
||||
|
||||
|
||||
for (name, value) in name_entries + id_entries:
|
||||
if isinstance(name, unicode):
|
||||
name = 0x80000000 | self.pack_name(name)
|
||||
@@ -200,11 +221,11 @@ class Packer(object):
|
||||
rest += packed
|
||||
else:
|
||||
addr = self.pack_tuple(value)
|
||||
|
||||
|
||||
rv += struct.pack("<II", name, addr)
|
||||
|
||||
return rv + rest
|
||||
|
||||
|
||||
##############################################################################
|
||||
# This loads in an icon file, and returns a dictionary that is suitable for
|
||||
# use in the resources of an exe file.
|
||||
@@ -219,8 +240,8 @@ def load_icon(fn):
|
||||
rv = { }
|
||||
rv[3] = { }
|
||||
|
||||
group = struct.pack("HHH", 0, 1, count)
|
||||
|
||||
group = struct.pack("HHH", 0, 1, count)
|
||||
|
||||
for i in range(count):
|
||||
width = f.u8()
|
||||
height = f.u8()
|
||||
@@ -235,17 +256,17 @@ def load_icon(fn):
|
||||
f.seek(offset + 16)
|
||||
if not f.u32():
|
||||
f.set_u32(offset + 20, 0)
|
||||
|
||||
|
||||
rv[3][i + 1] = { 0 : (1252, f.substring(offset, size)) }
|
||||
|
||||
|
||||
group += struct.pack("BBBBHHIH", width, height, colors, reserved,
|
||||
planes, bpp, size, i + 1)
|
||||
|
||||
|
||||
f.seek(addr)
|
||||
|
||||
rv[14] = { 1 : { 0 : (1252, group) } }
|
||||
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
@@ -269,25 +290,25 @@ def change_icons(oldexe, icofn):
|
||||
|
||||
physize = rsrc_section.SizeOfRawData
|
||||
virsize = rsrc_section.Misc_VirtualSize
|
||||
|
||||
|
||||
f = file(oldexe, "rb")
|
||||
f.seek(base)
|
||||
data = f.read(physize)
|
||||
f.close()
|
||||
|
||||
bf = BinFile(data)
|
||||
|
||||
|
||||
resources = parse_directory(bf, 0)
|
||||
# show_resources(resources, "")
|
||||
resources.update(load_icon(icofn))
|
||||
# show_resources(resources, "")
|
||||
|
||||
|
||||
rsrc = Packer().pack(resources)
|
||||
|
||||
alignment = pe.OPTIONAL_HEADER.SectionAlignment
|
||||
|
||||
|
||||
# print "Alignment is", alignment
|
||||
|
||||
|
||||
if len(rsrc) % alignment:
|
||||
pad = alignment - (len(rsrc) % alignment)
|
||||
padding = "RENPYVNE" * (pad / 8 + 1)
|
||||
@@ -295,34 +316,34 @@ def change_icons(oldexe, icofn):
|
||||
rsrc += padding
|
||||
|
||||
newsize = len(rsrc)
|
||||
|
||||
|
||||
rsrc_section.Misc_VirtualSize += newsize - virsize
|
||||
rsrc_section.Misc_PhysicalAddress += newsize - virsize
|
||||
rsrc_section.Misc += newsize - virsize
|
||||
rsrc_section.SizeOfRawData += newsize - physize
|
||||
|
||||
pe.OPTIONAL_HEADER.SizeOfInitializedData += newsize - physize
|
||||
|
||||
pe.OPTIONAL_HEADER.SizeOfInitializedData += newsize - physize
|
||||
|
||||
# Resource size.
|
||||
pe.OPTIONAL_HEADER.DATA_DIRECTORY[2].Size += newsize - virsize
|
||||
|
||||
# Compute the total size of the image.
|
||||
total_size = 0
|
||||
|
||||
|
||||
for i in pe.sections:
|
||||
|
||||
sec_size = i.Misc_VirtualSize
|
||||
sec_size = sec_size - (sec_size % alignment) + alignment
|
||||
|
||||
|
||||
total_size += sec_size
|
||||
|
||||
pe.OPTIONAL_HEADER.SizeOfImage = total_size
|
||||
|
||||
return pe.write()[:base] + rsrc
|
||||
|
||||
return pe.write()[:base] + rsrc
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
f = file(sys.argv[3], "wb")
|
||||
f.write(change_icons(sys.argv[1], sys.argv[2]))
|
||||
f.close()
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,5 +1,23 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init python:
|
||||
import random
|
||||
@@ -11,121 +29,132 @@ init python:
|
||||
"""
|
||||
Gets a list of all of the theme names we know about.
|
||||
"""
|
||||
|
||||
|
||||
names = list(theme_data.THEME.keys())
|
||||
names.sort(key=lambda a : a.lower())
|
||||
|
||||
|
||||
return names
|
||||
|
||||
|
||||
def scheme_names(theme):
|
||||
"""
|
||||
Gets a list of the color scheme names corresponding to the given
|
||||
theme.
|
||||
"""
|
||||
|
||||
|
||||
names = list(theme_data.THEME[theme].keys())
|
||||
names.sort(key=lambda a : a.lower())
|
||||
|
||||
|
||||
return names
|
||||
|
||||
def theme_yinitial():
|
||||
names = theme_names()
|
||||
|
||||
|
||||
if len(names) < 2:
|
||||
return 0
|
||||
|
||||
|
||||
return 1.0 * names.index(current_theme) / (len(names) - 1)
|
||||
|
||||
def scheme_yinitial():
|
||||
names = scheme_names(current_theme)
|
||||
|
||||
|
||||
if len(names) < 2:
|
||||
return 0
|
||||
|
||||
|
||||
return 1.0 * names.index(current_scheme) / (len(names) - 1)
|
||||
|
||||
def pick_theme(theme, scheme):
|
||||
"""
|
||||
Returns a theme and scheme that are similar to `theme` and `scheme`.
|
||||
|
||||
Returns a theme and scheme that are similar to `theme` and `scheme`.
|
||||
|
||||
If the theme is known, picks it, otherwise picks a random theme. If
|
||||
the scheme is known for that theme, picks it, otherwise picks a
|
||||
the scheme is known for that theme, picks it, otherwise picks a
|
||||
random scheme that is known for the current theme.
|
||||
"""
|
||||
|
||||
|
||||
if theme not in theme_data.THEME:
|
||||
theme = random.choice(list(theme_data.THEME))
|
||||
|
||||
|
||||
schemes = theme_data.THEME[theme]
|
||||
|
||||
|
||||
if scheme not in schemes:
|
||||
if theme in schemes:
|
||||
scheme = theme
|
||||
else:
|
||||
scheme = random.choice(list(schemes))
|
||||
|
||||
|
||||
return theme, scheme
|
||||
|
||||
|
||||
def implement_theme(theme, scheme):
|
||||
"""
|
||||
Implement the current theme.
|
||||
|
||||
This function uses non-public APIs.
|
||||
"""
|
||||
|
||||
global showing_theme, showing_scheme
|
||||
|
||||
|
||||
if theme == showing_theme and scheme == showing_scheme:
|
||||
return
|
||||
|
||||
renpy.style.restore(style_backup)
|
||||
exec theme_data.THEME[theme][scheme] in globals()
|
||||
renpy.style.rebuild()
|
||||
|
||||
# Rebuild the style cache.
|
||||
renpy.style.rebuild(False)
|
||||
|
||||
# Bust the render cache, so we re-evaluate the styles.
|
||||
renpy.display.interface.kill_textures()
|
||||
|
||||
showing_theme = theme
|
||||
showing_scheme = scheme
|
||||
|
||||
renpy.restart_interaction()
|
||||
|
||||
|
||||
showing_theme = None
|
||||
showing_scheme = None
|
||||
|
||||
class SetTheme(Action):
|
||||
def __init__(self, theme):
|
||||
self.theme = theme
|
||||
|
||||
|
||||
def __call__(self):
|
||||
global current_theme
|
||||
global current_scheme
|
||||
|
||||
global current_scheme
|
||||
|
||||
current_theme, current_scheme = pick_theme(self.theme, current_scheme)
|
||||
|
||||
|
||||
implement_theme(current_theme, current_scheme)
|
||||
renpy.restart_interaction()
|
||||
|
||||
def get_selected(self):
|
||||
return current_theme == self.theme
|
||||
|
||||
|
||||
class SetScheme(Action):
|
||||
def __init__(self, scheme):
|
||||
self.scheme = scheme
|
||||
|
||||
|
||||
def __call__(self):
|
||||
global current_theme
|
||||
global current_scheme
|
||||
|
||||
global current_scheme
|
||||
|
||||
current_theme, current_scheme = pick_theme(current_theme, self.scheme)
|
||||
|
||||
|
||||
implement_theme(current_theme, current_scheme)
|
||||
renpy.restart_interaction()
|
||||
|
||||
|
||||
def get_selected(self):
|
||||
return current_scheme == self.scheme
|
||||
|
||||
|
||||
class PreviewTheme(Action):
|
||||
|
||||
|
||||
def __init__(self, theme, scheme):
|
||||
self.theme = theme
|
||||
self.scheme = scheme
|
||||
|
||||
|
||||
def __call__(self):
|
||||
theme, scheme = pick_theme(self.theme, self.scheme)
|
||||
implement_theme(theme, scheme)
|
||||
|
||||
|
||||
def unhovered(self):
|
||||
if (showing_theme == self.theme and showing_scheme == self.scheme):
|
||||
implement_theme(current_theme, current_scheme)
|
||||
@@ -135,11 +164,11 @@ init python:
|
||||
|
||||
##########################################################################
|
||||
# Code to update options.rpy
|
||||
|
||||
|
||||
def list_logical_lines(filename):
|
||||
"""
|
||||
This reads in filename, and turns it into a list of logical
|
||||
lines.
|
||||
lines.
|
||||
"""
|
||||
|
||||
f = codecs.open(filename, "rb", "utf-8")
|
||||
@@ -227,7 +256,7 @@ init python:
|
||||
continue
|
||||
|
||||
continue
|
||||
|
||||
|
||||
line += c
|
||||
pos += 1
|
||||
|
||||
@@ -239,7 +268,7 @@ init python:
|
||||
|
||||
def switch_theme():
|
||||
"""
|
||||
Switches the theme of the current project to the current theme
|
||||
Switches the theme of the current project to the current theme
|
||||
and color scheme. (As set in current_theme and current_scheme.)
|
||||
"""
|
||||
|
||||
@@ -258,7 +287,7 @@ init python:
|
||||
if (not changed) and m and (m.group(1) in theme_data.THEME_FUNCTIONS):
|
||||
l = " " + theme_code
|
||||
changed = True
|
||||
|
||||
|
||||
out.write(l + "\n")
|
||||
|
||||
if changed:
|
||||
@@ -272,7 +301,7 @@ init python:
|
||||
else:
|
||||
os.unlink(filename + ".new")
|
||||
interface.error(_("Could not change the theme. Perhaps options.rpy was changed too much."))
|
||||
|
||||
|
||||
|
||||
# Now give the theme's screen-ops function a chance to make any
|
||||
# necessary changes to the screens.rpy file
|
||||
@@ -289,13 +318,13 @@ init python:
|
||||
for l in lines:
|
||||
out.write(l + "\n")
|
||||
changed = True
|
||||
|
||||
|
||||
if changed:
|
||||
try:
|
||||
os.unlink(filename + ".bak")
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
os.rename(filename, filename + ".bak")
|
||||
os.rename(filename + ".new", filename)
|
||||
|
||||
@@ -307,13 +336,20 @@ init python:
|
||||
pass
|
||||
pass
|
||||
|
||||
def make_style_backup():
|
||||
"""
|
||||
Call this to back up the styles. This should be called in a
|
||||
translate python block in each translation.
|
||||
"""
|
||||
|
||||
init 100 python:
|
||||
style_backup = renpy.style.backup()
|
||||
global style_backup
|
||||
style_backup = renpy.style.backup()
|
||||
|
||||
translate None python:
|
||||
make_style_backup()
|
||||
|
||||
screen theme_demo:
|
||||
|
||||
|
||||
window:
|
||||
style "gm_root"
|
||||
xpadding 5
|
||||
@@ -324,16 +360,16 @@ screen theme_demo:
|
||||
style_group "prefs"
|
||||
|
||||
vbox:
|
||||
|
||||
|
||||
frame:
|
||||
style_group "pref"
|
||||
has vbox
|
||||
|
||||
|
||||
label _("Display")
|
||||
textbutton _("Window") action SelectedIf(True)
|
||||
textbutton _("Fullscreen") action ui.returns(None)
|
||||
textbutton _("Planetarium") action None
|
||||
|
||||
|
||||
|
||||
frame:
|
||||
style_group "pref"
|
||||
@@ -368,16 +404,16 @@ screen choose_theme:
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
|
||||
window:
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
label _("Choose Theme")
|
||||
|
||||
hbox:
|
||||
yfill True
|
||||
|
||||
|
||||
# Theme selector.
|
||||
frame:
|
||||
style "l_indent"
|
||||
@@ -385,51 +421,51 @@ screen choose_theme:
|
||||
xmaximum 225
|
||||
|
||||
has vbox
|
||||
|
||||
|
||||
label _("Theme") style "l_label_small"
|
||||
|
||||
viewport:
|
||||
scrollbars "vertical"
|
||||
yinitial theme_yinitial()
|
||||
mousewheel True
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
|
||||
for i in theme_names():
|
||||
textbutton "[i]":
|
||||
action SetTheme(i)
|
||||
hovered PreviewTheme(i, current_scheme)
|
||||
style "l_list2"
|
||||
style "l_list2"
|
||||
|
||||
|
||||
|
||||
# Color scheme selector.
|
||||
frame:
|
||||
style "l_indent"
|
||||
bottom_margin HALF_SPACER_HEIGHT
|
||||
xmaximum 225
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
|
||||
label _("Color Scheme") style "l_label_small"
|
||||
|
||||
|
||||
viewport:
|
||||
scrollbars "vertical"
|
||||
mousewheel True
|
||||
yinitial scheme_yinitial()
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
|
||||
for i in scheme_names(current_theme):
|
||||
textbutton "[i]":
|
||||
textbutton "[i]":
|
||||
action SetScheme(i)
|
||||
hovered PreviewTheme(current_theme, i)
|
||||
style "l_list2"
|
||||
style "l_list2"
|
||||
|
||||
|
||||
|
||||
# Preview
|
||||
frame:
|
||||
style "l_default"
|
||||
background Frame("pattern.png", 0, 0, tile=True)
|
||||
background Frame(PATTERN, 0, 0, tile=True)
|
||||
xpadding 5
|
||||
ypadding 5
|
||||
|
||||
@@ -437,19 +473,19 @@ screen choose_theme:
|
||||
yfill True
|
||||
xmargin 20
|
||||
bottom_margin 6
|
||||
|
||||
|
||||
use theme_demo
|
||||
|
||||
textbutton _("Back") action Jump("front_page") style "l_left_button"
|
||||
textbutton _("Continue") action Return(True) style "l_right_button"
|
||||
|
||||
|
||||
|
||||
label choose_theme_callable:
|
||||
|
||||
python:
|
||||
current_theme, current_scheme = pick_theme(None, None)
|
||||
implement_theme(current_theme, current_scheme)
|
||||
|
||||
implement_theme(current_theme, current_scheme)
|
||||
|
||||
call screen choose_theme
|
||||
|
||||
python hide:
|
||||
@@ -457,9 +493,7 @@ label choose_theme_callable:
|
||||
switch_theme()
|
||||
|
||||
return
|
||||
|
||||
|
||||
label choose_theme:
|
||||
call choose_theme_callable
|
||||
jump front_page
|
||||
|
||||
|
||||
|
||||
@@ -1,70 +1,88 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init python:
|
||||
class PackageToggle(Action):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
def get_selected(self):
|
||||
return self.name in project.current.data['packages']
|
||||
|
||||
return self.name in project.current.data['packages']
|
||||
|
||||
def __call__(self):
|
||||
packages = project.current.data['packages']
|
||||
|
||||
|
||||
if self.name in packages:
|
||||
packages.remove(self.name)
|
||||
else:
|
||||
packages.append(self.name)
|
||||
|
||||
|
||||
project.current.save_data()
|
||||
renpy.restart_interaction()
|
||||
|
||||
class DataToggle(Action):
|
||||
def __init__(self, field):
|
||||
self.field = field
|
||||
|
||||
|
||||
def get_selected(self):
|
||||
return project.current.data[self.field]
|
||||
|
||||
|
||||
def __call__(self):
|
||||
project.current.data[self.field] = not project.current.data[self.field]
|
||||
|
||||
|
||||
project.current.save_data()
|
||||
renpy.restart_interaction()
|
||||
|
||||
|
||||
DEFAULT_BUILD_INFO = """
|
||||
|
||||
## This section contains information about how to build your project into
|
||||
|
||||
## This section contains information about how to build your project into
|
||||
## distribution files.
|
||||
init python:
|
||||
|
||||
|
||||
## The name that's used for directories and archive files. For example, if
|
||||
## this is 'mygame-1.0', the windows distribution will be in the
|
||||
## directory 'mygame-1.0-win', in the 'mygame-1.0-win.zip' file.
|
||||
build.directory_name = "PROJECTNAME-1.0"
|
||||
|
||||
|
||||
## The name that's uses for executables - the program that users will run
|
||||
## to start the game. For example, if this is 'mygame', then on Windows,
|
||||
## users can click 'mygame.exe' to start the game.
|
||||
build.executable_name = "PROJECTNAME"
|
||||
|
||||
|
||||
## If True, Ren'Py will include update information into packages. This
|
||||
## allows the updater to run.
|
||||
build.include_update = False
|
||||
|
||||
|
||||
## File patterns:
|
||||
##
|
||||
##
|
||||
## The following functions take file patterns. File patterns are case-
|
||||
## insensitive, and matched against the path relative to the base
|
||||
## directory, with and without a leading /. If multiple patterns match,
|
||||
## the first is used.
|
||||
##
|
||||
##
|
||||
##
|
||||
## In a pattern:
|
||||
##
|
||||
## /
|
||||
## /
|
||||
## Is the directory separator.
|
||||
## *
|
||||
## Matches all characters, except the directory separator.
|
||||
@@ -87,9 +105,9 @@ init python:
|
||||
build.classify('**/.**', None)
|
||||
build.classify('**/#**', None)
|
||||
build.classify('**/thumbs.db', None)
|
||||
|
||||
|
||||
## To archive files, classify them as 'archive'.
|
||||
|
||||
|
||||
# build.classify('game/**.png', 'archive')
|
||||
# build.classify('game/**.jpg', 'archive')
|
||||
|
||||
@@ -100,7 +118,7 @@ init python:
|
||||
build.documentation('*.txt')
|
||||
"""
|
||||
|
||||
# A screen that displays a file or directory name, and
|
||||
# A screen that displays a file or directory name, and
|
||||
# lets the user change it,
|
||||
#
|
||||
# title
|
||||
@@ -108,17 +126,17 @@ init python:
|
||||
# value
|
||||
# The value of the field.
|
||||
screen distribute_name:
|
||||
|
||||
|
||||
add SEPARATOR2
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
has vbox
|
||||
|
||||
|
||||
text title
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
text "[value!q]"
|
||||
@@ -127,27 +145,27 @@ screen distribute_name:
|
||||
|
||||
|
||||
screen build_distributions:
|
||||
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
|
||||
window:
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
label _("Build Distributions: [project.current.name!q]")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
hbox:
|
||||
|
||||
|
||||
# Left side.
|
||||
frame:
|
||||
style "l_indent"
|
||||
xmaximum ONEHALF
|
||||
xfill True
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
use distribute_name(
|
||||
@@ -159,23 +177,23 @@ screen build_distributions:
|
||||
value=project.current.dump["build"]["executable_name"])
|
||||
|
||||
add SEPARATOR2
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
has vbox
|
||||
|
||||
|
||||
text _("Actions:")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
frame style "l_indent":
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
textbutton _("Edit options.rpy") action editor.Edit("game/options.rpy", check=True)
|
||||
textbutton _("Refresh") action Jump("build_distributions")
|
||||
|
||||
|
||||
|
||||
|
||||
# Right side.
|
||||
frame:
|
||||
style "l_indent"
|
||||
@@ -185,23 +203,22 @@ screen build_distributions:
|
||||
has vbox
|
||||
|
||||
add SEPARATOR2
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
has vbox
|
||||
|
||||
|
||||
text _("Build Packages:")
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
$ packages = project.current.dump["build"]["packages"]
|
||||
|
||||
|
||||
for pkg in packages:
|
||||
|
||||
$ description = pkg["description"]
|
||||
|
||||
textbutton "[description!q]" action PackageToggle(pkg["name"]) style "l_checkbox"
|
||||
|
||||
if not pkg["hidden"]:
|
||||
$ description = pkg["description"]
|
||||
textbutton "[description!q]" action PackageToggle(pkg["name"]) style "l_checkbox"
|
||||
|
||||
add SPACER
|
||||
|
||||
if project.current.dump["build"]["include_update"]:
|
||||
@@ -214,34 +231,30 @@ screen build_distributions:
|
||||
label build_update_dump:
|
||||
python:
|
||||
project.current.update_dump(True)
|
||||
|
||||
|
||||
if project.current.dump.get("error", False):
|
||||
interface.error(_("Errors were detected when running the project. Please ensure the project runs without errors before building distributions."))
|
||||
|
||||
|
||||
return
|
||||
|
||||
label build_distributions:
|
||||
|
||||
|
||||
call build_update_dump
|
||||
|
||||
|
||||
if not project.current.dump["build"]["directory_name"]:
|
||||
jump build_missing
|
||||
|
||||
call screen build_distributions
|
||||
|
||||
label build_missing:
|
||||
|
||||
|
||||
python hide:
|
||||
|
||||
|
||||
interface.yesno(_("Your project does not contain build information. Would you like to add build information to the end of options.rpy?"), yes=Return(True), no=Jump("front_page"))
|
||||
|
||||
build_info = DEFAULT_BUILD_INFO.replace("PROJECTNAME", project.current.name)
|
||||
|
||||
|
||||
with open(os.path.join(project.current.path, "game", "options.rpy"), "a") as f:
|
||||
f.write(build_info)
|
||||
|
||||
jump build_distributions
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init python:
|
||||
|
||||
import urllib2
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
|
||||
class Downloader(object):
|
||||
|
||||
def __init__(self, url, dest):
|
||||
"""
|
||||
Downloads `url` to `dest`, providing progress reports
|
||||
as necessary.
|
||||
"""
|
||||
|
||||
self.url = url
|
||||
|
||||
# The destination file, and the destination temp file.
|
||||
self.dest = dest
|
||||
self.tmp = dest + ".tmp"
|
||||
|
||||
# Open the tmpfile.
|
||||
self.safe_unlink(self.tmp)
|
||||
self.tmpfile = open(self.tmp, "wb")
|
||||
|
||||
# Set by the thread to indicate progress (ranges from 0.0 to 1.0).
|
||||
self.progress = 0.0
|
||||
|
||||
# This is set to true by cancel() to indicate the download should be cancelled.
|
||||
self.cancelled = False
|
||||
|
||||
# Set on succes or failure.
|
||||
self.success = False
|
||||
self.failure = None
|
||||
|
||||
try:
|
||||
# Open the URL.
|
||||
self.urlfile = urllib2.urlopen(url)
|
||||
|
||||
t = threading.Thread(target=self.thread)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
except Exception as e:
|
||||
self.failure = str(e)
|
||||
|
||||
def thread(self):
|
||||
|
||||
try:
|
||||
count = 0
|
||||
|
||||
if "content-length" in self.urlfile.headers:
|
||||
length = int(self.urlfile.headers["content-length"])
|
||||
else:
|
||||
length = 0
|
||||
|
||||
while not self.cancelled:
|
||||
|
||||
data = self.urlfile.read(65536)
|
||||
|
||||
if not data:
|
||||
break
|
||||
|
||||
count += len(data)
|
||||
self.tmpfile.write(data)
|
||||
|
||||
if length > 0:
|
||||
self.progress = 1.0 * count / length
|
||||
|
||||
self.tmpfile.close()
|
||||
|
||||
if self.cancelled:
|
||||
return
|
||||
|
||||
if length and count != length:
|
||||
self.failure = "Download length does not match content length."
|
||||
return
|
||||
|
||||
self.safe_unlink(self.dest)
|
||||
os.rename(self.tmp, self.dest)
|
||||
|
||||
self.success = True
|
||||
|
||||
except Exception as e:
|
||||
self.failure = str(e)
|
||||
|
||||
|
||||
def safe_unlink(self, fn):
|
||||
if os.path.exists(fn):
|
||||
os.unlink(fn)
|
||||
|
||||
def cancel(self):
|
||||
"""
|
||||
Cancels the download.
|
||||
"""
|
||||
|
||||
self.cancelled = True
|
||||
|
||||
def check(self):
|
||||
"""
|
||||
Returns True if the download is finished, False if it was cancelled,
|
||||
None if it's ongoing, and raises an Exception if the download has failed.
|
||||
"""
|
||||
|
||||
if self.success:
|
||||
return True
|
||||
if self.cancelled:
|
||||
return False
|
||||
if self.failure:
|
||||
raise Exception("Downloading {} to {} failed: {}".format(self.url, self.dest, self.failure))
|
||||
|
||||
return None
|
||||
|
||||
class DownloaderValue(BarValue):
|
||||
"""
|
||||
A BarValue that reports the progress of a background download.
|
||||
"""
|
||||
|
||||
def __init__(self, d):
|
||||
self.downloader = d
|
||||
|
||||
def get_adjustment(self):
|
||||
self.adjustment = ui.adjustment(value=0.0, range=1.0, adjustable=False)
|
||||
return self.adjustment
|
||||
|
||||
def periodic(self, st):
|
||||
self.adjustment.change(self.downloader.progress)
|
||||
return .25
|
||||
|
||||
@@ -1,41 +1,60 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
# Editor Support.
|
||||
#
|
||||
# This contains code for scanning for editors, and for allowing the user to
|
||||
# select an editor.
|
||||
|
||||
init python in editor:
|
||||
init 1 python in editor:
|
||||
|
||||
from store import Action, renpy, config, persistent
|
||||
import store.project as project
|
||||
import store.updater as updater
|
||||
import store.interface as interface
|
||||
import store.util as util
|
||||
import store
|
||||
|
||||
|
||||
import glob
|
||||
import re
|
||||
import traceback
|
||||
import os
|
||||
import os.path
|
||||
|
||||
|
||||
# Should we set up the editor?
|
||||
set_editor = "RENPY_EDIT_PY" not in os.environ
|
||||
|
||||
# A map from editor name to EditorInfo object.
|
||||
editors = { }
|
||||
|
||||
|
||||
class EditorInfo(object):
|
||||
def __init__(self, filename):
|
||||
# The path to the editor info file.
|
||||
self.filename = filename
|
||||
|
||||
|
||||
# The name of the editor.
|
||||
self.name = os.path.basename(filename)[:-len(".edit.py")]
|
||||
|
||||
|
||||
# The time the editor file was last modified. We use this
|
||||
# to decide if we should update the editors mat when we
|
||||
# to decide if we should update the editors mat when we
|
||||
# have multiple versions of an editor in contention.
|
||||
self.mtime = os.path.getmtime(filename)
|
||||
|
||||
@@ -46,13 +65,13 @@ init python in editor:
|
||||
"""
|
||||
|
||||
ei = EditorInfo(filename)
|
||||
|
||||
|
||||
if ei.name in editors:
|
||||
if editors[ei.name].mtime >= ei.mtime:
|
||||
return
|
||||
|
||||
|
||||
editors[ei.name] = ei
|
||||
|
||||
|
||||
def scan_all():
|
||||
"""
|
||||
Finds all *.edit.py files, and uses them to populate the list
|
||||
@@ -60,13 +79,24 @@ init python in editor:
|
||||
"""
|
||||
|
||||
editors.clear()
|
||||
|
||||
|
||||
for d in [ config.renpy_base, persistent.projects_directory ]:
|
||||
if d is None:
|
||||
continue
|
||||
|
||||
for filename in glob.glob(d + "/*/*.edit.py"):
|
||||
scan_editor(filename)
|
||||
|
||||
if not os.path.isdir(d):
|
||||
continue
|
||||
|
||||
for i in util.listdir(d):
|
||||
i = os.path.join(d, i)
|
||||
if not os.path.isdir(d):
|
||||
continue
|
||||
|
||||
for j in util.listdir(i):
|
||||
j = os.path.join(i, j)
|
||||
|
||||
if j.endswith(".edit.py"):
|
||||
scan_editor(j)
|
||||
|
||||
########################################################################
|
||||
|
||||
@@ -78,42 +108,42 @@ init python in editor:
|
||||
|
||||
class FancyEditorInfo(object):
|
||||
"""
|
||||
Represents an editor in the selection screen. A FEI knows if the
|
||||
Represents an editor in the selection screen. A FEI knows if the
|
||||
editor is installed or not.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, priority, name, description=None, dlc=None, dldescription=None, error_message=None):
|
||||
# The priority of the editor. Lower priorities will come later
|
||||
# in the list.
|
||||
self.priority = priority
|
||||
|
||||
|
||||
# The name of the editor.
|
||||
self.name = name
|
||||
|
||||
|
||||
# Is the editor installed?
|
||||
self.installed = name in editors
|
||||
|
||||
|
||||
# The dlc needed to install the editor.
|
||||
self.dlc = dlc
|
||||
|
||||
|
||||
# A description of the editor.
|
||||
self.description = description
|
||||
|
||||
|
||||
# A description of the download.
|
||||
self.dldescription = dldescription
|
||||
|
||||
|
||||
# An error message to display if the editor failed to start.
|
||||
self.error_message = error_message
|
||||
|
||||
|
||||
def fancy_scan_editors():
|
||||
"""
|
||||
Creates the list of FancyEditorInfo objects.
|
||||
"""
|
||||
|
||||
|
||||
global fancy_editors
|
||||
|
||||
|
||||
scan_all()
|
||||
|
||||
|
||||
fei = fancy_editors = [ ]
|
||||
|
||||
# Editra.
|
||||
@@ -134,36 +164,36 @@ init python in editor:
|
||||
dlc = "editra-linux"
|
||||
installed = os.path.exists(os.path.join(config.basedir, "editra/Editra"))
|
||||
description = EDL
|
||||
error_message = _("The may have occured because wxPython is not installed on this system.")
|
||||
error_message = _("This may have occured because wxPython is not installed on this system.")
|
||||
|
||||
e = FancyEditorInfo(
|
||||
1,
|
||||
"Editra",
|
||||
"Editra",
|
||||
description,
|
||||
dlc,
|
||||
_("Up to 22 MB download required."),
|
||||
error_message)
|
||||
|
||||
|
||||
e.installed = e.installed or installed
|
||||
|
||||
|
||||
fei.append(e)
|
||||
|
||||
|
||||
# jEdit
|
||||
fei.append(FancyEditorInfo(
|
||||
2,
|
||||
"jEdit",
|
||||
"A mature editor that requires Java.",
|
||||
_("A mature editor that requires Java."),
|
||||
"jedit",
|
||||
_("1.8 MB download required."),
|
||||
_("This may have occured because Java is not installed on this system."),
|
||||
))
|
||||
|
||||
|
||||
fei.append(FancyEditorInfo(
|
||||
3,
|
||||
"System Editor",
|
||||
"Invokes the editor your operating system has associated with .rpy files.",
|
||||
_("Invokes the editor your operating system has associated with .rpy files."),
|
||||
None))
|
||||
|
||||
|
||||
for k in editors:
|
||||
if k in [ "Editra", "jEdit", "System Editor", "None" ]:
|
||||
continue
|
||||
@@ -173,13 +203,13 @@ init python in editor:
|
||||
k,
|
||||
None,
|
||||
None))
|
||||
|
||||
|
||||
fei.append(FancyEditorInfo(
|
||||
5,
|
||||
"None",
|
||||
"Prevents Ren'Py from opening a text editor.",
|
||||
_("Prevents Ren'Py from opening a text editor."),
|
||||
None))
|
||||
|
||||
|
||||
fei.sort(key=lambda e : (e.priority, e.name.lower()))
|
||||
|
||||
# If we're in a linux distro or something, assume all editors work.
|
||||
@@ -190,40 +220,40 @@ init python in editor:
|
||||
def fancy_activate_editor(default=False):
|
||||
"""
|
||||
Activates the editor in persistent.editor, if it's installed.
|
||||
|
||||
|
||||
`default`
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
global error_message
|
||||
|
||||
|
||||
fancy_scan_editors()
|
||||
|
||||
|
||||
if default and not set_editor:
|
||||
renpy.editor.init()
|
||||
return
|
||||
|
||||
|
||||
for i in fancy_editors:
|
||||
|
||||
|
||||
if i.name == persistent.editor:
|
||||
if i.installed and i.name in editors:
|
||||
ei = editors[i.name]
|
||||
os.environ["RENPY_EDIT_PY"] = renpy.fsencode(os.path.abspath(ei.filename))
|
||||
error_message = i.error_message
|
||||
break
|
||||
|
||||
|
||||
else:
|
||||
persistent.editor = None
|
||||
os.environ.pop("RENPY_EDIT_PY", None)
|
||||
|
||||
|
||||
renpy.editor.init()
|
||||
|
||||
def fancy_select_editor(name):
|
||||
"""
|
||||
Selects the editor with the given name, installing it if it
|
||||
doesn't already exist.
|
||||
doesn't already exist.
|
||||
"""
|
||||
|
||||
|
||||
for fe in fancy_editors:
|
||||
if fe.name == name:
|
||||
break
|
||||
@@ -231,91 +261,93 @@ init python in editor:
|
||||
return
|
||||
|
||||
if not fe.installed:
|
||||
|
||||
|
||||
# We don't check the status of this because fancy_activate_editor
|
||||
# will fail if the editor is not installed.
|
||||
store.add_dlc(fe.dlc)
|
||||
|
||||
persistent.editor = fe.name
|
||||
fancy_activate_editor()
|
||||
|
||||
|
||||
return persistent.editor is not None
|
||||
|
||||
# Call fancy_activate_editor on startup.
|
||||
fancy_activate_editor(True)
|
||||
|
||||
|
||||
class SelectEditor(Action):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
def get_selected(self):
|
||||
return persistent.editor == self.name
|
||||
|
||||
|
||||
def __call__(self):
|
||||
return fancy_select_editor(self.name)
|
||||
|
||||
|
||||
def check_editor():
|
||||
"""
|
||||
Checks to see if an editor is set. If one isn't asks the user to
|
||||
select one.
|
||||
|
||||
Returns True if the editor is set and editing can proceed, and
|
||||
Checks to see if an editor is set. If one isn't asks the user to
|
||||
select one.
|
||||
|
||||
Returns True if the editor is set and editing can proceed, and
|
||||
False otherwise.
|
||||
"""
|
||||
|
||||
|
||||
if not set_editor:
|
||||
return True
|
||||
|
||||
|
||||
if persistent.editor:
|
||||
return True
|
||||
|
||||
|
||||
return renpy.invoke_in_new_context(renpy.call_screen, "editor")
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Editing actions.
|
||||
|
||||
|
||||
class Edit(Action):
|
||||
alt = "Edit [text]."
|
||||
|
||||
def __init__(self, filename, line=None, check=False):
|
||||
"""
|
||||
An action that opens the given line of the given file in a
|
||||
text editor.
|
||||
|
||||
text editor.
|
||||
|
||||
`filename`
|
||||
The filename to open.
|
||||
|
||||
|
||||
`line`
|
||||
The line in the file to jump to.
|
||||
|
||||
|
||||
`check`
|
||||
If true, we will check to see if the file exists, and gray
|
||||
out the box if it does not.
|
||||
"""
|
||||
|
||||
|
||||
self.filename = filename
|
||||
self.line = line
|
||||
self.check = check
|
||||
|
||||
|
||||
def get_sensitive(self):
|
||||
if not self.check:
|
||||
return True
|
||||
|
||||
|
||||
fn = project.current.unelide_filename(self.filename)
|
||||
return os.path.exists(fn)
|
||||
|
||||
|
||||
def __call__(self):
|
||||
|
||||
|
||||
if not self.get_sensitive():
|
||||
return
|
||||
|
||||
|
||||
if not check_editor():
|
||||
return
|
||||
|
||||
|
||||
fn = project.current.unelide_filename(self.filename)
|
||||
|
||||
|
||||
try:
|
||||
|
||||
|
||||
e = renpy.editor.editor
|
||||
|
||||
e.begin()
|
||||
@@ -325,35 +357,83 @@ init python in editor:
|
||||
except Exception, e:
|
||||
exception = traceback.format_exception_only(type(e), e)[-1][:-1]
|
||||
renpy.invoke_in_new_context(interface.error, _("An exception occured while launching the text editor:\n[exception!q]"), error_message, exception=exception)
|
||||
|
||||
|
||||
|
||||
class EditAbsolute(Action):
|
||||
def __init__(self, filename, line=None, check=False):
|
||||
"""
|
||||
An action that lets us edit an absolutely-specified filename.
|
||||
|
||||
`filename`
|
||||
The filename to open.
|
||||
|
||||
`line`
|
||||
The line in the file to jump to.
|
||||
|
||||
`check`
|
||||
If true, we will check to see if the file exists, and gray
|
||||
out the box if it does not.
|
||||
"""
|
||||
|
||||
self.filename = filename
|
||||
self.line = line
|
||||
self.check = check
|
||||
|
||||
def get_sensitive(self):
|
||||
if not self.check:
|
||||
return True
|
||||
|
||||
return os.path.exists(self.filename)
|
||||
|
||||
def __call__(self):
|
||||
|
||||
if not self.get_sensitive():
|
||||
return
|
||||
|
||||
if not check_editor():
|
||||
return
|
||||
|
||||
try:
|
||||
|
||||
e = renpy.editor.editor
|
||||
|
||||
e.begin()
|
||||
e.open(self.filename, line=self.line)
|
||||
e.end()
|
||||
|
||||
except Exception, e:
|
||||
exception = traceback.format_exception_only(type(e), e)[-1][:-1]
|
||||
renpy.invoke_in_new_context(interface.error, _("An exception occured while launching the text editor:\n[exception!q]"), error_message, exception=exception)
|
||||
|
||||
|
||||
class EditAll(Action):
|
||||
"""
|
||||
Opens all scripts that are part of the current project in a web browser.
|
||||
"""
|
||||
|
||||
|
||||
alt = "Edit [text]."
|
||||
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
|
||||
def __call__(self):
|
||||
|
||||
if not check_editor():
|
||||
return
|
||||
|
||||
scripts = project.current.script_files()
|
||||
scripts = project.current.script_files()
|
||||
scripts = [ i for i in scripts if not i.startswith("game/tl/") ]
|
||||
scripts.sort(key=lambda fn : fn.lower())
|
||||
|
||||
for fn in [ "game/screens.rpy", "game/options.rpy", "game/script.rpy" ]:
|
||||
if fn in scripts:
|
||||
scripts.remove(fn)
|
||||
scripts.insert(0, fn)
|
||||
|
||||
|
||||
try:
|
||||
|
||||
e = renpy.editor.editor
|
||||
e.begin()
|
||||
|
||||
|
||||
for fn in scripts:
|
||||
fn = project.current.unelide_filename(fn)
|
||||
e.open(fn)
|
||||
@@ -365,56 +445,54 @@ init python in editor:
|
||||
renpy.invoke_in_new_context(interface.error, _("An exception occured while launching the text editor:\n[exception!q]"), error_message, exception=exception)
|
||||
|
||||
screen editor:
|
||||
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
|
||||
window:
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
label _("Select Editor")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
|
||||
hbox:
|
||||
frame:
|
||||
style "l_indent"
|
||||
xfill True
|
||||
|
||||
|
||||
viewport:
|
||||
scrollbars "vertical"
|
||||
mousewheel True
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
|
||||
text _("A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed.") style "l_small_text"
|
||||
|
||||
for fe in editor.fancy_editors:
|
||||
|
||||
|
||||
add SPACER
|
||||
|
||||
|
||||
textbutton fe.name action editor.SelectEditor(fe.name)
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
has vbox
|
||||
|
||||
|
||||
if fe.description:
|
||||
text fe.description style "l_small_text"
|
||||
|
||||
|
||||
if not fe.installed:
|
||||
add HALF_SPACER
|
||||
text fe.dldescription style "l_small_text"
|
||||
|
||||
|
||||
|
||||
textbutton _("Cancel") action Return(False) style "l_left_button"
|
||||
|
||||
label editor_preference:
|
||||
call screen editor
|
||||
jump preferences
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
define PROJECT_ADJUSTMENT = ui.adjustment()
|
||||
|
||||
|
||||
init python:
|
||||
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -13,127 +31,164 @@ init python:
|
||||
Opens `directory` in a file browser. `directory` is relative to
|
||||
the project root.
|
||||
"""
|
||||
|
||||
|
||||
alt = _("Open [text] directory.")
|
||||
|
||||
def __init__(self, directory, absolute=False):
|
||||
if absolute:
|
||||
self.directory = directory
|
||||
else:
|
||||
self.directory = os.path.join(project.current.path, directory)
|
||||
|
||||
|
||||
def get_sensitive(self):
|
||||
return os.path.exists(self.directory)
|
||||
|
||||
|
||||
def __call__(self):
|
||||
|
||||
directory = renpy.fsencode(self.directory)
|
||||
|
||||
if renpy.windows:
|
||||
os.startfile(directory)
|
||||
elif renpy.macintosh:
|
||||
subprocess.Popen([ "open", directory ])
|
||||
else:
|
||||
subprocess.Popen([ "xdg-open", directory ])
|
||||
|
||||
try:
|
||||
directory = renpy.fsencode(self.directory)
|
||||
|
||||
if renpy.windows:
|
||||
os.startfile(directory)
|
||||
elif renpy.macintosh:
|
||||
subprocess.Popen([ "open", directory ])
|
||||
else:
|
||||
subprocess.Popen([ "xdg-open", directory ])
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
# Used for testing.
|
||||
def Relaunch():
|
||||
renpy.quit(relaunch=True)
|
||||
|
||||
|
||||
screen front_page:
|
||||
frame:
|
||||
alt ""
|
||||
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
|
||||
has hbox
|
||||
|
||||
|
||||
# Projects list section - on left.
|
||||
|
||||
|
||||
frame:
|
||||
style "l_default"
|
||||
style "l_projects"
|
||||
xmaximum 300
|
||||
right_margin 2
|
||||
|
||||
top_margin 20
|
||||
bottom_margin 26
|
||||
|
||||
|
||||
top_padding 20
|
||||
bottom_padding 26
|
||||
|
||||
side "t c b":
|
||||
|
||||
window style "l_label":
|
||||
text "PROJECTS:" style "l_label_text" size 36 yoffset 10
|
||||
|
||||
|
||||
has hbox:
|
||||
xfill True
|
||||
|
||||
text "PROJECTS:" style "l_label_text" size 36 yoffset 10
|
||||
|
||||
textbutton _("refresh"):
|
||||
xalign 1.0
|
||||
yalign 1.0
|
||||
yoffset 5
|
||||
style "l_small_button"
|
||||
action project.Rescan()
|
||||
right_margin HALF_INDENT
|
||||
|
||||
side "c r":
|
||||
|
||||
|
||||
viewport:
|
||||
yadjustment PROJECT_ADJUSTMENT
|
||||
mousewheel True
|
||||
use front_page_project_list
|
||||
|
||||
|
||||
vbar:
|
||||
style "l_vscrollbar"
|
||||
adjustment PROJECT_ADJUSTMENT
|
||||
|
||||
|
||||
vbox:
|
||||
add HALF_SPACER
|
||||
add SEPARATOR
|
||||
add HALF_SPACER
|
||||
|
||||
textbutton _("+ Create New Project"):
|
||||
left_margin (HALF_INDENT)
|
||||
action Jump("new_project")
|
||||
|
||||
|
||||
|
||||
hbox:
|
||||
xfill True
|
||||
|
||||
textbutton _("+ Create New Project"):
|
||||
left_margin (HALF_INDENT)
|
||||
action Jump("new_project")
|
||||
|
||||
|
||||
|
||||
# Project section - on right.
|
||||
|
||||
if project.current is not None:
|
||||
use front_page_project
|
||||
|
||||
|
||||
if project.current is not None:
|
||||
textbutton _("Launch Project") action project.Launch() style "l_right_button"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# This is used by front_page to display the list of known projects on the screen.
|
||||
screen front_page_project_list:
|
||||
|
||||
|
||||
$ projects = project.manager.projects
|
||||
|
||||
$ templates = project.manager.templates
|
||||
|
||||
vbox:
|
||||
|
||||
|
||||
if templates and persistent.show_templates:
|
||||
|
||||
for p in templates:
|
||||
|
||||
textbutton _("[p.name!q] (template)"):
|
||||
action project.Select(p)
|
||||
alt _("Select project [text].")
|
||||
style "l_list"
|
||||
|
||||
null height 12
|
||||
|
||||
if projects:
|
||||
|
||||
|
||||
for p in projects:
|
||||
|
||||
textbutton "[p.name!q]":
|
||||
action project.Select(p)
|
||||
alt _("Select project [text].")
|
||||
style "l_list"
|
||||
|
||||
null height 12
|
||||
|
||||
textbutton _("Tutorial") action project.Select("tutorial") style "l_list"
|
||||
textbutton _("The Question") action project.Select("the_question") style "l_list"
|
||||
|
||||
|
||||
# This is used for the right side of the screen, which is where the project-specific
|
||||
null height 12
|
||||
|
||||
textbutton _("Tutorial") action project.Select("tutorial") style "l_list" alt _("Select project [text].")
|
||||
textbutton _("The Question") action project.Select("the_question") style "l_list" alt _("Select project [text].")
|
||||
|
||||
|
||||
# This is used for the right side of the screen, which is where the project-specific
|
||||
# buttons are.
|
||||
screen front_page_project:
|
||||
|
||||
|
||||
$ p = project.current
|
||||
|
||||
|
||||
window:
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
frame style "l_label":
|
||||
has hbox xfill True
|
||||
text "[p.name!q]" style "l_label_text"
|
||||
label "Active Project" style "l_alternate"
|
||||
label _("Active Project") style "l_alternate"
|
||||
|
||||
grid 2 1:
|
||||
xfill True
|
||||
spacing HALF_INDENT
|
||||
|
||||
|
||||
vbox:
|
||||
|
||||
label _("Open Directory") style "l_label_small"
|
||||
|
||||
label _("Open Directory") style "l_label_small"
|
||||
|
||||
frame style "l_indent":
|
||||
has vbox
|
||||
@@ -142,30 +197,30 @@ screen front_page_project:
|
||||
textbutton _("base") action OpenDirectory(".")
|
||||
# textbutton _("images") action OpenDirectory("game/images") style "l_list"
|
||||
# textbutton _("save") action None style "l_list"
|
||||
|
||||
|
||||
vbox:
|
||||
|
||||
|
||||
label _("Edit File") style "l_label_small"
|
||||
|
||||
frame style "l_indent":
|
||||
has vbox
|
||||
|
||||
textbutton _("script.rpy") action editor.Edit("game/script.rpy", check=True)
|
||||
textbutton _("options.rpy") action editor.Edit("game/options.rpy", check=True)
|
||||
textbutton _("screens.rpy") action editor.Edit("game/screens.rpy", check=True)
|
||||
|
||||
textbutton "script.rpy" action editor.Edit("game/script.rpy", check=True)
|
||||
textbutton "options.rpy" action editor.Edit("game/options.rpy", check=True)
|
||||
textbutton "screens.rpy" action editor.Edit("game/screens.rpy", check=True)
|
||||
textbutton _("All script files") action editor.EditAll()
|
||||
|
||||
|
||||
add SPACER
|
||||
add SEPARATOR
|
||||
add SPACER
|
||||
|
||||
|
||||
frame style "l_indent":
|
||||
has vbox
|
||||
|
||||
|
||||
textbutton _("Navigate Script") text_size 30 action Jump("navigation")
|
||||
|
||||
|
||||
add SPACER
|
||||
|
||||
|
||||
grid 2 1:
|
||||
xfill True
|
||||
spacing HALF_INDENT
|
||||
@@ -176,7 +231,8 @@ screen front_page_project:
|
||||
textbutton _("Check Script (Lint)") action Jump("lint")
|
||||
textbutton _("Change Theme") action Jump("choose_theme")
|
||||
textbutton _("Delete Persistent") action Jump("rmpersistent")
|
||||
|
||||
textbutton _("Force Recompile") action Jump("force_recompile")
|
||||
|
||||
# textbutton "Relaunch" action Relaunch
|
||||
|
||||
frame style "l_indent":
|
||||
@@ -184,27 +240,30 @@ screen front_page_project:
|
||||
|
||||
if ability.can_distribute:
|
||||
textbutton _("Build Distributions") action Jump("build_distributions")
|
||||
|
||||
|
||||
|
||||
textbutton _("Android") action Jump("android")
|
||||
textbutton _("Generate Translations") action Jump("translate")
|
||||
textbutton _("Extract Dialogue") action Jump("extract_dialogue")
|
||||
|
||||
label main_menu:
|
||||
return
|
||||
|
||||
|
||||
label start:
|
||||
show screen bottom_info
|
||||
|
||||
|
||||
label front_page:
|
||||
call screen front_page
|
||||
call screen front_page
|
||||
jump front_page
|
||||
|
||||
|
||||
|
||||
|
||||
label lint:
|
||||
python hide:
|
||||
|
||||
interface.processing(_("Checking script for potential problems..."))
|
||||
lint_fn = project.current.temp_filename("lint.txt")
|
||||
|
||||
|
||||
project.current.launch([ 'lint', lint_fn ], wait=True)
|
||||
|
||||
|
||||
e = renpy.editor.editor
|
||||
e.begin(True)
|
||||
e.open(lint_fn)
|
||||
@@ -213,10 +272,17 @@ label lint:
|
||||
jump front_page
|
||||
|
||||
label rmpersistent:
|
||||
|
||||
|
||||
python hide:
|
||||
interface.processing(_("Deleting persistent data..."))
|
||||
project.current.launch([ 'rmpersistent' ], wait=True)
|
||||
|
||||
|
||||
jump front_page
|
||||
|
||||
label force_recompile:
|
||||
|
||||
python hide:
|
||||
interface.processing(_("Recompiling all rpy files into rpyc files..."))
|
||||
project.current.launch([ 'compile' ], wait=True)
|
||||
|
||||
jump front_page
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 96 B After Width: | Height: | Size: 96 B |
|
Before Width: | Height: | Size: 106 B After Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -1,22 +1,41 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
################################################################################
|
||||
# Interface actions.
|
||||
init python in interface:
|
||||
from store import OpenURL, config, Return
|
||||
import store
|
||||
|
||||
import os.path
|
||||
import contextlib
|
||||
|
||||
|
||||
RENPY_URL = "http://www.renpy.org"
|
||||
RENPY_GAMES_URL = "http://games.renpy.org"
|
||||
RENPY_GAMES_URL = "http://games.renpy.org"
|
||||
DOC_PATH = os.path.join(config.renpy_base, "doc/index.html")
|
||||
DOC_URL = "http://www.renpy.org/doc/html/"
|
||||
|
||||
LICENSE_PATH = os.path.join(config.renpy_base, "doc/license.html")
|
||||
LICENSE_URL = "http://www.renpy.org/doc/html/license.html"
|
||||
|
||||
|
||||
if os.path.exists(DOC_PATH):
|
||||
DOC_LOCAL_URL = "file:///" + DOC_PATH
|
||||
else:
|
||||
@@ -26,12 +45,12 @@ init python in interface:
|
||||
LICENSE_LOCAL_URL = "file:///" + LICENSE_PATH
|
||||
else:
|
||||
LICENSE_LOCAL_URL = None
|
||||
|
||||
|
||||
def OpenDocumentation():
|
||||
"""
|
||||
An action that opens the documentation.
|
||||
"""
|
||||
|
||||
|
||||
if DOC_LOCAL_URL is not None:
|
||||
return OpenURL(DOC_LOCAL_URL)
|
||||
else:
|
||||
@@ -41,97 +60,122 @@ init python in interface:
|
||||
"""
|
||||
An action that opens the license.
|
||||
"""
|
||||
|
||||
|
||||
if LICENSE_LOCAL_URL is not None:
|
||||
return OpenURL(LICENSE_LOCAL_URL)
|
||||
else:
|
||||
return OpenURL(LICENSE_URL)
|
||||
|
||||
|
||||
|
||||
|
||||
# Should we display the bottom links?
|
||||
links = True
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def nolinks():
|
||||
global links
|
||||
links = False
|
||||
|
||||
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
links = True
|
||||
|
||||
|
||||
# This displays the bottom of the screen. If the tooltip is not None, this displays the
|
||||
# tooltip. Otherwise, it displays a list of links (to various websites, and to the
|
||||
# tooltip. Otherwise, it displays a list of links (to various websites, and to the
|
||||
# preferences and update screen), or is just blank.
|
||||
screen bottom_info:
|
||||
|
||||
|
||||
zorder 100
|
||||
|
||||
|
||||
if interface.links:
|
||||
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_default"
|
||||
|
||||
|
||||
left_margin (10 + INDENT)
|
||||
right_margin (10 + INDENT)
|
||||
xfill True
|
||||
ypos 536
|
||||
yanchor 0.0
|
||||
|
||||
|
||||
hbox:
|
||||
xfill True
|
||||
|
||||
|
||||
hbox:
|
||||
spacing INDENT
|
||||
textbutton _("Documentation") style "l_link" action interface.OpenDocumentation()
|
||||
textbutton _("Ren'Py Website") style "l_link" action OpenURL(interface.RENPY_URL)
|
||||
textbutton _("Ren'Py Games List") style "l_link" action OpenURL(interface.RENPY_GAMES_URL)
|
||||
textbutton _("About") style "l_link" action Jump("about")
|
||||
|
||||
|
||||
hbox:
|
||||
spacing INDENT
|
||||
xalign 1.0
|
||||
|
||||
if ability.can_update:
|
||||
textbutton _("update") action Jump("update") style "l_link"
|
||||
|
||||
|
||||
textbutton _("preferences") style "l_link" action Jump("preferences")
|
||||
textbutton _("quit") style "l_link" action Quit(confirm=False)
|
||||
|
||||
|
||||
|
||||
screen common:
|
||||
|
||||
|
||||
default complete = None
|
||||
default total = None
|
||||
default yes = None
|
||||
default no = None
|
||||
|
||||
default choices = None
|
||||
default cancel = None
|
||||
default bar_value = None
|
||||
|
||||
frame:
|
||||
style "l_root"
|
||||
|
||||
frame:
|
||||
style_group "l_info"
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
|
||||
text message:
|
||||
text_align 0.5
|
||||
xalign 0.5
|
||||
layout "subtitle"
|
||||
|
||||
|
||||
if complete is not None:
|
||||
add SPACER
|
||||
|
||||
|
||||
frame:
|
||||
style "l_progress_frame"
|
||||
|
||||
|
||||
bar:
|
||||
range total
|
||||
value complete
|
||||
style "l_progress_bar"
|
||||
|
||||
|
||||
if bar_value is not None:
|
||||
add SPACER
|
||||
|
||||
frame:
|
||||
style "l_progress_frame"
|
||||
|
||||
bar:
|
||||
value bar_value
|
||||
style "l_progress_bar"
|
||||
|
||||
|
||||
if choices:
|
||||
add SPACER
|
||||
|
||||
for v, l in choices:
|
||||
textbutton l action SetScreenVariable("selected", v)
|
||||
|
||||
if selected is not None:
|
||||
$ continue_ = Return(selected)
|
||||
else:
|
||||
$ continue_ = None
|
||||
|
||||
if submessage:
|
||||
add SPACER
|
||||
|
||||
@@ -142,21 +186,23 @@ screen common:
|
||||
|
||||
if yes:
|
||||
add SPACER
|
||||
|
||||
|
||||
hbox:
|
||||
xalign 0.5
|
||||
textbutton _("Yes") style "l_button" action yes
|
||||
null width 160
|
||||
textbutton _("No") style "l_button" action no
|
||||
|
||||
|
||||
|
||||
label title text_color title_color style "l_info_label"
|
||||
|
||||
if back:
|
||||
textbutton _("Back") action Return(False) style "l_left_button"
|
||||
|
||||
textbutton _("Back") action back style "l_left_button"
|
||||
elif cancel:
|
||||
textbutton _("Cancel") action cancel style "l_left_button"
|
||||
|
||||
if continue_:
|
||||
textbutton _("Continue") action Return(True) style "l_right_button"
|
||||
textbutton _("Continue") action continue_ style "l_right_button"
|
||||
|
||||
|
||||
screen launcher_input:
|
||||
@@ -166,142 +212,168 @@ screen launcher_input:
|
||||
|
||||
frame:
|
||||
style_group "l_info"
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
text message
|
||||
|
||||
text message:
|
||||
text_align 0.5
|
||||
xalign 0.5
|
||||
layout "subtitle"
|
||||
|
||||
add SPACER
|
||||
|
||||
input style "l_default" size 24 xalign 0.5 default default color "#d86b45"
|
||||
input style "l_default" size 24 xalign 0.5 default default color INPUT_COLOR
|
||||
|
||||
if filename:
|
||||
add SPACER
|
||||
text _("Due to package format limitations, non-ASCII file and directory names are not allowed.")
|
||||
|
||||
label _("[title]") style "l_info_label" text_color "#d19753"
|
||||
|
||||
|
||||
label title style "l_info_label" text_color QUESTION_COLOR
|
||||
|
||||
if cancel:
|
||||
textbutton _("Cancel") action cancel style "l_left_button"
|
||||
|
||||
|
||||
init python in interface:
|
||||
|
||||
import traceback
|
||||
|
||||
def common(title, title_color, message, submessage=None, back=False, continue_=False, pause0=False, **kwargs):
|
||||
from store import Jump
|
||||
|
||||
def common(title, title_color, message, submessage=None, back=None, continue_=None, pause0=False, show_screen=False, **kwargs):
|
||||
"""
|
||||
Displays the info, interaction, and processing screens.
|
||||
|
||||
`title`
|
||||
The title of the screen.
|
||||
|
||||
|
||||
`message`
|
||||
The main message that is displayed when the screen is.
|
||||
|
||||
|
||||
`submessage`
|
||||
If not None, a message that is displayed below the main message.
|
||||
|
||||
|
||||
`back`
|
||||
If True, a back button will be present. If it's clicked, False will
|
||||
be returned.
|
||||
|
||||
If not None, a back button will be present. `back` is the action that
|
||||
is called when the button is clicked.
|
||||
|
||||
`cancel`
|
||||
If not None, a cancel button will be present. `cancel` is the action
|
||||
that is called when the button is clicked.
|
||||
|
||||
`continue_`
|
||||
If True, a continue button will be present. If it's clicked, True
|
||||
will be returned.
|
||||
|
||||
If True, a continue button will be present. `continue_` gives the action
|
||||
that is called when that button is clicked.
|
||||
|
||||
`pause0`
|
||||
If True, a zero-length pause will be inserted before calling the
|
||||
screen. This will display it to the user and then immediately
|
||||
If True, a zero-length pause will be inserted before calling the
|
||||
screen. This will display it to the user and then immediately
|
||||
return.
|
||||
|
||||
|
||||
|
||||
`show_screen`
|
||||
If True, the screen will be show, and will return immediately. if False,
|
||||
the screen will be called, and interaction will pause.
|
||||
|
||||
Other keyword arguments are passed to the screen itself.
|
||||
"""
|
||||
|
||||
if pause0:
|
||||
ui.pausebehavior(0)
|
||||
|
||||
return renpy.call_screen("common", title=title, title_color=title_color, message=message, submessage=submessage, back=back, continue_=continue_, **kwargs)
|
||||
|
||||
|
||||
if show_screen:
|
||||
screen_func = renpy.show_screen
|
||||
else:
|
||||
screen_func = renpy.call_screen
|
||||
|
||||
if pause0:
|
||||
ui.pausebehavior(0)
|
||||
|
||||
return screen_func("common", title=title, title_color=title_color, message=message, submessage=submessage, back=back, continue_=continue_, **kwargs)
|
||||
|
||||
def hide_screen():
|
||||
"""
|
||||
Hides a screen that was shown with show_screen=True.
|
||||
"""
|
||||
|
||||
renpy.hide_screen("common")
|
||||
|
||||
|
||||
def error(message, submessage=None, label="front_page", **kwargs):
|
||||
"""
|
||||
Indicates to the user that an error has occured.
|
||||
|
||||
|
||||
`message`
|
||||
The message to display.
|
||||
The message to display.
|
||||
|
||||
`submessage`
|
||||
Optional secondary message information. For example, this may be
|
||||
Optional secondary message information. For example, this may be
|
||||
used to display an exception string.
|
||||
|
||||
|
||||
`label`
|
||||
The label to redirect to when the user finishes displaying the error. None
|
||||
to just return.
|
||||
|
||||
to just return False.
|
||||
|
||||
Keyword arguments are passed into the screen so that they can be substituted into
|
||||
the message.
|
||||
"""
|
||||
|
||||
common(_("ERROR"), "#d15353", message=message, submessage=submessage, back=True, **kwargs)
|
||||
|
||||
if label is None:
|
||||
action = Return(False)
|
||||
else:
|
||||
action = Jump(label)
|
||||
|
||||
common(_("ERROR"), store.ERROR_COLOR, message=message, submessage=submessage, back=action, **kwargs)
|
||||
|
||||
if label:
|
||||
renpy.jump(label)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def error_handling(what, label="front_page"):
|
||||
"""
|
||||
This is a context manager that catches exceptions and displays them using
|
||||
This is a context manager that catches exceptions and displays them using
|
||||
interface.error.
|
||||
|
||||
|
||||
`what`
|
||||
What we're doing when the error occurs. This is usually written using
|
||||
What we're doing when the error occurs. This is usually written using
|
||||
the present participle.
|
||||
|
||||
|
||||
`label`
|
||||
The label to jump to when error handling finishes.
|
||||
|
||||
|
||||
As an example of usage::
|
||||
|
||||
|
||||
with interface.error_handling("opening the log file"):
|
||||
f = open("log.txt", "w")
|
||||
f = open("log.txt", "w")
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
try:
|
||||
yield
|
||||
except Exception, e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
error(_("While [what!q], an error occured:"),
|
||||
_("[exception!q]"),
|
||||
what=what,
|
||||
error(_("While [what!q], an error occured:"),
|
||||
_("[exception!q]"),
|
||||
what=what,
|
||||
label=label,
|
||||
exception=traceback.format_exception_only(type(e), e)[-1][:-1])
|
||||
|
||||
|
||||
def input(title, message, filename=False, sanitize=True, cancel=None, default=""):
|
||||
"""
|
||||
Requests typewritten input from the user.
|
||||
"""
|
||||
|
||||
|
||||
rv = default
|
||||
|
||||
|
||||
while True:
|
||||
|
||||
|
||||
rv = renpy.call_screen("launcher_input", title=title, message=message, filename=filename, cancel=cancel, default=rv)
|
||||
|
||||
|
||||
if sanitize:
|
||||
if ("[" in rv) or ("{" in rv):
|
||||
error(_("Text input may not contain the {{ or [[ characters."), label=None)
|
||||
continue
|
||||
|
||||
|
||||
if filename:
|
||||
if ("\\" in rv) or ("/" in rv):
|
||||
if filename and (filename != "withslash") and (("\\" in rv) or ("/" in rv)):
|
||||
error(_("File and directory names may not contain / or \\."), label=None)
|
||||
continue
|
||||
|
||||
|
||||
try:
|
||||
rv.encode("ascii")
|
||||
except:
|
||||
@@ -310,83 +382,100 @@ init python in interface:
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
|
||||
def info(message, submessage=None, pause=True, **kwargs):
|
||||
"""
|
||||
Displays an informational message to the user. The user will be asked to click to
|
||||
Displays an informational message to the user. The user will be asked to click to
|
||||
confirm that he has read the message.
|
||||
|
||||
|
||||
`message`
|
||||
The message to display.
|
||||
|
||||
The message to display.
|
||||
|
||||
`pause`
|
||||
True if we should pause while showing the info.
|
||||
|
||||
|
||||
Keyword arguments are passed into the screen so that they can be substituted into
|
||||
the message.
|
||||
"""
|
||||
|
||||
|
||||
if pause:
|
||||
common(_("INFORMATION"), "#545454", message, submessage, continue_=True, **kwargs)
|
||||
common(_("INFORMATION"), store.INFO_COLOR, message, submessage, continue_=Return(True), **kwargs)
|
||||
else:
|
||||
common(_("INFORMATION"), "#545454", message, submessage, pause=0, **kwargs)
|
||||
|
||||
|
||||
def interaction(title, message, submessage=None, **kwargs):
|
||||
common(_("INFORMATION"), store.INFO_COLOR, message, submessage, pause0=True, **kwargs)
|
||||
|
||||
|
||||
def interaction(title, message, submessage=None, pause=0, **kwargs):
|
||||
"""
|
||||
Put up on the screen while an interaction with an external program occurs.
|
||||
This shows the message, then immediately returns.
|
||||
|
||||
`title`
|
||||
The title of the interaction.
|
||||
|
||||
|
||||
`message`
|
||||
The message itself.
|
||||
|
||||
|
||||
`submessage`
|
||||
An optional sub message.
|
||||
|
||||
`pause`
|
||||
The amount of time to pause for after showing the message.
|
||||
"""
|
||||
|
||||
common(title, "#d19753", message, submessage, pause0=True, **kwargs)
|
||||
|
||||
common(title, store.INTERACTION_COLOR, message, submessage=None, pause=pause, show_screen=True, **kwargs)
|
||||
renpy.pause(pause)
|
||||
|
||||
def processing(message, submessage=None, complete=None, total=None, **kwargs):
|
||||
"""
|
||||
Indicates to the user that processing is taking place. This should be used when
|
||||
there is an indefinite amount of work to be done.
|
||||
|
||||
|
||||
`message`
|
||||
The message to display.
|
||||
|
||||
The message to display.
|
||||
|
||||
`submessage`
|
||||
An additional message to display.
|
||||
|
||||
`complete`
|
||||
The fraction complete the step is.
|
||||
|
||||
|
||||
`total`
|
||||
The total amount of work to do in this step.
|
||||
|
||||
|
||||
Keyword arguments are passed into the screen so that they can be substituted into
|
||||
the message.
|
||||
"""
|
||||
|
||||
common(_("PROCESSING"), "#545454", message, submessage, pause0=True, complete=complete, total=total, **kwargs)
|
||||
common(_("PROCESSING"), store.INTERACTION_COLOR, message, submessage, pause0=True, complete=complete, total=total, **kwargs)
|
||||
|
||||
|
||||
|
||||
def yesno(message, yes=Return(True), no=Return(False), **kwargs):
|
||||
"""
|
||||
Asks the user a yes or no question.
|
||||
|
||||
|
||||
`message`
|
||||
The question to ask.
|
||||
|
||||
|
||||
`yes`
|
||||
The action to perform if the user answers yes.
|
||||
|
||||
|
||||
`no`
|
||||
The action to perform if the user answer no.
|
||||
"""
|
||||
|
||||
return common(_("QUESTION"), "#d19753", message, yes=yes, no=no, **kwargs)
|
||||
|
||||
return common(_("QUESTION"), store.QUESTION_COLOR, message, yes=yes, no=no, **kwargs)
|
||||
|
||||
def choice(message, choices, selected, **kwargs):
|
||||
"""
|
||||
Asks the user to pick a choice from a menu.
|
||||
|
||||
`choices`
|
||||
A list of (value, label) tuples, giving the choices.
|
||||
|
||||
`selected`
|
||||
The default choice that we mark as selected.
|
||||
"""
|
||||
|
||||
return common(_("CHOICE"), store.QUESTION_COLOR, message, choices=choices, selected=selected, **kwargs)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,30 +1,48 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init python in navigation:
|
||||
import store.interface as interface
|
||||
import store.project as project
|
||||
import store.editor as editor
|
||||
from store import persistent, Action
|
||||
|
||||
|
||||
|
||||
# The last navigation screen we've seen. This is the scree we try to go
|
||||
# to the next time we enter navigation. (We may not be able to go there,
|
||||
# if the screen is empty.)
|
||||
if persistent.navigation is None:
|
||||
persistent.navigation = "label"
|
||||
|
||||
# A map from a kind of information, to how we should sort it. Possible
|
||||
|
||||
# A map from a kind of information, to how we should sort it. Possible
|
||||
# sorts are alphabetical, by-file, natural.
|
||||
if persistent.navigation_sort is None:
|
||||
persistent.navigation_sort = { }
|
||||
|
||||
|
||||
if persistent.navigate_private is None:
|
||||
persistent.navigate_private = False
|
||||
|
||||
|
||||
if persistent.navigate_library is None:
|
||||
persistent.navigate_library = False
|
||||
|
||||
|
||||
# A list of kinds of navigation we support.
|
||||
KINDS = [ "file", "label", "define", "transform", "screen", "callable", "todo" ]
|
||||
|
||||
@@ -37,22 +55,22 @@ init python in navigation:
|
||||
|
||||
def group_and_sort(kind):
|
||||
"""
|
||||
This is responsible for pulling navigation information of the
|
||||
appropriate kind out of project.current.dump, grouping it,
|
||||
This is responsible for pulling navigation information of the
|
||||
appropriate kind out of project.current.dump, grouping it,
|
||||
and sorting it.
|
||||
|
||||
This returns a list of (group, list of (name, filename, line)). The
|
||||
|
||||
This returns a list of (group, list of (name, filename, line)). The
|
||||
group may be a string or None.
|
||||
"""
|
||||
|
||||
project.current.update_dump()
|
||||
|
||||
sort = persistent.navigation_sort[kind]
|
||||
|
||||
|
||||
name_map = project.current.dump.get("location", {}).get(kind, { })
|
||||
|
||||
|
||||
groups = { }
|
||||
|
||||
|
||||
for name, loc in name_map.items():
|
||||
filename, line = loc
|
||||
filename = filename.replace("\\", "/")
|
||||
@@ -63,56 +81,56 @@ init python in navigation:
|
||||
group = filename
|
||||
if group.startswith("game/"):
|
||||
group = group[5:]
|
||||
|
||||
|
||||
g = groups.get(group, None)
|
||||
if g is None:
|
||||
groups[group] = g = [ ]
|
||||
|
||||
|
||||
g.append((name, filename, line))
|
||||
|
||||
|
||||
for g in groups.values():
|
||||
if sort == "natural":
|
||||
g.sort(key=lambda a : a[2])
|
||||
else:
|
||||
g.sort(key=lambda a : a[0].lower())
|
||||
|
||||
|
||||
rv = list(groups.items())
|
||||
rv.sort()
|
||||
|
||||
return rv
|
||||
|
||||
def group_and_sort_files():
|
||||
|
||||
|
||||
rv = [ ]
|
||||
|
||||
|
||||
for fn in project.current.script_files():
|
||||
shortfn = fn
|
||||
shortfn = shortfn.replace("\\", "/")
|
||||
|
||||
if shortfn.startswith("game/"):
|
||||
shortfn = fn[5:]
|
||||
|
||||
|
||||
rv.append((shortfn, fn, None))
|
||||
|
||||
|
||||
rv.sort()
|
||||
|
||||
|
||||
return [ (None, rv) ]
|
||||
|
||||
class ChangeKind(Action):
|
||||
"""
|
||||
Changes the kind of thing we're navigating over.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, kind):
|
||||
self.kind = kind
|
||||
|
||||
|
||||
def get_selected(self):
|
||||
return persistent.navigation == self.kind
|
||||
|
||||
def __call__(self):
|
||||
if persistent.navigation == self.kind:
|
||||
return
|
||||
|
||||
|
||||
persistent.navigation = self.kind
|
||||
renpy.jump("navigation_loop")
|
||||
|
||||
@@ -123,38 +141,38 @@ init python in navigation:
|
||||
|
||||
def __init__(self, sort):
|
||||
self.sort = sort
|
||||
|
||||
|
||||
def get_selected(self):
|
||||
return persistent.navigation_sort[persistent.navigation] == self.sort
|
||||
|
||||
|
||||
def __call__(self):
|
||||
if self.get_selected():
|
||||
return
|
||||
|
||||
|
||||
persistent.navigation_sort[persistent.navigation] = self.sort
|
||||
renpy.jump("navigation_loop")
|
||||
|
||||
|
||||
|
||||
screen navigation:
|
||||
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
|
||||
window:
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
|
||||
frame style "l_label":
|
||||
has hbox xfill True
|
||||
text _("Navigate: [project.current.name]") style "l_label_text"
|
||||
|
||||
|
||||
frame:
|
||||
style "l_alternate"
|
||||
style_group "l_small"
|
||||
|
||||
|
||||
has hbox
|
||||
|
||||
|
||||
if persistent.navigation != "file":
|
||||
text _("Order: ")
|
||||
textbutton _("alphabetical") action navigation.ChangeSort("alphabetical")
|
||||
@@ -164,17 +182,17 @@ screen navigation:
|
||||
textbutton _("natural") action navigation.ChangeSort("natural")
|
||||
|
||||
null width HALF_INDENT
|
||||
|
||||
|
||||
textbutton _("refresh") action Jump("navigation_refresh")
|
||||
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
|
||||
frame style "l_indent":
|
||||
hbox:
|
||||
spacing HALF_INDENT
|
||||
text _("Category:")
|
||||
|
||||
|
||||
textbutton _("files") action navigation.ChangeKind("file")
|
||||
textbutton _("labels") action navigation.ChangeKind("label")
|
||||
textbutton _("defines") action navigation.ChangeKind("define")
|
||||
@@ -199,31 +217,35 @@ screen navigation:
|
||||
style_group "l_navigation"
|
||||
|
||||
for group_name, group in groups:
|
||||
|
||||
|
||||
if group_name is not None:
|
||||
text "[group_name!q]"
|
||||
|
||||
if persistent.navigation == "todo":
|
||||
|
||||
if persistent.navigation == "todo":
|
||||
vbox:
|
||||
for name, filename, line in group:
|
||||
textbutton "[name!q]" action editor.Edit(filename, line)
|
||||
|
||||
|
||||
else:
|
||||
hbox:
|
||||
box_wrap True
|
||||
|
||||
|
||||
for name, filename, line in group:
|
||||
textbutton "[name!q]" action editor.Edit(filename, line)
|
||||
|
||||
if group_name is not None:
|
||||
add SPACER
|
||||
|
||||
if persistent.navigation == "file":
|
||||
add SPACER
|
||||
textbutton _("+ Add script file") action Jump("add_file") style "l_button"
|
||||
|
||||
else:
|
||||
|
||||
|
||||
fixed:
|
||||
|
||||
|
||||
if persistent.navigation == "todo":
|
||||
|
||||
|
||||
text _("No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."):
|
||||
text_align 0.5
|
||||
xalign 0.5
|
||||
@@ -240,18 +262,18 @@ screen navigation:
|
||||
|
||||
label navigation:
|
||||
label navigation_loop:
|
||||
|
||||
|
||||
python in navigation:
|
||||
|
||||
kind = persistent.navigation
|
||||
|
||||
kind = persistent.navigation
|
||||
|
||||
if kind == "file":
|
||||
groups = group_and_sort_files()
|
||||
else:
|
||||
groups = group_and_sort(kind)
|
||||
|
||||
|
||||
renpy.call_screen("navigation", groups=groups)
|
||||
|
||||
|
||||
label navigation_refresh:
|
||||
$ project.current.update_dump(True)
|
||||
jump navigation_loop
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init python:
|
||||
import shutil
|
||||
@@ -9,14 +27,14 @@ init python:
|
||||
|
||||
screen select_template:
|
||||
|
||||
default result = project.manager.get("template")
|
||||
default result = project.manager.get("english")
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
|
||||
window:
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
label _("Choose Project Template")
|
||||
@@ -26,18 +44,18 @@ screen select_template:
|
||||
frame:
|
||||
style "l_indent"
|
||||
xmaximum ONETHIRD
|
||||
|
||||
|
||||
viewport:
|
||||
scrollbars "vertical"
|
||||
vbox:
|
||||
for p in project.manager.templates:
|
||||
textbutton "[p.name!q]" action SetScreenVariable("result", p) style "l_list"
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
xmaximum TWOTHIRDS
|
||||
|
||||
text _("Please select a template to use for your new project. Ren'Py ships with a default template that creates an English-language game with standard screens.")
|
||||
|
||||
text _("Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'.")
|
||||
|
||||
|
||||
textbutton _("Back") action Jump("front_page") style "l_left_button"
|
||||
@@ -45,27 +63,30 @@ screen select_template:
|
||||
|
||||
|
||||
label new_project:
|
||||
|
||||
|
||||
if persistent.projects_directory is None:
|
||||
call choose_projects_directory
|
||||
|
||||
|
||||
if persistent.projects_directory is None:
|
||||
$ interface.error(_("The projects directory could not be set. Giving up."))
|
||||
|
||||
python hide:
|
||||
|
||||
|
||||
project_name = interface.input(
|
||||
_("PROJECT NAME"),
|
||||
_("PROJECT NAME"),
|
||||
_("Please enter the name of your project:"),
|
||||
filename=True,
|
||||
cancel=Jump("front_page"))
|
||||
|
||||
|
||||
project_name = project_name.strip()
|
||||
if not project_name:
|
||||
interface.error(_("The project name may not be empty."))
|
||||
|
||||
project_dir = os.path.join(persistent.projects_directory, project_name)
|
||||
|
||||
|
||||
if project.manager.get(project_name) is not None:
|
||||
interface.error(_("[project_name!q] already exists. Please choose a different project name."), project_name=project_name)
|
||||
|
||||
|
||||
if os.path.exists(project_dir):
|
||||
interface.error(_("[project_dir!q] already exists. Please choose a different project name."), project_dir=project_dir)
|
||||
|
||||
@@ -75,25 +96,25 @@ label new_project:
|
||||
template = renpy.call_screen("select_template")
|
||||
|
||||
template_path = template.path
|
||||
|
||||
|
||||
with interface.error_handling("creating a new project"):
|
||||
shutil.copytree(template_path, project_dir)
|
||||
|
||||
shutil.copytree(template_path, project_dir, symlinks=False)
|
||||
|
||||
# Delete the tmp directory, if it exists.
|
||||
if os.path.isdir(os.path.join(project_dir, "tmp")):
|
||||
os.path.rmtree(os.path.join(project_dir, "tmp"))
|
||||
|
||||
shutil.rmtree(os.path.join(project_dir, "tmp"))
|
||||
|
||||
# Delete project.json, which must exist.
|
||||
os.unlink(os.path.join(project_dir, "project.json"))
|
||||
|
||||
|
||||
# Change the save directory in options.rpy
|
||||
fn = os.path.join(project_dir, "game/options.rpy")
|
||||
with open(fn, "rb") as f:
|
||||
options = f.read().decode("utf-8")
|
||||
|
||||
save_dir = project_name + "-" + str(int(time.time()))
|
||||
options = re.sub(r'template-\d+', save_dir, options)
|
||||
|
||||
options = options.replace("PROJECT_NAME", project_name)
|
||||
options = options.replace("UNIQUE", str(int(time.time())))
|
||||
|
||||
with open(fn, "wb") as f:
|
||||
f.write(options.encode("utf-8"))
|
||||
|
||||
@@ -101,9 +122,7 @@ label new_project:
|
||||
with interface.error_handling("activating the new project"):
|
||||
project.manager.scan()
|
||||
project.Select(project.manager.get(project_name))()
|
||||
|
||||
|
||||
call choose_theme_callable
|
||||
|
||||
jump front_page
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## This file contains some of the options that can be changed to customize
|
||||
## your Ren'Py game. It only contains the most common options... there
|
||||
@@ -35,7 +53,7 @@ init -1 python hide:
|
||||
|
||||
#########################################
|
||||
# Themes
|
||||
|
||||
|
||||
## We then want to call a theme function. themes.roundrect is
|
||||
## a theme that features the use of rounded rectangles. It's
|
||||
## the only theme we currently support.
|
||||
@@ -46,7 +64,7 @@ init -1 python hide:
|
||||
theme.roundrect(
|
||||
## Theme: Roundrect
|
||||
## Color scheme: Basic Blue
|
||||
|
||||
|
||||
## The color of an idle widget face.
|
||||
widget = "#003c78",
|
||||
|
||||
@@ -60,7 +78,7 @@ init -1 python hide:
|
||||
## example, the current value of a preference.)
|
||||
widget_selected = "#ffffc8",
|
||||
|
||||
## The color of a disabled widget face.
|
||||
## The color of a disabled widget face.
|
||||
disabled = "#404040",
|
||||
|
||||
## The color of disabled widget text.
|
||||
@@ -88,7 +106,7 @@ init -1 python hide:
|
||||
|
||||
## And we're done with the theme. The theme will customize
|
||||
## various styles, so if we want to change them, we should
|
||||
## do so below.
|
||||
## do so below.
|
||||
)
|
||||
|
||||
#########################################
|
||||
@@ -100,7 +118,7 @@ init -1 python hide:
|
||||
## show help to the user.
|
||||
## - A file name relative to the base directory, which is opened in a
|
||||
## web browser.
|
||||
## - None, to disable help.
|
||||
## - None, to disable help.
|
||||
config.help = "README.html"
|
||||
|
||||
#########################################
|
||||
@@ -166,52 +184,69 @@ init -1 python hide:
|
||||
config.sound = False
|
||||
config.quit_action = Quit(confirm=False)
|
||||
config.gl_resize = False
|
||||
config.window_icon = "logo.png"
|
||||
config.windows_icon = "logo32.png"
|
||||
config.window_icon = "images/logo.png"
|
||||
config.windows_icon = "images/logo32.png"
|
||||
config.has_autosave = False
|
||||
config.log_enable = False
|
||||
config.mouse_hide_time = 86400 * 366
|
||||
|
||||
|
||||
_game_menu_screen = None
|
||||
|
||||
config.underlay = [ ]
|
||||
|
||||
config.underlay = [
|
||||
renpy.Keymap(
|
||||
quit = renpy.quit_event,
|
||||
iconify = renpy.iconify,
|
||||
choose_renderer = renpy.curried_call_in_new_context("_choose_renderer"),
|
||||
self_voicing = Preference("self voicing", "toggle"),
|
||||
),
|
||||
]
|
||||
|
||||
config.rollback_enabled = False
|
||||
|
||||
translate None python:
|
||||
config.rtl = False
|
||||
|
||||
## This section controls how to build Ren'Py. (Building the launcher is how
|
||||
## we build Ren'Py distributions.)
|
||||
init python:
|
||||
|
||||
|
||||
## We're building Ren'Py tonight.
|
||||
build.renpy = True
|
||||
|
||||
|
||||
## The version number that's supplied to the updater.
|
||||
build.version = "Ren'Py {}".format(config.version)
|
||||
|
||||
|
||||
## The name that's used for directories and archive files. For example, if
|
||||
## this is 'mygame-1.0', the windows distribution will be in the
|
||||
## directory 'mygame-1.0-win', in the 'mygame-1.0-win.zip' file.
|
||||
build.directory_name = "renpy-" + config.version.rsplit('.', 1)[0]
|
||||
|
||||
|
||||
if 'RENPY_NIGHTLY' in os.environ:
|
||||
build.directory_name = os.environ['RENPY_NIGHTLY']
|
||||
else:
|
||||
build.directory_name = "renpy-" + config.version.rsplit('.', 1)[0]
|
||||
|
||||
## The name that's uses for executables - the program that users will run
|
||||
## to start the game. For example, if this is 'mygame', then on Windows,
|
||||
## users can click 'mygame.exe' to start the game.
|
||||
build.executable_name = "renpy"
|
||||
|
||||
|
||||
## If True, Ren'Py will include update information into packages. This
|
||||
## allows the updater to run.
|
||||
build.include_update = True
|
||||
|
||||
|
||||
## Clear out various file patterns.
|
||||
build.renpy_patterns = [ ]
|
||||
build.early_base_patterns = [ ]
|
||||
build.base_patterns = [ ]
|
||||
build.late_base_patterns = [ ]
|
||||
|
||||
# We don't need to clear out the executable patterns, since they're
|
||||
|
||||
# We don't need to clear out the executable patterns, since they're
|
||||
# correct for Ren'Py.
|
||||
|
||||
## Now, add the Ren'Py distribution in using classify_renpy.
|
||||
|
||||
## Now, add the Ren'Py distribution in using classify_renpy.
|
||||
|
||||
build.classify_renpy("rapt/**", "rapt")
|
||||
|
||||
build.classify_renpy("**~", None)
|
||||
build.classify_renpy("**/#*", None)
|
||||
build.classify_renpy("**/thumbs.db", None)
|
||||
@@ -223,29 +258,45 @@ init python:
|
||||
build.classify_renpy("**.pyc", None)
|
||||
|
||||
build.classify_renpy("**/log.txt", None)
|
||||
build.classify_renpy("**/traceback.txt", None)
|
||||
build.classify_renpy("**/errors.txt", None)
|
||||
build.classify_renpy("**/saves/", None)
|
||||
build.classify_renpy("**/tmp/", None)
|
||||
build.classify_renpy("**/.Editra", None)
|
||||
|
||||
# main source.
|
||||
|
||||
def source_and_binary(pattern):
|
||||
"""
|
||||
Classifies source and binary files beginning with `pattern`.
|
||||
.pyo, .rpyc, .rpycm, and .rpyb go into binary, everything
|
||||
else goes into source.
|
||||
"""
|
||||
|
||||
build.classify_renpy(pattern + ".pyo", "binary")
|
||||
build.classify_renpy(pattern + ".rpyc", "binary")
|
||||
build.classify_renpy(pattern + ".rpymc", "binary")
|
||||
build.classify_renpy(pattern + ".rpyb", "binary")
|
||||
build.classify_renpy(pattern, "source")
|
||||
|
||||
build.classify_renpy("renpy.py", "source")
|
||||
build.classify_renpy("renpy/**", "source")
|
||||
build.classify_renpy("common/**", "source")
|
||||
source_and_binary("renpy/**")
|
||||
|
||||
# games.
|
||||
build.classify_renpy("launcher/**", "source")
|
||||
build.classify_renpy("template/**", "source")
|
||||
build.classify_renpy("the_question/**", "source")
|
||||
build.classify_renpy("tutorial/**", "source")
|
||||
build.classify_renpy("launcher/game/theme/", None)
|
||||
source_and_binary("launcher/**")
|
||||
source_and_binary("templates/**")
|
||||
source_and_binary("the_question/**")
|
||||
source_and_binary("tutorial/**")
|
||||
|
||||
# docs.
|
||||
# docs.
|
||||
build.classify_renpy("doc/", "source")
|
||||
build.classify_renpy("doc/.doctrees/", None)
|
||||
build.classify_renpy("doc/_sources/", None)
|
||||
build.classify_renpy("doc/**", "source")
|
||||
build.classify_renpy("LICENSE.txt", "source")
|
||||
|
||||
# module.
|
||||
|
||||
# module.
|
||||
build.classify_renpy("module/", "source")
|
||||
build.classify_renpy("module/*.c", "source")
|
||||
build.classify_renpy("module/gen/", "source")
|
||||
@@ -259,14 +310,12 @@ init python:
|
||||
build.classify_renpy("module/pysdlsound/*.pyx", "source")
|
||||
|
||||
# all-platforms binary.
|
||||
build.classify_renpy("lib/*/renpy", None)
|
||||
build.classify_renpy("lib/*/renpy.exe", None)
|
||||
build.classify_renpy("lib/**", "binary")
|
||||
build.classify_renpy("python27.dll", "binary")
|
||||
build.classify_renpy("msvcr90.dll", "binary")
|
||||
build.classify_renpy("Microsoft.VC90.CRT.manifest", "binary")
|
||||
build.classify_renpy("renpy.sh", "binary")
|
||||
build.classify_renpy("renpy.app/**", "binary")
|
||||
build.classify_renpy("renpy.exe", "binary")
|
||||
build.classify_renpy("console.exe", "binary")
|
||||
# renpy.app is now built from scratch from distribute.rpy.
|
||||
|
||||
# jedit rules.
|
||||
build.classify_renpy("jedit/**", "jedit")
|
||||
@@ -274,9 +323,11 @@ init python:
|
||||
# editra rules.
|
||||
build.classify_renpy("editra/", "editra-all")
|
||||
build.classify_renpy("editra/Editra.edit.py", "editra-all")
|
||||
build.classify_renpy("editra/Editra/**", "editra-linux")
|
||||
build.classify_renpy("editra/Editra/**", "editra-linux editra-windows")
|
||||
build.classify_renpy("editra/Editra-mac.app/**", "editra-mac")
|
||||
build.classify_renpy("editra/Editra-win32/**", "editra-windows")
|
||||
build.classify_renpy("editra/lib/**", "editra-windows")
|
||||
build.classify_renpy("editra/editra.exe", "editra-windows")
|
||||
|
||||
|
||||
# Executable rules.
|
||||
build.executable("editra/Editra/Editra")
|
||||
@@ -287,8 +338,9 @@ init python:
|
||||
build.package("sdk", "zip tar.bz2", "source binary")
|
||||
build.package("source", "tar.bz2", "source", update=False)
|
||||
|
||||
build.package("jedit", "zip", "jedit")
|
||||
build.package("jedit", "zip", "jedit", dlc=True)
|
||||
build.package("editra-linux", "tar.bz2", "editra-all editra-linux", dlc=True)
|
||||
build.package("editra-mac", "zip", "editra-all editra-mac", dlc=True)
|
||||
build.package("editra-windows", "zip", "editra-all editra-windows", dlc=True)
|
||||
build.package("rapt", "zip", "rapt", dlc=True)
|
||||
|
||||
|
||||
@@ -1,62 +1,165 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init python in distribute:
|
||||
|
||||
|
||||
import time
|
||||
import zipfile
|
||||
import tarfile
|
||||
import zlib
|
||||
import struct
|
||||
import stat
|
||||
import shutil
|
||||
|
||||
from zipfile import crc32
|
||||
|
||||
zlib.Z_DEFAULT_COMPRESSION = 9
|
||||
|
||||
|
||||
class ZipFile(zipfile.ZipFile):
|
||||
|
||||
def write_with_info(self, zinfo, filename):
|
||||
"""Put the bytes from filename into the archive under the name
|
||||
arcname."""
|
||||
if not self.fp:
|
||||
raise RuntimeError(
|
||||
"Attempt to write to ZIP archive that was already closed")
|
||||
|
||||
st = os.stat(filename)
|
||||
isdir = stat.S_ISDIR(st.st_mode)
|
||||
|
||||
zinfo.file_size = st.st_size
|
||||
zinfo.flag_bits = 0x00
|
||||
zinfo.header_offset = self.fp.tell() # Start of header bytes
|
||||
|
||||
self._writecheck(zinfo)
|
||||
self._didModify = True
|
||||
|
||||
if isdir:
|
||||
zinfo.file_size = 0
|
||||
zinfo.compress_size = 0
|
||||
zinfo.CRC = 0
|
||||
self.filelist.append(zinfo)
|
||||
self.NameToInfo[zinfo.filename] = zinfo
|
||||
self.fp.write(zinfo.FileHeader())
|
||||
return
|
||||
|
||||
with open(filename, "rb") as fp:
|
||||
# Must overwrite CRC and sizes with correct data later
|
||||
zinfo.CRC = CRC = 0
|
||||
zinfo.compress_size = compress_size = 0
|
||||
zinfo.file_size = file_size = 0
|
||||
self.fp.write(zinfo.FileHeader())
|
||||
if zinfo.compress_type == zipfile.ZIP_DEFLATED:
|
||||
cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
|
||||
zlib.DEFLATED, -15)
|
||||
else:
|
||||
cmpr = None
|
||||
while 1:
|
||||
buf = fp.read(1024 * 1024)
|
||||
if not buf:
|
||||
break
|
||||
file_size = file_size + len(buf)
|
||||
CRC = crc32(buf, CRC) & 0xffffffff
|
||||
if cmpr:
|
||||
buf = cmpr.compress(buf)
|
||||
compress_size = compress_size + len(buf)
|
||||
self.fp.write(buf)
|
||||
if cmpr:
|
||||
buf = cmpr.flush()
|
||||
compress_size = compress_size + len(buf)
|
||||
self.fp.write(buf)
|
||||
zinfo.compress_size = compress_size
|
||||
else:
|
||||
zinfo.compress_size = file_size
|
||||
zinfo.CRC = CRC
|
||||
zinfo.file_size = file_size
|
||||
# Seek backwards and write CRC and file sizes
|
||||
position = self.fp.tell() # Preserve current position in file
|
||||
self.fp.seek(zinfo.header_offset + 14, 0)
|
||||
self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
|
||||
zinfo.file_size))
|
||||
self.fp.seek(position, 0)
|
||||
self.filelist.append(zinfo)
|
||||
self.NameToInfo[zinfo.filename] = zinfo
|
||||
|
||||
|
||||
class ZipPackage(object):
|
||||
"""
|
||||
A class that creates a zip file.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, filename):
|
||||
self.zipfile = zipfile.ZipFile(filename, "w", zipfile.ZIP_DEFLATED)
|
||||
|
||||
self.zipfile = ZipFile(filename, "w", zipfile.ZIP_DEFLATED)
|
||||
|
||||
def add_file(self, name, path, xbit):
|
||||
|
||||
|
||||
if path is None:
|
||||
raise Exception("path for " + name + " must not be None.")
|
||||
|
||||
zi = zipfile.ZipInfo(name)
|
||||
|
||||
s = os.stat(path)
|
||||
zi.date_time = time.gmtime(s.st_mtime)[:6]
|
||||
try:
|
||||
s = os.stat(path)
|
||||
zi.date_time = time.gmtime(s.st_mtime)[:6]
|
||||
except:
|
||||
zi.date_time = time.gmtime()[:6]
|
||||
|
||||
zi.compress_type = zipfile.ZIP_DEFLATED
|
||||
zi.create_system = 3
|
||||
|
||||
if xbit:
|
||||
zi.external_attr = long(0100777) << 16
|
||||
zi.external_attr = long(0100755) << 16
|
||||
else:
|
||||
zi.external_attr = long(0100666) << 16
|
||||
zi.external_attr = long(0100644) << 16
|
||||
|
||||
with open(path, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
self.zipfile.writestr(zi, data)
|
||||
self.zipfile.write_with_info(zi, path)
|
||||
|
||||
def add_directory(self, name, path):
|
||||
return
|
||||
|
||||
if path is None:
|
||||
return
|
||||
|
||||
zi = zipfile.ZipInfo(name + "/")
|
||||
|
||||
s = os.stat(path)
|
||||
zi.date_time = time.gmtime(s.st_mtime)[:6]
|
||||
zi.compress_type = zipfile.ZIP_STORED
|
||||
zi.create_system = 3
|
||||
zi.external_attr = (long(0040755) << 16) | 0x10
|
||||
|
||||
self.zipfile.write_with_info(zi, path)
|
||||
|
||||
def close(self):
|
||||
self.zipfile.close()
|
||||
|
||||
|
||||
class TarPackage(object):
|
||||
|
||||
|
||||
def __init__(self, filename, mode, notime=False):
|
||||
"""
|
||||
notime
|
||||
If true, times will be forced to the epoch.
|
||||
"""
|
||||
|
||||
|
||||
self.tarfile = tarfile.open(filename, mode)
|
||||
self.tarfile.dereference = True
|
||||
self.tarfile.dereference = True
|
||||
self.notime = notime
|
||||
|
||||
def add_file(self, name, path, xbit):
|
||||
@@ -66,13 +169,13 @@ init python in distribute:
|
||||
else:
|
||||
info = tarfile.TarInfo(name)
|
||||
info.size = 0
|
||||
info.mtime = time.time()
|
||||
info.mtime = int(time.time())
|
||||
info.type = tarfile.DIRTYPE
|
||||
|
||||
if xbit:
|
||||
info.mode = 0777
|
||||
info.mode = 0755
|
||||
else:
|
||||
info.mode = 0666
|
||||
info.mode = 0644
|
||||
|
||||
info.uid = 1000
|
||||
info.gid = 1000
|
||||
@@ -93,3 +196,31 @@ init python in distribute:
|
||||
|
||||
def close(self):
|
||||
self.tarfile.close()
|
||||
|
||||
class DirectoryPackage(object):
|
||||
|
||||
def mkdir(self, path):
|
||||
if not os.path.isdir(path):
|
||||
os.mkdir(path, 0755)
|
||||
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.mkdir(path)
|
||||
|
||||
def add_file(self, name, path, xbit):
|
||||
fn = os.path.join(self.path, name)
|
||||
shutil.copy2(path, fn)
|
||||
|
||||
if xbit:
|
||||
os.chmod(fn, 0755)
|
||||
else:
|
||||
os.chmod(fn, 0644)
|
||||
|
||||
def add_directory(self, name, path):
|
||||
fn = os.path.join(self.path, name)
|
||||
self.mkdir(fn)
|
||||
|
||||
def close(self):
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -1,80 +1,120 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init python:
|
||||
if persistent.gl_enable is None:
|
||||
persistent.gl_enable = True
|
||||
|
||||
|
||||
config.gl_enable = persistent.gl_enable
|
||||
|
||||
|
||||
if persistent.windows_console is None:
|
||||
persistent.windows_console = False
|
||||
|
||||
def scan_translations():
|
||||
|
||||
languages = renpy.known_languages()
|
||||
|
||||
if not languages:
|
||||
return None
|
||||
|
||||
rv = [ ( "English", None) ]
|
||||
|
||||
for i in languages:
|
||||
rv.append((i.replace("_", " ").title(), i))
|
||||
|
||||
rv.sort()
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
screen preferences:
|
||||
|
||||
|
||||
$ translations = scan_translations()
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
alt "Preferences"
|
||||
|
||||
window:
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
label _("Launcher Preferences")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
|
||||
hbox:
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
xmaximum ONEHALF
|
||||
xmaximum ONETHIRD
|
||||
xfill True
|
||||
|
||||
|
||||
has vbox
|
||||
|
||||
# Projects directory selection.
|
||||
add SEPARATOR2
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
yminimum 75
|
||||
has vbox
|
||||
|
||||
|
||||
text _("Projects Directory:")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
|
||||
frame style "l_indent":
|
||||
|
||||
|
||||
frame style "l_indent":
|
||||
if persistent.projects_directory:
|
||||
textbutton _("[persistent.projects_directory!q]") action Jump("projects_directory_preference")
|
||||
textbutton _("[persistent.projects_directory!q]"):
|
||||
action Jump("projects_directory_preference")
|
||||
alt _("Projects directory: [text]")
|
||||
else:
|
||||
textbutton _("Not Set") action Jump("projects_directory_preference")
|
||||
|
||||
|
||||
textbutton _("Not Set"):
|
||||
action Jump("projects_directory_preference")
|
||||
alt _("Projects directory: [text]")
|
||||
|
||||
|
||||
add SPACER
|
||||
|
||||
# Text editor selection.
|
||||
add SEPARATOR2
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
yminimum 75
|
||||
has vbox
|
||||
|
||||
|
||||
text _("Text Editor:")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
frame style "l_indent":
|
||||
|
||||
frame style "l_indent":
|
||||
if persistent.editor:
|
||||
textbutton persistent.editor action Jump("editor_preference")
|
||||
textbutton persistent.editor action Jump("editor_preference") alt _("Text editor: [text]")
|
||||
else:
|
||||
textbutton _("Not Set") action Jump("editor_preference")
|
||||
|
||||
textbutton _("Not Set") action Jump("editor_preference") alt _("Text editor: [text]")
|
||||
|
||||
add SPACER
|
||||
|
||||
if ability.can_update:
|
||||
@@ -86,64 +126,100 @@ screen preferences:
|
||||
style "l_indent"
|
||||
yminimum 75
|
||||
has vbox
|
||||
|
||||
|
||||
text _("Update Channel:")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
frame style "l_indent":
|
||||
|
||||
frame style "l_indent":
|
||||
textbutton persistent.update_channel action Jump("update_preference")
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
xmaximum ONEHALF
|
||||
xmaximum ONETHIRD
|
||||
xfill True
|
||||
|
||||
|
||||
has vbox
|
||||
add SEPARATOR2
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
yminimum 75
|
||||
has vbox
|
||||
|
||||
|
||||
text _("Navigation Options:")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
|
||||
textbutton _("Include private names") style "l_checkbox" action ToggleField(persistent, "navigate_private")
|
||||
textbutton _("Include library names") style "l_checkbox" action ToggleField(persistent, "navigate_library")
|
||||
|
||||
add SPACER
|
||||
add SEPARATOR2
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
yminimum 75
|
||||
has vbox
|
||||
|
||||
|
||||
text _("Launcher Options:")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
|
||||
textbutton _("Hardware rendering") style "l_checkbox" action ToggleField(persistent, "gl_enable")
|
||||
|
||||
textbutton _("Show templates") style "l_checkbox" action ToggleField(persistent, "show_templates")
|
||||
textbutton _("Large fonts") style "l_checkbox" action [ ToggleField(persistent, "large_print"), renpy.utter_restart ]
|
||||
|
||||
if renpy.windows:
|
||||
textbutton _("Console output") style "l_checkbox" action ToggleField(persistent, "windows_console")
|
||||
|
||||
add SPACER
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
xmaximum ONETHIRD
|
||||
xfill True
|
||||
|
||||
has vbox
|
||||
|
||||
add SEPARATOR2
|
||||
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
yminimum 75
|
||||
has vbox
|
||||
|
||||
|
||||
text _("Actions:")
|
||||
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
textbutton _("Open launcher as project") style "l_nonbox" action [ project.Select("launcher"), Jump("front_page") ]
|
||||
textbutton _("Open launcher project") style "l_nonbox" action [ project.Select("launcher"), Jump("front_page") ]
|
||||
|
||||
if translations:
|
||||
|
||||
add SPACER
|
||||
|
||||
# Text editor selection.
|
||||
add SEPARATOR2
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
yminimum 75
|
||||
has vbox
|
||||
|
||||
text _("Language:")
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
viewport:
|
||||
scrollbars "vertical"
|
||||
mousewheel True
|
||||
|
||||
has vbox
|
||||
|
||||
# frame style "l_indent":
|
||||
|
||||
for tlname, tlvalue in translations:
|
||||
textbutton tlname action Language(tlvalue) style "l_list"
|
||||
|
||||
|
||||
textbutton _("Back") action Jump("front_page") style "l_left_button"
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
# Code that manages projects.
|
||||
|
||||
init python:
|
||||
try:
|
||||
import EasyDialogs
|
||||
except ImportError:
|
||||
try:
|
||||
import EasyDialogsWin as EasyDialogs
|
||||
except:
|
||||
EasyDialogs = None
|
||||
|
||||
import EasyDialogsWin as EasyDialogs
|
||||
except:
|
||||
EasyDialogs = None
|
||||
|
||||
import os
|
||||
|
||||
init python in project:
|
||||
@@ -24,9 +39,20 @@ init python in project:
|
||||
import json
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
import tempfile
|
||||
|
||||
if persistent.blurb is None:
|
||||
persistent.blurb = 0
|
||||
|
||||
LAUNCH_BLURBS = [
|
||||
_("After making changes to the script, press shift+R to reload your game."),
|
||||
_("Press shift+O (the letter) to access the console."),
|
||||
_("Press shift+D to access the developer menu."),
|
||||
_("Have you backed up your projects recently?"),
|
||||
]
|
||||
|
||||
class Project(object):
|
||||
|
||||
|
||||
def __init__(self, path):
|
||||
|
||||
while path.endswith("/"):
|
||||
@@ -34,36 +60,40 @@ init python in project:
|
||||
|
||||
if not os.path.exists(path):
|
||||
raise Exception("{} does not exist.".format(path))
|
||||
|
||||
|
||||
# The name of the project.
|
||||
self.name = os.path.basename(path)
|
||||
|
||||
if path.endswith(".app/Contents/Resources/autorun"):
|
||||
self.name = os.path.basename(path[:-len(".app/Contents/Resources/autorun")])
|
||||
else:
|
||||
self.name = os.path.basename(path)
|
||||
|
||||
# The path to the project.
|
||||
self.path = path
|
||||
|
||||
|
||||
# The path to the game directory.
|
||||
gamedir = os.path.join(path, "game")
|
||||
if os.path.isdir(gamedir):
|
||||
self.gamedir = gamedir
|
||||
else:
|
||||
self.gamedir = path
|
||||
|
||||
|
||||
# Load the data.
|
||||
self.load_data()
|
||||
|
||||
# The project's temporary directory.
|
||||
self.tmp = os.path.join(self.path, "tmp")
|
||||
|
||||
# The path to the json dumpfile.
|
||||
self.dump_filename = os.path.join(self.tmp, "navigation.json")
|
||||
|
||||
self.tmp = None
|
||||
|
||||
# This contains the result of dumping information about the game
|
||||
# to disk.
|
||||
self.dump = { }
|
||||
|
||||
|
||||
# The mtime of the last dump file loaded.
|
||||
self.dump_mtime = 0
|
||||
|
||||
def get_dump_filename(self):
|
||||
self.make_tmp()
|
||||
return os.path.join(self.tmp, "navigation.json")
|
||||
|
||||
def load_data(self):
|
||||
try:
|
||||
f = open(os.path.join(self.path, "project.json"), "rb")
|
||||
@@ -88,92 +118,141 @@ init python in project:
|
||||
|
||||
def update_data(self):
|
||||
data = self.data
|
||||
|
||||
|
||||
data.setdefault("build_update", False)
|
||||
data.setdefault("packages", [ "all" ])
|
||||
|
||||
def make_tmp(self):
|
||||
"""
|
||||
Makes the project's temporary directory, if it doesn't exist
|
||||
Makes the project's temporary directory, if it doesn't exist
|
||||
yet.
|
||||
"""
|
||||
|
||||
|
||||
if self.tmp and os.path.isdir(self.tmp):
|
||||
return
|
||||
|
||||
tmp = os.path.join(self.path, "tmp")
|
||||
|
||||
try:
|
||||
os.mkdir(self.tmp)
|
||||
os.mkdir(tmp)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if os.path.isdir(tmp):
|
||||
self.tmp = tmp
|
||||
return
|
||||
|
||||
self.tmp = tempfile.mkdtemp()
|
||||
|
||||
def temp_filename(self, filename):
|
||||
"""
|
||||
Returns a filename in the temporary directory.
|
||||
"""
|
||||
|
||||
|
||||
self.make_tmp()
|
||||
return os.path.join(self.tmp, filename)
|
||||
|
||||
def launch(self, args=[], wait=False):
|
||||
|
||||
def launch(self, args=[], wait=False, env={}):
|
||||
"""
|
||||
Launches the project.
|
||||
|
||||
`args`
|
||||
Additional arguments to give to the project.
|
||||
|
||||
`wait`
|
||||
If true, waits for the launched project to terminate before
|
||||
continuing.
|
||||
|
||||
`env`
|
||||
Additional variables to include in the environment.
|
||||
"""
|
||||
|
||||
self.make_tmp()
|
||||
|
||||
if renpy.renpy.windows and sys.argv[0].endswith(".exe"):
|
||||
if persistent.windows_console:
|
||||
cmd = [ os.path.join(config.renpy_base, "console.exe") ]
|
||||
else:
|
||||
cmd = [ os.path.join(config.renpy_base, "renpy.exe") ]
|
||||
# Find the python executable to run.
|
||||
executable_path = os.path.dirname(sys.executable)
|
||||
|
||||
if renpy.renpy.windows:
|
||||
extension = ".exe"
|
||||
else:
|
||||
cmd = [ sys.executable, "-OO", sys.argv[0] ]
|
||||
|
||||
extension = ""
|
||||
|
||||
if persistent.windows_console:
|
||||
executables = [ "python" + extension ]
|
||||
else:
|
||||
executables = [ "pythonw" + extension ]
|
||||
|
||||
executables.append(sys.executable)
|
||||
|
||||
for i in executables:
|
||||
executable = os.path.join(executable_path, i)
|
||||
if os.path.exists(executable):
|
||||
break
|
||||
else:
|
||||
raise Exception("Python interpreter not found: %r", executables)
|
||||
|
||||
# Put together the basic command line.
|
||||
cmd = [ executable, "-EO", sys.argv[0] ]
|
||||
|
||||
cmd.append(self.path)
|
||||
cmd.extend(args)
|
||||
|
||||
|
||||
# Add flags to dump game info.
|
||||
cmd.append("--json-dump")
|
||||
cmd.append(self.dump_filename)
|
||||
cmd.append(self.get_dump_filename())
|
||||
|
||||
if persistent.navigate_private:
|
||||
cmd.append("--json-dump-private")
|
||||
|
||||
|
||||
if persistent.navigate_library:
|
||||
cmd.append("--json-dump-common")
|
||||
|
||||
|
||||
with interface.error_handling("launching the project"):
|
||||
cmd = [ renpy.fsencode(i) for i in cmd ]
|
||||
|
||||
p = subprocess.Popen(cmd)
|
||||
|
||||
if wait:
|
||||
p.wait()
|
||||
|
||||
environ = dict(os.environ)
|
||||
environ.update(env)
|
||||
|
||||
for k in environ:
|
||||
environ[k] = renpy.fsencode(environ[k])
|
||||
|
||||
# Launch the project.
|
||||
cmd = [ renpy.fsencode(i) for i in cmd ]
|
||||
|
||||
p = subprocess.Popen(cmd, env=environ)
|
||||
|
||||
if wait:
|
||||
if p.wait():
|
||||
interface.error(_("Launching the project failed."), _("Please ensure that your project launches normally before running this command."))
|
||||
|
||||
def update_dump(self, force=False, gui=True):
|
||||
"""
|
||||
If the dumpfile does not exist, runs Ren'Py to create it. Otherwise,
|
||||
If the dumpfile does not exist, runs Ren'Py to create it. Otherwise,
|
||||
loads it in iff it's newer than the one that's already loaded.
|
||||
"""
|
||||
|
||||
if force or not os.path.exists(self.dump_filename):
|
||||
self.make_tmp()
|
||||
|
||||
dump_filename = self.get_dump_filename()
|
||||
|
||||
if force or not os.path.exists(dump_filename):
|
||||
|
||||
if gui:
|
||||
interface.processing(_("Ren'Py is scanning the project..."))
|
||||
|
||||
|
||||
self.launch(["quit"], wait=True)
|
||||
|
||||
if not os.path.exists(self.dump_filename):
|
||||
|
||||
if not os.path.exists(dump_filename):
|
||||
self.dump["error"] = True
|
||||
return
|
||||
|
||||
file_mtime = os.path.getmtime(self.dump_filename)
|
||||
|
||||
file_mtime = os.path.getmtime(dump_filename)
|
||||
if file_mtime == self.dump_mtime:
|
||||
return
|
||||
|
||||
self.dump_mtime = file_mtime
|
||||
|
||||
try:
|
||||
with open(self.dump_filename, "r") as f:
|
||||
with open(dump_filename, "r") as f:
|
||||
self.dump = json.load(f)
|
||||
# add todo list to dump data
|
||||
self.update_todos()
|
||||
|
||||
|
||||
except:
|
||||
self.dump["error"] = True
|
||||
|
||||
@@ -184,7 +263,7 @@ init python in project:
|
||||
"""
|
||||
|
||||
todos = self.dump.setdefault("location", {})["todo"] = {}
|
||||
|
||||
|
||||
files = self.script_files()
|
||||
|
||||
for f in files:
|
||||
@@ -193,12 +272,17 @@ init python in project:
|
||||
|
||||
for l, line in enumerate(data):
|
||||
l += 1
|
||||
|
||||
m = re.search(r".*#\s*TODO(\s*:\s*|\s+)(.*)", line, re.I)
|
||||
|
||||
|
||||
try:
|
||||
line = line.decode("utf-8")
|
||||
except:
|
||||
continue
|
||||
|
||||
m = re.search(ur".*#\s*TODO(\s*:\s*|\s+)(.*)", line, re.I)
|
||||
|
||||
if m is None:
|
||||
continue
|
||||
|
||||
|
||||
raw_todo_text = m.group(2).strip()
|
||||
todo_text = raw_todo_text
|
||||
|
||||
@@ -206,8 +290,8 @@ init python in project:
|
||||
|
||||
while not todo_text or todo_text in todos:
|
||||
index += 1
|
||||
todo_text = "{0} ({1})".format(raw_todo_text, index)
|
||||
|
||||
todo_text = u"{0} ({1})".format(raw_todo_text, index)
|
||||
|
||||
todos[todo_text] = [f, l]
|
||||
|
||||
|
||||
@@ -215,7 +299,7 @@ init python in project:
|
||||
"""
|
||||
Unelides the filename relative to the project base.
|
||||
"""
|
||||
|
||||
|
||||
fn1 = os.path.join(self.path, fn)
|
||||
if os.path.exists(fn1):
|
||||
return fn1
|
||||
@@ -223,90 +307,96 @@ init python in project:
|
||||
fn2 = os.path.join(config.renpy_base, fn)
|
||||
if os.path.exists(fn2):
|
||||
return fn2
|
||||
|
||||
|
||||
return fn
|
||||
|
||||
|
||||
def script_files(self):
|
||||
"""
|
||||
Return a list of the script files that make up the project. These
|
||||
are elided, and so need to be passed to unelide_filename before they
|
||||
can be included in the project.
|
||||
"""
|
||||
|
||||
|
||||
rv = [ ]
|
||||
rv.extend(i for i, isdir in util.walk(self.path) if (not isdir) and (i.endswith(".rpy") or i.endswith(".rpym")) )
|
||||
rv.extend(i for i, isdir in util.walk(self.path)
|
||||
if (not isdir) and (i.endswith(".rpy") or i.endswith(".rpym")) and (not i.startswith("tmp/")) )
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
|
||||
class ProjectManager(object):
|
||||
"""
|
||||
This maintains a list of the various types of projects that
|
||||
we know about.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# The projects directory.
|
||||
self.projects_directory = ""
|
||||
|
||||
|
||||
# Normal projects, in alphabetical order by lowercase name.
|
||||
self.projects = [ ]
|
||||
|
||||
|
||||
# Template projects.
|
||||
self.templates = [ ]
|
||||
|
||||
# All projects - normal, template, and hidden.
|
||||
self.all_projects = [ ]
|
||||
|
||||
|
||||
# Directories that have been scanned.
|
||||
self.scanned = set()
|
||||
|
||||
|
||||
self.scan()
|
||||
|
||||
|
||||
def scan(self):
|
||||
"""
|
||||
Scans for projects.
|
||||
"""
|
||||
|
||||
|
||||
if (persistent.projects_directory is not None) and not os.path.isdir(persistent.projects_directory):
|
||||
persistent.projects_directory = None
|
||||
|
||||
|
||||
self.projects_directory = persistent.projects_directory
|
||||
|
||||
self.projects = [ ]
|
||||
self.templates = [ ]
|
||||
self.all_projects = [ ]
|
||||
self.scanned = set()
|
||||
|
||||
|
||||
if self.projects_directory is not None:
|
||||
self.scan_directory(self.projects_directory)
|
||||
|
||||
|
||||
self.scan_directory(config.renpy_base)
|
||||
self.scan_directory(os.path.join(config.renpy_base, "templates"))
|
||||
|
||||
self.projects.sort(key=lambda p : p.name.lower())
|
||||
self.templates.sort(key=lambda p : p.name.lower())
|
||||
|
||||
|
||||
self.projects.sort(key=lambda p : p.name.lower())
|
||||
self.templates.sort(key=lambda p : p.name.lower())
|
||||
|
||||
def scan_directory(self, d):
|
||||
"""
|
||||
Scans for projects in directories directly underneath `d`.
|
||||
"""
|
||||
|
||||
|
||||
global current
|
||||
|
||||
|
||||
d = os.path.abspath(d)
|
||||
|
||||
|
||||
if not os.path.isdir(d):
|
||||
return
|
||||
|
||||
for pdir in os.listdir(d):
|
||||
|
||||
for pdir in util.listdir(d):
|
||||
|
||||
ppath = os.path.join(d, pdir)
|
||||
|
||||
|
||||
# A project must be a directory.
|
||||
if not os.path.isdir(ppath):
|
||||
continue
|
||||
|
||||
|
||||
autorun = os.path.join(ppath, "Contents", "Resources", "autorun")
|
||||
if os.path.exists(autorun):
|
||||
ppath = autorun
|
||||
|
||||
# A project has either a game/ directory, or a project.json
|
||||
# file.
|
||||
if (not os.path.isdir(os.path.join(ppath, "game"))) and (not os.path.exists(os.path.join(ppath, "project.json"))):
|
||||
@@ -315,52 +405,52 @@ init python in project:
|
||||
if ppath in self.scanned:
|
||||
continue
|
||||
self.scanned.add(ppath)
|
||||
|
||||
|
||||
# We have a project directory, so create a Project.
|
||||
p = Project(ppath)
|
||||
|
||||
|
||||
project_type = p.data.get("type", "normal")
|
||||
|
||||
|
||||
if project_type == "hidden":
|
||||
pass
|
||||
elif project_type == "template":
|
||||
self.templates.append(p)
|
||||
else:
|
||||
self.projects.append(p)
|
||||
|
||||
self.projects.append(p)
|
||||
|
||||
self.all_projects.append(p)
|
||||
|
||||
|
||||
# Select the default project.
|
||||
if persistent.active_project is not None:
|
||||
p = self.get(persistent.active_project)
|
||||
|
||||
|
||||
if p is not None:
|
||||
current = p
|
||||
return
|
||||
|
||||
|
||||
p = self.get("tutorial")
|
||||
if p is not None:
|
||||
current = p
|
||||
return
|
||||
|
||||
|
||||
current = None
|
||||
|
||||
|
||||
|
||||
|
||||
def get(self, name):
|
||||
"""
|
||||
Gets the project with the given name.
|
||||
|
||||
|
||||
Returns None if the project doesn't exist.
|
||||
"""
|
||||
|
||||
|
||||
for p in self.all_projects:
|
||||
if p.name == name:
|
||||
return p
|
||||
|
||||
|
||||
return None
|
||||
|
||||
manager = ProjectManager()
|
||||
|
||||
|
||||
manager = ProjectManager()
|
||||
|
||||
# The current project.
|
||||
current = None
|
||||
|
||||
@@ -370,38 +460,38 @@ init python in project:
|
||||
An action that causes p to become the selected project when it was
|
||||
clicked. If label is not None, jumps to the given label.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, p, label=None):
|
||||
"""
|
||||
`p`
|
||||
Either a project object, or a string giving the name of a
|
||||
Either a project object, or a string giving the name of a
|
||||
project.
|
||||
|
||||
|
||||
`label`
|
||||
The label to jump to when clicked.
|
||||
"""
|
||||
|
||||
|
||||
if isinstance(p, basestring):
|
||||
p = manager.get(p)
|
||||
|
||||
|
||||
self.project = p
|
||||
self.label = label
|
||||
|
||||
|
||||
def get_selected(self):
|
||||
if self.project is None:
|
||||
return False
|
||||
|
||||
if current is None:
|
||||
return False
|
||||
|
||||
|
||||
return current.path == self.project.path
|
||||
|
||||
|
||||
def get_sensitive(self):
|
||||
return self.project is not None
|
||||
|
||||
|
||||
def __call__(self):
|
||||
global current
|
||||
|
||||
|
||||
current = self.project
|
||||
persistent.active_project = self.project.name
|
||||
|
||||
@@ -409,14 +499,14 @@ init python in project:
|
||||
|
||||
if self.label is not None:
|
||||
renpy.jump(self.label)
|
||||
|
||||
|
||||
|
||||
|
||||
class Launch(Action):
|
||||
"""
|
||||
An action that launches the supplied project, or the current
|
||||
project if no project is supplied.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, p=None):
|
||||
if p is None:
|
||||
self.project = current
|
||||
@@ -424,12 +514,30 @@ init python in project:
|
||||
self.project = manager.get(p)
|
||||
else:
|
||||
self.project = p
|
||||
|
||||
|
||||
def get_sensitive(self):
|
||||
return self.project is not None
|
||||
|
||||
|
||||
def post_launch(self):
|
||||
blurb = LAUNCH_BLURBS[persistent.blurb % len(LAUNCH_BLURBS)]
|
||||
persistent.blurb += 1
|
||||
|
||||
interface.interaction(_("Launching"), blurb, pause=2.5)
|
||||
|
||||
|
||||
def __call__(self):
|
||||
self.project.launch()
|
||||
renpy.invoke_in_new_context(self.post_launch)
|
||||
|
||||
class Rescan(Action):
|
||||
def __call__(self):
|
||||
"""
|
||||
Rescans the projects directory.
|
||||
"""
|
||||
|
||||
manager.scan()
|
||||
renpy.restart_interaction()
|
||||
|
||||
|
||||
manager.scan()
|
||||
|
||||
@@ -438,60 +546,58 @@ init python in project:
|
||||
|
||||
###############################################################################
|
||||
# Code to choose the projects directory.
|
||||
|
||||
|
||||
label choose_projects_directory:
|
||||
|
||||
|
||||
python hide:
|
||||
|
||||
interface.interaction(_("PROJECTS DIRECTORY"), _("Please choose the projects directory."), _("This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."))
|
||||
|
||||
interface.interaction(_("PROJECTS DIRECTORY"), _("Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"), _("This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."),)
|
||||
|
||||
path = persistent.projects_directory
|
||||
|
||||
if path:
|
||||
|
||||
default_path = path
|
||||
|
||||
else:
|
||||
|
||||
try:
|
||||
default_path = os.path.dirname(os.path.abspath(config.renpy_base))
|
||||
except:
|
||||
default_path = os.path.abspath(config.renpy_base)
|
||||
|
||||
|
||||
|
||||
if EasyDialogs:
|
||||
|
||||
choice = EasyDialogs.AskFolder(defaultLocation=default_path, wanted=unicode)
|
||||
|
||||
if choice is not None:
|
||||
path = choice
|
||||
path = choice
|
||||
else:
|
||||
path = None
|
||||
|
||||
else:
|
||||
|
||||
try:
|
||||
env = os.environ.copy()
|
||||
|
||||
if 'RENPY_ORIGINAL_LD_LIBRARY_PATH' in env:
|
||||
env['LD_LIBRARY_PATH'] = env['RENPY_ORIGINAL_LD_LIBRARY_PATH']
|
||||
|
||||
cmd = [ "zenity", "--title=Select Projects Directory", "--file-selection", "--directory", "--filename=" + renpy.fsencode(default_path) ]
|
||||
cmd = [ "/usr/bin/python", os.path.join(config.gamedir, "tkaskdir.py"), renpy.fsencode(default_path) ]
|
||||
|
||||
zen = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
||||
choice = p.stdout.read()
|
||||
code = p.wait()
|
||||
|
||||
choice = zen.stdout.read()
|
||||
zen.wait()
|
||||
|
||||
if choice:
|
||||
path = renpy.fsdecode(choice[:-1])
|
||||
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
code = 0
|
||||
choice = ""
|
||||
path = None
|
||||
interface.error(_("Ren'Py was unable to run zenity to choose the projects directory."), label=None)
|
||||
|
||||
interface.error(_("Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."), label=None)
|
||||
|
||||
if code:
|
||||
interface.error(_("Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."), label=None)
|
||||
|
||||
elif choice:
|
||||
path = choice.decode("utf-8")
|
||||
|
||||
if path is None:
|
||||
path = default_path
|
||||
@@ -499,7 +605,36 @@ label choose_projects_directory:
|
||||
|
||||
path = renpy.fsdecode(path)
|
||||
|
||||
persistent.projects_directory = path
|
||||
if os.path.isdir(path):
|
||||
persistent.projects_directory = path
|
||||
else:
|
||||
path = os.path.abspath(config.renpy_base)
|
||||
|
||||
project.manager.scan()
|
||||
|
||||
|
||||
return
|
||||
|
||||
init python:
|
||||
|
||||
def set_projects_directory_command():
|
||||
ap = renpy.arguments.ArgumentParser()
|
||||
ap.add_argument("projects", help="The path to the projects directory.")
|
||||
|
||||
args = ap.parse_args()
|
||||
|
||||
persistent.projects_directory = args.projects
|
||||
renpy.save_persistent()
|
||||
|
||||
return False
|
||||
|
||||
renpy.arguments.register_command("set_projects_directory", set_projects_directory_command)
|
||||
|
||||
def get_projects_directory_command():
|
||||
ap = renpy.arguments.ArgumentParser()
|
||||
args = ap.parse_args()
|
||||
|
||||
print persistent.projects_directory
|
||||
|
||||
return False
|
||||
|
||||
renpy.arguments.register_command("get_projects_directory", get_projects_directory_command)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
init -999:
|
||||
$ config.script_version = (6, 15, 0)
|
||||
|
||||
|
||||
@@ -1,14 +1,95 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init -1 python:
|
||||
|
||||
# The color of non-interactive text.
|
||||
TEXT = "#545454"
|
||||
|
||||
# Colors for buttons in various states.
|
||||
IDLE = "#42637b"
|
||||
HOVER = "#d86b45"
|
||||
DISABLED = "#808080"
|
||||
|
||||
# Colors for reversed text buttons (selected list entries).
|
||||
REVERSE_IDLE = "#78a5c5"
|
||||
REVERSE_HOVER = "#d86b45"
|
||||
REVERSE_TEXT = "#ffffff"
|
||||
|
||||
# Colors for the scrollbar thumb.
|
||||
SCROLLBAR_IDLE = "#dfdfdf"
|
||||
SCROLLBAR_HOVER = "#d86b45"
|
||||
|
||||
# An image used as a separator pattern.
|
||||
PATTERN = "images/pattern.png"
|
||||
|
||||
# A displayable used for the background of everything.
|
||||
BACKGROUND = "images/background.png"
|
||||
|
||||
# A displayable used for the background of windows
|
||||
# containing commands, preferences, and navigation info.
|
||||
WINDOW = Frame("images/window.png", 0, 0, tile=True)
|
||||
|
||||
# A displayable used for the background of the projects list.
|
||||
PROJECTS_WINDOW = Null()
|
||||
|
||||
# A displayable used the background of information boxes.
|
||||
INFO_WINDOW = "#f9f9f9"
|
||||
|
||||
# Colors for the titles of information boxes.
|
||||
ERROR_COLOR = "#d15353"
|
||||
INFO_COLOR = "#545454"
|
||||
INTERACTION_COLOR = "#d19753"
|
||||
QUESTION_COLOR = "#d19753"
|
||||
|
||||
# The color of input text.
|
||||
INPUT_COLOR = "#d86b45"
|
||||
|
||||
# FONTS/WEIGHTS
|
||||
LIGHT = "Roboto-Light.ttf"
|
||||
REGULAR = "Roboto-Regular.ttf"
|
||||
|
||||
if persistent.large_print:
|
||||
LIGHT = REGULAR
|
||||
|
||||
init 1 python:
|
||||
|
||||
def size(n):
|
||||
"""
|
||||
Adjusts the font size if we're in large-print mode.
|
||||
"""
|
||||
|
||||
if persistent.large_print and n < 18:
|
||||
n = 18
|
||||
|
||||
return n
|
||||
|
||||
|
||||
init python:
|
||||
INDENT = 20
|
||||
HALF_INDENT = 10
|
||||
|
||||
SCROLLBAR_SIZE = 16
|
||||
|
||||
SEPARATOR = Frame("pattern.png", 0, 0, tile=True, ymaximum=5, yalign=1.0)
|
||||
SEPARATOR2 = Frame("pattern.png", 0, 0, tile=True, ymaximum=10, yalign=1.0)
|
||||
SEPARATOR = Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=1.0)
|
||||
SEPARATOR2 = Frame(PATTERN, 0, 0, tile=True, ymaximum=10, yalign=1.0)
|
||||
|
||||
SPACER_HEIGHT = 12
|
||||
SPACER = Null(height=SPACER_HEIGHT)
|
||||
@@ -16,233 +97,247 @@ init python:
|
||||
HALF_SPACER_HEIGHT = 6
|
||||
HALF_SPACER = Null(height=HALF_SPACER_HEIGHT)
|
||||
|
||||
# Colors.
|
||||
TEXT = "#545454"
|
||||
IDLE = "#42637b"
|
||||
LIGHT_IDLE = "#78a5c5"
|
||||
SCROLLBAR_IDLE = "#dfdfdf"
|
||||
HOVER = "#d86b45"
|
||||
WHITE = "#ffffff"
|
||||
DISABLED = "#808080"
|
||||
DANGER = "#d15353"
|
||||
|
||||
# FONTS/WEIGHTS
|
||||
LIGHT = "Roboto-Light.ttf"
|
||||
REGULAR = "Roboto-Regular.ttf"
|
||||
DARK = "Roboto-Medium.ttf"
|
||||
|
||||
# DIVIDING THE SCREEN
|
||||
ONETHIRD = 258
|
||||
TWOTHIRDS = 496
|
||||
ONEHALF = 377
|
||||
|
||||
|
||||
# Default style.
|
||||
style.l_default = Style(style.default)
|
||||
style.l_default.font = LIGHT
|
||||
style.l_default.color = TEXT
|
||||
style.l_default.idle_color = IDLE
|
||||
style.l_default.hover_color = HOVER
|
||||
style.l_default.size = 18
|
||||
|
||||
style.l_text = Style(style.l_default)
|
||||
def checkbox(full, color):
|
||||
if full:
|
||||
return im.Twocolor("images/checkbox_full.png", color, color, yalign=0.5)
|
||||
else:
|
||||
return im.Twocolor("images/checkbox_empty.png", color, color, yalign=0.5)
|
||||
|
||||
style.l_button = Style(style.l_default)
|
||||
style.l_button_text = Style(style.l_default)
|
||||
style.l_button_text.insensitive_color = DISABLED
|
||||
style.l_button_text.selected_font = REGULAR
|
||||
init 1:
|
||||
|
||||
# The default style.
|
||||
style l_default is default:
|
||||
font LIGHT
|
||||
color TEXT
|
||||
idle_color IDLE
|
||||
hover_color HOVER
|
||||
size size(18)
|
||||
|
||||
style l_text is l_default
|
||||
|
||||
style l_button is l_default
|
||||
style l_button_text is l_default:
|
||||
insensitive_color DISABLED
|
||||
selected_font REGULAR
|
||||
|
||||
# A small button, used at the bottom of the screen.
|
||||
style.l_link = Style(style.l_default)
|
||||
style.l_link_text = Style(style.l_default)
|
||||
style.l_link_text.size = 14
|
||||
style.l_link_text.font = LIGHT
|
||||
style l_link is l_default
|
||||
style l_link_text is l_default:
|
||||
size size(14)
|
||||
font LIGHT
|
||||
|
||||
# Action buttons on the bottom of the screen.
|
||||
style.l_right_button = Style(style.l_default)
|
||||
style.l_right_button.xalign = 1.0
|
||||
style.l_right_button.ypos = 600 - 128 + 12
|
||||
style.l_right_button.left_margin = 8 + INDENT
|
||||
style.l_right_button.right_margin = 10 + INDENT
|
||||
style.l_right_button_text = Style(style.l_default)
|
||||
style.l_right_button_text.size = 30
|
||||
style l_right_button is l_default:
|
||||
xalign 1.0
|
||||
ypos 600 - 128 + 12
|
||||
left_margin 8 + INDENT
|
||||
right_margin 10 + INDENT
|
||||
|
||||
style l_right_button_text is l_default:
|
||||
size size(30)
|
||||
|
||||
style l_left_button is l_right_button:
|
||||
xalign 0.0
|
||||
|
||||
style l_left_button_text is l_right_button_text
|
||||
|
||||
|
||||
# The root frame. This contains everything but the bottom navigation,
|
||||
# and buttons.
|
||||
style l_root is l_default:
|
||||
background BACKGROUND
|
||||
xpadding 10
|
||||
top_padding 64
|
||||
bottom_padding 128
|
||||
|
||||
style.l_left_button = Style(style.l_right_button)
|
||||
style.l_left_button.xalign = 0.0
|
||||
style.l_left_button_text = Style(style.l_right_button_text)
|
||||
|
||||
|
||||
# The root frame. This contains everything but the bottom navigation, back
|
||||
# button, and tooltip button.
|
||||
style.l_root = Style(style.l_default)
|
||||
style.l_root.background = "background.png"
|
||||
style.l_root.xpadding = 10
|
||||
style.l_root.top_padding = 64
|
||||
style.l_root.bottom_padding = 128
|
||||
|
||||
# An inner window.
|
||||
style.l_window = Style(style.l_default)
|
||||
style.l_window.background = Frame("window.png", 0, 0, tile=True)
|
||||
style.l_window.left_padding = 6
|
||||
style.l_window.xfill = True
|
||||
style.l_window.yfill = True
|
||||
|
||||
# Normal-sized labels.
|
||||
style.l_label = Style(style.l_default)
|
||||
style.l_label.xfill = True
|
||||
style.l_label.top_padding = 10
|
||||
style.l_label.bottom_padding = 8
|
||||
style.l_label.bottom_margin = 12
|
||||
style.l_label.background = SEPARATOR
|
||||
style.l_label_text = Style(style.l_default)
|
||||
style.l_label_text.size = 24
|
||||
style.l_label_text.xpos = INDENT
|
||||
style.l_label_text.yoffset = 6
|
||||
style l_window is l_default:
|
||||
background WINDOW
|
||||
left_padding 6
|
||||
xfill True
|
||||
yfill True
|
||||
|
||||
# Normal size labels.
|
||||
style l_label is l_default:
|
||||
xfill True
|
||||
top_padding 10
|
||||
bottom_padding 8
|
||||
bottom_margin 12
|
||||
background SEPARATOR
|
||||
|
||||
style l_label_text is l_default:
|
||||
size size(24)
|
||||
xpos INDENT
|
||||
yoffset 6
|
||||
|
||||
style l_label_small is l_default:
|
||||
xfill True
|
||||
bottom_padding 8
|
||||
bottom_margin HALF_SPACER_HEIGHT
|
||||
background SEPARATOR
|
||||
|
||||
# Small labels.
|
||||
style.l_label_small = Style(style.l_default)
|
||||
style.l_label_small.xfill = True
|
||||
style.l_label_small.bottom_padding = 8
|
||||
style.l_label_small.bottom_margin = HALF_SPACER_HEIGHT
|
||||
style.l_label_small.background = SEPARATOR
|
||||
style.l_label_small_text = Style(style.l_default)
|
||||
style.l_label_small_text.xpos = INDENT
|
||||
style.l_label_small_text.yoffset = 6
|
||||
style.l_label_small_text.size = 20
|
||||
|
||||
style l_label_small_text is l_default:
|
||||
xpos INDENT
|
||||
yoffset 6
|
||||
size size(20)
|
||||
|
||||
# Alternate labels. This nests inside an l_label, and gives a button
|
||||
# or label that's nested inside another label.
|
||||
style.l_alternate = Style(style.l_default)
|
||||
style.l_alternate.xalign = 1.0
|
||||
style.l_alternate.yalign = 1.0
|
||||
style.l_alternate.yoffset = 4
|
||||
style.l_alternate.right_margin = INDENT
|
||||
style.l_alternate_text = Style(style.l_default)
|
||||
style.l_alternate_text.size = 14
|
||||
style.l_alternate_text.font = LIGHT
|
||||
style.l_alternate_text.text_align = 1.0
|
||||
|
||||
style.l_small_button = Style(style.l_button)
|
||||
style.l_small_button_text = Style(style.l_button_text)
|
||||
style.l_small_button_text.size = 14
|
||||
style.l_small_text = Style(style.l_text)
|
||||
style.l_small_text.size = 14
|
||||
|
||||
|
||||
|
||||
style l_alternate is l_default:
|
||||
xalign 1.0
|
||||
yalign 1.0
|
||||
yoffset 4
|
||||
right_margin INDENT
|
||||
|
||||
style l_alternate_text is l_default:
|
||||
size size(14)
|
||||
font LIGHT
|
||||
text_align 1.0
|
||||
|
||||
style l_small_button is l_button
|
||||
|
||||
style l_small_button_text is l_button_text:
|
||||
size size(14)
|
||||
|
||||
style l_small_text is l_text:
|
||||
size size(14)
|
||||
|
||||
# Indents its contents.
|
||||
style.l_indent = Style(style.l_default)
|
||||
style.l_indent.left_margin = INDENT
|
||||
|
||||
# Indents its contents and pads them vertically.
|
||||
style.l_indent_margin = Style(style.l_indent)
|
||||
style.l_indent_margin.ymargin = 6
|
||||
|
||||
# List button.
|
||||
style.l_list = Style(style.l_default)
|
||||
style.l_list.left_padding = HALF_INDENT
|
||||
style.l_list.xfill = True
|
||||
style.l_list.selected_background = LIGHT_IDLE
|
||||
style.l_list.selected_hover_background = HOVER
|
||||
style.l_list_text = Style(style.l_default)
|
||||
style.l_list_text.idle_color = IDLE
|
||||
style.l_list_text.hover_color = HOVER
|
||||
style.l_list_text.selected_idle_color = WHITE
|
||||
style.l_list_text.selected_hover_color = WHITE
|
||||
style.l_list_text.insensitive_color = DISABLED
|
||||
style l_indent is l_default:
|
||||
left_margin INDENT
|
||||
|
||||
style.l_list2 = Style(style.l_list)
|
||||
style.l_list2.left_padding = HALF_INDENT + INDENT
|
||||
style.l_list2_text = Style(style.l_list_text)
|
||||
# Indents its contents and pads vertically.
|
||||
style l_indent_margin is l_indent:
|
||||
ymargin 6
|
||||
|
||||
# Lists.
|
||||
style l_list is l_default:
|
||||
left_padding HALF_INDENT
|
||||
xfill True
|
||||
selected_background REVERSE_IDLE
|
||||
selected_hover_background REVERSE_HOVER
|
||||
|
||||
style l_list_text is l_default:
|
||||
idle_color IDLE
|
||||
hover_color HOVER
|
||||
selected_idle_color REVERSE_TEXT
|
||||
selected_hover_color REVERSE_TEXT
|
||||
insensitive_color DISABLED
|
||||
|
||||
style l_list2 is l_list:
|
||||
left_padding (HALF_INDENT + INDENT)
|
||||
|
||||
style l_list2_text is l_list_text
|
||||
|
||||
# Scrollbar.
|
||||
style.l_vscrollbar = Style(style.l_default)
|
||||
style.l_vscrollbar.thumb = Fixed(
|
||||
Solid(SCROLLBAR_IDLE, xmaximum=8, xalign=0.5),
|
||||
Image("vscrollbar_center.png", xalign=0.5, yalign=0.5),
|
||||
xmaximum = SCROLLBAR_SIZE)
|
||||
style.l_vscrollbar.hover_thumb = Fixed(
|
||||
Solid(HOVER, xmaximum=8, xalign=0.5),
|
||||
Image("vscrollbar_center.png", xalign=0.5, yalign=0.5),
|
||||
xmaximum = SCROLLBAR_SIZE)
|
||||
style.l_vscrollbar.xmaximum = SCROLLBAR_SIZE
|
||||
style.l_vscrollbar.bar_vertical = True
|
||||
style.l_vscrollbar.bar_invert = True
|
||||
style.l_vscrollbar.unscrollable = "hide"
|
||||
|
||||
|
||||
style l_vscrollbar is l_default:
|
||||
thumb Fixed(
|
||||
Solid(SCROLLBAR_IDLE, xmaximum=8, xalign=0.5),
|
||||
Image("images/vscrollbar_center.png", xalign=0.5, yalign=0.5),
|
||||
xmaximum = SCROLLBAR_SIZE)
|
||||
hover_thumb Fixed(
|
||||
Solid(SCROLLBAR_HOVER, xmaximum=8, xalign=0.5),
|
||||
Image("images/vscrollbar_center.png", xalign=0.5, yalign=0.5),
|
||||
xmaximum = SCROLLBAR_SIZE)
|
||||
xmaximum SCROLLBAR_SIZE
|
||||
bar_vertical True
|
||||
bar_invert True
|
||||
unscrollable "hide"
|
||||
|
||||
# Information window.
|
||||
style.l_info_vbox = Style(style.vbox)
|
||||
style.l_info_vbox.yalign = 0.5
|
||||
style.l_info_vbox.xalign = 0.5
|
||||
style.l_info_vbox.xfill = True
|
||||
|
||||
style.l_info_frame = Style(style.l_default)
|
||||
style.l_info_frame.ypadding = 21
|
||||
style.l_info_frame.xfill = True
|
||||
style.l_info_frame.background = Fixed(
|
||||
"#f9f9f9",
|
||||
Frame("pattern.png", 0, 0, tile=True, ymaximum=5, yalign=0.0, yoffset=8),
|
||||
Frame("pattern.png", 0, 0, tile=True, ymaximum=5, yalign=1.0, yoffset=-8),
|
||||
)
|
||||
style.l_info_frame.yminimum = 180
|
||||
style.l_info_frame.ypos = 100
|
||||
|
||||
style.l_info_label = Style(style.l_default)
|
||||
style.l_info_label.xalign = 0.5
|
||||
style.l_info_label.ypos = 100
|
||||
style.l_info_label.yanchor = 1.0
|
||||
style.l_info_label.yoffset = 12
|
||||
style.l_info_label_text = Style(style.l_default)
|
||||
style.l_info_label_text.size = 36
|
||||
|
||||
style.l_info_text = Style(style.l_default)
|
||||
style.l_info_text.xalign = 0.5
|
||||
|
||||
style.l_info_button = Style(style.l_button)
|
||||
style.l_info_button.xalign = 0.5
|
||||
style.l_info_button_text = Style(style.l_button_text)
|
||||
style l_info_vbox is vbox:
|
||||
yalign 0.5
|
||||
xalign 0.5
|
||||
xfill True
|
||||
|
||||
# Code navigation
|
||||
style.l_navigation_button = Style(style.l_button)
|
||||
style.l_navigation_button.size_group = "navigation"
|
||||
style.l_navigation_button.right_margin = INDENT
|
||||
style.l_navigation_button.top_margin = 3
|
||||
style.l_navigation_button_text = Style(style.l_button_text)
|
||||
style.l_navigation_button_text.size = 14
|
||||
style.l_navigation_button_text.font = REGULAR
|
||||
style l_info_frame is l_default:
|
||||
ypadding 21
|
||||
xfill True
|
||||
background Fixed(
|
||||
INFO_WINDOW,
|
||||
Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=0.0, yoffset=8),
|
||||
Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=1.0, yoffset=-8),
|
||||
)
|
||||
yminimum 180
|
||||
ypos 75
|
||||
|
||||
style.l_navigation_text = Style(style.l_text)
|
||||
style.l_navigation_text.size = 12
|
||||
style.l_navigation_text.font = LIGHT
|
||||
style.l_navigation_text.color = TEXT
|
||||
style l_info_label is l_default:
|
||||
xalign 0.5
|
||||
ypos 75
|
||||
yanchor 1.0
|
||||
yoffset 12
|
||||
|
||||
# Check boxes
|
||||
style.l_checkbox = Style(style.l_button)
|
||||
style.l_checkbox.left_padding = INDENT
|
||||
style.l_checkbox.background = Image("checkbox_idle.png", yalign=0.5)
|
||||
style.l_checkbox.hover_background = Image("checkbox_hover.png", yalign=0.5)
|
||||
style.l_checkbox.selected_idle_background = Image("checkbox_selected_idle.png", yalign=0.5)
|
||||
style.l_checkbox.selected_hover_background = Image("checkbox_selected_hover.png", yalign=0.5)
|
||||
style.l_checkbox.insensitive_background = Image("checkbox_insensitive.png", yalign=0.5)
|
||||
style l_info_label_text is l_default:
|
||||
size size(36)
|
||||
|
||||
style.l_checkbox_text = Style(style.l_button_text)
|
||||
style.l_checkbox_text.selected_font = LIGHT
|
||||
|
||||
# A normal button that lines up with checkboxes.
|
||||
style.l_nonbox = Style(style.l_button)
|
||||
style.l_nonbox.xpadding = INDENT
|
||||
style.l_nonbox_text = Style(style.l_button_text)
|
||||
style.l_nonbox_text.selected_font = LIGHT
|
||||
|
||||
# A progress bar and its frame.
|
||||
style.l_progress_frame = Style(style.l_default)
|
||||
style.l_progress_frame.background = Frame("pattern.png", 0, 0, tile=True)
|
||||
style.l_progress_frame.ypadding = 5
|
||||
|
||||
style.l_progress_bar = Style(style.l_default)
|
||||
style.l_progress_bar.left_bar = LIGHT_IDLE
|
||||
style.l_progress_bar.right_bar = Null()
|
||||
style.l_progress_bar.ymaximum = 24
|
||||
style l_info_text is l_default:
|
||||
xalign 0.5
|
||||
|
||||
style l_info_button is l_button:
|
||||
xalign 0.5
|
||||
xmargin 50
|
||||
|
||||
style l_info_button_text is l_button_text:
|
||||
text_align 0.5
|
||||
layout "subtitle"
|
||||
|
||||
# Progress bar.
|
||||
style l_progress_frame is l_default:
|
||||
background Frame(PATTERN, 0, 0, tile=True)
|
||||
ypadding 5
|
||||
|
||||
style l_progress_bar is l_default:
|
||||
left_bar REVERSE_IDLE
|
||||
right_bar Null()
|
||||
ymaximum 24
|
||||
|
||||
# Navigation.
|
||||
style l_navigation_button is l_button:
|
||||
size_group "navigation"
|
||||
right_margin INDENT
|
||||
top_margin 3
|
||||
|
||||
style l_navigation_button_text is l_button_text:
|
||||
size size(14)
|
||||
font REGULAR
|
||||
|
||||
style l_navigation_text is l_text:
|
||||
size size(14)
|
||||
font LIGHT
|
||||
color TEXT
|
||||
|
||||
# Checkboxes.
|
||||
style l_checkbox is l_button:
|
||||
left_padding INDENT
|
||||
background checkbox(False, IDLE)
|
||||
hover_background checkbox(False, HOVER)
|
||||
selected_idle_background checkbox(True, IDLE)
|
||||
selected_hover_background checkbox(True, HOVER)
|
||||
insensitive_background checkbox(False, DISABLED)
|
||||
|
||||
style l_checkbox_text is l_button_text:
|
||||
selected_font LIGHT
|
||||
|
||||
# Lines up with a checkbox.
|
||||
style l_nonbox is l_button:
|
||||
xpadding INDENT
|
||||
|
||||
style l_nonbox_text is l_button_text:
|
||||
selected_font LIGHT
|
||||
|
||||
# Projects list.
|
||||
style l_projects is l_default:
|
||||
background PROJECTS_WINDOW
|
||||
|
||||
style hyperlink_text:
|
||||
size size(18)
|
||||
font LIGHT
|
||||
color IDLE
|
||||
hover_color HOVER
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
init python:
|
||||
|
||||
class FileTail(object):
|
||||
|
||||
def __init__(self, filename, lines=8):
|
||||
self.filename = filename
|
||||
self.text = ""
|
||||
self.lines = lines
|
||||
|
||||
def update(self):
|
||||
|
||||
try:
|
||||
with open(self.filename) as f:
|
||||
text = f.read()
|
||||
|
||||
try:
|
||||
text = renpy.fsdecode(text)
|
||||
except:
|
||||
text = text.decode("latin-1")
|
||||
|
||||
text = text.strip()
|
||||
text = text.split("\n")
|
||||
|
||||
newtext = [ ]
|
||||
for l in text:
|
||||
|
||||
if "\r" in l:
|
||||
_head, _sep, l = l.rpartition("\r")
|
||||
|
||||
while l:
|
||||
newtext.append(l[:100])
|
||||
l = l[100:]
|
||||
|
||||
text = newtext
|
||||
text = text[-self.lines:]
|
||||
text = "\n".join(text)
|
||||
|
||||
if text != self.text:
|
||||
self.text = text
|
||||
renpy.restart_interaction()
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
init python in theme_data:
|
||||
|
||||
@@ -9,18 +27,18 @@ init python in theme_data:
|
||||
|
||||
x = 0
|
||||
correct_section = False
|
||||
|
||||
|
||||
while x < len(lines):
|
||||
l = lines[x]
|
||||
|
||||
m = re.match(r'^screen\s+\w+\s*:\s*$', l)
|
||||
if m:
|
||||
correct_section = False
|
||||
|
||||
|
||||
m = re.match(r'^screen\s+file_picker\s*:\s*$', l)
|
||||
if m:
|
||||
correct_section = True
|
||||
|
||||
|
||||
if correct_section:
|
||||
m = re.match(r'^\s+\$\s*columns\s*=\s*(\d+)\s*$', l)
|
||||
if m:
|
||||
@@ -28,7 +46,7 @@ init python in theme_data:
|
||||
m = re.match(r'^\s+\$\s*rows\s*=\s*(\d+)\s*$', l)
|
||||
if m:
|
||||
l = l.replace(str(m.group(1)), str(file_picker_rows))
|
||||
|
||||
|
||||
lines[x] = l
|
||||
|
||||
x = x + 1
|
||||
@@ -37,7 +55,7 @@ init python in theme_data:
|
||||
|
||||
def roundrect_screen_ops(lines):
|
||||
return __PerformScreenOperations(lines)
|
||||
|
||||
|
||||
def awt_screen_ops(lines):
|
||||
return __PerformScreenOperations(lines, file_picker_rows=3)
|
||||
|
||||
@@ -49,12 +67,12 @@ init python in theme_data:
|
||||
|
||||
# The set of theme functions.
|
||||
THEME_FUNCTIONS = set()
|
||||
|
||||
|
||||
# theme name -> function name to call to munge screens.rpy as appropriate
|
||||
# for that theme.
|
||||
THEME_SCREEN_OPERATIONS = { }
|
||||
|
||||
# Color schemes that work (technically - some are eye-melting) with the
|
||||
|
||||
# Color schemes that work (technically - some are eye-melting) with the
|
||||
# roundrect-style themes.
|
||||
ROUNDRECT_SCHEMES = {
|
||||
'Basic Blue': {'disabled': '#404040',
|
||||
@@ -337,7 +355,7 @@ init python in theme_data:
|
||||
'widget_hover': '#b38698',
|
||||
'widget_selected': '#fffeed',
|
||||
'widget_text': '#ffffff'},
|
||||
|
||||
|
||||
'Watermelon': {'disabled': '#f9cdad',
|
||||
'disabled_text': '#fc9d9a',
|
||||
'frame': '#f9cdad',
|
||||
@@ -462,11 +480,11 @@ init python in theme_data:
|
||||
("Marker", "marker"),
|
||||
("Crayon", "crayon"),
|
||||
]
|
||||
|
||||
|
||||
ROUNDRECT_CODE = """theme.%(function)s(
|
||||
## Theme: %(theme)s
|
||||
## Color scheme: %(scheme)s
|
||||
|
||||
|
||||
## The color of an idle widget face.
|
||||
widget = "%(widget)s",
|
||||
|
||||
@@ -480,7 +498,7 @@ init python in theme_data:
|
||||
## example, the current value of a preference.)
|
||||
widget_selected = "%(widget_selected)s",
|
||||
|
||||
## The color of a disabled widget face.
|
||||
## The color of a disabled widget face.
|
||||
disabled = "%(disabled)s",
|
||||
|
||||
## The color of disabled widget text.
|
||||
@@ -508,9 +526,9 @@ init python in theme_data:
|
||||
|
||||
## And we're done with the theme. The theme will customize
|
||||
## various styles, so if we want to change them, we should
|
||||
## do so below.
|
||||
## do so below.
|
||||
)"""
|
||||
|
||||
|
||||
for theme, function in ROUNDRECT_VARIANTS:
|
||||
THEME[theme] = { }
|
||||
THEME_FUNCTIONS.add(function)
|
||||
@@ -521,13 +539,13 @@ init python in theme_data:
|
||||
subs["function"] = function
|
||||
subs["theme"] = theme
|
||||
subs["scheme"] = scheme
|
||||
|
||||
|
||||
THEME[theme][scheme] = ROUNDRECT_CODE % (subs)
|
||||
|
||||
AWT_CODE = """theme.a_white_tulip(
|
||||
## Theme: A White Tulip
|
||||
## Scheme %(scheme)s
|
||||
|
||||
|
||||
## The color of an idle widget face.
|
||||
widget = "%(widget)s",
|
||||
|
||||
@@ -538,7 +556,7 @@ init python in theme_data:
|
||||
## example, the current value of a preference.)
|
||||
widget_selected = "%(widget_selected)s",
|
||||
|
||||
## The color of a disabled widget face.
|
||||
## The color of a disabled widget face.
|
||||
disabled = "%(disabled)s",
|
||||
|
||||
## The color of a frame containing widgets.
|
||||
@@ -554,11 +572,16 @@ init python in theme_data:
|
||||
## should take up the full height and width of the screen.
|
||||
gm_root = "%(gm_root)s",
|
||||
|
||||
## The fonts used by this theme. The default fonts may not be
|
||||
## suitable for non-English languages.
|
||||
regular_font = "_theme_awt/Quicksand-Regular.ttf",
|
||||
bold_font = "_theme_awt/Quicksand-Bold.ttf",
|
||||
|
||||
## And we're done with the theme. The theme will customize
|
||||
## various styles, so if we want to change them, we should
|
||||
## do so below.
|
||||
## do so below.
|
||||
)"""
|
||||
|
||||
|
||||
THEME["A White Tulip"] = { }
|
||||
THEME_FUNCTIONS.add("a_white_tulip")
|
||||
THEME_SCREEN_OPERATIONS["A White Tulip"] = awt_screen_ops
|
||||
@@ -567,7 +590,7 @@ init python in theme_data:
|
||||
for scheme, colors in ROUNDRECT_SCHEMES.iteritems():
|
||||
subs = dict(colors)
|
||||
subs["scheme"] = scheme
|
||||
|
||||
|
||||
THEME["A White Tulip"][scheme] = AWT_CODE % (subs)
|
||||
|
||||
THEME["A White Tulip"]["A White Tulip"] = AWT_CODE % dict(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#@PydevCodeAnalysisIgnore
|
||||
# Copyright 2007 PyTom <pytom@bishoujo.us>
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2004-2014 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
@@ -20,27 +21,30 @@
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import renpy
|
||||
import pygame
|
||||
# This is used on Linux and Mac to prompt the user for the projects
|
||||
# directory.
|
||||
|
||||
import sys
|
||||
|
||||
# Python3 and Python2-style imports.
|
||||
try:
|
||||
import _renpy_font
|
||||
pygame.font = _renpy_font
|
||||
from tkinter import Tk
|
||||
from tkinter.filedialog import askdirectory
|
||||
except ImportError:
|
||||
from Tkinter import Tk
|
||||
from tkFileDialog import askdirectory
|
||||
|
||||
# Binary mode stdout for python3.
|
||||
try:
|
||||
sys.stdout = sys.stdout.buffer
|
||||
except:
|
||||
pass
|
||||
|
||||
def Font(filename, size):
|
||||
"""
|
||||
RPG: Extended to load fonts from the game directory.
|
||||
"""
|
||||
# Create the TK canvas.
|
||||
|
||||
if filename is None:
|
||||
filename = renpy.store.style.default.font #@UndefinedVariable
|
||||
|
||||
return pygame.font.Font(renpy.loader.transfn(filename), size)
|
||||
|
||||
def init():
|
||||
"""
|
||||
RPG: Does nothing.
|
||||
"""
|
||||
if __name__ == "__main__":
|
||||
root = Tk()
|
||||
root.withdraw()
|
||||
|
||||
result = askdirectory(initialdir=sys.argv[1], parent=root, title="Select Ren'Py Projects Directory")
|
||||
sys.stdout.write(result.encode("utf8"))
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/about.rpy:21
|
||||
old "[version!q]"
|
||||
new "[version!q]"
|
||||
|
||||
# game/about.rpy:25
|
||||
old "View license"
|
||||
new "عرض الرخصة"
|
||||
|
||||
# game/about.rpy:27
|
||||
old "Back"
|
||||
new "عودة"
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/add_file.rpy:7
|
||||
old "FILENAME"
|
||||
new "اسم الملف"
|
||||
|
||||
# game/add_file.rpy:7
|
||||
old "Enter the name of the script file to create."
|
||||
new "إختر اسم لملف الحوار الذي سيتم تكوينه"
|
||||
|
||||
# game/add_file.rpy:10
|
||||
old "The filename must have the .rpy extension."
|
||||
new "يجب ان ينتهي اسم الملف بالصيغة .rpy"
|
||||
|
||||
# game/add_file.rpy:18
|
||||
old "The file already exists."
|
||||
new "هذا الملف موجود مسبقاً"
|
||||
|
||||
# game/add_file.rpy:21
|
||||
old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
|
||||
new "رينباي يقوم بتشغيل الملفات المنتهية بـ .rpy تلقائياً. لكي تستعمل هذا الملف, اختر له تبويب وافتحه عبر ملف آخر."
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
# : Translation updated at 2013-11-17 23:18
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/android.rpy:12
|
||||
old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
|
||||
new "لتجهيز اللعبة للعمل على اجهزة اندرويد يمكنك تحميل الحزمة الخاصة بذلك {a=http://www.renpy.org/dl/android}here{/a}) و فك الضغط عنها, ثم نسخها إلى مجلد رينباي الرئيسي ثم إعادة فتح هذا المشغِّل."
|
||||
|
||||
# game/android.rpy:13
|
||||
old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
|
||||
new "حزمة الاندرويد RAPT موجوده, لكنك تحتاج لتنصيب Android SDK قبل ان تبدأ بتجهيز حزم للعمل على اندرويد. الرجاء اختيار تنصيب Android SDK لتستطيع ذلك."
|
||||
|
||||
# game/android.rpy:14
|
||||
old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
|
||||
new "حزمة اندرويد RAPT موجوده, لكن المفتاح لم يتم تجهيزه. الرجاء تكوين مفتاح جديد او استرجاع android.keystore"
|
||||
|
||||
# game/android.rpy:15
|
||||
old "The current project has not been configured. Use \"Configure\" to configure it before building."
|
||||
new "المشروع الحالي لم يتم تجهيز إعدادته. الرجاء اختيار \"Configure\" لتقوم بتجهيزها قبل بناء الحزمة."
|
||||
|
||||
# game/android.rpy:16
|
||||
old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
|
||||
new "قم باختيار زر \"Build\" لتقوم بتجهيز المشروع الحالي إلى حزمة قابلة للعمل على اندرويد. او قم بربط جهاز اندرويد و اختيار \"Build & Install\" ليتم تنصيبها مباشرة على الجهاز المطلوب."
|
||||
|
||||
# game/android.rpy:18
|
||||
old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
|
||||
new "يقوم بمحاكاة جهاز اندرويد هاتفي محمول. \n\n خاصية اللمس يتم محاكاتها عبر مؤشر الفأره, لكن فقط حين يكون زر الفأره مضغوطاً. زر الخروج يقوم باستدعاء نافذة القائمة الرئيسية, و PageUp هو زر العودة إلى الوراء."
|
||||
|
||||
# game/android.rpy:19
|
||||
old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
|
||||
new "يقوم بمحاكاة جهاز اندرويد تابلت. \n\n خاصية اللمس يتم محاكاتها عبر مؤشر الفأره, لكن فقط حين يكون زر الفأره مضغوطاً. زر الخروج يقوم باستدعاء نافذة القائمة الرئيسية, و PageUp هو زر العودة إلى الوراء"
|
||||
|
||||
# game/android.rpy:20
|
||||
old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
|
||||
new "يقوم بمحاكاة جهاز Ouya. \n\n يد التحكم تتم محاكاتها بأزرار الإتجاهات, زر الإدخال يحاكي select, زر الخروج يحاكي زر menu, و PageUp يحاكي زر العودة."
|
||||
|
||||
# game/android.rpy:22
|
||||
old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
|
||||
new "يقوم بتحميل و تنصيب Android SDK والحزم المساندة لها. يعطيك خيار تكوين المفاتيح المطلوبة لتتمكن من استعمال الحزمة."
|
||||
|
||||
# game/android.rpy:23
|
||||
old "Configures the package name, version, and other information about this project."
|
||||
new "يقوم بتجهيز إعدادات الحزمة, رقم النسخة, و معلومات أخرى تتعلق بهذا المشروع."
|
||||
|
||||
# game/android.rpy:24
|
||||
old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
|
||||
new "يفتح الملف الخاص بمعلومات مفتاح Google Play في محرر النصوص. \n\n هذه الخطوة غير مطلوبة إلا لو كان البرنامج يحتاج إحدى الحوم المساندة expansion APK. الرجاء الإطلاع على ملفات المساعدة للحصول على المزيد من المعلومات."
|
||||
|
||||
# game/android.rpy:25
|
||||
old "Builds the Android package."
|
||||
new "يقوم ببناء حزمة للأندرويد."
|
||||
|
||||
# game/android.rpy:26
|
||||
old "Builds the Android package, and installs it on an Android device connected to your computer."
|
||||
new "يقوم ببناء حزمة للأندرويد, ثم يقوم بتنصيبها على جهاز أندرويد المتصل بحاسوبك."
|
||||
|
||||
# game/android.rpy:142
|
||||
old "{a=%s}%s{/a}"
|
||||
new "{a=%s}%s{/a}"
|
||||
|
||||
# game/android.rpy:361
|
||||
old "Android: [project.current.name!q]"
|
||||
new "أندرويد: [project.current.name!q]"
|
||||
|
||||
# game/android.rpy:381
|
||||
old "Emulation:"
|
||||
new "محاكاة"
|
||||
|
||||
# game/android.rpy:389
|
||||
old "Phone"
|
||||
new "هاتف"
|
||||
|
||||
# game/android.rpy:393
|
||||
old "Tablet"
|
||||
new "تابلت/ لوحي"
|
||||
|
||||
# game/android.rpy:397
|
||||
old "Television / OUYA"
|
||||
new "تلفزيون / OUYA"
|
||||
|
||||
# game/android.rpy:409
|
||||
old "Build:"
|
||||
new ""
|
||||
|
||||
# game/android.rpy:417
|
||||
old "Install SDK & Create Keys"
|
||||
new "تنصيب SDK و اختلاق مفاتيح"
|
||||
|
||||
# game/android.rpy:421
|
||||
old "Configure"
|
||||
new "إعدادات"
|
||||
|
||||
# game/android.rpy:425
|
||||
old "Build Package"
|
||||
new "بناء الحزمة"
|
||||
|
||||
# game/android.rpy:429
|
||||
old "Build & Install"
|
||||
new "بناء و تنصيب"
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/android.rpy:30
|
||||
old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
|
||||
new "لبناء ملفات الأندرويد, الرجاء تحميل RAPT, ثم فك الضغط عن الملف ووضعه في مجلد رينباي. قد تحتاج لإعادة تشغيل رينباي ليعمل بشكل صحيح."
|
||||
|
||||
# game/android.rpy:31
|
||||
old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
|
||||
new "تحتاج لنسخة برمجية من جافا تعتمد الـ 32-بت لتستطيع إنشاء ملفات الأندرويد على نظام الوندوز. حزمة JDK تختلف عن JRE, قد تكون الجافا لديك موجوده لكنها تفتقد الـ JDK. \n\n الرجاء {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}تحميل و تنصيب JDK{/a} ثم إعادة تشغيل رينباي"
|
||||
|
||||
# game/android.rpy:39
|
||||
old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
|
||||
new "يحاول محاكاة نظام تلفزيوني للأندرويد مثل جهاز OUYA او Fire TV. \n\n يتم تخطيط الأزرار لعصا التحكم لتناسب ازرار جهاز التحكم عن بعد. Controller input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
|
||||
|
||||
# game/android.rpy:47
|
||||
old "Connects to an Android device running ADB in TCP/IP mode."
|
||||
new "يتصل بجهاز أندرويد يعمل على نظام ADB عن طريق TCP/IP mode"
|
||||
|
||||
# game/android.rpy:48
|
||||
old "Disconnects from an Android device running ADB in TCP/IP mode."
|
||||
new "يفصل الاتصال عن جهاز أندرويد يعمل على نظام ADB عن طريق TCP/IP mode"
|
||||
|
||||
# game/android.rpy:516
|
||||
old "Other:"
|
||||
new "آخر:"
|
||||
|
||||
# game/android.rpy:524
|
||||
old "Remote ADB Connect"
|
||||
new "الإتصال عن بعد عن طريق ADB"
|
||||
|
||||
# game/android.rpy:528
|
||||
old "Remote ADB Disconnect"
|
||||
new "قطع إتصال ADB عن بعد"
|
||||
|
||||
# game/android.rpy:561
|
||||
old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
|
||||
new "قبل ان تصتطيع إنشاء ملفات للأندرويد, عليك ان تقوم بتحميل ملفات RAPT الخاصة بتحويل ملفات رينباي للأندرويد. هل تريد ان تقوم بتحميل الحزمة الآن؟"
|
||||
|
||||
# game/android.rpy:608
|
||||
old "Remote ADB Address"
|
||||
new "عنوان ADB عن بعد"
|
||||
|
||||
# game/android.rpy:609
|
||||
old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
|
||||
new "الرجاء إدخال عنوان الأي بي ورقم المنفذ المطلوب للإتصال, على شكل \"192.168.1.143:5555\". الرجاء العودة لدليل المستخدم الخاص بجهازك لتعرف إن كان يدعم الإتصال عن بعد للـ ADB و إن كان قادراً على ذلك, ستجد العنوان و المنفذ المطلوبان."
|
||||
|
||||
# game/android.rpy:619
|
||||
old "Invalid remote ADB address"
|
||||
new "عنوان ِADB خاطيء"
|
||||
|
||||
# game/android.rpy:619
|
||||
old "The address must contain one exactly one ':'."
|
||||
new "العنوان يجب ان يحتوي على علامة ':' واحده فقط لا غير"
|
||||
|
||||
# game/android.rpy:623
|
||||
old "The host may not contain whitespace."
|
||||
new "الخادم يجب ان لا يحتوي على مساحات فارغة"
|
||||
|
||||
# game/android.rpy:629
|
||||
old "The port must be a number."
|
||||
new "يجب ان يكون العنوان مكون من أرقام فقط"
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/choose_theme.rpy:274
|
||||
old "Could not change the theme. Perhaps options.rpy was changed too much."
|
||||
new "لم يتمكن رينباي من تغيير المظهر, ربما ملف options.rpy قد تغير بشكل كبير"
|
||||
|
||||
# game/choose_theme.rpy:332
|
||||
old "Display"
|
||||
new "عرض"
|
||||
|
||||
# game/choose_theme.rpy:333
|
||||
old "Window"
|
||||
new "نافذة"
|
||||
|
||||
# game/choose_theme.rpy:334
|
||||
old "Fullscreen"
|
||||
new "ملء الشاشة"
|
||||
|
||||
# game/choose_theme.rpy:335
|
||||
old "Planetarium"
|
||||
new "Planetarium"
|
||||
|
||||
# game/choose_theme.rpy:342
|
||||
old "Sound Volume"
|
||||
new "مستوى الصوت"
|
||||
|
||||
# game/choose_theme.rpy:376
|
||||
old "Choose Theme"
|
||||
new "إختر المظهر"
|
||||
|
||||
# game/choose_theme.rpy:389
|
||||
old "Theme"
|
||||
new "المظهر"
|
||||
|
||||
# game/choose_theme.rpy:413
|
||||
old "Color Scheme"
|
||||
new "توليفة الألوان"
|
||||
|
||||
# game/choose_theme.rpy:444
|
||||
old "Continue"
|
||||
new "استمرار"
|
||||
|
||||
@@ -0,0 +1,528 @@
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00action_file.rpy:118
|
||||
old "%b %d, %H:%M"
|
||||
new "%b %d, %H:%M"
|
||||
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00gltest.rpy:50
|
||||
old "Graphics Acceleration"
|
||||
new "تسريع الرسومات"
|
||||
|
||||
# renpy/common/00gltest.rpy:54
|
||||
old "Automatically Choose"
|
||||
new "إختر بشكل اوتوماتيكي"
|
||||
|
||||
# renpy/common/00gltest.rpy:59
|
||||
old "Force Angle/DirectX Renderer"
|
||||
new "فرض استعمال محركات Angle/DirectX"
|
||||
|
||||
# renpy/common/00gltest.rpy:63
|
||||
old "Force OpenGL Renderer"
|
||||
new "فرض استعمال محركات OpenGL"
|
||||
|
||||
# renpy/common/00gltest.rpy:67
|
||||
old "Force Software Renderer"
|
||||
new "فرض استعمال المحركات البرمجية software renderer"
|
||||
|
||||
# renpy/common/00gltest.rpy:73
|
||||
old "Changes will take effect the next time this program is run."
|
||||
new "سيتم تفعيل التغييرات في المرة القادمة التي تفتح فيها البرنامج"
|
||||
|
||||
# renpy/common/00gltest.rpy:77
|
||||
old "Quit"
|
||||
new "خروج"
|
||||
|
||||
# renpy/common/00gltest.rpy:82
|
||||
old "Return"
|
||||
new "عودة"
|
||||
|
||||
# renpy/common/00gltest.rpy:112
|
||||
old "Performance Warning"
|
||||
new "تحذير عن الأداء"
|
||||
|
||||
# renpy/common/00gltest.rpy:117
|
||||
old "This computer is using software rendering."
|
||||
new "هذا الجهاز يستعمل software rendering"
|
||||
|
||||
# renpy/common/00gltest.rpy:119
|
||||
old "This computer is not using shaders."
|
||||
new "هذا الجهاز لا يستعمل shaders"
|
||||
|
||||
# renpy/common/00gltest.rpy:121
|
||||
old "This computer is displaying graphics slowly."
|
||||
new "هذا الجهاز يستعرض الرسوميات بشكل بطيء"
|
||||
|
||||
# renpy/common/00gltest.rpy:123
|
||||
old "This computer has a problem displaying graphics: [problem]."
|
||||
new "هذا الجهاز يواجه مشكلة في استعراض الرسوميات [problem]"
|
||||
|
||||
# renpy/common/00gltest.rpy:128
|
||||
old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
|
||||
new "محركات الرسوميات قد تكون قديمة او لا تعمل بشكل صحيح. قد يسبب ذلك بطء او اخطاء في الاستعراض, القيام بتحديث directX قد يساعد في حل المشكلة."
|
||||
|
||||
# renpy/common/00gltest.rpy:130
|
||||
old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
|
||||
new " محركات الرسوميات قد تكون قديمة او لا تعمل بشكل صحيح. قد يسبب ذلك بطء او اخطاء في الاستعراض."
|
||||
|
||||
# renpy/common/00gltest.rpy:135
|
||||
old "Update DirectX"
|
||||
new "تحديث DirectX"
|
||||
|
||||
# renpy/common/00gltest.rpy:141
|
||||
old "Continue, Show this warning again"
|
||||
new "استمرار, الرجاء عرض هذا التحذير في المرة الثادمة ايضاً"
|
||||
|
||||
# renpy/common/00gltest.rpy:145
|
||||
old "Continue, Don't show warning again"
|
||||
new "استمرار, لا تعرض هذا التحذير مرة اخرى"
|
||||
|
||||
# renpy/common/00gltest.rpy:171
|
||||
old "Updating DirectX."
|
||||
new "يتم تحديث DirectX"
|
||||
|
||||
# renpy/common/00gltest.rpy:175
|
||||
old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
|
||||
new "يتم الآن تنصيب DirectX, قد يبدأ ذلك بشكل مصغر في شريط المهام. الرجاء اتباع التعليمات لاكمال التنصيب."
|
||||
|
||||
# renpy/common/00gltest.rpy:179
|
||||
old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
|
||||
new "{b}ملاحظة:{/b} مايكروسوفت دايركت أكس يقوم تلقائياً بتنصيب شريط بينق Bing toolbar. إذا لم ترغب بذلك الرجاء القيام بإلغاء تحديد خانة الاختيار"
|
||||
|
||||
# renpy/common/00gltest.rpy:183
|
||||
old "When setup finishes, please click below to restart this program."
|
||||
new "حيثن ينتهي التنصيب, الرجاء الضغط ادناه لإعادة تشغيل البرنامج"
|
||||
|
||||
# renpy/common/00gltest.rpy:185
|
||||
old "Restart"
|
||||
new "إعادة تشغيل"
|
||||
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00keymap.rpy:167
|
||||
old "Saved screenshot as %s."
|
||||
new "تم حفظ الصورة كـ %s"
|
||||
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00layout.rpy:421
|
||||
old "Are you sure?"
|
||||
new "هل انت متأكد؟"
|
||||
|
||||
# renpy/common/00layout.rpy:422
|
||||
old "Are you sure you want to delete this save?"
|
||||
new "هل انت متأكد من رغبتك في حذف خانة الحفظ هذه؟"
|
||||
|
||||
# renpy/common/00layout.rpy:423
|
||||
old "Are you sure you want to overwrite your save?"
|
||||
new "هل انت متأكد من رغبتك في الحفظ على هذه الخانة؟"
|
||||
|
||||
# renpy/common/00layout.rpy:424
|
||||
old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
|
||||
new "الاسترجاع سيضيع كل ما فعلته منذ خانة الحفظ السابقة. \n هل انت متأكد من رغبتك في الاسترجاع إلى هذه النقطة؟"
|
||||
|
||||
# renpy/common/00layout.rpy:425
|
||||
old "Are you sure you want to quit?"
|
||||
new "هل انت متأكد من رغبتك في الخروج؟"
|
||||
|
||||
# renpy/common/00layout.rpy:426
|
||||
old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
|
||||
new "هل انت متأكد من رغبتك في العودة للقائمة الرئيسية؟ \n كل ما لم تقم بحفظة سيضيع."
|
||||
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00library.rpy:77
|
||||
old "Skip Mode"
|
||||
new "وضع التسريع"
|
||||
|
||||
# renpy/common/00library.rpy:80
|
||||
old "Fast Skip Mode"
|
||||
new "وضع التسريع السريع"
|
||||
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00updater.rpy:1258
|
||||
old "Updater"
|
||||
new "برنامج التحديث"
|
||||
|
||||
# renpy/common/00updater.rpy:1267
|
||||
old "This program is up to date."
|
||||
new "هذه النسخة هي الأحدث"
|
||||
|
||||
# renpy/common/00updater.rpy:1269
|
||||
old "[u.version] is available. Do you want to install it?"
|
||||
new "النسخة [u.version] متوفرة, هل ترغب في تنصيبها؟"
|
||||
|
||||
# renpy/common/00updater.rpy:1271
|
||||
old "Preparing to download the updates."
|
||||
new "يتم التجهيز لتحميل البرنامج من الانترنت"
|
||||
|
||||
# renpy/common/00updater.rpy:1273
|
||||
old "Downloading the updates."
|
||||
new "يتم تنزيل التحديثات"
|
||||
|
||||
# renpy/common/00updater.rpy:1275
|
||||
old "Unpacking the updates."
|
||||
new "يتم فك الضغط عن التحديثات"
|
||||
|
||||
# renpy/common/00updater.rpy:1279
|
||||
old "The updates have been installed. The program will restart."
|
||||
new "تم التحديث.. سيتم إعادة تشغيل البرنامج."
|
||||
|
||||
# renpy/common/00updater.rpy:1281
|
||||
old "The updates have been installed."
|
||||
new "تم التحديث."
|
||||
|
||||
# renpy/common/00updater.rpy:1283
|
||||
old "The updates were cancelled."
|
||||
new "تم إلغاء التحديث."
|
||||
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/_compat/gamemenu.rpym:180
|
||||
old "Empty Slot."
|
||||
new "خانة فارغة"
|
||||
|
||||
# renpy/common/_compat/gamemenu.rpym:337
|
||||
old "Previous"
|
||||
new "السابق"
|
||||
|
||||
# renpy/common/_compat/gamemenu.rpym:344
|
||||
old "Next"
|
||||
new "التالي"
|
||||
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/_compat/preferences.rpym:411
|
||||
old "Joystick Mapping"
|
||||
new "خيارات عصى التحكم"
|
||||
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/_errorhandling.rpym:408
|
||||
old "An exception has occurred."
|
||||
new "حصل استثناء"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:434
|
||||
old "Rollback"
|
||||
new "تراجع"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:436
|
||||
old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
|
||||
new "يقوم بالتراجع لنقطة سابقة لكي تستطيع اختيار شيء آخر"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:439
|
||||
old "Ignore"
|
||||
new "تجاهل"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:441
|
||||
old "Ignores the exception, allowing you to continue. This often leads to additional errors."
|
||||
new "يتجاهل الاستثناء مما يستمح لك بالاستمرار. قد يسبب هذا المزيد من الاخطاء."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:444
|
||||
old "Reload"
|
||||
new "إعادة المحاولة"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:446
|
||||
old "Reloads the game from disk, saving and restoring game state if possible."
|
||||
new "يعيد تشغيل اللعبة من القرص الصلب, مع محاولة استعمادة آخر نقطة وحفظها عند الإستطاعة."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:448
|
||||
old "Open Traceback"
|
||||
new "قراءة التقرير"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:450
|
||||
old "Opens the traceback.txt file in a text editor."
|
||||
new "يفتح تقرير الخطأ في برنامج الملفات النصية."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:456
|
||||
old "Quits the game."
|
||||
new "يخرج من اللعبة."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:483
|
||||
old "Parsing the script failed."
|
||||
new "حصل خطأ أثناء تشغيل النص."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:510
|
||||
old "Open Parse Errors"
|
||||
new "يفتح قائمة اخطاء التشغيل."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:512
|
||||
old "Opens the errors.txt file in a text editor."
|
||||
new "يفتح ملف errors.txt في برنامج الملفات النصية"
|
||||
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/_layout/classic_load_save.rpym:152
|
||||
old "a"
|
||||
new "a"
|
||||
|
||||
# renpy/common/_layout/classic_load_save.rpym:161
|
||||
old "q"
|
||||
new "q"
|
||||
|
||||
# : Translation updated at 2013-11-17 23:18
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00action_file.rpy:587
|
||||
old "Quick save complete."
|
||||
new "تم الحفظ السريع بنجاح"
|
||||
|
||||
# : Translation updated at 2013-11-17 23:18
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00gallery.rpy:521
|
||||
old "Image [index] of [count] locked."
|
||||
new "يوجد عدد صور [index] من أصل [count] مقفل"
|
||||
|
||||
# renpy/common/00gallery.rpy:539
|
||||
old "prev"
|
||||
new "السابق"
|
||||
|
||||
# renpy/common/00gallery.rpy:540
|
||||
old "next"
|
||||
new "التالي"
|
||||
|
||||
# renpy/common/00gallery.rpy:541
|
||||
old "slideshow"
|
||||
new "عرض الشرائح"
|
||||
|
||||
# renpy/common/00gallery.rpy:542
|
||||
old "return"
|
||||
new "العودة"
|
||||
|
||||
# : Translation updated at 2013-11-17 23:18
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00layout.rpy:427
|
||||
old "Are you sure you want to begin skipping?"
|
||||
new "هل أنت متأكد من رغبتك في البدء بالتسريع؟"
|
||||
|
||||
# renpy/common/00layout.rpy:428
|
||||
old "Are you sure you want to skip to the next choice?"
|
||||
new "هل انت متأكد من رغبتك في التسريع حتى الخيار التالي؟"
|
||||
|
||||
# renpy/common/00layout.rpy:429
|
||||
old "Are you sure you want to skip to unseen dialogue or the next choice?"
|
||||
new "هل انت متأكد من رغبتك في تسريع الخيارات و الحوار الذي لم يسبق لك قرائته؟"
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00console.rpy:179
|
||||
old "%(version)s console, originally by Shiz, C, and delta.\n"
|
||||
new ""
|
||||
|
||||
# renpy/common/00console.rpy:180
|
||||
old "Press <esc> to exit console. Type help for help.\n"
|
||||
new "إضغط زر الخروج لإغلاق لوحة التحكم, اكتب كلمة help للمساعدة"
|
||||
|
||||
# renpy/common/00console.rpy:184
|
||||
old "Ren'Py script enabled."
|
||||
new "لغة برمحة رينباي متاحه"
|
||||
|
||||
# renpy/common/00console.rpy:186
|
||||
old "Ren'Py script disabled."
|
||||
new "لغة برمجة رينباي غير متاحه"
|
||||
|
||||
# renpy/common/00console.rpy:392
|
||||
old "help: show this help"
|
||||
new "مساعده: عرض هذه المساعده"
|
||||
|
||||
# renpy/common/00console.rpy:397
|
||||
old "commands:\n"
|
||||
new "أوامر: \n"
|
||||
|
||||
# renpy/common/00console.rpy:407
|
||||
old " <renpy script statement>: run the statement\n"
|
||||
new "<renpy script statement>: عرض الأوامر\n"
|
||||
|
||||
# renpy/common/00console.rpy:409
|
||||
old " <python expression or statement>: run the expression or statement"
|
||||
new " <python expression or statement>: عرض التعبير او الأوامر"
|
||||
|
||||
# renpy/common/00console.rpy:417
|
||||
old "clear: clear the console history"
|
||||
new "clear: مسح تاريخ لوحة التحكم"
|
||||
|
||||
# renpy/common/00console.rpy:421
|
||||
old "exit: exit the console"
|
||||
new "exit: الخروج من لوحة التحكم"
|
||||
|
||||
# renpy/common/00console.rpy:429
|
||||
old "load <slot>: loads the game from slot"
|
||||
new "استرجاع <slot>: يقوم باسترجاع اللعب من نقطة الحفظ"
|
||||
|
||||
# renpy/common/00console.rpy:442
|
||||
old "save <slot>: saves the game in slot"
|
||||
new "حفظ <slot>: يقوم بحفظ اللعب في نقطة الحفظ"
|
||||
|
||||
# renpy/common/00console.rpy:453
|
||||
old "reload: reloads the game, refreshing the scripts"
|
||||
new "reload: يعيد تشغيل اللعبة مع عرض التغييرات في النص"
|
||||
|
||||
# renpy/common/00console.rpy:461
|
||||
old "watch <expression>: watch a python expression"
|
||||
new "مشاهده <expression>: يقوم بعرض تبيرات بايثون"
|
||||
|
||||
# renpy/common/00console.rpy:470
|
||||
old "unwatch <expression>: stop watching an expression"
|
||||
new "unwatch <expression>: يقوم بإيقاف تعبير بايثون"
|
||||
|
||||
# renpy/common/00console.rpy:478
|
||||
old "unwatchall: stop watching all expressions"
|
||||
new "unwatchall: يقوم بإيقاف كل تعبيرات بايثون"
|
||||
|
||||
# renpy/common/00console.rpy:484
|
||||
old "jump <label>: jumps to label"
|
||||
new "jump <label>: يقفز للعنوان"
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/00keymap.rpy:332
|
||||
old "Autoreload"
|
||||
new "إعادة التحميل تلقائياً"
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/_developer/developer.rpym:65
|
||||
old "Developer Menu"
|
||||
new "قائمة المبرمج"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:67
|
||||
old "Reload Game (Shift+R)"
|
||||
new "إعادة تشغيل اللعبة (Shift+R)"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:69
|
||||
old "Console (Shift+O)"
|
||||
new "لوحة التحكم (Shift+O)"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:71
|
||||
old "Variable Viewer"
|
||||
new "مستعرض الأوامر"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:73
|
||||
old "Theme Test"
|
||||
new "اختبار القوالب"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:75
|
||||
old "Image Location Picker"
|
||||
new "مكان الصور المطلوبة"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:77
|
||||
old "Filename List"
|
||||
new "قائمة اسماء الملفات"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:81
|
||||
old "Show Image Load Log"
|
||||
new "عرض قائمة الصور "
|
||||
|
||||
# renpy/common/_developer/developer.rpym:84
|
||||
old "Hide Image Load Log"
|
||||
new "إخفاء قائمة الصور"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:149
|
||||
old "No variables have changed since the game started."
|
||||
new "لم يتم تغيير اي من الأوامر منذ ان بدأت اللعبة"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:152
|
||||
old "Return to the developer menu"
|
||||
new "العودة للوحة المبرمج"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:272
|
||||
old "{b}Missing Images{/b}"
|
||||
new "{b}صور مفقودة{/b}"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:424
|
||||
old "Rectangle: %r"
|
||||
new "مثلث: %r"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:429
|
||||
old "Mouse position: %r"
|
||||
new "مكان المؤشر: %r"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:431
|
||||
old "Right-click or escape to quit."
|
||||
new "إضغط بالزر الايمن او إضغط زر الخروح للإغلاق"
|
||||
|
||||
# renpy/common/_developer/developer.rpym:482
|
||||
old "Done"
|
||||
new "تم"
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:43
|
||||
old "Displayable Inspector"
|
||||
new "اختبار المستعرضات"
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:49
|
||||
old "Nothing to inspect."
|
||||
new "لا يوجد شيء ليتم اختباره"
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:58
|
||||
old "Size"
|
||||
new "حجم"
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:63
|
||||
old "Style"
|
||||
new "مظهر"
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:123
|
||||
old "Inspecting Styles of [displayable_name!q]"
|
||||
new "يتم اختبار المظهر الخاص بـ [displayable_name!q]"
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:135
|
||||
old "displayable:"
|
||||
new "مستعرضات"
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:142
|
||||
old " (no properties affect the displayable)"
|
||||
new " (لا توجد اي مؤثرات على هذا المستعرض)"
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:144
|
||||
old " (default properties omitted)"
|
||||
new " (تم استبعاد تأثير المؤثرات القياسية)"
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:174
|
||||
old "<repr() failed>"
|
||||
new "<repr() failed>"
|
||||
|
||||
# Translation updated at 2014-09-30 23:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# renpy/common/_developer/inspector.rpym:80
|
||||
old "Location"
|
||||
new "الموقع"
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/distribute.rpy:333
|
||||
old "Nothing to do."
|
||||
new "لا شيء لإنجازه"
|
||||
|
||||
# game/distribute.rpy:337
|
||||
old "Scanning project files..."
|
||||
new "يتم فحص الملفات..."
|
||||
|
||||
# game/distribute.rpy:344
|
||||
old "Scanning Ren'Py files..."
|
||||
new "يتم فحص ملفات رينباي..."
|
||||
|
||||
# game/distribute.rpy:494
|
||||
old "Archiving files..."
|
||||
new "يتم أرشفة الملفات..."
|
||||
|
||||
# game/distribute.rpy:745
|
||||
old "Writing the [variant] [format] package."
|
||||
new "يتم كتابة ملفات [variant] [format]"
|
||||
|
||||
# game/distribute.rpy:758
|
||||
old "Making the [variant] update zsync file."
|
||||
new "Making the [variant] update zsync file."
|
||||
|
||||
# game/distribute.rpy:854
|
||||
old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
|
||||
new "تم انهاء {b}[complete]{/b} من عدد {b}[total]{/b} من الملفات."
|
||||
|
||||
# game/distribute.rpy:915
|
||||
old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
|
||||
new "تم الإنتهاء من تكوين رزمة البيانات لنشر اللعبة. بسبب اختلاف نظام الملفات في الأنظمة التشغيلية ماك و لينوكس, لا يمكن فك الضغط عن الرزمة الخاصة بتلك الأنظمة على نظام وندوز."
|
||||
|
||||
# : Translation updated at 2013-11-17 23:18
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/distribute.rpy:358
|
||||
old "No packages are selected, so there's nothing to do."
|
||||
new "لم يتم اختيار اي حزمة, لم يحصل اي شيء."
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/distribute.rpy:335
|
||||
old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
|
||||
new "فشل بناء ملفات النشر. build.directory_name يجب أن لا يحتوي على مساحات فارغة, فواصل, او فواصل منقوطة في إسم المجلد "
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/distribute_gui.rpy:139
|
||||
old "Build Distributions: [project.current.name!q]"
|
||||
new "تجميع الملفات تجهيزاً للنشر: [project.current.name!q]"
|
||||
|
||||
# game/distribute_gui.rpy:154
|
||||
old "Directory Name:"
|
||||
new "اسم المجلد:"
|
||||
|
||||
# game/distribute_gui.rpy:158
|
||||
old "Executable Name:"
|
||||
new "اسم الملف التشغيلي:"
|
||||
|
||||
# game/distribute_gui.rpy:167
|
||||
old "Actions:"
|
||||
new "الأوامر:"
|
||||
|
||||
# game/distribute_gui.rpy:175
|
||||
old "Edit options.rpy"
|
||||
new "تحرير options.rpy"
|
||||
|
||||
# game/distribute_gui.rpy:176
|
||||
old "Refresh"
|
||||
new "إعادة تحميل"
|
||||
|
||||
# game/distribute_gui.rpy:193
|
||||
old "Build Packages:"
|
||||
new "بناء الرزمة البيانية:"
|
||||
|
||||
# game/distribute_gui.rpy:208
|
||||
old "Build Updates"
|
||||
new "بناء تحديثات:"
|
||||
|
||||
# game/distribute_gui.rpy:212
|
||||
old "Build"
|
||||
new "بناء"
|
||||
|
||||
# game/distribute_gui.rpy:219
|
||||
old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
|
||||
new "تم ايجاد بعض الاخطاء في المشروع. الرجاء التأكد من خلو المشروع من الأخطاء قبل نشره بشكل نهائي."
|
||||
|
||||
# game/distribute_gui.rpy:236
|
||||
old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
|
||||
new "مشروعك يخلو من معلومات النشر, هل ترغب في إضافة هذه المعلومات في نهاية ملف options.rpy؟"
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/editor.rpy:120
|
||||
old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
|
||||
new "{b}نقترح.{/b} محرر نص له واجهة سهلة الاستعمال ويعين على كتابة النصوص البرمجية يفضل برنامج يحتوي على مدقق لغوي. Editraحالياً لا يدعم اللغات الأجنبية مثل اللغه الكورية و الصينية و اليابانية."
|
||||
|
||||
# game/editor.rpy:121
|
||||
old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
|
||||
new "{b}نقترح.{/b} محرر نص له واجهة سهلة الاستعمال ويعين على كتابة النصوص البرمجية يفضل برنامج يحتوي على مدقق لغوي. Editraحالياً لا يدعم اللغات الأجنبية مثل اللغه الكورية و الصينية و اليابانية. على نظام لينوكس, Editra يحتاج wxPython."
|
||||
|
||||
# game/editor.rpy:137
|
||||
old "The may have occured because wxPython is not installed on this system."
|
||||
new "قد يكون السبب ان wxPython غير موجود على هذا الجهاز."
|
||||
|
||||
# game/editor.rpy:144
|
||||
old "Up to 22 MB download required."
|
||||
new "مطلوب تحميل ملف بحجم 22 ميغا بايت."
|
||||
|
||||
# game/editor.rpy:157
|
||||
old "1.8 MB download required."
|
||||
new "مطلوب تحميل ملف بحجم 1.8 ميغا بايت."
|
||||
|
||||
# game/editor.rpy:158
|
||||
old "This may have occured because Java is not installed on this system."
|
||||
new "قد يكون السبب ان الجافا غير موجوده على هذا الجهاز."
|
||||
|
||||
# game/editor.rpy:327
|
||||
old "An exception occured while launching the text editor:\n[exception!q]"
|
||||
new "حصل استثناء اثناء فتح المحرر: \n[exception!q]"
|
||||
|
||||
# game/editor.rpy:378
|
||||
old "Select Editor"
|
||||
new "الرجاء اختيار المحرر"
|
||||
|
||||
# game/editor.rpy:393
|
||||
old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
|
||||
new "محرر النصوص هو برنامج يساعدك على تعديل ملفات رينباي البرمجية والحوار. هنا, يمكنك اختيار المحرر الذي سيستعلمه رينباي. إذا لم يكن لديك مسبقاً, سيتم تحميله و تنصيبه بشكل اوتوماتيكي."
|
||||
|
||||
# game/editor.rpy:415
|
||||
old "Cancel"
|
||||
new "إلغاء الامر"
|
||||
|
||||
# Translation updated at 2013-11-17 23:18
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/editor.rpy:137
|
||||
old "This may have occured because wxPython is not installed on this system."
|
||||
new "قد يكون سبب ذلك ان wxPython غير موجود في نظام التشغيل لديك"
|
||||
|
||||
# game/editor.rpy:155
|
||||
old "A mature editor that requires Java."
|
||||
new "محرر متخصص يستعمل لغة جافا"
|
||||
|
||||
# game/editor.rpy:164
|
||||
old "Invokes the editor your operating system has associated with .rpy files."
|
||||
new "يقوم بفتح البرنامج المسؤول عن تحرير ملفات .rpy في نظامك التشغيلي"
|
||||
|
||||
# game/editor.rpy:180
|
||||
old "Prevents Ren'Py from opening a text editor."
|
||||
new "يمنع رينباي من فتح اي محرر نصوص"
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/front_page.rpy:79
|
||||
old "+ Create New Project"
|
||||
new "+ إبدأ مشروعاً جديداً"
|
||||
|
||||
# game/front_page.rpy:90
|
||||
old "Launch Project"
|
||||
new "تشغيل المشروع"
|
||||
|
||||
# game/front_page.rpy:111
|
||||
old "Tutorial"
|
||||
new "الدليل العملي"
|
||||
|
||||
# game/front_page.rpy:112
|
||||
old "The Question"
|
||||
new "السؤال"
|
||||
|
||||
# game/front_page.rpy:128
|
||||
old "Active Project"
|
||||
new "المشروع الحالي"
|
||||
|
||||
# game/front_page.rpy:136
|
||||
old "Open Directory"
|
||||
new "فتح مجلد"
|
||||
|
||||
# game/front_page.rpy:141
|
||||
old "game"
|
||||
new "اللعبة"
|
||||
|
||||
# game/front_page.rpy:142
|
||||
old "base"
|
||||
new "المشروع كله"
|
||||
|
||||
# game/front_page.rpy:148
|
||||
old "Edit File"
|
||||
new "تحرير ملف"
|
||||
|
||||
# game/front_page.rpy:156
|
||||
old "All script files"
|
||||
new "جميع الملفات النصية"
|
||||
|
||||
# game/front_page.rpy:165
|
||||
old "Navigate Script"
|
||||
new "مهام إضافية"
|
||||
|
||||
# game/front_page.rpy:176
|
||||
old "Check Script (Lint)"
|
||||
new "فحص الملف (لينت)"
|
||||
|
||||
# game/front_page.rpy:177
|
||||
old "Change Theme"
|
||||
new "تغيير المظهر"
|
||||
|
||||
# game/front_page.rpy:178
|
||||
old "Delete Persistent"
|
||||
new "حذف الملفات المؤقتة"
|
||||
|
||||
# game/front_page.rpy:186
|
||||
old "Build Distributions"
|
||||
new "تجميع المشروع للنشر"
|
||||
|
||||
# game/front_page.rpy:188
|
||||
old "Generate Translations"
|
||||
new "تجهيز ملفات للترجمة"
|
||||
|
||||
# game/front_page.rpy:204
|
||||
old "Checking script for potential problems..."
|
||||
new "يتم فحص الملفات لأي اخطاء محتملة..."
|
||||
|
||||
# game/front_page.rpy:219
|
||||
old "Deleting persistent data..."
|
||||
new "يتم الآن حذف الملفات المؤقتة "
|
||||
|
||||
# : Translation updated at 2013-11-17 23:18
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/front_page.rpy:204
|
||||
old "Android"
|
||||
new "أندرويد"
|
||||
|
||||
# game/front_page.rpy:206
|
||||
old "Extract Dialogue"
|
||||
new "استخراج النص"
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/front_page.rpy:144
|
||||
old "[p.name!q] (template)"
|
||||
new "[p.name!q] (template)"
|
||||
|
||||
# Translation updated at 2014-09-30 23:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/front_page.rpy:35
|
||||
old "Open [text] directory."
|
||||
new "فتح المجلد [text]"
|
||||
|
||||
# game/front_page.rpy:150
|
||||
old "Select project [text]."
|
||||
new "اختر المشروع [text]"
|
||||
|
||||
# game/front_page.rpy:234
|
||||
old "Force Recompile"
|
||||
new "إعادة حزم الملفات"
|
||||
|
||||
# game/front_page.rpy:285
|
||||
old "Recompiling all rpy files into rpyc files..."
|
||||
new "يتم إعادة حزم الملفات من صيغة rpy إلى rpyc..."
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/interface.rpy:89
|
||||
old "Documentation"
|
||||
new "المستندات المرفقة"
|
||||
|
||||
# game/interface.rpy:90
|
||||
old "Ren'Py Website"
|
||||
new "موقع رينباي"
|
||||
|
||||
# game/interface.rpy:91
|
||||
old "Ren'Py Games List"
|
||||
new "قائمة ألعاب رينباي"
|
||||
|
||||
# game/interface.rpy:92
|
||||
old "About"
|
||||
new "معلومات"
|
||||
|
||||
# game/interface.rpy:99
|
||||
old "update"
|
||||
new "تحديث"
|
||||
|
||||
# game/interface.rpy:101
|
||||
old "preferences"
|
||||
new "خيارات"
|
||||
|
||||
# game/interface.rpy:102
|
||||
old "quit"
|
||||
new "خروج"
|
||||
|
||||
# game/interface.rpy:149
|
||||
old "Yes"
|
||||
new "نعم"
|
||||
|
||||
# game/interface.rpy:151
|
||||
old "No"
|
||||
new "لا"
|
||||
|
||||
# game/interface.rpy:181
|
||||
old "Due to package format limitations, non-ASCII file and directory names are not allowed."
|
||||
new "بسبب محدودية التجميع, الاحرف الغير لاتينيه غير مسموح بها في اسم الملف او المجلدات"
|
||||
|
||||
# game/interface.rpy:183
|
||||
old "[title]"
|
||||
new "[title]"
|
||||
|
||||
# game/interface.rpy:248
|
||||
old "ERROR"
|
||||
new "خطأ"
|
||||
|
||||
# game/interface.rpy:280
|
||||
old "While [what!q], an error occured:"
|
||||
new "حصل خطأ أثناء [what!q]"
|
||||
|
||||
# game/interface.rpy:281
|
||||
old "[exception!q]"
|
||||
new "[exception!q]"
|
||||
|
||||
# game/interface.rpy:298
|
||||
old "Text input may not contain the {{ or [[ characters."
|
||||
new "لا يمكن استعمال الرمزان {{ و ]] هنا"
|
||||
|
||||
# game/interface.rpy:303
|
||||
old "File and directory names may not contain / or \\."
|
||||
new "غير مسموح ان يحتوي اسم الملف او المجلد على الرمزان / أو \\"
|
||||
|
||||
# game/interface.rpy:309
|
||||
old "File and directory names must consist of ASCII characters."
|
||||
new "اسم الملف و المجلدات التي تحتويه يجب ان تكون مكتوبة بأحرف ASCII "
|
||||
|
||||
# game/interface.rpy:330
|
||||
old "INFORMATION"
|
||||
new "معلومات"
|
||||
|
||||
# game/interface.rpy:373
|
||||
old "PROCESSING"
|
||||
new "يتم إجراء العمليات"
|
||||
|
||||
# game/interface.rpy:390
|
||||
old "QUESTION"
|
||||
new "سؤال"
|
||||
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/interface.rpy:451
|
||||
old "CHOICE"
|
||||
new "إختيار"
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/navigation.rpy:150
|
||||
old "Navigate: [project.current.name]"
|
||||
new "الذهاب إلى: [project.current.name]"
|
||||
|
||||
# game/navigation.rpy:159
|
||||
old "Order: "
|
||||
new "الترتيب:"
|
||||
|
||||
# game/navigation.rpy:160
|
||||
old "alphabetical"
|
||||
new "أبجدي"
|
||||
|
||||
# game/navigation.rpy:162
|
||||
old "by-file"
|
||||
new "ملف ملف"
|
||||
|
||||
# game/navigation.rpy:164
|
||||
old "natural"
|
||||
new "طبيعي"
|
||||
|
||||
# game/navigation.rpy:168
|
||||
old "refresh"
|
||||
new "إعادة تحميل"
|
||||
|
||||
# game/navigation.rpy:176
|
||||
old "Category:"
|
||||
new "فئة:"
|
||||
|
||||
# game/navigation.rpy:178
|
||||
old "files"
|
||||
new "ملفات"
|
||||
|
||||
# game/navigation.rpy:179
|
||||
old "labels"
|
||||
new "وسم"
|
||||
|
||||
# game/navigation.rpy:180
|
||||
old "defines"
|
||||
new "تحديد"
|
||||
|
||||
# game/navigation.rpy:181
|
||||
old "transforms"
|
||||
new "التحول"
|
||||
|
||||
# game/navigation.rpy:182
|
||||
old "screens"
|
||||
new "النوافذ"
|
||||
|
||||
# game/navigation.rpy:183
|
||||
old "callables"
|
||||
new "ما يمكن استجلابه"
|
||||
|
||||
# game/navigation.rpy:184
|
||||
old "TODOs"
|
||||
new "TODOs"
|
||||
|
||||
# game/navigation.rpy:223
|
||||
old "+ Add script file"
|
||||
new "+إضافة ملف نص"
|
||||
|
||||
# game/navigation.rpy:231
|
||||
old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
|
||||
new "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
|
||||
|
||||
# game/navigation.rpy:238
|
||||
old "The list of names is empty."
|
||||
new "قائمة الأسماء فارغة"
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/new_project.rpy:22
|
||||
old "Choose Project Template"
|
||||
new "الرجاء اختيار تصميم المظهر للمشروع"
|
||||
|
||||
# game/new_project.rpy:40
|
||||
old "Please select a template to use for your new project. Ren'Py ships with a default template that creates an English-language game with standard screens."
|
||||
new "الرجاء اختيار التصميم الذي ترغبه لمشروعك الجديد. رينباي يأتي بعدة تصاميم قياسية يمكنك التعديل عليها لاحقاً."
|
||||
|
||||
# game/new_project.rpy:55
|
||||
old "PROJECT NAME"
|
||||
new "اسم المشروع"
|
||||
|
||||
# game/new_project.rpy:56
|
||||
old "Please enter the name of your project:"
|
||||
new "الرجاء اختيار اسم لمشروعك الجديد"
|
||||
|
||||
# game/new_project.rpy:62
|
||||
old "The project name may not be empty."
|
||||
new "لا يمكن ان يكون اسم المشروع فارغاً"
|
||||
|
||||
# game/new_project.rpy:67
|
||||
old "[project_name!q] already exists. Please choose a different project name."
|
||||
new "الاسم [project_name!q] يوجد مسبقاً, الرجاء اختيار اسم مختلف."
|
||||
|
||||
# game/new_project.rpy:70
|
||||
old "[project_dir!q] already exists. Please choose a different project name."
|
||||
new "[project_dir!q] يوجد مسبقاً, الرجاء اختيار اسم مختلف."
|
||||
|
||||
# : Translation updated at 2013-11-17 23:18
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/new_project.rpy:40
|
||||
old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
|
||||
new "الرجاء اختيار القالب المطلوب للمشروع الجديد. هذه القوالب تقوم بتجهيز اتجاه النص و اللغه المستخدمة في الواجهة لتسهل عملية البدء. إذا لم تكن لغتك مدعومة الرجاء اختيار اللغة الانجليزية."
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/new_project.rpy:71
|
||||
old "The projects directory could not be set. Giving up."
|
||||
new "لم يتم تحديد مجلد المشاريع, سيتم الإلغاء"
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/preferences.rpy:40
|
||||
old "Launcher Preferences"
|
||||
new "خيارات برنامج التشغيل"
|
||||
|
||||
# game/preferences.rpy:61
|
||||
old "Projects Directory:"
|
||||
new "دليل المشاريع:"
|
||||
|
||||
# game/preferences.rpy:68
|
||||
old "[persistent.projects_directory!q]"
|
||||
new "[persistent.projects_directory!q]"
|
||||
|
||||
# game/preferences.rpy:70
|
||||
old "Not Set"
|
||||
new "غير محدد"
|
||||
|
||||
# game/preferences.rpy:84
|
||||
old "Text Editor:"
|
||||
new "محرر الملفات النصية:"
|
||||
|
||||
# game/preferences.rpy:106
|
||||
old "Update Channel:"
|
||||
new "مصدر التحديثات:"
|
||||
|
||||
# game/preferences.rpy:126
|
||||
old "Navigation Options:"
|
||||
new "خيارات استعراض المجلدات"
|
||||
|
||||
# game/preferences.rpy:130
|
||||
old "Include private names"
|
||||
new "تضمين الأسماء الخاصة"
|
||||
|
||||
# game/preferences.rpy:131
|
||||
old "Include library names"
|
||||
new "تضمين اسماء المكتبات"
|
||||
|
||||
# game/preferences.rpy:141
|
||||
old "Launcher Options:"
|
||||
new "خيارات برنامج التشغيل:"
|
||||
|
||||
# game/preferences.rpy:145
|
||||
old "Hardware rendering"
|
||||
new "الإستعراض بواسطة قطع الجهاز الداخلية"
|
||||
|
||||
# game/preferences.rpy:148
|
||||
old "Console output"
|
||||
new "الإستعراض بواسطة البرمجيات المتوفرة"
|
||||
|
||||
# game/preferences.rpy:169
|
||||
old "Open launcher project"
|
||||
new "فتح الواجهة التشغيلية كمشروع"
|
||||
|
||||
# game/preferences.rpy:183
|
||||
old "Language:"
|
||||
new "اللغة:"
|
||||
|
||||
# Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/preferences.rpy:164
|
||||
old "Show templates"
|
||||
new "عرض القوالب"
|
||||
|
||||
# Translation updated at 2014-09-30 23:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/preferences.rpy:91
|
||||
old "Projects directory: [text]"
|
||||
new "مجلد المشاريع [text]"
|
||||
|
||||
# game/preferences.rpy:114
|
||||
old "Text editor: [text]"
|
||||
new "محرر النصوص [text]"
|
||||
|
||||
# game/preferences.rpy:171
|
||||
old "Large fonts"
|
||||
new "خط كبير"
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/project.rpy:196
|
||||
old "Ren'Py is scanning the project..."
|
||||
new "رينباي يقوم بفحص المشروع"
|
||||
|
||||
# game/project.rpy:485
|
||||
old "PROJECTS DIRECTORY"
|
||||
new "سياق مجلدات المشاريع"
|
||||
|
||||
# game/project.rpy:485
|
||||
old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
|
||||
new "الرجاء اختيار نسق المشاريع من الصفحة الخاصة بذلك. \n{b}قد تكون النافذة ظهرت خلف هذه النافذة.{/b}"
|
||||
|
||||
# game/project.rpy:485
|
||||
old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
|
||||
new "سيقوم البرنامج بفحص المجلد هذا لإيجاد المشاريع السابقة, أو ليضع المشاريع الجديده فيه, و ايضاً لوضع المشاريع المنتهيه عند تجهيزها للنشر."
|
||||
|
||||
# game/project.rpy:525
|
||||
old "Ren'Py was unable to run python with tkinter to choose the projects directory."
|
||||
new "رينباي لم يستطع تشغيل برمجيات بايثون للبحث عن مجلد المشاريع."
|
||||
|
||||
# game/project.rpy:529
|
||||
old "Ren'Py has set the projects directory to:"
|
||||
new "رينباي قام بتحديد مجلد المشاريع إلى المكان التالي:"
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/project.rpy:48
|
||||
old "After making changes to the script, press shift+R to reload your game."
|
||||
new "عند إجراء أي تغييرات في ملف الحوار, يمكنك ضغط shift+R لترى التغييرات داخل اللعبة"
|
||||
|
||||
# game/project.rpy:49
|
||||
old "Press shift+O (the letter) to access the console."
|
||||
new "إضغط shift+O للدخول على لوحة التحكم"
|
||||
|
||||
# game/project.rpy:50
|
||||
old "Press shift+D to access the developer menu."
|
||||
new "إضغط shift+D للدخول على لوحة تحكم المبرمج"
|
||||
|
||||
# game/project.rpy:219
|
||||
old "Launching the project failed."
|
||||
new "لم تنجح محاولة إقلاع المشروع"
|
||||
|
||||
# game/project.rpy:219
|
||||
old "Please ensure that your project launches normally before running this command."
|
||||
new "الرجاء التأكد من سلامة إقلاع المشروع قبل تشغيل هذا الأمر البرمجي"
|
||||
|
||||
# game/project.rpy:516
|
||||
old "Launching"
|
||||
new "جاري الإقلاع"
|
||||
|
||||
# game/project.rpy:585
|
||||
old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
|
||||
new "رينباي لم يتمكن من تشغيل بايثون مع tkinter لكي يختار مجلد المشاريع, الرجاء تنصيب Python-tk او tkinter"
|
||||
|
||||
# Translation updated at 2014-09-30 23:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/project.rpy:47
|
||||
old "Have you backed up your projects recently?"
|
||||
new "هل قمت بعمل نسخة احتياطية من مشاريعك مؤخراً؟"
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
translate arabic python:
|
||||
al = "DejaVuSans.ttf"
|
||||
style.l_default.font = al
|
||||
style.l_default.size = 16
|
||||
style.l_button_text.selected_font = al
|
||||
style.l_button_text.selected_bold = True
|
||||
style.l_link_text.font = al
|
||||
style.l_alternate_text.font = al
|
||||
style.l_navigation_button_text.font = al
|
||||
style.l_navigation_text.font = al
|
||||
style.l_navigation_text.bold = True
|
||||
style.l_checkbox_text.selected_font = al
|
||||
style.l_nonbox_text.selected_font = al
|
||||
style.hyperlink_text.font = al
|
||||
make_style_backup()
|
||||
|
||||
config.rtl = True
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/translations.rpy:10
|
||||
old "Create or Update Translations"
|
||||
new "صنع او تحديث الترجمات"
|
||||
|
||||
# game/translations.rpy:10
|
||||
old "Please enter the name of the language for which you want to create or update translations."
|
||||
new "الرجاء كتابة اسم اللغة التي ستقوم بالترجمة إليها و الضغط على زر انتر"
|
||||
|
||||
# game/translations.rpy:15
|
||||
old "The language name can not be the empty string."
|
||||
new "لا يمكن ان يكون اسم اللغة فارغاً"
|
||||
|
||||
# game/translations.rpy:26
|
||||
old "Ren'Py is generating translations...."
|
||||
new "يقوم رينباي بتصنيع ملفات الترجمة..."
|
||||
|
||||
# game/translations.rpy:30
|
||||
old "Ren'Py has finished generating [language] translations."
|
||||
new "انتهى رينباي من صناعة ملفات الترجمة إلى [language]"
|
||||
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/translations.rpy:44
|
||||
old "What format would you like for the extracted dialogue?"
|
||||
new "ما هي الصيغة التي تريدها للنص المستخرج؟"
|
||||
|
||||
# game/translations.rpy:56
|
||||
old "Ren'Py is extracting dialogue...."
|
||||
new "رينباي يقوم باستخراج الحوار إلى ملف نص"
|
||||
|
||||
# game/translations.rpy:60
|
||||
old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
|
||||
new "رينباي انتهى من استخراج الحوار. الحوار المستخرج يوجد الآن في [format] في المجلد الرئيسي"
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
# : Translation updated at 2013-04-30 07:54
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/updater.rpy:54
|
||||
old "Select Update Channel"
|
||||
new "الرجاء اختيار طريقة التحديث"
|
||||
|
||||
# game/updater.rpy:65
|
||||
old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
|
||||
new "طريقة التحديث تحدد لبرنامج رينباي اي المواقع يستخدم لإيجاد النسخ الجديدة. الرجاء اختيار الطريقة التي تناسبك."
|
||||
|
||||
# game/updater.rpy:70
|
||||
old "Release"
|
||||
new "نسخة مكتملة"
|
||||
|
||||
# game/updater.rpy:76
|
||||
old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
|
||||
new "{b}موصى به.{/b} نسخة رينباي التي يفضل استعمالها مع كل الالعاب الجديدة."
|
||||
|
||||
# game/updater.rpy:81
|
||||
old "Prerelease"
|
||||
new "نسخة مبدأية"
|
||||
|
||||
# game/updater.rpy:87
|
||||
old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
|
||||
new "عينة من نسخة رينباي القادمة تسمح لك بتجربة الإضافات الجديدة. لا ننصح باستعمالها لصناعة ألعاب معدة للنشر."
|
||||
|
||||
# game/updater.rpy:93
|
||||
old "Experimental"
|
||||
new "نسخة تجريبية"
|
||||
|
||||
# game/updater.rpy:99
|
||||
old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
|
||||
new "النسخ التجريبية من رينباي. الأفضل ألا تستعمل هذه النسخ إلا لو طلب منك ذلك احد مبرمجي رينباي"
|
||||
|
||||
# game/updater.rpy:119
|
||||
old "An error has occured:"
|
||||
new "حصل خطأ:"
|
||||
|
||||
# game/updater.rpy:121
|
||||
old "Checking for updates."
|
||||
new "يتم البحث عن تحديثات."
|
||||
|
||||
# game/updater.rpy:123
|
||||
old "Ren'Py is up to date."
|
||||
new "نسخة رينباي التي لديك هي الأحدث."
|
||||
|
||||
# game/updater.rpy:125
|
||||
old "[u.version] is now available. Do you want to install it?"
|
||||
new "النسخة [u.version] متوفرة, هل ترغب في تنصيبها؟"
|
||||
|
||||
# game/updater.rpy:127
|
||||
old "Preparing to download the update."
|
||||
new "يتم التجهيز لتنزيل التحديث."
|
||||
|
||||
# game/updater.rpy:129
|
||||
old "Downloading the update."
|
||||
new "يتم تنزيل التحديث."
|
||||
|
||||
# game/updater.rpy:131
|
||||
old "Unpacking the update."
|
||||
new "يتم فك الضغط عن التحديث."
|
||||
|
||||
# game/updater.rpy:133
|
||||
old "Finishing up."
|
||||
new "اللمسات النهائية."
|
||||
|
||||
# game/updater.rpy:135
|
||||
old "The update has been installed. Ren'Py will restart."
|
||||
new "تم تنصيب التحديثات بنجاح, سيتم إعادة تشغيل رينباي الآن."
|
||||
|
||||
# game/updater.rpy:137
|
||||
old "The update has been installed."
|
||||
new "تم تنصيب التحديثات."
|
||||
|
||||
# game/updater.rpy:139
|
||||
old "The update was cancelled."
|
||||
new "تم إلغاء التحديث."
|
||||
|
||||
# game/updater.rpy:156
|
||||
old "Ren'Py Update"
|
||||
new "تحديثات رينباي."
|
||||
|
||||
# game/updater.rpy:162
|
||||
old "Proceed"
|
||||
new "استمرار."
|
||||
|
||||
# : Translation updated at 2014-04-17 13:01
|
||||
|
||||
translate arabic strings:
|
||||
|
||||
# game/updater.rpy:129
|
||||
old "Nightly"
|
||||
new "مسائي"
|
||||
|
||||
# game/updater.rpy:135
|
||||
old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
|
||||
new "أحدث نسخة طازجة من رينباي التجريبي, قد يحتوي على آخر مستجدات رينباي و قد لا يعمل مطلقاً"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
translate french strings:
|
||||
|
||||
# game/about.rpy:21
|
||||
old "[version!q]"
|
||||
new "[version!q]"
|
||||
|
||||
# game/about.rpy:25
|
||||
old "View license"
|
||||
new "Voir la licence"
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
translate french strings:
|
||||
|
||||
# game/add_file.rpy:7
|
||||
old "FILENAME"
|
||||
new "NOM DU FICHIER"
|
||||
|
||||
# game/add_file.rpy:7
|
||||
old "Enter the name of the script file to create."
|
||||
new "Entrez le nom du fichier de script à créer."
|
||||
|
||||
# game/add_file.rpy:10
|
||||
old "The filename must have the .rpy extension."
|
||||
new "Le fichier doit avoir l'extension .rpy."
|
||||
|
||||
# game/add_file.rpy:18
|
||||
old "The file already exists."
|
||||
new "Le fichier éxiste déjà."
|
||||
|
||||
# game/add_file.rpy:21
|
||||
old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
|
||||
new "Ren'Py charge automatiquement tous les fichiers de script finissant par .rpy. Pour utiliser ce ficher\n#, définissez un label et faites un «jump» vers lui depuis un autre fichier.\n"
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
translate french strings:
|
||||
|
||||
# game/android.rpy:12
|
||||
old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
|
||||
new "Pour construire les paquets Android, téléchargez RAPT (depuis {a=http://www.renpy.org/dl/android}here{/a}), dézippé le, et placez le dans le répertoire de Ren'Py. Puis, redémarrez Ren'Py."
|
||||
|
||||
# game/android.rpy:13
|
||||
old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
|
||||
new "RAPT a été installé, mais vous devez installer le kit de développement Android pour pouvoir construire les paquets Android. Choisissez \"installer le kit de développement et créer les clés\" pour cela"
|
||||
|
||||
# game/android.rpy:14
|
||||
old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
|
||||
new "RAPT a été installé, mais aucune clé n'a été configurée. Créez une nouvelle clé, ou restaurez android.keystore."
|
||||
|
||||
# game/android.rpy:15
|
||||
old "The current project has not been configured. Use \"Configure\" to configure it before building."
|
||||
new "Le projet courant n'a pas été configuré. Choisissez \"Configurer\' pour effectuer la configuration."
|
||||
|
||||
# game/android.rpy:16
|
||||
old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
|
||||
new "Choisissez \"Construire\" pour construire le projet courant, ou connecté un appareil Android et choisissez \"Construire et Installer\" pour l'installer sur l'appareil."
|
||||
|
||||
# game/android.rpy:18
|
||||
old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
|
||||
new "Tentative d'émulation d'un téléphone Android.\n\nLe touché est émulé via la souris, mails uniquement lorsque le bouton est pressé. La barre d'espace correspond au bouton menu, et la touche PageUp correspond au bouton retour."
|
||||
|
||||
# game/android.rpy:19
|
||||
old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
|
||||
new "Tentative d'émulation d'une tablette Android.\n\nLe touché est émulé via la souris, mails uniquement lorsque le bouton est pressé. La barre d'espace correspond au bouton menu, et la touche PageUp correspond au bouton retour."
|
||||
|
||||
# game/android.rpy:20
|
||||
old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
|
||||
new "Tentative d'émulation d'une console OUYA.\n\nLe pad est émulé via les flèches du clavier. La touche Entrée correspond au bouton select, la barre d'espace au bouton menu, et la touche PageUp correspond au bouton retour."
|
||||
|
||||
# game/android.rpy:22
|
||||
old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
|
||||
new "Télécharge et installe le kit de développement Android et les paquets supportés. Optionnellement, génère les clés requises pour signer le paquet."
|
||||
|
||||
# game/android.rpy:23
|
||||
old "Configures the package name, version, and other information about this project."
|
||||
new "Configure le nom du packet, sa version et d'autres informations à propos de ce projet."
|
||||
|
||||
# game/android.rpy:24
|
||||
old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
|
||||
new "Ouvre le fichier contenant les clés Google Play dans l'éditeur.\n\nCela est nécessaire uniquement si l'application utilise une expansion APK. Référez-vous à la documentation pour plus d'informations."
|
||||
|
||||
# game/android.rpy:25
|
||||
old "Builds the Android package."
|
||||
new "Construire le paquet Android."
|
||||
|
||||
# game/android.rpy:26
|
||||
old "Builds the Android package, and installs it on an Android device connected to your computer."
|
||||
new "Construire le paquet Android, et l'installer sur l'appareil Android connecté à votre ordinateur."
|
||||
|
||||
# game/android.rpy:142
|
||||
old "{a=%s}%s{/a}"
|
||||
new "{a=%s}%s{/a}"
|
||||
|
||||
# game/android.rpy:361
|
||||
old "Android: [project.current.name!q]"
|
||||
new "Android: [project.current.name!q]"
|
||||
|
||||
# game/android.rpy:381
|
||||
old "Emulation:"
|
||||
new "Émulateur:"
|
||||
|
||||
# game/android.rpy:389
|
||||
old "Phone"
|
||||
new "Téléphone"
|
||||
|
||||
# game/android.rpy:393
|
||||
old "Tablet"
|
||||
new "Tablette"
|
||||
|
||||
# game/android.rpy:397
|
||||
old "Television / OUYA"
|
||||
new "Télévision / OUYA"
|
||||
|
||||
# game/android.rpy:409
|
||||
old "Build:"
|
||||
new "Construire:"
|
||||
|
||||
# game/android.rpy:417
|
||||
old "Install SDK & Create Keys"
|
||||
new "Installer le kit de développement et créer les clés"
|
||||
|
||||
# game/android.rpy:421
|
||||
old "Configure"
|
||||
new "Configurer"
|
||||
|
||||
# game/android.rpy:425
|
||||
old "Build Package"
|
||||
new "Construire le paquet"
|
||||
|
||||
# game/android.rpy:429
|
||||
old "Build & Install"
|
||||
new "Construire et installer"
|
||||
|
||||
# game/android.rpy:13
|
||||
old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
|
||||
new "Un Kit de Développement Java (JDK) 32 bits est nécessaire pour construire les paquets pour Android depuis Windows. Le JDK n'est pas la même chose que le JRE, il est possible que Java soit installé sur votre machine sans le JDK.\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}Téléchargez et installez le JDK{/a}, puis relancer le lanceur Ren'Py."
|
||||
@@ -0,0 +1,41 @@
|
||||
translate french strings:
|
||||
|
||||
# game/choose_theme.rpy:274
|
||||
old "Could not change the theme. Perhaps options.rpy was changed too much."
|
||||
new "Impossible de changer le thème. Peut être que options.rpy a été trop modifié."
|
||||
|
||||
# game/choose_theme.rpy:332
|
||||
old "Display"
|
||||
new "Affichage"
|
||||
|
||||
# game/choose_theme.rpy:333
|
||||
old "Window"
|
||||
new "Fenêtre"
|
||||
|
||||
# game/choose_theme.rpy:334
|
||||
old "Fullscreen"
|
||||
new "Plein écran"
|
||||
|
||||
# game/choose_theme.rpy:335
|
||||
old "Planetarium"
|
||||
new "Planetarium"
|
||||
|
||||
# game/choose_theme.rpy:342
|
||||
old "Sound Volume"
|
||||
new "Volume sonore"
|
||||
|
||||
# game/choose_theme.rpy:376
|
||||
old "Choose Theme"
|
||||
new "Choisir un thème"
|
||||
|
||||
# game/choose_theme.rpy:389
|
||||
old "Theme"
|
||||
new "Thème"
|
||||
|
||||
# game/choose_theme.rpy:413
|
||||
old "Color Scheme"
|
||||
new "Agencement des couleurs"
|
||||
|
||||
# game/choose_theme.rpy:444
|
||||
old "Continue"
|
||||
new "Continuer"
|
||||
@@ -0,0 +1,281 @@
|
||||
translate french strings:
|
||||
|
||||
# renpy/common/00updater.rpy:1258
|
||||
old "Updater"
|
||||
new "Programme de mise à jour"
|
||||
|
||||
# renpy/common/00updater.rpy:1267
|
||||
old "This program is up to date."
|
||||
new "Ce programme est à jour."
|
||||
|
||||
# renpy/common/00updater.rpy:1269
|
||||
old "[u.version] is available. Do you want to install it?"
|
||||
new "La version [u.version]. Voulez-vous l'installer ?"
|
||||
|
||||
# renpy/common/00updater.rpy:1271
|
||||
old "Preparing to download the updates."
|
||||
new "Préparation du téléchargement de la mise à jour."
|
||||
|
||||
# renpy/common/00updater.rpy:1273
|
||||
old "Downloading the updates."
|
||||
new "Téléchargement de la mise à jour."
|
||||
|
||||
# renpy/common/00updater.rpy:1275
|
||||
old "Unpacking the updates."
|
||||
new "Dépaquetage de la mise à jour."
|
||||
|
||||
# renpy/common/00updater.rpy:1279
|
||||
old "The updates have been installed. The program will restart."
|
||||
new "La mise à jour a bien été effectuée. Le programme va redémarrer."
|
||||
|
||||
# renpy/common/00updater.rpy:1281
|
||||
old "The updates have been installed."
|
||||
new "La mise à jour a bien été effectuée."
|
||||
|
||||
# renpy/common/00updater.rpy:1283
|
||||
old "The updates were cancelled."
|
||||
new "La mise à jour a été annullée."
|
||||
|
||||
# renpy/common/_layout/classic_load_save.rpym:120
|
||||
old "Empty Slot."
|
||||
new "Emplacement vide."
|
||||
|
||||
# renpy/common/_layout/classic_load_save.rpym:152
|
||||
old "a"
|
||||
new "a"
|
||||
|
||||
# renpy/common/_layout/classic_load_save.rpym:161
|
||||
old "q"
|
||||
new "q"
|
||||
|
||||
# renpy/common/_layout/classic_joystick_preferences.rpym:76
|
||||
old "Joystick Mapping"
|
||||
new "Joystick"
|
||||
|
||||
# renpy/common/00layout.rpy:421
|
||||
old "Are you sure?"
|
||||
new "Êtes-vous sûr ?"
|
||||
|
||||
# renpy/common/00layout.rpy:422
|
||||
old "Are you sure you want to delete this save?"
|
||||
new "Êtes-vous sûr de vouloir supprimer cette sauvegarde ?"
|
||||
|
||||
# renpy/common/00layout.rpy:423
|
||||
old "Are you sure you want to overwrite your save?"
|
||||
new "Êtes-vous sûr de vouloir écraser cette sauvegarde ?"
|
||||
|
||||
# renpy/common/00layout.rpy:424
|
||||
old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
|
||||
new "En effectuant ce chargement, vous perderez votre avancement non sauvegardé.\nÊtes-vous sûr de vouloire faire ça ?"
|
||||
|
||||
# renpy/common/00layout.rpy:425
|
||||
old "Are you sure you want to quit?"
|
||||
new "Êtes-vous sûr de vouloir quitter ?"
|
||||
|
||||
# renpy/common/00layout.rpy:426
|
||||
old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
|
||||
new "Êtes-vous sûr de vouloir retourner au menu principal ?\nVous perdrez votre avancement non sauvegardé."
|
||||
|
||||
# renpy/common/00keymap.rpy:167
|
||||
old "Saved screenshot as %s."
|
||||
new "La capture d'écran a été enregistrée en tant que %s"
|
||||
|
||||
# renpy/common/00gltest.rpy:50
|
||||
old "Graphics Acceleration"
|
||||
new "Accélération graphique"
|
||||
|
||||
# renpy/common/00gltest.rpy:54
|
||||
old "Automatically Choose"
|
||||
new "Choix automatique"
|
||||
|
||||
# renpy/common/00gltest.rpy:59
|
||||
old "Force Angle/DirectX Renderer"
|
||||
new "Forcer le rendu Angle/DirectX"
|
||||
|
||||
# renpy/common/00gltest.rpy:63
|
||||
old "Force OpenGL Renderer"
|
||||
new "Forcer le rendu OpenGL"
|
||||
|
||||
# renpy/common/00gltest.rpy:67
|
||||
old "Force Software Renderer"
|
||||
new "Forcer le rendu logiciel"
|
||||
|
||||
# renpy/common/00gltest.rpy:73
|
||||
old "Changes will take effect the next time this program is run."
|
||||
new "Les changement seront pris en compte au prochin démarrage du programme."
|
||||
|
||||
# renpy/common/00gltest.rpy:77
|
||||
old "Quit"
|
||||
new "Quitter"
|
||||
|
||||
# renpy/common/00gltest.rpy:82
|
||||
old "Return"
|
||||
new "Retour"
|
||||
|
||||
# renpy/common/00gltest.rpy:112
|
||||
old "Performance Warning"
|
||||
new "Avertissement sur les performances"
|
||||
|
||||
# renpy/common/00gltest.rpy:117
|
||||
old "This computer is using software rendering."
|
||||
new "Cet ordinateur utilise le rendu logiciel."
|
||||
|
||||
# renpy/common/00gltest.rpy:119
|
||||
old "This computer is not using shaders."
|
||||
new "Cet ordinateur n'utilise pas les shaders."
|
||||
|
||||
# renpy/common/00gltest.rpy:121
|
||||
old "This computer is displaying graphics slowly."
|
||||
new "Cet ordinateur affiche lentement les graphismes."
|
||||
|
||||
# renpy/common/00gltest.rpy:123
|
||||
old "This computer has a problem displaying graphics: [problem]."
|
||||
new "Cet ordinateur rencontre des difficultés à afficher les graphismes: [problem]."
|
||||
|
||||
# renpy/common/00gltest.rpy:128
|
||||
old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
|
||||
new "Les pilotes graphiques ne semblent pas à jour ou dysfonctionnent. Cela peut entraîner des ralentissements ou de mauvais affichages. Mettre à jour DirectX pourraît régler ce problème."
|
||||
|
||||
# renpy/common/00gltest.rpy:130
|
||||
old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
|
||||
new "Les pilotes graphiques ne semblent pas à jour ou dysfonctionnent. Cela peut entraîner des ralentissements ou de mauvais affichages."
|
||||
|
||||
# renpy/common/00gltest.rpy:135
|
||||
old "Update DirectX"
|
||||
new "Mettre à jour DirectX"
|
||||
|
||||
# renpy/common/00gltest.rpy:141
|
||||
old "Continue, Show this warning again"
|
||||
new "Continer, Afficher cet avertissement la prochaine fois."
|
||||
|
||||
# renpy/common/00gltest.rpy:145
|
||||
old "Continue, Don't show warning again"
|
||||
new "Continer, Ne plus afficher cet avertissement."
|
||||
|
||||
# renpy/common/00gltest.rpy:171
|
||||
old "Updating DirectX."
|
||||
new "Mettre à jour de DirectX en cours"
|
||||
|
||||
# renpy/common/00gltest.rpy:175
|
||||
old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
|
||||
new "La mise à jour de DirectX a débutée. Elle est sans doute minimisée dans la bare de tâche. Merci de suivre les instructions pour installer DirectX."
|
||||
|
||||
# renpy/common/00gltest.rpy:179
|
||||
old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
|
||||
new "{b}Note:{/b} le programme d'installation de Microsoft's DirectX va, par defaut, installer la barre d'outils Bing. Si vous ne voulez pas de cette barre, décochez la case appropriée."
|
||||
|
||||
# renpy/common/00gltest.rpy:183
|
||||
old "When setup finishes, please click below to restart this program."
|
||||
new "Lorsque l'instllation sera terminée, cliquez ci-dessous pour redémarrer ce programme."
|
||||
|
||||
# renpy/common/00gltest.rpy:185
|
||||
old "Restart"
|
||||
new "Redémarrer"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:408
|
||||
old "An exception has occurred."
|
||||
new "Une exception a été levée."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:434
|
||||
old "Rollback"
|
||||
new "Revenir en arrière"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:436
|
||||
old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
|
||||
new "Tenter de revenir en arrière, vous permet de sauvegarder ou de faire un autre choix."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:439
|
||||
old "Ignore"
|
||||
new "Ignorer"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:441
|
||||
old "Ignores the exception, allowing you to continue. This often leads to additional errors."
|
||||
new "Ignorer l'exception vous permet de continuer. Cela entraîne généralement des erreurs additionelles."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:444
|
||||
old "Reload"
|
||||
new "Recharger"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:446
|
||||
old "Reloads the game from disk, saving and restoring game state if possible."
|
||||
new "Recharger le jeu depuis le disque dur and tenter de restaurer le jeu dans l'état actuel."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:448
|
||||
old "Open Traceback"
|
||||
new "Ouvrir la pile d'appel"
|
||||
|
||||
# renpy/common/_errorhandling.rpym:450
|
||||
old "Opens the traceback.txt file in a text editor."
|
||||
new "Ouvrir traceback.txt dans un éditeur de texte."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:456
|
||||
old "Quits the game."
|
||||
new "Quitter le jeu."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:483
|
||||
old "Parsing the script failed."
|
||||
new "L'analyse du script a échouée."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:510
|
||||
old "Open Parse Errors"
|
||||
new "Ouvrir les erreurs d'analyse."
|
||||
|
||||
# renpy/common/_errorhandling.rpym:512
|
||||
old "Opens the errors.txt file in a text editor."
|
||||
new "Ouvrir errors.txt dans un éditeur de texte."
|
||||
|
||||
# renpy/common/00action_file.rpy:118
|
||||
old "%b %d, %H:%M"
|
||||
new "%b %d, %H:%M"
|
||||
|
||||
# renpy/common/_compat/gamemenu.rpym:337
|
||||
old "Previous"
|
||||
new "Précédent"
|
||||
|
||||
# renpy/common/_compat/gamemenu.rpym:344
|
||||
old "Next"
|
||||
new "Suivant"
|
||||
|
||||
# renpy/common/00library.rpy:77
|
||||
old "Skip Mode"
|
||||
new "Mode rapide"
|
||||
|
||||
# renpy/common/00library.rpy:80
|
||||
old "Fast Skip Mode"
|
||||
new "Mode très rapide"
|
||||
|
||||
# renpy/common/00gallery.rpy:521
|
||||
old "Image [index] of [count] locked."
|
||||
new "Image [index] sur [count] verrouillée."
|
||||
|
||||
# renpy/common/00gallery.rpy:539
|
||||
old "prev"
|
||||
new "précédent"
|
||||
|
||||
# renpy/common/00gallery.rpy:540
|
||||
old "next"
|
||||
new "suivant"
|
||||
|
||||
# renpy/common/00gallery.rpy:541
|
||||
old "slideshow"
|
||||
new "diaporama"
|
||||
|
||||
# renpy/common/00gallery.rpy:542
|
||||
old "return"
|
||||
new "retour"
|
||||
|
||||
# renpy/common/00layout.rpy:427
|
||||
old "Are you sure you want to begin skipping?"
|
||||
new "Êtes-vous sûr de vouloir commencer à sauter certaines étapes ?"
|
||||
|
||||
# renpy/common/00layout.rpy:428
|
||||
old "Are you sure you want to skip to the next choice?"
|
||||
new "Êtes-vous sûr de vouloir sauter le prochain choix ?"
|
||||
|
||||
# renpy/common/00layout.rpy:429
|
||||
old "Are you sure you want to skip to unseen dialogue or the next choice?"
|
||||
new "Êtes-vous sûr de vouloir sauter des dialogues non lus or le prochain choix ?"
|
||||
|
||||
# renpy/common/00action_file.rpy:587
|
||||
old "Quick save complete."
|
||||
new "Sauvegarde rapide effectuée."
|
||||
@@ -0,0 +1,37 @@
|
||||
translate french strings:
|
||||
|
||||
# game/distribute.rpy:333
|
||||
old "Nothing to do."
|
||||
new "Rien à faire."
|
||||
|
||||
# game/distribute.rpy:337
|
||||
old "Scanning project files..."
|
||||
new "Scan des fichiers du projet..."
|
||||
|
||||
# game/distribute.rpy:344
|
||||
old "Scanning Ren'Py files..."
|
||||
new "Scan des fichiers Ren'Py..."
|
||||
|
||||
# game/distribute.rpy:494
|
||||
old "Archiving files..."
|
||||
new "Archivage des fichiers..."
|
||||
|
||||
# game/distribute.rpy:745
|
||||
old "Writing the [variant] [format] package."
|
||||
new "Écriture du paquet [variant] [format]."
|
||||
|
||||
# game/distribute.rpy:758
|
||||
old "Making the [variant] update zsync file."
|
||||
new "Création du fichier de mise à jour zsync [variant]."
|
||||
|
||||
# game/distribute.rpy:854
|
||||
old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
|
||||
new "Traitement du fichier {b}[complete]{/b} sur {b}[total]{/b}."
|
||||
|
||||
# game/distribute.rpy:915
|
||||
old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
|
||||
new "Tous les paquets ont été contruits.\n\nDu fait de la présence des systèmes de permissions, il n'est pas possible de reconstruire les paquets construits sur GNU-Linux ou Mac OS sur Windows."
|
||||
|
||||
# game/distribute.rpy:358
|
||||
old "No packages are selected, so there's nothing to do."
|
||||
new "Aucun paquet sélectionné, il n'y a donc rien à faire."
|
||||
@@ -0,0 +1,41 @@
|
||||
translate french strings:
|
||||
|
||||
# game/distribute_gui.rpy:139
|
||||
old "Build Distributions: [project.current.name!q]"
|
||||
new "Construction des packets: [project.current.name!q]"
|
||||
|
||||
# game/distribute_gui.rpy:154
|
||||
old "Directory Name:"
|
||||
new "Nom du répertoire:"
|
||||
|
||||
# game/distribute_gui.rpy:158
|
||||
old "Executable Name:"
|
||||
new "Nom de l'exécutable:"
|
||||
|
||||
# game/distribute_gui.rpy:175
|
||||
old "Edit options.rpy"
|
||||
new "Éditer options.rpy"
|
||||
|
||||
# game/distribute_gui.rpy:176
|
||||
old "Refresh"
|
||||
new "Rafraichir"
|
||||
|
||||
# game/distribute_gui.rpy:193
|
||||
old "Build Packages:"
|
||||
new "Construire les packets:"
|
||||
|
||||
# game/distribute_gui.rpy:208
|
||||
old "Build Updates"
|
||||
new "Construire les mises à jour"
|
||||
|
||||
# game/distribute_gui.rpy:212
|
||||
old "Build"
|
||||
new "Construire"
|
||||
|
||||
# game/distribute_gui.rpy:219
|
||||
old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
|
||||
new "Des erreurs ont été détectées lors de l'utilisation du projet. Assurez-vous qu'il n'y ait plus d'erreur avant de construire les packets."
|
||||
|
||||
# game/distribute_gui.rpy:236
|
||||
old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
|
||||
new "Votre projet ne contient pas d'information pour la construction. Voulez-vous ajouter ces informations à la fin de options.rpy ?"
|
||||
@@ -0,0 +1,57 @@
|
||||
translate french strings:
|
||||
|
||||
# game/editor.rpy:120
|
||||
old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
|
||||
new "{b}Recommendé.{/b} Un éditeur en version bêta avec une interface simple et des fonctionnalités d'assistance au développement. Editra manque pour le moment du support pour les textes en chinois, japonais et coréen."
|
||||
|
||||
# game/editor.rpy:121
|
||||
old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
|
||||
new "{b}Recommendé.{/b} Un éditeur en version bêta avec une interface simple et des fonctionnalités d'assistance au développement. Editra manque pour le moment du support pour les textes en chinois, japonais et coréen. Sur GNU-Linux, Editra nécessite wxPython."
|
||||
|
||||
# game/editor.rpy:137
|
||||
old "The may have occured because wxPython is not installed on this system."
|
||||
new "Cela est sans doute arrivé car wxPython n'est pas installé sur ce système."
|
||||
|
||||
# game/editor.rpy:144
|
||||
old "Up to 22 MB download required."
|
||||
new "Jusqu'à 22 MB de téléchargement requis."
|
||||
|
||||
# game/editor.rpy:157
|
||||
old "1.8 MB download required."
|
||||
new "1.8 MB de réléchargement requis."
|
||||
|
||||
# game/editor.rpy:158
|
||||
old "This may have occured because Java is not installed on this system."
|
||||
new "Cela est sans doute arrivé car Java n'est pas installé sur ce système."
|
||||
|
||||
# game/editor.rpy:327
|
||||
old "An exception occured while launching the text editor:\n[exception!q]"
|
||||
new "Une exception a été levée lors du lancement de l'édieteur de texte :\n[exception!q]"
|
||||
|
||||
# game/editor.rpy:378
|
||||
old "Select Editor"
|
||||
new "Sélectionnez un éditeur"
|
||||
|
||||
# game/editor.rpy:393
|
||||
old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
|
||||
new "Un éditeur de texte est un logiciel que vous utilisez pour éditer les fichiers de script Ren'Py. Vous pouvez choisir l'édteur que Ren'Py utilise. Si ce n'est pas déjà le cas, l'éditeur sera automatiquement téléchargé et installé."
|
||||
|
||||
# game/editor.rpy:415
|
||||
old "Cancel"
|
||||
new "Annuler"
|
||||
|
||||
# game/editor.rpy:137
|
||||
old "This may have occured because wxPython is not installed on this system."
|
||||
new "Cela est sans doute dû au fait que wxPython n'est pas installé sur votre système."
|
||||
|
||||
# game/editor.rpy:155
|
||||
old "A mature editor that requires Java."
|
||||
new "Un éditeur éprouvé nécessitant Java."
|
||||
|
||||
# game/editor.rpy:164
|
||||
old "Invokes the editor your operating system has associated with .rpy files."
|
||||
new "Lance l'éditeur associé par votre systèmes aux fichiers .rpy."
|
||||
|
||||
# game/editor.rpy:180
|
||||
old "Prevents Ren'Py from opening a text editor."
|
||||
new "Empêche Ren'Py d'ouvrir un éditeur de texte."
|
||||
@@ -0,0 +1,81 @@
|
||||
translate french strings:
|
||||
|
||||
# game/front_page.rpy:79
|
||||
old "+ Create New Project"
|
||||
new "+ Créer un nouveau projet"
|
||||
|
||||
# game/front_page.rpy:111
|
||||
old "Tutorial"
|
||||
new "Tutoriel"
|
||||
|
||||
# game/front_page.rpy:112
|
||||
old "The Question"
|
||||
new "The Question"
|
||||
|
||||
# game/front_page.rpy:128
|
||||
old "Active Project"
|
||||
new "Projet actif"
|
||||
|
||||
# game/front_page.rpy:136
|
||||
old "Open Directory"
|
||||
new "Ouvrir le répertoire"
|
||||
|
||||
# game/front_page.rpy:141
|
||||
old "game"
|
||||
new "game"
|
||||
|
||||
# game/front_page.rpy:142
|
||||
old "base"
|
||||
new "base"
|
||||
|
||||
# game/front_page.rpy:148
|
||||
old "Edit File"
|
||||
new "Éditer le fichier"
|
||||
|
||||
# game/front_page.rpy:156
|
||||
old "All script files"
|
||||
new "Tous les fichiers de script"
|
||||
|
||||
# game/front_page.rpy:165
|
||||
old "Navigate Script"
|
||||
new "Naviguer dans le script"
|
||||
|
||||
# game/front_page.rpy:176
|
||||
old "Check Script (Lint)"
|
||||
new "Vérifier le script (Lint)"
|
||||
|
||||
# game/front_page.rpy:177
|
||||
old "Change Theme"
|
||||
new "Changer de thème"
|
||||
|
||||
# game/front_page.rpy:178
|
||||
old "Delete Persistent"
|
||||
new "Supprimer persistant"
|
||||
|
||||
# game/front_page.rpy:186
|
||||
old "Build Distributions"
|
||||
new "Construire les packets"
|
||||
|
||||
# game/front_page.rpy:188
|
||||
old "Generate Translations"
|
||||
new "Générer fichiers de traduction"
|
||||
|
||||
# game/front_page.rpy:204
|
||||
old "Checking script for potential problems..."
|
||||
new "Vérifier le script vis à vis des problèmes potentiels..."
|
||||
|
||||
# game/front_page.rpy:219
|
||||
old "Deleting persistent data..."
|
||||
new "Supprimer les données persistantes..."
|
||||
|
||||
# game/front_page.rpy:204
|
||||
old "Android"
|
||||
new "Android"
|
||||
|
||||
# game/front_page.rpy:206
|
||||
old "Extract Dialogue"
|
||||
new "Extraire dialogue"
|
||||
|
||||
# game/front_page.rpy:126
|
||||
old "[p.name!q] (template)"
|
||||
new "[p.name!q] (gabarit)"
|
||||
@@ -0,0 +1,85 @@
|
||||
translate french strings:
|
||||
|
||||
# game/interface.rpy:89
|
||||
old "Documentation"
|
||||
new "Documentation"
|
||||
|
||||
# game/interface.rpy:90
|
||||
old "Ren'Py Website"
|
||||
new "Site Web de Ren'Py"
|
||||
|
||||
# game/interface.rpy:91
|
||||
old "Ren'Py Games List"
|
||||
new "Liste des jeux Ren'Py"
|
||||
|
||||
# game/interface.rpy:92
|
||||
old "About"
|
||||
new "À propos"
|
||||
|
||||
# game/interface.rpy:99
|
||||
old "update"
|
||||
new "mise à jour"
|
||||
|
||||
# game/interface.rpy:101
|
||||
old "preferences"
|
||||
new "préférences"
|
||||
|
||||
# game/interface.rpy:102
|
||||
old "quit"
|
||||
new "quitter"
|
||||
|
||||
# game/interface.rpy:149
|
||||
old "Yes"
|
||||
new "Oui"
|
||||
|
||||
# game/interface.rpy:151
|
||||
old "No"
|
||||
new "Non"
|
||||
|
||||
# game/interface.rpy:181
|
||||
old "Due to package format limitations, non-ASCII file and directory names are not allowed."
|
||||
new "Les caractères non-ASCII ne sont pas autorisés pour les noms de fichiers et répertoires."
|
||||
|
||||
# game/interface.rpy:183
|
||||
old "[title]"
|
||||
new "[title]"
|
||||
|
||||
# game/interface.rpy:248
|
||||
old "ERROR"
|
||||
new "ERREUR"
|
||||
|
||||
# game/interface.rpy:280
|
||||
old "While [what!q], an error occured:"
|
||||
new "Pendant que [what!q], une erreur est arrivée:"
|
||||
|
||||
# game/interface.rpy:281
|
||||
old "[exception!q]"
|
||||
new "[exception!q]"
|
||||
|
||||
# game/interface.rpy:298
|
||||
old "Text input may not contain the {{ or [[ characters."
|
||||
new "Le texte ne devrait pas contenir les caractères {{ ou [[."
|
||||
|
||||
# game/interface.rpy:303
|
||||
old "File and directory names may not contain / or \\."
|
||||
new "Les noms de fichiers et répertoires ne devrait pas contenir / ou \\."
|
||||
|
||||
# game/interface.rpy:309
|
||||
old "File and directory names must consist of ASCII characters."
|
||||
new "Les noms de fichiers et de répertoires doivent contenir uniquement des caractères ASCII."
|
||||
|
||||
# game/interface.rpy:330
|
||||
old "INFORMATION"
|
||||
new "INFORMATION"
|
||||
|
||||
# game/interface.rpy:373
|
||||
old "PROCESSING"
|
||||
new "TRAITEMENT"
|
||||
|
||||
# game/interface.rpy:390
|
||||
old "QUESTION"
|
||||
new "QUESTION"
|
||||
|
||||
# game/interface.rpy:451
|
||||
old "CHOICE"
|
||||
new "CHOIX"
|
||||
@@ -0,0 +1,73 @@
|
||||
translate french strings:
|
||||
|
||||
# game/navigation.rpy:150
|
||||
old "Navigate: [project.current.name]"
|
||||
new "Navigation: [project.current.name]"
|
||||
|
||||
# game/navigation.rpy:159
|
||||
old "Order: "
|
||||
new "Ordre:"
|
||||
|
||||
# game/navigation.rpy:160
|
||||
old "alphabetical"
|
||||
new "alphabétique"
|
||||
|
||||
# game/navigation.rpy:162
|
||||
old "by-file"
|
||||
new "par fichier"
|
||||
|
||||
# game/navigation.rpy:164
|
||||
old "natural"
|
||||
new "naturel"
|
||||
|
||||
# game/navigation.rpy:168
|
||||
old "refresh"
|
||||
new "rafraichir"
|
||||
|
||||
# game/navigation.rpy:176
|
||||
old "Category:"
|
||||
new "Catégorie:"
|
||||
|
||||
# game/navigation.rpy:178
|
||||
old "files"
|
||||
new "fichiers"
|
||||
|
||||
# game/navigation.rpy:179
|
||||
old "labels"
|
||||
new "labels"
|
||||
|
||||
# game/navigation.rpy:180
|
||||
old "defines"
|
||||
new "définitions"
|
||||
|
||||
# game/navigation.rpy:181
|
||||
old "transforms"
|
||||
new "transformations"
|
||||
|
||||
# game/navigation.rpy:182
|
||||
old "screens"
|
||||
new "écrans"
|
||||
|
||||
# game/navigation.rpy:183
|
||||
old "callables"
|
||||
new "appelables"
|
||||
|
||||
# game/navigation.rpy:184
|
||||
old "TODOs"
|
||||
new "TODOs"
|
||||
|
||||
# game/navigation.rpy:223
|
||||
old "+ Add script file"
|
||||
new "+ Ajouter un fichier de script"
|
||||
|
||||
# game/navigation.rpy:231
|
||||
old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
|
||||
new "Aucun commentaire «TODO» trouvé.\n\nPour un créer un, écrivez \"# TODO\" dans le script."
|
||||
|
||||
# game/navigation.rpy:238
|
||||
old "The list of names is empty."
|
||||
new "La liste des noms est vide."
|
||||
|
||||
# game/navigation.rpy:243
|
||||
old "Launch Project"
|
||||
new "Lancer le projet"
|
||||
@@ -0,0 +1,33 @@
|
||||
translate french strings:
|
||||
|
||||
# game/new_project.rpy:22
|
||||
old "Choose Project Template"
|
||||
new "Choisissez un patron de projet"
|
||||
|
||||
# game/new_project.rpy:40
|
||||
old "Please select a template to use for your new project. Ren'Py ships with a default template that creates an English-language game with standard screens."
|
||||
new "Merci de sélectioner un patron à utiliser pour votre nouveau projet. Ren'Py est livré avec un patron par défaut qui créé un jeu en anglais avec des écrans standards."
|
||||
|
||||
# game/new_project.rpy:55
|
||||
old "PROJECT NAME"
|
||||
new "NOM DU PROJET"
|
||||
|
||||
# game/new_project.rpy:56
|
||||
old "Please enter the name of your project:"
|
||||
new "Entrez le nom de votre projet:"
|
||||
|
||||
# game/new_project.rpy:62
|
||||
old "The project name may not be empty."
|
||||
new "Le nom du projet ne doit pas être vide."
|
||||
|
||||
# game/new_project.rpy:67
|
||||
old "[project_name!q] already exists. Please choose a different project name."
|
||||
new "Le projet [project_name!q] éxiste déjà. Choisissez un nom de projet différend."
|
||||
|
||||
# game/new_project.rpy:70
|
||||
old "[project_dir!q] already exists. Please choose a different project name."
|
||||
new "Le projet [project_name!q] éxiste déjà. Choisissez un nom de projet différend."
|
||||
|
||||
# game/new_project.rpy:40
|
||||
old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
|
||||
new "Sélectionnez un gabarit pour votre nouveau projet. Le gabarit définit la police par défaut, ainsi que la langue de l'interface. Si votre langue n'est pas supportée, sélectionnez 'english'."
|
||||
@@ -0,0 +1,69 @@
|
||||
translate french strings:
|
||||
|
||||
# game/preferences.rpy:40
|
||||
old "Launcher Preferences"
|
||||
new "Préférence du lanceur"
|
||||
|
||||
# game/preferences.rpy:61
|
||||
old "Projects Directory:"
|
||||
new "Répertoire des projets:"
|
||||
|
||||
# game/preferences.rpy:68
|
||||
old "[persistent.projects_directory!q]"
|
||||
new "[persistent.projects_directory!q]"
|
||||
|
||||
# game/preferences.rpy:70
|
||||
old "Not Set"
|
||||
new "Non précisé"
|
||||
|
||||
# game/preferences.rpy:84
|
||||
old "Text Editor:"
|
||||
new "Éditeur:"
|
||||
|
||||
# game/preferences.rpy:106
|
||||
old "Update Channel:"
|
||||
new "Version"
|
||||
|
||||
# game/preferences.rpy:126
|
||||
old "Navigation Options:"
|
||||
new "Options de navigation:"
|
||||
|
||||
# game/preferences.rpy:130
|
||||
old "Include private names"
|
||||
new "Inclure les noms privés"
|
||||
|
||||
# game/preferences.rpy:131
|
||||
old "Include library names"
|
||||
new "Inclure les noms des bibliothèques"
|
||||
|
||||
# game/preferences.rpy:141
|
||||
old "Launcher Options:"
|
||||
new "Options du lanceur:"
|
||||
|
||||
# game/preferences.rpy:145
|
||||
old "Hardware rendering"
|
||||
new "Rendu matériel"
|
||||
|
||||
# game/preferences.rpy:148
|
||||
old "Console output"
|
||||
new "Sortie console"
|
||||
|
||||
# game/preferences.rpy:165
|
||||
old "Actions:"
|
||||
new "Actions:"
|
||||
|
||||
# game/preferences.rpy:169
|
||||
old "Open launcher project"
|
||||
new "Ouvrir le projet lanceur"
|
||||
|
||||
# game/preferences.rpy:183
|
||||
old "Language:"
|
||||
new "Langue:"
|
||||
|
||||
# game/preferences.rpy:193
|
||||
old "Back"
|
||||
new "Retour"
|
||||
|
||||
# game/preferences.rpy:146
|
||||
old "Show templates"
|
||||
new "Montrer les gabarits"
|
||||
@@ -0,0 +1,25 @@
|
||||
translate french strings:
|
||||
|
||||
# game/project.rpy:196
|
||||
old "Ren'Py is scanning the project..."
|
||||
new "Ren'Py est en train de scanner le projet..."
|
||||
|
||||
# game/project.rpy:485
|
||||
old "PROJECTS DIRECTORY"
|
||||
new "RÉPERTOIRE DES PROJETS"
|
||||
|
||||
# game/project.rpy:485
|
||||
old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
|
||||
new "Choisissez le répertoire des projets avec le sélecteur de fichier.\n{b}Il se peut que le sélecteur de fichier s'ouvre derière cette fenêtre.{/b}"
|
||||
|
||||
# game/project.rpy:485
|
||||
old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
|
||||
new "Ce lanceur va scanner ce répertoire pour trouver des projets éxistants, créra les nouveaux projets dans ce répertoire, et placera les projets construits dans ce répertoire."
|
||||
|
||||
# game/project.rpy:525
|
||||
old "Ren'Py was unable to run python with tkinter to choose the projects directory."
|
||||
new "Ren'Py n'a pas pu lancer python avec le module tkinker pout choisir le répertoire des projets."
|
||||
|
||||
# game/project.rpy:529
|
||||
old "Ren'Py has set the projects directory to:"
|
||||
new "Le répertoire des projets vient d'être établit:"
|
||||
@@ -0,0 +1,6 @@
|
||||
translate french python:
|
||||
style.l_default.size = 16
|
||||
style.l_button_text.selected_bold = True
|
||||
style.l_navigation_text.bold = False
|
||||
make_style_backup()
|
||||
|
||||