@zipit
Yes, thx - the system works :}

jochemdk
@jochemdk
Working in R20-S23
Posts made by jochemdk
-
RE: Issue dragging a pyTag with a message function > Type-/SystemError in R23/Python3 on both Mac&PC.
-
RE: Wrong random clone displayed issue
@m_adam
Thx anyway, hope to hear from you one day... all the best for the next year -
RE: Wrong random clone displayed issue
@m_adam
Hi Maxime, One additional remark + a question…I’m trying to build a minimum set of rules to avoid the dis/enabling of effectors if not really necessary. I can’t use moFlags to check whether a clone is visible or not, and that’s where the issue might be:
1_ Given the example in the previous post (with offset 2), the moFlags read something like [2,2,2,1,0,1,…..]. Flag 2 being “permanently disabled”. If it means that behind the scenes index 2 is totally ignored, this is where the problem might be…
2A_ So reading moFlags doesn’t give me the info I need. For the moSelections I was able to find the first index of an invisible clone via “baseSelection.GetAll(count)”. So everything fine here…
2B_ I’ve spend many hours trying to find a formula to find the (first) invisible clone with moWeights. Given any weight float value between 0 & 1, a clone gets invisible based on the strength & maximum value sliders (which are not limited and can go way past +/- 100%..).
The question: What is the formula (with strength & maximum) to check whether a weighted clone gets invisible?
Tia, Jochem
(If you want I can start a new thread, but this is so closely related…)One function added in the script below:
""" After some code I know which linearCloners have a moSel/Weight tag with the same name as the baseEffector selection string... Per effector - with visibility turned on - I run the func below to check what the minimal offset is (for multiple cloners) & return "update" True if the minOffset is >= the selection index where a clone gets invisible... The passed moSelDict has selection strings as keys & indices of an inexList as values. """ def checkUpd(effector, moSelDict): minOff = 999999 minSelIdx = 999998 for moInd in moSelDict[effector[c4d.ID_MG_BASEEFFECTOR_SELECTION]]: moObj = op[c4d.ID_USERDATA,5].ObjectFromIndex(doc,moInd) # moObj = cloner / index from a linearCloner in-exclusion list.. if moObj[c4d.MG_LINEAR_OFFSET] < minOff: minOff = moObj[c4d.MG_LINEAR_OFFSET] for tag in moObj.GetTags(): if tag.CheckType(1021338) and tag.GetName() == effector[c4d.ID_MG_BASEEFFECTOR_SELECTION]: # selection bs = mograph.GeGetMoDataSelection(tag) count = moObj[c4d.MG_LINEAR_COUNT] + moObj[c4d.MG_LINEAR_OFFSET] try: minSel = bs.GetAll(count).index(1) # << here is where I can find the correct (in)visible selection values for moSelections except ValueError: break # selectionTag with no selection.. if minSel < minSelIdx: minSelIdx = minSel break elif tag.CheckType(440000231) and tag.GetName() == effector[c4d.ID_MG_BASEEFFECTOR_SELECTION]: # weight strength = effector[c4d.ID_MG_BASEEFFECTOR_STRENGTH] maximum = effector[c4d.ID_MG_BASEEFFECTOR_MAXSTRENGTH] # WHAT IS THE FORMULA TO GET (IN)VISIBLE STATE OF A WEIGHTED CLONE, BASED ON THE 2 VALUES ABOVE?.. bs = mograph.GeGetMoDataWeights(tag) minSel = 999999 for w in range(len(bs)): if bs[w] > 0.0: # << this is of course not optimal :) minSel = w break if minSel < minSelIdx: minSelIdx = minSel break if minOff >= minSelIdx: return True return False
Edit:
It turns out I need a formula for the strength/maximum values for the moSelection version as well. I plotted some values (in excel:) for various combinations of strength/maximum with moSelections/moWeights. All show an exponential growth(/decay) curve... I know you're not supposed to write scripts for others, but if you've got some code lying around - it would be brilliant. -
RE: Wrong random clone displayed issue
@m_adam
Hi, I did some more testing…Things only go wrong with a linearCloner’s offset if:
_ any applied baseEffector has the visibility check turned on
_ has a mograph selection/weight tag
_ and if a linearCloner’s offset >= the smallest index of the selection
_ (so random has nothing to do with it :) -
RE: Wrong random clone displayed issue
@m_adam
Thx :) I thought it was a bug... I know how to control stuff myself, but this is about catching all kinds of things from "some" user's hierarchy - including cloners in cloners and animated moSelections/Weights. -
Wrong random clone displayed issue
Ok, here’s a thing you normally don’t notice when using a cloner with random clones, because random is random, right?.. Under certain circumstances the clones displayed in the viewport don’t correspond with the indices they are supposed to be.
This is noticeable if you manually turn off & on a/the effector, hence giving only the correct display after the toggle.
Well, this is not about manual things. For a lot of reasons it’s very important to me to know exactly which clone is which. So, I made a “hack” to get the right results…
See preview below for a simple example with index 2 selected in the moSelectionTag which is used in the plainEffector to hide the clone. Notice the nrs in the console - which I think are correct & don’t correspond with the viewport in the last 2 images..
_Left_image: all goes well because the cloners offset is smaller than the “hidden index 2”.
_Middle_image: here is where it goes wrong. The cloners offset passes index 2 (offset >= 3) and incorrect clones are shown.
_Right_image: going back to offset 2 also shows the incorrect children.
Once going to offset 1 everything is fine again - or after dis-/enabling the effector...So, none of this happens if I apply my “hack” in the script below which turns every effector off/on to get the right result.
Isn’t there a more elegant solution for this?
Is it a bug, or is it me?..import c4d, math from c4d.modules import mograph from c4d import utils def main(): moObj = op.GetObject() # cloner > with a pyTag ##### ----- ##### useHack = True # use a "hack", turning effector(s) on/off to get the correct random results.. if useHack == True: doc = op.GetDocument() inex = moObj[c4d.ID_MG_MOTIONGENERATOR_EFFECTORLIST] for i in range(inex.GetObjectCount()): effector = inex.ObjectFromIndex(doc, i) effector[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = False effector[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = True effector.Message(c4d.MSG_UPDATE) ##### ----- ##### moData = mograph.GeGetMoData(moObj) moCount = moData.GetCount() moFlags = moData.GetArray(c4d.MODATA_FLAGS) moChil = moData.GetArray(c4d.MODATA_CLONE) dirChil = len(moObj.GetChildren()) dirMod = 1/float(dirChil) for i in range(moCount): if moFlags[i] != 1: print ("-fl->", moFlags[i]) elif moFlags[i] == 1: # method 1 dirInst = int(math.floor(moChil[i]/dirMod)) if dirInst == dirChil: dirInst -= 1 # method 2 childIdx = int(math.floor(utils.ClampValue(moChil[i] * dirChil, 0, dirChil-1))) print ("-fl->", moFlags[i], "-m1->", dirInst, "-m2->", childIdx) print ("-----")
Note: there are 2 methods in the script to get the right index for the clone. The 2nd method I found on this page: https://plugincafe.maxon.net/topic/10032/13500_identify-name-of-clone-source-at-index/2 which I used as a sanity check. Both methods display the same indices, so effectively there’s no difference.
Also, a simple c4d file attached for testing purposes (R23). By the way, the above happens exactly the same in S22.
-
RE: Issue dragging a pyTag with a message function > Type-/SystemError in R23/Python3 on both Mac&PC.
Thx for your replies! I'll test it soon & hopefully the bug will be fixed :)
-
Issue dragging a pyTag with a message function > Type-/SystemError in R23/Python3 on both Mac&PC.
It took me a while to figure out which part caused the problem converting a scripting tag from py2 to py3...
The console printed the following errors (multiple times at a time):TypeError: Expected PyCapsule, not None
The above exception was the direct cause of the following exception:
SystemError: PyEval_EvalFrameEx returned a result with an error setThe problem was the message function (I think..). Did a simple test with a pyTag containing only 1 userData button and the following script:
import c4d def main(): pass def message(id, data): if id == c4d.MSG_DESCRIPTION_COMMAND: id2 = data['id'][0].id if id2 == c4d.ID_USERDATA: userDataId = data['id'][1].id if userDataId == 1: tst() def tst(): print ("tst")
_Copying an object with the pyTag - no problem.
_Yes, the button just prints “tst” in python2 & 3 :}
_Dragging in python2 - no problem.
_Dragging the pyTag to another object (or a duplicate onto itself) in R23 - gives 2 errorsHow can I solve this? I guess it's not the wisest idea in the world to put a SystemError in a try-except block...
Tia, Jochem
I saw the following code in the “python3_migration” in the SDK mentioning the "PyCapsule", but It doesn’t make much sense to me :{
PyCObject_AsVoidPtr is replaced by PyCapsule_GetPointer
_next code is only compatible in Python 2.7
P1MSG_UN = msg.GetVoid(c4d.BFM_CORE_PAR1)
pythonapi.PyCObject_AsVoidPtr.restype = c_int
pythonapi.PyCObject_AsVoidPtr.argtypes = [py_object]
P1MSG_EN = pythonapi.PyCObject_AsVoidPtr(P1MSG_UN)_next code is only compatible in 3.7
P1MSG_UN = msg.GetVoid(c4d.BFM_CORE_PAR1)
P1MSG_EN = pythonapi.PyCapsule_GetPointer(P1MSG_UN, None) -
RE: MographToNulls available for free as a Python scripting tag
OK, I feel pretty stupid now... I was so busy with the specific way I used the script in the past, I forgot about the animation part :(
So, I'll try to find some time soon to get the code up and running for animation. So my main function will be larger than "pass" :)