#include "operatingsystem.h" #include "c4d_objectplugin.h" #include "c4d_memory.h" #include "c4d_general.h" #ifdef __API_INTERN__ #include "c4d_resource.h" #include "basedraw.h" #include "res_colortab_priv.h" #else #include "c4d_tools.h" #include "c4d_basebitmap.h" #include "c4d_file.h" #include "c4d_resource.h" #include "c4d_baseobject.h" #include "c4d_basedraw.h" #include "dbasedraw.h" #endif Vector HandleInfo::CalculateNewPosition(BaseDraw* bd, const Matrix& mg, const Vector& mouse_pos) const { if (!bd) return position; Vector result = mg * position; switch (type) { case HANDLECONSTRAINTTYPE_LINEAR: result = bd->ProjectPointOnLine(mg * position, mg.TransformVector(direction), mouse_pos.x, mouse_pos.y); break; case HANDLECONSTRAINTTYPE_PLANAR: { Int32 err; result = bd->ProjectPointOnPlane(mg * position, mg.TransformVector(direction), mouse_pos.x, mouse_pos.y, &err); if (err) { Vector dir = Cross(!(bd->WS(mg * (position + direction)) - bd->WS(mg * position)), Vector(0.0, 0.0, 1.0)); dir = !(bd->SW(bd->WS(mg * position) + dir) - (mg * position)); result = bd->ProjectPointOnLine(mg * position, dir, mouse_pos.x, mouse_pos.y); } break; } case HANDLECONSTRAINTTYPE_FREE: if (mouse_pos.z != 0.0) result = bd->SW(mouse_pos); else result = bd->SW(Vector(mouse_pos.x, mouse_pos.y, bd->WC(result).z)); break; case HANDLECONSTRAINTTYPE_RADIAL: result = bd->ProjectPointOnPlane(mg * center, mg.TransformVector(direction), mouse_pos.x, mouse_pos.y); result = center + (radius * !(result - center)); break; case HANDLECONSTRAINTTYPE_SPHERICAL: { Float r, cp; r = radius * bd->WP_W(mg * center, true); if (r == 0.0) r = 0.1; result = (mouse_pos - bd->WS(mg * center)); result.z = 0.0; cp = FMin(Len(result), r); result = cp * !result; result.z = -Cos(ASin(cp / r)) * r; result = bd->SW(result + bd->WS(mg * center)); } break; default: break; } return ~mg * result; } void ObjectData::GetDimension(BaseObject* op, Vector* mp, Vector* rad) { // override GetDimension if you do not want C4D's default handling of bounding boxes and set *mp/*rad to 0.0 } DRAWRESULT ObjectData::Draw(BaseObject* op, DRAWPASS drawpass, BaseDraw* bd, BaseDrawHelp* bh) { if (drawpass != DRAWPASS_HANDLES) return DRAWRESULT_SKIP; Int32 i, pass; Vector p; Int32 cnt = GetHandleCount(op); if (!cnt) return DRAWRESULT_SKIP; #ifdef __API_INTERN__ Int32 hitid = C4DOS.Bo->GetHighlightHandle(op, bd); const Matrix& mg = bh->m; #else Int32 hitid = op->GetHighlightHandle(bd); const Matrix& mg = bh->GetMg(); #endif Vector col1 = GetViewColor(VIEWCOLOR_SELECTION_PREVIEW); Vector col2 = GetViewColor(VIEWCOLOR_ACTIVEPOINT); bd->SetMatrix_Matrix(op, mg); for (pass = 0; pass < 2; pass++) { if (pass == 0) bd->SetPen(col2); else bd->SetPen(col1); for (i = 0; i < cnt; i++) { if ((i == hitid) != pass) continue; HandleInfo info; GetHandle(op, i, info); if (info.type == HANDLECONSTRAINTTYPE_INVALID) continue; bd->DrawHandle(info.position, DRAWHANDLE_BIG, 0); //#ifndef __API_INTERN__ //bd->Line3D(Vector(0.0,0.0,0.0)*mg,p); //#endif } } return DRAWRESULT_OK; } DRAWRESULT ObjectData::DrawShadow(BaseObject* op, BaseDraw* bd, BaseDrawHelp* bh) { return DRAWRESULT_SKIP; } void ObjectData::GetHandle(BaseObject* op, Int32 i, HandleInfo& info) { } void ObjectData::SetHandle(BaseObject* op, Int32 i, Vector p, const HandleInfo& info) { } Int32 ObjectData::GetHandleCount(BaseObject* op) { return 0; } Int32 ObjectData::DetectHandle(BaseObject* op, BaseDraw* bd, Int32 x, Int32 y, QUALIFIER qualifier) { if (qualifier & QUALIFIER_CTRL) return NOTOK; Matrix mg = op->GetMg(); Int32 i, ret = NOTOK; for (i = 0; i < GetHandleCount(op); i++) { HandleInfo info; GetHandle(op, i, info); if (info.type == HANDLECONSTRAINTTYPE_INVALID) continue; if (bd->PointInRange(mg * info.position, x, y)) { ret = i; if (!(qualifier & QUALIFIER_SHIFT)) break; } } return ret; } Bool ObjectData::MoveHandle(BaseObject* op, BaseObject* undo, const Vector& mouse_pos, Int32 hit_id, QUALIFIER qualifier, BaseDraw* bd) { Matrix mg = op->GetUpMg() * undo->GetMl(); HandleInfo info; ((ObjectData*)undo->GetNodeData())->GetHandle(undo, hit_id, info); SetHandle(op, hit_id, info.CalculateNewPosition(bd, mg, mouse_pos), info); return true; } SplineObject* ObjectData::GetContour(BaseObject* op, BaseDocument* doc, Float lod, BaseThread* bt) { return nullptr; } BaseObject* ObjectData::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh) { return nullptr; } Bool ObjectData::ModifyObject(BaseObject* op, BaseDocument* doc, BaseObject* mod, const Matrix& op_mg, const Matrix& mod_mg, Float lod, Int32 flags, BaseThread* thread) { return true; } void ObjectData::CheckDirty(BaseObject* op, BaseDocument* doc) { } void ObjectData::ModifyParticles(BaseObject* op, Particle* pp, BaseParticle* ss, Int32 pcnt, Float diff) { } void ObjectData::GetModelingAxis(BaseObject* op, BaseDocument* doc, Matrix& axis) { } Bool ObjectData::AddToExecution(BaseObject* op, PriorityList* list) { return false; } EXECUTIONRESULT ObjectData::Execute(BaseObject* op, BaseDocument* doc, BaseThread* bt, Int32 priority, EXECUTIONFLAGS flags) { return EXECUTIONRESULT_OK; } static void FillObjectPlugin(OBJECTPLUGIN* np, DataAllocator* npalloc, Int32 info, Int32 disklevel, BaseBitmap* icon, void* emulation) { FillNodePlugin(np, info, npalloc, icon, disklevel, emulation); np->command_icon = icon; np->GetDimension = &ObjectData::GetDimension; np->Draw = &ObjectData::Draw; np->DrawShadow = &ObjectData::DrawShadow; np->DetectHandle = &ObjectData::DetectHandle; np->MoveHandle = &ObjectData::MoveHandle; np->Execute = &ObjectData::Execute; np->AddToExecution = &ObjectData::AddToExecution; np->GetModelingAxis = &ObjectData::GetModelingAxis; } Bool RegisterObjectPlugin(Int32 id, const String& str, Int32 objectinfo, DataAllocator* npalloc, const String& description, BaseBitmap* icon, Int32 disklevel) { if (description.Content() && !RegisterDescription(id, description)) return false; OBJECTPLUGIN np; ClearMem(&np, sizeof(np)); FillObjectPlugin(&np, npalloc, objectinfo, disklevel, icon, nullptr); np.CheckDirty = &ObjectData::CheckDirty; if (objectinfo & OBJECT_MODIFIER) np.ModifyObject = &ObjectData::ModifyObject; if (objectinfo & OBJECT_PARTICLEMODIFIER) np.ModifyParticles = &ObjectData::ModifyParticles; if (objectinfo & OBJECT_ISSPLINE) np.GetContour = &ObjectData::GetContour; if (objectinfo & OBJECT_GENERATOR) np.GetVirtualObjects = &ObjectData::GetVirtualObjects; return GeRegisterPlugin(PLUGINTYPE_OBJECT, id, str, &np, sizeof(np)); }