CELayoutUpgrader

From CEGUI Wiki - Crazy Eddie's GUI System (Open Source)
Jump to: navigation, search

Written for CEGUI 0.4


Works with versions 0.4.x (obsolete)

Introduction

CELayoutUpgrader is a python script that can upgrade XML layout files to the Unified Coordinate System. Hopefully it will make life a little easier. See this message board threadfor discussion.

Source

#!/usr/bin/env python
 
# CELayoutUpgrader: Upgrades CEGUI layout XML files to the Unified Coordinate System
# Copyright (C) 2006 Seth Yastrov <syastrov@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
import sys
import codecs
from glob import glob
 
from xml.dom import minidom
 
try:
  import xml.dom.ext
except ImportError:
  print 'Error importing PyXML: You need to install PyXML.'
  print 'The default XML pretty-printing implementation is pretty ugly.'
 
class InvalidDocumentError(Exception): pass
 
class UDim:
  def __init__(self, scale, offset):
    self.scale, self.offset = scale, offset
  def toString(self):
    return "{%f,%f}" % (self.scale, self.offset)
  def exists(self):
    return not (self.scale == self.offset == 0.0)
 
class UVector2:
  def __init__(self, xs, xo, ys, yo):
    self.xs, self.xo, self.ys, self.yo = xs, xo, ys, yo
  def toString(self):
    return "{{%f,%f},{%f,%f}}" % (self.xs, self.xo, self.ys, self.yo)
  def exists(self):
    return not (self.xs == self.xo == self.ys == self.yo == 0.0)
 
class URect:
  def __init__(self, ls, lo, ts, to, rs, ro, bs, bo):
    self.ls, self.lo, self.ts, self.to, self.rs, self.ro, self.bs, self.bo =\
      ls, lo, ts, to, rs, ro, bs, bo
  def toString(self):
    return "{{%f,%f},{%f,%f},{%f,%f},{%f,%f}}" %\
      (self.ls, self.lo, self.ts, self.to, self.rs, self.ro, self.bs, self.bo)
  def exists(self):
    return not (self.ls == self.lo == self.ts == self.to == self.rs ==\
      self.ro == self.bs == self.bo == 0.0)
 
def splitCoords(coords):
  result = {}
  for coord in coords.split(' '):
    name, value = coord.split(':',1)
    result[name] = value
  return result
 
