static Bool _InitRenderFn(HairVideoPost* vp, VolumeData* vd, BaseDocument* doc, BaseList2D* bl, HairObject* op, HairGuides* guides, Int32 oindex, Int32 pass) { //GePrint("Init Render"); BaseContainer* bc = bl->GetDataInstance(); HairRenderingTag* hrt = (HairRenderingTag*)bl->GetNodeData(); if (!bc || !hrt) return false; hrt->m_Shadow = bc->GetFloat(HAIR_RENDERING_SHADOW); hrt->m_Trans = bc->GetFloat(HAIR_RENDERING_TRANSPARENCY); hrt->m_Depth = bc->GetInt32(HAIR_RENDERING_DEPTH); return true; }
void DropEffector::InitPoints(BaseObject* op, BaseObject* gen, BaseDocument* doc, EffectorDataStruct* data, MoData* md, BaseThread* thread) { BaseContainer* bc = op->GetDataInstance(); if (!bc) return; if (!rcol) return; ed.mode = bc->GetInt32(DROPEFFECTOR_MODE); ed.maxdist = bc->GetFloat(DROPEFFECTOR_DISTANCE); ed.target = bc->GetObjectLink(DROPEFFECTOR_TARGET, doc); if (!ed.target) return; ed.targmg = ed.target->GetMg(); ed.itargmg = ~ed.targmg; ed.genmg = gen->GetMg(); ed.igenmg = ~ed.genmg; //Add a dependency so that the effector will update if the target changes AddEffectorDependence(ed.target); //Can't init raycollider or the target isn't polygonal, then skip if (!rcol->Init(ed.target)) ed.target = nullptr; else if (!ed.target->IsInstanceOf(Opolygon)) ed.target = nullptr; }
Bool SmplMatrixDialog::Command(Int32 id, const BaseContainer& msg) { Bool update_settings = false; if (preview.Command(id, msg)) return true; switch (id) { case GADGET_SMPL_MATRIX_TYPE_POPUP: { Int32 type; preview.ChangedSettings(); // stop running threads before settings are changed type = msg.GetInt32(BFM_ACTION_VALUE); if (settings->emr) { delete_effect_matrix(settings->emr); settings->emr = 0; } settings->type = type; update_settings = true; // indicates changed effect settings break; } case GADGET_SMPL_MATRIX_SLIDER_ANGLE: { Float32 slider_value; slider_value = (Float32)Deg(msg.GetFloat(BFM_ACTION_VALUE)); if (real_time || (msg.GetInt32(BFM_ACTION_INDRAG) == false)) { if (settings->angle != slider_value) { preview.ChangedSettings(); // stop running threads before settings are changed settings->angle = slider_value; update_settings = true; // indicates changed effect settings } } break; } case GADGET_SMPL_MATRIX_SLIDER_MIX: { Float32 slider_value; slider_value = (Float32)msg.GetFloat(BFM_ACTION_VALUE); if (real_time || msg.GetInt32(BFM_ACTION_INDRAG) == false) { if (settings->matrix_opacity != slider_value) { preview.ChangedSettings(); // stop running threads before settings are changed settings->matrix_opacity = slider_value; update_settings = true; // indicates changed effect settings } } break; } case GADGET_SMPL_MATRIX_TEXTURE_MODE: { preview.ChangedSettings(); // stop running threads before settings are changed settings->tile_flags = msg.GetInt32(BFM_ACTION_VALUE) ? TILE_REPEAT_TILING : TILE_REPEAT_BORDER; update_settings = true; break; } case GADGET_SMPL_MATRIX_DOCUMENT_PREVIEW: { document_preview = msg.GetInt32(BFM_ACTION_VALUE); preview.SetDocumentPreview(document_preview); break; } } if (update_settings) { change_effect_matrix(settings, bm); preview.Update(); } return true; }
/*********************************************************************\ Function name : CDialogCustomElement::Save Description : Created at : 27.03.02, @ 14:54:04 Created by : Thomas Kunert Modified by : \*********************************************************************/ Bool CDialogCustomElement::Save(BaseFile* pFile, String strFill) { if (g_pCustomElements && m_lElement >= 0 && m_lElement < g_pCustomElements->Entries()) { CustomProperty* pProp; CCustomElements* pElement = g_pCustomElements->GetItem(m_lElement); if (!pElement) return true; if (!m_pbcGUI) return false; BaseContainer* pBC = &m_pbcGUI[m_lElement]; pProp = pElement->m_pProp; WriteString(pFile, pElement->m_pChResSym); WriteString(pFile, " "); WriteString(pFile, m_strControlID); LineBreak(pFile, strFill); WriteString(pFile, "{"); LineBreak(pFile, strFill + *g_pstrFillSave); SaveAlignment(pFile); LineBreak(pFile, strFill); if (pElement->m_bIsOpen) { WriteString(pFile, *g_pstrFillSave); WriteString(pFile, "OPEN"); WriteString(pFile, "; "); LineBreak(pFile, strFill); } Int32 i; for (i = 0; pProp && pProp[i].type != CUSTOMTYPE_END; i++) { Bool b = false; if (pProp[i].type == CUSTOMTYPE_FLAG) { if (pBC->GetBool(pProp[i].id)) { WriteString(pFile, *g_pstrFillSave); WriteString(pFile, pProp[i].ident); WriteString(pFile, "; "); b = true; } } else if (pProp[i].type == CUSTOMTYPE_LONG) { WriteString(pFile, *g_pstrFillSave); WriteString(pFile, pProp[i].ident); WriteString(pFile, " "); WriteString(pFile, String::IntToString(pBC->GetInt32(pProp[i].id))); // XXX: BITMAPBUTTON SIZE is a CUSTOMTYPE_LONG property, yet it // requires a tuple for the SIZE parameter. Can we find a better // way than hardcoding this? // https://github.com/nr-plugins/resedit/issues/2 if (String(pElement->m_pChResSym) == String("BITMAPBUTTON") && String(pProp[i].ident) == String("SIZE")) { WriteString(pFile, ", "); WriteString(pFile, String::IntToString(pBC->GetInt32(pProp[i].id))); } WriteString(pFile, "; "); b = true; } else if (pProp[i].type == CUSTOMTYPE_REAL) { WriteString(pFile, *g_pstrFillSave); WriteString(pFile, pProp[i].ident); WriteString(pFile, " "); WriteString(pFile, String::FloatToString(pBC->GetFloat(pProp[i].id))); WriteString(pFile, "; "); b = true; } else if (pProp[i].type == CUSTOMTYPE_STRING) { if (pBC->GetString(pProp[i].id).Content()) { WriteString(pFile, *g_pstrFillSave); WriteString(pFile, pProp[i].ident); WriteString(pFile, " "); WriteString(pFile, pBC->GetString(pProp[i].id)); WriteString(pFile, "; "); b = true; } } else if (pProp[i].type == CUSTOMTYPE_VECTOR) { WriteString(pFile, *g_pstrFillSave); WriteString(pFile, pProp[i].ident); WriteString(pFile, " "); WriteString(pFile, String::FloatToString(pBC->GetVector(pProp[i].id).x)); WriteString(pFile, " "); WriteString(pFile, String::FloatToString(pBC->GetVector(pProp[i].id).y)); WriteString(pFile, " "); WriteString(pFile, String::FloatToString(pBC->GetVector(pProp[i].id).z)); WriteString(pFile, " "); WriteString(pFile, "; "); b = true; } if (b) LineBreak(pFile, strFill); } WriteString(pFile, "}"); } return true; }
Bool LiquidToolData::MouseInput(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, EditorWindow* win, const BaseContainer& msg) { Float mx = msg.GetFloat(BFM_INPUT_X); Float my = msg.GetFloat(BFM_INPUT_Y); Int32 button; switch (msg.GetInt32(BFM_INPUT_CHANNEL)) { case BFM_INPUT_MOUSELEFT: button = KEY_MLEFT; break; case BFM_INPUT_MOUSERIGHT: button = KEY_MRIGHT; break; default: return true; } BaseObject* cl = nullptr, *null = nullptr, *op = nullptr; Float dx, dy, rad = 5.0; Bool newmeta = false; op = BaseObject::Alloc(Osphere); if (!op) return false; null = BaseObject::Alloc(Ometaball); { null->GetDataInstance()->SetFloat(METABALLOBJECT_SUBEDITOR, 10.0); null->MakeTag(Tphong); } newmeta = true; if (newmeta) { doc->InsertObject(null, nullptr, nullptr); doc->SetActiveObject(null); doc->AddUndo(UNDOTYPE_NEW, null); DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW | DRAWFLAGS_NO_THREAD | DRAWFLAGS_NO_ANIMATION); } BaseContainer bc; BaseContainer device; win->MouseDragStart(button, mx, my, MOUSEDRAGFLAGS_DONTHIDEMOUSE | MOUSEDRAGFLAGS_NOMOVE); while (win->MouseDrag(&dx, &dy, &device) == MOUSEDRAGRESULT_CONTINUE) { bc = BaseContainer(); win->BfGetInputEvent(BFM_INPUT_MOUSE, &bc); if (bc.GetInt32(BFM_INPUT_CHANNEL) == BFM_INPUT_MOUSEWHEEL) { rad += bc.GetFloat(BFM_INPUT_VALUE) / 120.0; rad = ClampValue(rad, (Float) 0.1, (Float) MAXRANGE); GePrint(String::FloatToString(rad)); } if (dx == 0.0 && dy == 0.0) continue; mx += dx; my += dy; cl = (BaseObject*)op->GetClone(COPYFLAGS_0, nullptr); if (!cl) break; cl->GetDataInstance()->SetFloat(PRIM_SPHERE_RAD, rad); cl->SetAbsPos(bd->SW(Vector(mx, my, 500.0))); cl->InsertUnder(null); DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW | DRAWFLAGS_NO_THREAD | DRAWFLAGS_NO_ANIMATION); } if (win->MouseDragEnd() == MOUSEDRAGRESULT_ESCAPE) { doc->DoUndo(true); } BaseObject::Free(op); EventAdd(); return true; }
BaseObject* VoxelGenerator::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh) { BaseContainer* data = op->GetDataInstance(); BaseDocument* doc = op->GetDocument(); /************************************************************************/ Bool dirty = op->CheckCache(hh) || op->IsDirty(DIRTYFLAGS_DATA); if (!dirty) return op->GetCache(hh); /************************************************************************/ Float t_scale = data->GetFloat(VGEN_SCALE); if(t_scale == 0.0) return nullptr; Float t_threshold = data->GetFloat(VGEN_THRESHOLD); Vector scale(t_scale); //Just the vector version of the uniform scale /************************************************************************/ //Get the Effex Server (which contains all effex scenes) FXAPI::FXServer *server = FXAPI::FXServer::Get(doc); if(!server) return nullptr; //Get the scalar channel's BaseObject interface from the link field BaseObject* channel_object = op->GetDataInstance()->GetObjectLink(VGEN_CHANNEL, doc); if(!channel_object) return nullptr; //Find the Effex scene the scalar channel belongs to FXAPI::FXScene* effex_scene = server->GetEffexScene(channel_object); if(!effex_scene) return nullptr; //Finally retrieve the scalar channel node from the effex scene */ FXAPI::FXScalarChannel* ptr_channel = static_cast<FXAPI::FXScalarChannel*>(FXAPI::GetNode(effex_scene,channel_object,FXAPI::NodeRetrieveType_ScalarChannel)); if(!ptr_channel) return nullptr; /************************************************************************/ //We wanna place all voxel cubes under this null object BaseObject* ret = BaseObject::Alloc(Onull); if(!ret) { return nullptr; } //Create a reference cube BaseObject* voxel_cube = BaseObject::Alloc(Ocube); if(!voxel_cube) return ret; //Set Normal scale voxel_cube->GetDataInstance()->SetVector(PRIM_CUBE_LEN, Vector(1.0)); //Renaming the cube voxel_cube->SetName("Voxel Reference"); //Tell the cube to update bounding box etc. voxel_cube->Message(MSG_UPDATE); //Finally place the cube under our null object voxel_cube->InsertUnder(ret); /************************************************************************/ //Now we create a scalar cell iterator which lets us browse all cells of a scalar channel //You can use C4D's AutoAlloc class for scope based construction/destruction //Otherwise just use FXAPI::FXScalarCellIterator::Alloc/Free AutoAlloc<FXAPI::FXScalarCellIterator> iterator; //Initialise it with our scalar channel, the cpu threads count we use and if grid border cells should be browsed as well if(iterator->Init(ptr_channel, 1, true)) { /************************************************************************/ /* The following part could be called from multiple cpu threads */ /* but here we stay single-threaded */ /************************************************************************/ Int32 cpu_index = 0; //First cpu = 0 //Call once per thread iterator->Start(cpu_index,false); //passing true would give a reverse iterator do //Now we browse with a do...while loop all cells of this cpu { //The iterator gives us the current cell value double cell_scalar_value = iterator->GetValue(cpu_index); //Example: check for value threshold to only create instances in cells containing a value (e.g. smoke density) if(cell_scalar_value <= t_threshold) continue; //don't process this cell //Get the current cell's coordinate (in grid cell space) NAVIE_GLOBAL::VecInt3D xyz_cell = iterator->GetCoordinate(cpu_index); //Now convert coordinates from grid cell space to world space coordinates //which we will use to set the cube instances's position NAVIE_GLOBAL::vector3d xyz_global; if(FXAPI::GridToWorld(ptr_channel, xyz_cell, xyz_global, false)) { //Conversion was fine. Now we create an instance object for this cell BaseObject* voxel_instance = BaseObject::Alloc(Oinstance); if(!voxel_instance) continue; //Set the reference voxel cube as source voxel_instance->GetDataInstance()->SetLink(INSTANCEOBJECT_LINK, voxel_cube); //Make it a render instance voxel_instance->GetDataInstance()->SetBool(INSTANCEOBJECT_RENDERINSTANCE, true); //Renaming the instance to Voxel + its linear coordinate index voxel_instance->SetName("Voxel Reference" + String::IntToString(iterator->GetLinearCoordinate(cpu_index))); //Set position (converting from an Effex vector3d to a c4d Vector on the fly) voxel_instance->SetAbsPos(FXAPI::Vec3DToVector(xyz_global)); //We also control the scale by the scalar cell value voxel_instance->SetAbsScale(scale * cell_scalar_value); //Tell the instance to update all its data voxel_instance->Message(MSG_UPDATE); //Finally place the instance under our null object voxel_instance->InsertUnderLast(ret); } } while(iterator->SetNext(cpu_index)); //Go to next cell.. /************************************************************************/ } return ret; }