• BaseDraw in TagDataPlugin

    Cinema 4D SDK s22 python sdk
    3
    0 Votes
    3 Posts
    372 Views
    ?
    @m_adam My apologies for not being clearer. I thought there was something wrong with how I was doing the Draw function. The issue was the TAG_IMPLEMENTS_DRAW_FUNCTION flag was missing. Thank you very much!
  • Render filtered Hardware Preview

    Cinema 4D SDK s22 classic api python
    10
    0 Votes
    10 Posts
    2k Views
    a_blockA
    Thanks for validating my assumptions. Much appreciated. Yes, I already have multiple code branches and for S22 my workaround looks as described. Because it doesn't hurt to insert the RenderData in this case, it doesn't even need multiple branches. Thanks for looking into it, Maxime. Is this going to be fixed in a future version?
  • 0 Votes
    3 Posts
    441 Views
    ?
    @m_magalhaes Remap did the trick! Thanks for the help, Manuel
  • How is NBIT_CKEY_ACTIVE used?

    Cinema 4D SDK python s22 sdk
    3
    0 Votes
    3 Posts
    258 Views
    ?
    @r_gigante Ahhhhhhhh, okay, I get it now. Thank you
  • Get Active Timeline Request

    Cinema 4D SDK
    7
    0 Votes
    7 Posts
    1k Views
    annA
    Indeed a better sdk will be better. I actually also hope that sdk can recognize which parameters of the object are activated in the object manager. I know that because c4d supports opening multiple object managers at the same time, this is really convenient. But it will also make it impossible to know which object manager the user is using, so there is no way to identify it in the current SDK.
  • problem with loading plugin in python_init.py

    Moved Cinema 4D SDK
    3
    0 Votes
    3 Posts
    582 Views
    W
    @m_adam it's strange, but this small script works fine without any problems with cinema 4d s22. cinema 4d r20 show this error only.
  • any way to close cinema 4d from the python script

    Moved Cinema 4D SDK
    4
    0 Votes
    4 Posts
    874 Views
    M
    Hi @wob there is noting built-in for that in Cinema 4D. but you can use the regular python way to kill the current process import signal import os os.kill(os.getpid(), signal.SIGTERM) But I just let you know, that it may be useless by nature python should be pretty good at not creating any memory leak, and should free the data as soon as possible, moreover your approach ( I don't know the whole pipeline) but may also be a big issue for a user since this will clause Cinema 4D without asking for saving. People may lose their work. So I really encourage you to be very careful with the use of this. Cheers, Maxime.
  • pop-up dialog windows and c4dpy : the problem

    Moved Cinema 4D SDK
    3
    0 Votes
    3 Posts
    753 Views
    M
    Hi @wob unfortunately this is not possible, c4dpy is a regular Cinema 4D executed as command line with the NoGui, and as all NoGui Cinema 4D execution, GeDialog is disabled. So its a limitation, and as said by zipit there is no Tkinter shipped with Cinema 4D in order to force people to use Cinema 4D dialog. So possible workarounds are: Install pip and install any 3rd party GUI module (but this is not officially supported by Cinema 4D so you may have some odd issues, but it should work). Execute a python script before from a system python installation that will create the Dialog and later execute c4dpy to do the Cinema 4D work. Cheers, Maxime.
  • "Axis Center " Script button reuse problem

    General Talk r21 python
    3
    0 Votes
    3 Posts
    691 Views
    X
    Thank you very much for your help to solve the previous doubts. I will continue to work hard.
  • 0 Votes
    8 Posts
    1k Views
    indexofrefractionI
    I also just ran into this... < R24 you dont have BaseList2D.IsNodeBased, but as a small hack you can do: def isNodeMaterial(op): return True if op.GetType == c4d.Mmaterial and '[Node]' in op.GetBubbleHelp() else False
  • 0 Votes
    5 Posts
    1k Views
    ManuelM
    hi, from time to time i'm saying thanks to @zipit , but for sure he's contributing a lot to the community. there's not too much to say more that what have been said. Brut force is the only option without using external python librairies. You can always use an external library if you want to use a kd-tree structure to be faster. Using cpp would be a better solution if you really want to do it fast. We have in our API a kd-tree as show in this kd-stree manual. You can see on github a full example on how to use it And here are some code of me playing with different way of sampling a kd-tree using parallel method and also using voxelization to get the closest polygon. //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- /// GetClosestPolygon using voxelization //---------------------------------------------------------------------------------------- static maxon::Result<void> GETCLOSEST_POLY(BaseDocument* doc) { iferr_scope; if (doc == nullptr) return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION); // ------- Create a mesh with one poly const maxon::Int32 polyCnt{ 500 }; PolygonObject *mesh = PolygonObject::Alloc(polyCnt * 4, polyCnt ); if (mesh == nullptr) return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION); maxon::LinearCongruentialRandom<maxon::Float32> random; CPolygon *polyAdrW = mesh->GetPolygonW(); Vector* padrW = mesh->GetPointW(); const Float polySize{ 10 }; for (maxon::Int i = 0; i < polyCnt; i++) { CPolygon poly; maxon::Vector pointA(i * polySize, 0, 0); maxon::Vector pointB(i * polySize, 0, polySize); maxon::Vector pointC(i * polySize + polySize, 0, polySize); maxon::Vector pointD(i * polySize + polySize, 0, 0); const maxon::Int pointIndice = i * 4; padrW[pointIndice] = pointA; padrW[pointIndice + 1] = pointB; padrW[pointIndice + 2] = pointC; padrW[pointIndice + 3] = pointD; poly.a = pointIndice; poly.b = pointIndice + 1; poly.c = pointIndice + 2; poly.d = pointIndice + 3; polyAdrW[i] = poly; } doc->InsertObject(mesh, nullptr, nullptr); maxon::DistanceQueryRef distanceQueryRef = maxon::DistanceCalculator().Create() iferr_return; distanceQueryRef.Init(mesh, true) iferr_return; maxon::PrimitiveInformation result; const maxon::Int samplePointCnt = polyCnt; //---------------------------------------------------------------------------------------- /// sample using standard loop maxon::TimeValue start = maxon::TimeValue(maxon::TimeValue::NOW); for (maxon::Int i = 0; i < samplePointCnt; ++i) { const maxon::Vector pos{ i * polySize + polySize * 0.5, 0, 0 }; distanceQueryRef.GetClosestMeshPrimitive(pos, result); if (result.type == maxon::PRIMITIVETYPE::POLYGON) ApplicationOutput("pos @, polyIndex @ ", pos, result.GetRealPolyIndex()); else ApplicationOutput("not a polygon"); } ApplicationOutput("time to sample the points @ with MP", start.Stop()); //---------------------------------------------------------------------------------------- /// sample using parallelFor start = maxon::TimeValue(maxon::TimeValue::NOW); maxon::BaseArray< maxon::PrimitiveInformation> resultArray; resultArray.Resize(samplePointCnt) iferr_return; maxon::ParallelFor::Dynamic(0, samplePointCnt, [&resultArray, &polySize, &distanceQueryRef](maxon::Int i) { maxon::PrimitiveInformation result; const maxon::Vector pos{ i * polySize + polySize * 0.5, 0, 0 }; distanceQueryRef.GetClosestMeshPrimitive(pos, result); if (result.type == maxon::PRIMITIVETYPE::POLYGON) ApplicationOutput("pos @, polyIndex @ ", pos, result.GetRealPolyIndex()); else ApplicationOutput("not a polygon"); resultArray[i] = result; } ); ApplicationOutput("time to sample the points @ with MP", start.Stop()); for (auto& value : resultArray) { if (value.type == maxon::PRIMITIVETYPE::POLYGON) ApplicationOutput("polyIndex @ ", value.GetRealPolyIndex()); else ApplicationOutput("not a polygon"); } return maxon::OK; } //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- /// Sample a KD tree with multi thread //---------------------------------------------------------------------------------------- class SampleTreeJob : public maxon::JobInterfaceTemplate<SampleTreeJob, maxon::Int> { public: SampleTreeJob() { }; MAXON_IMPLICIT SampleTreeJob(maxon::KDTree* kdtree, const maxon::Vector& samplePoint) { _kdtree = kdtree; _samplePoint = samplePoint; } // function operator with the actual workload maxon::Result<void> operator ()() { maxon::Int nearestIndex = _kdtree->FindNearest(maxon::JobRef::GetCurrentWorkerThreadIndex(), _samplePoint, nullptr); // store result return SetResult(std::move(nearestIndex)); } private: maxon::KDTree* _kdtree; maxon::Vector _samplePoint; }; static maxon::Result <maxon::BaseArray<maxon::Vector>> CreateArrayOfPoints() { iferr_scope; const maxon::Int pointCnt = 1000000; maxon::BaseArray<maxon::Vector> points; points.EnsureCapacity(pointCnt) iferr_return; maxon::LinearCongruentialRandom<maxon::Float32> random; for (maxon::Int i = 0; i < pointCnt; ++i) { maxon::Vector pos(maxon::DONT_INITIALIZE); pos.x = random.Get01() * 100000.0; pos.y = random.Get01() * 100000.0; pos.z = random.Get01() * 100000.0; points.Append(pos) iferr_return; } return points; } static maxon::Result<maxon::BaseArray<maxon::Vector>> CreateSamplePoints() { iferr_scope; // sample points const maxon::Int samplePointCnt = 10000; maxon::BaseArray<maxon::Vector> samplePoints; samplePoints.EnsureCapacity(samplePointCnt) iferr_return; for (maxon::Int i = 0; i < samplePointCnt; ++i) { const maxon::Vector pos{ i* 10.0 }; samplePoints.Append(pos) iferr_return; } return samplePoints; } static maxon::Result<void> KDTREE_MP(BaseDocument* doc) { iferr_scope; maxon::BaseArray<maxon::Vector> points = CreateArrayOfPoints() iferr_return; maxon::BaseArray<maxon::Vector> samplePoints = CreateSamplePoints() iferr_return; const maxon::Int samplePointCnt = samplePoints.GetCount(); const maxon::Int pointCnt = points.GetCount(); maxon::KDTree tree; tree.Init(maxon::JobRef::GetCurrentThreadCount()) iferr_return; // insert points for (maxon::Int i = 0; i < pointCnt; ++i) { tree.Insert(points[i], i) iferr_return; } // balance tree tree.Balance(); //---------------------------------------------------------------------------------------- /// sample using classic loop maxon::TimeValue start{ maxon::TimeValue::NOW }; for (const maxon::Vector& samplePoint : samplePoints) { // find nearest point const maxon::Int nearestIndex = tree.FindNearest(0, samplePoint, nullptr); } ApplicationOutput("time to sample the points @ ", start.Stop()); //---------------------------------------------------------------------------------------- /// sample using parallelFor start = maxon::TimeValue(maxon::TimeValue::NOW); maxon::ParallelFor::Dynamic(0, samplePointCnt, [&samplePoints, &tree](maxon::Int i) { const maxon::Vector samplePoint = samplePoints[i]; const maxon::Int nearestIndex = tree.FindNearest(maxon::JobRef::GetCurrentWorkerThreadIndex(), samplePoint, nullptr); } ); ApplicationOutput("time to sample the points @ with MP", start.Stop()); //---------------------------------------------------------------------------------------- /// Sample using job // create group start = maxon::TimeValue(maxon::TimeValue::NOW); maxon::JobGroupRef group = maxon::JobGroupRef::Create() iferr_return; for (auto i = 0 ; i < samplePointCnt; i++) { // create and add job const maxon::Vector samplePoint = samplePoints[i]; auto job = SampleTreeJob::Create(&tree, samplePoint) iferr_return; group.Add(job) iferr_return; } // enqueue jobs and wait group.Enqueue(); group.Wait(); ApplicationOutput("time to sample the points @ with jobs", start.Stop()); //---------------------------------------------------------------------------------------- /// sample using classic loop again start = maxon::TimeValue(maxon::TimeValue::NOW); for (const maxon::Vector& samplePoint : samplePoints) { // find nearest point const maxon::Int nearestIndex = tree.FindNearest(0, samplePoint, nullptr); } ApplicationOutput("time to sample the points @ second time to see if caches are envolved", start.Stop()); return maxon::OK; } Cheers, Manuel
  • Sizing Plugin Dialogs

    Cinema 4D SDK python s22 sdk
    9
    1
    1 Votes
    9 Posts
    1k Views
    ferdinandF
    Hi @blastframe, without further questions or feedback, by Monday we will consider this thread as solved and flag it accordingly. Cheers, Ferdinand
  • How to create a layer Reflection (Legacy) ?

    Cinema 4D SDK python
    2
    0 Votes
    2 Posts
    592 Views
    KantroninK
    I found the solution to my problem, on the internet, with code samples: https://www.c4dcafe.com/ipb/forums/topic/101805-materials-and-shaders-with-python/
  • 0 Votes
    6 Posts
    979 Views
    P
    Ah sorry.
  • Using Console Variable in the Script Manager?

    Cinema 4D SDK r21 python
    4
    0 Votes
    4 Posts
    409 Views
    B
    @m_magalhaes Thanks for the confirmation. Although what zipit provided also works for my use case (i.e. defining the variable from Document B but using that same variable in Document A) @zipit Thanks for the code. It works as expected
  • Copy, Paste, Flip X a Pose Morph Target?

    Cinema 4D SDK r21 python
    12
    0 Votes
    12 Posts
    3k Views
    B
    @m_magalhaes @zipit I managed to flip the mesh (not necessarily a pose morph target since I'd have to know the API). Anyhow, here is a demo of it working: https://www.dropbox.com/s/bh4p26s4m9qwljw/c4d272_flip_miror_mesh.mp4?dl=0 Here is wip script. It only works if the x-axis is dead set on 0. Also, it is slow since it has to loop within a loop. import c4d from c4d import gui # Main function def main(): neutral_geo = doc.SearchObject('neutral_geo') posed_geo = doc.SearchObject('posed_geo') neutral_world_matrix = neutral_geo.GetMg() posed_world_matrix = posed_geo.GetMg() neut_lcl_pnts = neutral_geo.GetAllPoints() neut_gbl_pnts = [point * neutral_world_matrix for point in neut_lcl_pnts] posed_lcl_pnts = posed_geo.GetAllPoints() posed_gbl_pnts = [point * posed_world_matrix for point in posed_lcl_pnts] match_pnts = [] left_pnts = [] right_pnts = [] for idx, point in enumerate(neut_gbl_pnts): if point[0] == 0.0: # ignore points at the world x axis continue if point[0] > 0.0: left_pnts.append((idx,point)) if point[0] < 0.0: right_pnts.append((idx,point)) for left in left_pnts: for right in right_pnts: if left[1][1] == right[1][1]: # check if Y pos match if left[1][2] == right[1][2]: # check if Z pos match if left[1][0] == -1 * (right[1][0]):# check if X pos are inverse match_pnts.append((left[0],right[0])) for pnt in match_pnts: reversed_left = posed_lcl_pnts[pnt[1]] reversed_left[0] = reversed_left[0] * -1 reversed_right = posed_lcl_pnts[pnt[0]] reversed_right[0] = reversed_right[0] * -1 posed_geo.SetPoint(pnt[0], reversed_left) posed_geo.SetPoint(pnt[1], reversed_right) posed_geo.Message(c4d.MSG_UPDATE) c4d.EventAdd() # Execute main() if __name__=='__main__': main()
  • Message when leaving an Edit Text

    Cinema 4D SDK python s22 sdk
    5
    0 Votes
    5 Posts
    612 Views
    ?
    @m_adam Great idea! I'll use a Timer Thanks Maxime!
  • Setting Strength Values of the Pose Morph Target?

    Cinema 4D SDK r21 python
    4
    0 Votes
    4 Posts
    843 Views
    B
    @PluginStudent @m_magalhaes Thanks for the reference link and sample code. It works as expected. Thanks also for the giving different methods in setting the strength. Provides more flexibility.
  • From Line Object to Spline

    Cinema 4D SDK python s22
    5
    0 Votes
    5 Posts
    1k Views
    ManuelM
    hi, I'll consider this thread as solved without further feedback Cheers, Manuel