import sys
from panda3d.core import Filename, PandaSystem, getModelPath

# This file defines a number of standard "packages" that correspond to
# a Panda3D distribution.  These packages are built by passing this
# file to the ppackage utility, either as a packaged application, or
# as the module direct.p3d.ppackage.

# The packages in this file define Panda3D itself.  This is the third
# installed piece of the three-part plugin system (the plugin, the
# core API, Panda3D).

# When needed, these packages are downloaded by the core API, from the
# host URL specified in a given p3d file, and not from any hardcoded
# URL.  Thus, any custom version of Panda3D may be hosted on any
# server in the world, and any version of the plugin can download it.

# Also see coreapi.pdef.

class panda3d(package):
    # The main Panda3D package.  Contains Python and most of the graphics
    # code in Panda3D.

    config(display_name = "Panda3D")

    # First, add the minimum startup files for a Panda3D package.
    # These are files that the Panda3D runtime will explicitly look
    # for by name in order to get itself bootstrapped.
    setupPanda3D()

    # These are Python modules that are needed by most Panda3D
    # applications.  It doesn't matter too much if we miss one or two
    # here, since any module imported by any of this code will
    # automatically be included as well, and we end up with a pretty
    # complete list that way.
    module('direct.directbase.DirectStart',
           # Don't want to include all files in direct.p3d, because
           # that picks up the runtime scripts too, which are their
           # own p3d files below.
           'direct.p3d.AppRunner',
           'direct.p3d.DWBPackageInstaller',
           'direct.actor.*',
           'direct.controls.*',
           'direct.directdevices.*',
           'direct.directnotify.*',
           'direct.directtools.*',
           'direct.directutil.*',
           'direct.distributed.*',
           'direct.filter.*',
           'direct.fsm.*',
           'direct.gui.*',
           'direct.interval.*',
           'direct.particles.*',
           'direct.showbase.*',
           'direct.showutil.*',
           'direct.stdpy.*',
           'direct.task.*')

    # Keep these modules for backward compatibility.
    module('pandac.PandaModules', 'pandac.extension_native_helpers')

    module('panda3d.core',
           'panda3d.direct',
           'panda3d.fx',
           'panda3d.physics')

    # Include various standard Python encodings.  The rest is in morepy.
    module('encodings', 'encodings.aliases', 'encodings.undefined',
           'encodings.utf_8', 'encodings.ascii', 'encodings.mbcs',
           'encodings.latin_1', 'io')
    if sys.version_info < (3, 0):
        module('encodings.string_escape')

    # pandac.PandaModules pulls in other Panda3D libs automatically.
    # Exclude these Panda3D libs; they are big and many applications don't
    # use them.  We define them as separate, optional packages, below,
    # except for skel - this is useless in a shipped game anyways.
    excludeModule('panda3d.egg')
    excludeModule('panda3d.ode')
    excludeModule('panda3d.bullet')
    excludeModule('panda3d.vision')
    excludeModule('panda3d.skel')
    excludeModule('panda3d.physx')
    excludeModule('panda3d.ai')
    excludeModule('panda3d.vrpn')

    excludeModule('libpandaegg')
    excludeModule('libpandaode')
    excludeModule('libpandabullet')
    excludeModule('libp3vision')
    excludeModule('libpandaskel')
    excludeModule('libpandaphysx')
    excludeModule('libpandaai')
    excludeModule('libp3vrpn')

    # Exclude these GUI toolkits; they're big, and many applications don't
    # use them.  We define them as separate, optional packages, below.
    excludeModule('wx',
                  'direct.showbase.WxGlobal')

    excludeModule('Tkinter', 'tkinter', 'Pmw', 'tkinter.simpledialog',
                  'direct.showbase.TkGlobal',
                  'direct.tkpanels', 'direct.tkwidgets',
                  'tkCommonDialog', 'tkMessageBox', 'tkSimpleDialog')

    excludeModule('MySQLdb', 'MySQLdb.connections', 'MySQLdb.constants',
                  'MySQLdb.converters', '_mysql')

    # Some code in distributed conditionally imports these.
    excludeModule('otp.ai', 'otp.ai.AIZoneData')

    # Most of the core Panda3D DLL's will be included implicitly due to
    # being referenced by the above Python code.  Here we name a few more
    # that are also needed, but aren't referenced by any code.  Again,
    # note that the .dll extension is automatically replaced with the
    # platform-specific extension for an executable.
    file('libpandagl.dll', 'libp3tinydisplay.dll')
    if platform.startswith('win'):
        file('libpandadx9.dll')

    # A basic config file is needed to lay some some fundamental runtime
    # variables.
    if platform.startswith('win'):
        auxDisplays = """
aux-display pandagl
aux-display pandadx9
aux-display p3tinydisplay
"""
    else:
        auxDisplays = """
aux-display pandagl
aux-display p3tinydisplay
"""

    file('Config.prc', extract = True, text = """
plugin-path $PANDA3D_ROOT
default-model-extension .bam
cull-bin gui-popup 60 unsorted
""" + auxDisplays)

