Not sure how to describe this problem, (Video)

In the video I wave my cursor over the part of the code that scales the cube object (that has wireframe material) to match up with where the mouse cursor is, and I’ve provided the blend file below.

I’m not sure how to get a local location out of the mouse cursor, relative to where the cube object that scales is spawned. I might not be wording all this correctly, so my apologies for any misunderstandings. :spin:

Selection.blend (527 KB)

You just need to rotate the indicator and the scaling vector by the camera’s orientation matrix (with the z-component removed since I assume you don’t want your selection box to move out of the 2D plane).

Here’s a handy function you can use to get that matrix:

def get_camera_orientation_matrix(camera):
    camMat = camera.worldOrientation.copy()
    if camMat.col[2].z < 0:
        invert = -1
    else:
        invert = 1
    camMat.col[2] = [0, 0, 1]
    yAxis = camMat.col[1]
    yAxis.x *= invert
    yAxis.y *= invert
    yAxis.z = 0
    yAxis.normalize()
    return camMat

You can align the indicator like this:

indicator = scene.objects['indicator']
camMat = get_camera_orientation_matrix(scene.active_camera)
indicator.worldOrientation = camMat

And you can rotate the scaling vector before applying it like this:


# Remember to import mathutils
scaleVec = mathutils.Vector((
    (mouse_hit.localPosition[0] - own.localPosition[0]),
    -(mouse_hit.localPosition[1] - own.localPosition[1]),
    1
))
scaleVec.rotate(get_camera_orientation_matrix(scene.active_camera))

own.localScale = scaleVec

Do you mean

  • selection along screen or
  • selection along level (ground)


Selection along the ground.

If that’s the case, all you need to do is prevent the selection object from being rotated. You can do this by setting its orientation matrix to the identity matrix, or more simply by just adding it from an object that you know will never be rotated (the plane for example) instead of the rotated indicator.

Here is a demo

Attachments


SelectionArea.blend (513 KB)

I’m not exactly sure what you did, I see longer code, but the problem I stated in the video still remains.

Prevent it from being rotated? I’m trying to have it along the ground, but it align to the camera view, I succeed in aligning it to the camera view in the video, but the object scaling to the cursor is off when I rotate it.

I was wanting to know if there was a way to incorporate the rotation of the object in my code to give the scaling a sort of local location, where it will align with the mouse cursor regardless of rotation.

That’s exactly what the code in my first post does. Did you try it yet?

Well I am relatively new to using python for my games, and copy and paste your code as I might, I can’t seem to make it work.
You seem to be accessing stuff and terms I’ve never seen before, like,

yAxis.normalize()

I don’t know where you got yAxis from, or what objects Y axis you accessing, nor have I ever seen the term .normalize().

camMat.col[2] = [0, 0, 1]
yAxis = camMat.col[1]

I don’t know what a .col is or how you would get it from an objects orientation matrix, things like these are stumping me.

Judging by the structure of your code I’m sure you’ve achieved what I want, but the more I use these forums the more I realize there are so many things I’ve yet to learn in the python language, apparently some fundamentals as I can see. :spin:

So I haven’t tested it, I don’t know how to apply the code you’ve written.

Small change in the calculation. It considers the transformation of the object Selection.area. The above code used the position only.


import bge
from  mathutils import Vector

def startDragging():
    if not allSensorsPositive():
        return
    
    hitPosition = getHitPosition()
    
    areaMarker = getOwner()
    areaMarker.worldPosition.xy = hitPosition.xy
    areaMarker.localScale.xy = (0,0)
    
    activateAllActuators()
    
def drag():
    if not allSensorsPositive():
        return

    hitPosition = Vector(getHitPosition())
    
    areaMarker = getOwner()
    areaMarker.localScale.xy = (1,1)
         
    endPosition = areaMarker.worldTransform.inverted() * hitPosition
    areaMarker.localScale.xy = endPosition.xy
 
def release():
    activateAllActuators()
        
def allSensorsPositive():
    for sensor in bge.logic.getCurrentController().sensors:
        if not sensor.positive:
            return False
    return True

def getHitPosition():
    for sensor in bge.logic.getCurrentController().sensors:
        try:
            return sensor.hitPosition
        except AttributeError:
            continue

def getOwner():
    return bge.logic.getCurrentController().owner

def activateAllActuators():
    controller = bge.logic.getCurrentController()
    for actuator in controller.actuators:
        controller.activate(actuator)

Modified the demo to let Selection.area turn as well.


Attachments

SelectionArea.blend (536 KB)

Works like a charm, thanks Prof! :slight_smile: