Difference between revisions of "CELayoutUpgrader"

From CEGUI Wiki - Crazy Eddie's GUI System (Open Source)
Jump to: navigation, search
Line 4: Line 4:
 
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 [http://www.cegui.org.uk/phpBB2/viewtopic.php?t=1766 message board thread]for discussion.
 
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 [http://www.cegui.org.uk/phpBB2/viewtopic.php?t=1766 message board thread]for discussion.
  
= Download =
+
= Source =
 +
<source lang="python">
 +
#!/usr/bin/env python
  
[[CELayoutUpgrader.py]].
+
# 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
 +
from string import *
 +
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, str(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 (properties.has_key(prop)):
 +
        properties[prop] = splitCoords(properties[prop])
 +
   
 +
    def getUDim(properties, name):
 +
      scale, offset = 0.0, 0.0
 +
      if (properties.has_key(name)):
 +
        scale = float(properties[name])
 +
      if (properties.has_key('Relative'+name)):
 +
        scale = float(properties['Relative'+name])
 +
      if (properties.has_key('Absolute'+name)):
 +
        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 (properties.has_key(name)):
 +
        xs, ys = float(properties[name][c1]), float(properties[name][c2])
 +
      if (properties.has_key('Relative'+name)):
 +
        xs, ys = float(properties['Relative'+name][c1]), float(properties['Relative'+name][c2])
 +
      if (properties.has_key('Absolute'+name)):
 +
        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 (properties.has_key(name)):
 +
        ls, ts = float(properties[name]['l']), float(properties[name]['t'])
 +
        rs, bs = float(properties[name]['r']), float(properties[name]['b'])
 +
      if (properties.has_key('Relative'+name)):
 +
        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 (properties.has_key('Absolute'+name)):
 +
        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)
 +
</source>
  
 
= Dependencies =
 
= Dependencies =
Line 22: Line 233:
 
If you have a directory with a bunch of .layout files in it, stick the script in that directory and run it like this:
 
If you have a directory with a bunch of .layout files in it, stick the script in that directory and run it like this:
  
<code>python CELayoutUpgrader.py *.layout</code>
+
python CELayoutUpgrader.py *.layout
  
 
= How it works =
 
= How it works =

Revision as of 17:25, 4 March 2011

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
from string import *
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, str(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 (properties.has_key(prop)):
        properties[prop] = splitCoords(properties[prop])
 
    def getUDim(properties, name):
      scale, offset = 0.0, 0.0
      if (properties.has_key(name)):
        scale = float(properties[name])
      if (properties.has_key('Relative'+name)):
        scale = float(properties['Relative'+name])
      if (properties.has_key('Absolute'+name)):
        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 (properties.has_key(name)):
        xs, ys = float(properties[name][c1]), float(properties[name][c2])
      if (properties.has_key('Relative'+name)):
        xs, ys = float(properties['Relative'+name][c1]), float(properties['Relative'+name][c2])
      if (properties.has_key('Absolute'+name)):
        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 (properties.has_key(name)):
        ls, ts = float(properties[name]['l']), float(properties[name]['t'])
        rs, bs = float(properties[name]['r']), float(properties[name]['b'])
      if (properties.has_key('Relative'+name)):
        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 (properties.has_key('Absolute'+name)):
        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.