class morepy(package):
    # Additional Python modules provided by the standard Python
    # library.  Include this package to get the full suite of standard
    # Python functionality.

    config(display_name = "Python standard library")
    require('panda3d')

    module('string', 're', 'struct', 'difflib',
           'textwrap', 'codecs', 'unicodedata', 'stringprep', 'datetime',
           'calendar', 'collections', 'heapq', 'bisect', 'array',
           'sched', 'queue', 'weakref', 'types', 'copy', 'pprint',
           'numbers', 'math', 'cmath', 'decimal', 'fractions',
           'random', 'itertools', 'functools', 'operator', 'os.path',
           'fileinput', 'filecmp', 'tempfile', 'glob', 'fnmatch', 'linecache',
           'shutil', 'macpath', 'pickle', 'shelve', 'marshal', 'zlib',
           'gzip', 'bz2', 'zipfile', 'tarfile', 'csv', 'netrc',
           'xdrlib', 'plistlib', 'hashlib', 'hmac', 'os',
           'time', 'optparse', 'getopt', 'logging', 'logging.*')
    module('getpass', 'curses', 'curses.textpad', 'curses.wrapper',
           'curses.ascii', 'curses.panel', 'platform', 'errno',
           'ctypes', 'select', 'threading', 'dummy_threading', 'dummy_thread',
           'multiprocessing', 'mmap', 'readline', 'rlcompleter', 'subprocess',
           'socket', 'ssl', 'signal', 'asyncore', 'asynchat', 'email', 'json',
           'mailcap', 'mailbox', 'mimetypes', 'base64', 'binhex', 'binascii',
           'quopri', 'uu', 'xml.parsers.expat', 'xml.dom', 'xml.dom.minidom',
           'xml.dom.pulldom', 'xml.sax', 'xml.sax.handler',
           'xml.sax.saxutils', 'xml.sax.xmlreader',
           'xml.etree.ElementTree', 'webbrowser', 'cgi', 'cgitb')
    module('wsgiref', 'ftplib', 'poplib', 'imaplib', 'nntplib', 'smtplib',
           'smtpd', 'telnetlib', 'uuid', 'audioop', 'aifc', 'sunau',
           'wave', 'chunk', 'colorsys', 'imghdr', 'sndhdr',
           'ossaudiodev', 'gettext', 'locale', 'cmd', 'shlex',
           'pydoc', 'doctest', 'unittest', 'test',
           'bdb', 'pdb', 'timeit', 'trace', 'sys')
    module('warnings', 'contextlib', 'abc',
           'atexit', 'traceback', '__future__', 'gc', 'inspect',
           'site', 'fpectl', 'code', 'codeop', 'zipimport', 'pkgutil',
           'modulefinder', 'runpy', 'parser', 'symtable', 'symbol',
           'token', 'keyword', 'tokenize', 'tabnanny', 'pyclbr',
           'py_compile', 'compileall', 'dis', 'pickletools',
           'distutils', 'msilib', 'msvcrt', 'winsound', 'posix', 'pwd', 'spwd',
           'grp', 'crypt', 'termios', 'tty', 'pty', 'fcntl', 'pipes',
           'resource', 'nis', 'syslog', 'ast')

    # Handle module name differences between Python 2 and Python 3 (see PEP3108)
    if sys.version_info[0] < 3:
        # Deprecated modules that were removed in Python 3
        module('posixfile', 'rfc822', 'mimetools','MimeWriter', 'mimify',
               'multifile', 'sets', 'md5', 'sha', 'imp',  'formatter')
        # Mac-specific modules that were removed
        module('autoGIL', 'ColorPicker', 'EasyDialogs', 'findertools',
               'FrameWork', 'ic',  'MacOS', 'macostools')
        # Removed because they were hardly used
        module('imputil', 'mutex', 'user', 'new')
        # Removed because they were obsolete
        module('Bastion', 'rexec', 'commands', 'dircache', 'dl', 'fpformat',
               'htmllib', 'imageop', 'mhlib', 'popen2', 'sgmllib', 'stat',
               'statvfs', 'thread', 'UserDict', 'UserList', 'UserString',
               'future_builtins', 'hotshot', 'bsddb')
        # Renamed to fix PEP8 violations
        module('_winreg', 'ConfigParser', 'copy_reg', 'SocketServer')
        # C and Python implementations of the same interface were merged
        module('cPickle', 'cStringIO', 'StringIO')
        # Renamed because of poorly chosen names
        module('repr', 'test.test_support', '__builtins__')
        # Modules that got grouped under packages
        module('anydbm', 'whichdb', 'dbm', 'dumbdbm', 'gdbm', 'dbhash')
        module('HTMLParser', 'htmlentitydefs')
        module('BaseHTTPServer', 'SimpleHTTPServer', 'cookielib', 'Cookie',
               'CGIHTTPServer', 'httplib')
        module('urllib', 'urllib2', 'urlparse', 'robotparser')
        module('xmlrpclib', 'SimpleXMLRPCServer', 'DocXMLRPCServer')
    else:
        # Renamed to fix PEP8 violations
        module('winreg', 'configparser', 'copyreg', 'socketserver')
        # Renamed because of poorly chosen names
        module('reprlib', 'test.support', 'builtins')
        # Modules that got grouped under packages
        module('dbm')
        module('html')
        module('http')
        module('urllib')
        module('xmlrpc')

    # To add the multitude of standard Python string encodings.
    module('encodings', 'encodings.*')

