The Simplified BSD License
-Copyright (c) 2009, Charles McGarvey
+Copyright (c) 2009-2010, Charles McGarvey
All rights reserved.
Redistribution and use in source and binary forms, with or without
--- /dev/null
+# Doxyfile 1.5.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = Yoink
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
+# Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.cc *.hh
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE =
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature. Other possible values
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Options related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
The code is a complete rewrite, containing none of the original code. I've
made some effort to put the more generic or reusable code into a separate
-library called Moof. I've also made an effort to incorporate 3rd-party
+library called libmoof. I've also made an effort to incorporate 3rd-party
code that happened to fit well into what I needed. So, generally, the
source code is separated into these three categories:
2. Reusable code.
-Currently, the code is in src/Moof/, and it is compiled as a convenience
-library. These classes and helper functions reside in the Mf namespace.
+Currently, the code is in src/moof/, and it is compiled as a convenience
+library. These classes and helper functions reside in the moof namespace.
Since I wrote this code alongside the Yoink-specific stuff, there is
somewhat of a blurry line between the two categories, unfortunately.
AC_FUNC_ERROR_AT_LINE
AC_FUNC_STRTOD
-AC_CHECK_FUNCS([fcntl ioctl nanosleep strchr strcspn strrchr strstr])
+AC_CHECK_FUNCS([fcntl nanosleep strchr strcspn strrchr strstr])
if test x$clock_gettime = xyes
then
**************************************************************************/
#include <map>
+#include <stdexcept>
#include <vector>
-#include <Moof/Error.hh>
-#include <Moof/Manager.hh>
-#include <Moof/Log.hh>
-#include <Moof/Script.hh>
+#include <moof/manager.hh>
+#include <moof/log.hh>
+#include <moof/script.hh>
#include "Animation.hh"
/**
* The collection of nested animation classes. The animation
- * implementation consists of an Impl class which is allocated and
+ * implementation consists of an impl class 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 different class which can be shared amongst
* multiple animation implementation instances.
*/
-class Animation::Impl
+class Animation::impl
{
public:
* animation which wants to use these loaded sequences.
*/
- class Data : public Mf::Manager<Data>
+ class Data : public moof::manager<Data>
{
public:
public:
unsigned mIndex; ///< Frame index.
- Mf::Scalar mDuration; ///< Frame duration.
+ moof::scalar mDuration; ///< Frame duration.
/**
* Construction is initialization. The frame data is loaded
* animation file.
*/
- Frame(const Mf::Script::Slot& table) :
+ Frame(const moof::script::slot& table) :
mIndex(0),
mDuration(1.0)
{
public:
std::vector<Frame> mFrames; ///< List of frames.
- Mf::Scalar mDelay; ///< Scale frame durations.
+ moof::scalar mDelay; ///< Scale frame durations.
bool mLoop; ///< Does the sequence repeat?
std::string mNext; ///< Next sequence name.
* the frame's constructor which loads each individual frame.
*/
- Sequence(const Mf::Script::Slot& table) :
+ Sequence(const moof::script::slot& table) :
mDelay(0.0),
mLoop(true)
{
// TODO - sequence class/type not yet implemented
- Mf::Script::Slot frameTable = table.pushField("frames");
- if (frameTable.isTable())
+ moof::script::slot frameTable = table.push_field("frames");
+ if (frameTable.is_table())
{
int max = frameTable.length();
for (int index = 1; index <= max; ++index)
{
- Mf::Script::Slot top = frameTable.pushField(index);
+ moof::script::slot top = frameTable.push_field(index);
- if (top.isTable())
+ if (top.is_table())
{
mFrames.push_back(Frame(top));
}
else
{
- Mf::logWarning << "invalid frame at index "
+ moof::log_warning << "invalid frame at index "
<< index << std::endl;
}
}
void init(const std::string& name)
{
- Mf::Script script;
+ moof::script script;
std::string path(name);
- if (!Animation::getPath(path))
+ if (!Animation::find_path(path))
{
- Mf::Error(Mf::Error::RESOURCE_NOT_FOUND).raise();
+ throw std::runtime_error("cannot find resource " + name);
}
- script.importBaseLibrary();
- importLogFunctions(script);
+ script.import_base_library();
+ moof::log::import(script);
importAnimationBindings(script);
- if (script.doFile(path) != Mf::Script::SUCCESS)
+ if (script.do_file(path) != moof::script::success)
{
std::string str;
script[-1].get(str);
- Mf::logWarning(str);
+ moof::log_warning(str);
}
}
- int defineSequence(Mf::Script& script)
+ int defineSequence(moof::script& script)
{
- Mf::Script::Slot name = script[1].requireString();
- Mf::Script::Slot table = script[2].requireTable();
+ moof::script::slot name = script[1].require_string();
+ moof::script::slot table = script[2].require_table();
std::string nameStr;
name.get(nameStr);
}
- void importAnimationBindings(Mf::Script& script)
+ void importAnimationBindings(moof::script& script)
{
- script.importFunction("DefineSequence",
+ script.import_function("DefineSequence",
boost::bind(&Data::defineSequence,
this, _1));
- script.globals().setField("ATTACK", 1);
- script.globals().setField("CHARGE", 2);
- script.globals().setField("FLY", 3);
- script.globals().setField("HIT", 4);
- script.globals().setField("JUMP", 5);
- script.globals().setField("RUN", 6);
- script.globals().setField("STAND", 7);
+ script.globals().set_field("ATTACK", 1);
+ script.globals().set_field("CHARGE", 2);
+ script.globals().set_field("FLY", 3);
+ script.globals().set_field("HIT", 4);
+ script.globals().set_field("JUMP", 5);
+ script.globals().set_field("RUN", 6);
+ script.globals().set_field("STAND", 7);
}
* Construction is intialization.
*/
- Impl(const std::string& name) :
- mData(Data::getInstance(name)),
+ impl(const std::string& name) :
+ mData(Data::instance(name)),
mCurrentSequence(0),
mFrameCounter(0),
mFrameIndex(0),
* the animation essentially starts over again.
*/
- void update(Mf::Scalar t, Mf::Scalar dt)
+ void update(moof::scalar t, moof::scalar dt)
{
if (!mCurrentSequence) return;
Data::Sequence* mCurrentSequence; ///< Active sequence.
unsigned mFrameCounter; ///< Current frame.
unsigned mFrameIndex; ///< Index of current frame.
- Mf::Scalar mTimeAccum; ///< Time accumulation.
- Mf::Scalar mFrameDuration; ///< Scaled frame duration.
+ moof::scalar mTimeAccum; ///< Time accumulation.
+ moof::scalar mFrameDuration; ///< Scaled frame duration.
};
Animation::Animation(const std::string& name) :
// pass through
- mImpl(new Animation::Impl(name)) {}
+ impl_(new Animation::impl(name)) {}
void Animation::startSequence(const std::string& name)
{
// pass through
- mImpl->startSequence(name);
+ impl_->startSequence(name);
}
-void Animation::update(Mf::Scalar t, Mf::Scalar dt)
+void Animation::update(moof::scalar t, moof::scalar dt)
{
// pass through
- mImpl->update(t, dt);
+ impl_->update(t, dt);
}
unsigned Animation::getFrame() const
{
- return mImpl->mFrameIndex;
+ return impl_->mFrameIndex;
}
* the "animations" subdirectory of any of the search directories.
*/
-bool Animation::getPath(std::string& name)
+bool Animation::find_path(std::string& name)
{
- return Mf::Resource::getPath(name, "animations/", "lua");
+ return moof::resource::find_path(name, "animations/", "lua");
}
#include <boost/shared_ptr.hpp>
-#include <Moof/Math.hh>
-#include <Moof/Resource.hh>
+#include <moof/math.hh>
+#include <moof/resource.hh>
class Animation;
* about anything to whatever drawing context is used to render the frame.
*/
-class Animation : public Mf::Resource
+class Animation : public moof::resource
{
- class Impl;
- boost::shared_ptr<Impl> mImpl;
+ class impl;
+ boost::shared_ptr<impl> impl_;
public:
void startSequence(const std::string& name);
- void update(Mf::Scalar t, Mf::Scalar dt);
+ void update(moof::scalar t, moof::scalar dt);
unsigned getFrame() const;
- static bool getPath(std::string& name);
+ static bool find_path(std::string& name);
};
#include <iostream>
+#include <moof/log.hh>
+
#include "Character.hh"
-#include "Log.hh"
class SpringForce
{
public:
- explicit SpringForce(Mf::Vector2 x) :
+ explicit SpringForce(moof::vector2 x) :
location(x) {}
- const Mf::Vector2& operator () (const Mf::LinearState<2>& state)
+ const moof::vector2& operator () (const moof::linear_state<2>& state)
{
- Mf::Vector2 x = state.position - location;
- Mf::Scalar mag = x.length();
- Mf::Scalar d = 0.0;
+ moof::vector2 x = state.position - location;
+ moof::scalar mag = x.length();
+ moof::scalar d = 0.0;
// spring:
- //mState.force += -15.0 * x - 1.5 * mState.velocity;
+ //state_.force += -15.0 * x - 1.5 * state_.velocity;
force = SCALAR(-10.0) * (mag - d) * (x / mag);// - SCALAR(2.0) * state.velocity;
return force;
private:
- Mf::Vector2 force;
- Mf::Vector2 location;
+ moof::vector2 force;
+ moof::vector2 location;
};
class ResistanceForce
{
public:
- explicit ResistanceForce(Mf::Scalar scale = 1.0) :
+ explicit ResistanceForce(moof::scalar scale = 1.0) :
k(scale) {}
- const Mf::Vector2& operator () (const Mf::LinearState<2>& state)
+ const moof::vector2& operator () (const moof::linear_state<2>& state)
{
force = -k * state.velocity;
return force;
private:
- Mf::Vector2 force;
- Mf::Scalar k;
+ moof::vector2 force;
+ moof::scalar k;
};
tilemap(name),
animation(name)
{
- mState.init();
+ state_.init();
- mState.mass = 1.0;
- mState.inverseMass = 1.0 / mState.mass;
+ state_.mass = 1.0;
+ state_.inverse_mass = 1.0 / state_.mass;
// forces
- mState.force = Mf::Vector2(0.0, 0.0);
- //mState.forces.push_back(SpringForce(Mf::Vector2(5.0, 4.0)));
- mState.forces.push_back(ResistanceForce(2.0));
- //mState.forces.push_back(Mf::LinearState<2>::GravityForce(-9.8));
+ state_.force = moof::vector2(0.0, 0.0);
+ //state_.forces.push_back(SpringForce(moof::vector2(5.0, 4.0)));
+ state_.forces.push_back(ResistanceForce(2.0));
+ //state_.forces.push_back(moof::linear_state<2>::gravity_force(-9.8));
// starting position
- mState.position = Mf::Vector2(5.0, 5.0);
- mState.momentum = Mf::Vector2(0.0, 0.0);
- mState.recalculate();
+ state_.position = moof::vector2(5.0, 5.0);
+ state_.momentum = moof::vector2(0.0, 0.0);
+ state_.recalculate();
- mPrevState = mState;
+ prev_state_ = state_;
}
-void Character::update(Mf::Scalar t, Mf::Scalar dt)
+void Character::update(moof::scalar t, moof::scalar dt)
{
- Mf::RigidBody2::update(t, dt); // update physics
+ moof::rigid_body2::update(t, dt); // update physics
animation.update(t, dt);
- Mf::Vector3 center(mState.position[0], mState.position[1], 0.0);
- Mf::Vector3 a(mState.position[0] - 0.5, mState.position[1] - 0.5, 0.0);
- Mf::Vector3 b(mState.position[0] + 0.5, mState.position[1] + 0.5, 0.0);
+ moof::vector3 center(state_.position[0], state_.position[1], 0.0);
+ moof::vector3 a(state_.position[0] - 0.5, state_.position[1] - 0.5, 0.0);
+ moof::vector3 b(state_.position[0] + 0.5, state_.position[1] + 0.5, 0.0);
- mAabb.init(a, b);
- mSphere.init(center, a);
+ aabb_.init(a, b);
+ sphere_.init(center, a);
}
-void Character::draw(Mf::Scalar alpha) const
+void Character::draw(moof::scalar alpha) const
{
- Mf::State2 state = getState(alpha);
- Mf::Vector2 position = state.position;
+ moof::state2 state = moof::rigid_body2::state(alpha);
+ moof::vector2 position = state.position;
//glColor3f(1.0f, 1.0f, 1.0f);
tilemap.bind();
- Mf::Texture::TileIndex frame = animation.getFrame();
- Mf::Texture::Orientation orientation = Mf::Texture::NORMAL;
+ int frame = animation.getFrame();
+ moof::texture::orientation orientation = moof::texture::normal;
- if (mState.velocity[0] < 0.0) orientation = Mf::Texture::REVERSE;
+ if (state_.velocity[0] < 0.0) orientation = moof::texture::reverse;
- Mf::Scalar coords[8];
- tilemap.getTileCoords(frame, coords, orientation);
+ moof::scalar coords[8];
+ tilemap.tile_coordinates(frame, coords, orientation);
- Mf::Scalar s = 0.5;
+ moof::scalar s = 0.5;
glBegin(GL_TRIANGLE_FAN);
glTexCoord(coords[0], coords[1]);
}
-/*int Character::getOctant(const Mf::Aabb<3>& aabb) const
+/*int Character::getOctant(const moof::Aabb<3>& aabb) const
{
int octantNum = -1;
- Mf::Plane::Halfspace halfspace;
+ moof::plane::halfspace halfspace;
- Mf::Plane xy = aabb.getPlaneXY();
- halfspace = xy.intersects(mSphere);
- if (halfspace == Mf::Plane::INTERSECT)
+ moof::plane xy = aabb.xy_plane();
+ halfspace = xy.intersects(sphere_);
+ if (halfspace == moof::plane::intersecting)
{
- halfspace = xy.intersects(mAabb);
+ halfspace = xy.intersects(aabb_);
}
- if (halfspace == Mf::Plane::POSITIVE)
+ if (halfspace == moof::plane::positive)
{
- Mf::Plane xz = aabb.getPlaneXZ();
- halfspace = xz.intersects(mSphere);
- if (halfspace == Mf::Plane::INTERSECT)
+ moof::plane xz = aabb.xz_plane();
+ halfspace = xz.intersects(sphere_);
+ if (halfspace == moof::plane::intersecting)
{
- halfspace = xz.intersects(mAabb);
+ halfspace = xz.intersects(aabb_);
}
- if (halfspace == Mf::Plane::POSITIVE)
+ if (halfspace == moof::plane::positive)
{
- Mf::Plane yz = aabb.getPlaneYZ();
- halfspace = yz.intersects(mSphere);
- if (halfspace == Mf::Plane::INTERSECT)
+ moof::plane yz = aabb.yz_plane();
+ halfspace = yz.intersects(sphere_);
+ if (halfspace == moof::plane::intersecting)
{
- halfspace = yz.intersects(mAabb);
+ halfspace = yz.intersects(aabb_);
}
- if (halfspace == Mf::Plane::POSITIVE)
+ if (halfspace == moof::plane::positive)
{
octantNum = 2;
}
- else if (halfspace == Mf::Plane::NEGATIVE)
+ else if (halfspace == moof::plane::negative)
{
octantNum = 3;
}
}
- else if (halfspace == Mf::Plane::NEGATIVE)
+ else if (halfspace == moof::plane::negative)
{
- Mf::Plane yz = aabb.getPlaneYZ();
- halfspace = yz.intersects(mSphere);
- if (halfspace == Mf::Plane::INTERSECT)
+ moof::plane yz = aabb.yz_plane();
+ halfspace = yz.intersects(sphere_);
+ if (halfspace == moof::plane::intersecting)
{
- halfspace = yz.intersects(mAabb);
+ halfspace = yz.intersects(aabb_);
}
- if (halfspace == Mf::Plane::POSITIVE)
+ if (halfspace == moof::plane::positive)
{
octantNum = 1;
}
- else if (halfspace == Mf::Plane::NEGATIVE)
+ else if (halfspace == moof::plane::negative)
{
octantNum = 0;
}
}
}
- else if (halfspace == Mf::Plane::NEGATIVE)
+ else if (halfspace == moof::plane::negative)
{
- Mf::Plane xz = aabb.getPlaneXZ();
- halfspace = xz.intersects(mSphere);
- if (halfspace == Mf::Plane::INTERSECT)
+ moof::plane xz = aabb.xz_plane();
+ halfspace = xz.intersects(sphere_);
+ if (halfspace == moof::plane::intersecting)
{
- halfspace = xz.intersects(mAabb);
+ halfspace = xz.intersects(aabb_);
}
- if (halfspace == Mf::Plane::POSITIVE)
+ if (halfspace == moof::plane::positive)
{
- Mf::Plane yz = aabb.getPlaneYZ();
- halfspace = yz.intersects(mSphere);
- if (halfspace == Mf::Plane::INTERSECT)
+ moof::plane yz = aabb.yz_plane();
+ halfspace = yz.intersects(sphere_);
+ if (halfspace == moof::plane::intersecting)
{
- halfspace = yz.intersects(mAabb);
+ halfspace = yz.intersects(aabb_);
}
- if (halfspace == Mf::Plane::POSITIVE)
+ if (halfspace == moof::plane::positive)
{
octantNum = 6;
}
- else if (halfspace == Mf::Plane::NEGATIVE)
+ else if (halfspace == moof::plane::negative)
{
octantNum = 7;
}
}
- else if (halfspace == Mf::Plane::NEGATIVE)
+ else if (halfspace == moof::plane::negative)
{
- Mf::Plane yz = aabb.getPlaneYZ();
- halfspace = yz.intersects(mSphere);
- if (halfspace == Mf::Plane::INTERSECT)
+ moof::plane yz = aabb.yz_plane();
+ halfspace = yz.intersects(sphere_);
+ if (halfspace == moof::plane::intersecting)
{
- halfspace = yz.intersects(mAabb);
+ halfspace = yz.intersects(aabb_);
}
- if (halfspace == Mf::Plane::POSITIVE)
+ if (halfspace == moof::plane::positive)
{
octantNum = 5;
}
- else if (halfspace == Mf::Plane::NEGATIVE)
+ else if (halfspace == moof::plane::negative)
{
octantNum = 4;
}
*/
-void Character::addImpulse(Mf::Vector2 impulse)
+void Character::addImpulse(moof::vector2 impulse)
{
- mState.momentum += impulse;
+ state_.momentum += impulse;
}
-void Character::addForce(Mf::Vector2 force)
+void Character::addForce(moof::vector2 force)
{
- mState.force += force;
+ state_.force += force;
}
-void Character::setPosition(Mf::Vector2 position)
+void Character::setPosition(moof::vector2 position)
{
- mState.position = position;
+ state_.position = position;
}
#include <boost/shared_ptr.hpp>
-#include <Moof/Aabb.hh>
-#include <Moof/Entity.hh>
-#include <Moof/Math.hh>
-#include <Moof/RigidBody.hh>
-#include <Moof/Sphere.hh>
-#include <Moof/Texture.hh>
+#include <moof/aabb.hh>
+#include <moof/entity.hh>
+#include <moof/math.hh>
+#include <moof/rigid_body.hh>
+#include <moof/sphere.hh>
+#include <moof/texture.hh>
#include "Animation.hh"
* includes the heroine herself and the bad guys.
*/
-class Character : public Mf::RigidBody2
+class Character : public moof::rigid_body2
{
public:
Character(const std::string& name);
virtual ~Character() {}
- virtual void update(Mf::Scalar t, Mf::Scalar dt);
- virtual void draw(Mf::Scalar alpha) const;
+ virtual void update(moof::scalar t, moof::scalar dt);
+ virtual void draw(moof::scalar alpha) const;
- void addImpulse(Mf::Vector2 impulse);
- void addForce(Mf::Vector2 force);
- void setPosition(Mf::Vector2 position);
+ void addImpulse(moof::vector2 impulse);
+ void addForce(moof::vector2 force);
+ void setPosition(moof::vector2 position);
- //virtual int getOctant(const Mf::Aabb<3>& aabb) const;
+ //virtual int getOctant(const moof::Aabb<3>& aabb) const;
- Mf::Texture tilemap;
+ moof::texture tilemap;
Animation animation;
};
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <sstream>
-
-#include "ErrorHandler.hh"
-
-
-std::string getErrorString(const Mf::Error& error)
-{
- std::string str;
-
- switch(error.code())
- {
- case Mf::Error::ALC_INIT:
- str += "An error occurred during OpenAL initialization: ";
- str += error.what();
- return str;
-
- case Mf::Error::FASTEVENTS_INIT:
- case Mf::Error::SDL_INIT:
- str += "An error occurred during SDL initialization: ";
- str += error.what();
- return str;
-
- case Mf::Error::FILE_NOT_FOUND:
- str += "A required file (";
- str += error.what();
- str += ") could not be found.";
- return str;
-
- case Mf::Error::OPENAL_INIT:
- str += "The audio library returned an error: ";
- str += error.what();
- return str;
-
- case Mf::Error::RESOURCE_NOT_FOUND:
- str += "A required resource (";
- str += error.what();
- str += ") could not be found.";
- return str;
-
- case Mf::Error::SCRIPT_ERROR:
- str += "An error occurred in a script: ";
- str == error.what();
- return str;
-
- case Mf::Error::SDL_VIDEOMODE:
- str += "An error occurred while trying to set up the graphics.";
- return str;
-
- case Mf::Error::UNKNOWN_AUDIO_FORMAT:
- str += "An error occurred while trying to load an audio file, ";
- str += error.what();
- str += ".";
- return str;
-
- case Mf::Error::UNKNOWN_IMAGE_FORMAT:
- str += "An error occurred while trying to load an image file, ";
- str += error.what();
- str += ".";
- return str;
- }
-
- std::ostringstream stream;
- stream << "An unknown error (code " << error.code() << ") occurred.";
- return stream.str();
-}
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _ERRORHANDLER_HH_
-#define _ERRORHANDLER_HH_
-
-#include <Moof/Error.hh>
-
-
-std::string getErrorString(const Mf::Error& error);
-
-
-#endif // _ERRORHANDLER_HH_
-
*
**************************************************************************/
-#include <Moof/Error.hh>
-#include <Moof/Log.hh>
-#include <Moof/Math.hh>
-#include <Moof/OpenGL.hh>
-#include <Moof/Settings.hh>
-#include <Moof/Video.hh>
+#include <stdexcept>
+
+#include <moof/log.hh>
+#include <moof/math.hh>
+#include <moof/opengl.hh>
+#include <moof/settings.hh>
+#include <moof/video.hh>
#include "GameLayer.hh"
void GameLayer::loadSceneLoader()
{
- mState.script.importStandardLibraries();
- importLogFunctions(mState.script);
+ state_.script.import_standard_libraries();
+ moof::log::import(state_.script);
std::string path("loader");
- if (!Scene::getPath(path))
+ if (!Scene::find_path(path))
{
- throw Mf::Error(Mf::Error::RESOURCE_NOT_FOUND, "loader");
+ throw std::runtime_error("cannot find scene loader script");
}
- Mf::Script::Result status = mState.script.doFile(path);
- if (status != Mf::Script::SUCCESS)
+ moof::script::status status = state_.script.do_file(path);
+ if (status != moof::script::success)
{
std::string str;
- mState.script[-1].get(str);
-
- throw Mf::Error(Mf::Error::SCRIPT_ERROR, str);
+ state_.script[-1].get(str);
+ throw std::runtime_error("script error: " + str);
}
- mState.script.globals().pushField("scenes");
- mState.script.top().get(mState.sceneList);
- if (mState.sceneList.size() == 0)
+ state_.script.globals().push_field("scenes");
+ state_.script.top().get(state_.sceneList);
+ if (state_.sceneList.size() == 0)
{
- throw Mf::Error(Mf::Error::SCRIPT_ERROR,
- "no variable `scenes' within loader");
+ throw std::runtime_error("no variable `scenes' in script loader.");
}
}
-void GameLayer::advanceScene(Mf::Settings& settings)
+void GameLayer::advanceScene(moof::settings& settings)
{
- if (mState.sceneList.size() != 0)
+ if (state_.sceneList.size() != 0)
{
- mState.scene = Scene::alloc(mState.sceneList[0]);
- mState.sceneList.erase(mState.sceneList.begin());
+ state_.scene = Scene::alloc(state_.sceneList[0]);
+ state_.sceneList.erase(state_.sceneList.begin());
- Mf::Script::Result status = mState.scene->load(settings,
- mState.script);
- if (status != Mf::Script::SUCCESS)
+ moof::script::status status = state_.scene->load(settings,
+ state_.script);
+ if (status != moof::script::success)
{
std::string str;
- mState.script[-1].get(str);
-
- throw Mf::Error(Mf::Error::SCRIPT_ERROR, str);
+ state_.script[-1].get(str);
+ throw std::runtime_error("script error: " + str);
}
- Mf::Script::Slot table = mState.script.globals().pushField("Event");
- if (table.isTable())
+ moof::script::slot table = state_.script.globals().push_field("Event");
+ if (table.is_table())
{
- mState.script.push("Think");
- table.pushField("Think");
- mState.script.registry().setField();
+ state_.script.push("Think");
+ table.push_field("Think");
+ state_.script.registry().set_field();
}
- mState.script.pop();
+ state_.script.pop();
}
}
mMusic("NightFusionIntro"),
mPunchSound("Thump")
{
- mMusic.setLooping(true);
+ mMusic.loop(true);
mMusic.enqueue("NightFusionLoop");
- //mMusic.setPosition(Mf::Vector3(10.0, 5.0, 0.0));
+ //mMusic.setPosition(moof::vector3(10.0, 5.0, 0.0));
mThinkTimer.init(boost::bind(&GameLayer::thinkTimer, this),
- 0.1, Mf::Timer::REPEAT);
+ 0.1, moof::timer::repeat);
- mState.heroine = Heroine::alloc();
- mState.heroine->animation.startSequence("FlyDiagonallyUp");
+ state_.heroine = Heroine::alloc();
+ state_.heroine->animation.startSequence("FlyDiagonallyUp");
- mState.interp.init(0.0, 1.0);
- mState.interp.reset(4.0, Mf::Interp::OSCILLATE);
+ state_.interp.init(0.0, 1.0, 4.0, moof::lerp_scalar::oscillate);
}
-void GameLayer::didAddToView()
+void GameLayer::did_add_to_view()
{
bool isMute = false;
settings().get("nomusic", isMute);
loadSceneLoader();
advanceScene(settings()); // load the first scene
- mHud = Hud::alloc(mState);
- addChild(mHud);
+ mHud = Hud::alloc(state_);
+ add_child(mHud);
mRay.direction.set(1.0, 0.0);
mCircle.radius = 2;
mRayTimer.init(boost::bind(&GameLayer::rayTimer, this),
- 1.0, Mf::Timer::REPEAT);
+ 1.0, moof::timer::repeat);
- setProjection();
+ projection();
}
-void GameLayer::update(Mf::Scalar t, Mf::Scalar dt)
+void GameLayer::update(moof::scalar t, moof::scalar dt)
{
- if (!mState.scene) return;
- mState.camera.update(t, dt);
- mState.heroine->update(t, dt);
+ if (!state_.scene) return;
+ state_.camera.update(t, dt);
+ state_.heroine->update(t, dt);
- mState.scene->checkForCollision(*mState.heroine);
+ state_.scene->checkForCollision(*state_.heroine);
- Mf::Vector3 cam= -Mf::promote(mState.heroine->getState().position, 8);
- mState.camera.setPosition(cam);
+ moof::vector3 cam= -moof::promote(state_.heroine->state().position, 8);
+ state_.camera.position(cam);
- mRay.point = mState.heroine->getState().position;
+ mRay.point = state_.heroine->state().position;
- Mf::View::update(t, dt);
+ moof::view::update(t, dt);
}
void GameLayer::thinkTimer()
{
- mState.script.registry().pushField("Think");
- if (mState.script[-1].isFunction()) mState.script.call();
- else mState.script.pop();
+ state_.script.registry().push_field("Think");
+ if (state_.script[-1].is_function()) state_.script.call();
+ else state_.script.pop();
}
void GameLayer::rayTimer()
{
- Mf::Ray2::Contact meh;
- std::list<Mf::Ray2::Contact> hits;
- Mf::Vector2 point;
+ moof::ray2::contact meh;
+ std::list<moof::ray2::contact> hits;
+ moof::vector2 point;
- bool bam = mLine.intersectRay(mRay, meh);
+ bool bam = mLine.intersect_ray(mRay, meh);
if (bam)
{
//meh.normal.normalize();
//hits.push_back(meh);
mRay.solve(point, meh.distance);
- Mf::logInfo << "line: d = " << meh.distance << std::endl;
- Mf::logInfo << " P = " << point << std::endl;
- Mf::logInfo << " n = " << meh.normal << std::endl;
+ moof::log_info << "line: d = " << meh.distance << std::endl;
+ moof::log_info << " P = " << point << std::endl;
+ moof::log_info << " n = " << meh.normal << std::endl;
}
- bam = mCircle.intersectRay(mRay, meh);
+ bam = mCircle.intersect_ray(mRay, meh);
if (bam)
{
meh.normal.normalize();
hits.push_back(meh);
}
- if (mState.scene->castRay(mRay, hits))
+ if (state_.scene->castRay(mRay, hits))
{
hits.front().normal.normalize();
mRay.solve(point, hits.front().distance);
- Mf::logInfo << "scene: d = " << hits.front().distance << std::endl;
- Mf::logInfo << " P = " << point << std::endl;
- Mf::logInfo << " n = " << hits.front().normal << std::endl;
+ moof::log_info << "scene: d = " << hits.front().distance << std::endl;
+ moof::log_info << " P = " << point << std::endl;
+ moof::log_info << " n = " << hits.front().normal << std::endl;
}
}
-void GameLayer::draw(Mf::Scalar alpha) const
+void GameLayer::draw(moof::scalar alpha) const
{
- if (!mState.scene) return;
- mState.camera.uploadToGL(alpha);
+ if (!state_.scene) return;
+ state_.camera.upload_to_gl(alpha);
// DRAW THE SCENE
- Mf::Texture::resetBind();
+ moof::texture::reset_binding();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- mState.scene->drawIfVisible(alpha, mState.camera.getFrustum());
- mState.heroine->draw(alpha);
+ state_.scene->draw_if_visible(alpha, state_.camera.frustum());
+ state_.heroine->draw(alpha);
mRay.draw();
mLine.draw();
mCircle.draw();
- Mf::View::draw(alpha);
+ moof::view::draw(alpha);
}
-bool GameLayer::handleEvent(const Mf::Event& event)
+bool GameLayer::handle_event(const moof::event& event)
{
- if (Mf::View::handleEvent(event)) return true;
+ if (moof::view::handle_event(event)) return true;
switch (event.type)
{
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_SPACE)
{
- mState.heroine->animation.startSequence("Flattened");
- Mf::logInfo("thump!");
+ state_.heroine->animation.startSequence("Flattened");
+ moof::log_info("thump!");
mPunchSound.play();
return true;
}
}
else if (event.key.keysym.sym == SDLK_PAGEUP)
{
- mRay.direction = cml::rotate_vector_2D(mRay.direction,
- cml::rad(10.0));
+ mRay.direction = moof::rotate_vector_2D(mRay.direction,
+ moof::rad(10.0));
return true;
}
else if (event.key.keysym.sym == SDLK_PAGEDOWN)
{
- mRay.direction = cml::rotate_vector_2D(mRay.direction,
- cml::rad(-10.0));
+ mRay.direction = moof::rotate_vector_2D(mRay.direction,
+ moof::rad(-10.0));
return true;
}
else if (event.key.keysym.sym == SDLK_r)
advanceScene(settings());
return true;
}
- return mState.heroine->handleEvent(event);
+ return state_.heroine->handle_event(event);
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_ESCAPE)
{
- parent().removeChild(this);
+ parent().remove_child(this);
return true;
}
else if (event.key.keysym.sym == SDLK_h)
{
- addChild(mHud);
+ add_child(mHud);
return true;
}
- return mState.heroine->handleEvent(event);
+ return state_.heroine->handle_event(event);
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
- mState.camera.handleEvent(event);
+ state_.camera.handle_event(event);
return true;
case SDL_VIDEORESIZE:
- setProjection(event.resize.w, event.resize.h);
+ projection(event.resize.w, event.resize.h);
break;
}
}
-void GameLayer::setProjection()
+void GameLayer::projection()
{
- setProjection(video().getWidth(), video().getHeight());
+ projection(video().width(), video().height());
}
-void GameLayer::setProjection(Mf::Scalar width, Mf::Scalar height)
+void GameLayer::projection(moof::scalar width, moof::scalar height)
{
- mState.camera.setProjection(cml::rad(45.0),
- width / height,
- SCALAR(1.0), SCALAR(200.0));
+ state_.camera.projection(moof::rad(45.0),
+ width / height,
+ SCALAR(1.0), SCALAR(200.0));
}
#include <boost/shared_ptr.hpp>
-#include <Moof/Math.hh>
-#include <Moof/Sound.hh>
+#include <moof/math.hh>
+#include <moof/sound.hh>
-#include <Moof/Line.hh> // TODO
-#include <Moof/Plane.hh>
-#include <Moof/Ray.hh>
-#include <Moof/Sphere.hh>
-#include <Moof/Timer.hh>
-#include <Moof/View.hh>
+#include <moof/line.hh> // TODO
+#include <moof/plane.hh>
+#include <moof/ray.hh>
+#include <moof/sphere.hh>
+#include <moof/timer.hh>
+#include <moof/view.hh>
#include "GameState.hh"
#include "Hud.hh"
class GameLayer;
typedef boost::shared_ptr<GameLayer> GameLayerP;
-class GameLayer : public Mf::View
+class GameLayer : public moof::view
{
public:
}
GameLayer();
- void didAddToView();
+ void did_add_to_view();
- void update(Mf::Scalar t, Mf::Scalar dt);
- void draw(Mf::Scalar alpha) const;
- bool handleEvent(const Mf::Event& event);
+ void update(moof::scalar t, moof::scalar dt);
+ void draw(moof::scalar alpha) const;
+ bool handle_event(const moof::event& event);
private:
void loadSceneLoader();
- void advanceScene(Mf::Settings& settings);
+ void advanceScene(moof::settings& settings);
void thinkTimer();
- void setProjection();
- void setProjection(Mf::Scalar width, Mf::Scalar height);
+ void projection();
+ void projection(moof::scalar width, moof::scalar height);
- GameState mState;
- Mf::Timer mThinkTimer;
+ GameState state_;
+ moof::timer mThinkTimer;
HudP mHud;
- Mf::SoundStream mMusic;
- Mf::Sound mPunchSound;
+ moof::sound_stream mMusic;
+ moof::sound mPunchSound;
- Mf::Ray2 mRay;
- Mf::Line2 mLine;
- Mf::Circle mCircle;
+ moof::ray2 mRay;
+ moof::line2 mLine;
+ moof::circle mCircle;
- Mf::Timer mRayTimer;
+ moof::timer mRayTimer;
void rayTimer();
};
#define _GAMESTATE_HH_
/**
- * @file GameState.hh
+ * \file GameState.hh
* The data.
*/
#include <boost/shared_ptr.hpp>
-#include <Moof/Camera.hh>
-#include <Moof/Interpolator.hh>
-#include <Moof/Script.hh>
+#include <moof/camera.hh>
+#include <moof/interpolator.hh>
+#include <moof/script.hh>
#include "Character.hh"
#include "Heroine.hh"
struct GameState
{
- Mf::Script script;
+ moof::script script;
std::vector<std::string> sceneList;
HeroineP heroine;
SceneP scene;
- Mf::Lerp interp;
+ moof::lerp_scalar interp;
- Mf::Camera camera;
+ moof::camera camera;
};
*
**************************************************************************/
-#include <Moof/Sound.hh>
+#include <moof/log.hh>
+#include <moof/sound.hh>
#include "Heroine.hh"
-#include "Log.hh"
-
Heroine::Heroine() :
Character("Heroine") {}
-void Heroine::update(Mf::Scalar t, Mf::Scalar dt)
+void Heroine::update(moof::scalar t, moof::scalar dt)
{
Character::update(t, dt);
- Mf::Vector3 at(0.0, 0.0, 0.0);
- const Mf::Vector3 up(0.0, 1.0, 0.0);
+ moof::vector3 at(0.0, 0.0, 0.0);
+ const moof::vector3 up(0.0, 1.0, 0.0);
- if (mState.velocity[0] < 0.0) at[0] = -1.0;
+ if (state_.velocity[0] < 0.0) at[0] = -1.0;
else at[0] = 1.0;
- Mf::Sound::setListenerPosition(Mf::promote(mState.position));
- Mf::Sound::setListenerVelocity(Mf::promote(mState.velocity));
- Mf::Sound::setListenerOrientation(at, up);
+ moof::sound::listener_position(moof::promote(state_.position));
+ moof::sound::listener_velocity(moof::promote(state_.velocity));
+ moof::sound::listener_orientation(at, up);
}
-bool Heroine::handleEvent(const Mf::Event& event)
+bool Heroine::handle_event(const moof::event& event)
{
- Mf::Scalar force = 40.0;
+ moof::scalar force = 40.0;
switch (event.type)
{
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_a)
{
- mState.force += Mf::Vector2(-force, 0.0);
+ state_.force += moof::vector2(-force, 0.0);
return true;
}
else if (event.key.keysym.sym == SDLK_d)
{
- mState.force += Mf::Vector2(force, 0.0);
+ state_.force += moof::vector2(force, 0.0);
return true;
}
else if (event.key.keysym.sym == SDLK_s)
{
- mState.force += Mf::Vector2(0.0, -force);
+ state_.force += moof::vector2(0.0, -force);
return true;
}
else if (event.key.keysym.sym == SDLK_w)
{
- mState.force += Mf::Vector2(0.0, force);
+ state_.force += moof::vector2(0.0, force);
return true;
}
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_a)
{
- mState.force += Mf::Vector2(force, 0.0);
+ state_.force += moof::vector2(force, 0.0);
return true;
}
else if (event.key.keysym.sym == SDLK_d)
{
- mState.force += Mf::Vector2(-force, 0.0);
+ state_.force += moof::vector2(-force, 0.0);
return true;
}
else if (event.key.keysym.sym == SDLK_s)
{
- mState.force += Mf::Vector2(0.0, force);
+ state_.force += moof::vector2(0.0, force);
return true;
}
else if (event.key.keysym.sym == SDLK_w)
{
- mState.force += Mf::Vector2(0.0, -force);
+ state_.force += moof::vector2(0.0, -force);
return true;
}
}
#include <boost/shared_ptr.hpp>
-#include <Moof/Event.hh>
+#include <moof/event.hh>
#include "Character.hh"
return HeroineP(new Heroine);
}
- void update(Mf::Scalar t, Mf::Scalar dt);
- bool handleEvent(const Mf::Event& event);
+ void update(moof::scalar t, moof::scalar dt);
+ bool handle_event(const moof::event& event);
};
*
**************************************************************************/
-#include <Moof/Aabb.hh>
-#include <Moof/Log.hh>
-#include <Moof/OpenGL.hh>
-#include <Moof/Video.hh>
+#include <moof/aabb.hh>
+#include <moof/log.hh>
+#include <moof/opengl.hh>
+#include <moof/video.hh>
#include "Hud.hh"
-ProgressBar::ProgressBar(const Mf::Texture& tilemap,
- Mf::Texture::TileIndex index) :
+ProgressBar::ProgressBar(const moof::texture& tilemap, int index) :
mProgress(0.0),
mTilemap(tilemap)
{
- tilemap.getTileCoords(index, mTexCoords);
+ tilemap.tile_coordinates(index, mTexCoords);
- Mf::Scalar half = (mTexCoords[2] - mTexCoords[0]) / 2.0 + mTexCoords[0];
+ moof::scalar half = (mTexCoords[2] - mTexCoords[0]) / 2.0 + mTexCoords[0];
mMidCoords[0] = half - 0.01;
mMidCoords[1] = half + 0.01;
}
-void ProgressBar::resize(const Mf::Rectangle& rect)
+void ProgressBar::resize(const moof::rectangle& rect)
{
- Mf::logInfo << "rect: " << rect.min << ", " << rect.max << std::endl;
- Mf::Scalar height = rect.max[1] - rect.min[1];
- Mf::Scalar halfHeight = height / 2.0;
+ moof::log_info << "rect: " << rect.min << ", " << rect.max << std::endl;
+ moof::scalar height = rect.max[1] - rect.min[1];
+ moof::scalar halfHeight = height / 2.0;
mWidth = rect.max[0] - rect.min[0] - height;
ASSERT(mWidth > 0);
mVertices[0] = rect.min;
- mVertices[1] = Mf::Vector2(rect.min[0] + halfHeight, rect.min[1]);
+ mVertices[1] = moof::vector2(rect.min[0] + halfHeight, rect.min[1]);
mVertices[2] = mVertices[1];
- mVertices[3] = Mf::Vector2(rect.min[0] + height, rect.min[1]);
- mVertices[4] = Mf::Vector2(rect.min[0] + height, rect.max[1]);
- mVertices[5] = Mf::Vector2(rect.min[0] + halfHeight, rect.max[1]);
+ mVertices[3] = moof::vector2(rect.min[0] + height, rect.min[1]);
+ mVertices[4] = moof::vector2(rect.min[0] + height, rect.max[1]);
+ mVertices[5] = moof::vector2(rect.min[0] + halfHeight, rect.max[1]);
mVertices[6] = mVertices[5];
- mVertices[7] = Mf::Vector2(rect.min[0], rect.max[1]);
+ mVertices[7] = moof::vector2(rect.min[0], rect.max[1]);
setProgress(mProgress);
}
-void ProgressBar::setProgress(Mf::Scalar progress)
+void ProgressBar::setProgress(moof::scalar progress)
{
- Mf::Scalar halfHeight = (mVertices[7][1] - mVertices[0][1]) / 2.0;
+ moof::scalar halfHeight = (mVertices[7][1] - mVertices[0][1]) / 2.0;
mVertices[2][0] = mVertices[1][0] + progress * mWidth;
mVertices[3][0] = mVertices[1][0] + progress * mWidth + halfHeight;
mProgress = progress;
}
-void ProgressBar::draw(Mf::Scalar alpha) const
+void ProgressBar::draw(moof::scalar alpha) const
{
- if (Mf::isEqual(mProgress, 0.0))
+ if (moof::is_equal(mProgress, 0.0))
{
// don't draw anything if the progress is 0%
return;
Hud::Hud(GameState& state) :
- mState(state),
- mBar1(Mf::Texture("StatusBars"), 0),
- mBar2(Mf::Texture("StatusBars"), 2),
+ state_(state),
+ mBar1(moof::texture("StatusBars"), 0),
+ mBar2(moof::texture("StatusBars"), 2),
mFont("Font")
{
- Mf::Video* video = Mf::Video::current();
+ moof::video* video = moof::video::current();
ASSERT(video && "a current video context should be set");
- resize(video->getWidth(), video->getHeight());
+ resize(video->width(), video->height());
}
void Hud::resize(int width, int height)
{
- cml::matrix_orthographic_RH(mProjection,
- SCALAR(0.0),
- Mf::Scalar(width), SCALAR(0.0), Mf::Scalar(height),
- SCALAR(1.0), SCALAR(-1.0), cml::z_clip_neg_one);
+ moof::matrix_orthographic_RH(mProjection, SCALAR(0.0),
+ moof::scalar(width), SCALAR(0.0),
+ moof::scalar(height),
+ SCALAR(1.0), SCALAR(-1.0), moof::z_clip_neg_one);
// position the two progress bars at the top-left of the screen
- mBar1.resize(Mf::Rectangle(20, height - 51, 0.7 * width, height - 3));
- mBar2.resize(Mf::Rectangle(20, height - 28, 0.7 * width, height - 70));
+ mBar1.resize(moof::rectangle(20, height - 51, 0.7 * width, height - 3));
+ mBar2.resize(moof::rectangle(20, height - 28, 0.7 * width, height - 70));
setBar1Progress(0.05);
setBar2Progress(0.0);
}
-void Hud::update(Mf::Scalar t, Mf::Scalar dt)
+void Hud::update(moof::scalar t, moof::scalar dt)
{
- mState.interp.update(t, dt);
- setBar1Progress(mState.interp.getState(dt));
- setBar2Progress(1.0 - mState.interp.getState(dt));
+ state_.interp.update(t, dt);
+ setBar1Progress(state_.interp.state(dt));
+ setBar2Progress(1.0 - state_.interp.state(dt));
}
-void Hud::draw(Mf::Scalar alpha) const
+void Hud::draw(moof::scalar alpha) const
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glPopMatrix();
}
-bool Hud::handleEvent(const Mf::Event& event)
+bool Hud::handle_event(const moof::event& event)
{
switch (event.type)
{
if (event.key.keysym.sym == SDLK_h)
{
// don't want the hud anymore
- parent().removeChild(this);
+ parent().remove_child(this);
- Mf::logWarning("okay bye bye hud");
+ moof::log_warning("okay bye bye hud");
return true;
}
break;
* Heads-up Display
*/
-#include <Moof/Drawable.hh>
-#include <Moof/Math.hh>
-//#include <Moof/Rectangle.hh>
-#include <Moof/Texture.hh>
-#include <Moof/View.hh>
+#include <moof/drawable.hh>
+#include <moof/math.hh>
+//#include <moof/rectangle.hh>
+#include <moof/texture.hh>
+#include <moof/view.hh>
#include "GameState.hh"
-class Rectangle;
+class rectangle;
// TODO this stuff is still just hacked up
-class ProgressBar : public Mf::Drawable
+class ProgressBar : public moof::drawable
{
public:
- ProgressBar(const Mf::Texture& tilemap, Mf::Texture::TileIndex index);
+ ProgressBar(const moof::texture& tilemap, int index);
- void resize(const Mf::Rectangle& rect);
+ void resize(const moof::rectangle& rect);
- void setProgress(Mf::Scalar progress);
+ void setProgress(moof::scalar progress);
- void draw(Mf::Scalar alpha = 0.0) const;
+ void draw(moof::scalar alpha = 0.0) const;
private:
- Mf::Scalar mProgress;
+ moof::scalar mProgress;
- Mf::Vector2 mVertices[8];
- Mf::Scalar mWidth;
+ moof::vector2 mVertices[8];
+ moof::scalar mWidth;
- Mf::Texture mTilemap;
- Mf::Scalar mTexCoords[8];
- Mf::Scalar mMidCoords[2];
+ moof::texture mTilemap;
+ moof::scalar mTexCoords[8];
+ moof::scalar mMidCoords[2];
};
class Hud;
typedef boost::shared_ptr<Hud> HudP;
-class Hud : public Mf::View
+class Hud : public moof::view
{
public:
Hud(GameState& state);
- void setBar1Progress(Mf::Scalar progress)
+ void setBar1Progress(moof::scalar progress)
{
// pass through
mBar1.setProgress(progress);
}
- void setBar2Progress(Mf::Scalar progress)
+ void setBar2Progress(moof::scalar progress)
{
// pass through
mBar2.setProgress(progress);
void resize(int width, int height);
- void update(Mf::Scalar t, Mf::Scalar dt);
- void draw(Mf::Scalar alpha = 0.0) const;
- bool handleEvent(const Mf::Event& event);
+ void update(moof::scalar t, moof::scalar dt);
+ void draw(moof::scalar alpha = 0.0) const;
+ bool handle_event(const moof::event& event);
private:
- GameState& mState;
+ GameState& state_;
ProgressBar mBar1;
ProgressBar mBar2;
unsigned mNumber;
- Mf::Texture mFont;
+ moof::texture mFont;
- Mf::Matrix4 mProjection;
+ moof::matrix4 mProjection;
};
**************************************************************************/
#include <cstdlib> // atexit, getenv
+#include <exception>
#include <functional>
#include <iostream>
#include <string>
#include <unistd.h> // access
-#include <Moof/Log.hh>
-#include <Moof/ModalDialog.hh>
-#include <Moof/OpenGL.hh>
-#include <Moof/Resource.hh>
-#include <Moof/Settings.hh>
-#include <Moof/Video.hh>
+#include <moof/log.hh>
+#include <moof/modal_dialog.hh>
+#include <moof/opengl.hh>
+#include <moof/resource.hh>
+#include <moof/settings.hh>
+#include <moof/video.hh>
-#include "ErrorHandler.hh"
#include "GameLayer.hh"
#include "Main.hh"
#include "TitleLayer.hh"
#include "version.h"
-Main::Main(Mf::Settings& settings, Mf::Video& video) :
- Mf::View(settings, video)
+Main::Main(moof::settings& settings, moof::video& video) :
+ moof::view(settings, video)
{
- Mf::Dispatch& dispatch = Mf::Dispatch::global();
- mNewContextDispatch = dispatch.addTarget("video.newcontext",
+ moof::dispatcher& dispatcher = moof::dispatcher::global();
+ mNewContextDispatch = dispatcher.add_target("video.newcontext",
boost::bind(&Main::setupGL));
setupGL();
}
-void Main::update(Mf::Scalar t, Mf::Scalar dt)
+void Main::update(moof::scalar t, moof::scalar dt)
{
if (children().size() == 0)
{
- //Mf::logWarning("main view has no children");
+ //moof::log_warning("main view has no children");
//stop();
//return;
- addChild(TitleLayer::alloc());
+ add_child(TitleLayer::alloc());
}
- Mf::View::update(t, dt);
+ moof::view::update(t, dt);
}
-void Main::draw(Mf::Scalar alpha) const
+void Main::draw(moof::scalar alpha) const
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- Mf::View::draw(alpha);
+ moof::view::draw(alpha);
}
-bool Main::handleEvent(const Mf::Event& event)
+bool Main::handle_event(const moof::event& event)
{
- if (Mf::View::handleEvent(event)) return true;
+ if (moof::view::handle_event(event)) return true;
switch (event.type)
{
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_f)
{
- video().toggleFull();
+ video().toggle_fullscreen();
}
else if (event.key.keysym.sym == SDLK_l)
{
- video().toggleCursorGrab();
- video().toggleCursorVisible();
+ video().toggle_cursor_captured();
+ video().toggle_cursor_visible();
}
break;
// 4. YOINKRC (environment)
std::string path("yoinkrc");
- Mf::Resource::getPath(path);
+ moof::resource::find_path(path);
#if !defined(_WIN32)
path += ":/etc/yoinkrc";
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
- //Mf::Scalar ratio = Mf::core.getVideo()->getWidth() /
- //Mf::core.getVideo()->getHeight();
+ //moof::scalar ratio = moof::core.getVideo()->width() /
+ //moof::core.getVideo()->height();
//gluPerspective(60.0, ratio, 1.0, 250.0);
//glMatrixMode(GL_MODELVIEW);
}
-#include <Moof/Socket.hh>
+#include <moof/socket.hh>
int main(int argc, char* argv[])
{
- Mf::ResolverTask task("4950", "compy", SOCK_DGRAM);
+ moof::resolver_task task("4950", "lappy");
task.run();
int i = task.wait();
- Mf::logWarning << "task ended with code: " << i << std::endl;
+ moof::log_warning("task ended with code:", i);
- std::vector<Mf::SocketAddress>::const_iterator it;
+ std::vector<moof::socket::address>::const_iterator it;
for (it = task.addresses().begin(); it != task.addresses().end(); ++it)
{
- Mf::SocketAddress addr = *it;
+ moof::socket::address addr = *it;
- Mf::logInfo << "address: " << addr.name() << ":" << addr.port()
- << " (" << addr.type() << ")" << std::endl;
+ moof::log_info("address:", addr, "(", addr.type(), ")");
}
+ //ASSERT(5 == 8 && "uh oh that's not right");
+
std::vector<uint8_t> hi;
for (int a = 0; a < 4000; a++)
hi.push_back(a);
}
- Mf::logInfo << "array size: " << hi.size() << std::endl;
- Mf::Packet packet;
+ moof::log_info("array size:", hi.size());
+ moof::packet packet;
packet << hi;
- Mf::SocketAddress addr("4950", "155.98.111.159", SOCK_DGRAM);
- //Mf::SocketAddress addr = Mf::SocketAddress::broadcast("4950");
- //Mf::SocketAddress addr("4950", "155.98.109.255", SOCK_DGRAM);
- //Mf::logInfo << "local addr: " << addr.name() << std::endl;
-
//for (it = task.addresses().begin(); it != task.addresses().end(); ++it)
//{
- int bcast = 0;
-
- //Mf::SocketAddress addr = *it;
- Mf::Socket sock(addr);
+ //moof::socket sock(*it);
+ moof::socket sock(moof::socket::address::broadcast("4950"));
+ //moof::socket sock("4950", "lappy", SOCK_DGRAM);
+ sock.set(SO_BROADCAST, 1);
sock.connect();
- sock.get(SO_BROADCAST, bcast);
- Mf::logInfo << "bcast: " << bcast << std::endl;
-
- sock.set(SO_BROADCAST, 1);
+ //if (sock.isConnected())
+ //{
+ moof::packet pack;
+ pack << "hello world";
+ sock.write(pack);
+ //sock.write(pack, sock.address());
+ moof::log_info("sent", pack.size(), "bytes");
- sock.get(SO_BROADCAST, bcast);
- Mf::logInfo << "bcast: " << bcast << std::endl;
+ const char* data = pack.bytes();
+ for (unsigned i = 0; i < pack.size(); ++i)
+ {
+ moof::log_warning("meh:", data[i]);
+ }
- Mf::logInfo << "sending packet of size: " << packet.size() << std::endl;
- //sock.write(packet);
- sock.write(&bcast, sizeof(bcast));
+ char data2[56];
+ pack.read(data2, 13);
+ for (int i = 0; i < 13; ++i)
+ {
+ moof::log_warning("meh:", data2[i]);
+ }
+ //}
+ //else
+ //{
+ //moof::log_error("NOT CONNECTED");
+ //}
//}
- return 0;
+ //return 0;
if (argc > 1)
hello();
atexit(goodbye);
- Mf::Resource::addSearchPaths(Main::getSearchPath());
+ moof::resource::add_search_paths(Main::getSearchPath());
- Mf::Settings settings(argc, argv, Main::getConfigPath());
+ moof::settings settings(argc, argv, Main::getConfigPath());
- Mf::Log::Level logLevel = Mf::Log::INFO;
+ enum moof::log::level logLevel = moof::log::info;
settings.get("loglevel", logLevel);
- Mf::Log::setLevel(logLevel);
+ moof::log::level(logLevel);
try
{
- Mf::Video::Attributes attributes(settings);
- attributes.caption = PACKAGE_STRING;
- attributes.icon = Mf::Resource::getPath(PACKAGE".png");
+ std::string iconPath(PACKAGE".png");
+ moof::resource::find_path(iconPath);
+ moof::image icon(iconPath);
+ icon.set_as_icon();
- Mf::Video video(attributes);
+ class moof::video::attributes attributes(settings);
+ moof::video video(PACKAGE_STRING, attributes);
Main mainView(settings, video);
mainView.run();
return 0;
}
- catch (const Mf::Error& error)
+ catch (const std::exception& e)
{
- Mf::ModalDialog dialog(Mf::ModalDialog::CRITICAL,
- PACKAGE_STRING, "Unhandled Exception",
- getErrorString(error));
+ moof::modal_dialog dialog(moof::modal_dialog::error,
+ PACKAGE_STRING, "Unhandled Exception",
+ e.what());
dialog.run();
return 1;
#include <boost/shared_ptr.hpp>
-#include <Moof/Dispatch.hh>
-#include <Moof/Math.hh>
-#include <Moof/View.hh>
+#include <moof/dispatcher.hh>
+#include <moof/math.hh>
+#include <moof/view.hh>
-namespace Mf
+namespace moof
{
- class Settings;
- class View;
+ class settings;
+ class view;
}
class Main;
typedef boost::shared_ptr<Main> MainP;
-class Main : public Mf::View
+class Main : public moof::view
{
public:
- Main(Mf::Settings& settings, Mf::Video& video);
+ Main(moof::settings& settings, moof::video& video);
- void update(Mf::Scalar t, Mf::Scalar dt);
- void draw(Mf::Scalar alpha) const;
- bool handleEvent(const Mf::Event& event);
+ void update(moof::scalar t, moof::scalar dt);
+ void draw(moof::scalar alpha) const;
+ bool handle_event(const moof::event& event);
static std::string getSearchPath();
static std::string getConfigPath();
*/
static void setupGL();
- Mf::Dispatch::Handle mNewContextDispatch;
+ moof::dispatcher::handle mNewContextDispatch;
};
noinst_LIBRARIES = libmoof.a
-libmoof_a_CPPFLAGS = -I$(top_srcdir)/src/Moof
+libmoof_a_CPPFLAGS = -I$(top_srcdir)/src/moof
libmoof_a_SOURCES = \
- Moof/Aabb.cc \
- Moof/Aabb.hh \
- Moof/Backend.cc \
- Moof/Backend.hh \
- Moof/Camera.cc \
- Moof/Camera.hh \
- Moof/Contact.hh \
- Moof/ConvertUTF.c \
- Moof/ConvertUTF.h \
- Moof/Cullable.hh \
- Moof/Dispatch.cc \
- Moof/Dispatch.hh \
- Moof/Drawable.hh \
- Moof/Entity.hh \
- Moof/Error.hh \
- Moof/Event.hh \
- Moof/Frustum.cc \
- Moof/Frustum.hh \
- Moof/HashTools.cc \
- Moof/HashTools.hh \
- Moof/Image.cc \
- Moof/Image.hh \
- Moof/Interpolator.hh \
- Moof/Line.hh \
- Moof/Log.cc \
- Moof/Log.hh \
- Moof/Manager.hh \
- Moof/Math.hh \
- Moof/ModalDialog.hh \
- Moof/Network.hh \
- Moof/Octree.hh \
- Moof/OpenGL.hh \
- Moof/Packet.cc \
- Moof/Packet.hh \
- Moof/Plane.cc \
- Moof/Plane.hh \
- Moof/Ray.hh \
- Moof/Resource.cc \
- Moof/Resource.hh \
- Moof/RigidBody.hh \
- Moof/Script.hh \
- Moof/Service.cc \
- Moof/Service.hh \
- Moof/Settings.cc \
- Moof/Settings.hh \
- Moof/Shape.hh \
- Moof/Socket.hh \
- Moof/Sound.cc \
- Moof/Sound.hh \
- Moof/Sphere.hh \
- Moof/StringTools.cc \
- Moof/StringTools.hh \
- Moof/Texture.cc \
- Moof/Texture.hh \
- Moof/Thread.hh \
- Moof/Timer.cc \
- Moof/Timer.hh \
- Moof/Video.cc \
- Moof/Video.hh \
- Moof/View.cc \
- Moof/View.hh \
- Moof/fastevents.c \
- Moof/fastevents.h \
+ moof/aabb.cc \
+ moof/aabb.hh \
+ moof/backend.cc \
+ moof/backend.hh \
+ moof/camera.cc \
+ moof/camera.hh \
+ moof/contact.hh \
+ moof/ConvertUTF.c \
+ moof/ConvertUTF.h \
+ moof/cullable.hh \
+ moof/dispatcher.cc \
+ moof/dispatcher.hh \
+ moof/drawable.hh \
+ moof/entity.hh \
+ moof/event.hh \
+ moof/frustum.cc \
+ moof/frustum.hh \
+ moof/hash.cc \
+ moof/hash.hh \
+ moof/image.cc \
+ moof/image.hh \
+ moof/interpolator.hh \
+ moof/line.hh \
+ moof/log.cc \
+ moof/log.hh \
+ moof/manager.hh \
+ moof/math.hh \
+ moof/modal_dialog.hh \
+ moof/network.hh \
+ moof/opengl.hh \
+ moof/packet.cc \
+ moof/packet.hh \
+ moof/plane.cc \
+ moof/plane.hh \
+ moof/ray.hh \
+ moof/resource.cc \
+ moof/resource.hh \
+ moof/rigid_body.hh \
+ moof/script.hh \
+ moof/service.cc \
+ moof/service.hh \
+ moof/settings.cc \
+ moof/settings.hh \
+ moof/shape.hh \
+ moof/socket.hh \
+ moof/sound.cc \
+ moof/sound.hh \
+ moof/sphere.hh \
+ moof/string.cc \
+ moof/string.hh \
+ moof/texture.cc \
+ moof/texture.hh \
+ moof/thread.hh \
+ moof/timer.cc \
+ moof/timer.hh \
+ moof/video.cc \
+ moof/video.hh \
+ moof/view.cc \
+ moof/view.hh \
+ moof/fastevents.c \
+ moof/fastevents.h \
$(ENDLIST)
-EXTRA_DIST = Moof/cml Moof/stlplus
+EXTRA_DIST = moof/cml moof/stlplus
#
bin_PROGRAMS = yoink
-yoink_CPPFLAGS = -I$(top_srcdir)/src/Moof
+yoink_CPPFLAGS = -I$(top_srcdir)/src/moof
yoink_LDADD = libmoof.a
yoink_SOURCES = \
Animation.hh \
Character.cc \
Character.hh \
- ErrorHandler.cc \
- ErrorHandler.hh \
GameLayer.cc \
GameLayer.hh \
GameState.hh \
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <SDL/SDL.h>
-#include "fastevents.h"
-
-#include "Backend.hh"
-#include "Error.hh"
-#include "Log.hh"
-
-
-namespace Mf {
-
-
-struct Impl
-{
- static Error error;
- static int retainCount;
-};
-
-Error Impl::error(Error::UNINITIALIZED);
-int Impl::retainCount = 0;
-
-
-Backend::Backend()
-{
- if (Impl::retainCount++ == 0)
- {
-#if defined(_WIN32)
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
-#else
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) != 0)
-#endif
- {
- const char* error = SDL_GetError();
- Impl::error.init(Error::SDL_INIT, error);
- return; // fatal
- }
- else
- {
- char name[128];
- SDL_VideoDriverName(name, sizeof(name));
- logInfo << "initialized SDL; using video driver `"
- << name << "'" << std::endl;
- }
-
- if (FE_Init() != 0)
- {
- const char* error = FE_GetError();
- Impl::error.init(Error::FASTEVENTS_INIT, error);
- return; // fatal
- }
-
- Impl::error.init(Error::NONE);
- }
-}
-
-Backend::Backend(const Backend& backend)
-{
- ++Impl::retainCount;
-}
-
-Backend::~Backend()
-{
- if (--Impl::retainCount == 0)
- {
- FE_Quit();
- SDL_Quit();
-
- Impl::error.reset();
- }
-}
-
-bool Backend::isInitialized()
-{
- return Impl::error.code() == Error::NONE;
-}
-
-const Error& Backend::getError()
-{
- return Impl::error;
-}
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include "Camera.hh"
-#include "OpenGL.hh"
-
-
-namespace Mf {
-
-
-void Camera::setPosition(const Vector3& position)
-{
- mState.position = position;
-}
-
-void Camera::setRotation(const Quaternion& rotation)
-{
- mState.orientation = rotation;
-}
-
-void Camera::lookAt(const Vector3& point)
-{
- // FIXME this doesn't work as expected
- cml::quaternion_rotation_aim_at(mState.orientation,
- mState.position, point,
- Vector3(0.0, 1.0, 0.0));
-}
-
-
-void Camera::setProjection(const Matrix4& projection)
-{
- mProjection = projection;
-}
-
-void Camera::setProjection(Scalar fovy, Scalar aspect, Scalar abutting,
- Scalar distant)
-{
- cml::matrix_perspective_yfov_RH(mProjection, fovy, aspect, abutting,
- distant, cml::z_clip_neg_one);
-}
-
-
-void Camera::uploadToGL(Scalar alpha) const
-{
- calculate(alpha);
-
- glMatrixMode(GL_PROJECTION);
- glMultMatrix(mProjection.data());
-
- glMatrixMode(GL_MODELVIEW);
- glMultMatrix(mModelview.data());
-}
-
-void Camera::calculate(Scalar alpha) const
-{
- State3 state = getState(alpha);
-
- cml::matrix_rotation_quaternion(mModelview, state.orientation);
-
- Matrix4 translate;
- cml::matrix_translation(translate, state.position);
-
- mModelview *= translate;
-
- mFrustum.init(mModelview, mProjection);
-}
-
-
-void Camera::update(Scalar t, Scalar dt)
-{
- RigidBody3::update(t, dt);
-}
-
-void Camera::draw(Scalar alpha) const
-{
- mSphere.draw(alpha);
-}
-
-
-void Camera::handleEvent(const Event& event)
-{
- const Scalar ds = 50.0;
-
- switch (event.type)
- {
- case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_RIGHT)
- {
- mState.position[0] -= ds;
- }
- else if (event.key.keysym.sym == SDLK_LEFT)
- {
- mState.position[0] += ds;
- }
- else if (event.key.keysym.sym == SDLK_UP)
- {
- mState.position[1] -= ds;
- }
- else if (event.key.keysym.sym == SDLK_DOWN)
- {
- mState.position[1] += ds;
- }
- else if (event.key.keysym.sym == SDLK_PAGEUP)
- {
- mState.position[2] += ds;
- }
- else if (event.key.keysym.sym == SDLK_PAGEDOWN)
- {
- mState.position[2] -= ds;
- }
- break;
-
- case SDL_MOUSEMOTION:
- {
- Scalar xrel = cml::rad(Scalar(event.motion.xrel) / 6.0);
- Scalar yrel = cml::rad(Scalar(event.motion.yrel) / 6.0);
-
- Quaternion rotation = mState.orientation;
-
- cml::quaternion_rotate_about_world_x(rotation, yrel);
- //mRotation.normalize();
- cml::quaternion_rotate_about_world_y(rotation, xrel);
-
- rotation.normalize();
- mState.orientation = rotation;
- }
- break;
-
- case SDL_MOUSEBUTTONDOWN:
- if (event.button.button == SDL_BUTTON_WHEELUP)
- {
- mState.position[2] -= ds;
- }
- else if (event.button.button == SDL_BUTTON_WHEELDOWN)
- {
- mState.position[2] -= ds;
- }
- break;
- }
-}
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_CAMERA_HH_
-#define _MOOF_CAMERA_HH_
-
-#include <Moof/Event.hh>
-#include <Moof/Frustum.hh>
-#include <Moof/Math.hh>
-#include <Moof/RigidBody.hh>
-
-
-namespace Mf {
-
-
-class Camera : public RigidBody3
-{
-public:
-
- Camera()
- {
- mState.init();
- mPrevState.init();
-
- cml::quaternion_rotation_world_y(mState.orientation, SCALAR(0.0));
- }
-
- void setPosition(const Vector3& position);
- void setRotation(const Quaternion& rotation);
-
- void lookAt(const Vector3& point);
-
- void setProjection(const Matrix4& projection);
- void setProjection(Scalar fovy, Scalar aspect, Scalar near, Scalar far);
-
- const Matrix4& getModelview() const
- {
- return mModelview;
- }
-
- const Matrix4& getProjection() const
- {
- return mProjection;
- }
-
- const Frustum& getFrustum() const
- {
- return mFrustum;
- }
-
-
- void uploadToGL(Scalar alpha = 0) const;
-
- void update(Scalar t, Scalar dt);
- void draw(Scalar alpha = 0) const;
- void handleEvent(const Event& event);
-
-private:
-
- void calculate(Scalar alpha) const;
-
- mutable Matrix4 mModelview;
- Matrix4 mProjection;
-
- mutable Frustum mFrustum;
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_CAMERA_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <map>
-
-#include "Dispatch.hh"
-
-
-namespace Mf {
-
-
-class Dispatch::Impl
-{
-public:
-
- Impl(Dispatch* dispatch) :
- mDispatch(dispatch),
- mId(0) {}
-
- Dispatch::Handle getNewHandle()
- {
- ++mId;
- Dispatch::Handle handle(mDispatch->mImpl, mId);
- return handle;
- }
-
- typedef std::pair<unsigned,Dispatch::Function> Callback;
- typedef std::multimap<std::string,Callback> CallbackLookup;
- typedef CallbackLookup::iterator CallbackIt;
-
- typedef std::multimap<unsigned,std::string> HandleLookup;
- typedef HandleLookup::iterator HandleIt;
-
-
- inline Handle addTarget(const std::string& event,
- const Function& callback, Handle handle)
- {
- mCallbacks.insert(std::make_pair(event,
- std::make_pair(handle.getId(), callback)));
- mHandles.insert(std::make_pair(handle.getId(), event));
-
- return handle;
- }
-
- inline void removeTarget(unsigned id)
- {
- std::pair<HandleIt,HandleIt> matching(mHandles.equal_range(id));
-
- for (HandleIt it = matching.first; it != matching.second; ++it)
- {
- CallbackIt first = mCallbacks.find((*it).second);
- CallbackIt last = mCallbacks.end();
-
- for (CallbackIt jt = first; jt != last; ++jt)
- {
- if ((*jt).second.first == id)
- {
- mCallbacks.erase(jt);
- break;
- }
- }
- }
-
- mHandles.erase(id);
- }
-
- void dispatch(const std::string& event)
- {
- std::pair<CallbackIt,CallbackIt>
- callbacks(mCallbacks.equal_range(event));
-
- for (CallbackIt it = callbacks.first; it != callbacks.second; ++it)
- {
- Function callback = (*it).second.second;
- callback();
- }
- }
-
-
- Dispatch* mDispatch;
-
- unsigned mId;
-
- CallbackLookup mCallbacks;
- HandleLookup mHandles;
-};
-
-
-void Dispatch::Handle::clear()
-{
- boost::shared_ptr<Impl> dispatch;
- if (mId && (dispatch = mDispatch.lock()))
- {
- dispatch->removeTarget(mId);
- mId = 0;
- }
-}
-
-
-Dispatch::Dispatch() :
- mImpl(new Dispatch::Impl(this)) {}
-
-
-Dispatch::Handle Dispatch::addTarget(const std::string& event,
- const Function& callback)
-{
- return addTarget(event, callback, mImpl->getNewHandle());
-}
-
-Dispatch::Handle Dispatch::addTarget(const std::string& event,
- const Function& callback,
- Handle handle)
-{
- // pass through
- return mImpl->addTarget(event, callback, handle);
-}
-
-
-void Dispatch::removeTarget(unsigned id)
-{
- // pass through
- return mImpl->removeTarget(id);
-}
-
-
-void Dispatch::dispatch(const std::string& event)
-{
- // pass through
- mImpl->dispatch(event);
-}
-
-
-Dispatch& Dispatch::global()
-{
- static Dispatch dispatch;
- return dispatch;
-}
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_DISPATCH_HH_
-#define _MOOF_DISPATCH_HH_
-
-#include <string>
-
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/weak_ptr.hpp>
-
-
-namespace Mf {
-
-
-/**
- * Dispatcher of messages to interested parties.
- */
-
-class Dispatch
-{
- class Impl;
- boost::shared_ptr<Impl> mImpl;
-
- void removeTarget(unsigned id);
-
-
-public:
-
- class Handle
- {
- public:
-
- Handle() :
- mId(0) {}
-
- Handle(boost::weak_ptr<Impl> dispatch, unsigned id) :
- mDispatch(dispatch),
- mId(id) {}
-
- Handle(const Handle& handle) :
- mDispatch(handle.mDispatch),
- mId(handle.mId)
- {
- handle.mId = 0;
- }
-
- ~Handle()
- {
- clear();
- }
-
- Handle& operator = (const Handle& handle)
- {
- clear();
- mDispatch = handle.mDispatch;
- mId = handle.mId;
- handle.mId = 0;
- return *this;
- }
-
- unsigned getId() const
- {
- return mId;
- }
-
- void clear();
-
- private:
-
- boost::weak_ptr<Impl> mDispatch;
- mutable unsigned mId;
- };
-
- typedef boost::function<void(void)> Function;
-
-
- Dispatch();
-
- Handle addTarget(const std::string& event, const Function& callback);
- Handle addTarget(const std::string& event, const Function& callback,
- Handle handle);
-
- void dispatch(const std::string& event);
-
- static Dispatch& global();
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_DISPATCH_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_ENTITY_HH_
-#define _MOOF_ENTITY_HH_
-
-#include <boost/shared_ptr.hpp>
-
-#include <Moof/Aabb.hh>
-#include <Moof/Cullable.hh>
-#include <Moof/Drawable.hh>
-#include <Moof/Sphere.hh>
-
-
-namespace Mf {
-
-
-class Frustum;
-
-
-/**
- * Interface for game objects that can be drawn to the screen and have a
- * specified volume (take up space).
- */
-
-class Entity;
-typedef boost::shared_ptr<Entity> EntityP;
-
-
-class Entity : public Cullable, public Drawable
-{
-protected:
-
- Aabb<3> mAabb;
- Sphere<3> mSphere;
-
-public:
-
- virtual ~Entity() {}
-
- virtual void drawIfVisible(Scalar alpha, const Frustum& frustum) const
- {
- if (isVisible(frustum)) draw(alpha);
- }
-
- virtual bool isVisible(const Frustum& frustum) const
- {
- return mSphere.isVisible(frustum) && mAabb.isVisible(frustum);
- }
-
- const Aabb<3>& getAabb() const
- {
- return mAabb;
- }
-
- const Sphere<3>& getSphere() const
- {
- return mSphere;
- }
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_ENTITY_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_ERROR_HH_
-#define _MOOF_ERROR_HH_
-
-#include <cstring> // strncpy
-#include <exception>
-#include <string>
-
-
-namespace Mf {
-
-
-class Error : public std::exception
-{
-public:
-
- enum Code
- {
- UNINITIALIZED = -1, // -
- NONE = 0, // -
- ALC_INIT, // description
- FASTEVENTS_INIT, // description
- FILE_NOT_FOUND, // path of missing file
- OPENAL_INIT, // description
- RESOURCE_NOT_FOUND, // name of missing resource
- SCRIPT_ERROR, // description
- SDL_INIT, // description
- SDL_VIDEOMODE, // -
- UNKNOWN_AUDIO_FORMAT, // name of resource
- UNKNOWN_IMAGE_FORMAT, // name of resource
- };
-
- explicit Error(unsigned code = NONE, const std::string& what = "")
- {
- init(code, what);
- }
- virtual ~Error() throw() {}
-
- void init(unsigned code = NONE, const std::string& what = "")
- {
- strncpy(mWhat, what.c_str(), sizeof(mWhat)-1);
- mWhat[sizeof(mWhat)-1] = '\0';
- mCode = code;
- }
-
- virtual void raise() const
- {
- throw *this;
- }
-
- unsigned code() const throw()
- {
- return mCode;
- }
-
- const char* what() const throw()
- {
- return mWhat;
- }
-
- operator bool () const
- {
- // resolves to true if error code is not NONE
- return mCode != NONE;
- }
-
- void reset() throw()
- {
- mCode = NONE;
- mWhat[0] = '\0';
- }
-
-private:
-
- unsigned mCode;
- char mWhat[1024];
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_ERROR_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <Moof/Aabb.hh>
-#include <Moof/Frustum.hh>
-#include <Moof/Sphere.hh>
-
-
-namespace Mf {
-
-
-void Frustum::init(const Matrix4& modelview, const Matrix4& projection)
-{
- Scalar planes[6][4];
-
- cml::extract_frustum_planes(modelview, projection, planes,
- cml::z_clip_neg_one);
-
- mPlanes[0] = Plane(planes[0][0], planes[0][1],
- planes[0][2], planes[0][3]);
- mPlanes[1] = Plane(planes[1][0], planes[1][1],
- planes[1][2], planes[1][3]);
- mPlanes[2] = Plane(planes[2][0], planes[2][1],
- planes[2][2], planes[2][3]);
- mPlanes[3] = Plane(planes[3][0], planes[3][1],
- planes[3][2], planes[3][3]);
- mPlanes[4] = Plane(planes[4][0], planes[4][1],
- planes[4][2], planes[4][3]);
- mPlanes[5] = Plane(planes[5][0], planes[5][1],
- planes[5][2], planes[5][3]);
-}
-
-void Frustum::init(const Matrix4& modelview, Scalar fovy, Scalar aspect,
- Scalar abutting, Scalar distant)
-{
- Matrix4 projection;
-
- cml::matrix_perspective_yfov_RH(projection, fovy, aspect, abutting,
- distant, cml::z_clip_neg_one);
-
- init(modelview, projection);
-}
-
-Frustum::Collision Frustum::contains(const Aabb<3>& aabb) const
-{
- Vector3 corners[8];
- int nTotalInside = 0;
-
- aabb.getCorners(corners);
-
- for (int i = 0; i < 6; ++i)
- {
- int nInside = 8;
-
- for (int j = 0; j < 8; ++j)
- {
- if (mPlanes[i].intersects(corners[j]) == Plane::NEGATIVE)
- {
- --nInside;
- }
- }
-
- if (nInside == 0) return OUTSIDE;
- else if (nInside == 8) ++nTotalInside;
- }
-
- if (nTotalInside == 6) return INSIDE;
- else return INTERSECT;
-}
-
-
-Frustum::Collision Frustum::contains(const Sphere<3>& sphere) const
-{
- for (int i = 0; i < 6; ++i)
- {
- Plane::Halfspace halfspace = mPlanes[i].intersects(sphere);
-
- if (halfspace == Plane::NEGATIVE) return OUTSIDE;
- else if (halfspace == Plane::INTERSECT) return INTERSECT;
- }
-
- return INSIDE;
-}
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_FRUSTUM_HH_
-#define _MOOF_FRUSTUM_HH_
-
-#include <Moof/Math.hh>
-#include <Moof/Plane.hh>
-
-
-namespace Mf {
-
-
-template <int D> class Aabb;
-template <int D> class Sphere;
-
-class Frustum
-{
- Plane mPlanes[6]; // left, right, bottom, top, near, far
-
-public:
- typedef enum
- {
- OUTSIDE = 0,
- INSIDE = 1,
- INTERSECT = 2
- } Collision;
-
- Frustum() {}
- Frustum(const Matrix4& modelview, const Matrix4& projection)
- {
- init(modelview, projection);
- }
- Frustum(const Matrix4& modelview, Scalar fovy, Scalar aspect,
- Scalar abutting, Scalar distant)
- {
- init(modelview, fovy, aspect, abutting, distant);
- }
-
- void init(const Matrix4& modelview, const Matrix4& projection);
- void init(const Matrix4& modelview, Scalar fovy, Scalar aspect,
- Scalar abutting, Scalar distant);
-
- Collision contains(const Aabb<3>& aabb) const;
- Collision contains(const Sphere<3>& sphere) const;
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_FRUSTUM_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_IMAGE_HH_
-#define _MOOF_IMAGE_HH_
-
-#include <boost/shared_ptr.hpp>
-
-#include <Moof/OpenGL.hh>
-#include <Moof/Resource.hh>
-
-
-namespace Mf {
-
-
-class Image;
-typedef boost::shared_ptr<Image> ImageP;
-
-class Image : public Resource
-{
-public:
-
- static ImageP alloc(const std::string& name)
- {
- return ImageP(new Image(name));
- }
-
- explicit Image(const std::string& name);
-
- bool isValid() const;
-
- int getWidth() const;
- int getHeight() const;
-
- unsigned getDepth() const;
- unsigned getPitch() const;
- GLuint getMode() const;
-
- std::string getComment() const;
-
- const char* getPixels() const;
- char* getPixels();
-
- void flip();
-
- void setAsIcon() const;
-
- static bool getPath(std::string& name);
-
-private:
-
- static FILE* openFile(std::string& name);
-
- class Impl;
- boost::shared_ptr<Impl> mImpl;
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_IMAGE_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_INTERPOLATOR_HH_
-#define _MOOF_INTERPOLATOR_HH_
-
-#include <Moof/Log.hh>
-#include <Moof/Math.hh>
-
-
-namespace Mf {
-
-
-namespace Interp {
-
- typedef enum
- {
- STOP = 0,
- REPEAT = 1,
- OSCILLATE = 2
- } Mode;
-
-} // namespace Interp
-
-
-template <class T>
-class Interpolator : public T
-{
-public:
-
- Interpolator(Scalar t = 1.0, Interp::Mode mode = Interp::STOP)
- {
- reset(t, mode);
- }
-
- void reset(Scalar t = 1.0, Interp::Mode mode = Interp::STOP)
- {
- mAlpha = 0.0;
- mScale = 1.0 / t;
- mMode = mode;
- mIsDone = false;
- }
-
- void update(Scalar t, Scalar dt)
- {
- if (!mIsDone)
- {
- mPrevState = T::getValue();
- mAlpha += dt * mScale;
- clamp();
- if (mPrevState == T::calculate(mAlpha)) mIsDone = true;
- }
- }
-
- typename T::Type getState(Scalar alpha) const
- {
- return cml::lerp(mPrevState, T::getValue(), alpha);
- }
-
- bool isDone() const
- {
- return mIsDone;
- }
-
-private:
-
- void clamp()
- {
- if (mAlpha > 1.0)
- {
- switch (mMode)
- {
- case Interp::STOP:
- mAlpha = SCALAR(1.0);
- break;
- case Interp::REPEAT:
- mAlpha -= SCALAR(1.0);
- break;
- case Interp::OSCILLATE:
- mAlpha = SCALAR(2.0) - mAlpha;
- mScale = -mScale;
- break;
- }
- }
- else if (mAlpha < 0.0)
- {
- switch (mMode)
- {
- case Interp::STOP:
- mAlpha = SCALAR(0.0);
- break;
- case Interp::REPEAT:
- mAlpha += SCALAR(1.0);
- break;
- case Interp::OSCILLATE:
- mAlpha = -mAlpha;
- mScale = -mScale;
- break;
- }
- }
- }
-
- Scalar mAlpha;
- Scalar mScale;
- Interp::Mode mMode;
- bool mIsDone;
-
- typename T::Type mPrevState;
-};
-
-
-template <class T = Scalar>
-class Linear
-{
-public:
-
- typedef T Type;
-
- void init(const Type& a, const Type& b)
- {
- mStart = a;
- mFinish = b;
- }
-
- const Type& calculate(Scalar alpha)
- {
- mState = cml::lerp(mStart, mFinish, alpha);
- return mState;
- }
-
- const Type& getValue() const
- {
- return mState;
- }
-
-private:
-
- Type mState;
- Type mStart;
- Type mFinish;
-};
-
-
-typedef Interpolator< Linear<Scalar> > Lerp;
-
-
-} // namespace Mf
-
-#endif // _MOOF_INTERPOLATOR_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <fstream>
-
-#include "Log.hh"
-#include "Script.hh"
-
-
-namespace Mf {
-
-
-Log::Level Log::gLevel = Log::INFO;
-
-
-void Log::setLevel(Level level)
-{
- gLevel = level;
-}
-
-Log::Level Log::level()
-{
- return gLevel;
-}
-
-
-std::ostream& log(std::clog);
-
-static std::ofstream nullLog_;
-std::ostream& nullLog(nullLog_);
-
-Log logError( Log::ERRORR, " error: ");
-Log logWarning(Log::WARNING, "warning: ");
-Log logInfo( Log::INFO, " info: ");
-
-
-static int logScript_(Script& script, Log::Level level)
-{
- static Log* logs[] = {0, &logError, &logWarning, &logInfo};
-
- Script::Slot param = script[1];
-
- while (!param.isNone())
- {
- (*logs[level])(param);
- ++param.index;
- }
-
- return 0;
-}
-
-
-void importLogFunctions(Script& script)
-{
- script.importFunction("LogError",
- boost::bind(logScript_, _1, Log::ERRORR));
- script.importFunction("LogWarning",
- boost::bind(logScript_, _1, Log::WARNING));
- script.importFunction("LogInfo",
- boost::bind(logScript_, _1, Log::INFO));
- script.importFunction("print",
- boost::bind(logScript_, _1, Log::INFO));
-}
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_MATH_HH_
-#define _MOOF_MATH_HH_
-
-/**
- * @file Math.hh
- * General math-related types and functions.
- */
-
-#include <cmath>
-#include <cml/cml.h>
-
-#include <SDL/SDL_opengl.h>
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
-#if USE_DOUBLE_PRECISION
-
-typedef GLdouble GLscalar;
-#define GL_SCALAR GL_DOUBLE
-#define SCALAR(D) (D)
-
-#else
-
-typedef GLfloat GLscalar;
-#define GL_SCALAR GL_FLOAT
-#define SCALAR(F) (F##f)
-
-#endif
-
-
-namespace Mf {
-
-
-typedef GLscalar Scalar;
-
-typedef cml::vector< Scalar, cml::fixed<2> > Vector2;
-typedef cml::vector< Scalar, cml::fixed<3> > Vector3;
-typedef cml::vector< Scalar, cml::fixed<4> > Vector4;
-
-typedef cml::matrix< Scalar, cml::fixed<2,2>,
- cml::col_basis, cml::col_major > Matrix2;
-typedef cml::matrix< Scalar, cml::fixed<3,3>,
- cml::col_basis, cml::col_major > Matrix3;
-typedef cml::matrix< Scalar, cml::fixed<4,4>,
- cml::col_basis, cml::col_major > Matrix4;
-
-typedef cml::quaternion< Scalar, cml::fixed<>, cml::vector_first,
- cml::positive_cross > Quaternion;
-
-typedef cml::constants<Scalar> Constants;
-
-
-inline Vector3 demote(const Vector4& vec)
-{
- return Vector3(vec[0], vec[1], vec[2]);
-}
-
-inline Vector2 demote(const Vector3& vec)
-{
- return Vector2(vec[0], vec[1]);
-}
-
-inline Vector4 promote(const Vector3& vec, Scalar extra = 0.0)
-{
- return Vector4(vec[0], vec[1], vec[2], extra);
-}
-
-inline Vector3 promote(const Vector2& vec, Scalar extra = 0.0)
-{
- return Vector3(vec[0], vec[1], extra);
-}
-
-
-template <class R, class P>
-inline R convert(const P& p)
-{
- return R(p);
-}
-
-template <>
-inline Vector3 convert<Vector3,Vector4>(const Vector4& vec)
-{
- return Vector3(vec[0], vec[1], vec[2]);
-}
-
-template <>
-inline Vector2 convert<Vector2,Vector3>(const Vector3& vec)
-{
- return Vector2(vec[0], vec[1]);
-}
-
-template <>
-inline Vector4 convert<Vector4,Vector3>(const Vector3& vec)
-{
- return Vector4(vec[0], vec[1], vec[2], SCALAR(0.0));
-}
-
-template <>
-inline Vector3 convert<Vector3,Vector2>(const Vector2& vec)
-{
- return Vector3(vec[0], vec[1], SCALAR(0.0));
-}
-
-template <class P>
-struct cast
-{
- cast(const P& p) : param(p) {}
- template <class R>
- operator R() { return convert<R,P>(param); }
-private:
- const P& param;
-};
-
-
-
-const Scalar EPSILON = SCALAR(0.000001);
-
-/**
- * Check the equality of scalars with a certain degree of error allowed.
- */
-
-inline bool isEqual(Scalar a, Scalar b, Scalar epsilon = EPSILON)
-{
- return std::abs(a - b) < epsilon;
-}
-
-
-
-// Here are some generic implementations of a few simple integrators. To
-// use, you need one type representing the state and another containing the
-// derivatives of the primary state variables. The state class must
-// implement these methods:
-//
-// void getDerivative(Derivative_Type& derivative, Scalar absoluteTime);
-// void step(const Derivative_Type& derivative, Scalar deltaTime);
-//
-// Additionally, the derivative class must overload a few operators:
-//
-// Derivative_Type operator+(const Derivative_Type& other) const
-// Derivative_Type operator*(const Derivative_Type& other) const
-
-template <class S, class D>
-inline D evaluate(const S& state, Scalar t)
-{
- D derivative;
- state.getDerivative(derivative, t);
- return derivative;
-}
-
-template <class S, class D>
-inline D evaluate(S state, Scalar t, Scalar dt, const D& derivative)
-{
- state.step(derivative, dt);
- return evaluate<S,D>(state, t + dt);
-}
-
-
-template <class S, class D>
-inline void euler(S& state, Scalar t, Scalar dt)
-{
- D a = evaluate<S,D>(state, t);
-
- state.step(a, dt);
-}
-
-template <class S, class D>
-inline void rk2(S& state, Scalar t, Scalar dt)
-{
- D a = evaluate<S,D>(state, t);
- D b = evaluate<S,D>(state, t, dt * SCALAR(0.5), a);
-
- state.step(b, dt);
-}
-
-template <class S, class D>
-inline void rk4(S& state, Scalar t, Scalar dt)
-{
- D a = evaluate<S,D>(state, t);
- D b = evaluate<S,D>(state, t, dt * SCALAR(0.5), a);
- D c = evaluate<S,D>(state, t, dt * SCALAR(0.5), b);
- D d = evaluate<S,D>(state, t, dt, c);
-
- state.step((a + (b + c) * SCALAR(2.0) + d) * SCALAR(1.0/6.0), dt);
-}
-
-
-} // namespace Mf
-
-#endif // _MOOF_MATH_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_MODALDIALOG_HH_
-#define _MOOF_MODALDIALOG_HH_
-
-#include <string>
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if defined(_WIN32)
-#include <windows.h>
-#elif defined(__APPLE__) && defined(__MACH__)
-#include <Carbon/Carbon.h>
-#elif USE_GTK
-#include <gtk/gtk.h>
-#elif USE_QT4
-#include <QApplication>
-#include <QIcon>
-#include <QMessageBox>
-#endif
-
-#include <Moof/Log.hh>
-#include <Moof/Resource.hh>
-
-
-namespace Mf {
-
-
-/**
- * Small wrapper over various user interface modal dialog windows.
- */
-
-struct ModalDialog
-{
- enum Type
- {
- INFO = 1,
- WARNING = 2,
- CRITICAL = 3
- };
-
-
- std::string title;
- Type type;
- std::string text1;
- std::string text2;
-
-
-
- ModalDialog(Type pType = INFO,
- const std::string& pTitle = "",
- const std::string& pText1 = "",
- const std::string& pText2 = "") :
- title(pTitle),
- type(pType),
- text1(pText1),
- text2(pText2) {}
-
-
- void run() const
- {
- switch (type)
- {
- case WARNING:
- logWarning(text1);
- logWarning(text2);
- break;
- case CRITICAL:
- logError(text1);
- logError(text2);
- break;
- default:
- logInfo(text1);
- logInfo(text2);
- break;
- }
-
-#if defined(_WIN32)
-
- int iconType;
- switch (type)
- {
- case WARNING:
- iconType = MB_ICONWARNING;
- break;
- case CRITICAL:
- iconType = MB_ICONERROR;
- break;
- default:
- iconType = MB_ICONINFORMATION;
- break;
- }
-
- MessageBox(0, (text1 + "\n" + text2).c_str(), title.c_str(),
- MB_OK | iconType);
-
-#elif USE_GTK
-
- int argc = 0;
- char** argv;
- gtk_init(&argc, &argv);
-
- GtkMessageType iconType;
- switch (type)
- {
- case WARNING:
- iconType = GTK_MESSAGE_WARNING;
- break;
- case CRITICAL:
- iconType = GTK_MESSAGE_ERROR;
- break;
- default:
- iconType = GTK_MESSAGE_INFO;
- break;
- }
-
- GtkWidget* dialog = gtk_message_dialog_new(NULL,
- GTK_DIALOG_DESTROY_WITH_PARENT, iconType,
- GTK_BUTTONS_CLOSE, "%s", text1.c_str());
- gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
- "%s", text2.c_str());
- gtk_window_set_title(GTK_WINDOW(dialog), title.c_str());
-
- std::string iconPath(PACKAGE".png");
- if (Resource::getPath(iconPath))
- {
- GdkPixbuf* iconPixbuf = gdk_pixbuf_new_from_file(iconPath.c_str(),
- NULL);
- gtk_window_set_icon(GTK_WINDOW(dialog), iconPixbuf);
- }
-
- gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy(dialog);
- // FIXME - this doesn't seem to actually remove the window from the
- // screen when it closes
-
-#elif USE_QT4
-
- int argc = 0;
- char** argv;
- QApplication qtApp(argc, argv);
-
- QMessageBox::Icon iconType;
- switch (type)
- {
- case WARNING:
- iconType = QMessageBox::Warning;
- break;
- case CRITICAL:
- iconType = QMessageBox::Critical;
- break;
- default:
- iconType = QMessageBox::Information;
- break;
- }
-
- QMessageBox dialog;
- dialog.setWindowTitle(title.c_str());
- dialog.setIcon(iconType);
- dialog.setText(text1.c_str());
- dialog.setInformativeText(text2.c_str());
- dialog.setStandardButtons(QMessageBox::Close);
-
- std::string iconPath(PACKAGE".png");
- if (Resource::getPath(iconPath))
- {
- QIcon icon(iconPath.c_str());
- dialog.setWindowIcon(icon);
- }
-
- dialog.exec();
-
-#endif
- }
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_MODALDIALOG_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_OCTREE_HH_
-#define _MOOF_OCTREE_HH_
-
-#include <algorithm>
-#include <list>
-
-#include <boost/shared_ptr.hpp>
-#include <stlplus/ntree.hpp>
-
-#include <Moof/Aabb.hh>
-#include <Moof/Drawable.hh>
-#include <Moof/Entity.hh>
-#include <Moof/Frustum.hh>
-#include <Moof/Log.hh>
-#include <Moof/Math.hh>
-#include <Moof/Sphere.hh>
-
-
-namespace Mf {
-
-
-struct OctreeInsertable
-{
- virtual ~OctreeInsertable() {}
-
- virtual int getOctant(const Aabb<3>& aabb) const = 0;
-};
-
-
-template <class T>
-class Octree : public Entity
-{
- typedef boost::shared_ptr<T> InsertableP;
-
- struct Node : public Entity
- {
- std::list<InsertableP> objects;
-
- Node(const Aabb<3>& aabb)
- {
- mAabb = aabb;
- mSphere.point = mAabb.getCenter();
- mSphere.radius = (mAabb.min - mSphere.point).length();
- }
-
- void draw(Scalar alpha) const
- {
- mAabb.draw(alpha);
- }
-
- void printSize()
- {
- logInfo << "size of node " << objects.size() << std::endl;
- }
-
- void getAll(std::list<InsertableP>& insertables) const
- {
- insertables.insert(insertables.end(), objects.begin(),
- objects.end());
- }
-
- void getIfVisible(std::list<InsertableP>& insertables,
- const Frustum& frustum) const
- {
- typename std::list<InsertableP>::const_iterator it;
-
- for (it = objects.begin(); it != objects.end(); ++it)
- {
- if ((*it)->isVisible(frustum)) insertables.push_back(*it);
- }
- }
- };
-
-
-public:
-
- typedef boost::shared_ptr<Octree> Ptr;
- typedef typename stlplus::ntree<Node>::iterator NodeP;
-
-private:
-
-
- NodeP insert(InsertableP entity, NodeP node)
- {
- ASSERT(node.valid() && "invalid node passed");
- ASSERT(entity && "null entity passed");
-
- Aabb<3> entityAabb = entity->getAabb();
- Aabb<3> nodeAabb = node->getAabb();
-
- if (!(entityAabb.max[0] < nodeAabb.max[0] &&
- entityAabb.min[0] > nodeAabb.min[0] &&
- entityAabb.max[1] < nodeAabb.max[1] &&
- entityAabb.min[1] > nodeAabb.min[1] &&
- entityAabb.max[2] < nodeAabb.max[2] &&
- entityAabb.min[2] > nodeAabb.min[2]))
- {
- node->objects.push_back(entity);
- return node;
- }
- else
- {
- return insert_recurse(entity, node);
- }
- }
-
- NodeP insert_recurse(InsertableP entity, NodeP node)
- {
- ASSERT(node.valid() && "invalid node passed");
- ASSERT(entity && "null entity passed");
-
- int octantNum = entity->getOctant(node->getAabb());
- if (octantNum == -1)
- {
- node->objects.push_back(entity);
- return node;
- }
- else
- {
- if ((int)mTree.children(node) <= octantNum)
- {
- addChild(node, octantNum);
- }
-
- NodeP child = mTree.child(node, octantNum);
- ASSERT(child.valid() && "expected valid child node");
-
- return insert_recurse(entity, child);
- }
- }
-
- void addChild(NodeP node, int index)
- {
- ASSERT(node.valid() && "invalid node passed");
-
- Aabb<3> octant;
-
- for (int i = mTree.children(node); i <= index; ++i)
- {
- node->getAabb().getOctant(octant, i);
- mTree.append(node, octant);
- }
- }
-
-
- void getNearbyObjects(std::list<InsertableP>& insertables,
- const OctreeInsertable& entity, NodeP node) const
- {
- ASSERT(node.valid() && "invalid node passed");
-
- node->printSize();
-
- int octantNum = entity.getOctant(node->getAabb());
- if (octantNum != -1)
- {
- node->getAll(insertables);
-
- if (octantNum < (int)mTree.children(node))
- {
- NodeP child = mTree.child(node, octantNum);
- ASSERT(child.valid() && "expected valid child node");
-
- getNearbyObjects(insertables, entity, child);
- }
- }
- else
- {
- logInfo("getting all the rest...");
- getAll(insertables, node);
- }
- }
-
-
- void getAll(std::list<InsertableP>& insertables, NodeP node) const
- {
- ASSERT(node.valid() && "invalid node passed");
-
- node->getAll(insertables);
-
- for (unsigned i = 0; i < mTree.children(node); ++i)
- {
- NodeP child = mTree.child(node, i);
- ASSERT(child.valid() && "expected valid child node");
-
- getAll(insertables, child);
- }
- }
-
- void getIfVisible(std::list<InsertableP>& insertables,
- const Frustum& frustum, NodeP node) const
- {
- ASSERT(node.valid() && "invalid node passed");
-
- // try to cull by sphere
- Frustum::Collision collision = frustum.contains(node->getSphere());
- if (collision == Frustum::OUTSIDE) return;
-
- // try to cull by aabb
- collision = frustum.contains(node->getAabb());
- if (collision == Frustum::OUTSIDE) return;
-
-
- if (collision == Frustum::INSIDE)
- {
- node->getAll(insertables);
- }
- else // collision == Frustum::INTERSECT
- {
- node->getIfVisible(insertables, frustum);
- }
-
- if (mTree.children(node) > 0)
- {
- if (collision == Frustum::INSIDE)
- {
- for (unsigned i = 0; i < mTree.children(node); ++i)
- {
- NodeP child = mTree.child(node, i);
- ASSERT(child.valid() && "expected valid child node");
-
- getAll(insertables, child);
- }
- }
- else // collision == Frustum::INTERSECT
- {
- for (unsigned i = 0; i < mTree.children(node); ++i)
- {
- NodeP child = mTree.child(node, i);
- ASSERT(child.valid() && "expected valid child node");
-
- getIfVisible(insertables, frustum, child);
- }
- }
- }
- }
-
-
- mutable stlplus::ntree<Node> mTree;
-
-
-public:
-
- void print(NodeP node)
- {
- logInfo("-----");
- logInfo << "depth to node: " << mTree.depth(node) << std::endl;
- logInfo << "size of node: " << mTree.size(node) << std::endl;
- }
-
- static Ptr alloc(const Node& rootNode)
- {
- return Ptr(new Octree(rootNode));
- }
-
- explicit Octree(const Node& rootNode)
- {
- mTree.insert(rootNode);
- }
-
-
- NodeP insert(InsertableP entity)
- {
- return insert(entity, mTree.root());
- }
-
- void remove(InsertableP entity, NodeP node)
- {
- ASSERT(entity && "null entity passed");
- ASSERT(node.valid() && "invalid node passed");
-
- typename std::list<InsertableP>::iterator it;
- it = std::find(node->objects.begin(), node->objects.end(), entity);
-
- if (it != node->objects.end())
- {
- node->objects.erase(it);
- }
- }
-
-
- NodeP reinsert(InsertableP entity, NodeP node)
- {
- remove(entity, node);
- return insert(entity);
- }
-
-
- void draw(Scalar alpha) const
- {
- std::list<InsertableP> objects;
- getAll(objects);
-
- typename std::list<InsertableP>::const_iterator it;
- for (it = objects.begin(); it != objects.end(); ++it)
- {
- (*it)->draw(alpha);
- }
- }
-
- void drawIfVisible(Scalar alpha, const Frustum& frustum) const
- {
- std::list<InsertableP> objects;
- getIfVisible(objects, frustum);
- //getNearbyObjects(objects, *savedObj);
-
- typename std::list<InsertableP>::const_iterator it;
- for (it = objects.begin(); it != objects.end(); ++it)
- {
- (*it)->draw(alpha);
- }
- }
-
-
- void getAll(std::list<InsertableP>& insertables) const
- {
- getAll(insertables, mTree.root());
- }
-
- void getIfVisible(std::list<InsertableP>& insertables,
- const Frustum& frustum) const
- {
- getIfVisible(insertables, frustum, mTree.root());
- }
-
- mutable const OctreeInsertable* savedObj;
-
-
- void getNearbyObjects(std::list<InsertableP>& insertables,
- const OctreeInsertable& entity) const
- {
- logInfo("--- GETTING NEARBY");
- getNearbyObjects(insertables, entity, mTree.root());
- logInfo("---");
- savedObj = &entity;
- }
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_OCTREE_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include "Aabb.hh"
-#include "Plane.hh"
-#include "Sphere.hh"
-
-
-namespace Mf {
-
-
-Plane::Halfspace Plane::intersects(const Aabb<3>& aabb) const
-{
- Vector3 corners[8];
- int nPositive = 8;
-
- aabb.getCorners(corners);
-
- for (int i = 0; i < 8; ++i)
- {
- if (intersects(corners[i]) == NEGATIVE)
- {
- --nPositive;
- }
- }
-
- if (nPositive == 0) return NEGATIVE;
- else if (nPositive == 8) return POSITIVE;
- else return INTERSECT;
-}
-
-Plane::Halfspace Plane::intersects(const Sphere<3>& sphere) const
-{
- Scalar distance = getDistanceToPoint(sphere.point);
-
- if (distance < -sphere.radius) return NEGATIVE;
- else if (distance < sphere.radius) return INTERSECT;
- else return POSITIVE;
-}
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_RAY_HH_
-#define _MOOF_RAY_HH_
-
-#include <Moof/Drawable.hh>
-#include <Moof/Math.hh>
-#include <Moof/OpenGL.hh>
-#include <Moof/Texture.hh>
-
-
-namespace Mf {
-
-
-/**
- * A line that goes to infinity.
- */
-
-template <int D>
-struct Ray : public Drawable
-{
- typedef cml::vector< Scalar, cml::fixed<D> > Vector;
-
- // solution = point + t*direction
- Vector point;
- Vector direction;
-
- struct Contact
- {
- Scalar distance; // distance from the origin to the nearest point
- Vector normal; // surface normal at contact point
-
- bool operator < (const Contact& rhs)
- {
- return distance < rhs.distance;
- }
- };
-
- void solve(Vector& p, Scalar t) const
- {
- p = point + t*direction;
- }
-
- void draw(Scalar alpha = 0.0) const
- {
- Vector end = point + 1000.0 * direction;
- // FIXME this is kinda cheesy
-
- Mf::Texture::resetBind();
- glBegin(GL_LINES);
- glVertex(point);
- glVertex(end);
- glEnd();
- }
-
- void normalize()
- {
- direction.normalize();
- }
-};
-
-
-typedef Ray<2> Ray2;
-typedef Ray<3> Ray3;
-
-
-} // namespace Mf
-
-#endif // _MOOF_RAY_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_RESOURCE_HH_
-#define _MOOF_RESOURCE_HH_
-
-/**
- * @file Resource.hh
- * Interface for textures, sounds, and other types of resources.
- */
-
-#include <cstdio>
-#include <string>
-#include <vector>
-
-
-namespace Mf {
-
-
-/**
- * Generic resource class.
- */
-
-class Resource
-{
-public:
-
- virtual ~Resource() {}
-
-
- /**
- * Add a directory to search when looking for resource files.
- * @param directory Path to a directory.
- */
-
- static void addSearchPaths(const std::string& paths);
- static void addSearchPaths(const std::vector<std::string>& pathList);
-
- /**
- * Get the path to a resource of a given name.
- * @param name Name of a resource. The name will be appended to each
- * search directory in order.
- * @return The first path found which resolves to a file.
- */
-
- static std::string getPath(const std::string& path,
- const std::string& prefix = "",
- const std::string& extension = "");
-
- static bool getPath(std::string& path,
- const std::string& prefix = "",
- const std::string& extension = "");
-
- static FILE* openFile(std::string& path,
- std::string prefix = "",
- const std::string& extension = "",
- const std::string& mode = "rb");
-
-private:
-
- static std::vector<std::string> gSearchPaths;
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_RESOURCE_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_RIGIDBODY_HH_
-#define _MOOF_RIGIDBODY_HH_
-
-#include <vector>
-
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-
-#include <Moof/Entity.hh>
-#include <Moof/Math.hh>
-
-
-namespace Mf {
-
-
-template <int D = 3>
-struct LinearState
-{
- typedef cml::vector< Scalar, cml::fixed<D> > Vector;
- typedef boost::function<const Vector& (const LinearState&)>
- ForceFunction;
-
- // primary
-
- Vector position;
- Vector momentum;
-
- // secondary
-
- Vector velocity;
-
- // user
-
- Vector force;
- std::vector<ForceFunction> forces;
-
- // constant
-
- Scalar mass;
- Scalar inverseMass;
-
-
- void recalculateLinear()
- {
- velocity = momentum * inverseMass;
- }
-
-
- struct GravityForce
- {
- explicit GravityForce(Scalar a = -9.8)
- {
- force.zero();
- acceleration = a;
- }
-
- const Vector& operator () (const LinearState& state)
- {
- force[1] = state.mass * acceleration;
- return force;
- }
-
- private:
-
- Vector force;
- Scalar acceleration;
- };
-
-
- void init()
- {
- position.zero();
- momentum.zero();
-
- velocity.zero();
-
- force.zero();
- forces.clear();
-
- mass = SCALAR(1.0);
- inverseMass = 1.0 / mass;
- }
-
-
- struct Derivative
- {
- Vector velocity;
- Vector force;
-
- Derivative operator*(Scalar dt) const
- {
- Derivative derivative;
- derivative.velocity = dt * velocity;
- derivative.force = dt * force;
- return derivative;
- }
-
- Derivative operator+(const Derivative& other) const
- {
- Derivative derivative;
- derivative.velocity = velocity + other.velocity;
- derivative.force = force + other.force;
- return derivative;
- }
- };
-
-
- Vector getForce() const
- {
- Vector f(force);
-
- for (size_t i = 0; i < forces.size(); ++i)
- {
- f += forces[i](*this);
- }
-
- return f;
- }
-
- void getDerivative(Derivative& derivative, Scalar t) const
- {
- derivative.velocity = velocity;
- derivative.force = getForce();
- }
-
- void step(const Derivative& derivative, Scalar dt)
- {
- position += dt * derivative.velocity;
- momentum += dt * derivative.force;
- recalculateLinear();
- }
-};
-
-
-struct RotationalState2
-{
- // primary
-
- Scalar orientation;
- Scalar angularMomentum;
-
- // secondary
-
- Scalar angularVelocity;
-
- // constant
-
- Scalar inertia;
- Scalar inverseInertia;
-
-
- void recalculateRotational()
- {
- angularVelocity = angularMomentum * inertia;
- }
-
-
- struct Derivative
- {
- Scalar angularVelocity;
- Scalar torque;
- };
-
- void step(const Derivative& derivative, Scalar dt)
- {
- orientation += dt * derivative.angularVelocity;
- angularMomentum += dt * derivative.torque;
- recalculateRotational();
- }
-};
-
-struct RotationalState3
-{
- // primary
-
- Quaternion orientation;
- Vector3 angularMomentum;
-
- // secondary
-
- Quaternion spin;
- Vector3 angularVelocity;
-
- // constant
-
- Scalar inertia;
- Scalar inverseInertia;
-
-
- void recalculateRotational()
- {
- angularVelocity = angularMomentum * inertia;
- }
-};
-
-
-struct State2 : public LinearState<2>, public RotationalState2
-{
- void recalculate()
- {
- recalculateLinear();
- recalculateRotational();
- }
-
- void update(Scalar t, Scalar dt)
- {
- rk4<LinearState<2>,LinearState<2>::Derivative>(*this, t, dt);
- }
-};
-
-struct State3 : public LinearState<3>, public RotationalState3
-{
- void recalculate()
- {
- recalculateLinear();
- recalculateRotational();
- }
-
- void update(Scalar t, Scalar dt)
- {
- rk4<LinearState<3>,LinearState<3>::Derivative>(*this, t, dt);
- }
-};
-
-
-template <class T>
-inline T interpolate(const T& a, const T& b, Scalar alpha)
-{
- return cml::lerp(a, b, alpha);
-}
-
-template <>
-inline State2 interpolate<State2>(const State2& a, const State2& b,
- Scalar alpha)
-{
- State2 state(b);
- state.position = interpolate(a.position, b.position, alpha);
- state.momentum = interpolate(a.momentum, b.momentum, alpha);
- state.orientation = interpolate(a.orientation, b.orientation, alpha);
- state.angularMomentum = interpolate(a.angularMomentum,
- b.angularMomentum, alpha);
- return state;
-}
-
-template <>
-inline State3 interpolate<State3>(const State3& a, const State3& b,
- Scalar alpha)
-{
- State3 state(b);
- state.position = interpolate(a.position, b.position, alpha);
- state.momentum = interpolate(a.momentum, b.momentum, alpha);
- state.orientation = cml::slerp(a.orientation, b.orientation, alpha);
- state.angularMomentum = interpolate(a.angularMomentum,
- b.angularMomentum, alpha);
- return state;
-}
-
-
-
-/**
- * Interface for anything that can move.
- */
-
-template <class T>
-class RigidBody : public Entity
-{
-protected:
-
- T mState;
- T mPrevState;
-
-public:
-
- virtual ~RigidBody() {}
-
- virtual void update(Scalar t, Scalar dt)
- {
- mPrevState = mState;
- mState.update(t, dt);
- }
-
- const T& getState() const
- {
- return mState;
- }
-
- T getState(Scalar alpha) const
- {
- return interpolate(mPrevState, mState, alpha);
- }
-
- const T& getLastState() const
- {
- return mPrevState;
- }
-};
-
-typedef RigidBody<State2> RigidBody2;
-typedef RigidBody<State3> RigidBody3;
-
-
-} // namespace Mf
-
-#endif // _MOOF_RIGIDBODY_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_SCRIPT_HH_
-#define _MOOF_SCRIPT_HH_
-
-/**
- * @file Script.hh
- * A thin wrapper over Lua. This is not meant as a complicated binding
- * package between C++ and Lua. It is not meant to obscure the division
- * between C++ and Lua but rather to clarify it and make it more
- * manageable. It does not hide the concept of the Lua stack, but rather
- * provides that mechanism with a certain level of abstraction while also
- * providing a cleaner, more consistent API.
- */
-
-#include <iostream>
-#include <list>
-#include <map>
-#include <string>
-#include <vector>
-
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-#include <boost/shared_ptr.hpp>
-#include <lua.hpp>
-
-
-namespace Mf {
-
-
-class Script;
-typedef boost::shared_ptr<Script> ScriptP;
-
-
-class Script
-{
-public:
-
- typedef boost::function<int(Script&)> Function;
-
- enum Type
- {
- NONE = LUA_TNONE,
- NIL = LUA_TNIL,
- BOOLEAN = LUA_TBOOLEAN,
- LIGHTUSERDATA = LUA_TLIGHTUSERDATA,
- NUMBER = LUA_TNUMBER,
- STRING = LUA_TSTRING,
- TABLE = LUA_TTABLE,
- FUNCTION = LUA_TFUNCTION,
- USERDATA = LUA_TUSERDATA,
- THREAD = LUA_TTHREAD
- };
-
- enum Result
- {
- SUCCESS = 0,
- YIELD = LUA_YIELD,
- RUNTIME_ERROR = LUA_ERRRUN,
- SYNTAX_ERROR = LUA_ERRSYNTAX,
- MEMORY_ERROR = LUA_ERRMEM,
- HANDLER_ERROR = LUA_ERRERR,
- FILE_ERROR = LUA_ERRFILE
- };
-
- enum PseudoIndex
- {
- REGISTRY = LUA_REGISTRYINDEX,
- ENVIRONMENT = LUA_ENVIRONINDEX,
- GLOBALS = LUA_GLOBALSINDEX
- };
-
- /**
- * This is the most prominent abstraction on top of the standard Lua
- * API. A Slot object represents a value on the stack. More
- * specifically, it represents a position on the stack. The
- * distinction is only important when objects are moved around on the
- * stack or if the Slot represents a negative index on the stack (the
- * value of which will change as things are pushed onto and popped from
- * the stack).
- */
-
- struct Slot
- {
- /**
- * You have direct access to the index of the value on the stack
- * being represented.
- */
-
- int index;
-
-
- Slot(const Script& s, int i = 0) :
- index(i),
- mScript(const_cast<Script&>(s)) {}
-
- /**
- * A copied value presently points to the same value, except the
- * real index is used. That means that if a value that refers to a
- * frame referenced from the top of the stack will have its
- * normalized index copied into the new value object.
- */
-
- //Slot(const Slot& copy) :
- //index(copy.positiveIndex()),
- //mScript(copy.mScript) {}
-
-
- // check the type of the value
- bool isBoolean() const
- { return (bool)lua_isboolean(mScript.mState, index); }
- bool isImportedFunction() const
- { return (bool)lua_iscfunction(mScript.mState, index); }
- bool isFunction() const
- { return (bool)lua_isfunction(mScript.mState, index); }
- bool isNil() const
- { return (bool)lua_isnil(mScript.mState, index); }
- bool isNone() const
- { return (bool)lua_isnone(mScript.mState, index); }
- bool isNoneOrNil() const
- { return (bool)lua_isnoneornil(mScript.mState, index); }
- bool isNumber() const
- { return (bool)lua_isnumber(mScript.mState, index); }
- bool isString() const
- { return (bool)lua_isstring(mScript.mState, index); }
- bool isTable() const
- { return (bool)lua_istable(mScript.mState, index); }
- bool isThread() const
- { return (bool)lua_isthread(mScript.mState, index); }
- bool isData() const
- { return (bool)lua_isuserdata(mScript.mState, index); }
- bool isLightData() const
- { return (bool)lua_islightuserdata(mScript.mState, index); }
-
- /**
- * Check the value and throw an error if its the wrong type.
- * There's a little caveat: This method never returns because it
- * does a long jump. Consequently, constructed C++ objects which
- * exist on the stack between the current frame and some lua
- * function will not be destructed. That's not a problem for
- * objects that only exist on the stack, but any objects that
- * allocate memory on the heap (such as containers or strings) will
- * leak. Therefore, you should only call this method after
- * cleaning up such objects. The best thing to do for defining
- * functions is to simply check all the parameters at the get-go
- * before any C++ objects are even constructed.
- */
-
- void requireType(Type t) const
- {
- if (t != type())
- {
- luaL_typerror(mScript.mState, index,
- lua_typename(mScript.mState, t));
- }
- }
-
- void raise(const char* error)
- {
- luaL_argerror(mScript.mState, index, error);
- }
-
-
- Slot& requireBoolean()
- {
- if (!isBoolean())
- {
- luaL_typerror(mScript.mState, index, "boolean");
- }
- return *this;
- }
- Slot& requireNumber()
- {
- if (!isNumber())
- {
- luaL_typerror(mScript.mState, index, "number");
- }
- return *this;
- }
- Slot& requireString()
- {
- if (!isString())
- {
- luaL_typerror(mScript.mState, index, "string");
- }
- return *this;
- }
- Slot& requireTable()
- {
- if (!isTable())
- {
- luaL_typerror(mScript.mState, index, "table");
- }
- return *this;
- }
- Slot& requireFunction()
- {
- if (!isFunction())
- {
- luaL_typerror(mScript.mState, index, "function");
- }
- return *this;
- }
- Slot& requireData()
- {
- if (!isData())
- {
- luaL_typerror(mScript.mState, index, "data");
- }
- return *this;
- }
- Slot& requireNil()
- {
- if (!isNil())
- {
- luaL_typerror(mScript.mState, index, "nil");
- }
- return *this;
- }
- Slot& requireThread()
- {
- if (!isThread())
- {
- luaL_typerror(mScript.mState, index, "thread");
- }
- return *this;
- }
-
-
- /**
- * Get the type of the value.
- */
-
- Type type() const
- {
- return (Type)lua_type(mScript.mState, index);
- }
-
- /**
- * Get the name of the type of the value as a string.
- */
-
- std::string typeName() const
- {
- return std::string(luaL_typename(mScript.mState, index));
- }
-
-
- /**
- * Get the length of the value according to the definition given by
- * Lua.
- */
-
- size_t length() const
- {
- return lua_objlen(mScript.mState, index);
- }
-
- int positiveIndex() const
- {
- if (index < 0) return index + lua_gettop(mScript.mState) + 1;
- else return index;
- }
-
-
- /**
- * Get a pointer value (for userdata, tables, threads, and
- * functions).
- */
-
- const void* id() const
- {
- return lua_topointer(mScript.mState, index);
- }
-
- bool isIdentical(const Slot& rhs) const
- {
- return &mScript == &(rhs.mScript) && index == rhs.index;
- }
-
- operator bool () const
- {
- return !isNone();
- }
-
-
- bool operator == (const Slot& rhs) const
- {
- return (bool)lua_equal(mScript.mState, index, rhs.index);
- }
- bool operator != (const Slot& rhs) const
- {
- return !(*this == rhs);
- }
-
- bool operator < (const Slot& rhs) const
- {
- return (bool)lua_lessthan(mScript.mState, index, rhs.index);
- }
- bool operator <= (const Slot& rhs) const
- {
- return *this < rhs || *this == rhs;
- }
- bool operator > (const Slot& rhs) const
- {
- return !(*this <= rhs);
- }
- bool operator >= (const Slot& rhs) const
- {
- return !(*this < rhs);
- }
-
-
- /**
- * Convert the underlying value to a C++ type.
- */
-
- template <class T>
- bool get(T& value) const
- {
- if (isNumber())
- {
- value = (T)lua_tointeger(mScript.mState, index);
- return true;
- }
- return false;
- }
-
- bool get(float& value) const
- {
- if (isNumber())
- {
- value = (float)lua_tonumber(mScript.mState, index);
- return true;
- }
- return false;
- }
- bool get(double& value) const
- {
- if (isNumber())
- {
- value = (double)lua_tonumber(mScript.mState, index);
- return true;
- }
- return false;
- }
-
- bool get(bool& value) const
- {
- if (isBoolean())
- {
- value = (bool)lua_toboolean(mScript.mState, index);
- return true;
- }
- return false;
- }
-
- bool get(const char*& value, size_t& size) const
- {
- if (isString())
- {
- value = lua_tolstring(mScript.mState, index, &size);
- return true;
- }
- return false;
- }
-
- bool get(std::string& value) const
- {
- const char* str;
- size_t size;
- if (get(str, size))
- {
- value.assign(str, size);
- return true;
- }
- return false;
- }
-
- bool get(void*& value) const
- {
- if (isData())
- {
- value = lua_touserdata(mScript.mState, index);
- return true;
- }
- return false;
- }
-
- template <class T>
- bool get(std::vector<T>& array) const
- {
- if (!isTable()) return false;
-
- array.clear();
-
- Slot value = mScript[-1];
- int realIndex = positiveIndex();
-
- bool done = false;
- for (int i = 1; !done; ++i)
- {
- lua_rawgeti(mScript.mState, realIndex, i);
-
- T v;
- if (value.get(v)) array.push_back(v);
- else done = true;
-
- mScript.pop();
- }
-
- return true;
- }
-
- template <class T>
- bool get(std::map<std::string,T>& dictionary) const
- {
- if (!isTable()) return false;
-
- dictionary.clear();
-
- Slot key = mScript[-2];
- Slot value = mScript[-1];
- int realIndex = positiveIndex();
-
- mScript.pushNil();
- while (lua_next(mScript.mState, realIndex) != 0)
- {
- std::string k;
- if (!key.isNumber() && key.get(k))
- {
- T v;
- if (value.get(v)) dictionary[k] = v;
- }
- mScript.pop();
- }
- mScript.pop();
-
- return true;
- }
-
- /**
- * Get the value of a field from the table.
- */
-
- template <class T, class V>
- bool get(T& value, V field) const
- {
- bool ret = pushField(field).get(value);
- mScript.pop();
- return ret;
- }
-
-
- template <class T, class V>
- void setField(T field, V value)
- {
- mScript.push(field);
- mScript.push(value);
- setField();
- }
-
- void setField()
- {
- lua_settable(mScript.mState, index);
- }
-
-
- template <class T>
- void setField(const std::string& field, T value)
- {
- setField(field.c_str(), value);
- }
- template <class T>
- void setField(const char* field, T value)
- {
- mScript.push(value);
- lua_setfield(mScript.mState, index, field);
- }
-
-
- /**
- * This set method, as opposed to the others, sets the value of the
- * actual slot. The others set table values.
- */
- template <class T>
- void set(T value)
- {
- mScript.push(value);
- replace();
- }
-
- void set()
- {
- replace();
- }
-
-
- /**
- * Replace this value with the value at the top of the stack.
- */
-
- void replace()
- {
- lua_replace(mScript.mState, index);
- }
-
- void remove()
- {
- lua_remove(mScript.mState, index);
- }
-
- void pop()
- {
- // removes this slot, taking with it everything above it
- mScript.pop(mScript.stackSize() - index + 1);
- }
-
- /**
- * Inserts the top-most value on the stack at position index,
- * shifting other values as needed.
- */
-
- void insertTopHere()
- {
- lua_insert(mScript.mState, index);
- }
-
-
- /**
- * Copy the value and push the copy to the stack.
- */
-
- Slot pushCopy() const
- {
- lua_pushvalue(mScript.mState, index);
- return mScript.top();
- }
-
- Slot pushMetaTable() const
- {
- lua_getmetatable(mScript.mState, index);
- return mScript.top();
- }
-
- Slot pushEnvironment() const
- {
- lua_getfenv(mScript.mState, index);
- return mScript.top();
- }
-
-
- Slot pushField() const
- {
- lua_gettable(mScript.mState, index);
- return mScript.top();
- }
-
- template <class T>
- Slot pushField(T index) const
- {
- mScript.push(index);
- return pushField();
- }
-
- Slot pushField(const std::string& name) const
- {
- return pushField(name.c_str());
- }
- Slot pushField(const char* name) const
- {
- lua_getfield(mScript.mState, index, name);
- return mScript.top();
- }
-
-
- Script& script()
- {
- return mScript;
- }
-
- const Script& script() const
- {
- return mScript;
- }
-
- private:
-
- Script& mScript;
- };
-
-
- Script() :
- mState(0)
- {
- reset();
- }
-
- ~Script()
- {
- destroy();
- }
-
-
- static ScriptP alloc()
- {
- return ScriptP(new Script);
- }
-
- void reset()
- {
- if (mState) destroy();
- mState = luaL_newstate();
- registry().setField("Script_hh_Object", (void*)this);
- }
-
-
- void importStandardLibraries()
- {
- luaL_openlibs(mState);
- }
-
- void importBaseLibrary()
- {
- lua_pushcfunction(mState, luaopen_base);
- push(LUA_COLIBNAME);
- call(1, 0);
- }
-
- void importPackageLibrary()
- {
- lua_pushcfunction(mState, luaopen_package);
- push(LUA_LOADLIBNAME);
- call(1, 0);
- }
-
- void importStringLibrary()
- {
- lua_pushcfunction(mState, luaopen_string);
- push(LUA_STRLIBNAME);
- call(1, 0);
- }
-
- void importTableLibrary()
- {
- lua_pushcfunction(mState, luaopen_table);
- push(LUA_TABLIBNAME);
- call(1, 0);
- }
-
- void importMathLibrary()
- {
- lua_pushcfunction(mState, luaopen_math);
- push(LUA_MATHLIBNAME);
- call(1, 0);
- }
-
- void importIoLibrary()
- {
- lua_pushcfunction(mState, luaopen_io);
- push(LUA_IOLIBNAME);
- call(1, 0);
- }
-
- void importOsLibrary()
- {
- lua_pushcfunction(mState, luaopen_os);
- push(LUA_OSLIBNAME);
- call(1, 0);
- }
-
- void importDebugLibrary()
- {
- lua_pushcfunction(mState, luaopen_debug);
- push(LUA_DBLIBNAME);
- call(1, 0);
- }
-
-
- void importFunction(const std::string& name, const Function& function)
- {
- push(function);
- lua_setglobal(mState, name.c_str());
- }
-
- Result doString(const std::string& commands)
- {
- return (Result)luaL_dostring(mState, commands.c_str());
- }
-
- Result doFile(const std::string& file)
- {
- return (Result)luaL_dofile(mState, file.c_str());
- }
-
-
- /**
- * Thread-handling methods.
- */
-
- Script pushNewThread()
- {
- return Script(mState);
- }
-
- void pushThread()
- {
- lua_pushthread(mState);
- }
-
- Result resume(int nargs)
- {
- return (Result)lua_resume(mState, nargs);
- }
-
- Result getStatus() const
- {
- return (Result)lua_status(mState);
- }
-
- int yield(int results)
- {
- return lua_yield(mState, results);
- }
-
- bool isMainThread() const
- {
- return mIsMainThread;
- }
-
-
- /**
- * Throw an error with the value at the top of the stack. This method
- * never returns because it does a long jump. Consequently,
- * constructed C++ objects which exist on the stack between the
- * current frame and some lua function will not be destructed. That's
- * not a problem for objects that only exist on the stack, but any
- * objects that allocate memory on the heap (such as containers or
- * strings) will leak. Therefore, you should only call this method
- * after cleaning up such objects.
- */
-
- void raise()
- {
- lua_error(mState);
- }
-
-
- /**
- * Get significant values.
- */
-
- Slot globals() const
- {
- return Slot(*this, GLOBALS);
- }
-
- Slot registry() const
- {
- return Slot(*this, REGISTRY);
- }
-
- Slot environment() const
- {
- return Slot(*this, ENVIRONMENT);
- }
-
- Slot top() const
- {
- return Slot(*this, stackSize());
- }
-
- /**
- * Get the size of the stack; this is also the index of the top-most
- * value.
- */
-
- int stackSize() const
- {
- return lua_gettop(mState);
- }
-
- void setStackSize(int size)
- {
- lua_settop(mState, size);
- }
-
- void clearStack()
- {
- setStackSize(0);
- }
-
-
- /**
- * Makes sure there is at least extra more places on the stack.
- * Returns false if space couldn't be created. Just like with the
- * regular Lua API, you are responsible to make sure the stack is big
- * enough to hold whatever you want to push on it. This is usually
- * only an issue if you're pushing stuff in a loop.
- */
-
- bool checkStack(int extra)
- {
- return (bool)lua_checkstack(mState, extra);
- }
-
-
- /**
- * Concatenates the top-most n slots on the stack.
- */
-
- void concatenate(int n = 2)
- {
- lua_concat(mState, n);
- }
-
-
- /**
- * Push some values onto the stack.
- */
-
- template <class T>
- Slot push(T value)
- {
- lua_pushinteger(mState, lua_Integer(value));
- return top();
- }
-
- Slot push(bool value)
- {
- lua_pushboolean(mState, int(value));
- return top();
- }
-
- Slot push(float value)
- {
- lua_pushnumber(mState, (lua_Number)value);
- return top();
- }
- Slot push(double value)
- {
- lua_pushnumber(mState, (lua_Number)value);
- return top();
- }
-
- Slot push(const std::string& value)
- {
- lua_pushlstring(mState, value.c_str(), value.length());
- return top();
- }
- Slot push(const char* value)
- {
- lua_pushstring(mState, value);
- return top();
- }
- Slot push(const char* value, size_t length)
- {
- lua_pushlstring(mState, value, length);
- return top();
- }
-
- Slot push(const Function& function)
- {
- mFunctions.push_back(function);
- lua_pushlightuserdata(mState, (void*)&mFunctions.back());
- lua_pushcclosure(mState, dispatchCall, 1);
- return top();
- }
-
- Slot push(void* data)
- {
- lua_pushlightuserdata(mState, data);
- return top();
- }
-
- Slot pushNil()
- {
- lua_pushnil(mState);
- return top();
- }
-
- Slot pushFromThread(Script& thread, int n)
- {
- lua_xmove(thread.mState, mState, n);
- return top();
- }
-
- Slot pushCode(const std::string& file, Result& result)
- {
- result = (Result)luaL_loadfile(mState, file.c_str());
- return top();
- }
-
- Slot pushCode(const std::string& name, const char* buffer,
- size_t size, Result& result)
- {
- result = (Result)luaL_loadbuffer(mState,
- buffer, size, name.c_str());
- return top();
- }
-
- Slot pushNewData(void*& data, size_t size)
- {
- data = lua_newuserdata(mState, size);
- return top();
- }
-
- Slot pushNewTable(int narr = 0, int nrec = 0)
- {
- lua_createtable(mState, narr, nrec);
- return top();
- }
-
-
- /**
- * Call a function on the stack. The correct procedure is to push a
- * function onto the stack followed by nargs arguments. This method
- * will pop them off upon return, leaving up to nresults return values
- * (default is any number of return values, depending on the callee).
- */
-
- Result call(int nargs = 0, int nresults = LUA_MULTRET)
- {
- return (Result)lua_pcall(mState, nargs, nresults, 0);
- }
-
-
- /**
- * Pops n values from the top of the stack.
- */
-
- void pop(int n = 1)
- {
- lua_pop(mState, n);
- }
-
-
- /**
- * Index into the stack to get a Slot.
- */
-
- Slot operator [] (int index) const
- {
- return Slot(*this, index);
- }
-
-
- /**
- * Control over the garbage collection process.
- */
-
- void collectAll()
- {
- lua_gc(mState, LUA_GCCOLLECT, 0);
- }
-
- void stopCollector()
- {
- lua_gc(mState, LUA_GCSTOP, 0);
- }
-
- void restartCollector()
- {
- lua_gc(mState, LUA_GCRESTART, 0);
- }
-
- int getUsedMemory() const
- {
- // in kilobytes
- return lua_gc(mState, LUA_GCCOUNT, 0);
- }
-
- void collectStep(int step)
- {
- lua_gc(mState, LUA_GCSTEP, step);
- }
-
- void tuneCollector(int pause, int step)
- {
- lua_gc(mState, LUA_GCSETPAUSE, pause);
- lua_gc(mState, LUA_GCSETSTEPMUL, step);
- }
-
-
-private:
-
- Script(lua_State* state) :
- mState(lua_newthread(state)),
- mIsMainThread(false) {}
-
- static int dispatchCall(lua_State* state)
- {
- const Function* function = (const Function*)lua_touserdata(state,
- lua_upvalueindex(1));
-
- lua_getfield(state, LUA_REGISTRYINDEX, "Script_hh_Object");
- Script* script = (Script*)lua_touserdata(state, -1);
- lua_pop(state, 1);
-
- return (*function)(*script);
- }
-
- void destroy()
- {
- if (mIsMainThread) lua_close(mState);
- }
-
- lua_State* mState;
- bool mIsMainThread;
- std::list<Function> mFunctions;
-};
-
-
-inline std::ostream& operator << (std::ostream& stream,
- const Script::Slot& slot)
-{
- if (slot.isString())
- {
- std::string str;
- slot.get(str);
- stream << str;
- }
- else if (slot.isBoolean())
- {
- bool value;
- slot.get(value);
- if (value) stream << "true";
- else stream << "false";
- }
- else if (slot.isNil())
- {
- stream << "nil";
- }
- else
- {
- stream << slot.typeName() << " (" << slot.id() << ")";
- }
-
- return stream;
-}
-
-
-} // namespace Mf
-
-#endif // _MOOF_SCRIPT_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-/**
- * \file Socket.hh
- * Network-related classes, including a reinterpreted sockets API.
- */
-
-#ifndef _MOOF_SOCKET_HH_
-#define _MOOF_SOCKET_HH_
-
-#include <algorithm>
-#include <cstring>
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#else
-#error No alternative to fcntl implemented yet.
-#endif
-
-#if defined(_WIN32)
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <wspiapi.h>
-#define SHUT_RD SD_RECEIVE
-#define SHUT_WR SD_SEND
-#define SHUT_RDWR SD_BOTH
-#else
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#endif
-
-#include <Moof/Log.hh>
-#include <Moof/Packet.hh>
-#include <Moof/Thread.hh>
-
-
-#ifndef AI_ADDRCONFIG
-#define AI_ADDRCONFIG 0
-#endif
-
-#ifndef AI_V4MAPPED
-#define AI_V4MAPPED 0
-#endif
-
-
-namespace Mf {
-
-
-/**
- * A class to represent the address of a remote host, including the type of
- * service and socket communication.
- */
-class SocketAddress
-{
-public:
-
- /**
- * Construct an unspecified address.
- */
- SocketAddress() :
- mSize(0),
- mType(0)
- {
- mAddr.sa.sa_family = AF_UNSPEC;
- mAddr.in.sin_port = 0;
- }
-
- /**
- * Construct an address with a specified host. The address can be used
- * to connect to a host.
- * \param service The service name or port number.
- * \param name The numeric IP address of the host.
- * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
- * \param family The family; can be AF_INET or AF_INET6.
- */
- SocketAddress(const std::string& service,
- const std::string& name,
- int type = SOCK_STREAM,
- int family = AF_UNSPEC)
- {
- init(service, name, type, family);
- }
-
- /**
- * Construct an address without a specified host. The address can be
- * used to accept on a local port.
- * \param service The service name or port number.
- * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
- * \param family The family; can be AF_INET or AF_INET6.
- */
- explicit SocketAddress(const std::string& service,
- int type = SOCK_STREAM,
- int family = AF_UNSPEC)
- {
- init(service, type, family);
- }
-
- /**
- * Construct an address from the information in an addrinfo structure.
- * \param addr The addrinfo structure.
- */
- SocketAddress(const struct addrinfo* addr) :
- mSize(addr->ai_addrlen),
- mType(addr->ai_socktype)
- {
- memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
- getNameAndService(mName, mService);
- }
-
- /**
- * Construct an address from a sockaddr structure.
- * \param addr The sockaddr structure.
- * \param size The size of the sockaddr structure.
- * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
- */
- SocketAddress(const struct sockaddr* addr,
- size_t size,
- int type = SOCK_STREAM) :
- mSize(size),
- mType(type)
- {
- memcpy(&mAddr.sa, addr, size);
- getNameAndService(mName, mService);
- }
-
-
- /**
- * Get an IPv4 broadcast address.
- * \param service The service name or port number.
- * \return The socket address.
- */
- static SocketAddress broadcast(const std::string& service)
- {
- std::istringstream stream(service);
- unsigned short port;
- stream >> port;
-
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = INADDR_BROADCAST;
- memset(&addr.sin_zero, 0, sizeof(addr.sin_zero));
- return SocketAddress((sockaddr*)&addr, sizeof(addr), SOCK_DGRAM);
- }
-
-
- /**
- * Initialize the address with a specified host. The address can be
- * used to connect to a host.
- * \param service The service name or port number.
- * \param name The numeric IP address of the host.
- * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
- * \param family The family; can be AF_INET or AF_INET6.
- */
- void init(const std::string& service,
- const std::string& name,
- int type = SOCK_STREAM,
- int family = AF_UNSPEC)
- {
- struct addrinfo* addr = resolve(service.c_str(), name.c_str(),
- type, family,
- AI_ADDRCONFIG | AI_NUMERICHOST | AI_V4MAPPED);
- if (addr)
- {
- mSize = addr->ai_addrlen;
- mType = addr->ai_socktype;
- memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
-
- mService = service;
- mName = name;
-
- freeaddrinfo(addr);
- }
- else
- {
- mType = 0;
- mSize = 0;
- mAddr.sa.sa_family = AF_UNSPEC;
- mAddr.in.sin_port = 0;
- }
- }
-
- /**
- * Initialize the address without a specified host. The address can be
- * used to accept on a local port.
- * \param service The service name or port number.
- * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
- * \param family The family; can be AF_INET or AF_INET6.
- */
- void init(const std::string& service,
- int type = SOCK_STREAM,
- int family = AF_UNSPEC)
- {
- struct addrinfo* addr = resolve(service.c_str(), 0,
- type, family,
- AI_PASSIVE);
- if (addr)
- {
- mSize = addr->ai_addrlen;
- mType = addr->ai_socktype;
- memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
-
- mService = service;
- getName(mName);
-
- freeaddrinfo(addr);
- }
- else
- {
- mType = 0;
- mSize = 0;
- mAddr.sa.sa_family = AF_UNSPEC;
- mAddr.in.sin_port = 0;
- }
- }
-
-
- /**
- * Get the name of the service. This could also be a port number if
- * there is no service name associated with the number.
- * \return The service.
- */
- const std::string& service() const
- {
- return mService;
- }
-
- /**
- * Get the name of the host. This may be the host used to construct
- * the address, or a resolved numeric host if none was used.
- * \return The host.
- */
- const std::string& name() const
- {
- return mName;
- }
-
- /**
- * Get the port number of the address service.
- * \return Port number.
- */
- unsigned short port() const
- {
- return ntohs(mAddr.in.sin_port);
- }
-
- /**
- * Get the type of socket associated with the service of this address.
- * \return Socket type; either SOCK_STREAM or SOCK_DGRAM.
- */
- int type() const
- {
- return mType;
- }
-
- /**
- * Get the family of the protocol associated with the address.
- * \return Protocol family; either AF_INET, AF_INET6, or AF_UNSPEC.
- */
- int family() const
- {
- return mAddr.sa.sa_family;
- }
-
-
- /**
- * Get the sockaddr structure of the address.
- * \return The sockaddr structure.
- */
- const struct sockaddr* address() const
- {
- return mSize != 0 ? &mAddr.sa : 0;
- }
-
- /**
- * Get the size of the sockaddr structure of the address.
- * \return The size of the sockaddr structure.
- */
- size_t size() const
- {
- return mSize;
- }
-
-
- /**
- * Get a list of addresses resolved to by the given search criteria.
- * This can be used to perform lookups for name resolution, so this
- * method may take some time to return. Use the ResolveTask class to
- * resolve addresses asynchronously.
- * \param service The service name or port number.
- * \param name The name of the local or remote host.
- * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
- * \param family The family; can be AF_INET or AF_INET6.
- * \param resolved The list to be filled with addresses.
- * \return 0 on success, -1 on error.
- */
- static int resolve(const std::string& service,
- const std::string& name,
- int type,
- int family,
- std::vector<SocketAddress>& resolved)
- {
- struct addrinfo* list = resolve(service.c_str(), name.c_str(),
- type, family,
- AI_ADDRCONFIG | AI_V4MAPPED);
- int result = collectAddresses(list, resolved);
- freeaddrinfo(list);
- return result;
- }
-
- /**
- * Get a list of addresses resolved to by the given search criteria.
- * The addresses will be suitable for accepting on a local port.
- * \param service The service name or port number.
- * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
- * \param family The family; can be AF_INET or AF_INET6.
- * \param resolved The list to be filled with addresses.
- * \return 0 on success, -1 on error.
- */
- static int resolve(const std::string& service,
- int type,
- int family,
- std::vector<SocketAddress>& resolved)
- {
- struct addrinfo* list = resolve(service.c_str(), 0,
- type, family,
- AI_PASSIVE);
- int result = collectAddresses(list, resolved);
- freeaddrinfo(list);
- return result;
- }
-
-
- /**
- * Resolve the hostname of the address. The default behavior is to
- * avoid a reverse lookup by giving the numeric address. You can
- * change that behavior with the getnameinfo flags.
- * \param name The place to store the hostname or IP address.
- * \param flags The getnameinfo flags.
- */
- void getName(std::string& name, int flags = NI_NUMERICHOST)
- {
- char node[256] = {'\0'};
- int result = getnameinfo(&mAddr.sa, mSize,
- node, sizeof(node),
- 0, 0,
- flags);
- if (result == 0) name.assign(node);
- }
-
- /**
- * Resolve the service name of the address.
- * \param service The place to store the service name or port number.
- * \param flags The getnameinfo flags.
- */
- void getService(std::string& service, int flags)
- {
- flags |= mType == SOCK_DGRAM ? NI_DGRAM : 0;
-
- char serv[64] = {'\0'};
- int result = getnameinfo(&mAddr.sa, mSize,
- 0, 0,
- serv, sizeof(serv),
- flags);
- if (result == 0) service.assign(serv);
- }
-
- /**
- * Resolve the service and hostname of the address. The default
- * behavior is to avoid a reverse lookup by giving the numeric address.
- * You can change that behavior with the getnameinfo flags.
- * \param name The place to store the hostname or IP address.
- * \param service The place to store the service name or port number.
- * \param flags The getnameinfo flags.
- */
- void getNameAndService(std::string& name,
- std::string& service,
- int flags = NI_NUMERICHOST)
- {
- flags |= mType == SOCK_DGRAM ? NI_DGRAM : 0;
-
- char serv[64] = {'\0'};
- char node[256] = {'\0'};
- int result = getnameinfo(&mAddr.sa, mSize,
- node, sizeof(node),
- serv, sizeof(serv),
- flags);
- if (result == 0)
- {
- service.assign(serv);
- name.assign(node);
- }
- }
-
-
-private:
-
- static struct addrinfo* resolve(const char* service,
- const char* node,
- int type,
- int family,
- int flags)
- {
- ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
- ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
-
- struct addrinfo hints;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
- hints.ai_socktype = type;
- hints.ai_flags = flags;
-
- struct addrinfo* addr;
- int status = getaddrinfo(node, service, &hints, &addr);
-
- if (status == 0)
- {
- return addr;
- }
- else
- {
- Mf::logWarning(gai_strerror(status));
- return 0;
- }
- }
-
- static int collectAddresses(struct addrinfo* addresses,
- std::vector<SocketAddress>& resolved)
- {
- if (addresses)
- {
- resolved.clear();
-
- for (struct addrinfo* addr = addresses;
- addr != 0;
- addr = addr->ai_next)
- {
- resolved.push_back(SocketAddress(addr));
- }
-
- return 0;
- }
- else return -1;
- }
-
-
- union
- {
- sockaddr sa;
- sockaddr_in in;
- sockaddr_storage storage;
- } mAddr;
- size_t mSize;
- int mType;
-
- std::string mName;
- std::string mService;
-};
-
-
-/**
- * The socket class represents a connection or between this node and a
- * remote node.
- */
-class Socket
-{
- struct Impl
- {
- SocketAddress address;
- int fd;
- bool isConnected;
-
- Impl() :
- fd(-1),
- isConnected(false) {}
-
- Impl(const SocketAddress& address, int flags = 0) :
- address(address),
- fd(::socket(address.family(), address.type(), flags)),
- isConnected(false) {}
- } mImpl;
-
-
-public:
-
- /**
- * Construct a socket with no associated peer.
- */
- Socket() {}
-
- /**
- * Construct a socket with an address.
- * \param address The address.
- * \param flags The socket options.
- */
- Socket(const SocketAddress& address, int flags = 0) :
- mImpl(address, flags) {}
-
- /**
- * Construct a socket with a specified host. The socket can be used to
- * connect to a host.
- * \param service The service name or port number.
- * \param name The numeric IP address of the host.
- * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
- * \param family The family; can be AF_INET or AF_INET6.
- * \param flags The socket options.
- */
- Socket(const std::string& service,
- const std::string& name,
- int type = SOCK_STREAM,
- int family = AF_UNSPEC,
- int flags = 0) :
- mImpl(SocketAddress(service, name, type, family), flags) {}
-
- /**
- * Construct a socket without a specified host. The socket can be used
- * to accept sockets on a local port.
- * \param service The service name or port number.
- * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
- * \param family The family; can be AF_INET or AF_INET6.
- * \param flags The socket options.
- */
- explicit Socket(const std::string& service,
- int type = SOCK_STREAM,
- int family = AF_UNSPEC,
- int flags = 0) :
- mImpl(SocketAddress(service, type, family), flags) {}
-
-
- /**
- * Deconstruct the socket, closing it.
- */
- ~Socket()
- {
- close();
- }
-
-
- /**
- * Get whether or not the socket is connected.
- * \return True if the socket is connected, false otherwise.
- */
- bool isConnected() const
- {
- return mImpl.isConnected;
- }
-
- /**
- * Get the address associated with the socket.
- */
- const SocketAddress& address() const
- {
- return mImpl.address;
- }
-
-
- /**
- * Connect the socket to its peer.
- * \return 0 on success, -1 on failure.
- */
- int connect()
- {
- int result = ::connect(mImpl.fd,
- mImpl.address.address(),
- mImpl.address.size());
- mImpl.isConnected = result != -1;
- return result;
- }
-
- /**
- * Disconnect a connected socket from its peer.
- * \param flags Specify the socket directions to close.
- * \return 0 on success, -1 on failure.
- */
- int disconnect(int flags = SHUT_RDWR)
- {
- return shutdown(mImpl.fd, flags);
- }
-
-
- /**
- * Bind the socket to interface and port number specified in the
- * address.
- * \return 0 on success, -1 on failure.
- */
- int bind()
- {
- return ::bind(mImpl.fd,
- mImpl.address.address(),
- mImpl.address.size());
- }
-
- /**
- * Listen on the socket for incoming connections. This is only useful
- * for sockets of type SOCK_STREAM.
- * \param backlog The number of unaccepted connections to queue.
- * \return 0 on success, -1 on failure.
- */
- int listen(int backlog = SOMAXCONN)
- {
- return ::listen(mImpl.fd, backlog > 0 ? backlog : SOMAXCONN);
- }
-
- /**
- * Accept a new connection on the socket. This is only useful for
- * sockets of type SOCK_STREAM.
- * \param socket Set to the new socket on return.
- * \return 0 on success, -1 on failure.
- */
- int accept(Socket& socket)
- {
- Socket temp = Socket(mImpl.fd);
- if (temp.mImpl.fd != -1)
- {
- socket = temp;
- return socket.mImpl.fd;
- }
- return -1;
- }
-
-
- /**
- * Set an integer socket option.
- * \param option The option to set.
- * \param value The new value.
- * \param level The layer to handle the option.
- * \return 0 on success, -1 on failure.
- */
- template <class T>
- int set(int option, const T& value, int level = SOL_SOCKET)
- {
-#if defined(_WIN32)
- return setsockopt(mImpl.fd,
- level,
- option,
- reinterpret_cast<const char*>(&value),
- sizeof(value));
-#else
- return setsockopt(mImpl.fd, level, option, &value, sizeof(value));
-#endif
- }
-
- /**
- * Set a string socket option.
- * \param option The option to set.
- * \param value The new value.
- * \param level The layer to handle the option.
- * \return 0 on success, -1 on failure.
- */
- int set(int option, const std::string& value, int level = SOL_SOCKET)
- {
- return setsockopt(mImpl.fd, level, option,
- value.data(), value.length());
- }
-
- /**
- * Get an integer socket option.
- * \param option The option to set.
- * \param value The new value.
- * \param level The layer to handle the option.
- * \return 0 on success, -1 on failure.
- */
- template <class T>
- int get(int option, T& value, int level = SOL_SOCKET) const
- {
- int size = sizeof(value);
- return getsockopt(mImpl.fd, level, option, &value, &size);
- }
-
- /**
- * Get a string socket option.
- * \param option The option to set.
- * \param value The new value.
- * \param level The layer to handle the option.
- * \return 0 on success, -1 on failure.
- */
- int get(int option, std::string& value, int level = SOL_SOCKET) const
- {
- char str[256] = {'\0'};
- socklen_t size = sizeof(str);
-
-#if defined(_WIN32)
- int result = getsockopt(mImpl.fd,
- level,
- option,
- reinterpret_cast<char*>(&str),
- &size);
-#else
- int result = getsockopt(mImpl.fd, level, option, &str, &size);
-#endif
- value.assign(str, size);
- return result;
- }
-
-
- /**
- * Set the socket IO mode to either blocking or non-blocking.
- * \param isBlocking True if the socket blocks, false otherwise.
- */
- void setBlocking(bool isBlocking)
- {
-#ifdef HAVE_FCNTL
- int flags = fcntl(mImpl.fd, F_GETFL);
- flags = isBlocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
- fcntl(mImpl.fd, F_SETFL, flags);
-#elif defined(_WIN32)
- u_long value = isBlocking;
- ioctlsocket(mImpl.fd, FIONBIO, &value);
-#endif
- }
-
- /**
- * Get whether or not the socket is blocking or non-blocking. If the
- * IO mode can't be determined, this method will assume the socket is
- * a blocking socket.
- * \return True if the socket blocks, false otherwise.
- */
- bool isBlocking() const
- {
-#ifdef HAVE_FCNTL
- int flags = fcntl(mImpl.fd, F_GETFL);
- return !(flags & O_NONBLOCK);
-#endif
- return true;
- }
-
-
- /**
- * Write some bytes to the socket. Use this for connected sockets.
- * \param bytes The bytes.
- * \param size The number of bytes.
- * \param flags The send options.
- * \return The number of bytes written.
- */
- ssize_t write(const void* bytes, size_t size, int flags = 0)
- {
-#if defined(_WIN32)
- return send(mImpl.fd,
- reinterpret_cast<const char *>(bytes), size,
- flags);
-#else
- return send(mImpl.fd, bytes, size, flags);
-#endif
- }
-
- /**
- * Write some bytes to the socket using the given address. Use this
- * for unconnected sockets.
- * \param bytes The bytes.
- * \param size The number of bytes.
- * \param address The address to send to.
- * \param flags The send options.
- * \return The number of bytes written.
- */
- ssize_t write(const void* bytes,
- size_t size,
- const SocketAddress& address,
- int flags = 0)
- {
-#if defined(_WIN32)
- return sendto(mImpl.fd,
- reinterpret_cast<const char*>(bytes), size,
- flags,
- address.address(), address.size());
-#else
- return sendto(mImpl.fd, bytes, size, flags,
- address.address(), address.size());
-#endif
- }
-
- /**
- * Write a packet to the socket. Use this for connected sockets.
- * \param packet The packet.
- * \param flags The send options.
- * \return The number of bytes written.
- */
- ssize_t write(const Packet& packet, int flags = 0)
- {
- return write(packet.bytes(), packet.size(), flags);
- }
-
- /**
- * Write a packet to the socket using the given address. Use this for
- * unconnected sockets.
- * \param packet The packet.
- * \param address The address to send to.
- * \param flags The send options.
- * \return The number of bytes written.
- */
- ssize_t write(const Packet& packet,
- const SocketAddress& address,
- int flags = 0)
- {
- return write(packet.bytes(), packet.size(), address, flags);
- }
-
-
- /**
- * Read some bytes from the socket. Use this for connected sockets.
- * \param bytes The buffer to store the bytes.
- * \param size The size of the buffer.
- * \param flags The recv options.
- * \return The number of bytes read.
- */
- ssize_t read(void* bytes, size_t size, int flags = 0)
- {
-#if defined(_WIN32)
- ssize_t result = recv(mImpl.fd,
- reinterpret_cast<char*>(bytes), size,
- flags);
-#else
- ssize_t result = recv(mImpl.fd, bytes, size, flags);
-#endif
- if (result == 0) mImpl.isConnected = false;
- return result;
- }
-
- /**
- * Read some bytes from the socket using the given address. Use this
- * for unconnected sockets.
- * \param bytes The buffer to store the bytes.
- * \param size The size of the buffer.
- * \param address The address to read from.
- * \param flags The recv options.
- * \return The number of bytes read.
- */
- ssize_t read(void* bytes,
- size_t size,
- SocketAddress& address,
- int flags = 0)
- {
- union
- {
- sockaddr sa;
- sockaddr_storage storage;
- } addr;
- socklen_t length = sizeof(addr);
-
-#if defined(_WIN32)
- ssize_t result = recvfrom(mImpl.fd,
- reinterpret_cast<char*>(bytes), size,
- flags,
- &addr.sa, &length);
-#else
- ssize_t result = recvfrom(mImpl.fd, bytes, size, flags,
- &addr.sa, &length);
-#endif
- if (result != -1)
- {
- address = SocketAddress(&addr.sa, length, mImpl.address.type());
- }
- else if (result == 0)
- {
- mImpl.isConnected = false;
- }
- return result;
- }
-
- /**
- * Read a packet from the socket. Use this for connected sockets.
- * \param packet Set to the packet read on return.
- * \param flags The recv options.
- * \return The number of bytes read.
- */
- ssize_t read(Packet& packet, int flags = 0)
- {
- char buffer[65536];
- ssize_t result = read(buffer, sizeof(buffer), flags);
- if (result != -1) packet = Packet(buffer, result);
- return result;
- }
-
- /**
- * Read a packet from the socket using the given address. Use this for
- * unconnected sockets.
- * \param packet Set to the packet read on return.
- * \param address The address to read from.
- * \param flags The recv options.
- * \return The number of bytes read.
- */
- ssize_t read(Packet& packet, SocketAddress& address, int flags = 0)
- {
- char buffer[65536];
- ssize_t result = read(buffer, sizeof(buffer), address, flags);
- if (result != -1) packet = Packet(buffer, result);
- return result;
- }
-
-
- // The rest of this junk is used to implement the "move" semantics
- // correctly, since it makes no sense for socket objects to be copied.
-
- Socket(Socket& move) :
- mImpl(move.mImpl)
- {
- move.mImpl.fd = -1;
- move.mImpl.isConnected = false;
- }
-
- Socket(Impl move) :
- mImpl(move) {}
-
- Socket& operator=(Socket& move)
- {
- close();
- mImpl = move.mImpl;
- move.mImpl.fd = -1;
- move.mImpl.isConnected = false;
- return *this;
- }
-
- Socket& operator=(Impl move)
- {
- close();
- mImpl = move;
- return *this;
- }
-
- operator Impl()
- {
- Impl impl(mImpl);
- mImpl.fd = -1;
- mImpl.isConnected = false;
- return impl;
- }
-
-
-private:
-
- Socket(int fd)
- {
- // for accepting a socket from fd
- union
- {
- sockaddr sa;
- sockaddr_storage storage;
- } addr;
- socklen_t length = sizeof(addr);
-
- mImpl.fd = ::accept(fd, &addr.sa, &length);
- if (mImpl.fd != -1)
- {
- mImpl.isConnected = true;
- mImpl.address = SocketAddress(&addr.sa, length);
- }
- }
-
- void close()
- {
-#if defined(_WIN32)
- if (mImpl.fd != -1) closesocket(mImpl.fd);
-#else
- if (mImpl.fd != -1) ::close(mImpl.fd);
-#endif
- }
-};
-
-
-class SocketMultiplexer
-{
-public:
-
- typedef boost::function<int(SocketMultiplexer&,
- Packet&,
- const SocketAddress&)> Function;
-
- explicit SocketMultiplexer(Socket sock) :
- mSocket(sock) {}
-
-
- void setSocket(Socket sock)
- {
- Mutex::ScopedLock lock(mMutex);
- mSocket = sock;
- }
-
- Socket& socket()
- {
- return mSocket;
- }
-
-
- std::vector<Function>& protocols()
- {
- return mProtocols;
- }
-
-
- void update(Scalar t, Scalar dt)
- {
- SocketAddress address;
- Packet packet;
- ssize_t bytes = mSocket.read(packet, address);
-
- if (bytes > 0)
- {
- std::vector<Function>::iterator it;
- for (it = mProtocols.begin(); it < mProtocols.end(); ++it)
- {
- packet.reset();
- if ((*it)(*this, packet, address)) break;
- }
- }
- }
-
-
- int background()
- {
- return 0;
- }
-
-
-private:
-
- Socket mSocket;
- std::vector<Function> mProtocols;
- Mutex mMutex;
-};
-
-
-/**
- * An asynchronous task to resolve addresses.
- */
-class ResolverTask : public ThreadedTask
-{
-public:
-
- /**
- * Construct a resolver task from a service and hostname.
- * \param service Server name or port number.
- * \param name The hostname or numeric address.
- * \param type The type of communication.
- * \param family The requested protocol family.
- */
- ResolverTask(const std::string& service,
- const std::string& name,
- int type = SOCK_STREAM,
- int family = AF_UNSPEC) :
- mIsDone(false)
- {
- mFunction = boost::bind(&ResolverTask::resolve,
- this, service, name, type, family);
- }
-
-
- /**
- * Get whether or not the task is done.
- * \return True if the task has finished, false otherwise.
- */
- bool isDone() const
- {
- return mIsDone;
- }
-
- /**
- * Start the task. This does nothing if the task was already run or is
- * currently running.
- */
- void run()
- {
- if (!isDone() && !mThread.isValid())
- {
- mThread = Thread::detach(mFunction);
- }
- }
-
-
- /**
- * Get the addresses resolved. This is filled and safe to access after
- * the task finishes.
- * \return List of addresses.
- * \see isDone()
- */
- const std::vector<SocketAddress>& addresses() const
- {
- return mAddressList;
- }
-
-
-private:
-
- int resolve(const std::string& service,
- const std::string& name,
- int type,
- int family)
- {
- int status = SocketAddress::resolve(service, name,
- type, family,
- mAddressList);
- mIsDone = true;
- return status;
- }
-
-
- std::vector<SocketAddress> mAddressList;
- bool mIsDone;
- Thread::Function mFunction;
-};
-
-
-std::ostream& operator<<(std::ostream& stream, const SocketAddress& addr)
-{
- stream << addr.name() << ":" << addr.service();
- return stream;
-}
-
-std::ostream& operator<<(std::ostream& stream, const Socket& sock)
-{
- stream << sock.address();
- return stream;
-}
-
-
-} // namespace Mf
-
-#endif // _MOOF_SOCKET_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <cstdio>
-#include <deque>
-#include <list>
-#include <string>
-
-#include <boost/algorithm/string.hpp>
-
-#include <AL/al.h>
-#include <AL/alc.h>
-#include <vorbis/codec.h>
-#include <vorbis/vorbisfile.h>
-
-#include "Error.hh"
-#include "Manager.hh"
-#include "Log.hh"
-#include "Sound.hh"
-#include "Timer.hh"
-
-#define BUFFER_SIZE (64 * 1024)
-//#define BUFFER_SIZE (5*2048)
-
-namespace Mf {
-
-
-class Sound::Impl
-{
-public:
-
- static ALenum getAudioFormat(const vorbis_info* audioInfo)
- {
- if (audioInfo->channels == 1) return AL_FORMAT_MONO16;
- else return AL_FORMAT_STEREO16;
- }
-
-
- class Buffer;
- typedef boost::shared_ptr<Buffer> BufferP;
-
- class Buffer : public Manager<Buffer>
- {
- public:
-
- Buffer() :
- mBuffer(-1)
- {
- mOggStream.datasource = 0;
- }
-
- ~Buffer()
- {
- if (mOggStream.datasource)
- {
- ov_clear(&mOggStream);
- }
- if (int(mBuffer) != -1) alDeleteBuffers(1, &mBuffer);
- }
-
-
- void init(const std::string& name)
- {
- if (mOggStream.datasource)
- {
- ov_clear(&mOggStream);
- mOggStream.datasource = 0;
- }
-
- std::string path(name);
- if (!Sound::getPath(path))
- {
- Error(Error::RESOURCE_NOT_FOUND, path).raise();
- }
-
- if (ov_fopen((char*)path.c_str(), &mOggStream) < 0)
- {
- Error(Error::UNKNOWN_AUDIO_FORMAT, path).raise();
- }
-
- vorbis_info* vorbisInfo = ov_info(&mOggStream, -1);
- mFormat = getAudioFormat(vorbisInfo);
- mFreq = vorbisInfo->rate;
- }
-
-
- void loadAll(ALuint source)
- {
- if (!mOggStream.datasource) init(getName());
- if (!mOggStream.datasource) return;
-
- char data[BUFFER_SIZE];
- int size = 0;
-
- for (;;)
- {
- int section;
- int result = ov_read(&mOggStream, data + size,
- BUFFER_SIZE - size, 0, 2, 1, §ion);
-
- if (result > 0)
- {
- size += result;
- }
- else
- {
- if (result < 0) logWarning("vorbis playback error");
- break;
- }
- }
- if (size == 0)
- {
- logWarning << "decoded no bytes from "
- << getName() << std::endl;
- return;
- }
-
- alGenBuffers(1, &mBuffer);
-
- alBufferData(mBuffer, mFormat, data, size, mFreq);
- alSourcei(source, AL_BUFFER, mBuffer);
-
- // don't need to keep this loaded
- ov_clear(&mOggStream);
- mOggStream.datasource = 0;
- }
-
- bool stream(ALuint buffer)
- {
- char data[BUFFER_SIZE];
- int size = 0;
-
- while (size < BUFFER_SIZE)
- {
- int section;
- int result = ov_read(&mOggStream, data + size,
- BUFFER_SIZE - size, 0, 2, 1, §ion);
-
- if (result > 0)
- {
- size += result;
- }
- else
- {
- if (result < 0) logWarning("vorbis playback error");
- break;
- }
- }
-
- if (size == 0) return false;
-
- alBufferData(buffer, mFormat, data, size, mFreq);
-
- return true;
- }
-
- void rewind()
- {
- if (!mOggStream.datasource) init(getName());
- else ov_raw_seek(&mOggStream, 0);
- }
-
-
- private:
-
- OggVorbis_File mOggStream;
- ALenum mFormat;
- ALsizei mFreq;
- ALuint mBuffer;
- };
-
-
- Impl()
- {
- init();
- }
-
- Impl(const std::string& name)
- {
- init();
- enqueue(name);
- }
-
- void init()
- {
- retainBackend();
-
- mIsLoaded = false;
- mIsPlaying = false;
- mIsLooping = false;
-
- alGenSources(1, &mSource);
-
- ALfloat zero[] = {0.0f, 0.0f, 0.0f};
- alSourcef(mSource, AL_PITCH, 1.0f);
- alSourcef(mSource, AL_GAIN, 1.0f);
- alSourcefv(mSource, AL_POSITION, zero);
- alSourcefv(mSource, AL_VELOCITY, zero);
-
- alSourcei(mSource, AL_LOOPING, mIsLooping);
- }
-
- ~Impl()
- {
- stop();
-
- alDeleteSources(1, &mSource);
-
- while (!mBuffers.empty())
- {
- alDeleteBuffers(1, &mBuffers.back());
- mBuffers.pop_back();
- }
-
- releaseBackend();
- }
-
-
- void play()
- {
- if (mQueue.empty()) return;
-
- if (!mIsLoaded) mQueue.front()->loadAll(mSource);
-
- alSourcePlay(mSource);
- mIsLoaded = true;
- }
-
-
- void playStream()
- {
- if (mQueue.empty()) return;
-
- if (!mIsPlaying)
- {
- alSourcei(mSource, AL_LOOPING, false);
- bufferStream();
- }
-
- if (!mStreamTimer.isValid())
- {
- mStreamTimer.init(boost::bind(&Impl::streamUpdate, this, _1, _2),
- 1.0, Timer::REPEAT);
- }
-
- alSourcePlay(mSource);
- mIsPlaying = true;
- }
-
- void bufferStream()
- {
- ALuint buffer;
- for (int i = mBuffers.size(); i <= 8; ++i)
- {
- alGenBuffers(1, &buffer);
-
- if (mQueue.front()->stream(buffer))
- {
- alSourceQueueBuffers(mSource, 1, &buffer);
- mBuffers.push_back(buffer);
- }
- else
- {
- alDeleteBuffers(1, &buffer);
- break;
- }
- }
- }
-
-
- void update()
- {
- ALint finished = 0;
-
- alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &finished);
-
- while (finished-- > 0)
- {
- ALuint bufferObj;
- alSourceUnqueueBuffers(mSource, 1, &bufferObj);
-
- BufferP buffer = mQueue.front();
- bool streamed = buffer->stream(bufferObj);
-
- if (streamed)
- {
- alSourceQueueBuffers(mSource, 1, &bufferObj);
- }
- else
- {
- // the buffer couldn't be streamed, so get rid of it
- mQueue.pop_front();
-
- if (!mQueue.empty())
- {
- // begin the next buffer in the queue
- mQueue.front()->rewind();
- mQueue.front()->stream(bufferObj);
- alSourceQueueBuffers(mSource, 1, &bufferObj);
- logInfo("loading new buffer");
-
- // queue up any unused buffers
- bufferStream();
- }
- else if (mIsLooping)
- {
- // reload the same buffer
- mQueue.push_back(buffer);
- buffer->rewind();
- buffer->stream(bufferObj);
- alSourceQueueBuffers(mSource, 1, &bufferObj);
- logInfo("looping same buffer");
- }
- else
- {
- // nothing more to play, stopping...
- mIsPlaying = false;
- std::remove(mBuffers.begin(), mBuffers.end(),
- bufferObj);
- }
- }
- }
-
- ALenum state;
- alGetSourcei(mSource, AL_SOURCE_STATE, &state);
-
- // restart playing if we're stopped but supposed to be playing...
- // this means we didn't queue enough and the audio skipped :-(
- if (mIsPlaying && state != AL_PLAYING)
- {
- alSourcePlay(mSource);
- }
- }
-
-
- void stop()
- {
- alSourceStop(mSource);
- mIsPlaying = false;
-
- mStreamTimer.invalidate();
- }
-
- void pause()
- {
- alSourcePause(mSource);
- mIsPlaying = false;
-
- mStreamTimer.invalidate();
- }
-
-
- void setSample(const std::string& name)
- {
- stop();
- alSourcei(mSource, AL_BUFFER, AL_NONE);
-
- mQueue.clear();
- mIsLoaded = false;
-
- enqueue(name);
-
- while (!mBuffers.empty())
- {
- alDeleteBuffers(1, &mBuffers.back());
- mBuffers.pop_back();
- }
- }
-
- void enqueue(const std::string& name)
- {
- BufferP buffer = Buffer::getInstance(name);
- mQueue.push_back(buffer);
- }
-
-
- bool isPlaying() const
- {
- if (mIsPlaying) return true;
-
- ALenum state;
- alGetSourcei(mSource, AL_SOURCE_STATE, &state);
-
- return state == AL_PLAYING;
- }
-
-
- void setLooping(bool looping)
- {
- mIsLooping = looping;
-
- ALenum type;
- alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
-
- if (type != AL_STREAMING)
- {
- alSourcei(mSource, AL_LOOPING, mIsLooping);
- }
- }
-
-
- void streamUpdate(Timer& timer, Scalar t)
- {
- // don't let the music die!
- update();
- // TODO - might be nice to also allow using threads for streaming
- // rather than a timer, probably as a compile-time option
- }
-
- static void retainBackend()
- {
- if (gRetainCount++ == 0)
- {
- gAlDevice = alcOpenDevice(0);
- gAlContext = alcCreateContext(gAlDevice, 0);
- if (!gAlDevice || !gAlContext)
- {
- const char* error = alcGetString(gAlDevice,
- alcGetError(gAlDevice));
- logError << "audio subsystem initialization failure: "
- << error << std::endl;
- }
- else
- {
- alcMakeContextCurrent(gAlContext);
- logInfo << "opened sound device `"
- << alcGetString(gAlDevice,
- ALC_DEFAULT_DEVICE_SPECIFIER)
- << "'" << std::endl;
- }
- }
- }
-
- static void releaseBackend()
- {
- if (--gRetainCount == 0)
- {
- alcMakeContextCurrent(0);
- alcDestroyContext(gAlContext);
- alcCloseDevice(gAlDevice);
- }
- }
-
-
- ALuint mSource;
- std::list<ALuint> mBuffers;
-
- bool mIsLoaded;
- bool mIsPlaying;
- bool mIsLooping;
-
- std::deque<BufferP> mQueue;
-
- Timer mStreamTimer;
-
- static unsigned gRetainCount;
- static ALCdevice* gAlDevice;
- static ALCcontext* gAlContext;
-};
-
-unsigned Sound::Impl::gRetainCount = 0;
-ALCdevice* Sound::Impl::gAlDevice = 0;
-ALCcontext* Sound::Impl::gAlContext = 0;
-
-
-Sound::Sound() :
- // pass through
- mImpl(new Sound::Impl) {}
-
-Sound::Sound(const std::string& name) :
- // pass through
- mImpl(new Sound::Impl(name)) {}
-
-
-void Sound::setSample(const std::string& name)
-{
- // pass through
- mImpl->setSample(name);
-}
-
-
-void Sound::play()
-{
- // pass through
- mImpl->play();
-}
-
-void Sound::stop()
-{
- // pass through
- mImpl->stop();
-}
-
-void Sound::pause()
-{
- // pass through
- mImpl->pause();
-}
-
-
-void Sound::toggle()
-{
- if (isPlaying()) pause();
- else play();
-}
-
-bool Sound::isPlaying() const
-{
- // pass through
- return mImpl->isPlaying();
-}
-
-
-void Sound::setPosition(const Vector3& position)
-{
- float vec[3] = {position[0], position[1], position[2]};
- alSourcefv(mImpl->mSource, AL_POSITION, vec);
-}
-
-void Sound::setVelocity(const Vector3& velocity)
-{
- float vec[3] = {velocity[0], velocity[1], velocity[2]};
- alSourcefv(mImpl->mSource, AL_VELOCITY, vec);
-}
-
-void Sound::setGain(Scalar gain)
-{
- alSourcef(mImpl->mSource, AL_GAIN, float(gain));
-}
-
-void Sound::setPitch(Scalar pitch)
-{
- alSourcef(mImpl->mSource, AL_PITCH, float(pitch));
-}
-
-void Sound::setLooping(bool looping)
-{
- // pass through
- mImpl->setLooping(looping);
-}
-
-
-void Sound::setListenerPosition(const Vector3& position)
-{
- float vec[] = {position[0], position[1], position[2]};
- alListenerfv(AL_POSITION, vec);
-}
-
-void Sound::setListenerVelocity(const Vector3& velocity)
-{
- float vec[] = {velocity[0], velocity[1], velocity[2]};
- alListenerfv(AL_VELOCITY, vec);
-}
-
-void Sound::setListenerOrientation(const Vector3& forward,
- const Vector3& up)
-{
- float vec[6];
- vec[0] = float(forward[0]);
- vec[1] = float(forward[1]);
- vec[2] = float(forward[2]);
- vec[3] = float(up[0]);
- vec[4] = float(up[1]);
- vec[5] = float(up[2]);
- alListenerfv(AL_ORIENTATION, vec);
-}
-
-
-bool Sound::getPath(std::string& name)
-{
- return Resource::getPath(name, "sounds/", "ogg");
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-
-void SoundStream::enqueue(const std::string& name)
-{
- // pass through
- mImpl->enqueue(name);
-}
-
-
-void SoundStream::play()
-{
- // pass through
- mImpl->playStream();
-}
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_SOUND_HH_
-#define _MOOF_SOUND_HH_
-
-/**
- * @file Sound.hh
- * Load and play sounds, current supports ogg vorbis.
- */
-
-#include <string>
-
-#include <boost/shared_ptr.hpp>
-
-#include <Moof/Math.hh>
-#include <Moof/Resource.hh>
-
-
-namespace Mf {
-
-
-class Sound;
-typedef boost::shared_ptr<Sound> SoundP;
-
-class SoundStream;
-typedef boost::shared_ptr<SoundStream> SoundStreamP;
-
-
-class Sound : public Resource
-{
-public:
-
- static SoundP alloc(const std::string& name)
- {
- return SoundP(new Sound(name));
- }
-
- Sound();
- explicit Sound(const std::string& name);
-
- virtual ~Sound() {}
-
- // this implicitly stops the sound if it is playing
- void setSample(const std::string& name);
-
- virtual void play();
- void stop();
- void pause();
-
- void toggle();
- bool isPlaying() const;
-
- void setPosition(const Vector3& position);
- void setVelocity(const Vector3& velocity);
- void setGain(Scalar gain);
- void setPitch(Scalar pitch);
- void setLooping(bool looping);
-
- static void setListenerPosition(const Vector3& position);
- static void setListenerVelocity(const Vector3& velocity);
- static void setListenerOrientation(const Vector3& forward,
- const Vector3& up);
-
- static bool getPath(std::string& name);
-
-protected:
-
- class Impl;
- boost::shared_ptr<Impl> mImpl;
-};
-
-
-class SoundStream : public Sound
-{
-public:
-
- static SoundStreamP alloc(const std::string& name)
- {
- return SoundStreamP(new SoundStream(name));
- }
-
- SoundStream();
- explicit SoundStream(const std::string& name) :
- Sound(name) {}
-
- void enqueue(const std::string& name);
-
- void play();
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_SOUND_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_STRINGTOOLS_HH_
-#define _MOOF_STRINGTOOLS_HH_
-
-#include <string>
-
-
-namespace Mf {
-
-std::wstring multiToWide(const std::string& multiStr);
-std::string wideToMulti(const std::wstring& wideStr);
-
-} // namespace Mf
-
-
-#endif // _MOOF_STRINGTOOLS_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <cstdio> // FILE
-#include <cstring> // strncmp
-
-#include <boost/algorithm/string.hpp>
-#include <boost/bind.hpp>
-
-#include "Dispatch.hh"
-#include "Error.hh"
-#include "Manager.hh"
-#include "Log.hh"
-#include "OpenGL.hh"
-#include "Script.hh"
-#include "Texture.hh"
-#include "Video.hh"
-
-
-namespace Mf {
-
-
-/**
- * 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 manager so that multiple texture
- * objects can share the same internal objects and avoid having duplicate
- * textures loaded to GL.
- */
-
-class Texture::Impl : public Manager<Impl>
-{
-
- /**
- * Delete the texture (if it is loaded) from GL.
- */
-
- void unloadFromGL()
- {
- if (mObject)
- {
- if (mObject == gObject)
- {
- gObject = 0;
- }
-
- glDeleteTextures(1, &mObject);
- mObject = 0;
- }
- }
-
- /**
- * If the GL context was recreated, we 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()
- {
- mObject = gObject = 0;
- uploadToGL();
- }
-
- /**
- * 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)
- {
- int value = 1;
-
- while (value < input)
- {
- value <<= 1;
- }
- return value;
- }
-
-
- static void bindScriptConstants(Script& script)
- {
- Script::Slot g = script.globals();
-
- g.setField("CLAMP", GL_CLAMP);
- g.setField("REPEAT", GL_REPEAT);
- g.setField("LINEAR", GL_LINEAR);
- g.setField("NEAREST", GL_NEAREST);
- g.setField("LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR);
- g.setField("LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST);
- g.setField("NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR);
- g.setField("NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST);
- }
-
-public:
-
- /**
- * Construction is initialization.
- */
-
- Impl() :
- mMinFilter(GL_NEAREST),
- mMagFilter(GL_NEAREST),
- mWrapS(GL_CLAMP),
- mWrapT(GL_CLAMP),
- mTilesS(1),
- mTilesT(1),
- mObject(0)
- {
- // make sure we have a video context
- Video* video = Video::current();
- ASSERT(video && "should have a video context set");
-
- // we want to know when the GL context is recreated
- Dispatch& dispatch = Dispatch::global();
- mNewContextDispatch = dispatch.addTarget("video.newcontext",
- boost::bind(&Impl::contextRecreated, this));
- }
-
- ~Impl()
- {
- unloadFromGL();
- }
-
-
- /**
- * 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)
- {
- int w = powerOfTwo(surface->w);
- int h = powerOfTwo(surface->h);
-
- // 2. OpenGL textures make more sense within the coordinate system
- // when they are "upside down," so let's flip it.
-
- flipSurface(surface);
-
- // 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 if textures are the right size
- // to begin with.
-
- SDL_Surface* image = SDL_CreateRGBSurface
- (
- SDL_SWSURFACE,
- w, h,
- 32,
-#if SDL_BYTEORDER == SDL_LIL_ENDIAN
- 0x000000FF,
- 0x0000FF00,
- 0x00FF0000,
- 0xFF000000
-#else
- 0xFF000000,
- 0x00FF0000,
- 0x0000FF00,
- 0x000000FF
-#endif
- );
-
- if (!image)
- {
- return 0;
- }
-
- Uint32 savedFlags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
- Uint8 savedAlpha = surface->format->alpha;
- if (savedFlags & SDL_SRCALPHA)
- {
- SDL_SetAlpha(surface, 0, 0);
- }
-
- SDL_Rect srcArea, destArea;
- srcArea.x = 0; destArea.x = 0;
- srcArea.y = 0; destArea.y = h - surface->h;
- srcArea.w = surface->w;
- srcArea.h = surface->h;
- SDL_BlitSurface(surface, &srcArea, image, &destArea);
-
- if (savedFlags & SDL_SRCALPHA)
- {
- SDL_SetAlpha(surface, savedFlags, savedAlpha);
- }
-
- return image;
- }
- */
-
- /**
- * Use SDL_image to load images from file. A surface with the image
- * data is returned.
- * @return Image data.
- */
-
- void init(const std::string& name)
- {
- std::string path(name);
-
- Texture::getPath(path);
-
- mImage = Image::alloc(path);
- if (!mImage->isValid())
- {
- logWarning << "texture not found: " << path << std::endl;
- Error(Error::RESOURCE_NOT_FOUND, path).raise();
- }
-
- mImage->flip();
-
- Script script;
-
- importLogFunctions(script);
- bindScriptConstants(script);
-
- if (script.doString(mImage->getComment()) != Script::SUCCESS)
- {
- std::string str;
- script[-1].get(str);
- logWarning(str);
- }
- else
- {
- logInfo << "loading tiles from texture " << path
- << std::endl;
-
- Script::Slot globals = script.globals();
- globals.get(mTilesS, "tiles_s");
- globals.get(mTilesT, "tiles_t");
- globals.get(mMinFilter, "min_filter");
- globals.get(mMagFilter, "mag_filter");
- globals.get(mWrapS, "wrap_s");
- globals.get(mWrapT, "wrap_t");
- }
- }
-
-
- /**
- * 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 (mObject)
- {
- // already loaded
- return;
- }
-
- glGenTextures(1, &mObject);
- glBindTexture(GL_TEXTURE_2D, mObject);
-
- glTexImage2D
- //gluBuild2DMipmaps
- (
- GL_TEXTURE_2D,
- 0,
- mImage->getMode(),
- //3,
- mImage->getWidth(),
- mImage->getHeight(),
- 0,
- mImage->getMode(),
- GL_UNSIGNED_BYTE,
- mImage->getPixels()
- );
-
- setProperties();
- }
-
-
- /**
- * Sets some texture properties such as the filters and external
- * coordinate behavior.
- */
-
- void setProperties()
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mMinFilter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mMagFilter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mWrapS);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mWrapT);
- }
-
- inline void setMinFilter(GLuint filter)
- {
- bind();
- mMinFilter = filter;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mMinFilter);
- }
-
- inline void setMagFilter(GLuint filter)
- {
- bind();
- mMagFilter = filter;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mMagFilter);
- }
-
- inline void setWrapS(GLuint wrap)
- {
- bind();
- mWrapS = wrap;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mWrapS);
- }
-
- inline void setWrapT(GLuint wrap)
- {
- bind();
- mWrapT = wrap;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mWrapT);
- }
-
-
- inline void bind()
- {
- if (mObject == 0)
- {
- uploadToGL();
- }
- if (mObject != gObject)
- {
- glBindTexture(GL_TEXTURE_2D, mObject);
- gObject = mObject;
- }
- }
-
-
- bool getTileCoords(Texture::TileIndex index, Scalar coords[8]) const
- {
- // make sure the index represents a real tile
- if (index >= mTilesS * mTilesT) return false;
-
- Scalar w = 1.0 / Scalar(mTilesS);
- Scalar h = 1.0 / Scalar(mTilesT);
-
- coords[0] = Scalar(index % mTilesS) * w;
- coords[1] = (Scalar(mTilesT - 1) - Scalar(index / mTilesS)) * 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];
-
- return true;
- }
-
- ImageP mImage;
-
- GLuint mMinFilter; ///< Minification filter.
- GLuint mMagFilter; ///< Magnification filter.
- GLuint mWrapS; ///< Wrapping behavior horizontally.
- GLuint mWrapT; ///< Wrapping behavior vertically.
- unsigned mTilesS;
- unsigned mTilesT;
-
- GLuint mObject; ///< GL texture handle.
- static GLuint gObject; ///< Global GL texture handle.
-
- Dispatch::Handle mNewContextDispatch;
-};
-
-GLuint Texture::Impl::gObject = 0;
-
-
-Texture::Texture(const std::string& name) : // TODO hmm..
- Image(name),
- // pass through
- mImpl(Texture::Impl::getInstance(name)) {}
-
-
-/**
- * Bind the GL texture for mapping, etc.
- */
-
-void Texture::bind() const
-{
- // pass through
- mImpl->bind();
-}
-
-
-/**
- * Get the texture object, for the curious.
- */
-
-GLuint Texture::getObject() const
-{
- // pass through
- return mImpl->mObject;
-}
-
-
-void Texture::resetBind()
-{
- glBindTexture(GL_TEXTURE_2D, 0);
- Impl::gObject = 0;
-}
-
-
-void Texture::setMinFilter(GLuint filter)
-{
- // pass through
- mImpl->setMinFilter(filter);
-}
-
-void Texture::setMagFilter(GLuint filter)
-{
- // pass through
- mImpl->setMagFilter(filter);
-}
-
-void Texture::setWrapS(GLuint wrap)
-{
- // pass through
- mImpl->setWrapS(wrap);
-}
-
-void Texture::setWrapT(GLuint wrap)
-{
- // pass through
- mImpl->setWrapT(wrap);
-}
-
-
-bool Texture::getTileCoords(TileIndex index, Scalar coords[8]) const
-{
- // pass through
- return mImpl->getTileCoords(index, coords);
-}
-
-bool Texture::getTileCoords(TileIndex index, Scalar coords[8],
- Orientation orientation) const
-{
- if (getTileCoords(index, coords))
- {
- if (orientation & FLIP)
- {
- // this looks kinda weird, but it's just swapping in a way that
- // doesn't require an intermediate variable
- coords[1] = coords[5];
- coords[5] = coords[3];
- coords[3] = coords[7];
- coords[7] = coords[5];
- }
- if (orientation & REVERSE)
- {
- coords[0] = coords[2];
- coords[2] = coords[6];
- coords[4] = coords[6];
- coords[6] = coords[0];
- }
-
- return true;
- }
-
- return false;
-}
-
-
-bool Texture::getPath(std::string& name)
-{
- return Resource::getPath(name, "textures/", "png");
-}
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <cerrno>
-#include <ctime>
-#include <limits>
-
-#include <SDL/SDL.h>
-
-#include "Log.hh"
-#include "Timer.hh"
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
-namespace Mf {
-
-
-Scalar Timer::gNextFire = std::numeric_limits<Scalar>::max();
-std::map<unsigned,Timer*> Timer::gTimers;
-
-
-unsigned Timer::getNewID()
-{
- static unsigned id = 1;
- return id++;
-}
-
-
-void Timer::init(const Function& function, Scalar seconds, Mode mode)
-{
- invalidate();
-
- mMode = mode;
-
- if (mMode != INVALID)
- {
- mFunction = function;
-
- if (mode == ACTUAL)
- {
- mAbsolute = seconds;
- }
- else
- {
- mAbsolute = seconds - getTicks();
- mInterval = seconds;
- }
-
- mId = getNewID();
- gTimers.insert(std::pair<unsigned,Timer*>(mId, this));
-
- if (mAbsolute < gNextFire) gNextFire = mAbsolute;
- }
-}
-
-
-bool Timer::isValid() const
-{
- return mMode != INVALID;
-}
-
-void Timer::invalidate()
-{
- if (mMode != INVALID)
- {
- gTimers.erase(mId);
- mMode = INVALID;
-
- if (isEqual(mAbsolute, gNextFire)) gNextFire = findNextFire();
- }
-}
-
-
-void Timer::fire()
-{
- Scalar t = getTicks();
-
- if (mFunction) mFunction(*this, t);
-
- if (isRepeating())
- {
- Scalar absolute = mAbsolute;
-
- if (isEqual(mAbsolute, t, 1.0)) mAbsolute += mInterval;
- else mAbsolute = mInterval + t;
-
- if (isEqual(absolute, gNextFire)) gNextFire = findNextFire();
- }
- else
- {
- invalidate();
- }
-}
-
-
-Scalar Timer::findNextFire()
-{
- std::map<unsigned,Timer*>::iterator it;
- Scalar nextFire = std::numeric_limits<Scalar>::max();
-
- for (it = gTimers.begin(); it != gTimers.end(); ++it)
- {
- Scalar absolute = (*it).second->mAbsolute;
- if (absolute < nextFire) nextFire = absolute;
- }
-
- return nextFire;
-}
-
-
-Scalar Timer::getSecondsRemaining() const
-{
- return mAbsolute - getTicks();
-}
-
-bool Timer::isExpired() const
-{
- return getSecondsRemaining() < 0.0;
-}
-
-bool Timer::isRepeating() const
-{
- return mMode == REPEAT;
-}
-
-
-void Timer::fireIfExpired()
-{
- fireIfExpired(getTicks());
-}
-
-void Timer::fireIfExpired(Scalar t)
-{
- std::map<unsigned,Timer*>::iterator it;
-
- if (gNextFire > t) return;
-
- for (it = gTimers.begin(); it != gTimers.end(); ++it)
- {
- Timer* timer = (*it).second;
- if (timer->isExpired()) timer->fire();
- }
-}
-
-
-#if HAVE_CLOCK_GETTIME
-
-// Since the monotonic clock will provide us with the time 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 uptime), 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-precision number.
-
-static time_t setReference_()
-{
- struct timespec ts;
-
- if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
- {
- return 0;
- }
-
- return ts.tv_sec;
-}
-
-static const time_t reference = setReference_();
-
-
-Scalar Timer::getTicks()
-{
- struct timespec ts;
-
- int result = clock_gettime(CLOCK_MONOTONIC, &ts);
- ASSERT(result == 0 && "cannot access clock");
-
- return Scalar(ts.tv_sec - reference) +
- Scalar(ts.tv_nsec) / 1000000000.0;
-}
-
-void Timer::sleep(Scalar seconds, Mode mode)
-{
- struct timespec ts;
- int ret;
-
- if (mode == ACTUAL) seconds -= getTicks();
- ts.tv_sec = time_t(seconds);
- ts.tv_nsec = long((seconds - Scalar(ts.tv_sec)) * 1000000000.0);
-
- do
- {
- ret = nanosleep(&ts, &ts);
- }
- while (ret == -1 && errno == EINTR);
-}
-
-
-#else // ! HAVE_CLOCK_GETTIME
-
-
-// If we don't have posix timers, we'll have to use a different timing
-// method. SDL only promises centisecond accuracy, but that's better than
-// a kick in the pants.
-
-Scalar Timer::getTicks()
-{
- Uint32 ms = SDL_GetTicks();
- return Scalar(ms / 1000) + Scalar(ms % 1000) / 1000.0;
-}
-
-void Timer::sleep(Scalar seconds, Mode mode)
-{
- if (mode == ACTUAL) seconds -= getTicks();
- SDL_Delay(Uint32(cml::clamp(int(seconds * 1000.0), 0, 1000)));
-}
-
-#endif // HAVE_CLOCK_GETTIME
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#define _MOOF_TRANSITION_HH_
-#ifndef _MOOF_TRANSITION_HH_
-#define _MOOF_TRANSITION_HH_
-
-#include <boost/shared_ptr.hpp>
-
-#include <Moof/Core.hh>
-#include <Moof/Interpolator.hh>
-#include <Moof/Layer.hh>
-#include <Moof/Log.hh>
-#include <Moof/Math.hh>
-#include <Moof/OpenGL.hh>
-#include <Moof/Texture.hh>
-
-
-namespace Mf {
-
-
-template <class T>
-class Transition : public Layer
-{
- LayerP mTo;
- LayerP mFrom;
-
- T mInterp;
-
-public:
-
- Transition(LayerP t, LayerP f, const T& interp) :
- mTo(t),
- mFrom(f),
- mInterp(interp) {}
-
- typedef boost::shared_ptr<Transition> Ptr;
-
- static Ptr alloc(LayerP t, LayerP f, const T& interp)
- {
- return Ptr(new Transition(t, f, interp));
- }
-
-
- void removedFromCore(Core& core)
- {
- if (mTo) core.push(mTo);
- }
-
- void update(Core& core, Scalar t, Scalar dt)
- {
- mInterp.update(t, dt);
-
- if (mFrom) mFrom->update(core, t, dt);
- if (mTo) mTo->update(core, t, dt);
-
- if (mInterp.isDone())
- {
- // to should /replace/ this
- core.pop(this);
- }
- }
-
- void drawFade(Scalar alpha) const
- {
- // DRAW FADE
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_ALPHA_TEST);
- glEnable(GL_BLEND);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glColor(1.0, 1.0, 1.0, alpha);
- Mf::Texture::resetBind();
-
- //glRectf(-1.0f, -1.0f, 1.0f, 1.0f);
- glBegin(GL_QUADS);
- glVertex(-1.0, -1.0, -0.1);
- glVertex(1.0, -1.0, -0.1);
- glVertex(1.0, 1.0, -0.1);
- glVertex(-1.0, 1.0, -0.1);
- glEnd();
-
- glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_ALPHA_TEST);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
-
- void draw(Core& core, Scalar alpha) const
- {
- Scalar a = mInterp.getState(alpha);
- logInfo << "transition state: " << a << std::endl;
-
- //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- if (mFrom)
- {
- glPushMatrix();
- glLoadIdentity();
- glRotate(180.0 * a, 0.0, 1.0, 0.0);
- mFrom->draw(core, alpha);
- glPopMatrix();
- }
- //drawFade(a);
-
- if (mTo)
- {
- glPushMatrix();
- glLoadIdentity();
- glRotate(180.0 * (1.0 - a), 0.0, 1.0, 0.0);
- mTo->draw(core, alpha);
- glPopMatrix();
- }
- //drawFade(1.0 - a);
- }
-
- bool handleEvent(Core& core, const Event& event)
- {
- if (mTo)
- {
- return mTo->handleEvent(core, event);
- }
- else if (mFrom)
- {
- return mFrom->handleEvent(core, event);
- }
- return false;
- }
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_TRANSITION_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include "Dispatch.hh"
-#include "Error.hh"
-#include "Image.hh"
-#include "Log.hh"
-#include "Settings.hh"
-#include "Video.hh"
-
-
-namespace Mf {
-
-
-Video::Video()
-{
- init();
-}
-
-Video::Video(const Attributes& attribs) :
- mAttribs(attribs)
-{
- init();
-}
-
-void Video::init()
-{
- Error error = Backend::getError();
- if (error) error.raise();
-
- mContext = 0;
- mFlags = 0;
-
- setFull(mAttribs.fullscreen);
- setResizable(mAttribs.resizable);
- setOpenGLAttributes();
- setCaption(mAttribs.caption);
- setIcon();
- setCursorVisible(mAttribs.cursorVisible);
- setCursorGrab(mAttribs.cursorGrab);
- setVideoMode(mAttribs.mode);
-
- if (!gCurrentVideo) makeCurrent();
-}
-
-void Video::recreateContext()
-{
- SDL_FreeSurface(mContext);
- mContext = 0;
- setVideoMode(mAttribs.mode);
-}
-
-void Video::setOpenGLAttributes()
-{
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE,
- mAttribs.colorBuffer[0]);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,
- mAttribs.colorBuffer[1]);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,
- mAttribs.colorBuffer[2]);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,
- mAttribs.colorBuffer[3]);
- SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,
- mAttribs.frameBuffer);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,
- mAttribs.doubleBuffer);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,
- mAttribs.depthBuffer);
- SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,
- mAttribs.stencilBuffer);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE,
- mAttribs.accumBuffer[0]);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE,
- mAttribs.accumBuffer[1]);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE,
- mAttribs.accumBuffer[2]);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE,
- mAttribs.accumBuffer[3]);
- SDL_GL_SetAttribute(SDL_GL_STEREO,
- mAttribs.stereo);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,
- mAttribs.multisampleBuffers);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES,
- mAttribs.multisampleSamples);
- SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL,
- mAttribs.swapControl);
- SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,
- mAttribs.hardwareOnly);
-}
-
-
-Video::~Video()
-{
- SDL_FreeSurface(mContext);
-
- if (gCurrentVideo == this) gCurrentVideo = 0;
-}
-
-
-void Video::setVideoMode(const int mode[3])
-{
- if (mode != mAttribs.mode || !mContext)
- {
- if (mContext) SDL_FreeSurface(mContext);
-
- mContext = SDL_SetVideoMode(mode[0], mode[1], mode[2],
- SDL_OPENGL | mFlags);
-
- if (mContext)
- {
- mAttribs.mode[0] = mode[0];
- mAttribs.mode[1] = mode[1];
- mAttribs.mode[2] = mode[2];
-
-#if !defined(linux) && !defined(__linux) && !defined(__linux__)
- logInfo("video context recreated");
- Dispatch::global().dispatch("video.newcontext");
-#endif
- }
- else Error(Error::SDL_VIDEOMODE).raise();
- }
-}
-
-Video::Attributes Video::attributes() const
-{
- return mAttribs;
-}
-
-
-void Video::resize(int width, int height)
-{
- int mode[] = {width, height, mAttribs.mode[2]};
- setVideoMode(mode);
-}
-
-bool Video::iconify()
-{
- return SDL_WM_IconifyWindow();
-}
-
-
-void Video::setCaption(const std::string& caption)
-{
- mAttribs.caption = caption;
- SDL_WM_SetCaption(caption.c_str(), 0);
-}
-
-void Video::setIcon()
-{
- if (mAttribs.icon != "")
- {
- Image icon(mAttribs.icon);
- icon.setAsIcon();
- }
-}
-
-std::string Video::getCaption() const
-{
- return mAttribs.caption;
-}
-
-const std::string& Video::getIcon() const
-{
- return mAttribs.icon;
-}
-
-
-void Video::setFull(bool full)
-{
- if (full != isFull() || !mContext)
- {
- if (mContext)
- {
- mFlags ^= SDL_FULLSCREEN;
-
-#if defined(linux) || defined(__linux) || defined(__linux__)
- if (SDL_WM_ToggleFullScreen(mContext) == 0)
-#endif
- recreateContext();
- }
- else
- {
- if (full) mFlags |= SDL_FULLSCREEN;
- else mFlags &= ~SDL_FULLSCREEN;
- }
- }
-}
-
-void Video::toggleFull()
-{
- setFull(!isFull());
-}
-
-bool Video::isFull() const
-{
- return mFlags & SDL_FULLSCREEN;
-}
-
-
-void Video::setCursorVisible(bool hasCursor)
-{
- SDL_ShowCursor(hasCursor? SDL_ENABLE : SDL_DISABLE);
-}
-
-void Video::toggleCursorVisible()
-{
- setCursorVisible(!isCursorVisible());
-}
-
-bool Video::isCursorVisible() const
-{
- return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE);
-}
-
-
-void Video::setResizable(bool resizable)
-{
- if (resizable != isResizable() || !mContext)
- {
- if (mContext)
- {
- mFlags ^= SDL_RESIZABLE;
- recreateContext();
- }
- else
- {
- if (resizable) mFlags |= SDL_RESIZABLE;
- else mFlags &= ~SDL_RESIZABLE;
- }
- }
-}
-
-void Video::toggleResizable()
-{
- setResizable(!isResizable());
-}
-
-bool Video::isResizable() const
-{
- return mFlags & SDL_RESIZABLE;
-}
-
-
-bool Video::isCursorGrab() const
-{
- return (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON);
-}
-
-void Video::toggleCursorGrab()
-{
- setCursorGrab(!isCursorGrab());
-}
-
-void Video::setCursorGrab(bool cursorGrab)
-{
- SDL_WM_GrabInput(cursorGrab? SDL_GRAB_ON : SDL_GRAB_OFF);
-}
-
-
-void Video::swap()
-{
- SDL_GL_SwapBuffers();
-}
-
-
-int Video::getWidth() const
-{
- return mContext->w;
-}
-
-int Video::getHeight() const
-{
- return mContext->h;
-}
-
-
-void Video::makeCurrent() const
-{
- gCurrentVideo = const_cast<Video*>(this);
-}
-
-
-Video::Attributes::Attributes()
-{
- init();
-}
-
-Video::Attributes::Attributes(const Settings& settings)
-{
- init();
-
- std::vector<int> colors;
- settings.get("colorbuffers", colors);
- if (colors.size() > 0) colorBuffer[0] = colors[0];
- if (colors.size() > 1) colorBuffer[1] = colors[1];
- if (colors.size() > 2) colorBuffer[2] = colors[2];
- if (colors.size() > 3) colorBuffer[3] = colors[3];
-
- settings.get("framebuffer", frameBuffer);
- settings.get("doublebuffer", doubleBuffer);
- settings.get("depthbuffer", depthBuffer);
- settings.get("stencilbuffer", stencilBuffer);
-
- std::vector<int> accum;
- settings.get("accumbuffers", accum);
- if (accum.size() > 0) accumBuffer[0] = accum[0];
- if (accum.size() > 1) accumBuffer[1] = accum[1];
- if (accum.size() > 2) accumBuffer[2] = accum[2];
- if (accum.size() > 3) accumBuffer[3] = accum[3];
-
- settings.get("stereo", stereo);
- settings.get("multiesamplebuffers", multisampleBuffers);
- settings.get("multiesamplesamples", multisampleSamples);
- settings.get("swapcontrol", swapControl);
- settings.get("hardwareonly", hardwareOnly);
-
- if (!settings.get("caption", caption))
- {
- caption = "Untitled";
- }
- settings.get("icon", icon);
-
- settings.get("fullscreen", fullscreen);
- settings.get("resizable", resizable);
- settings.get("showcursor", cursorVisible);
- settings.get("grab", cursorGrab);
-
- std::vector<int> dimensions;
- settings.get("videomode", dimensions);
- if (dimensions.size() > 1)
- {
- mode[0] = dimensions[0];
- mode[1] = dimensions[1];
- }
- else if (fullscreen && Backend::isInitialized())
- {
- SDL_Rect** modes = SDL_ListModes(NULL,
- SDL_FULLSCREEN | SDL_HWSURFACE);
-
- if (modes == (SDL_Rect**)0)
- {
- Mf::logError("no native video mode");
- }
- else if (modes == (SDL_Rect**)-1)
- {
- Mf::logWarning("any resolution allowed; "
- "choosing default 800x600");
- mode[0] = 800;
- mode[1] = 600;
- }
- else
- {
- mode[0] = (*modes)->w;
- mode[1] = (*modes)->h;
- Mf::logInfo << "choosing native resolution "
- << mode[0] << "x" << mode[1] << std::endl;
- }
- }
- if (dimensions.size() > 2) mode[2] = dimensions[2];
-}
-
-void Video::Attributes::init()
-{
- // set some sane GL and window defaults (see SDL_video.c:217)
- colorBuffer[0] = 3;
- colorBuffer[1] = 3;
- colorBuffer[2] = 2;
- colorBuffer[3] = 0;
- frameBuffer = 0;
- doubleBuffer = true;
- depthBuffer = 16;
- stencilBuffer = 0;
- accumBuffer[0] = 0;
- accumBuffer[1] = 0;
- accumBuffer[2] = 0;
- accumBuffer[3] = 0;
- stereo = false;
- multisampleBuffers = 0;
- multisampleSamples = 0;
- swapControl = false;
- hardwareOnly = false;
- mode[0] = 640;
- mode[1] = 480;
- mode[2] = 0;
- fullscreen = false;
- resizable = false;
- cursorVisible = true;
- cursorGrab = false;
-}
-
-
-Video* Video::gCurrentVideo = 0; // most recently instantiated instance
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_VIDEO_HH_
-#define _MOOF_VIDEO_HH_
-
-#include <string>
-
-#include <boost/shared_ptr.hpp>
-#include <SDL/SDL.h>
-
-#include <Moof/Backend.hh>
-
-
-namespace Mf {
-
-
-class Settings;
-
-class Video;
-typedef boost::shared_ptr<Video> VideoP;
-
-
-class Video
-{
-public:
-
- struct Attributes
- {
- // OpenGL attributes
- int colorBuffer[4]; // rgba
- int frameBuffer;
- bool doubleBuffer;
- int depthBuffer;
- int stencilBuffer;
- int accumBuffer[4]; // rgba
- bool stereo;
- int multisampleBuffers;
- int multisampleSamples;
- bool swapControl;
- bool hardwareOnly;
-
- // Window attributes
- std::string caption;
- std::string icon;
- int mode[3]; // width, height, bpp
- bool fullscreen;
- bool resizable;
- bool cursorVisible;
- bool cursorGrab;
-
- Attributes();
- Attributes(const Settings& settings);
-
- private:
-
- void init();
-
- Backend mBackend;
- };
-
-
- static VideoP alloc(const Attributes& attribs)
- {
- return VideoP(new Video(attribs));
- }
-
- Video();
- explicit Video(const Attributes& attribs);
- ~Video();
-
- void setVideoMode(const int mode[3]);
- Attributes attributes() const;
-
- void resize(int width, int height);
- bool iconify();
-
- void setCaption(const std::string& caption);
- std::string getCaption() const;
-
- const std::string& getIcon() const;
-
- void setFull(bool full);
- void toggleFull();
- bool isFull() const;
-
- void setCursorVisible(bool hasCursor);
- void toggleCursorVisible();
- bool isCursorVisible() const;
-
- void setResizable(bool resizable);
- void toggleResizable();
- bool isResizable() const;
-
- void setCursorGrab(bool cursorGrab);
- void toggleCursorGrab();
- bool isCursorGrab() const;
-
- void swap();
-
- int getWidth() const;
- int getHeight() const;
-
- void makeCurrent() const;
-
- static Video* current()
- {
- return gCurrentVideo;
- }
-
-private:
-
- void init();
-
- void recreateContext();
- void setOpenGLAttributes();
-
- void setIcon();
-
- // TODO this implementation should be hidden
-
- SDL_Surface* mContext;
- unsigned mFlags;
- Attributes mAttribs;
-
- static Video* gCurrentVideo;
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_VIDEO_HH_
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <algorithm>
-#include <cstdlib> // exit, srand
-#include <ctime> // time
-#include <string>
-
-#include <SDL/SDL.h>
-#include "fastevents.h"
-
-#include "Error.hh"
-#include "Event.hh"
-#include "Log.hh"
-#include "Math.hh"
-#include "ModalDialog.hh"
-#include "Settings.hh"
-#include "Timer.hh"
-#include "Video.hh"
-#include "View.hh"
-
-
-namespace Mf {
-
-
-class RootView : public View
-{
- void update(Scalar t, Scalar dt)
- {
- if (children().size() == 0) stop();
- }
-};
-
-static RootView gRootView;
-
-
-class View::Impl
-{
-public:
-
- Impl(View* view, Settings& settings, Video& video) :
- mView(*view),
- mSettings(&settings),
- mVideo(&video),
- mParent(&gRootView)
- {
- init();
-
- unsigned randomSeed;
- if (settings.get("rngseed", randomSeed)) srand(randomSeed);
- else srand(time(0));
-
- Scalar timestep = 80.0;
- settings.get("timestep", timestep);
- mTimestep = 1.0 / timestep;
-
- Scalar framerate = 40.0;
- settings.get("framerate", framerate);
- mFramerate = 1.0 / framerate;
-
- mShowFps = false;
- settings.get("showfps", mShowFps);
- }
-
- Impl(View* view) :
- mView(*view),
- mSettings(0),
- mVideo(0),
- mParent(&gRootView)
- {
- init();
- }
-
- void init()
- {
- mTimestep = SCALAR(0.01);
- mFramerate = SCALAR(0.02);
- mShowFps = false;
- }
-
-
- /**
- * The main loop. This just calls dispatchEvents(), update(), and
- * draw() over and over again. The timing of the update and draw are
- * decoupled. The actual frame rate is also calculated here. This
- * function will return the exit code used to stop the loop.
- */
-
- void run()
- {
- ASSERT(mVideo && "running without video set");
-
- Scalar totalTime = 0.0;
- Scalar ticks = Timer::getTicks();
-
- Scalar nextUpdate = ticks;
- Scalar nextDraw = ticks;
- Scalar nextSecond = ticks + SCALAR(1.0);
-
- mFps = 0;
- int frameCount = 0;
-
- const Scalar timestep = mTimestep;
- const Scalar framerate = mFramerate;
-
- const int MAX_FRAMESKIP = 15;
- const Scalar inverseTimestep = SCALAR(1.0) / timestep;
-
- mIsRunning = true;
- for (;;)
- {
- Timer::fireIfExpired(); // 1. fire timers
- dispatchEvents(); // 2. dispatch events
-
- if (!mIsRunning) break;
-
- int i = 0;
- while (nextUpdate < Timer::getTicks() && i < MAX_FRAMESKIP)
- {
- totalTime += timestep; // 3. update state
- mView.update(totalTime, timestep);
-
- nextUpdate += timestep;
- ++i;
-
- if (!mIsRunning) break;
- }
-
- if (nextDraw < (ticks = Timer::getTicks()))
- {
- mView.draw(
- (ticks + timestep - nextUpdate) * inverseTimestep);
- mVideo->swap(); // 4. draw state
-
- nextDraw += framerate;
- ++frameCount;
-
- if (nextSecond < Timer::getTicks())
- {
- mFps = frameCount;
- frameCount = 0;
-
- if (mShowFps) logInfo << mFps << " fps" << std::endl;
-
- nextSecond += SCALAR(1.0);
- }
- }
-
- if (!mIsRunning) break;
-
- ticks = Timer::getTicks(); // 5. yield timeslice
- if (ticks < nextUpdate && ticks < nextDraw) Timer::sleep(0.0);
- }
- }
-
- void stop()
- {
- mIsRunning = false;
- }
-
-
- void dispatchEvents()
- {
- Event event;
-
- while (FE_PollEvent(&event) == 1)
- {
- switch (event.type)
- {
- case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_ESCAPE &&
- (SDL_GetModState() & KMOD_CTRL) )
- {
- // emergency escape
- logWarning("escape forced");
- exit(1);
- }
- break;
-
- case SDL_VIDEORESIZE:
- mVideo->resize(event.resize.w, event.resize.h);
- break;
- }
-
- mView.handleEvent(event);
- }
- }
-
- bool handleEvent(const Event& event)
- {
- std::list<ViewP>::iterator it;
- for (it = mChildren.begin(); it != mChildren.end(); ++it)
- {
- if ((*it)->handleEvent(event)) return true;
- }
-
- return false;
- }
-
- void update(Scalar t, Scalar dt)
- {
- std::list<ViewP>::iterator it;
- for (it = mChildren.begin(); it != mChildren.end(); ++it)
- {
- (*it)->update(t, dt);
- }
- }
-
- void draw(Scalar alpha)
- {
- std::list<ViewP>::iterator it;
- for (it = mChildren.begin(); it != mChildren.end(); ++it)
- {
- (*it)->draw(alpha);
- }
- }
-
-
- void addChild(ViewP child)
- {
- ASSERT(child && "adding null view");
- ASSERT(child.get() != &mView && "adding view to itself");
-
- child->mImpl->mParent->removeChild(child);
- mChildren.push_back(child);
-
- child->mImpl->mParent = &mView;
- child->mImpl->percolateObjects();
-
- child->didAddToView();
- }
-
- void percolateObjects()
- {
- bool recurseAgain = false;
-
- if (mParent->mImpl->mVideo && mParent->mImpl->mVideo != mVideo)
- {
- mVideo = mParent->mImpl->mVideo;
- recurseAgain = true;
- }
-
- if (mParent->mImpl->mSettings &&
- mParent->mImpl->mSettings != mSettings)
- {
- mSettings = mParent->mImpl->mSettings;
- recurseAgain = true;
- }
-
- if (recurseAgain)
- {
- std::list<ViewP>::iterator it;
- for (it = mChildren.begin(); it != mChildren.end(); ++it)
- {
- (*it)->mImpl->percolateObjects();
- }
- }
- }
-
- ViewP removeChild(View* child)
- {
- ASSERT(child && "cannot remove null child");
-
- std::list<ViewP>::iterator it;
- for (it = mChildren.begin(); it != mChildren.end(); ++it)
- {
- if ((*it).get() == child)
- {
- ViewP found = *it;
- found->willRemoveFromView();
- mChildren.erase(it);
-
- found->mImpl->mParent = &gRootView;
-
- return found;
- }
- }
-
- return ViewP();
- }
-
- void clear()
- {
- mChildren.clear();
- }
-
-
- bool mIsRunning;
- View& mView;
-
- Settings* mSettings;
- Video* mVideo;
-
- View* mParent;
- std::list<ViewP> mChildren;
-
- Scalar mTimestep;
- Scalar mFramerate;
-
- int mFps;
- bool mShowFps;
-};
-
-
-View::View(Settings& settings, Video& video) :
- // pass through
- mImpl(new View::Impl(this, settings, video)) {}
-
-View::View() :
- mImpl(new View::Impl(this)) {}
-
-
-void View::update(Scalar t, Scalar dt)
-{
- // pass through
- mImpl->update(t, dt);
-}
-
-void View::draw(Scalar alpha) const
-{
- // pass through
- mImpl->draw(alpha);
-}
-
-bool View::handleEvent(const Event& event)
-{
- // pass through
- return mImpl->handleEvent(event);
-}
-
-
-void View::addChild(ViewP view)
-{
- // pass through
- mImpl->addChild(view);
-}
-
-ViewP View::removeChild(View* view)
-{
- // pass through
- return mImpl->removeChild(view);
-}
-
-ViewP View::removeChild(ViewP view)
-{
- // pass through
- return mImpl->removeChild(view.get());
-}
-
-void View::clear()
-{
- // pass through
- mImpl->clear();
-}
-
-
-View& View::parent() const
-{
- return *(mImpl->mParent);
-}
-
-const std::list<ViewP>& View::children() const
-{
- return mImpl->mChildren;
-}
-
-
-Settings& View::settings() const
-{
- ASSERT(mImpl->mSettings && "accessing null reference");
- // pass through
- return *(mImpl->mSettings);
-}
-
-Video& View::video() const
-{
- ASSERT(mImpl->mVideo && "accessing null reference");
- // pass through
- return *(mImpl->mVideo);
-}
-
-
-void View::run()
-{
- // pass through
- return mImpl->run();
-}
-
-void View::stop()
-{
- // pass through
- return mImpl->stop();
-}
-
-bool View::isRunning() const
-{
- // pass through
- return mImpl->mIsRunning;
-}
-
-
-} // namespace Mf
-
#include <map>
-#include <Moof/Aabb.hh>
-#include <Moof/Camera.hh>
-#include <Moof/Entity.hh>
-#include <Moof/Manager.hh>
-#include <Moof/Line.hh>
-#include <Moof/Log.hh>
-#include <Moof/Math.hh>
-//#include <Moof/Octree.hh>
-#include <Moof/Script.hh>
-#include <Moof/Settings.hh>
-#include <Moof/Texture.hh>
+#include <moof/aabb.hh>
+#include <moof/camera.hh>
+#include <moof/entity.hh>
+#include <moof/line.hh>
+#include <moof/log.hh>
+#include <moof/manager.hh>
+#include <moof/math.hh>
+#include <moof/script.hh>
+#include <moof/settings.hh>
+#include <moof/texture.hh>
#include "Character.hh"
#include "Scene.hh"
-struct Scene::Impl : public Mf::Manager<Impl>
+struct Scene::impl : public moof::manager<impl>
{
- struct Quad : public Mf::Entity
+ struct Quad : public moof::entity
{
enum Surface
{
TOP = 3
};
- Quad(const Mf::Vector3* vertices[4], const std::string& texture,
- Mf::Texture::TileIndex tileIndex) :
+ Quad(const moof::vector3* vertices[4],
+ const std::string& texture,
+ int tileIndex) :
mTilemap(texture),
mBlending(false),
mFog(false),
//}
}
- if (!mTilemap.getTileCoords(tileIndex, mTexCoords))
+ if (!mTilemap.tile_coordinates(tileIndex, mTexCoords))
{
- Mf::logWarning << "no index " << tileIndex <<
+ moof::log_warning << "no index " << tileIndex <<
" in texture " << texture << std::endl;
mTexCoords[0] = mTexCoords[1] =
mTexCoords[5] = mTexCoords[7] = 1.0;
}
- mAabb.encloseVertices(mVertices, 4);
- mSphere.point = mAabb.getCenter();
- mSphere.radius = (mAabb.min - mSphere.point).length();
+ aabb_.enclose_vertices(mVertices, 4);
+ sphere_.point = aabb_.center();
+ sphere_.radius = (aabb_.min - sphere_.point).length();
}
void setBlending(bool blending)
return mSurface;
}
- void draw(Mf::Scalar alpha = 0.0) const
+ void draw(moof::scalar alpha = 0.0) const
{
if (mBlending)
{
glDisable(GL_FOG);
}
- bool isVisible(const Mf::Frustum& frustum) const
+ bool is_visible(const moof::frustum& frustum) const
{
- return mSphere.isVisible(frustum);
+ return sphere_.is_visible(frustum);
}
- Mf::Vector3 mVertices[4];
- Mf::Scalar mTexCoords[8];
+ moof::vector3 mVertices[4];
+ moof::scalar mTexCoords[8];
- Mf::Texture mTilemap;
+ moof::texture mTilemap;
bool mBlending;
bool mFog;
- Mf::Matrix4 mTransform;
+ moof::matrix4 mTransform;
std::string mTexture;
- //Mf::Octree<Quad>::Ptr mOctree;
- std::list< boost::shared_ptr<Impl::Quad> > mObjects;
- std::list<Mf::Line2> mLines;
+ std::list< boost::shared_ptr<impl::Quad> > mObjects;
+ std::list<moof::line2> mLines;
- Mf::Aabb<3> mBounds;
+ moof::aabb<3> mBounds;
enum AXIS
void init(const std::string& name) {}
- void importSceneBindings(Mf::Settings& settings, Mf::Script& script)
+ void importSceneBindings(moof::settings& settings, moof::script& script)
{
- script.importFunction("SetBounds",
- boost::bind(&Impl::setBounds, this, _1));
- script.importFunction("ResetTransform",
- boost::bind(&Impl::resetTransform, this, _1));
- script.importFunction("Translate",
- boost::bind(&Impl::translate, this, _1));
- script.importFunction("Scale",
- boost::bind(&Impl::scale, this, _1));
- script.importFunction("Rotate",
- boost::bind(&Impl::rotate, this, _1));
- script.importFunction("SetTexture",
- boost::bind(&Impl::setTexture, this, _1));
- script.importFunction("DrawTilemap",
- boost::bind(&Impl::drawTilemap, this, _1));
- script.importFunction("DrawTile",
- boost::bind(&Impl::drawTile, this, _1));
+ script.import_function("SetBounds",
+ boost::bind(&impl::setBounds, this, _1));
+ script.import_function("ResetTransform",
+ boost::bind(&impl::resetTransform, this, _1));
+ script.import_function("Translate",
+ boost::bind(&impl::translate, this, _1));
+ script.import_function("Scale",
+ boost::bind(&impl::scale, this, _1));
+ script.import_function("Rotate",
+ boost::bind(&impl::rotate, this, _1));
+ script.import_function("SetTexture",
+ boost::bind(&impl::setTexture, this, _1));
+ script.import_function("DrawTilemap",
+ boost::bind(&impl::drawTilemap, this, _1));
+ script.import_function("DrawTile",
+ boost::bind(&impl::drawTile, this, _1));
int detail = 3;
settings.get("detail", detail);
- script.globals().setField("detail", detail);
+ script.globals().set_field("detail", detail);
- script.globals().setField("LOW", 1);
- script.globals().setField("MEDIUM", 2);
- script.globals().setField("HIGH", 3);
+ script.globals().set_field("LOW", 1);
+ script.globals().set_field("MEDIUM", 2);
+ script.globals().set_field("HIGH", 3);
- script.globals().setField("X", X);
- script.globals().setField("Y", Y);
- script.globals().setField("Z", Z);
+ script.globals().set_field("X", X);
+ script.globals().set_field("Y", Y);
+ script.globals().set_field("Z", Z);
- script.globals().setField("LEFT", Quad::LEFT);
- script.globals().setField("RIGHT", Quad::RIGHT);
- script.globals().setField("TOP", Quad::TOP);
+ script.globals().set_field("LEFT", Quad::LEFT);
+ script.globals().set_field("RIGHT", Quad::RIGHT);
+ script.globals().set_field("TOP", Quad::TOP);
}
- Mf::Script::Result load(Mf::Settings& settings, Mf::Script& script)
+ moof::script::status load(moof::settings& settings, moof::script& script)
{
- std::string path(getName());
- if (!Scene::getPath(path))
+ std::string path(name());
+ if (!Scene::find_path(path))
{
script.push("the scene file could not be found");
- return Mf::Script::FILE_ERROR;
+ return moof::script::file_error;
}
importSceneBindings(settings, script);
- return script.doFile(path);
+ return script.do_file(path);
}
- static int loadBox(Mf::Script& script, Mf::Aabb3& aabb)
+ static int loadBox(moof::script& script, moof::aabb3& aabb)
{
- script[1].requireTable();
- script[2].requireTable();
+ script[1].require_table();
+ script[2].require_table();
- script[1].pushField(1).get(aabb.min[0]);
- script[1].pushField(2).get(aabb.min[1]);
- script[1].pushField(3).get(aabb.min[2]);
- script[2].pushField(1).get(aabb.max[0]);
- script[2].pushField(2).get(aabb.max[1]);
- script[2].pushField(3).get(aabb.max[2]);
+ script[1].push_field(1).get(aabb.min[0]);
+ script[1].push_field(2).get(aabb.min[1]);
+ script[1].push_field(3).get(aabb.min[2]);
+ script[2].push_field(1).get(aabb.max[0]);
+ script[2].push_field(2).get(aabb.max[1]);
+ script[2].push_field(3).get(aabb.max[2]);
return 0;
}
- int setBounds(Mf::Script& script)
+ int setBounds(moof::script& script)
{
int ret = loadBox(script, mBounds);
- //mOctree = Mf::Octree<Quad>::alloc(mBounds);
return ret;
}
- int resetTransform(Mf::Script& script)
+ int resetTransform(moof::script& script)
{
mTransform.identity();
return 0;
}
- int translate(Mf::Script& script)
+ int translate(moof::script& script)
{
- Mf::Vector3 vec;
- script[1].requireNumber().get(vec[0]);
- script[2].requireNumber().get(vec[1]);
- script[3].requireNumber().get(vec[2]);
+ moof::vector3 vec;
+ script[1].require_number().get(vec[0]);
+ script[2].require_number().get(vec[1]);
+ script[3].require_number().get(vec[2]);
- Mf::Matrix4 translation;
- cml::matrix_translation(translation, vec);
+ moof::matrix4 translation;
+ moof::matrix_translation(translation, vec);
mTransform = translation * mTransform;
return 0;
}
- int scale(Mf::Script& script)
+ int scale(moof::script& script)
{
- int size = script.stackSize();
+ int size = script.stack_size();
if (size == 1)
{
- Mf::Scalar value = 1.0;
- script[1].requireNumber().get(value);
+ moof::scalar value = 1.0;
+ script[1].require_number().get(value);
- Mf::Matrix4 scaling;
- cml::matrix_uniform_scale(scaling, value);
+ moof::matrix4 scaling;
+ moof::matrix_uniform_scale(scaling, value);
mTransform = scaling * mTransform;
}
else if (size == 3)
{
- Mf::Vector3 vec;
- script[1].requireNumber().get(vec[0]);
- script[2].requireNumber().get(vec[1]);
- script[3].requireNumber().get(vec[2]);
+ moof::vector3 vec;
+ script[1].require_number().get(vec[0]);
+ script[2].require_number().get(vec[1]);
+ script[3].require_number().get(vec[2]);
- Mf::Matrix4 scaling;
- cml::matrix_scale(scaling, vec);
+ moof::matrix4 scaling;
+ moof::matrix_scale(scaling, vec);
mTransform = scaling * mTransform;
}
else
return 0;
}
- int rotate(Mf::Script& script)
+ int rotate(moof::script& script)
{
size_t index = 0;
- script[1].requireNumber().get(index);
+ script[1].require_number().get(index);
- Mf::Scalar value;
- script[2].requireNumber().get(value);
+ moof::scalar value;
+ script[2].require_number().get(value);
- cml::matrix_rotate_about_world_axis(mTransform,
- index, cml::rad(value));
+ moof::matrix_rotate_about_world_axis(mTransform, index,
+ moof::rad(value));
return 0;
}
- int setTexture(Mf::Script& script)
+ int setTexture(moof::script& script)
{
- script[1].requireString().get(mTexture);
+ script[1].require_string().get(mTexture);
return 0;
}
- int drawTilemap(Mf::Script& script)
+ int drawTilemap(moof::script& script)
{
- Mf::Script::Slot table = script[1].requireTable();
+ moof::script::slot table = script[1].require_table();
int width = 1;
table.get(width, "width");
if (width == 0) table.raise("width field must not be zero");
int height = nTiles / width;
- Mf::Vector3 vertices[height+1][width+1];
+ moof::vector3 vertices[height+1][width+1];
// the indices are stored upside-down in the scene file so that
// they are easier to edit as text, so we'll need to load them last
for (int w = 0; w <= width; ++w)
{
- vertices[height][w] = Mf::demote(mTransform *
- Mf::Vector4(w, height, 0.0, 1.0));
+ vertices[height][w] = moof::demote(mTransform *
+ moof::vector4(w, height, 0.0, 1.0));
}
for (int h = 0; h < height; ++h)
{
- vertices[h][0] = Mf::demote(mTransform *
- Mf::Vector4(0.0, h, 0.0, 1.0));
+ vertices[h][0] = moof::demote(mTransform *
+ moof::vector4(0.0, h, 0.0, 1.0));
}
size_t i = 1;
int wPlus1 = w + 1;
int hPlus1 = h + 1;
- Mf::Texture::TileIndex index;
+ int index;
table.get(index, i);
- vertices[h][wPlus1] = Mf::demote(mTransform *
- Mf::Vector4(wPlus1, h, 0.0, 1.0));
+ vertices[h][wPlus1] = moof::demote(mTransform *
+ moof::vector4(wPlus1, h, 0.0, 1.0));
- if (index == Mf::Texture::NO_TILE) continue;
+ if (index == moof::texture::no_tile) continue;
- const Mf::Vector3* corners[4] = {
+ const moof::vector3* corners[4] = {
&vertices[h][w],
&vertices[h][wPlus1],
&vertices[hPlus1][wPlus1],
// scene is built, simply demoting the vector again should
// project the points to the xy-plane
- Mf::Vector2 bl = Mf::demote(vertices[0][0]);
- Mf::Vector2 tr = Mf::demote(vertices[height][width]);
+ moof::vector2 bl = moof::demote(vertices[0][0]);
+ moof::vector2 tr = moof::demote(vertices[height][width]);
- mLines.push_back(Mf::Line<2>(bl, tr));
+ mLines.push_back(moof::line<2>(bl, tr));
}
return 0;
}
- int drawTile(Mf::Script& script)
+ int drawTile(moof::script& script)
{
- Mf::Script::Slot param = script[1];
- Mf::Script::Slot top = script[-1];
+ moof::script::slot param = script[1];
+ moof::script::slot top = script[-1];
- Mf::Texture::TileIndex index = 0;
- int width = 1;
- bool blending = false;
- bool fog = false;
+ int index = 0;
+ int width = 1;
+ bool blending = false;
+ bool fog = false;
- if (param.isTable())
+ if (param.is_table())
{
param.get(index, 1);
param.get(width, "u_scale");
param.get(blending, "blend");
param.get(fog, "fog");
}
- else if (param.isNumber())
+ else if (param.is_number())
{
param.get(index);
}
- Mf::Vector3 vertices[2][width+1];
+ moof::vector3 vertices[2][width+1];
- Mf::Scalar xf;
- Mf::Scalar increment = SCALAR(1.0) / Mf::Scalar(width);
+ moof::scalar xf;
+ moof::scalar increment = SCALAR(1.0) / moof::scalar(width);
for (int h = 0; h <= 1; ++h)
{
xf = 0.0;
for (int w = 0; w <= width; ++w, xf += increment)
{
- vertices[h][w] = Mf::demote(mTransform *
- Mf::Vector4(xf, Mf::Scalar(h), 0.0, 1.0));
+ vertices[h][w] = moof::demote(mTransform *
+ moof::vector4(xf, moof::scalar(h), 0.0, 1.0));
}
}
{
int wPlus1 = w + 1;
- const Mf::Vector3* corners[4] = {
+ const moof::vector3* corners[4] = {
&vertices[0][w],
&vertices[0][wPlus1],
&vertices[1][wPlus1],
Scene::Scene(const std::string& name) :
// pass through
- mImpl(Scene::Impl::getInstance(name)) {}
+ impl_(Scene::impl::instance(name)) {}
-Mf::Script::Result Scene::load(Mf::Settings& settings, Mf::Script& script)
+moof::script::status Scene::load(moof::settings& settings, moof::script& script)
{
// pass through
- return mImpl->load(settings, script);
+ return impl_->load(settings, script);
}
-void Scene::draw(Mf::Scalar alpha) const
+void Scene::draw(moof::scalar alpha) const
{
- std::list< boost::shared_ptr<Impl::Quad> >& objects = mImpl->mObjects;
- std::list< boost::shared_ptr<Impl::Quad> >::const_iterator it;
+ std::list< boost::shared_ptr<impl::Quad> >& objects = impl_->mObjects;
+ std::list< boost::shared_ptr<impl::Quad> >::const_iterator it;
for (it = objects.begin(); it != objects.end(); ++it)
{
(*it)->draw(alpha);
}
- mImpl->mBounds.draw();
+ impl_->mBounds.draw();
}
-void Scene::drawIfVisible(Mf::Scalar alpha,
- const Mf::Frustum& frustum) const
+void Scene::draw_if_visible(moof::scalar alpha,
+ const moof::frustum& frustum) const
{
- std::list< boost::shared_ptr<Impl::Quad> >& objects = mImpl->mObjects;
- std::list< boost::shared_ptr<Impl::Quad> >::const_iterator it;
+ std::list< boost::shared_ptr<impl::Quad> >& objects = impl_->mObjects;
+ std::list< boost::shared_ptr<impl::Quad> >::const_iterator it;
for (it = objects.begin(); it != objects.end(); ++it)
{
- (*it)->drawIfVisible(alpha, frustum);
+ (*it)->draw_if_visible(alpha, frustum);
}
- std::list< Mf::Line<2> >& lines = mImpl->mLines;
- std::list< Mf::Line<2> >::const_iterator lit;
+ std::list< moof::line<2> >& lines = impl_->mLines;
+ std::list< moof::line<2> >::const_iterator lit;
for (lit = lines.begin(); lit != lines.end(); ++lit)
{
(*lit).draw(alpha);
}
- mImpl->mBounds.draw();
+ impl_->mBounds.draw();
}
-bool Scene::castRay(const Mf::Ray<2>& ray,
- std::list<Mf::Ray<2>::Contact>& hits) const
+bool Scene::castRay(const moof::ray<2>& ray,
+ std::list<moof::ray<2>::contact>& hits) const
{
- std::list< Mf::Line<2> >& lines = mImpl->mLines;
- std::list< Mf::Line<2> >::const_iterator it;
+ std::list< moof::line<2> >& lines = impl_->mLines;
+ std::list< moof::line<2> >::const_iterator it;
for (it = lines.begin(); it != lines.end(); ++it)
{
- Mf::Ray<2>::Contact hit;
- Mf::Scalar d = (*it).intersectRay(ray, hit);
+ moof::ray<2>::contact hit;
+ moof::scalar d = (*it).intersect_ray(ray, hit);
if (d > 0.0)
{
hits.push_back(hit);
bool Scene::checkForCollision(Character& character)
{
return false;
- //std::list< boost::shared_ptr<Impl::Quad> > objects;
- //std::list<Mf::Octree<Impl::Quad>::InsertableP> objects;
- //mImpl->mOctree->getNearbyObjects(objects, character);
- std::list< boost::shared_ptr<Impl::Quad> >& objects = mImpl->mObjects;
- std::list< boost::shared_ptr<Impl::Quad> >::const_iterator it;
+ std::list< boost::shared_ptr<impl::Quad> >& objects = impl_->mObjects;
+ std::list< boost::shared_ptr<impl::Quad> >::const_iterator it;
int collisions = 0;
- Mf::Sphere<3> sphere = character.getSphere();
+ moof::sphere<3> sphere = character.sphere();
for (it = objects.begin(); it != objects.end(); ++it)
{
- Impl::Quad::Surface type = (*it)->getSurface();
- if (type == Impl::Quad::NONE) continue;
+ impl::Quad::Surface type = (*it)->getSurface();
+ if (type == impl::Quad::NONE) continue;
- if (Mf::checkCollision(sphere, (*it)->getSphere()))
+ if (moof::checkCollision(sphere, (*it)->sphere()))
{
++collisions;
- Mf::Vector2 impulse(0.0, 0.0);
- Mf::Vector2 p = character.getState().momentum;
+ moof::vector2 impulse(0.0, 0.0);
+ moof::vector2 p = character.state().momentum;
- Mf::State2 state = character.getState(1.0);
- sphere = character.getSphere();
- Mf::Scalar alpha = 1.0;
- while (Mf::checkCollision(sphere, (*it)->getSphere()))
+ moof::state2 state = character.state(1.0);
+ sphere = character.sphere();
+ moof::scalar alpha = 1.0;
+ while (moof::checkCollision(sphere, (*it)->sphere()))
{
alpha -= 0.05;
- state = character.getState(alpha);
+ state = character.state(alpha);
}
character.setPosition(state.position);
//switch (type)
//{
- //case Impl::Quad::TOP:
+ //case impl::Quad::TOP:
//if (p[1] < 0.0) impulse[1] = -p[1];
//break;
- //case Impl::Quad::LEFT:
+ //case impl::Quad::LEFT:
//if (p[0] > 0.0) impulse[0] = 1.5*-p[0];
//break;
- //case Impl::Quad::RIGHT:
+ //case impl::Quad::RIGHT:
//if (p[0] < 0.0) impulse[0] = 1.5*-p[0];
//break;
//}
if (collisions > 0)
{
- Mf::logInfo << "collisions: " << collisions << std::endl;
+ moof::log_info << "collisions: " << collisions << std::endl;
}
return false;
}
-bool Scene::getPath(std::string& name)
+bool Scene::find_path(std::string& name)
{
- return Mf::Resource::getPath(name, "scenes/", "lua");
+ return moof::resource::find_path(name, "scenes/", "lua");
}
#include <boost/shared_ptr.hpp>
-#include <Moof/Cullable.hh>
-#include <Moof/Drawable.hh>
-#include <Moof/Resource.hh>
-#include <Moof/Script.hh>
+#include <moof/cullable.hh>
+#include <moof/drawable.hh>
+#include <moof/resource.hh>
+#include <moof/script.hh>
class Character;
-namespace Mf {
-class Settings;
+namespace moof {
+class settings;
}
class Scene;
typedef boost::shared_ptr<Scene> SceneP;
-class Scene : public Mf::Cullable, public Mf::Drawable, public Mf::Resource
+class Scene : public moof::cullable, public moof::drawable, public moof::resource
{
- class Impl;
- boost::shared_ptr<Impl> mImpl;
+ class impl;
+ boost::shared_ptr<impl> impl_;
public:
return SceneP(new Scene(name));
}
- Mf::Script::Result load(Mf::Settings& settings, Mf::Script& script);
+ moof::script::status load(moof::settings& settings, moof::script& script);
- void draw(Mf::Scalar alpha) const;
- void drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const;
+ void draw(moof::scalar alpha) const;
+ void draw_if_visible(moof::scalar alpha, const moof::frustum& frustum) const;
- Mf::Scalar getZCoord(const Mf::Vector2& position) const;
+ moof::scalar getZCoord(const moof::vector2& position) const;
- bool castRay(const Mf::Ray<2>& ray,
- std::list<Mf::Ray<2>::Contact>& hits) const;
+ bool castRay(const moof::ray<2>& ray,
+ std::list<moof::ray<2>::contact>& hits) const;
bool checkForCollision(Character& character);
- static bool getPath(std::string& name);
+ static bool find_path(std::string& name);
};
TilemapFont::TilemapFont() :
- Mf::Texture("Font") {}
+ moof::texture("Font") {}
-void TilemapFont::getTileCoords(char symbol, Mf::Scalar coords[8],
- Mf::Texture::Orientation what)
+void TilemapFont::tile_coordinates(char symbol, moof::scalar coords[8],
+ moof::texture::orientation what)
{
- Mf::Texture::TileIndex index = 0;
+ int index = 0;
if (symbol >= ' ' && symbol <= '_')
{
index = 0;
}
- Mf::Texture::getTileCoords(index, coords, what);
+ moof::texture::tile_coordinates(index, coords, what);
}
* Text on the screen.
*/
-#include <Moof/Texture.hh>
+#include <moof/texture.hh>
-class TilemapFont : public Mf::Texture
+class TilemapFont : public moof::texture
{
public:
TilemapFont();
- void getTileCoords(char symbol, Mf::Scalar coords[8],
- Mf::Texture::Orientation what = Mf::Texture::NORMAL);
+ void tile_coordinates(char symbol, moof::scalar coords[8],
+ moof::texture::orientation what = moof::texture::normal);
};
*
**************************************************************************/
-#include <Moof/OpenGL.hh>
+#include <moof/opengl.hh>
#include "GameLayer.hh"
#include "TitleLayer.hh"
-void TitleLayer::didAddToView()
+void TitleLayer::did_add_to_view()
{
- mFadeIn.init(0.0, 1.0);
- mFadeIn.reset(0.1);
+ mFadeIn.init(0.0, 1.0, 0.1);
//mGameLayer = GameLayer::alloc();
}
-void TitleLayer::update(Mf::Scalar t, Mf::Scalar dt)
+void TitleLayer::update(moof::scalar t, moof::scalar dt)
{
mFadeIn.update(t, dt);
- Mf::View::update(t, dt);
+ moof::view::update(t, dt);
}
-void TitleLayer::draw(Mf::Scalar alpha) const
+void TitleLayer::draw(moof::scalar alpha) const
{
- glClearColor(0.0, 0.0, mFadeIn.getState(alpha), 1.0);
+ glClearColor(0.0, 0.0, mFadeIn.state(alpha), 1.0);
glClear(GL_COLOR_BUFFER_BIT);
- Mf::View::draw(alpha);
+ moof::view::draw(alpha);
}
-bool TitleLayer::handleEvent(const Mf::Event& event)
+bool TitleLayer::handle_event(const moof::event& event)
{
- if (Mf::View::handleEvent(event)) return true;
+ if (moof::view::handle_event(event)) return true;
switch (event.type)
{
}
mGameLayer = GameLayer::alloc();
- parent().addChild(mGameLayer);
+ parent().add_child(mGameLayer);
- parent().removeChild(this);
+ parent().remove_child(this);
- //Mf::Lerp interp(0.1);
+ //moof::lerp_scalar interp(0.1);
//interp.init(0.0, 1.0);
- //Mf::Transition<Mf::Lerp>::Ptr transition =
- //Mf::Transition<Mf::Lerp>::alloc(mGameLayer, titleLayer,
+ //moof::Transition<moof::lerp_scalar>::Ptr transition =
+ //moof::Transition<moof::lerp_scalar>::alloc(mGameLayer, titleLayer,
//interp);
return true;
#include <boost/shared_ptr.hpp>
-#include <Moof/Interpolator.hh>
-#include <Moof/Math.hh>
-#include <Moof/View.hh>
+#include <moof/interpolator.hh>
+#include <moof/math.hh>
+#include <moof/view.hh>
class TitleLayer;
typedef boost::shared_ptr<TitleLayer> TitleLayerP;
-class TitleLayer : public Mf::View
+class TitleLayer : public moof::view
{
public:
return TitleLayerP(new TitleLayer);
}
- void didAddToView();
+ void did_add_to_view();
- void update(Mf::Scalar t, Mf::Scalar dt);
- void draw(Mf::Scalar alpha) const;
- bool handleEvent(const Mf::Event& event);
+ void update(moof::scalar t, moof::scalar dt);
+ void draw(moof::scalar alpha) const;
+ bool handle_event(const moof::event& event);
private:
- Mf::Lerp mFadeIn;
- Mf::ViewP mGameLayer;
+ moof::lerp_scalar mFadeIn;
+ moof::view_ptr mGameLayer;
};
#include <string>
-#include <Moof/Math.hh>
+#include <moof/math.hh>
class Typesetter
Typesetter();
- void setLineSpacing(Mf::Scalar spacing);
+ void setLineSpacing(moof::scalar spacing);
void print(const std::string& format, ...);
private:
- Mf::Scalar mLeftBound;
- Mf::Scalar mTopBound;
- Mf::Scalar mLineSpacing;
+ moof::scalar mLeftBound;
+ moof::scalar mTopBound;
+ moof::scalar mLineSpacing;
};
*
**************************************************************************/
-#include "Aabb.hh"
-#include "Script.hh"
+#include "aabb.hh"
+#include "script.hh"
-namespace Mf {
+namespace moof {
-void importAabbClass(Script& script)
+void import_aabb_class(script& script)
{
}
-} // namepsace Mf
+} // namepsace moof
#ifndef _MOOF_AABB_HH_
#define _MOOF_AABB_HH_
-#include <Moof/Cullable.hh>
-#include <Moof/Drawable.hh>
-#include <Moof/Math.hh>
-#include <Moof/Plane.hh>
-#include <Moof/Shape.hh>
+/**
+ * \file aabb.hh
+ * Axis-aligned Bounding Box
+ */
-#include <Moof/Frustum.hh> // FIXME this file is quite broken
-#include <Moof/OpenGL.hh>
-#include <Moof/Texture.hh>
+#include <moof/cullable.hh>
+#include <moof/drawable.hh>
+#include <moof/math.hh>
+#include <moof/plane.hh>
+#include <moof/shape.hh>
+#include <moof/frustum.hh> // FIXME: this file is quite broken
+#include <moof/opengl.hh>
+#include <moof/texture.hh>
-namespace Mf {
+namespace moof {
-class Script;
+class script;
-/**
- * Axis-aligned Bounding Box
- */
template <int D = 3>
-struct Aabb : public Cullable, public Drawable, public Shape<D>
+struct aabb : public cullable, public drawable, public shape<D>
{
- typedef cml::vector< Scalar, cml::fixed<D> > Vector;
+ typedef moof::vector< scalar, fixed<D> > vector;
- Vector min;
- Vector max;
+ vector min;
+ vector max;
- Aabb() {}
+ aabb() {}
- Aabb(const Vector& a, const Vector& b)
+ aabb(const vector& a, const vector& b)
{
init(a, b);
}
- Aabb(Scalar x1, Scalar y1, Scalar x2, Scalar y2)
+ aabb(scalar x1, scalar y1, scalar x2, scalar y2)
{
- Vector a(x1, y1);
- Vector b(x2, y2);
+ vector a(x1, y1);
+ vector b(x2, y2);
init(a, b);
}
- Aabb(Scalar x1, Scalar y1, Scalar z1, Scalar x2, Scalar y2, Scalar z2)
+ aabb(scalar x1, scalar y1, scalar z1, scalar x2, scalar y2, scalar z2)
{
- Vector a(x1, y1, z1);
- Vector b(x2, y2, z2);
+ vector a(x1, y1, z1);
+ vector b(x2, y2, z2);
init(a, b);
}
- void init(const Vector2& a, const Vector2& b)
+ void init(const vector2& a, const vector2& b)
{
if (a[0] < b[0])
{
}
}
- void init(const Vector3& a, const Vector3& b)
+ void init(const vector3& a, const vector3& b)
{
if (a[0] < b[0])
{
}
- Vector getCenter() const
+ vector center() const
{
return (min + max) / 2.0;
}
- Plane getPlaneXY() const
+ plane xy_plane() const
{
- Plane plane;
- plane.normal = Vector3(0.0, 0.0, 1.0);
- plane.d = cml::dot(-plane.normal, getCenter());
+ plane plane;
+ plane.normal = vector3(0.0, 0.0, 1.0);
+ plane.d = dot(-plane.normal, center());
return plane;
}
- Plane getPlaneXZ() const
+ plane xz_plane() const
{
- Plane plane;
- plane.normal = Vector3(0.0, 1.0, 0.0);
- plane.d = cml::dot(-plane.normal, getCenter());
+ plane plane;
+ plane.normal = vector3(0.0, 1.0, 0.0);
+ plane.d = dot(-plane.normal, center());
return plane;
}
- Plane getPlaneYZ() const
+ plane yz_plane() const
{
- Plane plane;
- plane.normal = Vector3(1.0, 0.0, 0.0);
- plane.d = cml::dot(-plane.normal, getCenter());
+ plane plane;
+ plane.normal = vector3(1.0, 0.0, 0.0);
+ plane.d = dot(-plane.normal, center());
return plane;
}
- void getCorners(Vector2 corners[4]) const
+ void get_corners(vector2 corners[4]) const
{
corners[0][0] = min[0]; corners[0][1] = min[1];
corners[1][0] = max[0]; corners[1][1] = min[1];
corners[3][0] = min[0]; corners[3][1] = max[1];
}
- void getCorners(Vector3 corners[8]) const
+ void get_corners(vector3 corners[8]) const
{
corners[0][0] = min[0];
corners[0][1] = min[1];
}
- void encloseVertices(const Vector vertices[], unsigned count)
+ void enclose_vertices(const vector vertices[], unsigned count)
{
min.zero();
max.zero();
}
- void draw(Scalar alpha = 0.0) const
+ void draw(scalar alpha = 0.0) const
{
glRect(min[0], min[1], max[0], max[1]);
}
- bool isVisible(const Frustum& frustum) const
+ bool is_visible(const frustum& frustum) const
{
return true;
}
};
-void importAabbClass(Script& script);
+void import_aabb_class(script& script);
template <>
-inline void Aabb<3>::draw(Scalar alpha) const
+inline void aabb<3>::draw(scalar alpha) const
{
- Scalar vertices[] = {min[0], min[1], min[2],
+ scalar vertices[] = {min[0], min[1], min[2],
min[0], max[1], min[2],
max[0], max[1], min[2],
max[0], min[1], min[2],
glVertexPointer(3, GL_SCALAR, 0, vertices);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- Texture::resetBind();
+ texture::reset_binding();
glDrawElements(GL_QUADS, sizeof(indices), GL_UNSIGNED_BYTE,
indices);
}
template <>
-inline bool Aabb<3>::isVisible(const Frustum& frustum) const
+inline bool aabb<3>::is_visible(const frustum& frustum) const
{
return frustum.contains(*this);
}
-typedef Aabb<2> Aabb2;
-typedef Aabb2 Rectangle;
-typedef Aabb<3> Aabb3;
+typedef aabb<2> aabb2;
+typedef aabb2 rectangle;
+typedef aabb<3> aabb3;
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_AABB_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <stdexcept>
+
+#include <SDL/SDL.h>
+#include "fastevents.h"
+
+#include "backend.hh"
+#include "log.hh"
+
+
+namespace moof {
+
+
+struct impl
+{
+ static bool is_initialized;
+ static int retain_count;
+};
+
+bool impl::is_initialized = false;
+int impl::retain_count = 0;
+
+
+backend::backend()
+{
+ if (impl::retain_count++ == 0)
+ {
+#if defined(_WIN32)
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
+#else
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) != 0)
+#endif
+ {
+ throw std::runtime_error(SDL_GetError());
+ }
+ else
+ {
+ char name[128];
+ SDL_VideoDriverName(name, sizeof(name));
+ log_info << "initialized SDL; using video driver `"
+ << name << "'" << std::endl;
+ }
+
+ if (FE_Init() != 0)
+ {
+ throw std::runtime_error(FE_GetError());
+ }
+ }
+
+ impl::is_initialized = true;
+}
+
+backend::backend(const backend& backend)
+{
+ ++impl::retain_count;
+}
+
+backend& backend::operator=(const backend& backend)
+{
+ ++impl::retain_count;
+ return *this;
+}
+
+backend::~backend()
+{
+ if (--impl::retain_count == 0)
+ {
+ FE_Quit();
+ SDL_Quit();
+
+ impl::is_initialized = false;
+ }
+}
+
+bool backend::is_initialized()
+{
+ return impl::is_initialized;
+}
+
+
+} // namespace moof
+
#ifndef _MOOF_BACKEND_HH_
#define _MOOF_BACKEND_HH_
-
-namespace Mf {
+/**
+ * \file backend.hh
+ * Initialize the backend libraries and subsystems.
+ */
-class Error;
+namespace moof {
-/*
+/**
* Some classes and subsystems require certain backend libraries to be
* initialized. This is the mechanism to accomplish that. Classes which
* rely on any backend libraries just need to instantiate this class as a
* member. Backend cleanup will occur automagically when there are no more
* instances.
*/
-
-class Backend
+class backend
{
public:
- Backend();
- Backend(const Backend& backend);
- ~Backend();
+ /**
+ * Construct a backend reference, initializing the backend if it hasn't
+ * already been initialized.
+ */
+ backend();
+
+ /**
+ * Get whether or not the backend has been initialized.
+ * \return True if the backend is initialized, false otherwise.
+ */
+ static bool is_initialized();
+
+
+ // The rest of this stuff is to implement the reference counting.
- static bool isInitialized();
- static const Error& getError();
+ backend(const backend& backend);
+ backend& operator=(const backend& backend);
+ ~backend();
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_BACKEND_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include "camera.hh"
+#include "opengl.hh"
+
+
+namespace moof {
+
+
+void camera::position(const vector3& position)
+{
+ state_.position = position;
+}
+
+void camera::rotation(const quaternion& rotation)
+{
+ state_.orientation = rotation;
+}
+
+void camera::look_at(const vector3& point)
+{
+ // FIXME: this doesn't work as expected
+ quaternion_rotation_aim_at(state_.orientation,
+ state_.position, point,
+ vector3(0.0, 1.0, 0.0));
+}
+
+
+void camera::projection(const matrix4& projection)
+{
+ projection_ = projection;
+}
+
+void camera::projection(scalar fovy, scalar aspect, scalar abutting,
+ scalar distant)
+{
+ matrix_perspective_yfov_RH(projection_, fovy, aspect, abutting,
+ distant, z_clip_neg_one);
+}
+
+
+void camera::upload_to_gl(scalar alpha) const
+{
+ calculate(alpha);
+
+ glMatrixMode(GL_PROJECTION);
+ glMultMatrix(projection_.data());
+
+ glMatrixMode(GL_MODELVIEW);
+ glMultMatrix(modelview_.data());
+}
+
+void camera::calculate(scalar alpha) const
+{
+ state3 state = rigid_body3::state(alpha);
+
+ matrix_rotation_quaternion(modelview_, state.orientation);
+
+ matrix4 translate;
+ matrix_translation(translate, state.position);
+
+ modelview_ *= translate;
+
+ frustum_.init(modelview_, projection_);
+}
+
+
+void camera::update(scalar t, scalar dt)
+{
+ rigid_body3::update(t, dt);
+}
+
+void camera::draw(scalar alpha) const
+{
+ sphere_.draw(alpha);
+}
+
+
+void camera::handle_event(const event& event)
+{
+ const scalar ds = 50.0;
+
+ switch (event.type)
+ {
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_RIGHT)
+ {
+ state_.position[0] -= ds;
+ }
+ else if (event.key.keysym.sym == SDLK_LEFT)
+ {
+ state_.position[0] += ds;
+ }
+ else if (event.key.keysym.sym == SDLK_UP)
+ {
+ state_.position[1] -= ds;
+ }
+ else if (event.key.keysym.sym == SDLK_DOWN)
+ {
+ state_.position[1] += ds;
+ }
+ else if (event.key.keysym.sym == SDLK_PAGEUP)
+ {
+ state_.position[2] += ds;
+ }
+ else if (event.key.keysym.sym == SDLK_PAGEDOWN)
+ {
+ state_.position[2] -= ds;
+ }
+ break;
+
+ case SDL_MOUSEMOTION:
+ {
+ scalar xrel = rad(scalar(event.motion.xrel) / 6.0);
+ scalar yrel = rad(scalar(event.motion.yrel) / 6.0);
+
+ quaternion rotation = state_.orientation;
+
+ quaternion_rotate_about_world_x(rotation, yrel);
+ //mRotation.normalize();
+ quaternion_rotate_about_world_y(rotation, xrel);
+
+ rotation.normalize();
+ state_.orientation = rotation;
+ }
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ if (event.button.button == SDL_BUTTON_WHEELUP)
+ {
+ state_.position[2] -= ds;
+ }
+ else if (event.button.button == SDL_BUTTON_WHEELDOWN)
+ {
+ state_.position[2] -= ds;
+ }
+ break;
+ }
+}
+
+
+} // namespace moof
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_CAMERA_HH_
+#define _MOOF_CAMERA_HH_
+
+/**
+ * \file camera.hh
+ * Classes related to managing the modelview and perspective matrices.
+ */
+
+#include <moof/event.hh>
+#include <moof/frustum.hh>
+#include <moof/math.hh>
+#include <moof/rigid_body.hh>
+
+
+namespace moof {
+
+
+class camera : public rigid_body3
+{
+public:
+
+ camera()
+ {
+ state_.init();
+ prev_state_.init();
+
+ quaternion_rotation_world_y(state_.orientation, SCALAR(0.0));
+ }
+
+ void position(const vector3& position);
+ void rotation(const quaternion& rotation);
+
+ void look_at(const vector3& point);
+
+ void projection(const matrix4& projection);
+ void projection(scalar fovy, scalar aspect, scalar near, scalar far);
+
+ const matrix4& modelview() const
+ {
+ return modelview_;
+ }
+
+ const matrix4& projection() const
+ {
+ return projection_;
+ }
+
+ const class frustum& frustum() const
+ {
+ return frustum_;
+ }
+
+
+ void upload_to_gl(scalar alpha = 0) const;
+
+ void update(scalar t, scalar dt);
+ void draw(scalar alpha = 0) const;
+ void handle_event(const event& event);
+
+
+private:
+
+ void calculate(scalar alpha) const;
+
+ mutable matrix4 modelview_;
+ matrix4 projection_;
+
+ mutable class frustum frustum_;
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_CAMERA_HH_
+
#ifndef _MOOF_CONTACT_HH_
#define _MOOF_CONTACT_HH_
-#include <Moof/Math.hh>
+/**
+ * \file contact.hh
+ * Represents a collision between entities.
+ */
+#include <moof/math.hh>
-namespace Mf {
+
+namespace moof {
template <int D = 3>
-struct Contact
+struct contact
{
- typedef cml::vector< Scalar, cml::fixed<D> > Vector;
+ typedef moof::vector< scalar, fixed<D> > vector;
- Vector point; // point of contact
- Scalar distance; // distance of penetration
- Vector normal; // normal of surface at point of contact
+ vector point; // point of contact
+ scalar distance; // distance of penetration
+ vector normal; // normal of surface at point of contact
- bool operator < (const Contact& rhs)
+ bool operator < (const contact& rhs)
{
return distance < rhs.distance;
}
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_CONTACT_HH_
#ifndef _MOOF_CULLABLE_HH_
#define _MOOF_CULLABLE_HH_
+/**
+ * \file cullable.hh
+ * Representation for an object that may or may not be visible.
+ */
+
-namespace Mf {
+namespace moof {
-class Frustum;
+class frustum;
/**
* Interface for anything that can be culled.
*/
-class Cullable
+class cullable
{
public:
- virtual ~Cullable() {}
+ virtual ~cullable() {}
- virtual bool isVisible(const Frustum& frustum) const
+ virtual bool is_visible(const frustum& frustum) const
{
// unless determined otherwise, assume visible
return true;
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_CULLABLE_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <map>
+
+#include "dispatcher.hh"
+
+
+namespace moof {
+
+
+class dispatcher::impl
+{
+public:
+
+ impl(dispatcher* dispatcher) :
+ dispatcher_(dispatcher),
+ id_(0) {}
+
+ dispatcher::handle getNewHandle()
+ {
+ ++id_;
+ dispatcher::handle handle(dispatcher_->impl_, id_);
+ return handle;
+ }
+
+ typedef std::pair<unsigned,dispatcher::function> callback;
+ typedef std::multimap<std::string,callback> callback_lookup;
+ typedef callback_lookup::iterator callback_it;
+
+ typedef std::multimap<unsigned,std::string> handle_lookup;
+ typedef handle_lookup::iterator handle_it;
+
+
+ handle add_target(const std::string& event,
+ const function& callback,
+ handle handle)
+ {
+ callbacks_.insert(std::make_pair(event, std::make_pair(handle.id(),
+ callback)));
+ handles_.insert(std::make_pair(handle.id(), event));
+
+ return handle;
+ }
+
+ void remove_target(unsigned id)
+ {
+ std::pair<handle_it,handle_it> matching(handles_.equal_range(id));
+
+ for (handle_it it = matching.first; it != matching.second; ++it)
+ {
+ callback_it first = callbacks_.find((*it).second);
+ callback_it last = callbacks_.end();
+
+ for (callback_it jt = first; jt != last; ++jt)
+ {
+ if ((*jt).second.first == id)
+ {
+ callbacks_.erase(jt);
+ break;
+ }
+ }
+ }
+
+ handles_.erase(id);
+ }
+
+ void dispatch(const std::string& event)
+ {
+ std::pair<callback_it,callback_it>
+ callbacks(callbacks_.equal_range(event));
+
+ for (callback_it it = callbacks.first; it != callbacks.second; ++it)
+ {
+ function callback = (*it).second.second;
+ callback();
+ }
+ }
+
+
+ dispatcher* dispatcher_;
+
+ unsigned id_;
+
+ callback_lookup callbacks_;
+ handle_lookup handles_;
+};
+
+
+void dispatcher::handle::clear()
+{
+ boost::shared_ptr<impl> dispatcher;
+ if (id_ && (dispatcher = dispatcher_.lock()))
+ {
+ dispatcher->remove_target(id_);
+ id_ = 0;
+ }
+}
+
+
+dispatcher::dispatcher() :
+ impl_(new dispatcher::impl(this)) {}
+
+
+dispatcher::handle dispatcher::add_target(const std::string& event,
+ const function& callback)
+{
+ return add_target(event, callback, impl_->getNewHandle());
+}
+
+dispatcher::handle dispatcher::add_target(const std::string& event,
+ const function& callback,
+ handle handle)
+{
+ // pass through
+ return impl_->add_target(event, callback, handle);
+}
+
+
+void dispatcher::remove_target(unsigned id)
+{
+ // pass through
+ return impl_->remove_target(id);
+}
+
+
+void dispatcher::dispatch(const std::string& event)
+{
+ // pass through
+ impl_->dispatch(event);
+}
+
+
+dispatcher& dispatcher::global()
+{
+ static dispatcher dispatcher;
+ return dispatcher;
+}
+
+
+} // namespace moof
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_DISPATCH_HH_
+#define _MOOF_DISPATCH_HH_
+
+/**
+ * \file dispatcher.hh
+ * Classes that deal with message dispatching.
+ */
+
+#include <string>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+
+namespace moof {
+
+
+/**
+ * Dispatcher of messages to interested parties.
+ */
+
+class dispatcher
+{
+ class impl;
+ boost::shared_ptr<impl> impl_;
+
+ void remove_target(unsigned id);
+
+
+public:
+
+ class handle
+ {
+ public:
+
+ handle() :
+ id_(0) {}
+
+ handle(boost::weak_ptr<impl> dispatcher, unsigned id) :
+ dispatcher_(dispatcher),
+ id_(id) {}
+
+ handle(const handle& handle) :
+ dispatcher_(handle.dispatcher_),
+ id_(handle.id_)
+ {
+ handle.id_ = 0;
+ }
+
+ ~handle()
+ {
+ clear();
+ }
+
+ handle& operator = (const handle& handle)
+ {
+ clear();
+ dispatcher_ = handle.dispatcher_;
+ id_ = handle.id_;
+ handle.id_ = 0;
+ return *this;
+ }
+
+ unsigned id() const
+ {
+ return id_;
+ }
+
+ void clear();
+
+ private:
+
+ boost::weak_ptr<impl> dispatcher_;
+ mutable unsigned id_;
+ };
+
+ typedef boost::function<void(void)> function;
+
+
+ dispatcher();
+
+ handle add_target(const std::string& event, const function& callback);
+ handle add_target(const std::string& event, const function& callback,
+ handle handle);
+
+ void dispatch(const std::string& event);
+
+ static dispatcher& global();
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_DISPATCH_HH_
+
#ifndef _MOOF_DRAWABLE_HH_
#define _MOOF_DRAWABLE_HH_
-#include <Moof/Math.hh>
+/**
+ * \file drawable.hh
+ * Representation for an object that can be drawn to the screen.
+ */
+#include <moof/math.hh>
-namespace Mf {
+
+namespace moof {
/**
* Interface for anything that can be drawn.
*/
-
-class Drawable
+class drawable
{
public:
- virtual ~Drawable() {}
+ virtual ~drawable() {}
- virtual void draw(Scalar alpha) const = 0;
+ virtual void draw(scalar alpha) const = 0;
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_DRAWABLE_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_ENTITY_HH_
+#define _MOOF_ENTITY_HH_
+
+/**
+ * \file entity.hh
+ * Interface class for cullable and drawable objects.
+ */
+
+#include <boost/shared_ptr.hpp>
+
+#include <moof/aabb.hh>
+#include <moof/cullable.hh>
+#include <moof/drawable.hh>
+#include <moof/sphere.hh>
+
+
+namespace moof {
+
+
+class frustum;
+
+
+class entity;
+
+/**
+ * Entity pointer.
+ */
+typedef boost::shared_ptr<entity> entity_ptr;
+
+
+/**
+ * Interface for game objects that can be drawn to the screen and have a
+ * specified volume (take up space).
+ */
+class entity : public cullable, public drawable
+{
+public:
+
+ virtual ~entity() {}
+
+ /**
+ * Draw the entity only if it is visible. This method melds the
+ * cullable and drawable interfaces, and the default implementation is
+ * usually on the money.
+ * \param alpha The fraction between the last timestep and the next
+ * timestep.
+ * \param frustum The camera frustum for determining visibility.
+ */
+ virtual void draw_if_visible(scalar alpha, const frustum& frustum) const
+ {
+ if (is_visible(frustum)) draw(alpha);
+ }
+
+ /**
+ * Get whether or not the entity is within a frustum. The default
+ * implementation returns the visibility of the bounding sphere and
+ * box.
+ * \param frustum The camera frustum.
+ * \return True if the entity is visible, false otherwise.
+ */
+ virtual bool is_visible(const frustum& frustum) const
+ {
+ return sphere_.is_visible(frustum) && aabb_.is_visible(frustum);
+ }
+
+
+ /**
+ * Get the axis-aligned bounding box surrounding the entity.
+ * \return The AABB.
+ */
+ const moof::aabb<3>& aabb() const
+ {
+ return aabb_;
+ }
+
+ /** Get the bounding sphere surrounding the entity.
+ * \return The sphere.
+ */
+ const moof::sphere<3>& sphere() const
+ {
+ return sphere_;
+ }
+
+
+protected:
+
+ moof::aabb<3> aabb_;
+ moof::sphere<3> sphere_;
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_ENTITY_HH_
+
#ifndef _MOOF_EVENT_HH_
#define _MOOF_EVENT_HH_
+
+/**
+ * \file event.hh
+ * Defines an event object.
+ */
#include <SDL/SDL.h>
-namespace Mf {
-
+namespace moof {
-// 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 complete
-// abstractions.
-typedef SDL_Event Event;
+/**
+ * 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 or provide complete
+ * abstractions.
+ */
+typedef SDL_Event event;
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_EVENT_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include "aabb.hh"
+#include "frustum.hh"
+#include "sphere.hh"
+
+
+namespace moof {
+
+
+void frustum::init(const matrix4& modelview, const matrix4& projection)
+{
+ scalar planes[6][4];
+
+ extract_frustum_planes(modelview, projection, planes, z_clip_neg_one);
+
+ planes_[0] = plane(planes[0][0], planes[0][1],
+ planes[0][2], planes[0][3]);
+ planes_[1] = plane(planes[1][0], planes[1][1],
+ planes[1][2], planes[1][3]);
+ planes_[2] = plane(planes[2][0], planes[2][1],
+ planes[2][2], planes[2][3]);
+ planes_[3] = plane(planes[3][0], planes[3][1],
+ planes[3][2], planes[3][3]);
+ planes_[4] = plane(planes[4][0], planes[4][1],
+ planes[4][2], planes[4][3]);
+ planes_[5] = plane(planes[5][0], planes[5][1],
+ planes[5][2], planes[5][3]);
+}
+
+void frustum::init(const matrix4& modelview, scalar fovy, scalar aspect,
+ scalar abutting, scalar distant)
+{
+ matrix4 projection;
+
+ matrix_perspective_yfov_RH(projection, fovy, aspect, abutting,
+ distant, z_clip_neg_one);
+
+ init(modelview, projection);
+}
+
+frustum::collision frustum::contains(const aabb<3>& aabb) const
+{
+ vector3 corners[8];
+ int nTotalInside = 0;
+
+ aabb.get_corners(corners);
+
+ for (int i = 0; i < 6; ++i)
+ {
+ int nInside = 8;
+
+ for (int j = 0; j < 8; ++j)
+ {
+ if (planes_[i].intersects(corners[j]) == plane::negative)
+ {
+ --nInside;
+ }
+ }
+
+ if (nInside == 0) return outside;
+ else if (nInside == 8) ++nTotalInside;
+ }
+
+ if (nTotalInside == 6) return inside;
+ else return intersecting;
+}
+
+
+frustum::collision frustum::contains(const sphere<3>& sphere) const
+{
+ for (int i = 0; i < 6; ++i)
+ {
+ plane::halfspace halfspace = planes_[i].intersects(sphere);
+
+ if (halfspace == plane::negative) return outside;
+ else if (halfspace == plane::intersecting) return intersecting;
+ }
+
+ return inside;
+}
+
+
+} // namespace moof
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_FRUSTUM_HH_
+#define _MOOF_FRUSTUM_HH_
+
+/**
+ * \file frustum.hh
+ * All things related to frustums!
+ */
+
+#include <moof/math.hh>
+#include <moof/plane.hh>
+
+
+namespace moof {
+
+
+template <int D> class aabb;
+template <int D> class sphere;
+
+
+/**
+ * A six-sided volume for representing the space visible by a position
+ * looking outward.
+ */
+class frustum
+{
+public:
+
+ enum collision
+ {
+ outside = 0,
+ inside = 1,
+ intersecting = 2
+ };
+
+ frustum() {}
+ frustum(const matrix4& modelview, const matrix4& projection)
+ {
+ init(modelview, projection);
+ }
+ frustum(const matrix4& modelview, scalar fovy, scalar aspect,
+ scalar abutting, scalar distant)
+ {
+ init(modelview, fovy, aspect, abutting, distant);
+ }
+
+ void init(const matrix4& modelview, const matrix4& projection);
+ void init(const matrix4& modelview, scalar fovy, scalar aspect,
+ scalar abutting, scalar distant);
+
+ collision contains(const aabb<3>& aabb) const;
+ collision contains(const sphere<3>& sphere) const;
+
+
+private:
+
+ plane planes_[6]; // left, right, bottom, top, near, far
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_FRUSTUM_HH_
+
*
**************************************************************************/
-#include "HashTools.hh"
+#include "hash.hh"
-namespace Mf {
+namespace moof {
// MurmurHash2, by Austin Appleby
// 2. It will not produce the same results on little-endian and big-endian
// machines.
-unsigned HashFunction::operator()(const void* key, int len,
- unsigned int seed) const
+unsigned hash_function::operator()(const void* key, int len,
+ unsigned int seed) const
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
}
-} // namespace Mf
+} // namespace moof
*
**************************************************************************/
-#ifndef _MOOF_HASHTOOLS_HH_
-#define _MOOF_HASHTOOLS_HH_
+#ifndef _MOOF_HASH_HH_
+#define _MOOF_HASH_HH_
+
+/**
+ * \file hash.hh
+ * Hash tables and functions.
+ */
#include <string>
-#include <stlplus/hash.hpp>
+#include <moof/stlplus/hash.hpp>
+
+
+namespace moof {
-namespace Mf {
+using stlplus::hash;
-struct HashFunction
+struct hash_function
{
// generic hash function
- unsigned operator()(const void* key, int len,
- unsigned seed = -1) const;
+ unsigned operator () (const void* key, int len,
+ unsigned seed = -1) const;
- inline unsigned operator()(const std::string& val) const
+ unsigned operator () (const std::string& val) const
{
return (*this)(val.data(), val.length());
}
- inline unsigned operator()(int val) const
+ unsigned operator () (int val) const
{
return val;
}
};
-} // namespace Mf
+} // namespace moof
-#endif // _MOOF_HASHTOOLS_HH_
+#endif // _MOOF_HASH_HH_
#include <png.h>
#include <SDL/SDL.h>
-#include "Backend.hh"
-#include "Error.hh"
-#include "Image.hh"
-#include "Log.hh"
-#include "Manager.hh"
+#include "backend.hh"
+#include "image.hh"
+#include "log.hh"
+#include "manager.hh"
-namespace Mf {
+namespace moof {
-class Image::Impl : public Manager<Impl>
+class image::impl : public manager<impl>
{
public:
- explicit Impl() :
- mContext(0),
- mPixels(0) {}
+ explicit impl() :
+ context_(0),
+ pixels_(0) {}
- ~Impl()
+ ~impl()
{
- SDL_FreeSurface(mContext);
- delete[] mPixels;
+ SDL_FreeSurface(context_);
+ delete[] pixels_;
}
void flip()
{
- unsigned char* pixels = (Uint8*)(mContext->pixels);
+ unsigned char* pixels = (Uint8*)(context_->pixels);
- unsigned pitch = mContext->pitch;
+ unsigned pitch = context_->pitch;
unsigned char line[pitch];
int yBegin = 0;
- int yEnd = mContext->h - 1;
+ int yEnd = context_->h - 1;
- if (SDL_MUSTLOCK(mContext)) SDL_LockSurface(mContext);
+ if (SDL_MUSTLOCK(context_)) SDL_LockSurface(context_);
while (yBegin < yEnd)
{
memcpy(line, pixels + pitch * yBegin, pitch);
yBegin++;
yEnd--;
}
- if (SDL_MUSTLOCK(mContext)) SDL_UnlockSurface(mContext);
+ if (SDL_MUSTLOCK(context_)) SDL_UnlockSurface(context_);
}
- void setAsIcon() const
+ void set_as_icon() const
{
- SDL_WM_SetIcon(mContext, 0);
+ SDL_WM_SetIcon(context_, 0);
}
{
std::string path(name);
- FILE* fp = Image::openFile(path);
+ FILE* fp = image::open_file(path);
if (!fp) return;
png_byte signature[8];
png_bytepp rows = 0;
png_textp texts = 0;
- int numTexts;
+ int nutext_s;
bytesRead = fread(signature, 1, sizeof(signature), fp);
if (bytesRead < sizeof(signature) ||
bpp = png_get_bit_depth(pngObj, pngInfo);
channels = png_get_channels(pngObj, pngInfo);
- mDepth = bpp * channels;
+ depth_ = bpp * channels;
- if (channels == 3) mColorMode = GL_RGB;
- else mColorMode = GL_RGBA;
+ if (channels == 3) color_mode_ = GL_RGB;
+ else color_mode_ = GL_RGBA;
// read comments
- png_get_text(pngObj, pngInfo, &texts, &numTexts);
- for (int i = 0; i < numTexts; ++i)
+ png_get_text(pngObj, pngInfo, &texts, &nutext_s);
+ for (int i = 0; i < nutext_s; ++i)
{
if (strncmp(texts[i].key, "TextureInfo", 11) == 0)
{
- mComment = texts[i].text;
+ comment_ = texts[i].text;
break;
}
}
height = png_get_image_height(pngObj, pngInfo);
pitch = png_get_rowbytes(pngObj, pngInfo);
- mPixels = new char[width * pitch];
+ pixels_ = new char[width * pitch];
rows = new png_bytep[height];
if (flipped)
{
for (int i = 0; i < height; ++i)
{
- rows[height - 1 - i] = (png_bytep)(mPixels +
+ rows[height - 1 - i] = (png_bytep)(pixels_ +
i * channels * width);
}
}
{
for (int i = 0; i < height; ++i)
{
- rows[i] = (png_bytep)(mPixels + i * channels * width);
+ rows[i] = (png_bytep)(pixels_ + i * channels * width);
}
}
png_read_image(pngObj, rows);
png_read_end(pngObj, 0);
- mContext = SDL_CreateRGBSurfaceFrom
+ context_ = SDL_CreateRGBSurfaceFrom
(
- mPixels,
+ pixels_,
width,
height,
bpp * channels,
}
- SDL_Surface* mContext;
- char* mPixels;
+ SDL_Surface* context_;
+ char* pixels_;
- unsigned mDepth;
- GLuint mColorMode;
+ unsigned depth_;
+ GLuint color_mode_;
- std::string mComment;
+ std::string comment_;
private:
- Backend mBackend;
+ backend backend_;
};
-Image::Image(const std::string& name) :
+image::image(const std::string& name) :
// pass through
- mImpl(Image::Impl::getInstance(name)) {}
+ impl_(image::impl::instance(name)) {}
-bool Image::isValid() const
+bool image::is_valid() const
{
- return mImpl->mContext;
+ return impl_->context_;
}
-int Image::getWidth() const
+int image::width() const
{
- return mImpl->mContext->w;
+ return impl_->context_->w;
}
-int Image::getHeight() const
+int image::height() const
{
- return mImpl->mContext->h;
+ return impl_->context_->h;
}
-unsigned Image::getDepth() const
+unsigned image::depth() const
{
- return mImpl->mDepth;
+ return impl_->depth_;
}
-unsigned Image::getPitch() const
+unsigned image::pitch() const
{
- return mImpl->mContext->pitch;
+ return impl_->context_->pitch;
}
-GLuint Image::getMode() const
+GLuint image::mode() const
{
- return mImpl->mColorMode;
+ return impl_->color_mode_;
}
-std::string Image::getComment() const
+std::string image::comment() const
{
- return mImpl->mComment;
+ return impl_->comment_;
}
-const char* Image::getPixels() const
+const char* image::pixels() const
{
- return mImpl->mPixels;
+ return impl_->pixels_;
}
-char* Image::getPixels()
+char* image::pixels()
{
- return mImpl->mPixels;
+ return impl_->pixels_;
}
-void Image::flip()
+void image::flip()
{
// pass through
- mImpl->flip();
+ impl_->flip();
}
-void Image::setAsIcon() const
+void image::set_as_icon() const
{
// pass through
- mImpl->setAsIcon();
+ impl_->set_as_icon();
}
-bool Image::getPath(std::string& name)
+bool image::find_path(std::string& name)
{
- return Resource::getPath(name, "images/", "png");
+ return resource::find_path(name, "images/", "png");
}
-FILE* Image::openFile(std::string& name)
+FILE* image::open_file(std::string& name)
{
- return Resource::openFile(name, "images/", "png");
+ return resource::open_file(name, "images/", "png");
}
-} // namespace Mf
+} // namespace moof
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_IMAGE_HH_
+#define _MOOF_IMAGE_HH_
+
+/**
+ * \file image.hh
+ * Defines classes for loading and manipulating images.
+ */
+
+#include <boost/shared_ptr.hpp>
+
+#include <moof/opengl.hh>
+#include <moof/resource.hh>
+
+
+namespace moof {
+
+
+class image;
+typedef boost::shared_ptr<image> image_ptr;
+
+class image : public resource
+{
+public:
+
+ static image_ptr alloc(const std::string& name)
+ {
+ return image_ptr(new image(name));
+ }
+
+ explicit image(const std::string& name);
+
+ bool is_valid() const;
+
+ int width() const;
+ int height() const;
+
+ unsigned depth() const;
+ unsigned pitch() const;
+ GLuint mode() const;
+
+ std::string comment() const;
+
+ const char* pixels() const;
+ char* pixels();
+
+ void flip();
+
+ void set_as_icon() const;
+
+ static bool find_path(std::string& name);
+
+
+private:
+
+ static FILE* open_file(std::string& name);
+
+ class impl;
+ boost::shared_ptr<impl> impl_;
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_IMAGE_HH_
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_INTERPOLATOR_HH_
+#define _MOOF_INTERPOLATOR_HH_
+
+/**
+ * \file interpolator.hh
+ * Functions and classes concerning interpolations between values.
+ */
+
+#include <moof/math.hh>
+
+
+namespace moof {
+
+
+/**
+ * Interpolators should inherit from this base class to get some free
+ * functionality. Subclasses of this base class will implement their own
+ * interpolation functions.
+ */
+template <class F, class T = scalar>
+class interpolator
+{
+public:
+
+ /**
+ * Interpolation mode.
+ */
+ enum mode
+ {
+ stop = 0, /// Interpolator will stop when done.
+ repeat = 1, /// Interpolator will go back to the beginning.
+ oscillate = 2 /// Interpolator will reverse direction.
+ };
+
+
+ /**
+ * Construct an uninitialized interpolator.
+ */
+ interpolator() :
+ is_done_(true) {}
+
+ /**
+ * Construct an interpolator.
+ * \param a The initial value.
+ * \param b The target value.
+ * \param t The duration of the interpolation.
+ * \param mode The interpolation mode.
+ */
+ interpolator(const T& a, const T& b, scalar t = 1.0, mode mode = stop) :
+ state_(a),
+ prior_(a),
+ a_(a),
+ b_(b),
+ alpha_(SCALAR(0.0)),
+ scale_(SCALAR(1.0) / t),
+ mode_(mode),
+ is_done_(false) {}
+
+ /**
+ * Initialize the interpolator. Any interpolation already being
+ * tracked by this object will be replaced with a new interpolation
+ * based on the initialization arguments.
+ * \param a The initial value.
+ * \param b The target value.
+ * \param t The duration of the interpolation.
+ * \param mode The interpolation mode.
+ */
+ void init(const T& a, const T& b, scalar t = 1.0, mode mode = stop)
+ {
+ a_ = a;
+ b_ = b;
+ alpha_ = 0.0;
+ scale_ = 1.0 / t;
+ mode_ = mode;
+ is_done_ = false;
+ }
+
+
+ /**
+ * Update the interpolation state with a timeslice.
+ * \param t The total time in seconds.
+ * \param dt The number of seconds passed since the last call to
+ * update.
+ */
+ void update(scalar t, scalar dt)
+ {
+ if (!is_done_)
+ {
+ alpha_ += dt * scale_;
+ prior_ = state_;
+ state_ = function_(a_, b_, alpha_);
+
+ if (alpha_ > 1.0)
+ {
+ switch (mode_)
+ {
+ case stop:
+ alpha_ = SCALAR(1.0);
+ is_done_ = true;
+ break;
+ case repeat:
+ alpha_ -= SCALAR(1.0);
+ break;
+ case oscillate:
+ alpha_ = SCALAR(2.0) - alpha_;
+ scale_ = -scale_;
+ break;
+ }
+ }
+ else if (alpha_ < 0.0)
+ {
+ switch (mode_)
+ {
+ case stop:
+ alpha_ = SCALAR(0.0);
+ is_done_ = true;
+ break;
+ case repeat:
+ alpha_ += SCALAR(1.0);
+ break;
+ case oscillate:
+ alpha_ = -alpha_;
+ scale_ = -scale_;
+ break;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Get the interpolated value.
+ * \return The interpolated value.
+ */
+ T state() const
+ {
+ return state_;
+ }
+
+ /**
+ * Get the interpolated value interpolated between two updates.
+ * \param alpha The fraction between updates.
+ * \return The interpolated value.
+ */
+ T state(scalar alpha) const
+ {
+ return lerp(prior_, state_, alpha);
+ }
+
+ /**
+ * Get whether or not the interpolation is done. This will only return
+ * true if the interpolation mode is stop.
+ * \return True if the interpolation has finished.
+ */
+ bool is_done() const
+ {
+ return is_done_;
+ }
+
+
+private:
+
+ T state_;
+ T prior_;
+ T a_;
+ T b_;
+
+ F function_;
+
+ scalar alpha_;
+ scalar scale_;
+ mode mode_;
+ bool is_done_;
+};
+
+
+struct linear_interpolation_function
+{
+ template <class T>
+ T operator () (const T& a, const T& b, scalar alpha)
+ {
+ return lerp(a, b, alpha);
+ }
+};
+
+
+typedef interpolator<linear_interpolation_function> lerp_scalar;
+
+
+} // namespace moof
+
+#endif // _MOOF_INTERPOLATOR_HH_
+
#ifndef _MOOF_LINE_HH_
#define _MOOF_LINE_HH_
-#include <Moof/Contact.hh>
-#include <Moof/Drawable.hh>
-#include <Moof/Log.hh>
-#include <Moof/Math.hh>
-#include <Moof/OpenGL.hh>
-#include <Moof/Ray.hh>
-#include <Moof/Shape.hh>
-#include <Moof/Sphere.hh>
-#include <Moof/Texture.hh>
+/**
+ * \file line.hh
+ * Classes related to line segments.
+ */
+#include <moof/contact.hh>
+#include <moof/drawable.hh>
+#include <moof/log.hh>
+#include <moof/math.hh>
+#include <moof/opengl.hh>
+#include <moof/ray.hh>
+#include <moof/shape.hh>
+#include <moof/sphere.hh>
+#include <moof/texture.hh>
-namespace Mf {
+
+namespace moof {
template <int D>
-struct Line : public Drawable, public Shape<D>
+struct line : public drawable, public shape<D>
{
- typedef cml::vector< Scalar, cml::fixed<D> > Vector;
+ typedef moof::vector< scalar, fixed<D> > vector;
+
- Vector a;
- Vector b;
+ vector a;
+ vector b;
- Line() {}
+ line() {}
- Line(const Vector& point1, const Vector& point2) :
+ line(const vector& point1, const vector& point2) :
a(point1),
b(point2) {}
- Vector getDirection() const
+ vector direction() const
{
return b - a;
}
- Scalar getLength() const
+ scalar length() const
{
- return getDirection().length();
+ return direction().length();
}
- bool intersect(const Line& other, Contact<D>& hit) const
+ bool intersect(const line& other, contact<D>& hit) const
{
- Scalar d = (other.b[1] - other.a[1]) * (b[0] - a[0]) -
+ scalar d = (other.b[1] - other.a[1]) * (b[0] - a[0]) -
(other.b[0] - other.a[0]) * (b[1] - a[1]);
if (d == SCALAR(0.0)) return false; // lines are parallel
// ignoring the (somewhat remote) possibility of coincidence
- Scalar m = ((other.b[0] - other.a[0]) * (a[1] - other.a[1]) -
+ scalar m = ((other.b[0] - other.a[0]) * (a[1] - other.a[1]) -
(other.b[1] - other.a[1]) * (a[0] - other.a[0])) / d;
- Scalar n = ((b[0] - a[0]) * (b[1] - other.a[1]) -
+ scalar n = ((b[0] - a[0]) * (b[1] - other.a[1]) -
(b[1] - a[1]) * (b[0] - other.a[0])) / d;
if (m < SCALAR(0.0) || m > SCALAR(1.0) || // not intersecting
n < SCALAR(0.0) || n > SCALAR(1.0)) return false;
- Vector2 tangent = b - a;
- Vector2 normal = cml::perp(tangent).normalize();
+ vector2 tangent = b - a;
+ vector2 normal = perp(tangent).normalize();
- if (cml::dot(normal, other.a - other.b) < SCALAR(0.0))
+ if (dot(normal, other.a - other.b) < SCALAR(0.0))
{
normal = -normal;
}
return true;
}
- bool intersect(const Sphere<D>& other, Contact<D>& hit) const
+ bool intersect(const sphere<D>& other, contact<D>& hit) const
{
- Vector surface = b - a;
- Vector toPoint = other.point - a;
+ vector surface = b - a;
+ vector toPoint = other.point - a;
- Scalar surfaceLength = surface.length();
+ scalar surfaceLength = surface.length();
surface.normalize();
- Scalar projection = cml::dot(surface, toPoint);
+ scalar projection = dot(surface, toPoint);
if (projection < SCALAR(0.0) || projection > surfaceLength)
{
return false;
}
- Vector point = a + surface * projection;
- Vector normal = other.point - point;
+ vector point = a + surface * projection;
+ vector normal = other.point - point;
- Scalar distance = normal.length();
+ scalar distance = normal.length();
if (distance > other.radius) false; // not intersecting
}
- bool intersectRay(const Ray<2>& ray, Ray<2>::Contact& hit) const
+ bool intersect_ray(const ray<2>& ray, ray<2>::contact& hit) const
{
- Vector2 v1 = a - ray.point;
- Scalar a1 = cml::signed_angle_2D(v1, b - ray.point);
+ vector2 v1 = a - ray.point;
+ scalar a1 = signed_angle_2D(v1, b - ray.point);
- //logWarning << "angle:::::::::: " << a1 << std::endl;
+ //log_warning << "angle:::::::::: " << a1 << std::endl;
- if (a1 == Constants::pi())
+ if (a1 == constants::pi())
{
hit.distance = 5.4321;
return true;
return true;
}
- Scalar a2 = cml::signed_angle_2D(v1, ray.direction);
+ scalar a2 = signed_angle_2D(v1, ray.direction);
if (a2 < SCALAR(0.0) || a2 > a1) return false;
//hit.distance = 1.23456;
- //hit.normal = Vector2(0.0, 0.0);
+ //hit.normal = vector2(0.0, 0.0);
- Vector2 n = (b - a).normalize();
- Scalar z = cml::dot(ray.point - a, n);
- Vector2 p = a + n * z;
+ vector2 n = (b - a).normalize();
+ scalar z = dot(ray.point - a, n);
+ vector2 p = a + n * z;
hit.distance = (ray.point - p).length();
- hit.normal = cml::perp(a - b);
+ hit.normal = perp(a - b);
return true;
// C = ray.point
// D = ray.direction
- Scalar denom = ray.direction[0] * (b[1] - a[1]) +
+ scalar denom = ray.direction[0] * (b[1] - a[1]) +
ray.direction[1] * (a[0] - b[0]);
// check if the ray and line are parallel
- //if (isEqual(denom, SCALAR(0.0)))
+ //if (is_equal(denom, SCALAR(0.0)))
if (denom == SCALAR(0.0))
{
- Scalar numer = a[0] * (ray.point[1] - b[1]) +
+ scalar numer = a[0] * (ray.point[1] - b[1]) +
b[0] * (a[1] - ray.point[1]) +
ray.point[0] * (b[1] - a[1]);
// check if they are collinear
- if (isEqual(numer, SCALAR(0.0)))
+ if (is_equal(numer, SCALAR(0.0)))
{
hit.distance = SCALAR(0.0);
hit.normal.set(0.0, 0.0);
return false;
}
- Scalar s = (ray.direction[0] * (ray.point[1] - a[1]) +
+ scalar s = (ray.direction[0] * (ray.point[1] - a[1]) +
ray.direction[1] * (a[0] - ray.point[0])) / denom;
// check if the ray hits the segment
// check if the intersection is behind the ray
if (hit.distance < SCALAR(0.0)) return false;
- Vector normal = cml::perp(a - b);
- if (cml::dot(a - ray.point, normal) < 0) hit.normal = normal;
+ vector normal = perp(a - b);
+ if (dot(a - ray.point, normal) < 0) hit.normal = normal;
else hit.normal = -normal;
return true;
*/
}
- void draw(Scalar alpha = 0.0) const
+ void draw(scalar alpha = 0.0) const
{
- Mf::Texture::resetBind();
+ texture::reset_binding();
glBegin(GL_LINES);
glVertex(a);
glVertex(b);
};
-typedef Line<2> Line2;
-typedef Line<3> Line3;
+typedef line<2> line2;
+typedef line<3> line3;
template <int D, int N>
-struct Polygon : public Drawable, public Shape<D>
+struct polygon : public drawable, public shape<D>
{
- typedef cml::vector< Scalar, cml::fixed<D> > Vector;
+ typedef moof::vector< scalar, fixed<D> > vector;
- Vector points[N];
+ vector points[N];
- Polygon() {}
+ polygon() {}
- bool intersectRay(const Ray<D>& ray, typename Ray<D>::Contact& hit)
+ bool intersect_ray(const ray<D>& ray, typename ray<D>::contact& hit)
{
return false;
}
- void draw(Scalar alpha = 0.0) const
+ void draw(scalar alpha = 0.0) const
{
- Mf::Texture::resetBind();
+ texture::reset_binding();
glBegin(GL_POLYGON);
for (int i = 0; i < D; ++i)
{
};
-typedef Polygon<2,3> Triangle2;
-typedef Polygon<3,3> Triangle3;
+typedef polygon<2,3> triangle2;
+typedef polygon<3,3> triangle3;
template <int D>
-bool intersect(const Line<D>& line, const Sphere<D>& sphere,
- Contact<D>& hit)
+bool intersect(const line<D>& line, const sphere<D>& sphere,
+ contact<D>& hit)
{
return false;
}
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_LINE_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <fstream>
+
+#include "log.hh"
+#include "script.hh"
+
+
+namespace moof {
+
+
+enum log::level log::gLevel = log::info;
+
+
+void log::level(enum level level)
+{
+ gLevel = level;
+}
+
+enum log::level log::level()
+{
+ return gLevel;
+}
+
+
+std::ostream& log(std::clog);
+
+static std::ofstream null_log_;
+std::ostream& null_log(null_log_);
+
+class log log_error( log::error, " error: ");
+class log log_warning(log::warning, "warning: ");
+class log log_info( log::info, " info: ");
+
+
+static int log_script(script& script, enum log::level level)
+{
+ static class log* logs[] = {0, &log_error, &log_warning, &log_info};
+
+ script::slot param = script[1];
+
+ while (!param.is_none())
+ {
+ (*logs[level])(param);
+ ++param.index;
+ }
+
+ return 0;
+}
+
+void log::import(script& script)
+{
+ script.import_function("LogError",
+ boost::bind(log_script, _1, log::error));
+ script.import_function("LogWarning",
+ boost::bind(log_script, _1, log::warning));
+ script.import_function("LogInfo",
+ boost::bind(log_script, _1, log::info));
+ script.import_function("print",
+ boost::bind(log_script, _1, log::info));
+}
+
+
+} // namespace moof
+
*
**************************************************************************/
-#ifndef _MOOF_LOG_H_
-#define _MOOF_LOG_H_
+#ifndef _MOOF_LOG_HH_
+#define _MOOF_LOG_HH_
/**
- * \file Log.h
+ * \file log.hh
* Functions related to logging the process.
- * The logging functions are logError(), logWarning(), and logInfo(),
+ * The logging functions are log_error(), log_warning(), and log_info(),
* listed from most critical to least critical.
*/
#include <iostream>
-/**
- * Macro which tests an assertion and issues a logError() and exits if the
- * assertion is false.
- * \param X test to perform
- */
-
#undef ASSERT
-
#if NDEBUG
#define ASSERT(X)
#else
-#define ASSERT(X) if (!(X)) Mf::logError \
+/**
+ * Macro which tests an assertion and issues a log_error() and exits if the
+ * assertion is false.
+ * \param X test to perform
+ */
+#define ASSERT(X) if (!(X)) moof::log_error \
<< "false assertion at " << __FILE__ << ":" << __LINE__ << ", " \
<< #X, exit(1)
#endif
-namespace Mf {
+namespace moof {
+
+
+class script;
/**
* stream. Either way, any object can be printed to the log as long as
* there is an override for the ostream insertion operator.
*/
-class Log
+class log
{
public:
/**
* A type for the level or priority of a log message.
*/
- enum Level
+ enum level
{
- NONE = 0, ///< Disable all logging.
- ERRORR = 1, ///< Log only errors.
- WARNING = 2, ///< Log warnings and errors.
- INFO = 3, ///< Log everything.
+ none = 0, ///< Disable all logging.
+ error = 1, ///< Log only errors.
+ warning = 2, ///< Log warnings and errors.
+ info = 3, ///< Log everything.
};
* log. Any logging with a lower priority will be ignored.
* \param level The log level.
*/
- static void setLevel(Level level);
+ static void level(level level);
/**
* Get the current lowest-priority log level. If unchanged, the
- * default level is INFO.
+ * default level is info.
* \return The log level.
*/
- static Level level();
+ static enum level level();
+
+
+ /**
+ * Import log functions to a script.
+ * \param The script.
+ */
+ static void import(script& script);
/**
* \param level The log level.
* \param prefix The string printed before each log message.
*/
- Log(Level level, const char* prefix) :
- mLevel(level),
- mPrefix(prefix) /* only pass literal strings */ {}
+ log(enum level level, const char* prefix) :
+ level_(level),
+ prefix_(prefix) /* only pass literal strings */ {}
template <class A>
private:
- template <class T> friend std::ostream& operator << (Log&, const T&);
+ template <class T> friend std::ostream& operator << (log&, const T&);
- static Level gLevel;
+ static enum level gLevel;
- Level mLevel;
- const char* mPrefix;
+ enum level level_;
+ const char* prefix_;
};
extern std::ostream& log;
-extern std::ostream& nullLog;
+extern std::ostream& null_log;
-extern Log logError;
-extern Log logWarning;
-extern Log logInfo;
+extern class log log_error;
+extern class log log_warning;
+extern class log log_info;
template <class T>
-inline std::ostream& operator << (Log& logObj, const T& item)
+inline std::ostream& operator << (class log& log, const T& item)
{
- if (Log::gLevel < logObj.mLevel) return nullLog;
- return log << logObj.mPrefix << item;
+ if (log::gLevel < log.level_) return null_log;
+ return moof::log << log.prefix_ << item;
}
-class Script;
-void importLogFunctions(Script& script);
-
-
-} // namespace Mf
+} // namespace moof
-#endif // _MOOF_LOG_H_
+#endif // _MOOF_LOG_HH_
#define _MOOF_MANAGER_HH_
/**
- * @file Manager.hh
- * A library is a collection of named objects of the same type. Libraries
+ * \file manager.hh
+ * A manager is a collection of named objects of the same type. Libraries
* use reference counting to automagically delete objects which no longer
* have any interested code.
*/
#include <boost/shared_ptr.hpp>
-#include <Moof/HashTools.hh>
+#include <moof/hash.hh>
-namespace Mf {
+namespace moof {
template <class T>
-class Manager
+class manager
{
public:
- Manager() :
- mRetainCount(1) {}
+ manager() :
+ retain_count_(1) {}
- const std::string& getName() const
+ const std::string& name() const
{
- return mName;
+ return name_;
}
- static boost::shared_ptr<T> getInstance(const std::string& name)
+ static boost::shared_ptr<T> instance(const std::string& name)
{
return boost::shared_ptr<T>(retain(name), &release);
}
-private:
- typedef stlplus::hash<std::string,T*,HashFunction> PtrMap;
+private:
- static PtrMap mPtrMap;
- std::string mName;
- unsigned mRetainCount;
+ typedef stlplus::hash<std::string,T*,hash_function> ptr_lookup;
static T* retain(const std::string& name)
{
- typename PtrMap::iterator it = mPtrMap.find(name);
+ typename ptr_lookup::iterator it = ptr_lookup_.find(name);
- if (it != mPtrMap.end())
+ if (it != ptr_lookup_.end())
{
- ++((*it).second->mRetainCount);
+ ++((*it).second->retain_count_);
return (*it).second;
}
else
{
- T* newObj(new T);
- if (newObj)
+ T* new_object(new T);
+ if (new_object)
{
- newObj->mName = name;
- newObj->init(name);
- mPtrMap.insert(std::make_pair(name, newObj));
+ new_object->name_ = name;
+ new_object->init(name);
+ ptr_lookup_.insert(std::make_pair(name, new_object));
}
- return newObj;
+ return new_object;
}
}
static void release(T* obj)
{
- if (--(obj->mRetainCount) == 0)
+ if (--(obj->retain_count_) == 0)
{
- mPtrMap.erase(obj->mName);
+ ptr_lookup_.erase(obj->name_);
delete obj;
}
}
+
+
+ static ptr_lookup ptr_lookup_;
+ std::string name_;
+ unsigned retain_count_;
};
template <class T>
-stlplus::hash<std::string,T*,HashFunction> Manager<T>::mPtrMap;
+hash<std::string,T*,hash_function> manager<T>::ptr_lookup_;
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_MANAGER_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_MATH_HH_
+#define _MOOF_MATH_HH_
+
+/**
+ * \file math.hh
+ * General math-related types and functions.
+ */
+
+#include <cmath>
+
+#include <SDL/SDL_opengl.h>
+
+#include <moof/cml/cml.h>
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#if USE_DOUBLE_PRECISION
+typedef GLdouble GLscalar;
+#define GL_SCALAR GL_DOUBLE
+#define SCALAR(D) (D)
+#else
+typedef GLfloat GLscalar;
+#define GL_SCALAR GL_FLOAT
+#define SCALAR(F) (F##f)
+#endif
+
+
+namespace moof {
+
+
+using namespace cml;
+
+
+typedef GLscalar scalar;
+
+typedef vector< scalar, fixed<2> > vector2;
+typedef vector< scalar, fixed<3> > vector3;
+typedef vector< scalar, fixed<4> > vector4;
+
+typedef matrix< scalar, fixed<2,2>, col_basis, col_major > matrix2;
+typedef matrix< scalar, fixed<3,3>, col_basis, col_major > matrix3;
+typedef matrix< scalar, fixed<4,4>, col_basis, col_major > matrix4;
+
+typedef quaternion< scalar, fixed<>, vector_first, positive_cross > quaternion;
+
+typedef constants<scalar> constants;
+
+
+inline vector3 demote(const vector4& vec)
+{
+ return vector3(vec[0], vec[1], vec[2]);
+}
+
+inline vector2 demote(const vector3& vec)
+{
+ return vector2(vec[0], vec[1]);
+}
+
+inline vector4 promote(const vector3& vec, scalar extra = SCALAR(0.0))
+{
+ return vector4(vec[0], vec[1], vec[2], extra);
+}
+
+inline vector3 promote(const vector2& vec, scalar extra = SCALAR(0.0))
+{
+ return vector3(vec[0], vec[1], extra);
+}
+
+
+const scalar EPSILON = SCALAR(0.000001);
+
+/**
+ * Check the equality of scalars with a certain degree of error allowed.
+ */
+
+inline bool is_equal(scalar a, scalar b, scalar epsilon = EPSILON)
+{
+ return std::abs(a - b) < epsilon;
+}
+
+
+// Here are some generic implementations of a few simple integrators. To
+// use, you need one type representing the state and another containing the
+// derivatives of the primary state variables. The state class must
+// implement these methods:
+//
+// void calculate_derivative(Derivative_Type& derivative, scalar absoluteTime);
+// void step(const Derivative_Type& derivative, scalar deltaTime);
+//
+// Additionally, the derivative class must overload a few operators:
+//
+// Derivative_Type operator + (const Derivative_Type& other) const
+// Derivative_Type operator * (const Derivative_Type& other) const
+
+template <class S, class D>
+inline D evaluate(const S& state, scalar t)
+{
+ D derivative;
+ state.calculate_derivative(derivative, t);
+ return derivative;
+}
+
+template <class S, class D>
+inline D evaluate(S state, scalar t, scalar dt, const D& derivative)
+{
+ state.step(derivative, dt);
+ return evaluate<S,D>(state, t + dt);
+}
+
+
+template <class S, class D>
+inline void euler(S& state, scalar t, scalar dt)
+{
+ D a = evaluate<S,D>(state, t);
+
+ state.step(a, dt);
+}
+
+template <class S, class D>
+inline void rk2(S& state, scalar t, scalar dt)
+{
+ D a = evaluate<S,D>(state, t);
+ D b = evaluate<S,D>(state, t, dt * SCALAR(0.5), a);
+
+ state.step(b, dt);
+}
+
+template <class S, class D>
+inline void rk4(S& state, scalar t, scalar dt)
+{
+ D a = evaluate<S,D>(state, t);
+ D b = evaluate<S,D>(state, t, dt * SCALAR(0.5), a);
+ D c = evaluate<S,D>(state, t, dt * SCALAR(0.5), b);
+ D d = evaluate<S,D>(state, t, dt, c);
+
+ state.step((a + (b + c) * SCALAR(2.0) + d) * SCALAR(1.0/6.0), dt);
+}
+
+
+} // namespace moof
+
+#endif // _MOOF_MATH_HH_
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_MODAL_DIALOG_HH_
+#define _MOOF_MODAL_DIALOG_HH_
+
+/**
+ * \file modal_dialog.hh
+ * A class for creating and running modal dialogs. Several toolkits are
+ * supported, but only one can be used as determined at build time.
+ */
+
+#include <string>
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(_WIN32)
+#include <windows.h>
+#elif USE_GTK
+#include <gtk/gtk.h>
+#elif USE_QT4
+#include <QApplication>
+#include <QIcon>
+#include <QMessageBox>
+#endif
+
+#include <moof/log.hh>
+#include <moof/resource.hh>
+
+
+namespace moof {
+
+
+/**
+ * Small wrapper over various user interface modal dialog windows.
+ */
+
+struct modal_dialog
+{
+ enum type
+ {
+ information = 1,
+ warning = 2,
+ error = 3
+ };
+
+
+ std::string title;
+ type type;
+ std::string text1;
+ std::string text2;
+
+
+ /**
+ * Construct a dialog box.
+ * \param type The type of dialog, indicating its priority.
+ * \param title The text used as the title of the dialog.
+ * \param text1 The first line of the dialog window.
+ * \param text2 The second line.
+ */
+ modal_dialog(enum type type = information,
+ const std::string& title = "",
+ const std::string& text1 = "",
+ const std::string& text2 = "") :
+ title(title),
+ type(type),
+ text1(text1),
+ text2(text2) {}
+
+
+ void run() const
+ {
+ switch (type)
+ {
+ case warning:
+ log_warning(text1);
+ log_warning(text2);
+ break;
+ case error:
+ log_error(text1);
+ log_error(text2);
+ break;
+ default:
+ log_info(text1);
+ log_info(text2);
+ break;
+ }
+
+#if defined(_WIN32)
+
+ int icon_type;
+ switch (type)
+ {
+ case warning:
+ icon_type = MB_ICONWARNING;
+ break;
+ case error:
+ icon_type = MB_ICONERROR;
+ break;
+ default:
+ icon_type = MB_ICONINFORMATION;
+ break;
+ }
+
+ MessageBox(0, (text1 + "\n" + text2).c_str(), title.c_str(),
+ MB_OK | icon_type);
+
+#elif USE_GTK
+
+ int argc = 0;
+ char** argv;
+ gtk_init(&argc, &argv);
+
+ GtkMessageType icon_type;
+ switch (type)
+ {
+ case warning:
+ icon_type = GTK_MESSAGE_WARNING;
+ break;
+ case error:
+ icon_type = GTK_MESSAGE_ERROR;
+ break;
+ default:
+ icon_type = GTK_MESSAGE_INFO;
+ break;
+ }
+
+ GtkWidget* dialog = gtk_message_dialog_new(NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT, icon_type,
+ GTK_BUTTONS_CLOSE, "%s", text1.c_str());
+ gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
+ "%s", text2.c_str());
+ gtk_window_set_title(GTK_WINDOW(dialog), title.c_str());
+
+ std::string icon_path(PACKAGE".png");
+ if (resource::find_path(icon_path))
+ {
+ GdkPixbuf* iconPixbuf = gdk_pixbuf_new_from_file(icon_path.c_str(),
+ NULL);
+ gtk_window_set_icon(GTK_WINDOW(dialog), iconPixbuf);
+ }
+
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ // FIXME - this doesn't seem to actually remove the window from the
+ // screen when it closes
+
+#elif USE_QT4
+
+ int argc = 0;
+ char** argv;
+ QApplication qt_app(argc, argv);
+
+ QMessageBox::Icon icon_type;
+ switch (type)
+ {
+ case warning:
+ icon_type = QMessageBox::Warning;
+ break;
+ case error:
+ icon_type = QMessageBox::Critical;
+ break;
+ default:
+ icon_type = QMessageBox::Information;
+ break;
+ }
+
+ QMessageBox dialog;
+ dialog.setWindowTitle(title.c_str());
+ dialog.setIcon(icon_type);
+ dialog.setText(text1.c_str());
+ dialog.setInformativeText(text2.c_str());
+ dialog.setStandardButtons(QMessageBox::Close);
+
+ std::string icon_path(PACKAGE".png");
+ if (resource::find_path(icon_path))
+ {
+ QIcon icon(icon_path.c_str());
+ dialog.setWindowIcon(icon);
+ }
+
+ dialog.exec();
+
+#endif
+ }
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_MODAL_DIALOG_HH_
+
#ifndef _MOOF_NETWORK_HH_
#define _MOOF_NETWORK_HH_
+/**
+ * \file network.hh
+ * Builds a high-level protocol and match-making system on top of network
+ * sockets for multiplayer support.
+ */
+
#include <string>
#include <vector>
-namespace Mf {
+namespace moof {
-class NetworkGamer
+class network_gamer
{
};
-class NetworkSession
+class network_session
{
public:
- const std::vector<NetworkGamer>& gamers();
+ const std::vector<network_gamer>& gamers();
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_NETWORK_HH_
#ifndef _MOOF_OPENGL_HH_
#define _MOOF_OPENGL_HH_
+/**
+ * \file opengl.hh
+ * Defines macros for OpenGL functions that operate on scalars, vectors,
+ * and matrices.
+ */
+
#include <SDL/SDL_opengl.h>
-#include <Moof/Math.hh>
+#include <moof/math.hh>
#if HAVE_CONFIG_H
#include "config.h"
#define ARGS_P const GLscalar* p
#define PASS_P p
-#define ARGS_M const Mf::Matrix4& m
+#define ARGS_M const moof::matrix4& m
#define PASS_M m.data()
// ordinal function arguments
#define ARGS_S4 GLscalar a, GLscalar b, GLscalar c, GLscalar d
#define PASS_S4 a, b, c, d
-#define ARGS_P2 const Mf::Vector2& p
+#define ARGS_P2 const moof::vector2& p
#define PASS_P2 p.data()
-#define ARGS_P3 const Mf::Vector3& p
+#define ARGS_P3 const moof::vector3& p
#define PASS_P3 p.data()
-#define ARGS_P4 const Mf::Vector4& p
+#define ARGS_P4 const moof::vector4& p
#define PASS_P4 p.data()
-#define ARGS_V2 const Mf::Vector2& v
+#define ARGS_V2 const moof::vector2& v
#define PASS_V2 v[0], v[1]
-#define ARGS_V3 const Mf::Vector3& v
+#define ARGS_V3 const moof::vector3& v
#define PASS_V3 v[0], v[1], v[2]
-#define ARGS_V4 const Mf::Vector4& v
+#define ARGS_V4 const moof::vector4& v
#define PASS_V4 v[0], v[1], v[2], v[3]
#include <SDL/SDL.h>
-#include "Packet.hh"
+#include "packet.hh"
#ifndef bswap_16
}
-namespace Mf {
+namespace moof {
-Packet::Packet(size_t size) :
- mBuffer((char*)malloc(size)),
- mSize(size),
- mR(0),
- mW(0),
- mOriginalW(0),
- mBoolR(0),
- mBoolW(0),
- mBoolNumR(0),
- mBoolNumW(0) {}
-
-Packet::Packet(const char* data, size_t size) :
- mBuffer((char*)malloc(size)),
- mSize(size),
- mR(0),
- mW(size),
- mOriginalW(size),
- mBoolR(0),
- mBoolW(0),
- mBoolNumR(0),
- mBoolNumW(0)
-{
- if (mBuffer) memcpy(mBuffer, data, size);
+packet::packet(size_t size) :
+ buffer_((char*)malloc(size)),
+ size_(size) {}
+
+packet::packet(const char* data, size_t size) :
+ buffer_((char*)malloc(size)),
+ size_(size),
+ state_(size),
+ saved_(size)
+{
+ if (buffer_) memcpy(buffer_, data, size);
else throw std::length_error("out of memory");
}
-Packet::Packet(const Packet& copy) :
- mBuffer((char*)malloc(copy.mSize)),
- mSize(copy.mSize),
- mR(copy.mR),
- mW(copy.mW),
- mOriginalW(copy.mOriginalW),
- mBoolR(copy.mBoolR),
- mBoolW(copy.mBoolW),
- mBoolNumR(copy.mBoolNumR),
- mBoolNumW(copy.mBoolNumW)
+packet::packet(const packet& copy) :
+ buffer_((char*)malloc(copy.size_)),
+ size_(copy.size_),
+ state_(copy.state_),
+ saved_(copy.saved_)
{
- if (mBuffer) memcpy(mBuffer, copy.mBuffer, mSize);
+ if (buffer_) memcpy(buffer_, copy.buffer_, size_);
else throw std::length_error("out of memory");
}
-Packet& Packet::operator=(const Packet& copy)
+packet& packet::operator = (const packet& copy)
{
- free(mBuffer);
-
- mBuffer = (char*)malloc(copy.mSize);
- mSize = copy.mSize;
- mR = copy.mR;
- mW = copy.mW;
- mOriginalW = copy.mOriginalW;
- mBoolR = copy.mBoolR;
- mBoolW = copy.mBoolW;
- mBoolNumR = copy.mBoolNumR;
- mBoolNumW = copy.mBoolNumW;
- if (mBuffer) memcpy(mBuffer, copy.mBuffer, mSize);
+ free(buffer_);
+ buffer_ = (char*)malloc(copy.size_);
+ size_ = copy.size_;
+ if (buffer_) memcpy(buffer_, copy.buffer_, size_);
else throw std::length_error("out of memory");
+
+ state_ = copy.state_;
+ saved_ = copy.saved_;
return *this;
}
-Packet::~Packet()
+packet::~packet()
{
- free(mBuffer);
+ free(buffer_);
}
-Packet& Packet::operator<<(bool value)
+packet& packet::operator << (bool value)
{
- int bit = mBoolNumW % 8;
+ int bit = state_.write_bool_num % 8;
if (bit == 0)
{
- mBoolW = mW;
+ state_.write_bool_mark = state_.write_mark;
unsigned char byte = 0;
if (write(&byte, 1) == 0) throw std::length_error("out of memory");
}
- if (value) mBuffer[mBoolW] |= (1 << bit);
- ++mBoolNumW;
+ if (value) buffer_[state_.write_bool_mark] |= (1 << bit);
+ ++state_.write_bool_num;
return *this;
}
-Packet& Packet::operator<<(int8_t value)
+packet& packet::operator << (int8_t value)
{
return *this << reinterpret_cast<uint8_t&>(value);
}
-Packet& Packet::operator<<(int16_t value)
+packet& packet::operator << (int16_t value)
{
return *this << reinterpret_cast<uint16_t&>(value);
}
-Packet& Packet::operator<<(int32_t value)
+packet& packet::operator << (int32_t value)
{
return *this << reinterpret_cast<uint32_t&>(value);
}
-Packet& Packet::operator<<(int64_t value)
+packet& packet::operator << (int64_t value)
{
return *this << reinterpret_cast<uint64_t&>(value);
}
-Packet& Packet::operator<<(uint8_t value)
+packet& packet::operator << (uint8_t value)
{
if (write(&value, sizeof(value)) != sizeof(value))
{
return *this;
}
-Packet& Packet::operator<<(uint16_t value)
+packet& packet::operator << (uint16_t value)
{
value = htons(value);
if (write(&value, sizeof(value)) != sizeof(value))
return *this;
}
-Packet& Packet::operator<<(uint32_t value)
+packet& packet::operator << (uint32_t value)
{
value = htonl(value);
if (write(&value, sizeof(value)) != sizeof(value))
return *this;
}
-Packet& Packet::operator<<(uint64_t value)
+packet& packet::operator << (uint64_t value)
{
value = htonll(value);
if (write(&value, sizeof(value)) != sizeof(value))
return *this;
}
-Packet& Packet::operator<<(float value)
+packet& packet::operator << (float value)
{
// XXX: assumes the ieee-754
uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
return *this;
}
-Packet& Packet::operator<<(double value)
+packet& packet::operator << (double value)
{
// XXX: assumes the ieee-754
uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
return *this;
}
-size_t Packet::write(const void* bytes, size_t size)
+size_t packet::write(const void* bytes, size_t size)
{
- size_t nBytes = std::min(size, mSize - mW);
- if (!mBuffer || nBytes < size)
+ size_t num_bytes = std::min(size, size_ - state_.write_mark);
+ if (!buffer_ || num_bytes < size)
{
- int nPages = 1 + size / PAGE_SIZE;
- int newSize = mSize + nPages * PAGE_SIZE;
- char* newBuffer = (char*)realloc(mBuffer, newSize);
- if (newBuffer)
+ int num_pages = 1 + size / PAGE_SIZE;
+ int new_size = size_ + num_pages * PAGE_SIZE;
+ char* new_buffer = (char*)realloc(buffer_, new_size);
+ if (new_buffer)
{
- mBuffer = newBuffer;
- mSize = newSize;
- nBytes = size;
+ buffer_ = new_buffer;
+ size_ = new_size;
+ num_bytes = size;
}
- if (!mBuffer) return 0;
+ if (!buffer_) return 0;
}
- memcpy(mBuffer + mW, bytes, nBytes);
- mW += nBytes;
- return nBytes;
+ memcpy(buffer_ + state_.write_mark, bytes, num_bytes);
+ state_.write_mark += num_bytes;
+ return num_bytes;
}
-Packet& Packet::operator>>(bool& value)
+packet& packet::operator >> (bool& value)
{
- int bit = mBoolNumR % 8;
+ int bit = state_.read_bool_num % 8;
if (bit == 0)
{
- mBoolR = mR;
+ state_.read_bool_mark = state_.read_mark;
unsigned char byte = 0;
if (read(&byte, 1) == 0) throw std::out_of_range("end of packet");
}
- value = 1 & (mBuffer[mBoolR] >> bit);
- ++mBoolNumR;
+ value = 1 & (buffer_[state_.read_bool_mark] >> bit);
+ ++state_.read_bool_num;
return *this;
}
-Packet& Packet::operator>>(int8_t& value)
+packet& packet::operator >> (int8_t& value)
{
return *this >> reinterpret_cast<uint8_t&>(value);
}
-Packet& Packet::operator>>(int16_t& value)
+packet& packet::operator >> (int16_t& value)
{
return *this >> reinterpret_cast<uint16_t&>(value);
}
-Packet& Packet::operator>>(int32_t& value)
+packet& packet::operator >> (int32_t& value)
{
return *this >> reinterpret_cast<uint32_t&>(value);
}
-Packet& Packet::operator>>(int64_t& value)
+packet& packet::operator >> (int64_t& value)
{
return *this >> reinterpret_cast<uint64_t&>(value);
}
-Packet& Packet::operator>>(uint8_t& value)
+packet& packet::operator >> (uint8_t& value)
{
if (read(&value, sizeof(value)) != sizeof(value))
{
return *this;
}
-Packet& Packet::operator>>(uint16_t& value)
+packet& packet::operator >> (uint16_t& value)
{
if (read(&value, sizeof(value)) != sizeof(value))
{
return *this;
}
-Packet& Packet::operator>>(uint32_t& value)
+packet& packet::operator >> (uint32_t& value)
{
if (read(&value, sizeof(value)) != sizeof(value))
{
return *this;
}
-Packet& Packet::operator>>(uint64_t& value)
+packet& packet::operator >> (uint64_t& value)
{
if (read(&value, sizeof(value)) != sizeof(value))
{
return *this;
}
-Packet& Packet::operator>>(float& value)
+packet& packet::operator >> (float& value)
{
// XXX: assumes the ieee-754
uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
return *this;
}
-Packet& Packet::operator>>(double& value)
+packet& packet::operator >> (double& value)
{
// XXX: assumes the ieee-754
uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
return *this;
}
-size_t Packet::read(void* bytes, size_t size)
+size_t packet::read(void* bytes, size_t size)
{
- size_t nBytes = std::min(size, mW - mR);
- memcpy(bytes, mBuffer + mR, nBytes);
- mR += nBytes;
- return nBytes;
+ size_t num_bytes = std::min(size, state_.write_mark - state_.read_mark);
+ memcpy(bytes, buffer_ + state_.read_mark, num_bytes);
+ state_.read_mark += num_bytes;
+ return num_bytes;
}
-void Packet::clear()
+void packet::clear()
{
- mR = 0;
- mW = 0;
- mBoolR = 0;
- mBoolW = 0;
- mBoolNumR = 0;
- mBoolNumW = 0;
+ state_.read_mark = state_.write_mark;
+ state_.read_bool_mark = 0;
+ state_.read_bool_num = 0;
+ state_.write_bool_mark = 0;
+ state_.write_bool_num = 0;
}
-void Packet::reset()
+void packet::save()
+{
+ saved_ = state_;
+}
+
+void packet::revert()
{
- mR = 0;
- mW = mOriginalW;
- mBoolR = 0;
- mBoolW = 0;
- mBoolNumR = 0;
- mBoolNumW = 0;
+ state_ = saved_;
}
-} // namespace Mf
+} // namespace moof
*
**************************************************************************/
+#ifndef _MOOF_PACKET_HH_
+#define _MOOF_PACKET_HH_
+
/**
- * \file Packet.hh
+ * \file packet.hh
* Classes for building and interpreting datagram packets.
*/
-#ifndef _MOOF_PACKET_HH_
-#define _MOOF_PACKET_HH_
-
#include <cstring>
#include <stdexcept>
#include <string>
#endif
-namespace Mf {
+namespace moof {
/**
* handles endian differences by serializing variables in network byte
* order (big endian).
*/
-class Packet
+class packet
{
public:
* Construct a packet with an initial capacity.
* \param capacity Initial capacity of the packet.
*/
- explicit Packet(size_t size = PAGE_SIZE);
+ explicit packet(size_t size = PAGE_SIZE);
/**
* Construct a packet with some bytes from a buffer. The bytes will be
* \param data The bytes.
* \param size The number of bytes.
*/
- Packet(const char* data, size_t size);
+ packet(const char* data, size_t size);
/**
* Insert a variable into the packet, serializing it. This usually
* \param value The value to insert.
* \return This.
*/
- Packet& operator<<(bool value);
- Packet& operator<<(int8_t value);
- Packet& operator<<(int16_t value);
- Packet& operator<<(int32_t value);
- Packet& operator<<(int64_t value);
- Packet& operator<<(uint8_t value);
- Packet& operator<<(uint16_t value);
- Packet& operator<<(uint32_t value);
- Packet& operator<<(uint64_t value);
- Packet& operator<<(float value);
- Packet& operator<<(double value);
+ packet& operator << (bool value);
+ packet& operator << (int8_t value);
+ packet& operator << (int16_t value);
+ packet& operator << (int32_t value);
+ packet& operator << (int64_t value);
+ packet& operator << (uint8_t value);
+ packet& operator << (uint16_t value);
+ packet& operator << (uint32_t value);
+ packet& operator << (uint64_t value);
+ packet& operator << (float value);
+ packet& operator << (double value);
/**
* Write some bytes to the packet.
* \param value Reference to the variable to extract.
* \return This.
*/
- Packet& operator>>(bool& value);
- Packet& operator>>(int8_t& value);
- Packet& operator>>(int16_t& value);
- Packet& operator>>(int32_t& value);
- Packet& operator>>(int64_t& value);
- Packet& operator>>(uint8_t& value);
- Packet& operator>>(uint16_t& value);
- Packet& operator>>(uint32_t& value);
- Packet& operator>>(uint64_t& value);
- Packet& operator>>(float& value);
- Packet& operator>>(double& value);
+ packet& operator >> (bool& value);
+ packet& operator >> (int8_t& value);
+ packet& operator >> (int16_t& value);
+ packet& operator >> (int32_t& value);
+ packet& operator >> (int64_t& value);
+ packet& operator >> (uint8_t& value);
+ packet& operator >> (uint16_t& value);
+ packet& operator >> (uint32_t& value);
+ packet& operator >> (uint64_t& value);
+ packet& operator >> (float& value);
+ packet& operator >> (double& value);
/**
* Read some bytes from the packet.
/**
- * Reset the read/write markers to their initial positions, putting the
- * packet in the state it was at right after construction.
+ * Save the current state internally, allowing it to be reverted to
+ * later using revert().
*/
- void reset();
+ void save();
+
+ /**
+ * Revert the packet to a previously saved state, or to that state
+ * immediately after construction if none other state has been
+ * explicitly saved using save().
+ */
+ void revert();
/**
*/
const char* bytes() const
{
- return mBuffer + mR;
+ return buffer_ + state_.read_mark;
}
/**
*/
size_t size() const
{
- return mW - mR;
+ return state_.write_mark - state_.read_mark;
}
// The rest of this stuff is just to implement correct copy semantics.
- Packet(const Packet& copy);
- Packet& operator=(const Packet& copy);
- ~Packet();
+ packet(const packet& copy);
+ packet& operator = (const packet& copy);
+ ~packet();
private:
- char* mBuffer;
- size_t mSize;
+ char* buffer_;
+ size_t size_;
- size_t mR;
- size_t mW;
- size_t mOriginalW;
-
- size_t mBoolR;
- size_t mBoolW;
- size_t mBoolNumR;
- size_t mBoolNumW;
+ struct state
+ {
+ size_t read_mark;
+ size_t read_bool_mark;
+ size_t read_bool_num;
+ size_t write_mark;
+ size_t write_bool_mark;
+ size_t write_bool_num;
+
+ state(size_t size = 0) :
+ read_mark(0),
+ read_bool_mark(0),
+ read_bool_num(0),
+ write_mark(size),
+ write_bool_mark(0),
+ write_bool_num(0) {}
+ };
+
+ state state_;
+ state saved_;
};
-inline Packet& operator<<(Packet& packet, const char* value)
+template <class T>
+inline packet& operator << (packet& packet, const T& value)
+{
+ value.pack(packet);
+ return packet;
+}
+
+template <class T>
+inline packet& operator >> (packet& packet, T& value)
+{
+ value.unpack(packet);
+ return packet;
+}
+
+
+inline packet& operator << (packet& packet, const char* value)
{
uint16_t length = strlen(value);
packet << length;
}
template <class T>
-inline Packet& operator<<(Packet& packet, const std::basic_string<T>& value)
+inline packet& operator << (packet& packet, const std::basic_string<T>& value)
{
packet << static_cast<uint16_t>(value.length());
- size_t numBytes = value.length() * sizeof(T);
- if (packet.write(value.data(), numBytes) != numBytes)
+ size_t num_bytes = value.length() * sizeof(T);
+ if (packet.write(value.data(), num_bytes) != num_bytes)
{
throw std::length_error("out of memory");
}
}
template <class T>
-inline Packet& operator>>(Packet& packet, std::basic_string<T>& value)
+inline packet& operator >> (packet& packet, std::basic_string<T>& value)
{
uint16_t length = 0;
packet >> length;
T str[length];
- size_t numBytes = length * sizeof(T);
- if (packet.read(str, numBytes) != numBytes)
+ size_t num_bytes = length * sizeof(T);
+ if (packet.read(str, num_bytes) != num_bytes)
{
throw std::out_of_range("end of packet");
}
template <class T>
-inline Packet& operator<<(Packet& packet, const std::vector<T>& value)
+inline packet& operator << (packet& packet, const std::vector<T>& value)
{
packet << static_cast<uint16_t>(value.size());
typename std::vector<T>::const_iterator it;
}
template <class T>
-inline Packet& operator>>(Packet& packet, std::vector<T>& value)
+inline packet& operator >> (packet& packet, std::vector<T>& value)
{
uint16_t size = 0;
packet >> size;
}
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_PACKET_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include "aabb.hh"
+#include "plane.hh"
+#include "sphere.hh"
+
+
+namespace moof {
+
+
+plane::halfspace plane::intersects(const aabb<3>& aabb) const
+{
+ vector3 corners[8];
+ int nPositive = 8;
+
+ aabb.get_corners(corners);
+
+ for (int i = 0; i < 8; ++i)
+ {
+ if (intersects(corners[i]) == negative)
+ {
+ --nPositive;
+ }
+ }
+
+ if (nPositive == 0) return negative;
+ else if (nPositive == 8) return positive;
+ else return intersecting;
+}
+
+plane::halfspace plane::intersects(const sphere<3>& sphere) const
+{
+ scalar distance = distance_to_point(sphere.point);
+
+ if (distance < -sphere.radius) return negative;
+ else if (distance < sphere.radius) return intersecting;
+ else return positive;
+}
+
+
+} // namespace moof
+
#ifndef _MOOF_PLANE_HH_
#define _MOOF_PLANE_HH_
-#include <Moof/Math.hh>
-#include <Moof/Shape.hh>
+/**
+ * \file plane.hh
+ * Classes and functions related to planes.
+ */
+
+#include <moof/math.hh>
+#include <moof/shape.hh>
-namespace Mf {
+namespace moof {
-template <int D> class Aabb;
-template <int D> class Sphere;
+template <int D> class aabb;
+template <int D> class sphere;
-/*
+/**
* A plane in 3-space defined by the equation Ax + By + Cz = D, where [A,
* B, C] is normal to the plane.
*/
-
-struct Plane : public Shape<3>
+struct plane : public shape<3>
{
- Vector3 normal;
- Scalar d;
+ vector3 normal;
+ scalar d;
- typedef enum
+ enum halfspace
{
- NEGATIVE = -1,
- INTERSECT = 0,
- POSITIVE = 1
- } Halfspace;
+ negative = -1,
+ intersecting = 0,
+ positive = 1
+ };
- Plane() {}
- Plane(const Vector3& vector, Scalar scalar) :
+ plane() {}
+ plane(const vector3& vector, scalar scalar) :
normal(vector),
d(scalar) {}
- Plane(Scalar a, Scalar b, Scalar c, Scalar scalar) :
+ plane(scalar a, scalar b, scalar c, scalar scalar) :
normal(a, b, c),
d(scalar) {}
- bool intersectRay(const Ray<3>& ray, Ray<3>::Contact& hit)
+ bool intersect_ray(const ray<3>& ray, ray<3>::contact& hit)
{
// solve: [(ray.point + t*ray.direction) dot normal] + d = 0
- Scalar denom = cml::dot(ray.direction, normal);
+ scalar denom = dot(ray.direction, normal);
// check for parallel condition
if (denom == SCALAR(0.0))
{
- if (isEqual(cml::dot(ray.point, normal), -d))
+ if (is_equal(dot(ray.point, normal), -d))
{
// the ray lies on the plane
hit.distance = SCALAR(0.0);
return false;
}
- Scalar numer = cml::dot(ray.point, normal) + d;
+ scalar numer = dot(ray.point, normal) + d;
hit.distance = -numer / denom;
if (hit.distance < SCALAR(0.0)) return false;
*/
void normalize()
{
- Scalar mag = normal.length();
+ scalar mag = normal.length();
normal /= mag;
d /= mag;
/**
* Determine the shortest distance between a point and the plane.
*/
- Scalar getDistanceToPoint(const Vector3& point) const
+ scalar distance_to_point(const vector3& point) const
{
- return cml::dot(point, normal) + d;
+ return dot(point, normal) + d;
}
- Halfspace intersects(const Vector3& point) const
+ halfspace intersects(const vector3& point) const
{
- Scalar distance = getDistanceToPoint(point);
+ scalar distance = distance_to_point(point);
- if (isEqual(distance, 0.0)) return INTERSECT;
- else if (distance < 0.0) return NEGATIVE;
- else return POSITIVE;
+ if (is_equal(distance, 0.0)) return intersecting;
+ else if (distance < 0.0) return negative;
+ else return positive;
}
- Halfspace intersects(const Aabb<3>& aabb) const;
- Halfspace intersects(const Sphere<3>& sphere) const;
+ halfspace intersects(const aabb<3>& aabb) const;
+ halfspace intersects(const sphere<3>& sphere) const;
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_PLANE_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_RAY_HH_
+#define _MOOF_RAY_HH_
+
+/**
+ * \file ray.hh
+ * A class for lines that start at one point and go to infinity in some
+ * direction.
+ */
+
+#include <moof/drawable.hh>
+#include <moof/math.hh>
+#include <moof/opengl.hh>
+#include <moof/texture.hh>
+
+
+namespace moof {
+
+
+/**
+ * A line that goes to infinity.
+ */
+template <int D>
+struct ray : public drawable
+{
+ typedef moof::vector< scalar, fixed<D> > vector;
+
+ // solution = point + t*direction
+ vector point;
+ vector direction;
+
+ struct contact
+ {
+ scalar distance; // distance from the origin to the nearest point
+ vector normal; // surface normal at contact point
+
+ bool operator < (const contact& rhs)
+ {
+ return distance < rhs.distance;
+ }
+ };
+
+ void solve(vector& p, scalar t) const
+ {
+ p = point + t*direction;
+ }
+
+ void draw(scalar alpha = 0.0) const
+ {
+ vector end = point + 1000.0 * direction;
+ // FIXME: this is kinda cheesy
+
+ moof::texture::reset_binding();
+ glBegin(GL_LINES);
+ glVertex(point);
+ glVertex(end);
+ glEnd();
+ }
+
+ void normalize()
+ {
+ direction.normalize();
+ }
+};
+
+
+typedef ray<2> ray2;
+typedef ray<3> ray3;
+
+
+} // namespace moof
+
+#endif // _MOOF_RAY_HH_
+
#include <boost/algorithm/string.hpp>
-#include "Log.hh"
-#include "Resource.hh"
+#include "log.hh"
+#include "resource.hh"
-namespace Mf {
+namespace moof {
// static member
-std::vector<std::string> Resource::gSearchPaths;
+std::vector<std::string> resource::search_paths_;
-void Resource::addSearchPaths(const std::string& paths)
+void resource::add_search_paths(const std::string& paths)
{
std::vector<std::string> pathList;
boost::split(pathList, paths, boost::is_any_of(":"));
- addSearchPaths(pathList);
+ add_search_paths(pathList);
}
-void Resource::addSearchPaths(const std::vector<std::string>& pathList)
+void resource::add_search_paths(const std::vector<std::string>& pathList)
{
std::vector<std::string>::const_iterator it;
for (it = pathList.begin(); it != pathList.end(); ++it)
boost::replace_all(path, "/", "\\");
#endif
- gSearchPaths.push_back(path);
- logInfo << "added search path " << path << std::endl;
+ search_paths_.push_back(path);
+ log_info << "added search path " << path << std::endl;
}
}
-std::string Resource::getPath(const std::string& path,
- const std::string& prefix,
- const std::string& extension)
-{
- std::string realPath(path);
- if (getPath(realPath, prefix, extension)) return realPath;
-
- return std::string();
-}
-
-bool Resource::getPath(std::string& path,
+bool resource::find_path(std::string& path,
const std::string& prefix,
const std::string& extension)
{
- FILE* file = openFile(path, prefix, extension);
+ FILE* file = open_file(path, prefix, extension);
if (file)
{
fclose(file);
return false;
}
-FILE* Resource::openFile(std::string& path,
- std::string prefix,
+FILE* resource::open_file(std::string& path,
+ const std::string& prefix,
const std::string& extension,
const std::string& mode)
{
#if defined(_WIN32)
- // Windows always has to be the odd one.
+ // windows always has to be a little different
boost::replace_all(path, "/", "\\");
- boost::replace_all(prefix, "/", "\\");
-#endif
-
+ std::string temp_prefix(prefix);
+ boost::replace_all(temp_prefix, "/", "\\");
+ std::vector<std::string> preList;
+ boost::split(preList, temp_prefix, boost::is_any_of(":"));
+#else
std::vector<std::string> preList;
boost::split(preList, prefix, boost::is_any_of(":"));
+#endif
+
std::vector<std::string> postList;
boost::split(postList, extension, boost::is_any_of(":"));
std::vector<std::string>::iterator it;
- for (it = gSearchPaths.begin(); it != gSearchPaths.end(); ++it)
+ for (it = search_paths_.begin(); it != search_paths_.end(); ++it)
{
std::vector<std::string>::iterator jt;
for (jt = preList.begin(); jt != preList.end(); ++jt)
}
-} // namespace Mf
+} // namespace moof
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_RESOURCE_HH_
+#define _MOOF_RESOURCE_HH_
+
+/**
+ * \file resource.hh
+ * Interface for textures, sounds, and other types of resources.
+ */
+
+#include <cstdio>
+#include <string>
+#include <vector>
+
+
+namespace moof {
+
+
+/**
+ * Generic resource class.
+ */
+
+class resource
+{
+public:
+
+ virtual ~resource() {}
+
+
+ /**
+ * Add a directory to search when looking for resource files.
+ * \param paths A colon-separated list of directory paths.
+ */
+ static void add_search_paths(const std::string& paths);
+
+ /**
+ * Add directories to search when looking for resource files.
+ * \param pathList The list of directory paths.
+ */
+ static void add_search_paths(const std::vector<std::string>& pathList);
+
+
+ /**
+ * Get the path to a resource of a given name.
+ * \param path The name of the resource to find. Upon successful
+ * return, this is changed to an absolute path to the resource.
+ * \param prefix A colon-separated list of subdirectories to search.
+ * \param extension A colon-separated list of possible extensions.
+ * \return True if a path to a resource was found, false otherwise.
+ */
+ static bool find_path(std::string& path,
+ const std::string& prefix = "",
+ const std::string& extension = "");
+
+ /**
+ * Get the path to a resource of a given name and open it if a resource
+ * was found.
+ * \param path The name of the resource to find. Upon successful
+ * return, this is changed to an absolute path to the resource.
+ * \param prefix A colon-separated list of subdirectories to search.
+ * \param extension A colon-separated list of possible extensions.
+ * \param mode The open mode.
+ * \return The FILE* if the resource was found, 0 otherwise.
+ */
+ static FILE* open_file(std::string& path,
+ const std::string& prefix = "",
+ const std::string& extension = "",
+ const std::string& mode = "rb");
+
+
+private:
+
+ static std::vector<std::string> search_paths_;
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_RESOURCE_HH_
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_RIGID_BODY_HH_
+#define _MOOF_RIGID_BODY_HH_
+
+/**
+ * \file rigid_body.hh
+ * Classes and functions for simulating rigid body physics.
+ */
+
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
+#include <moof/entity.hh>
+#include <moof/math.hh>
+
+
+namespace moof {
+
+
+template <int D = 3>
+struct linear_state
+{
+ typedef moof::vector< scalar, fixed<D> > vector;
+ typedef boost::function<const vector& (const linear_state&)>
+ force_function;
+
+ // primary
+
+ vector position;
+ vector momentum;
+
+ // secondary
+
+ vector velocity;
+
+ // user
+
+ vector force;
+ std::vector<force_function> forces;
+
+ // constant
+
+ scalar mass;
+ scalar inverse_mass;
+
+
+ void recalculate()
+ {
+ velocity = momentum * inverse_mass;
+ }
+
+
+ struct gravity_force
+ {
+ explicit gravity_force(scalar a = -9.8)
+ {
+ force.zero();
+ acceleration = a;
+ }
+
+ const vector& operator () (const linear_state& state)
+ {
+ force[1] = state.mass * acceleration;
+ return force;
+ }
+
+
+ private:
+
+ vector force;
+ scalar acceleration;
+ };
+
+
+ void init()
+ {
+ position.zero();
+ momentum.zero();
+
+ velocity.zero();
+
+ force.zero();
+ forces.clear();
+
+ mass = SCALAR(1.0);
+ inverse_mass = 1.0 / mass;
+ }
+
+
+ struct derivative
+ {
+ vector velocity;
+ vector force;
+
+ derivative operator * (scalar dt) const
+ {
+ derivative derivative;
+ derivative.velocity = dt * velocity;
+ derivative.force = dt * force;
+ return derivative;
+ }
+
+ derivative operator + (const derivative& other) const
+ {
+ derivative derivative;
+ derivative.velocity = velocity + other.velocity;
+ derivative.force = force + other.force;
+ return derivative;
+ }
+ };
+
+
+ vector total_force() const
+ {
+ vector f(force);
+
+ for (size_t i = 0; i < forces.size(); ++i)
+ {
+ f += forces[i](*this);
+ }
+
+ return f;
+ }
+
+ void calculate_derivative(derivative& derivative, scalar t) const
+ {
+ derivative.velocity = velocity;
+ derivative.force = total_force();
+ }
+
+ void step(const derivative& derivative, scalar dt)
+ {
+ position += dt * derivative.velocity;
+ momentum += dt * derivative.force;
+ recalculate();
+ }
+};
+
+
+struct rotational_state2
+{
+ // primary
+
+ scalar orientation;
+ scalar angular_momentum;
+
+ // secondary
+
+ scalar angularVelocity;
+
+ // constant
+
+ scalar inertia;
+ scalar inverse_inertia;
+
+
+ void recalculate()
+ {
+ angularVelocity = angular_momentum * inertia;
+ }
+
+
+ struct derivative
+ {
+ scalar angularVelocity;
+ scalar torque;
+ };
+
+ void step(const derivative& derivative, scalar dt)
+ {
+ orientation += dt * derivative.angularVelocity;
+ angular_momentum += dt * derivative.torque;
+ recalculate();
+ }
+};
+
+struct rotational_state3
+{
+ // primary
+
+ quaternion orientation;
+ vector3 angular_momentum;
+
+ // secondary
+
+ quaternion spin;
+ vector3 angularVelocity;
+
+ // constant
+
+ scalar inertia;
+ scalar inverse_inertia;
+
+
+ void recalculate()
+ {
+ angularVelocity = angular_momentum * inertia;
+ }
+};
+
+
+struct state2 : public linear_state<2>, public rotational_state2
+{
+ void recalculate()
+ {
+ linear_state<2>::recalculate();
+ rotational_state2::recalculate();
+ }
+
+ void update(scalar t, scalar dt)
+ {
+ rk4<linear_state<2>,linear_state<2>::derivative>(*this, t, dt);
+ }
+};
+
+struct state3 : public linear_state<3>, public rotational_state3
+{
+ void recalculate()
+ {
+ linear_state<3>::recalculate();
+ rotational_state3::recalculate();
+ }
+
+ void update(scalar t, scalar dt)
+ {
+ rk4<linear_state<3>,linear_state<3>::derivative>(*this, t, dt);
+ }
+};
+
+
+template <class T>
+inline T interpolate(const T& a, const T& b, scalar alpha)
+{
+ return lerp(a, b, alpha);
+}
+
+template <>
+inline state2 interpolate<state2>(const state2& a, const state2& b,
+ scalar alpha)
+{
+ state2 state(b);
+ state.position = interpolate(a.position, b.position, alpha);
+ state.momentum = interpolate(a.momentum, b.momentum, alpha);
+ state.orientation = interpolate(a.orientation, b.orientation, alpha);
+ state.angular_momentum = interpolate(a.angular_momentum,
+ b.angular_momentum, alpha);
+ return state;
+}
+
+template <>
+inline state3 interpolate<state3>(const state3& a, const state3& b,
+ scalar alpha)
+{
+ state3 state(b);
+ state.position = interpolate(a.position, b.position, alpha);
+ state.momentum = interpolate(a.momentum, b.momentum, alpha);
+ state.orientation = slerp(a.orientation, b.orientation, alpha);
+ state.angular_momentum = interpolate(a.angular_momentum,
+ b.angular_momentum, alpha);
+ return state;
+}
+
+
+
+/**
+ * Interface for anything that can move.
+ */
+
+template <class T>
+class rigid_body : public entity
+{
+protected:
+
+ T state_;
+ T prev_state_;
+
+public:
+
+ virtual ~rigid_body() {}
+
+ virtual void update(scalar t, scalar dt)
+ {
+ prev_state_ = state_;
+ state_.update(t, dt);
+ }
+
+ const T& state() const
+ {
+ return state_;
+ }
+
+ T state(scalar alpha) const
+ {
+ return interpolate(prev_state_, state_, alpha);
+ }
+
+ const T& getLastState() const
+ {
+ return prev_state_;
+ }
+};
+
+typedef rigid_body<state2> rigid_body2;
+typedef rigid_body<state3> rigid_body3;
+
+
+} // namespace moof
+
+#endif // _MOOF_RIGID_BODY_HH_
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_SCRIPT_HH_
+#define _MOOF_SCRIPT_HH_
+
+/**
+ * \file script.hh
+ * A thin wrapper over Lua. This is not meant as a complicated binding
+ * package between C++ and Lua. It is not meant to obscure the division
+ * between C++ and Lua but rather to clarify it and make it more
+ * manageable. It does not hide the concept of the Lua stack, but rather
+ * provides that mechanism with a certain level of abstraction while also
+ * providing a cleaner, more consistent API.
+ */
+
+#include <iostream>
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <lua.hpp>
+
+
+namespace moof {
+
+
+class script;
+typedef boost::shared_ptr<script> script_ptr;
+
+
+class script
+{
+public:
+
+ typedef boost::function<int(script&)> function;
+
+ enum status
+ {
+ success = 0,
+ yielding = LUA_YIELD,
+ runtime_error = LUA_ERRRUN,
+ syntax_error = LUA_ERRSYNTAX,
+ memory_error = LUA_ERRMEM,
+ handler_error = LUA_ERRERR,
+ file_error = LUA_ERRFILE
+ };
+
+ enum pseudoindex
+ {
+ registry_index = LUA_REGISTRYINDEX,
+ environment_index = LUA_ENVIRONINDEX,
+ globals_index = LUA_GLOBALSINDEX
+ };
+
+ /**
+ * This is the most prominent abstraction on top of the standard Lua
+ * API. A slot object represents a value on the stack. More
+ * specifically, it represents a position on the stack. The
+ * distinction is only important when objects are moved around on the
+ * stack or if the slot represents a negative index on the stack (the
+ * value of which will change as things are pushed onto and popped from
+ * the stack).
+ */
+
+ struct slot
+ {
+ /**
+ * You have direct access to the index of the value on the stack
+ * being represented.
+ */
+
+ int index;
+
+
+ enum type
+ {
+ none = LUA_TNONE,
+ nil = LUA_TNIL,
+ boolean = LUA_TBOOLEAN,
+ light_data = LUA_TLIGHTUSERDATA,
+ number = LUA_TNUMBER,
+ string = LUA_TSTRING,
+ table = LUA_TTABLE,
+ function = LUA_TFUNCTION,
+ data = LUA_TUSERDATA,
+ thread = LUA_TTHREAD
+ };
+
+
+ slot(const class script& s, int i = 0) :
+ index(i),
+ script_(const_cast<class script&>(s)) {}
+
+ /**
+ * A copied value presently points to the same value, except the
+ * real index is used. That means that if a value that refers to a
+ * frame referenced from the top of the stack will have its
+ * normalized index copied into the new value object.
+ */
+
+ //slot(const slot& copy) :
+ //index(copy.positiveIndex()),
+ //script_(copy.script_) {}
+
+
+ // check the type of the value
+ bool is_boolean() const
+ { return (bool)lua_isboolean(script_.state_, index); }
+ bool is_imported_function() const
+ { return (bool)lua_iscfunction(script_.state_, index); }
+ bool is_function() const
+ { return (bool)lua_isfunction(script_.state_, index); }
+ bool is_nil() const
+ { return (bool)lua_isnil(script_.state_, index); }
+ bool is_none() const
+ { return (bool)lua_isnone(script_.state_, index); }
+ bool is_none_or_nil() const
+ { return (bool)lua_isnoneornil(script_.state_, index); }
+ bool is_number() const
+ { return (bool)lua_isnumber(script_.state_, index); }
+ bool is_string() const
+ { return (bool)lua_isstring(script_.state_, index); }
+ bool is_table() const
+ { return (bool)lua_istable(script_.state_, index); }
+ bool is_thread() const
+ { return (bool)lua_isthread(script_.state_, index); }
+ bool is_data() const
+ { return (bool)lua_isuserdata(script_.state_, index); }
+ bool is_light_data() const
+ { return (bool)lua_islightuserdata(script_.state_, index); }
+
+ /**
+ * Check the value and throw an error if its the wrong type.
+ * There's a little caveat: This method never returns because it
+ * does a long jump. Consequently, constructed C++ objects which
+ * exist on the stack between the current frame and some lua
+ * function will not be destructed. That's not a problem for
+ * objects that only exist on the stack, but any objects that
+ * allocate memory on the heap (such as containers or strings) will
+ * leak. Therefore, you should only call this method after
+ * cleaning up such objects. The best thing to do for defining
+ * functions is to simply check all the parameters at the get-go
+ * before any C++ objects are even constructed.
+ */
+
+ void require_type(type t) const
+ {
+ if (t != type())
+ {
+ luaL_typerror(script_.state_, index,
+ lua_typename(script_.state_, t));
+ }
+ }
+
+ void raise(const char* error)
+ {
+ luaL_argerror(script_.state_, index, error);
+ }
+
+
+ slot& require_boolean()
+ {
+ if (!is_boolean())
+ {
+ luaL_typerror(script_.state_, index, "boolean");
+ }
+ return *this;
+ }
+ slot& require_number()
+ {
+ if (!is_number())
+ {
+ luaL_typerror(script_.state_, index, "number");
+ }
+ return *this;
+ }
+ slot& require_string()
+ {
+ if (!is_string())
+ {
+ luaL_typerror(script_.state_, index, "string");
+ }
+ return *this;
+ }
+ slot& require_table()
+ {
+ if (!is_table())
+ {
+ luaL_typerror(script_.state_, index, "table");
+ }
+ return *this;
+ }
+ slot& require_function()
+ {
+ if (!is_function())
+ {
+ luaL_typerror(script_.state_, index, "function");
+ }
+ return *this;
+ }
+ slot& require_data()
+ {
+ if (!is_data())
+ {
+ luaL_typerror(script_.state_, index, "data");
+ }
+ return *this;
+ }
+ slot& require_nil()
+ {
+ if (!is_nil())
+ {
+ luaL_typerror(script_.state_, index, "nil");
+ }
+ return *this;
+ }
+ slot& require_thread()
+ {
+ if (!is_thread())
+ {
+ luaL_typerror(script_.state_, index, "thread");
+ }
+ return *this;
+ }
+
+
+ /**
+ * Get the type of the value.
+ */
+
+ enum type type() const
+ {
+ return (enum type)lua_type(script_.state_, index);
+ }
+
+ /**
+ * Get the name of the type of the value as a string.
+ */
+
+ std::string type_name() const
+ {
+ return std::string(luaL_typename(script_.state_, index));
+ }
+
+
+ /**
+ * Get the length of the value according to the definition given by
+ * Lua.
+ */
+
+ size_t length() const
+ {
+ return lua_objlen(script_.state_, index);
+ }
+
+ int positiveIndex() const
+ {
+ if (index < 0) return index + lua_gettop(script_.state_) + 1;
+ else return index;
+ }
+
+
+ /**
+ * Get a pointer value (for userdata, tables, threads, and
+ * functions).
+ */
+
+ const void* id() const
+ {
+ return lua_topointer(script_.state_, index);
+ }
+
+ bool is_identical(const slot& rhs) const
+ {
+ return &script_ == &(rhs.script_) && index == rhs.index;
+ }
+
+ operator bool () const
+ {
+ return !is_none();
+ }
+
+
+ bool operator == (const slot& rhs) const
+ {
+ return (bool)lua_equal(script_.state_, index, rhs.index);
+ }
+ bool operator != (const slot& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ bool operator < (const slot& rhs) const
+ {
+ return (bool)lua_lessthan(script_.state_, index, rhs.index);
+ }
+ bool operator <= (const slot& rhs) const
+ {
+ return *this < rhs || *this == rhs;
+ }
+ bool operator > (const slot& rhs) const
+ {
+ return !(*this <= rhs);
+ }
+ bool operator >= (const slot& rhs) const
+ {
+ return !(*this < rhs);
+ }
+
+
+ /**
+ * Convert the underlying value to a C++ type.
+ */
+
+ template <class T>
+ bool get(T& value) const
+ {
+ if (is_number())
+ {
+ value = (T)lua_tointeger(script_.state_, index);
+ return true;
+ }
+ return false;
+ }
+
+ bool get(float& value) const
+ {
+ if (is_number())
+ {
+ value = (float)lua_tonumber(script_.state_, index);
+ return true;
+ }
+ return false;
+ }
+ bool get(double& value) const
+ {
+ if (is_number())
+ {
+ value = (double)lua_tonumber(script_.state_, index);
+ return true;
+ }
+ return false;
+ }
+
+ bool get(bool& value) const
+ {
+ if (is_boolean())
+ {
+ value = (bool)lua_toboolean(script_.state_, index);
+ return true;
+ }
+ return false;
+ }
+
+ bool get(const char*& value, size_t& size) const
+ {
+ if (is_string())
+ {
+ value = lua_tolstring(script_.state_, index, &size);
+ return true;
+ }
+ return false;
+ }
+
+ bool get(std::string& value) const
+ {
+ const char* str;
+ size_t size;
+ if (get(str, size))
+ {
+ value.assign(str, size);
+ return true;
+ }
+ return false;
+ }
+
+ bool get(void*& value) const
+ {
+ if (is_data())
+ {
+ value = lua_touserdata(script_.state_, index);
+ return true;
+ }
+ return false;
+ }
+
+ template <class T>
+ bool get(std::vector<T>& array) const
+ {
+ if (!is_table()) return false;
+
+ array.clear();
+
+ slot value = script_[-1];
+ int realIndex = positiveIndex();
+
+ bool done = false;
+ for (int i = 1; !done; ++i)
+ {
+ lua_rawgeti(script_.state_, realIndex, i);
+
+ T v;
+ if (value.get(v)) array.push_back(v);
+ else done = true;
+
+ script_.pop();
+ }
+
+ return true;
+ }
+
+ template <class T>
+ bool get(std::map<std::string,T>& dictionary) const
+ {
+ if (!is_table()) return false;
+
+ dictionary.clear();
+
+ slot key = script_[-2];
+ slot value = script_[-1];
+ int realIndex = positiveIndex();
+
+ script_.push_nil();
+ while (lua_next(script_.state_, realIndex) != 0)
+ {
+ std::string k;
+ if (!key.is_number() && key.get(k))
+ {
+ T v;
+ if (value.get(v)) dictionary[k] = v;
+ }
+ script_.pop();
+ }
+ script_.pop();
+
+ return true;
+ }
+
+ /**
+ * Get the value of a field from the table.
+ */
+
+ template <class T, class V>
+ bool get(T& value, V field) const
+ {
+ bool ret = push_field(field).get(value);
+ script_.pop();
+ return ret;
+ }
+
+
+ template <class T, class V>
+ void set_field(T field, V value)
+ {
+ script_.push(field);
+ script_.push(value);
+ set_field();
+ }
+
+ void set_field()
+ {
+ lua_settable(script_.state_, index);
+ }
+
+
+ template <class T>
+ void set_field(const std::string& field, T value)
+ {
+ set_field(field.c_str(), value);
+ }
+ template <class T>
+ void set_field(const char* field, T value)
+ {
+ script_.push(value);
+ lua_setfield(script_.state_, index, field);
+ }
+
+
+ /**
+ * This set method, as opposed to the others, sets the value of the
+ * actual slot. The others set table values.
+ */
+ template <class T>
+ void set(T value)
+ {
+ script_.push(value);
+ replace();
+ }
+
+ void set()
+ {
+ replace();
+ }
+
+
+ /**
+ * Replace this value with the value at the top of the stack.
+ */
+
+ void replace()
+ {
+ lua_replace(script_.state_, index);
+ }
+
+ void remove()
+ {
+ lua_remove(script_.state_, index);
+ }
+
+ void pop()
+ {
+ // removes this slot, taking with it everything above it
+ script_.pop(script_.stack_size() - index + 1);
+ }
+
+ /**
+ * Inserts the top-most value on the stack at position index,
+ * shifting other values as needed.
+ */
+
+ void insert_top_here()
+ {
+ lua_insert(script_.state_, index);
+ }
+
+
+ /**
+ * Copy the value and push the copy to the stack.
+ */
+
+ slot push_copy() const
+ {
+ lua_pushvalue(script_.state_, index);
+ return script_.top();
+ }
+
+ slot push_metatable() const
+ {
+ lua_getmetatable(script_.state_, index);
+ return script_.top();
+ }
+
+ slot push_environment() const
+ {
+ lua_getfenv(script_.state_, index);
+ return script_.top();
+ }
+
+
+ slot push_field() const
+ {
+ lua_gettable(script_.state_, index);
+ return script_.top();
+ }
+
+ template <class T>
+ slot push_field(T index) const
+ {
+ script_.push(index);
+ return push_field();
+ }
+
+ slot push_field(const std::string& name) const
+ {
+ return push_field(name.c_str());
+ }
+ slot push_field(const char* name) const
+ {
+ lua_getfield(script_.state_, index, name);
+ return script_.top();
+ }
+
+
+ class script& script()
+ {
+ return script_;
+ }
+
+ const class script& script() const
+ {
+ return script_;
+ }
+
+
+ private:
+
+ class script& script_;
+ };
+
+
+ script() :
+ state_(0)
+ {
+ reset();
+ }
+
+ ~script()
+ {
+ destroy();
+ }
+
+
+ static script_ptr alloc()
+ {
+ return script_ptr(new script);
+ }
+
+ void reset()
+ {
+ if (state_) destroy();
+ state_ = luaL_newstate();
+ registry().set_field("Script_hh_Object", (void*)this);
+ }
+
+
+ void import_standard_libraries()
+ {
+ luaL_openlibs(state_);
+ }
+
+ void import_base_library()
+ {
+ lua_pushcfunction(state_, luaopen_base);
+ push(LUA_COLIBNAME);
+ call(1, 0);
+ }
+
+ void import_package_library()
+ {
+ lua_pushcfunction(state_, luaopen_package);
+ push(LUA_LOADLIBNAME);
+ call(1, 0);
+ }
+
+ void import_string_library()
+ {
+ lua_pushcfunction(state_, luaopen_string);
+ push(LUA_STRLIBNAME);
+ call(1, 0);
+ }
+
+ void import_table_library()
+ {
+ lua_pushcfunction(state_, luaopen_table);
+ push(LUA_TABLIBNAME);
+ call(1, 0);
+ }
+
+ void import_math_library()
+ {
+ lua_pushcfunction(state_, luaopen_math);
+ push(LUA_MATHLIBNAME);
+ call(1, 0);
+ }
+
+ void import_io_library()
+ {
+ lua_pushcfunction(state_, luaopen_io);
+ push(LUA_IOLIBNAME);
+ call(1, 0);
+ }
+
+ void import_os_library()
+ {
+ lua_pushcfunction(state_, luaopen_os);
+ push(LUA_OSLIBNAME);
+ call(1, 0);
+ }
+
+ void import_debug_library()
+ {
+ lua_pushcfunction(state_, luaopen_debug);
+ push(LUA_DBLIBNAME);
+ call(1, 0);
+ }
+
+
+ void import_function(const std::string& name, const function& function)
+ {
+ push(function);
+ lua_setglobal(state_, name.c_str());
+ }
+
+ status do_string(const std::string& commands)
+ {
+ return status(luaL_dostring(state_, commands.c_str()));
+ }
+
+ status do_file(const std::string& file)
+ {
+ return status(luaL_dofile(state_, file.c_str()));
+ }
+
+
+ /**
+ * Thread-handling methods.
+ */
+
+ script push_new_thread()
+ {
+ return script(state_);
+ }
+
+ void push_thread()
+ {
+ lua_pushthread(state_);
+ }
+
+ status resume(int nargs)
+ {
+ return status(lua_resume(state_, nargs));
+ }
+
+ status getStatus() const
+ {
+ return status(lua_status(state_));
+ }
+
+ int yield(int results)
+ {
+ return lua_yield(state_, results);
+ }
+
+ bool is_main_thread() const
+ {
+ return is_main_thread_;
+ }
+
+
+ /**
+ * Throw an error with the value at the top of the stack. This method
+ * never returns because it does a long jump. Consequently,
+ * constructed C++ objects which exist on the stack between the
+ * current frame and some lua function will not be destructed. That's
+ * not a problem for objects that only exist on the stack, but any
+ * objects that allocate memory on the heap (such as containers or
+ * strings) will leak. Therefore, you should only call this method
+ * after cleaning up such objects.
+ */
+
+ void raise()
+ {
+ lua_error(state_);
+ }
+
+
+ /**
+ * Get significant values.
+ */
+
+ slot globals() const
+ {
+ return slot(*this, globals_index);
+ }
+
+ slot registry() const
+ {
+ return slot(*this, registry_index);
+ }
+
+ slot environment() const
+ {
+ return slot(*this, environment_index);
+ }
+
+ slot top() const
+ {
+ return slot(*this, stack_size());
+ }
+
+
+ /**
+ * Set the size of the stack.
+ * \param size The stack size.
+ */
+ void stack_size(int size)
+ {
+ lua_settop(state_, size);
+ }
+
+ /**
+ * Get the size of the stack; this is also the index of the top-most
+ * value.
+ * \return The stack size.
+ */
+ int stack_size() const
+ {
+ return lua_gettop(state_);
+ }
+
+ /**
+ * Clear the stack, setting its size to zero.
+ */
+ void clear_stack()
+ {
+ stack_size(0);
+ }
+
+
+ /**
+ * Makes sure there is at least extra more places on the stack.
+ * Returns false if space couldn't be created. Just like with the
+ * regular Lua API, you are responsible to make sure the stack is big
+ * enough to hold whatever you want to push on it. This is usually
+ * only an issue if you're pushing stuff in a loop.
+ */
+ bool checkStack(int extra)
+ {
+ return (bool)lua_checkstack(state_, extra);
+ }
+
+
+ /**
+ * Concatenates the top-most n slots on the stack.
+ */
+ void concatenate(int n = 2)
+ {
+ lua_concat(state_, n);
+ }
+
+
+ /**
+ * Push some values onto the stack.
+ */
+ template <class T>
+ slot push(T value)
+ {
+ lua_pushinteger(state_, lua_Integer(value));
+ return top();
+ }
+
+ slot push(bool value)
+ {
+ lua_pushboolean(state_, int(value));
+ return top();
+ }
+
+ slot push(float value)
+ {
+ lua_pushnumber(state_, (lua_Number)value);
+ return top();
+ }
+ slot push(double value)
+ {
+ lua_pushnumber(state_, (lua_Number)value);
+ return top();
+ }
+
+ slot push(const std::string& value)
+ {
+ lua_pushlstring(state_, value.c_str(), value.length());
+ return top();
+ }
+ slot push(const char* value)
+ {
+ lua_pushstring(state_, value);
+ return top();
+ }
+ slot push(const char* value, size_t length)
+ {
+ lua_pushlstring(state_, value, length);
+ return top();
+ }
+
+ slot push(const function& function)
+ {
+ functions_.push_back(function);
+ lua_pushlightuserdata(state_, (void*)&functions_.back());
+ lua_pushcclosure(state_, dispatch_call, 1);
+ return top();
+ }
+
+ slot push(void* data)
+ {
+ lua_pushlightuserdata(state_, data);
+ return top();
+ }
+
+ slot push_nil()
+ {
+ lua_pushnil(state_);
+ return top();
+ }
+
+ slot push_from_thread(script& thread, int n)
+ {
+ lua_xmove(thread.state_, state_, n);
+ return top();
+ }
+
+ slot push_code(const std::string& file, status& result)
+ {
+ result = status(luaL_loadfile(state_, file.c_str()));
+ return top();
+ }
+
+ slot push_code(const std::string& name,
+ const char* buffer,
+ size_t size,
+ status& result)
+ {
+ result = status(luaL_loadbuffer(state_,
+ buffer, size, name.c_str()));
+ return top();
+ }
+
+ slot push_new_data(void*& data, size_t size)
+ {
+ data = lua_newuserdata(state_, size);
+ return top();
+ }
+
+ slot push_new_table(int narr = 0, int nrec = 0)
+ {
+ lua_createtable(state_, narr, nrec);
+ return top();
+ }
+
+
+ /**
+ * Call a function on the stack. The correct procedure is to push a
+ * function onto the stack followed by nargs arguments. This method
+ * will pop them off upon return, leaving up to nresults return values
+ * (default is any number of return values, depending on the callee).
+ */
+
+ status call(int nargs = 0, int nresults = LUA_MULTRET)
+ {
+ return status(lua_pcall(state_, nargs, nresults, 0));
+ }
+
+
+ /**
+ * Pops n values from the top of the stack.
+ */
+
+ void pop(int n = 1)
+ {
+ lua_pop(state_, n);
+ }
+
+
+ /**
+ * Index into the stack to get a slot.
+ */
+
+ slot operator [] (int index) const
+ {
+ return slot(*this, index);
+ }
+
+
+ /**
+ * Control over the garbage collection process.
+ */
+
+ void collect_all()
+ {
+ lua_gc(state_, LUA_GCCOLLECT, 0);
+ }
+
+ void stop_collector()
+ {
+ lua_gc(state_, LUA_GCSTOP, 0);
+ }
+
+ void restart_collector()
+ {
+ lua_gc(state_, LUA_GCRESTART, 0);
+ }
+
+ int memory_used() const
+ {
+ // in kilobytes
+ return lua_gc(state_, LUA_GCCOUNT, 0);
+ }
+
+ void collect(int step)
+ {
+ lua_gc(state_, LUA_GCSTEP, step);
+ }
+
+ void tune_collector(int pause, int step)
+ {
+ lua_gc(state_, LUA_GCSETPAUSE, pause);
+ lua_gc(state_, LUA_GCSETSTEPMUL, step);
+ }
+
+
+private:
+
+ script(lua_State* state) :
+ state_(lua_newthread(state)),
+ is_main_thread_(false) {}
+
+ static int dispatch_call(lua_State* state)
+ {
+ const function* function = (const script::function*)lua_touserdata(state,
+ lua_upvalueindex(1));
+
+ lua_getfield(state, LUA_REGISTRYINDEX, "Script_hh_Object");
+ script* script = (moof::script*)lua_touserdata(state, -1);
+ lua_pop(state, 1);
+
+ return (*function)(*script);
+ }
+
+ void destroy()
+ {
+ if (is_main_thread_) lua_close(state_);
+ }
+
+ lua_State* state_;
+ bool is_main_thread_;
+ std::list<function> functions_;
+};
+
+
+inline std::ostream& operator << (std::ostream& stream,
+ const script::slot& slot)
+{
+ std::string str;
+ bool boolean;
+
+ if (slot.get(str))
+ {
+ stream << str;
+ }
+ else if (slot.get(boolean))
+ {
+ if (boolean) stream << "true";
+ else stream << "false";
+ }
+ else if (slot.is_nil())
+ {
+ stream << "nil";
+ }
+ else
+ {
+ stream << slot.type_name() << " (" << slot.id() << ")";
+ }
+
+ return stream;
+}
+
+
+} // namespace moof
+
+#endif // _MOOF_SCRIPT_HH_
+
*
**************************************************************************/
-#include "Service.hh"
-#include "Socket.hh"
+#include "service.hh"
+#include "socket.hh"
#define SOLICIT 0x1234ABCD
#define RESPONSE 0xABCD1234
-namespace Mf {
+namespace moof {
-int Service::handlePacket(SocketMultiplexer& mux,
- Packet& packet,
- const SocketAddress& address)
+int service::handle_packet(socket_multiplexer& mux,
+ packet& packet,
+ const socket::address& address)
{
try
{
{
std::string type;
packet >> type;
- if (type == mType)
+ if (type == type_)
{
packet.clear();
- packet << RESPONSE << mType << mName << mText;
+ packet << RESPONSE << type_ << name_ << text_;
mux.socket().write(packet);
return 0;
}
return -1;
}
-int ServiceFinder::handlePacket(SocketMultiplexer& mux,
- Packet& packet,
- const SocketAddress& address)
+int service_finder::handle_packet(socket_multiplexer& mux,
+ packet& packet,
+ const socket::address& address)
{
try
{
{
std::string type;
packet >> type;
- if (type == mType)
+ if (type == type_)
{
std::string name;
std::string text;
packet >> name >> text;
- Service service(address, type, name, text);
- mServices.insert(std::make_pair(name, service));
+ service service(address, type, name, text);
+ services_.insert(std::make_pair(name, service));
return 0;
}
}
return -1;
}
-ServiceFinder::ServiceFinder(const std::string& type, int sockType)
+service_finder::service_finder(const std::string& type, int sockType)
{
}
-} // namespace Mf
+} // namespace moof
*
**************************************************************************/
+#ifndef _MOOF_SERVICE_HH_
+#define _MOOF_SERVICE_HH_
+
/**
- * \file Service.hh
+ * \file service.hh
* Classes for publishing and finding network services.
*/
-#ifndef _MOOF_SERVICE_HH_
-#define _MOOF_SERVICE_HH_
-
#include <map>
-#include <Moof/Math.hh>
-#include <Moof/Socket.hh>
+#include <moof/math.hh>
+#include <moof/socket.hh>
-namespace Mf {
+namespace moof {
/**
* Class representing a network service.
*/
-class Service
+class service
{
public:
* \param name The service name.
* \param text The service information.
*/
- Service(const SocketAddress& address,
+ service(const socket::address& address,
const std::string& type,
const std::string& name,
const std::string& text);
* \param name The service name.
* \param text The service information.
*/
- Service(const SocketAddress& address,
+ service(const socket::address& address,
const std::string& name,
const std::string& text);
* Get the host address.
* \return The address.
*/
- const SocketAddress& address() const
+ const socket::address& address() const
{
- return mAddress;
+ return address_;
}
/**
*/
const std::string& type() const
{
- return mType;
+ return type_;
}
/**
*/
const std::string& name() const
{
- return mName;
+ return name_;
}
/**
*/
const std::string& text() const
{
- return mText;
+ return text_;
}
- ~Service();
+ ~service();
private:
- int handlePacket(SocketMultiplexer& mux,
- Packet& packet,
- const SocketAddress& address);
+ int handle_packet(socket_multiplexer& mux,
+ packet& packet,
+ const socket::address& address);
- SocketAddress mAddress;
- std::string mType;
- std::string mName;
- std::string mText;
+ socket::address address_;
+ std::string type_;
+ std::string name_;
+ std::string text_;
};
-class ServiceFinder
+class service_finder
{
public:
* address.
* \address The address.
*/
- explicit ServiceFinder(const SocketAddress& address);
+ explicit service_finder(const socket::address& address);
/**
* Construct a service finder to find services of a certain type.
* \param type The type of the service.
* \param sockType The type of socket.
*/
- explicit ServiceFinder(const std::string& type,
- int sockType = SOCK_STREAM);
+ explicit service_finder(const std::string& type,
+ int sockType = SOCK_STREAM);
- const std::map<std::string,Service>& services() const
+ const std::map<std::string,service>& services() const
{
- return mServices;
+ return services_;
}
private:
- int handlePacket(SocketMultiplexer& mux,
- Packet& packet,
- const SocketAddress& address);
+ int handle_packet(socket_multiplexer& mux,
+ packet& packet,
+ const socket::address& address);
- std::string mType;
- std::map<std::string,Service> mServices;
+ std::string type_;
+ std::map<std::string,service> services_;
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_SERVICE_HH_
#include <cstdlib> // getenv
-#include "Settings.hh"
+#include "log.hh"
+#include "settings.hh"
-namespace Mf {
+namespace moof {
-Settings::~Settings()
+settings::settings(int argc, char* argv[], const std::string& path)
+{
+ script_.import_base_library();
+ log::import(script_);
+
+ parse_args(argc, argv);
+ load_files(path);
+}
+
+settings::~settings()
{
save();
}
-void Settings::parseArgs(int argc, char* argv[])
+void settings::parse_args(int argc, char* argv[])
{
for (int i = 1; i < argc; ++i)
{
- if (mScript.doString(argv[i]) != Script::SUCCESS)
+ if (script_.do_string(argv[i]) != script::success)
{
std::string str;
- mScript[-1].get(str);
- logWarning << "invalid option: " << argv[i]
+ script_[-1].get(str);
+ log_warning << "invalid option: " << argv[i]
<< ": " << str << std::endl;
- mScript.clearStack();
+ script_.clear_stack();
}
}
}
-void Settings::loadFromFiles(const std::string& path)
+void settings::load_files(const std::string& path)
{
std::vector<std::string> paths;
boost::split(paths, path, boost::is_any_of(":"));
- loadFromFiles(paths);
+ load_files(paths);
}
-void Settings::loadFromFiles(const std::vector<std::string>& path)
+void settings::load_files(const std::vector<std::string>& path)
{
std::vector<std::string> copy(path);
std::vector<std::string>::iterator it;
{
boost::replace_all(*it, "$HOME", home);
- //Mf::logDebug("Copying global settings...");
+ //logDebug("Copying global settings...");
//mUserFile = *it;
- //mGlobals.pushCopy();
- //mScript.set("globals", Script::REGISTRY);
+ //mGlobals.push_copy();
+ //script_.set("globals", script::registry_index);
}
- if (mScript.doFile(*it) != Script::SUCCESS)
+ if (script_.do_file(*it) != script::success)
{
std::string str;
- mScript[-1].get(str);
- logWarning(str);
- mScript.clearStack();
+ script_[-1].get(str);
+ log_warning(str);
+ script_.clear_stack();
}
}
}
-void Settings::clear()
+void settings::clear()
{
- mScript.reset();
+ script_.reset();
}
-void Settings::saveAs(const std::string& path)
+void settings::save_as(const std::string& path)
{
mUserFile = path;
save();
}
-void Settings::save() const
+void settings::save() const
{
// TODO saving settings not yet implemented
}
-} // namepsace Mf
+} // namepsace moof
#define _MOOF_SETTINGS_HH_
/**
- * @file Settings.hh
+ * \file settings.hh
* Load, store, save program settings.
*/
#include <boost/algorithm/string.hpp>
-#include <Moof/Log.hh>
-#include <Moof/Script.hh>
+#include <moof/script.hh>
-namespace Mf {
+namespace moof {
-class Settings
+class settings
{
public:
- Settings(int argc, char* argv[], const std::string& path)
- {
- mScript.importBaseLibrary();
- importLogFunctions(mScript);
+ settings(int argc, char* argv[], const std::string& path);
- parseArgs(argc, argv);
- loadFromFiles(path);
- }
+ ~settings();
- ~Settings();
+ void parse_args(int argc, char* argv[]);
- void parseArgs(int argc, char* argv[]);
+ void load_files(const std::string& path);
+ void load_files(const std::vector<std::string>& path);
- void loadFromFiles(const std::string& path);
- void loadFromFiles(const std::vector<std::string>& path);
- void clear(); // remove all settings
+ /**
+ * Remove all settings.
+ */
+ void clear();
- void saveAs(const std::string& path);
+ void save_as(const std::string& path);
void save() const;
+
+ /**
+ * Get a setting by name.
+ * \param key The name of the setting.
+ * \param value A reference to the variable to store the setting.
+ * \return True if the setting exists, false otherwise.
+ */
template <class T>
bool get(const std::string& key, T& value) const;
+
private:
- mutable Script mScript;
+ mutable script script_;
std::string mUserFile;
};
template <class T>
-bool Settings::get(const std::string& key, T& value) const
+bool settings::get(const std::string& key, T& value) const
{
- Script::Slot top = mScript[-1];
- Script::Slot globals = mScript.globals();
+ script::slot top = script_[-1];
+ script::slot globals = script_.globals();
std::vector<std::string> fields;
boost::split(fields, key, boost::is_any_of("."));
- globals.pushCopy();
+ globals.push_copy();
std::vector<std::string>::iterator it;
for (it = fields.begin(); it != fields.end(); ++it)
{
- if (top.isTable())
+ if (top.is_table())
{
- top.pushField(*it);
+ top.push_field(*it);
}
else
{
- mScript.clearStack();
+ script_.clear_stack();
return false;
}
}
bool got = top.get(value);
- mScript.clearStack();
+ script_.clear_stack();
return got;
}
-} // namepsace Mf
+} // namepsace moof
#endif // _MOOF_SETTINGS_HH_
#ifndef _MOOF_SHAPE_HH_
#define _MOOF_SHAPE_HH_
-#include <Moof/Drawable.hh>
-#include <Moof/Math.hh>
-#include <Moof/OpenGL.hh>
-#include <Moof/Ray.hh>
-
-
-// Frustum
-// Plane (can construct from Triangle3)
-// Ray
-// Shape<>
-// +- Line<>
-// - Line2 Line<2>
-// - Line3 Line<3>
-// +- Sphere<>
-// | Sphere2, Circle Sphere<2>
-// | Sphere3 Sphere<3>
-// +- Aabb<>
-// | Aabb2, Rectangle Aabb<2>
-// | Aabb3 Aabb<3>
-// +- Polygon<>
-// | Triangle2 Polygon<2,3>
-// | Triangle3 Polygon<3,3>
-
-
-namespace Mf {
+/**
+ * \file shape.hh
+ * Declares an interface for shapes.
+ */
+
+#include <moof/drawable.hh>
+#include <moof/math.hh>
+#include <moof/opengl.hh>
+#include <moof/ray.hh>
+
+
+// frustum
+// plane (can construct from triangle2)
+// ray
+// shape<>
+// +- line<>
+// - line2 line<2>
+// - line3 line<3>
+// +- sphere<>
+// | sphere2, circle sphere<2>
+// | sphere3 sphere<3>
+// +- aabb<>
+// | aabb2, rectangle aabb<2>
+// | aabb3 aabb<3>
+// +- polygon<>
+// | triangle2 polygon<2,3>
+// | triangle3 polygon<3,3>
+
+
+namespace moof {
template <int D>
-class Shape
+class shape
{
public:
- virtual ~Shape() {}
+ virtual ~shape() {}
/**
* Checks if this shape is intersected by a given ray. If so, returns
* about the contact via the 2nd parameter. A negative value is
* returned if there is no contact.
*/
- virtual bool intersectRay(const Ray<D>& ray,
- typename Ray<D>::Contact& hit) const
+ virtual bool intersect_ray(const ray<D>& ray,
+ typename ray<D>::contact& hit) const
{
return false;
}
};
-typedef Shape<2> Shape2;
-typedef Shape<3> Shape3;
+typedef shape<2> shape2;
+typedef shape<3> shape3;
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_SHAPE_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_SOCKET_HH_
+#define _MOOF_SOCKET_HH_
+
+/**
+ * \file socket.hh
+ * Network-related classes, including a reinterpreted sockets API.
+ */
+
+#include <algorithm>
+#include <cstring>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#error No alternative to fcntl implemented yet.
+#endif
+
+#if defined(_WIN32)
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <wspiapi.h>
+#define SHUT_RD SD_RECEIVE
+#define SHUT_WR SD_SEND
+#define SHUT_RDWR SD_BOTH
+#else
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#endif
+
+#include <moof/log.hh>
+#include <moof/packet.hh>
+#include <moof/thread.hh>
+
+
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0
+#endif
+
+#ifndef AI_V4MAPPED
+#define AI_V4MAPPED 0
+#endif
+
+
+namespace moof {
+
+
+/**
+ * The socket class represents a connection or between this node and a
+ * remote node.
+ */
+class socket
+{
+public:
+
+ /**
+ * A class to represent the address of a remote host, including the
+ * type of service and socket communication.
+ */
+ class address
+ {
+ public:
+
+ /**
+ * Construct an unspecified address.
+ */
+ address() :
+ size_(0),
+ type_(0)
+ {
+ addr_.sa.sa_family = AF_UNSPEC;
+ addr_.in.sin_port = 0;
+ }
+
+ /**
+ * Construct an address with a specified host. The address can be
+ * used to connect to a host.
+ * \param service The service name or port number.
+ * \param name The numeric IP address of the host.
+ * \param type The type of socket; either SOCK_STREAM or
+ * SOCK_DGRAM.
+ * \param family The family; can be AF_INET or AF_INET6.
+ */
+ address(const std::string& service,
+ const std::string& name,
+ int type = SOCK_STREAM,
+ int family = AF_UNSPEC)
+ {
+ init(service, name, type, family);
+ }
+
+ /**
+ * Construct an address without a specified host. The address can
+ * be used to accept on a local port.
+ * \param service The service name or port number.
+ * \param type The type of socket; either SOCK_STREAM or
+ * SOCK_DGRAM.
+ * \param family The family; can be AF_INET or AF_INET6.
+ */
+ explicit address(const std::string& service,
+ int type = SOCK_STREAM,
+ int family = AF_UNSPEC)
+ {
+ init(service, type, family);
+ }
+
+ /**
+ * Construct an address from the information in an addrinfo
+ * structure.
+ * \param addr The addrinfo structure.
+ */
+ address(const struct addrinfo* addr) :
+ size_(addr->ai_addrlen),
+ type_(addr->ai_socktype)
+ {
+ memcpy(&addr_.sa, addr->ai_addr, addr->ai_addrlen);
+ get_name_and_service(name_, service_);
+ }
+
+ /**
+ * Construct an address from a sockaddr structure.
+ * \param addr The sockaddr structure.
+ * \param size The size of the sockaddr structure.
+ * \param type The type of socket; either SOCK_STREAM or
+ * SOCK_DGRAM.
+ */
+ address(const struct sockaddr* addr,
+ size_t size,
+ int type = SOCK_STREAM) :
+ size_(size),
+ type_(type)
+ {
+ memcpy(&addr_.sa, addr, size);
+ get_name_and_service(name_, service_);
+ }
+
+
+ /**
+ * Get an IPv4 broadcast address.
+ * \param service The service name or port number.
+ * \return The socket address.
+ */
+ static address broadcast(const std::string& service)
+ {
+ std::istringstream stream(service);
+ unsigned short port;
+ stream >> port;
+
+ struct sockaddr_in addr;
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = INADDR_BROADCAST;
+ memset(&addr.sin_zero, 0, sizeof(addr.sin_zero));
+ return address((struct sockaddr*)&addr, sizeof(addr),
+ SOCK_DGRAM);
+ }
+
+
+ /**
+ * Initialize the address with a specified host. The address can
+ * be used to connect to a host.
+ * \param service The service name or port number.
+ * \param name The numeric IP address of the host.
+ * \param type The type of socket; either SOCK_STREAM or
+ * SOCK_DGRAM.
+ * \param family The family; can be AF_INET or AF_INET6.
+ */
+ void init(const std::string& service,
+ const std::string& name,
+ int type = SOCK_STREAM,
+ int family = AF_UNSPEC)
+ {
+ const int flags = AI_ADDRCONFIG | AI_NUMERICHOST | AI_V4MAPPED;
+ struct addrinfo* addr = resolve(service.c_str(), name.c_str(),
+ type, family,
+ flags);
+ if (addr)
+ {
+ size_ = addr->ai_addrlen;
+ type_ = addr->ai_socktype;
+ memcpy(&addr_.sa, addr->ai_addr, addr->ai_addrlen);
+
+ service_ = service;
+ name_ = name;
+
+ freeaddrinfo(addr);
+ }
+ else
+ {
+ type_ = 0;
+ size_ = 0;
+ addr_.sa.sa_family = AF_UNSPEC;
+ addr_.in.sin_port = 0;
+ }
+ }
+
+ /**
+ * Initialize the address without a specified host. The address
+ * can be used to accept on a local port.
+ * \param service The service name or port number.
+ * \param type The type of socket; either SOCK_STREAM or
+ * SOCK_DGRAM.
+ * \param family The family; can be AF_INET or AF_INET6.
+ */
+ void init(const std::string& service,
+ int type = SOCK_STREAM,
+ int family = AF_UNSPEC)
+ {
+ struct addrinfo* addr = resolve(service.c_str(), 0,
+ type, family,
+ AI_PASSIVE);
+ if (addr)
+ {
+ size_ = addr->ai_addrlen;
+ type_ = addr->ai_socktype;
+ memcpy(&addr_.sa, addr->ai_addr, addr->ai_addrlen);
+
+ service_ = service;
+ get_name(name_);
+
+ freeaddrinfo(addr);
+ }
+ else
+ {
+ type_ = 0;
+ size_ = 0;
+ addr_.sa.sa_family = AF_UNSPEC;
+ addr_.in.sin_port = 0;
+ }
+ }
+
+
+ /**
+ * Get the name of the service. This could also be a port number
+ * if there is no service name associated with the number.
+ * \return The service.
+ */
+ const std::string& service() const
+ {
+ return service_;
+ }
+
+ /**
+ * Get the name of the host. This may be the host used to
+ * construct the address, or a resolved numeric host if none was
+ * used.
+ * \return The host.
+ */
+ const std::string& name() const
+ {
+ return name_;
+ }
+
+ /**
+ * Get the port number of the address service.
+ * \return Port number.
+ */
+ unsigned short port() const
+ {
+ return ntohs(addr_.in.sin_port);
+ }
+
+ /**
+ * Get the type of socket associated with the service of this
+ * address.
+ * \return Socket type; either SOCK_STREAM or SOCK_DGRAM.
+ */
+ int type() const
+ {
+ return type_;
+ }
+
+ /**
+ * Get the family of the protocol associated with the address.
+ * \return Protocol family; either AF_INET, AF_INET6, or AF_UNSPEC.
+ */
+ int family() const
+ {
+ return addr_.sa.sa_family;
+ }
+
+
+ /**
+ * Get the sockaddr structure of the address.
+ * \return The sockaddr structure.
+ */
+ const struct sockaddr* sockaddr() const
+ {
+ return size_ != 0 ? &addr_.sa : 0;
+ }
+
+ /**
+ * Get the size of the sockaddr structure of the address.
+ * \return The size of the sockaddr structure.
+ */
+ size_t size() const
+ {
+ return size_;
+ }
+
+
+ /**
+ * Get a list of addresses resolved to by the given search
+ * criteria. This can be used to perform lookups for name
+ * resolution, so this method may take some time to return. Use
+ * the ResolveTask class to resolve addresses asynchronously.
+ * \param service The service name or port number.
+ * \param name The name of the local or remote host.
+ * \param type The type of socket; either SOCK_STREAM or
+ * SOCK_DGRAM.
+ * \param family The family; can be AF_INET or AF_INET6.
+ * \param resolved The list to be filled with addresses.
+ * \return 0 on success, -1 on error.
+ */
+ static int resolve(const std::string& service,
+ const std::string& name,
+ int type,
+ int family,
+ std::vector<address>& resolved)
+ {
+ struct addrinfo* list = resolve(service.c_str(), name.c_str(),
+ type, family,
+ AI_ADDRCONFIG | AI_V4MAPPED);
+ int result = collect_addresses(list, resolved);
+ freeaddrinfo(list);
+ return result;
+ }
+
+ /**
+ * Get a list of addresses resolved to by the given search
+ * criteria. The addresses will be suitable for accepting on a
+ * local port. \param service The service name or port number.
+ * \param type The type of socket; either SOCK_STREAM or
+ * SOCK_DGRAM.
+ * \param family The family; can be AF_INET or AF_INET6.
+ * \param resolved The list to be filled with addresses.
+ * \return 0 on success, -1 on error.
+ */
+ static int resolve(const std::string& service,
+ int type,
+ int family,
+ std::vector<address>& resolved)
+ {
+ struct addrinfo* list = resolve(service.c_str(), 0,
+ type, family,
+ AI_PASSIVE);
+ int result = collect_addresses(list, resolved);
+ freeaddrinfo(list);
+ return result;
+ }
+
+
+ /**
+ * Resolve the hostname of the address. The default behavior is to
+ * avoid a reverse lookup by giving the numeric address. You can
+ * change that behavior with the getnameinfo flags.
+ * \param name The place to store the hostname or IP address.
+ * \param flags The getnameinfo flags.
+ */
+ void get_name(std::string& name, int flags = NI_NUMERICHOST)
+ {
+ char node[256] = {'\0'};
+ int result = getnameinfo(&addr_.sa, size_,
+ node, sizeof(node),
+ 0, 0,
+ flags);
+ if (result == 0) name.assign(node);
+ }
+
+ /**
+ * Resolve the service name of the address.
+ * \param service The place to store the service name or port
+ * number.
+ * \param flags The getnameinfo flags.
+ */
+ void get_service(std::string& service, int flags)
+ {
+ flags |= type_ == SOCK_DGRAM ? NI_DGRAM : 0;
+
+ char serv[64] = {'\0'};
+ int result = getnameinfo(&addr_.sa, size_,
+ 0, 0,
+ serv, sizeof(serv),
+ flags);
+ if (result == 0) service.assign(serv);
+ }
+
+ /**
+ * Resolve the service and hostname of the address. The default
+ * behavior is to avoid a reverse lookup by giving the numeric
+ * address. You can change that behavior with the getnameinfo
+ * flags.
+ * \param name The place to store the hostname or IP address.
+ * \param service The place to store the service name or port
+ * number.
+ * \param flags The getnameinfo flags.
+ */
+ void get_name_and_service(std::string& name,
+ std::string& service,
+ int flags = NI_NUMERICHOST)
+ {
+ flags |= type_ == SOCK_DGRAM ? NI_DGRAM : 0;
+
+ char serv[64] = {'\0'};
+ char node[256] = {'\0'};
+ int result = getnameinfo(&addr_.sa, size_,
+ node, sizeof(node),
+ serv, sizeof(serv),
+ flags);
+ if (result == 0)
+ {
+ service.assign(serv);
+ name.assign(node);
+ }
+ }
+
+
+ private:
+
+ static struct addrinfo* resolve(const char* service,
+ const char* node,
+ int type,
+ int family,
+ int flags)
+ {
+ ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
+ ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
+
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = type;
+ hints.ai_flags = flags;
+
+ struct addrinfo* addr;
+ int status = getaddrinfo(node, service, &hints, &addr);
+
+ if (status == 0)
+ {
+ return addr;
+ }
+ else
+ {
+ log_warning(gai_strerror(status));
+ return 0;
+ }
+ }
+
+ static int collect_addresses(struct addrinfo* addresses,
+ std::vector<address>& resolved)
+ {
+ if (addresses)
+ {
+ resolved.clear();
+
+ for (struct addrinfo* addr = addresses;
+ addr != 0;
+ addr = addr->ai_next)
+ {
+ resolved.push_back(address(addr));
+ }
+
+ return 0;
+ }
+ else return -1;
+ }
+
+
+ union
+ {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+ struct sockaddr_storage storage;
+ } addr_;
+ size_t size_;
+ int type_;
+
+ std::string name_;
+ std::string service_;
+ };
+
+
+private:
+
+ struct impl
+ {
+ socket::address address;
+ int fd;
+ bool is_connected;
+
+ impl() :
+ fd(-1),
+ is_connected(false) {}
+
+ impl(const socket::address& address, int flags = 0) :
+ address(address),
+ fd(::socket(address.family(), address.type(), flags)),
+ is_connected(false) {}
+ } impl_;
+
+
+public:
+
+ /**
+ * Construct a socket with no associated peer.
+ */
+ socket() {}
+
+ /**
+ * Construct a socket with an address.
+ * \param address The address.
+ * \param flags The socket options.
+ */
+ socket(const address& address, int flags = 0) :
+ impl_(address, flags) {}
+
+ /**
+ * Construct a socket with a specified host. The socket can be used to
+ * connect to a host.
+ * \param service The service name or port number.
+ * \param name The numeric IP address of the host.
+ * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
+ * \param family The family; can be AF_INET or AF_INET6.
+ * \param flags The socket options.
+ */
+ socket(const std::string& service,
+ const std::string& name,
+ int type = SOCK_STREAM,
+ int family = AF_UNSPEC,
+ int flags = 0) :
+ impl_(address(service, name, type, family), flags) {}
+
+ /**
+ * Construct a socket without a specified host. The socket can be used
+ * to accept sockets on a local port.
+ * \param service The service name or port number.
+ * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
+ * \param family The family; can be AF_INET or AF_INET6.
+ * \param flags The socket options.
+ */
+ explicit socket(const std::string& service,
+ int type = SOCK_STREAM,
+ int family = AF_UNSPEC,
+ int flags = 0) :
+ impl_(address(service, type, family), flags) {}
+
+
+ /**
+ * Deconstruct the socket, closing it.
+ */
+ ~socket()
+ {
+ close();
+ }
+
+
+ /**
+ * Get whether or not the socket is connected.
+ * \return True if the socket is connected, false otherwise.
+ */
+ bool is_connected() const
+ {
+ return impl_.is_connected;
+ }
+
+ /**
+ * Get the address associated with the socket.
+ */
+ const address& peer_address() const
+ {
+ return impl_.address;
+ }
+
+
+ /**
+ * Connect the socket to its peer.
+ * \return 0 on success, -1 on failure.
+ */
+ int connect()
+ {
+ int result = ::connect(impl_.fd,
+ impl_.address.sockaddr(),
+ impl_.address.size());
+ impl_.is_connected = result != -1;
+ return result;
+ }
+
+ /**
+ * Disconnect a connected socket from its peer.
+ * \param flags Specify the socket directions to close.
+ * \return 0 on success, -1 on failure.
+ */
+ int disconnect(int flags = SHUT_RDWR)
+ {
+ return shutdown(impl_.fd, flags);
+ }
+
+
+ /**
+ * Bind the socket to interface and port number specified in the
+ * address.
+ * \return 0 on success, -1 on failure.
+ */
+ int bind()
+ {
+ return ::bind(impl_.fd,
+ impl_.address.sockaddr(),
+ impl_.address.size());
+ }
+
+ /**
+ * Listen on the socket for incoming connections. This is only useful
+ * for sockets of type SOCK_STREAM.
+ * \param backlog The number of unaccepted connections to queue.
+ * \return 0 on success, -1 on failure.
+ */
+ int listen(int backlog = SOMAXCONN)
+ {
+ return ::listen(impl_.fd, backlog > 0 ? backlog : SOMAXCONN);
+ }
+
+ /**
+ * Accept a new connection on the socket. This is only useful for
+ * sockets of type SOCK_STREAM.
+ * \param socket Set to the new socket on return.
+ * \return 0 on success, -1 on failure.
+ */
+ int accept(socket& socket)
+ {
+ moof::socket temp = moof::socket(impl_.fd);
+ if (temp.impl_.fd != -1)
+ {
+ socket = temp;
+ return socket.impl_.fd;
+ }
+ return -1;
+ }
+
+
+ /**
+ * Set an integer socket option.
+ * \param option The option to set.
+ * \param value The new value.
+ * \param level The layer to handle the option.
+ * \return 0 on success, -1 on failure.
+ */
+ template <class T>
+ int set(int option, const T& value, int level = SOL_SOCKET)
+ {
+#if defined(_WIN32)
+ return setsockopt(impl_.fd,
+ level,
+ option,
+ reinterpret_cast<const char*>(&value),
+ sizeof(value));
+#else
+ return setsockopt(impl_.fd, level, option, &value, sizeof(value));
+#endif
+ }
+
+ /**
+ * Set a string socket option.
+ * \param option The option to set.
+ * \param value The new value.
+ * \param level The layer to handle the option.
+ * \return 0 on success, -1 on failure.
+ */
+ int set(int option, const std::string& value, int level = SOL_SOCKET)
+ {
+ return setsockopt(impl_.fd, level, option,
+ value.data(), value.length());
+ }
+
+ /**
+ * Get an integer socket option.
+ * \param option The option to set.
+ * \param value The new value.
+ * \param level The layer to handle the option.
+ * \return 0 on success, -1 on failure.
+ */
+ template <class T>
+ int get(int option, T& value, int level = SOL_SOCKET) const
+ {
+ int size = sizeof(value);
+ return getsockopt(impl_.fd, level, option, &value, &size);
+ }
+
+ /**
+ * Get a string socket option.
+ * \param option The option to set.
+ * \param value The new value.
+ * \param level The layer to handle the option.
+ * \return 0 on success, -1 on failure.
+ */
+ int get(int option, std::string& value, int level = SOL_SOCKET) const
+ {
+ char str[256] = {'\0'};
+ socklen_t size = sizeof(str);
+
+#if defined(_WIN32)
+ int result = getsockopt(impl_.fd,
+ level,
+ option,
+ reinterpret_cast<char*>(&str),
+ &size);
+#else
+ int result = getsockopt(impl_.fd, level, option, &str, &size);
+#endif
+ value.assign(str, size);
+ return result;
+ }
+
+
+ /**
+ * Set the socket IO mode to either blocking or non-blocking.
+ * \param is_blocking True if the socket should block, false otherwise.
+ */
+ void is_blocking(bool is_blocking)
+ {
+#ifdef HAVE_FCNTL
+ int flags = fcntl(impl_.fd, F_GETFL);
+ flags = is_blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
+ fcntl(impl_.fd, F_SETFL, flags);
+#elif defined(_WIN32)
+ u_long value = is_blocking;
+ ioctlsocket(impl_.fd, FIONBIO, &value);
+#endif
+ }
+
+ /**
+ * Get whether or not the socket is blocking or non-blocking. If the
+ * IO mode can't be determined, this method will assume the socket is
+ * a blocking socket.
+ * \return True if the socket blocks, false otherwise.
+ */
+ bool is_blocking() const
+ {
+#ifdef HAVE_FCNTL
+ int flags = fcntl(impl_.fd, F_GETFL);
+ return !(flags & O_NONBLOCK);
+#endif
+ return true;
+ }
+
+
+ /**
+ * Write some bytes to the socket. Use this for connected sockets.
+ * \param bytes The bytes.
+ * \param size The number of bytes.
+ * \param flags The send options.
+ * \return The number of bytes written.
+ */
+ ssize_t write(const void* bytes, size_t size, int flags = 0)
+ {
+#if defined(_WIN32)
+ return send(impl_.fd,
+ reinterpret_cast<const char *>(bytes), size,
+ flags);
+#else
+ return send(impl_.fd, bytes, size, flags);
+#endif
+ }
+
+ /**
+ * Write some bytes to the socket using the given address. Use this
+ * for unconnected sockets.
+ * \param bytes The bytes.
+ * \param size The number of bytes.
+ * \param address The address to send to.
+ * \param flags The send options.
+ * \return The number of bytes written.
+ */
+ ssize_t write(const void* bytes,
+ size_t size,
+ const address& address,
+ int flags = 0)
+ {
+#if defined(_WIN32)
+ return sendto(impl_.fd,
+ reinterpret_cast<const char*>(bytes), size,
+ flags,
+ address.sockaddr(), address.size());
+#else
+ return sendto(impl_.fd, bytes, size, flags,
+ address.sockaddr(), address.size());
+#endif
+ }
+
+ /**
+ * Write a packet to the socket. Use this for connected sockets.
+ * \param packet The packet.
+ * \param flags The send options.
+ * \return The number of bytes written.
+ */
+ ssize_t write(const packet& packet, int flags = 0)
+ {
+ return write(packet.bytes(), packet.size(), flags);
+ }
+
+ /**
+ * Write a packet to the socket using the given address. Use this for
+ * unconnected sockets.
+ * \param packet The packet.
+ * \param address The address to send to.
+ * \param flags The send options.
+ * \return The number of bytes written.
+ */
+ ssize_t write(const packet& packet,
+ const address& address,
+ int flags = 0)
+ {
+ return write(packet.bytes(), packet.size(), address, flags);
+ }
+
+
+ /**
+ * Read some bytes from the socket. Use this for connected sockets.
+ * \param bytes The buffer to store the bytes.
+ * \param size The size of the buffer.
+ * \param flags The recv options.
+ * \return The number of bytes read.
+ */
+ ssize_t read(void* bytes, size_t size, int flags = 0)
+ {
+#if defined(_WIN32)
+ ssize_t result = recv(impl_.fd,
+ reinterpret_cast<char*>(bytes), size,
+ flags);
+#else
+ ssize_t result = recv(impl_.fd, bytes, size, flags);
+#endif
+ if (result == 0) impl_.is_connected = false;
+ return result;
+ }
+
+ /**
+ * Read some bytes from the socket using the given address. Use this
+ * for unconnected sockets.
+ * \param bytes The buffer to store the bytes.
+ * \param size The size of the buffer.
+ * \param address The address to read from.
+ * \param flags The recv options.
+ * \return The number of bytes read.
+ */
+ ssize_t read(void* bytes,
+ size_t size,
+ socket::address& address,
+ int flags = 0)
+ {
+ union
+ {
+ struct sockaddr sa;
+ struct sockaddr_storage storage;
+ } addr;
+ socklen_t length = sizeof(addr);
+
+#if defined(_WIN32)
+ ssize_t result = recvfrom(impl_.fd,
+ reinterpret_cast<char*>(bytes), size,
+ flags,
+ &addr.sa, &length);
+#else
+ ssize_t result = recvfrom(impl_.fd, bytes, size, flags,
+ &addr.sa, &length);
+#endif
+ if (result != -1)
+ {
+ address = socket::address(&addr.sa, length,
+ impl_.address.type());
+ }
+ else if (result == 0)
+ {
+ impl_.is_connected = false;
+ }
+ return result;
+ }
+
+ /**
+ * Read a packet from the socket. Use this for connected sockets.
+ * \param packet Set to the packet read on return.
+ * \param flags The recv options.
+ * \return The number of bytes read.
+ */
+ ssize_t read(packet& packet, int flags = 0)
+ {
+ char buffer[65536];
+ ssize_t result = read(buffer, sizeof(buffer), flags);
+ if (result != -1) packet = moof::packet(buffer, result);
+ return result;
+ }
+
+ /**
+ * Read a packet from the socket using the given address. Use this for
+ * unconnected sockets.
+ * \param packet Set to the packet read on return.
+ * \param address The address to read from.
+ * \param flags The recv options.
+ * \return The number of bytes read.
+ */
+ ssize_t read(packet& packet, address& address, int flags = 0)
+ {
+ char buffer[65536];
+ ssize_t result = read(buffer, sizeof(buffer), address, flags);
+ if (result != -1) packet = moof::packet(buffer, result);
+ return result;
+ }
+
+
+ // The rest of this junk is used to implement the "move" semantics
+ // correctly, since it makes no sense for socket objects to be copied.
+
+ socket(socket& move) :
+ impl_(move.impl_)
+ {
+ move.impl_.fd = -1;
+ move.impl_.is_connected = false;
+ }
+
+ socket(impl move) :
+ impl_(move) {}
+
+ socket& operator=(socket& move)
+ {
+ close();
+ impl_ = move.impl_;
+ move.impl_.fd = -1;
+ move.impl_.is_connected = false;
+ return *this;
+ }
+
+ socket& operator=(impl move)
+ {
+ close();
+ impl_ = move;
+ return *this;
+ }
+
+ operator impl()
+ {
+ impl impl(impl_);
+ impl_.fd = -1;
+ impl_.is_connected = false;
+ return impl;
+ }
+
+
+private:
+
+ socket(int fd)
+ {
+ // for accepting a socket from fd
+ union
+ {
+ struct sockaddr sa;
+ struct sockaddr_storage storage;
+ } addr;
+ socklen_t length = sizeof(addr);
+
+ impl_.fd = ::accept(fd, &addr.sa, &length);
+ if (impl_.fd != -1)
+ {
+ impl_.is_connected = true;
+ impl_.address = address(&addr.sa, length);
+ }
+ }
+
+ void close()
+ {
+#if defined(_WIN32)
+ if (impl_.fd != -1) closesocket(impl_.fd);
+#else
+ if (impl_.fd != -1) ::close(impl_.fd);
+#endif
+ }
+};
+
+
+class socket_multiplexer
+{
+public:
+
+ typedef boost::function<int(socket_multiplexer&,
+ packet&,
+ const socket::address&)> function;
+
+ explicit socket_multiplexer(moof::socket sock) :
+ socket_(sock) {}
+
+
+ void socket(moof::socket sock)
+ {
+ mutex::scoped_lock lock(mutex_);
+ socket_ = sock;
+ }
+
+ moof::socket& socket()
+ {
+ return socket_;
+ }
+
+
+ std::vector<function>& protocols()
+ {
+ return protocols_;
+ }
+
+
+ void update(scalar t, scalar dt)
+ {
+ socket::address address;
+ packet packet;
+ ssize_t bytes = socket_.read(packet, address);
+
+ if (bytes > 0)
+ {
+ std::vector<function>::iterator it;
+ for (it = protocols_.begin(); it < protocols_.end(); ++it)
+ {
+ packet.revert();
+ if ((*it)(*this, packet, address)) break;
+ }
+ }
+ }
+
+
+ int background()
+ {
+ return 0;
+ }
+
+
+private:
+
+ moof::socket socket_;
+ std::vector<function> protocols_;
+ mutex mutex_;
+};
+
+
+/**
+ * An asynchronous task to resolve addresses.
+ */
+class resolver_task : public threaded_task
+{
+public:
+
+ /**
+ * Construct a resolver task from a service and hostname.
+ * \param service Server name or port number.
+ * \param name The hostname or numeric address.
+ * \param type The type of communication.
+ * \param family The requested protocol family.
+ */
+ resolver_task(const std::string& service,
+ const std::string& name,
+ int type = SOCK_STREAM,
+ int family = AF_UNSPEC) :
+ is_done_(false)
+ {
+ function_ = boost::bind(&resolver_task::resolve,
+ this, service, name, type, family);
+ }
+
+
+ /**
+ * Get whether or not the task is done.
+ * \return True if the task has finished, false otherwise.
+ */
+ bool is_done() const
+ {
+ return is_done_;
+ }
+
+ /**
+ * Start the task. This does nothing if the task was already run or is
+ * currently running.
+ */
+ void run()
+ {
+ if (!is_done() && !thread_.is_valid())
+ {
+ thread_ = thread::detach(function_);
+ }
+ }
+
+
+ /**
+ * Get the addresses resolved. This is filled and safe to access after
+ * the task finishes.
+ * \return List of addresses.
+ * \see is_done()
+ */
+ const std::vector<socket::address>& addresses() const
+ {
+ return address_list_;
+ }
+
+
+private:
+
+ int resolve(const std::string& service,
+ const std::string& name,
+ int type,
+ int family)
+ {
+ int status = socket::address::resolve(service, name,
+ type, family,
+ address_list_);
+ is_done_ = true;
+ return status;
+ }
+
+
+ std::vector<socket::address> address_list_;
+ bool is_done_;
+ thread::function function_;
+};
+
+
+/**
+ * Insert a string representation of a socket address into a stream.
+ * \param stream The output stream.
+ * \param addr The socket address.
+ * \return The stream.
+ */
+std::ostream& operator << (std::ostream& stream, const socket::address& addr)
+{
+ stream << addr.name() << ":" << addr.service();
+ return stream;
+}
+
+/**
+ * Insert a string representation of a socket into a stream.
+ * \param stream The output stream.
+ * \param addr The socket.
+ * \return The stream.
+ */
+std::ostream& operator << (std::ostream& stream, const socket& sock)
+{
+ stream << sock.peer_address();
+ return stream;
+}
+
+
+} // namespace moof
+
+#endif // _MOOF_SOCKET_HH_
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <cstdio>
+#include <deque>
+#include <list>
+#include <stdexcept>
+#include <string>
+
+#include <boost/algorithm/string.hpp>
+
+#include <AL/al.h>
+#include <AL/alc.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+
+#include "log.hh"
+#include "manager.hh"
+#include "sound.hh"
+#include "timer.hh"
+
+#define BUF_SIZE (64 * 1024)
+//#define BUF_SIZE (5*2048)
+
+namespace moof {
+
+
+class sound::impl
+{
+public:
+
+ static ALenum getAudioFormat(const vorbis_info* audioInfo)
+ {
+ if (audioInfo->channels == 1) return AL_FORMAT_MONO16;
+ else return AL_FORMAT_STEREO16;
+ }
+
+
+ class buffer;
+ typedef boost::shared_ptr<buffer> buffer_ptr;
+
+ class buffer : public manager<buffer>
+ {
+ public:
+
+ buffer() :
+ buffer_(-1)
+ {
+ mOggStream.datasource = 0;
+ }
+
+ ~buffer()
+ {
+ if (mOggStream.datasource)
+ {
+ ov_clear(&mOggStream);
+ }
+ if (int(buffer_) != -1) alDeleteBuffers(1, &buffer_);
+ }
+
+
+ void init(const std::string& name)
+ {
+ if (mOggStream.datasource)
+ {
+ ov_clear(&mOggStream);
+ mOggStream.datasource = 0;
+ }
+
+ std::string path(name);
+ if (!sound::find_path(path))
+ {
+ throw std::runtime_error("cannot find resource: " + name);
+ }
+
+ if (ov_fopen((char*)path.c_str(), &mOggStream) < 0)
+ {
+ throw std::runtime_error("problem reading audio: " + name);
+ }
+
+ vorbis_info* vorbisInfo = ov_info(&mOggStream, -1);
+ mFormat = getAudioFormat(vorbisInfo);
+ mFreq = vorbisInfo->rate;
+ }
+
+
+ void load_all(ALuint source)
+ {
+ if (!mOggStream.datasource) init(name());
+ if (!mOggStream.datasource) return;
+
+ char data[BUF_SIZE];
+ int size = 0;
+
+ for (;;)
+ {
+ int section;
+ int result = ov_read(&mOggStream, data + size,
+ BUF_SIZE - size, 0, 2, 1, §ion);
+
+ if (result > 0)
+ {
+ size += result;
+ }
+ else
+ {
+ if (result < 0) log_warning("vorbis playback error");
+ break;
+ }
+ }
+ if (size == 0)
+ {
+ log_warning("decoded no bytes from", name());
+ return;
+ }
+
+ alGenBuffers(1, &buffer_);
+
+ alBufferData(buffer_, mFormat, data, size, mFreq);
+ alSourcei(source, AL_BUFFER, buffer_);
+
+ // don't need to keep this loaded
+ ov_clear(&mOggStream);
+ mOggStream.datasource = 0;
+ }
+
+ bool stream(ALuint buffer)
+ {
+ char data[BUF_SIZE];
+ int size = 0;
+
+ while (size < BUF_SIZE)
+ {
+ int section;
+ int result = ov_read(&mOggStream, data + size,
+ BUF_SIZE - size, 0, 2, 1, §ion);
+
+ if (result > 0)
+ {
+ size += result;
+ }
+ else
+ {
+ if (result < 0) log_warning("vorbis playback error");
+ break;
+ }
+ }
+
+ if (size == 0) return false;
+
+ alBufferData(buffer, mFormat, data, size, mFreq);
+
+ return true;
+ }
+
+ void rewind()
+ {
+ if (!mOggStream.datasource) init(name());
+ else ov_raw_seek(&mOggStream, 0);
+ }
+
+
+ private:
+
+ OggVorbis_File mOggStream;
+ ALenum mFormat;
+ ALsizei mFreq;
+ ALuint buffer_;
+ };
+
+
+ impl()
+ {
+ init();
+ }
+
+ impl(const std::string& name)
+ {
+ init();
+ enqueue(name);
+ }
+
+ void init()
+ {
+ retain_backend();
+
+ is_loaded_ = false;
+ is_playing_ = false;
+ is_looping_ = false;
+
+ alGenSources(1, &source_);
+
+ ALfloat zero[] = {0.0f, 0.0f, 0.0f};
+ alSourcef(source_, AL_PITCH, 1.0f);
+ alSourcef(source_, AL_GAIN, 1.0f);
+ alSourcefv(source_, AL_POSITION, zero);
+ alSourcefv(source_, AL_VELOCITY, zero);
+
+ alSourcei(source_, AL_LOOPING, is_looping_);
+ }
+
+ ~impl()
+ {
+ stop();
+
+ alDeleteSources(1, &source_);
+
+ while (!buffers_.empty())
+ {
+ alDeleteBuffers(1, &buffers_.back());
+ buffers_.pop_back();
+ }
+
+ release_backend();
+ }
+
+
+ void play()
+ {
+ if (queue_.empty()) return;
+
+ if (!is_loaded_) queue_.front()->load_all(source_);
+
+ alSourcePlay(source_);
+ is_loaded_ = true;
+ }
+
+
+ void play_stream()
+ {
+ if (queue_.empty()) return;
+
+ if (!is_playing_)
+ {
+ alSourcei(source_, AL_LOOPING, false);
+ buffer_stream();
+ }
+
+ if (!stream_timer_.is_valid())
+ {
+ stream_timer_.init(boost::bind(&impl::stream_update, this, _1, _2),
+ 1.0, timer::repeat);
+ }
+
+ alSourcePlay(source_);
+ is_playing_ = true;
+ }
+
+ void buffer_stream()
+ {
+ ALuint buffer;
+ for (int i = buffers_.size(); i <= 8; ++i)
+ {
+ alGenBuffers(1, &buffer);
+
+ if (queue_.front()->stream(buffer))
+ {
+ alSourceQueueBuffers(source_, 1, &buffer);
+ buffers_.push_back(buffer);
+ }
+ else
+ {
+ alDeleteBuffers(1, &buffer);
+ break;
+ }
+ }
+ }
+
+
+ void update()
+ {
+ ALint finished = 0;
+
+ alGetSourcei(source_, AL_BUFFERS_PROCESSED, &finished);
+
+ while (finished-- > 0)
+ {
+ ALuint bufferObj;
+ alSourceUnqueueBuffers(source_, 1, &bufferObj);
+
+ buffer_ptr buffer = queue_.front();
+ bool streamed = buffer->stream(bufferObj);
+
+ if (streamed)
+ {
+ alSourceQueueBuffers(source_, 1, &bufferObj);
+ }
+ else
+ {
+ // the buffer couldn't be streamed, so get rid of it
+ queue_.pop_front();
+
+ if (!queue_.empty())
+ {
+ // begin the next buffer in the queue
+ queue_.front()->rewind();
+ queue_.front()->stream(bufferObj);
+ alSourceQueueBuffers(source_, 1, &bufferObj);
+ log_info("loading new buffer");
+
+ // queue up any unused buffers
+ buffer_stream();
+ }
+ else if (is_looping_)
+ {
+ // reload the same buffer
+ queue_.push_back(buffer);
+ buffer->rewind();
+ buffer->stream(bufferObj);
+ alSourceQueueBuffers(source_, 1, &bufferObj);
+ log_info("looping same buffer");
+ }
+ else
+ {
+ // nothing more to play, stopping...
+ is_playing_ = false;
+ std::remove(buffers_.begin(), buffers_.end(),
+ bufferObj);
+ }
+ }
+ }
+
+ ALenum state;
+ alGetSourcei(source_, AL_SOURCE_STATE, &state);
+
+ // restart playing if we're stopped but supposed to be playing...
+ // this means we didn't queue enough and the audio skipped :-(
+ if (is_playing_ && state != AL_PLAYING)
+ {
+ alSourcePlay(source_);
+ }
+ }
+
+
+ void stop()
+ {
+ alSourceStop(source_);
+ is_playing_ = false;
+
+ stream_timer_.invalidate();
+ }
+
+ void pause()
+ {
+ alSourcePause(source_);
+ is_playing_ = false;
+
+ stream_timer_.invalidate();
+ }
+
+
+ void sample(const std::string& name)
+ {
+ stop();
+ alSourcei(source_, AL_BUFFER, AL_NONE);
+
+ queue_.clear();
+ is_loaded_ = false;
+
+ enqueue(name);
+
+ while (!buffers_.empty())
+ {
+ alDeleteBuffers(1, &buffers_.back());
+ buffers_.pop_back();
+ }
+ }
+
+ void enqueue(const std::string& name)
+ {
+ buffer_ptr buffer = buffer::instance(name);
+ queue_.push_back(buffer);
+ }
+
+
+ bool is_playing() const
+ {
+ if (is_playing_) return true;
+
+ ALenum state;
+ alGetSourcei(source_, AL_SOURCE_STATE, &state);
+
+ return state == AL_PLAYING;
+ }
+
+
+ void loop(bool looping)
+ {
+ is_looping_ = looping;
+
+ ALenum type;
+ alGetSourcei(source_, AL_SOURCE_TYPE, &type);
+
+ if (type != AL_STREAMING)
+ {
+ alSourcei(source_, AL_LOOPING, is_looping_);
+ }
+ }
+
+
+ void stream_update(timer& timer, scalar t)
+ {
+ update();
+ // TODO: might be nice to also allow using threads for streaming
+ // rather than a timer, probably as a compile-time option
+ }
+
+
+ static void retain_backend()
+ {
+ if (retain_count_++ == 0)
+ {
+ al_device_ = alcOpenDevice(0);
+ al_context_ = alcCreateContext(al_device_, 0);
+ if (!al_device_ || !al_context_)
+ {
+ const char* error = alcGetString(al_device_,
+ alcGetError(al_device_));
+ log_error("audio subsystem initialization failure", error);
+ }
+ else
+ {
+ alcMakeContextCurrent(al_context_);
+ log_info << "opened sound device `"
+ << alcGetString(al_device_,
+ ALC_DEFAULT_DEVICE_SPECIFIER)
+ << "'" << std::endl;
+ }
+ }
+ }
+
+ static void release_backend()
+ {
+ if (--retain_count_ == 0)
+ {
+ alcMakeContextCurrent(0);
+ alcDestroyContext(al_context_);
+ alcCloseDevice(al_device_);
+ }
+ }
+
+
+ ALuint source_;
+ std::list<ALuint> buffers_;
+
+ bool is_loaded_;
+ bool is_playing_;
+ bool is_looping_;
+
+ std::deque<buffer_ptr> queue_;
+
+ timer stream_timer_;
+
+ static unsigned retain_count_;
+ static ALCdevice* al_device_;
+ static ALCcontext* al_context_;
+};
+
+unsigned sound::impl::retain_count_ = 0;
+ALCdevice* sound::impl::al_device_ = 0;
+ALCcontext* sound::impl::al_context_ = 0;
+
+
+sound::sound() :
+ // pass through
+ impl_(new sound::impl) {}
+
+sound::sound(const std::string& name) :
+ // pass through
+ impl_(new sound::impl(name)) {}
+
+
+void sound::sample(const std::string& name)
+{
+ // pass through
+ impl_->sample(name);
+}
+
+
+void sound::play()
+{
+ // pass through
+ impl_->play();
+}
+
+void sound::stop()
+{
+ // pass through
+ impl_->stop();
+}
+
+void sound::pause()
+{
+ // pass through
+ impl_->pause();
+}
+
+
+void sound::toggle()
+{
+ if (is_playing()) pause();
+ else play();
+}
+
+bool sound::is_playing() const
+{
+ // pass through
+ return impl_->is_playing();
+}
+
+
+void sound::position(const vector3& position)
+{
+ float vec[3] = {position[0], position[1], position[2]};
+ alSourcefv(impl_->source_, AL_POSITION, vec);
+}
+
+void sound::velocity(const vector3& velocity)
+{
+ float vec[3] = {velocity[0], velocity[1], velocity[2]};
+ alSourcefv(impl_->source_, AL_VELOCITY, vec);
+}
+
+void sound::gain(scalar gain)
+{
+ alSourcef(impl_->source_, AL_GAIN, float(gain));
+}
+
+void sound::pitch(scalar pitch)
+{
+ alSourcef(impl_->source_, AL_PITCH, float(pitch));
+}
+
+void sound::loop(bool looping)
+{
+ // pass through
+ impl_->loop(looping);
+}
+
+
+void sound::listener_position(const vector3& position)
+{
+ float vec[] = {position[0], position[1], position[2]};
+ alListenerfv(AL_POSITION, vec);
+}
+
+void sound::listener_velocity(const vector3& velocity)
+{
+ float vec[] = {velocity[0], velocity[1], velocity[2]};
+ alListenerfv(AL_VELOCITY, vec);
+}
+
+void sound::listener_orientation(const vector3& forward,
+ const vector3& up)
+{
+ float vec[6];
+ vec[0] = float(forward[0]);
+ vec[1] = float(forward[1]);
+ vec[2] = float(forward[2]);
+ vec[3] = float(up[0]);
+ vec[4] = float(up[1]);
+ vec[5] = float(up[2]);
+ alListenerfv(AL_ORIENTATION, vec);
+}
+
+
+bool sound::find_path(std::string& name)
+{
+ return resource::find_path(name, "sounds/", "ogg");
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+void sound_stream::enqueue(const std::string& name)
+{
+ // pass through
+ impl_->enqueue(name);
+}
+
+
+void sound_stream::play()
+{
+ // pass through
+ impl_->play_stream();
+}
+
+
+} // namespace moof
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_SOUND_HH_
+#define _MOOF_SOUND_HH_
+
+/**
+ * \file sound.hh
+ * Load and play sounds, current supports ogg vorbis.
+ */
+
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+
+#include <moof/math.hh>
+#include <moof/resource.hh>
+
+
+namespace moof {
+
+
+class sound;
+typedef boost::shared_ptr<sound> sound_ptr;
+
+class sound_stream;
+typedef boost::shared_ptr<sound_stream> sound_stream_ptr;
+
+
+class sound : public resource
+{
+public:
+
+ static sound_ptr alloc(const std::string& name)
+ {
+ return sound_ptr(new sound(name));
+ }
+
+ sound();
+ explicit sound(const std::string& name);
+
+ virtual ~sound() {}
+
+ // this implicitly stops the sound if it is playing
+ void sample(const std::string& name);
+
+ virtual void play();
+ void stop();
+ void pause();
+
+ void toggle();
+ bool is_playing() const;
+
+ void position(const vector3& position);
+ void velocity(const vector3& velocity);
+ void gain(scalar gain);
+ void pitch(scalar pitch);
+ void loop(bool looping);
+
+ static void listener_position(const vector3& position);
+ static void listener_velocity(const vector3& velocity);
+ static void listener_orientation(const vector3& forward,
+ const vector3& up);
+
+ static bool find_path(std::string& name);
+
+protected:
+
+ class impl;
+ boost::shared_ptr<impl> impl_;
+};
+
+
+class sound_stream : public sound
+{
+public:
+
+ static sound_stream_ptr alloc(const std::string& name)
+ {
+ return sound_stream_ptr(new sound_stream(name));
+ }
+
+ sound_stream();
+ explicit sound_stream(const std::string& name) :
+ sound(name) {}
+
+ void enqueue(const std::string& name);
+
+ void play();
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_SOUND_HH_
+
*
**************************************************************************/
-#include "Frustum.hh"
-#include "OpenGL.hh"
-#include "Sphere.hh"
+#include "frustum.hh"
+#include "opengl.hh"
+#include "sphere.hh"
-namespace Mf {
+namespace moof {
-void Sphere::encloseVertices(const Vector3 vertices[], unsigned count)
+void sphere::enclose_vertices(const vector3 vertices[], unsigned count)
{
// TODO
}
-void Sphere::draw(Scalar alpha) const
+void sphere::draw(scalar alpha) const
{
GLUquadricObj* sphereObj = gluNewQuadric();
gluQuadricDrawStyle(sphereObj, GLU_LINE);
gluDeleteQuadric(sphereObj);
}
-bool Sphere::isVisible(const Frustum& frustum) const
+bool sphere::is_visible(const frustum& frustum) const
{
return frustum.contains(*this);
}
-} // namespace Mf
+} // namespace moof
#ifndef _MOOF_SPHERE_HH_
#define _MOOF_SPHERE_HH_
-#include <Moof/Contact.hh>
-#include <Moof/Cullable.hh>
-#include <Moof/Drawable.hh>
-#include <Moof/Frustum.hh>
-#include <Moof/Math.hh>
-#include <Moof/OpenGL.hh>
-#include <Moof/Shape.hh>
+/**
+ * \file sphere.hh
+ * A round shape like a circle or sphere.
+ * TODO: This class needs some work.
+ */
+
+#include <moof/contact.hh>
+#include <moof/cullable.hh>
+#include <moof/drawable.hh>
+#include <moof/frustum.hh>
+#include <moof/math.hh>
+#include <moof/opengl.hh>
+#include <moof/shape.hh>
-// TODO this needs work
-namespace Mf {
+namespace moof {
/**
* A round object.
*/
-
-
template <int D = 3>
-struct Sphere : public Cullable, public Drawable, public Shape<D>
+struct sphere : public cullable, public drawable, public shape<D>
{
- typedef cml::vector< Scalar, cml::fixed<D> > Vector;
+ typedef moof::vector< scalar, fixed<D> > vector;
- Vector point;
- Scalar radius;
+ vector point;
+ scalar radius;
- Sphere() {}
+ sphere() {}
- Sphere(const Vector& p, Scalar r) :
+ sphere(const vector& p, scalar r) :
point(p),
radius(r) {}
- void init(const Vector& p, Scalar r)
+ void init(const vector& p, scalar r)
{
point = p;
radius = r;
}
- void init(const Vector& p, const Vector& o)
+ void init(const vector& p, const vector& o)
{
point = p;
radius = (o - p).length();
}
- //void encloseVertices(const Vector vertices[], unsigned count);
+ //void enclose_vertices(const vector vertices[], unsigned count);
- //void draw(Scalar alpha = 0.0) const;
- //bool isVisible(const Frustum& frustum) const;
+ //void draw(scalar alpha = 0.0) const;
+ //bool is_visible(const frustum& frustum) const;
- void encloseVertices(const Vector vertices[], unsigned count)
+ void enclose_vertices(const vector vertices[], unsigned count)
{
// TODO
}
- void draw(Scalar alpha = 0.0) const;
+ void draw(scalar alpha = 0.0) const;
- bool isVisible(const Frustum& frustum) const
+ bool is_visible(const frustum& frustum) const
{
return true;
}
- bool intersect(const Sphere<D>& sphere, Contact<D>& hit) const
+ bool intersect(const sphere<D>& sphere, contact<D>& hit) const
{
- Vector n = sphere.point - point;
- Scalar distance = n.length();
- Scalar limit = radius + sphere.radius;
+ vector n = sphere.point - point;
+ scalar distance = n.length();
+ scalar limit = radius + sphere.radius;
if (distance > limit) return false;
return true;
}
- bool intersect(const Vector& point2, Contact<D>& hit) const
+ bool intersect(const vector& point2, contact<D>& hit) const
{
- Vector n = point2 - point;
- Scalar distance = n.length();
+ vector n = point2 - point;
+ scalar distance = n.length();
if (distance > radius) return false;
}
// a ray inside the sphere will not intersect on its way out
- bool intersect(const Ray<D>& ray, typename Ray<D>::Contact& hit) const
+ bool intersect(const ray<D>& ray, typename ray<D>::contact& hit) const
{
- Vector b = point - ray.point;
- Scalar z = cml::dot(b, ray.direction);
+ vector b = point - ray.point;
+ scalar z = dot(b, ray.direction);
// check if the ball is behind the ray
if (z < SCALAR(0.0)) return false;
- Scalar d2 = cml::dot(b, b) - z*z;
- Scalar r2 = radius * radius;
+ scalar d2 = dot(b, b) - z*z;
+ scalar r2 = radius * radius;
// check for an intersection
if (d2 > r2) return false;
hit.distance = z - std::sqrt(r2 - d2);
if (hit.distance < SCALAR(0.0)) return false;
- Vector surfacePoint;
+ vector surfacePoint;
ray.solve(surfacePoint, hit.distance);
hit.normal = surfacePoint - point;
return true;
template <>
-inline bool Sphere<3>::isVisible(const Frustum& frustum) const
+inline bool sphere<3>::is_visible(const frustum& frustum) const
{
return frustum.contains(*this);
}
template <>
-inline void Sphere<2>::draw(Scalar alpha) const
+inline void sphere<2>::draw(scalar alpha) const
{
GLUquadricObj* sphereObj = gluNewQuadric();
gluQuadricDrawStyle(sphereObj, GLU_LINE);
}
template <>
-inline void Sphere<3>::draw(Scalar alpha) const
+inline void sphere<3>::draw(scalar alpha) const
{
GLUquadricObj* sphereObj = gluNewQuadric();
gluQuadricDrawStyle(sphereObj, GLU_LINE);
}
template <int D>
-inline bool checkCollision(const Sphere<D>& a, const Sphere<D>& b)
+inline bool checkCollision(const sphere<D>& a, const sphere<D>& b)
{
- Scalar d = (a.point - b.point).length();
+ scalar d = (a.point - b.point).length();
return d < (a.radius + b.radius);
}
-typedef Sphere<2> Sphere2;
-typedef Sphere2 Circle;
-typedef Sphere<3> Sphere3;
+typedef sphere<2> sphere2;
+typedef sphere2 circle;
+typedef sphere<3> sphere3;
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_SPHERE_HH_
#include <stdexcept>
#include "ConvertUTF.h"
-#include "StringTools.hh"
+#include "string.hh"
-namespace Mf {
+namespace moof {
// TODO this code is ugly
-std::wstring multiToWide(const std::string& multiStr)
+wstring multi_to_wide(const string& multi)
{
- size_t length = multiStr.length();
+ size_t length = multi.length();
if (sizeof(wchar_t) == 2)
{
- wchar_t* wideStr = new wchar_t[length + 1];
+ wchar_t* wide = new wchar_t[length + 1];
- const UTF8* srcStart = reinterpret_cast<const UTF8*>(multiStr.c_str());
+ const UTF8* srcStart = reinterpret_cast<const UTF8*>(multi.c_str());
const UTF8* srcEnd = srcStart + length;
- UTF16* targetStart = reinterpret_cast<UTF16*>(wideStr);
+ UTF16* targetStart = reinterpret_cast<UTF16*>(wide);
UTF16* targetEnd = targetStart + length+1;
ConversionResult res = ConvertUTF8toUTF16(&srcStart, srcEnd,
&targetStart, targetEnd, lenientConversion);
if (res != conversionOK)
{
- delete[] wideStr;
+ delete[] wide;
throw std::runtime_error("bad conversion from multi to wide characters");
}
*targetStart = 0;
- std::wstring convertedStr(wideStr);
- delete[] wideStr;
+ wstring convertedStr(wide);
+ delete[] wide;
return convertedStr;
}
else if (sizeof(wchar_t) == 4)
{
- wchar_t* wideStr = new wchar_t[length];
+ wchar_t* wide = new wchar_t[length];
- const UTF8* srcStart = reinterpret_cast<const UTF8*>(multiStr.c_str());
+ const UTF8* srcStart = reinterpret_cast<const UTF8*>(multi.c_str());
const UTF8* srcEnd = srcStart + length;
- UTF32* targetStart = reinterpret_cast<UTF32*>(wideStr);
+ UTF32* targetStart = reinterpret_cast<UTF32*>(wide);
UTF32* targetEnd = targetStart + length;
ConversionResult res = ConvertUTF8toUTF32(&srcStart, srcEnd,
&targetStart, targetEnd, lenientConversion);
if (res != conversionOK)
{
- delete[] wideStr;
+ delete[] wide;
throw std::runtime_error("bad conversion from multi to wide characters");
}
*targetStart = 0;
- std::wstring convertedStr(wideStr);
- delete[] wideStr;
+ wstring convertedStr(wide);
+ delete[] wide;
return convertedStr;
}
return L"";
}
-std::string wideToMulti(const std::wstring& wideStr)
+string wide_to_multi(const wstring& wide)
{
- size_t length = wideStr.length();
+ size_t length = wide.length();
if (sizeof(wchar_t) == 2)
{
size_t multiLength = 3 * length + 1;
- char* multiStr = new char[multiLength];
+ char* multi = new char[multiLength];
- const UTF16* srcStart = reinterpret_cast<const UTF16*>(wideStr.c_str());
+ const UTF16* srcStart = reinterpret_cast<const UTF16*>(wide.c_str());
const UTF16* srcEnd = srcStart + length;
- UTF8* targetStart = reinterpret_cast<UTF8*>(multiStr);
+ UTF8* targetStart = reinterpret_cast<UTF8*>(multi);
UTF8* targetEnd = targetStart + multiLength;
ConversionResult res = ConvertUTF16toUTF8(&srcStart, srcEnd,
&targetStart, targetEnd, lenientConversion);
if (res != conversionOK)
{
- delete[] multiStr;
+ delete[] multi;
throw std::runtime_error("bad conversion from wide to multi-characters");
}
*targetStart = 0;
- std::string convertedStr(multiStr);
- delete[] multiStr;
+ string convertedStr(multi);
+ delete[] multi;
return convertedStr;
}
else if (sizeof(wchar_t) == 4)
{
size_t multiLength = 4 * length + 1;
- char* multiStr = new char[multiLength];
+ char* multi = new char[multiLength];
- const UTF32* srcStart = reinterpret_cast<const UTF32*>(wideStr.c_str());
+ const UTF32* srcStart = reinterpret_cast<const UTF32*>(wide.c_str());
const UTF32* srcEnd = srcStart + length;
- UTF8* targetStart = reinterpret_cast<UTF8*>(multiStr);
+ UTF8* targetStart = reinterpret_cast<UTF8*>(multi);
UTF8* targetEnd = targetStart + multiLength;
ConversionResult res = ConvertUTF32toUTF8(&srcStart, srcEnd,
&targetStart, targetEnd, lenientConversion);
if (res != conversionOK)
{
- delete[] multiStr;
+ delete[] multi;
throw std::runtime_error("bad conversion from wide to multi-characters");
}
*targetStart = 0;
- std::string convertedStr(multiStr);
- delete[] multiStr;
+ string convertedStr(multi);
+ delete[] multi;
return convertedStr;
}
}
-} // namespace Mf
+} // namespace moof
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_STRING_HH_
+#define _MOOF_STRING_HH_
+
+/**
+ * \file string.hh
+ * Functions related to string manipulations.
+ */
+
+#include <string>
+
+
+namespace moof {
+
+
+using std::string;
+using std::wstring;
+
+
+/**
+ * Convert a multi-byte (UTF-8) string to a wide string.
+ * \param multi The multi-byte string to convert.
+ * \return The equivalent wide string.
+ */
+wstring multi_to_wide(const string& multi);
+
+/**
+ * Convert a wide string to a multi-byte (UTF-8) string.
+ * \param wide The wide string to convert.
+ * \return The equivalent multi-byte string.
+ */
+string wide_to_multi(const wstring& wide);
+
+
+} // namespace moof
+
+
+#endif // _MOOF_STRINGTOOLS_HH_
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <cstdio> // FILE
+#include <cstring> // strncmp
+#include <stdexcept>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/bind.hpp>
+
+#include "dispatcher.hh"
+#include "manager.hh"
+#include "log.hh"
+#include "opengl.hh"
+#include "script.hh"
+#include "texture.hh"
+#include "video.hh"
+
+
+namespace moof {
+
+
+/**
+ * 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 manager so that multiple texture
+ * objects can share the same internal objects and avoid having duplicate
+ * textures loaded to GL.
+ */
+
+class texture::impl : public manager<impl>
+{
+
+ /**
+ * Delete the texture (if it is loaded) from GL.
+ */
+
+ void unload_from_gl()
+ {
+ if (mObject)
+ {
+ if (mObject == gObject)
+ {
+ gObject = 0;
+ }
+
+ glDeleteTextures(1, &mObject);
+ mObject = 0;
+ }
+ }
+
+ /**
+ * If the GL context was recreated, we 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 context_recreated()
+ {
+ mObject = gObject = 0;
+ upload_to_gl();
+ }
+
+ /**
+ * 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 power_of_two(int input)
+ {
+ int value = 1;
+
+ while (value < input)
+ {
+ value <<= 1;
+ }
+ return value;
+ }
+
+
+ static void bind_script_constants(script& script)
+ {
+ script::slot g = script.globals();
+
+ g.set_field("CLAMP", GL_CLAMP);
+ g.set_field("REPEAT", GL_REPEAT);
+ g.set_field("LINEAR", GL_LINEAR);
+ g.set_field("NEAREST", GL_NEAREST);
+ g.set_field("LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR);
+ g.set_field("LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST);
+ g.set_field("NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR);
+ g.set_field("NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST);
+ }
+
+public:
+
+ /**
+ * Construction is initialization.
+ */
+
+ impl() :
+ mMinFilter(GL_NEAREST),
+ mMagFilter(GL_NEAREST),
+ mWrapS(GL_CLAMP),
+ mWrapT(GL_CLAMP),
+ mTilesS(1),
+ mTilesT(1),
+ mObject(0)
+ {
+ // make sure we have a video context
+ video* video = video::current();
+ ASSERT(video && "should have a video context set");
+
+ // we want to know when the GL context is recreated
+ dispatcher& dispatcher = dispatcher::global();
+ mNewContextDispatch = dispatcher.add_target("video.newcontext",
+ boost::bind(&impl::context_recreated, this));
+ }
+
+ ~impl()
+ {
+ unload_from_gl();
+ }
+
+
+ void init(const std::string& name)
+ {
+ std::string path(name);
+
+ texture::find_path(path);
+
+ mImage = image::alloc(path);
+ if (!mImage->is_valid())
+ {
+ throw std::runtime_error("texture not found: " + name);
+ }
+
+ mImage->flip();
+
+ script script;
+
+ bind_script_constants(script);
+ log::import(script);
+
+ if (script.do_string(mImage->comment()) != script::success)
+ {
+ std::string str;
+ script[-1].get(str);
+ log_warning(str);
+ }
+ else
+ {
+ log_info << "loading tiles from texture " << path
+ << std::endl;
+
+ script::slot globals = script.globals();
+ globals.get(mTilesS, "tiles_s");
+ globals.get(mTilesT, "tiles_t");
+ globals.get(mMinFilter, "min_filter");
+ globals.get(mMagFilter, "mag_filter");
+ globals.get(mWrapS, "wrap_s");
+ globals.get(mWrapT, "wrap_t");
+ }
+ }
+
+
+ /**
+ * Upload the image to GL so that it will be accessible by a much more
+ * manageable handle and hopefully reside in video memory.
+ */
+
+ void upload_to_gl()
+ {
+ if (mObject)
+ {
+ // already loaded
+ return;
+ }
+
+ glGenTextures(1, &mObject);
+ glBindTexture(GL_TEXTURE_2D, mObject);
+
+ glTexImage2D
+ //gluBuild2DMipmaps
+ (
+ GL_TEXTURE_2D,
+ 0,
+ mImage->mode(),
+ //3,
+ mImage->width(),
+ mImage->height(),
+ 0,
+ mImage->mode(),
+ GL_UNSIGNED_BYTE,
+ mImage->pixels()
+ );
+
+ set_properties();
+ }
+
+
+ /**
+ * Sets some texture properties such as the filters and external
+ * coordinate behavior.
+ */
+
+ void set_properties()
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mMinFilter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mMagFilter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mWrapS);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mWrapT);
+ }
+
+ void min_filter(GLuint filter)
+ {
+ bind();
+ mMinFilter = filter;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mMinFilter);
+ }
+
+ void mag_filter(GLuint filter)
+ {
+ bind();
+ mMagFilter = filter;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mMagFilter);
+ }
+
+ void wrap_s(GLuint wrap)
+ {
+ bind();
+ mWrapS = wrap;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mWrapS);
+ }
+
+ void wrap_t(GLuint wrap)
+ {
+ bind();
+ mWrapT = wrap;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mWrapT);
+ }
+
+
+ void bind()
+ {
+ if (mObject == 0)
+ {
+ upload_to_gl();
+ }
+ if (mObject != gObject)
+ {
+ glBindTexture(GL_TEXTURE_2D, mObject);
+ gObject = mObject;
+ }
+ }
+
+
+ bool tile_coordinates(int index, scalar coords[8]) const
+ {
+ // make sure the index represents a real tile
+ if (index < 0 && index >= mTilesS * mTilesT) return false;
+
+ scalar w = 1.0 / scalar(mTilesS);
+ scalar h = 1.0 / scalar(mTilesT);
+
+ coords[0] = scalar(index % mTilesS) * w;
+ coords[1] = (scalar(mTilesT - 1) - scalar(index / mTilesS)) * 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];
+
+ return true;
+ }
+
+ image_ptr mImage;
+
+ GLuint mMinFilter; ///< Minification filter.
+ GLuint mMagFilter; ///< Magnification filter.
+ GLuint mWrapS; ///< Wrapping behavior horizontally.
+ GLuint mWrapT; ///< Wrapping behavior vertically.
+ int mTilesS;
+ int mTilesT;
+
+ GLuint mObject; ///< GL texture handle.
+ static GLuint gObject; ///< Global GL texture handle.
+
+ dispatcher::handle mNewContextDispatch;
+};
+
+GLuint texture::impl::gObject = 0;
+
+
+texture::texture(const std::string& name) : // FIXME: this is really weird
+ image(name),
+ // pass through
+ impl_(texture::impl::instance(name)) {}
+
+
+/**
+ * Bind the GL texture for mapping, etc.
+ */
+
+void texture::bind() const
+{
+ // pass through
+ impl_->bind();
+}
+
+
+/**
+ * Get the texture object, for the curious.
+ */
+
+GLuint texture::object() const
+{
+ // pass through
+ return impl_->mObject;
+}
+
+
+void texture::reset_binding()
+{
+ glBindTexture(GL_TEXTURE_2D, 0);
+ impl::gObject = 0;
+}
+
+
+void texture::min_filter(GLuint filter)
+{
+ // pass through
+ impl_->min_filter(filter);
+}
+
+void texture::mag_filter(GLuint filter)
+{
+ // pass through
+ impl_->mag_filter(filter);
+}
+
+void texture::wrap_s(GLuint wrap)
+{
+ // pass through
+ impl_->wrap_s(wrap);
+}
+
+void texture::wrap_t(GLuint wrap)
+{
+ // pass through
+ impl_->wrap_t(wrap);
+}
+
+
+bool texture::tile_coordinates(int index, scalar coords[8]) const
+{
+ // pass through
+ return impl_->tile_coordinates(index, coords);
+}
+
+bool texture::tile_coordinates(int index, scalar coords[8],
+ orientation orientation) const
+{
+ if (tile_coordinates(index, coords))
+ {
+ if (orientation & flip)
+ {
+ // this looks kinda weird, but it's just swapping in a way that
+ // doesn't require an intermediate variable
+ coords[1] = coords[5];
+ coords[5] = coords[3];
+ coords[3] = coords[7];
+ coords[7] = coords[5];
+ }
+ if (orientation & reverse)
+ {
+ coords[0] = coords[2];
+ coords[2] = coords[6];
+ coords[4] = coords[6];
+ coords[6] = coords[0];
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+bool texture::find_path(std::string& name)
+{
+ return resource::find_path(name, "textures/", "png");
+}
+
+
+} // namespace moof
+
#define _MOOF_TEXTURE_HH_
/**
- * @file Texture.hh
+ * \file texture.hh
* Image-loading and OpenGL texture loading.
*/
#include <boost/shared_ptr.hpp>
-#include <Moof/Image.hh>
-#include <Moof/OpenGL.hh>
+#include <moof/image.hh>
+#include <moof/opengl.hh>
-namespace Mf {
+namespace moof {
-class Texture;
-typedef boost::shared_ptr<Texture> TextureP;
+class texture;
+typedef boost::shared_ptr<texture> texture_ptr;
-class Texture : public Image
+class texture : public image
{
public:
+ static const int no_tile = -1;
+
/**
* Possible orientations for texture coordinates.
*/
-
- typedef unsigned TileIndex;
- static const TileIndex NO_TILE = -1;
-
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;
+ 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;
- static TextureP alloc(const std::string& name)
+ static texture_ptr alloc(const std::string& name)
{
- return TextureP(new Texture(name));
+ return texture_ptr(new texture(name));
}
- explicit Texture(const std::string& name);
+ explicit texture(const std::string& name);
void bind() const;
- GLuint getObject() const;
+ GLuint object() const;
- static void resetBind();
+ static void reset_binding();
- void setMinFilter(GLuint filter);
- void setMagFilter(GLuint filter);
- void setWrapS(GLuint wrap);
- void setWrapT(GLuint wrap);
+ void min_filter(GLuint filter);
+ void mag_filter(GLuint filter);
+ void wrap_s(GLuint wrap);
+ void wrap_t(GLuint wrap);
/**
* 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 scalars where the texture coordinates will
+ * \param index The tile index.
+ * \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
* scalars. The winding of the coordinates is always counter-clockwise
* (the GL default).
- * @return True if index is valid, false otherwise.
+ * \return True if index is valid, false otherwise.
*/
-
- bool getTileCoords(TileIndex index, Scalar coords[8]) const;
-
+ bool tile_coordinates(int index, scalar coords[8]) const;
/**
* This version let's you specify an orientation that will be reflected
* in the texture coordinates. This allows you to easily map a texture
* backwards or upside-down.
- * @param what The orientation; can be flip, reverse, or
+ * \param what The orientation; can be flip, reverse, or
* flip_and_reverse.
- * @return True if index is valid, false otherwise.
+ * \return True if index is valid, false otherwise.
*/
+ bool tile_coordinates(int index, scalar coords[8], orientation what) const;
- bool getTileCoords(TileIndex index, Scalar coords[8],
- Orientation what) const;
+ static bool find_path(std::string& name);
- static bool getPath(std::string& name);
private:
- class Impl;
- boost::shared_ptr<Impl> mImpl;
+ class impl;
+ boost::shared_ptr<impl> impl_;
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_TEXTURE_HH_
**************************************************************************/
/**
- * \file Thread.hh
+ * \file thread.hh
* Light C++ wrapper around the SDL threads API.
*/
#include <boost/function.hpp>
#include <SDL/SDL.h>
-#include <Moof/Math.hh>
+#include <moof/math.hh>
-namespace Mf {
+namespace moof {
/**
* running until the function returns. You don't need to keep the thread
* object you want to wait() or kill() the thread later.
*/
-class Thread
+class thread
{
public:
- typedef boost::function<int(void)> Function;
+ typedef boost::function<int(void)> function;
/**
* Construct an invalid thread object which has no association with any
* real thread.
*/
- Thread() :
- mThread(0) {}
+ thread() :
+ thread_(0) {}
/**
* Execute a function in a new thread.
* \param function The function to execute.
* \return The new thread, or an invalid thread if an error occurred.
*/
- static Thread detach(const Function& function)
+ static thread detach(const function& function)
{
- Function* fcopy = new Function(function);
- SDL_Thread* thread = SDL_CreateThread(&Thread::run, (void*)fcopy);
+ thread::function* fcopy = new thread::function(function);
+ SDL_Thread* thread = SDL_CreateThread(&thread::run, (void*)fcopy);
if (thread == 0) delete fcopy;
- return Thread(thread);
+ return moof::thread(thread);
}
int wait()
{
int i;
- SDL_WaitThread(mThread, &i);
- mThread = 0;
+ SDL_WaitThread(thread_, &i);
+ thread_ = 0;
return i;
}
*/
void kill()
{
- SDL_KillThread(mThread);
- mThread = 0;
+ SDL_KillThread(thread_);
+ thread_ = 0;
}
/**
* thread.
* \return True if the thread is valid, false otherwise.
*/
- bool isValid() const
+ bool is_valid() const
{
- return mThread != 0;
+ return thread_ != 0;
}
*/
uint32_t identifier() const
{
- return SDL_GetThreadID(mThread);
+ return SDL_GetThreadID(thread_);
}
/**
* Get the unique identifier of the calling thread.
* \return The identifier.
*/
- static uint32_t currentIdentifier()
+ static uint32_t current_identifier()
{
return SDL_ThreadID();
}
private:
- Thread(SDL_Thread* thread) :
- mThread(thread) {}
+ thread(SDL_Thread* thread) :
+ thread_(thread) {}
static int run(void* arg)
{
- int code = (*(Function*)arg)();
- delete (Function*)arg;
+ int code = (*(function*)arg)();
+ delete (function*)arg;
return code;
}
- SDL_Thread* mThread;
+ SDL_Thread* thread_;
};
* An abstract class representing some task that is to be run
* asynchronously.
*/
-class AsyncTask
+class async_task
{
public:
/**
* Deconstruct the task.
*/
- virtual ~AsyncTask() {}
+ virtual ~async_task() {}
/**
* Get whether or not the task is done.
* \return True if the task is done, false otherwise.
*/
- virtual bool isDone() const = 0;
+ virtual bool is_done() const = 0;
/**
* Begin the task.
/**
* An asynchronous task that is run to be executed in a separated thread.
*/
-class ThreadedTask
+class threaded_task
{
public:
* Get the thread object the task is executing in.
* \return The thread.
*/
- const Thread& thread() const { return mThread; }
+ const class thread& thread() const { return thread_; }
/**
* Block the current thread until the task thread is finished.
*/
int wait()
{
- return mThread.wait();
+ return thread_.wait();
}
protected:
- Thread mThread;
+ class thread thread_;
};
* A mutex to protect sensitive sections of code from threads which might
* otherwise cause unpredictable results.
*/
-class Mutex
+class mutex
{
public:
/**
* Construct a mutex.
*/
- Mutex() :
- mMutex(SDL_CreateMutex()) {}
+ mutex() :
+ mutex_(SDL_CreateMutex()) {}
/**
* Deconstruct a mutex.
*/
- ~Mutex()
+ ~mutex()
{
- SDL_DestroyMutex(mMutex);
+ SDL_DestroyMutex(mutex_);
}
* Block until the calling thread can secure exclusive access to the
* code protected by the mutex.
* \return True if the lock was acquired, false otherwise.
- * \see Lock
+ * \see lock
*/
- bool acquireLock()
+ bool acquire_lock()
{
- return (SDL_LockMutex(mMutex) == 0);
+ return (SDL_LockMutex(mutex_) == 0);
}
/**
* Unlock the mutex. Call this after the sensitive block of code to
* allow another thread to acquire the lock.
* \return True if the mutex was unlocked, false otherwise.
- * \see Lock
+ * \see lock
*/
- bool releaseLock()
+ bool release_lock()
{
- return (SDL_UnlockMutex(mMutex) == 0);
+ return (SDL_UnlockMutex(mutex_) == 0);
}
* deconstruction. Therefore, it's generally safer to use this method
* since it makes it much more difficult to forget to unlock a mutex.
*/
- class Lock
+ class lock
{
public:
* Construct a lock.
* \param mutex The mutex.
*/
- explicit Lock(Mutex& mutex) :
- mMutex(mutex),
- mIsLocked(false) {}
+ explicit lock(mutex& mutex) :
+ mutex_(mutex),
+ is_locked_(false) {}
/**
* Deconstruct a lock. The lock is automagically released if it is
* still locked.
*/
- ~Lock()
+ ~lock()
{
- if (mIsLocked) release();
+ if (is_locked_) release();
}
*/
bool acquire()
{
- return (mIsLocked = mMutex.acquireLock());
+ return (is_locked_ = mutex_.acquire_lock());
}
/**
*/
bool release()
{
- bool result = mMutex.releaseLock();
- mIsLocked = false;
+ bool result = mutex_.release_lock();
+ is_locked_ = false;
return result;
}
* Get whether or not the mutex is locked.
* \return True if the mutex is locked, false otherwise.
*/
- bool isLocked() const
+ bool is_locked() const
{
- return mIsLocked;
+ return is_locked_;
}
protected:
- Mutex& mMutex;
- bool mIsLocked;
+ mutex& mutex_;
+ bool is_locked_;
- friend class Condition;
+ friend class condition;
};
/**
* This type of lock tries to acquire a lock on the mutex during
* construction and releases the lock on deconstruction.
*/
- class ScopedLock : private Lock
+ class scoped_lock : private lock
{
public:
* Construct a lock.
* \param mutex The mutex.
*/
- explicit ScopedLock(Mutex& mutex) :
- Lock(mutex)
+ explicit scoped_lock(mutex& mutex) :
+ lock(mutex)
{
acquire();
}
* Get whether or not the mutex is locked.
* \return True if the mutex is locked, false otherwise.
*/
- bool isLocked() const
+ bool is_locked() const
{
- return Lock::isLocked();
+ return lock::is_locked();
}
};
private:
- SDL_mutex* mMutex;
+ SDL_mutex* mutex_;
- friend class Condition;
+ friend class condition;
};
/**
* A class representing a condition variable.
*/
-class Condition
+class condition
{
public:
/**
* Construct a condition.
*/
- Condition()
+ condition()
{
- mCondition = SDL_CreateCond();
+ condition_ = SDL_CreateCond();
}
/**
* Deconstruct a condition.
*/
- ~Condition()
+ ~condition()
{
- SDL_DestroyCond(mCondition);
+ SDL_DestroyCond(condition_);
}
* \param mutex The mutex.
* \return True if the thread was notified, false otherwise.
*/
- bool wait(Mutex& mutex)
+ bool wait(mutex& mutex)
{
- return (SDL_CondWait(mCondition, mutex.mMutex) == 0);
+ return (SDL_CondWait(condition_, mutex.mutex_) == 0);
}
/**
* \param lock The lock.
* \return True if the thread was notified, false otherwise.
*/
- bool wait(Mutex::Lock& lock)
+ bool wait(mutex::lock& lock)
{
- return (SDL_CondWait(mCondition, lock.mMutex.mMutex) == 0);
+ return (SDL_CondWait(condition_, lock.mutex_.mutex_) == 0);
}
/**
* \param timeout Number of seconds to wait.
* \return True if the thread was notified, false otherwise.
*/
- bool wait(Mutex& mutex, Scalar timeout)
+ bool wait(mutex& mutex, scalar timeout)
{
Uint32 ms = timeout * SCALAR(1000.0);
- return (SDL_CondWaitTimeout(mCondition, mutex.mMutex, ms) == 0);
+ return (SDL_CondWaitTimeout(condition_, mutex.mutex_, ms) == 0);
}
/**
* \param timeout Number of seconds to wait.
* \return True if the thread was notified, false otherwise.
*/
- bool wait(Mutex::Lock& lock, Scalar timeout)
+ bool wait(mutex::lock& lock, scalar timeout)
{
Uint32 ms = timeout * SCALAR(1000.0);
- return (SDL_CondWaitTimeout(mCondition,
- lock.mMutex.mMutex, ms) == 0);
+ return (SDL_CondWaitTimeout(condition_,
+ lock.mutex_.mutex_, ms) == 0);
}
*/
bool notify()
{
- return (SDL_CondSignal(mCondition) == 0);
+ return (SDL_CondSignal(condition_) == 0);
}
/**
* Notify all other threads that are waiting on the condition.
* \return True on success, false otherwise.
*/
- bool notifyAll()
+ bool notify_all()
{
- return (SDL_CondBroadcast(mCondition) == 0);
+ return (SDL_CondBroadcast(condition_) == 0);
}
private:
- SDL_cond* mCondition;
+ SDL_cond* condition_;
};
/**
* A semaphore class.
*/
-class Semaphore
+class semaphore
{
public:
* Construct a semaphore.
* \param value The initial value of the semaphore.
*/
- explicit Semaphore(uint32_t value)
+ explicit semaphore(uint32_t value)
{
- mSemaphore = SDL_CreateSemaphore(value);
+ semaphore_ = SDL_CreateSemaphore(value);
}
/**
* Deconstruct a semaphore.
*/
- ~Semaphore()
+ ~semaphore()
{
- SDL_DestroySemaphore(mSemaphore);
+ SDL_DestroySemaphore(semaphore_);
}
* Block until the calling thread can secure exclusive access to the
* code protected by the semaphore.
* \return True if the lock was acquired, false otherwise.
- * \see Lock
+ * \see lock
*/
- bool acquireLock()
+ bool acquire_lock()
{
- return (SDL_SemWait(mSemaphore) == 0);
+ return (SDL_SemWait(semaphore_) == 0);
}
/**
* \param timeout Number of seconds to try.
* \return True if the lock was acquired, false otherwise.
*/
- bool acquireLock(Scalar timeout)
+ bool acquire_lock(scalar timeout)
{
Uint32 ms = timeout * SCALAR(1000.0);
- return (SDL_SemWaitTimeout(mSemaphore, ms) == 0);
+ return (SDL_SemWaitTimeout(semaphore_, ms) == 0);
}
/**
* Unlock the semaphore. Call this after the sensitive block of code
* to allow another thread to acquire the lock.
* \return True if the semaphore was unlocked, false otherwise.
- * \see Lock
+ * \see lock
*/
- bool releaseLock()
+ bool release_lock()
{
- return (SDL_SemPost(mSemaphore) == 0);
+ return (SDL_SemPost(semaphore_) == 0);
}
/**
* immediately available.
* \return True if the semaphore was locked, false otherwise.
*/
- bool tryLock()
+ bool try_lock()
{
- return (SDL_SemTryWait(mSemaphore) == 0);
+ return (SDL_SemTryWait(semaphore_) == 0);
}
/**
* since it makes it much more difficult to forget to unlock a
* semaphore.
*/
- class Lock
+ class lock
{
public:
* Construct a lock.
* \param semaphore The semaphore.
*/
- explicit Lock(Semaphore& semaphore) :
- mSemaphore(semaphore),
- mIsLocked(false) {}
+ explicit lock(semaphore& semaphore) :
+ semaphore_(semaphore),
+ is_locked_(false) {}
/**
* Deconstruct a lock. The lock is automagically released if it is
* still locked.
*/
- ~Lock()
+ ~lock()
{
- if (mIsLocked) release();
+ if (is_locked_) release();
}
*/
bool acquire()
{
- return (mIsLocked = mSemaphore.acquireLock());
+ return (is_locked_ = semaphore_.acquire_lock());
}
/**
*/
bool release()
{
- bool result = mSemaphore.releaseLock();
- mIsLocked = false;
+ bool result = semaphore_.release_lock();
+ is_locked_ = false;
return result;
}
* Get whether or not the semaphore is locked.
* \return True if the semaphore is locked, false otherwise.
*/
- bool isLocked() const
+ bool is_locked() const
{
- return mIsLocked;
+ return is_locked_;
}
protected:
- Semaphore& mSemaphore;
- bool mIsLocked;
+ semaphore& semaphore_;
+ bool is_locked_;
};
/**
* This type of lock tries to acquire a lock on the semaphore during
* construction and releases the lock on deconstruction.
*/
- class ScopedLock : private Lock
+ class scoped_lock : private lock
{
public:
* Construct a lock.
* \param semaphore The semaphore.
*/
- explicit ScopedLock(Semaphore& semaphore) :
- Lock(semaphore)
+ explicit scoped_lock(semaphore& semaphore) :
+ lock(semaphore)
{
acquire();
}
* Get whether or not the semaphore is locked.
* \return True if the semaphore is locked, false otherwise.
*/
- bool isLocked() const
+ bool is_locked() const
{
- return Lock::isLocked();
+ return lock::is_locked();
}
};
private:
- SDL_sem* mSemaphore;
+ SDL_sem* semaphore_;
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_THREAD_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <cerrno>
+#include <ctime>
+#include <limits>
+
+#include <SDL/SDL.h>
+
+#include "log.hh"
+#include "timer.hh"
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+namespace moof {
+
+
+scalar timer::gNextFire = std::numeric_limits<scalar>::max();
+std::map<unsigned,timer*> timer::gTimers;
+
+
+unsigned timer::new_identifier()
+{
+ static unsigned id = 1;
+ return id++;
+}
+
+
+void timer::init(const function& function, scalar seconds, mode mode)
+{
+ invalidate();
+
+ mode_ = mode;
+
+ if (mode_ != invalid)
+ {
+ function_ = function;
+
+ if (mode == absolute)
+ {
+ absolute_ = seconds;
+ }
+ else
+ {
+ absolute_ = seconds - ticks();
+ interval_ = seconds;
+ }
+
+ id_ = new_identifier();
+ gTimers.insert(std::pair<unsigned,timer*>(id_, this));
+
+ if (absolute_ < gNextFire) gNextFire = absolute_;
+ }
+}
+
+
+bool timer::is_valid() const
+{
+ return mode_ != invalid;
+}
+
+void timer::invalidate()
+{
+ if (mode_ != invalid)
+ {
+ gTimers.erase(id_);
+ mode_ = invalid;
+
+ if (is_equal(absolute_, gNextFire)) gNextFire = find_next_expiration();
+ }
+}
+
+
+void timer::fire()
+{
+ scalar t = ticks();
+
+ if (function_) function_(*this, t);
+
+ if (is_repeating())
+ {
+ scalar absolute = absolute_;
+
+ if (is_equal(absolute_, t, 1.0)) absolute_ += interval_;
+ else absolute_ = interval_ + t;
+
+ if (is_equal(absolute, gNextFire)) gNextFire = find_next_expiration();
+ }
+ else
+ {
+ invalidate();
+ }
+}
+
+
+scalar timer::find_next_expiration()
+{
+ std::map<unsigned,timer*>::iterator it;
+ scalar nextFire = std::numeric_limits<scalar>::max();
+
+ for (it = gTimers.begin(); it != gTimers.end(); ++it)
+ {
+ scalar absolute = (*it).second->absolute_;
+ if (absolute < nextFire) nextFire = absolute;
+ }
+
+ return nextFire;
+}
+
+
+scalar timer::seconds_remaining() const
+{
+ return absolute_ - ticks();
+}
+
+bool timer::is_expired() const
+{
+ return seconds_remaining() < 0.0;
+}
+
+bool timer::is_repeating() const
+{
+ return mode_ == repeat;
+}
+
+
+void timer::fire_expired_timers()
+{
+ fire_expired_timers(ticks());
+}
+
+void timer::fire_expired_timers(scalar t)
+{
+ std::map<unsigned,timer*>::iterator it;
+
+ if (gNextFire > t) return;
+
+ for (it = gTimers.begin(); it != gTimers.end(); ++it)
+ {
+ timer* timer = (*it).second;
+ if (timer->is_expired()) timer->fire();
+ }
+}
+
+
+#if HAVE_CLOCK_GETTIME
+
+// Since the monotonic clock will provide us with the time 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 uptime), 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-precision number.
+
+static time_t set_reference()
+{
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
+ {
+ return 0;
+ }
+
+ return ts.tv_sec;
+}
+
+static const time_t reference = set_reference();
+
+
+scalar timer::ticks()
+{
+ struct timespec ts;
+
+ int result = clock_gettime(CLOCK_MONOTONIC, &ts);
+ ASSERT(result == 0 && "cannot access clock");
+
+ return scalar(ts.tv_sec - reference) +
+ scalar(ts.tv_nsec) / 1000000000.0;
+}
+
+void timer::sleep(scalar seconds, mode mode)
+{
+ struct timespec ts;
+ int ret;
+
+ if (mode == absolute) seconds -= ticks();
+ ts.tv_sec = time_t(seconds);
+ ts.tv_nsec = long((seconds - scalar(ts.tv_sec)) * 1000000000.0);
+
+ do
+ {
+ ret = nanosleep(&ts, &ts);
+ }
+ while (ret == -1 && errno == EINTR);
+}
+
+
+#else // ! HAVE_CLOCK_GETTIME
+
+
+// If we don't have posix timers, we'll have to use a different timing
+// method. SDL only promises centisecond accuracy, but that's better than
+// a kick in the pants.
+
+scalar timer::ticks()
+{
+ Uint32 ms = SDL_GetTicks();
+ return scalar(ms / 1000) + scalar(ms % 1000) / 1000.0;
+}
+
+void timer::sleep(scalar seconds, mode mode)
+{
+ if (mode == absolute) seconds -= ticks();
+ SDL_Delay(Uint32(clamp(int(seconds * 1000.0), 0, 1000)));
+}
+
+#endif // HAVE_CLOCK_GETTIME
+
+
+} // namespace moof
+
#define _MOOF_TIMER_HH_
/**
- * @file Timer.hh
+ * \file timer.hh
* Functions for measuring time in a friendly unit.
*/
#include <boost/bind.hpp>
#include <boost/function.hpp>
-#include <Moof/Math.hh>
+#include <moof/math.hh>
-namespace Mf {
+namespace moof {
-class Timer
+class timer
{
public:
- enum Mode
+ enum mode
{
- INVALID = -1,
- NORMAL = 0,
- ACTUAL = 1,
- REPEAT = 2
+ invalid = -1,
+ normal = 0,
+ absolute = 1,
+ repeat = 2
};
- typedef boost::function<void(Timer&,Scalar)> Function;
+ typedef boost::function<void(timer&,scalar)> function;
- Timer() :
- mMode(INVALID) {}
+ timer() :
+ mode_(invalid) {}
- Timer(const Function& function, Scalar seconds, Mode mode = NORMAL)
+ timer(const function& function, scalar seconds, mode mode = normal)
{
init(function, seconds, mode);
}
- ~Timer()
+ ~timer()
{
invalidate();
}
- void init(const Function& function, Scalar seconds,
- Mode mode = NORMAL);
+ void init(const function& function, scalar seconds, mode mode = normal);
- bool isValid() const;
+ bool is_valid() const;
void invalidate();
void fire();
- Scalar getSecondsRemaining() const;
- bool isExpired() const;
- bool isRepeating() const;
+ scalar seconds_remaining() const;
+ bool is_expired() const;
+ bool is_repeating() const;
/**
* Get the number of seconds since a fixed, arbitrary point in the
* past.
- * @return Seconds.
+ * \return Seconds.
*/
-
- static Scalar getTicks();
+ static scalar ticks();
/**
* sleep if sleep was interrupted by a signal. Therefore, calling this
* function is guaranteed to sleep for the requested amount of time
* (and maybe longer).
+ * \param seconds Number of seconds.
+ * \param mode The timer mode.
*/
-
- static void sleep(Scalar seconds, Mode mode = NORMAL);
+ static void sleep(scalar seconds, mode mode = normal);
- static Scalar getNextFire()
+ static scalar next_expiration()
{
return gNextFire;
}
- static void fireIfExpired();
- static void fireIfExpired(Scalar t);
+ static void fire_expired_timers();
+ static void fire_expired_timers(scalar t);
+
private:
- static unsigned getNewID();
- static Scalar findNextFire();
+ static unsigned new_identifier();
+ static scalar find_next_expiration();
- Function mFunction;
- Mode mMode;
- Scalar mAbsolute;
- Scalar mInterval;
- unsigned mId;
+ function function_;
+ mode mode_;
+ scalar absolute_;
+ scalar interval_;
+ unsigned id_;
- static Scalar gNextFire;
- static std::map<unsigned,Timer*> gTimers;
+ static scalar gNextFire;
+ static std::map<unsigned,timer*> gTimers;
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_TIMER_HH_
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <stdexcept>
+
+#include "dispatcher.hh"
+#include "image.hh"
+#include "log.hh"
+#include "settings.hh"
+#include "video.hh"
+
+
+namespace moof {
+
+
+video::video(const std::string& caption)
+{
+ video::caption(caption);
+ init();
+}
+
+video::video(const class attributes& attribs) :
+ attributes_(attribs)
+{
+ init();
+}
+
+video::video(const std::string& caption,
+ const class attributes& attribs) :
+ attributes_(attribs)
+{
+ video::caption(caption);
+ init();
+}
+
+void video::init()
+{
+ context_ = 0;
+ flags_ = 0;
+
+ fullscreen(attributes_.is_fullscreen);
+ resizable(attributes_.is_resizable);
+ set_opengl_attributes();
+ cursor_visible(attributes_.is_cursor_visible);
+ cursor_captured(attributes_.is_cursor_captured);
+ mode(attributes_.mode);
+
+ if (!current_) make_current();
+}
+
+void video::recreate_context()
+{
+ SDL_FreeSurface(context_);
+ context_ = 0;
+ mode(attributes_.mode);
+}
+
+void video::set_opengl_attributes()
+{
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE,
+ attributes_.color_buffer[0]);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,
+ attributes_.color_buffer[1]);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,
+ attributes_.color_buffer[2]);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,
+ attributes_.color_buffer[3]);
+ SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,
+ attributes_.frame_buffer);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,
+ attributes_.is_double_buffer);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,
+ attributes_.depth_buffer);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,
+ attributes_.stencil_buffer);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE,
+ attributes_.accumulator_buffer[0]);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE,
+ attributes_.accumulator_buffer[1]);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE,
+ attributes_.accumulator_buffer[2]);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE,
+ attributes_.accumulator_buffer[3]);
+ SDL_GL_SetAttribute(SDL_GL_STEREO,
+ attributes_.is_stereo);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,
+ attributes_.multisample_buffers);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES,
+ attributes_.multisample_samples);
+ SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL,
+ attributes_.is_swap_control);
+ SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,
+ attributes_.is_hardware_only);
+}
+
+
+video::~video()
+{
+ SDL_FreeSurface(context_);
+
+ if (current_ == this) current_ = 0;
+}
+
+
+class video::attributes video::attributes() const
+{
+ return attributes_;
+}
+
+
+void video::mode(const int mode[3])
+{
+ if (mode != attributes_.mode || !context_)
+ {
+ if (context_) SDL_FreeSurface(context_);
+
+ context_ = SDL_SetVideoMode(mode[0], mode[1], mode[2],
+ SDL_OPENGL | flags_);
+
+ if (context_)
+ {
+ attributes_.mode[0] = mode[0];
+ attributes_.mode[1] = mode[1];
+ attributes_.mode[2] = mode[2];
+
+#if !defined(linux) && !defined(__linux) && !defined(__linux__)
+ log_info("video context recreated");
+ dispatcher::global().dispatch("video.newcontext");
+#endif
+ }
+ else
+ {
+ throw std::runtime_error("bad video mode attempted");
+ }
+ }
+}
+
+
+void video::resize(int width, int height)
+{
+ int mode[] = {width, height, attributes_.mode[2]};
+ video::mode(mode);
+}
+
+bool video::iconify()
+{
+ return SDL_WM_IconifyWindow();
+}
+
+
+void video::caption(const std::string& caption)
+{
+ SDL_WM_SetCaption(caption.c_str(), 0);
+}
+
+std::string video::caption() const
+{
+ char* caption;
+ SDL_WM_GetCaption(&caption, 0);
+ return std::string(caption);
+}
+
+
+void video::fullscreen(bool full)
+{
+ if (full != fullscreen() || !context_)
+ {
+ if (context_)
+ {
+ flags_ ^= SDL_FULLSCREEN;
+
+#if defined(linux) || defined(__linux) || defined(__linux__)
+ if (SDL_WM_ToggleFullScreen(context_) == 0)
+#endif
+ recreate_context();
+ }
+ else
+ {
+ if (full) flags_ |= SDL_FULLSCREEN;
+ else flags_ &= ~SDL_FULLSCREEN;
+ }
+ }
+}
+
+bool video::fullscreen() const
+{
+ return flags_ & SDL_FULLSCREEN;
+}
+
+void video::toggle_fullscreen()
+{
+ fullscreen(!fullscreen());
+}
+
+
+void video::resizable(bool is_resizable)
+{
+ if (is_resizable != resizable() || !context_)
+ {
+ if (context_)
+ {
+ flags_ ^= SDL_RESIZABLE;
+ recreate_context();
+ }
+ else
+ {
+ if (is_resizable) flags_ |= SDL_RESIZABLE;
+ else flags_ &= ~SDL_RESIZABLE;
+ }
+ }
+}
+
+bool video::resizable() const
+{
+ return flags_ & SDL_RESIZABLE;
+}
+
+void video::toggle_resizable()
+{
+ resizable(!resizable());
+}
+
+
+void video::cursor_visible(bool is_cursor_visible)
+{
+ SDL_ShowCursor(is_cursor_visible? SDL_ENABLE : SDL_DISABLE);
+}
+
+bool video::cursor_visible() const
+{
+ return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE);
+}
+
+void video::toggle_cursor_visible()
+{
+ cursor_visible(!cursor_visible());
+}
+
+
+bool video::cursor_captured() const
+{
+ return (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON);
+}
+
+void video::cursor_captured(bool is_cursor_captured)
+{
+ SDL_WM_GrabInput(is_cursor_captured? SDL_GRAB_ON : SDL_GRAB_OFF);
+}
+
+void video::toggle_cursor_captured()
+{
+ cursor_captured(!cursor_captured());
+}
+
+
+void video::swap()
+{
+ SDL_GL_SwapBuffers();
+}
+
+
+int video::width() const
+{
+ return context_->w;
+}
+
+int video::height() const
+{
+ return context_->h;
+}
+
+
+void video::make_current() const
+{
+ current_ = const_cast<video*>(this);
+}
+
+
+video::attributes::attributes()
+{
+ init();
+}
+
+video::attributes::attributes(const settings& settings)
+{
+ init();
+
+ std::vector<int> colors;
+ settings.get("colorbuffers", colors);
+ if (colors.size() > 0) color_buffer[0] = colors[0];
+ if (colors.size() > 1) color_buffer[1] = colors[1];
+ if (colors.size() > 2) color_buffer[2] = colors[2];
+ if (colors.size() > 3) color_buffer[3] = colors[3];
+
+ settings.get("framebuffer", frame_buffer);
+ settings.get("doublebuffer", is_double_buffer);
+ settings.get("depthbuffer", depth_buffer);
+ settings.get("stencilbuffer", stencil_buffer);
+
+ std::vector<int> accum;
+ settings.get("accumbuffers", accum);
+ if (accum.size() > 0) accumulator_buffer[0] = accum[0];
+ if (accum.size() > 1) accumulator_buffer[1] = accum[1];
+ if (accum.size() > 2) accumulator_buffer[2] = accum[2];
+ if (accum.size() > 3) accumulator_buffer[3] = accum[3];
+
+ settings.get("stereo", is_stereo);
+ settings.get("multiesamplebuffers", multisample_buffers);
+ settings.get("multiesamplesamples", multisample_samples);
+ settings.get("swapcontrol", is_swap_control);
+ settings.get("hardwareonly", is_hardware_only);
+
+ settings.get("fullscreen", is_fullscreen);
+ settings.get("resizable", is_resizable);
+ settings.get("showcursor", is_cursor_visible);
+ settings.get("grab", is_cursor_captured);
+
+ std::vector<int> dimensions;
+ settings.get("videomode", dimensions);
+ if (dimensions.size() > 1)
+ {
+ mode[0] = dimensions[0];
+ mode[1] = dimensions[1];
+ }
+ else if (is_fullscreen && backend::is_initialized())
+ {
+ SDL_Rect** modes = SDL_ListModes(NULL,
+ SDL_FULLSCREEN | SDL_HWSURFACE);
+
+ if (modes == (SDL_Rect**)0)
+ {
+ log_error("no native video mode");
+ }
+ else if (modes == (SDL_Rect**)-1)
+ {
+ log_warning("any resolution allowed; "
+ "choosing default 800x600");
+ mode[0] = 800;
+ mode[1] = 600;
+ }
+ else
+ {
+ mode[0] = (*modes)->w;
+ mode[1] = (*modes)->h;
+ log_info << "choosing native resolution "
+ << mode[0] << "x" << mode[1] << std::endl;
+ }
+ }
+ if (dimensions.size() > 2) mode[2] = dimensions[2];
+}
+
+void video::attributes::init()
+{
+ // set some sane GL and window defaults (see SDL_video.c:217)
+ color_buffer[0] = 3;
+ color_buffer[1] = 3;
+ color_buffer[2] = 2;
+ color_buffer[3] = 0;
+ frame_buffer = 0;
+ is_double_buffer = true;
+ depth_buffer = 16;
+ stencil_buffer = 0;
+ accumulator_buffer[0] = 0;
+ accumulator_buffer[1] = 0;
+ accumulator_buffer[2] = 0;
+ accumulator_buffer[3] = 0;
+ is_stereo = false;
+ multisample_buffers = 0;
+ multisample_samples = 0;
+ is_swap_control = false;
+ is_hardware_only = false;
+ mode[0] = 640;
+ mode[1] = 480;
+ mode[2] = 0;
+ is_fullscreen = false;
+ is_resizable = false;
+ is_cursor_visible = true;
+ is_cursor_captured = false;
+}
+
+
+video* video::current_ = 0; // most recently instantiated instance
+
+
+} // namespace moof
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_VIDEO_HH_
+#define _MOOF_VIDEO_HH_
+
+/**
+ * \file video.hh
+ * Classes for managing a video context.
+ */
+
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+#include <SDL/SDL.h>
+
+#include <moof/backend.hh>
+
+
+namespace moof {
+
+
+class settings;
+
+class video;
+typedef boost::shared_ptr<video> video_ptr;
+
+
+class video
+{
+public:
+
+ struct attributes
+ {
+ int color_buffer[4]; // rgba
+ int frame_buffer;
+ bool is_double_buffer;
+ int depth_buffer;
+ int stencil_buffer;
+ int accumulator_buffer[4]; // rgba
+ bool is_stereo;
+ int multisample_buffers;
+ int multisample_samples;
+ bool is_swap_control;
+ bool is_hardware_only;
+ int mode[3]; // width, height, bpp
+ bool is_fullscreen;
+ bool is_resizable;
+ bool is_cursor_visible;
+ bool is_cursor_captured;
+
+ attributes();
+ attributes(const settings& settings);
+
+ private:
+
+ void init();
+
+ backend mBackend;
+ };
+
+
+ static video_ptr alloc(const attributes& attribs)
+ {
+ return video_ptr(new video(attribs));
+ }
+
+ explicit video(const std::string& caption = "Moof!!");
+ explicit video(const class attributes& attribs);
+ explicit video(const std::string& caption,
+ const class attributes& attribs);
+ ~video();
+
+ class attributes attributes() const;
+
+ void mode(const int mode[3]);
+
+ void resize(int width, int height);
+ bool iconify();
+
+ void caption(const std::string& caption);
+ std::string caption() const;
+
+ void fullscreen(bool full);
+ bool fullscreen() const;
+ void toggle_fullscreen();
+
+ void resizable(bool is_resizable);
+ bool resizable() const;
+ void toggle_resizable();
+
+ void cursor_visible(bool is_cursor_visible);
+ bool cursor_visible() const;
+ void toggle_cursor_visible();
+
+ void cursor_captured(bool is_cursor_captured);
+ bool cursor_captured() const;
+ void toggle_cursor_captured();
+
+
+ /**
+ * Swap the video buffers if double-buffered.
+ */
+ void swap();
+
+
+ /**
+ * Make this video context the current context which will be effected
+ * by future draw commands.
+ */
+ void make_current() const;
+
+ /**
+ * Get the current video context where draw commands are sent.
+ */
+ static video* current()
+ {
+ return current_;
+ }
+
+
+ /**
+ * Get the width of the video display.
+ * \return The pixel width.
+ */
+ int width() const;
+
+ /**
+ * Get the height of the video display.
+ * \return The pixel height.
+ */
+ int height() const;
+
+
+private:
+
+ void init();
+
+ void recreate_context();
+ void set_opengl_attributes();
+
+ // TODO: this implementation is not well hidden
+
+ SDL_Surface* context_;
+ int flags_;
+ class attributes attributes_;
+
+ static video* current_;
+};
+
+
+} // namespace moof
+
+#endif // _MOOF_VIDEO_HH_
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <algorithm>
+#include <cstdlib> // exit, srand
+#include <ctime> // time
+#include <string>
+
+#include <SDL/SDL.h>
+#include "fastevents.h"
+
+#include "event.hh"
+#include "log.hh"
+#include "math.hh"
+#include "modal_dialog.hh"
+#include "settings.hh"
+#include "timer.hh"
+#include "video.hh"
+#include "view.hh"
+
+
+namespace moof {
+
+
+class root_view : public view
+{
+ void update(scalar t, scalar dt)
+ {
+ if (children().size() == 0) stop();
+ }
+};
+
+static root_view gRootView;
+
+
+class view::impl
+{
+public:
+
+ impl(view* view, moof::settings& settings, moof::video& video) :
+ view_(*view),
+ settings_(&settings),
+ video_(&video),
+ parent_(&gRootView)
+ {
+ init();
+
+ unsigned randomSeed;
+ if (settings.get("rngseed", randomSeed)) srand(randomSeed);
+ else srand(time(0));
+
+ scalar timestep = 80.0;
+ settings.get("timestep", timestep);
+ timestep_ = 1.0 / timestep;
+
+ scalar framerate = 40.0;
+ settings.get("framerate", framerate);
+ framerate_ = 1.0 / framerate;
+
+ show_fps_ = false;
+ settings.get("showfps", show_fps_);
+ }
+
+ impl(view* view) :
+ view_(*view),
+ settings_(0),
+ video_(0),
+ parent_(&gRootView)
+ {
+ init();
+ }
+
+ void init()
+ {
+ timestep_ = SCALAR(0.01);
+ framerate_ = SCALAR(0.02);
+ show_fps_ = false;
+ }
+
+
+ /**
+ * The main loop. This just calls dispatch_events(), update(), and
+ * draw() over and over again. The timing of the update and draw are
+ * decoupled. The actual frame rate is also calculated here. This
+ * function will return the exit code used to stop the loop.
+ */
+
+ void run()
+ {
+ ASSERT(video_ && "running without video set");
+
+ scalar totalTime = 0.0;
+ scalar ticks = timer::ticks();
+
+ scalar nextUpdate = ticks;
+ scalar nextDraw = ticks;
+ scalar nextSecond = ticks + SCALAR(1.0);
+
+ fps_ = 0;
+ int frameCount = 0;
+
+ const scalar timestep = timestep_;
+ const scalar framerate = framerate_;
+
+ const int MAX_FRAMESKIP = 15;
+ const scalar inverseTimestep = SCALAR(1.0) / timestep;
+
+ is_running_ = true;
+ for (;;)
+ {
+ timer::fire_expired_timers(); // 1. fire timers
+ dispatch_events(); // 2. dispatch events
+
+ if (!is_running_) break;
+
+ int i = 0;
+ while (nextUpdate < timer::ticks() && i < MAX_FRAMESKIP)
+ {
+ totalTime += timestep; // 3. update state
+ view_.update(totalTime, timestep);
+
+ nextUpdate += timestep;
+ ++i;
+
+ if (!is_running_) break;
+ }
+
+ if (nextDraw < (ticks = timer::ticks()))
+ {
+ view_.draw(
+ (ticks + timestep - nextUpdate) * inverseTimestep);
+ video_->swap(); // 4. draw state
+
+ nextDraw += framerate;
+ ++frameCount;
+
+ if (nextSecond < timer::ticks())
+ {
+ fps_ = frameCount;
+ frameCount = 0;
+
+ if (show_fps_) log_info << fps_ << " fps" << std::endl;
+
+ nextSecond += SCALAR(1.0);
+ }
+ }
+
+ if (!is_running_) break;
+
+ ticks = timer::ticks(); // 5. yield timeslice
+ if (ticks < nextUpdate && ticks < nextDraw) timer::sleep(0.0);
+ }
+ }
+
+ void stop()
+ {
+ is_running_ = false;
+ }
+
+
+ void dispatch_events()
+ {
+ event event;
+
+ while (FE_PollEvent(&event) == 1)
+ {
+ switch (event.type)
+ {
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_ESCAPE &&
+ (SDL_GetModState() & KMOD_CTRL) )
+ {
+ // emergency escape
+ log_warning("escape forced");
+ exit(1);
+ }
+ break;
+
+ case SDL_VIDEORESIZE:
+ video_->resize(event.resize.w, event.resize.h);
+ break;
+ }
+
+ view_.handle_event(event);
+ }
+ }
+
+ bool handle_event(const event& event)
+ {
+ std::list<view_ptr>::iterator it;
+ for (it = children_.begin(); it != children_.end(); ++it)
+ {
+ if ((*it)->handle_event(event)) return true;
+ }
+
+ return false;
+ }
+
+ void update(scalar t, scalar dt)
+ {
+ std::list<view_ptr>::iterator it;
+ for (it = children_.begin(); it != children_.end(); ++it)
+ {
+ (*it)->update(t, dt);
+ }
+ }
+
+ void draw(scalar alpha)
+ {
+ std::list<view_ptr>::iterator it;
+ for (it = children_.begin(); it != children_.end(); ++it)
+ {
+ (*it)->draw(alpha);
+ }
+ }
+
+
+ void add_child(view_ptr child)
+ {
+ ASSERT(child && "adding null view");
+ ASSERT(child.get() != &view_ && "adding view to itself");
+
+ child->impl_->parent_->remove_child(child);
+ children_.push_back(child);
+
+ child->impl_->parent_ = &view_;
+ child->impl_->percolate_objects();
+
+ child->did_add_to_view();
+ }
+
+ void percolate_objects()
+ {
+ bool recurseAgain = false;
+
+ if (parent_->impl_->video_ && parent_->impl_->video_ != video_)
+ {
+ video_ = parent_->impl_->video_;
+ recurseAgain = true;
+ }
+
+ if (parent_->impl_->settings_ &&
+ parent_->impl_->settings_ != settings_)
+ {
+ settings_ = parent_->impl_->settings_;
+ recurseAgain = true;
+ }
+
+ if (recurseAgain)
+ {
+ std::list<view_ptr>::iterator it;
+ for (it = children_.begin(); it != children_.end(); ++it)
+ {
+ (*it)->impl_->percolate_objects();
+ }
+ }
+ }
+
+ view_ptr remove_child(view* child)
+ {
+ ASSERT(child && "cannot remove null child");
+
+ std::list<view_ptr>::iterator it;
+ for (it = children_.begin(); it != children_.end(); ++it)
+ {
+ if ((*it).get() == child)
+ {
+ view_ptr found = *it;
+ found->will_remove_from_view();
+ children_.erase(it);
+
+ found->impl_->parent_ = &gRootView;
+
+ return found;
+ }
+ }
+
+ return view_ptr();
+ }
+
+ void clear()
+ {
+ children_.clear();
+ }
+
+
+ bool is_running_;
+ view& view_;
+
+ moof::settings* settings_;
+ moof::video* video_;
+
+ view* parent_;
+ std::list<view_ptr> children_;
+
+ scalar timestep_;
+ scalar framerate_;
+
+ int fps_;
+ bool show_fps_;
+};
+
+
+view::view(moof::settings& settings, moof::video& video) :
+ // pass through
+ impl_(new view::impl(this, settings, video)) {}
+
+view::view() :
+ impl_(new view::impl(this)) {}
+
+
+void view::update(scalar t, scalar dt)
+{
+ // pass through
+ impl_->update(t, dt);
+}
+
+void view::draw(scalar alpha) const
+{
+ // pass through
+ impl_->draw(alpha);
+}
+
+bool view::handle_event(const event& event)
+{
+ // pass through
+ return impl_->handle_event(event);
+}
+
+
+void view::add_child(view_ptr view)
+{
+ // pass through
+ impl_->add_child(view);
+}
+
+view_ptr view::remove_child(view* view)
+{
+ // pass through
+ return impl_->remove_child(view);
+}
+
+view_ptr view::remove_child(view_ptr view)
+{
+ // pass through
+ return impl_->remove_child(view.get());
+}
+
+void view::clear()
+{
+ // pass through
+ impl_->clear();
+}
+
+
+view& view::parent() const
+{
+ return *(impl_->parent_);
+}
+
+const std::list<view_ptr>& view::children() const
+{
+ return impl_->children_;
+}
+
+
+moof::settings& view::settings() const
+{
+ ASSERT(impl_->settings_ && "accessing null reference");
+ // pass through
+ return *(impl_->settings_);
+}
+
+video& view::video() const
+{
+ ASSERT(impl_->video_ && "accessing null reference");
+ // pass through
+ return *(impl_->video_);
+}
+
+
+void view::run()
+{
+ // pass through
+ return impl_->run();
+}
+
+void view::stop()
+{
+ // pass through
+ return impl_->stop();
+}
+
+bool view::is_running() const
+{
+ // pass through
+ return impl_->is_running_;
+}
+
+
+} // namespace moof
+
#ifndef _MOOF_VIEW_HH_
#define _MOOF_VIEW_HH_
+/**
+ * \file view.hh
+ * Fundamental architectural classes.
+ */
+
#include <list>
#include <string>
#include <boost/shared_ptr.hpp>
-#include <Moof/Event.hh>
-#include <Moof/Math.hh>
+#include <moof/event.hh>
+#include <moof/math.hh>
-namespace Mf {
+namespace moof {
-class Settings;
-class Video;
+class settings;
+class video;
+
+class view;
+typedef boost::shared_ptr<view> view_ptr;
-class View;
-typedef boost::shared_ptr<View> ViewP;
/**
* The core is essentially a stack of layers. While running, it updates
* handled. The core is also responsible for firing timers on time. The
* core will continue running as long as there are layers on the stack.
*/
-
-class View
+class view
{
public:
// loads settings: rngseed, timestep, framerate, showfps
- View(Settings& settings, Video& video);
- View();
+ view(moof::settings& settings, moof::video& video);
+ view();
- virtual ~View() {}
+ virtual ~view() {}
- virtual void didAddToView() {}
- virtual void willRemoveFromView() {}
+ virtual void did_add_to_view() {}
+ virtual void will_remove_from_view() {}
- virtual void update(Scalar t, Scalar dt);
- virtual void draw(Scalar alpha) const;
- virtual bool handleEvent(const Event& event);
+ virtual void update(scalar t, scalar dt);
+ virtual void draw(scalar alpha) const;
+ virtual bool handle_event(const event& event);
- void addChild(ViewP view);
- ViewP removeChild(View* view);
- ViewP removeChild(ViewP view);
+ void add_child(view_ptr view);
+ view_ptr remove_child(view* view);
+ view_ptr remove_child(view_ptr view);
void clear();
- View& parent() const;
- const std::list<ViewP>& children() const;
+ view& parent() const;
+ const std::list<view_ptr>& children() const;
// do not call these without adding the view to a hierarchy with a base
// view constructed with settings and a video context
- Settings& settings() const;
- Video& video() const;
+ moof::settings& settings() const;
+ moof::video& video() const;
// set this machine in motion
void run();
void stop();
- bool isRunning() const;
+ bool is_running() const;
+
private:
- class Impl;
- boost::shared_ptr<Impl> mImpl;
+ class impl;
+ boost::shared_ptr<impl> impl_;
};
-} // namespace Mf
+} // namespace moof
#endif // _MOOF_VIEW_HH_