2d camera mouse coordinates

here is a snipplet for getting the mouse position for a 2d game (2d orthographical lens)
you could use it to drag around objects or so…

from pandac.PandaModules import *

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject

class Picking2D(DirectObject):
    def __init__(self):
        base.disableMouse()
        base.setBackgroundColor(0.0, 0.0, 0.0, 1)
        
        seg = LineSegs()
        seg.setColor(VBase4(1,1,1,1))
        seg.setThickness(1.0)
        seg.moveTo(Point3(-20,0,-20))
        seg.drawTo(Point3(20,0,-20))
        seg.drawTo(Point3(20,0,20))
        seg.drawTo(Point3(-20,0,20))
        seg.drawTo(Point3(-20,0,-20))
        np = render.attachNewNode(seg.create())
        
        #setup 2d camera-lens
        lens = OrthographicLens()
        ratio = base.getAspectRatio()
        lens.setFilmSize(100.0, 100.0/ratio)
        base.cam.node().setLens(lens)
        base.cam.setPos(0, -100, 0)

        self.accept('mouse1', self.startPrintTask)
        self.accept('mouse1-up', self.stopPrintTask)
        taskMgr.add(self.moveCam, "moveCamTask")
        
    def startPrintTask(self):
        taskMgr.add(self.dragTask, "dragTask")
        
    def stopPrintTask(self):
        taskMgr.remove("dragTask")
        
    def dragTask(self, task):
        orig = self.getOrig()
        dir = self.getDir()
        if dir:
            dest = orig + dir
            print dest
            
        return task.cont
        
    def moveCam(self, task):
        if not base.mouseWatcherNode.hasMouse(): return task.cont
        mpos=base.mouseWatcherNode.getMouse()
#        print mpos
        
        p = Point2(0,0)
        x = mpos.getX()
        y = mpos.getY()
        
        if x < -0.65 or x > 0.65:
            p.setX(x)
        if y < -0.65 or y > 0.65:
            p.setY(y)
            
        if p.getX() != 0 or p.getY() != 0:
            pos = base.cam.getPos()
            factor = globalClock.getDt() * 100.0
            pos.setX(pos.getX()+p.getX() * factor)
            pos.setZ(pos.getZ()+p.getY() * factor)
            base.cam.setPos(pos)
            
        return task.cont
    
    def getDir(self):
        if not base.mouseWatcherNode.hasMouse(): return None
        mpos=base.mouseWatcherNode.getMouse()

        factor = base.cam.node().getLens().getFilmSize().getX()/2.0
        x = mpos[0] * factor
        z = (mpos[1]/base.getAspectRatio()) * factor
        point = Point3(x,100,z)
        dir = render.getRelativeVector(base.cam, point)
        
        return dir
    
    def getOrig(self):
        origin = base.cam.getPos(render)
        return origin
    
if __name__ == '__main__':
    m = Picking2D()
    run()

With my 2500 fps, the square immediately disappears when my mouse moves to the corner.
Try multiplying with globalClock.getDt() for framerate independent movements:

            pos.setX(pos.getX()+p.getX() * globalClock.getDt() * 100)
            pos.setZ(pos.getZ()+p.getY() * globalClock.getDt() * 100)

yes thanks, i updated it in the code above.
this happens when vsync is off.
i didn’t think of it…

greets

crashes when i move cursor with pressed mouse button out of the window for about 200px. here the traceback:

Traceback (most recent call last):
  File "orto.py", line 89, in <module>
    run() 
  File "/opt/panda3d/direct/src/showbase/ShowBase.py", line 2266, in run
    self.taskMgr.run()
  File "/opt/panda3d/direct/src/task/Task.py", line 965, in run
    self.step()
  File "/opt/panda3d/direct/src/task/Task.py", line 903, in step
    self.__stepThroughList(taskPriList)
  File "/opt/panda3d/direct/src/task/Task.py", line 802, in __stepThroughList
    ret = self.__executeTask(task)
  File "/opt/panda3d/direct/src/task/Task.py", line 721, in __executeTask
    ret = task(*task.extraArgs)
  File "orto.py", line 41, in dragTask
    dest = orig + dir
TypeError: Must Match :
__add__(const Point3 this, const Vec3 other)
__add__(const Point3 this, const VBase3 other)

Hmm, looking at the code, it seems you need to replace this:

#        print mpos 

with this:

        return task.cont

the problem is the getDir-function, where i return None, if not base.mouseWatcherNode.hasMouse().
so checking the value of getDir() solves the problem.

by the way, i don’t get this error on my P3D_1.5.4 installation on windows xp…

greets

Nope, on Windows, the MouseWatcher code can always return a mouse position, even when the mouse is out of the window.
On Linux, however, it can’t track the mouse position when it’s outside of the window (which you can check by calling hasMouse.)