class models(package):
    # The standard models package.  This is the contents of the
    # "models" directory that ships with Panda; it includes a few
    # default fonts, and some silly little sample models like smiley
    # and teapot.
    config(display_name = "Standard models")

    # We assign it the same version as the panda3d package.  This
    # would be assigned by default if we had a requirement on panda3d,
    # but there's no real reason to declare that requirement.
    config(version = PandaSystem.getPackageVersionString())

    # Look for cmss12.egg on the model-path.  Wherever this is found,
    # we assume this is the models directory.
    pathname = getModelPath().findFile('cmss12.egg')
    if pathname:
        dir(pathname.getDirname(), newDir = 'models')

    # Some people are used to loading the models without models/ prefix.
    file('models.prc', extract = True, text = "model-path $MODELS_ROOT/models")


class fmod(package):
    # This package includes the FMod audio library.  This is
    # full-featured and robust, but it is closed-source and the
    # licensing is cost-free only for non-commercial products.

    config(display_name = "FMod audio library")
    require('panda3d')

    file('libp3fmod_audio.dll', required = True)

    file('fmod.prc', extract = True, text = """
plugin-path $FMOD_ROOT
audio-library-name p3fmod_audio
""")

class openal(package):
    # This package includes the OpenAL audio libraries.  This is free
    # in both senses, but there are some technical issues, especially
    # on certain platforms.

    config(display_name = "OpenAL audio library")
    require('panda3d')

    file('libp3openal_audio.dll', required = True)
    file('OpenAL32.dll')
    file('soft_oal.dll')
    file('wrap_oal.dll')

    file('openal.prc', extract = True, text = """
plugin-path $OPENAL_ROOT
audio-library-name p3openal_audio
""")

