Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Deformer update and Fields

    Cinema 4D SDK
    c++ r20 windows macos
    1
    2
    786
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ValkaariV
      Valkaari
      last edited by

      hello,

      i'm creating a deformer and i want to add the new falloff / fields option.
      everything seem to work fine but the deformer doesn't update when i move / modify a linear field or any field i've added.
      (the function modifyObject() isn't called)

      If i change frame or force the update with the a key, it does work.

      1 Reply Last reply Reply Quote 0
      • ValkaariV
        Valkaari
        last edited by Valkaari

        using the CheckDirty function seem to be the solution.

        void Spherify::CheckDirty(BaseObject* op, BaseDocument* doc)
        {
        	if (falloff)
        	{
        		BaseContainer *data = op->GetDataInstance();
        		Int32 dirty = falloff->GetDirty(doc, data);
        		if (dirty == lastFalloffDirtyCheck) 
                              return;
        		op->SetDirty(DIRTYFLAGS::DATA);
        		lastFalloffDirtyCheck = dirty;
        	}
        		
        }
        

        the full code for the spherify deformer :

        // deformer object example
        
        #include "c4d.h"
        #include "c4d_symbols.h"
        #include "main.h"
        #include "ospherifydeformer.h"
        #include "c4d_falloffdata.h"
        
        
        #define HANDLE_CNT 2
        
        class Spherify : public ObjectData
        {
        public:
        	virtual Bool Init(GeListNode* node);
        
        	virtual Bool Message			(GeListNode* node, Int32 type, void* data);
        	virtual void GetDimension		(BaseObject* op, Vector* mp, Vector* rad);
        	virtual DRAWRESULT Draw			(BaseObject* op, DRAWPASS type, BaseDraw* bd, BaseDrawHelp* bh);
        	virtual void GetHandle			(BaseObject* op, Int32 i, HandleInfo& info);
        	virtual Int32 DetectHandle		(BaseObject* op, BaseDraw* bd, Int32 x, Int32 y, QUALIFIER qualifier);
        	virtual Bool MoveHandle			(BaseObject* op, BaseObject* undo, const Vector& mouse_pos, Int32 hit_id, QUALIFIER qualifier, BaseDraw* bd);
        	virtual Bool ModifyObject		(BaseObject* op, BaseDocument* doc, BaseObject* mod, const Matrix& op_mg, const Matrix& mod_mg, Float lod, Int32 flags, BaseThread* thread);
        
        
        
        	
        	AutoAlloc<C4D_Falloff>		falloff;
        	Int32						lastFalloffDirtyCheck;
        	
        	virtual Int32				GetHandleCount(BaseObject *op);
        	
        	virtual void				SetHandle(BaseObject *op, Int32 i, Vector p, const HandleInfo &info);
        	virtual Bool				CopyTo(NodeData *dest, GeListNode *snode, GeListNode *dnode, COPYFLAGS flags, AliasTrans *trn);
        	virtual Bool				GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags);
        	virtual Bool            AddToExecution(BaseObject *op, PriorityList *list);
        	virtual EXECUTIONRESULT Execute(BaseObject *op, BaseDocument *doc, BaseThread *bt, Int32 priority, EXECUTIONFLAGS flags);
        	virtual void				CheckDirty(BaseObject* op, BaseDocument* doc);
        
        
        	static NodeData* Alloc() { return NewObjClear(Spherify); }
        };
        
        
        
        Int32 Spherify::GetHandleCount(BaseObject *op)
        {
        	BaseContainer *bc = op->GetDataInstance();
        	if (!bc) 
        		return 0;
        	if (falloff) 
        		return falloff->GetHandleCount(bc) + HANDLE_CNT;
        	return 0;
        }
        
        void Spherify::SetHandle(BaseObject *op, Int32 i, Vector p, const HandleInfo &info)
        {
        	BaseContainer *bc = op->GetDataInstance();
        	if (!bc) 
        		return;
        	if (falloff) 
        		falloff->SetHandle(i, p, bc, info);
        }
        
        Bool Spherify::CopyTo(NodeData *dest, GeListNode *snode, GeListNode *dnode, COPYFLAGS flags, AliasTrans *trn)
        {
        	Spherify *df = (Spherify*)dest;
        	if (!df) 
        		return false;
        	if (falloff && df->falloff)
        		if (!falloff->CopyTo(df->falloff)) 
        			return false;
        	return ObjectData::CopyTo(dest, snode, dnode, flags, trn);
        }
        
        Bool Spherify::GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags)
        {
        	BaseObject *op = (BaseObject*)node;
        	if (!op) 
        		return false;
        	BaseContainer *data = op->GetDataInstance();
        	if (!data) 
        		return false;
        
        	if (!description->LoadDescription(op->GetType())) 
        		return false;
        
        	//---------------------------------
        	// Add the falloff interface
        	if (falloff)
        	{
        		if (!falloff->SetMode(FIELDS, data)) // The falloff parameters have to have been setup before it can be added to the description, this like makes sure of that
        			return false; 
        		if (!falloff->AddFalloffToDescription(description, data, DESCFLAGS_DESC::NONE)) 
        			return false;
        	}
        
        	flags |= DESCFLAGS_DESC::LOADED;
        
        	return true;
        }
        
        
        void Spherify::CheckDirty(BaseObject* op, BaseDocument* doc)
        {
        	if (falloff)
        	{
        		BaseContainer *data = op->GetDataInstance();
        		Int32 dirty = falloff->GetDirty(doc, data);
        		if (dirty == lastFalloffDirtyCheck) 
                                return;
        		op->SetDirty(DIRTYFLAGS::DATA);
        		lastFalloffDirtyCheck = dirty;
        	}
        		
        }
        
        Bool Spherify::AddToExecution(BaseObject *op, PriorityList *list) {
        	list->Add(op, EXECUTIONPRIORITY_INITIAL, EXECUTIONFLAGS::NONE);
        	return TRUE;
        
        }
        EXECUTIONRESULT Spherify::Execute(BaseObject *op, BaseDocument *doc, BaseThread *bt, Int32 priority, EXECUTIONFLAGS flags)
        {
        	BaseContainer *data = op->GetDataInstance();
        	if (!data)
        		return EXECUTIONRESULT::USERBREAK;
        
        	if (falloff)
        		if (!falloff->InitFalloff(data, doc, op)) 
        			return EXECUTIONRESULT::OUTOFMEMORY;
        	return EXECUTIONRESULT::OK;
        }
        
        
        
        Bool Spherify::Message(GeListNode* node, Int32 type, void* data)
        {
        	if (type == MSG_MENUPREPARE)
        	{
        		((BaseObject*)node)->SetDeformMode(true);
        	}
        	return true;
        }
        
        Bool Spherify::ModifyObject(BaseObject* mod, BaseDocument* doc, BaseObject* op, const Matrix& op_mg, const Matrix& mod_mg, Float lod, Int32 flags, BaseThread* thread)
        {
        
        
        	BaseContainer* data = mod->GetDataInstance();
        
        	Vector	 p, *padr = nullptr;
        	Matrix	 m, im;
        	Int32		 i, pcnt;
        	Float		 rad = data->GetFloat(SPHERIFYDEFORMER_RADIUS), strength = data->GetFloat(SPHERIFYDEFORMER_STRENGTH);
        	Float		 s;
        	Float32* weight = nullptr;
        
        	if (!op->IsInstanceOf(Opoint))
        		return true;
        
        	padr = ToPoint(op)->GetPointW();
        	pcnt = ToPoint(op)->GetPointCount();
        	if (!pcnt)
        		return true;
        
        
        	FieldInput inputs(padr, pcnt, op_mg);
        	Bool outputsOK = falloff->PreSample(doc, mod, inputs, FIELDSAMPLE_FLAG::VALUE);
        	Float fallOffSampleValue(1.0);
        
        
        	weight = ToPoint(op)->CalcVertexMap(mod);
        
        	m	 = (~mod_mg) * op_mg;	// op  ->  world  ->  modifier
        	im = ~m;
        
        
        
        	for (i = 0; i < pcnt; i++)
        	{
        		if (thread && !(i & 63) && thread->TestBreak())
        			break;
        		p = m * padr[i];
        		s = strength;
        		if (weight)
        			s *= weight[i];
        		if (outputsOK)
        			falloff->Sample(p, &fallOffSampleValue, true, 0.0, nullptr, i);
        		s *= fallOffSampleValue;
        		p = s * (!p * rad) + (1.0 - s) * p;
        		padr[i] = im * p;
        	}
        
        	DeleteMem(weight);
        	op->Message(MSG_UPDATE);
        
        	return true;
        }
        
        void Spherify::GetDimension(BaseObject* op, Vector* mp, Vector* rad)
        {
        	BaseContainer* data = op->GetDataInstance();
        	*mp	 = Vector(0.0);
        	*rad = Vector(data->GetFloat(SPHERIFYDEFORMER_RADIUS));
        }
        
        DRAWRESULT Spherify::Draw(BaseObject* op, DRAWPASS drawpass, BaseDraw* bd, BaseDrawHelp* bh)
        {
        
        	if (!op->GetDeformMode()) 
        		return DRAWRESULT::SKIP;
        	BaseContainer *bc = op->GetDataInstance();
        	if (!bc) 
        		return DRAWRESULT::FAILURE;
        	if (falloff) 
        		falloff->Draw(bd, bh, drawpass, bc);
        	
        
        	if (drawpass == DRAWPASS::OBJECT)
        	{
        		BaseContainer* data = op->GetDataInstance();
        		Float	 rad = data->GetFloat(SPHERIFYDEFORMER_RADIUS);
        		Matrix m = bh->GetMg();
        
        		m.sqmat *= rad;
        
        		bd->SetMatrix_Matrix(nullptr, Matrix());
        		bd->SetPen(bd->GetObjectColor(bh, op));
        		bd->DrawCircle(m);
        		maxon::Swap(m.sqmat.v2, m.sqmat.v3);
        		bd->DrawCircle(m);
        		maxon::Swap(m.sqmat.v1, m.sqmat.v3);
        		bd->DrawCircle(m);
        	}
        	else if (drawpass == DRAWPASS::HANDLES)
        	{
        		Int32			 i;
        		Int32			 hitid = op->GetHighlightHandle(bd);
        		HandleInfo info;
        
        		bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT));
        		bd->SetMatrix_Matrix(op, bh->GetMg());
        		for (i = 0; i < HANDLE_CNT; i++)
        		{
        			GetHandle(op, i, info);
        			if (hitid == i)
        				bd->SetPen(GetViewColor(VIEWCOLOR_SELECTION_PREVIEW));
        			else
        				bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT));
        			bd->DrawHandle(info.position, DRAWHANDLE::BIG, 0);
        		}
        
        		GetHandle(op, 1, info);
        		bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT));
        		bd->DrawLine(info.position, Vector(0.0), 0);
        	}
        	return DRAWRESULT::OK;
        }
        
        void Spherify::GetHandle(BaseObject* op, Int32 i, HandleInfo& info)
        {
        	BaseContainer* data = op->GetDataInstance();
        	if (!data)
        		return;
        	
        	
        	if (falloff)  
        		falloff->GetHandle(i, data, info);
        
        	switch (i)
        	{
        		case 0:
        			info.position.x	 = data->GetFloat(SPHERIFYDEFORMER_RADIUS);
        			info.direction.x = 1.0;
        			info.type = HANDLECONSTRAINTTYPE::LINEAR;
        			break;
        
        		case 1:
        			info.position.x	 = data->GetFloat(SPHERIFYDEFORMER_STRENGTH) * 1000.0;
        			info.direction.x = 1.0;
        			info.type = HANDLECONSTRAINTTYPE::LINEAR;
        			break;
        
        		default: 
        			break;
        	}
        }
        
        Int32 Spherify::DetectHandle(BaseObject* op, BaseDraw* bd, Int32 x, Int32 y, QUALIFIER qualifier)
        {
        	if (qualifier & QUALIFIER::CTRL)
        		return NOTOK;
        
        	HandleInfo info;
        	Matrix		 mg = op->GetMg();
        	Int32			 i, ret = NOTOK;
        	Vector		 p;
        
        	for (i = 0; i < HANDLE_CNT; i++)
        	{
        		GetHandle(op, i, info);
        		if (bd->PointInRange(mg * info.position, x, y))
        		{
        			ret = i;
        			if (!(qualifier & QUALIFIER::SHIFT))
        				break;
        		}
        	}
        	return ret;
        }
        
        Bool Spherify::MoveHandle(BaseObject* op, BaseObject* undo, const Vector& mouse_pos, Int32 hit_id, QUALIFIER qualifier, BaseDraw* bd)
        {
        	BaseContainer* dst = op->GetDataInstance();
        
        	HandleInfo info;
        
        	Float val = mouse_pos.x;
        	GetHandle(op, hit_id, info);
        
        	if (bd)
        	{
        		Matrix mg	 = op->GetUpMg() * undo->GetMl();
        		Vector pos = bd->ProjectPointOnLine(mg * info.position, mg.sqmat * info.direction, mouse_pos.x, mouse_pos.y);
        		val = Dot(~mg * pos, info.direction);
        	}
        
        	switch (hit_id)
        	{
        		case 0:
        			dst->SetFloat(SPHERIFYDEFORMER_RADIUS, ClampValue(val, 0.0_f, (Float) MAXRANGE));
        			break;
        
        		case 1:
        			dst->SetFloat(SPHERIFYDEFORMER_STRENGTH, Clamp01(val * 0.001));
        			break;
        
        		default:
        			break;
        	}
        	return true;
        }
        
        Bool Spherify::Init(GeListNode* node)
        {
        	BaseObject*		 op = (BaseObject*)node;
        	BaseContainer* data = op->GetDataInstance();
        
        	data->SetFloat(SPHERIFYDEFORMER_RADIUS, 200.0);
        	data->SetFloat(SPHERIFYDEFORMER_STRENGTH, 0.5);
        	
        	if (falloff)
        	{
        		if (!falloff->InitFalloff(nullptr, nullptr, op))
        			return false;
        		lastFalloffDirtyCheck = -1;
        	}
        
        
        	return true;
        }
        
        // be sure to use a unique ID obtained from www.plugincafe.com
        #define ID_SPHERIFYOBJECT 1001158
        
        Bool RegisterSpherify()
        {
        	return RegisterObjectPlugin(ID_SPHERIFYOBJECT, GeLoadString(IDS_SPHERIZE), OBJECT_MODIFIER | OBJECT_CALL_ADDEXECUTION, Spherify::Alloc, "Ospherifydeformer"_s, AutoBitmap("spherify.tif"_s), 0);
        }
        
        
        1 Reply Last reply Reply Quote 3
        • First post
          Last post