SOLVED Click on the TOP depth instance of a layer??

FoxyOfJungle

Kazan Games
Hello!
I want to click on the instance that is on top of the others, but make the loop only on a specific layer.


The function I have works the way it should:



GML:
function layer_instance_top_position(mx, my, object, layer_id)
{
    /// @func layer_instance_top_position(mx, my, object, layer_id)
    /// @arg mx
    /// @arg my
    /// @arg object
    /// @arg layer_id

    var aaaaa_temporary = layer_id;


    var _instlist = ds_list_create(); // create the instance list

    var _instance = instance_position(mx, my, object); // find the first instance
    var _top_instance = _instance; // create the top instance variable

    // loop through each instance, check the individual depth
    while instance_exists(_instance)
    {
        ds_list_add(_instlist, _instance);
        instance_deactivate_object(_instance);

        if (_top_instance.gwp_depth < _instance.gwp_depth)
        {
            _top_instance = _instance;
        }

        _instance = instance_position(mx, my, object);
    }

    // Reactivate all the instances
    while (ds_list_size(_instlist) > 0)
    {
        instance_activate_object(_instlist[| 0]);
        ds_list_delete(_instlist, 0);
    }

    // Destroy the list
    ds_list_destroy(_instlist);

    // Return the top instance
    return _top_instance;
}

gwp_depth is the individual depth of each instance, it is calculated manually and works perfectly, whenever an instance is created, +1 is added to the variable, but each instance has a unique depth, it is only increasing (something similar to what we get with ids instances).

The above function is an adaptation of this video.



However, if I check objects from another layer, this happens:




(The left instance is on another layer) This number above is the instance depth (gwp_depth)

This problem is because it loops all obj_gwp_parent instances.
I really don't understand why that happens, the function is called that way:

Step Event of obj_controller:

GML:
// select gui objects
if mouse_check_button_pressed(mb_left)
{
    with(obj_gwp_parent) {gwp_selected = false;}

    var _inst = layer_instance_top_position(mouse_x_wp(), mouse_y_wp(), obj_gwp_parent, global.Layer_Wp_Array[global.Layer_Wp_Index]);
    if instance_exists(_inst)
    {
        _inst.gwp_selected = true;
        gui_inspector_guiobj_id = _inst;
    }
    else
    {
        gui_inspector_guiobj_id = -1;
        show_debug_message("dont exist");
    }
}
global.Layer_Wp_Array[global.Layer_Wp_Index] = Current Layer (created using layer_create())
gwp_selected = Activate the selected instance mode.
obj_gwp_parent = Parent object that contains all the children in which are the objects in which I will check the depth.


Step Event of obj_gwp_parent:

GML:
if (layer == global.Layer_Wp_Array[global.Layer_Wp_Index])
{
    // destroy gui object
    if mouse_check_button_pressed(mb_right)
    {
        if point_in_rectangle(mouse_x_wp(), mouse_y_wp(), bbox_left, bbox_top, bbox_right, bbox_bottom)
        {
            instance_destroy();
        }
    }
}
else
{
    gwp_selected = false;
}




So I thought as follows:

The layer_instance_top_position function loops through all instances associated with obj_gwp_parent, so I would like to loop only the instances that are inside the current layer being used (through the global.Layer_Wp_Array[global.Layer_Wp_Index] variable).

I tried to do this using this "pre-made" piece of code, but I didn't get it at all, I tried it in several possible ways! :(

GML:
var _array = layer_get_all_elements(layer_id);
 
var i = array_length(_array)-1;
repeat (array_length(_array))
{
    if (layer_get_element_type(_array[i]) == layerelementtype_instance)
    {
        var _inst = layer_instance_get_instance(_array[i]);
        // _inst Is the individual instance id got from the layer. This piece of code works perfectly on individual layers. I just don't know how to use this to get the top instance.
    }
    i -= 1;
}


