That's all there is to it!
+------------------------------------------------------------------------------
+
+The file m4/boost.m4 is licensed according to the following terms and
+conditions:
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
+
+
-SUBDIRS = yajl src
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = yajl src data doc
+
+EXTRA_DIST = yajl
+
+run: all
+ $(top_srcdir)/src/yoink
+
+debug: all
+ gdb $(top_srcdir)/src/yoink
+
-AC_PREREQ(2.60)
-AC_INIT([yoink],[0.1],[chaz@dogcows.com])
-AM_INIT_AUTOMAKE
+
+#
+# Yoink
+# Process this file with autoconf to produce a configure script.
+#
+
+AC_PREREQ([2.60])
+
+AC_INIT([Yoink], [0.1], [chaz@dogcows.com], [yoink])
+
+AC_CANONICAL_TARGET
+
AC_CONFIG_SRCDIR([src/YoinkApp.cc])
+AC_CONFIG_MACRO_DIR([m4])
+
+AM_INIT_AUTOMAKE
+
+
+#
+# Checks for programs.
+#
-AC_PROG_CC
AC_PROG_CXX
-AC_PROG_RANLIB
+#AC_PROG_AWK
+AC_PROG_CC
+AC_PROG_CPP
AC_PROG_INSTALL
-AM_PROG_CC_C_O
+#AC_PROG_LN_S
+#AC_PROG_MAKE_SET
+AC_PROG_LIBTOOL
-AC_HEADER_STDC
+#
+# Checks for configuration arguments.
+#
-AC_SEARCH_LIBS([glClear], [GL], [have_opengl=yes])
-if test ! "x${have_opengl}" = xyes
+AC_ARG_ENABLE([debug],
+ [ --enable-debug include debugging symbols and features],
+ [debug=$enableval
+ if test x$debug = xyes
+ then
+ CFLAGS="-Wall -Werror -g -O0 -DDEBUG"
+ CXXFLAGS="-Wall -Werror -g -O0 -DDEBUG"
+ else
+ CFLAGS="-O2 -DNDEBUG"
+ CXXFLAGS="-O2 -DNDEBUG"
+ fi],
+ [CFLAGS="-O2 -DNDEBUG"
+ CXXFLAGS="-O2 -DNDEBUG"])
+
+AC_ARG_ENABLE([profile],
+ [ --enable-profile make a binary for use with gprof],
+ [profile=$enableval
+ if test x$profile = xyes
+ then
+ CFLAGS="$CFLAGS -pg"
+ CXXFLAGS="$CXXFLAGS -pg"
+ fi])
+
+
+if test x$prefix = xNONE
then
- AC_MSG_ERROR([libGL is required])
+ prefix="$ac_default_prefix"
fi
-AC_SEARCH_LIBS([SDL_Init], [SDL], [have_sdl=yes])
-if test ! "x${have_sdl}" = xyes
+if test x$datadir = x'${datarootdir}'
then
- AC_MSG_ERROR([libSDL is required])
+ eval datarootdir="$datarootdir"
+ eval datadir="$datadir/yoink"
fi
-AC_SEARCH_LIBS([IMG_Load], [SDL_image], [have_sdlimage=yes])
-if test ! "x${have_sdlimage}" = xyes
+AC_DEFINE_UNQUOTED([YOINK_DATADIR], ["$datadir"],
+ [Define to path of game asset directory.])
+
+AC_DEFINE_UNQUOTED([YOINK_CONFIGFILES],
+ ["\$HOME/.yoinkrc:/etc/yoinkrc:$datadir/yoinkrc"],
+ [Define to colon-delimited config file paths.])
+
+
+#
+# Checks for libraries.
+#
+
+AM_PATH_SDL([1.2.14],
+ [CFLAGS="$CFLAGS $SDL_CFLAGS"
+ CXXFLAGS="$CXXFLAGS $SDL_CFLAGS"
+ LIBS="$LIBS $SDL_LIBS"])
+
+#BOOST_REQUIRE([1.35])
+#CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+BOOST_SMART_PTR
+BOOST_STRING_ALGO
+BOOST_BIND
+BOOST_FUNCTION
+
+AC_SEARCH_LIBS([IMG_Load], [SDL_image],,
+ [AC_MSG_ERROR([libSDL_image is required])])
+
+AC_SEARCH_LIBS([glBegin], [GL],,
+ [AC_MSG_ERROR([libGL is required])])
+
+AC_SEARCH_LIBS([clock_gettime], [rt],
+ [AC_DEFINE([HAVE_LIBRT], 1,
+ [Define to 1 if you have the 'rt' library.])])
+
+
+#
+# Checks for header files.
+#
+
+AC_HEADER_STDBOOL
+AC_HEADER_STDC
+AC_CHECK_HEADERS([stddef.h stdint.h stdlib.h string.h unistd.h])
+
+
+#
+# Checks for typedefs, structures, and compiler characteristics.
+#
+
+AC_C_STRINGIZE
+AC_C_INLINE
+
+AC_TYPE_UINT8_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+
+
+#
+# Checks for library functions.
+#
+
+AC_FUNC_ERROR_AT_LINE
+AC_FUNC_STRTOD
+AC_CHECK_FUNCS([strchr strcspn strrchr strstr])
+
+
+#
+# Find the data files to install.
+#
+
+DATA_FILES=$(echo $(cd data; \
+ find . -name "*.png" -o -name "*.json" -o -name yoinkrc))
+AC_SUBST([DATA_FILES])
+
+
+#
+# Create the build files.
+#
+
+AC_CONFIG_FILES([Makefile
+ data/Makefile
+ src/Makefile
+ doc/Makefile
+ doc/yoink.6
+ yajl/Makefile])
+
+AC_CONFIG_HEADERS([src/config.h])
+
+AC_OUTPUT
+
+
+#
+# Print a friendly little message.
+#
+
+echo "====================================="
+echo " Configuration complete!"
+echo ""
+
+echo " Prefix: $prefix"
+echo " Data: $datadir"
+echo ""
+
+if test x$debug = xyes
then
- AC_MSG_ERROR([libSDL_image is required])
+ echo " * Debugging enabled."
+ echo ""
fi
-AC_SEARCH_LIBS([clock_gettime], [rt], [have_librt=yes])
-if test "x${have_librt}" = xyes
+if test x$profile = xyes
then
- AC_DEFINE([HAVE_LIBRT], 1, [high-resolution timer enabled])
+ echo " * Profiling enabled."
+ echo ""
fi
-AC_CONFIG_FILES([Makefile
- yajl/Makefile
- src/Makefile])
-AC_OUTPUT
+echo " To finish the installation, execute:"
+echo " make"
+echo " make install"
+echo "====================================="
--- /dev/null
+
+nobase_dist_data_DATA = @DATA_FILES@
+
+appsdir=$(prefix)/share/applications
+dist_apps_DATA = yoink.desktop
+
+pixmapdir=$(prefix)/share/pixmaps
+dist_pixmap_DATA = yoink.png
+
--- /dev/null
+{
+ "playfield_bounds": [0, 0, -100, 1280, 500, 100],
+ "maximum_bounds": [-800, 0, -300, 2400, 1000, 600],
+ "instructions":
+ [
+
+ /* Left end tower block */
+
+ /* Front */
+
+ "reset_transform",
+ "translate", [-5, 0, 5],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 5,
+ "tiles":
+ [
+ 2, 2, 2, 2, 2,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 4, 4, 4, 4, 4
+ ]
+ },
+
+ /* Right side */
+
+ "reset_transform",
+ "rotate", ["y", 90],
+ "translate", [0, 0, 5],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 5,
+ "surface_type": "right",
+ "tiles":
+ [
+ 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 6,
+ 4, 5, 5, 5, 4
+ ]
+ },
+
+ /* Top */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [-5, 15, 0],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 5,
+ "surface_type": "top",
+ "tiles":
+ [
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3
+ ]
+ },
+
+ /* Leftmost background tower block */
+
+ /* Front */
+
+ "reset_transform",
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 7,
+ "detail": 1,
+ "tiles":
+ [
+ 2, 2, 2, 2, 2, 2, 2,
+ 0, 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 0, 6, 1, 0,
+ 0, 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 0, 0, 1, 0,
+ 4, 4, 5, 5, 5, 4, 4
+ ]
+ },
+
+ /* Right side */
+
+ "reset_transform",
+ "rotate", ["y", 90],
+ "translate", [7, 0, 0],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 6,
+ "detail": 1,
+ "tiles":
+ [
+ 2, 2, 2, 2, 2, 2,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 4, 4, 4, 4, 4, 4
+ ]
+ },
+
+ /* Top */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [-2, 8, -6],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 9,
+ "detail": 1,
+ "tiles":
+ [
+ 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3
+ ]
+ },
+
+ /* Foreground building with pitched roof */
+
+ /* Left wall */
+
+ "reset_transform",
+ "rotate", ["y", -90],
+ "translate", [10, 0, 1],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 4,
+ "surface_type": "left",
+ "tiles":
+ [
+ -1, 9, 11, -1,
+ 9, 10, 12, 11,
+ 15, 7, 7, 16,
+ 3, 5, 6, 4,
+ 3, 6, 5, 4
+ ]
+ },
+
+ /* Right wall */
+
+ "reset_transform",
+ "rotate", ["y", -90],
+ "translate", [13, 0, 1],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 4,
+ "surface_type": "right",
+ "tiles":
+ [
+ -1, 9, 11, -1,
+ 9, 10, 12, 11,
+ 15, 7, 7, 16,
+ 3, 5, 6, 4,
+ 3, 8, 5, 4
+ ]
+ },
+
+ /* Front wall */
+
+ "reset_transform",
+ "translate", [10, 0, 5],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 3,
+ "tiles":
+ [
+ 15, 7, 16,
+ 3, 5, 4,
+ 3, 6, 4
+ ]
+ },
+
+ /* Pitched roof */
+
+ "reset_transform",
+ "rotate", ["x", 135],
+ "scale", [1, 1.5, 1.5],
+ "translate", [10, 5, 3],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 3,
+ "tiles":
+ [
+ 13, 13, 13,
+ 13, 13, 13
+ ]
+ },
+
+ /* Finial */
+
+ "reset_transform",
+ "translate", [10, 5, 3],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 3,
+ "tiles":
+ [
+ 18, 18, 18
+ ]
+ },
+
+ /* Cheaty invisible platform */
+
+ "reset_transform",
+ "translate", [10, 4, 3],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 3,
+ "surface_type": "top",
+ "tiles":
+ [
+ -1, -1, -1
+ ]
+ },
+
+ /* The ground */
+
+ /* Courtyard */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [-3, 0, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "tilemap",
+ {
+ "width": 13,
+ "surface_type": "top",
+ "tiles":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ },
+
+ /* Front grass */
+
+ "reset_transform",
+ "scale", [8, 1, 1],
+ "translate", [1, -0.5, 5],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 8,
+ "detail": 2
+ },
+
+ /* Back grass */
+
+ "reset_transform",
+ "scale", [8, 1, 1],
+ "translate", [1, -0.5, 1],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 8,
+ "detail": 2
+ },
+
+ /* Left grass */
+
+ "reset_transform",
+ "scale", [4, 1, 1],
+ "rotate", ["y", -90],
+ "translate", [1, -0.5, 1],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 4,
+ "detail": 2
+ },
+
+ /* Right grass */
+
+ "reset_transform",
+ "scale", [4, 1, 1],
+ "rotate", ["y", -90],
+ "translate", [9, -0.5, 1],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 4,
+ "detail": 2
+ },
+
+ /* Fence behind house */
+
+ "reset_transform",
+ "scale", [11, 1, 1],
+ "translate", [7, 0, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 4,
+ "u_scale": 11,
+ "detail": 2
+ },
+
+ /* Background building with pitched roof */
+
+ /* Front wall */
+
+ "reset_transform",
+ "translate", [19, 0, 0],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 4,
+ "detail": 1,
+ "tiles":
+ [
+ -1, 9, 11, -1,
+ 9, 10, 12, 11,
+ 15, 7, 7, 16,
+ 3, 6, 5, 4,
+ 3, 5, 6, 4,
+ 3, 8, 5, 4
+ ]
+ },
+
+ /* Left wall */
+
+ "reset_transform",
+ "rotate", ["y", -90],
+ "translate", [19, 0, -3],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 3,
+ "surface_type": "left",
+ "detail": 1,
+ "tiles":
+ [
+ 15, 1, 16,
+ 3, 7, 4,
+ 3, 5, 4,
+ 3, 0, 4
+ ]
+ },
+
+ /* Right wall */
+
+ "reset_transform",
+ "rotate", ["y", -90],
+ "translate", [23, 0, -3],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 3,
+ "surface_type": "right",
+ "detail": 1,
+ "tiles":
+ [
+ 15, 0, 16,
+ 3, 7, 4,
+ 3, 6, 4,
+ 3, 2, 4
+ ]
+ },
+
+ /* Left pitched roof */
+
+ "reset_transform",
+ "rotate", ["x", 135],
+ "scale", [1, 1.5, 1.5],
+ "rotate", ["y", -90],
+ "translate", [21, 6, -3],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 3,
+ "detail": 1,
+ "tiles":
+ [
+ 13, 13, 13,
+ 13, 13, 13
+ ]
+ },
+
+ /* Right pitched roof */
+
+ "reset_transform",
+ "rotate", ["x", -135],
+ "scale", [1, 1.5, 1.5],
+ "rotate", ["y", -90],
+ "translate", [21, 6, -3],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 3,
+ "detail": 1,
+ "tiles":
+ [
+ 13, 13, 13,
+ 13, 13, 13
+ ]
+ },
+
+ /* Finial */
+
+ "reset_transform",
+ "rotate", ["y", -90],
+ "translate", [21, 6, -3],
+ "scale", [32],
+ "texture", "Building",
+ "tilemap",
+ {
+ "width": 3,
+ "detail": 1,
+ "tiles":
+ [
+ 18, 18, 18
+ ]
+ },
+
+ /* More ground to the right */
+
+ /* Ground under house */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [10, 0, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "tilemap",
+ {
+ "width": 3,
+ "surface_type": "top",
+ "tiles":
+ [
+ 1, 1, 1,
+ 1, 1, 1,
+ -1, -1, -1,
+ -1, -1, -1,
+ -1, -1, -1,
+ -1, -1, -1,
+ 1, 1, 1
+ ]
+ },
+
+ /* Left part of center courtyard */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [13, 0, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "tilemap",
+ {
+ "width": 8,
+ "surface_type": "top",
+ "tiles":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0, 0, 0
+ ]
+ },
+
+ /* Front grass */
+
+ "reset_transform",
+ "scale", [12, 1, 1],
+ "translate", [14, -0.5, 5],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 12,
+ "detail": 2
+ },
+
+ /* Back grass */
+
+ "reset_transform",
+ "scale", [4, 1, 1],
+ "translate", [14, -0.5, 1],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 4,
+ "detail": 2
+ },
+
+ /* Front grass next to door */
+
+ "reset_transform",
+ "scale", [1, 1, 1],
+ "translate", [13, -0.5, 3],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 1,
+ "detail": 2
+ },
+
+ /* Back grass next to door */
+
+ "reset_transform",
+ "scale", [1, 1, 1],
+ "translate", [13, -0.5, 2],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 1,
+ "detail": 2
+ },
+
+ /* Left grass */
+
+ "reset_transform",
+ "rotate", ["y", -90],
+ "translate", [14, -0.5, 1],
+ "scale", [32],
+ "texture", "Scenery",
+ "tilemap",
+ {
+ "width": 4,
+ "detail": 2,
+ "tiles":
+ [
+ 2, -1, 2, 2
+ ]
+ },
+
+ /* Grass left of house */
+
+ "reset_transform",
+ "rotate", ["y", -90],
+ "scale", [1, 1, 1],
+ "translate", [18, -0.5, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 1,
+ "detail": 2
+ },
+
+ /* Grass right of house */
+
+ "reset_transform",
+ "rotate", ["y", -90],
+ "scale", [1, 1, 1],
+ "translate", [24, -0.5, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 1,
+ "detail": 2
+ },
+
+ /* Front grass in center */
+
+ "reset_transform",
+ "scale", [4, 1, 1],
+ "translate", [19, -0.5, 4],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 4,
+ "detail": 2
+ },
+
+ /* Back grass in center */
+
+ "reset_transform",
+ "scale", [4, 1, 1],
+ "translate", [19, -0.5, 2],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 4,
+ "detail": 2
+ },
+
+ /* Left grass in center */
+
+ "reset_transform",
+ "scale", [2, 1, 1],
+ "rotate", ["y", -90],
+ "translate", [19, -0.5, 2],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 2,
+ "detail": 2
+ },
+
+ /* Right grass in center */
+
+ "reset_transform",
+ "scale", [2, 1, 1],
+ "rotate", ["y", -90],
+ "translate", [23, -0.5, 2],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 2,
+ "detail": 2
+ },
+
+ /* Still more ground */
+
+ /* Right part of center courtyard */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [21, 0, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "tilemap",
+ {
+ "width": 7,
+ "surface_type": "top",
+ "tiles":
+ [
+ 1, 1, 1, 1, 1, 0, 0,
+ 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1
+ ]
+ },
+
+ /* Fence to right of back house */
+
+ "reset_transform",
+ "scale", [4, 1, 1],
+ "translate", [24, 0, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 4,
+ "u_scale": 4,
+ "detail": 2
+ },
+
+ /* Grass in front of fence */
+
+ "reset_transform",
+ "scale", [4, 1, 1],
+ "translate", [24, -0.5, 1],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 4,
+ "detail": 2
+ },
+
+ /* Grass to left of tower block */
+
+ "reset_transform",
+ "scale", [2, 1, 1],
+ "rotate", ["y", -90],
+ "translate", [26, -0.5, 5],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 2,
+ "detail": 2
+ },
+
+ /* Grass to right of tower block */
+
+ "reset_transform",
+ "scale", [2, 1, 1],
+ "rotate", ["y", -90],
+ "translate", [35, -0.5, 5],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 2,
+ "detail": 2
+ },
+
+ /* Next bit of grass */
+
+ "reset_transform",
+ "scale", [5, 1, 1],
+ "translate", [35, -0.5, 5],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 5,
+ "detail": 2
+ },
+
+ /* Back grass */
+
+ "reset_transform",
+ "scale", [6, 1, 1],
+ "translate", [34, -0.5, 1],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 6,
+ "detail": 2
+ },
+
+ /* Extra bit of back grass */
+
+ "reset_transform",
+ "scale", [1, 1, 1],
+ "rotate", ["y", -90],
+ "translate", [34, -0.5, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "billboard",
+ {
+ "tile": 2,
+ "u_scale": 1,
+ "detail": 2
+ },
+
+ /* Ground around tower block */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [28, 0, 4],
+ "scale", [32],
+ "texture", "Scenery",
+ "tilemap",
+ {
+ "width": 5,
+ "surface_type": "top",
+ "tiles":
+ [
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0
+ ]
+ },
+
+ /* Rightmost ground */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [33, 0, 0],
+ "scale", [32],
+ "texture", "Scenery",
+ "tilemap",
+ {
+ "width": 10,
+ "surface_type": "top",
+ "tiles":
+ [
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, -1, -1, -1,
+ 0, 0, 0, 0, 0, 0, 0, -1, -1, -1,
+ 0, 0, 0, 0, 0, 0, 0, -1, -1, -1,
+ 0, 0, 0, 0, 0, 0, 0, -1, -1, -1,
+ 0, 1, 1, 1, 1, 1, 1, -1, -1, -1
+ ]
+ },
+
+ /* Right foreground tower block */
+
+ /* Front */
+
+ "reset_transform",
+ "translate", [28, 0, 4],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 5,
+ "tiles":
+ [
+ 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 6,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 6, 0,
+ 4, 4, 4, 4, 4
+ ]
+ },
+
+ /* Right side */
+
+ "reset_transform",
+ "rotate", ["y", 90],
+ "translate", [33, 0, 4],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 6,
+ "surface_type": "right",
+ "tiles":
+ [
+ 2, 2, 2, 2, 2, 2,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 5, 4, 5, 5, 4, 5
+ ]
+ },
+
+ /* Left side */
+
+ "reset_transform",
+ "rotate", ["y", 90],
+ "translate", [28, 0, 4],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 6,
+ "surface_type": "left",
+ "tiles":
+ [
+ 2, 2, 2, 2, 2, 2,
+ 0, 1, 6, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 5, 4, 5, 5, 4, 5
+ ]
+ },
+
+ /* Top */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [28, 7, -2],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 5,
+ "surface_type": "top",
+ "tiles":
+ [
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3
+ ]
+ },
+
+ /* Right end tower block */
+
+ /* Front */
+
+ "reset_transform",
+ "translate", [40, 0, 5],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 5,
+ "tiles":
+ [
+ 2, 2, 2, 2, 2,
+ 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 6, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 6, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1,
+ 4, 4, 4, 4, 4
+ ]
+ },
+
+ /* Left side */
+
+ "reset_transform",
+ "rotate", ["y", 90],
+ "translate", [40, 0, 5],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 5,
+ "surface_type": "left",
+ "tiles":
+ [
+ 2, 2, 2, 2, 2,
+ 6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 4, 5, 5, 5, 4
+ ]
+ },
+
+ /* Top */
+
+ "reset_transform",
+ "rotate", ["x", 90],
+ "translate", [40, 15, 0],
+ "scale", [32],
+ "texture", "TowerBlock1",
+ "tilemap",
+ {
+ "width": 5,
+ "surface_type": "top",
+ "tiles":
+ [
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3
+ ]
+ },
+
+ /* Background */
+
+ "reset_transform",
+ "translate", [-0.3, -0.17, -900],
+ "scale", [3200, 1600, 1],
+ "texture", "BackgroundFar",
+ "billboard",
+ {
+ "fog": false
+ },
+ "translate", [0, 0, 300],
+ "texture", "BackgroundNear",
+ "billboard",
+ {
+ "blend": true,
+ "fog": false
+ },
+
+ /* Trees */
+
+ "texture", "Trees",
+
+ /* Left courtyard */
+
+ "reset_transform",
+ "scale", [96],
+ "translate", [250, -2.5, 16],
+ "billboard",
+ {
+ "tile": 1,
+ "detail": 1
+ },
+
+ /* Center courtyard */
+
+ "reset_transform",
+ "scale", [96],
+ "translate", [610, -2.5, 85],
+ "billboard",
+ {
+ "tile": 0
+ },
+ "reset_transform",
+ "scale", [96],
+ "translate", [650, -2.5, 115],
+ "billboard",
+ {
+ "tile": 1
+ },
+
+ /* Right courtyard */
+
+ "reset_transform",
+ "scale", [96],
+ "translate", [1080, -2.5, 10],
+ "billboard",
+ {
+ "tile": 1,
+ "detail": 1
+ },
+ "reset_transform",
+ "scale", [96],
+ "translate", [1120, -2.5, -15],
+ "billboard",
+ {
+ "tile": 0,
+ "detail": 1
+ },
+ "reset_transform",
+ "scale", [96],
+ "translate", [1220, -2.5, -30],
+ "billboard",
+ {
+ "tile": 1,
+ "detail": 1
+ }
+
+ ]
+}
{
"TilesU": 8,
"TilesV": 4,
- "InvertAlpha": 0,
"MinFilter": Nearest,
"MagFilter": Nearest
}
{
"TilesU": 1,
"TilesV": 1,
- "InvertAlpha": 0,
"MinFilter": "Linear",
"MagFilter": "Linear",
- "WrapU": "Wrap",
- "WrapV": "Wrap"
+ "WrapU": "Clamp",
+ "WrapV": "Clamp"
}
{
"TilesU": 1,
"TilesV": 1,
- "InvertAlpha": 0,
"MinFilter": "Linear",
"MagFilter": "Linear",
- "WrapU": "ClampToEdge",
- "WrapV": "ClampToEdge"
+ "WrapU": "Repeat",
+ "WrapV": "Repeat"
}
{
"TilesU": 8,
"TilesV": 1,
- "InvertAlpha": 0,
"MinFilter": "Linear",
"MagFilter": "Linear",
- "WrapU": "ClampToEdge",
- "WrapV": "ClampToEdge"
+ "WrapU": "Clamp",
+ "WrapV": "Clamp"
}
{
"TilesU": 8,
"TilesV": 4,
- "InvertAlpha": 0,
"MinFilter": "Linear",
"MagFilter": "Linear",
- "WrapU": "ClampToEdge",
- "WrapV": "ClampToEdge"
+ "WrapU": "Clamp",
+ "WrapV": "Clamp"
}
{
"TilesU": 8,
"TilesV": 4,
- "InvertAlpha": 0,
"MinFilter": "Nearest",
"MagFilter": "Nearest",
- "WrapU": "ClampToEdge",
- "WrapV": "ClampToEdge"
+ "WrapU": "Clamp",
+ "WrapV": "Clamp"
}
{
"TilesU": 8,
"TilesV": 8,
- "InvertAlpha": 0,
"MinFilter": "Nearest",
"MagFilter": "Nearest"
}
{
"TilesU": 8,
"TilesV": 4,
- "InvertAlpha": 0,
"MinFilter": "Nearest",
"MagFilter": "Nearest"
}
{
"TilesU": 4,
"TilesV": 2,
- "InvertAlpha": 0,
"MinFilter": "Nearest",
"MagFilter": "Nearest"
}
{
"TilesU": 8,
"TilesV": 4,
- "InvertAlpha": 0,
"MinFilter": "Linear",
"MagFilter": "Linear",
- "WrapU": "ClampToEdge",
- "WrapV": "ClampToEdge"
+ "WrapU": "Clamp",
+ "WrapV": "Clamp"
}
{
"TilesU": 8,
"TilesV": 4,
- "InvertAlpha": 0,
"MinFilter": "Nearest",
"MagFilter": "Nearest"
}
{
"TilesU": 4,
"TilesV": 4,
- "InvertAlpha": 0,
"MinFilter": "Linear",
"MagFilter": "Linear",
- "WrapU": "Wrap",
- "WrapV": "Wrap"
+ "WrapU": "Repeat",
+ "WrapV": "Repeat"
}
{
"TilesU": 4,
"TilesV": 1,
- "InvertAlpha": 0,
"MinFilter": "Nearest",
"MagFilter": "Nearest"
}
{
"TilesU": 4,
"TilesV": 4,
- "InvertAlpha": 0,
"MinFilter": "Linear",
"MagFilter": "Linear",
- "WrapU": "ClampToEdge",
- "WrapV": "ClampToEdge"
+ "WrapU": "Clamp",
+ "WrapV": "Clamp"
}
{
"TilesU": 2,
"TilesV": 1,
- "InvertAlpha": 0,
"MinFilter": "Linear",
"MagFilter": "Linear",
- "WrapU": "ClampToEdge",
- "WrapV": "ClampToEdge"
+ "WrapU": "Clamp",
+ "WrapV": "Clamp"
}
--- /dev/null
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+Name=Yoink
+Type=Application
+Comment=Alien-stomping Entertainment
+Exec=yoink
+TryExec=yoink
+Icon=yoink
+Categories=Game;ActionGame;
"video.resizable": true,
"video.mode": [800, 600],
"video.colorbuffers": [8, 8, 8, 8],
- //"video.multisamplebuffers": 6,
- //"video.multisamplesamples": 6,
+ "video.multisamplebuffers": 6,
+ "video.multisamplesamples": 6,
"video.cursor": true,
"video.grab": false,
"video.doublebuffer": true,
"video.swapcontrol": true,
- "engine.maxfps": 40
+ "engine.maxfps": 45,
+ "engine.printfps": true,
+ "engine.timestep": 0.01
}
--- /dev/null
+
+man6_MANS = yoink.6
+
--- /dev/null
+.\"
+.\" Copyright (c) 2009, Charles McGarvey
+.\" 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, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+.\"
+.hy
+.TH YOINK 6 "July 24, 2009"
+.SH NAME
+Yoink \- An alien-smashing action game.
+.SH SYNOPSIS
+.B yoink [-h|--help] [-v|--version] [OPTION=VALUE]...
+.br
+.SH DESCRIPTION
+.PP
+Leap tall buildings! Crush stupid robots beneath your feet! Wield your
+extra-terrestrial powers in the defence of humanity, and send those alien
+invaders back from whence they came! Do all these things (apart from the last
+one at the moment) in Yoink! You play the part of a flying alien heroine who
+must defend her home on Earth from other airborne alien invaders. The game
+draws inspiration from classic arcade games like Joust, Bombjack, Rampage, and
+Defender--simple, fast-moving action.
+.PP
+.TP
+.B -h, --help
+display this help and exit
+.TP
+.B -v, --version
+output version information and exit
+.PP
+To attack, you must dive on the enemy at high speed. If you're going too
+slowly, you'll just drift harmlessly by. Diving from above gives different
+results from swooping in and hitting them from the side. If you're too close to
+attack, try to build up speed by running away and bouncing off a nearby
+building!
+.PP
+By charging your special alien powers, you can throw fireballs. The orange bar
+at the top of the screen represents your power level--at maximum, you can
+destroy almost anything. Aiming can be tricky, but with a little practice it's
+quite easy to launch them in the right direction. Try doing a little swoop or
+circle in the air to line yourself up before releasing your fireball.
+.PP
+The heroine has limited energy, measured by the blue bar at the top of the
+screen. When it runs out, it's game over! She can regain lost energy by
+picking up bonuses dropped by enemies.
+.PP
+To complete the current attack wave, you must destroy all the enemies. Hunt
+around, especially in the sky, if you can't find the last few.
+.br
+.SH OPTIONS
+.PP
+There are a plethora of options available for tweaking various aspects of the
+game. All options can be set either from a configuration file or by passing
+them as arguments. Some of the more common options can be set from within the
+game.
+.PP
+A
+.B yoink
+configuration file ("yoinkrc") consists of key-value pairs organized in a
+logical hierarchy. The format of the file is human-readable, so you can get in
+there with your favorite text editor if you like to work under the hood.
+.B yoink
+looks for configuration files and loads them in this order, with the options in
+prior configuration files taking precedence over the same options if they exist
+in multiple configuration files:
+.TP
+1. $YOINK_CONFIGFILE
+This is an optional environment variable.
+.TP
+2. $HOME/.yoinkrc
+This is a specific user's configuration file.
+.TP
+3. /etc/yoinkrc
+This is a system-wide configuration file.
+.TP
+4. @datadir@/yoinkrc
+This is the base configuration file which should be considered read-only. Look
+to this file as an example of the format used for configuration files.
+.PP
+Options that are passed as arguments take precedence over options loaded from
+the configuration file(s). This mechanism is good for running the game with a
+temporary setting which you do not intend to retain. Keep in mind that if you
+edit and save options in-game, any options you have passed as arguments during
+the invocation of the game will be saved to the $HOME/.yoinkrc configuration
+file. You may have to go into that file and remove any options you didn't
+intend to set. When passing options as arguments, you must use the fully
+qualified name of the option if it exists in a subgroup. For example:
+.PP
+.TP
+yoink video.fullscreen=true
+Set the option video.fullscreen to true. This will run the game in full-screen
+mode.
+.TP
+yoink video.maxfps=60
+Set the option video.maxfps to 60. This will cap the display rate at 60Hz.
+.PP
+You can also set options with array values. Arrays can be passed on the
+command line by surrounding all the parts with square brackets and separating
+each part by a comma. For example:
+.TP
+yoink video.mode=[1024,768]
+Set the option video.mode to an array with numbers 1024 and 768. The video size
+will be 1024x768.
+.PP
+Here is a list of some of the options available:
+.TP
+.B engine.timestep
+The amount of time in seconds between each update of the physics state. A value
+of 0.01 or lower is ideal for accurate physics approximations. Values that are
+much lower may introduce errors in the game.
+.TP
+.B input.grab
+Takes a boolean (true or false). If true, the cursor pointer will be "stuck"
+within the area of the window, and many key combinations which would otherwise
+be handled by the window manager will instead be dropped. This is a low-level
+option of limited usefulness.
+.TP
+.B video.colorbuffers
+This takes an array of four number values which represent the number of bits to
+use for red, green, blue, and the alpha channel. This is a low-level option of
+limited usefulness. The default value is almost always preferable.
+.TP
+.B video.cursor
+This option effects the visibility of the cursor while it is "hovering" over the
+window. If the value is true, the cursor will be visible. Otherwise, the
+cursor will be hidden.
+.TP
+.B video.doublebuffer
+If true, double-buffering will be used to render animations with minimal
+distortions. Otherwise, a single buffer will be used. The recommended value is
+true.
+.TP
+.B video.fullscreen
+If true, the window will capture the display and render the game in full screen
+splendor. A value of false means the game will run in a window.
+.TP
+.B video.maxfps
+The maximum number of frames to be drawn per second. A value of 50 is pretty
+good. If your computer is pretty old, can get away with decreasing this value
+and still have reasonably smooth animation. You can set this to a very high
+number to effectively render as many frames as is possible, but the actual rate
+could be limited by vertical display synchronization, depending on the X11
+driver and settings used. You should not set this option higher than the point
+where the vertical synchronization effectively limits the draw rate or else the
+game may not be able to update the physics on schedule which could actually
+significantly lower the quality of the animation.
+.TP
+.B video.mode
+The resolution or size of the window. The value is an array with three number
+elements representing the width, height, and bits per pixel that make up the
+video mode.. A typical value is [800,600,32] for a size of 800x600 pixels with
+millions of colors.
+.TP
+.B video.multisamplebuffers
+The number of multisample buffers used.
+.TP
+.B video.multisamplesamples
+The number of multisample samples used.
+.TP
+.B video.printfps
+If true, the current number of frames being draw per second will be printed to
+the console. This is usually off by default, but you can set this to true if
+you're interested in the draw rate you're actually getting.
+.TP
+.B video.resizable
+If true, the window will be resizable by the window manager. This option is
+meaningless if the game is drawing to the full screen.
+.TP
+.B video.swapcontrol
+If true, drawing will take place at a time which will minimize distortion caused
+by the vertical refreshing of displays. The recommended value is true.
+.br
+.SH ENVIRONMENT
+.PP
+.B yoink
+responds to some variables in the environment:
+.TP
+HOME
+If set to a path of a valid directory (presumably a user's home directory),
+.B yoink
+will load options from the configuration file at $HOME/.yoinkrc, if it exists.
+Saving options within the game will cause this file to be over-written with the
+new options.
+.TP
+USER
+.B yoink
+uses this variable to guess the user's nickname, for a high score entry or
+whatever.
+.TP
+YOINK_CONFIGFILE
+If set to a path of a valid configuration file,
+.B yoink
+will load the options from that file, and those options will take precedence
+over options loaded from other configuration files. Any in-game saving will
+cause this file to be over-written by the new options rather than the file at
+$HOME/.yoinkrc.
+.TP
+YOINK_DATADIR
+If set to a path of a valid directory,
+.B yoink
+will look in this directory first when it is loading game assets. Set this
+variable if you move the game's assets to another directory or want to load your
+own assets.
+.br
+.SH BUGS
+.PP
+The pixelated graphics are actually intentional. It adds to the charm of the
+game, don't you think?
+.PP
+Send bug reports and patches to:
+.br
+Charles McGarvey <onefriedrice@brokenzipper.com>
+.SH AUTHOR
+.PP
+Neil Carter was the original creator of Yoink, his winning entry in the
+uDevGames 2003 Mac game development contest. Charles McGarvey rewrote the game
+with SDL and is the current maintainer.
--- /dev/null
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI=2
+inherit autotools eutils games
+
+DESCRIPTION="Alien-smashing action game"
+HOMEPAGE="http://www.dogcows.com/"
+SRC_URI="http://www.dogcows.com/yoink/${P}.tar.bz2"
+
+LICENSE="BSD-2"
+SLOT="0"
+KEYWORDS="~amd64 ~ppc ~x86"
+IUSE="debug"
+
+RDEPEND="media-libs/libsdl[joystick,video]
+ media-libs/sdl-image[png]"
+DEPEND="${RDEPEND}
+ dev-util/pkgconfig"
+
+src_prepare() {
+ sed -i \
+ -e "s/-Werror//g" \
+ configure.ac \
+ || die "sed failed"
+ sed -i \
+ -e "/apps/d" \
+ -e "/pixmap/d" \
+ data/Makefile.am \
+ || die "sed failed"
+ sed -i \
+ -e "/man/d" \
+ doc/Makefile.am \
+ || die "sed failed"
+ eautoreconf
+}
+
+src_configure() {
+ egamesconf \
+ --disable-dependency-tracking \
+ --datadir="${GAMES_DATADIR}/${PN}" \
+ $(use_enable debug)
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die "emake install failed"
+ dodoc AUTHORS ChangeLog README TODO
+ doman doc/yoink.6
+ doicon data/yoink.png
+ make_desktop_entry ${PN} Yoink
+ prepgamesdirs
+}
--- /dev/null
+# boost.m4: Locate Boost headers and libraries for autoconf-based projects.
+# Copyright (C) 2007, 2008, 2009 Benoit Sigoure <tsuna@lrde.epita.fr>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Additional permission under section 7 of the GNU General Public
+# License, version 3 ("GPLv3"):
+#
+# If you convey this file as part of a work that contains a
+# configuration script generated by Autoconf, you may do so under
+# terms of your choice.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# serial 10
+# Original sources can be found at http://repo.or.cz/w/boost.m4.git
+# You can fetch the latest version of the script by doing:
+# wget 'http://repo.or.cz/w/boost.m4.git?a=blob_plain;f=build-aux/boost.m4;hb=HEAD' -O boost.m4
+
+# ------ #
+# README #
+# ------ #
+
+# This file provides several macros to use the various Boost libraries.
+# The first macro is BOOST_REQUIRE. It will simply check if it's possible to
+# find the Boost headers of a given (optional) minimum version and it will
+# define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to
+# your configure so that users can specify non standard locations.
+# If the user's environment contains BOOST_ROOT and --with-boost was not
+# specified, --with-boost=$BOOST_ROOT is implicitly used.
+# For more README and documentation, go to http://repo.or.cz/w/boost.m4.git
+# Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry,
+# simply read the README, it will show you what to do step by step.
+
+m4_pattern_forbid([^_?BOOST_])
+
+
+# _BOOST_SED_CPP(SED-PROGRAM, PROGRAM,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# --------------------------------------------------------
+# Same as AC_EGREP_CPP, but leave the result in conftest.i.
+# PATTERN is *not* overquoted, as in AC_EGREP_CPP. It could be useful
+# to turn this into a macro which extracts the value of any macro.
+m4_define([_BOOST_SED_CPP],
+[AC_LANG_PREPROC_REQUIRE()dnl
+AC_REQUIRE([AC_PROG_SED])dnl
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])])
+AS_IF([dnl eval is necessary to expand ac_cpp.
+dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell.
+(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD |
+ $SED -n -e "$1" >conftest.i 2>&1],
+ [$3],
+ [$4])dnl
+rm -f conftest*
+])# AC_EGREP_CPP
+
+
+
+# BOOST_REQUIRE([VERSION])
+# ------------------------
+# Look for Boost. If version is given, it must either be a literal of the form
+# "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a
+# variable "$var".
+# Defines the value BOOST_CPPFLAGS. This macro only checks for headers with
+# the required version, it does not check for any of the Boost libraries.
+# FIXME: Add a 2nd optional argument so that it's not fatal if Boost isn't found
+# and add an AC_DEFINE to tell whether HAVE_BOOST.
+AC_DEFUN([BOOST_REQUIRE],
+[boost_save_IFS=$IFS
+boost_version_req="$1"
+IFS=.
+set x $boost_version_req 0 0 0
+IFS=$boost_save_IFS
+shift
+boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"`
+AC_ARG_WITH([boost],
+ [AS_HELP_STRING([--with-boost=DIR],
+ [prefix of Boost $1 @<:@guess@:>@])])dnl
+AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl
+# If BOOST_ROOT is set and the user has not provided a value to
+# --with-boost, then treat BOOST_ROOT as if it the user supplied it.
+if test x"$BOOST_ROOT" != x; then
+ if test x"$with_boost" = x; then
+ AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT])
+ with_boost=$BOOST_ROOT
+ else
+ AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost])
+ fi
+fi
+AC_SUBST([DISTCHECK_CONFIGURE_FLAGS],
+ ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])
+boost_save_CPPFLAGS=$CPPFLAGS
+ AC_CACHE_CHECK([for Boost headers version >= $boost_version_req],
+ [boost_cv_inc_path],
+ [boost_cv_inc_path=no
+AC_LANG_PUSH([C++])dnl
+m4_pattern_allow([^BOOST_VERSION$])dnl
+ AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include <boost/version.hpp>
+#if !defined BOOST_VERSION
+# error BOOST_VERSION is not defined
+#elif BOOST_VERSION < $boost_version_req
+# error Boost headers version < $boost_version_req
+#endif
+]])])
+ # If the user provided a value to --with-boost, use it and only it.
+ case $with_boost in #(
+ ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \
+ /usr/include C:/Boost/include;; #(
+ *) set x "$with_boost/include" "$with_boost";;
+ esac
+ shift
+ for boost_dir
+ do
+ # Without --layout=system, Boost (or at least some versions) installs
+ # itself in <prefix>/include/boost-<version>. This inner loop helps to
+ # find headers in such directories.
+ # I didn't indent this loop on purpose (to avoid over-indented code)
+ for boost_inc in "$boost_dir" "$boost_dir"/boost-*
+ do
+ test x"$boost_inc" != x && CPPFLAGS="$CPPFLAGS -I$boost_inc"
+ AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no])
+ if test x"$boost_cv_inc_path" = xyes; then
+ if test x"$boost_inc" != x; then
+ boost_cv_inc_path=$boost_inc
+ fi
+ break 2
+ fi
+ done
+ done
+AC_LANG_POP([C++])dnl
+ ])
+ case $boost_cv_inc_path in #(
+ no) AC_MSG_ERROR([cannot find Boost headers version >= $boost_version_req]);;#(
+ yes) BOOST_CPPFLAGS=;;#(
+ *) AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"]);;
+ esac
+ AC_CACHE_CHECK([for Boost's header version],
+ [boost_cv_lib_version],
+ [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl
+ _BOOST_SED_CPP([/^boost-lib-version = /{s///;s/\"//g;p;g;}],
+ [#include <boost/version.hpp>
+boost-lib-version = BOOST_LIB_VERSION],
+ [boost_cv_lib_version=`cat conftest.i`])])
+ # e.g. "134" for 1_34_1 or "135" for 1_35
+ boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'`
+ case $boost_major_version in #(
+ '' | *[[!0-9]]*)
+ AC_MSG_ERROR([Invalid value: boost_major_version=$boost_major_version])
+ ;;
+ esac
+CPPFLAGS=$boost_save_CPPFLAGS
+])# BOOST_REQUIRE
+
+# BOOST_STATIC()
+# --------------
+# Add the "--enable-static-boost" configure argument. If this argument is given
+# on the command line, static versions of the libraries will be looked up.
+AC_DEFUN([BOOST_STATIC],
+ [AC_ARG_ENABLE([static-boost],
+ [AC_HELP_STRING([--enable-static-boost],
+ [Prefer the static boost libraries over the shared ones [no]])],
+ [enable_static_boost=yes],
+ [enable_static_boost=no])])# BOOST_STATIC
+
+# BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND])
+# --------------------------------------------------------------------------
+# Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for
+# some parts of the Boost library which are only made of headers and don't
+# require linking (such as Boost.Foreach).
+#
+# Default ACTION-IF-NOT-FOUND: Fail with a fatal error.
+#
+# Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_<HEADER-NAME> in
+# case of success # (where HEADER-NAME is written LIKE_THIS, e.g.,
+# HAVE_BOOST_FOREACH_HPP).
+AC_DEFUN([BOOST_FIND_HEADER],
+[AC_REQUIRE([BOOST_REQUIRE])dnl
+AC_LANG_PUSH([C++])dnl
+boost_save_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+AC_CHECK_HEADER([$1],
+ [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1],
+ [Define to 1 if you have <$1>])])],
+ [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])])
+CPPFLAGS=$boost_save_CPPFLAGS
+AC_LANG_POP([C++])dnl
+])# BOOST_FIND_HEADER
+
+
+# BOOST_FIND_LIB([LIB-NAME], [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST],
+# [CXX-PROLOGUE])
+# -------------------------------------------------------------------------
+# Look for the Boost library LIB-NAME (e.g., LIB-NAME = `thread', for
+# libboost_thread). Check that HEADER-NAME works and check that
+# libboost_LIB-NAME can link with the code CXX-TEST. The optional argument
+# CXX-PROLOGUE can be used to include some C++ code before the `main'
+# function.
+#
+# Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above).
+#
+# Boost libraries typically come compiled with several flavors (with different
+# runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one
+# or more of the following letters: sgdpn (in that order). s = static
+# runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build,
+# n = (unsure) STLPort build without iostreams from STLPort (it looks like `n'
+# must always be used along with `p'). Additionally, PREFERRED-RT-OPT can
+# start with `mt-' to indicate that there is a preference for multi-thread
+# builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp
+# ... If you want to make sure you have a specific version of Boost
+# (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro.
+AC_DEFUN([BOOST_FIND_LIB],
+[AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl
+AC_REQUIRE([BOOST_REQUIRE])dnl
+AC_REQUIRE([BOOST_STATIC])dnl
+AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl
+AC_LANG_PUSH([C++])dnl
+AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl
+AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl
+AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl
+BOOST_FIND_HEADER([$3])
+boost_save_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+# Now let's try to find the library. The algorithm is as follows: first look
+# for a given library name according to the user's PREFERRED-RT-OPT. For each
+# library name, we prefer to use the ones that carry the tag (toolset name).
+# Each library is searched through the various standard paths were Boost is
+# usually installed. If we can't find the standard variants, we try to
+# enforce -mt (for instance on MacOSX, libboost_threads.dylib doesn't exist
+# but there's -obviously- libboost_threads-mt.dylib).
+AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib],
+ [Boost_lib=no
+ case "$2" in #(
+ mt | mt-) boost_mt=-mt; boost_rtopt=;; #(
+ mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$2" : 'Xmt-*\(.*\)'`;; #(
+ *) boost_mt=; boost_rtopt=$2;;
+ esac
+ if test $enable_static_boost = yes; then
+ boost_rtopt="s$boost_rtopt"
+ fi
+ # Find the proper debug variant depending on what we've been asked to find.
+ case $boost_rtopt in #(
+ *d*) boost_rt_d=$boost_rtopt;; #(
+ *[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn')
+ boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #(
+ *) boost_rt_d='-d';;
+ esac
+ # If the PREFERRED-RT-OPT are not empty, prepend a `-'.
+ test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt"
+ $boost_guess_use_mt && boost_mt=-mt
+ # Look for the abs path the static archive.
+ # $libext is computed by Libtool but let's make sure it's non empty.
+ test -z "$libext" &&
+ AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?])
+ boost_save_ac_objext=$ac_objext
+ # Generate the test file.
+ AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$3>
+$5], [$4])])
+dnl Optimization hacks: compiling C++ is slow, especially with Boost. What
+dnl we're trying to do here is guess the right combination of link flags
+dnl (LIBS / LDFLAGS) to use a given library. This can take several
+dnl iterations before it succeeds and is thus *very* slow. So what we do
+dnl instead is that we compile the code first (and thus get an object file,
+dnl typically conftest.o). Then we try various combinations of link flags
+dnl until we succeed to link conftest.o in an executable. The problem is
+dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always
+dnl remove all the temporary files including conftest.o. So the trick here
+dnl is to temporarily change the value of ac_objext so that conftest.o is
+dnl preserved accross tests. This is obviously fragile and I will burn in
+dnl hell for not respecting Autoconf's documented interfaces, but in the
+dnl mean time, it optimizes the macro by a factor of 5 to 30.
+dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left
+dnl empty because the test file is generated only once above (before we
+dnl start the for loops).
+ AC_COMPILE_IFELSE([],
+ [ac_objext=do_not_rm_me_plz],
+ [AC_MSG_ERROR([Cannot compile a test that uses Boost $1])])
+ ac_objext=$boost_save_ac_objext
+ boost_failed_libs=
+# Don't bother to ident the 6 nested for loops, only the 2 innermost ones
+# matter.
+for boost_tag_ in -$boost_cv_lib_tag ''; do
+for boost_ver_ in -$boost_cv_lib_version ''; do
+for boost_mt_ in $boost_mt -mt ''; do
+for boost_rtopt_ in $boost_rtopt '' -d; do
+ for boost_lib in \
+ boost_$1$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \
+ boost_$1$boost_tag_$boost_rtopt_$boost_ver_ \
+ boost_$1$boost_tag_$boost_mt_$boost_ver_ \
+ boost_$1$boost_tag_$boost_ver_
+ do
+ # Avoid testing twice the same lib
+ case $boost_failed_libs in #(
+ *@$boost_lib@*) continue;;
+ esac
+ # If with_boost is empty, we'll search in /lib first, which is not quite
+ # right so instead we'll try to a location based on where the headers are.
+ boost_tmp_lib=$with_boost
+ test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include}
+ for boost_ldpath in "$boost_tmp_lib/lib" '' \
+ /opt/local/lib /usr/local/lib /opt/lib /usr/lib \
+ "$with_boost" C:/Boost/lib /lib /usr/lib64 /lib64
+ do
+ test -e "$boost_ldpath" || continue
+ boost_save_LDFLAGS=$LDFLAGS
+ # Are we looking for a static library?
+ case $boost_ldpath:$boost_rtopt_ in #(
+ *?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt)
+ Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext"
+ test -e "$Boost_lib_LIBS" || continue;; #(
+ *) # No: use -lboost_foo to find the shared library.
+ Boost_lib_LIBS="-l$boost_lib";;
+ esac
+ boost_save_LIBS=$LIBS
+ LIBS="$Boost_lib_LIBS $LIBS"
+ test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath"
+dnl First argument of AC_LINK_IFELSE left empty because the test file is
+dnl generated only once above (before we start the for loops).
+ _BOOST_AC_LINK_IFELSE([],
+ [Boost_lib=yes], [Boost_lib=no])
+ ac_objext=$boost_save_ac_objext
+ LDFLAGS=$boost_save_LDFLAGS
+ LIBS=$boost_save_LIBS
+ if test x"$Boost_lib" = xyes; then
+ Boost_lib_LDFLAGS="-L$boost_ldpath -R$boost_ldpath"
+ break 6
+ else
+ boost_failed_libs="$boost_failed_libs@$boost_lib@"
+ fi
+ done
+ done
+done
+done
+done
+done
+rm -f conftest.$ac_objext
+])
+case $Boost_lib in #(
+ no) AC_MSG_ERROR([Could not find the flags to link with Boost $1])
+ ;;
+esac
+AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])
+AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])
+CPPFLAGS=$boost_save_CPPFLAGS
+AS_VAR_POPDEF([Boost_lib])dnl
+AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl
+AS_VAR_POPDEF([Boost_lib_LIBS])dnl
+AC_LANG_POP([C++])dnl
+])# BOOST_FIND_LIB
+
+
+# --------------------------------------- #
+# Checks for the various Boost libraries. #
+# --------------------------------------- #
+
+# List of boost libraries: http://www.boost.org/libs/libraries.htm
+# The page http://beta.boost.org/doc/libs is useful: it gives the first release
+# version of each library (among other things).
+
+
+# BOOST_ASIO()
+# ------------
+# Look for Boost.Asio (new in Boost 1.35).
+AC_DEFUN([BOOST_ASIO],
+[AC_REQUIRE([BOOST_SYSTEM])dnl
+BOOST_FIND_HEADER([boost/asio.hpp])])
+
+
+# BOOST_BIND()
+# ------------
+# Look for Boost.Bind
+AC_DEFUN([BOOST_BIND],
+[BOOST_FIND_HEADER([boost/bind.hpp])])
+
+
+# BOOST_CONVERSION()
+# ------------------
+# Look for Boost.Conversion (cast / lexical_cast)
+AC_DEFUN([BOOST_CONVERSION],
+[BOOST_FIND_HEADER([boost/cast.hpp])
+BOOST_FIND_HEADER([boost/lexical_cast.hpp])
+])# BOOST_CONVERSION
+
+
+# BOOST_DATE_TIME([PREFERRED-RT-OPT])
+# -----------------------------------
+# Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+AC_DEFUN([BOOST_DATE_TIME],
+[BOOST_FIND_LIB([date_time], [$1],
+ [boost/date_time/posix_time/posix_time.hpp],
+ [boost::posix_time::ptime t;])
+])# BOOST_DATE_TIME
+
+
+# BOOST_FILESYSTEM([PREFERRED-RT-OPT])
+# ------------------------------------
+# Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see
+# the documentation of BOOST_FIND_LIB above.
+# Do not check for boost/filesystem.hpp because this file was introduced in
+# 1.34.
+AC_DEFUN([BOOST_FILESYSTEM],
+[# Do we have to check for Boost.System? This link-time dependency was
+# added as of 1.35.0. If we have a version <1.35, we must not attempt to
+# find Boost.System as it didn't exist by then.
+if test $boost_major_version -ge 135; then
+BOOST_SYSTEM([$1])
+fi # end of the Boost.System check.
+boost_filesystem_save_LIBS=$LIBS
+boost_filesystem_save_LDFLAGS=$LDFLAGS
+m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS"
+BOOST_FIND_LIB([filesystem], [$1],
+ [boost/filesystem/path.hpp], [boost::filesystem::path p;])
+LIBS=$boost_filesystem_save_LIBS
+LDFLAGS=$boost_filesystem_save_LDFLAGS
+])# BOOST_FILESYSTEM
+
+
+# BOOST_FOREACH()
+# ---------------
+# Look for Boost.Foreach
+AC_DEFUN([BOOST_FOREACH],
+[BOOST_FIND_HEADER([boost/foreach.hpp])])
+
+
+# BOOST_FORMAT()
+# --------------
+# Look for Boost.Format
+# Note: we can't check for boost/format/format_fwd.hpp because the header isn't
+# standalone. It can't be compiled because it triggers the following error:
+# boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std'
+# does not name a type
+AC_DEFUN([BOOST_FORMAT],
+[BOOST_FIND_HEADER([boost/format.hpp])])
+
+
+# BOOST_FUNCTION()
+# ----------------
+# Look for Boost.Function
+AC_DEFUN([BOOST_FUNCTION],
+[BOOST_FIND_HEADER([boost/function.hpp])])
+
+
+# BOOST_GRAPH([PREFERRED-RT-OPT])
+# -------------------------------
+# Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+AC_DEFUN([BOOST_GRAPH],
+[BOOST_FIND_LIB([graph], [$1],
+ [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;])
+])# BOOST_GRAPH
+
+
+# BOOST_IOSTREAMS([PREFERRED-RT-OPT])
+# -------------------------------
+# Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+AC_DEFUN([BOOST_IOSTREAMS],
+[BOOST_FIND_LIB([iostreams], [$1],
+ [boost/iostreams/device/file_descriptor.hpp],
+ [boost::iostreams::file_descriptor fd(0); fd.close();])
+])# BOOST_IOSTREAMS
+
+
+# BOOST_HASH()
+# ------------
+# Look for Boost.Functional/Hash
+AC_DEFUN([BOOST_HASH],
+[BOOST_FIND_HEADER([boost/functional/hash.hpp])])
+
+
+# BOOST_LAMBDA()
+# --------------
+# Look for Boost.Lambda
+AC_DEFUN([BOOST_LAMBDA],
+[BOOST_FIND_HEADER([boost/lambda/lambda.hpp])])
+
+
+# BOOST_OPTIONAL()
+# ----------------
+# Look for Boost.Optional
+AC_DEFUN([BOOST_OPTIONAL],
+[BOOST_FIND_HEADER([boost/optional.hpp])])
+
+
+# BOOST_PREPROCESSOR()
+# --------------------
+# Look for Boost.Preprocessor
+AC_DEFUN([BOOST_PREPROCESSOR],
+[BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])])
+
+
+# BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT])
+# -----------------------------------------
+# Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, see
+# the documentation of BOOST_FIND_LIB above.
+AC_DEFUN([BOOST_PROGRAM_OPTIONS],
+[BOOST_FIND_LIB([program_options], [$1],
+ [boost/program_options.hpp],
+ [boost::program_options::options_description d("test");])
+])# BOOST_PROGRAM_OPTIONS
+
+
+# BOOST_REF()
+# -----------
+# Look for Boost.Ref
+AC_DEFUN([BOOST_REF],
+[BOOST_FIND_HEADER([boost/ref.hpp])])
+
+
+# BOOST_REGEX([PREFERRED-RT-OPT])
+# -------------------------------
+# Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+AC_DEFUN([BOOST_REGEX],
+[BOOST_FIND_LIB([regex], [$1],
+ [boost/regex.hpp],
+ [boost::regex exp("*"); boost::regex_match("foo", exp);])
+])# BOOST_REGEX
+
+
+# BOOST_SERIALIZATION([PREFERRED-RT-OPT])
+# ---------------------------------------
+# Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see
+# the documentation of BOOST_FIND_LIB above.
+AC_DEFUN([BOOST_SERIALIZATION],
+[BOOST_FIND_LIB([serialization], [$1],
+ [boost/archive/text_oarchive.hpp],
+ [std::ostream* o = 0; // Cheap way to get an ostream...
+ boost::archive::text_oarchive t(*o);])
+])# BOOST_SIGNALS
+
+
+# BOOST_SIGNALS([PREFERRED-RT-OPT])
+# ---------------------------------
+# Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+AC_DEFUN([BOOST_SIGNALS],
+[BOOST_FIND_LIB([signals], [$1],
+ [boost/signal.hpp],
+ [boost::signal<void ()> s;])
+])# BOOST_SIGNALS
+
+
+# BOOST_SMART_PTR()
+# -----------------
+# Look for Boost.SmartPtr
+AC_DEFUN([BOOST_SMART_PTR],
+[BOOST_FIND_HEADER([boost/scoped_ptr.hpp])
+BOOST_FIND_HEADER([boost/shared_ptr.hpp])
+])
+
+
+# BOOST_STATICASSERT()
+# --------------------
+# Look for Boost.StaticAssert
+AC_DEFUN([BOOST_STATICASSERT],
+[BOOST_FIND_HEADER([boost/static_assert.hpp])])
+
+
+# BOOST_STRING_ALGO()
+# -------------------
+# Look for Boost.StringAlgo
+AC_DEFUN([BOOST_STRING_ALGO],
+[BOOST_FIND_HEADER([boost/algorithm/string.hpp])
+])
+
+
+# BOOST_SYSTEM([PREFERRED-RT-OPT])
+# --------------------------------
+# Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above. This library was introduced in Boost
+# 1.35.0.
+AC_DEFUN([BOOST_SYSTEM],
+[BOOST_FIND_LIB([system], [$1],
+ [boost/system/error_code.hpp],
+ [boost::system::error_code e; e.clear();])
+])# BOOST_SYSTEM
+
+
+# BOOST_TEST([PREFERRED-RT-OPT])
+# ------------------------------
+# Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+AC_DEFUN([BOOST_TEST],
+[m4_pattern_allow([^BOOST_CHECK$])dnl
+BOOST_FIND_LIB([unit_test_framework], [$1],
+ [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);],
+ [using boost::unit_test::test_suite;
+ test_suite* init_unit_test_suite(int argc, char ** argv)
+ { return NULL; }])
+])# BOOST_TEST
+
+
+# BOOST_THREADS([PREFERRED-RT-OPT])
+# ---------------------------------
+# Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+# FIXME: Provide an alias "BOOST_THREAD".
+AC_DEFUN([BOOST_THREADS],
+[dnl Having the pthread flag is required at least on GCC3 where
+dnl boost/thread.hpp would complain if we try to compile without
+dnl -pthread on GNU/Linux.
+AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl
+boost_threads_save_LIBS=$LIBS
+boost_threads_save_CPPFLAGS=$CPPFLAGS
+LIBS="$LIBS $boost_cv_pthread_flag"
+# Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3,
+# boost/thread.hpp will trigger a #error if -pthread isn't used:
+# boost/config/requires_threads.hpp:47:5: #error "Compiler threading support
+# is not turned on. Please set the correct command line options for
+# threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)"
+CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag"
+BOOST_FIND_LIB([thread], [$1],
+ [boost/thread.hpp], [boost::thread t; boost::mutex m;])
+BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $boost_cv_pthread_flag"
+BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag"
+LIBS=$boost_threads_save_LIBS
+CPPFLAGS=$boost_threads_save_CPPFLAGS
+])# BOOST_THREADS
+
+
+# BOOST_TOKENIZER()
+# -----------------
+# Look for Boost.Tokenizer
+AC_DEFUN([BOOST_TOKENIZER],
+[BOOST_FIND_HEADER([boost/tokenizer.hpp])])
+
+
+# BOOST_TRIBOOL()
+# ---------------
+# Look for Boost.Tribool
+AC_DEFUN([BOOST_TRIBOOL],
+[BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp])
+BOOST_FIND_HEADER([boost/logic/tribool.hpp])
+])
+
+
+# BOOST_TUPLE()
+# -------------
+# Look for Boost.Tuple
+AC_DEFUN([BOOST_TUPLE],
+[BOOST_FIND_HEADER([boost/tuple/tuple.hpp])])
+
+
+# BOOST_TYPETRAITS()
+# --------------------
+# Look for Boost.TypeTraits
+AC_DEFUN([BOOST_TYPETRAITS],
+[BOOST_FIND_HEADER([boost/type_traits.hpp])])
+
+
+# BOOST_UTILITY()
+# ---------------
+# Look for Boost.Utility (noncopyable, result_of, base-from-member idiom,
+# etc.)
+AC_DEFUN([BOOST_UTILITY],
+[BOOST_FIND_HEADER([boost/utility.hpp])])
+
+
+# BOOST_VARIANT()
+# ---------------
+# Look for Boost.Variant.
+AC_DEFUN([BOOST_VARIANT],
+[BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp])
+BOOST_FIND_HEADER([boost/variant.hpp])])
+
+
+# BOOST_WAVE([PREFERRED-RT-OPT])
+# ------------------------------
+# NOTE: If you intend to use Wave/Spirit with thread support, make sure you
+# call BOOST_THREADS first.
+# Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the
+# documentation of BOOST_FIND_LIB above.
+AC_DEFUN([BOOST_WAVE],
+[AC_REQUIRE([BOOST_FILESYSTEM])dnl
+AC_REQUIRE([BOOST_DATE_TIME])dnl
+boost_wave_save_LIBS=$LIBS
+boost_wave_save_LDFLAGS=$LDFLAGS
+m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl
+LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS\
+$BOOST_THREAD_LIBS"
+LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS\
+$BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS"
+BOOST_FIND_LIB([wave], [$1],
+ [boost/wave.hpp],
+ [boost::wave::token_id id; get_token_name(id);])
+LIBS=$boost_wave_save_LIBS
+LDFLAGS=$boost_wave_save_LDFLAGS
+])# BOOST_WAVE
+
+
+# BOOST_XPRESSIVE()
+# -----------------
+# Look for Boost.Xpressive (new since 1.36.0).
+AC_DEFUN([BOOST_XPRESSIVE],
+[BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])])
+
+
+# ----------------- #
+# Internal helpers. #
+# ----------------- #
+
+
+# _BOOST_PTHREAD_FLAG()
+# ---------------------
+# Internal helper for BOOST_THREADS. Based on ACX_PTHREAD:
+# http://autoconf-archive.cryp.to/acx_pthread.html
+AC_DEFUN([_BOOST_PTHREAD_FLAG],
+[AC_REQUIRE([AC_PROG_CXX])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_LANG_PUSH([C++])dnl
+AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag],
+[ boost_cv_pthread_flag=
+ # The ordering *is* (sometimes) important. Some notes on the
+ # individual items follow:
+ # (none): in case threads are in libc; should be tried before -Kthread and
+ # other compiler flags to prevent continual compiler warnings
+ # -lpthreads: AIX (must check this before -lpthread)
+ # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+ # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+ # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads)
+ # -pthreads: Solaris/GCC
+ # -mthreads: MinGW32/GCC, Lynx/GCC
+ # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+ # doesn't hurt to check since this sometimes defines pthreads too;
+ # also defines -D_REENTRANT)
+ # ... -mt is also the pthreads flag for HP/aCC
+ # -lpthread: GNU Linux, etc.
+ # --thread-safe: KAI C++
+ case $host_os in #(
+ *solaris*)
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+ boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #(
+ *)
+ boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \
+ -pthreads -mthreads -lpthread --thread-safe -mt";;
+ esac
+ # Generate the test file.
+ AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0);])])
+ for boost_pthread_flag in '' $boost_pthread_flags; do
+ boost_pthread_ok=false
+dnl Re-use the test file already generated.
+ boost_pthreads__save_LIBS=$LIBS
+ LIBS="$LIBS $boost_pthread_flag"
+ AC_LINK_IFELSE([],
+ [if grep ".*$boost_pthread_flag" conftest.err; then
+ echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD
+ else
+ boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag
+ fi])
+ LIBS=$boost_pthreads__save_LIBS
+ $boost_pthread_ok && break
+ done
+])
+AC_LANG_POP([C++])dnl
+])# _BOOST_PTHREAD_FLAG
+
+
+# _BOOST_gcc_test(MAJOR, MINOR)
+# -----------------------------
+# Internal helper for _BOOST_FIND_COMPILER_TAG.
+m4_define([_BOOST_gcc_test],
+["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl
+
+
+# _BOOST_FIND_COMPILER_TAG()
+# --------------------------
+# Internal. When Boost is installed without --layout=system, each library
+# filename will hold a suffix that encodes the compiler used during the
+# build. The Boost build system seems to call this a `tag'.
+AC_DEFUN([_BOOST_FIND_COMPILER_TAG],
+[AC_REQUIRE([AC_PROG_CXX])dnl
+AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag],
+[AC_LANG_PUSH([C++])dnl
+ boost_cv_lib_tag=unknown
+ # The following tests are mostly inspired by boost/config/auto_link.hpp
+ # The list is sorted to most recent/common to oldest compiler (in order
+ # to increase the likelihood of finding the right compiler with the
+ # least number of compilation attempt).
+ # Beware that some tests are sensible to the order (for instance, we must
+ # look for MinGW before looking for GCC3).
+ # I used one compilation test per compiler with a #error to recognize
+ # each compiler so that it works even when cross-compiling (let me know
+ # if you know a better approach).
+ # Known missing tags (known from Boost's tools/build/v2/tools/common.jam):
+ # como, edg, kcc, bck, mp, sw, tru, xlc
+ # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines
+ # the same defines as GCC's).
+ # TODO: Move the test on GCC 4.4 up once it's released.
+ for i in \
+ _BOOST_gcc_test(4, 3) \
+ _BOOST_gcc_test(4, 2) \
+ _BOOST_gcc_test(4, 1) \
+ _BOOST_gcc_test(4, 0) \
+ "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \
+ && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \
+ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \
+ _BOOST_gcc_test(3, 4) \
+ _BOOST_gcc_test(3, 3) \
+ "defined _MSC_VER && _MSC_VER >= 1400 @ vc80" \
+ _BOOST_gcc_test(3, 2) \
+ "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \
+ _BOOST_gcc_test(3, 1) \
+ _BOOST_gcc_test(3, 0) \
+ "defined __BORLANDC__ @ bcb" \
+ "defined __ICC && (defined __unix || defined __unix__) @ il" \
+ "defined __ICL @ iw" \
+ "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \
+ _BOOST_gcc_test(4, 4) \
+ _BOOST_gcc_test(2, 95) \
+ "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \
+ "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \
+ "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \
+ "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8"
+ do
+ boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '`
+ boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'`
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if $boost_tag_test
+/* OK */
+#else
+# error $boost_tag_test
+#endif
+]])], [boost_cv_lib_tag=$boost_tag; break], [])
+ done
+AC_LANG_POP([C++])dnl
+ case $boost_cv_lib_tag in #(
+ # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed
+ # to "gcc41" for instance.
+ *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there.
+ gcc*)
+ # We can specify multiple tags in this variable because it's used by
+ # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ...
+ boost_cv_lib_tag="$boost_cv_lib_tag -gcc"
+ ;; #(
+ unknown)
+ AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]])
+ boost_cv_lib_tag=
+ ;;
+ esac
+])dnl end of AC_CACHE_CHECK
+])# _BOOST_FIND_COMPILER_TAG
+
+
+# _BOOST_GUESS_WHETHER_TO_USE_MT()
+# --------------------------------
+# Compile a small test to try to guess whether we should favor MT (Multi
+# Thread) flavors of Boost. Sets boost_guess_use_mt accordingly.
+AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT],
+[# Check whether we do better use `mt' even though we weren't ask to.
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if defined _REENTRANT || defined _MT || defined __MT__
+/* use -mt */
+#else
+# error MT not needed
+#endif
+]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false])
+])
+
+# _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+# -------------------------------------------------------------------
+# Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile,
+# will break when Autoconf changes its internals. Requires that you manually
+# rm -f conftest.$ac_objext in between to really different tests, otherwise
+# you will try to link a conftest.o left behind by a previous test.
+# Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this
+# macro)
+m4_define([_BOOST_AC_LINK_IFELSE],
+[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl
+rm -f conftest$ac_exeext
+boost_ac_ext_save=$ac_ext
+boost_use_source=:
+# If we already have a .o, re-use it. We change $ac_ext so that $ac_link
+# tries to link the existing object file instead of compiling from source.
+test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false &&
+ _AS_ECHO_LOG([re-using the existing conftest.$ac_objext])
+AS_IF([_AC_DO_STDERR($ac_link) && {
+ test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_executable_p conftest$ac_exeext
+dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough.
+ }],
+ [$2],
+ [if $boost_use_source; then
+ _AC_MSG_LOG_CONFTEST
+ fi
+ $3])
+dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization)
+dnl information created by the PGI compiler (conftest_ipa8_conftest.oo),
+dnl as it would interfere with the next link command.
+rm -f core conftest.err conftest_ipa8_conftest.oo \
+ conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl
+])# _BOOST_AC_LINK_IFELSE
+
+# Local Variables:
+# mode: autoconf
+# End:
--- /dev/null
+# Configure paths for SDL
+# Sam Lantinga 9/21/99
+# stolen from Manish Singh
+# stolen back from Frank Belew
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
+dnl
+AC_DEFUN([AM_PATH_SDL],
+[dnl
+dnl Get the cflags and libraries from the sdl-config script
+dnl
+AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)],
+ sdl_prefix="$withval", sdl_prefix="")
+AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)],
+ sdl_exec_prefix="$withval", sdl_exec_prefix="")
+AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program],
+ , enable_sdltest=yes)
+
+ if test x$sdl_exec_prefix != x ; then
+ sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix"
+ if test x${SDL_CONFIG+set} != xset ; then
+ SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config
+ fi
+ fi
+ if test x$sdl_prefix != x ; then
+ sdl_args="$sdl_args --prefix=$sdl_prefix"
+ if test x${SDL_CONFIG+set} != xset ; then
+ SDL_CONFIG=$sdl_prefix/bin/sdl-config
+ fi
+ fi
+
+ AC_REQUIRE([AC_CANONICAL_TARGET])
+ PATH="$prefix/bin:$prefix/usr/bin:$PATH"
+ AC_PATH_PROG(SDL_CONFIG, sdl-config, no, [$PATH])
+ min_sdl_version=ifelse([$1], ,0.11.0,$1)
+ AC_MSG_CHECKING(for SDL - version >= $min_sdl_version)
+ no_sdl=""
+ if test "$SDL_CONFIG" = "no" ; then
+ no_sdl=yes
+ else
+ SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags`
+ SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs`
+
+ sdl_major_version=`$SDL_CONFIG $sdl_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ if test "x$enable_sdltest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $SDL_CFLAGS"
+ LIBS="$LIBS $SDL_LIBS"
+dnl
+dnl Now check if the installed SDL is sufficiently new. (Also sanity
+dnl checks the results of sdl-config to some extent
+dnl
+ rm -f conf.sdltest
+ AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "SDL.h"
+
+char*
+my_strdup (char *str)
+{
+ char *new_str;
+
+ if (str)
+ {
+ new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char));
+ strcpy (new_str, str);
+ }
+ else
+ new_str = NULL;
+
+ return new_str;
+}
+
+int main (int argc, char *argv[])
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ /* This hangs on some systems (?)
+ system ("touch conf.sdltest");
+ */
+ { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); }
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = my_strdup("$min_sdl_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) {
+ printf("%s, bad version string\n", "$min_sdl_version");
+ exit(1);
+ }
+
+ if (($sdl_major_version > major) ||
+ (($sdl_major_version == major) && ($sdl_minor_version > minor)) ||
+ (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version);
+ printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro);
+ printf("*** best to upgrade to the required version.\n");
+ printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n");
+ printf("*** to point to the correct copy of sdl-config, and remove the file\n");
+ printf("*** config.cache before re-running configure\n");
+ return 1;
+ }
+}
+
+],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ if test "x$no_sdl" = x ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ if test "$SDL_CONFIG" = "no" ; then
+ echo "*** The sdl-config script installed by SDL could not be found"
+ echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the SDL_CONFIG environment variable to the"
+ echo "*** full path to sdl-config."
+ else
+ if test -f conf.sdltest ; then
+ :
+ else
+ echo "*** Could not run SDL test program, checking why..."
+ CFLAGS="$CFLAGS $SDL_CFLAGS"
+ LIBS="$LIBS $SDL_LIBS"
+ AC_TRY_LINK([
+#include <stdio.h>
+#include "SDL.h"
+
+int main(int argc, char *argv[])
+{ return 0; }
+#undef main
+#define main K_and_R_C_main
+], [ return 0; ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding SDL or finding the wrong"
+ echo "*** version of SDL. If it is not finding SDL, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+ [ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means SDL was incorrectly installed"
+ echo "*** or that you have moved SDL since it was installed. In the latter case, you"
+ echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ SDL_CFLAGS=""
+ SDL_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+ AC_SUBST(SDL_CFLAGS)
+ AC_SUBST(SDL_LIBS)
+ rm -f conf.sdltest
+])
+++ /dev/null
-{
- "tilemap": "Heroine.png",
- "animation": "Heroine.json"
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>8</string>
- <key>TilesV</key>
- <string>4</string>
- <key>InvertAlpha</key>
- <string>0</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>1</string>
- <key>TilesV</key>
- <string>1</string>
- <key>InvertAlpha</key>
- <string>0</string>
-
- <key>WrapU</key>
- <string>ClampToEdge</string>
- <key>WrapV</key>
- <string>ClampToEdge</string>
- <key>MinFilter</key>
- <string>Linear</string>
- <key>MagFilter</key>
- <string>Linear</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>1</string>
- <key>TilesV</key>
- <string>1</string>
- <key>InvertAlpha</key>
- <string>0</string>
-
- <key>WrapU</key>
- <string>Wrap</string>
- <key>WrapV</key>
- <string>Wrap</string>
- <key>MinFilter</key>
- <string>Linear</string>
- <key>MagFilter</key>
- <string>Linear</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>8</string>
- <key>TilesV</key>
- <string>1</string>
- <key>InvertAlpha</key>
- <string>0</string>
-
- <key>MinFilter</key>
- <string>Linear</string>
- <key>MagFilter</key>
- <string>Linear</string>
- <key>WrapU</key>
- <string>ClampToEdge</string>
- <key>WrapV</key>
- <string>ClampToEdge</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>8</string>
- <key>TilesV</key>
- <string>4</string>
- <key>InvertAlpha</key>
- <string>0</string>
-
- <key>MinFilter</key>
- <string>Linear</string>
- <key>MagFilter</key>
- <string>Linear</string>
- <key>WrapU</key>
- <string>ClampToEdge</string>
- <key>WrapV</key>
- <string>ClampToEdge</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>8</string>
- <key>TilesV</key>
- <string>4</string>
- <key>InvertAlpha</key>
- <string>0</string>
-
- <key>WrapU</key>
- <string>ClampToEdge</string>
- <key>WrapV</key>
- <string>ClampToEdge</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>MinFilter</key>
- <string>Linear</string>
- <key>MagFilter</key>
- <string>Linear</string>
- <key>WrapU</key>
- <string>Repeat</string>
- <key>WrapV</key>
- <string>Repeat</string>
- <key>InvertAlpha</key>
- <string>0</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>8</string>
- <key>TilesV</key>
- <string>8</string>
- <key>InvertAlpha</key>
- <string>0</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>8</string>
- <key>TilesV</key>
- <string>4</string>
- <key>InvertAlpha</key>
- <string>0</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>4</string>
- <key>TilesV</key>
- <string>2</string>
- <key>InvertAlpha</key>
- <string>0</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>8</string>
- <key>TilesV</key>
- <string>4</string>
- <key>InvertAlpha</key>
- <string>0</string>
-
- <key>MinFilter</key>
- <string>Linear</string>
- <key>MagFilter</key>
- <string>Linear</string>
- <key>WrapU</key>
- <string>ClampToEdge</string>
- <key>WrapV</key>
- <string>ClampToEdge</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>8</string>
- <key>TilesV</key>
- <string>4</string>
- <key>InvertAlpha</key>
- <string>0</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>4</string>
- <key>TilesV</key>
- <string>4</string>
- <key>InvertAlpha</key>
- <string>0</string>
-
- <key>MinFilter</key>
- <string>Linear</string>
- <key>MagFilter</key>
- <string>Linear</string>
- <key>WrapU</key>
- <string>Wrap</string>
- <key>WrapV</key>
- <string>Wrap</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>4</string>
- <key>TilesV</key>
- <string>1</string>
- <key>InvertAlpha</key>
- <string>0</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>4</string>
- <key>TilesV</key>
- <string>4</string>
- <key>InvertAlpha</key>
- <string>0</string>
-
- <key>MinFilter</key>
- <string>Linear</string>
- <key>MagFilter</key>
- <string>Linear</string>
- <key>WrapU</key>
- <string>ClampToEdge</string>
- <key>WrapV</key>
- <string>ClampToEdge</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
- <key>TilesU</key>
- <string>2</string>
- <key>TilesV</key>
- <string>1</string>
- <key>InvertAlpha</key>
- <string>0</string>
-
- <key>MinFilter</key>
- <string>Linear</string>
- <key>MagFilter</key>
- <string>Linear</string>
- <key>WrapU</key>
- <string>ClampToEdge</string>
- <key>WrapV</key>
- <string>ClampToEdge</string>
- <key>MinFilter</key>
- <string>Nearest</string>
- <key>MagFilter</key>
- <string>Nearest</string>
-</dict>
-</plist>
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#include "Character.hh"
+
+
+Character::Character(const std::string& name) :
+ texture(name),
+ anim(name) {}
+
+Character::~Character()
+{
+ //delete texture;
+ //delete anim;
+}
+
+
+void Character::draw(dc::scalar alpha) {}
+
+dc::tilemap& Character::getTilemap()
+{
+ return texture;
+}
+
+dc::animation& Character::getAnimation()
+{
+ return anim;
+}
+
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#ifndef _CHARACTER_HH_
#define _CHARACTER_HH_
+#include "resource.hh"
+#include "drawable.hh"
+#include "animation.hh"
+#include "tilemap.hh"
+
+
/**
- * @file Character.hh
* Parent class of animate objects with "personalities."
*/
-
-class Character : public dc::resource, public dc::drawable
+class Character : public dc::drawable
{
public:
struct exception : public std::runtime_error
};
Character(const std::string& name);
+ ~Character();
void draw(dc::scalar alpha);
- dc::tilemap* texture;
- dc::animation* anim;
+ dc::tilemap& getTilemap();
+ dc::animation& getAnimation();
+
+private:
+ dc::tilemap texture;
+ dc::animation anim;
};
#endif // _CHARACTER_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
-noinst_LIBRARIES = libdc.a
+noinst_LTLIBRARIES = libdc.la
-libdc_a_SOURCES = \
+libdc_la_SOURCES = \
ConvertUTF.c \
ConvertUTF.h \
+ aabb.hh \
+ animation.cc \
+ animation.hh \
deserializer.cc \
deserializer.hh \
dispatcher.cc \
dispatcher.hh \
+ drawable.hh \
engine.cc \
engine.hh \
+ event.hh \
fastevents.c \
fastevents.h \
- math.cc \
+ interpolator.hh \
math.hh \
- matrix.hh \
+ mippleton.hh \
opengl.hh \
- quaternion.hh \
+ profiler.hh \
random.cc \
random.hh \
- rectangle.cc \
- rectangle.hh \
resource.cc \
resource.hh \
+ scene.cc \
+ scene.hh \
serializable.cc \
serializable.hh \
serializer.cc \
texture.cc \
texture.hh \
thread.hh \
+ tilemap.cc \
tilemap.hh \
timer.cc \
timer.hh \
- vector.hh \
video.cc \
video.hh \
$(ENDLIST)
-libdc_a_CPPFLAGS = -I/usr/include/SDL -I$(top_srcdir)/yajl/src -Wall
-#libdc_a_LDFLAGS = -lstdc++ -lSDL_image -lSDL_sound
-libdc_a_LIBADD = $(top_srcdir)/yajl/libyajl.a
+libdc_la_CPPFLAGS = -I/usr/include/SDL -I$(top_srcdir)/yajl/src
+libdc_la_LIBADD = $(top_srcdir)/yajl/libyajl.la
bin_PROGRAMS = yoink
yoink_SOURCES = \
+ Character.cc \
+ Character.hh \
+ TilemapFont.cc \
+ TilemapFont.hh \
+ Typesetter.cc \
+ Typesetter.hh \
YoinkApp.cc \
YoinkApp.hh \
$(ENDLIST)
-yoink_CPPFLAGS = -I/usr/include/SDL -Wall
-#yoink_LDFLAGS = -lstdc++ -lSDL_image -lSDL_sound
-yoink_LDADD = libdc.a libtinyxml.a ../yajl/libyajl.a
+yoink_CPPFLAGS = -I/usr/include/SDL
+yoink_LDADD = libdc.la
+
+
+EXTRA_DIST = cml
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#include "TilemapFont.hh"
+#include <iostream>
+
+
+TilemapFont::TilemapFont() :
+ dc::tilemap("Font")
+{}
+
+
+void TilemapFont::getTileCoords(char symbol, dc::scalar coords[8],
+ dc::tilemap::orientation what)
+{
+ unsigned index = 0;
+
+ if (symbol >= ' ' && symbol <= '_')
+ {
+ index = symbol - 32;
+ }
+ else if (symbol >= 'a' && symbol <= '~')
+ {
+ index = symbol - 64;
+ }
+ else
+ {
+ index = 0;
+ }
+
+ dc::tilemap::getTileCoords(index, coords, what);
+}
+
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#ifndef _TILEMAPFONT_HH_
+#define _TILEMAPFONT_HH_
+
+/**
+ * @file TilemapFont.hh
+ * Text on the screen.
+ */
+
+#include "tilemap.hh"
+
+
+class TilemapFont : public dc::tilemap
+{
+public:
+ struct exception : public std::runtime_error
+ {
+ explicit exception(const std::string& what_arg) :
+ std::runtime_error(what_arg) {}
+ };
+
+ TilemapFont();
+
+ void getTileCoords(char symbol, dc::scalar coords[8],
+ dc::tilemap::orientation what = dc::tilemap::normal);
+};
+
+
+#endif // _TILEMAPFONT_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#include <algorithm>
+#include <cstdio>
+#include <cstdarg>
+
+#include "Typesetter.hh"
+
+
+void Typesetter::print(const std::string& format, ...)
+{
+ va_list args;
+ char buffer[4096];
+ int nPrinted;
+
+ va_start(args, format);
+ buffer[0] = '\0';
+ nPrinted = vsnprintf(buffer, sizeof(buffer), format.c_str(), args);
+ va_end(args);
+
+ nPrinted = std::min(nPrinted, (int)sizeof(buffer) - 1);
+}
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#ifndef _TYPESETTER_HH_
+#define _TYPESETTER_HH_
+
+#include <string>
+
+#include "math.hh"
+
+
+class Typesetter
+{
+public:
+ Typesetter();
+
+ void setLineSpacing(dc::scalar spacing);
+
+ void print(const std::string& format, ...);
+
+private:
+ dc::scalar leftBound;
+ dc::scalar topBound;
+ dc::scalar lineSpacing;
+};
+
+
+#endif // _TYPESETTER_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#include <iostream>
#include <string>
+#include <cstdlib> // getenv
+
#include <boost/bind.hpp>
#include "opengl.hh"
#include "video.hh"
+#include "settings.hh"
-#include "vector.hh"
+#include "math.hh"
#include "YoinkApp.hh"
+#include "timer.hh"
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+static std::string configFiles()
+{
+ std::string files;
+
+ char* configFile = getenv("YOINK_CONFIGFILE");
+
+ if (configFile)
+ {
+ // if a config file from the environment variable is specified, we want
+ // to load it first
+ files += configFile;
+ files += ":";
+ }
+
+ files += YOINK_CONFIGFILES;
+
+ return files;
+}
+
-YoinkApp::YoinkApp(int argc, char* argv[])
- : dc::engine("Yoink "VERSION, argc, argv, "yoinkrc")
+YoinkApp::YoinkApp(int argc, char* argv[]) :
+ dc::engine(PACKAGE_STRING, argc, argv, configFiles())
{
- std::cout << "Yoink "VERSION << std::endl
+ std::cout << PACKAGE_STRING << std::endl
<< "Compiled " << __TIME__ " " __DATE__ << std::endl
- << "Send requests, patches, and bug reports to <" PACKAGE_BUGREPORT
- << ">." << std::endl << std::endl;
+ << "Send requests, patches, and bug reports to <"
+ PACKAGE_BUGREPORT << ">." << std::endl << std::endl;
+
+ dc::resource::addSearchPath(YOINK_DATADIR);
+
+ dc::dispatcher::instance().addHandler("video.context_recreated",
+ boost::bind(&YoinkApp::contextRecreated, this, _1), this);
+ setupGL();
state = 0.0;
- glEnable(GL_TEXTURE_2D);
+ someChar = new Character("RobotTrooper");
+ someChar->getAnimation().startSequence("Run");
- heroineTexture = new dc::texture("Heroine.png");
+ font = new TilemapFont;
- glShadeModel(GL_SMOOTH);
- //glEnable(GL_DEPTH_TEST);
-
- // Enable transparency:
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ dc::vector2 coeffs[4];
+ coeffs[0] = dc::vector2(0.0, 0.0);
+ coeffs[1] = dc::vector2(0.5, 0.0);
+ coeffs[2] = dc::vector2(0.5, 0.0);
+ coeffs[3] = dc::vector2(1.0, 0.0);
+ interp.init(coeffs, 1.0, dc::interpolator::oscillate);
- glLoadIdentity();
+ dc::scalar coeff[2] = {1.0, 0.0};
+ fadeIn.init(coeff, 0.5f);
+ testScene = new dc::scene("Test");
}
YoinkApp::~YoinkApp()
{
- delete heroineTexture;
+ delete someChar;
+ delete font;
+
+ dc::dispatcher::instance().removeHandler(this);
+
std::cout << "Goodbye..." << std::endl;
}
-void YoinkApp::update(double t, double dt)
+void YoinkApp::setupGL()
+{
+ glEnable(GL_TEXTURE_2D);
+ //glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glShadeModel(GL_SMOOTH);
+
+ //glEnable(GL_BLEND);
+ //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.0);
+
+ glClearColor(0.0, 0.0, 1.0, 1.0);
+
+ glLineWidth(10.0f);
+}
+
+void YoinkApp::contextRecreated(const dc::notification& note)
+{
+ // Whenever the context and a new one created, it probably won't contain our
+ // state so we need to set that up again.
+ setupGL();
+}
+
+
+void YoinkApp::update(dc::scalar t, dc::scalar dt)
{
- //dt *= 0.1;
+ //dt *= 0.2;
+
+ fadeIn.update(dt);
+
+ someChar->getAnimation().update(t, dt);
+ interp.update(dt);
prevstate = state;
state += dt;
}
-void drawrect(dc::scalar a, dc::scalar b, dc::scalar c, dc::scalar d)
+
+void YoinkApp::draw(dc::scalar alpha)
{
+ dc::vector4 meh;
+ meh.random(0.0, 1.0);
+ static dc::vector4 c1(meh);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ dc::scalar drawstate = cml::lerp(prevstate, state, alpha);
+ dc::scalar sinstate = std::sin(drawstate);
+ dc::scalar cosstate = std::cos(drawstate);
+
+
+ // DRAW THE SCENE
+ testScene->draw(alpha);
+
+
+ someChar->getTilemap().bind();
+ glColor3f(1.0, 1.0, 1.0);
+
+ unsigned heroFrame = someChar->getAnimation().getFrame();
+
+ float coords[8];
+ someChar->getTilemap().getTileCoords(heroFrame, coords);
+
glBegin(GL_QUADS);
- glTexCoord2f(1.0, 1.0);
- glVertex3d(a, d, 0.0);
- glTexCoord2f(1.0, 0.0);
- glVertex3d(a, b, 0.0);
- glTexCoord2f(0.0, 0.0);
- glVertex3d(c, b, 0.0);
- glTexCoord2f(0.0, 1.0);
- glVertex3d(c, d, 0.0);
+ glTexCoord2f(coords[0], coords[1]);
+ glVertex3f(-1.0, 0.0, 0.0);
+ glTexCoord2f(coords[2], coords[3]);
+ glVertex3f(0.0, 0.0, 0.0);
+ glTexCoord2f(coords[4], coords[5]);
+ glVertex3f(0.0, 1.0, 0.0);
+ glTexCoord2f(coords[6], coords[7]);
+ glVertex3f(-1.0, 1.0, 0.0);
glEnd();
-}
-void YoinkApp::draw(double alpha)
-{
- static dc::vector3 c1 = dc::vector3::random(0.0, 1.0);
- static dc::vector3 c2 = dc::vector3::random(0.0, 1.0);
- glClearColor(1.0, 0.0, 0.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+ someChar->getTilemap().getTileCoords(heroFrame, coords,
+ dc::tilemap::reverse);
- double drawstate = state * alpha + prevstate * (1.0 - alpha);
- double sinstate = std::sin(drawstate);
- double cosstate = std::cos(drawstate);
+ glBegin(GL_QUADS);
+ glTexCoord2f(coords[0], coords[1]);
+ glVertex3f(0.0, 0.0, 0.0);
+ glTexCoord2f(coords[2], coords[3]);
+ glVertex3f(1.0, 0.0, 0.0);
+ glTexCoord2f(coords[4], coords[5]);
+ glVertex3f(1.0, 1.0, 0.0);
+ glTexCoord2f(coords[6], coords[7]);
+ glVertex3f(0.0, 1.0, 0.0);
+ glEnd();
+
+ glColor4f(1.0,0.0,0.0,0.5);
glBindTexture(GL_TEXTURE_2D, 0);
+ glColor4fv(c1.data());
- glColor3dv(c1.array);
- drawrect(-cosstate, -sinstate, sinstate, cosstate);
- glColor3dv(c2.array);
- drawrect(0.0, 0.0, sinstate, cosstate);
+ glRectd(-cosstate, -sinstate, sinstate, cosstate);
+ glRectf(0.0f, 0.0f, sinstate, cosstate);
- glColor4f(1.0, 1.0, 1.0, 1.0);
+ font->bind();
+
+ font->getTileCoords('c', coords);
- heroineTexture->bind();
+ glBegin(GL_QUADS);
+ glTexCoord2f(coords[0], coords[1]);
+ glVertex3f(-1.0, 0.0, 0.0);
+ glTexCoord2f(coords[2], coords[3]);
+ glVertex3f(0.0, 0.0, 0.0);
+ glTexCoord2f(coords[4], coords[5]);
+ glVertex3f(0.0, 1.0, 0.0);
+ glTexCoord2f(coords[6], coords[7]);
+ glVertex3f(-1.0, 1.0, 0.0);
+ glEnd();
+
+ font->getTileCoords('h', coords);
glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0);
+ glTexCoord2f(coords[0], coords[1]);
glVertex3f(0.0, 0.0, 0.0);
- glTexCoord2f(1.0/8.0, 0.0);
+ glTexCoord2f(coords[2], coords[3]);
glVertex3f(1.0, 0.0, 0.0);
- glTexCoord2f(1.0/8.0, 1.0/4.0);
+ glTexCoord2f(coords[4], coords[5]);
glVertex3f(1.0, 1.0, 0.0);
- glTexCoord2f(0.0, 1.0/4.0);
+ glTexCoord2f(coords[6], coords[7]);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
+
+ font->getTileCoords('a', coords);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(coords[0], coords[1]);
+ glVertex3f(-1.0, -1.0, 0.0);
+ glTexCoord2f(coords[2], coords[3]);
+ glVertex3f(0.0, -1.0, 0.0);
+ glTexCoord2f(coords[4], coords[5]);
+ glVertex3f(0.0, 0.0, 0.0);
+ glTexCoord2f(coords[6], coords[7]);
+ glVertex3f(-1.0, 0.0, 0.0);
+ glEnd();
+
+ font->getTileCoords('z', coords);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(coords[0], coords[1]);
+ glVertex3f(0.0, -1.0, 0.0);
+ glTexCoord2f(coords[2], coords[3]);
+ glVertex3f(1.0, -1.0, 0.0);
+ glTexCoord2f(coords[4], coords[5]);
+ glVertex3f(1.0, 0.0, 0.0);
+ glTexCoord2f(coords[6], coords[7]);
+ glVertex3f(0.0, 0.0, 0.0);
+ glEnd();
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_DEPTH_TEST);
- glFlush();
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+
+ glBegin(GL_LINES);
+ glVertex2f(0.0f, 0.0f);
+ glVertex2fv(interp.getState(alpha).data());
+ glEnd();
+
+ glColor4f(0.0f, 0.0f, 0.0f, fadeIn.getState(alpha));
+ glRectf(-1.0f, -1.0f, 1.0f, 1.0f);
+
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
}
-void YoinkApp::dispatchEvent(const SDL_Event& event)
+void YoinkApp::handleEvent(const dc::event& e)
{
- switch (event.type)
+ switch (e.type)
{
case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_ESCAPE)
+ if (e.key.keysym.sym == SDLK_ESCAPE)
{
stop();
}
- else if (event.key.keysym.sym == SDLK_f)
+ else if (e.key.keysym.sym == SDLK_f)
{
getVideo().toggleFull();
}
+ else if (e.key.keysym.sym == SDLK_a)
+ {
+ someChar->getAnimation().startSequence("Punch");
+ }
break;
case SDL_QUIT:
stop();
break;
- }
-}
-
-#include "dispatcher.hh"
-
-class Foo : public dc::notification
-{
-public:
- static void func(const dc::notification& meh)
- {
- std::cout << "func: " << std::endl;
- }
-
- void snap(int zzz, const dc::notification& nice, float lean)
- {
- std::cout << "snap: " << zzz << "," << lean << std::endl;
+ case SDL_VIDEORESIZE:
+ glViewport(0, 0, e.resize.w, e.resize.h);
+ break;
}
-};
-
-void MyHandler(const dc::notification& cool)
-{
- std::cout << "MyHandler with a notification" << std::endl;
}
+
int main(int argc, char* argv[])
{
YoinkApp app(argc, argv);
return app.run();
}
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#ifndef _YOINKAPP_HH_
#define _YOINKAPP_HH_
+/**
+ * @file YoinkApp.hh
+ * This is the big enchilada.
+ */
+
#include <iostream>
#include <string>
+#include "dispatcher.hh"
+#include "math.hh"
+#include "interpolator.hh"
#include "engine.hh"
-#include "texture.hh"
+#include "Character.hh"
+
+#include "TilemapFont.hh"
+
+#include "scene.hh"
class YoinkApp : public dc::engine
~YoinkApp();
private:
- void update(double t, double dt);
- void draw(double alpha);
- void dispatchEvent(const SDL_Event& event);
+ void update(dc::scalar t, dc::scalar dt);
+ void draw(dc::scalar alpha);
+ void handleEvent(const dc::event& e);
+
+ /**
+ * Set OpenGL to a state we can know and depend on.
+ */
+ void setupGL();
+ void contextRecreated(const dc::notification& note);
- dc::texture* heroineTexture;
+ //dc::animation* heroAnimation;
+ //dc::tilemap* heroineTexture;
+ Character* someChar;
+ //dc::binomial_interpolator<dc::vector2,2> interp;
+ dc::cerpv2 interp;
+ dc::lerps fadeIn;
- double state;
- double prevstate;
+ dc::scene* testScene;
+
+ TilemapFont *font;
+
+ dc::scalar state;
+ dc::scalar prevstate;
};
#endif // _YOINKAPP_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+******************************************************************************/
+
+#ifndef _AABB_HH_
+#define _AABB_HH_
+
+#include "math.hh"
+
+
+namespace dc {
+
+
+/**
+ * Axis-aligned Bounding Box
+ */
+
+struct aabb
+{
+ aabb() {}
+
+ aabb(const vector3& minPoint, const vector3& maxPoint) :
+ min(minPoint),
+ max(maxPoint) {}
+
+ aabb (scalar minX, scalar minY, scalar minZ,
+ scalar maxX, scalar maxY, scalar maxZ) :
+ min(minX, minY, minZ),
+ max(maxX, maxY, maxZ) {}
+
+ vector3 min;
+ vector3 max;
+};
+
+
+} // namespace dc
+
+#endif // _AABB_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
*******************************************************************************/
+#include <map>
+#include <vector>
+
+#include "serializable.hh"
+#include "mippleton.hh"
#include "animation.hh"
namespace dc {
-class animation_impl
+/**
+ * The collection of nested animation classes. The animation implementation
+ * consists of an animation_impl classes which is allocated and initialized with
+ * the interface object. This class contains the specific fields which are
+ * required to run a single instance of an animation. The sequence data is
+ * loaded in a difference class which can be shared amongst multiple animation
+ * implementation instances.
+ */
+
+struct animation::animation_impl
{
-public:
- class sequence
+ /**
+ * Contains "global" animation data for the various animations which get
+ * loaded. This is a mippleton, so it will be shared amongst any animation
+ * which wants to use these loaded sequences.
+ */
+
+ struct animation_data : public mippleton<animation_data>
{
+ /**
+ * A frame of an animation sequence. A frame is merely an index which
+ * presumably represents a "slide" or tile which should be displayed,
+ * and the duration that is how long the slide will be shown.
+ */
+
+ struct frame
+ {
+ unsigned index; ///< Frame index.
+ scalar duration; ///< Frame duration.
+
+ /**
+ * Construction is initialization. The frame data is loaded from a
+ * frame map which is probably loaded within an animation file.
+ */
+
+ frame(serializable_ptr root) :
+ index(0),
+ duration(1.0)
+ {
+ std::map<std::string,serializable_ptr> rootObj;
+
+ if (root->get(rootObj))
+ {
+ std::map<std::string,serializable_ptr>::iterator i;
+ for (i = rootObj.begin(); i != rootObj.end(); i++)
+ {
+ std::string key = (*i).first;
+ if (key == "index")
+ {
+ long value = 0;
+ (*i).second->get(value);
+ index = unsigned(value);
+ }
+ else if (key == "duration")
+ {
+ double value = 0.0;
+ (*i).second->getNumber(value);
+ duration = scalar(value);
+ }
+ }
+ }
+ }
+ };
+
+
+ /**
+ * A sequence is just a few attributes and a list of frames in the order
+ * that they should be played.
+ */
+
+ struct sequence
+ {
+ std::vector<frame> frames; ///< List of frames.
+ scalar delay; ///< Scale frame durations.
+ bool loop; ///< Does the sequence repeat?
+ std::string next; ///< Next sequence name.
+
+ /**
+ * Construction is initialization. The constructor loads sequence
+ * data from the sequence map, presumably loaded from an animation
+ * file. The rest of the loading takes place in the frame's
+ * constructor which loads each individual frame.
+ */
+
+ sequence(serializable_ptr root) :
+ delay(0.0),
+ loop(true)
+ {
+ std::map<std::string,serializable_ptr> rootObj;
+
+ if (root->get(rootObj))
+ {
+ std::map<std::string,serializable_ptr>::iterator i;
+ for (i = rootObj.begin(); i != rootObj.end(); i++)
+ {
+ std::string key = (*i).first;
+
+ if (key == "frames")
+ {
+ std::vector<serializable_ptr> framesObj;
+
+ if ((*i).second->get(framesObj))
+ {
+ std::vector<serializable_ptr>::iterator j;
+
+ for (j = framesObj.begin();
+ j != framesObj.end(); j++)
+ {
+ if (*j)
+ {
+ frames.push_back(frame(*j));
+ }
+ }
+ }
+ }
+ else if (key == "delay")
+ {
+ double value;
+ (*i).second->getNumber(value);
+ delay = scalar(value);
+ }
+ else if (key == "loop")
+ {
+ (*i).second->get(loop);
+ }
+ else if (key == "next")
+ {
+ (*i).second->get(next);
+ }
+ }
+ }
+ }
+ };
+
+
+ /**
+ * Starts loading a file with animation data. Such a file is formatted
+ * as a map of named sequences. The sequence constructor loads each
+ * individual sequence.
+ */
+
+ void loadFromFile()
+ {
+ std::string filePath = animation::getPathToResource(getName());
+
+ deserializer in(filePath);
+
+ serializable_ptr root = in.deserialize();
+
+ if (root)
+ {
+ std::map<std::string,serializable_ptr> rootObj;
+
+ if (root->get(rootObj))
+ {
+ std::map<std::string,serializable_ptr>::iterator i;
+
+ for (i = rootObj.begin(); i != rootObj.end(); i++)
+ {
+ sequences.insert(std::pair<std::string,sequence>((*i).first,
+ sequence((*i).second)));
+ }
+ }
+ }
+ }
+
+ /**
+ * Construction is initialization. The animation class data container
+ * registers itself as a mippleton and then loads the animation data.
+ */
+
+ explicit animation_data(const std::string& name) :
+ mippleton<animation_data>(name)
+ {
+ loadFromFile();
+ }
+
+ std::map<std::string,sequence> sequences; ///< List of sequences.
};
- std::map<std::string,sequence> sequences;
+
+ /**
+ * Construction is intialization.
+ */
+
+ animation_impl(const std::string& name) :
+ data(animation_data::retain(name), &animation_data::release),
+ currentSequence(0),
+ frameCounter(0),
+ frameIndex(0),
+ timeAccum(0),
+ frameDuration(0) {}
+
+
+ /**
+ * Sets up the animation classes to "play" a named sequence. If another
+ * sequence was active, it will be replaced as the current sequence. Future
+ * updates will progress the new sequence.
+ */
+
+ void startSequence(const std::string& sequenceName)
+ {
+ std::map<std::string,animation_data::sequence>::iterator i;
+
+ i = data->sequences.find(sequenceName);
+
+ if (i != data->sequences.end())
+ {
+ currentSequence = &(*i).second;
+ frameCounter = 0;
+ frameIndex = currentSequence->frames[0].index;
+ timeAccum = 0.0;
+ frameDuration = currentSequence->delay *
+ currentSequence->frames[0].duration;
+ }
+ }
+
+ /**
+ * Updates or progresses the animation sequence. If the time interval
+ * surpasses the duration of the current frame, a new frame becomes the
+ * current frame. If the last frame of a sequence expires, the active
+ * sequence will switch automatically to the designated "next" sequence, or
+ * if none is specified but the sequence is set to loop, the first frame of
+ * the sequence will become the current frame, and the animation essentially
+ * starts over again.
+ */
+
+ void update(scalar t, scalar dt)
+ {
+ if (currentSequence)
+ {
+ timeAccum += dt;
+
+ if (timeAccum >= frameDuration)
+ {
+ if (++frameCounter >= currentSequence->frames.size())
+ {
+ if (!currentSequence->next.empty())
+ {
+ startSequence(currentSequence->next);
+ }
+ else if (currentSequence->loop)
+ {
+ frameCounter = 0;
+ }
+ else
+ {
+ frameCounter--;
+ currentSequence = 0;
+ }
+ }
+
+ frameIndex = currentSequence->frames[frameCounter].index;
+ timeAccum = frameDuration - timeAccum;
+ frameDuration = currentSequence->delay *
+ currentSequence->frames[frameCounter].duration;
+ }
+ }
+ }
+
+ boost::shared_ptr<animation_data> data; ///< Internal data.
+
+ animation_data::sequence* currentSequence; ///< Active sequence.
+ unsigned frameCounter; ///< Current frame.
+ unsigned frameIndex; ///< Index of current frame.
+ scalar timeAccum; ///< Time accumulation.
+ scalar frameDuration; ///< Scaled frame duration.
};
+animation::animation(const std::string& name) :
+ // pass through
+ impl(new animation::animation_impl(name)) {}
+
+
+void animation::startSequence(const std::string& sequenceName)
+{
+ // pass through
+ impl->startSequence(sequenceName);
+}
+
+void animation::update(scalar t, scalar dt)
+{
+ // pass through
+ impl->update(t, dt);
+}
+
+
+/**
+ * Gets the index for the current frame. This is presumably called by some
+ * drawing code which will draw the correct current frame.
+ */
+
+unsigned animation::getFrame() const
+{
+ return impl->frameIndex;
+}
+
+
+/**
+ * Specialized search location for animation files. They can be found in the
+ * "animations" subdirectory of any of the searched directories.
+ */
+
+std::string animation::getPathToResource(const std::string& name)
+{
+ return resource::getPathToResource("animations/" + name + ".json");
+}
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
* Motion picture!!
*/
+#include <string>
+
#include <boost/shared_ptr.hpp>
+#include "resource.hh"
+#include "math.hh"
+
namespace dc {
-class animation_impl;
+/**
+ * A class to manage frame-based animation. Animation sequences can be loaded
+ * from file, then named sequences are started. The animation is updated
+ * periodically (each update cycle), and the correct current frame is
+ * determined. This class is generic enough that a frame can mean just about
+ * anything to whatever drawing context is used to render the frame.
+ */
class animation : public resource
{
public:
animation(const std::string& name);
- void setSequence(const std::string& sequence);
- bool isSequenceDone();
+ void startSequence(const std::string& sequenceName);
+
+ void update(scalar t, scalar dt);
+ unsigned getFrame() const;
- void update(scalar dt);
- unsigned getFrame();
+ static std::string getPathToResource(const std::string& name);
private:
+ class animation_impl;
boost::shared_ptr<animation_impl> impl;
};
#endif // _ANIMATION_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#ifndef _CAMERA_HH_
+#define _CAMERA_HH_
+
+
+namespace dc {
+
+
+class camera
+{
+public:
+private:
+};
+
+
+} // namespace dc
+
+#endif // _CAMERA_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
*******************************************************************************/
-#include <algorithm>
+#ifndef _CULLABLE_HH_
+#define _CULLABLE_HH_
-#include "rectangle.hh"
+#include "camera.hh"
namespace dc {
-bool rectangle::containsRect(const rectangle& r) const
-{
- point o = r.origin;
- point s = r.size;
- if (origin.x <= o.x && origin.y <= o.y)
- {
- scalar a = origin.x + size.x;
- scalar b = origin.y + size.y;
- scalar c = o.x + s.x;
- scalar d = o.y + s.y;
- return o.x <= a && o.y <= b && origin.x <= c &&
- origin.y <= d && c <= a && d <= b;
- }
- return false;
-}
+/**
+ * Interface for anything that can be culled given a camera's frustrum.
+ */
-bool rectangle::intersectsRect(const rectangle& r) const
+class cullable
{
- // TODO - Perhaps this could be optimized if it proves to be a bottleneck.
- rectangle rect = intersectionWith(r);
- return rect.isValid();
-}
+public:
+ virtual bool isVisible(const camera& cam) = 0;
+};
-rectangle rectangle::unionWith(const rectangle& r) const
-{
- point o = r.origin;
- point s = r.size;
- scalar a = std::min(origin.x, o.x);
- scalar b = std::min(origin.y, o.y);
- return rectangle(point(a, b),
- point(std::max(origin.x + size.x, o.x + s.x) - a,
- std::max(origin.y + size.y, o.y + s.y) - b));
-}
-rectangle rectangle::intersectionWith(const rectangle& r) const
-{
- point o = r.origin;
- point s = r.size;
- scalar a = std::max(origin.x, o.x);
- scalar b = std::max(origin.y, o.y);
- return rectangle(point(a, b),
- point(std::min(origin.x + size.x, o.x + s.x) - a,
- std::min(origin.y + size.y, o.y + s.y) - b));
-}
+} // namespace dc
+#endif // _CULLABLE_HH_
-} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
namespace dc {
-class deserializer_impl
+class deserializer::deserializer_impl
{
public:
deserializer_impl(const std::string& filePath, bool comments = false,
void throwError()
{
unsigned char* errorMsg = yajl_get_error(hand, 0, 0, 0);
- deserializer::exception error((char*)errorMsg);
+ deserializer::exception problem((char*)errorMsg);
yajl_free_error(hand, errorMsg);
- throw error;
+ throw problem;
}
static int parsedBeginMap(void* ctx)
{
((deserializer_impl*)ctx)->parsed.push(new wrapped_dictionary);
+ return 1;
}
static int parsedMapKey(void* ctx, const unsigned char* value,
deserializer::deserializer(const std::string& filePath, bool comments,
- bool check) : impl(new deserializer_impl(filePath, comments, check)) {}
+ bool check) :
+ // pass through
+ impl(new deserializer::deserializer_impl(filePath, comments, check)) {}
deserializer::deserializer(std::istream& input, bool comments, bool check) :
- impl(new deserializer_impl(input, comments, check)) {}
+ // pass through
+ impl(new deserializer::deserializer_impl(input, comments, check)) {}
serializable_ptr deserializer::deserialize()
void deserializer::pop()
{
+ // pass through
impl->parsed.pop();
}
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
namespace dc {
-class serializable;
+class serializable; // forward declaration
typedef boost::shared_ptr<serializable> serializable_ptr;
-class deserializer_impl;
-
class deserializer
{
public:
+
+ /**
+ * Construction is initialization. A deserializer can be constructed with
+ * either an input stream or a string representing a filename that will be
+ * read from. If a stream is provided, it will not be closed after parsing,
+ * but the parser may read past the end of usable bytes, so you should not
+ * use a deserializer on a stream that you expect to continue to use after
+ * the deserialization.
+ * @param comments If true, C and C++-style comments will be allowed and
+ * ignored by the parser.
+ * @param check If true, UTF-8 strings will be checked for validity and an
+ * exception thrown if such a problem exists. Otherwise strings will not be
+ * checked.
+ */
+
deserializer(const std::string& filePath, bool comments = false,
bool check = false);
deserializer(std::istream& input, bool comments = false, bool check = false);
+
+ /**
+ * Parse the object from of the stream. The stream is considered to be
+ * dominated by the parser and may read and discard bytes past the end of
+ * the actual parsed object. Only one object can be deserialized by the
+ * deserializer.
+ */
+
serializable_ptr deserialize();
+ /**
+ * Used by serializable objects to parse themselves. These methods should
+ * generally not be used directory for deserialization. This one returns
+ * the next object in the queue which has been parsed. This method may
+ * block if more data is pending and an object has not bee constructed yet.
+ * The caller takes ownership of the object which has been allocated with
+ * the new operator and must therefore be sure to delete the object as
+ * appropriated. Null (0) will be returned by this method to signify one of
+ * three things: 1) the end of an array, 2) the end of a map/dictionary, or
+ * 3) there is nothing more to be obtained. Container objects will be empty
+ * and will have to be filled with their contained elements by repeatedly
+ * calling this method until a null is returned. This method will continue
+ * to return the same value until pop() is called which will cause this
+ * method to return the next object as expected.
+ */
+
serializable* pullNext();
+
+ /**
+ * If the object returned by pullNext() has been received successfully and
+ * the caller is ready for the next object, this method should be called to
+ * take that object off of the queue.
+ */
+
void pop();
+
+ /**
+ * This exception is thrown upon deserialization errors.
+ */
+
struct exception : std::runtime_error
{
explicit exception(const std::string& what_arg) :
};
private:
+ class deserializer_impl;
boost::shared_ptr<deserializer_impl> impl;
};
#endif // _DESERIALIZER_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
notification::~notification() {}
-class dispatcher_impl
+class dispatcher::dispatcher_impl
{
public:
dispatcher_impl() : id(1) {}
};
-dispatcher::dispatcher() : impl(new dispatcher_impl) {}
+dispatcher::dispatcher() : impl(new dispatcher::dispatcher_impl) {}
+// TODO these methods are ugly
+
dispatcher::handler dispatcher::addHandler(const std::string& message,
const function& callback)
{
dispatcher::handler dispatcher::addHandler(const std::string& message,
const function& callback, handler id)
{
- std::pair<std::string,dispatcher_impl::callback_t>
- callbackPair(message, dispatcher_impl::callback_t(id, callback));
+ std::pair<std::string,dispatcher::dispatcher_impl::callback_t>
+ callbackPair(message, dispatcher::dispatcher_impl::callback_t(id, callback));
std::pair<handler,std::string> handlerPair(id, message);
void dispatcher::removeHandler(handler id)
{
- std::pair<dispatcher_impl::handler_it_t,dispatcher_impl::handler_it_t>
+ std::pair<dispatcher::dispatcher_impl::handler_it_t,dispatcher::dispatcher_impl::handler_it_t>
handlers(impl->handlers.equal_range(id));
- dispatcher_impl::handler_it_t i;
+ dispatcher::dispatcher_impl::handler_it_t i;
for (i = handlers.first; i != handlers.second; i++)
{
- dispatcher_impl::callback_it_t it = impl->callbacks.find((*i).second);
- dispatcher_impl::callback_it_t last = impl->callbacks.end();
+ dispatcher::dispatcher_impl::callback_it_t it = impl->callbacks.find((*i).second);
+ dispatcher::dispatcher_impl::callback_it_t last = impl->callbacks.end();
- dispatcher_impl::callback_it_t j;
+ dispatcher::dispatcher_impl::callback_it_t j;
for (j = it; j != last; j++)
{
if (((*j).second).first == id)
void dispatcher::dispatch(const std::string& message, const notification& param)
{
- std::pair<dispatcher_impl::callback_it_t,dispatcher_impl::callback_it_t>
+ std::pair<dispatcher::dispatcher_impl::callback_it_t,dispatcher::dispatcher_impl::callback_it_t>
callbacks(impl->callbacks.equal_range(message));
- dispatcher_impl::callback_it_t i;
+ dispatcher::dispatcher_impl::callback_it_t i;
for (i = callbacks.first; i != callbacks.second; i++)
{
function callback = ((*i).second).second;
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#ifndef _DISPATCHER_HH_
#define _DISPATCHER_HH_
-/**
- * @file dispatcher.hh
- * Dispatching of information.
- */
-
#include <string>
#include <boost/shared_ptr.hpp>
namespace dc {
-// Subclass this to create more specific notes to dispatch.
+/**
+ * Interface for a notification class.
+ */
+
class notification
{
public:
};
-class dispatcher_impl;
+/**
+ * Dispatcher of notifications to interested parties.
+ */
class dispatcher : public singleton<dispatcher>
{
void dispatch(const std::string& message, const notification& param);
private:
+ class dispatcher_impl;
boost::shared_ptr<dispatcher_impl> impl;
};
#endif // _DISPATCHER_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#ifndef _DRAWABLE_HH_
#define _DRAWABLE_HH_
-/**
- * @file drawable.hh
- * Interface for a drawable object.
- */
+#include "math.hh"
namespace dc {
+/**
+ * Interface for anything that can be drawn.
+ */
+
class drawable
{
public:
#endif // _DRAWABLE_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
namespace dc {
-class engine_impl
+class engine::engine_impl
{
public:
engine_impl(const std::string& name, int argc, char* argv[],
- const std::string& configFile, engine* outer) : config(argc, argv),
- interface(outer)
+ const std::string& configFile, engine* outer) :
+ config(argc, argv),
+ interface(outer)
{
if (SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) != 0)
{
screen = video_ptr(new video(name));
screen->makeActive();
- timestep = 0.01;
- config.get("engine.timestep", timestep);
+ double ts = 0.01;
+ config.get("engine.timestep", ts);
+ timestep = scalar(ts);
long maxfps = 40;
config.get("engine.maxfps", maxfps);
scalar nextFPSUpdate = ticksNow + 1.0;
scalar totalTime = 0.0;
- scalar accumulator = 0.0;
+ scalar accumulator = timestep;
- fps = 0.0;
- int frameAccum = 0.0;
+ fps = 0;
+ int frameAccum = 0;
running = true;
do
accumulator += newTicks - ticksNow;
ticksNow = newTicks;
- if (ticksNow >= nextStep)
+ if (accumulator >= timestep)
{
interface->update(totalTime, timestep);
accumulator -= timestep;
nextStep += timestep;
- if (ticksNow >= nextStep) nextStep = ticksNow + timestep;
+ if (ticksNow >= nextStep)
+ {
+ // we missed some scheduled steps, so reset the schedule
+ nextStep = ticksNow + timestep;
+ accumulator = 0.0;
+ }
}
if (ticksNow >= nextDraw)
{
frameAccum++;
- if (ticksNow >= nextFPSUpdate)
+ if (ticksNow >= nextFPSUpdate) // determine the actual fps
{
- fps = frameAccum;// + (ticksNow - nextFPSUpdate) / 1.0;
+ fps = frameAccum;
frameAccum = 0;
nextFPSUpdate += 1.0;
- if (ticksNow >= nextFPSUpdate) nextFPSUpdate = ticksNow + 1.0;
+ if (ticksNow >= nextFPSUpdate)
+ {
+ nextFPSUpdate = ticksNow + 1.0;
+ }
if (printfps)
{
screen->swap();
nextDraw += drawrate;
- if (ticksNow >= nextDraw) nextDraw = ticksNow + drawrate;
+ if (ticksNow >= nextDraw)
+ {
+ // we missed some scheduled draws, so reset the schedule
+ nextDraw = ticksNow + drawrate;
+ }
}
+ // be a good citizen and give back what you don't need
sleep(std::min(nextStep, nextDraw), true);
}
while (running);
+
+ return 0;
}
void dispatchEvents()
{
- SDL_Event event;
+ SDL_Event e;
- while (FE_PollEvent(&event) == 1)
+ while (FE_PollEvent(&e) == 1)
{
- switch (event.type)
+ switch (e.type)
{
case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_ESCAPE &&
+ if (e.key.keysym.sym == SDLK_ESCAPE &&
(SDL_GetModState() & KMOD_CTRL) )
{
exit(0);
break;
case SDL_VIDEORESIZE:
- screen->resize(event.resize.w, event.resize.h);
+ screen->resize(e.resize.w, e.resize.h);
break;
}
- interface->dispatchEvent(event);
+ interface->handleEvent(e);
}
}
engine* interface;
};
+
engine::engine(const std::string& name, int argc, char* argv[],
- const std::string& configFile)
- : impl(new engine_impl(name, argc, argv, configFile, this)) {}
+ const std::string& configFile) :
+ impl(new engine::engine_impl(name, argc, argv, configFile, this)) {}
engine::~engine() {}
int engine::run()
{
- impl->run();
+ return impl->run();
}
void engine::stop()
void engine::update(scalar t, scalar dt) {}
void engine::draw(scalar alpha) {}
-void engine::dispatchEvent(const SDL_Event& event) {}
+void engine::handleEvent(const SDL_Event& e) {}
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#define _ENGINE_HH_
#include <boost/shared_ptr.hpp>
-#include <SDL/SDL.h>
#include "singleton.hh"
+#include "event.hh"
#include "dispatcher.hh"
namespace dc {
-class engine_impl;
class video;
class engine : public singleton<engine>
// Override these if you want.
virtual void update(scalar t, scalar dt);
virtual void draw(scalar alpha);
- virtual void dispatchEvent(const SDL_Event& event);
+ virtual void handleEvent(const event& e);
private:
+ class engine_impl;
boost::shared_ptr<engine_impl> impl;
};
#endif // _ENGINE_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#ifndef _EVENT_HH_
#define _EVENT_HH_
-
-#include "bz/date.h"
-#include "bz/object.h"
-
-
-namespace bz {
+#include <SDL/SDL.h>
-class event
-{
-public:
- typedef enum
- {
- left_click_down = 1<<1,
- left_click_up = 1<<2,
- right_click_down = 1<<3,
- right_click_up = 1<<4,
- other_click_down = 1<<5,
- other_click_up = 1<<6,
- mouse_moved = 1<<7,
- mouse_entered = 1<<8,
- mouse_exited = 1<<9,
- key_down = 1<<10,
- key_up = 1<<11,
- activated = 1<<12,
- iconified = 1<<13,
- deactivated = 1<<14,
-
- file_new = 1<<20,
- file_open = 1<<21,
- file_revert = 1<<22,
- file_save = 1<<23,
- file_save_as = 1<<24,
- edit_undo = 1<<25,
- edit_redo = 1<<26,
- edit_copy = 1<<27,
- edit_cut = 1<<28,
- edit_paste = 1<<29,
- edit_select_all = 1<<30,
- app_quit = 1<<31,
- any = 0xffffffffU
- } type;
-
- // This constructor is for keyboard events:
- event( type theType, // What happened?
- unsigned char keycode, // The ASCII value.
- int modifiers, // Ctrl, Shift, Opt, etc...
- bool isRepeat ) : // Is the key held down?
- type_(theType), keycode_(keycode), modifiers_(modifiers),
- isRepeat_(isRepeat)
- {
- timestamp_ = date();
- id_ = getIdentifier();
- }
-
- // This constructor is for mouse events:
- event( type theType, // What happened?
- vec2d location, // Where? (window coordinates)
- vec2d delta, // How far has it moved?
- int nClick, // How many consecutive clicks?
- float pressure ) : // How hard was it pushed?
- type_(theType), location_(location), delta_(delta), nClick_(nClick),
- pressure_(pressure)
- {
- timestamp_ = date();
- id_ = getIdentifier();
- }
- // This constructor is for other event types:
- event( type theType ) : type_(theType) // What happened?
- {
- timestamp_ = date();
- id_ = getIdentifier();
- }
+namespace dc {
- // Accessors for all event types:
- type kind() const { return type_; }
- const date& timestamp() const { return timestamp_; }
- unsigned int identifier() const { return id_; }
- void *userInfo() const { return userInfo_; }
- void setUserInfo( void* userInfo ) { userInfo_ = userInfo; }
- unsigned int tag() const { return tag_; }
- void setTag( unsigned int tag ) { tag_ = tag; }
+// The event handling in SDL is so big that it would take more time than it's
+// worth to add an object-oriented abstraction layer that would completely cover
+// what SDL has already layed down. Fortunately, SDL event structures are easy
+// to work with, and it is not the purpose of this library to completely hide
+// its dependencies and provide full functionality.
- // Accessors for keyboard events:
- unsigned char keycode() const { return keycode_; }
- int modifiers() const { return modifiers_; }
- bool isRepeat() const { return isRepeat_; }
+typedef SDL_Event event;
- // Accessors for mouse events:
- const vec2d& location() const { return location_; }
- const vec2d& delta() const { return delta_; }
- int clicks() const { return nClick_; }
- float pressure() const { return pressure_; }
-private:
- unsigned int getIdentifier() {
- static unsigned int identifier = 1;
- return identifier++;
- }
-
- type type_;
- date timestamp_;
- unsigned int id_;
- void *userInfo_;
- unsigned int tag_;
-
- unsigned char keycode_;
- unsigned char modifiers_;
- bool isRepeat_;
-
- vec2d location_;
- vec2d delta_;
- int nClick_;
- float pressure_;
-};
-
} // namespace dc
#endif // _EVENT_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#ifndef _INTERPOLATOR_HH_
+#define _INTERPOLATOR_HH_
+
+
+namespace dc {
+
+
+class interpolator
+{
+ void clamp(scalar& value)
+ {
+ if (value > 1.0)
+ {
+ switch (theMode)
+ {
+ case stop:
+ value = 1.0;
+ stopped = true;
+ break;
+ case repeat:
+ value -= 1.0;
+ break;
+ case oscillate:
+ value = 2.0 - value;
+ scale *= -1.0;
+ break;
+ }
+ }
+ else if (value < 0.0)
+ {
+ switch (theMode)
+ {
+ case stop:
+ value = 0.0;
+ stopped = true;
+ break;
+ case repeat:
+ value += 1.0;
+ break;
+ case oscillate:
+ value = -value;
+ scale *= -1.0;
+ break;
+ }
+ }
+ }
+
+public:
+ typedef enum
+ {
+ stop = 0,
+ repeat = 1,
+ oscillate = 2
+ } mode;
+
+ void init(scalar seconds = 1.0, mode onFinish = stop)
+ {
+ scale = 1.0 / seconds;
+ alpha = 0.0;
+ setMode(onFinish);
+ }
+
+
+ void setMode(mode onFinish)
+ {
+ theMode = onFinish;
+ stopped = false;
+ }
+
+
+ void update(scalar dt)
+ {
+ if (!stopped)
+ {
+ alpha += dt * scale;
+ clamp(alpha);
+ calculate(alpha);
+ }
+ }
+
+ virtual void calculate(scalar alpha) = 0;
+
+private:
+ mode theMode;
+ scalar alpha;
+ scalar scale;
+ bool stopped;
+};
+
+template <class T>
+class interpolator_base : public interpolator
+{
+public:
+ void init(scalar seconds = 1.0, mode onFinish = stop)
+ {
+ interpolator::init(seconds, onFinish);
+
+ calculate(0.0); // set value
+ calculate(0.0); // set previous
+ }
+
+ void calculate(scalar alpha)
+ {
+ previous = value;
+ calculate(value, alpha);
+ }
+
+ virtual void calculate(T& value, scalar alpha) = 0;
+
+ const T& getValue()
+ {
+ return value;
+ }
+
+ const T getState(scalar alpha)
+ {
+ return cml::lerp(previous, value, alpha);
+ }
+
+private:
+ T value;
+ T previous;
+};
+
+
+template <class T, int D>
+class binomial_interpolator : public interpolator_base<T>
+{
+public:
+ binomial_interpolator() {}
+
+ explicit binomial_interpolator(const T coeff[D+1], scalar seconds = 1.0,
+ interpolator::mode onFinish = interpolator::stop)
+ {
+ init(coeff, seconds, onFinish);
+ }
+
+ void init(const T coeff[D+1], scalar seconds = 1.0,
+ interpolator::mode onFinish = interpolator::stop)
+ {
+ scalar fac[D+1];
+
+ fac[0] = 1.0;
+ fac[1] = 1.0;
+
+ // build an array of the computed factorials we will need
+ for (int i = 2; i <= D; i++)
+ {
+ fac[i] = i * fac[i - 1];
+ }
+
+ // combine the coefficients for fast updating
+ for (int i = 0; i <= D; i++)
+ {
+ // n! / (k! * (n - k)!)
+ coefficient[i] = coeff[i] * fac[D] / (fac[i] * fac[D - i]);
+ }
+
+ interpolator_base<T>::init(seconds, onFinish);
+ }
+
+
+ void calculate(T& value, scalar alpha)
+ {
+ scalar beta = 1.0 - alpha;
+
+ value = coefficient[0] * std::pow(beta, D);
+
+ for (int i = 1; i <= D; i++)
+ {
+ value += coefficient[i] * std::pow(beta, D - i) * std::pow(alpha, i);
+ }
+ }
+
+private:
+
+ T coefficient[D+1];
+};
+
+
+template <class T>
+class binomial_interpolator<T,1> : public interpolator_base<T>
+{
+public:
+ binomial_interpolator() {}
+
+ explicit binomial_interpolator(const T coeff[2], scalar seconds = 1.0,
+ interpolator::mode onFinish = interpolator::stop)
+ //interpolator_base<T>(seconds, onFinish)
+ {
+ init(coeff, seconds, onFinish);
+ }
+
+ void init(const T coeff[2], scalar seconds = 1.0,
+ interpolator::mode onFinish = interpolator::stop)
+ {
+ coefficient[0] = coeff[0];
+ coefficient[1] = coeff[1];
+
+ interpolator_base<T>::init(seconds, onFinish);
+ }
+
+
+ void calculate(T& value, scalar alpha)
+ {
+ value = cml::lerp(coefficient[0], coefficient[1], alpha);
+ }
+
+private:
+ T coefficient[2];
+};
+
+
+// Here are some aliases for more common interpolators. Also see the
+// interpolation functions in cml for other types of interpolation such as
+// slerp and some multi-alpha interpolators.
+
+typedef binomial_interpolator<scalar, 1> lerps; // linear
+typedef binomial_interpolator<vector2,1> lerpv2;
+typedef binomial_interpolator<vector3,1> lerpv3;
+typedef binomial_interpolator<vector4,1> lerpv4;
+
+typedef binomial_interpolator<scalar ,2> qerps; // quadratic
+typedef binomial_interpolator<vector2,2> qerpv2;
+typedef binomial_interpolator<vector3,2> qerpv3;
+typedef binomial_interpolator<vector4,2> qerpv4;
+
+typedef binomial_interpolator<scalar ,3> cerps; // cubic
+typedef binomial_interpolator<vector2,3> cerpv2;
+typedef binomial_interpolator<vector3,3> cerpv3;
+typedef binomial_interpolator<vector4,3> cerpv4;
+
+
+} // namespace dc
+
+#endif // _INTERPOLATOR_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#include <cmath>
#include <cml/cml.h>
+#include <iostream>
-namespace dc {
+namespace dc {
-typedef double scalar; ///< Scalar variable.
-typedef cml::vector2d vector2;
-typedef cml::vector3d vector3;
-typedef cml::vector4d vector4;
+// Basic types.
-typedef cml::matrix33d_c matrix3;
-typedef cml::matrix44d_c matrix4;
+typedef float scalar; ///< Scalar type.
-typedef cml::quaterniond_p quaternion;
+typedef cml::vector2f vector2;
+typedef cml::vector3f vector3;
+typedef cml::vector4f vector4;
-typedef cml::vector4f color;
+typedef cml::matrix33f_c matrix3;
+typedef cml::matrix44f_c matrix4;
+typedef cml::quaternionf_p quaternion;
-// Here's a simple way to check the equality of floating-point variables more
-// reliably using approximation.
+typedef vector4 color;
-const scalar default_epsilon = 0.00001; ///< @see equals()
+const scalar default_epsilon = 0.00001;
/**
* Check the equality of scalars with a certain degree of error allowed.
#endif // _MATH_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#ifndef _MIPPLETON_HH_
+#define _MIPPLETON_HH_
+
+/**
+ * @file mippleton.hh
+ * Related to singletons, a mippleton is an object which can be obtained
+ * globally using a unique name. Unlike singletons, there can be multiple
+ * mippletons per class, each with a different name or identifier. Mippletons
+ * are create automatically when they are first requested (retained) and deleted
+ * after the last interested code releases its hold on the object.
+ */
+
+#include <map>
+#include <string>
+
+
+namespace dc {
+
+
+template <class T>
+class mippleton
+{
+ typedef std::pair<unsigned,T*> ptr_value_t;
+ typedef std::pair<std::string,ptr_value_t> ptr_map_pair_t;
+ typedef std::map<std::string,ptr_value_t> ptr_map_t;
+
+ static ptr_map_t ptrs_;
+ std::string name_;
+
+public:
+ explicit mippleton(const std::string& name) : name_(name) {}
+
+ inline const std::string& getName() const
+ {
+ return name_;
+ }
+
+ inline static T* retain(const std::string& name)
+ {
+ typename ptr_map_t::iterator it;
+
+ if ((it = ptrs_.find(name)) != ptrs_.end())
+ {
+ (*it).second.first++;
+ return (*it).second.second;
+ }
+ else
+ {
+ T* newObj = new T(name);
+ ptrs_.insert(ptr_map_pair_t(name, ptr_value_t(1, newObj)));
+ return newObj;
+ }
+ }
+
+ inline static void releaseByName(const std::string& name)
+ {
+ typename ptr_map_t::iterator it;
+
+ if ((it = ptrs_.find(name)) != ptrs_.end() && -(*it).second.first == 0)
+ {
+ delete (*it).second.second;
+ ptrs_.erase(it);
+ }
+ }
+
+ inline static void release(T* obj)
+ {
+ releaseByName(obj->getName());
+ }
+};
+
+template <class T>
+std::map<std::string,std::pair<unsigned,T*> > mippleton<T>::ptrs_;
+
+
+} // namespace dc
+
+#endif // _MIPPLETON_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#endif // _GL_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#endif // _PROFILER_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
}; // namespace rng
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#endif // _RNG_RANDOM_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
+++ /dev/null
-
-/*******************************************************************************
-
- Copyright (c) 2009, Charles McGarvey
- 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, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
-
-*******************************************************************************/
-
-#ifndef _RECTANGLE_HH_
-#define _RECTANGLE_HH_
-
-#include "math.hh"
-#include "vector.hh"
-
-
-namespace dc {
-
-//
-// A rectangle is a 2d shape defined by point (origin) and size (width & height)
-// vectors. The usual rectangle maths are available. Valid rectangles have
-// positive width and height. Invalid rectangles will be returned for invalid
-// operations such as trying to get the intersection of two rectangles which
-// don't intersect. Using an invalid rectangle is undefined, but it may be used
-// after "fixing" it using the fix method which will cause the size to be
-// positive and adjust the origin to be the bottom-left point. Check the
-// validity of a rectangle using the isValid method especially if the rectangle
-// is a result of an operation which could fail.
-//
-
-class rectangle
-{
-public:
- // Constructors.
- rectangle() {}
- rectangle(point o, point s) {
- origin = o;
- size = s;
- }
-
- // Rectangle validity.
- bool isValid() const { return size.x >= 0.0 && size.y >= 0.0; }
- void fix()
- {
- if (size.x <= 0.0)
- {
- size.x = 0.0 - size.x;
- origin.x -= size.x;
- }
- if (size.y <= 0.0)
- {
- size.y = 0.0 - size.y;
- origin.y -= size.y;
- }
- }
-
- // Rectangle operations.
- scalar area() const { return size.x * size.y; }
- scalar perimeter() const {
- return size.x + size.x + size.y + size.y;
- }
-
- bool containsPoint(point pt) const
- {
- return origin.x <= pt.x && origin.y <= pt.y &&
- pt.x <= origin.x + size.x && pt.y <= origin.y + size.y;
- }
-
- void inset(scalar h, scalar v)
- {
- origin.x += h;
- origin.y += v;
- size.x -= h + h;
- size.y -= v + v;
- }
- void offset(scalar h, scalar v)
- {
- origin.x -= h;
- origin.y -= v;
- size.x += h + h;
- size.y += v + v;
- }
-
- bool containsRect(const rectangle& r) const;
- bool intersectsRect(const rectangle& r) const;
- rectangle unionWith(const rectangle& r) const;
- rectangle intersectionWith(const rectangle& r) const;
-
- // Checking equality.
- bool operator == (const rectangle& r) const {
- return origin == r.origin && size == r.size;
- }
- bool operator != (const rectangle& r) const {
- return !(*this == r);
- }
-
- // Data.
- point origin, size;
-};
-
-} // namespace dc
-
-
-#endif // _RECTANGLE_HH_
-
std::vector<std::string> resource::searchPaths_;
-resource::resource(const std::string& name) throw(exception)
-{
- filePath_ = getPathToResource(name);
-
- if (!filePath_.empty())
- {
- throw exception("cannot find resource file " + name);
- }
-}
-
resource::~resource() {}
-const std::string& resource::getPathToFile()
-{
- return filePath_;
-}
-
void resource::addSearchPath(const std::string& directory)
{
+ // add a slash if there isn't one already
if (directory[directory.length() - 1] != '/')
{
searchPaths_.push_back(directory + '/');
for (i = searchPaths_.begin(); i != searchPaths_.end(); i++)
{
- const char* fullPath = ((*i) + name).c_str();
- if (access(fullPath, R_OK) == 0)
+ std::string fullPath(*i);
+ fullPath += name;
+
+ // TODO access(2) is not all that portable
+ if (access(fullPath.c_str(), R_OK) == 0)
{
- return std::string(fullPath);
+ return fullPath;
}
}
+ // empty string
return std::string();
}
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
std::runtime_error(what_arg) {}
};
- resource(const std::string& name) throw(exception);
virtual ~resource();
- /**
- * Get the path of the file associated with this resource.
- * @return Path.
- */
-
- const std::string& getPathToFile();
-
/**
* Add a directory to search when looking for resource files.
static std::string getPathToResource(const std::string& name);
private:
- std::string filePath_;
static std::vector<std::string> searchPaths_;
};
#endif // _RESOURCE_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#include <map>
+#include <vector>
+
+#include "mippleton.hh"
+#include "deserializer.hh"
+#include "serializable.hh"
+#include "aabb.hh"
+
+#include "scene.hh"
+
+
+namespace dc {
+
+
+class scene::scene_impl : public mippleton<scene_impl>
+{
+ static bool loadBox(aabb& theBox, serializable_ptr obj)
+ {
+ std::vector<serializable_ptr> numbers;
+
+ if (obj->get(numbers))
+ {
+ if (numbers.size() == 6)
+ {
+ double num;
+
+ if (numbers[0]->getNumber(num))
+ {
+
+ }
+ }
+ }
+
+ return false;
+ }
+
+public:
+
+ scene_impl(const std::string& name) :
+ mippleton<scene_impl>(name)
+ {
+ loadFromFile();
+ }
+
+
+ void loadFromFile()
+ {
+ std::string filePath = scene::getPathToResource(getName());
+
+ deserializer in(filePath, true);
+
+ serializable_ptr root = in.deserialize();
+
+ if (root)
+ {
+ std::map<std::string,serializable_ptr> rootObj;
+
+ if (root->get(rootObj))
+ {
+ std::map<std::string,serializable_ptr>::iterator it;
+
+ if ((it = rootObj.find("playfield_bounds")) != rootObj.end())
+ {
+ loadBox(playfieldBounds, (*it).second);
+ }
+ if ((it = rootObj.find("maximum_bounds")) != rootObj.end())
+ {
+ loadBox(maximumBounds, (*it).second);
+ }
+
+ //for (i = rootObj.begin(); i != rootObj.end(); i++)
+ //{
+ //sequences.insert(std::pair<std::string,sequence>((*i).first,
+ //sequence((*i).second)));
+ //}
+ }
+ }
+ }
+
+ aabb playfieldBounds;
+ aabb maximumBounds;
+
+};
+
+
+scene::scene(const std::string& name) :
+ // pass through
+ impl(scene::scene_impl::retain(name), &scene::scene_impl::release) {}
+
+
+void scene::draw(scalar alpha)
+{
+}
+
+
+/**
+ * Specialized search location for scene files. They can be found in the
+ * "scenes" subdirectory of any of the searched directories.
+ */
+
+std::string scene::getPathToResource(const std::string& name)
+{
+ return resource::getPathToResource("scenes/" + name + ".json");
+}
+
+
+} // namespace dc
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#ifndef _SCENE_HH_
+#define _SCENE_HH_
+
+#include <string>
+#include <boost/shared_ptr.hpp>
+
+#include "resource.hh"
+#include "drawable.hh"
+
+
+namespace dc {
+
+
+class scene : public resource, public drawable
+{
+public:
+ scene(const std::string& name);
+
+ void draw(scalar alpha);
+
+ static std::string getPathToResource(const std::string& name);
+
+private:
+ class scene_impl;
+ boost::shared_ptr<scene_impl> impl;
+};
+
+
+} // namespace dc
+
+#endif // _SCENE_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
return false;
}
+
bool serializable::isNull()
{
return false;
}
+bool serializable::getNumber(long& value)
+{
+ if (get(value))
+ {
+ return true;
+ }
+ else
+ {
+ double dValue;
+ if (get(dValue))
+ {
+ value = long(dValue);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool serializable::getNumber(double& value)
+{
+ if (get(value))
+ {
+ return true;
+ }
+ else
+ {
+ long lValue;
+ if (get(lValue))
+ {
+ value = double(lValue);
+ return true;
+ }
+ }
+ return false;
+}
+
+
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#include <map>
#include <vector>
+#include "stringtools.hh"
#include "serializer.hh"
#include "deserializer.hh"
-#include "stringtools.hh"
namespace dc {
virtual bool get(std::wstring& value);
virtual bool get(std::vector<serializable_ptr>& value);
virtual bool get(std::map<std::string,serializable_ptr>& value);
+
+ /*
+ * To get a number value which may have been parsed as either an integer or
+ * double, use these instead.
+ */
+
+ bool getNumber(long&);
+ bool getNumber(double&);
+
virtual bool isNull();
};
void print() const;
bool get(T& value);
-
public:
T variable;
};
#endif // _SERIALIZABLE_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
namespace dc {
-class serializer_impl
+class serializer::serializer_impl
{
public:
serializer_impl(const std::string& filePath, const std::string& indent = "")
throw serializer::exception("maximum archive depth exceeded");
case yajl_gen_in_error_state:
throw serializer::exception("serializer already in error state");
+ case yajl_gen_status_ok:
+ ; // There is no error here. Move along...
}
}
serializer::serializer(const std::string& filePath, const std::string& indent) :
- impl(new serializer_impl(filePath, indent)) {}
+ // pass through
+ impl(new serializer::serializer_impl(filePath, indent)) {}
serializer::serializer(std::ostream& output, const std::string& indent) :
- impl(new serializer_impl(output, indent)) {}
+ // pass through
+ impl(new serializer::serializer_impl(output, indent)) {}
serializer::~serializer()
{
void serializer::push(long value)
{
yajl_gen_status stat = yajl_gen_integer(impl->gen, value);
- if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat);
+ if (stat != yajl_gen_status_ok)
+ serializer::serializer_impl::throwError(stat);
}
void serializer::push(double value)
{
yajl_gen_status stat = yajl_gen_double(impl->gen, value);
- if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat);
+ if (stat != yajl_gen_status_ok)
+ serializer::serializer_impl::throwError(stat);
}
void serializer::push(bool value)
{
yajl_gen_status stat = yajl_gen_bool(impl->gen, value);
- if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat);
+ if (stat != yajl_gen_status_ok)
+ serializer::serializer_impl::throwError(stat);
}
void serializer::push(const std::string& value)
{
yajl_gen_status stat = yajl_gen_string(impl->gen,
(const unsigned char*)value.c_str(), value.length());
- if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat);
+ if (stat != yajl_gen_status_ok)
+ serializer::serializer_impl::throwError(stat);
}
void serializer::push(const std::wstring& value)
void serializer::pushNull()
{
yajl_gen_status stat = yajl_gen_null(impl->gen);
- if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat);
+ if (stat != yajl_gen_status_ok)
+ serializer::serializer_impl::throwError(stat);
}
void serializer::pushMapHead()
{
yajl_gen_status stat = yajl_gen_map_open(impl->gen);
- if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat);
+ if (stat != yajl_gen_status_ok)
+ serializer::serializer_impl::throwError(stat);
}
void serializer::pushMapTail()
{
yajl_gen_status stat = yajl_gen_map_close(impl->gen);
- if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat);
+ if (stat != yajl_gen_status_ok)
+ serializer::serializer_impl::throwError(stat);
}
void serializer::pushArrayHead()
{
yajl_gen_status stat = yajl_gen_array_open(impl->gen);
- if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat);
+ if (stat != yajl_gen_status_ok)
+ serializer::serializer_impl::throwError(stat);
}
void serializer::pushArrayTail()
{
yajl_gen_status stat = yajl_gen_array_close(impl->gen);
- if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat);
+ if (stat != yajl_gen_status_ok)
+ serializer::serializer_impl::throwError(stat);
}
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
namespace dc {
-class serializer_impl;
-
class serializer
{
public:
+
+ /**
+ * Construction is initialization. Use either an output stream or a string
+ * representing a path to a fill to which the serialized data will be
+ * written (replacing any previous file).
+ * @param indent If non-empty, the string's characters will be used as
+ * indentation. Otherwise, the serialized data will not be formatted neatly
+ * but will be tightly packed.
+ */
+
serializer(const std::string& filePath, const std::string& indent = "");
serializer(std::ostream& output, const std::string& indent = "");
~serializer();
+ /**
+ * Push various types of data onto the stream.
+ */
+
void push(long value);
void push(double value);
void push(bool value);
void push(const std::wstring& value);
void pushNull();
+ /**
+ * Push a map onto the stream. Each map head must be matched by a map tail.
+ */
+
void pushMapHead();
void pushMapTail();
+ /**
+ * Push an array onto the stream. Each array head must be matched by an
+ * array tail.
+ */
+
void pushArrayHead();
void pushArrayTail();
+ /**
+ * Write any pending bytes to the stream. This is called automatically by
+ * the destructor of this class.
+ */
+
void flush();
+ /**
+ * This exception is thrown for serializer-related exceptional errors.
+ */
+
struct exception : std::runtime_error
{
explicit exception(const std::string& what_arg) :
};
private:
+ class serializer_impl;
boost::shared_ptr<serializer_impl> impl;
};
#endif // _SERIALIZER_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
*******************************************************************************/
#include <sstream>
-#include <cstring>
+#include <cstdlib> // getenv
+#include <cstring> // strchr
+
+#include <boost/algorithm/string.hpp>
#include "settings.hh"
}
catch (std::exception e)
{
+ // it doesn't deserialize to anything we know, so just store it
+ // as a string
map[key] = serializable_ptr(new wrapped_string(stringValue));
}
}
}
}
-void settings::loadFromFile(std::string filePath)
+
+void settings::loadFromFile(const std::string& filePath, bool precedence)
{
- deserializer in(filePath, true);
+ std::vector<std::string> paths;
+ boost::split(paths, filePath, boost::is_any_of(":"));
- try
+ loadFromFiles(paths, precedence);
+}
+
+void settings::loadFromFiles(const std::vector<std::string>& filePaths,
+ bool precedence)
+{
+ std::vector<std::string>::const_iterator it;
+
+ char* home = getenv("HOME");
+
+ for (it = filePaths.begin(); it != filePaths.end(); it++)
{
- serializable_ptr obj = in.deserialize();
- std::map<std::string,serializable_ptr> dict;
- if (obj && obj->get(dict))
+ std::string path = *it;
+
+ if (home)
{
- map.insert(dict.begin(), dict.end());
+ boost::replace_first(path, "$HOME", home);
}
- else
+
+ deserializer in(*it, true);
+
+ std::cout << "Looking for a config file at " << path << std::endl;
+ try
{
- std::cerr << "The settings file " << filePath <<
- " does not contain any valid settings." << std::endl;
+ serializable_ptr obj = in.deserialize();
+ std::map<std::string,serializable_ptr> dict;
+ if (obj && obj->get(dict))
+ {
+ if (!precedence)
+ {
+ map.insert(dict.begin(), dict.end());
+ }
+ else
+ {
+ dict.insert(map.begin(), map.end());
+ map = dict;
+ }
+ }
+ }
+ catch (deserializer::exception e)
+ {
+ std::cerr << "Cannot load settings from " << *it <<
+ " because an exception was thrown: " << e.what() << std::endl;
}
- }
- catch (deserializer::exception e)
- {
- std::cerr << "Cannot load settings from " << filePath <<
- " because an exception was thrown: " << e.what() << std::endl;
}
}
} // namepsace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
settings(int argc, char* argv[]);
void parseArgs(int argc, char* argv[]);
- void loadFromFile(std::string filePath);
+
+ void loadFromFile(const std::string& filePath, bool precedence = false);
+ void loadFromFiles(const std::vector<std::string>& filePaths,
+ bool precedence = false);
template <typename T>
bool get(const std::string& key, T& value);
#endif // _SETTINGS_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#include <stdexcept>
+namespace dc {
+
+
template <typename T>
class singleton
{
static T* ptr_;
public:
+ struct exception : public std::runtime_error
+ {
+ explicit exception(const std::string& what_arg) :
+ std::runtime_error(what_arg) {}
+ };
+
singleton()
{
if (!ptr_)
{
if (!ptr_)
{
- throw std::runtime_error("accessing uninstantiated singleton");
+ throw exception("accessing uninstantiated singleton");
}
return *ptr_;
}
- static T* instance__ptr()
+ static T* instance_ptr()
{
return ptr_;
}
template <typename T> T* singleton<T>::ptr_ = 0;
+} // namespace dc
+
#endif // _SINGLETON_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#endif // _STRINGTOOLS_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
+#include "mippleton.hh"
+
#include "dispatcher.hh"
#include "opengl.hh"
namespace dc {
-class texture_impl
+/**
+ * The texture implementation just contains all the information about the image
+ * which is worth having in memory. The image data itself is not worth keeping
+ * in memory if the texture has been loaded to GL, but the name of the resource
+ * is retained so that it can be reloaded if necessary. The implementation is a
+ * mippleton so that multiple texture objects can share the same internal
+ * objects and avoid having duplicate textures loaded to GL.
+ */
+
+class texture::texture_impl : public mippleton<texture_impl>
{
+
+ /**
+ * Delete the texture (if it is loaded) from GL.
+ */
+
void unloadFromGL()
{
- if (object)
+ if (object_)
{
- glDeleteTextures(1, &object);
- object = 0;
+ glDeleteTextures(1, &object_);
+ object_ = 0;
}
}
+ /**
+ * If the GL context was recreated, we probably need to reload the texture.
+ * This may involve reading it from disk again, but hopefully the OS was
+ * smart enough to cache it if the client has plenty of RAM.
+ */
+
void contextRecreated(const notification& note)
{
unloadFromGL();
uploadToGL();
}
-public:
- texture_impl(texture* outside, bool keepInMemory)
- : interface(outside), keepData(keepInMemory), object(0), imageData(0)
- {
- dispatcher::instance().addHandler("video.context_recreated",
- boost::bind(&texture_impl::contextRecreated, this, _1),
- this);
- }
-
- ~texture_impl()
- {
- dispatcher::instance().removeHandler(this);
-
- if (imageData)
- {
- SDL_FreeSurface(imageData);
- }
- unloadFromGL();
- }
-
+ /**
+ * This is a helper method used by some of the texture loading code. It
+ * returns the first power of two which is greater than the input value.
+ */
static int powerOfTwo(int input)
{
return value;
}
+public:
+
+ /**
+ * Construction is initialization.
+ */
+
+ explicit texture_impl(const std::string& name) :
+ mippleton<texture_impl>(name),
+ width_(0),
+ height_(0),
+ mode_(0),
+ minFilter_(GL_NEAREST),
+ maxFilter_(GL_NEAREST),
+ wrapU_(GL_CLAMP),
+ wrapV_(GL_CLAMP),
+ object_(0)
+ {
+ uploadToGL();
+
+ // we want to know when the GL context is recreated
+ dispatcher::instance().addHandler("video.context_recreated",
+ boost::bind(&texture_impl::contextRecreated, this, _1), this);
+ }
+
+ ~texture_impl()
+ {
+ unloadFromGL();
+
+ dispatcher::instance().removeHandler(this);
+ }
+
+
+ /**
+ * Adapted from some public domain code. This stuff is common enough that
+ * it really should be included in SDL_image... We need this because images
+ * loaded with SDL_image aren't exactly GL-ready right out of the box. This
+ * method makes them ready.
+ */
+
static SDL_Surface* prepareImageForGL(SDL_Surface* surface)
{
- // Adapted from some public domain code. This stuff is common enough
- // that it really should be included in SDL_image... We need this
- // because images loaded with SDL_image aren't exactly OpenGL-ready
- // right out of the box.
-
int w = powerOfTwo(surface->w);
int h = powerOfTwo(surface->h);
// 1. OpenGL images must (generally) have dimensions of a power-of-two.
+ // If this one doesn't, we can at least be more friendly by expanding
+ // the dimensions so that they are, though there will be some empty
+ // space within the range of normal texture coordinates. It's better of
+ // textures are the right size to begin with.
SDL_Surface* image = SDL_CreateRGBSurface
(
SDL_SetAlpha(surface, savedFlags, savedAlpha);
}
- // 2. OpenGL textures make more sense when they are "upside down."
+ // 2. OpenGL textures make more sense within the coordinate system when
+ // they are "upside down," so let's flip it.
Uint8 line[image->pitch];
return image;
}
+ /**
+ * Use SDL_image to load images from file. A surface with the image data is
+ * returned.
+ * @return Image data.
+ */
- void loadImageData()
+ SDL_Surface* loadImageData()
{
SDL_Surface* surface;
- surface = IMG_Load(interface->getPathToFile().c_str());
+ surface = IMG_Load(texture::getPathToResource(getName()).c_str());
if (!surface)
{
throw texture::exception("loading failed");
}
- imageData = prepareImageForGL(surface);
+ SDL_Surface* temp = prepareImageForGL(surface);
SDL_FreeSurface(surface);
- if (!imageData)
+ if (!temp)
{
- throw texture::exception("");
+ throw texture::exception("image couldn't be prepared for GL");
}
- if (imageData->format->BytesPerPixel == 3)
+ if (temp->format->BytesPerPixel == 3)
{
- mode = GL_RGB;
+ mode_ = GL_RGB;
}
- else if (imageData->format->BytesPerPixel == 4)
+ else if (temp->format->BytesPerPixel == 4)
{
- mode = GL_RGBA;
+ mode_ = GL_RGBA;
}
else
{
- SDL_FreeSurface(imageData);
+ SDL_FreeSurface(temp);
throw texture::exception("image is not the required 24 or 32 bpp");
}
- width = imageData->w;
- height = imageData->h;
+ width_ = temp->w;
+ height_ = temp->h;
+
+ return temp;
}
+ /**
+ * Upload the image to GL so that it will be accessible by a much more
+ * manageable handle and hopefully reside in video memory.
+ */
+
void uploadToGL()
{
- if (object)
+ if (object_)
{
// Already loaded.
return;
}
- if (!imageData)
- {
- loadImageData();
- }
+ SDL_Surface* imageData = loadImageData();
- glGenTextures(1, &object);
-
- glBindTexture(GL_TEXTURE_2D, object);
+ glGenTextures(1, &object_);
+ glBindTexture(GL_TEXTURE_2D, object_);
glTexImage2D
(
GL_TEXTURE_2D,
0,
- mode,
+ mode_,
imageData->w,
imageData->h,
0,
- mode,
+ mode_,
GL_UNSIGNED_BYTE,
imageData->pixels
);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ setProperties();
- if (!keepData)
- {
- SDL_FreeSurface(imageData);
- imageData = 0;
- }
+ SDL_FreeSurface(imageData);
}
- unsigned width;
- unsigned height;
- int mode;
- GLuint object;
+ /**
+ * Sets some texture properties such as the filters and external coordinate
+ * behavior.
+ */
+
+ void setProperties()
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, maxFilter_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapU_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapV_);
+ }
+
- bool keepData;
- SDL_Surface* imageData;
+ unsigned width_; ///< Horizontal dimension of the image.
+ unsigned height_; ///< Vertical dimension.
- texture* interface;
+ GLuint mode_; ///< Depth of the image, GL_RGB or GL_RGBA.
+ GLuint minFilter_; ///< Filter.
+ GLuint maxFilter_; ///< Filter.
+ GLuint wrapU_; ///< Wrapping behavior horizontally.
+ GLuint wrapV_; ///< Wrapping behavior vertically.
+ GLuint object_; ///< GL texture handle.
};
-texture::texture(const std::string& name, bool keepInMemory)
- : resource(name), impl(new texture_impl(this, keepInMemory)) {}
+texture::texture(const std::string& name) :
+ // pass through
+ impl(texture::texture_impl::retain(name), &texture::texture_impl::release)
+{}
+
+/**
+ * Bind the GL texture for mapping, etc.
+ */
void texture::bind()
{
glBindTexture(GL_TEXTURE_2D, getObject());
}
+
+/**
+ * Get the texture object, for the curious.
+ */
+
GLuint texture::getObject()
{
- if (!impl->object)
- {
- impl->uploadToGL();
- }
-
- return impl->object;
+ // pass through
+ return impl->object_;
}
unsigned texture::getWidth()
{
- if (!impl->object)
- {
- impl->uploadToGL();
- }
-
- return impl->width;
+ // pass through
+ return impl->width_;
}
unsigned texture::getHeight()
{
- if (!impl->object)
- {
- impl->uploadToGL();
- }
+ // pass through
+ return impl->height_;
+}
+
- return impl->height;
+void texture::setMinFilter(GLuint filter)
+{
+ impl->minFilter_ = filter;
+}
+
+void texture::setMaxFilter(GLuint filter)
+{
+ impl->maxFilter_ = filter;
+}
+
+void texture::setWrapU(GLuint wrap)
+{
+ impl->wrapU_ = wrap;
+}
+
+void texture::setWrapV(GLuint wrap)
+{
+ impl->wrapV_ = wrap;
+}
+
+
+void texture::applyChanges()
+{
+ bind();
+ impl->setProperties();
+}
+
+
+std::string texture::getPathToResource(const std::string& name)
+{
+ // TODO since this is a generic library class, more than PNG should be
+ // supported
+ return resource::getPathToResource("textures/" + name + ".png");
}
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#include <boost/shared_ptr.hpp>
-#include "resource.hh"
#include "opengl.hh"
+#include "resource.hh"
namespace dc {
-class texture_impl;
-
class texture : public resource
{
public:
- texture(const std::string& name, bool keepInMemory = false);
+ texture(const std::string& name);
void bind();
GLuint getObject();
unsigned getWidth();
unsigned getHeight();
+ void setMinFilter(GLuint filter);
+ void setMaxFilter(GLuint filter);
+ void setWrapU(GLuint wrap);
+ void setWrapV(GLuint wrap);
+
+ void applyChanges();
+
+ static std::string getPathToResource(const std::string& name);
+
struct exception : std::runtime_error
{
explicit exception(const std::string& what_arg) :
};
private:
+ class texture_impl;
boost::shared_ptr<texture_impl> impl;
};
#endif // _TEXTURE_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#endif // _THREAD_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ 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, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
+
+*******************************************************************************/
+
+#include <cassert>
+
+#include "mippleton.hh"
+#include "serializable.hh"
+#include "deserializer.hh"
+
+#include "opengl.hh"
+
+#include "tilemap.hh"
+
+
+namespace dc {
+
+
+class tilemap::tilemap_impl : public mippleton<tilemap_impl>
+{
+public:
+ tilemap_impl(const std::string& name) :
+ mippleton<tilemap_impl>(name),
+ tilesU_(1),
+ tilesV_(1),
+ minFilter_(GL_NEAREST),
+ maxFilter_(GL_NEAREST),
+ wrapU_(GL_CLAMP),
+ wrapV_(GL_CLAMP)
+ {
+ loadFromFile();
+ }
+
+ void loadFromFile()
+ {
+ deserializer in(tilemap::getPathToResource(getName()));
+
+ serializable_ptr root = in.deserialize();
+
+ if (root)
+ {
+ std::map<std::string,serializable_ptr> rootMap;
+
+ if (root->get(rootMap))
+ {
+ std::map<std::string,serializable_ptr>::iterator it;
+
+ if ((it = rootMap.find("TilesU")) != rootMap.end())
+ {
+ long value;
+ if ((*it).second->get(value))
+ {
+ tilesU_ = unsigned(value);
+ }
+ }
+ if ((it = rootMap.find("TilesV")) != rootMap.end())
+ {
+ long value;
+ if ((*it).second->get(value))
+ {
+ tilesV_ = unsigned(value);
+ }
+ }
+ if ((it = rootMap.find("MinFilter")) != rootMap.end())
+ {
+ std::string value;
+ if ((*it).second->get(value))
+ {
+ if (value == "Linear")
+ {
+ minFilter_ = GL_LINEAR;
+ }
+ }
+ }
+ if ((it = rootMap.find("MaxFilter")) != rootMap.end())
+ {
+ std::string value;
+ if ((*it).second->get(value))
+ {
+ if (value == "Linear")
+ {
+ maxFilter_ = GL_LINEAR;
+ }
+ }
+ }
+ if ((it = rootMap.find("WrapU")) != rootMap.end())
+ {
+ std::string value;
+ if ((*it).second->get(value))
+ {
+ if (value == "Repeat")
+ {
+ wrapU_ = GL_REPEAT;
+ }
+ }
+ }
+ if ((it = rootMap.find("WrapV")) != rootMap.end())
+ {
+ std::string value;
+ if ((*it).second->get(value))
+ {
+ if (value == "Repeat")
+ {
+ wrapV_ = GL_REPEAT;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ unsigned tilesU_;
+ unsigned tilesV_;
+ GLuint minFilter_;
+ GLuint maxFilter_;
+ GLuint wrapU_;
+ GLuint wrapV_;
+};
+
+
+tilemap::tilemap(const std::string& name) :
+ texture(name),
+ impl(tilemap::tilemap_impl::retain(name), &tilemap::tilemap_impl::release)
+{
+ setMinFilter(impl->minFilter_);
+ setMaxFilter(impl->maxFilter_);
+ setWrapU(impl->wrapU_);
+ setWrapV(impl->wrapV_);
+ applyChanges();
+}
+
+
+void tilemap::getTileCoords(unsigned index, scalar coords[8])
+{
+ assert(index < impl->tilesU_ * impl->tilesV_);
+
+ scalar w = 1.0 / scalar(impl->tilesU_);
+ scalar h = 1.0 / scalar(impl->tilesV_);
+
+ coords[0] = scalar(index % impl->tilesU_) * w;
+ coords[1] = (scalar(impl->tilesV_ - 1) - scalar(index / impl->tilesU_)) * h;
+ coords[2] = coords[0] + w;
+ coords[3] = coords[1];
+ coords[4] = coords[2];
+ coords[5] = coords[1] + h;
+ coords[6] = coords[0];
+ coords[7] = coords[5];
+}
+
+void tilemap::getTileCoords(unsigned index, scalar coords[8], orientation what)
+{
+ getTileCoords(index, coords);
+
+ if (what & flip)
+ {
+ coords[1] = coords[5];
+ coords[5] = coords[3];
+ coords[3] = coords[7];
+ coords[7] = coords[5];
+ }
+ if (what & reverse)
+ {
+ coords[0] = coords[2];
+ coords[2] = coords[6];
+ coords[4] = coords[6];
+ coords[6] = coords[0];
+ }
+}
+
+
+std::string tilemap::getPathToResource(const std::string& name)
+{
+ return resource::getPathToResource("tilemaps/" + name + ".json");
+}
+
+
+} // namespace dc
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
* Small subclass to give some basic tile-mapping functionality to textures.
*/
-#include <cassert>
-
#include <boost/shared_ptr.hpp>
-#include "opengl.hh"
#include "texture.hh"
+#include "math.hh"
namespace dc {
-namespace tile {
-
-/**
- * Possible orientations for texture coordinates.
- */
-
-typedef enum
-{
- normal = 0, ///< Normal orientation.
- flip = 1, ///< Flip over a horizontal axis.
- reverse = 2, ///< Flip over a vertical axis.
- flip_and_reverse = 3 ///< Flip over both.
-} orientation;
-
-} // namespace tile
-
-
/**
* A tilemap is a texture which is meant to be divided into smaller sprites.
* This class provides all the functionality of a texture and adds some methods
class tilemap : public texture
{
public:
- tilemap(const std::string& filePath, bool keepInMemory = false,
- unsigned tilesU = 1, unsigned tilesV = 1)
- : texture(filePath, keepInMemory), tilesU_(tilesU), tilesV_(tilesV) {}
-
-
/**
- * Set the number of rows and columns of square tiles.
- * @param tilesU Columns of tiles.
- * @param tilesV Rows of tiles.
+ * Possible orientations for texture coordinates.
*/
- void setTileDimensions(unsigned tilesU, unsigned tilesV)
+ typedef enum
{
- assert(tilesU != 0 && tilesV != 0);
- tilesU_ = tilesU;
- tilesV_ = tilesV;
- }
+ normal = 0, ///< Normal orientation.
+ flip = 1, ///< Flip over a horizontal axis.
+ reverse = 2, ///< Flip over a vertical axis.
+ flip_and_reverse = 3 ///< Flip over both.
+ } orientation;
+
+ tilemap(const std::string& name);
/**
* Calculate texture coordinates for a tile at a certain index. Tiles are
* indexed start with zero as the to-left tile and moving across, then down.
* @param index The tile index.
- * @param coords An array of floats where the texture coordinates will be
+ * @param coords An array of scalars where the texture coordinates will be
* stored after this call. The first coordinate (u,v) will be in the first
* two places and so on until all four coordinates are stored, therefore
- * requiring enough room for an array of eight floats. The winding of the
+ * requiring enough room for an array of eight scalars. The winding of the
* coordinates is always counter-clockwise (the GL default).
*/
- void getTileCoords(unsigned index, float coords[8])
- {
- assert(index < tilesU_ * tilesV_);
-
- float w = 1.0 / float(tilesU_);
- float h = 1.0 / float(tilesV_);
+ void getTileCoords(unsigned index, scalar coords[8]);
- coords[0] = float(index % tilesU_) * w;
- coords[1] = (float(tilesV_ - 1) - float(index / tilesU_)) * h;
- coords[2] = coords[0] + w;
- coords[3] = coords[1];
- coords[4] = coords[2];
- coords[5] = coords[1] + h;
- coords[6] = coords[0];
- coords[7] = coords[5];
- }
/**
* This version let's you specify an orientation that will be reflected in
* @param what The orientation; can be flip, reverse, or flip_and_reverse.
*/
- void getTileCoords(unsigned index, float coords[8], tile::orientation what)
- {
- getTileCoords(index, coords);
-
- if (what & tile::flip)
- {
- coords[1] = coords[5];
- coords[5] = coords[3];
- coords[3] = coords[7];
- coords[7] = coords[5];
- }
- if (what & tile::reverse)
- {
- coords[0] = coords[2];
- coords[2] = coords[6];
- coords[4] = coords[6];
- coords[6] = coords[0];
- }
- }
+ void getTileCoords(unsigned index, scalar coords[8], orientation what);
+
+
+ static std::string getPathToResource(const std::string& name);
private:
- unsigned tilesU_;
- unsigned tilesV_;
+ class tilemap_impl;
+ boost::shared_ptr<tilemap_impl> impl;
};
#endif // _TILEMAP_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#include <ctime>
#include <cerrno>
-#include <SDL/SDL.h>
-
#include "timer.hh"
#if HAVE_LIBRT
-scalar ticks()
+// Since the monotonic clock will provide us with the timer since the computer
+// started, the number of seconds since that time could easily become so large
+// that it cannot be accurately stored in a float (even with as little two days
+// update), therefore we need to start from a more recent reference (when the
+// program starts). Of course this isn't much of an issue if scalar is a
+// double-precious number.
+
+static time_t setReference()
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
{
- throw std::runtime_error("cannot access monotonic clock");
+ return 0;
}
- return scalar(ts.tv_sec) + scalar(ts.tv_nsec) / 1000000000.0;
+ return ts.tv_sec;
}
-void sleep(scalar seconds, bool absolute)
+static const time_t reference = setReference();
+
+
+scalar ticks()
{
struct timespec ts;
- int ret;
- if (!absolute) seconds += ticks();
- ts.tv_sec = time_t(seconds);
- ts.tv_nsec = time_t((seconds - scalar(ts.tv_sec)) * 1000000000.0);
-
- do
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
{
- ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, 0);
+ throw std::runtime_error("cannot access monotonic clock");
}
- while (ret == -1 && errno == EINTR);
+
+ return scalar(ts.tv_sec - reference) + scalar(ts.tv_nsec) / 1000000000.0;
}
+
#else // ! HAVE_LIBRT
-// If we don't have librt, we'll have to use different timing methods.
+
+// If we don't have librt, we'll have to use a different timing method. SDL
+// only promises centisecond accuracy, but it may be better than nothing.
+
+#include <SDL/SDL.h>
scalar ticks()
{
- unsigned ms = SDL_GetTicks();
+ Uint32 ms = SDL_GetTicks();
return scalar(ms / 1000) + scalar(ms % 1000) / 1000.0;
}
+
+#endif // HAVE_LIBRT
+
+
void sleep(scalar seconds, bool absolute)
{
struct timespec ts;
if (absolute) seconds -= ticks();
ts.tv_sec = time_t(seconds);
- ts.tv_nsec = time_t((seconds - scalar(ts.tv_sec)) * 1000000000.0);
+ ts.tv_nsec = long((seconds - scalar(ts.tv_sec)) * 1000000000.0);
do
{
while (ret == -1 && errno == EINTR);
}
-#endif // HAVE_LIBRT
-
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#endif // _TIMER_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#include "serializable.hh"
#include "settings.hh"
+#include "dispatcher.hh"
#include "video.hh"
SDL_FreeSurface(context_);
context_ = 0;
setVideoMode(attribs_.mode);
+ dc::dispatcher::instance().dispatch("video.context_recreated");
}
void video::setOpenGLAttributes()
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
#endif // _VIDEO_HH_
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
# To make yajl works as a convenience library, the directory src/api must be
-# renamed to src/yajl, and any sources or headers which refer to headers in in
-# that directory will need to be modified to look in the new directory.
+# renamed to src/yajl, and any sources or headers which refer to headers in that
+# directory will need to be modified to look in the new directory.
-noinst_LIBRARIES = libyajl.a
+noinst_LTLIBRARIES = libyajl.la
-libyajl_a_SOURCES = \
- src/yajl.c \
- src/yajl_alloc.c \
- src/yajl_alloc.h \
- src/yajl_buf.c \
- src/yajl_buf.h \
- src/yajl_bytestack.h \
- src/yajl_encode.c \
- src/yajl_encode.h \
- src/yajl_gen.c \
- src/yajl_lex.c \
- src/yajl_lex.h \
- src/yajl_parser.c \
- src/yajl_parser.h \
- $(ENDLIST)
+libyajl_la_SOURCES = \
+ src/yajl.c \
+ src/yajl_alloc.c \
+ src/yajl_alloc.h \
+ src/yajl_buf.c \
+ src/yajl_buf.h \
+ src/yajl_bytestack.h \
+ src/yajl_encode.c \
+ src/yajl_encode.h \
+ src/yajl_gen.c \
+ src/yajl_lex.c \
+ src/yajl_lex.h \
+ src/yajl_parser.c \
+ src/yajl_parser.h \
+ $(ENDLIST)
noinst_HEADERS = \
src/yajl/yajl_common.h \
src/yajl/yajl_parse.h \
$(ENDLIST)
-libyajl_a_CPPFLAGS = -Isrc
+libyajl_la_CPPFLAGS = -Isrc