DirectEntry in 3D environment


#1

Is it possible to create application where
when the user presses some keys (i.e types something through keyboard)
that text appears above the character(or anywhere on the screen for that matter).

e.g In Roaming Ralph sample when I type something that text should appear above the ralph(as DirectLabel or DirectEntry).
Any ideas on how to achieve this.

Thanks


#2

discourse.panda3d.org/viewtopic.php?t=3486


#3

I think you misunderstood.
I don’t want static text to appear above the character.

I want to develop a 3D chat kinda thing where the user will be typing and simultaneously the alphabets(being typed) will appear above the character.

Any ideas on how to achieve this.


#4

Who told you that the text is static ? It’s modifiable if you use mayChange=1.
Take advantage of offscreen DirectEntry and instance it to the avatar’s top, so you would get the blinking cursor too.

from pandac.PandaModules import *
loadPrcFileData('','''
sync-video 1
''')
import direct.directbase.DirectStart
from direct.interval.IntervalGlobal import *
from direct.gui.DirectGui import *
from direct.showbase.DirectObject import DirectObject
import sys

class World(DirectObject):
  def __init__(self):
      base.setFrameRateMeter(1)
      base.disableMouse()
      camera.setY(-15)
      
      self.startChatKey='enter'
      self.accept('escape',sys.exit)
      self.acceptOnce(self.startChatKey, self.startTextInput)
      
      dummy=render.attachNewNode('dummy')
      smi=loader.loadModel('smiley')
      smi.reparentTo(dummy)
      smi.setX(3)
      dummy.hprInterval(5,Vec3(-360,0,0)).loop()
      
      chatTextParent=aspect2d.attachNewNode('chat text dummy')
      self.chatTextDE = DirectEntry( parent=chatTextParent,
                      width=20, numLines=3,
                      frameColor=(0,0,0,0),
                      text_fg=(1,1,1,1), #text_shadow=(0,0,0,1),
                      text_align=TextNode.ACenter,
                      text='SMILEY', # the name
                      text_pos=(0,-1.2),
                      initialText='_____________ press Enter to chat _____________',
                      command=self.stopTextInput)
      chatTextParent.setZ(-5) # put it offscreen
#       self.chatTextDE.hide()

      # dummy node for the billboard, or else the result would be weird
      # if there is translation on the node
      chatTextOutputParent=smi.attachNewNode('chat text dummy')
      self.chatTextOutput=self.chatTextDE.instanceUnderNode(chatTextOutputParent,'chat text')
      self.chatTextOutput.setScale(.2)
      self.chatTextOutput.setZ(smi.getTightBounds()[1][2]+1) # put it above smiley
      chatTextOutputParent.setBillboardPointEye()

  def startTextInput(self):
      self.chatTextDE.show()
      self.chatTextDE['focus']=1
      # setting '' as text places the cursor on the left side, not center.
      # So use space, nobody would notice.
      self.chatTextDE.set(' ') 
      print 'START INPUT'

  def stopTextInput(self,c):
      # keypress input check is performed after DirectEntry command,
      # so let a frame pass by before accepting the key
      taskMgr.step() 
      self.acceptOnce(self.startChatKey, self.startTextInput)
      print 'STOP INPUT',c

World()
run()

#5

Oh…I didn’t know this earlier.
Thanks a lot. This is really great. :laughing:

Edit: Actually, ynjh_jo, You have made my day. Thanks again.


#6

ynjh_jo, once again you are doing something clever here and I am trying to understand it. The difficulty is understanding the instanceUnderNode function, which is not well described in the docs:

It’s the description of instanceTo that is really bad. It’s the kind of thing that really needs a picture (of the scene graph before and after the opetation) to be comprehensible. The page on instancing in the manual helps though.

If I understand your code, you create a DirectEntry (chatTextDE) in the 2D scene graph, and move it off screen. But then you use instanceUnderNode to create a node, chatTextOutput, which I think has two parents, chatTextOutputParent in the 3D scene and chatTextDE in the 2D scene. It is as if chatTextOutput is a copy (instance) of chatTextDE that moves around in the 3D scene, giving you the behaviour of a DirectEdit without actually placing one into the 3D scene. Do I have the right idea?

Why would you do this? Is it not possible to simply place a DirectEdit in the 3D scene? And is this why you have to press a key to start typing rather than clicking on the text field?

I hacked your code to place the DirectEdit chatTextDE directly into the 3D scene graph instead (I attached it to chatTextOutputParent) and this seemed to confirm my suspicion: typing into the DirectEdit didn’t work. But I’m surprised because I don’t see why this shouldn’t just work.

Thanks


#7

The returned node of instanceTo is referencing the same actual node. You can’t have individual different states across instances this way.
So, you have to create a dummy parent node above each instance, which is exactly what instanceUnderNode does. The returned node is the dummy parent, so you have a free slot for different states, which propagates to the individual instance.

Yes, you’ve got the idea.
Now you know that DirectGUI objects don’t work outside aspect2d.