So I basically want him to check the instances and return the ID of the top depth instance, in which is present in the current layer.
I could use something like if (layer == global.Layer_Wp_Array[global.Layer_Wp_Index]), but it didn't work. (And I also don't prefer to do that, I want to loop only the instances that are on the layer).


Can you help me with this please? How would I do that? Is there any other more efficient way to do this?
Thank you very much!
 
Last edited:

Kezarus

Member
Hi mate!

I see that you are activating and deactivating instances just to select them. I personally would go for another approach.

Look into the function collision_point_list. It gives you all instances in a point.

First time you click, you could get the max depth from a list if it is not empty and select it. Or get a depth from a "layer" that you are in in your IDE.

Does that helps you?
 

Kezarus

Member
Another thing is, as you are creating your objects it seems that you are placing your objects on top of one another in the same layer. You are using the variable gwp_depth for depth correctness internally on your software, is that it?

In GM if you create instances on the same layer and they are on top of one another they will follow the creation order to display themselves.

In any case, collision_point_list could help you get all instances in a point and you can cycle them by your gwp_depth variable if need be or select the max from a list.
 
If there is to be just a couple of these instances that overlap, maybe it would be managable to have them on a separate layer, and then get their depth with layer_get_depth()?
You wouldn't need more layers than the max overlapping number of icons, so it probably wouldn't be so bad.
 

FoxyOfJungle

Kazan Games
Hi mate!

I see that you are activating and deactivating instances just to select them. I personally would go for another approach.

Look into the function collision_point_list. It gives you all instances in a point.

First time you click, you could get the max depth from a list if it is not empty and select it. Or get a depth from a "layer" that you are in in your IDE.

Does that helps you?
I managed to make it work using your method! Thank you very much!

GML:
function instance_top_position(mx, my, object)
{
    /// @func instance_top_position(mx, my, object)
    /// @arg mx
    /// @arg my
    /// @arg object
 
    var _top_instance = -1;
 
    var _list = ds_list_create();
    var _num = collision_point_list(mx, my, object, false, true, _list, false);
    if (_num > 0)
    {
        for (var i = 0; i < _num; ++i;)
        {
            _top_instance = _list[| ds_list_size(_list)-1]
        }
    }
 
    ds_list_destroy(_list);
 
    return _top_instance;
}

However, as I want to check the instances only on one specific layer, I managed to adapt this way:

GML:
function layer_instance_top_position(mx, my, layer_id)
{
    /// @func layer_instance_top_position(mx, my, layer_id)
    /// @arg mx
    /// @arg my
    /// @arg layer_id
 
    var _top_instance = -1;
 
    // create list
    var _list = ds_list_create();
 
    // add layer objects to the list
    var _array = layer_get_all_elements(layer_id);

    var i = array_length(_array)-1;
    repeat (array_length(_array))
    {
        if (layer_get_element_type(_array[i]) == layerelementtype_instance)
        {
            var _inst = layer_instance_get_instance(_array[i]);
             
            if position_meeting(mx, my, _inst) ds_list_add(_list, _inst);
        }
        i -= 1;
    }
 
    // get top instance
    var _num = ds_list_size(_list);
    if (_num > 0)
    {
        for (var i = 0; i < _num; ++i;)
        {
            print(_list[| i], _list[| i].gwp_depth);
            _top_instance = _list[| ds_list_size(_list)-1]
        }
    }
 
    // destroy list
    ds_list_destroy(_list);
 
    return _top_instance;
}
And it works beautifully now!



I made a post here too:


If there is to be just a couple of these instances that overlap, maybe it would be managable to have them on a separate layer, and then get their depth with layer_get_depth()?
You wouldn't need more layers than the max overlapping number of icons, so it probably wouldn't be so bad.
layer_get_depth() only returns the depth of the layer, in my system, the depth of all layers is generated automatically (through a loop, using the size of the layer array), so I can't use this to my advantage in this case. Thanks for the answer and the help!

In the end, I didn't have to use the gwp_depth variable anymore! šŸ˜ƒ

Solved! Thank you!
 
Last edited:
Top