Set Material Default Projection



  • On 29/07/2017 at 07:50, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R17 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hello,

    There are custom material plugins. And when they are assigned to objects their default projection is Spherical. I want default projection to be UVW (as for std Cinema materials).
    Same history as https://plugincafe.maxon.net/topic/8133/10594_set-material-default-projection-solved&PID=41173#41173

    // note: nullptr checks omitted
    Bool MyMaterial::Message(GeListNode* node, Int32 type, void* pData)
    {
      if(type == MSG_MATERIALDRAGANDDROP)
      {
        BaseMaterial* mat = static_cast<BaseMaterial*>(node);
        MaterialDragAndDrop* mdd = static_cast<MaterialDragAndDrop*>(pData);
        mdd->result = mdd->op->MakeTag(Ttexture);
        mdd->result->SetParameter(TEXTURETAG_MATERIAL, mat, DESCFLAGS_SET_0);
        mdd->result->SetParameter(TEXTURETAG_PROJECTION, TEXTURETAG_PROJECTION_UVW, DESCFLAGS_SET_0);
        return true;
      }
      return MaterialData::Message(node, type, pData);
    }
    

    But that solution works only for simple cases.

    Consider a case. E.g. when we have a selection of polygons and try to assign own custom material with suggested method then SelectionTag is not created together with the TextureTag that we create on our own. Why? How to fix that?
    However when we don't write the pointer to mdd->result then we can't change default projection of texture but anything else works fine and Selection Tag too.



  • On 29/07/2017 at 09:42, xxxxxxxx wrote:

    And here is my workaround:

    In MaterialData message I remember who is assigned where:

    		case MSG_MATERIALDRAGANDDROP:
    		{
    			MaterialDragAndDrop * mdd = (MaterialDragAndDrop * )(msgdat);
    			if (mdd != 0 && mat != 0)
    			{
    				BaseObject * obj = mdd->op;
    				if (obj != 0)
    				{
    					MY_COMMON_DATA * rendata = MyCommonDataInstance();
      
    					int next_id = rendata->mat_dnd_num;
    					rendata->mat_dnd.SetLink(next_id + 0, mat);
    					rendata->mat_dnd.SetLink(next_id + 1, obj);
    					rendata->mat_dnd_num += 2;
    				}
    			}
      
    			break;
    		}
    

    And in CoreMessage I intercept "change" message. It occurs for any change in scene also for previous one but with assigned and allocated Tags!

    void ChangeDefaultProjection(BaseDocument * doc)
    {
    	if (!doc) return;
      
    	MY_COMMON_DATA * rendata = MyCommonDataInstance();
    	if (rendata->mat_dnd_num <= 0) return;
      
    	for (int i = 0; i < rendata->mat_dnd_num; i += 2)
    	{
    		BaseMaterial * mat = (BaseMaterial * )rendata->mat_dnd.GetLink(i + 0, doc);
    		BaseObject * obj = (BaseObject * )rendata->mat_dnd.GetLink(i + 1, doc);
      
    		if (obj != 0 && mat != 0)
    		{
    			if (obj->IsInstanceOf(Obase) && mat->IsInstanceOf(Mbase))
    			{
    				BaseTag * tsearch = 0;
    				for (BaseTag * tag = obj->GetFirstTag(); tag; tag = tag->GetNext())
    				{
    					// search the last tag with this material
    					if (tag->IsInstanceOf(Ttexture)) {
    						BaseMaterial * mi = (BaseMaterial * )getParameterLink(*tag, TEXTURETAG_MATERIAL, 0);
    						if (mi == mat)
    							tsearch = tag;
    					}
    				}
      
    				if (tsearch != 0)
    					tsearch->SetParameter(TEXTURETAG_PROJECTION, TEXTURETAG_PROJECTION_UVW, DESCFLAGS_SET_0);
    			}
    		}
    	}
      
    	rendata->mat_dnd_num = 0; // flush the queue
    }
      
    Bool MyTimer::CoreMessage(Int32 id, const BaseContainer &bc)
    {
      
    	BaseDocument * doc = GetActiveDocument();
    	if (id == EVMSG_CHANGE)
    	{
    		ChangeDefaultProjection(doc);
    	}
    }
    

    It works for cases that I have tested. Pls, can anybody consult on any potential non-working scenarious in this method? However, I don't like such huge code constructions for so small needs.



  • On 31/07/2017 at 05:36, xxxxxxxx wrote:

    Hi,

    in another support case (not in this forum) Sebastian came up with this solution:

    When you handle the MSG_MATERIALDRAGANDDROP message you have to handle the full creation of the (optional) TextureTag yourself. That's the point of that message.

    But if you just want that the UVW projection is set by default you could simply return the VOLUMEINFO_EVALUATEPROJECTION flag in GetRenderInfo(). In this case the tag's projection will be set to UVW.



  • On 31/07/2017 at 07:20, xxxxxxxx wrote:

    Super! How could we guess about that :) I will give it a try



  • On 31/07/2017 at 09:44, xxxxxxxx wrote:

    Sometimes it's not about guessing, but just about asking 😉
    Nah, you are right of course, our docs could well be more informative in this area.



  • On 01/08/2017 at 12:36, xxxxxxxx wrote:

    Don't worry! You are informative! Sometimes people hang inside the code editor and make gazillion of tests before the idea of asking on forum comes to mind :))
    Making tests in Cinema 4D environment are very cool because it launches in 1 second. No need for own standalone testing app.
    I tested the trick. It works as you describe. Thanks!


Log in to reply