class audio(package):
    # This package includes the best audio library for the given
    # platform, assuming a non-commercial application.
    require('panda3d')

    # OpenAL seems to work pretty well universally now.
    require('openal')

class ffmpeg(package):
    # This package includes the ffmpeg libraries and integration.
    # It's a bit big, and is restricted by patents and the restrictive
    # GPLv3 license, which is why it is included as a separate package.

    config(display_name = "FFMpeg multimedia decoder")
    require('panda3d')

    file('libp3ffmpeg.dll', required = True)

    file('ffmpeg.prc', extract = True, text = """
plugin-path $FFMPEG_ROOT
load-audio-type * p3ffmpeg
load-video-type * p3ffmpeg
""")

class egg(package):
    # This package contains the code for reading and operating on egg
    # files and other model files.  Since the Packager automatically
    # converts egg files to bam files, this is not needed for most
    # Panda3D applications.

    config(display_name = "Panda3D egg loader")
    require('panda3d')

    module('panda3d.egg', required = True)
    file('libpandaegg.dll', required = True)
    file('libp3ptloader.dll', required = True)

    file('egg.prc', extract = True, text = """
plugin-path $EGG_ROOT
load-file-type egg pandaegg
load-file-type p3ptloader

# These are excerpted from the default Confauto.prc file.
egg-object-type-portal          <Scalar> portal { 1 }
egg-object-type-polylight       <Scalar> polylight { 1 }
egg-object-type-seq24           <Switch> { 1 } <Scalar> fps { 24 }
egg-object-type-seq12           <Switch> { 1 } <Scalar> fps { 12 }
egg-object-type-indexed         <Scalar> indexed { 1 }
egg-object-type-seq10           <Switch> { 1 } <Scalar> fps { 10 }
egg-object-type-seq8            <Switch> { 1 } <Scalar> fps { 8 }
egg-object-type-seq6            <Switch> { 1 } <Scalar>  fps { 6 }
egg-object-type-seq4            <Switch> { 1 } <Scalar>  fps { 4 }
egg-object-type-seq2            <Switch> { 1 } <Scalar>  fps { 2 }

egg-object-type-binary          <Scalar> alpha { binary }
egg-object-type-dual            <Scalar> alpha { dual }
egg-object-type-glass           <Scalar> alpha { blend_no_occlude }

egg-object-type-model           <Model> { 1 }
egg-object-type-dcs             <DCS> { 1 }
egg-object-type-notouch         <DCS> { no_touch }

egg-object-type-barrier         <Collide> { Polyset descend }
egg-object-type-sphere          <Collide> { Sphere descend }
egg-object-type-invsphere       <Collide> { InvSphere descend }
egg-object-type-tube            <Collide> { Tube descend }
egg-object-type-trigger         <Collide> { Polyset descend intangible }
egg-object-type-trigger-sphere  <Collide> { Sphere descend intangible }
egg-object-type-floor           <Collide> { Polyset descend level }
egg-object-type-dupefloor       <Collide> { Polyset keep descend level }
egg-object-type-bubble          <Collide> { Sphere keep descend }
egg-object-type-ghost           <Scalar> collide-mask { 0 }
egg-object-type-glow            <Scalar> blend { add }
egg-object-type-direct-widget   <Scalar> collide-mask { 0x80000000 } <Collide> { Polyset descend }
""")

class ode(package):
    # This package contains the code for the ODE integration.
    # As not every application uses the ODE layers, and to cut down
    # the download size, it is provided as separate package.

    config(display_name = "Panda3D Open Dynamics Engine integration")
    require('panda3d')

    module('panda3d.ode', required = True)
    file('libpandaode.dll', required = True)

class bullet(package):
    # This package contains the code for the Bullet integration.
    # As not every application uses the Bullet layers, and to cut down
    # the download size, it is provided as separate package.

    config(display_name = "Panda3D Bullet integration")
    require('panda3d')

    module('panda3d.bullet', required = True)
    file('libpandabullet.dll', required = True)

