Package tdl |
[frames] | no frames]

# Source Code for Package tdl

      1  """
      2      The documentation for python-tdl.  A Pythonic port of
      3      U{libtcod<http://doryen.eptalys.net/libtcod/>}.
      4
      5      Getting Started
      6      ===============
      7        Once the library is imported you can load the font you want to use with
      8        L{tdl.setFont}.  This is optional and can be skipped to get a decent
      9        default font.  After that you call L{tdl.init} to set the size of the
     10        window and get the root console in return.  This console is the canvas
     11        to what will appear on the screen.
     12
     13      Drawing
     14      =======
     15        Once you have the root console from L{tdl.init} you can start drawing on
     16        it using a method such as L{Console.drawChar}.  When using this method
     17        you can have the char parameter be an intiger or a single character
     18        string.  The fgcolor and bgcolor parameters expect a three item list
     19        [red, green, blue] with integers in the 0-255 range with [0, 0, 0] being
     20        black and [255, 255, 255] being white.  Or instead you can use None for
     21        any of the three parameters to tell the library to keep what is at that
     22        spot instead of overwriting it.  After the drawing functions are called
     23        a call to L{tdl.flush} will update the screen.
     24  """
     25
     26  import sys
     27  import os
     28  import ctypes
     29  import weakref
     30  import array
     31  import itertools
     32
     33  from . import event
     34  from .__tcod import _lib, _Color, _unpackfile
     35
     36  _IS_PYTHON3 = (sys.version_info[0] == 3)
     37  _USE_FILL = False
     38  'Set to True to use the libtcod fill optimization.  This is actually slower than the normal mode.'
     39
     40 -def _format_string(string): # still used for filepaths, and that's about it
     41      "changes string into bytes if running in python 3, for sending to ctypes"
     42      if _IS_PYTHON3 and isinstance(string, str):
     43          return string.encode()
     44      return string
     45
     46  #def _encodeString(string):
     47  #    pass
     48
     49 -def _formatChar(char):
     50      """Prepares a single character for passing to ctypes calls, needs to return
     51      an integer but can also pass None which will keep the current character
     52      instead of overrwriting it.
     53
     54      This is called often and needs to be optimized whenever possible.
     55      """
     56      if char is None:
     57          return None
     58      if isinstance(char, int) or not _IS_PYTHON3 and isinstance(char, long):
     59          return char
     60      if isinstance(char, (str, bytes)) and len(char) == 1:
     61          return ord(char)
     62      raise TypeError('Expected char parameter to be a single character string, number, or None, got: %s' % repr(char))
     63
     64  _fontinitialized = False
     65  _rootinitialized = False
     66  _rootconsole = None
     67  # remove dots from common functions
     68  _setchar = _lib.TCOD_console_set_char
     69  _setfore = _lib.TCOD_console_set_char_foreground
     70  _setback = _lib.TCOD_console_set_char_background
     71  _setcharEX = _lib.TCOD_console_put_char_ex
     72 -def _verify_colors(*colors):
     73      """Used internally.
     74      Raise an assertion error if the parameters can not be converted into colors.
     75      """
     76      for color in colors:
     77          assert _iscolor(color), 'a color must be a 3 item tuple, web format, or None, received %s' % repr(color)
     78      return True
     79
     80 -def _iscolor(color):
     81      """Used internally.
     82      A debug function to see if an object can be used as a TCOD color struct.
     83      None counts as a parameter to keep the current colors instead.
     84
     85      This function is often part of an inner-loop and can slow a program down.
     86      It has been made to work with assert and can be skipped with the -O flag.
     87      Still it's called often and must be optimized.
     88      """
     89      if color is None:
     90          return True
     91      if isinstance(color, (tuple, list, _Color)):
     92          return len(color) == 3
     93      if isinstance(color, int) or not _IS_PYTHON3 and isinstance(color, long):
     94          return True
     95      return False
     96
     97 -def _formatColor(color):
     98      """Format the color to ctypes
     99      """
    100      if color is None:
    101          return None
    102      # avoid isinstance, checking __class__ gives a small speed increase
    103      if color.__class__ is _Color:
    104          return color
    105      if isinstance(color, int) or not _IS_PYTHON3 and isinstance(color, long):
    106          # format a web style color with the format 0xRRGGBB
    107          return _Color(color >> 16 & 0xff, color >> 8 & 0xff, color & 0xff)
    108      return _Color(*color)
    109
    110 -class TDLError(Exception):
    111      """
    112      The catch all for most TDL specific errors.
    113      """
    114
    115 -class _MetaConsole(object):
    116      """
    117      Contains methods shared by both the L{Console} and L{Window} classes.
    118      """
    119      __slots__ = ('width', 'height', '__weakref__', '__dict__')
    120
    121 -    def drawChar(self, x, y, char, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
    122          """Draws a single character.
    123
    124          @type x: int
    125          @type y: int
    126          @type char: int, string, or None
    127          @type fgcolor: 3-item list or None
    128          @type bgcolor: 3-item list or None
    129          @param char: Should be an integer, single character string, or None.
    130
    131                       You can set the char parameter as None if you only want to change
    132                       the colors of the tile.
    133
    134          @param fgcolor: For fgcolor and bgcolor you use a 3 item list with integers ranging 0 - 255 or None.
    135                          None will keep the current color at this position unchanged.
    136
    137
    138          @raise AssertionError: Having the x or y values outside of the console will raise an
    139                                 AssertionError.  You can use ((x, y) in console)
    140                                 to check if a cell is drawable.
    141          """
    142
    143          assert _verify_colors(fgcolor, bgcolor)
    144          assert self._drawable(x, y)
    145
    146          self._setChar(x, y, _formatChar(char),
    147                        _formatColor(fgcolor), _formatColor(bgcolor))
    148
    149 -    def drawStr(self, x, y, string, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
    150          """Draws a string starting at x and y.  Optinally colored.
    151
    152          A string that goes past the right side will wrap around.  A string
    153          wraping to below the console will raise a L{TDLError} but will still be
    154          written out.  This means you can safely ignore the errors with a
    155          try... except block if you're fine with partily written strings.
    156
    157          \\r and \\n are drawn on the console as normal character tiles.  No
    158          special encoding is done and any string will translate to the character
    159          table as is.
    160
    161          fgcolor and bgcolor can be set to None to keep the colors unchanged.
    162
    163          @type x: int
    164          @type y: int
    165          @type string: string or iterable
    166          @type fgcolor: 3-item list or None
    167          @type bgcolor: 3-item list or None
    168
    169          """
    170
    171          assert self._drawable(x, y)
    172          assert _verify_colors(fgcolor, bgcolor)
    173          fgcolor, bgcolor = _formatColor(fgcolor), _formatColor(bgcolor)
    174          width, height = self.getSize()
    175          for char in string:
    176              if y == height:
    177                  raise TDLError('End of console reached.')
    178              self._setChar(x, y, _formatChar(char), fgcolor, bgcolor)
    179              x += 1 # advance cursor
    180              if x == width: # line break
    181                  x = 0
    182                  y += 1
    183
    184 -    def drawRect(self, x, y, width, height, string, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
    185          """Draws a rectangle starting from x and y and extending to width and
    186          height.  If width or height are None then it will extend to the edge
    187          of the console.  The rest are the same as drawChar.
    188
    189          @type x: int
    190          @type y: int
    191          @type width: int or None
    192          @type height: int or None
    193          @type string: int, string, or None
    194          @type fgcolor: 3-item list or None
    195          @type bgcolor: 3-item list or None
    196          """
    197          x, y, width, height = self._normalizeRect(x, y, width, height)
    198          assert _verify_colors(fgcolor, bgcolor)
    199          fgcolor, bgcolor = _formatColor(fgcolor), _formatColor(bgcolor)
    200          char = _formatChar(string)
    201          for cellY in range(y, y + height):
    202              for cellX in range(x, x + width):
    203                  self._setChar(cellX, cellY, char, fgcolor, bgcolor)
    204
    205 -    def drawFrame(self, x, y, width, height, string, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
    206          """Similar to drawRect but only draws the outline of the rectangle.
    207
    208          @type x: int
    209          @type y: int
    210          @type width: int or None
    211          @type height: int or None
    212          @type string: int, string, or None
    213          @type fgcolor: 3-item list or None
    214          @type bgcolor: 3-item list or None
    215          """
    216          x, y, width, height = self._normalizeRect(x, y, width, height)
    217          assert _verify_colors(fgcolor, bgcolor)
    218          fgcolor, bgcolor = _formatColor(fgcolor), _formatColor(bgcolor)
    219          char = _formatChar(string)
    220          if width == 1 or height == 1: # it's just a single width line here
    221              return self.drawRect(x, y, width, height, char, fgcolor, bgcolor)
    222
    223          # draw sides of frame with drawRect
    224          self.drawRect(x, y, 1, height, char, fgcolor, bgcolor)
    225          self.drawRect(x, y, width, 1, char, fgcolor, bgcolor)
    226          self.drawRect(x + width - 1, y, 1, height, char, fgcolor, bgcolor)
    227          self.drawRect(x, y + height - 1, width, 1, char, fgcolor, bgcolor)
    228
    229
    230 -    def _normalizeRect(self, x, y, width, height):
    231          """Check if the rectangle is in bounds and make minor adjustments.
    232          raise AssertionError's for any problems
    233          """
    234          old = x, y, width, height
    235          assert isinstance(x, int), 'x must be an integer, got %s' % repr(x)
    236          assert isinstance(y, int), 'y must be an integer, got %s' % repr(y)
    237          if width == None: # if width or height are None then extend them to the edge
    238              width = self.width - x
    239          if height == None:
    240              height = self.height - y
    241          assert isinstance(width, int), 'width must be an integer or None, got %s' % repr(width)
    242          assert isinstance(height, int), 'height must be an integer or None, got %s' % repr(height)
    243
    244          assert width >= 0 and height >= 0, 'width and height cannot be negative'
    245          # later idea, negative numbers work like Python list indexing
    246
    247          assert x >= 0 and y >= 0 and x + width <= self.width and y + height <= self.height, \
    248          'Rect is out of bounds at (x=%i y=%i width=%i height=%i), Console bounds are (width=%i, height=%i)' % (old + self.getSize())
    249          return x, y, width, height
    250
    251 -    def _rectInBounds(self, x, y, width, height):
    252          "check the rect so see if it's within the bounds of this console"
    253          if width is None:
    254              width = 0
    255          if height is None:
    256              height = 0
    257          if (x < 0 or y < 0 or
    258              x + width > self.width or y + height > self.height):
    259              return False
    260
    261          return True
    262
    263 -    def _clampRect(self, x=0, y=0, width=None, height=None):
    264          """Alter a rectange to fit inside of this console
    265
    266          width and hight of None will extend to the edge and
    267          an area out of bounds will end with a width and height of 0
    268          """
    269          # extend any width and height of None to the end of the console
    270          if width is None:
    271              width = self.width - x
    272          if height is None:
    273              height = self.height - y
    274          # move x and y within bounds, shrinking the width and height to match
    275          if x < 0:
    276              width += x
    277              x = 0
    278          if y < 0:
    279              height += y
    280              y = 0
    281          # move width and height within bounds
    282          width = min(width, self.width - x)
    283          height = min(height, self.height - y)
    284          # a rect that was out of bounds will have a 0 or negative width or height at this point
    285          if width <= 0 or height <= 0:
    286              width = height = 0
    287          return x, y, width, height
    288
    289 -    def blit(self, source, x=0, y=0, width=None, height=None, srcX=0, srcY=0):
    290          """Blit another console or Window onto the current console.
    291
    292          By default it blits the entire source to the topleft corner.
    293
    294          @type source: Console or Window
    295          @type x: int
    296          @type y: int
    297          @type width: int or None
    298          @type height: int or None
    299          @type srcX: int
    300          @type srcY: int
    301          """
    302          # hardcode alpha settings for now
    303          fgalpha=1.0
    304          bgalpha=1.0
    305
    306          assert isinstance(source, (Console, Window)), "source muse be a Window or Console instance"
    307
    308          assert width is None or isinstance(width, (int)), "width must be a number or None, got %s" % repr(width)
    309          assert height is None or isinstance(height, (int)), "height must be a number or None, got %s" % repr(height)
    310
    311          # fill in width, height
    312          if width == None:
    313              width = min(self.width - x, source.width - srcX)
    314          if height == None:
    315              height = min(self.height - y, source.height - srcY)
    316
    317          x, y, width, height = self._normalizeRect(x, y, width, height)
    318          srcX, srcY, width, height = source._normalizeRect(srcX, srcY, width, height)
    319
    320          # translate source and self if any of them are Window instances
    321          if isinstance(source, Window):
    322              srcX, srcY = source._translate(srcX, srcY)
    323              source = source.console
    324
    325          if isinstance(self, Window):
    326              x, y = self._translate(x, y)
    327              self = self.console
    328
    329          if self == source:
    330              # if we are the same console then we need a third console to hold
    331              # onto the data, otherwise it tries to copy into itself and
    332              # starts destroying everything
    333              tmp = Console(width, height)
    334              _lib.TCOD_console_blit(source, srcX, srcY, width, height, tmp, 0, 0, fgalpha, bgalpha)
    335              _lib.TCOD_console_blit(tmp, 0, 0, width, height, self, x, y, fgalpha, bgalpha)
    336          else:
    337              _lib.TCOD_console_blit(source, srcX, srcY, width, height, self, x, y, fgalpha, bgalpha)
    338
    339 -    def getSize(self):
    340          """Return the size of the console as (width, height)
    341
    342          @rtype: (int, int)
    343          """
    344          return self.width, self.height
    345
    346 -    def scroll(self, x, y):
    347          """Scroll the contents of the console in the direction of x,y.
    348
    349          Uncovered areas will be cleared.
    350          @type x: int
    351          @type y: int
    352          """
    353          assert isinstance(x, int), "x must be an integer, got %s" % repr(x)
    354          assert isinstance(y, int), "y must be an integer, got %s" % repr(x)
    355          def getSlide(x, length):
    356              """get the parameters needed to scroll the console in the given
    357              direction with x
    358              returns (x, length, srcx)
    359              """
    360              if x > 0:
    361                  srcx = 0
    362                  length -= x
    363              elif x < 0:
    364                  srcx = abs(x)
    365                  x = 0
    366                  length -= srcx
    367              else:
    368                  srcx = 0
    369              return x, length, srcx
    370          def getCover(x, length):
    371              """return the (x, width) ranges of what is covered and uncovered"""
    372              cover = (0, length) # everything covered
    373              uncover = None  # nothing uncovered
    374              if x > 0: # left side uncovered
    375                  cover = (x, length - x)
    376                  uncover = (0, x)
    377              elif x < 0: # right side uncovered
    378                  x = abs(x)
    379                  cover = (0, length - x)
    380                  uncover = (length - x, x)
    381              return cover, uncover
    382
    383          width, height = self.getSize()
    384          if abs(x) >= width or abs(y) >= height:
    385              return self.clear() # just clear the console normally
    386
    387          # get the ranges of the areas that will be uncovered
    388          coverX, uncoverX = getCover(x, width)
    389          coverY, uncoverY = getCover(y, height)
    390          # so at this point we know that coverX and coverY makes a rect that
    391          # encases the area that we end up blitting to.  uncoverX/Y makes a
    392          # rect in the corner of the uncovered area.  So we need to combine
    393          # the uncoverX/Y with coverY/X to make what's left of the uncovered
    394          # area.  Explaining it makes it mush easier to do now.
    395
    396          # But first we need to blit.
    397          x, width, srcx = getSlide(x, width)
    398          y, height, srcy = getSlide(y, height)
    399          self.blit(self, x, y, width, height, srcx, srcy)
    400
    401          if uncoverX: # clear sides (0x20 is space)
    402              self.drawRect(uncoverX[0], coverY[0], uncoverX[1], coverY[1], 0x20)
    403          if uncoverY: # clear top/bottom
    404              self.drawRect(coverX[0], uncoverY[0], coverX[1], uncoverY[1], 0x20)
    405          if uncoverX and uncoverY: # clear corner
    406              self.drawRect(uncoverX[0], uncoverY[0], uncoverX[1], uncoverY[1], 0x20)
    407
    408 -    def __contains__(self, position):
    409          """Use ((x, y) in console) to check if a position is drawable on this console.
    410          """
    411          x, y = position
    412          return (0 <= x < self.width) and (0 <= y < self.height)
    413
    414 -    def _drawable(self, x, y):
    415          """Used internally
    416          Checks if a cell is part of the console.
    417          Raises an AssertionError if it can not be used.
    418          """
    419          assert isinstance(x, int), 'x must be an integer, got %s' % repr(x)
    420          assert isinstance(y, int), 'y must be an integer, got %s' % repr(y)
    421
    422          assert (0 <= x < self.width) and (0 <= y < self.height), \
    423                  ('(%i, %i) is an invalid postition.  %s size is (%i, %i)' %
    424                   (x, y, self.__class__.__name__, self.width, self.height))
    425          return True
    426
    427 -class Console(_MetaConsole):
    428      """The Console is the main class of the tdl library.
    429
    430      The console created by the L{tdl.init} function is the root console and is the
    431      consle that is rendered to the screen with flush.
    432
    433      Any console made from Console is an off-screen console that can be drawn
    434      on and then L{blit} to the root console.
    435      """
    436
    437      __slots__ = ('_as_parameter_',)
    438
    439 -    def __init__(self, width, height):
    440          """Create a new offscreen console
    441          """
    442          self._as_parameter_ = _lib.TCOD_console_new(width, height)
    443          self.width = width
    444          self.height = height
    445          self._initArrays()
    446          #self.clear()
    447
    448      @classmethod
    449 -    def _newConsole(cls, console):
    450          """Make a Console instance, from a console ctype"""
    451          self = cls.__new__(cls)
    452          self._as_parameter_ = console
    453          self.width = _lib.TCOD_console_get_width(self)
    454          self.height = _lib.TCOD_console_get_height(self)
    455          self._initArrays()
    456          #self.clear()
    457          return self
    458
    459 -    def _initArrays(self):
    460          if not _USE_FILL:
    461              return
    462          # used for the libtcod fill optimization
    463          IntArray = ctypes.c_int * (self.width * self.height)
    464          self.chArray = IntArray()
    465          self.fgArrays = (IntArray(),
    466                           IntArray(),
    467                           IntArray())
    468          self.bgArrays = (IntArray(),
    469                           IntArray(),
    470                           IntArray())
    471
    472 -    def __del__(self):
    473          """
    474          If the main console is garbage collected then the window will be closed as well
    475          """
    476          # If this is the root console the window will close when collected
    477          try:
    478              if isinstance(self._as_parameter_, ctypes.c_void_p):
    479                  global _rootinitialized, _rootconsole
    480                  _rootinitialized = False
    481                  _rootconsole = None
    482              _lib.TCOD_console_delete(self)
    483          except StandardError:
    484              pass # I forget why I put this here but I'm to afraid to delete it
    485
    486 -    def _replace(self, console):
    487          """Used internally
    488
    489          Mostly used just to replace this Console object with the root console
    490          If another Console object is used then they are swapped
    491          """
    492          if isinstance(console, Console):
    493              self._as_parameter_, console._as_parameter_ = \
    494                console._as_parameter_, self._as_parameter_ # swap tcod consoles
    495          else:
    496              self._as_parameter_ = console
    497          self.width = _lib.TCOD_console_get_width(self)
    498          self.height = _lib.TCOD_console_get_height(self)
    499          return self
    500
    501 -    def _translate(self, x, y):
    502          """Convertion x and y to their position on the root Console for this Window
    503
    504          Because this is a Console instead of a Window we return the paramaters
    505          untouched"""
    506          return x, y
    507
    508 -    def clear(self, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
    509          """Clears the entire console.
    510
    511          @type fgcolor: 3-item list
    512          @type bgcolor: 3-item list
    513          """
    514          assert _verify_colors(fgcolor, bgcolor)
    515          assert fgcolor and bgcolor, 'Can not use None with clear'
    516          _lib.TCOD_console_set_default_background(self, _formatColor(bgcolor))
    517          _lib.TCOD_console_set_default_foreground(self, _formatColor(fgcolor))
    518          _lib.TCOD_console_clear(self)
    519
    520 -    def _setCharFill(self, x, y, char, fgcolor=None, bgcolor=None):
    521          """An optimized version using the fill wrappers that didn't work out to be any faster"""
    522          index = x + y * self.width
    523          self.chArray[index] = char
    524          for channel, color in zip(itertools.chain(self.fgArrays, self.bgArrays),
    525                                    itertools.chain(fgcolor, bgcolor)):
    526              channel[index] = color
    527
    528 -    def _setCharCall(self, x, y, char, fgcolor=None, bgcolor=None, bgblend=1):
    529          """
    530          Sets a character.
    531          This is called often and is designed to be as fast as possible.
    532
    533          Because of the need for speed this function will do NO TYPE CHECKING
    534          AT ALL, it's up to the drawing functions to use the functions:
    535          _formatChar and _formatColor before passing to this."""
    536          if char is not None and fgcolor is not None and bgcolor is not None:
    537              return _setcharEX(self, x, y, char, fgcolor, bgcolor)
    538          if char is not None:
    539              _setchar(self, x, y, char)
    540          if fgcolor is not None:
    541              _setfore(self, x, y, fgcolor)
    542          if bgcolor is not None:
    543              _setback(self, x, y, bgcolor, bgblend)
    544
    545      if _USE_FILL:
    546          _setChar = _setCharFill
    547      else:
    548          _setChar = _setCharCall
    549
    550 -    def getChar(self, x, y):
    551          """Return the character and colors of a cell as
    552          (char, fgcolor, bgcolor)
    553
    554          The charecter is returned as a number.
    555          Each color is returned as a tuple.
    556
    557          @rtype: (int, 3-item tuple, 3-item tuple)
    558          """
    559          self._drawable(x, y)
    560          char = _lib.TCOD_console_get_char(self, x, y)
    561          bgcolor = _lib.TCOD_console_get_char_background_wrapper(self, x, y)
    562          fgcolor = _lib.TCOD_console_get_char_foreground_wrapper(self, x, y)
    563          return char, tuple(fgcolor), tuple(bgcolor)
    564
    565 -    def __repr__(self):
    566          return "<Console (Width=%i Height=%i)>" % (self.width, self.height)
    567
    568
    569 -class Window(_MetaConsole):
    570      """A Window contains a small isolated part of a Console.
    571
    572      Drawing on the Window draws on the Console.
    573
    574      Making a Window and setting its width or height to None will extend it to
    575      the edge of the console.
    576      """
    577
    578      __slots__ = ('console', 'parent', 'x', 'y')
    579
    580 -    def __init__(self, console, x, y, width, height):
    581          assert isinstance(console, (Console, Window)), 'console parameter must be a Console or Window instance, got %s' % repr(console)
    582          self.parent = console
    583          self.x, self.y, self.width, self.height = console._normalizeRect(x, y, width, height)
    584          if isinstance(console, Console):
    585              self.console = console
    586          else:
    587              self.console = self.parent.console
    588
    589 -    def _translate(self, x, y):
    590          """Convertion x and y to their position on the root Console"""
    591          # we add our position relative to our parent and then call then next parent up
    592          return self.parent._translate((x + self.x), (y + self.y))
    593
    594 -    def clear(self, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
    595          """Clears the entire Window.
    596
    597          @type fgcolor: 3-item list
    598          @type bgcolor: 3-item list
    599          """
    600          assert _verify_colors(fgcolor, bgcolor)
    601          assert fgcolor and bgcolor, 'Can not use None with clear'
    602          self.draw_rect(0, 0, None, None, 0x20, fgcolor, bgcolor)
    603
    604 -    def _setChar(self, x, y, char=None, fgcolor=None, bgcolor=None, bgblend=1):
    605          self.parent._setChar((x + self.x), (y + self.y), char, fgcolor, bgcolor, bgblend)
    606
    607 -    def getChar(self, x, y):
    608          """Return the character and colors of a cell as (ch, fg, bg)
    609
    610          @rtype: (int, 3-item tuple, 3-item tuple)
    611          """
    612          self._drawable(x, y)
    613          return self.console.getChar(self._translate(x, y))
    614
    615 -    def __repr__(self):
    616          return "<Window(X=%i Y=%i Width=%i Height=%i)>" % (self.x, self.y,
    617                                                            self.width,
    618                                                            self.height)
    619
    620
    621 -def init(width, height, title='python-tdl', fullscreen=False, renderer='OPENGL'):
    622      """Start the main console with the given width and height and return the
    623      root console.
    624
    625      Call the consoles drawing functions.  Then remember to use L{tdl.flush} to
    626      make what's drawn visible on the console.
    627
    628      @type width: int
    629      @type height: int
    630
    631      @type title: string
    632
    633      @type fullscreen: boolean
    634      @param fullscreen: Can be set to True to start in fullscreen mode.
    635
    636      @type renderer: string
    637      @param renderer: Can be one of 'GLSL', 'OPENGL', or 'SDL'.
    638
    639                       Due to way Python works you're unlikely to see much of an
    640                       improvement by using 'GLSL' or 'OPENGL' as most of the
    641                       time Python is slow interacting with the console and the
    642                       rendering itself is pretty fast even on 'SDL'.
    643
    644                       This should be left at default or switched to 'SDL' for
    645                       better reliability and an instantaneous start up time.
    646
    647      @rtype: L{Console}
    648      @return: The root console.  Only what is drawn on the root console is
    649               what's visible after a call to L{tdl.flush}.
    650               After the root console is garbage collected, the window made by
    651               this function will close.
    652      """
    653      RENDERERS = {'GLSL': 0, 'OPENGL': 1, 'SDL': 2}
    654      global _rootinitialized, _rootconsole
    655      if not _fontinitialized: # set the default font to the one that comes with tdl
    656          setFont(_unpackfile('terminal.png'), 16, 16, colomn=True)
    657
    658      if renderer.upper() not in RENDERERS:
    659          raise TDLError('No such render type "%s", expected one of "%s"' % (renderer, '", "'.join(RENDERERS)))
    660      renderer = RENDERERS[renderer.upper()]
    661
    662      # If a console already exists then make a clone to replace it
    663      if _rootconsole is not None:
    664          oldroot = _rootconsole()
    665          rootreplacement = Console(oldroot.width, oldroot.height)
    666          rootreplacement.blit(oldroot)
    667          oldroot._replace(rootreplacement)
    668          del rootreplacement
    669
    670      _lib.TCOD_console_init_root(width, height, _format_string(title), fullscreen, renderer)
    671
    672      #event.get() # flush the libtcod event queue to fix some issues
    673      # issues may be fixed already
    674
    675      event._eventsflushed = False
    676      _rootinitialized = True
    677      rootconsole = Console._newConsole(ctypes.c_void_p())
    678      _rootconsole = weakref.ref(rootconsole)
    679
    680      return rootconsole
    681
    682 -def flush():
    683      """Make all changes visible and update the screen.
    684
    685      Remember to call this function after drawing operations.
    686      Calls to flush will enfore the frame rate limit set by L{tdl.setFPS}.
    687
    688      This function can only be called after L{tdl.init}
    689      """
    690      if not _rootinitialized:
    691          raise TDLError('Cannot flush without first initializing with tdl.init')
    692
    693      if _USE_FILL:
    694          console = _rootconsole()
    695          _lib.TCOD_console_fill_background(console, *console.bgArrays)
    696          _lib.TCOD_console_fill_foreground(console, *console.fgArrays)
    697          _lib.TCOD_console_fill_char(console, console.chArray)
    698
    699      _lib.TCOD_console_flush()
    700
    701 -def setFont(path, tileWidth, tileHeight, colomn=False,
    702              greyscale=False, altLayout=False):
    703      """Changes the font to be used for this session.
    704      This should be called before L{tdl.init}
    705
    706      While it's possible you can change the font mid program it can sometimes
    707      break in rare circumstances.  So use caution when doing this.
    708
    709      @type path: string
    710      @param path: Must be a string filepath where a bmp or png file is found.
    711
    712      @type tileWidth: int
    713      @param tileWidth: The width of an individual tile.
    714
    715      @type tileHeight: int
    716      @param tileHeight: The height of an individual tile.
    717
    718      @type colomn: boolean
    719      @param colomn: Defines if the characer order goes along the rows or
    720                     colomns.
    721                     It should be True if the charater codes 0-15 are in the
    722                     first column.  And should be False if the characters 0-15
    723                     are in the first row.
    724
    725      @type greyscale: boolean
    726      @param greyscale: Creates an anti-aliased font from a greyscale bitmap.
    727                        Otherwise it uses the alpha channel for anti-aliasing.
    728
    729      @type altLayout: boolean
    730      @param altLayout: An alternative layout with space in the upper left
    731                        corner.  The colomn parameter is ignored if this is
    732                        True, find examples of this layout in the font/
    733                        directory included with the python-tdl source.
    734
    735      @raise TDLError: Will be raised if no file is found at path.
    736
    737      @note: A png file that's been optimized can fail to load correctly on
    738             MAC OS X creating a garbled mess when rendering.
    739             Don't use a program like optipng or just use bmp files instead if
    740             you want your program to work on macs.
    741      """
    742      # put up some constants that are only used here
    743      FONT_LAYOUT_ASCII_INCOL = 1
    744      FONT_LAYOUT_ASCII_INROW = 2
    745      FONT_TYPE_GREYSCALE = 4
    746      FONT_LAYOUT_TCOD = 8
    747      global _fontinitialized
    748      _fontinitialized = True
    749      flags = 0
    750      if altLayout:
    751          flags |= FONT_LAYOUT_TCOD
    752      elif colomn:
    753          flags |= FONT_LAYOUT_ASCII_INCOL
    754      else:
    755          flags |= FONT_LAYOUT_ASCII_INROW
    756      if greyscale:
    757          flags |= FONT_TYPE_GREYSCALE
    758      if not os.path.exists(path):
    759          raise TDLError('no file exists at: "%s"' % path)
    760      _lib.TCOD_console_set_custom_font(_format_string(path), flags, tileWidth, tileHeight)
    761
    762 -def getFullscreen():
    763      """Returns True if program is fullscreen.
    764
    765      @rtype: boolean
    766      @return: Returns True if the window is in fullscreen mode.
    767               Otherwise returns False.
    768      """
    769      if not _rootinitialized:
    770          raise TDLError('Initialize first with tdl.init')
    771      return _lib.TCOD_console_is_fullscreen()
    772
    773 -def setFullscreen(fullscreen):
    774      """Changes the fullscreen state.
    775
    776      @type fullscreen: boolean
    777      """
    778      if not _rootinitialized:
    779          raise TDLError('Initialize first with tdl.init')
    780      _lib.TCOD_console_set_fullscreen(fullscreen)
    781
    782 -def setTitle(title):
    783      """Change the window title.
    784
    785      @type title: string
    786      """
    787      if not _rootinitialized:
    788          raise TDLError('Not initilized.  Set title with tdl.init')
    789      _lib.TCOD_console_set_window_title(_format_string(title))
    790
    791 -def screenshot(path=None):
    792      """Capture the screen and save it as a png file
    793
    794      @type path: string
    795      @param path: The filepath to save the screenshot.
    796
    797                   If path is None then the image will be placed in the current
    798                   folder with the names:
    799                   screenshot001.png, screenshot002.png, ...
    800      """
    801      if not _rootinitialized:
    802          raise TDLError('Initialize first with tdl.init')
    803      if isinstance(fileobj, str):
    804          _lib.TCOD_sys_save_screenshot(_format_string(fileobj))
    805      elif isinstance(fileobj, file): # save to temp file and copy to file-like obj
    806          tmpname = os.tempnam()
    807          _lib.TCOD_sys_save_screenshot(_format_string(tmpname))
    808          with tmpname as tmpfile:
    809              fileobj.write(tmpfile.read())
    810          os.remove(tmpname)
    811      elif fileobj is None: # save to screenshot001.png, screenshot002.png, ...
    812          filelist = os.listdir('.')
    813          n = 1
    814          filename = 'screenshot%.3i.png' % n
    815          while filename in filelist:
    816              n += 1
    817              filename = 'screenshot%.4i.png' % n
    818          _lib.TCOD_sys_save_screenshot(_format_string(filename))
    819      else:
    820          raise TypeError('fileobj is an invalid type: %s' % type(fileobj))
    821
    822 -def setFPS(frameRate):
    823      """Set the maximum frame rate.
    824
    825      @type frameRate: int
    826      @param frameRate: Further calls to L{tdl.flush} will limit the speed of
    827                        the program to run at <frameRate> frames per second. Can
    828                        also be set to 0 to run without a limit.
    829
    830                        Defaults to None.
    831      """
    832      if frameRate is None:
    833          frameRate = 0
    834      assert isinstance(frameRate, int), 'frameRate must be an integer or None, got: %s' % repr(frameRate)
    835      _lib.TCOD_sys_set_fps(frameRate)
    836
    837 -def getFPS():
    838      """Return the current frames per second of the running program set by
    839      L{setFPS}
    840
    841      @rtype: int
    842      @return: Returns the frameRate set by setFPS.
    843               If set to no limit, this will return 0.
    844      """
    845      return _lib.TCOD_sys_get_fps()
    846
    847 -def forceResolution(width, height):
    848      """Change the fullscreen resoulution
    849
    850      @type width: int
    851      @type height: int
    852      """
    853      _lib.TCOD_sys_force_fullscreen_resolution(width, height)
    854
    855  __all__ = [_var for _var in locals().keys() if _var[0] != '_' and _var not in ['sys', 'os', 'ctypes', 'array', 'weakref', 'itertools']]
    856  __all__ += ['_MetaConsole'] # keep this object public to show the documentation in epydoc
    857