SOLVED Selected object to selected layer

Hello for everyone! How to add selected objects at selected layer in layer mager?!!

image.png

@ferdinand

edit: I restored your image, we will answer the posting tomorrow 🙂 [ferdinand]

Hi,

First, just in case, i want you to know that cinema4D already have several functions to add the selected object to a layer.
One in the layer manager itself that will add the selected object to the current selected layer.
One in the object manager that will add the selected objets (or tags) to the layer selected in the sub menu.
One in the material manager.

I think, you want to combine those functions into one script.

We have this example on github that create a layer and add the current selected object to the layer. To add an object to a layer you just define its field c4d.ID_LAYER_LINK to the layer you want.

You can retrieve the selected materials using GetActiveMaterials, the selected objects with GetActiveObjects, the selected tags with GetActiveTags

The materials, tags, objects or layers are GeListNode so you can use GetNext, GetUp, GetDown, GetPred to navigate through the hierarchy. There are many posts where you will find how to iterate all the objects, tags..., this is one where @Cairyn show how to iterate objects and tracks. The most important function is GetNextObject that you can use for any GeListNode.

While having a menu to display the layers is cool, i would rather just check for the selected layer. You can iterate through all of them and return the first selected layer founded. To check if GeListNode is selected or not you can use the function GetBit and check if BIT_ACTIVE is set to true or not. You can still create a popupmenu as in this example on github but there is no function to create a popupMenu for the layers. So you need to create a BaseContainer containing all the information the popupMenu need.

To give you an idea, this is how it is done in c++ in our code.

static void MakeLayerMenu(BaseDocument *doc, LayerObject *bl, BaseContainer *menu, Int32 *cnt, IconDataArray &icons)
{
	while (bl)
	{
		String subname = bl->GetName();
		IconData *dat = NewObjClear(IconData);
		if (dat)
		{
			dat->bmp = BaseBitmap::Alloc(); if (!dat->bmp) return;
			dat->w = 32;
			dat->h = 32;
			if (IMAGERESULT::OK != dat->bmp->Init(dat->w, dat->h)) return;
			bl->GetIcon(dat);
			subname += "&"+String::HexToString((UInt)dat)+"&";
			icons.Append(dat);
		}

		if (bl->GetDown())
		{
			BaseContainer submenu;
			submenu.SetString(1, subname);
			submenu.SetString((*cnt)++, subname);
			submenu.InsData(0, String());
			MakeLayerMenu(doc, bl->GetDown(), &submenu, cnt, icons);
			menu->InsData(0, submenu);
		}
		else
		{
			menu->SetString((*cnt)++, subname);
		}

		bl = bl->GetNext();
	}
}

Cheers,
Manuel

I want to add selected objects at selected layer

To my mind it should be in the following way:

  1. select object
  2. press the button of script
  3. select layer from the list of layers

How to add all layers in custom menu If this variant is right?

But isn't that exactly how the context menu works? Select objects, call up context menu in the OM, go to "Add to layer", select the layer from the dynamic list of layers... okay, it's one submenu more, but I wouldn't bother.

(Edit: It gets even more interesting if the layers are not just linear, but hierarchical - one layer is child of another layer. Then the existing "Add to layer" menus automatically create submenus for these child layers.)

Hi,

First, just in case, i want you to know that cinema4D already have several functions to add the selected object to a layer.
One in the layer manager itself that will add the selected object to the current selected layer.
One in the object manager that will add the selected objets (or tags) to the layer selected in the sub menu.
One in the material manager.

I think, you want to combine those functions into one script.

We have this example on github that create a layer and add the current selected object to the layer. To add an object to a layer you just define its field c4d.ID_LAYER_LINK to the layer you want.

You can retrieve the selected materials using GetActiveMaterials, the selected objects with GetActiveObjects, the selected tags with GetActiveTags

The materials, tags, objects or layers are GeListNode so you can use GetNext, GetUp, GetDown, GetPred to navigate through the hierarchy. There are many posts where you will find how to iterate all the objects, tags..., this is one where @Cairyn show how to iterate objects and tracks. The most important function is GetNextObject that you can use for any GeListNode.

While having a menu to display the layers is cool, i would rather just check for the selected layer. You can iterate through all of them and return the first selected layer founded. To check if GeListNode is selected or not you can use the function GetBit and check if BIT_ACTIVE is set to true or not. You can still create a popupmenu as in this example on github but there is no function to create a popupMenu for the layers. So you need to create a BaseContainer containing all the information the popupMenu need.

To give you an idea, this is how it is done in c++ in our code.

static void MakeLayerMenu(BaseDocument *doc, LayerObject *bl, BaseContainer *menu, Int32 *cnt, IconDataArray &icons)
{
	while (bl)
	{
		String subname = bl->GetName();
		IconData *dat = NewObjClear(IconData);
		if (dat)
		{
			dat->bmp = BaseBitmap::Alloc(); if (!dat->bmp) return;
			dat->w = 32;
			dat->h = 32;
			if (IMAGERESULT::OK != dat->bmp->Init(dat->w, dat->h)) return;
			bl->GetIcon(dat);
			subname += "&"+String::HexToString((UInt)dat)+"&";
			icons.Append(dat);
		}

		if (bl->GetDown())
		{
			BaseContainer submenu;
			submenu.SetString(1, subname);
			submenu.SetString((*cnt)++, subname);
			submenu.InsData(0, String());
			MakeLayerMenu(doc, bl->GetDown(), &submenu, cnt, icons);
			menu->InsData(0, submenu);
		}
		else
		{
			menu->SetString((*cnt)++, subname);
		}

		bl = bl->GetNext();
	}
}

Cheers,
Manuel

Hello @ROMAN,

without any further questions and other postings, we will consider this topic as solved and flag it as such by Friday, 17/06/2022.

Thank you for your understanding,
Ferdinand