stop mouseclick in main scene while clicking on an overlay item... python

Hello,

How do i stop a mouse click from happening in the main scene while i click on an item in an overlay scene?

I am trying to add/change objects trough the overlay scene and spawn it in the main scene. While this is working, it also gives a problem if i want to change the object that i want to spawn. Every click i make in the overlay scene get’s also registered in the main scene (both scenes got (a) mouse sensor(s) i want to stop that from happening, anyone know howto?

.blend
rts_engine.blend (555 KB)

Your blend file doesn’t do anything when I run it, and I don’t have a lot of time to look through to find what events are supposed to trigger functionality.

The simplest solution is to suspend the main scene when using the overlay scene. However, this will arrest any animations / logic processing in the main scene which may be undesirable. The alternative is to use Python instead of the mouse over actuator, or create a mouse guard, to only allow mouse events from the main scene.

The attached blend file demonstrates the interception of the mouse events, and changing mouse left click sensors to messages. This way, we can optionally inhibit mouse down messages if the scene is not allowed them (i.e if the overlay is visible)

Mouseguard.blend (496 KB)

If you are using an overlay for UI you simple need to set a property in the global Dict when a mouse over in the overlay is positive.

Then in the main scene check if the globalDict property is false before triggering the mouse click sensor.

Pseudo-code:

def overlay_function():
    mouse_over_sensor = foo
    left_click = bar
    if mouse_over_sensor.positive:
        global_dict['overlay_focus'] = True
        if left_click.positive:
            do_something()

    else:
        global_dict['overlay_focus'] = False

def main_scene_function():
    mouse_over_sensor = foo
    left_click = bar
    out_of_focus =global_dict.get(overlay_focus',True)

    if mouse_over_sensor.positive:
        if left_click.positive and not out_of_focus:
            do_something()

The other way of doing it is to get the main scene by going through the active scenes list, then get the object running your mouseover sensor setup and set the out_of_focus property directly.

Looking at your code I’d also say don’t get scenes from the scene list by index. That can change later and is anyway not guaranteed to be always correct.

Here’s a little function to get a scene by name:

def get_scene_by_name(name):
    scenes = bge.logic.getSceneList()   
    
    named_scene = None
         
    for scene in scenes:
        if scene.name == name:
            named_scene = scene
            
    return named_scene

it will return None if the scene doesn’t exist.

This is very very simple. Just do not click the mouse!

My mouse is in front of me. Nothing, really nothing of my software can prevent me from using the mouse buttons. All it could do is to ignore the event. And that is … what you can do.

Obviously you want to have two different modes in your game:

  • add mode
  • select mode

There are several options to implement that. As it is game global multiple objects needs to know the current mode.

Option A: local mode storage:
Each object registers mode change events (e.g message: “set add mode”, “set select mode”).
Unfortunately it might happen that one object thinks one mode is active while another thinks a different mode is active.

Option B: mode managing object:
One object deals with the mode and mode changes. The modes still can change on the above messages. The difference is, that each single object asks the manager what the current mode is.

Option C) a mixture of A) and B)
One object manages the current mode. Single objects “copy” the mode from the manager when they are notified the mode changed.

I hope it gives you the idea.

This is what i am doing:
An empty getting dragged over the floor this one also holds the busy property, and the carry_building property.
When i click on an “building” to add it, i set busy True, and give carry_building the name of the object it going to add.
And spawn the object in the main layer at the spawner(empty) and parent the building to it. From here the main scene takes it over and you can drag, place or remove the building. (when one of the option happends, busy get set to False and carry_building set to ‘’ ).

If i do the above in a normal way it works without any problems, as you can see in the blend. But if i am dragging a building and then open the building menu and click on an other building to add/change too…, the main scene is also registering the mouse click and it adds the building i was dragging already, instead of deleting it then adding the new building (as i thought it would do that).

@agoose77

Your blend file doesn’t do anything when I run it,

Forgot to say, hit B ingame to open build menu then simply l.click to drag, l.click to place or r.click to remove.

The simplest solution is to suspend the main scene when using the overlay scene. However, this will arrest any animations / logic processing in the main scene which may be undesirable

Yes i thought of doing that, but that will ruin the players game time, so i cant use this option.

I will take a look at your blend.

@monster

I hope it gives you the idea

It does give me some idea’s, but i wanted it to be uhm simple and use python over bricks, because i dont like the mess it creates. i found a great rts system a week ago, it is for 95% made with logic bricks and it works great. But that’s to much logic for me, i prefer to read and learn code instead of following wires.

@smoking_mirror

you simple need to set a property in the global Dict when a mouse over in the overlay is positive

i am setting an property busy to True when i click on a building. and checking this property when i click on a building again, with or without a building dragging and it’s not working. would GD be any differend?

OMG, i feel so stupid. i got it working now.

I have looked at the blend of agoose and he’s is using a property when he set the overlay, verry smart, if using a property for that aswell, and added it to the script, i also made a huge mistake in the code, some of it is missing.

Anyway it is solved for me and it works like a charm now.

Here is the .blend of the working version, compare the playstyle if you like with the one from the first post.

Attachments

rts_engine.blend (559 KB)

the first guess was to use globalDict, then some message, but why really to this??

if not there some problem of performances,
better check the source directly, (using the function of smoking mirror)
to check if the scene is active.

the first guess was to use globalDict, then some message, but why really to this??

if not there some problem of performances,
better check the source directly, (using the function of smoking mirror)
to check if the scene is active.

problems with performance, hmm dont thing it will get that far.
GD is good to use, but with a property instead of GD (it does the same) it works.

As to get the scene i am using the function of smoke_mirror.


#the function
def get_scene(scene_name):
    scenes = logic.getSceneList()   
    
    scene = None
         
    for sce in scenes:
        if sce.name == scene_name:
            scene = sce
            
    return scene


#the part to grab the scene
    main_scene  = get_scene('spel')  
    
if not main_scene:
        print('could not get scene(line 45), it returned: ' + str(main_scene))
        return

Ah, it works for me now. i didn’t realize you have to press B to add the overlay scene.

yes i forgot to say that, and in the blend its wxplained aswell but i didnt scroll the code to the top lol.

i am setting an property busy to True when i click on a building. and checking this property when i click on a building again, with or without a building dragging and it’s not working. would GD be any differend?

I’ve taken a look at your blend and I see a problem with it. Blender often has issues when you try to use a script in one scene to do things like add objects in a different scene. It’s always best to work in the same scene as the operation you’re trying to do. So the add object script should be in the main scene. The set object script should be in the overlay scene.

From a design perspective, the user interface in the overlay scene should only send messages or set properties in your main scene, it shouldn’t do any of the heavy stuff like adding/removing objects or moving things around. There are a lot of open bug reports around that area of Blender and it’s better to be safe than sorry.

Later on I assume you’ll have some kind of UI overlay in your RTS, like click on a tool bar to change unit formations or use special abilities, that kind of thing. Or an options menu to load and save games. When you have that, you’ll have stuff going on in the main scene, where you will left mouse click to move a unit, or select units or whatever you need to do and things happening in the overlay scene too.

The problem will come when you want to click on a button in the UI to change formation, and you have a selected unit in game. That’s when GD comes in handy (or messages, as Monster suggested) because you need to tell the main scene not to take any action when the overlay scene is being interfaced. GD can be read from any scene, so that’s useful.

The alternative is to get the main scene by name and set a busy property in the main scene when the overlay scene is being used (a UI button is moused over).