def upgrade(file):
  try:
    doc = minidom.parse(file);
  except Exception, detail:
    raise IOError, ("Failed to parse `%s': %s" % (file, detail))
 
  global upgradeCount
  upgradeCount = 0
 
  if doc.firstChild.nodeName != 'GUILayout':
    raise InvalidDocumentError
 
  for window in doc.getElementsByTagName('Window'):
    # Collect all the old properties for each window
    coordProperties = ['RelativeMinSize', 'AbsoluteMinSize',\
      'RelativeMaxSize', 'AbsoluteMaxSize',\
      'Rect', 'RelativeRect', 'AbsoluteRect',\
      'Position', 'AbsolutePosition', 'RelativePosition',\
      'Size', 'RelativeSize', 'AbsoluteSize']
 
    properties = {}
    for child in window.getElementsByTagName('Property'):
      if child in window.childNodes:
        properties[child.getAttribute('Name')] = child.getAttribute('Value')
 
    for prop in coordProperties:
      if prop in properties:
        properties[prop] = splitCoords(properties[prop])
 
    def getUDim(properties, name):
      scale, offset = 0.0, 0.0
      if name in properties:
        scale = float(properties[name])
      if 'Relative'+name in properties:
        scale = float(properties['Relative'+name])
      if 'Absolute'+name in properties:
        offset = float(properties[('Absolute'+name)])
      return UDim(scale, offset)
 
    def getUVector2(properties, name, c1, c2):
      xs, xo, ys, yo = 0.0, 0.0, 0.0, 0.0
      if name in properties:
        xs, ys = float(properties[name][c1]), float(properties[name][c2])
      if 'Relative'+name in properties:
        xs, ys = float(properties['Relative'+name][c1]), float(properties['Relative'+name][c2])
      if 'Absolute'+name in properties:
        xo, yo = float(properties[('Absolute'+name)][c1]), float(properties[('Absolute'+name)][c2])
      return UVector2(xs, xo, ys, yo)
 
    def getURect(properties, name):
      ls, lo, ts, to, rs, ro, bs, bo = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
      if name in properties:
        ls, ts = float(properties[name]['l']), float(properties[name]['t'])
        rs, bs = float(properties[name]['r']), float(properties[name]['b'])
      if 'Relative'+name in properties:
        ls, ts = float(properties['Relative'+name]['l']), float(properties['Relative'+name]['t'])
        rs, bs = float(properties['Relative'+name]['r']), float(properties['Relative'+name]['b'])
      if 'Absolute'+name in properties:
        lo, to = float(properties['Absolute'+name]['l']), float(properties['Absolute'+name]['t'])
        ro, bo = float(properties['Absolute'+name]['r']), float(properties['Absolute'+name]['b'])
      return URect(ls, lo, ts, to, rs, ro, bs, bo)
 
    width = getUDim(properties, 'Width')
    height = getUDim(properties, 'Height')
    xposition = getUDim(properties, 'XPosition')
    yposition = getUDim(properties, 'YPosition')
    position = getUVector2(properties, 'Position', 'x', 'y')
    size = getUVector2(properties, 'Size', 'w', 'h')
    minSize = getUVector2(properties, 'MinSize', 'w', 'h')
    maxSize = getUVector2(properties, 'MaxSize', 'w', 'h')
    rect = getURect(properties, 'Rect')
 
    # Add new unified ones
    def addProperty(parent, name, value):
      global upgradeCount
      upgradeCount += 1
 
      node = doc.createElement('Property')
      node.setAttribute('Name', name)
      node.setAttribute('Value', value)
      window.insertBefore(node, parent.firstChild)
      return node
 
    if width.exists():
      addProperty(window, 'UnifiedWidth', width.toString())
    if height.exists():
      addProperty(window, 'UnifiedHeight', height.toString())
    if xposition.exists():
      addProperty(window, 'UnifiedXPosition', xposition.toString())
    if yposition.exists():
      addProperty(window, 'UnifiedYPosition', yposition.toString())
 
    if position.exists():
      addProperty(window, 'UnifiedPosition', position.toString())
    if size.exists():
      addProperty(window, 'UnifiedSize', size.toString())
    if minSize.exists():
      addProperty(window, 'UnifiedMinSize', minSize.toString())  
    if maxSize.exists():
      addProperty(window, 'UnifiedMaxSize', maxSize.toString())  
 
    if rect.exists():
      addProperty(window, 'UnifiedAreaRect', rect.toString())  
 
  # Remove old coord system nodes
  for child in doc.getElementsByTagName('Property'):
    if child.getAttribute('Name') in coordProperties:
      child.parentNode.removeChild(child)
      child.unlink()
 
  f = codecs.open(file, 'w', 'utf-8')
  #doc.writexml(f, "", "    ")
  xml.dom.ext.PrettyPrint(doc, f, indent='\t')
  f.close()
 
def usage(scriptname):
  print 'Usage: %s FILES' % scriptname
  print 'FILES can be a glob-style pattern or a list of files.'
 
def main(argv):
  print 'CELayoutUpgrader: Upgrades CEGUI layout XML files to the Unified Coordinate System'
  print 'Copyright (C) 2006 Seth Yastrov <syastrov@gmail.com>\n'
 
  if len(argv) < 2:
    usage(argv[0])
    sys.exit(2)
 
  global upgradeCount
 
  for arg in argv[1:]:
    for file in glob(arg):
      try:
        upgrade(file)
      except InvalidDocumentError:
        print "'%s' => Failed. Does not appear to be a valid GUILayout file." % file
        sys.exit(2)
      except IOError, detail:
        print "'%s' => %s" % (file, detail)
      else:
        print "'%s' => Upgraded (%d properties)" % (file, upgradeCount)
 
if __name__ == "__main__":
  main(sys.argv)

Dependencies

  • Python (any relatively recent version will do)
  • PyXML (0.8 and up should be fine)

Usage

python CELayoutUpgrader.py FILES

FILES can be a glob-style pattern or a list of files.

Example

If you have a directory with a bunch of .layout files in it, stick the script in that directory and run it like this:

python CELayoutUpgrader.py *.layout

How it works

It will parse the layout files you specified searching for old-style properties. It will convert each one to the Unified Coordinate System equivalent. If the file already has some Unified Coordinate System properties, it will leave them in place. After upgrading each file, it will report how many properties it upgraded.