Ray Casting for Drag/Drop in 2.53

Hi everyone,

I have a couple of questions:

  1. With generous help from the community(read Monster and Almost) here, I have this script that enables the dragging and dropping of objects. Here it is:
import GameLogic
import Rasterizer
import mousetools
from Mathutils import Vector

motionSpeed = 5
rotationSpeed = 5
#find point on 2D plane of fixed z
#that is between the camera and the hitposition
lowestLevel = 0.5 #this is the fixed z  value

#---- debugging function not really needed
def moveToTargetPosition(cont):
    Moves the owner of the controller to the position stored 
    in the property "targetPosition" of the owner of the first sensor.
        cont.owner.worldPosition = cont.sensors[0].owner["targetPosition"]
    except KeyError:
#---- utility function
def onePositive(cont):
    for sensor in cont.sensors:
        if sensor.positive:
            return True
    return False
#---- Just to make the cursor visible
def showMouse(cont):
    if not onePositive(cont):
    print "show Mouse"
def hideMouse(cont):
    if not onePositive(cont):
    print "hide Mouse"

#---- dragging functions        
def storeDraggedObject(own, hitObject):
    if hitObject != None and "drag" in hitObject: 
        own["draggedObject"] = hitObject
        own["draggedObject"] = None

def getDraggedObject(own):
        return own["draggedObject"]
        return None

def getTargetPosition(overAny, restriction, axis):
    raySource = Vector(overAny.raySource)
    hitPosition = Vector(overAny.hitPosition)
    rayVector = hitPosition-raySource
    if not "drag" in overAny.hitObject \
    and hitPosition[axis] > restriction:
        targetPosition = hitPosition
        planeContactPoint = ( restriction-raySource[axis])/rayVector[axis]
        targetPosition = (rayVector*planeContactPoint) + raySource
    return targetPosition

#---- BGE callable functions
def startDrag(cont):
    overAny = cont.sensors["overAny"]
    activateDrag = cont.sensors["activateDrag"]
    if activateDrag.triggered: #just activated
        storeDraggedObject(cont.owner, overAny.hitObject)

def endDrag(cont):
    activateDrag = cont.sensors["activateDrag"]

    if not activateDrag.positive:# no dragging
        storeDraggedObject(cont.owner, None)

def doDrag(cont):
    overAny = cont.sensors["overAny"]
    activateDrag = cont.sensors["activateDrag"]
    activateRotation = cont.sensors["activateRotation"]
    if not activateDrag.positive: #not active
    draggedObject = getDraggedObject(cont.owner)
    if draggedObject == None:
        #Nothing to drag

    if overAny.positive:
        restrictedAxis = cont.owner["restrictedAxis"]
        restriction = draggedObject.worldPosition[restrictedAxis]
        targetPosition = getTargetPosition(overAny, restriction, restrictedAxis)
        #just for debugging see moveToTargetPosition
        cont.owner["targetPosition"] = targetPosition
    currentPosition = Vector(draggedObject.position)
    rayToWall = draggedObject.rayCast(targetPosition,draggedObject,0,'wall')
    if rayToWall[0] == None:
        targetPosition = targetPosition
        targetPosition = rayToWall[1]
    speed = motionSpeed
    vec = (targetPosition - currentPosition)*speed
    # only move in motion mode
    if not activateRotation.positive:

#---- All in one    
def dragDrop(cont):
    overAny = cont.sensors["overAny"]
    activateDrag = cont.sensors["activateDrag"] 
    activateRotation = cont.sensors["activateRotation"]
    if not activateDrag.positive:# no dragging
    if activateDrag.triggered: #just activated
    if activateDrag.positive: #activate

Could someone please outline the changes I need to make to port this to 2.53?

  1. As for the algorithm itself, could someone dilineate what makes a ray casting algorithm faster / more efficient?

Thanks a lot,

To convert to 2.53 you must:

  1. Change GameLogic to bge.logic

  2. Change Rasterizer to bge.render

  3. Change “from Mathutils import Vector” to “from mathutils import Vector”

  4. Change and .position attributes to .worldPosition

  5. Any functions that returned a list in 2.49 now return a vector, so .hitPosition, .raySouce, .worldPosition no longer need to be made Vectors because they already are.

Optimisation to the script:

  1. getDraggedObject(own) can be replaced with “draggedObject = cont.owner.get(“draggedObject”, None)”

Other than that it looks like a pretty good script. The ray casting can’t really be optimised by python, its coded in C so the performance can be expected to be pretty decent.

Thanks a lot :slight_smile:

Is there some place I can read about these functions to understand what happens under the hood better? I get the bigger picture rather crudely and the intricacies elude me.

For eg. I want to understand how the vector math behind raycasting works.
And the details behind hitob.
And what is meant by cont.owner[“restrictedAxis”]…I cant find where these things are defined. Is it like the “restrictedAxis” is a property of the owner?

Pardon the ignorance…I feel quite stupid :slight_smile:

Moguri has summed up the difference between 2.49 and 2.5 APIs:

If there is a specific function you are un-aware of you can look it up in the documentation, the documentation includes both the “normal blender” and the GE API. You should make sure you understand the difference in them. The bpy module is the normal blender module and bge is the GE module. All the other modules can be used by both APIs (mathutils, geometry ect)

cont.owner[“retrictedAxis”] is exactly the property of the object set in the logic editor.

In regards to the ray casting and vector stuff, I am perhaps not the best person to answer that ^.^

P.S, you don’t sound ignorant at all, stupid in regards to the BGE API maybe but not ignorant