diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..8ac84100 --- /dev/null +++ b/LICENSE @@ -0,0 +1,892 @@ +Copyright (c), W.Dee and contributors All rights reserved. +Contributors + Go Watanabe, Kenjo, Kiyobee, Kouhei Yanagita, mey, MIK, Takenori Imoto, yun +Kirikiri Z Project Contributors +W.Dee, casper, 有限会社MCF, Biscrat, 青猫, nagai, ルー, 高際 雅之, 永劫, +ゆんゆん探偵, りょうご(今は無きあの星), AZ-UME, 京 秋人, +Katsumasa Tsuneyoshi, 小池潤, miahmie, サークル獏, アザナシ, はっしぃ, +棚中製作所, わっふる/waffle, ワムソフト, TYPE-MOON, 有限会社エムツー, +Takenori Imoto +Kirikiri Z 64bit Project Contributors +合資会社ワムソフト, Takenori Imoto, 他 +---------------------------------------------------------------------------- +ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満 +たす場合に限り、再頒布および使用が許可されます。 + +・ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責 + 条項を含めること。 +・バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の + 著作権表示、本条件一覧、および下記免責条項を含めること。 +・書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売 + 促進に、組織の名前またはコントリビューターの名前を使用してはならない。 + +本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供 +されており、明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適 +合性に関する暗黙の保証も含め、またそれに限定されない、いかなる保証もありませ +ん。著作権者もコントリビューターも、事由のいかんを問わず、損害発生の原因いか +んを問わず、かつ責任の根拠が契約であるか厳格責任であるか(過失その他の)不法 +行為であるかを問わず、仮にそのような損害が発生する可能性を知らされていたとし +ても、本ソフトウェアの使用によって発生した(代替品または代用サービスの調達、 +使用の喪失、データの喪失、利益の喪失、業務の中断も含め、またそれに限定されな +い)直接損害、間接損害、偶発的な損害、特別損害、懲罰的損害、または結果損害に +ついて、一切責任を負わないものとします。 + +------------------------------------------------------------------------------ +Thanks for many libraries to contributors and other supporters that were not +listed here. + +This software is based in part on the work of Independent JPEG Group. +------------------------------------------------------------------------------ +libjpeg-turbo + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +? Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +? Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. +? Neither the name of the libjpeg-turbo Project nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. +------------------------------------------------------------------------------ +Using "A C-program for MT19937" + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +------------------------------------------------------------------------------ +libpng LICENSE + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.6.1, March 28, 2013, are +Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +March 28, 2013 +------------------------------------------------------------------------------ +zlib LICENSE + + The deflate format used by zlib was defined by Phil Katz. The deflate and + zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; they + are too numerous to cite here. + +Copyright notice: + + (C) 1995-2012 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. +------------------------------------------------------------------------------ + +Oniguruma LICENSE +----------------- + +/*- + * Copyright (c) 2002-2007 K.Kosako + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +------------------------------------------------------------------------------ + The FreeType Project LICENSE + ---------------------------- + + 2006-Jan-27 + + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright ゥ The FreeType + Project (www.freetype.org). All rights reserved. + """ + + Please replace with the value from the FreeType version you + actually use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@nongnu.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o freetype-devel@nongnu.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + Our home page can be found at + + http://www.freetype.org +------------------------------------------------------------------------------ +picojson LICENSE + +/* Copyright 2009 Cybozu Labs, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY CYBOZU LABS, INC. ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL CYBOZU LABS, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are + * those of the authors and should not be interpreted as representing official + * policies, either expressed or implied, of Cybozu Labs, Inc. + * + */ +------------------------------------------------------------------------------ + + Copyright (c) 2012, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +------------------------------------------------------------------------------ +Microsoft Corporation Technical Documentation License Agreement for the +specification “JPEG XR Device Porting Kit” +Copyright (c) 2013 Microsoft Corp. +All rights reserved. +Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSEARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BELIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OFSUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESSINTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER INCONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE.. +------------------------------------------------------------------------------ +------------------------------------------------------------------------ +*** vorbis +*** ogg + +Copyright (c) 1994-2004 Xiph.org Foundation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------ +*** theora + +Copyright (C) 2002-2008 Xiph.org Foundation and contributors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------ +*** libfishsound +*** dsfSeeking + +Copyright (C) 2003, 2004 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the CSIRO Australia nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------ +*** libCMMLParse +*** libCMMLTags +*** libCMMLTagsDotNET +*** libOOOggChef +*** libTemporalURI +*** libWinCMMLParse +*** dsfCMMLDecoder +*** dsfAnxDemux +*** AnxCutter +*** CMMLDump +*** mod_oggchef + +Copyright (C) 2003-2005 Zentaro Kavanagh + +Copyright (C) 2003-2005 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of CSIRO Australia nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------ +*** dsfOggDemux +*** dsfOggMux +*** dsfSpeexDecoder +*** dsfSpeexEncoder +*** dsfVorbisDecoder +*** dsfVorbisEncoder +*** dsfFLACDecoder +*** dsfFLACEncoder +*** dsfTheoraDecoder +*** dsfTheoraEncoder +*** dsfAbstractAudioDecoder +*** dsfAbstractAudioEncoder +*** dsfAbstractVideoDecoder +*** dsfAbstractVideoEncoder +*** dsfSubtitleVMR9 +*** libiWrapper +*** libilliCore +*** libOOTheora +*** libOOOgg +*** libOOOggSeek +*** libVorbisComment +*** libVorbisCommentDotNET +*** OOOggDump +*** OOOggStat +*** OOOggCommentDump +*** CLOgg +*** DNPlay +*** iOCE + +Copyright (C) 2008-2010 Cristian Adam +Copyright (C) 2003-2005 Zentaro Kavanagh + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +- Neither the name of Zentaro Kavanagh nor the names of contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +------------------------------------------------------------------------ diff --git a/project/android/AndroidManifest.xml b/project/android/AndroidManifest.xml new file mode 100644 index 00000000..523d0cbe --- /dev/null +++ b/project/android/AndroidManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/project/android/jni/Android.mk b/project/android/jni/Android.mk new file mode 100644 index 00000000..117a9034 --- /dev/null +++ b/project/android/jni/Android.mk @@ -0,0 +1,43 @@ +#ndk-build MODULE_PATH=jni + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := kirikiri2 + +LOCAL_MODULE_FILENAME := libgame + +LOCAL_SRC_FILES := src/SDL_android_main.cpp + +LOCAL_LDLIBS := -lGLESv1_CM -llog -ldl -lGLESv2 -landroid -lm +LOCAL_LDLIBS += -Wl,--wrap=malloc -Wl,--wrap=free -Wl,--wrap=realloc -Wl,--wrap=calloc + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../../../vendor/libgdiplus/src \ + $(LOCAL_PATH)/../../../vendor/google_breakpad/current/src \ + $(LOCAL_PATH)/../../../vendor/google_breakpad/current/src/common/android/include \ + $(LOCAL_PATH)/../../../src/core/environ \ + $(LOCAL_PATH)/../../../src/core/environ/android \ + $(LOCAL_PATH)/../../../src/core/tjs2 \ + $(LOCAL_PATH)/../../../src/core/base \ + $(LOCAL_PATH)/../../../src/core/visual \ + $(LOCAL_PATH)/../../../src/core/visual/win32 \ + $(LOCAL_PATH)/../../../src/core/sound \ + $(LOCAL_PATH)/../../../src/core/sound/win32 \ + $(LOCAL_PATH)/../../../src/core/utils \ + +LOCAL_WHOLE_STATIC_LIBRARIES := kr2plugin krkr2 krkr2_neon_opt cocos2dx_static +#LOCAL_WHOLE_STATIC_LIBRARIES += tcmalloc +LOCAL_STATIC_LIBRARIES := android-ndk-profiler +LOCAL_CPPFLAGS += -Dtypeof=decltype + +include $(BUILD_SHARED_LIBRARY) +$(call import-module, core) +$(call import-module, ARM_neon) +$(call import-module, plugins) +#$(call import-module, png) #cocos +#$(call import-module, jpeg) #cocos +$(call import-module, cocos) +#$(call import-module, tcmalloc) +#$(call import-module, ../../../vendor/libgdiplus/jni) \ No newline at end of file diff --git a/project/android/jni/Application.mk b/project/android/jni/Application.mk new file mode 100644 index 00000000..d428bd97 --- /dev/null +++ b/project/android/jni/Application.mk @@ -0,0 +1,9 @@ +APP_STL := gnustl_static +APP_CPPFLAGS := -fexceptions -std=c++11 +APP_CPPFLAGS += -O3 -DNDEBUG -Wno-inconsistent-missing-override +#APP_CPPFLAGS += -D__DO_PROF__ -g -pg +APP_ABI := armeabi-v7a +#APP_ABI += arm64-v8a +APP_PLATFORM := android-9 +#NDK_TOOLCHAIN_VERSION := 4.9 +NDK_TOOLCHAIN_VERSION := clang \ No newline at end of file diff --git a/project/android/jni/src/SDL_android_main.cpp b/project/android/jni/src/SDL_android_main.cpp new file mode 100644 index 00000000..2eb33e68 --- /dev/null +++ b/project/android/jni/src/SDL_android_main.cpp @@ -0,0 +1,277 @@ +/* Include the SDL main definition header */ +#include +#include "platform/android/jni/JniHelper.h" +#include "cocos2d/AppDelegate.h" +#include "cocos2d/MainScene.h" +#include "ConfigManager/GlobalConfigManager.h" + +/******************************************************************************* + Functions called by JNI +*******************************************************************************/ +#include +#include +#include +#include +#include "client/linux/handler/exception_handler.h" +#include "client/linux/handler/minidump_descriptor.h" + +//std::string Android_GetDumpStoragePath(); +void start_profile() {} +void stop_profile() {} + +static bool __DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, + void* context, bool succeeded) +{ + return succeeded; +} + +extern bool TVPSystemUninitCalled; + +static bool __DumpFilter(void *data) { + if(TVPSystemUninitCalled) return false; // if trying exit system, ignore all exception + return true; +} + + +//static void __InitAndroidDump() { +// static google_breakpad::MinidumpDescriptor descriptor(Android_GetDumpStoragePath()); +// static google_breakpad::ExceptionHandler eh(descriptor, __DumpFilter, __DumpCallback, +// NULL, true, -1); +//} + +void cocos_android_app_init (JNIEnv* env) { // for cocos3.10+ +// __InitAndroidDump(); + static TVPAppDelegate *pAppDelegate = new TVPAppDelegate(); +} + +void cocos_android_app_init(JNIEnv* env, jobject thiz) { +// __InitAndroidDump(); + static TVPAppDelegate *pAppDelegate = new TVPAppDelegate(); +} + +namespace kr2android { + extern std::condition_variable MessageBoxCond; + extern std::mutex MessageBoxLock; + extern int MsgBoxRet; + extern std::string MessageBoxRetText; +} +void Android_PushEvents(const std::function &func); +using namespace kr2android; +extern "C" { + void Java_org_tvp_kirikiri2_KR2Activity_initDump(JNIEnv* env, jclass cls, jstring path) { + const char* pszPath = env->GetStringUTFChars(path, NULL); + if (pszPath && *pszPath) { + static google_breakpad::MinidumpDescriptor descriptor(pszPath); + static google_breakpad::ExceptionHandler eh(descriptor, __DumpFilter, __DumpCallback, + NULL, true, -1); + } + env->ReleaseStringUTFChars(path, pszPath); + } + + void Java_org_tvp_kirikiri2_KR2Activity_onMessageBoxOK(JNIEnv* env, jclass cls, jint nButton) { + MsgBoxRet = nButton; + MessageBoxCond.notify_one(); + } + + void Java_org_tvp_kirikiri2_KR2Activity_onMessageBoxText(JNIEnv* env, jclass cls, jstring text) { + const char* pszText = env->GetStringUTFChars(text, NULL); + if (pszText && *pszText) { + MessageBoxRetText = pszText; + } + env->ReleaseStringUTFChars(text, pszText); + } + + JNIEXPORT void JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeTouchesBegin(JNIEnv * env, jobject thiz, jint id, jfloat x, jfloat y) { + intptr_t idlong = id; + Android_PushEvents([idlong, x, y](){ + cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1, (intptr_t*)&idlong, (float*)&x, (float*)&y); + }); + } + + JNIEXPORT void JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeTouchesEnd(JNIEnv * env, jobject thiz, jint id, jfloat x, jfloat y) { + intptr_t idlong = id; + Android_PushEvents([idlong, x, y](){ + cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesEnd(1, (intptr_t*)&idlong, (float*)&x, (float*)&y); + }); + } + + JNIEXPORT void JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeTouchesMove(JNIEnv * env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys) { + int size = env->GetArrayLength(ids); + if (size == 1) { + intptr_t idlong; + jint id; + jfloat x; + jfloat y; + env->GetIntArrayRegion(ids, 0, size, &id); + env->GetFloatArrayRegion(xs, 0, size, &x); + env->GetFloatArrayRegion(ys, 0, size, &y); + idlong = id; + Android_PushEvents([idlong, x, y](){ + cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesMove(1, (intptr_t*)&idlong, (float*)&x, (float*)&y); + }); + return; + } + + jint id[size]; + std::vector x; x.resize(size); + std::vector y; y.resize(size); + + env->GetIntArrayRegion(ids, 0, size, id); + env->GetFloatArrayRegion(xs, 0, size, &x[0]); + env->GetFloatArrayRegion(ys, 0, size, &y[0]); + + std::vector idlong; idlong.resize(size); + for (int i = 0; i < size; i++) + idlong[i] = id[i]; + + Android_PushEvents([idlong, x, y](){ + cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesMove(idlong.size(), (intptr_t*)&idlong[0], (float*)&x[0], (float*)&y[0]); + }); + } + + JNIEXPORT void JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeTouchesCancel(JNIEnv * env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys) { + int size = env->GetArrayLength(ids); + if (size == 1) { + intptr_t idlong; + jint id; + jfloat x; + jfloat y; + env->GetIntArrayRegion(ids, 0, size, &id); + env->GetFloatArrayRegion(xs, 0, size, &x); + env->GetFloatArrayRegion(ys, 0, size, &y); + idlong = id; + Android_PushEvents([idlong, x, y](){ + cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesCancel(1, (intptr_t*)&idlong, (float*)&x, (float*)&y); + }); + return; + } + + jint id[size]; + std::vector x; x.resize(size); + std::vector y; y.resize(size); + + env->GetIntArrayRegion(ids, 0, size, id); + env->GetFloatArrayRegion(xs, 0, size, &x[0]); + env->GetFloatArrayRegion(ys, 0, size, &y[0]); + + std::vector idlong; idlong.resize(size); + for (int i = 0; i < size; i++) + idlong[i] = id[i]; + + Android_PushEvents([idlong, x, y](){ + cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesCancel(idlong.size(), (intptr_t*)&idlong[0], (float*)&x[0], (float*)&y[0]); + }); + } + +#define KEYCODE_BACK 0x04 +#define KEYCODE_MENU 0x52 +#define KEYCODE_DPAD_UP 0x13 +#define KEYCODE_DPAD_DOWN 0x14 +#define KEYCODE_DPAD_LEFT 0x15 +#define KEYCODE_DPAD_RIGHT 0x16 +#define KEYCODE_ENTER 0x42 +#define KEYCODE_PLAY 0x7e +#define KEYCODE_DPAD_CENTER 0x17 +#define KEYCODE_DEL 0x43 + + JNIEXPORT jboolean JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeKeyAction(JNIEnv * env, jclass cls, jint keyCode, jboolean isPress) { + cocos2d::EventKeyboard::KeyCode pKeyCode; + switch (keyCode) { + case KEYCODE_BACK : pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_ESCAPE ; break; + case KEYCODE_MENU : pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_MENU ; break; + case KEYCODE_DPAD_UP : pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_DPAD_UP ; break; + case KEYCODE_DPAD_DOWN : pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_DPAD_DOWN ; break; + case KEYCODE_DPAD_LEFT : pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_DPAD_LEFT ; break; + case KEYCODE_DPAD_RIGHT : pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_DPAD_RIGHT; break; + case KEYCODE_ENTER : pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_ENTER ; break; + case KEYCODE_PLAY : pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_PLAY ; break; + case KEYCODE_DPAD_CENTER: pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_DPAD_CENTER; break; + case KEYCODE_DEL : pKeyCode = cocos2d::EventKeyboard::KeyCode::KEY_BACKSPACE; break; + default: return JNI_FALSE; + } + + Android_PushEvents([pKeyCode, isPress](){ + cocos2d::EventKeyboard event(pKeyCode, isPress); + cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(&event); + }); + return JNI_TRUE; + } + + JNIEXPORT void JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeInsertText(JNIEnv* env, jclass cls, jstring text) { + const char* pszText = env->GetStringUTFChars(text, NULL); + if (pszText && *pszText) { + std::string str = pszText; + Android_PushEvents([str](){ + cocos2d::IMEDispatcher::sharedDispatcher()->dispatchInsertText(str.c_str(), str.length()); + }); + } + env->ReleaseStringUTFChars(text, pszText); + } + + JNIEXPORT void JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeDeleteBackward(JNIEnv* env, jclass cls) { + Android_PushEvents(std::bind(&cocos2d::IMEDispatcher::dispatchDeleteBackward, + cocos2d::IMEDispatcher::sharedDispatcher())); + } + + JNIEXPORT void JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeCharInput(JNIEnv* env, jclass cls, jint keyCode) { + TVPMainScene *pScene = TVPMainScene::GetInstance(); + if (!pScene) return; + pScene->getScheduler()->performFunctionInCocosThread(std::bind(&TVPMainScene::onCharInput, keyCode)); + } + + JNIEXPORT void JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeCommitText( + JNIEnv* env, jclass cls, + jstring text, jint newCursorPosition) + { + TVPMainScene *pScene = TVPMainScene::GetInstance(); + if (!pScene) return; + const char *utftext = env->GetStringUTFChars(text, NULL); + std::string str(utftext); + pScene->getScheduler()->performFunctionInCocosThread(std::bind(&TVPMainScene::onTextInput, str)); + env->ReleaseStringUTFChars(text, utftext); + } + + JNIEXPORT jboolean JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeGetHideSystemButton(JNIEnv* env, jclass cls) + { + return GlobalConfigManager::GetInstance()->GetValue("hide_android_sys_btn", false); + } + + static float _mouseX, _mouseY; + + JNIEXPORT jboolean JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeHoverMoved(JNIEnv* env, jclass cls, jfloat x, jfloat y) + { + Android_PushEvents([x, y]() { + cocos2d::GLView *glview = cocos2d::Director::getInstance()->getOpenGLView(); + float _scaleX = glview->getScaleX(), _scaleY = glview->getScaleY(); + _mouseX = x; _mouseY = y; + const cocos2d::Rect _viewPortRect = glview->getViewPortRect(); + + float cursorX = (_mouseX - _viewPortRect.origin.x) / _scaleX; + float cursorY = (_viewPortRect.origin.y + _viewPortRect.size.height - _mouseY) / _scaleY; + + cocos2d::EventMouse event(cocos2d::EventMouse::MouseEventType::MOUSE_MOVE); + event.setCursorPosition(cursorX, cursorY); + cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(&event); + }); + return true; + } + + JNIEXPORT jboolean JNICALL Java_org_tvp_kirikiri2_KR2Activity_nativeMouseScrolled(JNIEnv* env, jclass cls, jfloat v) + { + Android_PushEvents([v]() { + cocos2d::GLView *glview = cocos2d::Director::getInstance()->getOpenGLView(); + float _scaleX = glview->getScaleX(), _scaleY = glview->getScaleY(); + const cocos2d::Rect _viewPortRect = glview->getViewPortRect(); + + float cursorX = (_mouseX - _viewPortRect.origin.x) / _scaleX; + float cursorY = (_viewPortRect.origin.y + _viewPortRect.size.height - _mouseY) / _scaleY; + + cocos2d::EventMouse event(cocos2d::EventMouse::MouseEventType::MOUSE_SCROLL); + event.setScrollData(0, v); + event.setCursorPosition(cursorX, cursorY); + cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(&event); + }); + return true; + } + +} \ No newline at end of file diff --git a/project/android/project.properties b/project/android/project.properties new file mode 100644 index 00000000..7f89e8a8 --- /dev/null +++ b/project/android/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-22 +android.library.reference.1=../../vendor/cocos2d-x/current/cocos/platform/android/java diff --git a/project/android/src/org/tvp/kirikiri2/KR2Activity.java b/project/android/src/org/tvp/kirikiri2/KR2Activity.java new file mode 100644 index 00000000..dc35e694 --- /dev/null +++ b/project/android/src/org/tvp/kirikiri2/KR2Activity.java @@ -0,0 +1,1229 @@ +package org.tvp.kirikiri2; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import org.cocos2dx.lib.Cocos2dxActivity; +import org.cocos2dx.lib.Cocos2dxGLSurfaceView; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.ActivityManager; +import android.app.AlertDialog; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.database.Cursor; +import android.graphics.PixelFormat; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Debug; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; +import android.os.storage.StorageManager; +import android.preference.PreferenceManager; +import android.provider.BaseColumns; +import android.provider.MediaStore; +import android.provider.MediaStore.MediaColumns; +import android.provider.Settings.Secure; +import android.support.annotation.NonNull; +import android.support.v4.provider.DocumentFile; +import android.telephony.TelephonyManager; +import android.util.AttributeSet; +import android.util.Log; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.inputmethod.BaseInputConnection; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +/** + * Utility class for handling the media store. + */ +abstract class MediaStoreUtil { + public static Uri getUriFromFile(final String path,Context context) { + ContentResolver resolver = context.getContentResolver(); + + Cursor filecursor = resolver.query(MediaStore.Files.getContentUri("external"), + new String[] { BaseColumns._ID }, MediaColumns.DATA + " = ?", + new String[] { path }, MediaColumns.DATE_ADDED + " desc"); + filecursor.moveToFirst(); + + if (filecursor.isAfterLast()) { + filecursor.close(); + ContentValues values = new ContentValues(); + values.put(MediaColumns.DATA, path); + return resolver.insert(MediaStore.Files.getContentUri("external"), values); + } + else { + int imageId = filecursor.getInt(filecursor.getColumnIndex(BaseColumns._ID)); + Uri uri = MediaStore.Files.getContentUri("external").buildUpon().appendPath( + Integer.toString(imageId)).build(); + filecursor.close(); + return uri; + } + } + + public static final void addFileToMediaStore(final String path,Context context) { + Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + File file = new File(path); + Uri contentUri = Uri.fromFile(file); + mediaScanIntent.setData(contentUri); + context.sendBroadcast(mediaScanIntent); + } + + /** + * Retrieve a thumbnail of a bitmap from the mediastore. + * + * @param path + * The path of the image + * @param maxSize + * The maximum size of this bitmap (used for selecting the sample size) + * @return the thumbnail. + */ + + /** + * Delete the thumbnail of a bitmap. + * + * @param path + * The path of the image + */ + +} + +/* This is a fake invisible editor view that receives the input and defines the + * pan&scan region + */ +class DummyEdit extends View implements View.OnKeyListener { + InputConnection ic; + + public DummyEdit(Context context) { + super(context); + setFocusableInTouchMode(true); + setFocusable(true); + setOnKeyListener(this); + } + + @Override + public boolean onCheckIsTextEditor() { + return true; + } + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + + // This handles the hardware keyboard input + if (event.isPrintingKey()) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1); + } + return true; + } + +// if (event.getAction() == KeyEvent.ACTION_DOWN) { +// KR2Activity.nativeKeyAction(keyCode, true); +// return true; +// } else if (event.getAction() == KeyEvent.ACTION_UP) { +// KR2Activity.nativeKeyAction(keyCode, false); +// return true; +// } + + return false; + } + + // + @Override + public boolean onKeyPreIme (int keyCode, KeyEvent event) { + // As seen on StackOverflow: http://stackoverflow.com/questions/7634346/keyboard-hide-event + // FIXME: Discussion at http://bugzilla.libsdl.org/show_bug.cgi?id=1639 + // FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not + // FIXME: A more effective solution would be to change our Layout from AbsoluteLayout to Relative or Linear + // FIXME: And determine the keyboard presence doing this: http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android + // FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :) + if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { + if (KR2Activity.mTextEdit != null && KR2Activity.mTextEdit.getVisibility() == View.VISIBLE) { + KR2Activity.hideTextInput(); + //KR2Activity.nativeKeyboardFocusLost(); + } + } + return super.onKeyPreIme(keyCode, event); + } + + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + ic = new SDLInputConnection(this, true); + + outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI + | 33554432 /* API 11: EditorInfo.IME_FLAG_NO_FULLSCREEN */; + + return ic; + } +} + +class SDLInputConnection extends BaseInputConnection { + + public SDLInputConnection(View targetView, boolean fullEditor) { + super(targetView, fullEditor); + + } + + @Override + public boolean sendKeyEvent(KeyEvent event) { + /* + * This handles the keycodes from soft keyboard (and IME-translated + * input from hardkeyboard) + */ + int keyCode = event.getKeyCode(); + if (event.getAction() == KeyEvent.ACTION_DOWN) { + if (event.isPrintingKey()) { + commitText(String.valueOf((char) event.getUnicodeChar()), 1); + KR2Activity.nativeCharInput(keyCode); + } else if(keyCode == KeyEvent.KEYCODE_DEL) { + KR2Activity.nativeKeyAction(keyCode, true); + } + return true; + } else if (event.getAction() == KeyEvent.ACTION_UP) { + if(keyCode == KeyEvent.KEYCODE_DEL) { + KR2Activity.nativeKeyAction(keyCode, false); + } + //KR2Activity.nativeKeyAction(keyCode, false); + return true; + } + return super.sendKeyEvent(event); + } + + @Override + public boolean commitText(CharSequence text, int newCursorPosition) { + + KR2Activity.nativeCommitText(text.toString(), newCursorPosition); + + return super.commitText(text, newCursorPosition); + } + + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition) { + + //nativeSetComposingText(text.toString(), newCursorPosition); + + return super.setComposingText(text, newCursorPosition); + } + + //public native void nativeSetComposingText(String text, int newCursorPosition); + + @Override + public boolean deleteSurroundingText(int beforeLength, int afterLength) { + // Workaround to capture backspace key. Ref: http://stackoverflow.com/questions/14560344/android-backspace-in-webview-baseinputconnection + if (beforeLength == 1 && afterLength == 0) { + // backspace + return super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)) + && super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL)); + } + + return super.deleteSurroundingText(beforeLength, afterLength); + } +} + +public class KR2Activity extends Cocos2dxActivity { + static ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); + static ActivityManager mAcitivityManager = null; + static Debug.MemoryInfo mDbgMemoryInfo = new Debug.MemoryInfo(); + public static void updateMemoryInfo() { + if(mAcitivityManager == null) { + mAcitivityManager =(ActivityManager)sInstance.getSystemService(Activity.ACTIVITY_SERVICE); + } + mAcitivityManager.getMemoryInfo(memoryInfo); + Debug.getMemoryInfo(mDbgMemoryInfo); + } + + public static long getAvailMemory() { + return memoryInfo.availMem; + } + + public static long getUsedMemory() { + return mDbgMemoryInfo.getTotalPss(); // in kB + } + + static public String getDeviceId() { + TelephonyManager mgr = (TelephonyManager)GetInstance().getSystemService(Context.TELEPHONY_SERVICE); + String DeviceID = mgr.getDeviceId(); + if(DeviceID != null) { + return "DevID:" + DeviceID; + } + String androidId = Secure.getString(GetInstance().getContentResolver(), Secure.ANDROID_ID); + if (null != androidId && androidId.length() > 8 && + (!"9774d56d682e549c".equals(androidId)) ) { + return "AndroidID:" + androidId; + } else if(null != android.os.Build.SERIAL && android.os.Build.SERIAL.length() > 3) { + return "AndroidID:" + android.os.Build.SERIAL; + } + return ""; + } + + static public KR2Activity sInstance; + static public KR2Activity GetInstance() {return sInstance;} + + static { + System.loadLibrary("ffmpeg"); + System.loadLibrary("game"); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + sInstance = this; + Sp = PreferenceManager.getDefaultSharedPreferences(this); + super.onCreate(savedInstanceState); + + if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) { + for(String path : getExtSdCardPaths(this)) { + if (!isWritableNormalOrSaf(path)) { + guideDialogForLEXA(path); + } + } + } + + initDump(this.getFilesDir().getAbsolutePath() + "/dump"); + } + + @Override + public void onDestroy() { + super.onDestroy(); + System.exit(0); + } + + static class DialogMessage + { + public String Title; + public String Text; + public String[] Buttons; + public EditText TextEditor = null; + + public DialogMessage() + { + } + + public void Init(final String title, final String text, final String[] buttons) + { + this.Title = title; + this.Text = text; + this.Buttons = buttons; + } + + void onButtonClick(int n) { + if(TextEditor != null) { + onMessageBoxText(TextEditor.getText().toString()); + } + onMessageBoxOK(n); + } + + public AlertDialog.Builder CreateBuilder() { + /* TextView showText = new TextView(sInstance); + showText.setText(Text); + if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) + showText.setTextIsSelectable(true);*/ + AlertDialog.Builder builder = new AlertDialog.Builder(sInstance). + setTitle(Title). + setMessage(Text). + //setView(showText). + setCancelable(false); + if(Buttons.length >= 1) { + builder = builder.setPositiveButton(Buttons[0], new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onButtonClick(0); + } + }); + } + if(Buttons.length >= 2) { + builder = builder.setNeutralButton(Buttons[1], new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onButtonClick(1); + } + }); + } + if(Buttons.length >= 3) { + builder = builder.setNegativeButton(Buttons[2], new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onButtonClick(2); + } + }); + } + return builder; + } + + public void ShowMessageBox() + { + CreateBuilder().create().show(); + } + + public void ShowInputBox(final String text) { + AlertDialog.Builder builder = CreateBuilder(); + TextEditor = new EditText(sInstance); + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT); + TextEditor.setLayoutParams(lp); + TextEditor.setText(text); + builder.setView(TextEditor); + AlertDialog ad = builder.create(); + ad.show(); + TextEditor.requestFocus(); + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(TextEditor, 0); + } + } + static DialogMessage mDialogMessage = new DialogMessage(); + + protected static View mTextEdit = null; + SharedPreferences Sp; + + static Handler msgHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + sInstance.handleMessage(msg); + } + }; + + public void handleMessage(Message msg) { + + } + + static public void ShowMessageBox(final String title, final String text, final String[] Buttons) { + mDialogMessage.Init(title, text, Buttons); + msgHandler.post(new Runnable() { + @Override + public void run() { + mDialogMessage.ShowMessageBox(); + } + }); + } + + static public void ShowInputBox(final String title, final String prompt, final String text, final String[] Buttons) { + mDialogMessage.Init(title, prompt, Buttons); + msgHandler.post(new Runnable() { + @Override + public void run() { + mDialogMessage.ShowInputBox(text); + } + }); + } + + static class ShowTextInputTask implements Runnable { + /* + * This is used to regulate the pan&scan method to have some offset from + * the bottom edge of the input region and the top edge of an input + * method (soft keyboard) + */ + static final int HEIGHT_PADDING = 15; + + public int x, y, w, h; + + public ShowTextInputTask(int x, int y, int w, int h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + } + + @Override + public void run() { + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(w, h + HEIGHT_PADDING); + params.leftMargin = x; + params.topMargin = y; + + if (mTextEdit == null) { + mTextEdit = new DummyEdit(getContext()); + + sInstance.mFrameLayout.addView(mTextEdit, params); + } else { + mTextEdit.setLayoutParams(params); + } + + mTextEdit.setVisibility(View.VISIBLE); + mTextEdit.requestFocus(); + + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(mTextEdit, 0); + } + } + + static public void showTextInput(int x, int y, int w, int h) { + msgHandler.post(new ShowTextInputTask(x, y, w, h)); + } + static public void hideTextInput() { + msgHandler.post(new Runnable() { + @Override + public void run() { + if (mTextEdit != null) { + mTextEdit.setVisibility(View.GONE); + InputMethodManager imm = (InputMethodManager) sInstance.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0); + } + } + }); + } + + static private native void onMessageBoxOK(int nButton); + static private native void onMessageBoxText(String text); + static private native void onNativeExit(); + static public native void onNativeInit(); + static public native void onBannerSizeChanged(int w, int h); + static private native void initDump(String path); + + static public void MessageController(int what, int arg1, int arg2) { + Message msg = msgHandler.obtainMessage(); + msg.what = what; + msg.arg1 = arg1; + msg.arg2 = arg2; + msgHandler.sendMessage(msg); + } + + static public String GetVersion() { + String verstr = null; + try { + verstr = sInstance.getPackageManager().getPackageInfo(sInstance.getPackageName(), 0).versionName; + } catch (NameNotFoundException e1) { + } + return verstr; + } + + StorageManager mStorageManager = null; + Method mMethodGetPaths = null; + Method mGetVolumeState = null; + + public String[] getStoragePath() { + String[] ret = new String[0]; + if(mStorageManager == null) { + mStorageManager = (StorageManager)getSystemService(STORAGE_SERVICE); + try { + mMethodGetPaths = StorageManager.class.getMethod("getVolumePaths"); + mGetVolumeState = StorageManager.class.getMethod("getVolumeState", String.class); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + if(mMethodGetPaths != null) { + try { + ret = (String[])mMethodGetPaths.invoke(mStorageManager); + } catch (IllegalArgumentException e) { + + } catch (IllegalAccessException e) { + + } catch (InvocationTargetException e) { + + } catch (Exception e) { + + } + } + + if(mGetVolumeState != null) { + try { + for(int i = 0; i < ret.length; ++i) { + String status = (String)mGetVolumeState.invoke(mStorageManager, ret[i]); + if(Environment.MEDIA_MOUNTED.equals(status) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status)) { + ; + } else { + ret[i] = null; + } + } + } catch (IllegalArgumentException e) { + + } catch (IllegalAccessException e) { + + } catch (InvocationTargetException e) { + + } catch (Exception e) { + + } + } + + return ret; + } + + private static native void nativeTouchesBegin(final int id, final float x, final float y); + private static native void nativeTouchesEnd(final int id, final float x, final float y); + private static native void nativeTouchesMove(final int[] ids, final float[] xs, final float[] ys); + private static native void nativeTouchesCancel(final int[] ids, final float[] xs, final float[] ys); + public static native boolean nativeKeyAction(final int keyCode, final boolean isPress); + public static native void nativeCharInput(final int keyCode); + public static native void nativeCommitText(String text, int newCursorPosition); + + private static native void nativeInsertText(final String text); + public static native void nativeDeleteBackward(); + private static native String nativeGetContentText(); + private static native void nativeHoverMoved(final float x, final float y); + private static native void nativeMouseScrolled(final float scroll); + + class KR2GLSurfaceView extends Cocos2dxGLSurfaceView { + + public KR2GLSurfaceView(final Context context) { + super(context); + } + + public KR2GLSurfaceView(final Context context, final AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void insertText(final String pText) { + nativeInsertText(pText); + } + + @Override + public void deleteBackward() { + nativeDeleteBackward(); + } + + @Override + public boolean onKeyDown(final int pKeyCode, final KeyEvent pKeyEvent) { + switch (pKeyCode) { + case KeyEvent.KEYCODE_BACK: + case KeyEvent.KEYCODE_MENU: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_ENTER: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_DPAD_CENTER: + nativeKeyAction(pKeyCode, true); + return true; + default: + return super.onKeyDown(pKeyCode, pKeyEvent); + } + } + + @Override + public boolean onKeyUp(final int pKeyCode, final KeyEvent pKeyEvent) { + switch (pKeyCode) { + case KeyEvent.KEYCODE_BACK: + case KeyEvent.KEYCODE_MENU: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_ENTER: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_DPAD_CENTER: + nativeKeyAction(pKeyCode, false); + return true; + default: + return super.onKeyUp(pKeyCode, pKeyEvent); + } + } + + @Override + public boolean onHoverEvent(final MotionEvent pMotionEvent) { + final int pointerNumber = pMotionEvent.getPointerCount(); + final float[] xs = new float[pointerNumber]; + final float[] ys = new float[pointerNumber]; + for (int i = 0; i < pointerNumber; i++) { + xs[i] = pMotionEvent.getX(i); + ys[i] = pMotionEvent.getY(i); + } + + switch(pMotionEvent.getActionMasked()) { + case MotionEvent.ACTION_HOVER_MOVE: + nativeHoverMoved(xs[0], ys[0]); + break; + } + return true; + } + + @Override + public boolean onTouchEvent(final MotionEvent pMotionEvent) { + + // these data are used in ACTION_MOVE and ACTION_CANCEL + final int pointerNumber = pMotionEvent.getPointerCount(); + final int[] ids = new int[pointerNumber]; + final float[] xs = new float[pointerNumber]; + final float[] ys = new float[pointerNumber]; + + for (int i = 0; i < pointerNumber; i++) { + ids[i] = pMotionEvent.getPointerId(i); + xs[i] = pMotionEvent.getX(i); + ys[i] = pMotionEvent.getY(i); + } + + switch (pMotionEvent.getAction() & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_POINTER_DOWN: + final int indexPointerDown = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int idPointerDown = pMotionEvent.getPointerId(indexPointerDown); + final float xPointerDown = pMotionEvent.getX(indexPointerDown); + final float yPointerDown = pMotionEvent.getY(indexPointerDown); + nativeTouchesBegin(idPointerDown, xPointerDown, yPointerDown); + break; + + case MotionEvent.ACTION_DOWN: + // there are only one finger on the screen + final int idDown = pMotionEvent.getPointerId(0); + final float xDown = xs[0]; + final float yDown = ys[0]; + nativeTouchesBegin(idDown, xDown, yDown); + break; + + case MotionEvent.ACTION_MOVE: + nativeTouchesMove(ids, xs, ys); + break; + + case MotionEvent.ACTION_POINTER_UP: + final int indexPointUp = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int idPointerUp = pMotionEvent.getPointerId(indexPointUp); + final float xPointerUp = pMotionEvent.getX(indexPointUp); + final float yPointerUp = pMotionEvent.getY(indexPointUp); + nativeTouchesEnd(idPointerUp, xPointerUp, yPointerUp); + break; + + case MotionEvent.ACTION_UP: + // there are only one finger on the screen + final int idUp = pMotionEvent.getPointerId(0); + final float xUp = xs[0]; + final float yUp = ys[0]; + nativeTouchesEnd(idUp, xUp, yUp); + break; + + case MotionEvent.ACTION_CANCEL: + nativeTouchesCancel(ids, xs, ys); + break; + } + + /* + if (BuildConfig.DEBUG) { + Cocos2dxGLSurfaceView.dumpMotionEvent(pMotionEvent); + } + */ + return true; + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override + public boolean onGenericMotionEvent(MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_SCROLL: + float v = event.getAxisValue(MotionEvent.AXIS_VSCROLL); + nativeMouseScrolled(-v); + return true; + default: + break; + } + return super.onGenericMotionEvent(event); + } + } + + @Override + public Cocos2dxGLSurfaceView onCreateView() { + Cocos2dxGLSurfaceView glSurfaceView = new KR2GLSurfaceView(this); + hideSystemUI(); + //this line is need on some device if we specify an alpha bits + if(this.mGLContextAttrs[3] > 0) glSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT); + + Cocos2dxEGLConfigChooser chooser = new Cocos2dxEGLConfigChooser(this.mGLContextAttrs); + glSurfaceView.setEGLConfigChooser(chooser); + + return glSurfaceView; + } + + public int get_res_sd_operate_step() { return -1; } + + void guideDialogForLEXA(String path) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + ImageView image = new ImageView(this); + image.setImageResource(get_res_sd_operate_step()); + builder + .setView(image) + .setTitle(path) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + triggerStorageAccessFramework(); + } + }) + .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // nothing to do + } + }) + .show(); + } + + static final boolean isWritable(final File file) { + if(file==null) + return false; + boolean isExisting = file.exists(); + + try { + FileOutputStream output = new FileOutputStream(file, true); + try { + output.close(); + } + catch (IOException e) { + // do nothing. + } + } + catch (FileNotFoundException e) { + return false; + } + boolean result = file.canWrite(); + + // Ensure that file is not created during this process. + if (!isExisting) { + file.delete(); + } + + return result; + } + + static final boolean isWritableNormalOrSaf(final String path) { + Context c = sInstance; + File folder = new File(path); + if (!folder.exists() || !folder.isDirectory()) { + return false; + } + + // Find a non-existing file in this directory. + int i = 0; + File file; + do { + String fileName = "AugendiagnoseDummyFile" + (++i); + file = new File(folder, fileName); + } + while (file.exists()); + + // First check regular writability + if (isWritable(file)) { + return true; + } + + // Next check SAF writability. + DocumentFile document = getDocumentFile(file, false,c); + + if (document == null) { + return false; + } + + // This should have created the file - otherwise something is wrong with access URL. + boolean result = document.canWrite() && file.exists(); + + // Ensure that the dummy file is not remaining. + document.delete(); + + return result; + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + private static String[] getExtSdCardPaths(Context context) { + List paths = new ArrayList(); + for (File file : context.getExternalFilesDirs("external")) { + if (file != null && !file.equals(context.getExternalFilesDir("external"))) { + int index = file.getAbsolutePath().lastIndexOf("/Android/data"); + if (index < 0) { + Log.w("FileUtils", "Unexpected external file dir: " + file.getAbsolutePath()); + } else { + String path = file.getAbsolutePath().substring(0, index); + try { + path = new File(path).getCanonicalPath(); + } + catch (IOException e) { + // Keep non-canonical path. + } + paths.add(path); + } + } + } + //if(paths.isEmpty())paths.add("/storage/sdcard1"); + return paths.toArray(new String[0]); + } + static String[] _extSdPaths; + + public static String getExtSdCardFolder(final File file,Context context) { + if(_extSdPaths == null) + _extSdPaths = getExtSdCardPaths(context); + try { + for (int i = 0; i < _extSdPaths.length; i++) { + if (file.getCanonicalPath().startsWith(_extSdPaths[i])) { + return _extSdPaths[i]; + } + } + } + catch (IOException e) { + return null; + } + return null; + } + + public static boolean isOnExtSdCard(final File file,Context c) { + return getExtSdCardFolder(file,c) != null; + } + + public static DocumentFile getDocumentFile(final File file, final boolean isDirectory,Context context) { + String baseFolder = getExtSdCardFolder(file,context); + boolean originalDirectory=false; + if (baseFolder == null) { + return null; + } + + String relativePath = null; + try { + String fullPath = file.getCanonicalPath(); + if(!baseFolder.equals(fullPath)) + relativePath = fullPath.substring(baseFolder.length() + 1); + else originalDirectory=true; + } + catch (IOException e) { + return null; + } + catch (Exception f){ + originalDirectory=true; + //continue + } + String as=PreferenceManager.getDefaultSharedPreferences(context).getString("URI",null); + + Uri treeUri =null; + if(as!=null)treeUri=Uri.parse(as); + if (treeUri == null) { + return null; + } + + // start with root of SD card and then parse through document tree. + DocumentFile document = DocumentFile.fromTreeUri(context, treeUri); + if(originalDirectory)return document; + String[] parts = relativePath.split("\\/"); + for (int i = 0; i < parts.length; i++) { + DocumentFile nextDocument = document.findFile(parts[i]); + if (nextDocument == null) { + try { + if ((i < parts.length - 1) || isDirectory) { + nextDocument = document.createDirectory(parts[i]); + } else { + nextDocument = document.createFile("image", parts[i]); + } + } catch (Exception e) { + return null; + } + } + document = nextDocument; + } + + return document; + } + + static public boolean RenameFile(String from, String to) { + File file = new File(from); + File target = new File(to); + if(!file.exists()) + return false; + if(target.exists()) { + if(!DeleteFile(target.getAbsolutePath())) return false; + } + + File parent = target.getParentFile(); + if(!parent.exists()) { + if(!CreateFolders(parent.getAbsolutePath())) return false; + } + // Try the normal way + if(file.renameTo(target)) return true; + + // Try with Storage Access Framework. + if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP /*&& isOnExtSdCard(file, sInstance)*/) { + DocumentFile document = getDocumentFile(file, false, sInstance); + if(document.renameTo(to)) + return true; + } + + // Try Media Store Hack + if (Build.VERSION.SDK_INT==Build.VERSION_CODES.KITKAT) { + try { + FileInputStream input = new FileInputStream(file); + int filesize = (int) file.length(); + byte []buffer = new byte[filesize]; + input.read(buffer); + input.close(); + OutputStream out = MediaStoreHack.getOutputStream(sInstance, target.getAbsolutePath()); + out.write(buffer); + out.close(); + return MediaStoreHack.delete(sInstance, file); + } catch (IOException e) { + // TODO Auto-generated catch block + return false; + //e.printStackTrace(); + } + } + + return false; + } + + public static final boolean deleteFilesInFolder(final File folder,Context context) { + boolean totalSuccess = true; + if(folder==null) + return false; + if (folder.isDirectory()) { + for (File child : folder.listFiles()) { + deleteFilesInFolder(child, context); + } + + if (!folder.delete()) + totalSuccess = false; + } else { + + if (!folder.delete()) + totalSuccess = false; + } + return totalSuccess; + } + + static public boolean DeleteFile(String path) { + File file = new File(path); + // First try the normal deletion. + boolean fileDelete = deleteFilesInFolder(file, sInstance); + if (file.delete() || fileDelete) + return true; + + // Try with Storage Access Framework. + if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP && isOnExtSdCard(file, sInstance)) { + + DocumentFile document = getDocumentFile(file, false,sInstance); + return document.delete(); + } + + // Try the Kitkat workaround. + if (Build.VERSION.SDK_INT==Build.VERSION_CODES.KITKAT) { + ContentResolver resolver = sInstance.getContentResolver(); + + try { + Uri uri = MediaStoreHack.getUriFromFile(file.getAbsolutePath(),sInstance); + resolver.delete(uri, null, null); + return !file.exists(); + } + catch (Exception e) { + Log.e("FileUtils", "Error when deleting file " + file.getAbsolutePath(), e); + return false; + } + } + + return !file.exists(); + } + + public static OutputStream getOutputStream(@NonNull final File target,Context context,long s)throws Exception { + OutputStream outStream = null; + try { + // First try the normal way + if (isWritable(target)) { + // standard way + outStream = new FileOutputStream(target); + } else { + if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) { + // Storage Access Framework + DocumentFile targetDocument = getDocumentFile(target, false,context); + outStream = context.getContentResolver().openOutputStream(targetDocument.getUri()); + } else if (Build.VERSION.SDK_INT==Build.VERSION_CODES.KITKAT) { + // Workaround for Kitkat ext SD card + return MediaStoreHack.getOutputStream(context,target.getPath()); + } + } + } catch (Exception e) { + Log.e("FileUtils", + "Error when copying file from " + target.getAbsolutePath(), e); + } + return outStream; + } + + + static public boolean WriteFile(String path, byte data[]) { + File target = new File(path); + if(target.exists()) { + DeleteFile(target.getAbsolutePath()); // to avoid number suffix name + } else { + File parent = target.getParentFile(); + if(!parent.exists()) + CreateFolders(parent.getAbsolutePath()); + } + OutputStream out = null; + + // Try the normal way + try { + if(isWritable(target)) { + OutputStream os = new FileOutputStream(target); + os.write(data); + os.close(); + return true; + } + + // Try with Storage Access Framework. + if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP /*&& isOnExtSdCard(file, sInstance)*/) { + DocumentFile document = getDocumentFile(target, false, sInstance); + try { + Uri docUri = document.getUri(); + out = sInstance.getContentResolver().openOutputStream(docUri); + } catch (FileNotFoundException e) { + // e.printStackTrace(); + } catch (IOException e) { + // e.printStackTrace(); + } + } else if (Build.VERSION.SDK_INT==Build.VERSION_CODES.KITKAT) { + // Workaround for Kitkat ext SD card + Uri uri = MediaStoreHack.getUriFromFile(target.getAbsolutePath(),sInstance); + out = sInstance.getContentResolver().openOutputStream(uri); + } else { + return false; + } + + if (out != null) { + out.write(data); + out.close(); + return true; + } + } catch (FileNotFoundException e) { + //return false; + } catch (IOException e) { + //return false; + } + + return false; + } + + static public boolean CreateFolders(String path) { + File file = new File(path); + + // Try the normal way + if(file.mkdirs()) { + return true; + } + + // Try with Storage Access Framework. + if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP /*&& FileUtil.isOnExtSdCard(file, context)*/) { + DocumentFile document = getDocumentFile(file, true,sInstance); + // getDocumentFile implicitly creates the directory. + + return document.exists(); + } + + // Try the Kitkat workaround. + if (Build.VERSION.SDK_INT==Build.VERSION_CODES.KITKAT) { + try { + return MediaStoreHack.mkdir(sInstance,file); + } catch (IOException e) { + //return false; + } + } + + return false; + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + + //SDLActivity.mHasFocus = hasFocus; + if (hasFocus) { + hideSystemUI(); + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + void doSetSystemUiVisibility() { + int uiOpts = View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + getWindow().getDecorView().setSystemUiVisibility(uiOpts); + } + + private static native boolean nativeGetHideSystemButton(); + void hideSystemUI() { + if(nativeGetHideSystemButton() && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + doSetSystemUiVisibility(); + } + } + + static public String getLocaleName() { + Locale defloc = Locale.getDefault(); + String lang = defloc.getLanguage(); + String country = defloc.getCountry(); + if(!country.isEmpty()) { + lang += "_"; + lang += country.toLowerCase(); + } + return lang; + } + + static public void exit() { + System.exit(0); + } + + static final int ORIENT_VERTICAL = 1; + static final int ORIENT_HORIZONTAL = 2; + + static public void setOrientation(int orient) { + if(orient == ORIENT_VERTICAL) { + sInstance.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } else if(orient == ORIENT_HORIZONTAL) { + sInstance.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + static public void triggerStorageAccessFramework() { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); + sInstance.startActivityForResult(intent, 3); + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + protected void onActivityResult(int requestCode, int responseCode, Intent intent) { + if (requestCode == 3) { + String p = Sp.getString("URI", null); + Uri oldUri = null; + if (p != null) oldUri = Uri.parse(p); + Uri treeUri = null; + if (responseCode == Activity.RESULT_OK) { + // Get Uri from Storage Access Framework. + treeUri = intent.getData(); + // Persist URI - this is required for verification of writability. + if (treeUri != null) Sp.edit().putString("URI", treeUri.toString()).commit(); + } + + // If not confirmed SAF, or if still not writable, then revert settings. + if (responseCode != Activity.RESULT_OK) { + /* DialogUtil.displayError(getActivity(), R.string.message_dialog_cannot_write_to_folder_saf, false, + currentFolder);||!FileUtil.isWritableNormalOrSaf(currentFolder) +*/ + if (treeUri != null) Sp.edit().putString("URI", oldUri.toString()).commit(); + return; + } + + // After confirmation, update stored value of folder. + // Persist access permissions. + final int takeFlags = intent.getFlags() + & (Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + getContentResolver().takePersistableUriPermission(treeUri, takeFlags); + } + } + +} diff --git a/project/android/src/org/tvp/kirikiri2/Kirikiroid2.java b/project/android/src/org/tvp/kirikiri2/Kirikiroid2.java new file mode 100644 index 00000000..1c8bc53e --- /dev/null +++ b/project/android/src/org/tvp/kirikiri2/Kirikiroid2.java @@ -0,0 +1,28 @@ +package org.tvp.kirikiri2; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.Date; + +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; + +public class Kirikiroid2 extends KR2Activity { + + @Override + public int get_res_sd_operate_step() { return R.drawable.sd_operate_step; } +} diff --git a/project/android/src/org/tvp/kirikiri2/MediaStoreHack.java b/project/android/src/org/tvp/kirikiri2/MediaStoreHack.java new file mode 100644 index 00000000..f8d64643 --- /dev/null +++ b/project/android/src/org/tvp/kirikiri2/MediaStoreHack.java @@ -0,0 +1,488 @@ +package org.tvp.kirikiri2; + +/** + * Created by Arpit on 29-06-2015. + */ +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Locale; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.ParcelFileDescriptor; +import android.provider.BaseColumns; +import android.provider.MediaStore; +import android.util.Log; + +/** + * Wrapper for manipulating files via the Android Media Content Provider. As of Android 4.4 KitKat, + * applications can no longer write to the "secondary storage" of a device. Write operations using + * the java.io.File API will thus fail. This class restores access to those write operations by way + * of the Media Content Provider.