class physx(package):
    # This package contains the code for the NVIDIA PhysX integration.
    # As not every application uses the NVIDIA PhysX layers, and to cut down
    # the download size, it is provided as separate package.

    config(display_name = "Panda3D PhysX integration")
    require('panda3d')

    module('panda3d.physx', required = True)
    file('libpandaphysx.dll', required = True)
    file('physxcudart_20.dll')
    file('PhysXDevice.dll')

class ai(package):
    # This package contains the PandAI library for pathfinding
    # and seek/flee behaviors. As some games may not need this
    # functionality, it is provided as separate package to save
    # on package download size.

    config(display_name = "Panda3D AI modules")
    require('panda3d')

    module('panda3d.ai', required = True)
    file('libpandaai.dll', required = True)

class vision(package):
    # This package contains the code for webcam support, augmented
    # reality and computer vision. As many games will not need this
    # functionality, it is provided as separate package to save
    # on package download size.

    config(display_name = "Panda3D vision modules")
    require('panda3d')

    module('panda3d.vision', required = True)
    file('libp3vision.dll', required = True)

class rocket(package):
    # This package contains the code for libRocket integration.
    # As not every application uses libRocket GUI, and to cut down
    # the download size, it is provided as separate package.

    config(display_name = "Panda3D libRocket support")
    require('panda3d')

    file('rocket.py', extract = True, text = """
from _rocketcore import *
try:
    from _rocketcontrols import *
except ImportError:
    pass
""")

    module('panda3d.rocket', '_rocketcore', required = True)
    module('_rocketcontrols')
    file('libp3rocket.dll', required = True)

class vrpn(package):
    # This package contains the code for VRPN integration.
    # Most applications don't use this, which is why it's separate.

    config(display_name = "Panda3D VRPN support")
    require('panda3d')

    module('panda3d.vrpn', required = True)
    file('libp3vrpn.dll', required = True)


class packp3d(p3d):
    # This application is a command-line convenience for building a p3d
    # application out of a directory hierarchy on disk.  We build it here
    # into its own p3d application, to allow end-users to easily build p3d
    # applications using the appropriate version of Python and Panda for
    # the targeted runtime.

    config(display_name = "Panda3D Application Packer",
           hidden = True, platform_specific = False,
           keep_user_env = True)
    require('panda3d', 'egg')

    mainModule('direct.p3d.packp3d')

    file('packp3d.prc', extract = True, text = "preload-textures false")


class ppackage(p3d):
    # As above, a packaging utility.  This is the fully-general ppackage
    # utility, which reads pdef files (like this one!) and creates one or
    # more packages or p3d applications.

    config(display_name = "Panda3D General Package Utility",
           hidden = True, platform_specific = False,
           keep_user_env = True)
    require('panda3d', 'egg')

    mainModule('direct.p3d.ppackage')

    file('ppackage.prc', extract = True, text = "preload-textures false")


class ppatcher(p3d):
    # A handy utility to go along with ppackage.  This builds
    # patchfiles as needed in the directory structure created by
    # ppackage.

    config(display_name = "Panda3D Patch Maker",
           hidden = True, platform_specific = False,
           keep_user_env = True)
    require('panda3d')

    mainModule('direct.p3d.ppatcher')


class pmerge(p3d):
    # Another handy utility to go along with ppackage.  This
    # merges multiple directory structures as created by
    # ppackage into a single one.

    config(display_name = "Panda3D Package Merger",
           hidden = True, platform_specific = False,
           keep_user_env = True)
    require('panda3d')

    mainModule('direct.p3d.pmerge')


class pdeploy(p3d):
    # This utility can distribute a game in the form of
    # a standalone executable or a graphical installer.

    config(display_name = "Panda3D Deployment Tool",
           hidden = True, platform_specific = False,
           keep_user_env = True)
    require('panda3d', 'morepy')

    mainModule('direct.p3d.pdeploy')

