Thanks for your answer, it solved my problem.
I used: Vector::ClampMax()
and Vector::ClampMin()
to limit the tangent to the value I want.
Thank,
AiMiDi
Thanks for your answer, it solved my problem.
I used: Vector::ClampMax()
and Vector::ClampMin()
to limit the tangent to the value I want.
Thank,
AiMiDi
Hi everybody. I find when edit a interior scene or a huge map, it is hard to navigate through only mouse. The best way to control the camera is like FPS games or UE4.
There was vitual walkthrough in cinema 4d however it performs laggy and it's not a flying camera,then it was removed.
My friend write a plugin which make camera read keyboard, however it can only move along the world axis. Besides, it moves about 5 times per sec, laggy too. If anybody knows how to correctly do it, pls tell me thanks.
I used to take in game footage with a xbox controller, find it works perfectly.
So if a combine gamepad and real time keying(cappuccino in c4d), animating camera would be much easier.
These 2 videos demonstrates real time keying with mouse and keyboard to make camera movement and mechanical animations.
But with a gamepad, we can even achieve this level of control inside the soft ware. Follow character movement, focus on the face, camera shake you name it.
3D Connexion SpaceMouse can navigate like a gamepad, but not everybody afford that, and using 1 stick simultaneously to move and rotate is not that accurate.
If you knows how to get the right API, pls leave a comment. That would be really appriciated!
I can't download the Cineware sdk via the link below, is there any other way to download it?
https://developers.maxon.net/forum/topic/15234/cineware-22-downloads/1
Thank,
AiMiDi
@ferdinand Could you please check this out? This is quite important for me! Appreciation for your time!
Thank,
AiMiD
For only x-axis, there are two points defined (0,0) with right tangent(14.49, 0) and (60,47.869) with left tangent(-39, -1.532), and It is clear that the value at frame 23 is 31.49
But After I use these information to try to recreate the curve with Bezier algorithm myself, I somehow get the value 26.379:
And I have tried Hermite algorithm, but it's still wrong 26.5:
Can you reveal your way of interpolation?
Thank,
AiMiD
Hi @m_adam , thanks for your apply. I have solved this problem. The reason is I used maxon::BaseArray
to store tree node data. When I append the array, the address of node may change, but the next pointer in node remain unchanged. And this cause the crash.
I'm going to set a tree view as shown below. After adding items into the tree view for several times, it suddenly crashed in DrawText. This issue happens stably.
struct MyItem
{
enum
{
MATERIAL,
MESH,
CAMERA,
LIGTH
};
enum
{
OK,
WARNING,
ERROR
};
Int32 state = OK;
Int32 type = MATERIAL;
BaseList2D* element;
String parameter;
String problem;
};
struct MyItem
{
Int32 state = OK;
Int32 type = MATERIAL;
BaseList2D* element;
String parameter;
String problem;
};
struct MyItemNode
{
MyItem item; //data
MyItemNode* down = nullptr;
MyItemNode* next = nullptr;
};
using MyItemArray = maxon::BaseArray<MyItemNode>;
class MyTreeViewFunctions final : public TreeViewFunctions
{
void* m_selected_node = nullptr;
public:
static MyTreeViewFunctions& GetFunction()
{
static MyTreeViewFunctions func;
return func;
}
void* GetFirst(void* root, void* userdata) override
{
return static_cast<MyItemArray*>(root)->GetFirst();
}
void* GetDown(void* root, void* userdata, void* obj) override
{
return nullptr;
}
void* GetNext(void* root, void* userdata, void* obj) override
{
if (const auto node = static_cast<MyItemNode*>(obj))
return node->next;
return nullptr;
}
Bool IsSelected(void* root, void* userdata, void* obj) override
{
return m_selected_node == obj;
}
Int32 GetLineHeight(void* root, void* userdata, void* obj, Int32 col, GeUserArea* area) override
{
return 20;
}
Int32 GetColumnWidth(void* root, void* userdata, void* obj, Int32 col, GeUserArea* area) override
{
return 65;
}
void DrawCell(void* root, void* userdata, void* obj, const Int32 col, DrawInfo* drawinfo, const GeData& bgColor) override
{
if(!obj)
return;
const auto& item = static_cast<MyItemNode*>(obj)->item;
switch (col)
{
case MyDialog::LIST_COL_TYPE:
{
BaseBitmap* bm = nullptr;
switch (item.type)
{
case MyItem::MATERIAL:
bm = m_material_bitmap;
break;
case MyItem::MESH:
bm = m_mesh_bitmap;
break;
case MyItem::CAMERA:
bm = m_camera_bitmap;
break;
case MyItem::LIGTH:
bm = m_light_bitmap;
break;
default:;
}
drawinfo->frame->DrawBitmap(bm, drawinfo->xpos + drawinfo->width / 4, drawinfo->ypos + 2, ICON_SIZE, ICON_SIZE, 0, 0, bm->GetBw(), bm->GetBh(), BMP_NORMALSCALED);
break;
}
case MyDialog::LIST_COL_ELEMENT:
{
if (item.type == MyItem::MATERIAL)
{
if (auto* mat = reinterpret_cast<BaseMaterial*>(item.element); mat)
{
if (BaseBitmap* bm = mat->GetPreview(0); bm)
{
drawinfo->frame->DrawBitmap(bm, drawinfo->xpos, drawinfo->ypos + 2, ICON_SIZE, ICON_SIZE, 0, 0, bm->GetBw(), bm->GetBh(), BMP_NORMALSCALED);
}
}
}
drawinfo->frame->DrawSetTextCol(IsSelected(root, userdata, obj) ? COLOR_TEXT_SELECTED : COLOR_TEXT, COLOR_TRANS);
drawinfo->frame->DrawText(item.GetName(), drawinfo->xpos + ICON_SIZE + 2,drawinfo->ypos + drawinfo->height / 2, DRAWTEXT_VALIGN_CENTER);
break;
}
case MyDialog::LIST_COL_PARAMETER:
{
drawinfo->frame->DrawSetTextCol(IsSelected(root, userdata, obj) ? COLOR_TEXT_SELECTED : COLOR_TEXT, COLOR_TRANS);
drawinfo->frame->DrawText(item.parameter, drawinfo->xpos + 2,
drawinfo->ypos + (drawinfo->height - drawinfo->frame->DrawGetFontHeight()) / 2 + 2);
break;
}
case MyDialog::LIST_COL_PROBLEM:
{
drawinfo->frame->DrawSetTextCol(IsSelected(root, userdata, obj) ? COLOR_TEXT_SELECTED : COLOR_TEXT, COLOR_TRANS);
drawinfo->frame->DrawText(item.problem, drawinfo->xpos + 2, drawinfo->ypos + drawinfo->height / 2, DRAWTEXT_VALIGN_CENTER);
break;
}
default:;
}
}
Bool IsOpened(void* root, void* userdata, void* obj) override
{
return true;
}
String GetName(void* root, void* userdata, void* obj) override
{
return {};
}
Int GetId(void* root, void* userdata, void* obj) override
{
return 0;
}
Int32 GetDragType(void* root, void* userdata, void* obj) override
{
return NOTOK;
}
void Select(void* root, void* userdata, void* obj, Int32 mode) override
{
if(mode == SELECTION_SUB)
m_selected_node = nullptr;
else
m_selected_node = obj;
}
};
@kbar and @m_magalhaes, Thank you for your reply.
I know that parameter changes can be determined by overriding SetDParameter()
.
But I don't know how to override SetDParameter()
to know whether the user has added / deleted keyframes, or changed the value of keyframes (whether the small button next to the parameter is pressed). Thank you again for your help.
Thank,
AiMiD
As I demonstrated above, how to track the user's changes to the parameter animation in a custom ObjectPlugin
, or receive a message when the user changes the animation. Do I need to listen to the above events in ObjectData::Message()
?Can someone help me?
Thank,
AiMiD
@ferdinand Thank you for your reply.
My plugin is written in C++. Is there a way to call redshift.GetRSMaterialNodeMaster()
in C++ 's existing sdk? (or call the python code through C++)
Thank,
AiMiD
I need to get the node information on the Redshift material for a plugin that automatically adds maps, reads maps, and converts Redshift materials to default materials.
I don't know how to get the XPresso stored on the Redshift material. Can someone help me?
Thank,
AiMiD
I use ZipFile::CopyInFileInZip()
to compress the file into a zip package. However, when the file name contains non ASCII characters, the file name is replaced with an underscore. Is there a way to use non ASCII file names in zip without using external libraries?
AutoAlloc<ZipFile> zf;
if (zf == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
if (!zf->Open(fnZip, false, ZIP_APPEND_CREATE))
return maxon::UnknownError(MAXON_SOURCE_LOCATION);
Filename fnCopy;
while (fnCopy.FileSelect(FILESELECTTYPE::ANYTHING, FILESELECT::LOAD, "Select file to add to Zip File"_s))
{
zf->CopyInFileInZip(fnCopy, "textures/" + fnCopy.GetFileString());
}
Thank,
AiMiDi