+ * + * Note that this class relies on the internal operational characteristics of the media content + * provider API, and as such is not guaranteed to be future-proof. Then again, we did all think the + * java.io.File API was going to be future-proof for media card access, so all bets are off.

+ * + * If you're forced to use this class, it's because Google/AOSP made a very poor API decision in + * Android 4.4 KitKat. Read more at https://plus.google.com/+TodLiebeck/posts/gjnmuaDM8sn

+ * + * Your application must declare the permission "android.permission.WRITE_EXTERNAL_STORAGE".

+ * + * Adapted from: http://forum.xda-developers.com/showpost.php?p=52151865&postcount=20

+ * + * @author Jared Rummler + */ +public class MediaStoreHack { + + private static final String ALBUM_ART_URI = "content://media/external/audio/albumart"; + + private static final String[] ALBUM_PROJECTION = { + BaseColumns._ID, MediaStore.Audio.AlbumColumns.ALBUM_ID, "media_type" + }; + + /** + * Deletes the file. Returns true if the file has been successfully deleted or otherwise does + * not exist. This operation is not recursive. + */ + public static boolean delete(final Context context, final File file) { + final String where = MediaStore.MediaColumns.DATA + "=?"; + final String[] selectionArgs = new String[] { + file.getAbsolutePath() + }; + final ContentResolver contentResolver = context.getContentResolver(); + final Uri filesUri = MediaStore.Files.getContentUri("external"); + // Delete the entry from the media database. This will actually delete media files. + contentResolver.delete(filesUri, where, selectionArgs); + // If the file is not a media file, create a new entry. + if (file.exists()) { + final ContentValues values = new ContentValues(); + values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath()); + contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + // Delete the created entry, such that content provider will delete the file. + contentResolver.delete(filesUri, where, selectionArgs); + } + return !file.exists(); + } + + private static File getExternalFilesDir(final Context context) { + return context.getExternalFilesDir(null); + } + + public static InputStream + getInputStream(final Context context, final File file, final long size) { + try { + final String where = MediaStore.MediaColumns.DATA + "=?"; + final String[] selectionArgs = new String[] { + file.getAbsolutePath() + }; + final ContentResolver contentResolver = context.getContentResolver(); + final Uri filesUri = MediaStore.Files.getContentUri("external"); + contentResolver.delete(filesUri, where, selectionArgs); + final ContentValues values = new ContentValues(); + values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath()); + values.put(MediaStore.MediaColumns.SIZE, size); + final Uri uri = contentResolver.insert(filesUri, values); + return contentResolver.openInputStream(uri); + } catch (final Throwable t) { + return null; + } + } + public static OutputStream getOutputStream(Context context,String str) { + OutputStream outputStream = null; + Uri fileUri = getUriFromFile(str,context); + if (fileUri != null) { + try { + outputStream = context.getContentResolver().openOutputStream(fileUri); + } catch (Throwable th) { + } + } + return outputStream; + } + public static Uri getUriFromFile(final String path,Context context) { + ContentResolver resolver = context.getContentResolver(); + + Cursor filecursor = resolver.query(MediaStore.Files.getContentUri("external"), + new String[] { BaseColumns._ID }, MediaStore.MediaColumns.DATA + " = ?", + new String[] { path }, MediaStore.MediaColumns.DATE_ADDED + " desc"); + filecursor.moveToFirst(); + + if (filecursor.isAfterLast()) { + filecursor.close(); + ContentValues values = new ContentValues(); + values.put(MediaStore.MediaColumns.DATA, path); + return resolver.insert(MediaStore.Files.getContentUri("external"), values); + } + else { + int imageId = filecursor.getInt(filecursor.getColumnIndex(BaseColumns._ID)); + Uri uri = MediaStore.Files.getContentUri("external").buildUpon().appendPath( + Integer.toString(imageId)).build(); + filecursor.close(); + return uri; + } + } + + /** + * Returns an OutputStream to write to the file. The file will be truncated immediately. + */ + + private static int getTemporaryAlbumId(final Context context) { + final File temporaryTrack; + try { + temporaryTrack = installTemporaryTrack(context); + } catch (final IOException ex) { + Log.w("MediaFile", "Error installing tempory track.", ex); + return 0; + } + final Uri filesUri = MediaStore.Files.getContentUri("external"); + final String[] selectionArgs = { + temporaryTrack.getAbsolutePath() + }; + final ContentResolver contentResolver = context.getContentResolver(); + Cursor cursor = contentResolver.query(filesUri, ALBUM_PROJECTION, + MediaStore.MediaColumns.DATA + "=?", selectionArgs, null); + if (cursor == null || !cursor.moveToFirst()) { + if (cursor != null) { + cursor.close(); + cursor = null; + } + final ContentValues values = new ContentValues(); + values.put(MediaStore.MediaColumns.DATA, temporaryTrack.getAbsolutePath()); + values.put(MediaStore.MediaColumns.TITLE, "{MediaWrite Workaround}"); + values.put(MediaStore.MediaColumns.SIZE, temporaryTrack.length()); + values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mpeg"); + values.put(MediaStore.Audio.AudioColumns.IS_MUSIC, true); + contentResolver.insert(filesUri, values); + } + cursor = contentResolver.query(filesUri, ALBUM_PROJECTION, MediaStore.MediaColumns.DATA + + "=?", selectionArgs, null); + if (cursor == null) { + return 0; + } + if (!cursor.moveToFirst()) { + cursor.close(); + return 0; + } + final int id = cursor.getInt(0); + final int albumId = cursor.getInt(1); + final int mediaType = cursor.getInt(2); + cursor.close(); + final ContentValues values = new ContentValues(); + boolean updateRequired = false; + if (albumId == 0) { + values.put(MediaStore.Audio.AlbumColumns.ALBUM_ID, 13371337); + updateRequired = true; + } + if (mediaType != 2) { + values.put("media_type", 2); + updateRequired = true; + } + if (updateRequired) { + contentResolver.update(filesUri, values, BaseColumns._ID + "=" + id, null); + } + cursor = contentResolver.query(filesUri, ALBUM_PROJECTION, MediaStore.MediaColumns.DATA + + "=?", selectionArgs, null); + if (cursor == null) { + return 0; + } + try { + if (!cursor.moveToFirst()) { + return 0; + } + return cursor.getInt(1); + } finally { + cursor.close(); + } + } + + private static final byte [] temptrack_mp3 = new byte [] { + 73, 68, 51, 4, 0, 0, 0, 0, 8, 65, 84, 80, 69, 49, 0, 0, + 0, 24, 0, 0, 0, 123, 77, 101, 100, 105, 97, 87, 114, 105, 116, 101, + 32, 87, 111, 114, 107, 97, 114, 111, 117, 110, 100, 125, 84, 65, 76, 66, + 0, 0, 0, 24, 0, 0, 0, 123, 77, 101, 100, 105, 97, 87, 114, 105, + 116, 101, 32, 87, 111, 114, 107, 97, 114, 111, 117, 110, 100, 125, 84, 73, + 84, 50, 0, 0, 0, 24, 0, 0, 0, 123, 77, 101, 100, 105, 97, 87, + 114, 105, 116, 101, 32, 87, 111, 114, 107, 97, 114, 111, 117, 110, 100, 125, + 65, 80, 73, 67, 0, 0, 2, 33, 0, 0, 0, 105, 109, 97, 103, 101, + 47, 112, 110, 103, 0, 3, 0, -119, 80, 78, 71, 13, 10, 26, 10, 0, + 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 32, 0, 0, 0, 32, 8, + 2, 0, 0, 0, -4, 24, -19, -93, 0, 0, 0, 1, 115, 82, 71, 66, + 0, -82, -50, 28, -23, 0, 0, 0, -50, 73, 68, 65, 84, 72, -57, -19, + 85, -55, 10, -128, 64, 8, 77, -1, -1, -97, -19, 48, 36, -30, 62, 83, + -76, 64, 30, 66, -59, -52, 124, 79, -35, -74, 95, -34, 38, 68, 68, 68, + 82, 81, -2, -95, -69, 78, 25, 31, 102, 87, -70, 124, 70, -2, 40, 114, + 8, 74, 3, 0, -22, 42, 76, 77, 0, -112, 4, -96, -78, 59, -33, -112, + 1, 101, 60, 90, 0, -72, 34, -42, 71, 22, 78, 20, -107, 92, -2, -51, + 45, 20, -78, 96, 42, -14, -48, 33, 74, -17, 98, 96, 69, 117, -103, -101, + -58, -26, 28, -56, -106, 106, 121, 103, 75, 70, -96, 11, 84, -97, 39, 37, + -86, -24, -66, -48, 39, 67, 107, -128, -97, 100, 81, -78, 121, 58, 0, -44, + 44, 82, -112, 44, -20, 18, -100, 34, -122, 59, -25, 57, 12, 53, -117, -94, + -103, 96, 61, 31, -123, -126, 69, 35, -53, -45, 27, 102, -115, 72, -10, -94, + 37, -121, -56, 61, -126, -2, -70, 118, -69, -100, 0, -93, -100, 54, 12, -49, + 92, -85, -23, -125, 51, 123, -83, 58, -21, 8, 59, -47, -110, 75, 57, -81, + -66, 70, -71, 95, 46, -111, 29, -73, 67, 31, -101, 122, -93, -81, 8, 0, + 0, 0, 0, 73, 69, 78, 68, -82, 66, 96, -126, 84, 68, 84, 71, 0, + 0, 0, 20, 0, 0, 0, 50, 48, 49, 52, 45, 48, 52, 45, 48, 49, + 84, 50, 49, 58, 51, 57, 58, 51, 53, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -6, -112, -64, 95, + -85, 0, 0, 0, 0, 1, -92, 24, 0, 0, 0, 0, 0, 52, -125, -128, + 0, 0, 76, 65, 77, 69, 51, 46, 57, 51, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 76, 65, 77, 69, 51, 46, 57, 51, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -1, -6, -110, -64, + -26, -97, -59, 3, -64, 0, 1, -92, 0, 0, 0, 0, 0, 0, 52, -128, + 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 76, 65, 77, 69, 51, 46, + 57, 51, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, -1, -6, + -110, -64, -6, -34, -1, -125, -64, 0, 1, -92, 0, 0, 0, 0, 0, 0, + 52, -128, 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 76, 65, 77, 69, + 51, 46, 57, 51, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + -1, -6, -110, -64, -6, -34, -1, -125, -64, 0, 1, -92, 0, 0, 0, 0, + 0, 0, 52, -128, 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 76, 65, + 77, 69, 51, 46, 57, 51, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, -1, -6, -110, -64, -6, -34, -1, -125, -64, 0, 1, -92, 0, 0, + 0, 0, 0, 0, 52, -128, 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 76, 65, 77, 69, 51, 46, 57, 51, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, -1, -6, -110, -64, -6, -34, -1, -125, -64, 0, 1, -92, + 0, 0, 0, 0, 0, 0, 52, -128, 0, 0, 0, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85 + }; + + private static File installTemporaryTrack(final Context context) throws IOException { + final File externalFilesDir = getExternalFilesDir(context); + if (externalFilesDir == null) { + return null; + } + final File temporaryTrack = new File(externalFilesDir, "temptrack.mp3"); + OutputStream out = null; + try { + out = new FileOutputStream(temporaryTrack); + out.write(temptrack_mp3); + } finally { + out.close(); + } + return temporaryTrack; + } + + public static boolean mkdir(final Context context, final File file) throws IOException { + if (file.exists()) { + return file.isDirectory(); + } + final File tmpFile = new File(file, ".MediaWriteTemp"); + final int albumId = getTemporaryAlbumId(context); + if (albumId == 0) { + throw new IOException("Failed to create temporary album id."); + } + final Uri albumUri = Uri.parse(String.format(Locale.US, ALBUM_ART_URI + "/%d", albumId)); + final ContentValues values = new ContentValues(); + values.put(MediaStore.MediaColumns.DATA, tmpFile.getAbsolutePath()); + final ContentResolver contentResolver = context.getContentResolver(); + if (contentResolver.update(albumUri, values, null, null) == 0) { + values.put(MediaStore.Audio.AlbumColumns.ALBUM_ID, albumId); + contentResolver.insert(Uri.parse(ALBUM_ART_URI), values); + } + try { + final ParcelFileDescriptor fd = contentResolver.openFileDescriptor(albumUri, "r"); + fd.close(); + } finally { + delete(context, tmpFile); + } + return file.exists(); + } + + public static boolean mkfile(final Context context, final File file) { + final OutputStream outputStream = getOutputStream(context, file.getPath()); + if (outputStream == null) { + return false; + } + try { + outputStream.close(); + return true; + } catch (final IOException e) { + } + return false; + } + +} diff --git a/src/core/Android.mk b/src/core/Android.mk index 1f86f303..107f84fc 100644 --- a/src/core/Android.mk +++ b/src/core/Android.mk @@ -52,7 +52,6 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/base \ $(LOCAL_PATH)/environ/win32 \ $(LOCAL_PATH)/environ/android \ $(LOCAL_PATH)/environ/sdl \ - $(LOCAL_PATH)/environ/my_vcl \ $(LOCAL_PATH)/msg \ $(LOCAL_PATH)/msg/win32 \ $(LOCAL_PATH)/extension \ diff --git a/src/core/base/ScriptMgnIntf.cpp b/src/core/base/ScriptMgnIntf.cpp index 5bbfe725..7f724c2a 100644 --- a/src/core/base/ScriptMgnIntf.cpp +++ b/src/core/base/ScriptMgnIntf.cpp @@ -52,6 +52,7 @@ #include "BitmapLayerTreeOwner.h" #include "Extension.h" #include "Platform.h" +#include "ConfigManager/LocaleConfigManager.h" //--------------------------------------------------------------------------- // Script system initialization script @@ -880,11 +881,41 @@ bool TVPStartupSuccess = false; //--------------------------------------------------------------------------- void TVPExecuteStartupScript() { + ttstr strPatchError; try { ttstr patch = TVPGetAppPath() + "patch.tjs"; if(TVPIsExistentStorageNoSearch(patch)) - TVPExecuteStorage(patch); - } catch (...) { } + TVPExecuteStorage(patch); + } catch (const TJS::eTJSScriptError &e) { + ttstr &msg = strPatchError; + msg += e.GetMessage(); + const tjs_char *pszBlockName = e.GetBlockName(); + if (pszBlockName && *pszBlockName) { + msg += TJS_W("\n@line("); + tjs_char tmp[34]; + msg += TJS_int_to_str(e.GetSourceLine(), tmp); + msg += TJS_W(") "); + msg += pszBlockName; + } + msg += TJS_W("\n"); + msg += e.GetTrace(); + } catch (const TJS::eTJS &e) { + if (!TVPSystemUninitCalled) + strPatchError = e.GetMessage(); + } catch (const std::exception &e) { + strPatchError = e.what(); + } catch (const char* e) { + strPatchError = e; + } catch (const tjs_char* e) { + strPatchError = e; + } + + if (!strPatchError.IsEmpty()) { + ttstr msg = LocaleConfigManager::GetInstance()->GetText("startup_patch_fail"); + msg += "\n"; + msg += strPatchError; + TVPShowSimpleMessageBox(msg, TVPGetPackageVersionString()); + } // execute "startup.tjs" // try diff --git a/src/core/base/SystemIntf.cpp b/src/core/base/SystemIntf.cpp index 3772e0b9..92a872de 100644 --- a/src/core/base/SystemIntf.cpp +++ b/src/core/base/SystemIntf.cpp @@ -22,7 +22,7 @@ #include "Random.h" #include "ScriptMgnIntf.h" #include "DebugIntf.h" -#include "ConfigManager\LocaleConfigManager.h" +#include "ConfigManager/LocaleConfigManager.h" #include "Platform.h" extern bool TVPStartupSuccess; diff --git a/src/core/base/UtilStreams.cpp b/src/core/base/UtilStreams.cpp index 0d90229f..cac3ac7d 100644 --- a/src/core/base/UtilStreams.cpp +++ b/src/core/base/UtilStreams.cpp @@ -258,17 +258,17 @@ void tTVPMemoryStream::Init() //--------------------------------------------------------------------------- void * tTVPMemoryStream::Alloc(size_t size) { - return malloc(size); + return TJS_malloc(size); } //--------------------------------------------------------------------------- void * tTVPMemoryStream::Realloc(void *orgblock, size_t size) { - return realloc(orgblock, size); + return TJS_realloc(orgblock, size); } //--------------------------------------------------------------------------- void tTVPMemoryStream::Free(void *block) { - free(block); + TJS_free(block); } //--------------------------------------------------------------------------- diff --git a/src/core/base/win32/StorageImpl.cpp b/src/core/base/win32/StorageImpl.cpp index e1153c00..8bf55b4c 100644 --- a/src/core/base/win32/StorageImpl.cpp +++ b/src/core/base/win32/StorageImpl.cpp @@ -36,9 +36,13 @@ #include "dirent.h" #include "TickCount.h" #include +#include #include "win32io.h" #include "combase.h" #include +#ifdef CC_TARGET_OS_IPHONE +#define lseek64 lseek +#endif //--------------------------------------------------------------------------- // tTVPFileMedia @@ -828,13 +832,13 @@ tjs_uint64 TJS_INTF_METHOD tTVPLocalFileStream::Seek(tjs_int64 offset, tjs_int w return MemBuffer->Seek(offset, whence); } return lseek64(Handle, offset, whence); - } +} //--------------------------------------------------------------------------- tjs_uint TJS_INTF_METHOD tTVPLocalFileStream::Read(void *buffer, tjs_uint read_size) { if(MemBuffer) { return MemBuffer->Read(buffer, read_size); -} + } return read(Handle, buffer, read_size); } //--------------------------------------------------------------------------- @@ -842,7 +846,7 @@ tjs_uint TJS_INTF_METHOD tTVPLocalFileStream::Write(const void *buffer, tjs_uint { if(MemBuffer) { return MemBuffer->Write(buffer, write_size); -} + } return write(Handle, buffer, write_size); } //--------------------------------------------------------------------------- @@ -850,7 +854,7 @@ void TJS_INTF_METHOD tTVPLocalFileStream::SetEndOfStorage() { if(MemBuffer) { return MemBuffer->SetEndOfStorage(); -} + } lseek64(Handle, 0, SEEK_END); } //--------------------------------------------------------------------------- diff --git a/src/core/base/win32/SysInitImpl.cpp b/src/core/base/win32/SysInitImpl.cpp index ffd6a9a3..d415a3ca 100644 --- a/src/core/base/win32/SysInitImpl.cpp +++ b/src/core/base/win32/SysInitImpl.cpp @@ -1033,7 +1033,7 @@ void TVPBeforeSystemInit() TVPAddImportantLog(TVPFormatMessage(TVPInfoTotalPhysicalMemory, tjs_int64(TVPTotalPhysMemory))); if (TVPTotalPhysMemory > 256 * 1024 * 1024) { - std::string str = IndividualConfigManager::GetInstance()->GetValueString("memusage", "unlimited"); + std::string str = IndividualConfigManager::GetInstance()->GetValue("memusage", "unlimited"); if (str == ("low")) TVPTotalPhysMemory = 0; // assumes zero else if (str == ("medium")) @@ -1339,11 +1339,11 @@ void TVPAfterSystemInit() } } // check TVPGraphicSplitOperation option - std::string _val = IndividualConfigManager::GetInstance()->GetValueString("renderer", "software"); + std::string _val = IndividualConfigManager::GetInstance()->GetValue("renderer", "software"); if (_val != "software") { TVPGraphicSplitOperationType = gsotNone; } else { - TVPDrawThreadNum = IndividualConfigManager::GetInstance()->GetValueInt("software_draw_thread", 0); + TVPDrawThreadNum = IndividualConfigManager::GetInstance()->GetValue("software_draw_thread", 0); if (TVPGetCommandLine(TJS_W("-gsplit"), &opt)) { ttstr str(opt); diff --git a/src/core/base/win32/SystemImpl.cpp b/src/core/base/win32/SystemImpl.cpp index 3054d229..2fa5553c 100644 --- a/src/core/base/win32/SystemImpl.cpp +++ b/src/core/base/win32/SystemImpl.cpp @@ -784,6 +784,7 @@ extern void TVPDoSaveSystemVariables() try { // hack for save system variable iTJSDispatch2* global = TVPGetScriptDispatch(); + if (!global) return; tTJSVariant var; if (global->PropGet(0, TJS_W("kag"), nullptr, &var, global) == TJS_S_OK && var.Type() == tvtObject) { iTJSDispatch2* kag = var.AsObjectNoAddRef(); diff --git a/src/core/environ/Application.cpp b/src/core/environ/Application.cpp index 454085d4..6197d199 100644 --- a/src/core/environ/Application.cpp +++ b/src/core/environ/Application.cpp @@ -48,6 +48,7 @@ tTVPApplication* Application = new tTVPApplication; std::thread::id TVPMainThreadID; static tTJSCriticalSection _NoMemCallBackCS; static void *_reservedMem = malloc(1024 * 1024 * 4); // 4M reserved mem +static bool _project_startup = false; #define HOOK_MALLOC static void _do_compact() { @@ -459,6 +460,7 @@ tTVPApplication::~tTVPApplication() { // // TTVPWindowForm �̃f�X�g���N�^���Ń��X�g����폜�����͂� // } // windows_list_.clear(); + delete image_load_thread_; } #if 0 struct SEHException { @@ -599,7 +601,7 @@ bool tTVPApplication::StartApplication(ttstr path) { image_load_thread_->Resume(); /*if(TVPProjectDirSelected)*/ TVPInitializeStartupScript(); - + _project_startup = true; // Run(); #if 0 try { @@ -1010,18 +1012,23 @@ void tTVPApplication::FilterUserMessage(const std::functionLoadRequest( owner, bmp, name ); } } + +void tTVPApplication::RegisterActiveEvent(void *host, const std::function& func/*empty = unregister*/) +{ + if (func) + m_activeEvents.emplace(host, func); + else + m_activeEvents.erase(host); +} + #if 0 std::vector* LoadLinesFromFile( const std::wstring& path ) { FILE *fp = NULL; diff --git a/src/core/environ/Application.h b/src/core/environ/Application.h index 2d3f315b..84481128 100644 --- a/src/core/environ/Application.h +++ b/src/core/environ/Application.h @@ -8,6 +8,7 @@ #include #include #include +#include ttstr ExePath(); @@ -32,6 +33,10 @@ enum { enum { mbOK = /*MB_OK*/0x00000000L, }; +enum class eTVPActiveEvent { + onActive, + onDeactive, +}; #if 0 class AcceleratorKey { HACCEL hAccel_; @@ -179,9 +184,14 @@ class tTVPApplication { */ void LoadImageRequest( class iTJSDispatch2 *owner, class tTJSNI_Bitmap* bmp, const ttstr &name ); tTVPAsyncImageLoader* GetAsyncImageLoader() { return image_load_thread_; } + + void RegisterActiveEvent(void *host, const std::function& func/*empty = unregister*/); + +private: std::mutex m_msgQueueLock; std::vector > m_lstUserMsg; + std::map > m_activeEvents; }; std::vector* LoadLinesFromFile( const ttstr& path ); diff --git a/src/core/environ/ConfigManager/GlobalConfigManager.cpp b/src/core/environ/ConfigManager/GlobalConfigManager.cpp index 47949259..5ec01f49 100644 --- a/src/core/environ/ConfigManager/GlobalConfigManager.cpp +++ b/src/core/environ/ConfigManager/GlobalConfigManager.cpp @@ -84,31 +84,39 @@ std::string GlobalConfigManager::GetFilePath() { return TVPGetInternalPreferencePath() + "GlobalPreference.xml"; } -bool iSysConfigManager::GetValueBool(const std::string &name, bool defVal) { +template<> +bool iSysConfigManager::GetValue(const std::string &name, const bool& defVal) { + return !!GetValue(name, defVal); +} + +template<> +int iSysConfigManager::GetValue(const std::string &name, const int& defVal) { auto it = AllConfig.find(name); if (it == AllConfig.end()) { SetValueInt(name, defVal); return defVal; } - return !!atoi(it->second.c_str()); + return atoi(it->second.c_str()); } -int iSysConfigManager::GetValueInt(const std::string &name, int defVal /*= 0*/) { +template<> +float iSysConfigManager::GetValue(const std::string &name, const float& defVal) { auto it = AllConfig.find(name); if (it == AllConfig.end()) { - SetValueInt(name, defVal); + SetValueFloat(name, defVal); return defVal; } - return atoi(it->second.c_str()); + return atof(it->second.c_str()); } -float iSysConfigManager::GetValueFloat(const std::string &name, float defVal /*= 0*/) { +template<> +std::string iSysConfigManager::GetValue(const std::string &name, const std::string& defVal) { auto it = AllConfig.find(name); if (it == AllConfig.end()) { - SetValueFloat(name, defVal); + SetValue(name, defVal); return defVal; } - return atof(it->second.c_str()); + return it->second; } void iSysConfigManager::SetValueInt(const std::string &name, int val) { @@ -130,15 +138,6 @@ void iSysConfigManager::SetValue(const std::string &name, const std::string & va ConfigUpdated = true; } -std::string iSysConfigManager::GetValueString(const std::string &name, std::string defVal /*= ""*/) { - auto it = AllConfig.find(name); - if (it == AllConfig.end()) { - SetValue(name, defVal); - return defVal; - } - return it->second; -} - std::vector iSysConfigManager::GetCustomArgumentsForPush() { std::vector ret; for (auto arg : CustomArguments) { diff --git a/src/core/environ/ConfigManager/GlobalConfigManager.h b/src/core/environ/ConfigManager/GlobalConfigManager.h index d9284478..a7fbc33d 100644 --- a/src/core/environ/ConfigManager/GlobalConfigManager.h +++ b/src/core/environ/ConfigManager/GlobalConfigManager.h @@ -17,10 +17,8 @@ class iSysConfigManager { public: void SaveToFile(); - bool GetValueBool(const std::string &name, bool defVal = false); - int GetValueInt(const std::string &name, int defVal = 0); - float GetValueFloat(const std::string &name, float defVal = 0); - std::string GetValueString(const std::string &name, std::string defVal = ""); + template + T GetValue(const std::string &name, const T& defVal); void SetValueInt(const std::string &name, int val); void SetValueFloat(const std::string &name, float val); @@ -36,6 +34,11 @@ class iSysConfigManager { std::vector GetCustomArgumentsForPush(); }; +template<> bool iSysConfigManager::GetValue(const std::string &name, const bool& defVal); +template<> int iSysConfigManager::GetValue(const std::string &name, const int& defVal); +template<> float iSysConfigManager::GetValue(const std::string &name, const float& defVal); +template<> std::string iSysConfigManager::GetValue(const std::string &name, const std::string& defVal); + class GlobalConfigManager : public iSysConfigManager { virtual std::string GetFilePath() override; diff --git a/src/core/environ/ConfigManager/IndividualConfigManager.cpp b/src/core/environ/ConfigManager/IndividualConfigManager.cpp index d4dffd27..b45c2092 100644 --- a/src/core/environ/ConfigManager/IndividualConfigManager.cpp +++ b/src/core/environ/ConfigManager/IndividualConfigManager.cpp @@ -57,24 +57,25 @@ bool IndividualConfigManager::UsePreferenceAt(const std::string &folder) return true; } -bool IndividualConfigManager::GetValueBool(const std::string &name, bool defVal /*= false*/) +template<> +bool IndividualConfigManager::GetValue(const std::string &name, const bool &defVal /*= false*/) { - return inherit::GetValueBool(name, GlobalConfigManager::GetInstance()->GetValueBool(name, defVal)); + return inherit::GetValue(name, GlobalConfigManager::GetInstance()->GetValue(name, defVal)); } - -int IndividualConfigManager::GetValueInt(const std::string &name, int defVal /*= 0*/) +template<> +int IndividualConfigManager::GetValue(const std::string &name, const int &defVal /*= 0*/) { - return inherit::GetValueInt(name, GlobalConfigManager::GetInstance()->GetValueInt(name, defVal)); + return inherit::GetValue(name, GlobalConfigManager::GetInstance()->GetValue(name, defVal)); } - -float IndividualConfigManager::GetValueFloat(const std::string &name, float defVal /*= 0*/) +template<> +float IndividualConfigManager::GetValue(const std::string &name, const float &defVal /*= 0*/) { - return inherit::GetValueFloat(name, GlobalConfigManager::GetInstance()->GetValueFloat(name, defVal)); + return inherit::GetValue(name, GlobalConfigManager::GetInstance()->GetValue(name, defVal)); } - -std::string IndividualConfigManager::GetValueString(const std::string &name, std::string defVal /*= ""*/) +template<> +std::string IndividualConfigManager::GetValue(const std::string &name, const std::string &defVal /*= ""*/) { - return inherit::GetValueString(name, GlobalConfigManager::GetInstance()->GetValueString(name, defVal)); + return inherit::GetValue(name, GlobalConfigManager::GetInstance()->GetValue(name, defVal)); } std::vector IndividualConfigManager::GetCustomArgumentsForPush() diff --git a/src/core/environ/ConfigManager/IndividualConfigManager.h b/src/core/environ/ConfigManager/IndividualConfigManager.h index ac94c545..8aa1b3fd 100644 --- a/src/core/environ/ConfigManager/IndividualConfigManager.h +++ b/src/core/environ/ConfigManager/IndividualConfigManager.h @@ -19,10 +19,13 @@ class IndividualConfigManager : public iSysConfigManager { bool CreatePreferenceAt(const std::string &folder); bool UsePreferenceAt(const std::string &folder); - bool GetValueBool(const std::string &name, bool defVal = false); - int GetValueInt(const std::string &name, int defVal = 0); - float GetValueFloat(const std::string &name, float defVal = 0); - std::string GetValueString(const std::string &name, std::string defVal = ""); + template + T GetValue(const std::string &name, const T& defVal); std::vector GetCustomArgumentsForPush(); -}; \ No newline at end of file +}; + +template<> bool IndividualConfigManager::GetValue(const std::string &name, const bool& defVal); +template<> int IndividualConfigManager::GetValue(const std::string &name, const int& defVal); +template<> float IndividualConfigManager::GetValue(const std::string &name, const float& defVal); +template<> std::string IndividualConfigManager::GetValue(const std::string &name, const std::string& defVal); \ No newline at end of file diff --git a/src/core/environ/ConfigManager/LocaleConfigManager.cpp b/src/core/environ/ConfigManager/LocaleConfigManager.cpp index 7b400e74..1d3019cf 100644 --- a/src/core/environ/ConfigManager/LocaleConfigManager.cpp +++ b/src/core/environ/ConfigManager/LocaleConfigManager.cpp @@ -24,15 +24,18 @@ LocaleConfigManager* LocaleConfigManager::GetInstance() { return &instance; } -std::string LocaleConfigManager::GetText(const std::string &tid) { +const std::string &LocaleConfigManager::GetText(const std::string &tid) { auto it = AllConfig.find(tid); - if (it == AllConfig.end()) return tid; + if (it == AllConfig.end()) { + AllConfig[tid] = tid; + return AllConfig[tid]; + } return it->second; } void LocaleConfigManager::Initialize(const std::string &sysLang) { // override by global configured lang - currentLangCode = GlobalConfigManager::GetInstance()->GetValueString("user_language"); + currentLangCode = GlobalConfigManager::GetInstance()->GetValue("user_language", ""); if (currentLangCode.empty()) currentLangCode = sysLang; AllConfig.clear(); tinyxml2::XMLDocument doc; diff --git a/src/core/environ/ConfigManager/LocaleConfigManager.h b/src/core/environ/ConfigManager/LocaleConfigManager.h index 85255abf..a01045f1 100644 --- a/src/core/environ/ConfigManager/LocaleConfigManager.h +++ b/src/core/environ/ConfigManager/LocaleConfigManager.h @@ -26,7 +26,7 @@ class LocaleConfigManager { void Initialize(const std::string &sysLang); - std::string GetText(const std::string &tid); // in utf8 + const std::string &GetText(const std::string &tid); // in utf8 bool initText(cocos2d::ui::Text *ctrl); bool initText(cocos2d::ui::Text *ctrl, const std::string &tid); diff --git a/src/core/environ/MainFormUnit.cpp b/src/core/environ/MainFormUnit.cpp deleted file mode 100644 index 74e8675e..00000000 --- a/src/core/environ/MainFormUnit.cpp +++ /dev/null @@ -1,944 +0,0 @@ -//--------------------------------------------------------------------------- -/* - TVP2 ( T Visual Presenter 2 ) A script authoring tool - Copyright (C) 2000-2007 W.Dee and contributors - - See details of license at "license.txt" -*/ -//--------------------------------------------------------------------------- -// System Main Window (Controller) -//--------------------------------------------------------------------------- -#include "tjsCommHead.h" -//--------------------------------------------------------------------------- - - - - -//--------------------------------------------------------------------------- -#include "MainFormUnit.h" -#include "EventIntf.h" -#include "MsgIntf.h" -#include "WindowFormUnit.h" -#include "SysInitIntf.h" -#include "SysInitImpl.h" -#include "ScriptMgnIntf.h" -#include "WindowIntf.h" -#include "WindowImpl.h" -#include "StorageIntf.h" -#include "Random.h" -//#include "EmergencyExit.h" // for TVPCPUClock -#include "DebugIntf.h" -// #include "HintWindow.h" -#include "WaveImpl.h" -#include "SystemImpl.h" -#include "Application.h" - -//--------------------------------------------------------------------------- -#ifdef __BORLANDC__ -#pragma package(smart_init) -#pragma resource "*.dfm" -#else -//#include "MainFormUnit_dfm.h" -#endif -#include "TickCount.h" -#include "Platform.h" -TTVPMainForm *TVPMainForm = NULL; -bool TVPMainFormAlive = false; -//--------------------------------------------------------------------------- - - - - - -//--------------------------------------------------------------------------- -// Get whether debugging support windows can be shown -//--------------------------------------------------------------------------- -static bool TVPDebugSupportShowableGot = false; -static bool TVPDebugSupportShowable = true; -static bool TVPGetDebugSupportShowable() -{ - if(TVPDebugSupportShowableGot) return TVPDebugSupportShowable; - tTJSVariant val; - if( TVPGetCommandLine(TJS_W("-debugwin"), &val) ) - { - ttstr str(val); - if(str == TJS_W("no")) - TVPDebugSupportShowable = false; - } - - TVPDebugSupportShowableGot = true; - - return TVPDebugSupportShowable; -} -//--------------------------------------------------------------------------- - - - - - -//--------------------------------------------------------------------------- -// Get whether to control main thread priority or to insert wait -//--------------------------------------------------------------------------- -static bool TVPMainThreadPriorityControlInit = false; -static bool TVPMainThreadPriorityControl = false; -static bool TVPGetMainThreadPriorityControl() -{ - if(TVPMainThreadPriorityControlInit) return TVPMainThreadPriorityControl; - tTJSVariant val; - if( TVPGetCommandLine(TJS_W("-lowpri"), &val) ) - { - ttstr str(val); - if(str == TJS_W("yes")) - TVPMainThreadPriorityControl = true; - } - - TVPMainThreadPriorityControlInit = true; - - return TVPMainThreadPriorityControl; -} -//--------------------------------------------------------------------------- - - - - - - -//--------------------------------------------------------------------------- -// Get whether the modal windows are rearranged in full-screen -// (to avoid the modal window hides behind the main window) -//--------------------------------------------------------------------------- -//static bool TVPModalWindowRearrangeInFullScreenInit = false; -//static bool TVPModalWindowRearrangeInFullScreen = false; -static bool TVPGetModalWindowRearrangeInFullScreen() -{ - return true; -/* - if(TVPModalWindowRearrangeInFullScreenInit) - return TVPModalWindowRearrangeInFullScreen; - tTJSVariant val; - if( TVPGetCommandLine(TJS_W("-remodal"), &val) ) - { - ttstr str(val); - if(str == TJS_W("yes")) - TVPModalWindowRearrangeInFullScreen = true; - } - - TVPModalWindowRearrangeInFullScreenInit = true; - - return TVPModalWindowRearrangeInFullScreen; -*/ -} -//--------------------------------------------------------------------------- - - - - - - -//--------------------------------------------------------------------------- -// Global Definitions -//--------------------------------------------------------------------------- -//TTVPPadForm *TVPMainPadForm = NULL; -// TTVPConsoleForm *TVPMainConsoleForm = NULL; -// TTVPWatchForm * TVPMainWatchForm = NULL; -//--------------------------------------------------------------------------- -static void TVPUninitEnvironProfile(); -//--------------------------------------------------------------------------- - - - - -//--------------------------------------------------------------------------- -// TTVPMainForm -//--------------------------------------------------------------------------- -#include "float.h" -TTVPMainForm::TTVPMainForm(TWinControl* Owner) - //: TForm(Owner) -{ -#ifndef __BORLANDC__ - //init(this); -#endif - ContinuousEventCalling = false; - AutoShowConsoleOnError = false; - ApplicationStayOnTop = false; - ApplicationActivating = true; - ApplicationNotMinimizing = true; - LastCloseClickedTick = 0; - LastShowModalWindowSentTick = 0; - LastRehashedTick = 0; - //SystemWatchTimer = 0; -#ifdef __BORLANDC__ -// Application->OnIdle = ApplicationIdle; -// Application->OnActivate = ApplicationActivate; -// Application->OnDeactivate = ApplicationDeactivate; -// Application->OnMinimize = ApplicationMinimize; -// Application->OnRestore = ApplicationRestore; -#else - Application->OnIdle = EVENT_FUNC2(TTVPMainForm, ApplicationIdle); -// Application->OnActivate = EVENT_FUNC1(TTVPMainForm, ApplicationActivate); -// Application->OnDeactivate = EVENT_FUNC1(TTVPMainForm, ApplicationDeactivate); -// Application->OnMinimize = EVENT_FUNC1(TTVPMainForm, ApplicationMinimize); -// Application->OnRestore = EVENT_FUNC1(TTVPMainForm, ApplicationRestore); -#endif - // get command-line options which specifies global hot keys. -// SetHotKey(ShowControllerMenuItem, TJS_W("-hkcontroller")); -// SetHotKey(ShowScriptEditorMenuItem, TJS_W("-hkeditor")); -// SetHotKey(ShowWatchMenuItem, TJS_W("-hkwatch")); -// SetHotKey(ShowConsoleMenuItem, TJS_W("-hkconsole")); -// SetHotKey(ShowAboutMenuItem, TJS_W("-hkabout")); -// SetHotKey(CopyImportantLogMenuItem, TJS_W("-hkclipenvinfo")); - - - // read previous state from environ profile - tTVPProfileHolder *prof = TVPGetEnvironProfile(); - TVPEnvironProfileAddRef(); - static AnsiString section("controller"); - int n; - n = prof->ReadInteger(section, "left", -1); -// if(n != -1) setLeft (n); - n = prof->ReadInteger(section, "top", -1); -// if(n != -1) setTop (n); - n = prof->ReadInteger(section, "stayontop", 0); -// setFormStyle (n ? fsStayOnTop : fsNormal); - -// if(getLeft() > Screen->getWidth()) setLeft (Screen->getWidth() - getWidth()); -// if(getTop() > Screen->getHeight()) setTop (Screen->getHeight() - getHeight()); - - section = "console"; - n = prof->ReadInteger(section, "autoshowonerror", 0); - AutoShowConsoleOnError = (bool)n; - - TVPMainFormAlive = true; -} -//--------------------------------------------------------------------------- -void TTVPMainForm::FormDestroy(TObject *Sender) -{ - // write to environ profile - TVPMainFormAlive = false; - - tTVPProfileHolder *prof = TVPGetEnvironProfile(); - static AnsiString section("controller"); -// prof->WriteInteger(section, "left", getLeft()); -// prof->WriteInteger(section, "top", getTop()); -// prof->WriteInteger(section, "stayontop", getFormStyle() == fsStayOnTop); - section = "console"; - prof->WriteInteger(section, "autoshowonerror", (int)AutoShowConsoleOnError); - TVPEnvironProfileRelease(); // this may cause writing profile to disk -} -//--------------------------------------------------------------------------- -void TTVPMainForm::FormClose(TObject *Sender, - TCloseAction &Action) -{ - // - if(TVPGetWindowCount() == 0) - { - // no window - Action = caFree; - } - else - { - Action = caNone; -// setVisible (false); - if(TVPMainWindow) - TVPMainWindow->SendCloseMessage(); - } -} -//--------------------------------------------------------------------------- -TShortCut TTVPMainForm::GetHotKeyFromOption(TShortCut def, const tjs_char * optname) -{ - tTJSVariant val; - if(TVPGetCommandLine(optname, &val)) - { - TShortCut sc; - ttstr str(val); - if(str == TJS_W("")) - { - sc = (TShortCut)0; - } - else - { - sc = TextToShortCut(str.AsAnsiString()); - if(sc == 0) - TVPThrowExceptionMessage(TVPInvalidCommandLineParam, - optname, str); - } - return sc; - } - return def; -} -//--------------------------------------------------------------------------- -void TTVPMainForm::SetHotKey(TMenuItem *item, const tjs_char * optname) -{ - item->ShortCut = GetHotKeyFromOption(item->ShortCut, optname); -} -//--------------------------------------------------------------------------- -bool TTVPMainForm::CanHideAnyWindow() -{ - int viscount = 0; -// for(int i = 0; i < Screen->getFormCount(); i++) -// { -// if(Screen->getForms(i)->getVisible()) viscount++; -// } - return viscount >=2; -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ShowController() -{ - // show self - if(TVPGetDebugSupportShowable()) - { -// if(getVisible()) -// { -// if(CanHideAnyWindow()) setVisible (false); -// } -// else -// { -// setVisible (true); -// BringToFront(); -// } - } -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ShowControllerMenuItemClick(TObject *Sender) -{ - ShowController(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ShowScriptEditorButtonClick(TObject *Sender) -{ - if(TVPGetDebugSupportShowable()) - { -// if(TVPMainPadForm && TVPMainPadForm->Visible) -// { -// if(CanHideAnyWindow()) -// { -// TVPMainPadForm->Visible = false; -// ShowScriptEditorButton->Down = false; -// } -// } -// else -// { -// if(!TVPMainPadForm) -// { -// TVPMainPadForm = new TTVPPadForm(Application, true); -// TVPMainPadForm->Caption = ttstr(TVPMainCDPName).AsAnsiString(); -// } -// TVPMainPadForm->Visible = true; -// ShowScriptEditorButton->Down = true; -// TVPMainPadForm->BringToFront(); -// } - } -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ShowWatchButtonClick(TObject *Sender) -{ - if(TVPGetDebugSupportShowable()) - { -// if(TVPMainWatchForm && TVPMainWatchForm->Visible) -// { -// if(CanHideAnyWindow()) -// { -// TVPMainWatchForm->Visible = false; -// ShowWatchButton->Down = false; -// } -// } -// else -// { -// if(!TVPMainWatchForm) -// { -// TVPMainWatchForm = new TTVPWatchForm(Application); -// } -// TVPMainWatchForm->Visible = true; -// TVPMainWatchForm->BringToFront(); -// ShowWatchButton->Down = true; -// } - } -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ShowConsoleButtonClick(TObject *Sender) -{ - if(TVPGetDebugSupportShowable()) - { -// if(TVPMainConsoleForm && TVPMainConsoleForm->Visible) -// { -// if(CanHideAnyWindow()) -// { -// TVPMainConsoleForm->Visible = false; -// ShowConsoleButton->Down = false; -// } -// } -// else -// { -// if(!TVPMainConsoleForm) -// { -// TVPMainConsoleForm = new TTVPConsoleForm(Application); -// } -// TVPMainConsoleForm->Visible = true; -// TVPMainConsoleForm->BringToFront(); -// ShowConsoleButton->Down = true; -// } - } -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ShowOnTopMenuItemClick(TObject *Sender) -{ -// setFormStyle (fsStayOnTop ? fsNormal : fsStayOnTop); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::SetConsoleVisible(bool b) -{ -// if(b) -// { -// if(!TVPMainConsoleForm) -// { -// TVPMainConsoleForm = new TTVPConsoleForm(Application); -// } -// TVPMainConsoleForm->Visible = true; -// ShowConsoleButton->Down = true; -// } -// else -// { -// if(TVPMainConsoleForm) -// TVPMainConsoleForm->Visible = false; -// ShowConsoleButton->Down = false; -// } -} -//--------------------------------------------------------------------------- -bool TTVPMainForm::GetConsoleVisible() -{ -// if(TVPMainConsoleForm) -// return TVPMainConsoleForm->Visible; - return false; -} -//--------------------------------------------------------------------------- -void TTVPMainForm::NotifyConsoleHiding() -{ -// ShowConsoleButton->setDown (false); -} -//--------------------------------------------------------------------------- -bool TTVPMainForm::GetScriptEditorVisible() -{ -// if(TVPMainPadForm) return TVPMainPadForm->Visible; - return false; -} -//--------------------------------------------------------------------------- -void TTVPMainForm::NotifyScriptEditorHiding() -{ -// ShowScriptEditorButton->setDown (false); -} -//--------------------------------------------------------------------------- -bool TTVPMainForm::GetWatchVisible() -{ -// if(TVPMainWatchForm) return TVPMainWatchForm->Visible; - return false; -} -//--------------------------------------------------------------------------- -void TTVPMainForm::NotifyWatchHiding() -{ -// ShowWatchButton->setDown (false); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ExitButtonClick(TObject *Sender) -{ - Application->Terminate(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::PopupMenuPopup(TObject *Sender) -{ -// ShowOnTopMenuItem->setChecked (getFormStyle() == fsStayOnTop); -// ShowScriptEditorMenuItem->setChecked (GetScriptEditorVisible()); -// ShowWatchMenuItem->setChecked (GetWatchVisible()); -// ShowConsoleMenuItem->setChecked (GetConsoleVisible()); -// EnableEventMenuItem->setChecked( EventButton->getDown()); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::EnableEventMenuItemClick(TObject *Sender) -{ -// TVPSetSystemEventDisabledState(EventButton->getDown()); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::EventButtonClick(TObject *Sender) -{ -// TVPSetSystemEventDisabledState(!EventButton->getDown()); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ShowAboutMenuItemClick(TObject *Sender) -{ -// TVPShowVersionForm(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::CopyImportantLogMenuItemClick( - TObject *Sender) -{ -// TVPCopyImportantLogToClipboard(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::DumpMenuItemClick(TObject *Sender) -{ - TVPDumpScriptEngine(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::CreateMessageMapFileMenuItemClick( - TObject *Sender) -{ - try - { - ttstr fn = TVPGetAppPath() + TJS_W("msgmap.tjs"); - TVPGetLocalName(fn); -// MessageMapFileSaveDialog->FileName = fn.AsAnsiString(); - } - catch(...) - { -// MessageMapFileSaveDialog->FileName = "msgmap.tjs"; - } - -// if(MessageMapFileSaveDialog->Execute()) -// { -// TVPCreateMessageMapFile(MessageMapFileSaveDialog->FileName); -// } -} -//--------------------------------------------------------------------------- -void TTVPMainForm::RestartScriptEngineMenuItemClick(TObject *Sender) -{ - TVPRestartScriptEngine(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::InvokeEvents() -{ - CallDeliverAllEventsOnIdle(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::CallDeliverAllEventsOnIdle() -{ - //::PostMessage(TVPMainForm->Handle, WM_USER+0x31/*dummy msg*/, 0, 0); -// if(!SystemWatchTimer) -// SystemWatchTimer = SDL_AddTimer(50, SDL_SystemWatchTimerTimer, this); -// if(SystemWatchTimer->Interval != 50) -// SystemWatchTimer->Interval = 50; -} -//--------------------------------------------------------------------------- -void TTVPMainForm::BeginContinuousEvent() -{ - if(!ContinuousEventCalling) - { - ContinuousEventCalling = true; - InvokeEvents(); - if(TVPGetMainThreadPriorityControl()) - { - // make main thread priority lower - //SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW); - } - } -} -//--------------------------------------------------------------------------- -void TTVPMainForm::EndContinuousEvent() -{ - if(ContinuousEventCalling) - { - ContinuousEventCalling = false; - if(TVPGetMainThreadPriorityControl()) - { - // make main thread priority normal - //SDL_SetThreadPriority(SDL_THREAD_PRIORITY_NORMAL); - } - } -} -//--------------------------------------------------------------------------- -void TTVPMainForm::NotifyCloseClicked() -{ - // close Button is clicked - LastCloseClickedTick = TVPGetRoughTickCount32(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::NotifyEventDelivered() -{ - // called from event system, notifying the event is delivered. - LastCloseClickedTick = 0; - //if(TVPHaltWarnForm) delete TVPHaltWarnForm, TVPHaltWarnForm = NULL; -} -//--------------------------------------------------------------------------- -void TTVPMainForm::NotifyHaltWarnFormClosed() -{ - LastCloseClickedTick = 0; -} -//--------------------------------------------------------------------------- -void TTVPMainForm::NotifySystemError() -{ - if(AutoShowConsoleOnError) SetConsoleVisible(true); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::SetApplicationStayOnTop(bool b) -{ - ApplicationStayOnTop = b; -// if(ApplicationStayOnTop) -// SetWindowPos(Application->Handle,HWND_TOPMOST ,0,0,0,0, -// SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE); -// else -// SetWindowPos(Application->Handle,HWND_NOTOPMOST ,0,0,0,0, -// SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE); -} -//--------------------------------------------------------------------------- -// void TTVPMainForm::WMInvokeEvents(TMessage &Msg) -// { -// // indirectly called by TVPInvokeEvents *** currently not used *** -// if(EventButton->getDown()) -// { -// TVPDeliverAllEvents(); -// } -// } -//--------------------------------------------------------------------------- -void TTVPMainForm::DeliverEvents() -{ - if(ContinuousEventCalling) - TVPProcessContinuousHandlerEventFlag = true; // set flag - - /*if(EventButton->getDown())*/ TVPDeliverAllEvents(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ApplicationIdle(TObject *Sender, bool &Done) -{ - DeliverEvents(); - - bool cont = ContinuousEventCalling; - Done = !cont; - - MixedIdleTick += TVPGetRoughTickCount32(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ApplicationActivate() -{ - ApplicationActivating = true; - - TVPRestoreFullScreenWindowAtActivation(); - //TVPShowModalAtAppActivate(); -// TVPShowFontSelectFormAtAppActivate(); - TVPResetVolumeToAllSoundBuffer(); - UnlockSoundMixer(); - - // trigger System.onActivate event - TVPPostApplicationActivateEvent(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ApplicationDeactivate() -{ - ApplicationActivating = false; - - //TVPHideModalAtAppDeactivate(); -// TVPHideFontSelectFormAtAppDeactivate(); - - TVPMinimizeFullScreenWindowAtInactivation(); - - - // fire compact event - TVPDeliverCompactEvent(TVP_COMPACT_LEVEL_DEACTIVATE); - - // set application-level stay-on-top state -// if(ApplicationStayOnTop) -// SetWindowPos(Application->Handle,HWND_TOPMOST ,0,0,0,0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE); -// else -// SetWindowPos(Application->Handle,HWND_NOTOPMOST ,0,0,0,0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE); - - // set sound volume - TVPResetVolumeToAllSoundBuffer(); - LockSoundMixer(); - - // trigger System.onDeactivate event - TVPPostApplicationDeactivateEvent(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ApplicationMinimize(TObject *Sender) -{ - // fire compact event - ApplicationNotMinimizing = false; - - TVPDeliverCompactEvent(TVP_COMPACT_LEVEL_MINIMIZE); - - // set sound volume - TVPResetVolumeToAllSoundBuffer(); -} -//--------------------------------------------------------------------------- -void TTVPMainForm::ApplicationRestore(TObject *Sender) -{ - ApplicationNotMinimizing = true; - - // set sound volume - TVPResetVolumeToAllSoundBuffer(); -} -extern tjs_uint TVPTotalPhysMemory; -//--------------------------------------------------------------------------- -void TTVPMainForm::SystemWatchTimerTimer(TObject *) -{ -// if(TVPTerminated) -// { -// TVPExitApplication(0); -// } - - // call events - uint32_t tick = TVPGetRoughTickCount32(); - - // push environ noise - TVPPushEnvironNoise(&tick, sizeof(tick)); - TVPPushEnvironNoise(&LastCompactedTick, sizeof(LastCompactedTick)); - TVPPushEnvironNoise(&LastShowModalWindowSentTick, sizeof(LastShowModalWindowSentTick)); - TVPPushEnvironNoise(&MixedIdleTick, sizeof(MixedIdleTick)); -// POINT pt; -// GetCursorPos(&pt); -// TVPPushEnvironNoise(&pt, sizeof(pt)); - - // CPU clock monitoring -// { -// static bool clock_rough_printed = false; -// if(!clock_rough_printed && TVPCPUClockAccuracy == ccaRough) -// { -// tjs_char msg[80]; -// TJS_sprintf(msg, TJS_W("(info) CPU clock (roughly) : %dMHz"), (int)TVPCPUClock); -// TVPAddImportantLog(msg); -// clock_rough_printed = true; -// } -// static bool clock_printed = false; -// if(!clock_printed && TVPCPUClockAccuracy == ccaAccurate) -// { -// tjs_char msg[80]; -// TJS_sprintf(msg, TJS_W("(info) CPU clock : %.1fMHz"), (float)TVPCPUClock); -// TVPAddImportantLog(msg); -// clock_printed = true; -// } -// } - - // check status and deliver events - DeliverEvents(); - - if (tick - LastCompactedTick > 60000 || (!ContinuousEventCalling && tick - LastCompactedTick > 4000)) - { - // idle state over 4 sec. or forced clear after 1 min - LastCompactedTick = tick; - - // fire compact event - if (TVPGetSelfUsedMemory() > 1536 || - TVPGetSystemFreeMemory() < (TVPTotalPhysMemory / 1024) / 10) { - //less than 10% memory - TVPDeliverCompactEvent(TVP_COMPACT_LEVEL_MAX); - } else { - TVPDeliverCompactEvent(TVP_COMPACT_LEVEL_IDLE); - } - } - - if(!ContinuousEventCalling && tick > LastRehashedTick + 1500) - { - // TJS2 object rehash - LastRehashedTick = tick; - TJSDoRehash(); - } - - if(LastCloseClickedTick && tick - LastCloseClickedTick > 3100) - { - // display force suicide confirmation form -// if(TVPHaltWarnForm) -// { -// TVPHaltWarnForm->Visible = true; -// } -// else -// { -// TVPHaltWarnForm = new TTVPHaltWarnForm(Application); -// TVPHaltWarnForm->Visible = true; -// } - } - - // ensure modal window visible - if(tick > LastShowModalWindowSentTick + 4100) - { - // ::PostMessage(Handle, WM_USER+0x32, 0, 0); - // This is currently disabled because IME composition window - // hides behind the window which is bringed top by the - // window-rearrangement. - LastShowModalWindowSentTick = tick; - } - -} - -TTVPMainForm::~TTVPMainForm() -{ - //if(SystemWatchTimer) SDL_RemoveTimer(SystemWatchTimer); -} - -//--------------------------------------------------------------------------- -// void TTVPMainForm::WMRearrangeModalWindows(TMessage &Msg) -// { -// if(TVPFullScreenedWindow != NULL && TVPGetModalWindowRearrangeInFullScreen()) -// { -// HDWP hdwp = BeginDeferWindowPos(1); -// hdwp = TVPShowModalAtTimer(hdwp); -// hdwp = TVPShowFontSelectFormTop(hdwp); -// hdwp = TVPShowHintWindowTop(hdwp); -// EndDeferWindowPos(hdwp); -// } -// } -//--------------------------------------------------------------------------- - - - - - - -//--------------------------------------------------------------------------- -// Environment Profiling Support -//--------------------------------------------------------------------------- -static tTVPProfileHolder *TVPEnvironProfile = NULL; -tjs_int TVPEnvironProfileRefCount = 0; -static bool TVPProfileWrite = false; -//--------------------------------------------------------------------------- -static void TVPInitEnvironProfile() -{ - // initialize environ profile - if(!TVPEnvironProfile) - { - // read profile from project directory or - // current directory ( if projdir was not specified ) - if(strchr(TVPNativeDataPath.c_str(), TVPArchiveDelimiter)) - TVPProfileWrite = false; else TVPProfileWrite = true; - try - { - TVPEnvironProfile = - new tTVPProfileHolder(TVPNativeDataPath + "krenvprf.kep"); - } - catch(...) - { - TVPEnvironProfile = new tTVPProfileHolder(TVPGetTemporaryName().AsAnsiString()); - TVPProfileWrite = false; - } - } -} -//--------------------------------------------------------------------------- -void TVPWriteEnvironProfile() -{ - // write environ profile values - if(TVPEnvironProfile) - { - try - { - if(TVPProfileWrite) TVPEnvironProfile->UpdateFile(); - } - catch(...) - { - // suppress error - } - } -} -//--------------------------------------------------------------------------- -static void TVPUninitEnvironProfile() -{ - // clean up environ profile values - TVPWriteEnvironProfile(); - if(TVPEnvironProfile) - { - delete TVPEnvironProfile; - TVPEnvironProfile = NULL; - } -} -//--------------------------------------------------------------------------- -void TVPEnvironProfileAddRef() -{ - TVPEnvironProfileRefCount ++; -} -//--------------------------------------------------------------------------- -void TVPEnvironProfileRelease() -{ - TVPEnvironProfileRefCount --; - if(TVPEnvironProfileRefCount == 0) TVPUninitEnvironProfile(); -} -//--------------------------------------------------------------------------- -tTVPProfileHolder *TVPGetEnvironProfile() -{ - // read value from section and name, return defstr if not found. - TVPInitEnvironProfile(); - return TVPEnvironProfile; -} -//--------------------------------------------------------------------------- - - - - - -//--------------------------------------------------------------------------- -static AnsiString TVPEscapeAnsiString(const AnsiString & str) -{ - // escape to harmless string - char *buf = new char [str.length() * 2 + 1]; // enough to hold - const char *s = str.c_str(); - int i = 0; - while(*s) - { - if(*s == '@') - { - buf[i++] = '@'; - buf[i++] = '@'; - } - else if((unsigned char)*s < 0x20) - { - buf[i++] = '@'; - buf[i++] = ' ' + *s; - } - else - { - buf[i++] = *s; - } - - s++; - } - buf[i] = 0; - AnsiString ret = buf; - delete [] buf; - return ret; -} -//--------------------------------------------------------------------------- -static AnsiString TVPUnescapeAnsiString(const AnsiString & str) -{ - // unescape - int strlen = str.length(); - char *buf = new char [strlen + 1]; - const char *s = str.c_str(); - const char *slim = s + strlen; - int i = 0; - while(sgetText())); -} -//--------------------------------------------------------------------------- -void tTVPProfileHolder::ReadStrings(const AnsiString §ion, - const AnsiString &ident, TStrings * strings) -{ - AnsiString str; - str = ReadString(section, ident, ""); - //if(str != "") strings->getText() = TVPUnescapeAnsiString(str); -} -//--------------------------------------------------------------------------- - - - - - - - diff --git a/src/core/environ/MainFormUnit.h b/src/core/environ/MainFormUnit.h deleted file mode 100644 index b4d82fa9..00000000 --- a/src/core/environ/MainFormUnit.h +++ /dev/null @@ -1,185 +0,0 @@ -//--------------------------------------------------------------------------- -/* - TVP2 ( T Visual Presenter 2 ) A script authoring tool - Copyright (C) 2000-2007 W.Dee and contributors - - See details of license at "license.txt" -*/ -//--------------------------------------------------------------------------- -// System Main Window (Controller) -//--------------------------------------------------------------------------- -#ifndef MainFormUnitH -#define MainFormUnitH -//--------------------------------------------------------------------------- -#include "Classes.hpp" -#include "Controls.hpp" -//#include -#include "Forms.hpp" -//#include -// #include -// #include -// #include -//#include -#include "Menus.hpp" -#include "Dialogs.hpp" -//--------------------------------------------------------------------------- -class TTVPMainForm// : public TForm -{ -public: // IDE 管理のコンポーネント -// TImageList *VerySmallIconImageList; -// TImageList *SmallIconImageList; - //TToolBar *ToolBar; -// TToolButton *ShowScriptEditorButton; -// TToolButton *ShowConsoleButton; -// TToolButton *ToolButton3; -// TToolButton *ExitButton; -// TToolButton *EventButton; -// TPopupMenu *PopupMenu; -// TMenuItem *ShowScriptEditorMenuItem; -// TMenuItem *ShowConsoleMenuItem; -// TMenuItem *N1; -// TMenuItem *EnableEventMenuItem; -// TMenuItem *N2; -// TMenuItem *ExitMenuItem; -// TMenuItem *ShowAboutMenuItem; -// TMenuItem *N3; -// TMenuItem *DumpMenuItem; -// TToolButton *ToolButton1; -// TToolButton *ShowWatchButton; - //SDL_TimerID SystemWatchTimer; -// TMenuItem *ShowWatchMenuItem; -// TMenuItem *CopyImportantLogMenuItem; -// TMenuItem *CreateMessageMapFileMenuItem; -// TSaveDialog *MessageMapFileSaveDialog; -// TMenuItem *ShowOnTopMenuItem; -// TMenuItem *N4; -// TMenuItem *ShowControllerMenuItem; -// TMenuItem *RestartScriptEngineMenuItem; - void ShowScriptEditorButtonClick(TObject *Sender); - void ExitButtonClick(TObject *Sender); - void ShowConsoleButtonClick(TObject *Sender); - void PopupMenuPopup(TObject *Sender); - void EnableEventMenuItemClick(TObject *Sender); - void ShowAboutMenuItemClick(TObject *Sender); - void DumpMenuItemClick(TObject *Sender); - void EventButtonClick(TObject *Sender); - void ShowWatchButtonClick(TObject *Sender); - void SystemWatchTimerTimer(TObject *Sender); - void FormDestroy(TObject *Sender); - void FormClose(TObject *Sender, TCloseAction &Action); - void CopyImportantLogMenuItemClick(TObject *Sender); - void CreateMessageMapFileMenuItemClick(TObject *Sender); - void ShowOnTopMenuItemClick(TObject *Sender); - void ShowControllerMenuItemClick(TObject *Sender); - void RestartScriptEngineMenuItemClick(TObject *Sender); - -private: // ユーザー宣言 - bool ContinuousEventCalling; - bool AutoShowConsoleOnError; - bool ApplicationStayOnTop; - bool ApplicationActivating; - bool ApplicationNotMinimizing; - -public: // ユーザー宣言 - TTVPMainForm(TWinControl* Owner); - ~TTVPMainForm(); - - static TShortCut GetHotKeyFromOption(TShortCut def, const tjs_char * optname); - static void SetHotKey(TMenuItem *item, const tjs_char * optname); - - bool CanHideAnyWindow(); - - void SetConsoleVisible(bool b); - bool GetConsoleVisible(); - void NotifyConsoleHiding(); - - bool GetScriptEditorVisible(); - void NotifyScriptEditorHiding(); - - bool GetWatchVisible(); - void NotifyWatchHiding(); - - void SetAutoShowConsoleOnError(bool b) { AutoShowConsoleOnError = true; } - bool GetAutoShowConsoleOnError() const { return AutoShowConsoleOnError; } - - void ShowController(); - void InvokeEvents(); - void CallDeliverAllEventsOnIdle(); - - void BeginContinuousEvent(); - void EndContinuousEvent(); - - void NotifyCloseClicked(); - void NotifyEventDelivered(); - void NotifyHaltWarnFormClosed(); - - void NotifySystemError(); - - void SetApplicationStayOnTop(bool b); - bool GetApplicationStayOnTop() const { return ApplicationStayOnTop; } - - bool GetApplicationActivating() const { return ApplicationActivating; } - bool GetApplicationNotMinimizing() const { return ApplicationNotMinimizing; } - virtual void Dispatch(void*){}; - - void ApplicationDeactivate(); - void ApplicationActivate(); - -protected: -//BEGIN_MESSAGE_MAP -// VCL_MESSAGE_HANDLER( SDL_USEREVENT+0x30, TMessage, WMInvokeEvents) -// VCL_MESSAGE_HANDLER( SDL_USEREVENT+0x32, TMessage, WMRearrangeModalWindows) -//END_MESSAGE_MAP(TForm) -// void WMInvokeEvents(TMessage &Msg); -// void WMRearrangeModalWindows(TMessage &Msg); -private: - uint32_t LastCompactedTick; - uint32_t LastContinuousTick; - uint32_t LastCloseClickedTick; - uint32_t LastShowModalWindowSentTick; - uint32_t LastRehashedTick; - - uint32_t MixedIdleTick; - - void DeliverEvents(); - - void ApplicationIdle(TObject *Sender, bool &Done); - void ApplicationMinimize(TObject *Sender); - void ApplicationRestore(TObject *Sender); - -public: // hotkey management - TShortCut ShowUpdateRectShortCut; - TShortCut DumpLayerStructureShortCut; - -}; -//--------------------------------------------------------------------------- -extern TTVPMainForm *TVPMainForm; -extern bool TVPMainFormAlive; -//--------------------------------------------------------------------------- - - - -//--------------------------------------------------------------------------- -// Environment Profiling Support -//--------------------------------------------------------------------------- -#include "IniFiles.hpp" -class tTVPProfileHolder : public TMemIniFile -{ -public: - tTVPProfileHolder(const AnsiString &fn) : TMemIniFile(fn) {}; - ~tTVPProfileHolder() {}; - - void WriteStrings(const AnsiString §ion, const AnsiString &ident, - TStrings * strings); - void ReadStrings(const AnsiString §ion, const AnsiString &ident, - TStrings * strings); -}; -extern void TVPWriteEnvironProfile(); -extern void TVPEnvironProfileAddRef(); -extern void TVPEnvironProfileRelease(); -extern tTVPProfileHolder *TVPGetEnvironProfile(); -//--------------------------------------------------------------------------- - - - -#endif diff --git a/src/core/environ/MainFormUnit_dfm.h b/src/core/environ/MainFormUnit_dfm.h deleted file mode 100644 index c1219b38..00000000 --- a/src/core/environ/MainFormUnit_dfm.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -static void init(TTVPMainForm* p) -{ - _create_VCL_obj( &p->VerySmallIconImageList , p ); - _create_VCL_obj( &p->SmallIconImageList , p ); -// _create_VCL_obj( &p->ToolBar , p ); - _create_VCL_obj( &p->ShowScriptEditorButton , p ); - _create_VCL_obj( &p->ShowConsoleButton , p ); - _create_VCL_obj( &p->ToolButton3 , p ); - _create_VCL_obj( &p->ExitButton , p ); - _create_VCL_obj( &p->EventButton , p ); -// _create_VCL_obj( &p->PopupMenu , p ); -// _create_VCL_obj( &p->ShowScriptEditorMenuItem , p ); -// _create_VCL_obj( &p->ShowConsoleMenuItem , p ); -// _create_VCL_obj( &p->N1 , p ); -// _create_VCL_obj( &p->EnableEventMenuItem , p ); -// _create_VCL_obj( &p->N2 , p ); -// _create_VCL_obj( &p->ExitMenuItem , p ); -// _create_VCL_obj( &p->ShowAboutMenuItem , p ); -// _create_VCL_obj( &p->N3 , p ); -// _create_VCL_obj( &p->DumpMenuItem , p ); - _create_VCL_obj( &p->ToolButton1 , p ); - _create_VCL_obj( &p->ShowWatchButton , p ); -// _create_VCL_obj( &p->ShowWatchMenuItem , p ); -// _create_VCL_obj( &p->SystemWatchTimer , p ); -// _create_VCL_obj( &p->CopyImportantLogMenuItem , p ); -// _create_VCL_obj( &p->CreateMessageMapFileMenuItem, p ); -// _create_VCL_obj( &p->MessageMapFileSaveDialog , p ); -// _create_VCL_obj( &p->ShowOnTopMenuItem , p ); -// _create_VCL_obj( &p->N4 , p ); -// _create_VCL_obj( &p->ShowControllerMenuItem , p ); -// _create_VCL_obj( &p->RestartScriptEngineMenuItem , p ); - - p->OnClose = - std::bind(std::mem_fn(&TTVPMainForm::FormClose), p, std::placeholders::_1, std::placeholders::_2); - p->OnDestroy = - std::bind(std::mem_fn(&TTVPMainForm::FormDestroy), p, std::placeholders::_1); - - p->EventButton->setDown (true); -} - diff --git a/src/core/environ/Platform.h b/src/core/environ/Platform.h index e8c86df8..16611c37 100644 --- a/src/core/environ/Platform.h +++ b/src/core/environ/Platform.h @@ -39,3 +39,4 @@ void TVPShowIME(int x, int y, int w, int h); void TVPHideIME(); void TVPRelinquishCPU(); +void TVPPrintLog(const char *str); diff --git a/src/core/environ/cocos2d/AppDelegate.cpp b/src/core/environ/cocos2d/AppDelegate.cpp index 2f0f3f43..6a485146 100644 --- a/src/core/environ/cocos2d/AppDelegate.cpp +++ b/src/core/environ/cocos2d/AppDelegate.cpp @@ -8,6 +8,7 @@ #include "Application.h" #include "Platform.h" #include "ui/MessageBox.h" +#include "ui/GlobalPreferenceForm.h" USING_NS_CC; @@ -76,6 +77,7 @@ bool TVPAppDelegate::applicationDidFinishLaunching() { scene->scheduleOnce([](float dt){ TVPMainScene::GetInstance()->unschedule("launch"); + TVPGlobalPreferenceForm::Initialize(); if (!TVPCheckStartupArg()) { // std::string lastpath; diff --git a/src/core/environ/cocos2d/MainScene.cpp b/src/core/environ/cocos2d/MainScene.cpp index ee3dedf7..d592689b 100644 --- a/src/core/environ/cocos2d/MainScene.cpp +++ b/src/core/environ/cocos2d/MainScene.cpp @@ -1698,7 +1698,7 @@ bool TVPMainScene::startupFrom(const std::string &path) { popUIForm(nullptr); } - if (GlobalConfigManager::GetInstance()->GetValueBool("keep_screen_alive", true)) { + if (GlobalConfigManager::GetInstance()->GetValue("keep_screen_alive", true)) { Device::setKeepScreenOn(true); } // if (pGlobalCfgMgr->GetValueBool("rot_screen_180", false)) { @@ -1726,7 +1726,7 @@ void TVPMainScene::doStartup(float dt, std::string path) { // update one frame update(0); //_ResotreGLStatues(); // already in update() - GLubyte handlerOpacity = pGlobalCfgMgr->GetValueFloat("menu_handler_opa", 0.15f) * 255; + GLubyte handlerOpacity = pGlobalCfgMgr->GetValue("menu_handler_opa", 0.15f) * 255; _gameMenu = TVPGameMainMenu::create(handlerOpacity); GameNode->addChild(_gameMenu, GAME_MENU_ORDER); _gameMenu->shrinkWithTime(1); @@ -1745,11 +1745,12 @@ void TVPMainScene::doStartup(float dt, std::string path) { pWin = pWin->_prevWindow; } - if (pGlobalCfgMgr->GetValueBool("showfps", false)) { + if (pGlobalCfgMgr->GetValue("showfps", false)) { _fpsLabel = cocos2d::Label::createWithTTF("", "DroidSansFallback.ttf", 16); _fpsLabel->setAnchorPoint(Vec2(0, 1)); _fpsLabel->setPosition(Vec2(0, GameNode->getContentSize().height)); - _fpsLabel->setColor(Color3B::GRAY); + _fpsLabel->setColor(Color3B::WHITE); + _fpsLabel->enableOutline(Color4B::BLACK, 1); GameNode->addChild(_fpsLabel, GAME_MENU_ORDER); } } @@ -1834,7 +1835,6 @@ void TVPMainScene::setMaskLayTouchBegain(const std::functiongetOpenGLView(); float factor = (glview->getScaleX() + glview->getScaleY()) / 2; @@ -1890,6 +1890,15 @@ void TVPMainScene::onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event) { case EventKeyboard::KeyCode::KEY_PAUSE: GameNode->addChild(DebugViewLayerForm::create()); return; + case EventKeyboard::KeyCode::KEY_F12: + if (TVPGetCurrentShiftKeyState() & ssShift) { + std::vector btns({ "OK", "Cancel" }); + ttstr text; + if (TVPShowSimpleInputBox(text, "console command", "", btns) == 0) { + TVPExecuteExpression(text); + } + } + break; #endif default: break; @@ -2007,7 +2016,7 @@ void TVPMainScene::showVirtualMouseCursor(bool bVisible) { if (!_mouseCursor) return; _mouseCursorScale = _mouseCursor->getScale() * - convertCursorScale(IndividualConfigManager::GetInstance()->GetValueFloat("vcursor_scale", 0.5f)); + convertCursorScale(IndividualConfigManager::GetInstance()->GetValue("vcursor_scale", 0.5f)); _mouseCursor->setScale(_mouseCursorScale); GameNode->addChild(_mouseCursor, GAME_WINMGR_ORDER); _mouseCursor->setPosition(GameNode->getContentSize() / 2); @@ -2246,7 +2255,7 @@ void TVPRemoveWindowLayer(iWindowLayer *lay) { } void TVPConsoleLog(const ttstr &l, bool important) { - static bool TVPLoggingToConsole = IndividualConfigManager::GetInstance()->GetValueBool("outputlog", true); + static bool TVPLoggingToConsole = IndividualConfigManager::GetInstance()->GetValue("outputlog", true); if (!TVPLoggingToConsole) return; if (_consoleWin) { _consoleWin->addLine(l, important ? Color3B::YELLOW : Color3B::GRAY); diff --git a/src/core/environ/cocos2d/YUVSprite.cpp b/src/core/environ/cocos2d/YUVSprite.cpp index 60f07a8d..29f40f40 100644 --- a/src/core/environ/cocos2d/YUVSprite.cpp +++ b/src/core/environ/cocos2d/YUVSprite.cpp @@ -14,12 +14,12 @@ static const char *_yuvRenderProgram_fsh = "void main() {" "\n" " vec3 yuv;" "\n" - " yuv.x = texture2D(CC_Texture0, v_texCoord).r;" "\n" + " yuv.x = texture2D(CC_Texture0, v_texCoord).r - 0.0625;" "\n" " yuv.y = texture2D(CC_Texture1, v_texCoord).r - 0.5;" "\n" " yuv.z = texture2D(CC_Texture2, v_texCoord).r - 0.5;" "\n" - " vec3 rgb = mat3(1.0, 1.0, 1.0," "\n" - " 0.0, -0.39465, 2.03211," "\n" - " 1.13983, -0.58060, 0.0) * yuv;" "\n" + " vec3 rgb = mat3(1.164, 1.164, 1.164," "\n" + " 0.0, -0.392, 2.017," "\n" + " 1.596, -0.813, 0.0) * yuv;" "\n" " gl_FragColor = vec4(rgb, 1.0) * v_fragmentColor;" "\n" "}" ; diff --git a/src/core/environ/ui/BaseForm.cpp b/src/core/environ/ui/BaseForm.cpp index 705464d1..f75dbcc3 100644 --- a/src/core/environ/ui/BaseForm.cpp +++ b/src/core/environ/ui/BaseForm.cpp @@ -186,7 +186,7 @@ static bool _isModaling; int TVPShowSimpleInputBox(ttstr &text, const ttstr &caption, const ttstr &prompt, const std::vector &vecButtons) { Scale9Sprite *bg = Scale9Sprite::create(); EditBox *box = EditBox::create(Size(1, 1), bg); - box->setInputFlag(EditBox::InputFlag::INITIAL_CAPS_ALL_CHARACTERS); + box->setInputFlag(EditBox::InputFlag::SENSITIVE); box->setText(text.AsStdString().c_str()); box->setPlaceHolder(prompt.AsStdString().c_str()); class Delegate : public EditBoxDelegate { diff --git a/src/core/environ/ui/FileSelectorForm.cpp b/src/core/environ/ui/FileSelectorForm.cpp index 2c418d61..a51307df 100644 --- a/src/core/environ/ui/FileSelectorForm.cpp +++ b/src/core/environ/ui/FileSelectorForm.cpp @@ -12,6 +12,7 @@ #include "base/CCDirector.h" #include "MessageBox.h" #include +#include "platform/CCDevice.h" using namespace cocos2d; using namespace cocos2d::extension; @@ -19,6 +20,16 @@ using namespace cocos2d::ui; const char * const FileName_Cell = "ui/FileItem.csb"; static TVPListForm* _listform; +#define MOVE_INCH 7.0f/160.0f +static const std::string str_long_press("long_press"); + +static float convertDistanceFromPointToInch(const Vec2& dis) +{ + auto glview = cocos2d::Director::getInstance()->getOpenGLView(); + int dpi = cocos2d::Device::getDPI(); + float distance = Vec2(dis.x * glview->getScaleX() / dpi, dis.y * glview->getScaleY() / dpi).getLength(); + return distance; +} std::pair TVPBaseFileSelectorForm::PathSplit(const std::string &path) { std::pair ret; @@ -172,6 +183,32 @@ void TVPBaseFileSelectorForm::onCellClicked(int idx) { } } +void TVPBaseFileSelectorForm::onCellLongPress(int idx) +{ + LocaleConfigManager *localeMgr = LocaleConfigManager::GetInstance(); + const char *btnTitles[] = { + localeMgr->GetText("delete").c_str(), + localeMgr->GetText("cancel").c_str(), + }; + int n = TVPShowSimpleMessageBox( + localeMgr->GetText("file_operate_menu_text").c_str(), + localeMgr->GetText("file_operate_menu_title").c_str(), + sizeof(btnTitles) / sizeof(btnTitles[0]), btnTitles); + const FileInfo &info = CurrentDirList[idx]; + switch (n) { + case 0: + if (TVPShowSimpleMessageBoxYesNo(info.FullPath, localeMgr->GetText("ensure_to_delete_file")) == 0) { + TVPDeleteFile(info.FullPath); + scheduleOnce([this](float){ + ListDir(CurrentPath); + }, 0, "refresh_path"); + } + break; + default: + break; + } +} + void TVPBaseFileSelectorForm::getShortCutDirList(std::vector &pathlist) { std::vector paths = TVPGetDriverPath(); for (const std::string &path : paths) { @@ -238,7 +275,8 @@ TVPBaseFileSelectorForm::FileItemCellImpl* TVPBaseFileSelectorForm::FetchCell(Fi break; case Widget::TouchEventType::MOVED: FileList->onTouchMoved(touch, nullptr); - if ((sender->getTouchBeganPosition() - touchPoint).getLength() > 5.0f) { // TODO + if (sender->isHighlighted() && + convertDistanceFromPointToInch(sender->getTouchBeganPosition() - touchPoint) > MOVE_INCH) { sender->setHighlighted(false); } break; @@ -482,6 +520,21 @@ void TVPBaseFileSelectorForm::FileItemCellImpl::initFromFile(const char * filena Widget *HighLight = static_cast(reader.findController(str_highlight)); if (HighLight) { HighLight->addClickEventListener(std::bind(&FileItemCellImpl::onClicked, this, std::placeholders::_1)); + HighLight->addTouchEventListener([this](Ref* p, Widget::TouchEventType ev){ + Widget* sender = static_cast(p); + switch (ev) { + case Widget::TouchEventType::BEGAN: + sender->scheduleOnce([this, sender](float){ + if (sender->isHighlighted()) { + sender->scheduleOnce([this](float){_owner->onLongPress(); }, 0, "delay_call"); + } + }, 1.5f, str_long_press); + break; + case Widget::TouchEventType::CANCELED: + sender->unschedule(str_long_press); + break; + } + }); } } @@ -501,6 +554,10 @@ void TVPBaseFileSelectorForm::FileItemCellImpl::setInfo(const FileInfo &info) { _set = true; } -void TVPBaseFileSelectorForm::FileItemCellImpl::onClicked(cocos2d::Ref*) { - _owner->onClicked(); +void TVPBaseFileSelectorForm::FileItemCellImpl::onClicked(cocos2d::Ref* p) { + Widget* sender = static_cast(p); + if (sender->isScheduled(str_long_press)) { + sender->unschedule(str_long_press); + _owner->onClicked(); + } } diff --git a/src/core/environ/ui/FileSelectorForm.h b/src/core/environ/ui/FileSelectorForm.h index fbc26212..2609b002 100644 --- a/src/core/environ/ui/FileSelectorForm.h +++ b/src/core/environ/ui/FileSelectorForm.h @@ -28,6 +28,7 @@ class TVPBaseFileSelectorForm : public iTVPBaseForm, public cocos2d::extension:: virtual cocos2d::extension::TableViewCell* tableCellAtIndex(cocos2d::extension::TableView *table, ssize_t idx) override; virtual ssize_t numberOfCellsInTableView(cocos2d::extension::TableView *table) override; virtual void onCellClicked(int idx); + virtual void onCellLongPress(int idx); virtual void rearrangeLayout() override; static std::pair PathSplit(const std::string &path); @@ -136,6 +137,10 @@ class TVPBaseFileSelectorForm : public iTVPBaseForm, public cocos2d::extension:: _owner->onCellClicked(getIdx()); } + void onLongPress() { + _owner->onCellLongPress(getIdx()); + } + private: FileItemCellImpl *_impl; TVPBaseFileSelectorForm *_owner; diff --git a/src/core/environ/ui/GlobalPreferenceForm.cpp b/src/core/environ/ui/GlobalPreferenceForm.cpp index e1c27d40..25f745c4 100644 --- a/src/core/environ/ui/GlobalPreferenceForm.cpp +++ b/src/core/environ/ui/GlobalPreferenceForm.cpp @@ -18,7 +18,7 @@ namespace { }; TVPGlobalPreferenceForm * TVPGlobalPreferenceForm::create(const tPreferenceScreen *config) { - initAllConfig(); + Initialize(); if (!config) config = &RootPreference; TVPGlobalPreferenceForm *ret = new TVPGlobalPreferenceForm(); ret->autorelease(); @@ -28,3 +28,23 @@ TVPGlobalPreferenceForm * TVPGlobalPreferenceForm::create(const tPreferenceScree ret->setOnExitCallback(std::bind(&GlobalConfigManager::SaveToFile, GlobalConfigManager::GetInstance())); return ret; } + +static void WalkConfig(tPreferenceScreen* pref) { + for (iTVPPreferenceInfo* info : pref->Preferences) { + info->InitDefaultConfig(); + tPreferenceScreen* subpref = info->GetSubScreenInfo(); + if (subpref) { + WalkConfig(subpref); + } + } +} + +void TVPGlobalPreferenceForm::Initialize() +{ + static bool Inited = false; + if (!Inited) { + Inited = true; + initAllConfig(); + WalkConfig(&RootPreference); + } +} diff --git a/src/core/environ/ui/GlobalPreferenceForm.h b/src/core/environ/ui/GlobalPreferenceForm.h index 26895a3d..018bafc4 100644 --- a/src/core/environ/ui/GlobalPreferenceForm.h +++ b/src/core/environ/ui/GlobalPreferenceForm.h @@ -4,4 +4,5 @@ class TVPGlobalPreferenceForm : public TVPPreferenceForm { public: static TVPGlobalPreferenceForm *create(const tPreferenceScreen *config = nullptr); + static void Initialize(); }; \ No newline at end of file diff --git a/src/core/environ/ui/MainFileSelectorForm.cpp b/src/core/environ/ui/MainFileSelectorForm.cpp index 0c23bdf2..e437a8d5 100644 --- a/src/core/environ/ui/MainFileSelectorForm.cpp +++ b/src/core/environ/ui/MainFileSelectorForm.cpp @@ -35,6 +35,12 @@ bool TVPIsFirstLaunch = false; std::deque _HistoryPath; +static void _AskExit() { + if (TVPShowSimpleMessageBoxYesNo( + LocaleConfigManager::GetInstance()->GetText("sure_to_exit"), + "Kirikiroid2") == 0) TVPExitApplication(0); +} + bool TVPCheckIsVideoFile(const char *uri); static std::string _GetHistoryXMLPath() { return TVPGetInternalPreferencePath() + FileName_RecentPathListXML; @@ -246,7 +252,7 @@ void TVPMainFileSelectorForm::startup(const std::string &path) { void TVPMainFileSelectorForm::doStartup(const std::string &path) { if (TVPMainScene::GetInstance()->startupFrom(path)) { - if (GlobalConfigManager::GetInstance()->GetValueBool("remember_last_path", true)) { + if (GlobalConfigManager::GetInstance()->GetValue("remember_last_path", true)) { _AddHistory(path); // std::string lastpath_file = _getLastPathFilePath(); // FILE* fp = fopen(lastpath_file.c_str(), "wt"); @@ -258,6 +264,8 @@ void TVPMainFileSelectorForm::doStartup(const std::string &path) { } } +std::string TVPGetOpenGLInfo(); + void TVPMainFileSelectorForm::showMenu(Ref*) { if (!_menu) { Size uiSize = getContentSize(); @@ -331,23 +339,31 @@ void TVPMainFileSelectorForm::showMenu(Ref*) { versionText += "\n"; versionText += LocaleConfigManager::GetInstance()->GetText("about_content"); - std::string btnText[2] = { - LocaleConfigManager::GetInstance()->GetText("ok"), - LocaleConfigManager::GetInstance()->GetText("reactive") - }; const char * pszBtnText[] = { - btnText[0].c_str(), - btnText[1].c_str() + LocaleConfigManager::GetInstance()->GetText("ok").c_str(), + LocaleConfigManager::GetInstance()->GetText("device_info").c_str(), }; std::string strCaption = LocaleConfigManager::GetInstance()->GetText("menu_about"); - const char *caption = strCaption.c_str(); - int n = TVPShowSimpleMessageBox(versionText.c_str(), caption, 1, pszBtnText); + int n = TVPShowSimpleMessageBox(versionText.c_str(), strCaption.c_str(), + sizeof(pszBtnText) / sizeof(pszBtnText[0]), pszBtnText); + + switch (n) { + case 1: { + std::string text = TVPGetOpenGLInfo(); + const char *pOK = LocaleConfigManager::GetInstance()->GetText("ok").c_str(); + TVPShowSimpleMessageBox(text.c_str(), + LocaleConfigManager::GetInstance()->GetText("device_info").c_str(), + 1, &pOK); + } break; + } }); reader.findWidget("btnExit")->addClickEventListener([](Ref*) { - if (TVPShowSimpleMessageBoxYesNo( - LocaleConfigManager::GetInstance()->GetText("sure_to_exit"), - "Kirikiroid2") == 0) TVPExitApplication(0); + _AskExit(); +// TVPMessageBoxForm::showYesNo("Kirikiroid2", +// LocaleConfigManager::GetInstance()->GetText("sure_to_exit"), [](int n) { +// if (n == 0) TVPExitApplication(0); +// }); }); } const Size &uiSize = getContentSize(); @@ -438,7 +454,7 @@ void TVPMainFileSelectorForm::ListHistory() split_path = PathSplit(path); cell = HistoryCell::create(fullpath, split_path.first + "/", split_path.second, "/" + lastname); Widget::ccWidgetClickCallback funcConf; - if (FileUtils::getInstance()->isFileExist(path + "/Kirikiroid2Preference.xml")) + if (TVPCheckExistentLocalFile(path + "/Kirikiroid2Preference.xml")) funcConf = [this, path](Ref*){ onShowPreferenceConfigAt(path); }; cell->initFunction(std::bind(&TVPMainFileSelectorForm::RemoveHistoryCell, this, std::placeholders::_1, cell), [this, path](Ref*){ ListDir(path); }, funcConf, [this, fullpath](Ref*) { startup(fullpath); }); @@ -477,6 +493,8 @@ void TVPMainFileSelectorForm::onKeyPressed(cocos2d::EventKeyboard::KeyCode keyCo if (keyCode == cocos2d::EventKeyboard::KeyCode::KEY_BACK) { if (isMenuShowed()) { hideMenu(nullptr); + } else { + _AskExit(); } } else if (keyCode == EventKeyboard::KeyCode::KEY_MENU) { if (isMenuShrinked()) { @@ -504,6 +522,7 @@ void TVPMainFileSelectorForm::HistoryCell::initInfo(const std::string &fullpath, _panel_delete = reader.findController("panel_delete"); if (!_panel_delete) _panel_delete = _btn_delete; _scrollview->setScrollBarEnabled(false); + _scrollview->setPropagateTouchEvents(true); _prefix->setString(prefix); _path->setString(pathname); diff --git a/src/core/environ/ui/PreferenceConfig.h b/src/core/environ/ui/PreferenceConfig.h index 6167959a..aa99ddb3 100644 --- a/src/core/environ/ui/PreferenceConfig.h +++ b/src/core/environ/ui/PreferenceConfig.h @@ -1,5 +1,5 @@ static tPreferenceScreen RootPreference; -static tPreferenceScreen* OpenglOptPreference, *SoftRendererOptPreference; +static tPreferenceScreen OpenglOptPreference, SoftRendererOptPreference; static Size PrefListSize; class tTVPPreferenceInfoCheckBox : public tTVPPreferenceInfo { @@ -11,7 +11,7 @@ class tTVPPreferenceInfoCheckBox : public tTVPPreferenceInfo { LocaleConfigManager *locmgr = LocaleConfigManager::GetInstance(); return CreatePreferenceItem(PrefListSize, locmgr->GetText(Caption), [mgr, this](tPreferenceItemCheckBox* item) { - item->_getter = std::bind(&GlobalConfigManager::GetValueBool, mgr, Key, DefaultValue); + item->_getter = std::bind(&GlobalConfigManager::GetValue, mgr, Key, DefaultValue); item->_setter = [this](bool v){ GlobalConfigManager::GetInstance()->SetValueInt(Key, v); }; @@ -29,18 +29,32 @@ class tTVPPreferenceInfoSelectList : public tTVPPreferenceInfo, tPr return CreatePreferenceItem(PrefListSize, locmgr->GetText(Caption), [this](tPreferenceItemSelectList* item) { item->initInfo(this); - item->_getter = std::bind(&GlobalConfigManager::GetValueString, GlobalConfigManager::GetInstance(), Key, DefaultValue); - item->_setter = [this](std::string v){ - GlobalConfigManager::GetInstance()->SetValue(Key, v); - }; + item->_getter = std::bind(&GlobalConfigManager::GetValue, GlobalConfigManager::GetInstance(), Key, DefaultValue); + item->_setter = [this](std::string v){ onSetValue(v); }; }); } virtual const std::vector >& getListInfo() const override { return ListInfo; } + virtual void onSetValue(const std::string &v) { + GlobalConfigManager::GetInstance()->SetValue(Key, v); + } std::vector > ListInfo; }; +class tTVPPreferenceInfoSelectRenderer : public tTVPPreferenceInfoSelectList { + typedef tTVPPreferenceInfoSelectList inherit; +public: + tTVPPreferenceInfoSelectRenderer(const std::string &cap, const std::string &key, const std::string &defval, + const std::initializer_list > &listinfo) : inherit(cap, key, defval, listinfo) {} + virtual void onSetValue(const std::string &v) { + inherit::onSetValue(v); + if (v == "opengl") { + TVPOnOpenGLRendererSelected(); + } + } +}; + class tTVPPreferenceInfoSelectFile : public tTVPPreferenceInfo { public: tTVPPreferenceInfoSelectFile(const std::string &cap, const std::string &key, const std::string &defval) @@ -50,7 +64,7 @@ class tTVPPreferenceInfoSelectFile : public tTVPPreferenceInfo { LocaleConfigManager *locmgr = LocaleConfigManager::GetInstance(); return CreatePreferenceItem(PrefListSize, locmgr->GetText(Caption), [this](tPreferenceItemFileSelect* item) { - item->_getter = std::bind(&GlobalConfigManager::GetValueString, GlobalConfigManager::GetInstance(), Key, DefaultValue); + item->_getter = std::bind(&GlobalConfigManager::GetValue, GlobalConfigManager::GetInstance(), Key, DefaultValue); item->_setter = [this](std::string v) { GlobalConfigManager::GetInstance()->SetValue(Key, v); }; @@ -58,21 +72,45 @@ class tTVPPreferenceInfoSelectFile : public tTVPPreferenceInfo { } }; -class tTVPPreferenceInfoSubPref : public iTVPPreferenceInfo { +class tTVPPreferenceInfoRendererSubPref : public iTVPPreferenceInfo { public: - tTVPPreferenceInfoSubPref(const std::string &cap) { Caption = cap; } // Key is useless + tTVPPreferenceInfoRendererSubPref(const std::string &cap) { Caption = cap; } // Key is useless + static tPreferenceScreen* GetSubPreferenceInfo() { + std::string renderer = GlobalConfigManager::GetInstance()->GetValue("renderer", "software"); + if (renderer == "opengl") + return &OpenglOptPreference; + else if (renderer == "software") + return &SoftRendererOptPreference; + return nullptr; + } virtual iPreferenceItem *createItem() override { LocaleConfigManager *locmgr = LocaleConfigManager::GetInstance(); iPreferenceItem *ret = CreatePreferenceItem(PrefListSize, locmgr->GetText(Caption)); ret->addClickEventListener([](Ref*){ - std::string renderer = GlobalConfigManager::GetInstance()->GetValueString("renderer"); - if (renderer == "opengl") - TVPMainScene::GetInstance()->pushUIForm(TVPGlobalPreferenceForm::create(OpenglOptPreference)); - else if (renderer == "software") - TVPMainScene::GetInstance()->pushUIForm(TVPGlobalPreferenceForm::create(SoftRendererOptPreference)); + TVPMainScene::GetInstance()->pushUIForm(TVPGlobalPreferenceForm::create(GetSubPreferenceInfo())); }); return ret; } + virtual tPreferenceScreen* GetSubScreenInfo() { return GetSubPreferenceInfo(); } +}; + +class tTVPPreferenceInfoSubPref : public iTVPPreferenceInfo { + tPreferenceScreen Preference; +public: + tTVPPreferenceInfoSubPref(const std::string &title, const std::initializer_list &elem) + : Preference(title, elem) + { + Caption = title; + } + virtual iPreferenceItem *createItem() override { + LocaleConfigManager *locmgr = LocaleConfigManager::GetInstance(); + iPreferenceItem *ret = CreatePreferenceItem(PrefListSize, locmgr->GetText(Caption)); + ret->addClickEventListener([this](Ref*){ + TVPMainScene::GetInstance()->pushUIForm(TVPGlobalPreferenceForm::create(&Preference)); + }); + return ret; + } + virtual tPreferenceScreen* GetSubScreenInfo() { return &Preference; } }; class tTVPPreferenceInfoSliderIcon : public tTVPPreferenceInfo { @@ -85,7 +123,7 @@ class tTVPPreferenceInfoSliderIcon : public tTVPPreferenceInfo { tPreferenceItemCursorSlider * ret = new tPreferenceItemCursorSlider(DefaultValue, TVPMainScene::convertCursorScale); ret->autorelease(); - ret->_getter = std::bind(&GlobalConfigManager::GetValueFloat, mgr, Key, DefaultValue); + ret->_getter = std::bind(&GlobalConfigManager::GetValue, mgr, Key, DefaultValue); ret->_setter = std::bind(&GlobalConfigManager::SetValueFloat, mgr, Key, std::placeholders::_1); ret->initFromInfo(PrefListSize, locmgr->GetText(Caption)); return ret; @@ -109,7 +147,7 @@ class tTVPPreferenceInfoSliderText : public tTVPPreferenceInfo { tPreferenceItemTextSlider * ret = new tPreferenceItemTextSlider(DefaultValue, convertPercentScale); ret->autorelease(); - ret->_getter = std::bind(&GlobalConfigManager::GetValueFloat, mgr, Key, DefaultValue); + ret->_getter = std::bind(&GlobalConfigManager::GetValue, mgr, Key, DefaultValue); ret->_setter = std::bind(&GlobalConfigManager::SetValueFloat, mgr, Key, std::placeholders::_1); ret->initFromInfo(PrefListSize, locmgr->GetText(Caption)); return ret; @@ -122,11 +160,11 @@ static void initAllConfig() { RootPreference.Preferences = { new tTVPPreferenceInfoCheckBox("preference_output_log", "outputlog", true), new tTVPPreferenceInfoCheckBox("preference_show_fps", "showfps", false), - new tTVPPreferenceInfoSelectList("preference_select_renderer", "renderer", "software", { + new tTVPPreferenceInfoSelectRenderer("preference_select_renderer", "renderer", "software", { { "preference_opengl", "opengl" }, { "preference_software", "software" } }), - new tTVPPreferenceInfoSubPref("preference_renderer_opt"), + new tTVPPreferenceInfoRendererSubPref("preference_renderer_opt"), new tTVPPreferenceInfoSelectFile("preference_default_font", "default_font", ""), new tTVPPreferenceInfoSelectList("preference_mem_limit", "memusage", "unlimited", { { "preference_mem_unlimited", "unlimited" }, @@ -146,10 +184,11 @@ static void initAllConfig() { #if 0 new tTVPPreferenceInfo(tTVPPreferenceInfo::eTypeSubPref, "preference_custom_option"), #endif - nullptr +// nullptr }; - SoftRendererOptPreference = new tPreferenceScreen("preference_soft_renderer_opt", { + SoftRendererOptPreference.Title = "preference_soft_renderer_opt"; + SoftRendererOptPreference.Preferences = { new tTVPPreferenceInfoSelectList("preference_multi_draw_thread", "software_draw_thread", "0", { { "preference_draw_thread_auto", "0" }, { "preference_draw_thread_1", "1" }, @@ -167,11 +206,24 @@ static void initAllConfig() { // { "preference_soft_compress_tex_quarter", "quarter" }, // { "preference_soft_compress_tex_lz4", "lz4" } }), - }); + }; - OpenglOptPreference = new tPreferenceScreen("preference_opengl_renderer_opt", { + OpenglOptPreference.Title = "preference_opengl_renderer_opt"; + OpenglOptPreference.Preferences = { + new tTVPPreferenceInfoSubPref("preference_opengl_extension_opt", { + new tTVPPreferenceInfoCheckBox("GL_EXT_shader_framebuffer_fetch", "GL_EXT_shader_framebuffer_fetch", true), + new tTVPPreferenceInfoCheckBox("GL_ARM_shader_framebuffer_fetch", "GL_ARM_shader_framebuffer_fetch", true), + new tTVPPreferenceInfoCheckBox("GL_ARM_shader_framebuffer_fetch", "GL_NV_shader_framebuffer_fetch", true), + new tTVPPreferenceInfoCheckBox("GL_EXT_copy_image", "GL_EXT_copy_image", false), + new tTVPPreferenceInfoCheckBox("GL_OES_copy_image", "GL_OES_copy_image", false), + new tTVPPreferenceInfoCheckBox("GL_ARB_copy_image", "GL_ARB_copy_image", false), + new tTVPPreferenceInfoCheckBox("GL_NV_copy_image", "GL_NV_copy_image", false), + new tTVPPreferenceInfoCheckBox("GL_EXT_clear_texture", "GL_EXT_clear_texture", true), + new tTVPPreferenceInfoCheckBox("GL_ARB_clear_texture", "GL_ARB_clear_texture", true), + new tTVPPreferenceInfoCheckBox("GL_QCOM_alpha_test", "GL_QCOM_alpha_test", true), + }), new tTVPPreferenceInfoCheckBox("preference_ogl_accurate_render", "ogl_accurate_render", false), - new tTVPPreferenceInfoCheckBox("preference_opengl_dup_target", "ogl_dup_target", true), +// new tTVPPreferenceInfoCheckBox("preference_opengl_dup_target", "ogl_dup_target", true), new tTVPPreferenceInfoSelectList("preference_ogl_max_texsize", "ogl_max_texsize", "0", { { "preference_ogl_texsize_auto", "0" }, { "preference_ogl_texsize_1024", "1024" }, @@ -189,5 +241,5 @@ static void initAllConfig() { // { "preference_ogl_render_tex_quality_75", "0.75" }, // { "preference_ogl_render_tex_quality_50", "0.5" } // }), - }); + }; } \ No newline at end of file diff --git a/src/core/environ/ui/PreferenceForm.cpp b/src/core/environ/ui/PreferenceForm.cpp index a4920cd5..23850b85 100644 --- a/src/core/environ/ui/PreferenceForm.cpp +++ b/src/core/environ/ui/PreferenceForm.cpp @@ -48,6 +48,7 @@ void TVPPreferenceForm::bindHeaderController(const NodeMap &allNodes) void tPreferenceScreen::clear() { for (auto p : Preferences) delete p; + Preferences.clear(); } void iPreferenceItem::initFromInfo(Size size, const std::string& title) { diff --git a/src/core/environ/ui/PreferenceForm.h b/src/core/environ/ui/PreferenceForm.h index 311fd290..cbe94f51 100644 --- a/src/core/environ/ui/PreferenceForm.h +++ b/src/core/environ/ui/PreferenceForm.h @@ -1,6 +1,9 @@ #pragma once #include "BaseForm.h" #include "ui/UIWidget.h" +#include "ConfigManager/GlobalConfigManager.h" + +void TVPOnOpenGLRendererSelected(); namespace tinyxml2 { class XMLElement; @@ -25,6 +28,8 @@ class iPreferenceItem; class iTVPPreferenceInfo { public: virtual iPreferenceItem *createItem() = 0; + virtual void InitDefaultConfig() {} + virtual tPreferenceScreen* GetSubScreenInfo() { return nullptr; } iTVPPreferenceInfo() {} iTVPPreferenceInfo(const std::string &cap, const std::string &key) : Caption(cap), Key(key) {} @@ -49,8 +54,12 @@ struct tTVPPreferenceInfo : public iTVPPreferenceInfo { // if (SubPrefScreen) delete SubPrefScreen; // } + virtual void InitDefaultConfig() { + if (!Key.empty()) + GlobalConfigManager::GetInstance()->GetValue(Key, DefaultValue); + } - tPreferenceScreen *SubPrefScreen; // eTypeSubPref +// tPreferenceScreen *SubPrefScreen = nullptr; // eTypeSubPref }; class TVPPreferenceForm : public iTVPBaseForm { diff --git a/src/core/environ/ui/SimpleMediaFilePlayer.cpp b/src/core/environ/ui/SimpleMediaFilePlayer.cpp index 0ea3b489..ba3f73d4 100644 --- a/src/core/environ/ui/SimpleMediaFilePlayer.cpp +++ b/src/core/environ/ui/SimpleMediaFilePlayer.cpp @@ -1,4 +1,7 @@ #include "SimpleMediaFilePlayer.h" +#ifdef PixelFormat // libavcodec vs cocos2d +#undef PixelFormat +#endif #include "cocos2d.h" #include "StorageIntf.h" #include "SysInitIntf.h" @@ -7,9 +10,6 @@ #include "ui/UISlider.h" #include "cocos2d/MainScene.h" #include "cocos/ui/UIHelper.h" -#ifdef PixelFormat // libavcodec vs cocos2d -#undef PixelFormat -#endif #include "movie/ffmpeg/KRMoviePlayer.h" #include "StorageImpl.h" @@ -44,6 +44,7 @@ class SimplePlayerOverlay { _overlay->SetRootNode(rootNode); parent->addChild(rootNode); rootNode->setContentSize(cocos2d::Size::ZERO); + _overlay->SetVisible(true); } KRMovie::VideoPresentOverlay2 &GetOverlay() { return *_overlay; } }; diff --git a/src/core/environ/win32/Platform.cpp b/src/core/environ/win32/Platform.cpp index c5f7182e..38642e15 100644 --- a/src/core/environ/win32/Platform.cpp +++ b/src/core/environ/win32/Platform.cpp @@ -8,7 +8,9 @@ #include "StorageImpl.h" #include "SysInitIntf.h" #include "platform/CCFileUtils.h" -#include +#include +#include "Application.h" +#include "EventIntf.h" #pragma comment(lib,"psapi.lib") @@ -23,7 +25,7 @@ tjs_int TVPGetSelfUsedMemory() { PROCESS_MEMORY_COUNTERS info; GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); - return info.PeakWorkingSetSize / (1024 * 1024); + return info.WorkingSetSize / (1024 * 1024); } void TVPGetMemoryInfo(TVPMemoryInfo &m) @@ -287,7 +289,15 @@ std::string TVPGetCurrentLanguage() { return ret; } +extern tTJS *TVPScriptEngine; +void TVPReleaseFontLibrary(); void TVPExitApplication(int code) { + // clear some static data for memory leak detect + TVPDeliverCompactEvent(TVP_COMPACT_LEVEL_MAX); + if (TVPScriptEngine) TVPScriptEngine->Cleanup(); + TVPReleaseFontLibrary(); + delete ::Application; + TVPMainScene::GetInstance()->removeFromParent(); exit(code); } @@ -322,12 +332,11 @@ void TVPHideIME() {} void TVPRelinquishCPU(){ Sleep(0); } -tjs_int WIN32GetProcessorNum() { - SYSTEM_INFO info; - GetSystemInfo(&info); - return info.dwNumberOfProcessors; -} tjs_uint32 TVPGetRoughTickCount32() { return timeGetTime(); +} + +void TVPPrintLog(const char *str) { + printf("%s", str); } \ No newline at end of file diff --git a/src/core/movie/ffmpeg/BaseRenderer.cpp b/src/core/movie/ffmpeg/BaseRenderer.cpp index d1e50918..ef24e000 100644 --- a/src/core/movie/ffmpeg/BaseRenderer.cpp +++ b/src/core/movie/ffmpeg/BaseRenderer.cpp @@ -2,6 +2,7 @@ #include #include "BaseRenderer.h" #include "MathUtils.h" +#include NS_KRMOVIE_BEGIN @@ -542,7 +543,7 @@ void CBaseRenderer::MarkDirty() void CBaseRenderer::SettingOptionsRenderMethodsFiller(/*const CSetting *setting,*/ std::vector< std::pair > &list, int ¤t, void *data) { - list.push_back(std::make_pair("rendermethod_auto"/*g_localizeStrings.Get(13416)*/, RENDER_METHOD_AUTO)); + list.emplace_back("rendermethod_auto"/*g_localizeStrings.Get(13416)*/, RENDER_METHOD_AUTO); #ifdef HAS_DX list.push_back(make_pair(g_localizeStrings.Get(16319), RENDER_METHOD_DXVA)); diff --git a/src/core/movie/ffmpeg/Clock.cpp b/src/core/movie/ffmpeg/Clock.cpp index 261e7bfd..b8b14207 100644 --- a/src/core/movie/ffmpeg/Clock.cpp +++ b/src/core/movie/ffmpeg/Clock.cpp @@ -76,7 +76,7 @@ double CDVDClock::GetVsyncAdjust() CSingleLock lock(m_critSection); return m_vSyncAdjust; } -#if 0 + void CDVDClock::Pause(bool pause) { CSingleLock lock(m_critSection); @@ -96,7 +96,7 @@ void CDVDClock::Pause(bool pause) SetSpeed(m_speedAfterPause); } } -#endif + void CDVDClock::SetSpeed(int iSpeed) { // this will sometimes be a little bit of due to rounding errors, ie clock might jump abit when changing speed diff --git a/src/core/movie/ffmpeg/Clock.h b/src/core/movie/ffmpeg/Clock.h index 86b5a993..5eef4121 100644 --- a/src/core/movie/ffmpeg/Clock.h +++ b/src/core/movie/ffmpeg/Clock.h @@ -48,6 +48,7 @@ class CDVDClock { bool GetClockInfo(int& MissedVblanks, double& ClockSpeed, double& RefreshRate) const; void SetVsyncAdjust(double adjustment); double GetVsyncAdjust(); + void Pause(bool pause); protected: double SystemToAbsolute(int64_t system); diff --git a/src/core/movie/ffmpeg/KRMovieLayer.cpp b/src/core/movie/ffmpeg/KRMovieLayer.cpp index bdac40fc..df8f13de 100644 --- a/src/core/movie/ffmpeg/KRMovieLayer.cpp +++ b/src/core/movie/ffmpeg/KRMovieLayer.cpp @@ -82,7 +82,7 @@ int VideoPresentLayer::AddVideoPicture(DVDVideoPicture &pic, int index) int width = pic.iWidth, height = pic.iHeight; - uint8_t *data = new uint8_t[width * height * 4]; + uint8_t *data = (uint8_t*)TJSAlignedAlloc(width * height * 4, 4); int datasize = width * 4; img_convert_ctx = sws_getCachedContext( diff --git a/src/core/movie/ffmpeg/KRMoviePlayer.cpp b/src/core/movie/ffmpeg/KRMoviePlayer.cpp index 464d2fee..1219dbfc 100644 --- a/src/core/movie/ffmpeg/KRMoviePlayer.cpp +++ b/src/core/movie/ffmpeg/KRMoviePlayer.cpp @@ -110,7 +110,7 @@ void TVPMoviePlayer::GetAudioBalance(long *balance) { TVPALSoundWrap* alsound = GetSoundDevice(); if (alsound) { - *balance = alsound->GetPan() * 10000; + *balance = alsound->GetPan() * 100000; } } @@ -118,20 +118,20 @@ void TVPMoviePlayer::SetAudioBalance(long balance) { TVPALSoundWrap* alsound = GetSoundDevice(); if (alsound) { - alsound->SetPan(balance / 10000.0f); + alsound->SetPan(balance / 100000.0f); } } void TVPMoviePlayer::SetAudioVolume(long volume) { TVPALSoundWrap* alsound = GetSoundDevice(); - if (alsound) alsound->SetVolume((volume + 10000) / 10000.f); + if (alsound) alsound->SetVolume(volume / 100000.f); } void TVPMoviePlayer::GetAudioVolume(long *volume) { TVPALSoundWrap* alsound = GetSoundDevice(); - if (alsound) *volume = alsound->GetVolume() * 10000 - 10000; + if (alsound) *volume = alsound->GetVolume() * 100000; } void TVPMoviePlayer::GetNumberOfAudioStream(unsigned long *streamCount) { @@ -209,23 +209,13 @@ int TVPMoviePlayer::AddVideoPicture(DVDVideoPicture &pic, int index) if (m_usedPicture >= MAX_BUFFER_COUNT) return -1; int width = pic.iWidth, height = pic.iHeight; -#if 0 - uint8_t *data = new uint8_t[width * height * 4]; - int datasize = width * 4; - - img_convert_ctx = sws_getCachedContext( - img_convert_ctx, width, height, AV_PIX_FMT_YUV420P, width, height, - AV_PIX_FMT_RGBA, /*sws_flags*/SWS_FAST_BILINEAR, NULL, NULL, NULL); - assert(img_convert_ctx); - int processed = sws_scale(img_convert_ctx, pic.data, pic.iLineSize, 0, pic.iHeight, &data, &datasize); -#endif // YUV data passthrough int yuvwidth[3] = { width, width / 2, width / 2 }; int yuvheight[3] = { height, height / 2, height / 2 }; uint8_t *yuvdata[3] = { nullptr }; for (int i = 0; i < sizeof(yuvdata) / sizeof(yuvdata[0]); ++i) { int size = yuvwidth[i] * yuvheight[i]; - yuvdata[i] = new uint8_t[size]; + yuvdata[i] = (uint8_t*)TJSAlignedAlloc(size, 4); if (yuvwidth[i] == pic.iLineSize[i]) { memcpy(yuvdata[i], pic.data[i], size); } else { @@ -264,7 +254,10 @@ VideoPresentOverlay::~VideoPresentOverlay() void VideoPresentOverlay::ClearNode() { - if (m_pRootNode) m_pRootNode->removeFromParent(), m_pRootNode = nullptr; + if (m_pRootNode) { + m_pRootNode->removeFromParent(), m_pRootNode = nullptr; + m_pSprite = nullptr; + } } void VideoPresentOverlay::PresentPicture(float dt) @@ -328,6 +321,18 @@ void VideoPresentOverlay::PresentPicture(float dt) } } +void KRMovie::VideoPresentOverlay::Play() +{ + if (m_pSprite) m_pSprite->setVisible(true); + TVPMoviePlayer::Play(); +} + +void KRMovie::VideoPresentOverlay::Stop() +{ + if (m_pSprite) m_pSprite->setVisible(false); + TVPMoviePlayer::Stop(); +} + MoviePlayerOverlay::~MoviePlayerOverlay() { assert(std::this_thread::get_id() == TVPMainThreadID); @@ -377,6 +382,12 @@ void VideoPresentOverlay::BitmapPicture::swap(BitmapPicture &r) std::swap(height, r.height); } +void TVPMoviePlayer::BitmapPicture::Clear() +{ + for (int i = 0; i < sizeof(data) / sizeof(data[0]); ++i) + if (data[i]) TJSAlignedDealloc(data[i]), data[i] = nullptr; +} + void VideoPresentOverlay2::SetRootNode(cocos2d::Node *node) { ClearNode(); diff --git a/src/core/movie/ffmpeg/KRMoviePlayer.h b/src/core/movie/ffmpeg/KRMoviePlayer.h index 95336956..ccb9a4b9 100644 --- a/src/core/movie/ffmpeg/KRMoviePlayer.h +++ b/src/core/movie/ffmpeg/KRMoviePlayer.h @@ -143,10 +143,7 @@ class TVPMoviePlayer : public iTVPVideoOverlay, public CBaseRenderer { } ~BitmapPicture() { Clear(); } void swap(BitmapPicture &r); - void Clear() { - for (int i = 0; i < sizeof(data) / sizeof(data[0]); ++i) - if (data[i]) delete[] data[i], data[i] = nullptr; - } + void Clear(); }; BitmapPicture m_picture[MAX_BUFFER_COUNT]; int m_curPicture = 0, m_usedPicture = 0; @@ -166,6 +163,8 @@ class VideoPresentOverlay : public TVPMoviePlayer // cocos2d compatible video di void ClearNode(); public: void PresentPicture(float dt); + virtual void Stop() override; + virtual void Play() override; protected: virtual const tTVPRect &GetBounds() = 0; diff --git a/src/core/movie/ffmpeg/MessageQueue.cpp b/src/core/movie/ffmpeg/MessageQueue.cpp index a5e19c1b..36270d3b 100644 --- a/src/core/movie/ffmpeg/MessageQueue.cpp +++ b/src/core/movie/ffmpeg/MessageQueue.cpp @@ -1,6 +1,7 @@ #include "MessageQueue.h" #include "Clock.h" #include "DemuxPacket.h" +#include NS_KRMOVIE_BEGIN CDVDMessageQueue::CDVDMessageQueue(const std::string &owner) : /*m_hEvent(true),*/ m_owner(owner) @@ -251,7 +252,7 @@ int CDVDMessageQueue::GetLevel() if (IsDataBased()) return std::min(100, 100 * m_iDataSize / m_iMaxDataSize); - int level = std::min(100.0, ceil(100.0 * m_TimeSize * (m_TimeFront - m_TimeBack) / DVD_TIME_BASE)); + int level = std::min(100.0, std::ceil(100.0 * m_TimeSize * (m_TimeFront - m_TimeBack) / DVD_TIME_BASE)); // if we added lots of packets with NOPTS, make sure that the queue is not signalled empty if (level == 0 && m_iDataSize != 0) diff --git a/src/core/movie/ffmpeg/MessageQueue.h b/src/core/movie/ffmpeg/MessageQueue.h index 8949aa23..32728915 100644 --- a/src/core/movie/ffmpeg/MessageQueue.h +++ b/src/core/movie/ffmpeg/MessageQueue.h @@ -5,6 +5,7 @@ #include #include #include "Thread.h" +#include NS_KRMOVIE_BEGIN diff --git a/src/core/movie/ffmpeg/ProcessInfo.h b/src/core/movie/ffmpeg/ProcessInfo.h index 15a36b21..b00783cb 100644 --- a/src/core/movie/ffmpeg/ProcessInfo.h +++ b/src/core/movie/ffmpeg/ProcessInfo.h @@ -2,6 +2,7 @@ #include "KRMovieDef.h" #include "Thread.h" #include "RenderFormats.h" +#include NS_KRMOVIE_BEGIN class CProcessInfo diff --git a/src/core/movie/ffmpeg/Thread.cpp b/src/core/movie/ffmpeg/Thread.cpp index 69961b3f..ba9b1c24 100644 --- a/src/core/movie/ffmpeg/Thread.cpp +++ b/src/core/movie/ffmpeg/Thread.cpp @@ -1,9 +1,17 @@ #include "Thread.h" #include #include +#include "MsgIntf.h" +#include "ThreadImpl.h" NS_KRMOVIE_BEGIN +CThread::CThread() + : m_bStop(false), m_bRunning(false) +{ + +} + CThread::~CThread() { if (m_bRunning) { @@ -17,7 +25,7 @@ CThread::~CThread() void CThread::Create() { if (m_bRunning.exchange(true)) { - throw new std::logic_error("thread already in running"); + TVPThrowExceptionMessage(TJS_W("thread already in running")); } m_bStop = false; if (m_ThreadId) { @@ -59,6 +67,7 @@ int CThread::entry() Process(); OnExit(); m_bRunning = false; + TVPOnThreadExited(); return 0; } diff --git a/src/core/movie/ffmpeg/Thread.h b/src/core/movie/ffmpeg/Thread.h index 9fd9f038..aa51a005 100644 --- a/src/core/movie/ffmpeg/Thread.h +++ b/src/core/movie/ffmpeg/Thread.h @@ -2,14 +2,15 @@ #include "KRMovieDef.h" #include #include - -namespace std { class thread; } +#include +#include NS_KRMOVIE_BEGIN typedef std::recursive_mutex CCriticalSection; typedef std::unique_lock CSingleLock; class CThread { public: + CThread(); virtual ~CThread(); void Create(); bool IsRunning() const { return m_bRunning; } diff --git a/src/core/movie/ffmpeg/VideoCodecFFmpeg.cpp b/src/core/movie/ffmpeg/VideoCodecFFmpeg.cpp index aea9b48b..2c4660fb 100644 --- a/src/core/movie/ffmpeg/VideoCodecFFmpeg.cpp +++ b/src/core/movie/ffmpeg/VideoCodecFFmpeg.cpp @@ -38,6 +38,7 @@ extern "C" { #include "Clock.h" #include "CodecUtils.h" #include "tp_stub.h" +#include #include NS_KRMOVIE_BEGIN diff --git a/src/core/movie/ffmpeg/VideoPlayer.cpp b/src/core/movie/ffmpeg/VideoPlayer.cpp index c6c7eecc..250b2079 100644 --- a/src/core/movie/ffmpeg/VideoPlayer.cpp +++ b/src/core/movie/ffmpeg/VideoPlayer.cpp @@ -1,5 +1,5 @@ #include "VideoPlayer.h" -#include +#include #include #include "DemuxFFmpeg.h" #include "VideoPlayerVideo.h" @@ -9,6 +9,8 @@ #include "krmovie.h" #include "TimeUtils.h" #include "tjsConfig.h" +#include "Application.h" +#include NS_KRMOVIE_BEGIN @@ -198,6 +200,7 @@ BasePlayer::BasePlayer(CBaseRenderer *renderer) BasePlayer::~BasePlayer() { CloseInputStream(); DestroyPlayers(); + ::Application->RegisterActiveEvent(this, nullptr); } void BasePlayer::Play() @@ -245,6 +248,18 @@ void BasePlayer::SetLoopSegement(int beginFrame, unsigned int endFrame) m_iLoopSegmentEnd = endFrame; } +void BasePlayer::OnDeactive() +{ + m_origSpeed = GetSpeed(); + m_clock.Pause(true); +} + +void BasePlayer::OnActive() +{ + m_clock.Pause(false); + SetSpeed(m_origSpeed); +} + void BasePlayer::VideoParamsChange() { m_messenger.Put(new CDVDMsg(CDVDMsg::PLAYER_AVCHANGE)); diff --git a/src/core/movie/ffmpeg/VideoPlayer.h b/src/core/movie/ffmpeg/VideoPlayer.h index 5320bfb0..e3bbd5df 100644 --- a/src/core/movie/ffmpeg/VideoPlayer.h +++ b/src/core/movie/ffmpeg/VideoPlayer.h @@ -315,6 +315,8 @@ class BasePlayer : public CThread, public IRenderMsg void SetLoopSegement(int beginFrame, unsigned int endFrame); private: + void OnActive(); + void OnDeactive(); // bool Shutdown = false; bool m_bStopStatus = true; std::string m_strFileName; @@ -334,6 +336,7 @@ class BasePlayer : public CThread, public IRenderMsg std::atomic_int m_playSpeed; std::atomic_int m_newPlaySpeed; + double m_origSpeed = 0; int m_streamPlayerSpeed = DVD_PLAYSPEED_NORMAL; struct SSpeedState { diff --git a/src/core/msg/MsgIntfInc.h b/src/core/msg/MsgIntfInc.h index b992fdb2..6b60a511 100644 --- a/src/core/msg/MsgIntfInc.h +++ b/src/core/msg/MsgIntfInc.h @@ -27,7 +27,7 @@ TVP_MSG_DEFINE(TVPWriteError, "Write error") TVP_MSG_DEFINE(TVPSeekError, "Seek error") TVP_MSG_DEFINE(TVPTruncateError, "Truncate error") TVP_MSG_DEFINE(TVPInsufficientMemory, "Insufficient memory") -TVP_MSG_DEFINE(TVPUncompressionFailed,"Unpompression failed") +TVP_MSG_DEFINE(TVPUncompressionFailed,"Uncompression failed") TVP_MSG_DEFINE(TVPCompressionFailed, "Compression failed") TVP_MSG_DEFINE(TVPCannotWriteToArchive, "Cannot write to archive") TVP_MSG_DEFINE(TVPUnsupportedCipherMode, "%1 is unsupported cipher mode") diff --git a/src/core/sound/win32/WaveImpl.cpp b/src/core/sound/win32/WaveImpl.cpp index 3002fbbc..490ec2ba 100644 --- a/src/core/sound/win32/WaveImpl.cpp +++ b/src/core/sound/win32/WaveImpl.cpp @@ -47,8 +47,6 @@ #include "NativeEventQueue.h" #include "Platform.h" -static void PauseWaveSoundBufferThread(bool b); - //--------------------------------------------------------------------------- // Options management //--------------------------------------------------------------------------- @@ -71,6 +69,7 @@ static tjs_int TVPL1BufferLength = 1000; // in ms static tjs_int TVPL2BufferLength = 1000; // in ms static bool TVPDirectSoundUse3D = false; static tjs_int TVPVolumeLogFactor = 3322; +static bool TVPPrimarySoundBufferPlaying = false; //--------------------------------------------------------------------------- static void TVPInitSoundOptions() { @@ -545,6 +544,7 @@ static void TVPInitLogTable() } } //--------------------------------------------------------------------------- +#if 0 tjs_int TVPVolumeToDSAttenuate(tjs_int volume) { TVPInitLogTable(); @@ -582,6 +582,7 @@ tjs_int TVPDSAttenuateToPan(tjs_int att) return (100 - (tjs_int)(pow(10, (double)att / -TVPVolumeLogFactor) * 100.0)) * 1000; } //--------------------------------------------------------------------------- +#endif @@ -605,7 +606,6 @@ static void TVPEnsurePrimaryBufferPlay() if (!TVPControlPrimaryBufferRun) return; TVPInitDirectSound(); if (!TVPPrimaryBufferPlayingByProgram) { - PauseWaveSoundBufferThread(false); TVPPrimaryBufferPlayingByProgram = true; } #if 0 @@ -1494,7 +1494,6 @@ class tTVPWaveSoundBufferThread : public tTVPThread //HWND UtilWindow; // utility window to notify the pending events occur bool PendingLabelEventExists; bool WndProcToBeCalled; - bool IsPaused; DWORD NextLabelEventTick; DWORD LastFilledTick; @@ -1516,21 +1515,10 @@ class tTVPWaveSoundBufferThread : public tTVPThread public: void Start(void); void CheckBufferSleep(); - - void Pause(bool b); } static *TVPWaveSoundBufferThread = NULL; //--------------------------------------------------------------------------- -static void PauseWaveSoundBufferThread(bool b) { - if (TVPWaveSoundBufferThread) { - TVPWaveSoundBufferThread->Pause(false); - } -} - void TVPLockSoundMixer() { - if (TVPWaveSoundBufferThread) { - TVPWaveSoundBufferThread->Pause(true); - TVPControlPrimaryBufferRun = false; - } + TVPPrimaryBufferPlayingByProgram = false; } void TVPUnlockSoundMixer() { if (TVPWaveSoundBufferThread) TVPEnsurePrimaryBufferPlay(); @@ -1633,6 +1621,17 @@ void tTVPWaveSoundBufferThread::Execute(void) { // thread-protected tTJSCriticalSectionHolder holder(TVPWaveSoundBufferVectorCS); + if (TVPPrimaryBufferPlayingByProgram != TVPPrimarySoundBufferPlaying) { + TVPPrimarySoundBufferPlaying = TVPPrimaryBufferPlayingByProgram; + std::vector::iterator i; + for (i = TVPWaveSoundBufferVector.begin(); + i != TVPWaveSoundBufferVector.end(); i++) + { + if ((*i)->ThreadCallbackEnabled) + (*i)->SetBufferPaused(!TVPPrimaryBufferPlayingByProgram); // for preventing buffer runs out on iOS' OpenAL implement + } + } + // check PendingLabelEventExists if(PendingLabelEventExists) { @@ -1643,7 +1642,7 @@ void tTVPWaveSoundBufferThread::Execute(void) } } - if(time - LastFilledTick >= TVP_WSB_THREAD_SLEEP_TIME) + if (TVPPrimarySoundBufferPlaying && time - LastFilledTick >= TVP_WSB_THREAD_SLEEP_TIME) { std::vector::iterator i; for(i = TVPWaveSoundBufferVector.begin(); @@ -1681,6 +1680,7 @@ void tTVPWaveSoundBufferThread::Execute(void) //--------------------------------------------------------------------------- void tTVPWaveSoundBufferThread::Start() { + TVPPrimaryBufferPlayingByProgram = true; Event.Set(); Resume(); } @@ -1707,18 +1707,6 @@ void tTVPWaveSoundBufferThread::CheckBufferSleep() #endif } //--------------------------------------------------------------------------- -void tTVPWaveSoundBufferThread::Pause(bool b) { - IsPaused = b; - std::vector::iterator i; - for (i = TVPWaveSoundBufferVector.begin(); - i != TVPWaveSoundBufferVector.end(); i++) - { - if ((*i)->ThreadCallbackEnabled) - (*i)->SetBufferPaused(b); // for preventing buffer runs out on iOS' OpenAL implement - } - Event.Set(); -} -//--------------------------------------------------------------------------- //--------------------------------------------------------------------------- @@ -1918,7 +1906,7 @@ void tTVPWaveSoundBufferDecodeThread::Execute(void) } if(GetTerminated()) break; // sleep while running - Event.WaitFor(/*INFINITE*/-1); + Event.WaitFor(/*INFINITE*/0); } } //--------------------------------------------------------------------------- @@ -2624,6 +2612,7 @@ bool tTJSNI_WaveSoundBuffer::FillBuffer(bool firstwrite, bool allowpause) if(!SoundBuffer) return true; if(!Decoder) return true; if(!BufferPlaying) return true; + if (!TVPPrimarySoundBufferPlaying) return true; // check paused state if(allowpause) diff --git a/src/core/sound/win32/WaveImpl.h b/src/core/sound/win32/WaveImpl.h index a9836e33..ff5175ca 100644 --- a/src/core/sound/win32/WaveImpl.h +++ b/src/core/sound/win32/WaveImpl.h @@ -49,10 +49,12 @@ extern void TVPResetVolumeToAllSoundBuffer(); extern void TVPSetWaveSoundBufferUse3DMode(bool b); extern bool TVPGetWaveSoundBufferUse3DMode(); extern void TVPWaveSoundBufferCommitSettings(); +#if 0 extern tjs_int TVPVolumeToDSAttenuate(tjs_int volume); extern tjs_int TVPDSAttenuateToVolume(tjs_int att); extern tjs_int TVPPanToDSAttenuate(tjs_int volume); extern tjs_int TVPDSAttenuateToPan(tjs_int att); +#endif //--------------------------------------------------------------------------- diff --git a/src/core/tjs2/tjs.tab.cpp b/src/core/tjs2/tjs.tab.cpp index defc8b81..ef00fd89 100644 --- a/src/core/tjs2/tjs.tab.cpp +++ b/src/core/tjs2/tjs.tab.cpp @@ -83,7 +83,7 @@ /* TJS2 bison input file */ -#include +#include #include "tjsInterCodeGen.h" diff --git a/src/core/tjs2/tjsCommHead.h b/src/core/tjs2/tjsCommHead.h index ac7ece19..d4be493d 100644 --- a/src/core/tjs2/tjsCommHead.h +++ b/src/core/tjs2/tjsCommHead.h @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/core/tjs2/tjsConfig.cpp b/src/core/tjs2/tjsConfig.cpp index 91c8cfe6..49e9ac00 100644 --- a/src/core/tjs2/tjsConfig.cpp +++ b/src/core/tjs2/tjsConfig.cpp @@ -13,6 +13,7 @@ #include "tjsCommHead.h" #include #include +#include #ifdef __WIN32__ #include #define isfinite _finite @@ -696,6 +697,33 @@ tjs_char * TJS_strchr ( return((tjs_char *)string); return(NULL); } + +void * TJS_malloc(size_t len) +{ + char *ret = (char*)malloc(len+sizeof(size_t)); + if (!ret) return nullptr; + *(size_t*)ret = len; // embed size + return ret + sizeof(size_t); +} + +void * TJS_realloc(void* buf, size_t len) +{ + if (!buf) return TJS_malloc(len); + // compare embeded size + size_t * ptr = (size_t *)((char*)buf - sizeof(size_t)); + if (*ptr >= len) return buf; // still adequate + char *ret = (char*)TJS_malloc(len); + if (!ret) return nullptr; + memcpy(ret, ptr + 1, *ptr); + TJS_free(buf); + return ret; +} + +void TJS_free(void *buf) +{ + free((char*)buf - sizeof(size_t)); +} + tjs_char *TJS_strrchr(const tjs_char *s, int c) { tjs_char* ret = 0; @@ -2561,9 +2589,9 @@ double TJS_strtod(const tjs_char* string, tjs_char** endPtr) } else { mantSize -= 1; /* One of the digits was the point. */ } - if (mantSize > 18) { - fracExp = decPt - 18; - mantSize = 18; + if (mantSize > 48) { + fracExp = decPt - 48; + mantSize = 48; } else { fracExp = decPt - mantSize; } diff --git a/src/core/tjs2/tjsConfig.h b/src/core/tjs2/tjsConfig.h index 4f5c08d1..78ed9253 100644 --- a/src/core/tjs2/tjsConfig.h +++ b/src/core/tjs2/tjsConfig.h @@ -57,9 +57,9 @@ tjs_char * TJS_strncpy (tjs_char * dest, const tjs_char * source, size_t count); tjs_char * TJS_strcat (tjs_char * dst, const tjs_char * src); tjs_char * TJS_strstr (const tjs_char * wcs1, const tjs_char * wcs2); tjs_char * TJS_strchr (const tjs_char * string, tjs_char ch); -#define TJS_malloc malloc -#define TJS_free free -#define TJS_realloc realloc +void *TJS_malloc(size_t n); +void *TJS_realloc(void* orig, size_t n); +void TJS_free(void *p); #define TJS_nsprintf sprintf #define TJS_nstrcpy strcpy #define TJS_nstrcat strcat diff --git a/src/core/tjs2/tjsGlobalStringMap.cpp b/src/core/tjs2/tjsGlobalStringMap.cpp index bb3cee2a..2f8e8f48 100644 --- a/src/core/tjs2/tjsGlobalStringMap.cpp +++ b/src/core/tjs2/tjsGlobalStringMap.cpp @@ -12,6 +12,7 @@ #include "tjsGlobalStringMap.h" #include "tjsHashSearch.h" +#include /* Global String Map is a large string hash table, to share the string @@ -116,8 +117,11 @@ void TJSReleaseGlobalStringMap() tTJSGlobalStringMap::Release(); } //--------------------------------------------------------------------------- +static std::mutex _mutex; ttstr TJSMapGlobalStringMap(const ttstr & string) { + // for multi-thread + std::lock_guard lk(_mutex); return tTJSGlobalStringMap::Map(string); } //--------------------------------------------------------------------------- diff --git a/src/core/tjs2/tjsInterCodeExec.cpp b/src/core/tjs2/tjsInterCodeExec.cpp index 39024a82..db308abe 100644 --- a/src/core/tjs2/tjsInterCodeExec.cpp +++ b/src/core/tjs2/tjsInterCodeExec.cpp @@ -29,8 +29,9 @@ static bool isDebuggerPresent() { return true; } -#define IsDebuggerPresent() isDebuggerPresent +#define IsDebuggerPresent isDebuggerPresent #endif // ENABLE_DEBUGGER +#include namespace TJS { @@ -723,9 +724,11 @@ void TJSVariantArrayStackCompact() //--------------------------------------------------------------------------- void TJSVariantArrayStackCompactNow() { +#if 0 // due to multi-thread for (tTJSVariantArrayStack* stk : TJSVariantArrayStacks) { stk->Compact(); } +#endif } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- diff --git a/src/core/tjs2/tjsObject.cpp b/src/core/tjs2/tjsObject.cpp index ee590366..61ef697a 100644 --- a/src/core/tjs2/tjsObject.cpp +++ b/src/core/tjs2/tjsObject.cpp @@ -405,8 +405,10 @@ tTJSCustomObject::tTJSCustomObject(tjs_int hashbits) if(FinalizeName.IsEmpty()) { // first time; initialize 'finalize' name and 'missing' name - FinalizeName = TJSMapGlobalStringMap(TJS_W("finalize")); - MissingName = TJSMapGlobalStringMap(TJS_W("missing")); + static ttstr _finalize = TJSMapGlobalStringMap(TJS_W("finalize")); + static ttstr _missing = TJSMapGlobalStringMap(TJS_W("missing")); + FinalizeName = _finalize; + MissingName = _missing; } finalize_name = FinalizeName; missing_name = MissingName; diff --git a/src/core/tjs2/tjsTypes.h b/src/core/tjs2/tjsTypes.h index ae6fcd5b..d7e1d678 100644 --- a/src/core/tjs2/tjsTypes.h +++ b/src/core/tjs2/tjsTypes.h @@ -13,6 +13,7 @@ #define __TJSTYPES_H__ #include +#include // ptrdiff_t #ifdef HAVE_CONFIG_H #include "config.h" diff --git a/src/core/tjs2/tjsVariant.h b/src/core/tjs2/tjsVariant.h index f657a05d..b1966b47 100644 --- a/src/core/tjs2/tjsVariant.h +++ b/src/core/tjs2/tjsVariant.h @@ -11,7 +11,7 @@ #ifndef tjsVariantH #define tjsVariantH -#include +//#include //#include #ifdef TJS_SUPPORT_VCL diff --git a/src/core/tjs2/tjsVariantString.cpp b/src/core/tjs2/tjsVariantString.cpp index 6a4df411..5cf72808 100644 --- a/src/core/tjs2/tjsVariantString.cpp +++ b/src/core/tjs2/tjsVariantString.cpp @@ -14,6 +14,7 @@ #include "tjsError.h" #include "tjsUtils.h" #include "tjsLex.h" +#include namespace TJS @@ -83,10 +84,12 @@ tjs_int TJSGetShorterStrLen(const tjs_char *str, tjs_int max) else len = len + TJSVS_ALLOC_INC_SIZE_L; - char *ret = (char*)realloc(ptr, + char *ret = (char*)malloc(//ptr, len*sizeof(tjs_char) + sizeof(size_t)); if(!ret) TJSThrowStringAllocError(); + memcpy(ret + sizeof(size_t), ptr + 1, *ptr*sizeof(tjs_char)); *(size_t *)ret = len; // embed size + TJSVS_free(buf); return (tjs_char*)(ret + sizeof(size_t)); } //--------------------------------------------------------------------------- diff --git a/src/core/tjs2/tjsdate.tab.cpp b/src/core/tjs2/tjsdate.tab.cpp index 1dd93d4f..edcbdf12 100644 --- a/src/core/tjs2/tjsdate.tab.cpp +++ b/src/core/tjs2/tjsdate.tab.cpp @@ -90,7 +90,7 @@ /* tjsdate.y */ /* TJS2 date string parser */ -#include +#include #include "tjsTypes.h" #include "tjsDateParser.h" diff --git a/src/core/tjs2/tjspp.tab.cpp b/src/core/tjs2/tjspp.tab.cpp index 744b0ecf..f51d7626 100644 --- a/src/core/tjs2/tjspp.tab.cpp +++ b/src/core/tjs2/tjspp.tab.cpp @@ -90,7 +90,7 @@ /* tjspp.y */ /* TJS2 conditional compiling control's conditional expression parser */ -#include +#include #include "tjs.h" #include "tjsCompileControl.h" diff --git a/src/core/utils/ObjectList.h b/src/core/utils/ObjectList.h index 752753eb..eda5339e 100644 --- a/src/core/utils/ObjectList.h +++ b/src/core/utils/ObjectList.h @@ -73,7 +73,7 @@ class tVoidObjectList { // commit the current array // this simply free BackupedObjects ( and its related things ) - if(BackupedObjects) TJS_free(BackupedObjects); + if(BackupedObjects) delete [](BackupedObjects); BackupedObjects = NULL; BackupedCount = 0; Backuped = false; diff --git a/src/core/utils/ThreadIntf.h b/src/core/utils/ThreadIntf.h index efb9d6e1..759a1471 100644 --- a/src/core/utils/ThreadIntf.h +++ b/src/core/utils/ThreadIntf.h @@ -11,7 +11,7 @@ #ifndef ThreadIntfH #define ThreadIntfH #include "tjsNative.h" - +#include //--------------------------------------------------------------------------- diff --git a/src/core/utils/win32/ThreadImpl.cpp b/src/core/utils/win32/ThreadImpl.cpp index 2116644b..0b801a06 100644 --- a/src/core/utils/win32/ThreadImpl.cpp +++ b/src/core/utils/win32/ThreadImpl.cpp @@ -27,12 +27,7 @@ #ifdef USING_THREADPOOL11 #include "threadpool11/pool.hpp" #endif - -#ifdef _MSC_VER -tjs_int WIN32GetProcessorNum(); -#else -#include -#endif +#include //--------------------------------------------------------------------------- // tTVPThread : a wrapper class for thread @@ -66,6 +61,7 @@ void * tTVPThread::StartProc(void * arg) _this->_cond.wait(lk); } _this->Execute(); + TVPOnThreadExited(); return nullptr; } //--------------------------------------------------------------------------- @@ -148,7 +144,7 @@ void tTVPThreadEvent::WaitFor(tjs_uint timeout) // returns true if the event is set, otherwise (when timed out) returns false. std::unique_lock lk(Mutex); - if (timeout != (tjs_uint)-1) { + if (timeout != 0) { Handle.wait_for(lk, std::chrono::milliseconds(timeout)); } else { Handle.wait(lk); @@ -174,11 +170,7 @@ static tjs_int GetProcesserNum(void) { static tjs_int processor_num = 0; if (! processor_num) { -#ifdef _MSC_VER - processor_num = WIN32GetProcessorNum(); -#else - processor_num = sysconf(_SC_NPROCESSORS_CONF); -#endif + processor_num = std::thread::hardware_concurrency(); tjs_char tmp[34]; TVPAddLog(ttstr(TJS_W("Detected CPU core(s): ")) + TJS_tTVInt_to_str(processor_num, tmp)); } @@ -229,3 +221,16 @@ void TVPExecThreadTask(int numThreads, TVP_THREAD_TASK_FUNC func) #endif } //--------------------------------------------------------------------------- + +std::vector> _OnThreadExitedEvents; + +void TVPOnThreadExited() { + for (const auto &ev : _OnThreadExitedEvents) { + ev(); + } +} + +void TVPAddOnThreadExitEvent(const std::function &ev) +{ + _OnThreadExitedEvents.emplace_back(ev); +} diff --git a/src/core/utils/win32/ThreadImpl.h b/src/core/utils/win32/ThreadImpl.h index 8b8369f8..4a36d74c 100644 --- a/src/core/utils/win32/ThreadImpl.h +++ b/src/core/utils/win32/ThreadImpl.h @@ -72,7 +72,7 @@ class tTVPThreadEvent }; //--------------------------------------------------------------------------- - - +void TVPAddOnThreadExitEvent(const std::function &ev); +void TVPOnThreadExited(); //--------------------------------------------------------------------------- #endif diff --git a/src/core/visual/BitmapIntf.cpp b/src/core/visual/BitmapIntf.cpp index 7653eddf..746c99b5 100644 --- a/src/core/visual/BitmapIntf.cpp +++ b/src/core/visual/BitmapIntf.cpp @@ -444,7 +444,7 @@ TJS_BEGIN_NATIVE_PROP_DECL(buffer) { TJS_GET_NATIVE_INSTANCE(/*var. name*/_this, /*var. type*/tTJSNI_Bitmap); if( _this->IsLoading() ) TVPThrowExceptionMessage(TVPCurrentlyAsyncLoadBitmap); - *result = reinterpret_cast(_this->GetPixelBuffer()); + *result = (tTVInteger)reinterpret_cast(_this->GetPixelBuffer()); return TJS_S_OK; } TJS_END_NATIVE_PROP_GETTER @@ -459,7 +459,7 @@ TJS_BEGIN_NATIVE_PROP_DECL(bufferForWrite) { TJS_GET_NATIVE_INSTANCE(/*var. name*/_this, /*var. type*/tTJSNI_Bitmap); if( _this->IsLoading() ) TVPThrowExceptionMessage(TVPCurrentlyAsyncLoadBitmap); - *result = reinterpret_cast(_this->GetPixelBufferForWrite()); + *result = (tTVInteger)reinterpret_cast(_this->GetPixelBufferForWrite()); return TJS_S_OK; } TJS_END_NATIVE_PROP_GETTER diff --git a/src/core/visual/FontImpl.cpp b/src/core/visual/FontImpl.cpp index 221b48c5..acdf020c 100644 --- a/src/core/visual/FontImpl.cpp +++ b/src/core/visual/FontImpl.cpp @@ -33,8 +33,8 @@ void TVPGetAllFontList(std::vector& list) { list.push_back(it.GetKey()); } } +static FT_Library TVPFontLibrary; FT_Library &TVPGetFontLibrary() { - static FT_Library TVPFontLibrary; if (!TVPFontLibrary) { FT_Error error = FT_Init_FreeType(&TVPFontLibrary); if (error) TVPThrowExceptionMessage( @@ -43,6 +43,11 @@ FT_Library &TVPGetFontLibrary() { } return TVPFontLibrary; } +void TVPReleaseFontLibrary() { + if (TVPFontLibrary) { + FT_Done_FreeType(TVPFontLibrary); + } +} //--------------------------------------------------------------------------- int TVPEnumFontsProc(const ttstr &FontPath) { @@ -128,7 +133,7 @@ void TVPInitFontNames() std::vector pathlist = Android_GetExternalStoragePath(); #endif do { - ttstr userFont = IndividualConfigManager::GetInstance()->GetValueString("default_font"); + ttstr userFont = IndividualConfigManager::GetInstance()->GetValue("default_font", ""); if (!userFont.IsEmpty() && TVPEnumFontsProc(userFont)) break; if (TVPEnumFontsProc(TVPGetAppPath() + "default.ttf")) break; diff --git a/src/core/visual/FreeTypeFontRasterizer.cpp b/src/core/visual/FreeTypeFontRasterizer.cpp index 3163f16f..bc94c4d5 100644 --- a/src/core/visual/FreeTypeFontRasterizer.cpp +++ b/src/core/visual/FreeTypeFontRasterizer.cpp @@ -45,7 +45,7 @@ void FreeTypeFontRasterizer::ApplyFont( class tTVPNativeBaseBitmap *bmp, bool fo //--------------------------------------------------------------------------- void FreeTypeFontRasterizer::ApplyFont( const tTVPFont& font ) { CurrentFont = font; - ttstr stdname = TVPFontSystem->GetBeingFont(font.Face.AsStdString()); + ttstr stdname = TVPFontSystem->GetBeingFont(font.Face); // TVP_FACE_OPTIONS_NO_ANTIALIASING // TVP_FACE_OPTIONS_NO_HINTING // TVP_FACE_OPTIONS_FORCE_AUTO_HINTING diff --git a/src/core/visual/GraphicsLoadThread.cpp b/src/core/visual/GraphicsLoadThread.cpp index 1299795a..d2cf7be7 100644 --- a/src/core/visual/GraphicsLoadThread.cpp +++ b/src/core/visual/GraphicsLoadThread.cpp @@ -40,7 +40,7 @@ tTVPImageLoadCommand::~tTVPImageLoadCommand() { bmp_ = NULL; } -static int TVPLoadGraphicAsync_SizeCallback(void *callbackdata, tjs_uint w, tjs_uint h) +static int TVPLoadGraphicAsync_SizeCallback(void *callbackdata, tjs_uint w, tjs_uint h, tTVPGraphicPixelFormat fmt) { tTVPTmpBitmapImage* img = (tTVPTmpBitmapImage*)callbackdata; if (!img->bmp) { @@ -49,6 +49,14 @@ static int TVPLoadGraphicAsync_SizeCallback(void *callbackdata, tjs_uint w, tjs_ img->bmp->Release(); img->bmp = new tTVPBitmap(w, h, 32); } + switch (fmt) { + case gpfLuminance: + case gpfRGB: + img->bmp->IsOpaque = true; break; + case gpfPalette: + case gpfRGBA: + img->bmp->IsOpaque = false; break; + } return img->bmp->GetPitch(); } //--------------------------------------------------------------------------- diff --git a/src/core/visual/GraphicsLoaderIntf.cpp b/src/core/visual/GraphicsLoaderIntf.cpp index 1fedf257..3d2ded0c 100644 --- a/src/core/visual/GraphicsLoaderIntf.cpp +++ b/src/core/visual/GraphicsLoaderIntf.cpp @@ -468,7 +468,15 @@ void TVPInternalLoadBMP(void *callbackdata, height = bi.biHeight<0?-bi.biHeight:bi.biHeight; // positive value of bi.biHeight indicates top-down DIB - sizecallback(callbackdata, bi.biWidth, height); + tTVPGraphicPixelFormat pixfmt; + switch (orgbitcount) { + case 32: pixfmt = gpfRGBA; break; + case 24: case 16: case 15: + pixfmt = gpfRGB; break; + default: + pixfmt = gpfPalette; break; + } + sizecallback(callbackdata, bi.biWidth, height, pixfmt); tjs_int pitch; pitch = (((bi.biWidth * orgbitcount) + 31) & ~31) /8; @@ -971,7 +979,7 @@ struct tTVPLoadGraphicData }; //--------------------------------------------------------------------------- static int TVPLoadGraphic_SizeCallback(void *callbackdata, tjs_uint w, - tjs_uint h) + tjs_uint h, tTVPGraphicPixelFormat fmt) { tTVPLoadGraphicData * data = (tTVPLoadGraphicData *)callbackdata; @@ -994,6 +1002,7 @@ static int TVPLoadGraphic_SizeCallback(void *callbackdata, tjs_uint w, // allocate line buffer data->Buffer = new tjs_uint8 [w]; + data->Dest->IsOpaque = false; return w; } else @@ -1005,6 +1014,14 @@ static int TVPLoadGraphic_SizeCallback(void *callbackdata, tjs_uint w, data->Dest->Release(); data->Dest = new tTVPBitmap(w, h, data->Type == lgtFullColor ? 32 : 8); } + switch(fmt) { + case gpfLuminance: + case gpfRGB: + data->Dest->IsOpaque = true; break; + case gpfPalette: + case gpfRGBA: + data->Dest->IsOpaque = false; break; + } #if 0 data->Dest->Recreate(w, h, data->Type!=lgtFullColor?8:32); #endif diff --git a/src/core/visual/GraphicsLoaderIntf.h b/src/core/visual/GraphicsLoaderIntf.h index a4ae3e53..2e0cd1bc 100644 --- a/src/core/visual/GraphicsLoaderIntf.h +++ b/src/core/visual/GraphicsLoaderIntf.h @@ -20,13 +20,20 @@ namespace TJS { class tTJSBinaryStream; } +enum tTVPGraphicPixelFormat +{ + gpfLuminance, + gpfPalette, + gpfRGB, + gpfRGBA +}; /*[*/ //--------------------------------------------------------------------------- // Graphic Loading Handler Type //--------------------------------------------------------------------------- typedef int (*tTVPGraphicSizeCallback) // return line pitch - (void *callbackdata, tjs_uint w, tjs_uint h); + (void *callbackdata, tjs_uint w, tjs_uint h, tTVPGraphicPixelFormat fmt); /* callback type to inform the image's size. call this once before TVPGraphicScanLineCallback. @@ -289,9 +296,7 @@ extern void TVPLoadGraphicProvince(tTVPBaseBitmap *dest, const ttstr &name, tjs_ #define BI_BITFIELDS 3 #endif -#ifdef __WIN32__ #pragma pack(push, 1) -#endif struct TVP_WIN_BITMAPFILEHEADER { tjs_uint16 bfType; @@ -314,9 +319,7 @@ struct TVP_WIN_BITMAPINFOHEADER tjs_uint32 biClrUsed; tjs_uint32 biClrImportant; }; -#ifdef __WIN32__ #pragma pack(pop) -#endif enum tTVPBMPAlphaType { diff --git a/src/core/visual/LayerIntf.cpp b/src/core/visual/LayerIntf.cpp index f6b272a5..eaf74a6e 100644 --- a/src/core/visual/LayerIntf.cpp +++ b/src/core/visual/LayerIntf.cpp @@ -39,6 +39,7 @@ #include "ConfigManager/IndividualConfigManager.h" #include "vkdefine.h" #include "RenderManager.h" +#include extern void TVPSetFontRasterizer( tjs_int index ); extern tjs_int TVPGetFontRasterizer(); @@ -5585,7 +5586,7 @@ void tTJSNI_BaseLayer::QueryUpdateExcludeRect(tTVPRect &rect, bool parentvisible rect.bottom += Rect.top; // check visibility & opacity - if(parentvisible && DisplayType == ltOpaque && Opacity == 255) + if (parentvisible && (DisplayType == ltOpaque || (MainImage && MainImage->IsOpaque())) && Opacity == 255) { if(rect.is_empty()) { @@ -5602,7 +5603,7 @@ void tTJSNI_BaseLayer::QueryUpdateExcludeRect(tTVPRect &rect, bool parentvisible void tTJSNI_BaseLayer::BltImage(iTVPBaseBitmap *dest, tTVPLayerType destlayertype, tjs_int destx, tjs_int desty, iTVPBaseBitmap *src, const tTVPRect &srcrect, - tTVPLayerType drawtype, tjs_int opacity) + tTVPLayerType drawtype, tjs_int opacity, bool hda) { // draw src to dest according with layer type /* @@ -5616,7 +5617,6 @@ void tTJSNI_BaseLayer::BltImage(iTVPBaseBitmap *dest, tTVPLayerType destlayertyp */ // blt to the target - bool hda = false; tTVPBBBltMethod met; switch(drawtype) { @@ -5646,7 +5646,7 @@ void tTJSNI_BaseLayer::BltImage(iTVPBaseBitmap *dest, tTVPLayerType destlayertyp case ltAdditive: // additive blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); // hda = true if destination has alpha // ( preserving mask ) met = bmAdd; @@ -5654,37 +5654,37 @@ void tTJSNI_BaseLayer::BltImage(iTVPBaseBitmap *dest, tTVPLayerType destlayertyp case ltSubtractive: // subtractive blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmSub; break; case ltMultiplicative: // multiplicative blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmMul; break; case ltDodge: // color dodge ( "Ooi yaki" in Japanese ) - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmDodge; break; case ltDarken: // darken blend (select lower luminosity) - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmDarken; break; case ltLighten: // lighten blend (select higher luminosity) - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmLighten; break; case ltScreen: // screen multiplicative blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmScreen; break; @@ -5700,97 +5700,97 @@ void tTJSNI_BaseLayer::BltImage(iTVPBaseBitmap *dest, tTVPLayerType destlayertyp case ltPsNormal: // Photoshop compatible normal blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsNormal; break; case ltPsAdditive: // Photoshop compatible additive blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsAdditive; break; case ltPsSubtractive: // Photoshop compatible subtractive blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsSubtractive; break; case ltPsMultiplicative: // Photoshop compatible multiplicative blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsMultiplicative; break; case ltPsScreen: // Photoshop compatible screen blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsScreen; break; case ltPsOverlay: // Photoshop compatible overlay blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsOverlay; break; case ltPsHardLight: // Photoshop compatible hard light blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsHardLight; break; case ltPsSoftLight: // Photoshop compatible soft light blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsSoftLight; break; case ltPsColorDodge: // Photoshop compatible color dodge blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsColorDodge; break; case ltPsColorDodge5: // Photoshop 5.x compatible color dodge blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsColorDodge5; break; case ltPsColorBurn: // Photoshop compatible color burn blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsColorBurn; break; case ltPsLighten: // Photoshop compatible compare (lighten) blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsLighten; break; case ltPsDarken: // Photoshop compatible compare (darken) blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsDarken; break; case ltPsDifference: // Photoshop compatible difference blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsDifference; break; case ltPsDifference5: // Photoshop 5.x compatible difference blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsDifference5; break; case ltPsExclusion: // Photoshop compatible exclusion blend - hda = TVPIsTypeUsingAlphaChannel(destlayertype); + hda = hda || TVPIsTypeUsingAlphaChannel(destlayertype); met = bmPsExclusion; break; @@ -5968,6 +5968,8 @@ void tTJSNI_BaseLayer::Draw_GPU(tTVPDrawable *target, int x, int y, const tTVPRe tTVPRect rect; if(!TVPIntersectRect(&rect, r, Rect)) return; // no intersection + tTVPRect rctar(rect); + rctar.add_offsets(x, y); CurrentDrawTarget = target; @@ -5977,27 +5979,35 @@ void tTJSNI_BaseLayer::Draw_GPU(tTVPDrawable *target, int x, int y, const tTVPRe DirectTransferToParent = false; // caching is not enabled - tTVPRect rctar(r); - rctar.add_offsets(x, y); - if (InTransition && TransWithChildren) + if (Opacity < 255 || (InTransition && TransWithChildren)) { // rearrange pipe line for transition - TransDrawable.Init(this, target); - target = &TransDrawable; + if (InTransition && TransWithChildren) { + TransDrawable.Init(this, target); + target = &TransDrawable; + } if (GetVisibleChildrenCount() == 0) { DrawSelf(target, rctar, rect); } else { // rearrange pipe line for transition - UpdateBitmapForChild = CacheBitmap; - + if (GetCacheEnabled()) { + UpdateBitmapForChild = CacheBitmap; + } else { + UpdateBitmapForChild = tTVPTempBitmapHolder::GetTemp( + rect.get_width(), + rect.get_height()); + } // copy self image to UpdateBitmapForChild if (MainImage != NULL) { - CopySelf(UpdateBitmapForChild, - rect.left, - rect.top, rect); // transfer self image + if (UpdateExcludeRect.top <= rect.top && UpdateExcludeRect.bottom >= rect.bottom && + rect.left >= UpdateExcludeRect.left && rect.right <= UpdateExcludeRect.right) { + } else + CopySelfForRect(UpdateBitmapForChild, 0, 0, rect); // transfer self image } + x = 0; + y = 0; TVP_LAYER_FOR_EACH_CHILD_BEGIN(child) { // for each child... @@ -6013,21 +6023,27 @@ void tTJSNI_BaseLayer::Draw_GPU(tTVPDrawable *target, int x, int y, const tTVPRe UpdateRectForChildOfsY = UpdateRectForChild.top - child->Rect.top; // call children's "Draw" method - child->Draw_GPU((tTVPDrawable*)this, x + Rect.left, y + Rect.top, UpdateRectForChild); + child->Draw_GPU((tTVPDrawable*)this, x, y, UpdateRectForChild); } TVP_LAYER_FOR_EACH_CHILD_END - target->DrawCompleted(rctar, CacheBitmap, rect, DisplayType, Opacity); + rect.set_offsets(0, 0); + target->DrawCompleted(rctar, UpdateBitmapForChild, rect, DisplayType, Opacity); } } else { if (GetVisibleChildrenCount() == 0) { DrawSelf(target, rctar, rect); } else { DrawnRegion.Clear(); - tTVPRect updaterectforchild; - UpdateBitmapForChild = target->GetDrawTargetBitmap(rctar, updaterectforchild); - const tTVPComplexRect & overlapped = GetOverlappedRegion(); // send completion message to the target - DrawSelf(target, rctar, rect); + + if (UpdateExcludeRect.top <= rect.top && UpdateExcludeRect.bottom >= rect.bottom && + rect.left >= UpdateExcludeRect.left && rect.right <= UpdateExcludeRect.right) { + } else { + tTVPRect rc(rect); + DrawSelf(target, rctar, rc); + } + x += Rect.left; + y += Rect.top; TVP_LAYER_FOR_EACH_CHILD_BEGIN(child) { // for each child... @@ -6041,13 +6057,12 @@ void tTJSNI_BaseLayer::Draw_GPU(tTVPDrawable *target, int x, int y, const tTVPRe continue; // call children's "Draw" method - child->Draw_GPU(target, x + Rect.left, y + Rect.top, chrect); + child->Draw_GPU(target, x, y, chrect); } TVP_LAYER_FOR_EACH_CHILD_END } } - CurrentDrawTarget = NULL; } @@ -6760,6 +6775,15 @@ void tTJSNI_BaseLayer::InternalComplete2(tTVPComplexRect & updateregion, updateregion.Clear(); } + +//--------------------------------------------------------------------------- +void tTJSNI_BaseLayer::InternalComplete2_GPU(tTVPRect updateregion, tTVPDrawable *drawable) +{ + if (Manager) Manager->QueryUpdateExcludeRect(); + updateregion.add_offsets(Rect.left, Rect.top); + Draw_GPU(drawable, 0, 0, updateregion, false); +} + //--------------------------------------------------------------------------- void tTJSNI_BaseLayer::InternalComplete(tTVPComplexRect & updateregion, tTVPDrawable *drawable) @@ -6770,10 +6794,10 @@ void tTJSNI_BaseLayer::InternalComplete(tTVPComplexRect & updateregion, InCompletion = true; static bool isGPU = !TVPIsSoftwareRenderManager() - && !IndividualConfigManager::GetInstance()->GetValueBool("ogl_accurate_render", false); + && !IndividualConfigManager::GetInstance()->GetValue("ogl_accurate_render", false); if (isGPU) { - Draw_GPU(drawable, 0, 0, updateregion.GetBound(), false); + InternalComplete2_GPU(updateregion.GetBound(), drawable); } else { InternalComplete2(updateregion, drawable); } @@ -6790,13 +6814,13 @@ void tTJSNI_BaseLayer::CompleteForWindow(tTVPDrawable *drawable) InCompletion = true; static bool isGPU = !TVPIsSoftwareRenderManager() - && !IndividualConfigManager::GetInstance()->GetValueBool("ogl_accurate_render", false); + && !IndividualConfigManager::GetInstance()->GetValue("ogl_accurate_render", false); if(Manager) Manager->GetLayerTreeOwner()->StartBitmapCompletion(Manager); try { if (isGPU) { - Draw_GPU(drawable, 0, 0, Rect); + InternalComplete2_GPU(Rect, drawable); } else { InternalComplete2(Manager->GetUpdateRegionForCompletion(), drawable); } @@ -6844,12 +6868,16 @@ tTVPBaseTexture * tTJSNI_BaseLayer::Complete(const tTVPRect & rect) class tCompleteDrawable_GPU : public tCompleteDrawable { public: tCompleteDrawable_GPU(tTVPBaseTexture *bmp, tTVPLayerType layertype) - : tCompleteDrawable(bmp, layertype) {}; + : tCompleteDrawable(bmp, layertype) { + bmp->Fill(tTVPRect(0, 0, bmp->GetWidth(), bmp->GetHeight()), layertype == ltOpaque ? 0xFF000000 : 0); + }; virtual void DrawCompleted(const tTVPRect &destrect, tTVPBaseTexture *bmp, const tTVPRect &cliprect, tTVPLayerType type, tjs_int opacity) override { - Bitmap->Blt(destrect.left, destrect.top, bmp, cliprect, type, opacity, true); + if (bmp != Bitmap) { + BltImage(Bitmap, LayerType, destrect.left, destrect.top, bmp, cliprect, type, opacity, LayerType == ltOpaque); + } } }; @@ -6874,7 +6902,7 @@ tTVPBaseTexture * tTJSNI_BaseLayer::Complete(const tTVPRect & rect) } static bool isGPU = !TVPIsSoftwareRenderManager() - && !IndividualConfigManager::GetInstance()->GetValueBool("ogl_accurate_render", false); + && !IndividualConfigManager::GetInstance()->GetValue("ogl_accurate_render", false); tTVPComplexRect ur; ur.Or(rect); if (isGPU) { @@ -10527,7 +10555,7 @@ TJS_BEGIN_NATIVE_PROP_DECL(mainImageBuffer) TJS_BEGIN_NATIVE_PROP_GETTER { TJS_GET_NATIVE_INSTANCE(/*var. name*/_this, /*var. type*/tTJSNI_Layer);; - *result = reinterpret_cast(_this->GetMainImagePixelBuffer()); + *result = (tTVInteger)reinterpret_cast(_this->GetMainImagePixelBuffer()); return TJS_S_OK; } TJS_END_NATIVE_PROP_GETTER @@ -10541,7 +10569,7 @@ TJS_BEGIN_NATIVE_PROP_DECL(mainImageBufferForWrite) TJS_BEGIN_NATIVE_PROP_GETTER { TJS_GET_NATIVE_INSTANCE(/*var. name*/_this, /*var. type*/tTJSNI_Layer);; - *result = reinterpret_cast(_this->GetMainImagePixelBufferForWrite()); + *result = (tTVInteger)reinterpret_cast(_this->GetMainImagePixelBufferForWrite()); return TJS_S_OK; } TJS_END_NATIVE_PROP_GETTER @@ -10569,7 +10597,7 @@ TJS_BEGIN_NATIVE_PROP_DECL(provinceImageBuffer) TJS_BEGIN_NATIVE_PROP_GETTER { TJS_GET_NATIVE_INSTANCE(/*var. name*/_this, /*var. type*/tTJSNI_Layer);; - *result = reinterpret_cast(_this->GetProvinceImagePixelBuffer()); + *result = (tTVInteger)reinterpret_cast(_this->GetProvinceImagePixelBuffer()); return TJS_S_OK; } TJS_END_NATIVE_PROP_GETTER @@ -10583,7 +10611,7 @@ TJS_BEGIN_NATIVE_PROP_DECL(provinceImageBufferForWrite) TJS_BEGIN_NATIVE_PROP_GETTER { TJS_GET_NATIVE_INSTANCE(/*var. name*/_this, /*var. type*/tTJSNI_Layer);; - *result = reinterpret_cast(_this->GetProvinceImagePixelBufferForWrite()); + *result = (tTVInteger)reinterpret_cast(_this->GetProvinceImagePixelBufferForWrite()); return TJS_S_OK; } TJS_END_NATIVE_PROP_GETTER diff --git a/src/core/visual/LayerIntf.h b/src/core/visual/LayerIntf.h index 93b4d417..34580dbb 100644 --- a/src/core/visual/LayerIntf.h +++ b/src/core/visual/LayerIntf.h @@ -920,7 +920,7 @@ class tTJSNI_BaseLayer : static void BltImage(iTVPBaseBitmap *dest, tTVPLayerType targettype, tjs_int destx, tjs_int desty, iTVPBaseBitmap *src, const tTVPRect &srcrect, - tTVPLayerType drawtype, tjs_int opacity); + tTVPLayerType drawtype, tjs_int opacity, bool hda = false); void DrawSelf(tTVPDrawable *target, tTVPRect &pr, tTVPRect &cr); @@ -941,6 +941,7 @@ class tTJSNI_BaseLayer : tTVPLayerType type, tjs_int opacity) override; void InternalComplete2(tTVPComplexRect & updateregion, tTVPDrawable *drawable); + void InternalComplete2_GPU(tTVPRect updateregion, tTVPDrawable *drawable); void InternalComplete(tTVPComplexRect & updateregion, tTVPDrawable *drawable); void CompleteForWindow(tTVPDrawable *drawable); public: diff --git a/src/core/visual/LoadBPG.cpp b/src/core/visual/LoadBPG.cpp index bb3a9b67..f68371a5 100644 --- a/src/core/visual/LoadBPG.cpp +++ b/src/core/visual/LoadBPG.cpp @@ -40,7 +40,7 @@ void TVPLoadBPG(void* formatdata, void *callbackdata, bpg_decoder_get_info(img.get(), &img_info); - sizecallback(callbackdata, img_info.width, img_info.height); + sizecallback(callbackdata, img_info.width, img_info.height, img_info.has_alpha ? gpfRGBA : gpfRGB); bpg_decoder_start(img.get(), BPG_OUTPUT_FORMAT_RGBA32); if (glmNormal == mode) { for (uint32_t y = 0; y < img_info.height; y++) { diff --git a/src/core/visual/LoadJPEG.cpp b/src/core/visual/LoadJPEG.cpp index 7c4d5588..92b35329 100644 --- a/src/core/visual/LoadJPEG.cpp +++ b/src/core/visual/LoadJPEG.cpp @@ -201,7 +201,7 @@ void TVPLoadJPEG(void* formatdata, void *callbackdata, tTVPGraphicSizeCallback s int jpegSubsamp, width, height; tjhandle jpegDecompressor = tjInitDecompress(); tjDecompressHeader2( jpegDecompressor, jpegBuf, jpegSize, &width, &height, &jpegSubsamp ); - sizecallback(callbackdata, width, height); + sizecallback(callbackdata, width, height, gpfRGB); // jpeg has no alpha channel // decompress option int flags = TJFLAG_FASTDCT; diff --git a/src/core/visual/LoadJXR.cpp b/src/core/visual/LoadJXR.cpp index fa8894db..944140fd 100644 --- a/src/core/visual/LoadJXR.cpp +++ b/src/core/visual/LoadJXR.cpp @@ -523,7 +523,7 @@ void TVPLoadJXR(void* formatdata, void *callbackdata, tTVPGraphicSizeCallback si if( width == 0 || height == 0 ) { TVPThrowExceptionMessage( TJS_W("JPEG XR read error/%1"), TJS_W("width or height is zero.") ); } - sizecallback(callbackdata, width, height); + sizecallback(callbackdata, width, height, pDecoder->WMP.wmiSCP.uAlphaMode ? gpfRGBA : gpfRGB); const tjs_uint32 stride = GetStride( (tjs_uint32)width, (tjs_uint32)32 ); PKRect rect = {0, 0, width, height}; #ifdef _DEBUG diff --git a/src/core/visual/LoadPNG.cpp b/src/core/visual/LoadPNG.cpp index 84c5ca01..601d0499 100644 --- a/src/core/visual/LoadPNG.cpp +++ b/src/core/visual/LoadPNG.cpp @@ -360,7 +360,7 @@ void TVPLoadPNG(void* formatdata, void *callbackdata, tTVPGraphicSizeCallback si png_read_update_info(png_ptr,info_ptr); // set size - sizecallback(callbackdata, width, height); + sizecallback(callbackdata, width, height, color_type == PNG_COLOR_TYPE_RGB_ALPHA ? gpfRGBA : gpfRGB); // load image if (png_get_interlace_type(png_ptr,info_ptr) == PNG_INTERLACE_NONE) diff --git a/src/core/visual/LoadTLG.cpp b/src/core/visual/LoadTLG.cpp index 0ed9bf75..63eddf5b 100644 --- a/src/core/visual/LoadTLG.cpp +++ b/src/core/visual/LoadTLG.cpp @@ -69,7 +69,7 @@ void TVPLoadTLG5(void* formatdata, void *callbackdata, // decomperss - sizecallback(callbackdata, width, height); + sizecallback(callbackdata, width, height, colors == 3 ? gpfRGB : gpfRGBA); tjs_uint8 *inbuf = NULL; tjs_uint8 *outbuf[4]; @@ -246,7 +246,7 @@ void TVPLoadTLG6(void* formatdata, void *callbackdata, max_bit_length = src->ReadI32LE(); // set destination size - sizecallback(callbackdata, width, height); + sizecallback(callbackdata, width, height, colors == 3 ? gpfRGB : gpfRGBA); // compute some values tjs_int x_block_count = (tjs_int)((width - 1)/ TVP_TLG6_W_BLOCK_SIZE) + 1; diff --git a/src/core/visual/LoadWEBP.cpp b/src/core/visual/LoadWEBP.cpp index 548fa85d..f201aaf9 100644 --- a/src/core/visual/LoadWEBP.cpp +++ b/src/core/visual/LoadWEBP.cpp @@ -22,7 +22,8 @@ void TVPLoadWEBP(void* formatdata, void *callbackdata, TVPThrowExceptionMessage(TJS_W("Invalid WebP image")); } - unsigned int stride = sizecallback(callbackdata, config.input.width, config.input.height); + unsigned int stride = sizecallback(callbackdata, config.input.width, config.input.height, + config.input.has_alpha ? gpfRGBA : gpfRGB); #if 0 WebPData webp_data = { data, datasize }; WebPDemuxer* demux = WebPDemux(&webp_data); diff --git a/src/core/visual/RenderManager.cpp b/src/core/visual/RenderManager.cpp index b3fabeac..5ea994d1 100644 --- a/src/core/visual/RenderManager.cpp +++ b/src/core/visual/RenderManager.cpp @@ -336,6 +336,7 @@ class tTVPSoftwareTexture2D_static : public iTVPSoftwareTexture2D { Height = rc.get_height(); } virtual bool IsStatic() { return true; } + virtual bool IsOpaque() { return false; } virtual TVPTextureFormat::e GetFormat() const { return Format; } virtual void SetPoint(int x, int y, tjs_uint32 clr) { assert(false); @@ -621,6 +622,7 @@ class tTVPSoftwareTexture2D : public tTVPSoftwareTexture2D_static { src += pitch; } } + Bitmap->IsOpaque = false; } virtual uint32_t GetPoint(int x, int y) { @@ -635,8 +637,14 @@ class tTVPSoftwareTexture2D : public tTVPSoftwareTexture2D_static { *((tjs_uint32*)Bitmap->GetScanLine(y) + x) = clr; // 32bpp else *((tjs_uint8*)Bitmap->GetScanLine(y) + x) = (tjs_uint8)clr; // 8bpp + Bitmap->IsOpaque = false; } virtual bool IsStatic() { return false; } + virtual bool IsOpaque() { return Bitmap->IsOpaque; } + virtual void * GetScanLineForWrite(tjs_uint l) { + Bitmap->IsOpaque = false; + return (void*)GetScanLineForRead(l); + } }; class tTVPRenderMethod_Software : public iTVPRenderMethod { @@ -1632,7 +1640,8 @@ struct TDoBoxBlurLoop { tARGB * vert_sum = NULL; // vertical sum of the pixel - std::vector > dest_buf; // destination pixel temporary buffer + std::vector dest_buf; // destination pixel temporary buffer +// std::vector > dest_buf; tjs_int vert_sum_count; @@ -1646,8 +1655,8 @@ struct TDoBoxBlurLoop { { dest_buf.resize(dest_buf_size); for (tjs_int i = 0; i < dest_buf_size; i++) { - dest_buf[i].resize(rect.right - rect.left); - _log_ptr("alloc bufN", &dest_buf[i][0], (rect.right - rect.left) * 4); + dest_buf[i] = (tjs_uint32 *)TJSAlignedAlloc(rect.right - rect.left, 4); +// _log_ptr("alloc bufN", &dest_buf[i][0], (rect.right - rect.left) * 4); } } @@ -1831,20 +1840,24 @@ struct TDoBoxBlurLoop { if (dest_buf_wp >= dest_buf_size) dest_buf_wp = 0; dest_buf_free++; } - } catch (...) - { + } catch (...) { // exception caught if (vert_sum) TJSAlignedDealloc(vert_sum); + if (dest_buf_size) { + for (tjs_int i = 0; i < dest_buf_size; i++) { + // _log_ptr("free bufN", &dest_buf[i][0], (rect.right - rect.left) * 4); + TJSAlignedDealloc(dest_buf[i]); + } + } throw; } // free buffeers TJSAlignedDealloc(vert_sum); - if (dest_buf_size) - { + if (dest_buf_size) { for (tjs_int i = 0; i < dest_buf_size; i++) { - _log_ptr("free bufN", &dest_buf[i][0], (rect.right - rect.left) * 4); - //delete[] dest_buf[i]; + // _log_ptr("free bufN", &dest_buf[i][0], (rect.right - rect.left) * 4); + TJSAlignedDealloc(dest_buf[i]); } } } @@ -1946,51 +1959,48 @@ struct tRenderMethodCache { } } - iTVPRenderMethod *GetMethodWithOpa(tjs_int opa) { - WithOpa->SetParameterOpa(NormalOpaID, opa); - return WithOpa; - } - iTVPRenderMethod *GetMethodWithOpa_HDA(tjs_int opa) { - WithOpaHDA->SetParameterOpa(HDAOpaID, opa); - return WithOpaHDA; + iTVPRenderMethod *GetMethodWithOpa(tjs_int opa, bool hda) { + iTVPRenderMethod *ret = hda ? WithOpaHDA : WithOpa; + ret->SetParameterOpa(hda ? HDAOpaID : NormalOpaID, opa); + return ret; } }; MethodInfo Info[bmPsExclusion + 1]; tRenderMethodCache(iTVPRenderManager* mgr) { - Info[bmCopy].Init(mgr, "Copy", nullptr, "ConstAlphaBlend", nullptr); - Info[bmCopyOnAlpha].Init(mgr, "CopyOpaqueImage", nullptr, "ConstAlphaBlend_d", nullptr); - Info[bmAlpha].Init(mgr, nullptr, nullptr, "AlphaBlend", nullptr); - Info[bmAlphaOnAlpha].Init(mgr, nullptr, nullptr, "AlphaBlend_d", nullptr); - Info[bmAdd].Init(mgr, nullptr, nullptr, "AddBlend", nullptr); - Info[bmSub].Init(mgr, nullptr, nullptr, "SubBlend", nullptr); + Info[bmCopy].Init(mgr, "Copy", "CopyColor", "ConstAlphaBlend", "ConstAlphaBlend"); + Info[bmCopyOnAlpha].Init(mgr, "CopyOpaqueImage", "CopyColor", "ConstAlphaBlend_d", "ConstAlphaBlend_d"); + Info[bmAlpha].Init(mgr, nullptr, nullptr, "AlphaBlend", "AlphaBlend"); + Info[bmAlphaOnAlpha].Init(mgr, nullptr, nullptr, "AlphaBlend_d", "AlphaBlend_d"); + Info[bmAdd].Init(mgr, nullptr, nullptr, "AddBlend", "AddBlend"); + Info[bmSub].Init(mgr, nullptr, nullptr, "SubBlend", "SubBlend"); Info[bmMul].Init(mgr, nullptr, nullptr, "MulBlend", "MulBlend_HDA"); - Info[bmDodge].Init(mgr, nullptr, nullptr, "ColorDodgeBlend", nullptr); - Info[bmDarken].Init(mgr, nullptr, nullptr, "DarkenBlend", nullptr); - Info[bmLighten].Init(mgr, nullptr, nullptr, "LightenBlend", nullptr); - Info[bmScreen].Init(mgr, nullptr, nullptr, "ScreenBlend", nullptr); - Info[bmAddAlpha].Init(mgr, nullptr, nullptr, "AdditiveAlphaBlend", nullptr); - Info[bmAddAlphaOnAddAlpha].Init(mgr, nullptr, nullptr, "AdditiveAlphaBlend_a", nullptr); + Info[bmDodge].Init(mgr, nullptr, nullptr, "ColorDodgeBlend", "ColorDodgeBlend"); + Info[bmDarken].Init(mgr, nullptr, nullptr, "DarkenBlend", "DarkenBlend"); + Info[bmLighten].Init(mgr, nullptr, nullptr, "LightenBlend", "LightenBlend"); + Info[bmScreen].Init(mgr, nullptr, nullptr, "ScreenBlend", "ScreenBlend"); + Info[bmAddAlpha].Init(mgr, nullptr, nullptr, "AdditiveAlphaBlend", "AdditiveAlphaBlend"); + Info[bmAddAlphaOnAddAlpha].Init(mgr, nullptr, nullptr, "AdditiveAlphaBlend_a", "AdditiveAlphaBlend_a"); //Info[bmAddAlphaOnAlpha].Init(mgr, nullptr, nullptr, nullptr, nullptr); - Info[bmAlphaOnAddAlpha].Init(mgr, nullptr, nullptr, "AlphaBlend_a", nullptr); - Info[bmCopyOnAddAlpha].Init(mgr, "CopyOpaqueImage", nullptr, "ConstAlphaBlend_a", nullptr); - Info[bmPsNormal].Init(mgr, nullptr, nullptr, "PsAlphaBlend", nullptr); - Info[bmPsAdditive].Init(mgr, nullptr, nullptr, "PsAddBlend", nullptr); - Info[bmPsSubtractive].Init(mgr, nullptr, nullptr, "PsSubBlend", nullptr); - Info[bmPsMultiplicative].Init(mgr, nullptr, nullptr, "PsMulBlend", nullptr); - Info[bmPsScreen].Init(mgr, nullptr, nullptr, "PsScreenBlend", nullptr); - Info[bmPsOverlay].Init(mgr, nullptr, nullptr, "PsOverlayBlend", nullptr); - Info[bmPsHardLight].Init(mgr, nullptr, nullptr, "PsHardLightBlend", nullptr); - Info[bmPsSoftLight].Init(mgr, nullptr, nullptr, "PsSoftLightBlend", nullptr); - Info[bmPsColorDodge].Init(mgr, nullptr, nullptr, "PsColorDodgeBlend", nullptr); - Info[bmPsColorDodge5].Init(mgr, nullptr, nullptr, "PsColorDodge5Blend", nullptr); - Info[bmPsColorBurn].Init(mgr, nullptr, nullptr, "PsColorBurnBlend", nullptr); - Info[bmPsLighten].Init(mgr, nullptr, nullptr, "PsLightenBlend", nullptr); - Info[bmPsDarken].Init(mgr, nullptr, nullptr, "PsDarkenBlend", nullptr); - Info[bmPsDifference].Init(mgr, nullptr, nullptr, "PsDiffBlend", nullptr); - Info[bmPsDifference5].Init(mgr, nullptr, nullptr, "PsDiff5Blend", nullptr); - Info[bmPsExclusion].Init(mgr, nullptr, nullptr, "PsExclusionBlend", nullptr); + Info[bmAlphaOnAddAlpha].Init(mgr, nullptr, nullptr, "AlphaBlend_a", "AlphaBlend_a"); + Info[bmCopyOnAddAlpha].Init(mgr, "CopyOpaqueImage", nullptr, "ConstAlphaBlend_a", "ConstAlphaBlend_a"); + Info[bmPsNormal].Init(mgr, nullptr, nullptr, "PsAlphaBlend", "PsAlphaBlend"); + Info[bmPsAdditive].Init(mgr, nullptr, nullptr, "PsAddBlend", "PsAddBlend"); + Info[bmPsSubtractive].Init(mgr, nullptr, nullptr, "PsSubBlend", "PsSubBlend"); + Info[bmPsMultiplicative].Init(mgr, nullptr, nullptr, "PsMulBlend", "PsMulBlend"); + Info[bmPsScreen].Init(mgr, nullptr, nullptr, "PsScreenBlend", "PsScreenBlend"); + Info[bmPsOverlay].Init(mgr, nullptr, nullptr, "PsOverlayBlend", "PsOverlayBlend"); + Info[bmPsHardLight].Init(mgr, nullptr, nullptr, "PsHardLightBlend", "PsHardLightBlend"); + Info[bmPsSoftLight].Init(mgr, nullptr, nullptr, "PsSoftLightBlend", "PsSoftLightBlend"); + Info[bmPsColorDodge].Init(mgr, nullptr, nullptr, "PsColorDodgeBlend", "PsColorDodgeBlend"); + Info[bmPsColorDodge5].Init(mgr, nullptr, nullptr, "PsColorDodge5Blend", "PsColorDodge5Blend"); + Info[bmPsColorBurn].Init(mgr, nullptr, nullptr, "PsColorBurnBlend", "PsColorBurnBlend"); + Info[bmPsLighten].Init(mgr, nullptr, nullptr, "PsLightenBlend", "PsLightenBlend"); + Info[bmPsDarken].Init(mgr, nullptr, nullptr, "PsDarkenBlend", "PsDarkenBlend"); + Info[bmPsDifference].Init(mgr, nullptr, nullptr, "PsDiffBlend", "PsDiffBlend"); + Info[bmPsDifference5].Init(mgr, nullptr, nullptr, "PsDiff5Blend", "PsDiff5Blend"); + Info[bmPsExclusion].Init(mgr, nullptr, nullptr, "PsExclusionBlend", "PsExclusionBlend"); } iTVPRenderMethod* GetRenderMethod(const char *name, bool hda) { @@ -2016,9 +2026,9 @@ iTVPRenderMethod* iTVPRenderManager::GetRenderMethod(tjs_int opa, bool hda, int/ // constant ratio alpha blending (assuming source is opaque) // with consideration of destination additive alpha if (opa == 255) { - return RenderMethodCache->Info[method].Normal; + return hda ? RenderMethodCache->Info[method].HDA : RenderMethodCache->Info[method].Normal; } else { - return RenderMethodCache->Info[method].GetMethodWithOpa(opa); + return RenderMethodCache->Info[method].GetMethodWithOpa(opa, hda); } break; case bmAlpha: @@ -2076,14 +2086,9 @@ iTVPRenderMethod* iTVPRenderManager::GetRenderMethod(tjs_int opa, bool hda, int/ // Photoshop 5.x compatible difference blend case bmPsExclusion: // Photoshop compatible exclusion blend - return RenderMethodCache->Info[method].GetMethodWithOpa(opa); case bmMul: // multiplicative blending ( this does not consider distination alpha ) - if (hda) { - return RenderMethodCache->Info[method].GetMethodWithOpa_HDA(opa); - } else { - return RenderMethodCache->Info[method].GetMethodWithOpa(opa); - } + return RenderMethodCache->Info[method].GetMethodWithOpa(opa, hda); break; case bmAddAlphaOnAlpha: // additive alpha on simple alpha @@ -2366,7 +2371,7 @@ class tTVPSoftwareRenderManager : public iTVPRenderManager { , _drawCount(0) { _createStaticTexture2D = tTVPSoftwareTexture2D::Create; - std::string compTexMethod = IndividualConfigManager::GetInstance()->GetValueString("software_compress_tex", "none"); + std::string compTexMethod = IndividualConfigManager::GetInstance()->GetValue("software_compress_tex", "none"); if (compTexMethod == "halfline") _createStaticTexture2D = tTVPSoftwareTexture2D_half::Create; Register_1(); @@ -4064,7 +4069,7 @@ iTVPRenderManager * TVPGetRenderManager(const ttstr &name) iTVPRenderManager * TVPGetRenderManager() { static iTVPRenderManager *_RenderManager; if (!_RenderManager) { - ttstr str = IndividualConfigManager::GetInstance()->GetValueString("renderer", "software"); + ttstr str = IndividualConfigManager::GetInstance()->GetValue("renderer", "software"); _RenderManager = TVPGetRenderManager(str); } return _RenderManager; diff --git a/src/core/visual/RenderManager.h b/src/core/visual/RenderManager.h index 2a7b56ab..6b77be66 100644 --- a/src/core/visual/RenderManager.h +++ b/src/core/visual/RenderManager.h @@ -124,6 +124,7 @@ class iTVPTexture2D virtual uint32_t GetPoint(int x, int y) = 0; virtual void SetPoint(int x, int y, uint32_t clr) = 0; virtual bool IsStatic() = 0; // aka. is readonly + virtual bool IsOpaque() = 0; //virtual void RefreshBitmap() = 0; virtual cocos2d::Texture2D* GetAdapterTexture(cocos2d::Texture2D* origTex) = 0; virtual bool GetScale(float &x, float &y) { x = 1.f; y = 1.f; return true; } diff --git a/src/core/visual/SaveTLG6.cpp b/src/core/visual/SaveTLG6.cpp index bc07e428..b5d8d55f 100644 --- a/src/core/visual/SaveTLG6.cpp +++ b/src/core/visual/SaveTLG6.cpp @@ -106,7 +106,7 @@ class TLG6BitStream BufferBytePos = 0; BufferBitPos = 0; } - free(Buffer); + TJS_free(Buffer); BufferCapacity = 0; Buffer = NULL; } @@ -121,9 +121,9 @@ class TLG6BitStream long org_cap = BufferCapacity; BufferCapacity += 0x1000; if(Buffer) - Buffer = (unsigned char *)realloc(Buffer, BufferCapacity); + Buffer = (unsigned char *)TJS_realloc(Buffer, BufferCapacity); else - Buffer = (unsigned char *)malloc(BufferCapacity); + Buffer = (unsigned char *)TJS_malloc(BufferCapacity); if(!Buffer) TVPThrowExceptionMessage( TVPTlgInsufficientMemory ); memset(Buffer + org_cap, 0, BufferCapacity - org_cap); } diff --git a/src/core/visual/tvpgl.cpp b/src/core/visual/tvpgl.cpp index 7d0934e1..fc37515c 100644 --- a/src/core/visual/tvpgl.cpp +++ b/src/core/visual/tvpgl.cpp @@ -10433,8 +10433,11 @@ TVP_GL_FUNC_DECL(void, TVPUpscale65_255_c, (tjs_uint8 *dest, tjs_int len)) { tjs_uint64 c = *(tjs_uint64*)dest; // left shift with saturation tjs_uint64 tmp = c & 0x4040404040404040ULL; - tmp = (tmp << 2) - (tmp >> 6); - c = (c << 2) | tmp; + tjs_uint64 tmp2 = tmp << 2; + tmp = tmp2 - (tmp >> 6); + c <<= 2; + c -= tmp2; + c |= tmp; *(tjs_uint64*)dest = c; dest += 8; } @@ -12013,6 +12016,28 @@ TVP_GL_FUNC_DECL(void, TVPPsExclusionBlend_HDA_o_c, (tjs_uint32 *dest, const tjs #endif +TVP_GL_FUNC_DECL(void, TVPConvert32BitTo24Bit_c, (tjs_uint8 *dest, const tjs_uint8 *buf, tjs_int len)) +{ + const tjs_uint8 *slimglim = buf + len; // in bytes + const tjs_uint8 *slimglims = slimglim - 16; + while (buf < slimglims) { + tjs_uint32 c0 = 0[(tjs_uint32*)buf] & 0xFFFFFF; + tjs_uint32 c1 = 1[(tjs_uint32*)buf] & 0xFFFFFF; + tjs_uint32 c2 = 2[(tjs_uint32*)buf] & 0xFFFFFF; + tjs_uint32 c3 = 3[(tjs_uint32*)buf] & 0xFFFFFF; + 0[(tjs_uint32*)dest] = (c0) | (c1 << 24); + 1[(tjs_uint32*)dest] = (c1 >> 8) | (c2 << 16); + 2[(tjs_uint32*)dest] = (c2 >> 16) | (c3 << 8); + buf += 16; + dest += 12; + } + while (buf < slimglim) + { + *(tjs_uint32*)dest = *(tjs_uint32*)buf; + dest += 3; + buf += 4; + } +} TVP_GL_FUNC_PTR_DECL(void, TVPAlphaBlend, (tjs_uint32 *dest, const tjs_uint32 *src, tjs_int len)); TVP_GL_FUNC_PTR_DECL(void, TVPAlphaBlend_HDA, (tjs_uint32 *dest, const tjs_uint32 *src, tjs_int len)); @@ -12277,11 +12302,13 @@ TVP_GL_FUNC_PTR_DECL(void, TVPPsExclusionBlend_o, (tjs_uint32 *dest, const tjs_ TVP_GL_FUNC_PTR_DECL(void, TVPPsExclusionBlend_HDA, (tjs_uint32 *dest, const tjs_uint32 *src, tjs_int len)); TVP_GL_FUNC_PTR_DECL(void, TVPPsExclusionBlend_HDA_o, (tjs_uint32 *dest, const tjs_uint32 *src, tjs_int len, tjs_int opa)); -// add by zeas +// add by ZeaS TVP_GL_FUNC_PTR_DECL(void, TVPReverseRGB, (tjs_uint32 *dest, const tjs_uint32 *src, tjs_int len)); TVP_GL_FUNC_PTR_DECL(void, TVPUpscale65_255, (tjs_uint8 *dest, tjs_int len)); +TVP_GL_FUNC_PTR_DECL(void, TVPConvert32BitTo24Bit, (tjs_uint8 *dest, const tjs_uint8 *buf, tjs_int len)); /* suffix "_c" : function is written in C */ +#include "tvpgl_route.h" /*export*/ TVP_GL_FUNC_DECL(void, TVPInitTVPGL, ()) @@ -12563,9 +12590,10 @@ TVP_GL_FUNC_DECL(void, TVPInitTVPGL, ()) TVPPsExclusionBlend_HDA = TVPPsExclusionBlend_HDA_c; TVPPsExclusionBlend_HDA_o = TVPPsExclusionBlend_HDA_o_c; #endif -// add by zeas +// add by ZeaS TVPReverseRGB = TVPReverseRGB_c; TVPUpscale65_255 = TVPUpscale65_255_c; + TVPConvert32BitTo24Bit = TVPConvert32BitTo24Bit_c; #endif TVPCreateTable(); TVPGL_C_Init(); diff --git a/src/core/visual/tvpgl.h b/src/core/visual/tvpgl.h index 240da40c..38cb86c4 100644 --- a/src/core/visual/tvpgl.h +++ b/src/core/visual/tvpgl.h @@ -468,9 +468,10 @@ TVP_GL_FUNC_PTR_EXTERN_DECL(void, TVPPsExclusionBlend_HDA, (tjs_uint32 *dest, c TVP_GL_FUNC_PTR_EXTERN_DECL(void, TVPPsExclusionBlend_HDA_o, (tjs_uint32 *dest, const tjs_uint32 *src, tjs_int len, tjs_int opa)); /* end function list */ -// add by zeas +// add by ZeaS TVP_GL_FUNC_PTR_EXTERN_DECL(void, TVPReverseRGB, (tjs_uint32 *dest, const tjs_uint32 *src, tjs_int len)); TVP_GL_FUNC_PTR_EXTERN_DECL(void, TVPUpscale65_255, (tjs_uint8 *dest, tjs_int len)); +TVP_GL_FUNC_PTR_EXTERN_DECL(void, TVPConvert32BitTo24Bit, (tjs_uint8 *dest, const tjs_uint8 *buf, tjs_int len)); /* end function list */ TVP_GL_FUNC_EXTERN_DECL(void, TVPInitTVPGL, ()); diff --git a/src/plugins/Android.mk b/src/plugins/Android.mk index 0c85c945..e8df9c02 100644 --- a/src/plugins/Android.mk +++ b/src/plugins/Android.mk @@ -20,7 +20,6 @@ $(LOCAL_PATH)/../core/base \ $(LOCAL_PATH)/../core/base/win32 \ $(LOCAL_PATH)/../core/environ \ $(LOCAL_PATH)/../core/environ/sdl \ -$(LOCAL_PATH)/../core/environ/my_vcl \ $(LOCAL_PATH)/../core/msg \ $(LOCAL_PATH)/../core/msg/win32 \ $(LOCAL_PATH)/../core/sound \ diff --git a/src/plugins/xp3filter.cpp b/src/plugins/xp3filter.cpp index 2809da78..fdeb65ff 100644 --- a/src/plugins/xp3filter.cpp +++ b/src/plugins/xp3filter.cpp @@ -9,12 +9,7 @@ #include "SysInitIntf.h" #include "ThreadIntf.h" #include -#ifdef _MSC_VER #include -#define NOKERNEL -#define NOUSER -#include -#endif #define NCB_MODULE_NAME TJS_W("xp3filter.dll") @@ -50,12 +45,14 @@ tjs_error TJS_INTF_METHOD CBinaryAccessor::OperationByNum( /* operation with mem tjs_error TJS_INTF_METHOD CBinaryAccessor::Operation( /* operation with member */ tjs_uint32 flag, /* calling flag */ const tjs_char *membername, /* member name ( NULL for a default member ) */ tjs_uint32 *hint, /* hint for the member name (in/out) */ tTJSVariant *result, /* result ( can be NULL ) */ const tTJSVariant *param, /* parameters */ iTJSDispatch2 *objthis /* object as "this" */) { if (membername) { + static const ttstr str_ptr(TJS_W("ptr")); if (hint) { + static const tjs_uint32 hash_ptr = tTJSHashFunc::Make(str_ptr.c_str()); if (!*hint) - *hint = !TJS_strcmp(membername, TJS_W("ptr")); - if (!*hint) + *hint = tTJSHashFunc::Make(membername); + if (*hint != hash_ptr) return TJS_E_NOTIMPL; - } else if (TJS_strcmp(membername, TJS_W("ptr"))) { + } else if (str_ptr != membername) { return TJS_E_NOTIMPL; } } @@ -322,31 +319,37 @@ static XP3FilterDecoder* AddXP3Decoder() { return decoder; } -#if defined(_MSC_VER) && _MSC_VER <= 1800 -typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID); -void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv); -#pragma data_seg(push, old_seg) -#pragma data_seg(".CRT$XLB") -_TLSCB p_thread_callback = on_tls_callback; -#pragma data_seg() -#pragma data_seg(pop, old_seg) -static std::map _decoders; -__declspec(thread) static int _thread_id; -void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv) { - switch (dwReason) { - case DLL_THREAD_DETACH: - delete _decoders[std::this_thread::get_id()]; - _decoders.erase(std::this_thread::get_id()); - break; - } -} +#if (defined(_MSC_VER) && _MSC_VER <= 1800) || defined(CC_TARGET_OS_IPHONE) +static std::mutex _decoders_mtx; +static std::vector _cached_decoders; +static std::map _thread_decoders; static XP3FilterDecoder *FetchXP3Decoder() { - auto it = _decoders.find(std::this_thread::get_id()); - if (it != _decoders.end()) { - return it->second; + std::lock_guard lk(_decoders_mtx); + auto it = _thread_decoders.find(std::this_thread::get_id()); + if (it != _thread_decoders.end()) { + XP3FilterDecoder *ret = it->second; + return ret; } - XP3FilterDecoder *ret = AddXP3Decoder(); - _decoders[std::this_thread::get_id()] = ret; + static bool Inited = false; + if (!Inited) { + Inited = true; + TVPAddOnThreadExitEvent([](){ + std::lock_guard lk(_decoders_mtx); + auto it = _thread_decoders.find(std::this_thread::get_id()); + if (it != _thread_decoders.end()) { + _cached_decoders.emplace_back(it->second); + _thread_decoders.erase(it); + } + }); + } + XP3FilterDecoder *ret; + if(!_cached_decoders.empty()) { + ret = _cached_decoders.back(); + _cached_decoders.pop_back(); + } else { + ret = AddXP3Decoder(); + } + _thread_decoders[std::this_thread::get_id()] = ret; return ret; } #else @@ -355,7 +358,7 @@ static XP3FilterDecoder *FetchXP3Decoder() { return ret.get(); } #endif - +static void ReleaseXP3Decoder(XP3FilterDecoder *decoder, bool hold = false) { } tjs_int TVPXP3ArchiveContentFilterWrapper(const ttstr &filepath, const ttstr &archivename, tjs_uint64 filesize) { if (!_ManagedFilterInited) return 0; @@ -369,7 +372,9 @@ tjs_int TVPXP3ArchiveContentFilterWrapper(const ttstr &filepath, const ttstr &ar }; tTJSVariant result; decoder->ManagedFilter.FuncCall(0, NULL, NULL, &result, sizeof(vars) / sizeof(vars[0]), vars, NULL); - return result.operator tjs_int(); + tjs_int ret = result.operator tjs_int(); + ReleaseXP3Decoder(decoder, ret); + return ret; } void TVP_tTVPXP3ArchiveExtractionFilter_CONVENTION @@ -381,7 +386,9 @@ void TVP_tTVPXP3ArchiveExtractionFilter_CONVENTION if (decoder->ManagedDecoder.Object) { tTJSVariant FileHash = (tjs_int64)info->FileHash; tTJSVariant Offset = (tjs_int64)info->Offset; - tTJSVariant Buffer(new CBinaryAccessor((unsigned char*)info->Buffer, info->BufferSize)); + CBinaryAccessor *buf = new CBinaryAccessor((unsigned char*)info->Buffer, info->BufferSize); + tTJSVariant Buffer(buf); + buf->Release(); tTJSVariant BufferSize((tjs_int64)info->BufferSize); tTJSVariant FileName(info->FileName); tTJSVariant *vars[5] = { @@ -404,6 +411,7 @@ void TVP_tTVPXP3ArchiveExtractionFilter_CONVENTION delete []pBackup; #endif } + ReleaseXP3Decoder(decoder); } static void PostRegistCallback()