unicode

Hello,

Does anybody can publish an example for using unicode with Panda?

This code doesn’t work:

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.gui.DirectGui import *
from pandac.PandaModules import *
from direct.gui.OnscreenText import OnscreenText


class World(DirectObject):
  def __init__(self):
    text = TextNode('node name')
    text.setText(u'\u041F\u0440\u0438\u0432\u0435\u0442')
    text.setEncoding(2)
    textNodePath = aspect2d.attachNewNode(text)
    textNodePath.setScale(0.07)

w = World()

run()

An error is:

>ppython utf.py
DirectStart: Starting the game.
Warning: DirectNotify: category 'Interval' already exists
Known pipe types:
  wdxGraphicsPipe8
(3 aux display modules not yet loaded.)
Traceback (most recent call last):
  File "utf.py", line 16, in ?
    w = World()
  File "utf.py", line 11, in __init__
    text.setText(u'\u041F\u0440\u0438\u0432\u0435\u0442')
  File "TextNode", line 5045, in setText
  File "TextNode", line 1400, in __overloaded_setText_ptrTextNode_atomicstring
UnicodeError: ASCII encoding error: ordinal not in range(128)

Thank you very much

Panda does not (currently) accept the Python Unicode objects directly, but you can use Python’s codecs mechanism to encode them to utf-8 (or pre-encode them yourself). Note that the default Panda built-in font does not include definitions for Cyrillic characters, so you will have to load your own font:

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.gui.DirectGui import *
from pandac.PandaModules import *
from direct.gui.OnscreenText import OnscreenText
import codecs

class World(DirectObject):
  def __init__(self):
    font = loader.loadFont('/c/WINDOWS/Fonts/msmincho.ttc')
    text = TextNode('node name')
    text.setFont(font)
    text.setEncoding(TextNode.EUtf8)
    ustr = u'\u041F\u0440\u0438\u0432\u0435\u0442'
    text.setText(codecs.utf_8_encode(ustr)[0])
    textNodePath = aspect2d.attachNewNode(text)
    textNodePath.setScale(0.07)

w = World()

run()

David

On reflection, you can set up Python to automatically convert its Unicode strings into utf-8 for Panda. To do this, you must create a special file called sitecustomize.py which must be located in some directory your python path (for instance, in the current directory). Python will search file this file on startup and load it automatically (and silently) if it is found. Put the following in this file:

import sys
sys.setdefaultencoding('utf8')
print "Encoding set to UTF8"

If you don’t see that print message at startup, you didn’t put sitecustomize.py in the right place. See www.python.org for more information about sitecustomize.py and setdefaultencoding().

You can also automatically configure Panda to select utf-8 by default, and even to use a suitable font by default. Put the following in your Config.prc file:

text-encoding utf8
text-default-font /c/WINDOWS/Fonts/msmincho.ttc

Now your program above works unmodified:

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.gui.DirectGui import *
from pandac.PandaModules import *
from direct.gui.OnscreenText import OnscreenText

class World(DirectObject):
  def __init__(self):
    text = TextNode('node name')
    text.setText(u'\u041F\u0440\u0438\u0432\u0435\u0442')
    textNodePath = aspect2d.attachNewNode(text)
    textNodePath.setScale(0.07)

w = World()

run()

Of course, it would be better to supply your own font along with your application, rather than digging around in the Windows system directory (which is not in the same place on every Windows machine, and doesn’t even exist on Linux machines, of course). But loading the font out of the Windows system directory is fine for development on your own machine.

David

David,

Thank you very much for your help!

Yes, it works good with UTF8 (Ciryllic is ok too).

I made some more samples. OnscreenText works fine with UTF8.
But DirectButton has some problem with size.

This is a test for OnscreenText (works fine):

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.gui.DirectGui import *
from pandac.PandaModules import *
from direct.gui.OnscreenText import OnscreenText 

class World(DirectObject):
  def __init__(self):
    self.textObject = OnscreenText(text = u'\u041F\u0440\u0438\u0432\u0435\u0442') 

w = World()

run()

This is a test for DirectButton (has some problem):

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.gui.DirectGui import *
from pandac.PandaModules import *
from direct.gui.OnscreenText import OnscreenText 

class World(DirectObject):
  def __init__(self):
    self.textButton = DirectButton(text = u'\u041F\u0440\u0438\u0432\u0435\u0442')

w = World()

run()

Please run this test and you will see first letter in Cyrillic, but size is not ok. Thank you very much for your help.

This appears to be a minor bug in the DirectGui system; it is not recognizing that the unicode text is a legitimate string. I apologize for this bug. I will put in a fix for a future version of Panda, in the meantime you can work around the bug like this:


self.textObject = OnscreenText(text = str(u'\u041F\u0440\u0438\u0432\u0435\u0442'))

David

Hello David,

No, OnscreenText is working fine.

DirectButton has an error.

It is not urgent request, but if you will fix it many non-english speacking users will be appreciated to your help!

Thank you very much.

Oops, my mistake. I understand that OnscreenText is working; I meant to use DirectButton in the above. The point is that if you wrap the str() function around your text string, DirectButton will accept it correctly.

David

David,

Thank you very much. It works.

Thanks for fast and informative solution. It seems now we have everything to create game based on Cyrillic letters.