CAMorph Manual

About

A CAMorph represents a morph of a CAPoseMorphTag. It allows access to the internally stored data and can apply this data to the host object. The class is defined in the lib_ca.h header file.

Access

CAMorph elements are stored in a CAPoseMorphTag, see CAPoseMorphTag Manual.

// This example loops through all morphs of the given
// CAPoseMorphTag and prints the morph name.
const Int32 morphCount = poseMorphTag->GetMorphCount();
for (Int32 i = 0; i < morphCount; ++i)
{
CAMorph* const morph = poseMorphTag->GetMorph(i);
if (morph == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// print morph name
ApplicationOutput("Morph: " + morph->GetName());
}
Py_ssize_t i
Definition: abstract.h:645
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:69
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:204
maxon::Int32 Int32
Definition: ge_sys_math.h:51

Allocation/Deallocation

CAMorph elements are created and deleted using the parent CAPoseMorphTag, see CAPoseMorphTag Manual.

// This example adds a new morph to the given CAPoseMorphTag.
poseMorphTag->ExitEdit(doc, false);
CAMorph* const morph = poseMorphTag->AddMorph();
if (morph == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
morph->SetName("New Morph");
poseMorphTag->UpdateMorphs();
const char * doc
Definition: pyerrors.h:226

Copy

The data stored in one CAMorph can be copied from a CAMorph to another CAMorph:

  • CAMorph::CopyFrom(): Copies the data from the given source CAMorph.
// This example copies the currently active morph
// and makes the copy the new active morph.
poseMorphTag->ExitEdit(doc, false);
// get active morph
const Int32 activeIndex = poseMorphTag->GetActiveMorphIndex();
CAMorph* const activeMorph = poseMorphTag->GetMorph(activeIndex);
if (activeMorph == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// create new morph
CAMorph* const morph = poseMorphTag->AddMorph();
if (morph == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
// copy morph
morph->CopyFrom(activeMorph, nullptr, CAMORPH_COPY_FLAGS::NONE);
const String newName = activeMorph->GetName() + " Copy";
morph->SetName(newName);
// set new morph as active morph
const Int32 newIndex = poseMorphTag->GetMorphIndex(morph);
poseMorphTag->SetActiveMorphIndex(newIndex);
poseMorphTag->UpdateMorphs();
NONE
Definition: asset_browser.h:1

Properties

The internal data and several properties of a CAMorph can be edited through dedicated functions. But some properties can only be edited through the parent CAPoseMorphTag when the morph is selected. See Properties.

Name

Every CAMorph has a name:

  • CAMorph::GetName(): Returns the name of the morph.
  • CAMorph::SetName(): Sets the name of the morph.

ID

Every CAMorph has an internal ID:

  • CAMorph::GetID(): Returns the internal ID of the morph.

Post Morph

A morph can be applied as a post-deform morph (ID_CA_POSE_MIXING_DEFORMED). If this is the case can be checked with:

  • CAMorph::IsPostDeform(): Returns true if the morph is in post-deform mode.

CAMorphNode

The actual morph data is stored internally in CAMorphNode elements. See CAMorphNode Manual.

  • CAMorph::Find(): Returns the CAMorphNode for the given BaseList2D element.
  • CAMorph::GetNodeIndex(): Returns the index of the given CAMorphNode.
  • CAMorph::FindIndex(): Returns the index of the CAMorphNode for the given BaseList2D element.
  • CAMorph::FindFromIndex(): Returns the CAMorphNode for the given index.
  • CAMorph::GetFirst(): Returns the first stored CAMorphNode.

Mode

To edit or access data stored in a CAMorph one must switch the morph to a certain mode:

  • CAMorph::SetMode(): Sets the mode of the CAMorph.

Valid flags are:

The data modes are:

// This example accesses the morph data of the
// first morph of the given CAPoseMorphTag.
poseMorphTag->ExitEdit(doc, false);
// get active morph
const Int32 activeIndex = poseMorphTag->GetActiveMorphIndex();
CAMorph* const morph = poseMorphTag->GetMorph(activeIndex);
if (morph == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
CAMorphNode* const mnode = morph->GetFirst();
if (mnode == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// expand data to access it
morph->SetMode(doc, poseMorphTag, expandFlags, CAMORPH_MODE::ABS);
// check stored data
if (mnode->GetInfo() & CAMORPH_DATA_FLAGS::POINTS)
{
// access point data
const Int32 pointCount = mnode->GetPointCount();
for (Int32 i = 0; i < pointCount; ++i)
{
const Vector point = mnode->GetPoint(i);
ApplicationOutput("Point: " + String::VectorToString(point));
}
}
// collapse data
morph->SetMode(doc, poseMorphTag, collapseFlags, CAMORPH_MODE::AUTO);
poseMorphTag->UpdateMorphs();
ALL
Filter for all types.
Definition: asset_browser.h:0
CAMORPH_MODE_FLAGS
Definition: lib_ca.h:849
AUTO
Definition: lib_birender.h:1
POINTS
Points morphing.
Definition: lib_ca.h:3
EXPAND
Expand data. Needs to be passed before accessing any data.
Definition: lib_ca.h:1
ABS
Absolute morph data.
Definition: lib_ca.h:0
COLLAPSE
Collapse data. Needs to be passed to collapse the expanded data, for instance after data access.
Definition: lib_ca.h:0
maxon::Vec3< maxon::Float64, 1 > Vector
Definition: ge_math.h:140

Target

A CAMorph can use an object as a reference:

  • CAMorph::GetTarget(): Returns the target BaseList2D object.
  • CAMorph::SetTarget(): Sets the given BaseList2D object as the target.
// This example creates a new morph and uses
// the given BaseObject as the target object.
poseMorphTag->ExitEdit(doc, false);
// create new morph
CAMorph* const morph = poseMorphTag->AddMorph();
if (morph == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
// set given object as target
morph->SetTarget(poseMorphTag, doc, targetObject);
// set new morph as active morph
const Int32 newIndex = poseMorphTag->GetMorphIndex(morph);
poseMorphTag->SetActiveMorphIndex(newIndex);
poseMorphTag->UpdateMorphs();
const Int32 index = poseMorphTag->GetMorphIndex(morph);
poseMorphTag->SetActiveMorphIndex(index);
poseMorphTag->SetParameter(ConstDescID(DescLevel(ID_CA_POSE_MIXING)), ID_CA_POSE_MIXING_ABS, DESCFLAGS_SET::NONE);
Py_ssize_t * index
Definition: abstract.h:374
#define ConstDescID(...)
Definition: lib_description.h:592
@ ID_CA_POSE_MIXING
Definition: tcaposemorph.h:26
@ ID_CA_POSE_MIXING_ABS
Definition: tcaposemorph.h:89

Strength

The strength of a CAMorph controls how strongly it is applied to the host object.

  • CAMorph::GetStrength(): Returns the strength of the morph.
  • CAMorph::SetStrength(): Sets the strength of the morph.
// This example loops through all morphs and sets the strength
// of the currently active morph to 100%, all other morphs to 0%.
poseMorphTag->ExitEdit(doc, false);
// get index of active morph
const Int32 activeMorphIndex = poseMorphTag->GetActiveMorphIndex();
// loop through all morphs
const Int32 morphCount = poseMorphTag->GetMorphCount();
for (Int32 i = 0; i < morphCount; ++i)
{
CAMorph* const morph = poseMorphTag->GetMorph(i);
if (morph == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// set morph strength
if (activeMorphIndex != i)
morph->SetStrength(0.0);
else
morph->SetStrength(1.0);
}
poseMorphTag->UpdateMorphs(doc);

Object

The data stored in a CAMorph can be read from the host object and applied back to the host object:

  • CAMorph::Store(): Stores the current object's state in the morph.
  • CAMorph::Apply(): Applies the morph to the object.

The flags used to control what data is stored or applied are defined in ::CAMORPH_DATA_FLAGS. These flags are also used with CAMorphNode::GetInfo(), see CAMorphNode Manual.

// This example accesses the first (not base pose) morph
// and applies it to the host object.
poseMorphTag->ExitEdit(doc, false);
// get first morph
CAMorph* const morph = poseMorphTag->GetMorph(1);
if (morph)
{
morph->Apply(doc, poseMorphTag, CAMORPH_DATA_FLAGS::ALL);
}

Further Reading