Is There an OnscreenImage Mouse Over function?

Hey all,

I’ve been working on a strategy game that a group of friends and I designed a while back. It takes place during the Civil War. This is what it looks like so far:

The game essentially works like Risk. Of course, I have no ideas of how to capture the user’s mouse position and translate it into which state they selected. The only other option that came to mind was a ridiculously long image map, but I’m pretty sure there’s an easier way.

I’m using OnscreenImage to produce the pictures. Each state image was selected from one original map, so there is a large amount of transparent image underneath. Any ideas?

You’re very welcome, and I’m glad I was able to help solve your problem! Good luck in your adventures! :smiley:

I fear, given that poster’s responses to other threads (and in particular the links included), that he, she or it was likely a spammer. :confused:

However, as to your question, the only terribly good-seeming idea that has come to me thus far has been to set up some collision geometry that roughly matches the shapes of the various states, likely extending slightly beyond their borders but ideally not overlapping each other, and then use a picking ray to select them.

This is not a solution, but an idea for an improvement:
http://content.gpwiki.org/index.php/Magnetism_pattern

Maybe later, with more complex needs, it will help. But now, I agree with Thaumaturge. See also this manual page:
http://www.panda3d.org/manual/index.php/Clicking_on_3D_Objects.

The builtin sample ‘Chessboard’ are using kind of this technique.

Hello!

I have another question for you, if it isn’t too much trouble. I’ve defeated the last obstacle, but another quickly arose.

I am having a terrible time removing a floating highlight I plan to have. It is an OnscreenImage like the rest of the program, but it refuses to disappear. I have tried numerous combinations of detachNode(), removeNode(), and destroy(), but none seem to work.

Whenever I try to destroy() it, I get the error message:

AttributeError: 'libpanda.NodePath' object has no attribute 'destroy'

Any and all help is appreciated, and thanks again!

Things in Python don’t get destroyed until you have removed all of your references to it. However, removeNode() should detach it from its parent node, which should make it disappear from the window.

Could you show some code?

Certainly! As of now, I’m using a task to accomplish this. Also, in order to save the highlight data for the next iteration without it being set to 0 each time, I’m using a pickle.


def mousetask(task):
    """Piece of poop meant to highlight each state"""
    #Mouse-specific bounds:
    #X: -1.0 to 1.0
    #Y: -1.0 to 1.0
    #Multiply X by 2 (the graphics' range)(I think...)
    if base.mouseWatcherNode.hasMouse():
        x = base.mouseWatcherNode.getMouseX() * 2
        y = base.mouseWatcherNode.getMouseY()
    else:
        x = 0
        y = 0
    #Pickles!
    f = open("foo.dat", "rb")
    HL = pickle.load(f)
    HLstate = pickle.load(f)
    f.close()
    print("HL:", HL)
    print("HLstate:", HLstate)

    for s in states:
        if x + .02 > s.center[0] and x - .02 < s.center[0]:
            if y + .02 > s.center[1] and y - .02 < s.center[1]:
                f = open("foo.dat", "wb")
                HL = OnscreenImage(image="img/"+s.acr.upper()+"O.png", pos=(.5, 0, -.1), scale=(.9, 1, .6))
                HL.setTransparency(TransparencyAttrib.MAlpha)
                HLstate = s
                print(HL, HLstate)
                pickle.dump(HL, f)
                pickle.dump(HLstate, f)
                f.close()

    if HL:
        if x + .02 < HLstate.center[0] or x - .02 > HLstate.center[0]:
            f = open("foo.dat", "wb")
            #Specifically, this is where I run into problems.
            HL.detachNode()
            HL.removeNode()
            HL.destroy()
            pickle.dump(0, f)
            pickle.dump(0, f)
            f.close()
        if y + .02 < HLstate.center[1] or y - .02 > HLstate.center[1]:
            #Here as well.
            f = open("foo.dat", "wb")
            HL.detachNode()
            HL.removeNode()
            HL.destroy()
            pickle.dump(0, f)
            pickle.dump(0, f)
            f.close()

    return task.cont

Basically, once the cursor moves out of range of HLstate.center, I want both HL and HLstate to be erased and the pickle overwritten… If that helps.

You’re using the variable “HL” twice for something different. Once for the result of pickle.load, and once for the OnscreenImage. You should rename one of those.
Or am I misunderstanding, perhaps? Is the OnscreenImage itself stored in the file? That seems odd to me.

Also, calling detachNode, then removeNode, and then destroy is pointless. destroy already internally calls removeNode, and removeNode already internally calls detachNode. Just destroy() will suffice, or better yet, removeNode(). destroy() is OnscreenImage specific and simply calls removeNode() internally.

Yes, I am storing the OnscreenImage in the file and, yes, it is odd. I’ve been quite desperate. :smiley:

I have also heard that, in order to destroy an object, all references to it must be destroyed in turn. Would it be the pickle that’s holding me back? Simply calling destroy does not work.

Hmm… First of all, I fear that you’ve significantly overcomplicated this implementation; a simpler approach might give you less trouble. ^^;

That said, I think that I see the problem. If I’m reading your code correctly:

You first load a highlight and highlight state from pickle, calling them HL and and HLstate respectively.

You then go on to define the new highlights and highlight states for the current iteration, calling them each HL and HLstate - thus replacing each previous reference held by HL and HLstate, starting with the ones that you loaded.

If there are any new highlights at all, then by the time that you reach the code that removes the old highlight you are actually telling it to remove the most recent highlight.

As things stand, the simplest solution might be to rename the versions that you’re loading from pickle - call them “HLold” and “HLstateOld”, perhaps - and then remove those.

However, if I may suggest:

Should there ever be more than one highlight?

If so, then I note that you seem to reload only the first from the pickle file; any others are presumably missed and thus never removed.

If, however, there should never be more than one highlight, then I recommend simply keeping a single OnscreenImage for that highlight. When there is no highlight, hide it (HL.hide()), and when a highlight should be present, show it (HL.show()), first placing in the appropriate position.

This would also allow you to get rid of the pickling involved in your current implementation, which I fear is a significant element of the aforementioned overcomplication.